mbed.org implementation of the abstract SmartREST library for the Cumulocity Platform SmartREST protocol.

Dependents:   MbedSmartRestMain MbedSmartRestMain

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