jsonsax.cpp
changeset 1 ef7abb48573b
parent 0 d187e7fc9970
equal deleted inserted replaced
0:d187e7fc9970 1:ef7abb48573b
     1 #include "jsonsax.hpp"
       
     2 
       
     3 #include <assert.h>
       
     4 
       
     5 #define CASE_IS_SPACE \
       
     6 	case ' ':		  \
       
     7 case '\n':			  \
       
     8 case '\t':			  \
       
     9 case '\r'
       
    10 
       
    11 #define CASE_IS_DIGIT \
       
    12 	case '0':		  \
       
    13 case '1':			  \
       
    14 case '2':			  \
       
    15 case '3':			  \
       
    16 case '4':			  \
       
    17 case '5':			  \
       
    18 case '6':			  \
       
    19 case '7':			  \
       
    20 case '8':			  \
       
    21 case '9'
       
    22 
       
    23 JSLXParser::JSLXParser(IJSLXBackend* pBackend)
       
    24     : m_pBackend(pBackend)
       
    25 {}
       
    26 bool JSLXParser::Parse()
       
    27 {
       
    28     return GetNextChar() && ParseValue();
       
    29 }
       
    30 
       
    31 bool JSLXParser::_GetNextChar()
       
    32 {
       
    33     if (!m_pBackend->Eof())
       
    34     {
       
    35         m_lastChar = m_pBackend->GetChar();
       
    36         return true;
       
    37     }
       
    38     return false;
       
    39 }
       
    40 
       
    41 bool JSLXParser::TrimWhiteSpace()
       
    42 {
       
    43     do
       
    44     {
       
    45         switch(m_lastChar)
       
    46         {
       
    47         CASE_IS_SPACE:
       
    48             break;
       
    49         default:
       
    50             return true;
       
    51         }
       
    52     }
       
    53     while(_GetNextChar());
       
    54     return false;
       
    55 }
       
    56 
       
    57 bool JSLXParser::GetNextChar(bool trim /* = true */)
       
    58 {
       
    59     if (trim)
       
    60     {
       
    61         return _GetNextChar() && TrimWhiteSpace();
       
    62     }
       
    63     return _GetNextChar();
       
    64 }
       
    65 
       
    66 bool JSLXParser::ParseValue()
       
    67 {
       
    68     switch(m_lastChar)
       
    69     {
       
    70     case '[':
       
    71         return ParseArray();
       
    72     case '{':
       
    73         return ParseObject();
       
    74     case '"':
       
    75         return ParseString();
       
    76     case '-':
       
    77     CASE_IS_DIGIT:
       
    78         return ParseNumber();
       
    79     case 'n':
       
    80         return ParseNull();
       
    81     case 't':
       
    82         return ParseTrue();
       
    83     case 'f':
       
    84         return ParseFalse();
       
    85     default:
       
    86         return false;
       
    87     }
       
    88 }
       
    89 
       
    90 bool JSLXParser::ParseObject()
       
    91 {
       
    92     assert(m_lastChar == '{');
       
    93     m_pBackend->OnStartObject();
       
    94     GetNextChar();
       
    95     while(ParsePair())
       
    96     {
       
    97         switch(m_lastChar)
       
    98         {
       
    99         case ',':
       
   100             GetNextChar();
       
   101             break;
       
   102         case '}':
       
   103             m_pBackend->OnStopObject();
       
   104             GetNextChar();
       
   105             return true;
       
   106         default:
       
   107             m_pBackend->OnError("ParseObject: invalid char");
       
   108             return false;
       
   109         }
       
   110     }
       
   111     if (m_lastChar != '}')
       
   112     {
       
   113         m_pBackend->OnError("ParseObject: invalid char");
       
   114         return false;
       
   115     }
       
   116     m_pBackend->OnStopObject();
       
   117     GetNextChar();
       
   118     return true;
       
   119 }
       
   120 
       
   121 bool JSLXParser::ParsePair()
       
   122 {
       
   123     if (m_lastChar != '"')
       
   124     {
       
   125         m_pBackend->OnError("ParsePair: Invalid Key");
       
   126         return false;
       
   127     }
       
   128     if (!ParseString())
       
   129     {
       
   130         m_pBackend->OnError("ParsePair: Invalid Key");
       
   131         return false;
       
   132     }
       
   133     if (m_lastChar != ':')
       
   134     {
       
   135         m_pBackend->OnError("ParsePair: Missing pair separator");
       
   136         return false;
       
   137     }
       
   138     if (!GetNextChar())
       
   139     {
       
   140         m_pBackend->OnError("ParsePair: Missing value");
       
   141         return false;
       
   142     }
       
   143     return ParseValue();
       
   144 }
       
   145 
       
   146 bool JSLXParser::ParseArray()
       
   147 {
       
   148     assert(m_lastChar == '[');
       
   149     if (!GetNextChar()) return false;
       
   150     while(ParseValue())
       
   151     {
       
   152         switch(m_lastChar)
       
   153         {
       
   154         case ',':
       
   155             GetNextChar();
       
   156             break;
       
   157         case ']':
       
   158             m_pBackend->OnStopArray();
       
   159             GetNextChar();
       
   160             return true;
       
   161         default:
       
   162             m_pBackend->OnError("ParseArray: Missing seperator in array");
       
   163             return false;
       
   164         }
       
   165     }
       
   166     if (m_lastChar != ']')
       
   167     {
       
   168         m_pBackend->OnError("ParseArray: Bad value in array");
       
   169         return false;
       
   170     }
       
   171     m_pBackend->OnStopArray();
       
   172     GetNextChar();
       
   173     return true;
       
   174 }
       
   175 
       
   176 bool JSLXParser::ParseString()
       
   177 {
       
   178     assert(m_lastChar == '"');
       
   179     m_pBackend->OnStartString();
       
   180     while(GetNextChar())
       
   181     {
       
   182         switch(m_lastChar)
       
   183         {
       
   184         case '\\':
       
   185             GetNextChar();
       
   186             break;
       
   187         case '"':
       
   188             m_pBackend->OnStopString();
       
   189             GetNextChar();
       
   190             return true;
       
   191         }
       
   192     }
       
   193     return false;
       
   194 }
       
   195 
       
   196 bool JSLXParser::ParseNumber()
       
   197 {
       
   198     assert(m_lastChar == '-' ||
       
   199         m_lastChar == '0' ||
       
   200         m_lastChar == '1' ||
       
   201         m_lastChar == '2' ||
       
   202         m_lastChar == '3' ||
       
   203         m_lastChar == '4' ||
       
   204         m_lastChar == '5' ||
       
   205         m_lastChar == '6' ||
       
   206         m_lastChar == '7' ||
       
   207         m_lastChar == '8' ||
       
   208         m_lastChar == '9');
       
   209 
       
   210     m_pBackend->OnStartNumber();
       
   211     while(GetNextChar())
       
   212     {
       
   213         switch(m_lastChar)
       
   214         {
       
   215             // TODO: lookup for correct number format.
       
   216         case 'e':
       
   217         case '-':
       
   218         case '.':
       
   219         CASE_IS_DIGIT:
       
   220             break;
       
   221         default:
       
   222             m_pBackend->OnStopNumber();
       
   223             return true;
       
   224         }
       
   225     }
       
   226     return true;
       
   227 }
       
   228 
       
   229 bool JSLXParser::ParseNull()
       
   230 {
       
   231     if (ParseConstant("null"))
       
   232     {
       
   233         m_pBackend->OnNull();
       
   234         return true;
       
   235     }
       
   236     return false;
       
   237 }
       
   238 
       
   239 bool JSLXParser::ParseTrue()
       
   240 {
       
   241     if (ParseConstant("true"))
       
   242     {
       
   243         m_pBackend->OnTrue();
       
   244         return true;
       
   245     }
       
   246     return false;
       
   247 }
       
   248 
       
   249 bool JSLXParser::ParseFalse()
       
   250 {
       
   251     if (ParseConstant("false"))
       
   252     {
       
   253         m_pBackend->OnFalse();
       
   254         return true;
       
   255     }
       
   256     return false;
       
   257 }
       
   258 
       
   259 bool JSLXParser::ParseConstant(const char* constant)
       
   260 {
       
   261     assert(m_lastChar == constant[0]);
       
   262     ++constant;
       
   263     while(GetNextChar())
       
   264     {
       
   265         if (*constant == '\0')
       
   266             return true;
       
   267         if (*constant != m_lastChar)
       
   268             return false;
       
   269         constant++;
       
   270     }
       
   271     return *constant == '\0';
       
   272 }
       
   273 
       
   274 #undef CASE_IS_DIGIT
       
   275 #undef CASE_IS_SPACE
       
   276