Re: Parsing YAML into key:value tree nodes with C library

"Felix Krause" <[email protected]> Mon, 16 Aug 2021 21:01:02 +0200
Newsgroups gmane.text.yaml.general
Message-ID <[email protected]>
--===============5712187596356079265==
Content-Type: multipart/alternative;
 boundary="=_MailMate_BFAAB32E-E71F-42A8-89EA-4EB5BE0EB2BF_="
Content-Transfer-Encoding: 8bit


--=_MailMate_BFAAB32E-E71F-42A8-89EA-4EB5BE0EB2BF_=
Content-Type: text/plain; charset="UTF-8"; format=flowed
Content-Transfer-Encoding: 8bit

Hi David,

libyaml does contain such an API: 
https://github.com/yaml/libyaml/blob/master/include/yaml.h#L1457

This gives you a `yaml_document_t` with a root node accessible via 
`yaml_document_get_root_node`. The API is not well-documented but 
basically nodes can refer to sub-nodes via an `int` index and you use 
`yaml_document_get_node` to retrieve subnodes.

mapping and sequence nodes store their children in a stack structure – 
you iterate them via

```
for (yaml_node_item_t *cur = node->data.sequence.start; cur != 
node->data.sequence.top; ++cur) {
    // ...
}
```

Now if you load in a YAML that contains a mapping with scalar key/value 
pairs, your root node will be a mapping and the subnodes will be 
scalars.

---

If you want a more convenient API, I did write this utility in the past: 
https://github.com/flyx/libyaml_constructor

It is a code generator that reads in a C header containing type 
definitions and autogenerates code that loads YAML into those types 
(using libyaml). With this, you can define how your YAML structure must 
look via C types and some annotations in the given header.

That tool was a part of a project which I abandoned, hence I never did a 
proper release. However it did work quite well for all I can remember. 
The compile-time dependency on libclang (to parse your C header) may be 
a bit of a hurdle.


Cheers,
Felix

--=_MailMate_BFAAB32E-E71F-42A8-89EA-4EB5BE0EB2BF_=
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

<!DOCTYPE html>
<html>
<head>
<meta http-equiv=3D"Content-Type" content=3D"text/xhtml; charset=3Dutf-8"=
>
</head>
<body>
<div style=3D"font-family:sans-serif"><div style=3D"white-space:normal">
<p dir=3D"auto">Hi David,</p>

<p dir=3D"auto">libyaml does contain such an API: <a href=3D"https://gith=
ub.com/yaml/libyaml/blob/master/include/yaml.h#L1457" style=3D"color:#398=
3C4">https://github.com/yaml/libyaml/blob/master/include/yaml.h#L1457</a>=
</p>

<p dir=3D"auto">This gives you a <code style=3D"background-color:#F7F7F7;=
 border-radius:3px; margin:0; padding:0 0.4em" bgcolor=3D"#F7F7F7">yaml_d=
ocument_t</code> with a root node accessible via <code style=3D"backgroun=
d-color:#F7F7F7; border-radius:3px; margin:0; padding:0 0.4em" bgcolor=3D=
"#F7F7F7">yaml_document_get_root_node</code>. The API is not well-documen=
ted but basically nodes can refer to sub-nodes via an <code style=3D"back=
ground-color:#F7F7F7; border-radius:3px; margin:0; padding:0 0.4em" bgcol=
or=3D"#F7F7F7">int</code> index and you use <code style=3D"background-col=
or:#F7F7F7; border-radius:3px; margin:0; padding:0 0.4em" bgcolor=3D"#F7F=
7F7">yaml_document_get_node</code> to retrieve subnodes.</p>

<p dir=3D"auto">mapping and sequence nodes store their children in a stac=
k structure =E2=80=93 you iterate them via</p>

<pre style=3D"background-color:#F7F7F7; border-radius:5px 5px 5px 5px; ma=
rgin-left:15px; margin-right:15px; max-width:90vw; overflow-x:auto; paddi=
ng:5px" bgcolor=3D"#F7F7F7"><code style=3D"background-color:#F7F7F7; bord=
er-radius:3px; margin:0; padding:0" bgcolor=3D"#F7F7F7">for (yaml_node_it=
em_t *cur =3D node-&gt;data.sequence.start; cur !=3D node-&gt;data.sequen=
ce.top; ++cur) {
   // ...
}
</code></pre>

<p dir=3D"auto">Now if you load in a YAML that contains a mapping with sc=
alar key/value pairs, your root node will be a mapping and the subnodes w=
ill be scalars.</p>

<hr style=3D"background:#333; background-image:linear-gradient(to right, =
#ccc, #333, #ccc); border:0; height:1px" height=3D"1">

<p dir=3D"auto">If you want a more convenient API, I did write this utili=
ty in the past: <a href=3D"https://github.com/flyx/libyaml_constructor" s=
tyle=3D"color:#3983C4">https://github.com/flyx/libyaml_constructor</a></p=
>

<p dir=3D"auto">It is a code generator that reads in a C header containin=
g type definitions and autogenerates code that loads YAML into those type=
s (using libyaml). With this, you can define how your YAML structure must=
 look via C types and some annotations in the given header.</p>

<p dir=3D"auto">That tool was a part of a project which I abandoned, henc=
e I never did a proper release. However it did work quite well for all I =
can remember. The compile-time dependency on libclang (to parse your C he=
ader) may be a bit of a hurdle.</p>

<p dir=3D"auto">Cheers,<br>
Felix</p>
</div>
</div>
</body>
</html>

--=_MailMate_BFAAB32E-E71F-42A8-89EA-4EB5BE0EB2BF_=--


--===============5712187596356079265==
Content-Type: text/plain; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: inline


--===============5712187596356079265==
Content-Type: text/plain; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: inline

_______________________________________________
Yaml-core mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/yaml-core

--===============5712187596356079265==--