EvolvingObjects
|
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