From 849b588550d527c643d83cd89773688ad860a8e5 Mon Sep 17 00:00:00 2001 From: Joao Paulo Magalhaes Date: Mon, 20 Jan 2025 20:08:15 +0000 Subject: [PATCH] re #476 clarify that Byte Order Marks are not accepted --- .github/workflows/infra.yml | 50 ++++++++++++++++++ .github/workflows/infra.ys | 45 +++++++++++++++++ README.md | 1 + doc/Doxyfile | 3 +- doc/index.rst | 3 +- ext/c4core | 2 +- samples/quickstart.cpp | 26 +++++++--- src/c4/yml/parse.cpp | 84 +++++++++++++++---------------- src/c4/yml/parse.hpp | 78 +++++++++++++++++++--------- src/c4/yml/parse_engine.def.hpp | 5 +- src/c4/yml/reference_resolver.cpp | 3 ++ src/c4/yml/tree.cpp | 4 ++ tbump.toml | 3 ++ 13 files changed, 228 insertions(+), 79 deletions(-) diff --git a/.github/workflows/infra.yml b/.github/workflows/infra.yml index b9b1802d..493ef24c 100644 --- a/.github/workflows/infra.yml +++ b/.github/workflows/infra.yml @@ -42,3 +42,53 @@ jobs: echo "ERROR: generated workflows are out of date" fi exit $status + check_doc: + if: always() + continue-on-error: false + runs-on: ubuntu-24.04 + env: + DOXY_VERSION: 1.13.2 + DOXY_DIR: /tmp/doxydir/bin + steps: + - name: checkout (action) + uses: actions/checkout@v4 + with: + submodules: recursive + fetch-depth: 0 + - name: install python + uses: actions/setup-python@v5 + with: + python-version: 3.9 + - name: install requirements + run: pip install -r doc/requirements.txt + - name: install wget + run: | + apt-get update + apt install -y wget + - name: install doxygen + run: | + ver=$DOXY_VERSION + uver=$(echo $ver | sed "s:\.:_:g") + name=$(dirname $DOXY_DIR) + dst=$(dirname $name) + url="https://github.com/doxygen/doxygen/releases/download/Release_$uver/doxygen-$ver.linux.bin.tar.gz" + ( \ + cd $dst ; \ + wget $url ; \ + tar xvfz $(basename $url) ; \ + ls -lFhp | grep dox ; \ + mv -v doxygen-$ver $name ; \ + ) + - name: doxygen version + run: | + export PATH=$DOXY_DIR:$PATH + which doxygen + doxygen --version + - name: check doxygen docs + run: | + export PATH=$DOXY_DIR:$PATH + make -C doc doxy + - name: check sphinx + run: | + export PATH=$DOXY_DIR:$PATH + make -C doc doc diff --git a/.github/workflows/infra.ys b/.github/workflows/infra.ys index f9ecbe6a..d370067d 100644 --- a/.github/workflows/infra.ys +++ b/.github/workflows/infra.ys @@ -30,3 +30,48 @@ jobs: echo "ERROR: generated workflows are out of date" fi exit $status + + check_doc: + :: setup-job('infra' 'check_doxygen') + runs-on: ubuntu-24.04 + env: + DOXY_VERSION: 1.13.2 + DOXY_DIR: /tmp/doxydir/bin + steps: + - :: checkout-action + - name: install python + uses: actions/setup-python@v5 + with: {python-version: 3.9} + - name: install requirements + run: pip install -r doc/requirements.txt + - name: install wget + run: | + apt-get update + apt install -y wget + - name: install doxygen + run: | + ver=$DOXY_VERSION + uver=$(echo $ver | sed "s:\.:_:g") + name=$(dirname $DOXY_DIR) + dst=$(dirname $name) + url="https://github.com/doxygen/doxygen/releases/download/Release_$uver/doxygen-$ver.linux.bin.tar.gz" + ( \ + cd $dst ; \ + wget $url ; \ + tar xvfz $(basename $url) ; \ + ls -lFhp | grep dox ; \ + mv -v doxygen-$ver $name ; \ + ) + - name: doxygen version + run: | + export PATH=$DOXY_DIR:$PATH + which doxygen + doxygen --version + - name: check doxygen docs + run: | + export PATH=$DOXY_DIR:$PATH + make -C doc doxy + - name: check sphinx + run: | + export PATH=$DOXY_DIR:$PATH + make -C doc doc diff --git a/README.md b/README.md index b5a66daf..b29342b7 100644 --- a/README.md +++ b/README.md @@ -247,6 +247,7 @@ build and run this executable using any of the build samples, eg the ```cpp // Parse YAML code in place, potentially mutating the buffer: +// (Byte Order Marks are not accepted) char yml_buf[] = "{foo: 1, bar: [2, 3], john: doe}"; ryml::Tree tree = ryml::parse_in_place(yml_buf); diff --git a/doc/Doxyfile b/doc/Doxyfile index 7e87cea9..dac117cf 100644 --- a/doc/Doxyfile +++ b/doc/Doxyfile @@ -907,7 +907,7 @@ WARN_IF_UNDOC_ENUM_VAL = YES # Possible values are: NO, YES, FAIL_ON_WARNINGS and FAIL_ON_WARNINGS_PRINT. # The default value is: NO. -WARN_AS_ERROR = NO +WARN_AS_ERROR = FAIL_ON_WARNINGS # The WARN_FORMAT tag determines the format of the warning messages that doxygen # can produce. The string should contain the $file, $line, and $text tags, which @@ -959,6 +959,7 @@ INPUT = \ ../ext/c4core/src/c4/charconv.hpp \ ../ext/c4core/src/c4/format.hpp \ ../ext/c4core/src/c4/base64.hpp \ + ../ext/c4core/src/c4/utf.hpp \ ../ext/c4core/src/c4/std/string.hpp \ ../ext/c4core/src/c4/std/string_view.hpp \ ../ext/c4core/src/c4/std/vector.hpp \ diff --git a/doc/index.rst b/doc/index.rst index 67bd8871..a172c6cd 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -72,11 +72,12 @@ API teaser Here's a short teaser from the API quickstart overview (`see on doxygen `_ / `see full code on github -`_): +`_): .. code-block:: c++ // Parse YAML code in place, potentially mutating the buffer: + // (Byte Order Marks are not accepted) char yml_buf[] = "{foo: 1, bar: [2, 3], john: doe}"; ryml::Tree tree = ryml::parse_in_place(yml_buf); diff --git a/ext/c4core b/ext/c4core index 4b7c1a14..083e35b1 160000 --- a/ext/c4core +++ b/ext/c4core @@ -1 +1 @@ -Subproject commit 4b7c1a1401f642910c544243a2d8f6e0d879c3b8 +Subproject commit 083e35b124ba80c00dd51f62bcc2bdd1e5ef4341 diff --git a/samples/quickstart.cpp b/samples/quickstart.cpp index 06724aca..86696807 100644 --- a/samples/quickstart.cpp +++ b/samples/quickstart.cpp @@ -16,6 +16,7 @@ // For this sample, we will be using std interop, so... #include // optional header, provided for std:: interop #include // needed for the examples below + #include // needed for the examples below #endif // these are needed for the examples below @@ -269,6 +270,7 @@ struct ScopedErrorHandlerExample : public ErrorHandlerExample void sample_lightning_overview() { // Parse YAML code in place, potentially mutating the buffer: + // (NOTE: Byte Order Marks are not accepted) char yml_buf[] = "{foo: 1, bar: [2, 3], john: doe}"; ryml::Tree tree = ryml::parse_in_place(yml_buf); @@ -317,6 +319,7 @@ void sample_lightning_overview() void sample_quick_overview() { // Parse YAML code in place, potentially mutating the buffer: + // (NOTE: Byte Order Marks are not accepted) char yml_buf[] = R"( foo: 1 bar: [2, 3] @@ -1731,8 +1734,8 @@ void sample_substr() * * ryml offers no overload to directly parse files from disk; it only * parses source buffers (which may be mutable or immutable). It is - * up to the caller to load the file contents into a buffer before - * parsing with ryml. + * up to the caller to load the file contents **without Byte Order + * Marks** into a buffer before parsing with ryml. * * But that does not mean that loading a file is unimportant. There * are many ways to achieve this in C++, but for convenience and to @@ -1751,8 +1754,9 @@ void sample_parse_file() // now we can load it into a std::string (for example): { - std::string contents = file_get_contents(filename); - ryml::Tree tree = ryml::parse_in_arena(ryml::to_csubstr(contents)); // immutable (csubstr) overload + std::string buffer = file_get_contents(filename); + ryml::csubstr contents = ryml::skip_bom(ryml::to_csubstr(buffer)); // skip any Byte Order Marks + ryml::Tree tree = ryml::parse_in_arena(contents); // immutable (csubstr) overload CHECK(tree["foo"].val() == "1"); CHECK(tree["bar"][0].val() == "2"); CHECK(tree["bar"][1].val() == "3"); @@ -1760,8 +1764,9 @@ void sample_parse_file() // or we can use a vector instead: { - std::vector contents = file_get_contents>(filename); - ryml::Tree tree = ryml::parse_in_place(ryml::to_substr(contents)); // mutable (csubstr) overload + std::vector buffer = file_get_contents>(filename); + ryml::substr contents = ryml::skip_bom(ryml::to_substr(buffer)); // skip any Byte Order Marks + ryml::Tree tree = ryml::parse_in_place(contents); // mutable (csubstr) overload CHECK(tree["foo"].val() == "1"); CHECK(tree["bar"][0].val() == "2"); CHECK(tree["bar"][1].val() == "3"); @@ -5302,7 +5307,9 @@ void ErrorHandlerExample::check_effect(bool committed) const // helper functions for sample_parse_file() C4_SUPPRESS_WARNING_MSVC_WITH_PUSH(4996) // fopen: this function may be unsafe -/** load a file from disk into an existing CharContainer */ +/** load a file from disk into an existing CharContainer. Note that + * rapidyaml does not accept Byte Order Marks; use @ref c4::skip_bom() + * if the file may contain a Byte Order Mark. */ template size_t file_get_contents(const char *filename, CharContainer *v) { @@ -5321,7 +5328,10 @@ size_t file_get_contents(const char *filename, CharContainer *v) return v->size(); } -/** load a file from disk and return a newly created CharContainer */ +/** load a file from disk and return a newly created + * CharContainer. Note that rapidyaml does not accept Byte Order + * Marks; use @ref c4::skip_bom() if the file may contain a Byte Order + * Mark. */ template CharContainer file_get_contents(const char *filename) { diff --git a/src/c4/yml/parse.cpp b/src/c4/yml/parse.cpp index 6651fa9f..c6f347bd 100644 --- a/src/c4/yml/parse.cpp +++ b/src/c4/yml/parse.cpp @@ -59,74 +59,74 @@ Tree parse_in_place(Parser *parser, substr yaml // this is vertically aligned to highlight the parameter differences. void parse_in_place(csubstr filename, substr yaml, Tree *t, id_type node_id) { RYML_CHECK(t); Parser::handler_type event_handler(t->callbacks()); Parser parser(&event_handler); parse_in_place(&parser, filename, yaml, t, node_id); } void parse_in_place( substr yaml, Tree *t, id_type node_id) { RYML_CHECK(t); Parser::handler_type event_handler(t->callbacks()); Parser parser(&event_handler); parse_in_place(&parser, {} , yaml, t, node_id); } -void parse_in_place(csubstr filename, substr yaml, Tree *t ) { RYML_CHECK(t); Parser::handler_type event_handler(t->callbacks()); Parser parser(&event_handler); parse_in_place(&parser, filename, yaml, t, t->root_id()); } -void parse_in_place( substr yaml, Tree *t ) { RYML_CHECK(t); Parser::handler_type event_handler(t->callbacks()); Parser parser(&event_handler); parse_in_place(&parser, {} , yaml, t, t->root_id()); } -void parse_in_place(csubstr filename, substr yaml, NodeRef node ) { RYML_CHECK(!node.invalid()); Parser::handler_type event_handler(node.tree()->callbacks()); Parser parser(&event_handler); parse_in_place(&parser, filename, yaml, node.tree(), node.id()); } -void parse_in_place( substr yaml, NodeRef node ) { RYML_CHECK(!node.invalid()); Parser::handler_type event_handler(node.tree()->callbacks()); Parser parser(&event_handler); parse_in_place(&parser, {} , yaml, node.tree(), node.id()); } -Tree parse_in_place(csubstr filename, substr yaml ) { Parser::handler_type event_handler; Parser parser(&event_handler); Tree tree(parser.callbacks()); parse_in_place(&parser, filename, yaml, &tree, tree.root_id()); return tree; } -Tree parse_in_place( substr yaml ) { Parser::handler_type event_handler; Parser parser(&event_handler); Tree tree(parser.callbacks()); parse_in_place(&parser, {} , yaml, &tree, tree.root_id()); return tree; } +void parse_in_place(csubstr filename, substr yaml, Tree *t ) { RYML_CHECK(t); Parser::handler_type event_handler(t->callbacks()); Parser parser(&event_handler); parse_in_place(&parser, filename, yaml, t, t->root_id()); } +void parse_in_place( substr yaml, Tree *t ) { RYML_CHECK(t); Parser::handler_type event_handler(t->callbacks()); Parser parser(&event_handler); parse_in_place(&parser, {} , yaml, t, t->root_id()); } +void parse_in_place(csubstr filename, substr yaml, NodeRef node ) { RYML_CHECK(!node.invalid()); Parser::handler_type event_handler(node.tree()->callbacks()); Parser parser(&event_handler); parse_in_place(&parser, filename, yaml, node.tree(), node.id()); } +void parse_in_place( substr yaml, NodeRef node ) { RYML_CHECK(!node.invalid()); Parser::handler_type event_handler(node.tree()->callbacks()); Parser parser(&event_handler); parse_in_place(&parser, {} , yaml, node.tree(), node.id()); } +Tree parse_in_place(csubstr filename, substr yaml ) { Parser::handler_type event_handler; Parser parser(&event_handler); Tree tree(parser.callbacks()); parse_in_place(&parser, filename, yaml, &tree, tree.root_id()); return tree; } +Tree parse_in_place( substr yaml ) { Parser::handler_type event_handler; Parser parser(&event_handler); Tree tree(parser.callbacks()); parse_in_place(&parser, {} , yaml, &tree, tree.root_id()); return tree; } // this is vertically aligned to highlight the parameter differences. void parse_json_in_place(Parser *parser, substr json, Tree *t, id_type node_id) { parse_json_in_place(parser, {}, json, t, node_id); } -void parse_json_in_place(Parser *parser, csubstr filename, substr json, Tree *t ) { RYML_CHECK(t); parse_json_in_place(parser, filename, json, t, t->root_id()); } -void parse_json_in_place(Parser *parser, substr json, Tree *t ) { RYML_CHECK(t); parse_json_in_place(parser, {} , json, t, t->root_id()); } -void parse_json_in_place(Parser *parser, csubstr filename, substr json, NodeRef node ) { RYML_CHECK(!node.invalid()); parse_json_in_place(parser, filename, json, node.tree(), node.id()); } -void parse_json_in_place(Parser *parser, substr json, NodeRef node ) { RYML_CHECK(!node.invalid()); parse_json_in_place(parser, {} , json, node.tree(), node.id()); } -Tree parse_json_in_place(Parser *parser, csubstr filename, substr json ) { RYML_CHECK(parser); RYML_CHECK(parser->m_evt_handler); Tree tree(parser->callbacks()); parse_json_in_place(parser, filename, json, &tree, tree.root_id()); return tree; } -Tree parse_json_in_place(Parser *parser, substr json ) { RYML_CHECK(parser); RYML_CHECK(parser->m_evt_handler); Tree tree(parser->callbacks()); parse_json_in_place(parser, {} , json, &tree, tree.root_id()); return tree; } +void parse_json_in_place(Parser *parser, csubstr filename, substr json, Tree *t ) { RYML_CHECK(t); parse_json_in_place(parser, filename, json, t, t->root_id()); } +void parse_json_in_place(Parser *parser, substr json, Tree *t ) { RYML_CHECK(t); parse_json_in_place(parser, {} , json, t, t->root_id()); } +void parse_json_in_place(Parser *parser, csubstr filename, substr json, NodeRef node ) { RYML_CHECK(!node.invalid()); parse_json_in_place(parser, filename, json, node.tree(), node.id()); } +void parse_json_in_place(Parser *parser, substr json, NodeRef node ) { RYML_CHECK(!node.invalid()); parse_json_in_place(parser, {} , json, node.tree(), node.id()); } +Tree parse_json_in_place(Parser *parser, csubstr filename, substr json ) { RYML_CHECK(parser); RYML_CHECK(parser->m_evt_handler); Tree tree(parser->callbacks()); parse_json_in_place(parser, filename, json, &tree, tree.root_id()); return tree; } +Tree parse_json_in_place(Parser *parser, substr json ) { RYML_CHECK(parser); RYML_CHECK(parser->m_evt_handler); Tree tree(parser->callbacks()); parse_json_in_place(parser, {} , json, &tree, tree.root_id()); return tree; } // this is vertically aligned to highlight the parameter differences. void parse_json_in_place(csubstr filename, substr json, Tree *t, id_type node_id) { RYML_CHECK(t); Parser::handler_type event_handler(t->callbacks()); Parser parser(&event_handler); parse_json_in_place(&parser, filename, json, t, node_id); } void parse_json_in_place( substr json, Tree *t, id_type node_id) { RYML_CHECK(t); Parser::handler_type event_handler(t->callbacks()); Parser parser(&event_handler); parse_json_in_place(&parser, {} , json, t, node_id); } -void parse_json_in_place(csubstr filename, substr json, Tree *t ) { RYML_CHECK(t); Parser::handler_type event_handler(t->callbacks()); Parser parser(&event_handler); parse_json_in_place(&parser, filename, json, t, t->root_id()); } -void parse_json_in_place( substr json, Tree *t ) { RYML_CHECK(t); Parser::handler_type event_handler(t->callbacks()); Parser parser(&event_handler); parse_json_in_place(&parser, {} , json, t, t->root_id()); } -void parse_json_in_place(csubstr filename, substr json, NodeRef node ) { RYML_CHECK(!node.invalid()); Parser::handler_type event_handler(node.tree()->callbacks()); Parser parser(&event_handler); parse_json_in_place(&parser, filename, json, node.tree(), node.id()); } -void parse_json_in_place( substr json, NodeRef node ) { RYML_CHECK(!node.invalid()); Parser::handler_type event_handler(node.tree()->callbacks()); Parser parser(&event_handler); parse_json_in_place(&parser, {} , json, node.tree(), node.id()); } -Tree parse_json_in_place(csubstr filename, substr json ) { Parser::handler_type event_handler; Parser parser(&event_handler); Tree tree(parser.callbacks()); parse_json_in_place(&parser, filename, json, &tree, tree.root_id()); return tree; } -Tree parse_json_in_place( substr json ) { Parser::handler_type event_handler; Parser parser(&event_handler); Tree tree(parser.callbacks()); parse_json_in_place(&parser, {} , json, &tree, tree.root_id()); return tree; } +void parse_json_in_place(csubstr filename, substr json, Tree *t ) { RYML_CHECK(t); Parser::handler_type event_handler(t->callbacks()); Parser parser(&event_handler); parse_json_in_place(&parser, filename, json, t, t->root_id()); } +void parse_json_in_place( substr json, Tree *t ) { RYML_CHECK(t); Parser::handler_type event_handler(t->callbacks()); Parser parser(&event_handler); parse_json_in_place(&parser, {} , json, t, t->root_id()); } +void parse_json_in_place(csubstr filename, substr json, NodeRef node ) { RYML_CHECK(!node.invalid()); Parser::handler_type event_handler(node.tree()->callbacks()); Parser parser(&event_handler); parse_json_in_place(&parser, filename, json, node.tree(), node.id()); } +void parse_json_in_place( substr json, NodeRef node ) { RYML_CHECK(!node.invalid()); Parser::handler_type event_handler(node.tree()->callbacks()); Parser parser(&event_handler); parse_json_in_place(&parser, {} , json, node.tree(), node.id()); } +Tree parse_json_in_place(csubstr filename, substr json ) { Parser::handler_type event_handler; Parser parser(&event_handler); Tree tree(parser.callbacks()); parse_json_in_place(&parser, filename, json, &tree, tree.root_id()); return tree; } +Tree parse_json_in_place( substr json ) { Parser::handler_type event_handler; Parser parser(&event_handler); Tree tree(parser.callbacks()); parse_json_in_place(&parser, {} , json, &tree, tree.root_id()); return tree; } // this is vertically aligned to highlight the parameter differences. void parse_in_arena(Parser *parser, csubstr filename, csubstr yaml, Tree *t, id_type node_id) { RYML_CHECK(t); substr src = t->copy_to_arena(yaml); parse_in_place(parser, filename, src, t, node_id); } void parse_in_arena(Parser *parser, csubstr yaml, Tree *t, id_type node_id) { RYML_CHECK(t); substr src = t->copy_to_arena(yaml); parse_in_place(parser, {} , src, t, node_id); } -void parse_in_arena(Parser *parser, csubstr filename, csubstr yaml, Tree *t ) { RYML_CHECK(t); substr src = t->copy_to_arena(yaml); parse_in_place(parser, filename, src, t, t->root_id()); } -void parse_in_arena(Parser *parser, csubstr yaml, Tree *t ) { RYML_CHECK(t); substr src = t->copy_to_arena(yaml); parse_in_place(parser, {} , src, t, t->root_id()); } -void parse_in_arena(Parser *parser, csubstr filename, csubstr yaml, NodeRef node ) { RYML_CHECK(!node.invalid()); substr src = node.tree()->copy_to_arena(yaml); parse_in_place(parser, filename, src, node.tree(), node.id()); } -void parse_in_arena(Parser *parser, csubstr yaml, NodeRef node ) { RYML_CHECK(!node.invalid()); substr src = node.tree()->copy_to_arena(yaml); parse_in_place(parser, {} , src, node.tree(), node.id()); } -Tree parse_in_arena(Parser *parser, csubstr filename, csubstr yaml ) { RYML_CHECK(parser); RYML_CHECK(parser->m_evt_handler); Tree tree(parser->callbacks()); substr src = tree.copy_to_arena(yaml); parse_in_place(parser, filename, src, &tree, tree.root_id()); return tree; } -Tree parse_in_arena(Parser *parser, csubstr yaml ) { RYML_CHECK(parser); RYML_CHECK(parser->m_evt_handler); Tree tree(parser->callbacks()); substr src = tree.copy_to_arena(yaml); parse_in_place(parser, {} , src, &tree, tree.root_id()); return tree; } +void parse_in_arena(Parser *parser, csubstr filename, csubstr yaml, Tree *t ) { RYML_CHECK(t); substr src = t->copy_to_arena(yaml); parse_in_place(parser, filename, src, t, t->root_id()); } +void parse_in_arena(Parser *parser, csubstr yaml, Tree *t ) { RYML_CHECK(t); substr src = t->copy_to_arena(yaml); parse_in_place(parser, {} , src, t, t->root_id()); } +void parse_in_arena(Parser *parser, csubstr filename, csubstr yaml, NodeRef node ) { RYML_CHECK(!node.invalid()); substr src = node.tree()->copy_to_arena(yaml); parse_in_place(parser, filename, src, node.tree(), node.id()); } +void parse_in_arena(Parser *parser, csubstr yaml, NodeRef node ) { RYML_CHECK(!node.invalid()); substr src = node.tree()->copy_to_arena(yaml); parse_in_place(parser, {} , src, node.tree(), node.id()); } +Tree parse_in_arena(Parser *parser, csubstr filename, csubstr yaml ) { RYML_CHECK(parser); RYML_CHECK(parser->m_evt_handler); Tree tree(parser->callbacks()); substr src = tree.copy_to_arena(yaml); parse_in_place(parser, filename, src, &tree, tree.root_id()); return tree; } +Tree parse_in_arena(Parser *parser, csubstr yaml ) { RYML_CHECK(parser); RYML_CHECK(parser->m_evt_handler); Tree tree(parser->callbacks()); substr src = tree.copy_to_arena(yaml); parse_in_place(parser, {} , src, &tree, tree.root_id()); return tree; } // this is vertically aligned to highlight the parameter differences. void parse_in_arena(csubstr filename, csubstr yaml, Tree *t, id_type node_id) { RYML_CHECK(t); Parser::handler_type event_handler(t->callbacks()); Parser parser(&event_handler); substr src = t->copy_to_arena(yaml); parse_in_place(&parser, filename, src, t, node_id); } void parse_in_arena( csubstr yaml, Tree *t, id_type node_id) { RYML_CHECK(t); Parser::handler_type event_handler(t->callbacks()); Parser parser(&event_handler); substr src = t->copy_to_arena(yaml); parse_in_place(&parser, {} , src, t, node_id); } -void parse_in_arena(csubstr filename, csubstr yaml, Tree *t ) { RYML_CHECK(t); Parser::handler_type event_handler(t->callbacks()); Parser parser(&event_handler); substr src = t->copy_to_arena(yaml); parse_in_place(&parser, filename, src, t, t->root_id()); } -void parse_in_arena( csubstr yaml, Tree *t ) { RYML_CHECK(t); Parser::handler_type event_handler(t->callbacks()); Parser parser(&event_handler); substr src = t->copy_to_arena(yaml); parse_in_place(&parser, {} , src, t, t->root_id()); } -void parse_in_arena(csubstr filename, csubstr yaml, NodeRef node ) { RYML_CHECK(!node.invalid()); Parser::handler_type event_handler(node.tree()->callbacks()); Parser parser(&event_handler); substr src = node.tree()->copy_to_arena(yaml); parse_in_place(&parser, filename, src, node.tree(), node.id()); } -void parse_in_arena( csubstr yaml, NodeRef node ) { RYML_CHECK(!node.invalid()); Parser::handler_type event_handler(node.tree()->callbacks()); Parser parser(&event_handler); substr src = node.tree()->copy_to_arena(yaml); parse_in_place(&parser, {} , src, node.tree(), node.id()); } -Tree parse_in_arena(csubstr filename, csubstr yaml ) { Parser::handler_type event_handler; Parser parser(&event_handler); Tree tree(parser.callbacks()); substr src = tree.copy_to_arena(yaml); parse_in_place(&parser, filename, src, &tree, tree.root_id()); return tree; } -Tree parse_in_arena( csubstr yaml ) { Parser::handler_type event_handler; Parser parser(&event_handler); Tree tree(parser.callbacks()); substr src = tree.copy_to_arena(yaml); parse_in_place(&parser, {} , src, &tree, tree.root_id()); return tree; } +void parse_in_arena(csubstr filename, csubstr yaml, Tree *t ) { RYML_CHECK(t); Parser::handler_type event_handler(t->callbacks()); Parser parser(&event_handler); substr src = t->copy_to_arena(yaml); parse_in_place(&parser, filename, src, t, t->root_id()); } +void parse_in_arena( csubstr yaml, Tree *t ) { RYML_CHECK(t); Parser::handler_type event_handler(t->callbacks()); Parser parser(&event_handler); substr src = t->copy_to_arena(yaml); parse_in_place(&parser, {} , src, t, t->root_id()); } +void parse_in_arena(csubstr filename, csubstr yaml, NodeRef node ) { RYML_CHECK(!node.invalid()); Parser::handler_type event_handler(node.tree()->callbacks()); Parser parser(&event_handler); substr src = node.tree()->copy_to_arena(yaml); parse_in_place(&parser, filename, src, node.tree(), node.id()); } +void parse_in_arena( csubstr yaml, NodeRef node ) { RYML_CHECK(!node.invalid()); Parser::handler_type event_handler(node.tree()->callbacks()); Parser parser(&event_handler); substr src = node.tree()->copy_to_arena(yaml); parse_in_place(&parser, {} , src, node.tree(), node.id()); } +Tree parse_in_arena(csubstr filename, csubstr yaml ) { Parser::handler_type event_handler; Parser parser(&event_handler); Tree tree(parser.callbacks()); substr src = tree.copy_to_arena(yaml); parse_in_place(&parser, filename, src, &tree, tree.root_id()); return tree; } +Tree parse_in_arena( csubstr yaml ) { Parser::handler_type event_handler; Parser parser(&event_handler); Tree tree(parser.callbacks()); substr src = tree.copy_to_arena(yaml); parse_in_place(&parser, {} , src, &tree, tree.root_id()); return tree; } // this is vertically aligned to highlight the parameter differences. void parse_json_in_arena(Parser *parser, csubstr filename, csubstr json, Tree *t, id_type node_id) { RYML_CHECK(t); substr src = t->copy_to_arena(json); parse_json_in_place(parser, filename, src, t, node_id); } void parse_json_in_arena(Parser *parser, csubstr json, Tree *t, id_type node_id) { RYML_CHECK(t); substr src = t->copy_to_arena(json); parse_json_in_place(parser, {} , src, t, node_id); } -void parse_json_in_arena(Parser *parser, csubstr filename, csubstr json, Tree *t ) { RYML_CHECK(t); substr src = t->copy_to_arena(json); parse_json_in_place(parser, filename, src, t, t->root_id()); } -void parse_json_in_arena(Parser *parser, csubstr json, Tree *t ) { RYML_CHECK(t); substr src = t->copy_to_arena(json); parse_json_in_place(parser, {} , src, t, t->root_id()); } -void parse_json_in_arena(Parser *parser, csubstr filename, csubstr json, NodeRef node ) { RYML_CHECK(!node.invalid()); substr src = node.tree()->copy_to_arena(json); parse_json_in_place(parser, filename, src, node.tree(), node.id()); } -void parse_json_in_arena(Parser *parser, csubstr json, NodeRef node ) { RYML_CHECK(!node.invalid()); substr src = node.tree()->copy_to_arena(json); parse_json_in_place(parser, {} , src, node.tree(), node.id()); } -Tree parse_json_in_arena(Parser *parser, csubstr filename, csubstr json ) { RYML_CHECK(parser); RYML_CHECK(parser->m_evt_handler); Tree tree(parser->callbacks()); substr src = tree.copy_to_arena(json); parse_json_in_place(parser, filename, src, &tree, tree.root_id()); return tree; } -Tree parse_json_in_arena(Parser *parser, csubstr json ) { RYML_CHECK(parser); RYML_CHECK(parser->m_evt_handler); Tree tree(parser->callbacks()); substr src = tree.copy_to_arena(json); parse_json_in_place(parser, {} , src, &tree, tree.root_id()); return tree; } +void parse_json_in_arena(Parser *parser, csubstr filename, csubstr json, Tree *t ) { RYML_CHECK(t); substr src = t->copy_to_arena(json); parse_json_in_place(parser, filename, src, t, t->root_id()); } +void parse_json_in_arena(Parser *parser, csubstr json, Tree *t ) { RYML_CHECK(t); substr src = t->copy_to_arena(json); parse_json_in_place(parser, {} , src, t, t->root_id()); } +void parse_json_in_arena(Parser *parser, csubstr filename, csubstr json, NodeRef node ) { RYML_CHECK(!node.invalid()); substr src = node.tree()->copy_to_arena(json); parse_json_in_place(parser, filename, src, node.tree(), node.id()); } +void parse_json_in_arena(Parser *parser, csubstr json, NodeRef node ) { RYML_CHECK(!node.invalid()); substr src = node.tree()->copy_to_arena(json); parse_json_in_place(parser, {} , src, node.tree(), node.id()); } +Tree parse_json_in_arena(Parser *parser, csubstr filename, csubstr json ) { RYML_CHECK(parser); RYML_CHECK(parser->m_evt_handler); Tree tree(parser->callbacks()); substr src = tree.copy_to_arena(json); parse_json_in_place(parser, filename, src, &tree, tree.root_id()); return tree; } +Tree parse_json_in_arena(Parser *parser, csubstr json ) { RYML_CHECK(parser); RYML_CHECK(parser->m_evt_handler); Tree tree(parser->callbacks()); substr src = tree.copy_to_arena(json); parse_json_in_place(parser, {} , src, &tree, tree.root_id()); return tree; } // this is vertically aligned to highlight the parameter differences. void parse_json_in_arena(csubstr filename, csubstr json, Tree *t, id_type node_id) { RYML_CHECK(t); Parser::handler_type event_handler(t->callbacks()); Parser parser(&event_handler); substr src = t->copy_to_arena(json); parse_json_in_place(&parser, filename, src, t, node_id); } void parse_json_in_arena( csubstr json, Tree *t, id_type node_id) { RYML_CHECK(t); Parser::handler_type event_handler(t->callbacks()); Parser parser(&event_handler); substr src = t->copy_to_arena(json); parse_json_in_place(&parser, {} , src, t, node_id); } -void parse_json_in_arena(csubstr filename, csubstr json, Tree *t ) { RYML_CHECK(t); Parser::handler_type event_handler(t->callbacks()); Parser parser(&event_handler); substr src = t->copy_to_arena(json); parse_json_in_place(&parser, filename, src, t, t->root_id()); } -void parse_json_in_arena( csubstr json, Tree *t ) { RYML_CHECK(t); Parser::handler_type event_handler(t->callbacks()); Parser parser(&event_handler); substr src = t->copy_to_arena(json); parse_json_in_place(&parser, {} , src, t, t->root_id()); } -void parse_json_in_arena(csubstr filename, csubstr json, NodeRef node ) { RYML_CHECK(!node.invalid()); Parser::handler_type event_handler(node.tree()->callbacks()); Parser parser(&event_handler); substr src = node.tree()->copy_to_arena(json); parse_json_in_place(&parser, filename, src, node.tree(), node.id()); } -void parse_json_in_arena( csubstr json, NodeRef node ) { RYML_CHECK(!node.invalid()); Parser::handler_type event_handler(node.tree()->callbacks()); Parser parser(&event_handler); substr src = node.tree()->copy_to_arena(json); parse_json_in_place(&parser, {} , src, node.tree(), node.id()); } -Tree parse_json_in_arena(csubstr filename, csubstr json ) { Parser::handler_type event_handler; Parser parser(&event_handler); Tree tree(parser.callbacks()); substr src = tree.copy_to_arena(json); parse_json_in_place(&parser, filename, src, &tree, tree.root_id()); return tree; } -Tree parse_json_in_arena( csubstr json ) { Parser::handler_type event_handler; Parser parser(&event_handler); Tree tree(parser.callbacks()); substr src = tree.copy_to_arena(json); parse_json_in_place(&parser, {} , src, &tree, tree.root_id()); return tree; } +void parse_json_in_arena(csubstr filename, csubstr json, Tree *t ) { RYML_CHECK(t); Parser::handler_type event_handler(t->callbacks()); Parser parser(&event_handler); substr src = t->copy_to_arena(json); parse_json_in_place(&parser, filename, src, t, t->root_id()); } +void parse_json_in_arena( csubstr json, Tree *t ) { RYML_CHECK(t); Parser::handler_type event_handler(t->callbacks()); Parser parser(&event_handler); substr src = t->copy_to_arena(json); parse_json_in_place(&parser, {} , src, t, t->root_id()); } +void parse_json_in_arena(csubstr filename, csubstr json, NodeRef node ) { RYML_CHECK(!node.invalid()); Parser::handler_type event_handler(node.tree()->callbacks()); Parser parser(&event_handler); substr src = node.tree()->copy_to_arena(json); parse_json_in_place(&parser, filename, src, node.tree(), node.id()); } +void parse_json_in_arena( csubstr json, NodeRef node ) { RYML_CHECK(!node.invalid()); Parser::handler_type event_handler(node.tree()->callbacks()); Parser parser(&event_handler); substr src = node.tree()->copy_to_arena(json); parse_json_in_place(&parser, {} , src, node.tree(), node.id()); } +Tree parse_json_in_arena(csubstr filename, csubstr json ) { Parser::handler_type event_handler; Parser parser(&event_handler); Tree tree(parser.callbacks()); substr src = tree.copy_to_arena(json); parse_json_in_place(&parser, filename, src, &tree, tree.root_id()); return tree; } +Tree parse_json_in_arena( csubstr json ) { Parser::handler_type event_handler; Parser parser(&event_handler); Tree tree(parser.callbacks()); substr src = tree.copy_to_arena(json); parse_json_in_place(&parser, {} , src, &tree, tree.root_id()); return tree; } RYML_EXPORT C4_NO_INLINE size_t _find_last_newline_and_larger_indentation(csubstr s, size_t indentation) noexcept diff --git a/src/c4/yml/parse.hpp b/src/c4/yml/parse.hpp index fd5a0ba1..7ef7e1df 100644 --- a/src/c4/yml/parse.hpp +++ b/src/c4/yml/parse.hpp @@ -21,13 +21,20 @@ RYML_EXPORT id_type estimate_tree_capacity(csubstr src); // NOLINT /** This is the main ryml parser, where the parser events are handled * to create a ryml tree. * - * @warning Because the ryml @ref Tree does not accept containers as - * keys, this class cannot successfully parse YAML source with this - * feature. See @ref ParseEngine for more details. + * @warning This class cannot parse YAML where there are container + * keys. This is not a limitation of the @ref ParseEngine, but of the + * @ref EventHandlerTree, which is present because the @ref Tree does + * not accept containers as keys. However, the @ref ParseEngine *can* + * parse container keys; consult its documentation for more details. * * @see ParserOptions * @see ParseEngine * @see EventHandlerTree + * + * @warning Byte Order Marks are not accepted. Before calling any + * parse facility, any existing Byte Order Marks should be skipped + * from the YAML string. See @ref c4::skip_bom(), which can be used to + * achieve this. * */ using Parser = RYML_EXPORT ParseEngine; @@ -36,12 +43,17 @@ using Parser = RYML_EXPORT ParseEngine; /** @defgroup doc_parse_in_place__with_existing_parser Parse in place with existing parser * - * @brief parse a mutable YAML source buffer. Scalars requiring - * filtering are mutated in place (except in the rare cases where the - * filtered scalar is longer than the original scalar, or where - * filtering was disabled before the call). These overloads accept an - * existing parser object, and provide the opportunity to use special - * parser options. + * @brief parse a mutable YAML source buffer (re)using an existing + * parser. Scalars requiring filtering are mutated in place (except in + * the rare cases where the filtered scalar is longer than the + * original scalar, or where filtering was disabled before the + * call). These overloads accept an existing parser object, and + * provide the opportunity to use special parser options. + * + * @warning Byte Order Marks are not accepted. Before calling any + * parse facility, any existing Byte Order Marks should be skipped + * from the YAML string. See @ref c4::skip_bom(), which can be used to + * achieve this. * * @see ParserOptions * @@ -51,27 +63,27 @@ using Parser = RYML_EXPORT ParseEngine; // this is vertically aligned to highlight the parameter differences. RYML_EXPORT void parse_in_place(Parser *parser, csubstr filename, substr yaml, Tree *t, id_type node_id); /**< (1) parse YAML into an existing tree node. - * - * The filename will be used in any error messages - * arising during the parse. The callbacks in the - * tree are kept, and used to allocate - * the tree members, if any allocation is required. */ + * + * The filename will be used in any error messages + * arising during the parse. The callbacks in the + * tree are kept, and used to allocate + * the tree members, if any allocation is required. */ RYML_EXPORT void parse_in_place(Parser *parser, substr yaml, Tree *t, id_type node_id); /**< (2) like (1) but no filename will be reported */ -RYML_EXPORT void parse_in_place(Parser *parser, csubstr filename, substr yaml, Tree *t ); /**< (3) parse YAML into an existing tree, into its root node. - * - * The filename will be used in any error messages - * arising during the parse. The callbacks in the - * tree are kept, and used to allocate - * the tree members, if any allocation is required. */ +RYML_EXPORT void parse_in_place(Parser *parser, csubstr filename, substr yaml, Tree *t ); /**< (3) parse YAML into the root node of an existing tree. + * + * The filename will be used in any error messages + * arising during the parse. The callbacks in the + * tree are kept, and used to allocate + * the tree members, if any allocation is required. */ RYML_EXPORT void parse_in_place(Parser *parser, substr yaml, Tree *t ); /**< (4) like (3) but no filename will be reported */ RYML_EXPORT void parse_in_place(Parser *parser, csubstr filename, substr yaml, NodeRef node ); /**< (5) like (1) but the node is given as a NodeRef */ RYML_EXPORT void parse_in_place(Parser *parser, substr yaml, NodeRef node ); /**< (6) like (5) but no filename will be reported */ RYML_EXPORT Tree parse_in_place(Parser *parser, csubstr filename, substr yaml ); /**< (7) create a new tree, and parse YAML into its root node. - * - * The filename will be used in any error messages - * arising during the parse. The tree is created with - * the callbacks currently in the parser. - */ + * + * The filename will be used in any error messages + * arising during the parse. The tree is created with + * the callbacks currently in the parser. + */ RYML_EXPORT Tree parse_in_place(Parser *parser, substr yaml ); /**< (8) like (7) but no filename will be reported */ @@ -104,6 +116,11 @@ RYML_EXPORT Tree parse_json_in_place(Parser *parser, substr js * class. If you need access to any of these properties, use * the appropriate overload from @ref doc_parse_in_place__with_existing_parser * + * @warning Byte Order Marks are not accepted. Before calling any + * parse facility, any existing Byte Order Marks should be skipped + * from the YAML string. See @ref c4::skip_bom(), which can be used to + * achieve this. + * * @{ */ @@ -171,6 +188,11 @@ RYML_EXPORT Tree parse_json_in_place( substr json * parser.parse_in_arena(immutable_buffer); // ok * ``` * + * @warning Byte Order Marks are not accepted. Before calling any + * parse facility, any existing Byte Order Marks should be skipped + * from the YAML string. See @ref c4::skip_bom(), which can be used to + * achieve this. + * * @{ */ @@ -265,6 +287,11 @@ RYML_DEPRECATED(RYML_DONT_PARSE_SUBSTR_IN_ARENA) Tree parse_json_in_arena(Parser * parser.parse_in_arena(immutable_buffer); // ok * ``` * + * @warning Byte Order Marks are not accepted. Before calling any + * parse facility, any existing Byte Order Marks should be skipped + * from the YAML string. See @ref c4::skip_bom(), which can be used to + * achieve this. + * * @{ */ @@ -288,6 +315,7 @@ RYML_EXPORT void parse_json_in_arena( csubstr json, NodeRef nod RYML_EXPORT Tree parse_json_in_arena(csubstr filename, csubstr json ); ///< (7) create a new tree, and parse JSON into its root node. RYML_EXPORT Tree parse_json_in_arena( csubstr json ); ///< (8) like (7) but no filename will be reported + /* READ THE DEPRECATION NOTE! * * All of the functions below are intentionally left undefined, to diff --git a/src/c4/yml/parse_engine.def.hpp b/src/c4/yml/parse_engine.def.hpp index 0e378b01..28add7a8 100644 --- a/src/c4/yml/parse_engine.def.hpp +++ b/src/c4/yml/parse_engine.def.hpp @@ -5,13 +5,13 @@ #include "c4/error.hpp" #include "c4/charconv.hpp" #include "c4/utf.hpp" -#include #include #include "c4/yml/detail/parser_dbg.hpp" #include "c4/yml/filter_processor.hpp" #ifdef RYML_DBG +#include #include "c4/yml/detail/print.hpp" #endif @@ -2246,6 +2246,7 @@ void ParseEngine::_scan_block(ScannedBlock *C4_RESTRICT sb, size_t //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- +/** @cond dev */ // a debugging scaffold: #if 0 @@ -8137,6 +8138,7 @@ template void ParseEngine::parse_in_place_ev(csubstr filename, substr src) { _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, m_evt_handler->m_stack.size() >= 1); + _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, first_non_bom(src) == 0u); // source must not contain byte order marks m_file = filename; m_buf = src; _reset(); @@ -8200,6 +8202,7 @@ void ParseEngine::parse_in_place_ev(csubstr filename, substr src) _end_stream(); m_evt_handler->finish_parse(); } +/** @endcond */ } // namespace yml } // namespace c4 diff --git a/src/c4/yml/reference_resolver.cpp b/src/c4/yml/reference_resolver.cpp index 392699a0..2c9e62b0 100644 --- a/src/c4/yml/reference_resolver.cpp +++ b/src/c4/yml/reference_resolver.cpp @@ -12,6 +12,8 @@ namespace c4 { namespace yml { +/** @cond dev */ + id_type ReferenceResolver::count_anchors_and_refs_(id_type n) { id_type c = 0; @@ -291,6 +293,7 @@ void ReferenceResolver::resolve(Tree *t_) _c4dbgp("resolving references: finished"); } +/** @endcond */ } // namespace ryml } // namespace c4 diff --git a/src/c4/yml/tree.cpp b/src/c4/yml/tree.cpp index 584aec50..fe68df8f 100644 --- a/src/c4/yml/tree.cpp +++ b/src/c4/yml/tree.cpp @@ -514,6 +514,7 @@ void Tree::_rem_hierarchy(id_type i) } //----------------------------------------------------------------------------- +/** @cond dev */ id_type Tree::_do_reorder(id_type *node, id_type count) { // swap this node if it's not in place @@ -533,6 +534,7 @@ id_type Tree::_do_reorder(id_type *node, id_type count) } return count; } +/** @endcond */ void Tree::reorder() { @@ -542,6 +544,7 @@ void Tree::reorder() //----------------------------------------------------------------------------- +/** @cond dev */ void Tree::_swap(id_type n_, id_type m_) { _RYML_CB_ASSERT(m_callbacks, (parent(n_) != NONE) || type(n_) == NOTYPE); @@ -773,6 +776,7 @@ void Tree::_swap_props(id_type n_, id_type m_) std::swap(n.m_key, m.m_key); std::swap(n.m_val, m.m_val); } +/** @endcond */ //----------------------------------------------------------------------------- void Tree::move(id_type node, id_type after) diff --git a/tbump.toml b/tbump.toml index 055be7eb..35776986 100644 --- a/tbump.toml +++ b/tbump.toml @@ -50,6 +50,9 @@ search = ".*{current_version}.*" src = "doc/sphinx_*.rst" search = ".*{current_version}.*" [[file]] +src = "doc/index.rst" +search = ".*{current_version}.*" +[[file]] src = "src/c4/yml/version.hpp" search = "#define RYML_VERSION ['\"]{current_version}['\"]" [[file]]