EvolvingObjects
Parser.cpp
00001 /*
00002 (c) Thales group, 2012
00003 
00004     This library is free software; you can redistribute it and/or
00005     modify it under the terms of the GNU Lesser General Public
00006     License as published by the Free Software Foundation;
00007     version 2 of the License.
00008 
00009     This library is distributed in the hope that it will be useful,
00010     but WITHOUT ANY WARRANTY; without even the implied warranty of
00011     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012     Lesser General Public License for more details.
00013 
00014     You should have received a copy of the GNU Lesser General Public
00015     License along with this library; if not, write to the Free Software
00016     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00017 Contact: http://eodev.sourceforge.net
00018 
00019 Authors:
00020     Benjamin Bouvier <benjamin.bouvier@gmail.com>
00021 */
00022 # include <string>
00023 
00024 # include "Parser.h"
00025 
00026 # include "Array.h"
00027 # include "Object.h"
00028 # include "String.h"
00029 
00030 // in debug mode only
00031 // # define DEBUG(x) std::cout << x << std::endl;
00032 # define DEBUG(x)
00033 
00034 using namespace eoserial;
00035 
00036 namespace eoserial
00037 {
00038 
00048 static std::string parseString(const std::string& str, size_t & pos)
00049 {
00050     // example : "hello"
00051     // example 2 : "\"world\""
00052     // for hello:
00053     // firstQuote == 0, secondQuote == 6
00054     // sub string should be from firstQuote+1 to secondQuote-1
00055     // so its size should be (secondQuote-1 -(firstQuote+1) + 1)
00056     std::string value;
00057     size_t firstQuote = str.find( '"', pos );
00058     size_t secondQuote;
00059 
00060     /* instead of just seeking the second quote, we need to ensure
00061     // that there is no escaped quote before this one.
00062     // actually this is harder than that. Using backslashes
00063     // to escape double quotes mean that backslashes have to be
00064     // escaped to.
00065     // example : "text\\" to symbolize : text\
00066     // example : "text\\\" to symbolize : text\"
00067     // In fact, we should find if number of backslashes is odd; in this case,
00068     // the double quotes are escaped and we should find the next one.
00069     */
00070     int backslashesCount;
00071     do {
00072         ++pos;
00073         secondQuote = str.find( '"', pos );
00074         size_t i = secondQuote - 1;
00075 
00076         // Find the backslashes
00077         backslashesCount = 0;
00078         while ( str[ i ] == '\\' )
00079         {
00080             --i;
00081             ++backslashesCount;
00082         }
00083         pos = secondQuote;
00084     } while( backslashesCount % 2 == 1 );
00085 
00086     value = str.substr( firstQuote+1, secondQuote-firstQuote-1 );
00087     pos = secondQuote + 1;
00088     return value;
00089 }
00090 
00098 static void ignoreChars(const std::string& str, size_t & pos)
00099 {
00100     // ignore white spaces and comas
00101     for (char current = str[ pos ];
00102         current == ',' || current == ' ' || current == '\n';
00103         current = str[ ++pos ]);
00104 }
00105 
00106 String* Parser::parseJsonString(const std::string & str, size_t & pos)
00107 {
00108     return new String( parseString( str, pos ) );
00109 }
00110 
00111 Object* Parser::parse(const std::string & str)
00112 {
00113     size_t initial(0); // we begin at position 0
00114     return static_cast<Object*>( parseRight(str, initial) );
00115 }
00116 
00117 Entity* Parser::parseRight(const std::string & str, size_t & pos)
00118 {
00119     Entity* value = 0;
00120 
00121     if ( str[ pos ] == '{' )
00122     {
00123         // next one is an object
00124         DEBUG("We read an object.")
00125         Object* obj = new Object;
00126         pos += 1;
00127         while( pos < str.size() && str[ pos ] != '}' )
00128         {
00129             parseLeft( str, pos, obj );
00130             ignoreChars( str, pos );
00131         }
00132         DEBUG("We just finished to read an object ! ")
00133         pos += 1; // we're on the }, go to the next char
00134         value = obj;
00135     }
00136     else if ( str[ pos ] == '"' )
00137     {
00138         // next one is a string
00139         DEBUG("We read a string")
00140         value = parseJsonString( str, pos );
00141     }
00142     else if ( str[ pos ] == '[' )
00143     {
00144         // next one is an array
00145         DEBUG("We read an array")
00146         Array* array = new Array;
00147         pos += 1;
00148         while( pos < str.size() && str[ pos ] != ']' )
00149         {
00150             Entity* child = parseRight( str, pos );
00151             if ( child )
00152                 array->push_back( child );
00153         }
00154         DEBUG("We've finished to read our array.")
00155         pos += 1; // we're on the ], go to the next char
00156         value = array;
00157     }
00158     ignoreChars( str, pos );
00159     return value;
00160 }
00161 
00162 void Parser::parseLeft(const std::string & str, size_t & pos, Object* eoserial)
00163 {
00164     std::string key = parseString(str, pos);
00165     ++pos; // the colon
00166     DEBUG("We've read the key ")
00167     (*eoserial)[ key ] = parseRight( str, pos ); 
00168 }
00169 
00170 } // namespace eoserial
00171 
 All Classes Namespaces Files Functions Variables Typedefs Friends