Own fork of MbedSmartRest

Dependents:   MbedSmartRestMain MbedSmartRestMain

Fork of MbedSmartRest by Cumulocity Official

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 <assert.h>
00030 #include <stdio.h>
00031 #include <ctype.h>
00032 #include "Parser.h"
00033 
00034 #define STATE_BLANK 0
00035 #define STATE_STRUCTURE 1
00036 #define STATE_VALUE 2
00037 #define STATE_INQUOTES 3
00038 #define STATE_AFTERQUOTE 4
00039 #define STATE_COMPLETE 5
00040 #define STATE_ERROR 6
00041 
00042 
00043 /*-------------------------------------------------------------------------*/
00044 Parser::Parser()
00045 {
00046     reset();
00047 }
00048 /*-------------------------------------------------------------------------*/
00049 uint8_t Parser::readFrom(AbstractDataSource& source, ParsedRecord& record)
00050 {
00051     reset();
00052     record.clear();
00053 
00054     int status = -1;
00055     char read;
00056     while (_state < STATE_COMPLETE) {
00057         read = source.read();
00058         status = source.status();
00059 //      if (isprint(read)) {
00060 //          printf("%4c: %u\n", read, status);
00061 //      } else {
00062 //          printf("#%04x: %u\n", read, status);
00063 //      }
00064         if (read > 0 || status == DS_STATUS_OK)
00065             parse(read);
00066         else
00067             break;
00068     }
00069 //  printf("Parser: [E]while! %u, %d\r\n", _state, status);
00070     if (_state == STATE_COMPLETE) { // successfully read record
00071         if (!record.set(_buffer, _count))
00072             return PARSER_INTERNAL_ERROR;
00073         else
00074             return PARSER_SUCCESS;
00075     } else if (_state == STATE_BLANK) {
00076         if (status == DS_STATUS_CLOSED)
00077             return PARSER_END_OF_RESPONSE;
00078         else if (status == DS_STATUS_TIMEOUT)
00079             return PARSER_TIMEOUT_ERROR;
00080         else
00081             return PARSER_INTERNAL_ERROR;
00082     } else {
00083         if (status == DS_STATUS_TIMEOUT)
00084             return PARSER_TIMEOUT_ERROR;
00085         else if (status == DS_STATUS_ERROR)
00086             return PARSER_INTERNAL_ERROR;
00087         else
00088             return PARSER_PARSE_ERROR;
00089     }
00090 }
00091 /*-------------------------------------------------------------------------*/
00092 void Parser::parse(char c)
00093 {
00094     if (_ptr-_buffer >= SMARTREST_PARSER_BUFFER_SIZE) {
00095         _state = STATE_ERROR;
00096         return;
00097     }
00098 
00099     switch (_state)
00100     {
00101     case STATE_BLANK: _state = STATE_STRUCTURE;
00102     case STATE_STRUCTURE:
00103         switch (c)
00104         {
00105         case ' ':
00106         case '\t':
00107         case '\r': break;
00108         case '"': _state = STATE_INQUOTES; break;
00109         case ',': close(); break;
00110         case '\0':
00111         case '\n':
00112             if (_count==0 && _length==0) {
00113                 _state = STATE_BLANK;
00114             } else {
00115                 close();
00116                 _state = STATE_COMPLETE;
00117             }
00118             break;
00119         default:
00120             if (_length > 0) {
00121                 _state = STATE_ERROR;
00122             } else {
00123                 _state = STATE_VALUE;
00124                 parse(c);
00125             }
00126             break;
00127         }
00128         break;
00129     case STATE_VALUE:
00130         switch (c)
00131         {
00132         case ',':
00133         case '\n':  _state = STATE_STRUCTURE; parse(c); break;
00134         case '"':   _state = STATE_ERROR; break;
00135         default:
00136             if ((c == ' ') || (c == '\t') || (c == '\r'))
00137                 _trailing++;
00138             else
00139                 _trailing = 0;
00140             append(c);
00141             break;
00142         }
00143         break;
00144     case STATE_INQUOTES:
00145         switch (c)
00146         {
00147         case '"': _state = STATE_AFTERQUOTE; break;
00148         default: append(c); break;
00149         }
00150         break;
00151     case STATE_AFTERQUOTE:
00152         switch (c)
00153         {
00154         case '"': append(c); _state = STATE_INQUOTES; break;
00155         default: _state = STATE_STRUCTURE; parse(c); break;
00156         }
00157         break;
00158     }
00159 }
00160 /*-------------------------------------------------------------------------*/
00161 void Parser::append(char c)
00162 {
00163     *_ptr++ = c;
00164     _length++;
00165 }
00166 /*-------------------------------------------------------------------------*/
00167 void Parser::close()
00168 {
00169     _ptr -= _trailing;
00170     *_ptr++ = 0;
00171     _trailing = 0;
00172     _length = 0;
00173     _count++;
00174 }
00175 /*-------------------------------------------------------------------------*/
00176 void Parser::reset()
00177 {
00178     _state = STATE_BLANK;
00179     _ptr = _buffer;
00180     _count = 0;
00181     _trailing = 0;
00182     _length = 0;
00183 }
00184 /*-------------------------------------------------------------------------*/