Анализ файлов YAML на С++
Я хочу, чтобы простой учебник показывал мне, чтобы загрузить файл yaml и проанализировать данные. Стиль Expat был бы велик, но любое решение, которое фактически показывает мне данные в какой-то форме, было бы полезно.
До сих пор я запускал несколько тестов в источнике yaml-0.1.1 для C, и я либо получал ошибку, либо выводил то, что так когда-либо или в run-emitter.c. Он читает в файле yaml и печатает его в STDOUT, он не создает текст через libyaml functions/structs. В случаях с ошибкой я не знаю, был ли файл bc плохим, или моя сборка некорректна (я ничего не модифицировал...) Файл был скопирован из yaml.org
Может ли кто-нибудь указать мне на учебник? (Я искал Google по крайней мере 30 минут, читая что-нибудь, что выглядело соответствующим) или имя lib, у которого есть хороший учебник или пример. Может быть, вы можете сказать мне, какой тест libyaml загружается в файлы и что-то с ним или почему я получил ошибки. В этом документе не объясняется, как использовать файл, только как его загрузить.
http://pyyaml.org/wiki/LibYAML#Documentation
Ответы
Ответ 1
Попробуйте yaml-cpp (как предложено этот вопрос) для С++ синтаксический анализатор.
Раскрытие информации: Я автор.
Пример синтаксиса (из Tutorial):
YAML::Node config = YAML::LoadFile("config.yaml");
if (config["lastLogin"]) {
std::cout << "Last logged in: " << config["lastLogin"].as<DateTime>() << "\n";
}
const std::string username = config["username"].as<std::string>();
const std::string password = config["password"].as<std::string>();
login(username, password);
config["lastLogin"] = getCurrentDateTime();
std::ofstream fout("config.yaml");
fout << config;
Ответ 2
Пример C - разбор дерева YAML на glib "N-arry tree" :
#include <yaml.h>
#include <stdio.h>
#include <glib.h>
void process_layer(yaml_parser_t *parser, GNode *data);
gboolean dump(GNode *n, gpointer data);
int main (int argc, char **argv) {
char *file_path = "test.yaml";
GNode *cfg = g_node_new(file_path);
yaml_parser_t parser;
FILE *source = fopen(file_path, "rb");
yaml_parser_initialize(&parser);
yaml_parser_set_input_file(&parser, source);
process_layer(&parser, cfg); // Recursive parsing
yaml_parser_delete(&parser);
fclose(source);
printf("Results iteration:\n");
g_node_traverse(cfg, G_PRE_ORDER, G_TRAVERSE_ALL, -1, dump, NULL);
g_node_destroy(cfg);
return(0);
}
enum storage_flags { VAR, VAL, SEQ }; // "Store as" switch
void process_layer(yaml_parser_t *parser, GNode *data) {
GNode *last_leaf = data;
yaml_event_t event;
int storage = VAR; // mapping cannot start with VAL definition w/o VAR key
while (1) {
yaml_parser_parse(parser, &event);
// Parse value either as a new leaf in the mapping
// or as a leaf value (one of them, in case it a sequence)
if (event.type == YAML_SCALAR_EVENT) {
if (storage) g_node_append_data(last_leaf, g_strdup((gchar*) event.data.scalar.value));
else last_leaf = g_node_append(data, g_node_new(g_strdup((gchar*) event.data.scalar.value)));
storage ^= VAL; // Flip VAR/VAL switch for the next event
}
// Sequence - all the following scalars will be appended to the last_leaf
else if (event.type == YAML_SEQUENCE_START_EVENT) storage = SEQ;
else if (event.type == YAML_SEQUENCE_END_EVENT) storage = VAR;
// depth += 1
else if (event.type == YAML_MAPPING_START_EVENT) {
process_layer(parser, last_leaf);
storage ^= VAL; // Flip VAR/VAL, w/o touching SEQ
}
// depth -= 1
else if (
event.type == YAML_MAPPING_END_EVENT
|| event.type == YAML_STREAM_END_EVENT
) break;
yaml_event_delete(&event);
}
}
gboolean dump(GNode *node, gpointer data) {
int i = g_node_depth(node);
while (--i) printf(" ");
printf("%s\n", (char*) node->data);
return(FALSE);
}
Ответ 3
Я написал учебное пособие в
http://wpsoftware.net/andrew/pages/libyaml.html.
Это охватывает основы использования libyaml в C, используя анализ на основе токенов и событий. Он содержит пример кода для вывода содержимого файла YAML.
Ответ 4
Поиск кода Google (в настоящее время несуществующий) для "yaml load lang: С++" дал это как первую ссылку: demo.cc:
#include <iyaml++.hh>
#include <tr1/memory>
#include <iostream>
#include <stdexcept>
using namespace std;
// What should libyaml++ do when a YAML entity is parsed?
// NOTE: if any of the event handlers is not defined, a respective default
// no-op handler will be used. For example, not defining on_eos() is
// equivalent to defining void on_eos() { }.
class my_handler : public yaml::event_handler {
void on_string(const std::string& s) { cout << "parsed string: " << s << endl; }
void on_integer(const std::string& s) { cout << "parsed integer: " << s << endl; }
void on_sequence_begin() { cout << "parsed sequence-begin." << endl; }
void on_mapping_begin() { cout << "parsed mapping-begin." << endl; }
void on_sequence_end() { cout << "parsed sequence-end." << endl; }
void on_mapping_end() { cout << "parsed mapping-end." << endl; }
void on_document() { cout << "parsed document." << endl; }
void on_pair() { cout << "parsed pair." << endl; }
void on_eos() { cout << "parsed eos." << endl; }
};
// ok then, now that i know how to behave on each YAML entity encountered, just
// give me a stream to parse!
int main(int argc, char* argv[])
{
tr1::shared_ptr<my_handler> handler(new my_handler());
while( cin ) {
try { yaml::load(cin, handler); } // throws on syntax error
catch( const runtime_error& e ) {
cerr << e.what() << endl;
}
}
return 0;
}