lookaheadparser.cpp 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352
  1. #include <rtthread.h>
  2. #include "rapidjson/reader.h"
  3. #include "rapidjson/document.h"
  4. #include <iostream>
  5. RAPIDJSON_DIAG_PUSH
  6. #ifdef __GNUC__
  7. RAPIDJSON_DIAG_OFF(effc++)
  8. #endif
  9. // This example demonstrates JSON token-by-token parsing with an API that is
  10. // more direct; you don't need to design your logic around a handler object and
  11. // callbacks. Instead, you retrieve values from the JSON stream by calling
  12. // GetInt(), GetDouble(), GetString() and GetBool(), traverse into structures
  13. // by calling EnterObject() and EnterArray(), and skip over unwanted data by
  14. // calling SkipValue(). When you know your JSON's structure, this can be quite
  15. // convenient.
  16. //
  17. // If you aren't sure of what's next in the JSON data, you can use PeekType() and
  18. // PeekValue() to look ahead to the next object before reading it.
  19. //
  20. // If you call the wrong retrieval method--e.g. GetInt when the next JSON token is
  21. // not an int, EnterObject or EnterArray when there isn't actually an object or array
  22. // to read--the stream parsing will end immediately and no more data will be delivered.
  23. //
  24. // After calling EnterObject, you retrieve keys via NextObjectKey() and values via
  25. // the normal getters. When NextObjectKey() returns null, you have exited the
  26. // object, or you can call SkipObject() to skip to the end of the object
  27. // immediately. If you fetch the entire object (i.e. NextObjectKey() returned null),
  28. // you should not call SkipObject().
  29. //
  30. // After calling EnterArray(), you must alternate between calling NextArrayValue()
  31. // to see if the array has more data, and then retrieving values via the normal
  32. // getters. You can call SkipArray() to skip to the end of the array immediately.
  33. // If you fetch the entire array (i.e. NextArrayValue() returned null),
  34. // you should not call SkipArray().
  35. //
  36. // This parser uses in-situ strings, so the JSON buffer will be altered during the
  37. // parse.
  38. using namespace rapidjson;
  39. class LookaheadParserHandler {
  40. public:
  41. bool Null() { st_ = kHasNull; v_.SetNull(); return true; }
  42. bool Bool(bool b) { st_ = kHasBool; v_.SetBool(b); return true; }
  43. bool Int(int i) { st_ = kHasNumber; v_.SetInt(i); return true; }
  44. bool Uint(unsigned u) { st_ = kHasNumber; v_.SetUint(u); return true; }
  45. bool Int64(int64_t i) { st_ = kHasNumber; v_.SetInt64(i); return true; }
  46. bool Uint64(uint64_t u) { st_ = kHasNumber; v_.SetUint64(u); return true; }
  47. bool Double(double d) { st_ = kHasNumber; v_.SetDouble(d); return true; }
  48. bool RawNumber(const char*, SizeType, bool) { return false; }
  49. bool String(const char* str, SizeType length, bool) { st_ = kHasString; v_.SetString(str, length); return true; }
  50. bool StartObject() { st_ = kEnteringObject; return true; }
  51. bool Key(const char* str, SizeType length, bool) { st_ = kHasKey; v_.SetString(str, length); return true; }
  52. bool EndObject(SizeType) { st_ = kExitingObject; return true; }
  53. bool StartArray() { st_ = kEnteringArray; return true; }
  54. bool EndArray(SizeType) { st_ = kExitingArray; return true; }
  55. protected:
  56. LookaheadParserHandler(char* str);
  57. void ParseNext();
  58. protected:
  59. enum LookaheadParsingState {
  60. kInit,
  61. kError,
  62. kHasNull,
  63. kHasBool,
  64. kHasNumber,
  65. kHasString,
  66. kHasKey,
  67. kEnteringObject,
  68. kExitingObject,
  69. kEnteringArray,
  70. kExitingArray
  71. };
  72. Value v_;
  73. LookaheadParsingState st_;
  74. Reader r_;
  75. InsituStringStream ss_;
  76. static const int parseFlags = kParseDefaultFlags | kParseInsituFlag;
  77. };
  78. LookaheadParserHandler::LookaheadParserHandler(char* str) : v_(), st_(kInit), r_(), ss_(str) {
  79. r_.IterativeParseInit();
  80. ParseNext();
  81. }
  82. void LookaheadParserHandler::ParseNext() {
  83. if (r_.HasParseError()) {
  84. st_ = kError;
  85. return;
  86. }
  87. r_.IterativeParseNext<parseFlags>(ss_, *this);
  88. }
  89. class LookaheadParser : protected LookaheadParserHandler {
  90. public:
  91. LookaheadParser(char* str) : LookaheadParserHandler(str) {}
  92. bool EnterObject();
  93. bool EnterArray();
  94. const char* NextObjectKey();
  95. bool NextArrayValue();
  96. int GetInt();
  97. double GetDouble();
  98. const char* GetString();
  99. bool GetBool();
  100. void GetNull();
  101. void SkipObject();
  102. void SkipArray();
  103. void SkipValue();
  104. Value* PeekValue();
  105. int PeekType(); // returns a rapidjson::Type, or -1 for no value (at end of object/array)
  106. bool IsValid() { return st_ != kError; }
  107. protected:
  108. void SkipOut(int depth);
  109. };
  110. bool LookaheadParser::EnterObject() {
  111. if (st_ != kEnteringObject) {
  112. st_ = kError;
  113. return false;
  114. }
  115. ParseNext();
  116. return true;
  117. }
  118. bool LookaheadParser::EnterArray() {
  119. if (st_ != kEnteringArray) {
  120. st_ = kError;
  121. return false;
  122. }
  123. ParseNext();
  124. return true;
  125. }
  126. const char* LookaheadParser::NextObjectKey() {
  127. if (st_ == kHasKey) {
  128. const char* result = v_.GetString();
  129. ParseNext();
  130. return result;
  131. }
  132. if (st_ != kExitingObject) {
  133. st_ = kError;
  134. return 0;
  135. }
  136. ParseNext();
  137. return 0;
  138. }
  139. bool LookaheadParser::NextArrayValue() {
  140. if (st_ == kExitingArray) {
  141. ParseNext();
  142. return false;
  143. }
  144. if (st_ == kError || st_ == kExitingObject || st_ == kHasKey) {
  145. st_ = kError;
  146. return false;
  147. }
  148. return true;
  149. }
  150. int LookaheadParser::GetInt() {
  151. if (st_ != kHasNumber || !v_.IsInt()) {
  152. st_ = kError;
  153. return 0;
  154. }
  155. int result = v_.GetInt();
  156. ParseNext();
  157. return result;
  158. }
  159. double LookaheadParser::GetDouble() {
  160. if (st_ != kHasNumber) {
  161. st_ = kError;
  162. return 0.;
  163. }
  164. double result = v_.GetDouble();
  165. ParseNext();
  166. return result;
  167. }
  168. bool LookaheadParser::GetBool() {
  169. if (st_ != kHasBool) {
  170. st_ = kError;
  171. return false;
  172. }
  173. bool result = v_.GetBool();
  174. ParseNext();
  175. return result;
  176. }
  177. void LookaheadParser::GetNull() {
  178. if (st_ != kHasNull) {
  179. st_ = kError;
  180. return;
  181. }
  182. ParseNext();
  183. }
  184. const char* LookaheadParser::GetString() {
  185. if (st_ != kHasString) {
  186. st_ = kError;
  187. return 0;
  188. }
  189. const char* result = v_.GetString();
  190. ParseNext();
  191. return result;
  192. }
  193. void LookaheadParser::SkipOut(int depth) {
  194. do {
  195. if (st_ == kEnteringArray || st_ == kEnteringObject) {
  196. ++depth;
  197. }
  198. else if (st_ == kExitingArray || st_ == kExitingObject) {
  199. --depth;
  200. }
  201. else if (st_ == kError) {
  202. return;
  203. }
  204. ParseNext();
  205. }
  206. while (depth > 0);
  207. }
  208. void LookaheadParser::SkipValue() {
  209. SkipOut(0);
  210. }
  211. void LookaheadParser::SkipArray() {
  212. SkipOut(1);
  213. }
  214. void LookaheadParser::SkipObject() {
  215. SkipOut(1);
  216. }
  217. Value* LookaheadParser::PeekValue() {
  218. if (st_ >= kHasNull && st_ <= kHasKey) {
  219. return &v_;
  220. }
  221. return 0;
  222. }
  223. int LookaheadParser::PeekType() {
  224. if (st_ >= kHasNull && st_ <= kHasKey) {
  225. return v_.GetType();
  226. }
  227. if (st_ == kEnteringArray) {
  228. return kArrayType;
  229. }
  230. if (st_ == kEnteringObject) {
  231. return kObjectType;
  232. }
  233. return -1;
  234. }
  235. //-------------------------------------------------------------------------
  236. int look_ahead_parser() {
  237. using namespace std;
  238. char json[] = " { \"hello\" : \"world\", \"t\" : true , \"f\" : false, \"n\": null,"
  239. "\"i\":123, \"pi\": 3.1416, \"a\":[-1, 2, 3, 4, \"array\", []], \"skipArrays\":[1, 2, [[[3]]]], "
  240. "\"skipObject\":{ \"i\":0, \"t\":true, \"n\":null, \"d\":123.45 }, "
  241. "\"skipNested\":[[[[{\"\":0}, {\"\":[-9.87]}]]], [], []], "
  242. "\"skipString\":\"zzz\", \"reachedEnd\":null, \"t\":true }";
  243. LookaheadParser r(json);
  244. RAPIDJSON_ASSERT(r.PeekType() == kObjectType);
  245. r.EnterObject();
  246. while (const char* key = r.NextObjectKey()) {
  247. if (0 == strcmp(key, "hello")) {
  248. RAPIDJSON_ASSERT(r.PeekType() == kStringType);
  249. cout << key << ":" << r.GetString() << endl;
  250. }
  251. else if (0 == strcmp(key, "t") || 0 == strcmp(key, "f")) {
  252. RAPIDJSON_ASSERT(r.PeekType() == kTrueType || r.PeekType() == kFalseType);
  253. cout << key << ":" << r.GetBool() << endl;
  254. continue;
  255. }
  256. else if (0 == strcmp(key, "n")) {
  257. RAPIDJSON_ASSERT(r.PeekType() == kNullType);
  258. r.GetNull();
  259. cout << key << endl;
  260. continue;
  261. }
  262. else if (0 == strcmp(key, "pi")) {
  263. RAPIDJSON_ASSERT(r.PeekType() == kNumberType);
  264. cout << key << ":" << r.GetDouble() << endl;
  265. continue;
  266. }
  267. else if (0 == strcmp(key, "a")) {
  268. RAPIDJSON_ASSERT(r.PeekType() == kArrayType);
  269. r.EnterArray();
  270. cout << key << ":[ ";
  271. while (r.NextArrayValue()) {
  272. if (r.PeekType() == kNumberType) {
  273. cout << r.GetDouble() << " ";
  274. }
  275. else if (r.PeekType() == kStringType) {
  276. cout << r.GetString() << " ";
  277. }
  278. else {
  279. r.SkipArray();
  280. break;
  281. }
  282. }
  283. cout << "]" << endl;
  284. }
  285. else {
  286. cout << key << ":skipped" << endl;
  287. r.SkipValue();
  288. }
  289. }
  290. return 0;
  291. }
  292. MSH_CMD_EXPORT(look_ahead_parser, rapid json look ahead parser example);
  293. RAPIDJSON_DIAG_POP