|
#include <iostream> |
|
#include <string> |
|
|
|
extern "C" { |
|
#include <jv.h> |
|
#include <jq.h> |
|
} |
|
|
|
using namespace std; |
|
|
|
/* |
|
* libjq の基本を理解したい。 |
|
* |
|
* 以下、jq の Wiki ページより |
|
* https://github.com/stedolan/jq/wiki/C-API:-jq-program-invocation |
|
* |
|
* Hint: the API in jv.h is for dealing with parsed JSON values, while the API in |
|
* jq.h is for evaluating jq programs. Use jq_init() to allocate a jq_state * |
|
* value, then use jq_compile_args() to compile a jq program, then use jq_start() |
|
* to get ready to evaluate it on one input value, and then repeatedly call |
|
* jq_next() to extract all the output values that the program produces. |
|
* Termination is indicated by jq_next() outputting an invalid value (without a |
|
* message), while errors are indicated by jq_next() outputting an invalid value |
|
* with a message. When done, use jq_teardown() to release the jq_state * value. |
|
* |
|
* まずはこの基本の処理を実装してみる。 |
|
*/ |
|
int main() { |
|
// テスト用の文字列 |
|
const string input = R"EOS( |
|
[ |
|
{ |
|
"name": "Ness", |
|
"age": 12, |
|
"origin": { "country": "Eagleland", "town": "Onett" } |
|
}, |
|
{ |
|
"name": "Paula", |
|
"age": 11, |
|
"origin": { "country": "Eagleland", "town": "Twoson" } |
|
} |
|
] |
|
)EOS"; |
|
// jq プログラム |
|
const string program = ".[] | {town: .origin.town}"; |
|
|
|
int ret = 0; |
|
// jq_state* の領域確保するために jq_init をコールする |
|
jq_state* jq = jq_init(); |
|
|
|
// jq プログラムをコンパイルする |
|
int compiled = jq_compile_args(jq, program.c_str(), jv_object()); |
|
|
|
if (!compiled) { |
|
cerr << "jq_compile_args failed." << endl; |
|
ret = 1; |
|
} else { |
|
// input のパーサーを準備する |
|
jv_parser* parser = jv_parser_new(/* flag */ 0); // TODO: flag の意味を調べる |
|
jv_parser_set_buf(parser, input.c_str(), input.size(), /* is_partial */ 0); // TODO: is_partial の意味を調べる |
|
|
|
/* |
|
* jq の main.c:main() ではここでループしているけれど、それは複数の |
|
* 入力を可能にするため |
|
* ここでは入力は input 一つなのでループしない |
|
*/ |
|
|
|
// 次の入力値を得る |
|
jv value = jv_parser_next(parser); |
|
|
|
if (jv_is_valid(value)) { |
|
// 入力値を評価するための準備をするために jq_start をコールする |
|
jq_start(jq, value, /* flags */ 0); // TODO: flags の意味を調べる |
|
|
|
// jq プログラムの出力値を得るために繰り返し jq_next をコールする |
|
jv result = jq_next(jq); |
|
|
|
// jq_is_valid な限り jq_next をコールする |
|
while (jv_is_valid(result)) { |
|
// 標準出力に出力したいので jv_dump_string する |
|
jv dumped = jv_dump_string(jv_copy(result), /* flags */ 0); // TODO: flags の意味を調べる |
|
cout << jv_string_value(dumped) << endl; |
|
jv_free(dumped); |
|
jv_free(result); |
|
result = jq_next(jq); |
|
} |
|
} else if (jv_invalid_has_msg(jv_copy(value))) { |
|
// パースエラー |
|
jv msg = jv_invalid_get_msg(value); |
|
cerr << jv_string_value(msg) << endl; |
|
jv_free(msg); |
|
ret = 2; |
|
} else { |
|
// System error |
|
ret = 3; |
|
} |
|
} |
|
|
|
// jq_state* を解放するために jq_teardown をコールする |
|
jq_teardown(&jq); |
|
return ret; |
|
} |