PageRenderTime 67ms CodeModel.GetById 36ms RepoModel.GetById 0ms app.codeStats 0ms

/CS/migrated/tags/PRE_CROSSBUILD_REMOVAL/plugins/aws2/object.cpp

#
C++ | 699 lines | 479 code | 157 blank | 63 comment | 66 complexity | 8cb9ffd63c3149423f37dafe3f931a84 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.1, LGPL-2.0
  1. /*
  2. Copyright (C) 2005 by Christopher Nelson
  3. This library is free software; you can redistribute it and/or
  4. modify it under the terms of the GNU Library General Public
  5. License as published by the Free Software Foundation; either
  6. version 2 of the License, or (at your option) any later version.
  7. This library is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  10. Library General Public License for more details.
  11. You should have received a copy of the GNU Library General Public
  12. License along with this library; if not, write to the Free
  13. Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  14. */
  15. #include "cssysdef.h"
  16. #include "registrar.h"
  17. #include "csutil/snprintf.h"
  18. #include <cstdlib>
  19. #include <cstdio>
  20. #include <ctype.h>
  21. #include <stdlib.h>
  22. namespace aws
  23. {
  24. namespace autom
  25. {
  26. SCF_IMPLEMENT_IBASE(object)
  27. SCF_IMPLEMENTS_INTERFACE(iObject)
  28. SCF_IMPLEMENT_IBASE_END
  29. /////////////////////////////////// Object - Record Allocation with GC ///////////////////////////////////////
  30. object::object(TYPE _otype):otype(_otype)
  31. {
  32. }
  33. object::~object()
  34. {
  35. }
  36. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  37. /** Converts the object into a string object if possible. */
  38. string
  39. string::ToString()
  40. {
  41. return string(value);
  42. }
  43. /** Converts the object into an integer object, if possible. */
  44. integer
  45. string::ToInt()
  46. {
  47. return integer(strtol(value.GetData(), 0, 10));
  48. }
  49. /** Converts the object into a float object, if possible. */
  50. floating
  51. string::ToFloat()
  52. {
  53. return floating(strtod(value.GetData(), 0));
  54. }
  55. bool
  56. string::parseObject(std::string::iterator &pos, const std::string::iterator &end)
  57. {
  58. value = "";
  59. if (pos==end || *pos != '"') return false;
  60. ++pos;
  61. for(;pos!=end && *pos!='"'; ++pos)
  62. {
  63. if (*pos=='\\')
  64. {
  65. ++pos;
  66. switch((*pos))
  67. {
  68. case 'n': value+=('\n'); break;
  69. case 'r': value+=('\r'); break;
  70. case 't': value+=('\t'); break;
  71. default: value+=(*pos);
  72. }
  73. continue;
  74. }
  75. value+=(*pos);
  76. }
  77. return true;
  78. }
  79. //////////////////// Integer Object //////////////////////////////////////
  80. /** Converts the object into a string object if possible. */
  81. string
  82. integer::ToString()
  83. {
  84. char buf[128]={0};
  85. return string(csString(buf, cs_snprintf(buf, sizeof(buf), "%lld", value)));
  86. }
  87. /** Converts the object into an integer object, if possible. */
  88. integer
  89. integer::ToInt()
  90. {
  91. return integer(value);
  92. }
  93. /** Converts the object into a float object, if possible. */
  94. floating
  95. integer::ToFloat()
  96. {
  97. return floating((float)value);
  98. }
  99. csRef<iString>
  100. integer::ReprObject()
  101. {
  102. return csPtr<iString> (new scfString (ToString().Value()));
  103. }
  104. bool
  105. integer::parseObject(std::string::iterator &pos, const std::string::iterator &end)
  106. {
  107. if (pos==end || !isdigit(*pos)) return false;
  108. std::string temp;
  109. for(; pos!=end && isdigit(*pos); ++pos)
  110. temp+=(*pos);
  111. value = strtoll(temp.c_str(), 0, 10);
  112. return true;
  113. }
  114. //////////////////// Floating Point Object //////////////////////////////////////
  115. /** Converts the object into a string object if possible. */
  116. string
  117. floating::ToString()
  118. {
  119. csString buf;
  120. buf.Format ("%g", value);
  121. return string(buf);
  122. }
  123. /** Converts the object into an integer object, if possible. */
  124. integer
  125. floating::ToInt()
  126. {
  127. return integer((int)value);
  128. }
  129. /** Converts the object into a float object, if possible. */
  130. floating
  131. floating::ToFloat()
  132. {
  133. return floating(value);
  134. }
  135. csRef<iString>
  136. floating::ReprObject()
  137. {
  138. return csPtr<iString> (new scfString (ToString().Value()));
  139. }
  140. bool
  141. floating::parseObject(std::string::iterator &pos, const std::string::iterator &end)
  142. {
  143. std::string::iterator start = pos;
  144. if (pos==end || !isdigit(*pos)) return false;
  145. std::string temp;
  146. bool have_radix_point=false;
  147. while(pos!=end && (isdigit(*pos) || (*pos=='.' && have_radix_point==false)))
  148. {
  149. if (*pos=='.') have_radix_point=true;
  150. temp+=(*pos);
  151. ++pos;
  152. }
  153. if (have_radix_point==false)
  154. {
  155. pos=start;
  156. return false;
  157. }
  158. value = strtod(temp.c_str(), 0);
  159. return true;
  160. }
  161. //////////////////// List Object //////////////////////////////////////
  162. list::list(std::string &s):object(T_LIST)
  163. {
  164. std::string::iterator pos = s.begin();
  165. parseObject(pos, s.end());
  166. }
  167. /** Converts the object into a string object if possible. */
  168. string
  169. list::ToString()
  170. {
  171. std::string temp;
  172. temp+=('[');
  173. for(list_type::iterator it=value.begin(); it!=value.end(); ++it)
  174. {
  175. keeper k = *it;
  176. switch(k->ObjectType())
  177. {
  178. case object::T_STRING:
  179. {
  180. temp+=(k->ToString().QuotedValue());
  181. } break;
  182. default:
  183. {
  184. temp+=(k->ToString().Value());
  185. }
  186. }
  187. temp+=(',');
  188. }
  189. temp+=(']');
  190. return string(temp.c_str());
  191. }
  192. /** Converts the object into an integer object, if possible. */
  193. integer
  194. list::ToInt()
  195. {
  196. return integer(0);
  197. }
  198. /** Converts the object into a float object, if possible. */
  199. floating
  200. list::ToFloat()
  201. {
  202. return floating(0.0);
  203. }
  204. csRef<iString>
  205. list::ReprObject()
  206. {
  207. return csPtr<iString> (new scfString (ToString().Value()));
  208. }
  209. bool
  210. list::parseObject(std::string::iterator &pos, const std::string::iterator &end)
  211. {
  212. value.clear();
  213. if (pos==end || *pos!='[') return false;
  214. ++pos;
  215. for(; pos!=end && *pos!=']'; ++pos)
  216. {
  217. // ignore whitespace
  218. if (isspace(*pos) || *pos==',') continue;
  219. keeper k(Parse(pos, end));
  220. if (k.IsValid())
  221. {
  222. value.push_back(k);
  223. }
  224. else
  225. value.push_back(keeper(Nil()));
  226. }
  227. return true;
  228. }
  229. list
  230. list::operator+=(const keeper &k)
  231. {
  232. value.push_back(k);
  233. return *this;
  234. }
  235. keeper
  236. list::at(size_t index)
  237. {
  238. if (index>value.size()) return keeper(Nil());
  239. else return keeper(value.at(index));
  240. }
  241. //////////////////// Reference Object //////////////////////////////////////
  242. /** Converts the object into a reference object if possible. */
  243. string
  244. reference::ToString()
  245. {
  246. return (*fn)[value]->ToString();
  247. }
  248. /** Converts the object into an integer object, if possible. */
  249. integer
  250. reference::ToInt()
  251. {
  252. return (*fn)[value]->ToInt();
  253. }
  254. /** Converts the object into a float object, if possible. */
  255. floating
  256. reference::ToFloat()
  257. {
  258. return (*fn)[value]->ToFloat();
  259. }
  260. csRef<iString>
  261. reference::ReprObject()
  262. {
  263. return csPtr<iString> (new scfString (value));
  264. }
  265. bool
  266. reference::parseObject(std::string::iterator &pos, const std::string::iterator &end)
  267. {
  268. value = "";
  269. if (pos==end || *pos != '$') return false;
  270. for(; pos!=end && (*pos=='$' || isalnum(*pos)); ++pos)
  271. value+=(*pos);
  272. return true;
  273. }
  274. //////////////////// Nil Object //////////////////////////////////////
  275. /** Converts the object into a string object if possible. */
  276. string
  277. nil::ToString()
  278. {
  279. return string();
  280. }
  281. /** Converts the object into an integer object, if possible. */
  282. integer
  283. nil::ToInt()
  284. {
  285. return integer(0);
  286. }
  287. /** Converts the object into a float object, if possible. */
  288. floating
  289. nil::ToFloat()
  290. {
  291. return floating(0.0);
  292. }
  293. csRef<iString>
  294. nil::ReprObject()
  295. {
  296. return csPtr<iString> (new scfString ("nil"));
  297. }
  298. bool
  299. nil::parseObject(std::string::iterator &pos, const std::string::iterator &end)
  300. {
  301. if (pos==end || *pos!='n') return false;
  302. if (pos==end || *(++pos)!='i') return false;
  303. if (pos==end || *(++pos)!='l') return false;
  304. ++pos;
  305. return true;
  306. }
  307. //////////////////// Blob Object //////////////////////////////////////
  308. static uint pow85[] = {
  309. 85*85*85*85, 85*85*85, 85*85, 85, 1
  310. };
  311. /** Encodes a tuple into ascii85 format. */
  312. void
  313. blob::encode_tuple(uint tuple, int /*count*/)
  314. {
  315. //filter::console_output out;
  316. int i;
  317. char buf[5];
  318. for(i=0; i<5; ++i)
  319. {
  320. buf[i] = tuple % 85;
  321. tuple /= 85;
  322. }
  323. for(i=4; i>=0; --i)
  324. {
  325. char c = buf[i];
  326. encoded+=(c + '!');
  327. //out << "blob: encoded " << c << ":" << (c + '!') << "\n";
  328. }
  329. }
  330. /** Encodes a data buffer into ascii85 format. */
  331. void
  332. blob::encode(unsigned char *data, uint size)
  333. {
  334. encoded.assign("<~", 2);
  335. uint tuple=0;
  336. uint i;
  337. int count=0;
  338. for(i=0; i<size; ++i)
  339. {
  340. unsigned char c = data[i];
  341. switch(count++)
  342. {
  343. case 0: tuple |= (c<<24); break;
  344. case 1: tuple |= (c<<16); break;
  345. case 2: tuple |= (c<<8); break;
  346. case 3:
  347. tuple |= c;
  348. if (tuple==0) encoded+=('z');
  349. else encode_tuple(tuple, count);
  350. tuple=0;
  351. count=0;
  352. break;
  353. }
  354. }
  355. if (count>0) encode_tuple(tuple, count);
  356. encoded.append("~>", 2);
  357. }
  358. void
  359. blob::decode_tuple(uint tuple, int bytes, raw_data_t &output)
  360. {
  361. switch (bytes)
  362. {
  363. case 4:
  364. output.push_back(tuple >> 24);
  365. output.push_back(tuple >> 16);
  366. output.push_back(tuple >> 8);
  367. output.push_back(tuple);
  368. break;
  369. case 3:
  370. output.push_back(tuple >> 24);
  371. output.push_back(tuple >> 16);
  372. output.push_back(tuple >> 8);
  373. break;
  374. case 2:
  375. output.push_back(tuple >> 24);
  376. output.push_back(tuple >> 16);
  377. break;
  378. case 1:
  379. output.push_back(tuple >> 24);
  380. break;
  381. }
  382. }
  383. bool
  384. blob::decode(raw_data_t &output)
  385. {
  386. output.clear();
  387. uint tuple=0;
  388. int count=0;
  389. unsigned char c;
  390. std::string::iterator pos=encoded.begin();
  391. if (encoded.size()<2) return false;
  392. // Check for the <~ opening sequence.
  393. if (*pos != '<') return false;
  394. else ++pos;
  395. if (*pos != '~') return false;
  396. else ++pos;
  397. for(; pos!=encoded.end(); ++pos)
  398. {
  399. c = *pos;
  400. switch(c)
  401. {
  402. default:
  403. // Check to see if the character is in range. If not, abort.
  404. if (c < '!' || c > 'u')
  405. {
  406. //out << "blob: bad character in the stream, char code=" << c << ".\n";
  407. return false;
  408. }
  409. tuple += (c-'!') * pow85[count++];
  410. // out << "blob: decode tuple: " << tuple << "\n";
  411. if (count==5)
  412. {
  413. decode_tuple(tuple, 4, output);
  414. count=0;
  415. tuple=0;
  416. }
  417. break;
  418. case 'z':
  419. // A 'z' should appear only by itself, not inside a 5-tuple.
  420. if (count!=0)
  421. {
  422. //out << "blob: decode error: 'z' occurs inside 5-tuple.\n";
  423. return false;
  424. }
  425. output.push_back(0);
  426. output.push_back(0);
  427. output.push_back(0);
  428. output.push_back(0);
  429. break;
  430. case '~':
  431. c= *(++pos);
  432. if (c=='>')
  433. {
  434. if (count>0)
  435. {
  436. --count;
  437. tuple+=pow85[count];
  438. decode_tuple(tuple, count, output);
  439. }
  440. return true;
  441. }
  442. else
  443. {
  444. //out << "blob: decode: invalid terminating sequence. Data may be corrupt.\n";
  445. // Invalid terminating sequence. A '~' must be followed by a '>' or preceded by a '<'
  446. // to begin or end an ascii85 sequence.
  447. return false;
  448. }
  449. break;
  450. // Ignore whitespace or other control characters.
  451. case '\n': case '\r': case '\t': case ' ':
  452. case '\0': case '\f': case '\b': case 0177:
  453. break;
  454. }
  455. }
  456. return true;
  457. }
  458. string
  459. blob::ToString()
  460. {
  461. return string(encoded.c_str());
  462. }
  463. integer
  464. blob::ToInt()
  465. {
  466. return 0;
  467. }
  468. floating
  469. blob::ToFloat()
  470. {
  471. return 0.0;
  472. }
  473. csRef<iString>
  474. blob::ReprObject()
  475. {
  476. char buf[128]={0};
  477. std::string tmp("/");
  478. tmp.append(std::string(buf, cs_snprintf(buf, sizeof(buf), "%zu", encoded.size())));
  479. tmp.append(encoded);
  480. return csPtr<iString>(new scfString(tmp.c_str()));
  481. }
  482. bool
  483. blob::parseObject(std::string::iterator &pos, const std::string::iterator &end)
  484. {
  485. uint size;
  486. if (pos==end || *pos!='/') return false;
  487. ++pos;
  488. // Get the size of the blob.
  489. std::string temp;
  490. for(; pos!=end && isdigit(*pos); ++pos)
  491. temp+=(*pos);
  492. // If there is no size, then abort.
  493. if (temp.size()==0) return false;
  494. size = strtoll(temp.c_str(), 0, 10);
  495. // Get the entire encoded string.
  496. for(uint i=0; i<size && pos!=end; ++i, ++pos)
  497. {
  498. encoded+=(*pos);
  499. }
  500. return true;
  501. }
  502. /////////////////////////////////// Variable Object ///////////////////////
  503. string
  504. var::ToString()
  505. {
  506. return sc->get(id)->ToString();
  507. }
  508. integer
  509. var::ToInt()
  510. {
  511. return sc->get(id)->ToInt();
  512. }
  513. floating
  514. var::ToFloat()
  515. {
  516. return sc->get(id)->ToFloat();
  517. }
  518. csRef<iString>
  519. var::ReprObject()
  520. {
  521. return sc->get(id)->ReprObject();
  522. }
  523. bool
  524. var::parseObject(std::string::iterator &pos, const std::string::iterator &end)
  525. {
  526. ++pos;
  527. csString name;
  528. // Get the name
  529. while(pos!=end && isalnum(*pos))
  530. {
  531. name+=(*pos);
  532. ++pos;
  533. }
  534. id = Registrar()->getId(name);
  535. return true;
  536. }
  537. } // namespace autom
  538. } // namespace aws