pantoniou / libfyaml

Fully feature complete YAML parser and emitter, supporting the latest YAML spec and passing the full YAML testsuite.
MIT License
241 stars 74 forks source link

fy_document_scanf() and scalar value #55

Closed majklik closed 2 years ago

majklik commented 2 years ago

I tried using the fy_document_scanf() function to read a scalar value from an array and it looks like it doesn't work? This test code:

#include <stdlib.h>

#include <libfyaml.h>

int main(int argc, char *argv[])
{
    static const char *yaml = 
        "---\n"
        " - aaa\n"
        " - bbb\n"
        " - ccc\n";
    static const char *json = "{\"bla\":[\"AAA\",\"BBB\",\"CCC\"]}";

    struct fy_document *fyd1, *fyd2;
    char sout[10];

    if (!(fyd1=fy_document_build_from_string(NULL, yaml, (size_t)-1))) return EXIT_FAILURE;
    if (!(fyd2=fy_document_build_from_string(NULL, json, (size_t)-1))) return EXIT_FAILURE;

    if (fy_document_scanf(fyd1, "/[1] %10s", sout)!=1) return EXIT_FAILURE;
    printf("sout.yaml='%s'\n", sout);

    if (fy_document_scanf(fyd2, "/bla/[-2] %10s", sout)!=1) return EXIT_FAILURE;
    printf("sout.json='%s'\n", sout);

    return EXIT_SUCCESS;
}

I looked in the library and after a small intervention it looks better, I can also read the value from a document containing only one scalar (path /):

--- src/lib/fy-doc.c.orig   2022-06-11 19:57:44.000000000 +0100
+++ src/lib/fy-doc.c    2022-06-12 07:51:53.000000000 +0100
@@ -4070,9 +4070,10 @@
            __func__, __LINE__, fy_node_get_path(fyn), (int)(e - s), s); */
    fyn = fy_node_follow_aliases(fyn, flags, true);

-   /* scalar can't match (it has no key) */
+   /* scalar can be only last element in the path (it has no key) */
    if (fy_node_is_scalar(fyn)) {
-       fyn = NULL;
+       if (*s)
+           fyn = NULL; /* not end of the path - fail */
        goto out;
    }

Please, is there a documented search path format?

pantoniou commented 2 years ago

a4230d9c06282df798bd408b0e2353d83b895e2a incorporates your fix and I also added a couple of tests to make sure it never happens again.

Thanks.