int main(int, char*[]) { // Prepare JSON reader and input stream. Reader reader; char readBuffer[65536]; FileReadStream is(stdin, readBuffer, sizeof(readBuffer)); // Prepare JSON writer and output stream. char writeBuffer[65536]; FileWriteStream os(stdout, writeBuffer, sizeof(writeBuffer)); JsonxWriter<FileWriteStream> writer(os); // JSON reader parse from the input stream and let writer generate the output. if (!reader.Parse(is, writer)) { fprintf(stderr, "\nError(%u): %s\n", static_cast<unsigned>(reader.GetErrorOffset()), GetParseError_En(reader.GetParseErrorCode())); return 1; } return 0; }
TEST(Document, ParseStream_EncodedInputStream) { // UTF8 -> UTF16 FILE* fp = OpenEncodedFile("utf8.json"); char buffer[256]; FileReadStream bis(fp, buffer, sizeof(buffer)); EncodedInputStream<UTF8<>, FileReadStream> eis(bis); GenericDocument<UTF16<> > d; d.ParseStream<0, UTF8<> >(eis); EXPECT_FALSE(d.HasParseError()); fclose(fp); wchar_t expected[] = L"I can eat glass and it doesn't hurt me."; GenericValue<UTF16<> >& v = d[L"en"]; EXPECT_TRUE(v.IsString()); EXPECT_EQ(sizeof(expected) / sizeof(wchar_t) - 1, v.GetStringLength()); EXPECT_EQ(0, StrCmp(expected, v.GetString())); // UTF16 -> UTF8 in memory StringBuffer bos; typedef EncodedOutputStream<UTF8<>, StringBuffer> OutputStream; OutputStream eos(bos, false); // Not writing BOM { Writer<OutputStream, UTF16<>, UTF8<> > writer(eos); d.Accept(writer); } // Condense the original file and compare. fp = OpenEncodedFile("utf8.json"); FileReadStream is(fp, buffer, sizeof(buffer)); Reader reader; StringBuffer bos2; Writer<StringBuffer> writer2(bos2); reader.Parse(is, writer2); fclose(fp); EXPECT_EQ(bos.GetSize(), bos2.GetSize()); EXPECT_EQ(0, memcmp(bos.GetString(), bos2.GetString(), bos2.GetSize())); }
TEST(Document, ParseStream_AutoUTFInputStream) { // Any -> UTF8 FILE* fp = OpenEncodedFile("utf32be.json"); char buffer[256]; FileReadStream bis(fp, buffer, sizeof(buffer)); AutoUTFInputStream<unsigned, FileReadStream> eis(bis); Document d; d.ParseStream<0, AutoUTF<unsigned> >(eis); EXPECT_FALSE(d.HasParseError()); fclose(fp); char expected[] = "I can eat glass and it doesn't hurt me."; Value& v = d["en"]; EXPECT_TRUE(v.IsString()); EXPECT_EQ(sizeof(expected) - 1, v.GetStringLength()); EXPECT_EQ(0, StrCmp(expected, v.GetString())); // UTF8 -> UTF8 in memory StringBuffer bos; Writer<StringBuffer> writer(bos); d.Accept(writer); { // Condense the original file and compare. FILE *fp = OpenEncodedFile("utf8.json"); FileReadStream is(fp, buffer, sizeof(buffer)); Reader reader; StringBuffer bos2; Writer<StringBuffer> writer(bos2); reader.Parse(is, writer); fclose(fp); EXPECT_EQ(bos.GetSize(), bos2.GetSize()); EXPECT_EQ(0, memcmp(bos.GetString(), bos2.GetString(), bos2.GetSize())); } }
// For covering FileWriteStream::PutN() TEST(PrettyWriter, FileWriteStream) { char filename[L_tmpnam]; FILE* fp = TempFile(filename); char buffer[16]; FileWriteStream os(fp, buffer, sizeof(buffer)); PrettyWriter<FileWriteStream> writer(os); Reader reader; StringStream s(kJson); reader.Parse(s, writer); fclose(fp); fp = fopen(filename, "rb"); fseek(fp, 0, SEEK_END); size_t size = (size_t)ftell(fp); fseek(fp, 0, SEEK_SET); char* json = (char*)malloc(size + 1); size_t readLength = fread(json, 1, size, fp); json[readLength] = '\0'; fclose(fp); remove(filename); EXPECT_STREQ(kPrettyJson, json); free(json); }
TEST(Reader, ParseObject) { const char* json = "{ \"hello\" : \"world\", \"t\" : true , \"f\" : false, \"n\": null, \"i\":123, \"pi\": 3.1416, \"a\":[1, 2, 3] } "; // Insitu { char* json2 = StrDup(json); InsituStringStream s(json2); ParseObjectHandler h; Reader reader; reader.Parse<kParseInsituFlag>(s, h); EXPECT_EQ(20u, h.step_); free(json2); } // Normal { StringStream s(json); ParseObjectHandler h; Reader reader; reader.Parse(s, h); EXPECT_EQ(20u, h.step_); } }
/* Converts string to input stream and feeds it to rapidJSON Parse function */ extern "C" bool tm_json_parse(tm_json_r_handler_t* rh,const char* json_s) { // allocate memory for the struct rh = (tm_json_r_handler_t*)malloc(sizeof(tm_json_r_handler_t)); // link the function pointers to the callbacks rh->Default = tm_json_read_default; rh->Null = tm_json_read_null; rh->Bool = tm_json_read_boolean; rh->Int = tm_json_read_int; rh->Uint = tm_json_read_uint; rh->Int64 = tm_json_read_int64; rh->Uint64 = tm_json_read_uint64; rh->Double = tm_json_read_double; rh->String = tm_json_read_string; rh->StartObject = tm_json_read_startObject; rh->EndObject = tm_json_read_endObject; rh->StartArray = tm_json_read_startArray; rh->EndArray = tm_json_read_endArray; // create an input stream from the stringified JSON input StringStream is(json_s); // create a defaults flags GenericReader object Reader reader; // get a copy of the reader handler tm_json_r_handler_t rh_copy = *rh; // get rid of the allocated space free(rh); // call rapidJSON's Parser using the input stream and the given handler return reader.Parse(is,rh_copy); }
TEST(Writer, Transcode) { const char json[] = "{\"hello\":\"world\",\"t\":true,\"f\":false,\"n\":null,\"i\":123,\"pi\":3.1416,\"a\":[1,2,3],\"dollar\":\"\x24\",\"cents\":\"\xC2\xA2\",\"euro\":\"\xE2\x82\xAC\",\"gclef\":\"\xF0\x9D\x84\x9E\"}"; // UTF8 -> UTF16 -> UTF8 TestTranscode<UTF8<> >(json); // UTF8 -> ASCII -> UTF8 TestTranscode<ASCII<> >(json); // UTF8 -> UTF16 -> UTF8 TestTranscode<UTF16<> >(json); // UTF8 -> UTF32 -> UTF8 TestTranscode<UTF32<> >(json); // UTF8 -> AutoUTF -> UTF8 UTFType types[] = { kUTF8, kUTF16LE , kUTF16BE, kUTF32LE , kUTF32BE }; for (size_t i = 0; i < 5; i++) { StringStream s(json); MemoryBuffer buffer; AutoUTFOutputStream<unsigned, MemoryBuffer> os(buffer, types[i], true); Writer<AutoUTFOutputStream<unsigned, MemoryBuffer>, UTF8<>, AutoUTF<unsigned> > writer(os); Reader reader; reader.Parse(s, writer); StringBuffer buffer2; Writer<StringBuffer> writer2(buffer2); GenericReader<AutoUTF<unsigned>, UTF8<> > reader2; MemoryStream s2(buffer.GetBuffer(), buffer.GetSize()); AutoUTFInputStream<unsigned, MemoryStream> is(s2); reader2.Parse(is, writer2); EXPECT_STREQ(json, buffer2.GetString()); } }
TEST(Reader, ParseString) { #define TEST_STRING(Encoding, e, x) \ { \ Encoding::Ch* buffer = StrDup(x); \ GenericInsituStringStream<Encoding> is(buffer); \ ParseStringHandler<Encoding> h; \ GenericReader<Encoding, Encoding> reader; \ reader.Parse<kParseInsituFlag | kParseValidateEncodingFlag>(is, h); \ EXPECT_EQ(0, StrCmp<Encoding::Ch>(e, h.str_)); \ EXPECT_EQ(StrLen(e), h.length_); \ free(buffer); \ GenericStringStream<Encoding> s(x); \ ParseStringHandler<Encoding> h2; \ GenericReader<Encoding, Encoding> reader2; \ reader2.Parse(s, h2); \ EXPECT_EQ(0, StrCmp<Encoding::Ch>(e, h2.str_)); \ EXPECT_EQ(StrLen(e), h2.length_); \ } // String constant L"\xXX" can only specify character code in bytes, which is not endianness-neutral. // And old compiler does not support u"" and U"" string literal. So here specify string literal by array of Ch. // In addition, GCC 4.8 generates -Wnarrowing warnings when character code >= 128 are assigned to signed integer types. // Therefore, utype is added for declaring unsigned array, and then cast it to Encoding::Ch. #define ARRAY(...) { __VA_ARGS__ } #define TEST_STRINGARRAY(Encoding, utype, array, x) \ { \ static const utype ue[] = array; \ static const Encoding::Ch* e = reinterpret_cast<const Encoding::Ch *>(&ue[0]); \ TEST_STRING(Encoding, e, x); \ } #define TEST_STRINGARRAY2(Encoding, utype, earray, xarray) \ { \ static const utype ue[] = earray; \ static const utype xe[] = xarray; \ static const Encoding::Ch* e = reinterpret_cast<const Encoding::Ch *>(&ue[0]); \ static const Encoding::Ch* x = reinterpret_cast<const Encoding::Ch *>(&xe[0]); \ TEST_STRING(Encoding, e, x); \ } TEST_STRING(UTF8<>, "", "\"\""); TEST_STRING(UTF8<>, "Hello", "\"Hello\""); TEST_STRING(UTF8<>, "Hello\nWorld", "\"Hello\\nWorld\""); TEST_STRING(UTF8<>, "\"\\/\b\f\n\r\t", "\"\\\"\\\\/\\b\\f\\n\\r\\t\""); TEST_STRING(UTF8<>, "\x24", "\"\\u0024\""); // Dollar sign U+0024 TEST_STRING(UTF8<>, "\xC2\xA2", "\"\\u00A2\""); // Cents sign U+00A2 TEST_STRING(UTF8<>, "\xE2\x82\xAC", "\"\\u20AC\""); // Euro sign U+20AC TEST_STRING(UTF8<>, "\xF0\x9D\x84\x9E", "\"\\uD834\\uDD1E\""); // G clef sign U+1D11E // UTF16 TEST_STRING(UTF16<>, L"", L"\"\""); TEST_STRING(UTF16<>, L"Hello", L"\"Hello\""); TEST_STRING(UTF16<>, L"Hello\nWorld", L"\"Hello\\nWorld\""); TEST_STRING(UTF16<>, L"\"\\/\b\f\n\r\t", L"\"\\\"\\\\/\\b\\f\\n\\r\\t\""); TEST_STRINGARRAY(UTF16<>, wchar_t, ARRAY(0x0024, 0x0000), L"\"\\u0024\""); TEST_STRINGARRAY(UTF16<>, wchar_t, ARRAY(0x00A2, 0x0000), L"\"\\u00A2\""); // Cents sign U+00A2 TEST_STRINGARRAY(UTF16<>, wchar_t, ARRAY(0x20AC, 0x0000), L"\"\\u20AC\""); // Euro sign U+20AC TEST_STRINGARRAY(UTF16<>, wchar_t, ARRAY(0xD834, 0xDD1E, 0x0000), L"\"\\uD834\\uDD1E\""); // G clef sign U+1D11E // UTF32 TEST_STRINGARRAY2(UTF32<>, unsigned, ARRAY('\0'), ARRAY('\"', '\"', '\0')); TEST_STRINGARRAY2(UTF32<>, unsigned, ARRAY('H', 'e', 'l', 'l', 'o', '\0'), ARRAY('\"', 'H', 'e', 'l', 'l', 'o', '\"', '\0')); TEST_STRINGARRAY2(UTF32<>, unsigned, ARRAY('H', 'e', 'l', 'l', 'o', '\n', 'W', 'o', 'r', 'l', 'd', '\0'), ARRAY('\"', 'H', 'e', 'l', 'l', 'o', '\\', 'n', 'W', 'o', 'r', 'l', 'd', '\"', '\0')); TEST_STRINGARRAY2(UTF32<>, unsigned, ARRAY('\"', '\\', '/', '\b', '\f', '\n', '\r', '\t', '\0'), ARRAY('\"', '\\', '\"', '\\', '\\', '/', '\\', 'b', '\\', 'f', '\\', 'n', '\\', 'r', '\\', 't', '\"', '\0')); TEST_STRINGARRAY2(UTF32<>, unsigned, ARRAY(0x00024, 0x0000), ARRAY('\"', '\\', 'u', '0', '0', '2', '4', '\"', '\0')); TEST_STRINGARRAY2(UTF32<>, unsigned, ARRAY(0x000A2, 0x0000), ARRAY('\"', '\\', 'u', '0', '0', 'A', '2', '\"', '\0')); // Cents sign U+00A2 TEST_STRINGARRAY2(UTF32<>, unsigned, ARRAY(0x020AC, 0x0000), ARRAY('\"', '\\', 'u', '2', '0', 'A', 'C', '\"', '\0')); // Euro sign U+20AC TEST_STRINGARRAY2(UTF32<>, unsigned, ARRAY(0x1D11E, 0x0000), ARRAY('\"', '\\', 'u', 'D', '8', '3', '4', '\\', 'u', 'D', 'D', '1', 'E', '\"', '\0')); // G clef sign U+1D11E #undef TEST_STRINGARRAY #undef ARRAY #undef TEST_STRING // Support of null character in string { StringStream s("\"Hello\\u0000World\""); const char e[] = "Hello\0World"; ParseStringHandler<UTF8<> > h; Reader reader; reader.Parse(s, h); EXPECT_EQ(0, memcmp(e, h.str_, h.length_ + 1)); EXPECT_EQ(11u, h.length_); } }