duckstation

duckstation, but archived from the revision just before upstream changed it to a proprietary software project, this version is the libre one
git clone https://git.neptards.moe/u3shit/duckstation.git
Log | Files | Refs | README | LICENSE

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