Generic SmartRest library

Dependents:   SmartRestUnitTest MbedSmartRest MbedSmartRestStreaming

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers Parser.cpp Source File

Parser.cpp

00001 /*
00002  * Parser.cpp
00003  *
00004  * Created on: Nov 1, 2013
00005  * * Authors: Vincent Wochnik <v.wochnik@gmail.com>
00006  *
00007  * Copyright (c) 2013 Cumulocity GmbH
00008  *
00009  * Permission is hereby granted, free of charge, to any person obtaining
00010  * a copy of this software and associated documentation files (the
00011  * "Software"), to deal in the Software without restriction, including
00012  * without limitation the rights to use, copy, modify, merge, publish,
00013  * distribute, sublicense, and/or sell copies of the Software, and to
00014  * permit persons to whom the Software is furnished to do so, subject to
00015  * the following conditions:
00016  *
00017  * The above copyright notice and this permission notice shall be
00018  * included in all copies or substantial portions of the Software.
00019  *
00020  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
00021  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00022  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
00023  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
00024  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
00025  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
00026  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00027  */
00028 
00029 #include "Parser.h"
00030 
00031 #define STATE_BLANK 0
00032 #define STATE_STRUCTURE 1
00033 #define STATE_VALUE 2
00034 #define STATE_INQUOTES 3
00035 #define STATE_AFTERQUOTE 4
00036 #define STATE_COMPLETE 5
00037 #define STATE_ERROR 6
00038 
00039 Parser::Parser()
00040 {
00041     reset();
00042 }
00043 
00044 uint8_t Parser::readFrom(AbstractDataSource& source, ParsedRecord& record)
00045 {
00046     uint8_t status; char read;
00047 
00048     reset();
00049     record.set(NULL, 0);
00050 
00051     while ((_state < STATE_COMPLETE) &&
00052            (((read = source.read()) > 0 ) ||
00053             ((status = source.status()) == DS_STATUS_OK)))
00054         parse(read);
00055 
00056     if (_state == STATE_COMPLETE)
00057         record.set(_buffer, _count);
00058 
00059     if (_state == STATE_COMPLETE)
00060         return PARSER_SUCCESS;
00061     else if (_state == STATE_BLANK)
00062         if (status == DS_STATUS_CLOSED)
00063             return PARSER_END_OF_RESPONSE;
00064         else
00065             return PARSER_TIMEOUT_ERROR;
00066     else
00067         if (status == DS_STATUS_TIMEOUT)
00068             return PARSER_TIMEOUT_ERROR;
00069         else
00070             return PARSER_PARSE_ERROR;
00071 }
00072 
00073 void Parser::parse(char c)
00074 {
00075     if (_ptr-_buffer >= PARSER_BUFFER_SIZE) {
00076         _state = STATE_ERROR;
00077         return;
00078     }
00079 
00080     switch (_state) {
00081     case STATE_BLANK:
00082         _state = STATE_STRUCTURE;
00083     case STATE_STRUCTURE:
00084         switch (c) {
00085         case ' ':
00086         case '\t':
00087         case '\r':
00088             break;
00089         case '"':
00090             _state = STATE_INQUOTES;
00091             break;
00092         case ',':
00093             close();
00094             break;
00095         case '\0':
00096         case '\n':
00097             if ((_count == 0) && (_length == 0)) {
00098                 _state = STATE_BLANK;
00099             } else {
00100                 close();
00101                 _state = STATE_COMPLETE;
00102             }
00103             break;
00104         default:
00105             if (_length > 0) {
00106                 _state = STATE_ERROR;
00107             } else {
00108                 _state = STATE_VALUE;
00109                 parse(c);
00110             }
00111             break;
00112         }
00113         break;
00114     case STATE_VALUE:
00115         switch (c) {
00116         case ',':
00117         case '\n':
00118             _state = STATE_STRUCTURE;
00119             parse(c);
00120             break;
00121         case '"':
00122             _state = STATE_ERROR;
00123             break;
00124         default:
00125             if ((c == ' ') || (c == '\t') || (c == '\r'))
00126                 _trailing++;
00127             else
00128                 _trailing = 0;
00129             append(c);
00130             break;
00131         }
00132         break;
00133     case STATE_INQUOTES:
00134         switch (c) {
00135         case '"':
00136             _state = STATE_AFTERQUOTE;
00137             break;
00138         default:
00139             append(c);
00140             break;
00141         }
00142         break;
00143     case STATE_AFTERQUOTE:
00144         switch (c) {
00145         case '"':
00146             append(c);
00147             _state = STATE_INQUOTES;
00148             break;
00149         default:
00150             _state = STATE_STRUCTURE;
00151             parse(c);
00152             break;
00153         }
00154         break;
00155     }
00156 }
00157 
00158 void Parser::append(char c)
00159 {
00160     *_ptr++ = c;
00161     _length++;
00162 }
00163 
00164 void Parser::close()
00165 {
00166     _ptr -= _trailing;
00167     *_ptr++ = 0;
00168     _trailing = 0;
00169     _length = 0;
00170     _count++;
00171 }
00172 
00173 void Parser::reset()
00174 {
00175     _state = STATE_BLANK;
00176     _ptr = _buffer;
00177     _count = 0;
00178     _trailing = 0;
00179     _length = 0;
00180 }