preprocess.cpp (2888B)
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