Skip to content

Instantly share code, notes, and snippets.

@meffie
Last active December 12, 2023 13:26
Show Gist options
  • Star 6 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save meffie/89d106a86b81c579c2b2a1895ffa18b0 to your computer and use it in GitHub Desktop.
Save meffie/89d106a86b81c579c2b2a1895ffa18b0 to your computer and use it in GitHub Desktop.
libyaml examples
/*
* Example libyaml emitter.
*
* This is a basic example to demonstrate how to convert raw data to a yaml
* stream using the libyaml emitter API. The example data to be converted is
* is a simple array of structs,
*
* struct fruit data[] = {
* {"apple", "red", 12},
* {"orange", "orange", 3},
* {"bannana", "yellow", 4},
* {"mango", "green", 1},
* {NULL, NULL, 0}
* };
*
* The exmaple data is converted into a yaml sequence of mapped values,
*
* $ ./emit
* ---
* fruit:
* - name: apple
* color: red
* count: 12
* - name: orange
* color: orange
* count: 3
* - name: bannana
* color: yellow
* count: 4
* - name: mango
* color: green
* count: 1
* ...
*
* This example can be built and run on linux with the commands:
*
* gcc -c emit.c -g -O0 -Wall
* gcc -o emit emit.o -lyaml
* ./emit
*
* See the libyaml project page http://pyyaml.org/wiki/LibYAML
*/
#include <yaml.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct fruit {
char *name;
char *color;
int count;
};
struct fruit data[] = {
{"apple", "red", 12},
{"orange", "orange", 3},
{"bannana", "yellow", 4},
{"mango", "green", 1},
{NULL, NULL, 0}
};
int main(int argc, char *argv[])
{
yaml_emitter_t emitter;
yaml_event_t event;
struct fruit *f;
char buffer[64];
yaml_emitter_initialize(&emitter);
yaml_emitter_set_output_file(&emitter, stdout);
yaml_stream_start_event_initialize(&event, YAML_UTF8_ENCODING);
if (!yaml_emitter_emit(&emitter, &event)) goto error;
yaml_document_start_event_initialize(&event, NULL, NULL, NULL, 0);
if (!yaml_emitter_emit(&emitter, &event)) goto error;
yaml_mapping_start_event_initialize(&event, NULL, (yaml_char_t *)YAML_MAP_TAG,
1, YAML_ANY_MAPPING_STYLE);
if (!yaml_emitter_emit(&emitter, &event)) goto error;
yaml_scalar_event_initialize(&event, NULL, (yaml_char_t *)YAML_STR_TAG,
(yaml_char_t *)"fruit", strlen("fruit"), 1, 0, YAML_PLAIN_SCALAR_STYLE);
if (!yaml_emitter_emit(&emitter, &event)) goto error;
yaml_sequence_start_event_initialize(&event, NULL, (yaml_char_t *)YAML_SEQ_TAG,
1, YAML_ANY_SEQUENCE_STYLE);
if (!yaml_emitter_emit(&emitter, &event)) goto error;
for (f = data; f->name; f++) {
yaml_mapping_start_event_initialize(&event, NULL, (yaml_char_t *)YAML_MAP_TAG,
1, YAML_ANY_MAPPING_STYLE);
if (!yaml_emitter_emit(&emitter, &event)) goto error;
yaml_scalar_event_initialize(&event, NULL, (yaml_char_t *)YAML_STR_TAG,
(yaml_char_t *)"name", strlen("name"), 1, 0, YAML_PLAIN_SCALAR_STYLE);
if (!yaml_emitter_emit(&emitter, &event)) goto error;
yaml_scalar_event_initialize(&event, NULL, (yaml_char_t *)YAML_STR_TAG,
(yaml_char_t *)f->name, strlen(f->name), 1, 0, YAML_PLAIN_SCALAR_STYLE);
if (!yaml_emitter_emit(&emitter, &event)) goto error;
yaml_scalar_event_initialize(&event, NULL, (yaml_char_t *)YAML_STR_TAG,
(yaml_char_t *)"color", strlen("color"), 1, 0, YAML_PLAIN_SCALAR_STYLE);
if (!yaml_emitter_emit(&emitter, &event)) goto error;
yaml_scalar_event_initialize(&event, NULL, (yaml_char_t *)YAML_STR_TAG,
(yaml_char_t *)f->color, strlen(f->color), 1, 0, YAML_PLAIN_SCALAR_STYLE);
if (!yaml_emitter_emit(&emitter, &event)) goto error;
yaml_scalar_event_initialize(&event, NULL, (yaml_char_t *)YAML_STR_TAG,
(yaml_char_t *)"count", strlen("count"), 1, 0, YAML_PLAIN_SCALAR_STYLE);
if (!yaml_emitter_emit(&emitter, &event)) goto error;
sprintf(buffer, "%d", f->count);
yaml_scalar_event_initialize(&event, NULL, (yaml_char_t *)YAML_INT_TAG,
(yaml_char_t *)buffer, strlen(buffer), 1, 0, YAML_PLAIN_SCALAR_STYLE);
if (!yaml_emitter_emit(&emitter, &event)) goto error;
yaml_mapping_end_event_initialize(&event);
if (!yaml_emitter_emit(&emitter, &event)) goto error;
}
yaml_sequence_end_event_initialize(&event);
if (!yaml_emitter_emit(&emitter, &event)) goto error;
yaml_mapping_end_event_initialize(&event);
if (!yaml_emitter_emit(&emitter, &event)) goto error;
yaml_document_end_event_initialize(&event, 0);
if (!yaml_emitter_emit(&emitter, &event)) goto error;
yaml_stream_end_event_initialize(&event);
if (!yaml_emitter_emit(&emitter, &event)) goto error;
yaml_emitter_delete(&emitter);
return 0;
error:
fprintf(stderr, "Failed to emit event %d: %s\n", event.type, emitter.problem);
yaml_emitter_delete(&emitter);
return 1;
}
all: emit scan parse
emit.o: emit.c
gcc -c emit.c -g -O0 -Wall
emit: emit.o
gcc -o emit emit.o -lyaml
scan.o: scan.c
gcc -c scan.c -g -O0 -Wall
scan: scan.o
gcc -o scan scan.o -lyaml
parse.o: parse.c
gcc -c parse.c -g -O0 -Wall
parse: parse.o
gcc -o parse parse.o -lyaml
clean:
rm -f emit scan parse
rm -f *.o core
/*
* Example libyaml parser.
*
* This is a basic example to demonstrate how to convert yaml to raw data
* using the libyaml emitter API. Example yaml data to be parsed:
*
* $ cat fruit.yaml
* ---
* fruit:
* - name: apple
* color: red
* count: 12
* - name: orange
* color: orange
* count: 3
* - name: bannana
* color: yellow
* count: 4
* - name: mango
* color: green
* count: 1
* ...
*
* $ ./parse < fruit.yaml
* data[0]={name=apple, color=red, count=12}
* data[1]={name=orange, color=orange, count=3}
* data[2]={name=bannana, color=yellow, count=4}
* data[3]={name=mango, color=green, count=1}
*
* See the libyaml project page http://pyyaml.org/wiki/LibYAML
*/
#include <yaml.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* Example data structure */
struct fruit {
char *name;
char *color;
int count;
};
/* Our example parser states. */
enum state_value {
START,
ACCEPT_SECTION,
ACCEPT_LIST,
ACCEPT_VALUES,
ACCEPT_KEY,
ACCEPT_VALUE,
STOP,
ERROR,
};
struct parser_state {
enum state_value state;
int accepted;
int error;
char *key;
char *value;
struct fruit data;
};
/*
* Consume yaml events generated by the libyaml parser to
* import our data into raw c data structures. Error processing
* is keep to a mimimum since this is just an example.
*
* The expected sequence of events is:
*
* stream ::= STREAM-START document* STREAM-END
* document ::= DOCUMENT-START section* DOCUMENT-END
* section ::= MAPPING-START (key list) MAPPING-END
* list ::= SEQUENCE-START values* SEQUENCE-END
* values ::= MAPPING-START (key value)* MAPPING-END
* key = SCALAR
* value = SCALAR
*
* For example:
*
* stream-start-event
* document-start-event
* mapping-start-event
* scalar-event={value="fruit", length=5}
* sequence-start-event
* mapping-start-event
* scalar-event={value="name", length=4}
* scalar-event={value="apple", length=5}
* scalar-event={value="color", length=5}
* scalar-event={value="red", length=3}
* scalar-event={value="count", length=5}
* scalar-event={value="12", length=2}
* mapping-end-event
* mapping-start-event
* scalar-event={value="name", length=4}
* scalar-event={value="orange", length=6}
* scalar-event={value="color", length=5}
* scalar-event={value="orange", length=6}
* scalar-event={value="count", length=5}
* scalar-event={value="3", length=1}
* mapping-end-event
* sequence-end-event
* mapping-end-event
* document-end-event
* stream-end-event
*
*/
int consume_event(struct parser_state *s, yaml_event_t *event)
{
s->accepted = 0;
switch (s->state) {
case START:
switch (event->type) {
case YAML_MAPPING_START_EVENT:
s->state = ACCEPT_SECTION;
break;
case YAML_SCALAR_EVENT:
fprintf(stderr, "Ignoring unexpected scalar: %s\n",
(char*)event->data.scalar.value);
break;
case YAML_SEQUENCE_START_EVENT:
fprintf(stderr, "Unexpected sequence.\n");
s->state = ERROR;
break;
case YAML_STREAM_END_EVENT: s->state = STOP; break;
default:
break;
}
break;
case ACCEPT_SECTION:
switch (event->type) {
case YAML_SCALAR_EVENT:
if (strcmp((char*)event->data.scalar.value, "fruit") == 0) {
s->state = ACCEPT_LIST;
} else {
fprintf(stderr, "Unexpected scalar: %s\n",
(char*)event->data.scalar.value);
s->state = ERROR;
}
break;
default:
fprintf(stderr, "Unexpected event while getting scalar: %d\n", event->type);
s->state = ERROR;
break;
}
break;
case ACCEPT_LIST:
switch (event->type) {
case YAML_SEQUENCE_START_EVENT: s->state = ACCEPT_VALUES; break;
default:
fprintf(stderr, "Unexpected event while getting sequence: %d\n", event->type);
s->state = ERROR;
break;
}
break;
case ACCEPT_VALUES:
switch (event->type) {
case YAML_MAPPING_START_EVENT:
memset(&(s->data), 0, sizeof(s->data));
s->state = ACCEPT_KEY;
break;
case YAML_SEQUENCE_END_EVENT: s->state = START; break;
case YAML_DOCUMENT_END_EVENT: s->state = START; break;
default:
fprintf(stderr, "Unexpected event while getting mapped values: %d\n",
event->type);
s->state = ERROR;
break;
}
break;
case ACCEPT_KEY:
switch (event->type) {
case YAML_SCALAR_EVENT:
s->key = strdup((char*)event->data.scalar.value);
s->state = ACCEPT_VALUE;
break;
case YAML_MAPPING_END_EVENT:
s->accepted = 1;
s->state = ACCEPT_VALUES;
break;
default:
fprintf(stderr, "Unexpected event while getting key: %d\n",
event->type);
s->state = ERROR;
break;
}
break;
case ACCEPT_VALUE:
switch (event->type) {
case YAML_SCALAR_EVENT:
s->value = (char*)event->data.scalar.value;
if (strcmp(s->key, "name") == 0) {
s->data.name = strdup((char*)s->value);
} else if (strcmp(s->key, "color") == 0) {
s->data.color = strdup((char*)s->value);
} else if (strcmp(s->key, "count") == 0) {
s->data.count = atoi(s->value);
} else {
fprintf(stderr, "Ignoring unknown key: %s\n", s->key);
}
free(s->key);
s->state = ACCEPT_KEY;
break;
default:
fprintf(stderr, "Unexpected event while getting value: %d\n",
event->type);
s->state = ERROR;
break;
}
break;
case ERROR:
case STOP:
break;
}
return (s->state == ERROR ? 0 : 1);
}
int main(int argc, char *argv[])
{
yaml_parser_t parser;
yaml_event_t event;
struct parser_state state = {.state=START, .accepted=0, .error=0};
struct fruit data[64];
int i = 0;
memset(data, 0, sizeof(data));
yaml_parser_initialize(&parser);
yaml_parser_set_input_file(&parser, stdin);
do {
if (!yaml_parser_parse(&parser, &event)) {
goto error;
}
if (!consume_event(&state, &event)) {
goto error;
}
if (state.accepted && i < sizeof(data)/sizeof(*data)) {
data[i].name = state.data.name;
data[i].color = state.data.color;
data[i].count = state.data.count;
printf("data[%d]={name=%s, color=%s, count=%d}\n",
i, data[i].name, data[i].color, data[i].count);
i++;
}
yaml_event_delete(&event);
} while (state.state != STOP);
yaml_parser_delete(&parser);
return 0;
error:
yaml_parser_delete(&parser);
return 1;
}
/*
* Example libyaml parser.
*
* This is a simple libyaml parser example which scans and prints
* the libyaml parser events.
*
*/
#include <yaml.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define INDENT " "
#define STRVAL(x) ((x) ? (char*)(x) : "")
void indent(int level)
{
int i;
for (i = 0; i < level; i++) {
printf("%s", INDENT);
}
}
void print_event(yaml_event_t *event)
{
static int level = 0;
switch (event->type) {
case YAML_NO_EVENT:
indent(level);
printf("no-event\n");
break;
case YAML_STREAM_START_EVENT:
indent(level++);
printf("stream-start-event\n");
break;
case YAML_STREAM_END_EVENT:
indent(--level);
printf("stream-end-event\n");
break;
case YAML_DOCUMENT_START_EVENT:
indent(level++);
printf("document-start-event\n");
break;
case YAML_DOCUMENT_END_EVENT:
indent(--level);
printf("document-end-event\n");
break;
case YAML_ALIAS_EVENT:
indent(level);
printf("alias-event\n");
break;
case YAML_SCALAR_EVENT:
indent(level);
printf("scalar-event={value=\"%s\", length=%d}\n",
STRVAL(event->data.scalar.value),
(int)event->data.scalar.length);
break;
case YAML_SEQUENCE_START_EVENT:
indent(level++);
printf("sequence-start-event\n");
break;
case YAML_SEQUENCE_END_EVENT:
indent(--level);
printf("sequence-end-event\n");
break;
case YAML_MAPPING_START_EVENT:
indent(level++);
printf("mapping-start-event\n");
break;
case YAML_MAPPING_END_EVENT:
indent(--level);
printf("mapping-end-event\n");
break;
}
if (level < 0) {
fprintf(stderr, "indentation underflow!\n");
level = 0;
}
}
int main(int argc, char *argv[])
{
yaml_parser_t parser;
yaml_event_t event;
yaml_event_type_t event_type;
yaml_parser_initialize(&parser);
yaml_parser_set_input_file(&parser, stdin);
do {
if (!yaml_parser_parse(&parser, &event))
goto error;
print_event(&event);
event_type = event.type;
yaml_event_delete(&event);
} while (event_type != YAML_STREAM_END_EVENT);
yaml_parser_delete(&parser);
return 0;
error:
fprintf(stderr, "Failed to parse: %s\n", parser.problem);
yaml_parser_delete(&parser);
return 1;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment