PageRenderTime 49ms CodeModel.GetById 20ms RepoModel.GetById 1ms app.codeStats 0ms

/c++-libbu++/src/object.cpp

https://github.com/eichlan/libgats
C++ | 380 lines | 325 code | 48 blank | 7 comment | 87 complexity | 076689f62f79b1fd9277742df4ad4ebc MD5 | raw file
Possible License(s): BSD-3-Clause
  1. /*
  2. * Copyright (C) 2007-2013 Xagasoft, All rights reserved.
  3. *
  4. * This file is part of the libgats library and is released under the
  5. * terms of the license contained in the file LICENSE.
  6. */
  7. #include "gats/object.h"
  8. #include "gats/integer.h"
  9. #include "gats/float.h"
  10. #include "gats/boolean.h"
  11. #include "gats/string.h"
  12. #include "gats/list.h"
  13. #include "gats/dictionary.h"
  14. #include "gats/null.h"
  15. #include <stdlib.h>
  16. #include <bu/formatter.h>
  17. #include <bu/stream.h>
  18. #include <bu/sio.h>
  19. using namespace Bu;
  20. Gats::Object::Object()
  21. {
  22. }
  23. Gats::Object::~Object()
  24. {
  25. }
  26. Gats::Object *Gats::Object::read( Bu::Stream &rIn )
  27. {
  28. char buf;
  29. rIn.read( &buf, 1 );
  30. Object *pObj = NULL;
  31. switch( buf )
  32. {
  33. case 'i':
  34. pObj = new Gats::Integer();
  35. break;
  36. case 's':
  37. pObj = new Gats::String();
  38. break;
  39. case '0':
  40. case '1':
  41. pObj = new Gats::Boolean();
  42. break;
  43. case 'l':
  44. pObj = new Gats::List();
  45. break;
  46. case 'd':
  47. pObj = new Gats::Dictionary();
  48. break;
  49. case 'f': // Normal floats
  50. case 'F': // Special float values
  51. pObj = new Gats::Float();
  52. break;
  53. case 'n':
  54. pObj = new Gats::Null();
  55. break;
  56. case 'e':
  57. return NULL;
  58. default:
  59. throw Bu::ExceptionBase("Invalid Gats type discovered: %c.", buf );
  60. }
  61. pObj->read( rIn, buf );
  62. return pObj;
  63. }
  64. void Gats::Object::skipWs( Gats::Object::StrPos &i )
  65. {
  66. for(; *i == ' ' || *i == '\t' || *i == '\r' || *i == '\n' || *i == '/'; i++ )
  67. {
  68. if( *i == '/' )
  69. {
  70. i++;
  71. if( *i == '/' )
  72. for(i++; *i != '\n' && *i != '\r'; i++ ) { }
  73. else if( *i == '*' )
  74. {
  75. for(i++; i; i++ )
  76. {
  77. if( *i == '*' )
  78. {
  79. i++;
  80. if( *i == '/' )
  81. {
  82. i++;
  83. break;
  84. }
  85. }
  86. }
  87. }
  88. else
  89. return;
  90. }
  91. }
  92. }
  93. Bu::String Gats::Object::token( Gats::Object::StrPos &i )
  94. {
  95. Bu::String sRet;
  96. if( *i == '\"' )
  97. {
  98. for( i++; i && *i != '\"' ; i++ )
  99. {
  100. if( *i == '\\' )
  101. i++;
  102. sRet += *i;
  103. }
  104. i++;
  105. }
  106. else
  107. {
  108. for(; i && *i != ' ' && *i != '\t' && *i != '\r' && *i != '\n' &&
  109. *i != ',' && *i != ']' && *i != '}' && *i != '[' &&
  110. *i != '{' && *i != '/'; i++ )
  111. {
  112. sRet += *i;
  113. }
  114. }
  115. return sRet;
  116. }
  117. Bu::String::FormatProxy Gats::Object::posError( Gats::Object::StrPos &i, const Bu::String &msg )
  118. {
  119. return msg.format( new Thrower(i) );
  120. }
  121. Gats::Object *Gats::Object::strToGats( Gats::Object::StrPos &i )
  122. {
  123. skipWs( i );
  124. switch( *i )
  125. {
  126. case '[':
  127. {
  128. Gats::List *pLst = new Gats::List();
  129. i++;
  130. for(;;)
  131. {
  132. skipWs( i );
  133. if( *i == ']' )
  134. {
  135. i++;
  136. return pLst;
  137. }
  138. Gats::Object *pObj = strToGats( i );
  139. if( !pObj )
  140. break;
  141. pLst->append( pObj );
  142. skipWs( i );
  143. switch( *i )
  144. {
  145. case ',':
  146. i++;
  147. break;
  148. case ']':
  149. i++;
  150. return pLst;
  151. default:
  152. posError(i, "Expected ',' or ']' but found '%1'.").
  153. arg( *i );
  154. }
  155. }
  156. }
  157. break;
  158. case '{':
  159. {
  160. Gats::Dictionary *pDict = new Gats::Dictionary();
  161. i++;
  162. for(;;)
  163. {
  164. skipWs( i );
  165. if( *i == '}' )
  166. {
  167. i++;
  168. return pDict;
  169. }
  170. if( *i != '\"' )
  171. posError(i, "Dictionary keys must be quoted strings.");
  172. Bu::String sKey = token( i );
  173. skipWs( i );
  174. if( *i != ':' )
  175. posError(i, "Dictionary keys and values must be "
  176. "seperated with colons.");
  177. StrPos ih( i );
  178. i++;
  179. skipWs( i );
  180. Gats::Object *pObj = strToGats( i );
  181. if( !pObj )
  182. posError(ih, "Dictionary key has no value.");
  183. pDict->insert( sKey, pObj );
  184. skipWs( i );
  185. switch( *i )
  186. {
  187. case ',':
  188. i++;
  189. break;
  190. case '}':
  191. i++;
  192. return pDict;
  193. default:
  194. posError(i, "Expected ',' or '}' but found '%1'.")
  195. .arg( *i );
  196. }
  197. }
  198. }
  199. break;
  200. case '\"':
  201. return new Gats::String( token( i ) );
  202. break;
  203. case '0':
  204. case '1':
  205. case '2':
  206. case '3':
  207. case '4':
  208. case '5':
  209. case '6':
  210. case '7':
  211. case '8':
  212. case '9':
  213. case '.':
  214. case '+':
  215. case '-':
  216. {
  217. Bu::String s = token( i );
  218. int iSize = s.getSize();
  219. if( s[iSize-1] == 'i' )
  220. {
  221. return new Gats::Integer(
  222. strtoll( s.getStr(), NULL, 10 )
  223. );
  224. }
  225. else if( s[iSize-1] == 'f' )
  226. {
  227. return new Gats::Float(
  228. strtod( s.getStr(), NULL )
  229. );
  230. }
  231. else
  232. {
  233. for( Bu::String::iterator i = s.begin(); i; i++ )
  234. {
  235. if( *i == '.' )
  236. return new Gats::Float(
  237. strtod( s.getStr(), NULL )
  238. );
  239. }
  240. return new Gats::Integer(
  241. strtoll( s.getStr(), NULL, 10 )
  242. );
  243. }
  244. }
  245. break;
  246. default:
  247. {
  248. Bu::String s = token( i );
  249. int iSize = s.getSize();
  250. // Test for explicit types first
  251. if( iSize > 2 )
  252. {
  253. if( (s[0] >= '0' && s[0] <= '9') || s[0] == '+' || s[0] == '-' )
  254. {
  255. }
  256. else
  257. {
  258. Bu::String st = s.toLower();
  259. if( st == "true" )
  260. {
  261. return new Gats::Boolean( true );
  262. }
  263. else if( st == "false" )
  264. {
  265. return new Gats::Boolean( false );
  266. }
  267. else if( st == "null" )
  268. {
  269. return new Gats::Null();
  270. }
  271. }
  272. }
  273. }
  274. break;
  275. }
  276. return NULL;
  277. }
  278. Gats::Object *Gats::Object::strToGats( const Bu::String &sStr )
  279. {
  280. StrPos i( sStr.begin() );
  281. return strToGats( i );
  282. }
  283. Bu::Formatter &operator<<( Bu::Formatter &f, const Gats::Object &obj )
  284. {
  285. switch( obj.getType() )
  286. {
  287. case Gats::typeDictionary:
  288. return f << dynamic_cast<const Gats::Dictionary &>(obj);
  289. case Gats::typeList:
  290. return f << dynamic_cast<const Gats::List &>(obj);
  291. case Gats::typeString:
  292. return f << dynamic_cast<const Gats::String &>(obj);
  293. case Gats::typeInteger:
  294. return f << dynamic_cast<const Gats::Integer &>(obj);
  295. case Gats::typeFloat:
  296. return f << dynamic_cast<const Gats::Float &>(obj);
  297. case Gats::typeBoolean:
  298. return f << dynamic_cast<const Gats::Boolean &>(obj);
  299. case Gats::typeNull:
  300. return f << dynamic_cast<const Gats::Null &>(obj);
  301. default:
  302. return f << "***ERROR: Bad Gats type***";
  303. }
  304. }
  305. Bu::Formatter &operator<<( Bu::Formatter &f, const Gats::Type &t )
  306. {
  307. switch( t )
  308. {
  309. case Gats::typeDictionary: return f << "dictionary";
  310. case Gats::typeList: return f << "list";
  311. case Gats::typeString: return f << "string";
  312. case Gats::typeInteger: return f << "integer";
  313. case Gats::typeFloat: return f << "float";
  314. case Gats::typeBoolean: return f << "boolean";
  315. case Gats::typeNull: return f << "null";
  316. }
  317. return f << "***unknown***";
  318. }
  319. const char *Gats::typeToStr( Gats::Type t )
  320. {
  321. switch( t )
  322. {
  323. case Gats::typeDictionary: return "dictionary";
  324. case Gats::typeList: return "list";
  325. case Gats::typeString: return "string";
  326. case Gats::typeInteger: return "integer";
  327. case Gats::typeFloat: return "float";
  328. case Gats::typeBoolean: return "boolean";
  329. case Gats::typeNull: return "null";
  330. }
  331. return "***unknown***";
  332. }