0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Claudeにファイルの読み込みについて聞いてみた

0
Last updated at Posted at 2026-07-06

ClaudeにTOMLファイル読み込みについて聞いた

# GitHubからcloneする場合
$ git clone https://github.com/ToruNiina/toml11

# Ubuntu
$ apt install nlohmann-json3-dev libyaml-cpp-dev libtoml11-dev

# Redhat
$ dnf install https://dl.fedoraproject.org/pub/epel/epel-release-latest-9.noarch.rpm
$ dnf config-manager --enable codeready-builder-for-rhel-9-rhui-rpms
$ dnf install json-devel yaml-cpp-devel toml11-devel
// toml_config.h : テストパターン設定TOMLを読み込むクラス(toml11バックエンド)
// toml11: https://github.com/ToruNiina/toml11 (MITライセンス、C++11以上、ヘッダオンリー)
#ifndef TOML_CONFIG_H
#define TOML_CONFIG_H

#include <string>
#include <toml.hpp>

class TomlConfig {
public:
  TomlConfig( void );
  TomlConfig( const char *fname );
  ~TomlConfig( void );

  bool load( const char *fname );
  void release( void );
  bool isLoaded( void ) const;

  int         getSectionNum( void ) const;
  std::string getSectionName( int idx ) const;
  bool        hasSection( const char *section ) const;
  bool        hasKey( const char *section, const char *key ) const;
  int         getKeyNum( const char *section ) const;
  std::string getKeyName( const char *section, int idx ) const;

  int         getInt( const char *section, const char *key, int defval ) const;
  std::string getStr( const char *section, const char *key, const char *defval ) const;

private:
  // ordered_type_config: セクションとキーのファイル記載順を保持する
  typedef toml::basic_value<toml::ordered_type_config> Value;

  bool  loaded_;
  Value root_;

  const Value *findSec( const char *section ) const;
  const Value *findVal( const char *section, const char *key ) const;
};

#endif
// toml_config.cpp
#include <cstdio>
#include "toml_config.h"

TomlConfig::TomlConfig( void )
{
  loaded_ = false;
}

TomlConfig::TomlConfig( const char *fname )
{
  loaded_ = false;
  load(fname);
}

TomlConfig::~TomlConfig( void )
{
  release();
}

bool TomlConfig::load( const char *fname )
{
  release();

  try {
    root_ = toml::parse<toml::ordered_type_config>(fname);
  } catch( const std::exception &e ) {
    // 構文エラー時はtoml11が行番号と位置指示付きのメッセージを生成する
    fprintf(stderr, "TomlConfig::load: %s\n", e.what());
    return false;
  }

  loaded_ = true;
  return true;
}

void TomlConfig::release( void )
{
  root_   = Value();
  loaded_ = false;
}

bool TomlConfig::isLoaded( void ) const
{
  return loaded_;
}

int TomlConfig::getSectionNum( void ) const
{
  if( !loaded_||!root_.is_table() ) {
    return 0;
  }
  const auto &tbl = root_.as_table();
  int n = 0;
  for( auto it=tbl.begin(); it!=tbl.end(); ++it ) {
    if( it->second.is_table() ) {
      n++;
    }
  }
  return n;
}

std::string TomlConfig::getSectionName( int idx ) const
{
  if( loaded_&&root_.is_table() ) {
    const auto &tbl = root_.as_table();
    int n = 0;
    for( auto it=tbl.begin(); it!=tbl.end(); ++it ) {
      if( it->second.is_table() ) {
        if( n==idx ) {
          return it->first;
        }
        n++;
      }
    }
  }
  fprintf(stderr, "TomlConfig::getSectionName: out of range idx=%d (num=%d)\n",
          idx, getSectionNum());
  return "";
}

bool TomlConfig::hasSection( const char *section ) const
{
  return findSec(section)!=NULL;
}

bool TomlConfig::hasKey( const char *section, const char *key ) const
{
  return findVal(section, key)!=NULL;
}

int TomlConfig::getKeyNum( const char *section ) const
{
  const Value *sec = findSec(section);
  if( sec==NULL ) {
    return 0;
  }
  return (int)sec->as_table().size();
}

std::string TomlConfig::getKeyName( const char *section, int idx ) const
{
  const Value *sec = findSec(section);
  if( sec!=NULL ) {
    const auto &tbl = sec->as_table();
    int n = 0;
    for( auto it=tbl.begin(); it!=tbl.end(); ++it ) {
      if( n==idx ) {
        return it->first;
      }
      n++;
    }
  }
  fprintf(stderr, "TomlConfig::getKeyName: out of range [%s] idx=%d\n", section, idx);
  return "";
}

int TomlConfig::getInt( const char *section, const char *key, int defval ) const
{
  const Value *v = findVal(section, key);
  if( v==NULL ) {
    return defval;
  }
  if( v->is_integer() ) {
    return (int)v->as_integer();
  }
  if( v->is_boolean() ) {
    return v->as_boolean() ? 1 : 0;
  }
  fprintf(stderr, "TomlConfig::getInt: [%s] %s is not an integer, use default %d\n",
          section, key, defval);
  return defval;
}

std::string TomlConfig::getStr( const char *section, const char *key, const char *defval ) const
{
  const Value *v = findVal(section, key);
  if( v==NULL ) {
    return defval;
  }
  if( v->is_string() ) {
    return v->as_string();
  }
  if( v->is_integer() ) {
    return std::to_string(v->as_integer());
  }
  if( v->is_floating() ) {
    return std::to_string(v->as_floating());
  }
  if( v->is_boolean() ) {
    return v->as_boolean() ? "true" : "false";
  }
  fprintf(stderr, "TomlConfig::getStr: [%s] %s is not a string, use default \"%s\"\n",
          section, key, defval);
  return defval;
}

const TomlConfig::Value *TomlConfig::findSec( const char *section ) const
{
  if( !loaded_||!root_.is_table() ) {
    return NULL;
  }
  const auto &tbl = root_.as_table();
  for( auto it=tbl.begin(); it!=tbl.end(); ++it ) {
    if( it->first==section&&it->second.is_table() ) {
      return &it->second;
    }
  }
  return NULL;
}

const TomlConfig::Value *TomlConfig::findVal( const char *section, const char *key ) const
{
  const Value *sec = findSec(section);
  if( sec==NULL ) {
    return NULL;
  }
  const auto &tbl = sec->as_table();
  for( auto it=tbl.begin(); it!=tbl.end(); ++it ) {
    if( it->first==key ) {
      return &it->second;
    }
  }
  return NULL;
}
// toml_main.cpp : TomlConfigの使用例(xlsx2toml.py生成ファイルの読み出し)
#include <cstdio>
#include "toml_config.h"

int main( int argc, char *argv[] )
{
  const char *fname = "hoge.toml";
  if( argc>=2 ) {
    fname = argv[1];
  }

  TomlConfig cfg(fname);
  if( !cfg.isLoaded() ) {
    return 1;
  }

  // 先頭セクション名=パターン名
  std::string num0   = cfg.getSectionName(0);
  int         num1   = cfg.getInt(num0.c_str(), "NUMBER1", 0);
  int         num2 = cfg.getInt(num0.c_str(), "NUMBER2", 0);
  printf("num0=%s  NUMBER1=%d  NUMBER2=%d\n", num0.c_str(), num1, num2);

  for( int i=0; i<num2; i++ ) {
    char sec[64];
    snprintf(sec, sizeof(sec), "NO_%d", i);
    if( !cfg.hasSection(sec) ) {
      fprintf(stderr, "missing section [%s]\n", sec);
      return 1;
    }
    printf("[%s] name=%s\n", sec, cfg.getStr(sec, "name", "(none)").c_str());
    for( int k=0; k<cfg.getKeyNum(sec); k++ ) {
      std::string key = cfg.getKeyName(sec, k);
      if( key=="name" ) {
        continue;
      }
      printf("  %-20s = %d\n", key.c_str(), cfg.getInt(sec, key.c_str(), 0));
    }
  }

  return 0;
}
[hoge]
NUMBER1=0
NUMBER2=2
[NO_0]
name="hoge_0"
kokugo = 100
sansuu = 1
rika = 0
syakai = 1
eigo = 1
[NO_1]
name="hoge_1"
kokugo = 100
sansuu = 1
rika = 0
syakai = 1
eigo = 1
# コンパイル
$ g++ -std=c++11 -O2 -Wall -I toml11/include -o toml_test toml_main.cpp toml_config.cpp

Claudeにjsonファイル読み込みについて聞いてみた

# GitHubからcloneする場合
$ git clone https://github.com/nlohmann/json

# Ubuntu
$ sudo apt install nlohmann-json3-dev

# Redhat
$ dnf install https://dl.fedoraproject.org/pub/epel/epel-release-latest-9.noarch.rpm
$ dnf config-manager --enable codeready-builder-for-rhel-9-rhui-rpms
$ dnf install json-devel
// json_config.h : テストパターン設定JSONを読み込むクラス(nlohmann/jsonバックエンド)
// nlohmann/json: https://github.com/nlohmann/json (MITライセンス、C++11以上、ヘッダオンリー)
#ifndef JSON_CONFIG_H
#define JSON_CONFIG_H

#include <string>
#include <nlohmann/json.hpp>

class JsonConfig {
public:
  JsonConfig( void );
  JsonConfig( const char *fname );
  ~JsonConfig( void );

  bool load( const char *fname );
  void release( void );
  bool isLoaded( void ) const;

  int         getSectionNum( void ) const;
  std::string getSectionName( int idx ) const;
  bool        hasSection( const char *section ) const;
  bool        hasKey( const char *section, const char *key ) const;
  int         getKeyNum( const char *section ) const;
  std::string getKeyName( const char *section, int idx ) const;

  int         getInt( const char *section, const char *key, int defval ) const;
  std::string getStr( const char *section, const char *key, const char *defval ) const;

private:
  // ordered_json: セクションとキーのファイル記載順を保持する(既定のjsonはキーを辞書順ソートするため不可)
  typedef nlohmann::ordered_json Value;

  bool  loaded_;
  Value root_;

  const Value *findSec( const char *section ) const;
  const Value *findVal( const char *section, const char *key ) const;
};

#endif
// json_config.cpp
#include <cstdio>
#include <fstream>
#include "json_config.h"

JsonConfig::JsonConfig( void )
{
  loaded_ = false;
}

JsonConfig::JsonConfig( const char *fname )
{
  loaded_ = false;
  load(fname);
}

JsonConfig::~JsonConfig( void )
{
  release();
}

bool JsonConfig::load( const char *fname )
{
  release();

  std::ifstream ifs(fname);
  if( !ifs ) {
    fprintf(stderr, "JsonConfig::load: cannot open %s\n", fname);
    return false;
  }

  try {
    // 第4引数true: //と/* */のコメントを無視(手編集ファイルへの配慮。標準JSONにコメントはない)
    root_ = Value::parse(ifs, nullptr, true, true);
  } catch( const std::exception &e ) {
    // 構文エラー時はnlohmannが行/桁位置付きのメッセージを生成する
    fprintf(stderr, "JsonConfig::load: %s\n", e.what());
    return false;
  }

  if( !root_.is_object() ) {
    fprintf(stderr, "JsonConfig::load: %s: top level is not an object\n", fname);
    release();
    return false;
  }
  loaded_ = true;
  return true;
}

void JsonConfig::release( void )
{
  root_   = Value();
  loaded_ = false;
}

bool JsonConfig::isLoaded( void ) const
{
  return loaded_;
}

int JsonConfig::getSectionNum( void ) const
{
  if( !loaded_ ) {
    return 0;
  }
  int n = 0;
  for( auto it=root_.begin(); it!=root_.end(); ++it ) {
    if( it.value().is_object() ) {
      n++;
    }
  }
  return n;
}

std::string JsonConfig::getSectionName( int idx ) const
{
  if( loaded_ ) {
    int n = 0;
    for( auto it=root_.begin(); it!=root_.end(); ++it ) {
      if( it.value().is_object() ) {
        if( n==idx ) {
          return it.key();
        }
        n++;
      }
    }
  }
  fprintf(stderr, "JsonConfig::getSectionName: out of range idx=%d (num=%d)\n",
          idx, getSectionNum());
  return "";
}

bool JsonConfig::hasSection( const char *section ) const
{
  return findSec(section)!=NULL;
}

bool JsonConfig::hasKey( const char *section, const char *key ) const
{
  return findVal(section, key)!=NULL;
}

int JsonConfig::getKeyNum( const char *section ) const
{
  const Value *sec = findSec(section);
  if( sec==NULL ) {
    return 0;
  }
  return (int)sec->size();
}

std::string JsonConfig::getKeyName( const char *section, int idx ) const
{
  const Value *sec = findSec(section);
  if( sec!=NULL ) {
    int n = 0;
    for( auto it=sec->begin(); it!=sec->end(); ++it ) {
      if( n==idx ) {
        return it.key();
      }
      n++;
    }
  }
  fprintf(stderr, "JsonConfig::getKeyName: out of range [%s] idx=%d\n", section, idx);
  return "";
}

int JsonConfig::getInt( const char *section, const char *key, int defval ) const
{
  const Value *v = findVal(section, key);
  if( v==NULL ) {
    return defval;
  }
  if( v->is_number_integer() ) {
    return (int)v->get<long long>();
  }
  if( v->is_boolean() ) {
    return v->get<bool>() ? 1 : 0;
  }
  fprintf(stderr, "JsonConfig::getInt: [%s] %s is not an integer, use default %d\n",
          section, key, defval);
  return defval;
}

std::string JsonConfig::getStr( const char *section, const char *key, const char *defval ) const
{
  const Value *v = findVal(section, key);
  if( v==NULL ) {
    return defval;
  }
  if( v->is_string() ) {
    return v->get<std::string>();
  }
  if( v->is_number_integer() ) {
    return std::to_string(v->get<long long>());
  }
  if( v->is_number_float() ) {
    return std::to_string(v->get<double>());
  }
  if( v->is_boolean() ) {
    return v->get<bool>() ? "true" : "false";
  }
  fprintf(stderr, "JsonConfig::getStr: [%s] %s is not a string, use default \"%s\"\n",
          section, key, defval);
  return defval;
}

const JsonConfig::Value *JsonConfig::findSec( const char *section ) const
{
  if( !loaded_ ) {
    return NULL;
  }
  for( auto it=root_.begin(); it!=root_.end(); ++it ) {
    if( it.key()==section&&it.value().is_object() ) {
      return &it.value();
    }
  }
  return NULL;
}

const JsonConfig::Value *JsonConfig::findVal( const char *section, const char *key ) const
{
  const Value *sec = findSec(section);
  if( sec==NULL ) {
    return NULL;
  }
  for( auto it=sec->begin(); it!=sec->end(); ++it ) {
    if( it.key()==key ) {
      return &it.value();
    }
  }
  return NULL;
}
// json_main.cpp : JsonConfigの使用例(xlsx2json.py生成ファイルの読み出し)
#include <cstdio>
#include "json_config.h"

int main( int argc, char *argv[] )
{
  const char *fname = "hoge.json";
  if( argc>=2 ) {
    fname = argv[1];
  }

  JsonConfig cfg(fname);
  if( !cfg.isLoaded() ) {
    return 1;
  }

  // 先頭セクション名=パターン名
  std::string num0   = cfg.getSectionName(0);
  int         num1   = cfg.getInt(num0.c_str(), "NUMBER1", 0);
  int         num2 = cfg.getInt(num0.c_str(), "NUMBER2", 0);
  printf("num0=%s  NUMBER1=%d  NUMBER2=%d\n", num0.c_str(), num1, num2);

  for( int i=0; i<num2; i++ ) {
    char sec[64];
    snprintf(sec, sizeof(sec), "NO_%d", i);
    if( !cfg.hasSection(sec) ) {
      fprintf(stderr, "missing section [%s]\n", sec);
      return 1;
    }
    printf("[%s] name=%s\n", sec, cfg.getStr(sec, "name", "(none)").c_str());
    for( int k=0; k<cfg.getKeyNum(sec); k++ ) {
      std::string key = cfg.getKeyName(sec, k);
      if( key=="name" ) {
        continue;
      }
      printf("  %-20s = %d\n", key.c_str(), cfg.getInt(sec, key.c_str(), 0));
    }
  }

  return 0;
}
{
  "hoge": {
    "NUMBER1": 0,
    "NUMBER2": 2
  },
  "NO_0": {
    "name": "hoge_0",
    "kokugo": 100,
    "sansuu": 1,
    "rika": 0,
    "syakai": 1,
    "eigo": 1
  },
  "NO_1": {
    "name": "hoge_1",
    "kokugo": 100,
    "sansuu": 1,
    "rika": 0,
    "syakai": 1,
    "eigo": 1
  }
}
# コンパイル
g++ -std=c++11 -O2 -Wall -I json/single_include -o json_test json_main.cpp json_config.cpp

Claudeにyamlファイル読み込みについて聞いてみた

# Ubuntuの場合
$ sudo apt install libyaml-cpp-dev

# Redhatの場合
$ sudo dnf install yaml-cpp-devel
// yaml_config.h : テストパターン設定YAMLを読み込むクラス(yaml-cppバックエンド)
// yaml-cpp: https://github.com/jbeder/yaml-cpp (MIT/X11ライセンス、C++11以上、要リンク -lyaml-cpp)
#ifndef YAML_CONFIG_H
#define YAML_CONFIG_H

#include <string>
#include <yaml-cpp/yaml.h>

class YamlConfig {
public:
  YamlConfig( void );
  YamlConfig( const char *fname );
  ~YamlConfig( void );

  bool load( const char *fname );
  void release( void );
  bool isLoaded( void ) const;

  int         getSectionNum( void ) const;
  std::string getSectionName( int idx ) const;
  bool        hasSection( const char *section ) const;
  bool        hasKey( const char *section, const char *key ) const;
  int         getKeyNum( const char *section ) const;
  std::string getKeyName( const char *section, int idx ) const;

  int         getInt( const char *section, const char *key, int defval ) const;
  std::string getStr( const char *section, const char *key, const char *defval ) const;

private:
  bool       loaded_;
  YAML::Node root_;  // yaml-cppのマップ走査は記載順を保持する

  YAML::Node findSec( const char *section ) const;
  YAML::Node findVal( const char *section, const char *key ) const;
};

#endif
// yaml_config.cpp
#include <cstdio>
#include "yaml_config.h"

YamlConfig::YamlConfig( void )
{
  loaded_ = false;
}

YamlConfig::YamlConfig( const char *fname )
{
  loaded_ = false;
  load(fname);
}

YamlConfig::~YamlConfig( void )
{
  release();
}

bool YamlConfig::load( const char *fname )
{
  release();

  try {
    root_ = YAML::LoadFile(fname);
  } catch( const std::exception &e ) {
    // 構文エラー時はyaml-cppが行/桁位置付きのメッセージを生成する
    fprintf(stderr, "YamlConfig::load: %s: %s\n", fname, e.what());
    return false;
  }

  if( !root_.IsMap() ) {
    fprintf(stderr, "YamlConfig::load: %s: top level is not a map\n", fname);
    release();
    return false;
  }
  loaded_ = true;
  return true;
}

void YamlConfig::release( void )
{
  root_   = YAML::Node(YAML::NodeType::Undefined);
  loaded_ = false;
}

bool YamlConfig::isLoaded( void ) const
{
  return loaded_;
}

int YamlConfig::getSectionNum( void ) const
{
  if( !loaded_ ) {
    return 0;
  }
  int n = 0;
  for( YAML::const_iterator it=root_.begin(); it!=root_.end(); ++it ) {
    if( it->second.IsMap() ) {
      n++;
    }
  }
  return n;
}

std::string YamlConfig::getSectionName( int idx ) const
{
  if( loaded_ ) {
    int n = 0;
    for( YAML::const_iterator it=root_.begin(); it!=root_.end(); ++it ) {
      if( it->second.IsMap() ) {
        if( n==idx ) {
          return it->first.as<std::string>();
        }
        n++;
      }
    }
  }
  fprintf(stderr, "YamlConfig::getSectionName: out of range idx=%d (num=%d)\n",
          idx, getSectionNum());
  return "";
}

bool YamlConfig::hasSection( const char *section ) const
{
  return findSec(section).IsDefined();
}

bool YamlConfig::hasKey( const char *section, const char *key ) const
{
  return findVal(section, key).IsDefined();
}

int YamlConfig::getKeyNum( const char *section ) const
{
  YAML::Node sec = findSec(section);
  if( !sec.IsDefined() ) {
    return 0;
  }
  return (int)sec.size();
}

std::string YamlConfig::getKeyName( const char *section, int idx ) const
{
  YAML::Node sec = findSec(section);
  if( sec.IsDefined() ) {
    int n = 0;
    for( YAML::const_iterator it=sec.begin(); it!=sec.end(); ++it ) {
      if( n==idx ) {
        return it->first.as<std::string>();
      }
      n++;
    }
  }
  fprintf(stderr, "YamlConfig::getKeyName: out of range [%s] idx=%d\n", section, idx);
  return "";
}

int YamlConfig::getInt( const char *section, const char *key, int defval ) const
{
  YAML::Node v = findVal(section, key);
  if( !v.IsDefined() ) {
    return defval;
  }
  try {
    return v.as<int>();
  } catch( const std::exception & ) {
  }
  try {
    return v.as<bool>() ? 1 : 0;
  } catch( const std::exception & ) {
  }
  fprintf(stderr, "YamlConfig::getInt: [%s] %s is not an integer, use default %d\n",
          section, key, defval);
  return defval;
}

std::string YamlConfig::getStr( const char *section, const char *key, const char *defval ) const
{
  YAML::Node v = findVal(section, key);
  if( !v.IsDefined() ) {
    return defval;
  }
  if( v.IsScalar() ) {
    return v.as<std::string>();
  }
  fprintf(stderr, "YamlConfig::getStr: [%s] %s is not a scalar, use default \"%s\"\n",
          section, key, defval);
  return defval;
}

YAML::Node YamlConfig::findSec( const char *section ) const
{
  if( loaded_ ) {
    for( YAML::const_iterator it=root_.begin(); it!=root_.end(); ++it ) {
      if( it->first.as<std::string>()==section&&it->second.IsMap() ) {
        return it->second;
      }
    }
  }
  return YAML::Node(YAML::NodeType::Undefined);
}

YAML::Node YamlConfig::findVal( const char *section, const char *key ) const
{
  YAML::Node sec = findSec(section);
  if( sec.IsDefined() ) {
    for( YAML::const_iterator it=sec.begin(); it!=sec.end(); ++it ) {
      if( it->first.as<std::string>()==key ) {
        return it->second;
      }
    }
  }
  return YAML::Node(YAML::NodeType::Undefined);
}
// yaml_main.cpp : YamlConfigの使用例(xlsx2yaml.py生成ファイルの読み出し)
#include <cstdio>
#include "yaml_config.h"

int main( int argc, char *argv[] )
{
  const char *fname = "hoge.yaml";
  if( argc>=2 ) {
    fname = argv[1];
  }

  YamlConfig cfg(fname);
  if( !cfg.isLoaded() ) {
    return 1;
  }

  // 先頭セクション名=パターン名
  std::string num0   = cfg.getSectionName(0);
  int         num1   = cfg.getInt(num0.c_str(), "NUMBER1", 0);
  int         num2 = cfg.getInt(num0.c_str(), "NUMBER2", 0);
  printf("num0=%s  NUMBER1=%d  NUMBER2=%d\n", num0.c_str(), num1, num2);

  for( int i=0; i<num2; i++ ) {
    char sec[64];
    snprintf(sec, sizeof(sec), "NO_%d", i);
    if( !cfg.hasSection(sec) ) {
      fprintf(stderr, "missing section [%s]\n", sec);
      return 1;
    }
    printf("[%s] name=%s\n", sec, cfg.getStr(sec, "name", "(none)").c_str());
    for( int k=0; k<cfg.getKeyNum(sec); k++ ) {
      std::string key = cfg.getKeyName(sec, k);
      if( key=="name" ) {
        continue;
      }
      printf("  %-20s = %d\n", key.c_str(), cfg.getInt(sec, key.c_str(), 0));
    }
  }

  return 0;
}

hoge:
  NUMBER1: 0
  NUMBER2: 2
NO_0:
  name: hoge_0.bin
  kokugo: 100
  sansuu: 1
  rika: 0
  syakai: 1
  eigo: 1
NO_1:
  name: hoge_0.bin
  kokugo: 100
  sansuu: 1
  rika: 0
  syakai: 1
  eigo: 1
# コンパイル
g++ -std=c++11 -O2 -Wall -I json/single_include -o json_test json_main.cpp json_config.cpp
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?