おなじみC/C++から使えるJSONライブラリを紹介するコーナー。まずは過去のまとめ。
- 最速と言われる JSON パーサ「rapidjson」が本当に爆速なのか試してみた。
- C言語から使えるJSONパーサ、parson が思った以上に良い仕事をしている。
- 僕がboost::asioとboost::property_treeを使いHTTPプロキシ環境下で非同期にGoogle Search APIから検索するまでにやった、たった一つの事。
- C言語から使えるJSONパーサ、JSMNを試してみた。
- 何も見ずにC++でjsonパーサが書けるか試してみた。
- ヘッダファイルだけでC++から使えるJSONパーサ「picojson」が凄い!
- C言語から使えるJSONパーサ、jansson がとても直感的で良い
ずいぶんと前から GitHub Trend の C++ 言語枠には登場していましたが、このコーナーでレビューしてませんでした。
GitHub - nlohmann/json: JSON for Modern C++
JSON for Modern C++
https://github.com/nlohmann/json
特徴(目指すところ)は以下の通り。
- Python の様な操作感で、ファーストクラスオブジェクトの様に扱える事
- シングルヘッダで他のライブラリに依存しない事
- テストカバレッジ 100% を目指す
触ってみた感じ picojson に近いです。picojson よりもオペレータが沢山定義されているのでバイナリにした際には picojson よりも大きくなるかもしれません。今日はこの json.hpp を使って、wandbox の shebang コマンドを作ってみました。
wandbox は画面で入力したソースコードを多種多様なコンパイラやインタプリタを使って実行してくれるウェブサービスです。API が公開されているので扱いやすいインタフェースを自分で作る事ができます。
wandbox/API.rst at master - melpon/wandbox - GitHub
API API home is melpon.org/wandbox/api GET /list.json List compiler informations. Parameter Nothing....
https://github.com/melpon/wandbox/blob/master/kennel2/API.rst
#include <iostream>
#include <fstream>
#include "json.hpp"
#include <curl/curl.h>
size_t
write_cb(char *ptr, size_t size, size_t nmemb, std::string *strm) {
size_t len = size * nmemb;
strm->append(ptr, len);
return len;
}
int
main(int argc, char* argv[]) {
if (argc < 3) {
std::cerr << "usage: " << argv[0] << " [compiler] [file] [arguments...]" << std::endl;
return 1;
}
std::stringstream ss;
if (std::string(argv[2]) != "-") {
std::ifstream in(argv[2], std::ifstream::in);
std::string line;
std::getline(in, line);
ss << in.rdbuf();
} else {
ss << std::cin.rdbuf();
}
nlohmann::json obj;
obj["code"] = ss.str();
ss.str("");
ss.clear(std::stringstream::goodbit);
obj["compiler"] = argv[1];
for (int i = 3; i < argc; i++) {
if (i > 3) ss << "\n";
ss << argv[i];
}
obj["runtime-option-raw"] = ss.str();
ss.str("");
ss.clear(std::stringstream::goodbit);
ss << obj;
std::string chunk;
CURLcode ret;
CURL *curl = curl_easy_init();
if (curl == NULL) {
std::cerr << "curl_easy_init() failed" << std::endl;
return 1;
}
std::string data = ss.str();
struct curl_slist *headerlist = NULL;
headerlist = curl_slist_append(headerlist, "Content-Type: application/json");
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headerlist);
curl_easy_setopt(curl, CURLOPT_URL, "http://melpon.org/wandbox/api/compile.json");
curl_easy_setopt(curl, CURLOPT_POST, 1);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, data.c_str());
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_cb);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &chunk);
ret = curl_easy_perform(curl);
curl_easy_cleanup(curl);
if (ret != CURLE_OK) {
std::cerr << "curl_easy_perform() failed" << std::endl;
curl_easy_strerror(ret);
return 1;
}
obj = nlohmann::json::parse(chunk);
try {
std::cout << obj["program_message"].get<std::string>();
} catch(std::exception& e) {
std::cerr << obj["compiler_message"].get<std::string>() << std::endl;
}
int code;
ss.str("");
ss.clear(std::stringstream::goodbit);
ss << obj["status"];
ss >> code;
return code;
}
使い方は shebang として設定するだけで、第一引数にコンパイラもしくはインタプリタ名を設定します。
#!/usr/bin/wandbox-run clang-head
#include <stdio.h>
int
main(int argc, char* argv[]) {
puts("hello clang");
return 0;
}
こんな風に書いて実行権限を付けて実行すれば hello clang
が表示されます。C言語のソースなのにコンパイラをインストールしなくても実行できて便利ですね(そうでもない)。なお扱えるコンパイラやインタプリタは wandbox から参照して下さい。ソースコードは以下に置いておきます。
mattn/wandbox-run · GitHub
https://github.com/mattn/wandbox-run