File: quickstart-ints.cpp

package info (click to toggle)
rapidyaml 0.10.0%2Bds-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 53,676 kB
  • sloc: cpp: 73,851; python: 3,678; javascript: 414; xml: 253; makefile: 96; sh: 44
file content (159 lines) | stat: -rw-r--r-- 6,289 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
// This file shows a quick example of parsing YAML to an int events
// buffer. Since this functionality is meant to implement in other
// programming languages, the code is kept very simple, and using only
// C-like idioms.

// ryml can be used as a single header, or as a simple library:
#if defined(RYML_SINGLE_HEADER) // using the single header directly in the executable
    #define RYML_SINGLE_HDR_DEFINE_NOW
    #ifndef RYML_SINGLE_HEADER_INTS
        #include <ryml_all.hpp>
    #else
        #include <ryml_ints.hpp>
    #endif
#elif defined(RYML_SINGLE_HEADER_LIB) // using the single header from a library
    #ifndef RYML_SINGLE_HEADER_INTS
        #include <ryml_all.hpp>
    #else
        #include <ryml_ints.hpp>
    #endif
#else
#include <c4/yml/parse_engine.def.hpp>
#endif

#ifndef RYML_SINGLE_HEADER_INTS
#include <c4/yml/extra/event_handler_ints.hpp>
#endif


// NOLINTBEGIN(hicpp-signed-bitwise)

int main(int, const char *[])
{
    using namespace c4::yml::extra::ievt;
    auto PSTR_ = c4::yml::extra::ievt::PSTR; // PSTR does not work in windows
    // YAML code to be parsed in place
    char yaml[] = "do: a deer, a female deer\n"
                  "re: a drop of golden sun\n"
                  "mi: a name I call myself\n"
                  "fa: a long long way to run\n";
    // these are the event values we expect
    const int expected_events[] = {
        BSTR,
        BDOC,
        VAL_|BMAP|BLCK,
        //
        KEY_|SCLR|PLAI,        0,  2,  // "do"
        VAL_|SCLR|PLAI|PSTR_,  4, 21,  // "a deer, a female deer"
        //
        KEY_|SCLR|PLAI|PSTR_, 26,  2,  // "re"
        VAL_|SCLR|PLAI|PSTR_, 30, 20,  // "a drop of golden sun"
        //
        KEY_|SCLR|PLAI|PSTR_, 51,  2,  // "mi"
        VAL_|SCLR|PLAI|PSTR_, 55, 20,  // "a name I call myself"
        //
        KEY_|SCLR|PLAI|PSTR_, 76,  2,  // "fa"
        VAL_|SCLR|PLAI|PSTR_, 80, 22,  // "a long long way to run"
        //
        EMAP|PSTR_,
        EDOC,
        ESTR,
    };

    /* the output should be this:
     *
     * success! YAML requires event size 30, estimated=49
     * pos=0	event[0]:	0x1
     * pos=1	event[1]:	0x4
     * pos=2	event[2]:	0x110010
     * pos=3	event[3]:	0x80500 	str=(0,2)	'do'
     * pos=6	event[4]:	0x900500	str=(4,21)	'a deer, a female deer'
     * pos=9	event[5]:	0x880500	str=(26,2)	're'
     * pos=12	event[6]:	0x900500	str=(30,20)	'a drop of golden sun'
     * pos=15	event[7]:	0x880500	str=(51,2)	'mi'
     * pos=18	event[8]:	0x900500	str=(55,20)	'a name I call myself'
     * pos=21	event[9]:	0x880500	str=(76,2)	'fa'
     * pos=24	event[10]:	0x900500	str=(80,22)	'a long long way to run'
     * pos=27	event[11]:	0x800020
     * pos=28	event[12]:	0x8
     * pos=29	event[13]:	0x2
     */

    // buffer to where we will write the events
    constexpr const int events_size = 100;
    int events[events_size] = {};
    static_assert(events_size >= sizeof(expected_events)/sizeof(expected_events[0]), "buffer too small");
    // buffer for placing any scalars/tags that cannot be filtered
    // in-place
    char arena[100] = {};


    // ensure the estimation will succeed vs required size
    int estimated_size = c4::yml::extra::estimate_events_ints_size(yaml);
    if (estimated_size > events_size)
    {
        printf("the estimated size (%d) will not fit the events array (%d)\n", estimated_size, events_size); // LCOV_EXCL_LINE
        return 1; // LCOV_EXCL_LINE
    }

    // parse now. the parse should succeed (because the YAML above is
    // legit), but if there were would be a parse error, we would get
    // the default behavior which is abort on error, since we did not
    // set up the error callbacks
    c4::yml::extra::EventHandlerInts handler;
    c4::yml::ParseEngine<c4::yml::extra::EventHandlerInts> parser(&handler);
    handler.reset(yaml, arena, events, estimated_size); // note we pass the estimated size!
    parser.parse_in_place_ev("filename", yaml);

    // the YAML was successfully parsed, but it may happen that it
    // requires more events than may fit in the buffer. so we need to
    // check that it actually fits (this is mandatory):
    if(!handler.fits_buffers())
    {
        printf("error: buffers too small:   required_evt=%d actual_evt=%d\n   required_arena=%zu actual_arena=%zu\n",     // LCOV_EXCL_LINE
               handler.required_size_events(), estimated_size, handler.required_size_arena(), c4::to_csubstr(arena).len); // LCOV_EXCL_LINE
        // WATCHOUT: if you want to retry the parse, you need to set
        // up the source buffer again, because it is invalidated from
        // being parsed in place. refer to the doxygen documentation
        // for more details.
        return 1; // LCOV_EXCL_LINE
    }

    // done!
    printf("success! YAML requires event size %d, estimated=%d (required_arena=%zu actual=%zu)\n",                    // LCOV_EXCL_LINE
           handler.required_size_events(), estimated_size, handler.required_size_arena(), c4::to_csubstr(arena).len); // LCOV_EXCL_LINE

    // ensure the result is as expected
    bool compare = true;

    // example iterating through the events array: compare and print
    // the result
    for (int pos = 0, evt = 0; pos < handler.required_size_events(); ++pos, ++evt)
    {
        bool status = (events[pos] == expected_events[pos]);
        printf("pos=%d\tevent[%d]:\t0x%x", pos, evt, events[pos]);
        if(events[pos] & WSTR) // the event has a string following it
        {
            int offset = events[pos + 1];
            int length = events[pos + 2];
            bool in_arena = (events[pos] & AREN);
            // WATCHOUT! the string is NOT ZERO TERMINATED!
            const char *ptr = in_arena ? arena : yaml;
            const char *str = ptr + offset;
            printf("\tstr=(%d,%d)\t'%.*s'", offset, length, length, str);
            status = status && (offset == expected_events[pos + 1]);
            status = status && (length == expected_events[pos + 2]);
            pos += 2; // advance the two ints from the string
        }
        if(!status)
        {
            printf("  ... fail!"); // LCOV_EXCL_LINE
            compare = false;       // LCOV_EXCL_LINE
        }
        printf("\n");
    }

    return compare ? 0 : 1;
}

// NOLINTEND(hicpp-signed-bitwise)