rapidyaml  0.7.0
parse and emit YAML, and do it fast
preprocess.cpp
Go to the documentation of this file.
1 #include "c4/yml/preprocess.hpp"
2 #include "c4/yml/detail/parser_dbg.hpp"
3 
4 /** @file preprocess.hpp Functions for preprocessing YAML prior to parsing. */
5 
6 namespace c4 {
7 namespace yml {
8 
9 C4_SUPPRESS_WARNING_GCC_CLANG_WITH_PUSH("-Wold-style-cast")
10 
11 //-----------------------------------------------------------------------------
12 //-----------------------------------------------------------------------------
13 //-----------------------------------------------------------------------------
14 
15 namespace {
16 C4_ALWAYS_INLINE bool _is_idchar(char c)
17 {
18  return (c >= 'a' && c <= 'z')
19  || (c >= 'A' && c <= 'Z')
20  || (c >= '0' && c <= '9')
21  || (c == '_' || c == '-' || c == '~' || c == '$');
22 }
23 
24 typedef enum { kReadPending = 0, kKeyPending = 1, kValPending = 2 } _ppstate;
25 C4_ALWAYS_INLINE _ppstate _next(_ppstate s)
26 {
27  int n = (int)s + 1;
28  return (_ppstate)(n <= (int)kValPending ? n : 0);
29 }
30 } // empty namespace
31 
32 
33 //-----------------------------------------------------------------------------
34 
35 size_t preprocess_rxmap(csubstr s, substr buf)
36 {
37  detail::_SubstrWriter writer(buf);
38  _ppstate state = kReadPending;
39  size_t last = 0;
40 
41  if(s.begins_with('{'))
42  {
43  RYML_CHECK(s.ends_with('}'));
44  s = s.offs(1, 1);
45  }
46 
47  writer.append('{');
48 
49  for(size_t i = 0; i < s.len; ++i)
50  {
51  const char curr = s[i];
52  const char next = i+1 < s.len ? s[i+1] : '\0';
53 
54  if(curr == '\'' || curr == '"')
55  {
56  csubstr ss = s.sub(i).pair_range_esc(curr, '\\');
57  i += static_cast<size_t>(ss.end() - (s.str + i));
58  state = _next(state);
59  }
60  else if(state == kReadPending && _is_idchar(curr))
61  {
62  state = _next(state);
63  }
64 
65  switch(state)
66  {
67  case kKeyPending:
68  {
69  if(curr == ':' && next == ' ')
70  {
71  state = _next(state);
72  }
73  else if(curr == ',' && next == ' ')
74  {
75  writer.append(s.range(last, i));
76  writer.append(": 1, ");
77  last = i + 2;
78  }
79  break;
80  }
81  case kValPending:
82  {
83  if(curr == '[' || curr == '{' || curr == '(')
84  {
85  csubstr ss = s.sub(i).pair_range_nested(curr, '\\');
86  i += static_cast<size_t>(ss.end() - (s.str + i));
87  state = _next(state);
88  }
89  else if(curr == ',' && next == ' ')
90  {
91  state = _next(state);
92  }
93  break;
94  }
95  default:
96  // nothing to do
97  break;
98  }
99  }
100 
101  writer.append(s.sub(last));
102  if(state == kKeyPending)
103  writer.append(": 1");
104  writer.append('}');
105 
106  return writer.pos;
107 }
108 
109 C4_SUPPRESS_WARNING_GCC_CLANG_POP
110 
111 } // namespace yml
112 } // namespace c4
size_t preprocess_rxmap(csubstr s, substr buf)
Write into a given output buffer.
Definition: preprocess.cpp:35
Definition: common.cpp:12
Functions for preprocessing YAML prior to parsing.