rapidyaml  0.11.0
parse and emit YAML, and do it fast
quickstart-ints.cpp File Reference

Go to the source code of this file.

Functions

int main (int, const char *[])
 

Function Documentation

◆ main()

int main ( int  ,
const char *  [] 
)

Definition at line 32 of file quickstart-ints.cpp.

33 {
34  using namespace c4::yml::extra::ievt;
35  auto PSTR_ = c4::yml::extra::ievt::PSTR; // PSTR does not work in windows
36  // YAML code to be parsed in place
37  char yaml[] = "do: a deer, a female deer\n"
38  "re: a drop of golden sun\n"
39  "mi: a name I call myself\n"
40  "fa: a long long way to run\n";
41  // these are the event values we expect
42  const int expected_events[] = {
43  BSTR,
44  BDOC,
45  VAL_|BMAP|BLCK,
46  //
47  KEY_|SCLR|PLAI, 0, 2, // "do"
48  VAL_|SCLR|PLAI|PSTR_, 4, 21, // "a deer, a female deer"
49  //
50  KEY_|SCLR|PLAI|PSTR_, 26, 2, // "re"
51  VAL_|SCLR|PLAI|PSTR_, 30, 20, // "a drop of golden sun"
52  //
53  KEY_|SCLR|PLAI|PSTR_, 51, 2, // "mi"
54  VAL_|SCLR|PLAI|PSTR_, 55, 20, // "a name I call myself"
55  //
56  KEY_|SCLR|PLAI|PSTR_, 76, 2, // "fa"
57  VAL_|SCLR|PLAI|PSTR_, 80, 22, // "a long long way to run"
58  //
59  EMAP|PSTR_,
60  EDOC,
61  ESTR,
62  };
63 
64  /* the output should be this:
65  *
66  * success! YAML requires event size 30, estimated=49 (required_arena=0 actual=99)
67  * pos=0 event[0]: BSTR = 0x00000001
68  * pos=1 event[1]: BDOC = 0x00000004
69  * pos=2 event[2]: VAL_|BMAP|BLCK = 0x00140010
70  * pos=3 event[3]: KEY_|SCLR|PLAI = 0x00081100 str=(0,2) 'do'
71  * pos=6 event[4]: VAL_|SCLR|PLAI|PSTR = 0x04101100 str=(4,21) 'a deer, a female deer'
72  * pos=9 event[5]: KEY_|SCLR|PLAI|PSTR = 0x04081100 str=(26,2) 're'
73  * pos=12 event[6]: VAL_|SCLR|PLAI|PSTR = 0x04101100 str=(30,20) 'a drop of golden sun'
74  * pos=15 event[7]: KEY_|SCLR|PLAI|PSTR = 0x04081100 str=(51,2) 'mi'
75  * pos=18 event[8]: VAL_|SCLR|PLAI|PSTR = 0x04101100 str=(55,20) 'a name I call myself'
76  * pos=21 event[9]: KEY_|SCLR|PLAI|PSTR = 0x04081100 str=(76,2) 'fa'
77  * pos=24 event[10]: VAL_|SCLR|PLAI|PSTR = 0x04101100 str=(80,22) 'a long long way to run'
78  * pos=27 event[11]: EMAP|PSTR = 0x04000020
79  * pos=28 event[12]: EDOC = 0x00000008
80  * pos=29 event[13]: ESTR = 0x00000002
81  */
82 
83  // buffer to where we will write the events
84  constexpr const int events_size = 100;
85  int events[events_size] = {};
86  static_assert(events_size >= sizeof(expected_events)/sizeof(expected_events[0]), "buffer too small");
87  // buffer for placing any scalars/tags that cannot be filtered
88  // in-place
89  char arena[100] = {};
90 
91 
92  // ensure the estimation will succeed vs required size
93  int estimated_size = c4::yml::extra::estimate_events_ints_size(yaml);
94  if (estimated_size > events_size)
95  {
96  printf("the estimated size (%d) will not fit the events array (%d)\n", estimated_size, events_size); // LCOV_EXCL_LINE
97  return 1; // LCOV_EXCL_LINE
98  }
99 
100  // parse now. the parse should succeed (because the YAML above is
101  // legit), but if there were would be a parse error, we would get
102  // the default behavior which is abort on error, since we did not
103  // set up the error callbacks
106  handler.reset(yaml, arena, events, estimated_size); // note we pass the estimated size!
107  parser.parse_in_place_ev("filename", yaml);
108 
109  // the YAML was successfully parsed, but it may happen that it
110  // requires more events than may fit in the buffers. so we need to
111  // check that it actually fits (this is mandatory):
112  if(!handler.fits_buffers())
113  {
114  printf("error: buffers too small: required_evt=%d actual_evt=%d\n required_arena=%zu actual_arena=%zu\n", // LCOV_EXCL_LINE
115  handler.required_size_events(), estimated_size, handler.required_size_arena(), c4::to_csubstr(arena).len); // LCOV_EXCL_LINE
116  // WATCHOUT: if you want to retry the parse, you need to set
117  // up the source buffer again, because it is invalidated from
118  // being parsed in place. refer to the doxygen documentation
119  // for more details.
120  return 1; // LCOV_EXCL_LINE
121  }
122 
123  // done!
124  printf("success! YAML requires event size %d, estimated=%d (required_arena=%zu actual_arena=%zu)\n", // LCOV_EXCL_LINE
125  handler.required_size_events(), estimated_size, handler.required_size_arena(), c4::to_csubstr(arena).len); // LCOV_EXCL_LINE
126 
127  // ensure the result is as expected
128  bool success = true;
129 
130  // example iterating through the events array: compare and print
131  // the result
132  char flags[100];
133  for (int pos = 0, evt = 0; pos < handler.required_size_events(); ++pos, ++evt)
134  {
135  bool status = (events[pos] == expected_events[pos]);
136  // let's format the event flags to print them as string.
137  // we need to zero-terminate them to be able to align using printf.
138  memset(flags, 0, sizeof(flags)); // ensure flags are zero-terminated
139  size_t len = c4::yml::extra::ievt::to_chars(flags, events[pos]);
140  if(len + 1 >= sizeof(flags)) { printf("error: could not format flags"); return 1; } // ensure flags are zero-terminated
141  // print the event
142  printf("pos=%d\tevent[%d]:\t%20s = 0x%08x", pos, evt, flags, events[pos]);
143  if(events[pos] & WSTR) // the event has a string following it
144  {
145  int offset = events[pos + 1];
146  int length = events[pos + 2];
147  bool in_arena = (events[pos] & AREN);
148  // WATCHOUT! the string is NOT ZERO TERMINATED!
149  const char *ptr = in_arena ? arena : yaml;
150  const char *str = ptr + offset;
151  printf("\tstr=(%d,%d)\t'%.*s'", offset, length, length, str);
152  status = status && (offset == expected_events[pos + 1]);
153  status = status && (length == expected_events[pos + 2]);
154  pos += 2; // advance the two ints from the string
155  }
156  if(!status)
157  {
158  printf(" ... fail!"); // LCOV_EXCL_LINE
159  success = false; // LCOV_EXCL_LINE
160  }
161  printf("\n");
162  }
163 
164  return success ? 0 : 1;
165 }
This is the main driver of parsing logic: it scans the YAML or JSON source for tokens,...
int32_t estimate_events_ints_size(csubstr src)
Read YAML source and, without undergoing a full parse, estimate the size of the integer buffer requir...
csubstr to_csubstr(substr s) noexcept
neutral version for use in generic code
Definition: substr.hpp:2210
@ SCLR
scalar (=VAL in test suite events)
@ EMAP
end map (-MAP in test suite events)
@ BMAP
begin map (+MAP in test suite events)
@ ESTR
end stream (-STR in test suite events)
@ BSTR
begin stream (+STR in test suite events)
@ WSTR
WithSTRing: mask of all the events that encode a string following the event. For such events,...
@ VAL_
as value special flag to enable look-back in the event array. it signifies that the previous event ha...
@ BDOC
begin doc (+DOC in test suite events)
@ BLCK
container: block
@ AREN
IMPORTANT. Marks events whose string was placed in the arena. This happens when the filtered string i...
@ EDOC
end doc (-DOC in test suite events)
size_t to_chars(substr buf, ievt::DataType flags)
Convert bit mask of ievt::EventFlags to text.
Definition: ints_utils.cpp:68
A parser event handler that creates a compact representation of the YAML tree in a buffer of integers...
bool fits_buffers() const
Predicate to test if the event buffer successfully accomodated all the parse events.
int required_size_events() const
get the size needed for the event buffer from the previous parse
size_t required_size_arena() const
get the size needed for the arena from the previous parse
void reset(csubstr str, substr arena, ievt::DataType *dst, int32_t dst_size)

References c4::yml::extra::ievt::AREN, c4::yml::extra::ievt::BDOC, c4::yml::extra::ievt::BLCK, c4::yml::extra::ievt::BMAP, c4::yml::extra::ievt::BSTR, c4::yml::extra::ievt::EDOC, c4::yml::extra::ievt::EMAP, c4::yml::extra::estimate_events_ints_size(), c4::yml::extra::ievt::ESTR, c4::yml::extra::EventHandlerInts::fits_buffers(), c4::yml::extra::ievt::KEY_, c4::yml::ParseEngine< EventHandler >::parse_in_place_ev(), c4::yml::extra::ievt::PLAI, c4::yml::extra::ievt::PSTR, c4::yml::extra::EventHandlerInts::required_size_arena(), c4::yml::extra::EventHandlerInts::required_size_events(), c4::yml::extra::EventHandlerInts::reset(), c4::yml::extra::ievt::SCLR, c4::yml::extra::ievt::to_chars(), c4::to_csubstr(), c4::yml::extra::ievt::VAL_, and c4::yml::extra::ievt::WSTR.