unit-class_parser.cpp 87 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790
  1. /*
  2. __ _____ _____ _____
  3. __| | __| | | | JSON for Modern C++ (test suite)
  4. | | |__ | | | | | | version 3.7.3
  5. |_____|_____|_____|_|___| https://github.com/nlohmann/json
  6. Licensed under the MIT License <http://opensource.org/licenses/MIT>.
  7. SPDX-License-Identifier: MIT
  8. Copyright (c) 2013-2019 Niels Lohmann <http://nlohmann.me>.
  9. Permission is hereby granted, free of charge, to any person obtaining a copy
  10. of this software and associated documentation files (the "Software"), to deal
  11. in the Software without restriction, including without limitation the rights
  12. to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  13. copies of the Software, and to permit persons to whom the Software is
  14. furnished to do so, subject to the following conditions:
  15. The above copyright notice and this permission notice shall be included in all
  16. copies or substantial portions of the Software.
  17. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  18. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  19. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  20. AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  21. LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  22. OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  23. SOFTWARE.
  24. */
  25. #include "doctest_compatibility.h"
  26. #define private public
  27. #include <nlohmann/json.hpp>
  28. using nlohmann::json;
  29. #undef private
  30. #include <valarray>
  31. namespace
  32. {
  33. class SaxEventLogger
  34. {
  35. public:
  36. bool null()
  37. {
  38. events.push_back("null()");
  39. return true;
  40. }
  41. bool boolean(bool val)
  42. {
  43. events.push_back(val ? "boolean(true)" : "boolean(false)");
  44. return true;
  45. }
  46. bool number_integer(json::number_integer_t val)
  47. {
  48. events.push_back("number_integer(" + std::to_string(val) + ")");
  49. return true;
  50. }
  51. bool number_unsigned(json::number_unsigned_t val)
  52. {
  53. events.push_back("number_unsigned(" + std::to_string(val) + ")");
  54. return true;
  55. }
  56. bool number_float(json::number_float_t, const std::string& s)
  57. {
  58. events.push_back("number_float(" + s + ")");
  59. return true;
  60. }
  61. bool string(std::string& val)
  62. {
  63. events.push_back("string(" + val + ")");
  64. return true;
  65. }
  66. bool binary(json::binary_t& val)
  67. {
  68. std::string binary_contents = "binary(";
  69. std::string comma_space = "";
  70. for (auto b : val)
  71. {
  72. binary_contents.append(comma_space);
  73. binary_contents.append(std::to_string(static_cast<int>(b)));
  74. comma_space = ", ";
  75. }
  76. binary_contents.append(")");
  77. events.push_back(binary_contents);
  78. return true;
  79. }
  80. bool start_object(std::size_t elements)
  81. {
  82. if (elements == std::size_t(-1))
  83. {
  84. events.push_back("start_object()");
  85. }
  86. else
  87. {
  88. events.push_back("start_object(" + std::to_string(elements) + ")");
  89. }
  90. return true;
  91. }
  92. bool key(std::string& val)
  93. {
  94. events.push_back("key(" + val + ")");
  95. return true;
  96. }
  97. bool end_object()
  98. {
  99. events.push_back("end_object()");
  100. return true;
  101. }
  102. bool start_array(std::size_t elements)
  103. {
  104. if (elements == std::size_t(-1))
  105. {
  106. events.push_back("start_array()");
  107. }
  108. else
  109. {
  110. events.push_back("start_array(" + std::to_string(elements) + ")");
  111. }
  112. return true;
  113. }
  114. bool end_array()
  115. {
  116. events.push_back("end_array()");
  117. return true;
  118. }
  119. bool parse_error(std::size_t position, const std::string&, const json::exception&)
  120. {
  121. errored = true;
  122. events.push_back("parse_error(" + std::to_string(position) + ")");
  123. return false;
  124. }
  125. std::vector<std::string> events {};
  126. bool errored = false;
  127. };
  128. class SaxCountdown : public nlohmann::json::json_sax_t
  129. {
  130. public:
  131. explicit SaxCountdown(const int count) : events_left(count)
  132. {}
  133. bool null() override
  134. {
  135. return events_left-- > 0;
  136. }
  137. bool boolean(bool) override
  138. {
  139. return events_left-- > 0;
  140. }
  141. bool number_integer(json::number_integer_t) override
  142. {
  143. return events_left-- > 0;
  144. }
  145. bool number_unsigned(json::number_unsigned_t) override
  146. {
  147. return events_left-- > 0;
  148. }
  149. bool number_float(json::number_float_t, const std::string&) override
  150. {
  151. return events_left-- > 0;
  152. }
  153. bool string(std::string&) override
  154. {
  155. return events_left-- > 0;
  156. }
  157. bool binary(json::binary_t&) override
  158. {
  159. return events_left-- > 0;
  160. }
  161. bool start_object(std::size_t) override
  162. {
  163. return events_left-- > 0;
  164. }
  165. bool key(std::string&) override
  166. {
  167. return events_left-- > 0;
  168. }
  169. bool end_object() override
  170. {
  171. return events_left-- > 0;
  172. }
  173. bool start_array(std::size_t) override
  174. {
  175. return events_left-- > 0;
  176. }
  177. bool end_array() override
  178. {
  179. return events_left-- > 0;
  180. }
  181. bool parse_error(std::size_t, const std::string&, const json::exception&) override
  182. {
  183. return false;
  184. }
  185. private:
  186. int events_left = 0;
  187. };
  188. json parser_helper(const std::string& s);
  189. bool accept_helper(const std::string& s);
  190. json parser_helper(const std::string& s)
  191. {
  192. json j;
  193. json::parser(nlohmann::detail::input_adapter(s)).parse(true, j);
  194. // if this line was reached, no exception occurred
  195. // -> check if result is the same without exceptions
  196. json j_nothrow;
  197. CHECK_NOTHROW(json::parser(nlohmann::detail::input_adapter(s), nullptr, false).parse(true, j_nothrow));
  198. CHECK(j_nothrow == j);
  199. json j_sax;
  200. nlohmann::detail::json_sax_dom_parser<json> sdp(j_sax);
  201. json::sax_parse(s, &sdp);
  202. CHECK(j_sax == j);
  203. return j;
  204. }
  205. bool accept_helper(const std::string& s)
  206. {
  207. CAPTURE(s)
  208. // 1. parse s without exceptions
  209. json j;
  210. CHECK_NOTHROW(json::parser(nlohmann::detail::input_adapter(s), nullptr, false).parse(true, j));
  211. const bool ok_noexcept = not j.is_discarded();
  212. // 2. accept s
  213. const bool ok_accept = json::parser(nlohmann::detail::input_adapter(s)).accept(true);
  214. // 3. check if both approaches come to the same result
  215. CHECK(ok_noexcept == ok_accept);
  216. // 4. parse with SAX (compare with relaxed accept result)
  217. SaxEventLogger el;
  218. CHECK_NOTHROW(json::sax_parse(s, &el, json::input_format_t::json, false));
  219. CHECK(json::parser(nlohmann::detail::input_adapter(s)).accept(false) == not el.errored);
  220. // 5. parse with simple callback
  221. json::parser_callback_t cb = [](int, json::parse_event_t, json&)
  222. {
  223. return true;
  224. };
  225. json j_cb = json::parse(s, cb, false);
  226. const bool ok_noexcept_cb = not j_cb.is_discarded();
  227. // 6. check if this approach came to the same result
  228. CHECK(ok_noexcept == ok_noexcept_cb);
  229. // 7. return result
  230. return ok_accept;
  231. }
  232. }
  233. TEST_CASE("parser class")
  234. {
  235. SECTION("parse")
  236. {
  237. SECTION("null")
  238. {
  239. CHECK(parser_helper("null") == json(nullptr));
  240. }
  241. SECTION("true")
  242. {
  243. CHECK(parser_helper("true") == json(true));
  244. }
  245. SECTION("false")
  246. {
  247. CHECK(parser_helper("false") == json(false));
  248. }
  249. SECTION("array")
  250. {
  251. SECTION("empty array")
  252. {
  253. CHECK(parser_helper("[]") == json(json::value_t::array));
  254. CHECK(parser_helper("[ ]") == json(json::value_t::array));
  255. }
  256. SECTION("nonempty array")
  257. {
  258. CHECK(parser_helper("[true, false, null]") == json({true, false, nullptr}));
  259. }
  260. }
  261. SECTION("object")
  262. {
  263. SECTION("empty object")
  264. {
  265. CHECK(parser_helper("{}") == json(json::value_t::object));
  266. CHECK(parser_helper("{ }") == json(json::value_t::object));
  267. }
  268. SECTION("nonempty object")
  269. {
  270. CHECK(parser_helper("{\"\": true, \"one\": 1, \"two\": null}") == json({{"", true}, {"one", 1}, {"two", nullptr}}));
  271. }
  272. }
  273. SECTION("string")
  274. {
  275. // empty string
  276. CHECK(parser_helper("\"\"") == json(json::value_t::string));
  277. SECTION("errors")
  278. {
  279. // error: tab in string
  280. CHECK_THROWS_AS(parser_helper("\"\t\""), json::parse_error&);
  281. CHECK_THROWS_WITH(parser_helper("\"\t\""),
  282. "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+0009 (HT) must be escaped to \\u0009 or \\t; last read: '\"<U+0009>'");
  283. // error: newline in string
  284. CHECK_THROWS_AS(parser_helper("\"\n\""), json::parse_error&);
  285. CHECK_THROWS_AS(parser_helper("\"\r\""), json::parse_error&);
  286. CHECK_THROWS_WITH(parser_helper("\"\n\""),
  287. "[json.exception.parse_error.101] parse error at line 2, column 0: syntax error while parsing value - invalid string: control character U+000A (LF) must be escaped to \\u000A or \\n; last read: '\"<U+000A>'");
  288. CHECK_THROWS_WITH(parser_helper("\"\r\""),
  289. "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+000D (CR) must be escaped to \\u000D or \\r; last read: '\"<U+000D>'");
  290. // error: backspace in string
  291. CHECK_THROWS_AS(parser_helper("\"\b\""), json::parse_error&);
  292. CHECK_THROWS_WITH(parser_helper("\"\b\""),
  293. "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+0008 (BS) must be escaped to \\u0008 or \\b; last read: '\"<U+0008>'");
  294. // improve code coverage
  295. CHECK_THROWS_AS(parser_helper("\uFF01"), json::parse_error&);
  296. CHECK_THROWS_AS(parser_helper("[-4:1,]"), json::parse_error&);
  297. // unescaped control characters
  298. CHECK_THROWS_AS(parser_helper("\"\x00\""), json::parse_error&);
  299. CHECK_THROWS_AS(parser_helper("\"\x01\""), json::parse_error&);
  300. CHECK_THROWS_AS(parser_helper("\"\x02\""), json::parse_error&);
  301. CHECK_THROWS_AS(parser_helper("\"\x03\""), json::parse_error&);
  302. CHECK_THROWS_AS(parser_helper("\"\x04\""), json::parse_error&);
  303. CHECK_THROWS_AS(parser_helper("\"\x05\""), json::parse_error&);
  304. CHECK_THROWS_AS(parser_helper("\"\x06\""), json::parse_error&);
  305. CHECK_THROWS_AS(parser_helper("\"\x07\""), json::parse_error&);
  306. CHECK_THROWS_AS(parser_helper("\"\x08\""), json::parse_error&);
  307. CHECK_THROWS_AS(parser_helper("\"\x09\""), json::parse_error&);
  308. CHECK_THROWS_AS(parser_helper("\"\x0a\""), json::parse_error&);
  309. CHECK_THROWS_AS(parser_helper("\"\x0b\""), json::parse_error&);
  310. CHECK_THROWS_AS(parser_helper("\"\x0c\""), json::parse_error&);
  311. CHECK_THROWS_AS(parser_helper("\"\x0d\""), json::parse_error&);
  312. CHECK_THROWS_AS(parser_helper("\"\x0e\""), json::parse_error&);
  313. CHECK_THROWS_AS(parser_helper("\"\x0f\""), json::parse_error&);
  314. CHECK_THROWS_AS(parser_helper("\"\x10\""), json::parse_error&);
  315. CHECK_THROWS_AS(parser_helper("\"\x11\""), json::parse_error&);
  316. CHECK_THROWS_AS(parser_helper("\"\x12\""), json::parse_error&);
  317. CHECK_THROWS_AS(parser_helper("\"\x13\""), json::parse_error&);
  318. CHECK_THROWS_AS(parser_helper("\"\x14\""), json::parse_error&);
  319. CHECK_THROWS_AS(parser_helper("\"\x15\""), json::parse_error&);
  320. CHECK_THROWS_AS(parser_helper("\"\x16\""), json::parse_error&);
  321. CHECK_THROWS_AS(parser_helper("\"\x17\""), json::parse_error&);
  322. CHECK_THROWS_AS(parser_helper("\"\x18\""), json::parse_error&);
  323. CHECK_THROWS_AS(parser_helper("\"\x19\""), json::parse_error&);
  324. CHECK_THROWS_AS(parser_helper("\"\x1a\""), json::parse_error&);
  325. CHECK_THROWS_AS(parser_helper("\"\x1b\""), json::parse_error&);
  326. CHECK_THROWS_AS(parser_helper("\"\x1c\""), json::parse_error&);
  327. CHECK_THROWS_AS(parser_helper("\"\x1d\""), json::parse_error&);
  328. CHECK_THROWS_AS(parser_helper("\"\x1e\""), json::parse_error&);
  329. CHECK_THROWS_AS(parser_helper("\"\x1f\""), json::parse_error&);
  330. CHECK_THROWS_WITH(parser_helper("\"\x00\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: missing closing quote; last read: '\"'");
  331. CHECK_THROWS_WITH(parser_helper("\"\x01\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+0001 (SOH) must be escaped to \\u0001; last read: '\"<U+0001>'");
  332. CHECK_THROWS_WITH(parser_helper("\"\x02\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+0002 (STX) must be escaped to \\u0002; last read: '\"<U+0002>'");
  333. CHECK_THROWS_WITH(parser_helper("\"\x03\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+0003 (ETX) must be escaped to \\u0003; last read: '\"<U+0003>'");
  334. CHECK_THROWS_WITH(parser_helper("\"\x04\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+0004 (EOT) must be escaped to \\u0004; last read: '\"<U+0004>'");
  335. CHECK_THROWS_WITH(parser_helper("\"\x05\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+0005 (ENQ) must be escaped to \\u0005; last read: '\"<U+0005>'");
  336. CHECK_THROWS_WITH(parser_helper("\"\x06\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+0006 (ACK) must be escaped to \\u0006; last read: '\"<U+0006>'");
  337. CHECK_THROWS_WITH(parser_helper("\"\x07\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+0007 (BEL) must be escaped to \\u0007; last read: '\"<U+0007>'");
  338. CHECK_THROWS_WITH(parser_helper("\"\x08\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+0008 (BS) must be escaped to \\u0008 or \\b; last read: '\"<U+0008>'");
  339. CHECK_THROWS_WITH(parser_helper("\"\x09\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+0009 (HT) must be escaped to \\u0009 or \\t; last read: '\"<U+0009>'");
  340. CHECK_THROWS_WITH(parser_helper("\"\x0a\""), "[json.exception.parse_error.101] parse error at line 2, column 0: syntax error while parsing value - invalid string: control character U+000A (LF) must be escaped to \\u000A or \\n; last read: '\"<U+000A>'");
  341. CHECK_THROWS_WITH(parser_helper("\"\x0b\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+000B (VT) must be escaped to \\u000B; last read: '\"<U+000B>'");
  342. CHECK_THROWS_WITH(parser_helper("\"\x0c\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+000C (FF) must be escaped to \\u000C or \\f; last read: '\"<U+000C>'");
  343. CHECK_THROWS_WITH(parser_helper("\"\x0d\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+000D (CR) must be escaped to \\u000D or \\r; last read: '\"<U+000D>'");
  344. CHECK_THROWS_WITH(parser_helper("\"\x0e\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+000E (SO) must be escaped to \\u000E; last read: '\"<U+000E>'");
  345. CHECK_THROWS_WITH(parser_helper("\"\x0f\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+000F (SI) must be escaped to \\u000F; last read: '\"<U+000F>'");
  346. CHECK_THROWS_WITH(parser_helper("\"\x10\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+0010 (DLE) must be escaped to \\u0010; last read: '\"<U+0010>'");
  347. CHECK_THROWS_WITH(parser_helper("\"\x11\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+0011 (DC1) must be escaped to \\u0011; last read: '\"<U+0011>'");
  348. CHECK_THROWS_WITH(parser_helper("\"\x12\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+0012 (DC2) must be escaped to \\u0012; last read: '\"<U+0012>'");
  349. CHECK_THROWS_WITH(parser_helper("\"\x13\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+0013 (DC3) must be escaped to \\u0013; last read: '\"<U+0013>'");
  350. CHECK_THROWS_WITH(parser_helper("\"\x14\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+0014 (DC4) must be escaped to \\u0014; last read: '\"<U+0014>'");
  351. CHECK_THROWS_WITH(parser_helper("\"\x15\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+0015 (NAK) must be escaped to \\u0015; last read: '\"<U+0015>'");
  352. CHECK_THROWS_WITH(parser_helper("\"\x16\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+0016 (SYN) must be escaped to \\u0016; last read: '\"<U+0016>'");
  353. CHECK_THROWS_WITH(parser_helper("\"\x17\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+0017 (ETB) must be escaped to \\u0017; last read: '\"<U+0017>'");
  354. CHECK_THROWS_WITH(parser_helper("\"\x18\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+0018 (CAN) must be escaped to \\u0018; last read: '\"<U+0018>'");
  355. CHECK_THROWS_WITH(parser_helper("\"\x19\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+0019 (EM) must be escaped to \\u0019; last read: '\"<U+0019>'");
  356. CHECK_THROWS_WITH(parser_helper("\"\x1a\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+001A (SUB) must be escaped to \\u001A; last read: '\"<U+001A>'");
  357. CHECK_THROWS_WITH(parser_helper("\"\x1b\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+001B (ESC) must be escaped to \\u001B; last read: '\"<U+001B>'");
  358. CHECK_THROWS_WITH(parser_helper("\"\x1c\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+001C (FS) must be escaped to \\u001C; last read: '\"<U+001C>'");
  359. CHECK_THROWS_WITH(parser_helper("\"\x1d\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+001D (GS) must be escaped to \\u001D; last read: '\"<U+001D>'");
  360. CHECK_THROWS_WITH(parser_helper("\"\x1e\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+001E (RS) must be escaped to \\u001E; last read: '\"<U+001E>'");
  361. CHECK_THROWS_WITH(parser_helper("\"\x1f\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+001F (US) must be escaped to \\u001F; last read: '\"<U+001F>'");
  362. SECTION("additional test for null byte")
  363. {
  364. // The test above for the null byte is wrong, because passing
  365. // a string to the parser only reads int until it encounters
  366. // a null byte. This test inserts the null byte later on and
  367. // uses an iterator range.
  368. std::string s = "\"1\"";
  369. s[1] = '\0';
  370. json _;
  371. CHECK_THROWS_AS(_ = json::parse(s.begin(), s.end()), json::parse_error&);
  372. CHECK_THROWS_WITH(_ = json::parse(s.begin(), s.end()), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+0000 (NUL) must be escaped to \\u0000; last read: '\"<U+0000>'");
  373. }
  374. }
  375. SECTION("escaped")
  376. {
  377. // quotation mark "\""
  378. auto r1 = R"("\"")"_json;
  379. CHECK(parser_helper("\"\\\"\"") == r1);
  380. // reverse solidus "\\"
  381. auto r2 = R"("\\")"_json;
  382. CHECK(parser_helper("\"\\\\\"") == r2);
  383. // solidus
  384. CHECK(parser_helper("\"\\/\"") == R"("/")"_json);
  385. // backspace
  386. CHECK(parser_helper("\"\\b\"") == json("\b"));
  387. // formfeed
  388. CHECK(parser_helper("\"\\f\"") == json("\f"));
  389. // newline
  390. CHECK(parser_helper("\"\\n\"") == json("\n"));
  391. // carriage return
  392. CHECK(parser_helper("\"\\r\"") == json("\r"));
  393. // horizontal tab
  394. CHECK(parser_helper("\"\\t\"") == json("\t"));
  395. CHECK(parser_helper("\"\\u0001\"").get<json::string_t>() == "\x01");
  396. CHECK(parser_helper("\"\\u000a\"").get<json::string_t>() == "\n");
  397. CHECK(parser_helper("\"\\u00b0\"").get<json::string_t>() == "°");
  398. CHECK(parser_helper("\"\\u0c00\"").get<json::string_t>() == "ఀ");
  399. CHECK(parser_helper("\"\\ud000\"").get<json::string_t>() == "퀀");
  400. CHECK(parser_helper("\"\\u000E\"").get<json::string_t>() == "\x0E");
  401. CHECK(parser_helper("\"\\u00F0\"").get<json::string_t>() == "ð");
  402. CHECK(parser_helper("\"\\u0100\"").get<json::string_t>() == "Ā");
  403. CHECK(parser_helper("\"\\u2000\"").get<json::string_t>() == " ");
  404. CHECK(parser_helper("\"\\uFFFF\"").get<json::string_t>() == "￿");
  405. CHECK(parser_helper("\"\\u20AC\"").get<json::string_t>() == "€");
  406. CHECK(parser_helper("\"€\"").get<json::string_t>() == "€");
  407. CHECK(parser_helper("\"🎈\"").get<json::string_t>() == "🎈");
  408. CHECK(parser_helper("\"\\ud80c\\udc60\"").get<json::string_t>() == u8"\U00013060");
  409. CHECK(parser_helper("\"\\ud83c\\udf1e\"").get<json::string_t>() == "🌞");
  410. }
  411. }
  412. SECTION("number")
  413. {
  414. SECTION("integers")
  415. {
  416. SECTION("without exponent")
  417. {
  418. CHECK(parser_helper("-128") == json(-128));
  419. CHECK(parser_helper("-0") == json(-0));
  420. CHECK(parser_helper("0") == json(0));
  421. CHECK(parser_helper("128") == json(128));
  422. }
  423. SECTION("with exponent")
  424. {
  425. CHECK(parser_helper("0e1") == json(0e1));
  426. CHECK(parser_helper("0E1") == json(0e1));
  427. CHECK(parser_helper("10000E-4") == json(10000e-4));
  428. CHECK(parser_helper("10000E-3") == json(10000e-3));
  429. CHECK(parser_helper("10000E-2") == json(10000e-2));
  430. CHECK(parser_helper("10000E-1") == json(10000e-1));
  431. CHECK(parser_helper("10000E0") == json(10000e0));
  432. CHECK(parser_helper("10000E1") == json(10000e1));
  433. CHECK(parser_helper("10000E2") == json(10000e2));
  434. CHECK(parser_helper("10000E3") == json(10000e3));
  435. CHECK(parser_helper("10000E4") == json(10000e4));
  436. CHECK(parser_helper("10000e-4") == json(10000e-4));
  437. CHECK(parser_helper("10000e-3") == json(10000e-3));
  438. CHECK(parser_helper("10000e-2") == json(10000e-2));
  439. CHECK(parser_helper("10000e-1") == json(10000e-1));
  440. CHECK(parser_helper("10000e0") == json(10000e0));
  441. CHECK(parser_helper("10000e1") == json(10000e1));
  442. CHECK(parser_helper("10000e2") == json(10000e2));
  443. CHECK(parser_helper("10000e3") == json(10000e3));
  444. CHECK(parser_helper("10000e4") == json(10000e4));
  445. CHECK(parser_helper("-0e1") == json(-0e1));
  446. CHECK(parser_helper("-0E1") == json(-0e1));
  447. CHECK(parser_helper("-0E123") == json(-0e123));
  448. // numbers after exponent
  449. CHECK(parser_helper("10E0") == json(10e0));
  450. CHECK(parser_helper("10E1") == json(10e1));
  451. CHECK(parser_helper("10E2") == json(10e2));
  452. CHECK(parser_helper("10E3") == json(10e3));
  453. CHECK(parser_helper("10E4") == json(10e4));
  454. CHECK(parser_helper("10E5") == json(10e5));
  455. CHECK(parser_helper("10E6") == json(10e6));
  456. CHECK(parser_helper("10E7") == json(10e7));
  457. CHECK(parser_helper("10E8") == json(10e8));
  458. CHECK(parser_helper("10E9") == json(10e9));
  459. CHECK(parser_helper("10E+0") == json(10e0));
  460. CHECK(parser_helper("10E+1") == json(10e1));
  461. CHECK(parser_helper("10E+2") == json(10e2));
  462. CHECK(parser_helper("10E+3") == json(10e3));
  463. CHECK(parser_helper("10E+4") == json(10e4));
  464. CHECK(parser_helper("10E+5") == json(10e5));
  465. CHECK(parser_helper("10E+6") == json(10e6));
  466. CHECK(parser_helper("10E+7") == json(10e7));
  467. CHECK(parser_helper("10E+8") == json(10e8));
  468. CHECK(parser_helper("10E+9") == json(10e9));
  469. CHECK(parser_helper("10E-1") == json(10e-1));
  470. CHECK(parser_helper("10E-2") == json(10e-2));
  471. CHECK(parser_helper("10E-3") == json(10e-3));
  472. CHECK(parser_helper("10E-4") == json(10e-4));
  473. CHECK(parser_helper("10E-5") == json(10e-5));
  474. CHECK(parser_helper("10E-6") == json(10e-6));
  475. CHECK(parser_helper("10E-7") == json(10e-7));
  476. CHECK(parser_helper("10E-8") == json(10e-8));
  477. CHECK(parser_helper("10E-9") == json(10e-9));
  478. }
  479. SECTION("edge cases")
  480. {
  481. // From RFC7159, Section 6:
  482. // Note that when such software is used, numbers that are
  483. // integers and are in the range [-(2**53)+1, (2**53)-1]
  484. // are interoperable in the sense that implementations will
  485. // agree exactly on their numeric values.
  486. // -(2**53)+1
  487. CHECK(parser_helper("-9007199254740991").get<int64_t>() == -9007199254740991);
  488. // (2**53)-1
  489. CHECK(parser_helper("9007199254740991").get<int64_t>() == 9007199254740991);
  490. }
  491. SECTION("over the edge cases") // issue #178 - Integer conversion to unsigned (incorrect handling of 64 bit integers)
  492. {
  493. // While RFC7159, Section 6 specifies a preference for support
  494. // for ranges in range of IEEE 754-2008 binary64 (double precision)
  495. // this does not accommodate 64 bit integers without loss of accuracy.
  496. // As 64 bit integers are now widely used in software, it is desirable
  497. // to expand support to to the full 64 bit (signed and unsigned) range
  498. // i.e. -(2**63) -> (2**64)-1.
  499. // -(2**63) ** Note: compilers see negative literals as negated positive numbers (hence the -1))
  500. CHECK(parser_helper("-9223372036854775808").get<int64_t>() == -9223372036854775807 - 1);
  501. // (2**63)-1
  502. CHECK(parser_helper("9223372036854775807").get<int64_t>() == 9223372036854775807);
  503. // (2**64)-1
  504. CHECK(parser_helper("18446744073709551615").get<uint64_t>() == 18446744073709551615u);
  505. }
  506. }
  507. SECTION("floating-point")
  508. {
  509. SECTION("without exponent")
  510. {
  511. CHECK(parser_helper("-128.5") == json(-128.5));
  512. CHECK(parser_helper("0.999") == json(0.999));
  513. CHECK(parser_helper("128.5") == json(128.5));
  514. CHECK(parser_helper("-0.0") == json(-0.0));
  515. }
  516. SECTION("with exponent")
  517. {
  518. CHECK(parser_helper("-128.5E3") == json(-128.5E3));
  519. CHECK(parser_helper("-128.5E-3") == json(-128.5E-3));
  520. CHECK(parser_helper("-0.0e1") == json(-0.0e1));
  521. CHECK(parser_helper("-0.0E1") == json(-0.0e1));
  522. }
  523. }
  524. SECTION("overflow")
  525. {
  526. // overflows during parsing yield an exception
  527. CHECK_THROWS_AS(parser_helper("1.18973e+4932") == json(), json::out_of_range&);
  528. CHECK_THROWS_WITH(parser_helper("1.18973e+4932") == json(),
  529. "[json.exception.out_of_range.406] number overflow parsing '1.18973e+4932'");
  530. }
  531. SECTION("invalid numbers")
  532. {
  533. CHECK_THROWS_AS(parser_helper("01"), json::parse_error&);
  534. CHECK_THROWS_AS(parser_helper("--1"), json::parse_error&);
  535. CHECK_THROWS_AS(parser_helper("1."), json::parse_error&);
  536. CHECK_THROWS_AS(parser_helper("1E"), json::parse_error&);
  537. CHECK_THROWS_AS(parser_helper("1E-"), json::parse_error&);
  538. CHECK_THROWS_AS(parser_helper("1.E1"), json::parse_error&);
  539. CHECK_THROWS_AS(parser_helper("-1E"), json::parse_error&);
  540. CHECK_THROWS_AS(parser_helper("-0E#"), json::parse_error&);
  541. CHECK_THROWS_AS(parser_helper("-0E-#"), json::parse_error&);
  542. CHECK_THROWS_AS(parser_helper("-0#"), json::parse_error&);
  543. CHECK_THROWS_AS(parser_helper("-0.0:"), json::parse_error&);
  544. CHECK_THROWS_AS(parser_helper("-0.0Z"), json::parse_error&);
  545. CHECK_THROWS_AS(parser_helper("-0E123:"), json::parse_error&);
  546. CHECK_THROWS_AS(parser_helper("-0e0-:"), json::parse_error&);
  547. CHECK_THROWS_AS(parser_helper("-0e-:"), json::parse_error&);
  548. CHECK_THROWS_AS(parser_helper("-0f"), json::parse_error&);
  549. // numbers must not begin with "+"
  550. CHECK_THROWS_AS(parser_helper("+1"), json::parse_error&);
  551. CHECK_THROWS_AS(parser_helper("+0"), json::parse_error&);
  552. CHECK_THROWS_WITH(parser_helper("01"),
  553. "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - unexpected number literal; expected end of input");
  554. CHECK_THROWS_WITH(parser_helper("-01"),
  555. "[json.exception.parse_error.101] parse error at line 1, column 3: syntax error while parsing value - unexpected number literal; expected end of input");
  556. CHECK_THROWS_WITH(parser_helper("--1"),
  557. "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid number; expected digit after '-'; last read: '--'");
  558. CHECK_THROWS_WITH(parser_helper("1."),
  559. "[json.exception.parse_error.101] parse error at line 1, column 3: syntax error while parsing value - invalid number; expected digit after '.'; last read: '1.'");
  560. CHECK_THROWS_WITH(parser_helper("1E"),
  561. "[json.exception.parse_error.101] parse error at line 1, column 3: syntax error while parsing value - invalid number; expected '+', '-', or digit after exponent; last read: '1E'");
  562. CHECK_THROWS_WITH(parser_helper("1E-"),
  563. "[json.exception.parse_error.101] parse error at line 1, column 4: syntax error while parsing value - invalid number; expected digit after exponent sign; last read: '1E-'");
  564. CHECK_THROWS_WITH(parser_helper("1.E1"),
  565. "[json.exception.parse_error.101] parse error at line 1, column 3: syntax error while parsing value - invalid number; expected digit after '.'; last read: '1.E'");
  566. CHECK_THROWS_WITH(parser_helper("-1E"),
  567. "[json.exception.parse_error.101] parse error at line 1, column 4: syntax error while parsing value - invalid number; expected '+', '-', or digit after exponent; last read: '-1E'");
  568. CHECK_THROWS_WITH(parser_helper("-0E#"),
  569. "[json.exception.parse_error.101] parse error at line 1, column 4: syntax error while parsing value - invalid number; expected '+', '-', or digit after exponent; last read: '-0E#'");
  570. CHECK_THROWS_WITH(parser_helper("-0E-#"),
  571. "[json.exception.parse_error.101] parse error at line 1, column 5: syntax error while parsing value - invalid number; expected digit after exponent sign; last read: '-0E-#'");
  572. CHECK_THROWS_WITH(parser_helper("-0#"),
  573. "[json.exception.parse_error.101] parse error at line 1, column 3: syntax error while parsing value - invalid literal; last read: '-0#'; expected end of input");
  574. CHECK_THROWS_WITH(parser_helper("-0.0:"),
  575. "[json.exception.parse_error.101] parse error at line 1, column 5: syntax error while parsing value - unexpected ':'; expected end of input");
  576. CHECK_THROWS_WITH(parser_helper("-0.0Z"),
  577. "[json.exception.parse_error.101] parse error at line 1, column 5: syntax error while parsing value - invalid literal; last read: '-0.0Z'; expected end of input");
  578. CHECK_THROWS_WITH(parser_helper("-0E123:"),
  579. "[json.exception.parse_error.101] parse error at line 1, column 7: syntax error while parsing value - unexpected ':'; expected end of input");
  580. CHECK_THROWS_WITH(parser_helper("-0e0-:"),
  581. "[json.exception.parse_error.101] parse error at line 1, column 6: syntax error while parsing value - invalid number; expected digit after '-'; last read: '-:'; expected end of input");
  582. CHECK_THROWS_WITH(parser_helper("-0e-:"),
  583. "[json.exception.parse_error.101] parse error at line 1, column 5: syntax error while parsing value - invalid number; expected digit after exponent sign; last read: '-0e-:'");
  584. CHECK_THROWS_WITH(parser_helper("-0f"),
  585. "[json.exception.parse_error.101] parse error at line 1, column 4: syntax error while parsing value - invalid literal; last read: '-0f'; expected end of input");
  586. }
  587. }
  588. }
  589. SECTION("accept")
  590. {
  591. SECTION("null")
  592. {
  593. CHECK(accept_helper("null"));
  594. }
  595. SECTION("true")
  596. {
  597. CHECK(accept_helper("true"));
  598. }
  599. SECTION("false")
  600. {
  601. CHECK(accept_helper("false"));
  602. }
  603. SECTION("array")
  604. {
  605. SECTION("empty array")
  606. {
  607. CHECK(accept_helper("[]"));
  608. CHECK(accept_helper("[ ]"));
  609. }
  610. SECTION("nonempty array")
  611. {
  612. CHECK(accept_helper("[true, false, null]"));
  613. }
  614. }
  615. SECTION("object")
  616. {
  617. SECTION("empty object")
  618. {
  619. CHECK(accept_helper("{}"));
  620. CHECK(accept_helper("{ }"));
  621. }
  622. SECTION("nonempty object")
  623. {
  624. CHECK(accept_helper("{\"\": true, \"one\": 1, \"two\": null}"));
  625. }
  626. }
  627. SECTION("string")
  628. {
  629. // empty string
  630. CHECK(accept_helper("\"\""));
  631. SECTION("errors")
  632. {
  633. // error: tab in string
  634. CHECK(accept_helper("\"\t\"") == false);
  635. // error: newline in string
  636. CHECK(accept_helper("\"\n\"") == false);
  637. CHECK(accept_helper("\"\r\"") == false);
  638. // error: backspace in string
  639. CHECK(accept_helper("\"\b\"") == false);
  640. // improve code coverage
  641. CHECK(accept_helper("\uFF01") == false);
  642. CHECK(accept_helper("[-4:1,]") == false);
  643. // unescaped control characters
  644. CHECK(accept_helper("\"\x00\"") == false);
  645. CHECK(accept_helper("\"\x01\"") == false);
  646. CHECK(accept_helper("\"\x02\"") == false);
  647. CHECK(accept_helper("\"\x03\"") == false);
  648. CHECK(accept_helper("\"\x04\"") == false);
  649. CHECK(accept_helper("\"\x05\"") == false);
  650. CHECK(accept_helper("\"\x06\"") == false);
  651. CHECK(accept_helper("\"\x07\"") == false);
  652. CHECK(accept_helper("\"\x08\"") == false);
  653. CHECK(accept_helper("\"\x09\"") == false);
  654. CHECK(accept_helper("\"\x0a\"") == false);
  655. CHECK(accept_helper("\"\x0b\"") == false);
  656. CHECK(accept_helper("\"\x0c\"") == false);
  657. CHECK(accept_helper("\"\x0d\"") == false);
  658. CHECK(accept_helper("\"\x0e\"") == false);
  659. CHECK(accept_helper("\"\x0f\"") == false);
  660. CHECK(accept_helper("\"\x10\"") == false);
  661. CHECK(accept_helper("\"\x11\"") == false);
  662. CHECK(accept_helper("\"\x12\"") == false);
  663. CHECK(accept_helper("\"\x13\"") == false);
  664. CHECK(accept_helper("\"\x14\"") == false);
  665. CHECK(accept_helper("\"\x15\"") == false);
  666. CHECK(accept_helper("\"\x16\"") == false);
  667. CHECK(accept_helper("\"\x17\"") == false);
  668. CHECK(accept_helper("\"\x18\"") == false);
  669. CHECK(accept_helper("\"\x19\"") == false);
  670. CHECK(accept_helper("\"\x1a\"") == false);
  671. CHECK(accept_helper("\"\x1b\"") == false);
  672. CHECK(accept_helper("\"\x1c\"") == false);
  673. CHECK(accept_helper("\"\x1d\"") == false);
  674. CHECK(accept_helper("\"\x1e\"") == false);
  675. CHECK(accept_helper("\"\x1f\"") == false);
  676. }
  677. SECTION("escaped")
  678. {
  679. // quotation mark "\""
  680. auto r1 = R"("\"")"_json;
  681. CHECK(accept_helper("\"\\\"\""));
  682. // reverse solidus "\\"
  683. auto r2 = R"("\\")"_json;
  684. CHECK(accept_helper("\"\\\\\""));
  685. // solidus
  686. CHECK(accept_helper("\"\\/\""));
  687. // backspace
  688. CHECK(accept_helper("\"\\b\""));
  689. // formfeed
  690. CHECK(accept_helper("\"\\f\""));
  691. // newline
  692. CHECK(accept_helper("\"\\n\""));
  693. // carriage return
  694. CHECK(accept_helper("\"\\r\""));
  695. // horizontal tab
  696. CHECK(accept_helper("\"\\t\""));
  697. CHECK(accept_helper("\"\\u0001\""));
  698. CHECK(accept_helper("\"\\u000a\""));
  699. CHECK(accept_helper("\"\\u00b0\""));
  700. CHECK(accept_helper("\"\\u0c00\""));
  701. CHECK(accept_helper("\"\\ud000\""));
  702. CHECK(accept_helper("\"\\u000E\""));
  703. CHECK(accept_helper("\"\\u00F0\""));
  704. CHECK(accept_helper("\"\\u0100\""));
  705. CHECK(accept_helper("\"\\u2000\""));
  706. CHECK(accept_helper("\"\\uFFFF\""));
  707. CHECK(accept_helper("\"\\u20AC\""));
  708. CHECK(accept_helper("\"€\""));
  709. CHECK(accept_helper("\"🎈\""));
  710. CHECK(accept_helper("\"\\ud80c\\udc60\""));
  711. CHECK(accept_helper("\"\\ud83c\\udf1e\""));
  712. }
  713. }
  714. SECTION("number")
  715. {
  716. SECTION("integers")
  717. {
  718. SECTION("without exponent")
  719. {
  720. CHECK(accept_helper("-128"));
  721. CHECK(accept_helper("-0"));
  722. CHECK(accept_helper("0"));
  723. CHECK(accept_helper("128"));
  724. }
  725. SECTION("with exponent")
  726. {
  727. CHECK(accept_helper("0e1"));
  728. CHECK(accept_helper("0E1"));
  729. CHECK(accept_helper("10000E-4"));
  730. CHECK(accept_helper("10000E-3"));
  731. CHECK(accept_helper("10000E-2"));
  732. CHECK(accept_helper("10000E-1"));
  733. CHECK(accept_helper("10000E0"));
  734. CHECK(accept_helper("10000E1"));
  735. CHECK(accept_helper("10000E2"));
  736. CHECK(accept_helper("10000E3"));
  737. CHECK(accept_helper("10000E4"));
  738. CHECK(accept_helper("10000e-4"));
  739. CHECK(accept_helper("10000e-3"));
  740. CHECK(accept_helper("10000e-2"));
  741. CHECK(accept_helper("10000e-1"));
  742. CHECK(accept_helper("10000e0"));
  743. CHECK(accept_helper("10000e1"));
  744. CHECK(accept_helper("10000e2"));
  745. CHECK(accept_helper("10000e3"));
  746. CHECK(accept_helper("10000e4"));
  747. CHECK(accept_helper("-0e1"));
  748. CHECK(accept_helper("-0E1"));
  749. CHECK(accept_helper("-0E123"));
  750. }
  751. SECTION("edge cases")
  752. {
  753. // From RFC7159, Section 6:
  754. // Note that when such software is used, numbers that are
  755. // integers and are in the range [-(2**53)+1, (2**53)-1]
  756. // are interoperable in the sense that implementations will
  757. // agree exactly on their numeric values.
  758. // -(2**53)+1
  759. CHECK(accept_helper("-9007199254740991"));
  760. // (2**53)-1
  761. CHECK(accept_helper("9007199254740991"));
  762. }
  763. SECTION("over the edge cases") // issue #178 - Integer conversion to unsigned (incorrect handling of 64 bit integers)
  764. {
  765. // While RFC7159, Section 6 specifies a preference for support
  766. // for ranges in range of IEEE 754-2008 binary64 (double precision)
  767. // this does not accommodate 64 bit integers without loss of accuracy.
  768. // As 64 bit integers are now widely used in software, it is desirable
  769. // to expand support to to the full 64 bit (signed and unsigned) range
  770. // i.e. -(2**63) -> (2**64)-1.
  771. // -(2**63) ** Note: compilers see negative literals as negated positive numbers (hence the -1))
  772. CHECK(accept_helper("-9223372036854775808"));
  773. // (2**63)-1
  774. CHECK(accept_helper("9223372036854775807"));
  775. // (2**64)-1
  776. CHECK(accept_helper("18446744073709551615"));
  777. }
  778. }
  779. SECTION("floating-point")
  780. {
  781. SECTION("without exponent")
  782. {
  783. CHECK(accept_helper("-128.5"));
  784. CHECK(accept_helper("0.999"));
  785. CHECK(accept_helper("128.5"));
  786. CHECK(accept_helper("-0.0"));
  787. }
  788. SECTION("with exponent")
  789. {
  790. CHECK(accept_helper("-128.5E3"));
  791. CHECK(accept_helper("-128.5E-3"));
  792. CHECK(accept_helper("-0.0e1"));
  793. CHECK(accept_helper("-0.0E1"));
  794. }
  795. }
  796. SECTION("overflow")
  797. {
  798. // overflows during parsing
  799. CHECK(not accept_helper("1.18973e+4932"));
  800. }
  801. SECTION("invalid numbers")
  802. {
  803. CHECK(accept_helper("01") == false);
  804. CHECK(accept_helper("--1") == false);
  805. CHECK(accept_helper("1.") == false);
  806. CHECK(accept_helper("1E") == false);
  807. CHECK(accept_helper("1E-") == false);
  808. CHECK(accept_helper("1.E1") == false);
  809. CHECK(accept_helper("-1E") == false);
  810. CHECK(accept_helper("-0E#") == false);
  811. CHECK(accept_helper("-0E-#") == false);
  812. CHECK(accept_helper("-0#") == false);
  813. CHECK(accept_helper("-0.0:") == false);
  814. CHECK(accept_helper("-0.0Z") == false);
  815. CHECK(accept_helper("-0E123:") == false);
  816. CHECK(accept_helper("-0e0-:") == false);
  817. CHECK(accept_helper("-0e-:") == false);
  818. CHECK(accept_helper("-0f") == false);
  819. // numbers must not begin with "+"
  820. CHECK(accept_helper("+1") == false);
  821. CHECK(accept_helper("+0") == false);
  822. }
  823. }
  824. }
  825. SECTION("parse errors")
  826. {
  827. // unexpected end of number
  828. CHECK_THROWS_AS(parser_helper("0."), json::parse_error&);
  829. CHECK_THROWS_AS(parser_helper("-"), json::parse_error&);
  830. CHECK_THROWS_AS(parser_helper("--"), json::parse_error&);
  831. CHECK_THROWS_AS(parser_helper("-0."), json::parse_error&);
  832. CHECK_THROWS_AS(parser_helper("-."), json::parse_error&);
  833. CHECK_THROWS_AS(parser_helper("-:"), json::parse_error&);
  834. CHECK_THROWS_AS(parser_helper("0.:"), json::parse_error&);
  835. CHECK_THROWS_AS(parser_helper("e."), json::parse_error&);
  836. CHECK_THROWS_AS(parser_helper("1e."), json::parse_error&);
  837. CHECK_THROWS_AS(parser_helper("1e/"), json::parse_error&);
  838. CHECK_THROWS_AS(parser_helper("1e:"), json::parse_error&);
  839. CHECK_THROWS_AS(parser_helper("1E."), json::parse_error&);
  840. CHECK_THROWS_AS(parser_helper("1E/"), json::parse_error&);
  841. CHECK_THROWS_AS(parser_helper("1E:"), json::parse_error&);
  842. CHECK_THROWS_WITH(parser_helper("0."),
  843. "[json.exception.parse_error.101] parse error at line 1, column 3: syntax error while parsing value - invalid number; expected digit after '.'; last read: '0.'");
  844. CHECK_THROWS_WITH(parser_helper("-"),
  845. "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid number; expected digit after '-'; last read: '-'");
  846. CHECK_THROWS_WITH(parser_helper("--"),
  847. "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid number; expected digit after '-'; last read: '--'");
  848. CHECK_THROWS_WITH(parser_helper("-0."),
  849. "[json.exception.parse_error.101] parse error at line 1, column 4: syntax error while parsing value - invalid number; expected digit after '.'; last read: '-0.'");
  850. CHECK_THROWS_WITH(parser_helper("-."),
  851. "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid number; expected digit after '-'; last read: '-.'");
  852. CHECK_THROWS_WITH(parser_helper("-:"),
  853. "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid number; expected digit after '-'; last read: '-:'");
  854. CHECK_THROWS_WITH(parser_helper("0.:"),
  855. "[json.exception.parse_error.101] parse error at line 1, column 3: syntax error while parsing value - invalid number; expected digit after '.'; last read: '0.:'");
  856. CHECK_THROWS_WITH(parser_helper("e."),
  857. "[json.exception.parse_error.101] parse error at line 1, column 1: syntax error while parsing value - invalid literal; last read: 'e'");
  858. CHECK_THROWS_WITH(parser_helper("1e."),
  859. "[json.exception.parse_error.101] parse error at line 1, column 3: syntax error while parsing value - invalid number; expected '+', '-', or digit after exponent; last read: '1e.'");
  860. CHECK_THROWS_WITH(parser_helper("1e/"),
  861. "[json.exception.parse_error.101] parse error at line 1, column 3: syntax error while parsing value - invalid number; expected '+', '-', or digit after exponent; last read: '1e/'");
  862. CHECK_THROWS_WITH(parser_helper("1e:"),
  863. "[json.exception.parse_error.101] parse error at line 1, column 3: syntax error while parsing value - invalid number; expected '+', '-', or digit after exponent; last read: '1e:'");
  864. CHECK_THROWS_WITH(parser_helper("1E."),
  865. "[json.exception.parse_error.101] parse error at line 1, column 3: syntax error while parsing value - invalid number; expected '+', '-', or digit after exponent; last read: '1E.'");
  866. CHECK_THROWS_WITH(parser_helper("1E/"),
  867. "[json.exception.parse_error.101] parse error at line 1, column 3: syntax error while parsing value - invalid number; expected '+', '-', or digit after exponent; last read: '1E/'");
  868. CHECK_THROWS_WITH(parser_helper("1E:"),
  869. "[json.exception.parse_error.101] parse error at line 1, column 3: syntax error while parsing value - invalid number; expected '+', '-', or digit after exponent; last read: '1E:'");
  870. // unexpected end of null
  871. CHECK_THROWS_AS(parser_helper("n"), json::parse_error&);
  872. CHECK_THROWS_AS(parser_helper("nu"), json::parse_error&);
  873. CHECK_THROWS_AS(parser_helper("nul"), json::parse_error&);
  874. CHECK_THROWS_AS(parser_helper("nulk"), json::parse_error&);
  875. CHECK_THROWS_AS(parser_helper("nulm"), json::parse_error&);
  876. CHECK_THROWS_WITH(parser_helper("n"),
  877. "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid literal; last read: 'n'");
  878. CHECK_THROWS_WITH(parser_helper("nu"),
  879. "[json.exception.parse_error.101] parse error at line 1, column 3: syntax error while parsing value - invalid literal; last read: 'nu'");
  880. CHECK_THROWS_WITH(parser_helper("nul"),
  881. "[json.exception.parse_error.101] parse error at line 1, column 4: syntax error while parsing value - invalid literal; last read: 'nul'");
  882. CHECK_THROWS_WITH(parser_helper("nulk"),
  883. "[json.exception.parse_error.101] parse error at line 1, column 4: syntax error while parsing value - invalid literal; last read: 'nulk'");
  884. CHECK_THROWS_WITH(parser_helper("nulm"),
  885. "[json.exception.parse_error.101] parse error at line 1, column 4: syntax error while parsing value - invalid literal; last read: 'nulm'");
  886. // unexpected end of true
  887. CHECK_THROWS_AS(parser_helper("t"), json::parse_error&);
  888. CHECK_THROWS_AS(parser_helper("tr"), json::parse_error&);
  889. CHECK_THROWS_AS(parser_helper("tru"), json::parse_error&);
  890. CHECK_THROWS_AS(parser_helper("trud"), json::parse_error&);
  891. CHECK_THROWS_AS(parser_helper("truf"), json::parse_error&);
  892. CHECK_THROWS_WITH(parser_helper("t"),
  893. "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid literal; last read: 't'");
  894. CHECK_THROWS_WITH(parser_helper("tr"),
  895. "[json.exception.parse_error.101] parse error at line 1, column 3: syntax error while parsing value - invalid literal; last read: 'tr'");
  896. CHECK_THROWS_WITH(parser_helper("tru"),
  897. "[json.exception.parse_error.101] parse error at line 1, column 4: syntax error while parsing value - invalid literal; last read: 'tru'");
  898. CHECK_THROWS_WITH(parser_helper("trud"),
  899. "[json.exception.parse_error.101] parse error at line 1, column 4: syntax error while parsing value - invalid literal; last read: 'trud'");
  900. CHECK_THROWS_WITH(parser_helper("truf"),
  901. "[json.exception.parse_error.101] parse error at line 1, column 4: syntax error while parsing value - invalid literal; last read: 'truf'");
  902. // unexpected end of false
  903. CHECK_THROWS_AS(parser_helper("f"), json::parse_error&);
  904. CHECK_THROWS_AS(parser_helper("fa"), json::parse_error&);
  905. CHECK_THROWS_AS(parser_helper("fal"), json::parse_error&);
  906. CHECK_THROWS_AS(parser_helper("fals"), json::parse_error&);
  907. CHECK_THROWS_AS(parser_helper("falsd"), json::parse_error&);
  908. CHECK_THROWS_AS(parser_helper("falsf"), json::parse_error&);
  909. CHECK_THROWS_WITH(parser_helper("f"),
  910. "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid literal; last read: 'f'");
  911. CHECK_THROWS_WITH(parser_helper("fa"),
  912. "[json.exception.parse_error.101] parse error at line 1, column 3: syntax error while parsing value - invalid literal; last read: 'fa'");
  913. CHECK_THROWS_WITH(parser_helper("fal"),
  914. "[json.exception.parse_error.101] parse error at line 1, column 4: syntax error while parsing value - invalid literal; last read: 'fal'");
  915. CHECK_THROWS_WITH(parser_helper("fals"),
  916. "[json.exception.parse_error.101] parse error at line 1, column 5: syntax error while parsing value - invalid literal; last read: 'fals'");
  917. CHECK_THROWS_WITH(parser_helper("falsd"),
  918. "[json.exception.parse_error.101] parse error at line 1, column 5: syntax error while parsing value - invalid literal; last read: 'falsd'");
  919. CHECK_THROWS_WITH(parser_helper("falsf"),
  920. "[json.exception.parse_error.101] parse error at line 1, column 5: syntax error while parsing value - invalid literal; last read: 'falsf'");
  921. // missing/unexpected end of array
  922. CHECK_THROWS_AS(parser_helper("["), json::parse_error&);
  923. CHECK_THROWS_AS(parser_helper("[1"), json::parse_error&);
  924. CHECK_THROWS_AS(parser_helper("[1,"), json::parse_error&);
  925. CHECK_THROWS_AS(parser_helper("[1,]"), json::parse_error&);
  926. CHECK_THROWS_AS(parser_helper("]"), json::parse_error&);
  927. CHECK_THROWS_WITH(parser_helper("["),
  928. "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - unexpected end of input; expected '[', '{', or a literal");
  929. CHECK_THROWS_WITH(parser_helper("[1"),
  930. "[json.exception.parse_error.101] parse error at line 1, column 3: syntax error while parsing array - unexpected end of input; expected ']'");
  931. CHECK_THROWS_WITH(parser_helper("[1,"),
  932. "[json.exception.parse_error.101] parse error at line 1, column 4: syntax error while parsing value - unexpected end of input; expected '[', '{', or a literal");
  933. CHECK_THROWS_WITH(parser_helper("[1,]"),
  934. "[json.exception.parse_error.101] parse error at line 1, column 4: syntax error while parsing value - unexpected ']'; expected '[', '{', or a literal");
  935. CHECK_THROWS_WITH(parser_helper("]"),
  936. "[json.exception.parse_error.101] parse error at line 1, column 1: syntax error while parsing value - unexpected ']'; expected '[', '{', or a literal");
  937. // missing/unexpected end of object
  938. CHECK_THROWS_AS(parser_helper("{"), json::parse_error&);
  939. CHECK_THROWS_AS(parser_helper("{\"foo\""), json::parse_error&);
  940. CHECK_THROWS_AS(parser_helper("{\"foo\":"), json::parse_error&);
  941. CHECK_THROWS_AS(parser_helper("{\"foo\":}"), json::parse_error&);
  942. CHECK_THROWS_AS(parser_helper("{\"foo\":1,}"), json::parse_error&);
  943. CHECK_THROWS_AS(parser_helper("}"), json::parse_error&);
  944. CHECK_THROWS_WITH(parser_helper("{"),
  945. "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing object key - unexpected end of input; expected string literal");
  946. CHECK_THROWS_WITH(parser_helper("{\"foo\""),
  947. "[json.exception.parse_error.101] parse error at line 1, column 7: syntax error while parsing object separator - unexpected end of input; expected ':'");
  948. CHECK_THROWS_WITH(parser_helper("{\"foo\":"),
  949. "[json.exception.parse_error.101] parse error at line 1, column 8: syntax error while parsing value - unexpected end of input; expected '[', '{', or a literal");
  950. CHECK_THROWS_WITH(parser_helper("{\"foo\":}"),
  951. "[json.exception.parse_error.101] parse error at line 1, column 8: syntax error while parsing value - unexpected '}'; expected '[', '{', or a literal");
  952. CHECK_THROWS_WITH(parser_helper("{\"foo\":1,}"),
  953. "[json.exception.parse_error.101] parse error at line 1, column 10: syntax error while parsing object key - unexpected '}'; expected string literal");
  954. CHECK_THROWS_WITH(parser_helper("}"),
  955. "[json.exception.parse_error.101] parse error at line 1, column 1: syntax error while parsing value - unexpected '}'; expected '[', '{', or a literal");
  956. // missing/unexpected end of string
  957. CHECK_THROWS_AS(parser_helper("\""), json::parse_error&);
  958. CHECK_THROWS_AS(parser_helper("\"\\\""), json::parse_error&);
  959. CHECK_THROWS_AS(parser_helper("\"\\u\""), json::parse_error&);
  960. CHECK_THROWS_AS(parser_helper("\"\\u0\""), json::parse_error&);
  961. CHECK_THROWS_AS(parser_helper("\"\\u01\""), json::parse_error&);
  962. CHECK_THROWS_AS(parser_helper("\"\\u012\""), json::parse_error&);
  963. CHECK_THROWS_AS(parser_helper("\"\\u"), json::parse_error&);
  964. CHECK_THROWS_AS(parser_helper("\"\\u0"), json::parse_error&);
  965. CHECK_THROWS_AS(parser_helper("\"\\u01"), json::parse_error&);
  966. CHECK_THROWS_AS(parser_helper("\"\\u012"), json::parse_error&);
  967. CHECK_THROWS_WITH(parser_helper("\""),
  968. "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: missing closing quote; last read: '\"'");
  969. CHECK_THROWS_WITH(parser_helper("\"\\\""),
  970. "[json.exception.parse_error.101] parse error at line 1, column 4: syntax error while parsing value - invalid string: missing closing quote; last read: '\"\\\"'");
  971. CHECK_THROWS_WITH(parser_helper("\"\\u\""),
  972. "[json.exception.parse_error.101] parse error at line 1, column 4: syntax error while parsing value - invalid string: '\\u' must be followed by 4 hex digits; last read: '\"\\u\"'");
  973. CHECK_THROWS_WITH(parser_helper("\"\\u0\""),
  974. "[json.exception.parse_error.101] parse error at line 1, column 5: syntax error while parsing value - invalid string: '\\u' must be followed by 4 hex digits; last read: '\"\\u0\"'");
  975. CHECK_THROWS_WITH(parser_helper("\"\\u01\""),
  976. "[json.exception.parse_error.101] parse error at line 1, column 6: syntax error while parsing value - invalid string: '\\u' must be followed by 4 hex digits; last read: '\"\\u01\"'");
  977. CHECK_THROWS_WITH(parser_helper("\"\\u012\""),
  978. "[json.exception.parse_error.101] parse error at line 1, column 7: syntax error while parsing value - invalid string: '\\u' must be followed by 4 hex digits; last read: '\"\\u012\"'");
  979. CHECK_THROWS_WITH(parser_helper("\"\\u"),
  980. "[json.exception.parse_error.101] parse error at line 1, column 4: syntax error while parsing value - invalid string: '\\u' must be followed by 4 hex digits; last read: '\"\\u'");
  981. CHECK_THROWS_WITH(parser_helper("\"\\u0"),
  982. "[json.exception.parse_error.101] parse error at line 1, column 5: syntax error while parsing value - invalid string: '\\u' must be followed by 4 hex digits; last read: '\"\\u0'");
  983. CHECK_THROWS_WITH(parser_helper("\"\\u01"),
  984. "[json.exception.parse_error.101] parse error at line 1, column 6: syntax error while parsing value - invalid string: '\\u' must be followed by 4 hex digits; last read: '\"\\u01'");
  985. CHECK_THROWS_WITH(parser_helper("\"\\u012"),
  986. "[json.exception.parse_error.101] parse error at line 1, column 7: syntax error while parsing value - invalid string: '\\u' must be followed by 4 hex digits; last read: '\"\\u012'");
  987. // invalid escapes
  988. for (int c = 1; c < 128; ++c)
  989. {
  990. auto s = std::string("\"\\") + std::string(1, static_cast<char>(c)) + "\"";
  991. switch (c)
  992. {
  993. // valid escapes
  994. case ('"'):
  995. case ('\\'):
  996. case ('/'):
  997. case ('b'):
  998. case ('f'):
  999. case ('n'):
  1000. case ('r'):
  1001. case ('t'):
  1002. {
  1003. CHECK_NOTHROW(parser_helper(s.c_str()));
  1004. break;
  1005. }
  1006. // \u must be followed with four numbers, so we skip it here
  1007. case ('u'):
  1008. {
  1009. break;
  1010. }
  1011. // any other combination of backslash and character is invalid
  1012. default:
  1013. {
  1014. CHECK_THROWS_AS(parser_helper(s.c_str()), json::parse_error&);
  1015. // only check error message if c is not a control character
  1016. if (c > 0x1f)
  1017. {
  1018. CHECK_THROWS_WITH_STD_STR(parser_helper(s.c_str()),
  1019. "[json.exception.parse_error.101] parse error at line 1, column 3: syntax error while parsing value - invalid string: forbidden character after backslash; last read: '\"\\" + std::string(1, static_cast<char>(c)) + "'");
  1020. }
  1021. break;
  1022. }
  1023. }
  1024. }
  1025. // invalid \uxxxx escapes
  1026. {
  1027. // check whether character is a valid hex character
  1028. const auto valid = [](int c)
  1029. {
  1030. switch (c)
  1031. {
  1032. case ('0'):
  1033. case ('1'):
  1034. case ('2'):
  1035. case ('3'):
  1036. case ('4'):
  1037. case ('5'):
  1038. case ('6'):
  1039. case ('7'):
  1040. case ('8'):
  1041. case ('9'):
  1042. case ('a'):
  1043. case ('b'):
  1044. case ('c'):
  1045. case ('d'):
  1046. case ('e'):
  1047. case ('f'):
  1048. case ('A'):
  1049. case ('B'):
  1050. case ('C'):
  1051. case ('D'):
  1052. case ('E'):
  1053. case ('F'):
  1054. {
  1055. return true;
  1056. }
  1057. default:
  1058. {
  1059. return false;
  1060. }
  1061. }
  1062. };
  1063. for (int c = 1; c < 128; ++c)
  1064. {
  1065. std::string s = "\"\\u";
  1066. // create a string with the iterated character at each position
  1067. auto s1 = s + "000" + std::string(1, static_cast<char>(c)) + "\"";
  1068. auto s2 = s + "00" + std::string(1, static_cast<char>(c)) + "0\"";
  1069. auto s3 = s + "0" + std::string(1, static_cast<char>(c)) + "00\"";
  1070. auto s4 = s + std::string(1, static_cast<char>(c)) + "000\"";
  1071. if (valid(c))
  1072. {
  1073. CAPTURE(s1)
  1074. CHECK_NOTHROW(parser_helper(s1.c_str()));
  1075. CAPTURE(s2)
  1076. CHECK_NOTHROW(parser_helper(s2.c_str()));
  1077. CAPTURE(s3)
  1078. CHECK_NOTHROW(parser_helper(s3.c_str()));
  1079. CAPTURE(s4)
  1080. CHECK_NOTHROW(parser_helper(s4.c_str()));
  1081. }
  1082. else
  1083. {
  1084. CAPTURE(s1)
  1085. CHECK_THROWS_AS(parser_helper(s1.c_str()), json::parse_error&);
  1086. // only check error message if c is not a control character
  1087. if (c > 0x1f)
  1088. {
  1089. CHECK_THROWS_WITH_STD_STR(parser_helper(s1.c_str()),
  1090. "[json.exception.parse_error.101] parse error at line 1, column 7: syntax error while parsing value - invalid string: '\\u' must be followed by 4 hex digits; last read: '" + s1.substr(0, 7) + "'");
  1091. }
  1092. CAPTURE(s2)
  1093. CHECK_THROWS_AS(parser_helper(s2.c_str()), json::parse_error&);
  1094. // only check error message if c is not a control character
  1095. if (c > 0x1f)
  1096. {
  1097. CHECK_THROWS_WITH_STD_STR(parser_helper(s2.c_str()),
  1098. "[json.exception.parse_error.101] parse error at line 1, column 6: syntax error while parsing value - invalid string: '\\u' must be followed by 4 hex digits; last read: '" + s2.substr(0, 6) + "'");
  1099. }
  1100. CAPTURE(s3)
  1101. CHECK_THROWS_AS(parser_helper(s3.c_str()), json::parse_error&);
  1102. // only check error message if c is not a control character
  1103. if (c > 0x1f)
  1104. {
  1105. CHECK_THROWS_WITH_STD_STR(parser_helper(s3.c_str()),
  1106. "[json.exception.parse_error.101] parse error at line 1, column 5: syntax error while parsing value - invalid string: '\\u' must be followed by 4 hex digits; last read: '" + s3.substr(0, 5) + "'");
  1107. }
  1108. CAPTURE(s4)
  1109. CHECK_THROWS_AS(parser_helper(s4.c_str()), json::parse_error&);
  1110. // only check error message if c is not a control character
  1111. if (c > 0x1f)
  1112. {
  1113. CHECK_THROWS_WITH_STD_STR(parser_helper(s4.c_str()),
  1114. "[json.exception.parse_error.101] parse error at line 1, column 4: syntax error while parsing value - invalid string: '\\u' must be followed by 4 hex digits; last read: '" + s4.substr(0, 4) + "'");
  1115. }
  1116. }
  1117. }
  1118. }
  1119. json _;
  1120. // missing part of a surrogate pair
  1121. CHECK_THROWS_AS(_ = json::parse("\"\\uD80C\""), json::parse_error&);
  1122. CHECK_THROWS_WITH(_ = json::parse("\"\\uD80C\""),
  1123. "[json.exception.parse_error.101] parse error at line 1, column 8: syntax error while parsing value - invalid string: surrogate U+D800..U+DBFF must be followed by U+DC00..U+DFFF; last read: '\"\\uD80C\"'");
  1124. // invalid surrogate pair
  1125. CHECK_THROWS_AS(_ = json::parse("\"\\uD80C\\uD80C\""), json::parse_error&);
  1126. CHECK_THROWS_AS(_ = json::parse("\"\\uD80C\\u0000\""), json::parse_error&);
  1127. CHECK_THROWS_AS(_ = json::parse("\"\\uD80C\\uFFFF\""), json::parse_error&);
  1128. CHECK_THROWS_WITH(_ = json::parse("\"\\uD80C\\uD80C\""),
  1129. "[json.exception.parse_error.101] parse error at line 1, column 13: syntax error while parsing value - invalid string: surrogate U+D800..U+DBFF must be followed by U+DC00..U+DFFF; last read: '\"\\uD80C\\uD80C'");
  1130. CHECK_THROWS_WITH(_ = json::parse("\"\\uD80C\\u0000\""),
  1131. "[json.exception.parse_error.101] parse error at line 1, column 13: syntax error while parsing value - invalid string: surrogate U+D800..U+DBFF must be followed by U+DC00..U+DFFF; last read: '\"\\uD80C\\u0000'");
  1132. CHECK_THROWS_WITH(_ = json::parse("\"\\uD80C\\uFFFF\""),
  1133. "[json.exception.parse_error.101] parse error at line 1, column 13: syntax error while parsing value - invalid string: surrogate U+D800..U+DBFF must be followed by U+DC00..U+DFFF; last read: '\"\\uD80C\\uFFFF'");
  1134. }
  1135. SECTION("parse errors (accept)")
  1136. {
  1137. // unexpected end of number
  1138. CHECK(accept_helper("0.") == false);
  1139. CHECK(accept_helper("-") == false);
  1140. CHECK(accept_helper("--") == false);
  1141. CHECK(accept_helper("-0.") == false);
  1142. CHECK(accept_helper("-.") == false);
  1143. CHECK(accept_helper("-:") == false);
  1144. CHECK(accept_helper("0.:") == false);
  1145. CHECK(accept_helper("e.") == false);
  1146. CHECK(accept_helper("1e.") == false);
  1147. CHECK(accept_helper("1e/") == false);
  1148. CHECK(accept_helper("1e:") == false);
  1149. CHECK(accept_helper("1E.") == false);
  1150. CHECK(accept_helper("1E/") == false);
  1151. CHECK(accept_helper("1E:") == false);
  1152. // unexpected end of null
  1153. CHECK(accept_helper("n") == false);
  1154. CHECK(accept_helper("nu") == false);
  1155. CHECK(accept_helper("nul") == false);
  1156. // unexpected end of true
  1157. CHECK(accept_helper("t") == false);
  1158. CHECK(accept_helper("tr") == false);
  1159. CHECK(accept_helper("tru") == false);
  1160. // unexpected end of false
  1161. CHECK(accept_helper("f") == false);
  1162. CHECK(accept_helper("fa") == false);
  1163. CHECK(accept_helper("fal") == false);
  1164. CHECK(accept_helper("fals") == false);
  1165. // missing/unexpected end of array
  1166. CHECK(accept_helper("[") == false);
  1167. CHECK(accept_helper("[1") == false);
  1168. CHECK(accept_helper("[1,") == false);
  1169. CHECK(accept_helper("[1,]") == false);
  1170. CHECK(accept_helper("]") == false);
  1171. // missing/unexpected end of object
  1172. CHECK(accept_helper("{") == false);
  1173. CHECK(accept_helper("{\"foo\"") == false);
  1174. CHECK(accept_helper("{\"foo\":") == false);
  1175. CHECK(accept_helper("{\"foo\":}") == false);
  1176. CHECK(accept_helper("{\"foo\":1,}") == false);
  1177. CHECK(accept_helper("}") == false);
  1178. // missing/unexpected end of string
  1179. CHECK(accept_helper("\"") == false);
  1180. CHECK(accept_helper("\"\\\"") == false);
  1181. CHECK(accept_helper("\"\\u\"") == false);
  1182. CHECK(accept_helper("\"\\u0\"") == false);
  1183. CHECK(accept_helper("\"\\u01\"") == false);
  1184. CHECK(accept_helper("\"\\u012\"") == false);
  1185. CHECK(accept_helper("\"\\u") == false);
  1186. CHECK(accept_helper("\"\\u0") == false);
  1187. CHECK(accept_helper("\"\\u01") == false);
  1188. CHECK(accept_helper("\"\\u012") == false);
  1189. // unget of newline
  1190. CHECK(parser_helper("\n123\n") == 123);
  1191. // invalid escapes
  1192. for (int c = 1; c < 128; ++c)
  1193. {
  1194. auto s = std::string("\"\\") + std::string(1, static_cast<char>(c)) + "\"";
  1195. switch (c)
  1196. {
  1197. // valid escapes
  1198. case ('"'):
  1199. case ('\\'):
  1200. case ('/'):
  1201. case ('b'):
  1202. case ('f'):
  1203. case ('n'):
  1204. case ('r'):
  1205. case ('t'):
  1206. {
  1207. CHECK(json::parser(nlohmann::detail::input_adapter(std::string(s.c_str()))).accept());
  1208. break;
  1209. }
  1210. // \u must be followed with four numbers, so we skip it here
  1211. case ('u'):
  1212. {
  1213. break;
  1214. }
  1215. // any other combination of backslash and character is invalid
  1216. default:
  1217. {
  1218. CHECK(json::parser(nlohmann::detail::input_adapter(std::string(s.c_str()))).accept() == false);
  1219. break;
  1220. }
  1221. }
  1222. }
  1223. // invalid \uxxxx escapes
  1224. {
  1225. // check whether character is a valid hex character
  1226. const auto valid = [](int c)
  1227. {
  1228. switch (c)
  1229. {
  1230. case ('0'):
  1231. case ('1'):
  1232. case ('2'):
  1233. case ('3'):
  1234. case ('4'):
  1235. case ('5'):
  1236. case ('6'):
  1237. case ('7'):
  1238. case ('8'):
  1239. case ('9'):
  1240. case ('a'):
  1241. case ('b'):
  1242. case ('c'):
  1243. case ('d'):
  1244. case ('e'):
  1245. case ('f'):
  1246. case ('A'):
  1247. case ('B'):
  1248. case ('C'):
  1249. case ('D'):
  1250. case ('E'):
  1251. case ('F'):
  1252. {
  1253. return true;
  1254. }
  1255. default:
  1256. {
  1257. return false;
  1258. }
  1259. }
  1260. };
  1261. for (int c = 1; c < 128; ++c)
  1262. {
  1263. std::string s = "\"\\u";
  1264. // create a string with the iterated character at each position
  1265. auto s1 = s + "000" + std::string(1, static_cast<char>(c)) + "\"";
  1266. auto s2 = s + "00" + std::string(1, static_cast<char>(c)) + "0\"";
  1267. auto s3 = s + "0" + std::string(1, static_cast<char>(c)) + "00\"";
  1268. auto s4 = s + std::string(1, static_cast<char>(c)) + "000\"";
  1269. if (valid(c))
  1270. {
  1271. CAPTURE(s1)
  1272. CHECK(json::parser(nlohmann::detail::input_adapter(std::string(s1.c_str()))).accept());
  1273. CAPTURE(s2)
  1274. CHECK(json::parser(nlohmann::detail::input_adapter(std::string(s2.c_str()))).accept());
  1275. CAPTURE(s3)
  1276. CHECK(json::parser(nlohmann::detail::input_adapter(std::string(s3.c_str()))).accept());
  1277. CAPTURE(s4)
  1278. CHECK(json::parser(nlohmann::detail::input_adapter(std::string(s4.c_str()))).accept());
  1279. }
  1280. else
  1281. {
  1282. CAPTURE(s1)
  1283. CHECK(json::parser(nlohmann::detail::input_adapter(std::string(s1.c_str()))).accept() == false);
  1284. CAPTURE(s2)
  1285. CHECK(json::parser(nlohmann::detail::input_adapter(std::string(s2.c_str()))).accept() == false);
  1286. CAPTURE(s3)
  1287. CHECK(json::parser(nlohmann::detail::input_adapter(std::string(s3.c_str()))).accept() == false);
  1288. CAPTURE(s4)
  1289. CHECK(json::parser(nlohmann::detail::input_adapter(std::string(s4.c_str()))).accept() == false);
  1290. }
  1291. }
  1292. }
  1293. // missing part of a surrogate pair
  1294. CHECK(accept_helper("\"\\uD80C\"") == false);
  1295. // invalid surrogate pair
  1296. CHECK(accept_helper("\"\\uD80C\\uD80C\"") == false);
  1297. CHECK(accept_helper("\"\\uD80C\\u0000\"") == false);
  1298. CHECK(accept_helper("\"\\uD80C\\uFFFF\"") == false);
  1299. }
  1300. SECTION("tests found by mutate++")
  1301. {
  1302. // test case to make sure no comma precedes the first key
  1303. CHECK_THROWS_AS(parser_helper("{,\"key\": false}"), json::parse_error&);
  1304. CHECK_THROWS_WITH(parser_helper("{,\"key\": false}"),
  1305. "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing object key - unexpected ','; expected string literal");
  1306. // test case to make sure an object is properly closed
  1307. CHECK_THROWS_AS(parser_helper("[{\"key\": false true]"), json::parse_error&);
  1308. CHECK_THROWS_WITH(parser_helper("[{\"key\": false true]"),
  1309. "[json.exception.parse_error.101] parse error at line 1, column 19: syntax error while parsing object - unexpected true literal; expected '}'");
  1310. // test case to make sure the callback is properly evaluated after reading a key
  1311. {
  1312. json::parser_callback_t cb = [](int, json::parse_event_t event, json&)
  1313. {
  1314. if (event == json::parse_event_t::key)
  1315. {
  1316. return false;
  1317. }
  1318. else
  1319. {
  1320. return true;
  1321. }
  1322. };
  1323. json x = json::parse("{\"key\": false}", cb);
  1324. CHECK(x == json::object());
  1325. }
  1326. }
  1327. SECTION("callback function")
  1328. {
  1329. auto s_object = R"(
  1330. {
  1331. "foo": 2,
  1332. "bar": {
  1333. "baz": 1
  1334. }
  1335. }
  1336. )";
  1337. auto s_array = R"(
  1338. [1,2,[3,4,5],4,5]
  1339. )";
  1340. SECTION("filter nothing")
  1341. {
  1342. json j_object = json::parse(s_object, [](int, json::parse_event_t, const json&)
  1343. {
  1344. return true;
  1345. });
  1346. CHECK (j_object == json({{"foo", 2}, {"bar", {{"baz", 1}}}}));
  1347. json j_array = json::parse(s_array, [](int, json::parse_event_t, const json&)
  1348. {
  1349. return true;
  1350. });
  1351. CHECK (j_array == json({1, 2, {3, 4, 5}, 4, 5}));
  1352. }
  1353. SECTION("filter everything")
  1354. {
  1355. json j_object = json::parse(s_object, [](int, json::parse_event_t, const json&)
  1356. {
  1357. return false;
  1358. });
  1359. // the top-level object will be discarded, leaving a null
  1360. CHECK (j_object.is_null());
  1361. json j_array = json::parse(s_array, [](int, json::parse_event_t, const json&)
  1362. {
  1363. return false;
  1364. });
  1365. // the top-level array will be discarded, leaving a null
  1366. CHECK (j_array.is_null());
  1367. }
  1368. SECTION("filter specific element")
  1369. {
  1370. json j_object = json::parse(s_object, [](int, json::parse_event_t, const json & j)
  1371. {
  1372. // filter all number(2) elements
  1373. if (j == json(2))
  1374. {
  1375. return false;
  1376. }
  1377. else
  1378. {
  1379. return true;
  1380. }
  1381. });
  1382. CHECK (j_object == json({{"bar", {{"baz", 1}}}}));
  1383. json j_array = json::parse(s_array, [](int, json::parse_event_t, const json & j)
  1384. {
  1385. if (j == json(2))
  1386. {
  1387. return false;
  1388. }
  1389. else
  1390. {
  1391. return true;
  1392. }
  1393. });
  1394. CHECK (j_array == json({1, {3, 4, 5}, 4, 5}));
  1395. }
  1396. SECTION("filter specific events")
  1397. {
  1398. SECTION("first closing event")
  1399. {
  1400. {
  1401. json j_object = json::parse(s_object, [](int, json::parse_event_t e, const json&)
  1402. {
  1403. static bool first = true;
  1404. if (e == json::parse_event_t::object_end and first)
  1405. {
  1406. first = false;
  1407. return false;
  1408. }
  1409. else
  1410. {
  1411. return true;
  1412. }
  1413. });
  1414. // the first completed object will be discarded
  1415. CHECK (j_object == json({{"foo", 2}}));
  1416. }
  1417. {
  1418. json j_array = json::parse(s_array, [](int, json::parse_event_t e, const json&)
  1419. {
  1420. static bool first = true;
  1421. if (e == json::parse_event_t::array_end and first)
  1422. {
  1423. first = false;
  1424. return false;
  1425. }
  1426. else
  1427. {
  1428. return true;
  1429. }
  1430. });
  1431. // the first completed array will be discarded
  1432. CHECK (j_array == json({1, 2, 4, 5}));
  1433. }
  1434. }
  1435. }
  1436. SECTION("special cases")
  1437. {
  1438. // the following test cases cover the situation in which an empty
  1439. // object and array is discarded only after the closing character
  1440. // has been read
  1441. json j_empty_object = json::parse("{}", [](int, json::parse_event_t e, const json&)
  1442. {
  1443. if (e == json::parse_event_t::object_end)
  1444. {
  1445. return false;
  1446. }
  1447. else
  1448. {
  1449. return true;
  1450. }
  1451. });
  1452. CHECK(j_empty_object == json());
  1453. json j_empty_array = json::parse("[]", [](int, json::parse_event_t e, const json&)
  1454. {
  1455. if (e == json::parse_event_t::array_end)
  1456. {
  1457. return false;
  1458. }
  1459. else
  1460. {
  1461. return true;
  1462. }
  1463. });
  1464. CHECK(j_empty_array == json());
  1465. }
  1466. }
  1467. SECTION("constructing from contiguous containers")
  1468. {
  1469. SECTION("from std::vector")
  1470. {
  1471. std::vector<uint8_t> v = {'t', 'r', 'u', 'e'};
  1472. json j;
  1473. json::parser(nlohmann::detail::input_adapter(std::begin(v), std::end(v))).parse(true, j);
  1474. CHECK(j == json(true));
  1475. }
  1476. SECTION("from std::array")
  1477. {
  1478. std::array<uint8_t, 5> v { {'t', 'r', 'u', 'e'} };
  1479. json j;
  1480. json::parser(nlohmann::detail::input_adapter(std::begin(v), std::end(v))).parse(true, j);
  1481. CHECK(j == json(true));
  1482. }
  1483. SECTION("from array")
  1484. {
  1485. uint8_t v[] = {'t', 'r', 'u', 'e'};
  1486. json j;
  1487. json::parser(nlohmann::detail::input_adapter(std::begin(v), std::end(v))).parse(true, j);
  1488. CHECK(j == json(true));
  1489. }
  1490. SECTION("from char literal")
  1491. {
  1492. CHECK(parser_helper("true") == json(true));
  1493. }
  1494. SECTION("from std::string")
  1495. {
  1496. std::string v = {'t', 'r', 'u', 'e'};
  1497. json j;
  1498. json::parser(nlohmann::detail::input_adapter(std::begin(v), std::end(v))).parse(true, j);
  1499. CHECK(j == json(true));
  1500. }
  1501. SECTION("from std::initializer_list")
  1502. {
  1503. std::initializer_list<uint8_t> v = {'t', 'r', 'u', 'e'};
  1504. json j;
  1505. json::parser(nlohmann::detail::input_adapter(std::begin(v), std::end(v))).parse(true, j);
  1506. CHECK(j == json(true));
  1507. }
  1508. SECTION("from std::valarray")
  1509. {
  1510. std::valarray<uint8_t> v = {'t', 'r', 'u', 'e'};
  1511. json j;
  1512. json::parser(nlohmann::detail::input_adapter(std::begin(v), std::end(v))).parse(true, j);
  1513. CHECK(j == json(true));
  1514. }
  1515. }
  1516. SECTION("improve test coverage")
  1517. {
  1518. SECTION("parser with callback")
  1519. {
  1520. json::parser_callback_t cb = [](int, json::parse_event_t, json&)
  1521. {
  1522. return true;
  1523. };
  1524. CHECK(json::parse("{\"foo\": true:", cb, false).is_discarded());
  1525. json _;
  1526. CHECK_THROWS_AS(_ = json::parse("{\"foo\": true:", cb), json::parse_error&);
  1527. CHECK_THROWS_WITH(_ = json::parse("{\"foo\": true:", cb),
  1528. "[json.exception.parse_error.101] parse error at line 1, column 13: syntax error while parsing object - unexpected ':'; expected '}'");
  1529. CHECK_THROWS_AS(_ = json::parse("1.18973e+4932", cb), json::out_of_range&);
  1530. CHECK_THROWS_WITH(_ = json::parse("1.18973e+4932", cb),
  1531. "[json.exception.out_of_range.406] number overflow parsing '1.18973e+4932'");
  1532. }
  1533. SECTION("SAX parser")
  1534. {
  1535. SECTION("} without value")
  1536. {
  1537. SaxCountdown s(1);
  1538. CHECK(json::sax_parse("{}", &s) == false);
  1539. }
  1540. SECTION("} with value")
  1541. {
  1542. SaxCountdown s(3);
  1543. CHECK(json::sax_parse("{\"k1\": true}", &s) == false);
  1544. }
  1545. SECTION("second key")
  1546. {
  1547. SaxCountdown s(3);
  1548. CHECK(json::sax_parse("{\"k1\": true, \"k2\": false}", &s) == false);
  1549. }
  1550. SECTION("] without value")
  1551. {
  1552. SaxCountdown s(1);
  1553. CHECK(json::sax_parse("[]", &s) == false);
  1554. }
  1555. SECTION("] with value")
  1556. {
  1557. SaxCountdown s(2);
  1558. CHECK(json::sax_parse("[1]", &s) == false);
  1559. }
  1560. SECTION("float")
  1561. {
  1562. SaxCountdown s(0);
  1563. CHECK(json::sax_parse("3.14", &s) == false);
  1564. }
  1565. SECTION("false")
  1566. {
  1567. SaxCountdown s(0);
  1568. CHECK(json::sax_parse("false", &s) == false);
  1569. }
  1570. SECTION("null")
  1571. {
  1572. SaxCountdown s(0);
  1573. CHECK(json::sax_parse("null", &s) == false);
  1574. }
  1575. SECTION("true")
  1576. {
  1577. SaxCountdown s(0);
  1578. CHECK(json::sax_parse("true", &s) == false);
  1579. }
  1580. SECTION("unsigned")
  1581. {
  1582. SaxCountdown s(0);
  1583. CHECK(json::sax_parse("12", &s) == false);
  1584. }
  1585. SECTION("integer")
  1586. {
  1587. SaxCountdown s(0);
  1588. CHECK(json::sax_parse("-12", &s) == false);
  1589. }
  1590. SECTION("string")
  1591. {
  1592. SaxCountdown s(0);
  1593. CHECK(json::sax_parse("\"foo\"", &s) == false);
  1594. }
  1595. }
  1596. }
  1597. }