1
0
mirror of https://github.com/libretro/RetroArch synced 2024-07-05 09:48:42 +00:00

(rapidjson) Remove unused files

This commit is contained in:
twinaphex 2020-09-21 01:27:41 +02:00
parent 9aa008834e
commit a117811936
51 changed files with 0 additions and 14848 deletions

View File

@ -1,42 +0,0 @@
cmake_minimum_required(VERSION 2.8)
if(POLICY CMP0054)
cmake_policy(SET CMP0054 NEW)
endif()
set(EXAMPLES
capitalize
condense
filterkey
filterkeydom
jsonx
messagereader
parsebyparts
pretty
prettyauto
schemavalidator
serialize
simpledom
simplereader
simplewriter
tutorial)
include_directories("../include/")
add_definitions(-D__STDC_FORMAT_MACROS)
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread -Werror -Wall -Wextra -Weffc++ -Wswitch-default")
elseif (CMAKE_CXX_COMPILER_ID MATCHES "Clang")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror -Wall -Wextra -Weffc++ -Wswitch-default -Wfloat-equal -Wimplicit-fallthrough -Weverything")
endif()
foreach (example ${EXAMPLES})
add_executable(${example} ${example}/${example}.cpp)
endforeach()
if (CMAKE_CXX_COMPILER_ID MATCHES "Clang")
target_link_libraries(parsebyparts pthread)
endif()
add_custom_target(examples ALL DEPENDS ${EXAMPLES})

View File

@ -1,67 +0,0 @@
// JSON condenser example
// This example parses JSON from stdin with validation,
// and re-output the JSON content to stdout with all string capitalized, and without whitespace.
#include "rapidjson/reader.h"
#include "rapidjson/writer.h"
#include "rapidjson/filereadstream.h"
#include "rapidjson/filewritestream.h"
#include "rapidjson/error/en.h"
#include <vector>
#include <cctype>
using namespace rapidjson;
template<typename OutputHandler>
struct CapitalizeFilter {
CapitalizeFilter(OutputHandler& out) : out_(out), buffer_() {}
bool Null() { return out_.Null(); }
bool Bool(bool b) { return out_.Bool(b); }
bool Int(int i) { return out_.Int(i); }
bool Uint(unsigned u) { return out_.Uint(u); }
bool Int64(int64_t i) { return out_.Int64(i); }
bool Uint64(uint64_t u) { return out_.Uint64(u); }
bool Double(double d) { return out_.Double(d); }
bool RawNumber(const char* str, SizeType length, bool copy) { return out_.RawNumber(str, length, copy); }
bool String(const char* str, SizeType length, bool) {
buffer_.clear();
for (SizeType i = 0; i < length; i++)
buffer_.push_back(static_cast<char>(std::toupper(str[i])));
return out_.String(&buffer_.front(), length, true); // true = output handler need to copy the string
}
bool StartObject() { return out_.StartObject(); }
bool Key(const char* str, SizeType length, bool copy) { return String(str, length, copy); }
bool EndObject(SizeType memberCount) { return out_.EndObject(memberCount); }
bool StartArray() { return out_.StartArray(); }
bool EndArray(SizeType elementCount) { return out_.EndArray(elementCount); }
OutputHandler& out_;
std::vector<char> buffer_;
private:
CapitalizeFilter(const CapitalizeFilter&);
CapitalizeFilter& operator=(const CapitalizeFilter&);
};
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));
Writer<FileWriteStream> writer(os);
// JSON reader parse from the input stream and let writer generate the output.
CapitalizeFilter<Writer<FileWriteStream> > filter(writer);
if (!reader.Parse(is, filter)) {
fprintf(stderr, "\nError(%u): %s\n", static_cast<unsigned>(reader.GetErrorOffset()), GetParseError_En(reader.GetParseErrorCode()));
return 1;
}
return 0;
}

View File

@ -1,32 +0,0 @@
// JSON condenser example
// This example parses JSON text from stdin with validation,
// and re-output the JSON content to stdout without whitespace.
#include "rapidjson/reader.h"
#include "rapidjson/writer.h"
#include "rapidjson/filereadstream.h"
#include "rapidjson/filewritestream.h"
#include "rapidjson/error/en.h"
using namespace rapidjson;
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));
Writer<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;
}

View File

@ -1,135 +0,0 @@
// JSON filterkey example with SAX-style API.
// This example parses JSON text from stdin with validation.
// During parsing, specified key will be filtered using a SAX handler.
// It re-output the JSON content to stdout without whitespace.
#include "rapidjson/reader.h"
#include "rapidjson/writer.h"
#include "rapidjson/filereadstream.h"
#include "rapidjson/filewritestream.h"
#include "rapidjson/error/en.h"
#include <stack>
using namespace rapidjson;
// This handler forwards event into an output handler, with filtering the descendent events of specified key.
template <typename OutputHandler>
class FilterKeyHandler {
public:
typedef char Ch;
FilterKeyHandler(OutputHandler& outputHandler, const Ch* keyString, SizeType keyLength) :
outputHandler_(outputHandler), keyString_(keyString), keyLength_(keyLength), filterValueDepth_(), filteredKeyCount_()
{}
bool Null() { return filterValueDepth_ > 0 ? EndValue() : outputHandler_.Null() && EndValue(); }
bool Bool(bool b) { return filterValueDepth_ > 0 ? EndValue() : outputHandler_.Bool(b) && EndValue(); }
bool Int(int i) { return filterValueDepth_ > 0 ? EndValue() : outputHandler_.Int(i) && EndValue(); }
bool Uint(unsigned u) { return filterValueDepth_ > 0 ? EndValue() : outputHandler_.Uint(u) && EndValue(); }
bool Int64(int64_t i) { return filterValueDepth_ > 0 ? EndValue() : outputHandler_.Int64(i) && EndValue(); }
bool Uint64(uint64_t u) { return filterValueDepth_ > 0 ? EndValue() : outputHandler_.Uint64(u) && EndValue(); }
bool Double(double d) { return filterValueDepth_ > 0 ? EndValue() : outputHandler_.Double(d) && EndValue(); }
bool RawNumber(const Ch* str, SizeType len, bool copy) { return filterValueDepth_ > 0 ? EndValue() : outputHandler_.RawNumber(str, len, copy) && EndValue(); }
bool String (const Ch* str, SizeType len, bool copy) { return filterValueDepth_ > 0 ? EndValue() : outputHandler_.String (str, len, copy) && EndValue(); }
bool StartObject() {
if (filterValueDepth_ > 0) {
filterValueDepth_++;
return true;
}
else {
filteredKeyCount_.push(0);
return outputHandler_.StartObject();
}
}
bool Key(const Ch* str, SizeType len, bool copy) {
if (filterValueDepth_ > 0)
return true;
else if (len == keyLength_ && std::memcmp(str, keyString_, len) == 0) {
filterValueDepth_ = 1;
return true;
}
else {
++filteredKeyCount_.top();
return outputHandler_.Key(str, len, copy);
}
}
bool EndObject(SizeType) {
if (filterValueDepth_ > 0) {
filterValueDepth_--;
return EndValue();
}
else {
// Use our own filtered memberCount
SizeType memberCount = filteredKeyCount_.top();
filteredKeyCount_.pop();
return outputHandler_.EndObject(memberCount) && EndValue();
}
}
bool StartArray() {
if (filterValueDepth_ > 0) {
filterValueDepth_++;
return true;
}
else
return outputHandler_.StartArray();
}
bool EndArray(SizeType elementCount) {
if (filterValueDepth_ > 0) {
filterValueDepth_--;
return EndValue();
}
else
return outputHandler_.EndArray(elementCount) && EndValue();
}
private:
FilterKeyHandler(const FilterKeyHandler&);
FilterKeyHandler& operator=(const FilterKeyHandler&);
bool EndValue() {
if (filterValueDepth_ == 1) // Just at the end of value after filtered key
filterValueDepth_ = 0;
return true;
}
OutputHandler& outputHandler_;
const char* keyString_;
const SizeType keyLength_;
unsigned filterValueDepth_;
std::stack<SizeType> filteredKeyCount_;
};
int main(int argc, char* argv[]) {
if (argc != 2) {
fprintf(stderr, "filterkey key < input.json > output.json\n");
return 1;
}
// 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));
Writer<FileWriteStream> writer(os);
// Prepare Filter
FilterKeyHandler<Writer<FileWriteStream> > filter(writer, argv[1], static_cast<SizeType>(strlen(argv[1])));
// JSON reader parse from the input stream, filter handler filters the events, and forward to writer.
// i.e. the events flow is: reader -> filter -> writer
if (!reader.Parse(is, filter)) {
fprintf(stderr, "\nError(%u): %s\n", static_cast<unsigned>(reader.GetErrorOffset()), GetParseError_En(reader.GetParseErrorCode()));
return 1;
}
return 0;
}

View File

@ -1,170 +0,0 @@
// JSON filterkey example which populates filtered SAX events into a Document.
// This example parses JSON text from stdin with validation.
// During parsing, specified key will be filtered using a SAX handler.
// And finally the filtered events are used to populate a Document.
// As an example, the document is written to standard output.
#include "rapidjson/document.h"
#include "rapidjson/writer.h"
#include "rapidjson/filereadstream.h"
#include "rapidjson/filewritestream.h"
#include "rapidjson/error/en.h"
#include <stack>
using namespace rapidjson;
// This handler forwards event into an output handler, with filtering the descendent events of specified key.
template <typename OutputHandler>
class FilterKeyHandler {
public:
typedef char Ch;
FilterKeyHandler(OutputHandler& outputHandler, const Ch* keyString, SizeType keyLength) :
outputHandler_(outputHandler), keyString_(keyString), keyLength_(keyLength), filterValueDepth_(), filteredKeyCount_()
{}
bool Null() { return filterValueDepth_ > 0 ? EndValue() : outputHandler_.Null() && EndValue(); }
bool Bool(bool b) { return filterValueDepth_ > 0 ? EndValue() : outputHandler_.Bool(b) && EndValue(); }
bool Int(int i) { return filterValueDepth_ > 0 ? EndValue() : outputHandler_.Int(i) && EndValue(); }
bool Uint(unsigned u) { return filterValueDepth_ > 0 ? EndValue() : outputHandler_.Uint(u) && EndValue(); }
bool Int64(int64_t i) { return filterValueDepth_ > 0 ? EndValue() : outputHandler_.Int64(i) && EndValue(); }
bool Uint64(uint64_t u) { return filterValueDepth_ > 0 ? EndValue() : outputHandler_.Uint64(u) && EndValue(); }
bool Double(double d) { return filterValueDepth_ > 0 ? EndValue() : outputHandler_.Double(d) && EndValue(); }
bool RawNumber(const Ch* str, SizeType len, bool copy) { return filterValueDepth_ > 0 ? EndValue() : outputHandler_.RawNumber(str, len, copy) && EndValue(); }
bool String (const Ch* str, SizeType len, bool copy) { return filterValueDepth_ > 0 ? EndValue() : outputHandler_.String (str, len, copy) && EndValue(); }
bool StartObject() {
if (filterValueDepth_ > 0) {
filterValueDepth_++;
return true;
}
else {
filteredKeyCount_.push(0);
return outputHandler_.StartObject();
}
}
bool Key(const Ch* str, SizeType len, bool copy) {
if (filterValueDepth_ > 0)
return true;
else if (len == keyLength_ && std::memcmp(str, keyString_, len) == 0) {
filterValueDepth_ = 1;
return true;
}
else {
++filteredKeyCount_.top();
return outputHandler_.Key(str, len, copy);
}
}
bool EndObject(SizeType) {
if (filterValueDepth_ > 0) {
filterValueDepth_--;
return EndValue();
}
else {
// Use our own filtered memberCount
SizeType memberCount = filteredKeyCount_.top();
filteredKeyCount_.pop();
return outputHandler_.EndObject(memberCount) && EndValue();
}
}
bool StartArray() {
if (filterValueDepth_ > 0) {
filterValueDepth_++;
return true;
}
else
return outputHandler_.StartArray();
}
bool EndArray(SizeType elementCount) {
if (filterValueDepth_ > 0) {
filterValueDepth_--;
return EndValue();
}
else
return outputHandler_.EndArray(elementCount) && EndValue();
}
private:
FilterKeyHandler(const FilterKeyHandler&);
FilterKeyHandler& operator=(const FilterKeyHandler&);
bool EndValue() {
if (filterValueDepth_ == 1) // Just at the end of value after filtered key
filterValueDepth_ = 0;
return true;
}
OutputHandler& outputHandler_;
const char* keyString_;
const SizeType keyLength_;
unsigned filterValueDepth_;
std::stack<SizeType> filteredKeyCount_;
};
// Implements a generator for Document::Populate()
template <typename InputStream>
class FilterKeyReader {
public:
typedef char Ch;
FilterKeyReader(InputStream& is, const Ch* keyString, SizeType keyLength) :
is_(is), keyString_(keyString), keyLength_(keyLength), parseResult_()
{}
// SAX event flow: reader -> filter -> handler
template <typename Handler>
bool operator()(Handler& handler) {
FilterKeyHandler<Handler> filter(handler, keyString_, keyLength_);
Reader reader;
parseResult_ = reader.Parse(is_, filter);
return parseResult_;
}
const ParseResult& GetParseResult() const { return parseResult_; }
private:
FilterKeyReader(const FilterKeyReader&);
FilterKeyReader& operator=(const FilterKeyReader&);
InputStream& is_;
const char* keyString_;
const SizeType keyLength_;
ParseResult parseResult_;
};
int main(int argc, char* argv[]) {
if (argc != 2) {
fprintf(stderr, "filterkeydom key < input.json > output.json\n");
return 1;
}
// Prepare input stream.
char readBuffer[65536];
FileReadStream is(stdin, readBuffer, sizeof(readBuffer));
// Prepare Filter
FilterKeyReader<FileReadStream> reader(is, argv[1], static_cast<SizeType>(strlen(argv[1])));
// Populates the filtered events from reader
Document document;
document.Populate(reader);
ParseResult pr = reader.GetParseResult();
if (!pr) {
fprintf(stderr, "\nError(%u): %s\n", static_cast<unsigned>(pr.Offset()), GetParseError_En(pr.Code()));
return 1;
}
// Prepare JSON writer and output stream.
char writeBuffer[65536];
FileWriteStream os(stdout, writeBuffer, sizeof(writeBuffer));
Writer<FileWriteStream> writer(os);
// Write the document to standard output
document.Accept(writer);
return 0;
}

View File

@ -1,207 +0,0 @@
// JSON to JSONx conversion exmaple, using SAX API.
// JSONx is an IBM standard format to represent JSON as XML.
// https://www-01.ibm.com/support/knowledgecenter/SS9H2Y_7.1.0/com.ibm.dp.doc/json_jsonx.html
// This example parses JSON text from stdin with validation,
// and convert to JSONx format to stdout.
// Need compile with -D__STDC_FORMAT_MACROS for defining PRId64 and PRIu64 macros.
#include "rapidjson/reader.h"
#include "rapidjson/stringbuffer.h"
#include "rapidjson/filereadstream.h"
#include "rapidjson/filewritestream.h"
#include "rapidjson/error/en.h"
#include <cstdio>
using namespace rapidjson;
// For simplicity, this example only read/write in UTF-8 encoding
template <typename OutputStream>
class JsonxWriter {
public:
JsonxWriter(OutputStream& os) : os_(os), name_(), level_(0), hasName_(false) {
}
bool Null() {
return WriteStartElement("null", true);
}
bool Bool(bool b) {
return
WriteStartElement("boolean") &&
WriteString(b ? "true" : "false") &&
WriteEndElement("boolean");
}
bool Int(int i) {
char buffer[12];
return WriteNumberElement(buffer, sprintf(buffer, "%d", i));
}
bool Uint(unsigned i) {
char buffer[11];
return WriteNumberElement(buffer, sprintf(buffer, "%u", i));
}
bool Int64(int64_t i) {
char buffer[21];
return WriteNumberElement(buffer, sprintf(buffer, "%" PRId64, i));
}
bool Uint64(uint64_t i) {
char buffer[21];
return WriteNumberElement(buffer, sprintf(buffer, "%" PRIu64, i));
}
bool Double(double d) {
char buffer[30];
return WriteNumberElement(buffer, sprintf(buffer, "%.17g", d));
}
bool RawNumber(const char* str, SizeType length, bool) {
return
WriteStartElement("number") &&
WriteEscapedText(str, length) &&
WriteEndElement("number");
}
bool String(const char* str, SizeType length, bool) {
return
WriteStartElement("string") &&
WriteEscapedText(str, length) &&
WriteEndElement("string");
}
bool StartObject() {
return WriteStartElement("object");
}
bool Key(const char* str, SizeType length, bool) {
// backup key to name_
name_.Clear();
for (SizeType i = 0; i < length; i++)
name_.Put(str[i]);
hasName_ = true;
return true;
}
bool EndObject(SizeType) {
return WriteEndElement("object");
}
bool StartArray() {
return WriteStartElement("array");
}
bool EndArray(SizeType) {
return WriteEndElement("array");
}
private:
bool WriteString(const char* s) {
while (*s)
os_.Put(*s++);
return true;
}
bool WriteEscapedAttributeValue(const char* s, size_t length) {
for (size_t i = 0; i < length; i++) {
switch (s[i]) {
case '&': WriteString("&amp;"); break;
case '<': WriteString("&lt;"); break;
case '"': WriteString("&quot;"); break;
default: os_.Put(s[i]); break;
}
}
return true;
}
bool WriteEscapedText(const char* s, size_t length) {
for (size_t i = 0; i < length; i++) {
switch (s[i]) {
case '&': WriteString("&amp;"); break;
case '<': WriteString("&lt;"); break;
default: os_.Put(s[i]); break;
}
}
return true;
}
bool WriteStartElement(const char* type, bool emptyElement = false) {
if (level_ == 0)
if (!WriteString("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"))
return false;
if (!WriteString("<json:") || !WriteString(type))
return false;
// For root element, need to add declarations
if (level_ == 0) {
if (!WriteString(
" xsi:schemaLocation=\"http://www.datapower.com/schemas/json jsonx.xsd\""
" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""
" xmlns:json=\"http://www.ibm.com/xmlns/prod/2009/jsonx\""))
return false;
}
if (hasName_) {
hasName_ = false;
if (!WriteString(" name=\"") ||
!WriteEscapedAttributeValue(name_.GetString(), name_.GetSize()) ||
!WriteString("\""))
return false;
}
if (emptyElement)
return WriteString("/>");
else {
level_++;
return WriteString(">");
}
}
bool WriteEndElement(const char* type) {
if (!WriteString("</json:") ||
!WriteString(type) ||
!WriteString(">"))
return false;
// For the last end tag, flush the output stream.
if (--level_ == 0)
os_.Flush();
return true;
}
bool WriteNumberElement(const char* buffer, int length) {
if (!WriteStartElement("number"))
return false;
for (int j = 0; j < length; j++)
os_.Put(buffer[j]);
return WriteEndElement("number");
}
OutputStream& os_;
StringBuffer name_;
unsigned level_;
bool hasName_;
};
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;
}

View File

@ -1,105 +0,0 @@
// Reading a message JSON with Reader (SAX-style API).
// The JSON should be an object with key-string pairs.
#include "rapidjson/reader.h"
#include "rapidjson/error/en.h"
#include <iostream>
#include <string>
#include <map>
using namespace std;
using namespace rapidjson;
typedef map<string, string> MessageMap;
#if defined(__GNUC__)
RAPIDJSON_DIAG_PUSH
RAPIDJSON_DIAG_OFF(effc++)
#endif
#ifdef __clang__
RAPIDJSON_DIAG_PUSH
RAPIDJSON_DIAG_OFF(switch-enum)
#endif
struct MessageHandler
: public BaseReaderHandler<UTF8<>, MessageHandler> {
MessageHandler() : messages_(), state_(kExpectObjectStart), name_() {}
bool StartObject() {
switch (state_) {
case kExpectObjectStart:
state_ = kExpectNameOrObjectEnd;
return true;
default:
return false;
}
}
bool String(const char* str, SizeType length, bool) {
switch (state_) {
case kExpectNameOrObjectEnd:
name_ = string(str, length);
state_ = kExpectValue;
return true;
case kExpectValue:
messages_.insert(MessageMap::value_type(name_, string(str, length)));
state_ = kExpectNameOrObjectEnd;
return true;
default:
return false;
}
}
bool EndObject(SizeType) { return state_ == kExpectNameOrObjectEnd; }
bool Default() { return false; } // All other events are invalid.
MessageMap messages_;
enum State {
kExpectObjectStart,
kExpectNameOrObjectEnd,
kExpectValue
}state_;
std::string name_;
};
#if defined(__GNUC__)
RAPIDJSON_DIAG_POP
#endif
#ifdef __clang__
RAPIDJSON_DIAG_POP
#endif
static void ParseMessages(const char* json, MessageMap& messages) {
Reader reader;
MessageHandler handler;
StringStream ss(json);
if (reader.Parse(ss, handler))
messages.swap(handler.messages_); // Only change it if success.
else {
ParseErrorCode e = reader.GetParseErrorCode();
size_t o = reader.GetErrorOffset();
cout << "Error: " << GetParseError_En(e) << endl;;
cout << " at offset " << o << " near '" << string(json).substr(o, 10) << "...'" << endl;
}
}
int main() {
MessageMap messages;
const char* json1 = "{ \"greeting\" : \"Hello!\", \"farewell\" : \"bye-bye!\" }";
cout << json1 << endl;
ParseMessages(json1, messages);
for (MessageMap::const_iterator itr = messages.begin(); itr != messages.end(); ++itr)
cout << itr->first << ": " << itr->second << endl;
cout << endl << "Parse a JSON with invalid schema." << endl;
const char* json2 = "{ \"greeting\" : \"Hello!\", \"farewell\" : \"bye-bye!\", \"foo\" : {} }";
cout << json2 << endl;
ParseMessages(json2, messages);
return 0;
}

View File

@ -1,173 +0,0 @@
// Example of parsing JSON to document by parts.
// Using C++11 threads
// Temporarily disable for clang (older version) due to incompatibility with libstdc++
#if (__cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1700)) && !defined(__clang__)
#include "rapidjson/document.h"
#include "rapidjson/error/en.h"
#include "rapidjson/writer.h"
#include "rapidjson/ostreamwrapper.h"
#include <condition_variable>
#include <iostream>
#include <mutex>
#include <thread>
using namespace rapidjson;
template<unsigned parseFlags = kParseDefaultFlags>
class AsyncDocumentParser {
public:
AsyncDocumentParser(Document& d)
: stream_(*this)
, d_(d)
, parseThread_(&AsyncDocumentParser::Parse, this)
, mutex_()
, notEmpty_()
, finish_()
, completed_()
{}
~AsyncDocumentParser() {
if (!parseThread_.joinable())
return;
{
std::unique_lock<std::mutex> lock(mutex_);
// Wait until the buffer is read up (or parsing is completed)
while (!stream_.Empty() && !completed_)
finish_.wait(lock);
// Automatically append '\0' as the terminator in the stream.
static const char terminator[] = "";
stream_.src_ = terminator;
stream_.end_ = terminator + 1;
notEmpty_.notify_one(); // unblock the AsyncStringStream
}
parseThread_.join();
}
void ParsePart(const char* buffer, size_t length) {
std::unique_lock<std::mutex> lock(mutex_);
// Wait until the buffer is read up (or parsing is completed)
while (!stream_.Empty() && !completed_)
finish_.wait(lock);
// Stop further parsing if the parsing process is completed.
if (completed_)
return;
// Set the buffer to stream and unblock the AsyncStringStream
stream_.src_ = buffer;
stream_.end_ = buffer + length;
notEmpty_.notify_one();
}
private:
void Parse() {
d_.ParseStream<parseFlags>(stream_);
// The stream may not be fully read, notify finish anyway to unblock ParsePart()
std::unique_lock<std::mutex> lock(mutex_);
completed_ = true; // Parsing process is completed
finish_.notify_one(); // Unblock ParsePart() or destructor if they are waiting.
}
struct AsyncStringStream {
typedef char Ch;
AsyncStringStream(AsyncDocumentParser& parser) : parser_(parser), src_(), end_(), count_() {}
char Peek() const {
std::unique_lock<std::mutex> lock(parser_.mutex_);
// If nothing in stream, block to wait.
while (Empty())
parser_.notEmpty_.wait(lock);
return *src_;
}
char Take() {
std::unique_lock<std::mutex> lock(parser_.mutex_);
// If nothing in stream, block to wait.
while (Empty())
parser_.notEmpty_.wait(lock);
count_++;
char c = *src_++;
// If all stream is read up, notify that the stream is finish.
if (Empty())
parser_.finish_.notify_one();
return c;
}
size_t Tell() const { return count_; }
// Not implemented
char* PutBegin() { return 0; }
void Put(char) {}
void Flush() {}
size_t PutEnd(char*) { return 0; }
bool Empty() const { return src_ == end_; }
AsyncDocumentParser& parser_;
const char* src_; //!< Current read position.
const char* end_; //!< End of buffer
size_t count_; //!< Number of characters taken so far.
};
AsyncStringStream stream_;
Document& d_;
std::thread parseThread_;
std::mutex mutex_;
std::condition_variable notEmpty_;
std::condition_variable finish_;
bool completed_;
};
int main() {
Document d;
{
AsyncDocumentParser<> parser(d);
const char json1[] = " { \"hello\" : \"world\", \"t\" : tr";
//const char json1[] = " { \"hello\" : \"world\", \"t\" : trX"; // Fot test parsing error
const char json2[] = "ue, \"f\" : false, \"n\": null, \"i\":123, \"pi\": 3.14";
const char json3[] = "16, \"a\":[1, 2, 3, 4] } ";
parser.ParsePart(json1, sizeof(json1) - 1);
parser.ParsePart(json2, sizeof(json2) - 1);
parser.ParsePart(json3, sizeof(json3) - 1);
}
if (d.HasParseError()) {
std::cout << "Error at offset " << d.GetErrorOffset() << ": " << GetParseError_En(d.GetParseError()) << std::endl;
return EXIT_FAILURE;
}
// Stringify the JSON to cout
OStreamWrapper os(std::cout);
Writer<OStreamWrapper> writer(os);
d.Accept(writer);
std::cout << std::endl;
return EXIT_SUCCESS;
}
#else // Not supporting C++11
#include <iostream>
int main() {
std::cout << "This example requires C++11 compiler" << std::endl;
}
#endif

View File

@ -1,30 +0,0 @@
// JSON pretty formatting example
// This example can only handle UTF-8. For handling other encodings, see prettyauto example.
#include "rapidjson/reader.h"
#include "rapidjson/prettywriter.h"
#include "rapidjson/filereadstream.h"
#include "rapidjson/filewritestream.h"
#include "rapidjson/error/en.h"
using namespace rapidjson;
int main(int, char*[]) {
// Prepare reader and input stream.
Reader reader;
char readBuffer[65536];
FileReadStream is(stdin, readBuffer, sizeof(readBuffer));
// Prepare writer and output stream.
char writeBuffer[65536];
FileWriteStream os(stdout, writeBuffer, sizeof(writeBuffer));
PrettyWriter<FileWriteStream> writer(os);
// JSON reader parse from the input stream and let writer generate the output.
if (!reader.Parse<kParseValidateEncodingFlag>(is, writer)) {
fprintf(stderr, "\nError(%u): %s\n", static_cast<unsigned>(reader.GetErrorOffset()), GetParseError_En(reader.GetParseErrorCode()));
return 1;
}
return 0;
}

View File

@ -1,56 +0,0 @@
// JSON pretty formatting example
// This example can handle UTF-8/UTF-16LE/UTF-16BE/UTF-32LE/UTF-32BE.
// The input firstly convert to UTF8, and then write to the original encoding with pretty formatting.
#include "rapidjson/reader.h"
#include "rapidjson/prettywriter.h"
#include "rapidjson/filereadstream.h"
#include "rapidjson/filewritestream.h"
#include "rapidjson/encodedstream.h" // NEW
#include "rapidjson/error/en.h"
#ifdef _WIN32
#include <fcntl.h>
#include <io.h>
#endif
using namespace rapidjson;
int main(int, char*[]) {
#ifdef _WIN32
// Prevent Windows converting between CR+LF and LF
_setmode(_fileno(stdin), _O_BINARY); // NEW
_setmode(_fileno(stdout), _O_BINARY); // NEW
#endif
// Prepare reader and input stream.
//Reader reader;
GenericReader<AutoUTF<unsigned>, UTF8<> > reader; // CHANGED
char readBuffer[65536];
FileReadStream is(stdin, readBuffer, sizeof(readBuffer));
AutoUTFInputStream<unsigned, FileReadStream> eis(is); // NEW
// Prepare writer and output stream.
char writeBuffer[65536];
FileWriteStream os(stdout, writeBuffer, sizeof(writeBuffer));
#if 1
// Use the same Encoding of the input. Also use BOM according to input.
typedef AutoUTFOutputStream<unsigned, FileWriteStream> OutputStream; // NEW
OutputStream eos(os, eis.GetType(), eis.HasBOM()); // NEW
PrettyWriter<OutputStream, UTF8<>, AutoUTF<unsigned> > writer(eos); // CHANGED
#else
// You may also use static bound encoding type, such as output to UTF-16LE with BOM
typedef EncodedOutputStream<UTF16LE<>,FileWriteStream> OutputStream; // NEW
OutputStream eos(os, true); // NEW
PrettyWriter<OutputStream, UTF8<>, UTF16LE<> > writer(eos); // CHANGED
#endif
// JSON reader parse from the input stream and let writer generate the output.
//if (!reader.Parse<kParseValidateEncodingFlag>(is, writer)) {
if (!reader.Parse<kParseValidateEncodingFlag>(eis, writer)) { // CHANGED
fprintf(stderr, "\nError(%u): %s\n", static_cast<unsigned>(reader.GetErrorOffset()), GetParseError_En(reader.GetParseErrorCode()));
return 1;
}
return 0;
}

View File

@ -1,72 +0,0 @@
// Schema Validator example
// The example validates JSON text from stdin with a JSON schema specified in the argument.
#include "rapidjson/error/en.h"
#include "rapidjson/filereadstream.h"
#include "rapidjson/schema.h"
#include "rapidjson/stringbuffer.h"
using namespace rapidjson;
int main(int argc, char *argv[]) {
if (argc != 2) {
fprintf(stderr, "Usage: schemavalidator schema.json < input.json\n");
return EXIT_FAILURE;
}
// Read a JSON schema from file into Document
Document d;
char buffer[4096];
{
FILE *fp = fopen(argv[1], "r");
if (!fp) {
printf("Schema file '%s' not found\n", argv[1]);
return -1;
}
FileReadStream fs(fp, buffer, sizeof(buffer));
d.ParseStream(fs);
if (d.HasParseError()) {
fprintf(stderr, "Schema file '%s' is not a valid JSON\n", argv[1]);
fprintf(stderr, "Error(offset %u): %s\n",
static_cast<unsigned>(d.GetErrorOffset()),
GetParseError_En(d.GetParseError()));
fclose(fp);
return EXIT_FAILURE;
}
fclose(fp);
}
// Then convert the Document into SchemaDocument
SchemaDocument sd(d);
// Use reader to parse the JSON in stdin, and forward SAX events to validator
SchemaValidator validator(sd);
Reader reader;
FileReadStream is(stdin, buffer, sizeof(buffer));
if (!reader.Parse(is, validator) && reader.GetParseErrorCode() != kParseErrorTermination) {
// Schema validator error would cause kParseErrorTermination, which will handle it in next step.
fprintf(stderr, "Input is not a valid JSON\n");
fprintf(stderr, "Error(offset %u): %s\n",
static_cast<unsigned>(reader.GetErrorOffset()),
GetParseError_En(reader.GetParseErrorCode()));
}
// Check the validation result
if (validator.IsValid()) {
printf("Input JSON is valid.\n");
return EXIT_SUCCESS;
}
else {
printf("Input JSON is invalid.\n");
StringBuffer sb;
validator.GetInvalidSchemaPointer().StringifyUriFragment(sb);
fprintf(stderr, "Invalid schema: %s\n", sb.GetString());
fprintf(stderr, "Invalid keyword: %s\n", validator.GetInvalidSchemaKeyword());
sb.Clear();
validator.GetInvalidDocumentPointer().StringifyUriFragment(sb);
fprintf(stderr, "Invalid document: %s\n", sb.GetString());
return EXIT_FAILURE;
}
}

View File

@ -1,173 +0,0 @@
// Serialize example
// This example shows writing JSON string with writer directly.
#include "rapidjson/prettywriter.h" // for stringify JSON
#include <cstdio>
#include <string>
#include <vector>
using namespace rapidjson;
class Person {
public:
Person(const std::string& name, unsigned age) : name_(name), age_(age) {}
Person(const Person& rhs) : name_(rhs.name_), age_(rhs.age_) {}
virtual ~Person();
Person& operator=(const Person& rhs) {
name_ = rhs.name_;
age_ = rhs.age_;
return *this;
}
protected:
template <typename Writer>
void Serialize(Writer& writer) const {
// This base class just write out name-value pairs, without wrapping within an object.
writer.String("name");
#if RAPIDJSON_HAS_STDSTRING
writer.String(name_);
#else
writer.String(name_.c_str(), static_cast<SizeType>(name_.length())); // Supplying length of string is faster.
#endif
writer.String("age");
writer.Uint(age_);
}
private:
std::string name_;
unsigned age_;
};
Person::~Person() {
}
class Education {
public:
Education(const std::string& school, double GPA) : school_(school), GPA_(GPA) {}
Education(const Education& rhs) : school_(rhs.school_), GPA_(rhs.GPA_) {}
template <typename Writer>
void Serialize(Writer& writer) const {
writer.StartObject();
writer.String("school");
#if RAPIDJSON_HAS_STDSTRING
writer.String(school_);
#else
writer.String(school_.c_str(), static_cast<SizeType>(school_.length()));
#endif
writer.String("GPA");
writer.Double(GPA_);
writer.EndObject();
}
private:
std::string school_;
double GPA_;
};
class Dependent : public Person {
public:
Dependent(const std::string& name, unsigned age, Education* education = 0) : Person(name, age), education_(education) {}
Dependent(const Dependent& rhs) : Person(rhs), education_(0) { education_ = (rhs.education_ == 0) ? 0 : new Education(*rhs.education_); }
virtual ~Dependent();
Dependent& operator=(const Dependent& rhs) {
if (this == &rhs)
return *this;
delete education_;
education_ = (rhs.education_ == 0) ? 0 : new Education(*rhs.education_);
return *this;
}
template <typename Writer>
void Serialize(Writer& writer) const {
writer.StartObject();
Person::Serialize(writer);
writer.String("education");
if (education_)
education_->Serialize(writer);
else
writer.Null();
writer.EndObject();
}
private:
Education *education_;
};
Dependent::~Dependent() {
delete education_;
}
class Employee : public Person {
public:
Employee(const std::string& name, unsigned age, bool married) : Person(name, age), dependents_(), married_(married) {}
Employee(const Employee& rhs) : Person(rhs), dependents_(rhs.dependents_), married_(rhs.married_) {}
virtual ~Employee();
Employee& operator=(const Employee& rhs) {
static_cast<Person&>(*this) = rhs;
dependents_ = rhs.dependents_;
married_ = rhs.married_;
return *this;
}
void AddDependent(const Dependent& dependent) {
dependents_.push_back(dependent);
}
template <typename Writer>
void Serialize(Writer& writer) const {
writer.StartObject();
Person::Serialize(writer);
writer.String("married");
writer.Bool(married_);
writer.String(("dependents"));
writer.StartArray();
for (std::vector<Dependent>::const_iterator dependentItr = dependents_.begin(); dependentItr != dependents_.end(); ++dependentItr)
dependentItr->Serialize(writer);
writer.EndArray();
writer.EndObject();
}
private:
std::vector<Dependent> dependents_;
bool married_;
};
Employee::~Employee() {
}
int main(int, char*[]) {
std::vector<Employee> employees;
employees.push_back(Employee("Milo YIP", 34, true));
employees.back().AddDependent(Dependent("Lua YIP", 3, new Education("Happy Kindergarten", 3.5)));
employees.back().AddDependent(Dependent("Mio YIP", 1));
employees.push_back(Employee("Percy TSE", 30, false));
StringBuffer sb;
PrettyWriter<StringBuffer> writer(sb);
writer.StartArray();
for (std::vector<Employee>::const_iterator employeeItr = employees.begin(); employeeItr != employees.end(); ++employeeItr)
employeeItr->Serialize(writer);
writer.EndArray();
puts(sb.GetString());
return 0;
}

View File

@ -1,29 +0,0 @@
// JSON simple example
// This example does not handle errors.
#include "rapidjson/document.h"
#include "rapidjson/writer.h"
#include "rapidjson/stringbuffer.h"
#include <iostream>
using namespace rapidjson;
int main() {
// 1. Parse a JSON string into DOM.
const char* json = "{\"project\":\"rapidjson\",\"stars\":10}";
Document d;
d.Parse(json);
// 2. Modify it by DOM.
Value& s = d["stars"];
s.SetInt(s.GetInt() + 1);
// 3. Stringify the DOM
StringBuffer buffer;
Writer<StringBuffer> writer(buffer);
d.Accept(writer);
// Output {"project":"rapidjson","stars":11}
std::cout << buffer.GetString() << std::endl;
return 0;
}

View File

@ -1,42 +0,0 @@
#include "rapidjson/reader.h"
#include <iostream>
using namespace rapidjson;
using namespace std;
struct MyHandler {
bool Null() { cout << "Null()" << endl; return true; }
bool Bool(bool b) { cout << "Bool(" << boolalpha << b << ")" << endl; return true; }
bool Int(int i) { cout << "Int(" << i << ")" << endl; return true; }
bool Uint(unsigned u) { cout << "Uint(" << u << ")" << endl; return true; }
bool Int64(int64_t i) { cout << "Int64(" << i << ")" << endl; return true; }
bool Uint64(uint64_t u) { cout << "Uint64(" << u << ")" << endl; return true; }
bool Double(double d) { cout << "Double(" << d << ")" << endl; return true; }
bool RawNumber(const char* str, SizeType length, bool copy) {
cout << "Number(" << str << ", " << length << ", " << boolalpha << copy << ")" << endl;
return true;
}
bool String(const char* str, SizeType length, bool copy) {
cout << "String(" << str << ", " << length << ", " << boolalpha << copy << ")" << endl;
return true;
}
bool StartObject() { cout << "StartObject()" << endl; return true; }
bool Key(const char* str, SizeType length, bool copy) {
cout << "Key(" << str << ", " << length << ", " << boolalpha << copy << ")" << endl;
return true;
}
bool EndObject(SizeType memberCount) { cout << "EndObject(" << memberCount << ")" << endl; return true; }
bool StartArray() { cout << "StartArray()" << endl; return true; }
bool EndArray(SizeType elementCount) { cout << "EndArray(" << elementCount << ")" << endl; return true; }
};
int main() {
const char json[] = " { \"hello\" : \"world\", \"t\" : true , \"f\" : false, \"n\": null, \"i\":123, \"pi\": 3.1416, \"a\":[1, 2, 3, 4] } ";
MyHandler handler;
Reader reader;
StringStream ss(json);
reader.Parse(ss, handler);
return 0;
}

View File

@ -1,36 +0,0 @@
#include "rapidjson/writer.h"
#include "rapidjson/stringbuffer.h"
#include <iostream>
using namespace rapidjson;
using namespace std;
int main() {
StringBuffer s;
Writer<StringBuffer> writer(s);
writer.StartObject(); // Between StartObject()/EndObject(),
writer.Key("hello"); // output a key,
writer.String("world"); // follow by a value.
writer.Key("t");
writer.Bool(true);
writer.Key("f");
writer.Bool(false);
writer.Key("n");
writer.Null();
writer.Key("i");
writer.Uint(123);
writer.Key("pi");
writer.Double(3.1416);
writer.Key("a");
writer.StartArray(); // Between StartArray()/EndArray(),
for (unsigned i = 0; i < 4; i++)
writer.Uint(i); // all values are elements of the array.
writer.EndArray();
writer.EndObject();
// {"hello":"world","t":true,"f":false,"n":null,"i":123,"pi":3.1416,"a":[0,1,2,3]}
cout << s.GetString() << endl;
return 0;
}

View File

@ -1,151 +0,0 @@
// Hello World example
// This example shows basic usage of DOM-style API.
#include "rapidjson/document.h" // rapidjson's DOM-style API
#include "rapidjson/prettywriter.h" // for stringify JSON
#include <cstdio>
using namespace rapidjson;
using namespace std;
int main(int, char*[]) {
////////////////////////////////////////////////////////////////////////////
// 1. Parse a JSON text string to a document.
const char json[] = " { \"hello\" : \"world\", \"t\" : true , \"f\" : false, \"n\": null, \"i\":123, \"pi\": 3.1416, \"a\":[1, 2, 3, 4] } ";
printf("Original JSON:\n %s\n", json);
Document document; // Default template parameter uses UTF8 and MemoryPoolAllocator.
#if 0
// "normal" parsing, decode strings to new buffers. Can use other input stream via ParseStream().
if (document.Parse(json).HasParseError())
return 1;
#else
// In-situ parsing, decode strings directly in the source string. Source must be string.
char buffer[sizeof(json)];
memcpy(buffer, json, sizeof(json));
if (document.ParseInsitu(buffer).HasParseError())
return 1;
#endif
printf("\nParsing to document succeeded.\n");
////////////////////////////////////////////////////////////////////////////
// 2. Access values in document.
printf("\nAccess values in document:\n");
assert(document.IsObject()); // Document is a JSON value represents the root of DOM. Root can be either an object or array.
assert(document.HasMember("hello"));
assert(document["hello"].IsString());
printf("hello = %s\n", document["hello"].GetString());
// Since version 0.2, you can use single lookup to check the existing of member and its value:
Value::MemberIterator hello = document.FindMember("hello");
assert(hello != document.MemberEnd());
assert(hello->value.IsString());
assert(strcmp("world", hello->value.GetString()) == 0);
(void)hello;
assert(document["t"].IsBool()); // JSON true/false are bool. Can also uses more specific function IsTrue().
printf("t = %s\n", document["t"].GetBool() ? "true" : "false");
assert(document["f"].IsBool());
printf("f = %s\n", document["f"].GetBool() ? "true" : "false");
printf("n = %s\n", document["n"].IsNull() ? "null" : "?");
assert(document["i"].IsNumber()); // Number is a JSON type, but C++ needs more specific type.
assert(document["i"].IsInt()); // In this case, IsUint()/IsInt64()/IsUInt64() also return true.
printf("i = %d\n", document["i"].GetInt()); // Alternative (int)document["i"]
assert(document["pi"].IsNumber());
assert(document["pi"].IsDouble());
printf("pi = %g\n", document["pi"].GetDouble());
{
const Value& a = document["a"]; // Using a reference for consecutive access is handy and faster.
assert(a.IsArray());
for (SizeType i = 0; i < a.Size(); i++) // rapidjson uses SizeType instead of size_t.
printf("a[%d] = %d\n", i, a[i].GetInt());
int y = a[0].GetInt();
(void)y;
// Iterating array with iterators
printf("a = ");
for (Value::ConstValueIterator itr = a.Begin(); itr != a.End(); ++itr)
printf("%d ", itr->GetInt());
printf("\n");
}
// Iterating object members
static const char* kTypeNames[] = { "Null", "False", "True", "Object", "Array", "String", "Number" };
for (Value::ConstMemberIterator itr = document.MemberBegin(); itr != document.MemberEnd(); ++itr)
printf("Type of member %s is %s\n", itr->name.GetString(), kTypeNames[itr->value.GetType()]);
////////////////////////////////////////////////////////////////////////////
// 3. Modify values in document.
// Change i to a bigger number
{
uint64_t f20 = 1; // compute factorial of 20
for (uint64_t j = 1; j <= 20; j++)
f20 *= j;
document["i"] = f20; // Alternate form: document["i"].SetUint64(f20)
assert(!document["i"].IsInt()); // No longer can be cast as int or uint.
}
// Adding values to array.
{
Value& a = document["a"]; // This time we uses non-const reference.
Document::AllocatorType& allocator = document.GetAllocator();
for (int i = 5; i <= 10; i++)
a.PushBack(i, allocator); // May look a bit strange, allocator is needed for potentially realloc. We normally uses the document's.
// Fluent API
a.PushBack("Lua", allocator).PushBack("Mio", allocator);
}
// Making string values.
// This version of SetString() just store the pointer to the string.
// So it is for literal and string that exists within value's life-cycle.
{
document["hello"] = "rapidjson"; // This will invoke strlen()
// Faster version:
// document["hello"].SetString("rapidjson", 9);
}
// This version of SetString() needs an allocator, which means it will allocate a new buffer and copy the the string into the buffer.
Value author;
{
char buffer2[10];
int len = sprintf(buffer2, "%s %s", "Milo", "Yip"); // synthetic example of dynamically created string.
author.SetString(buffer2, static_cast<SizeType>(len), document.GetAllocator());
// Shorter but slower version:
// document["hello"].SetString(buffer, document.GetAllocator());
// Constructor version:
// Value author(buffer, len, document.GetAllocator());
// Value author(buffer, document.GetAllocator());
memset(buffer2, 0, sizeof(buffer2)); // For demonstration purpose.
}
// Variable 'buffer' is unusable now but 'author' has already made a copy.
document.AddMember("author", author, document.GetAllocator());
assert(author.IsNull()); // Move semantic for assignment. After this variable is assigned as a member, the variable becomes null.
////////////////////////////////////////////////////////////////////////////
// 4. Stringify JSON
printf("\nModified JSON with reformatting:\n");
StringBuffer sb;
PrettyWriter<StringBuffer> writer(sb);
document.Accept(writer); // Accept() traverses the DOM and generates Handler events.
puts(sb.GetString());
return 0;
}

View File

@ -1,20 +0,0 @@
find_package(GTestSrc)
IF(GTESTSRC_FOUND)
enable_testing()
if (WIN32 AND (NOT CYGWIN) AND (NOT MINGW))
set(gtest_disable_pthreads ON)
set(gtest_force_shared_crt ON)
endif()
add_subdirectory(${GTEST_SOURCE_DIR} ${CMAKE_BINARY_DIR}/googletest)
include_directories(SYSTEM ${GTEST_INCLUDE_DIR})
set(TEST_LIBRARIES gtest gtest_main)
add_custom_target(tests ALL)
add_subdirectory(perftest)
add_subdirectory(unittest)
ENDIF(GTESTSRC_FOUND)

View File

@ -1,26 +0,0 @@
set(PERFTEST_SOURCES
misctest.cpp
perftest.cpp
platformtest.cpp
rapidjsontest.cpp
schematest.cpp)
add_executable(perftest ${PERFTEST_SOURCES})
target_link_libraries(perftest ${TEST_LIBRARIES})
add_dependencies(tests perftest)
find_program(CCACHE_FOUND ccache)
if(CCACHE_FOUND)
set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ccache)
set_property(GLOBAL PROPERTY RULE_LAUNCH_LINK ccache)
if (CMAKE_CXX_COMPILER_ID MATCHES "Clang")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Qunused-arguments -fcolor-diagnostics")
endif()
endif(CCACHE_FOUND)
IF(NOT (CMAKE_BUILD_TYPE STREQUAL "Debug"))
add_test(NAME perftest
COMMAND ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/perftest
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/bin)
ENDIF()

View File

@ -1,974 +0,0 @@
// Tencent is pleased to support the open source community by making RapidJSON available.
//
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
//
// Licensed under the MIT License (the "License"); you may not use this file except
// in compliance with the License. You may obtain a copy of the License at
//
// http://opensource.org/licenses/MIT
//
// Unless required by applicable law or agreed to in writing, software distributed
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
// specific language governing permissions and limitations under the License.
#include "perftest.h"
#if TEST_MISC
#define __STDC_FORMAT_MACROS
#include "rapidjson/stringbuffer.h"
#define protected public
#include "rapidjson/writer.h"
#undef private
class Misc : public PerfTest {
};
// Copyright (c) 2008-2010 Bjoern Hoehrmann <bjoern@hoehrmann.de>
// See http://bjoern.hoehrmann.de/utf-8/decoder/dfa/ for details.
#define UTF8_ACCEPT 0
#define UTF8_REJECT 12
static const unsigned char utf8d[] = {
// The first part of the table maps bytes to character classes that
// to reduce the size of the transition table and create bitmasks.
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
8,8,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
10,3,3,3,3,3,3,3,3,3,3,3,3,4,3,3, 11,6,6,6,5,8,8,8,8,8,8,8,8,8,8,8,
// The second part is a transition table that maps a combination
// of a state of the automaton and a character class to a state.
0,12,24,36,60,96,84,12,12,12,48,72, 12,12,12,12,12,12,12,12,12,12,12,12,
12, 0,12,12,12,12,12, 0,12, 0,12,12, 12,24,12,12,12,12,12,24,12,24,12,12,
12,12,12,12,12,12,12,24,12,12,12,12, 12,24,12,12,12,12,12,12,12,24,12,12,
12,12,12,12,12,12,12,36,12,36,12,12, 12,36,12,12,12,12,12,36,12,36,12,12,
12,36,12,12,12,12,12,12,12,12,12,12,
};
static unsigned inline decode(unsigned* state, unsigned* codep, unsigned byte) {
unsigned type = utf8d[byte];
*codep = (*state != UTF8_ACCEPT) ?
(byte & 0x3fu) | (*codep << 6) :
(0xff >> type) & (byte);
*state = utf8d[256 + *state + type];
return *state;
}
static bool IsUTF8(unsigned char* s) {
unsigned codepoint, state = 0;
while (*s)
decode(&state, &codepoint, *s++);
return state == UTF8_ACCEPT;
}
TEST_F(Misc, Hoehrmann_IsUTF8) {
for (size_t i = 0; i < kTrialCount; i++) {
EXPECT_TRUE(IsUTF8((unsigned char*)json_));
}
}
////////////////////////////////////////////////////////////////////////////////
// CountDecimalDigit: Count number of decimal places
inline unsigned CountDecimalDigit_naive(unsigned n) {
unsigned count = 1;
while (n >= 10) {
n /= 10;
count++;
}
return count;
}
inline unsigned CountDecimalDigit_enroll4(unsigned n) {
unsigned count = 1;
while (n >= 10000) {
n /= 10000u;
count += 4;
}
if (n < 10) return count;
if (n < 100) return count + 1;
if (n < 1000) return count + 2;
return count + 3;
}
inline unsigned CountDecimalDigit64_enroll4(uint64_t n) {
unsigned count = 1;
while (n >= 10000) {
n /= 10000u;
count += 4;
}
if (n < 10) return count;
if (n < 100) return count + 1;
if (n < 1000) return count + 2;
return count + 3;
}
inline unsigned CountDecimalDigit_fast(unsigned n) {
static const uint32_t powers_of_10[] = {
0,
10,
100,
1000,
10000,
100000,
1000000,
10000000,
100000000,
1000000000
};
#if defined(_M_IX86) || defined(_M_X64)
unsigned long i = 0;
_BitScanReverse(&i, n | 1);
uint32_t t = (i + 1) * 1233 >> 12;
#elif defined(__GNUC__)
uint32_t t = (32 - __builtin_clz(n | 1)) * 1233 >> 12;
#else
#error
#endif
return t - (n < powers_of_10[t]) + 1;
}
inline unsigned CountDecimalDigit64_fast(uint64_t n) {
static const uint64_t powers_of_10[] = {
0,
10,
100,
1000,
10000,
100000,
1000000,
10000000,
100000000,
1000000000,
10000000000,
100000000000,
1000000000000,
10000000000000,
100000000000000,
1000000000000000,
10000000000000000,
100000000000000000,
1000000000000000000,
10000000000000000000U
};
#if defined(_M_IX86)
uint64_t m = n | 1;
unsigned long i = 0;
if (_BitScanReverse(&i, m >> 32))
i += 32;
else
_BitScanReverse(&i, m & 0xFFFFFFFF);
uint32_t t = (i + 1) * 1233 >> 12;
#elif defined(_M_X64)
unsigned long i = 0;
_BitScanReverse64(&i, n | 1);
uint32_t t = (i + 1) * 1233 >> 12;
#elif defined(__GNUC__)
uint32_t t = (64 - __builtin_clzll(n | 1)) * 1233 >> 12;
#else
#error
#endif
return t - (n < powers_of_10[t]) + 1;
}
#if 0
// Exhaustive, very slow
TEST_F(Misc, CountDecimalDigit_Verify) {
unsigned i = 0;
do {
if (i % (65536 * 256) == 0)
printf("%u\n", i);
ASSERT_EQ(CountDecimalDigit_enroll4(i), CountDecimalDigit_fast(i));
i++;
} while (i != 0);
}
static const unsigned kDigits10Trial = 1000000000u;
TEST_F(Misc, CountDecimalDigit_naive) {
unsigned sum = 0;
for (unsigned i = 0; i < kDigits10Trial; i++)
sum += CountDecimalDigit_naive(i);
printf("%u\n", sum);
}
TEST_F(Misc, CountDecimalDigit_enroll4) {
unsigned sum = 0;
for (unsigned i = 0; i < kDigits10Trial; i++)
sum += CountDecimalDigit_enroll4(i);
printf("%u\n", sum);
}
TEST_F(Misc, CountDecimalDigit_fast) {
unsigned sum = 0;
for (unsigned i = 0; i < kDigits10Trial; i++)
sum += CountDecimalDigit_fast(i);
printf("%u\n", sum);
}
#endif
TEST_F(Misc, CountDecimalDigit64_VerifyFast) {
uint64_t i = 1, j;
do {
//printf("%" PRIu64 "\n", i);
ASSERT_EQ(CountDecimalDigit64_enroll4(i), CountDecimalDigit64_fast(i));
j = i;
i *= 3;
} while (j < i);
}
////////////////////////////////////////////////////////////////////////////////
// integer-to-string conversion
// https://gist.github.com/anonymous/7179097
static const int randval[] ={
936116, 369532, 453755, -72860, 209713, 268347, 435278, -360266, -416287, -182064,
-644712, 944969, 640463, -366588, 471577, -69401, -744294, -505829, 923883, 831785,
-601136, -636767, -437054, 591718, 100758, 231907, -719038, 973540, -605220, 506659,
-871653, 462533, 764843, -919138, 404305, -630931, -288711, -751454, -173726, -718208,
432689, -281157, 360737, 659827, 19174, -376450, 769984, -858198, 439127, 734703,
-683426, 7, 386135, 186997, -643900, -744422, -604708, -629545, 42313, -933592,
-635566, 182308, 439024, -367219, -73924, -516649, 421935, -470515, 413507, -78952,
-427917, -561158, 737176, 94538, 572322, 405217, 709266, -357278, -908099, -425447,
601119, 750712, -862285, -177869, 900102, 384877, 157859, -641680, 503738, -702558,
278225, 463290, 268378, -212840, 580090, 347346, -473985, -950968, -114547, -839893,
-738032, -789424, 409540, 493495, 432099, 119755, 905004, -174834, 338266, 234298,
74641, -965136, -754593, 685273, 466924, 920560, 385062, 796402, -67229, 994864,
376974, 299869, -647540, -128724, 469890, -163167, -547803, -743363, 486463, -621028,
612288, 27459, -514224, 126342, -66612, 803409, -777155, -336453, -284002, 472451,
342390, -163630, 908356, -456147, -825607, 268092, -974715, 287227, 227890, -524101,
616370, -782456, 922098, -624001, -813690, 171605, -192962, 796151, 707183, -95696,
-23163, -721260, 508892, 430715, 791331, 482048, -996102, 863274, 275406, -8279,
-556239, -902076, 268647, -818565, 260069, -798232, -172924, -566311, -806503, -885992,
813969, -78468, 956632, 304288, 494867, -508784, 381751, 151264, 762953, 76352,
594902, 375424, 271700, -743062, 390176, 924237, 772574, 676610, 435752, -153847,
3959, -971937, -294181, -538049, -344620, -170136, 19120, -703157, 868152, -657961,
-818631, 219015, -872729, -940001, -956570, 880727, -345910, 942913, -942271, -788115,
225294, 701108, -517736, -416071, 281940, 488730, 942698, 711494, 838382, -892302,
-533028, 103052, 528823, 901515, 949577, 159364, 718227, -241814, -733661, -462928,
-495829, 165170, 513580, -629188, -509571, -459083, 198437, 77198, -644612, 811276,
-422298, -860842, -52584, 920369, 686424, -530667, -243476, 49763, 345866, -411960,
-114863, 470810, -302860, 683007, -509080, 2, -174981, -772163, -48697, 447770,
-268246, 213268, 269215, 78810, -236340, -639140, -864323, 505113, -986569, -325215,
541859, 163070, -819998, -645161, -583336, 573414, 696417, -132375, 3, -294501,
320435, 682591, 840008, 351740, 426951, 609354, 898154, -943254, 227321, -859793,
-727993, 44137, -497965, -782239, 14955, -746080, -243366, 9837, -233083, 606507,
-995864, -615287, -994307, 602715, 770771, -315040, 610860, 446102, -307120, 710728,
-590392, -230474, -762625, -637525, 134963, -202700, -766902, -985541, 218163, 682009,
926051, 525156, -61195, 403211, -810098, 245539, -431733, 179998, -806533, 745943,
447597, 131973, -187130, 826019, 286107, -937230, -577419, 20254, 681802, -340500,
323080, 266283, -667617, 309656, 416386, 611863, 759991, -534257, 523112, -634892,
-169913, -204905, -909867, -882185, -944908, 741811, -717675, 967007, -317396, 407230,
-412805, 792905, 994873, 744793, -456797, 713493, 355232, 116900, -945199, 880539,
342505, -580824, -262273, 982968, -349497, -735488, 311767, -455191, 570918, 389734,
-958386, 10262, -99267, 155481, 304210, 204724, 704367, -144893, -233664, -671441,
896849, 408613, 762236, 322697, 981321, 688476, 13663, -970704, -379507, 896412,
977084, 348869, 875948, 341348, 318710, 512081, 6163, 669044, 833295, 811883,
708756, -802534, -536057, 608413, -389625, -694603, 541106, -110037, 720322, -540581,
645420, 32980, 62442, 510157, -981870, -87093, -325960, -500494, -718291, -67889,
991501, 374804, 769026, -978869, 294747, 714623, 413327, -199164, 671368, 804789,
-362507, 798196, -170790, -568895, -869379, 62020, -316693, -837793, 644994, -39341,
-417504, -243068, -957756, 99072, 622234, -739992, 225668, 8863, -505910, 82483,
-559244, 241572, 1315, -36175, -54990, 376813, -11, 162647, -688204, -486163,
-54934, -197470, 744223, -762707, 732540, 996618, 351561, -445933, -898491, 486531,
456151, 15276, 290186, -817110, -52995, 313046, -452533, -96267, 94470, -500176,
-818026, -398071, -810548, -143325, -819741, 1338, -897676, -101577, -855445, 37309,
285742, 953804, -777927, -926962, -811217, -936744, -952245, -802300, -490188, -964953,
-552279, 329142, -570048, -505756, 682898, -381089, -14352, 175138, 152390, -582268,
-485137, 717035, 805329, 239572, -730409, 209643, -184403, -385864, 675086, 819648,
629058, -527109, -488666, -171981, 532788, 552441, 174666, 984921, 766514, 758787,
716309, 338801, -978004, -412163, 876079, -734212, 789557, -160491, -522719, 56644,
-991, -286038, -53983, 663740, 809812, 919889, -717502, -137704, 220511, 184396,
-825740, -588447, 430870, 124309, 135956, 558662, -307087, -788055, -451328, 812260,
931601, 324347, -482989, -117858, -278861, 189068, -172774, 929057, 293787, 198161,
-342386, -47173, 906555, -759955, -12779, 777604, -97869, 899320, 927486, -25284,
-848550, 259450, -485856, -17820, 88, 171400, 235492, -326783, -340793, 886886,
112428, -246280, 5979, 648444, -114982, 991013, -56489, -9497, 419706, 632820,
-341664, 393926, -848977, -22538, 257307, 773731, -905319, 491153, 734883, -868212,
-951053, 644458, -580758, 764735, 584316, 297077, 28852, -397710, -953669, 201772,
879050, -198237, -588468, 448102, -116837, 770007, -231812, 642906, -582166, -885828,
9, 305082, -996577, 303559, 75008, -772956, -447960, 599825, -295552, 870739,
-386278, -950300, 485359, -457081, 629461, -850276, 550496, -451755, -620841, -11766,
-950137, 832337, 28711, -273398, -507197, 91921, -271360, -705991, -753220, -388968,
967945, 340434, -320883, -662793, -554617, -574568, 477946, -6148, -129519, 689217,
920020, -656315, -974523, -212525, 80921, -612532, 645096, 545655, 655713, -591631,
-307385, -816688, -618823, -113713, 526430, 673063, 735916, -809095, -850417, 639004,
432281, -388185, 270708, 860146, -39902, -786157, -258180, -246169, -966720, -264957,
548072, -306010, -57367, -635665, 933824, 70553, -989936, -488741, 72411, -452509,
529831, 956277, 449019, -577850, -360986, -803418, 48833, 296073, 203430, 609591,
715483, 470964, 658106, -718254, -96424, 790163, 334739, 181070, -373578, 5,
-435088, 329841, 330939, -256602, 394355, 912412, 231910, 927278, -661933, 788539,
-769664, -893274, -96856, 298205, 901043, -608122, -527430, 183618, -553963, -35246,
-393924, 948832, -483198, 594501, 35460, -407007, 93494, -336881, -634072, 984205,
-812161, 944664, -31062, 753872, 823933, -69566, 50445, 290147, 85134, 34706,
551902, 405202, -991246, -84642, 154341, 316432, -695101, -651588, -5030, 137564,
-294665, 332541, 528307, -90572, -344923, 523766, -758498, -968047, 339028, 494578,
593129, -725773, 31834, -718406, -208638, 159665, -2043, 673344, -442767, 75816,
755442, 769257, -158730, -410272, 691688, 589550, -878398, -184121, 460679, 346312,
294163, -544602, 653308, 254167, -276979, 52073, -892684, 887653, -41222, 983065,
-68258, -408799, -99069, -674069, -863635, -32890, 622757, -743862, 40872, -4837,
-967228, 522370, -903951, -818669, 524459, 514702, 925801, 20007, -299229, 579348,
626021, 430089, 348139, -562692, -607728, -130606, -928451, -424793, -458647, -448892,
-312230, 143337, 109746, 880042, -339658, -785614, 938995, 540916, 118429, 661351,
-402967, 404729, -40918, -976535, 743230, 713110, 440182, -381314, -499252, 74613,
193652, 912717, 491323, 583633, 324691, 459397, 281253, 195540, -2764, -888651,
892449, 132663, -478373, -430002, -314551, 527826, 247165, 557966, 554778, 481531,
-946634, 431685, -769059, -348371, 174046, 184597, -354867, 584422, 227390, -850397,
-542924, -849093, -737769, 325359, 736314, 269101, 767940, 674809, 81413, -447458,
445076, 189072, 906218, 502688, -718476, -863827, -731381, 100660, 623249, 710008,
572060, 922203, 685740, 55096, 263394, -243695, -353910, -516788, 388471, 455165,
844103, -643772, 363976, 268875, -899450, 104470, 104029, -238874, -274659, 732969,
-676443, 953291, -916289, -861849, -242344, 958083, -479593, -970395, 799831, 277841,
-243236, -283462, -201510, 166263, -259105, -575706, 878926, 891064, 895297, 655262,
-34807, -809833, -89281, 342585, 554920, 1, 902141, -333425, 139703, 852318,
-618438, 329498, -932596, -692836, -513372, 733656, -523411, 85779, 500478, -682697,
-502836, 138776, 156341, -420037, -557964, -556378, 710993, -50383, -877159, 916334,
132996, 583516, -603392, -111615, -12288, -780214, 476780, 123327, 137607, 519956,
745837, 17358, -158581, -53490
};
static const size_t randvalCount = sizeof(randval) / sizeof(randval[0]);
static const size_t kItoaTrialCount = 10000;
static const char digits[201] =
"0001020304050607080910111213141516171819"
"2021222324252627282930313233343536373839"
"4041424344454647484950515253545556575859"
"6061626364656667686970717273747576777879"
"8081828384858687888990919293949596979899";
// Prevent code being optimized out
//#define OUTPUT_LENGTH(length) printf("", length)
#define OUTPUT_LENGTH(length) printf("%u\n", (unsigned)length)
template<typename OutputStream>
class Writer1 {
public:
Writer1() : os_() {}
Writer1(OutputStream& os) : os_(&os) {}
void Reset(OutputStream& os) {
os_ = &os;
}
bool WriteInt(int i) {
if (i < 0) {
os_->Put('-');
i = -i;
}
return WriteUint((unsigned)i);
}
bool WriteUint(unsigned u) {
char buffer[10];
char *p = buffer;
do {
*p++ = char(u % 10) + '0';
u /= 10;
} while (u > 0);
do {
--p;
os_->Put(*p);
} while (p != buffer);
return true;
}
bool WriteInt64(int64_t i64) {
if (i64 < 0) {
os_->Put('-');
i64 = -i64;
}
WriteUint64((uint64_t)i64);
return true;
}
bool WriteUint64(uint64_t u64) {
char buffer[20];
char *p = buffer;
do {
*p++ = char(u64 % 10) + '0';
u64 /= 10;
} while (u64 > 0);
do {
--p;
os_->Put(*p);
} while (p != buffer);
return true;
}
private:
OutputStream* os_;
};
template<>
bool Writer1<rapidjson::StringBuffer>::WriteUint(unsigned u) {
char buffer[10];
char* p = buffer;
do {
*p++ = char(u % 10) + '0';
u /= 10;
} while (u > 0);
char* d = os_->Push(p - buffer);
do {
--p;
*d++ = *p;
} while (p != buffer);
return true;
}
// Using digits LUT to reduce divsion/modulo
template<typename OutputStream>
class Writer2 {
public:
Writer2() : os_() {}
Writer2(OutputStream& os) : os_(&os) {}
void Reset(OutputStream& os) {
os_ = &os;
}
bool WriteInt(int i) {
if (i < 0) {
os_->Put('-');
i = -i;
}
return WriteUint((unsigned)i);
}
bool WriteUint(unsigned u) {
char buffer[10];
char* p = buffer;
while (u >= 100) {
const unsigned i = (u % 100) << 1;
u /= 100;
*p++ = digits[i + 1];
*p++ = digits[i];
}
if (u < 10)
*p++ = char(u) + '0';
else {
const unsigned i = u << 1;
*p++ = digits[i + 1];
*p++ = digits[i];
}
do {
--p;
os_->Put(*p);
} while (p != buffer);
return true;
}
bool WriteInt64(int64_t i64) {
if (i64 < 0) {
os_->Put('-');
i64 = -i64;
}
WriteUint64((uint64_t)i64);
return true;
}
bool WriteUint64(uint64_t u64) {
char buffer[20];
char* p = buffer;
while (u64 >= 100) {
const unsigned i = static_cast<unsigned>(u64 % 100) << 1;
u64 /= 100;
*p++ = digits[i + 1];
*p++ = digits[i];
}
if (u64 < 10)
*p++ = char(u64) + '0';
else {
const unsigned i = static_cast<unsigned>(u64) << 1;
*p++ = digits[i + 1];
*p++ = digits[i];
}
do {
--p;
os_->Put(*p);
} while (p != buffer);
return true;
}
private:
OutputStream* os_;
};
// First pass to count digits
template<typename OutputStream>
class Writer3 {
public:
Writer3() : os_() {}
Writer3(OutputStream& os) : os_(&os) {}
void Reset(OutputStream& os) {
os_ = &os;
}
bool WriteInt(int i) {
if (i < 0) {
os_->Put('-');
i = -i;
}
return WriteUint((unsigned)i);
}
bool WriteUint(unsigned u) {
char buffer[10];
char *p = buffer;
do {
*p++ = char(u % 10) + '0';
u /= 10;
} while (u > 0);
do {
--p;
os_->Put(*p);
} while (p != buffer);
return true;
}
bool WriteInt64(int64_t i64) {
if (i64 < 0) {
os_->Put('-');
i64 = -i64;
}
WriteUint64((uint64_t)i64);
return true;
}
bool WriteUint64(uint64_t u64) {
char buffer[20];
char *p = buffer;
do {
*p++ = char(u64 % 10) + '0';
u64 /= 10;
} while (u64 > 0);
do {
--p;
os_->Put(*p);
} while (p != buffer);
return true;
}
private:
void WriteUintReverse(char* d, unsigned u) {
do {
*--d = char(u % 10) + '0';
u /= 10;
} while (u > 0);
}
void WriteUint64Reverse(char* d, uint64_t u) {
do {
*--d = char(u % 10) + '0';
u /= 10;
} while (u > 0);
}
OutputStream* os_;
};
template<>
inline bool Writer3<rapidjson::StringBuffer>::WriteUint(unsigned u) {
unsigned digit = CountDecimalDigit_fast(u);
WriteUintReverse(os_->Push(digit) + digit, u);
return true;
}
template<>
inline bool Writer3<rapidjson::InsituStringStream>::WriteUint(unsigned u) {
unsigned digit = CountDecimalDigit_fast(u);
WriteUintReverse(os_->Push(digit) + digit, u);
return true;
}
template<>
inline bool Writer3<rapidjson::StringBuffer>::WriteUint64(uint64_t u) {
unsigned digit = CountDecimalDigit64_fast(u);
WriteUint64Reverse(os_->Push(digit) + digit, u);
return true;
}
template<>
inline bool Writer3<rapidjson::InsituStringStream>::WriteUint64(uint64_t u) {
unsigned digit = CountDecimalDigit64_fast(u);
WriteUint64Reverse(os_->Push(digit) + digit, u);
return true;
}
// Using digits LUT to reduce divsion/modulo, two passes
template<typename OutputStream>
class Writer4 {
public:
Writer4() : os_() {}
Writer4(OutputStream& os) : os_(&os) {}
void Reset(OutputStream& os) {
os_ = &os;
}
bool WriteInt(int i) {
if (i < 0) {
os_->Put('-');
i = -i;
}
return WriteUint((unsigned)i);
}
bool WriteUint(unsigned u) {
char buffer[10];
char* p = buffer;
while (u >= 100) {
const unsigned i = (u % 100) << 1;
u /= 100;
*p++ = digits[i + 1];
*p++ = digits[i];
}
if (u < 10)
*p++ = char(u) + '0';
else {
const unsigned i = u << 1;
*p++ = digits[i + 1];
*p++ = digits[i];
}
do {
--p;
os_->Put(*p);
} while (p != buffer);
return true;
}
bool WriteInt64(int64_t i64) {
if (i64 < 0) {
os_->Put('-');
i64 = -i64;
}
WriteUint64((uint64_t)i64);
return true;
}
bool WriteUint64(uint64_t u64) {
char buffer[20];
char* p = buffer;
while (u64 >= 100) {
const unsigned i = static_cast<unsigned>(u64 % 100) << 1;
u64 /= 100;
*p++ = digits[i + 1];
*p++ = digits[i];
}
if (u64 < 10)
*p++ = char(u64) + '0';
else {
const unsigned i = static_cast<unsigned>(u64) << 1;
*p++ = digits[i + 1];
*p++ = digits[i];
}
do {
--p;
os_->Put(*p);
} while (p != buffer);
return true;
}
private:
void WriteUintReverse(char* d, unsigned u) {
while (u >= 100) {
const unsigned i = (u % 100) << 1;
u /= 100;
*--d = digits[i + 1];
*--d = digits[i];
}
if (u < 10) {
*--d = char(u) + '0';
}
else {
const unsigned i = u << 1;
*--d = digits[i + 1];
*--d = digits[i];
}
}
void WriteUint64Reverse(char* d, uint64_t u) {
while (u >= 100) {
const unsigned i = (u % 100) << 1;
u /= 100;
*--d = digits[i + 1];
*--d = digits[i];
}
if (u < 10) {
*--d = char(u) + '0';
}
else {
const unsigned i = u << 1;
*--d = digits[i + 1];
*--d = digits[i];
}
}
OutputStream* os_;
};
template<>
inline bool Writer4<rapidjson::StringBuffer>::WriteUint(unsigned u) {
unsigned digit = CountDecimalDigit_fast(u);
WriteUintReverse(os_->Push(digit) + digit, u);
return true;
}
template<>
inline bool Writer4<rapidjson::InsituStringStream>::WriteUint(unsigned u) {
unsigned digit = CountDecimalDigit_fast(u);
WriteUintReverse(os_->Push(digit) + digit, u);
return true;
}
template<>
inline bool Writer4<rapidjson::StringBuffer>::WriteUint64(uint64_t u) {
unsigned digit = CountDecimalDigit64_fast(u);
WriteUint64Reverse(os_->Push(digit) + digit, u);
return true;
}
template<>
inline bool Writer4<rapidjson::InsituStringStream>::WriteUint64(uint64_t u) {
unsigned digit = CountDecimalDigit64_fast(u);
WriteUint64Reverse(os_->Push(digit) + digit, u);
return true;
}
template <typename Writer>
void itoa_Writer_StringBufferVerify() {
rapidjson::StringBuffer sb;
Writer writer(sb);
for (size_t j = 0; j < randvalCount; j++) {
char buffer[32];
sprintf(buffer, "%d", randval[j]);
writer.WriteInt(randval[j]);
ASSERT_STREQ(buffer, sb.GetString());
sb.Clear();
}
}
template <typename Writer>
void itoa_Writer_InsituStringStreamVerify() {
Writer writer;
for (size_t j = 0; j < randvalCount; j++) {
char buffer[32];
sprintf(buffer, "%d", randval[j]);
char buffer2[32];
rapidjson::InsituStringStream ss(buffer2);
writer.Reset(ss);
char* begin = ss.PutBegin();
writer.WriteInt(randval[j]);
ss.Put('\0');
ss.PutEnd(begin);
ASSERT_STREQ(buffer, buffer2);
}
}
template <typename Writer>
void itoa_Writer_StringBuffer() {
size_t length = 0;
rapidjson::StringBuffer sb;
Writer writer(sb);
for (size_t i = 0; i < kItoaTrialCount; i++) {
for (size_t j = 0; j < randvalCount; j++) {
writer.WriteInt(randval[j]);
length += sb.GetSize();
sb.Clear();
}
}
OUTPUT_LENGTH(length);
}
template <typename Writer>
void itoa_Writer_InsituStringStream() {
size_t length = 0;
char buffer[32];
Writer writer;
for (size_t i = 0; i < kItoaTrialCount; i++) {
for (size_t j = 0; j < randvalCount; j++) {
rapidjson::InsituStringStream ss(buffer);
writer.Reset(ss);
char* begin = ss.PutBegin();
writer.WriteInt(randval[j]);
length += ss.PutEnd(begin);
}
}
OUTPUT_LENGTH(length);
};
template <typename Writer>
void itoa64_Writer_StringBufferVerify() {
rapidjson::StringBuffer sb;
Writer writer(sb);
for (size_t j = 0; j < randvalCount; j++) {
char buffer[32];
int64_t x = randval[j] * randval[j];
sprintf(buffer, "%" PRIi64, x);
writer.WriteInt64(x);
ASSERT_STREQ(buffer, sb.GetString());
sb.Clear();
}
}
template <typename Writer>
void itoa64_Writer_InsituStringStreamVerify() {
Writer writer;
for (size_t j = 0; j < randvalCount; j++) {
char buffer[32];
int64_t x = randval[j] * randval[j];
sprintf(buffer, "%" PRIi64, x);
char buffer2[32];
rapidjson::InsituStringStream ss(buffer2);
writer.Reset(ss);
char* begin = ss.PutBegin();
writer.WriteInt64(x);
ss.Put('\0');
ss.PutEnd(begin);
ASSERT_STREQ(buffer, buffer2);
}
}
template <typename Writer>
void itoa64_Writer_StringBuffer() {
size_t length = 0;
rapidjson::StringBuffer sb;
Writer writer(sb);
for (size_t i = 0; i < kItoaTrialCount; i++) {
for (size_t j = 0; j < randvalCount; j++) {
writer.WriteInt64(randval[j] * randval[j]);
length += sb.GetSize();
sb.Clear();
}
}
OUTPUT_LENGTH(length);
}
template <typename Writer>
void itoa64_Writer_InsituStringStream() {
size_t length = 0;
char buffer[32];
Writer writer;
for (size_t i = 0; i < kItoaTrialCount; i++) {
for (size_t j = 0; j < randvalCount; j++) {
rapidjson::InsituStringStream ss(buffer);
writer.Reset(ss);
char* begin = ss.PutBegin();
writer.WriteInt64(randval[j] * randval[j]);
length += ss.PutEnd(begin);
}
}
OUTPUT_LENGTH(length);
};
// Full specialization for InsituStringStream to prevent memory copying
// (normally we will not use InsituStringStream for writing, just for testing)
namespace rapidjson {
template<>
bool rapidjson::Writer<InsituStringStream>::WriteInt(int i) {
char *buffer = os_->Push(11);
const char* end = internal::i32toa(i, buffer);
os_->Pop(11 - (end - buffer));
return true;
}
template<>
bool Writer<InsituStringStream>::WriteUint(unsigned u) {
char *buffer = os_->Push(10);
const char* end = internal::u32toa(u, buffer);
os_->Pop(10 - (end - buffer));
return true;
}
template<>
bool Writer<InsituStringStream>::WriteInt64(int64_t i64) {
char *buffer = os_->Push(21);
const char* end = internal::i64toa(i64, buffer);
os_->Pop(21 - (end - buffer));
return true;
}
template<>
bool Writer<InsituStringStream>::WriteUint64(uint64_t u) {
char *buffer = os_->Push(20);
const char* end = internal::u64toa(u, buffer);
os_->Pop(20 - (end - buffer));
return true;
}
} // namespace rapidjson
TEST_F(Misc, itoa_Writer_StringBufferVerify) { itoa_Writer_StringBufferVerify<rapidjson::Writer<rapidjson::StringBuffer> >(); }
TEST_F(Misc, itoa_Writer1_StringBufferVerify) { itoa_Writer_StringBufferVerify<Writer1<rapidjson::StringBuffer> >(); }
TEST_F(Misc, itoa_Writer2_StringBufferVerify) { itoa_Writer_StringBufferVerify<Writer2<rapidjson::StringBuffer> >(); }
TEST_F(Misc, itoa_Writer3_StringBufferVerify) { itoa_Writer_StringBufferVerify<Writer3<rapidjson::StringBuffer> >(); }
TEST_F(Misc, itoa_Writer4_StringBufferVerify) { itoa_Writer_StringBufferVerify<Writer4<rapidjson::StringBuffer> >(); }
TEST_F(Misc, itoa_Writer_InsituStringStreamVerify) { itoa_Writer_InsituStringStreamVerify<rapidjson::Writer<rapidjson::InsituStringStream> >(); }
TEST_F(Misc, itoa_Writer1_InsituStringStreamVerify) { itoa_Writer_InsituStringStreamVerify<Writer1<rapidjson::InsituStringStream> >(); }
TEST_F(Misc, itoa_Writer2_InsituStringStreamVerify) { itoa_Writer_InsituStringStreamVerify<Writer2<rapidjson::InsituStringStream> >(); }
TEST_F(Misc, itoa_Writer3_InsituStringStreamVerify) { itoa_Writer_InsituStringStreamVerify<Writer3<rapidjson::InsituStringStream> >(); }
TEST_F(Misc, itoa_Writer4_InsituStringStreamVerify) { itoa_Writer_InsituStringStreamVerify<Writer4<rapidjson::InsituStringStream> >(); }
TEST_F(Misc, itoa_Writer_StringBuffer) { itoa_Writer_StringBuffer<rapidjson::Writer<rapidjson::StringBuffer> >(); }
TEST_F(Misc, itoa_Writer1_StringBuffer) { itoa_Writer_StringBuffer<Writer1<rapidjson::StringBuffer> >(); }
TEST_F(Misc, itoa_Writer2_StringBuffer) { itoa_Writer_StringBuffer<Writer2<rapidjson::StringBuffer> >(); }
TEST_F(Misc, itoa_Writer3_StringBuffer) { itoa_Writer_StringBuffer<Writer3<rapidjson::StringBuffer> >(); }
TEST_F(Misc, itoa_Writer4_StringBuffer) { itoa_Writer_StringBuffer<Writer4<rapidjson::StringBuffer> >(); }
TEST_F(Misc, itoa_Writer_InsituStringStream) { itoa_Writer_InsituStringStream<rapidjson::Writer<rapidjson::InsituStringStream> >(); }
TEST_F(Misc, itoa_Writer1_InsituStringStream) { itoa_Writer_InsituStringStream<Writer1<rapidjson::InsituStringStream> >(); }
TEST_F(Misc, itoa_Writer2_InsituStringStream) { itoa_Writer_InsituStringStream<Writer2<rapidjson::InsituStringStream> >(); }
TEST_F(Misc, itoa_Writer3_InsituStringStream) { itoa_Writer_InsituStringStream<Writer3<rapidjson::InsituStringStream> >(); }
TEST_F(Misc, itoa_Writer4_InsituStringStream) { itoa_Writer_InsituStringStream<Writer4<rapidjson::InsituStringStream> >(); }
TEST_F(Misc, itoa64_Writer_StringBufferVerify) { itoa64_Writer_StringBufferVerify<rapidjson::Writer<rapidjson::StringBuffer> >(); }
TEST_F(Misc, itoa64_Writer1_StringBufferVerify) { itoa64_Writer_StringBufferVerify<Writer1<rapidjson::StringBuffer> >(); }
TEST_F(Misc, itoa64_Writer2_StringBufferVerify) { itoa64_Writer_StringBufferVerify<Writer2<rapidjson::StringBuffer> >(); }
TEST_F(Misc, itoa64_Writer3_StringBufferVerify) { itoa64_Writer_StringBufferVerify<Writer3<rapidjson::StringBuffer> >(); }
TEST_F(Misc, itoa64_Writer4_StringBufferVerify) { itoa64_Writer_StringBufferVerify<Writer4<rapidjson::StringBuffer> >(); }
TEST_F(Misc, itoa64_Writer_InsituStringStreamVerify) { itoa64_Writer_InsituStringStreamVerify<rapidjson::Writer<rapidjson::InsituStringStream> >(); }
TEST_F(Misc, itoa64_Writer1_InsituStringStreamVerify) { itoa64_Writer_InsituStringStreamVerify<Writer1<rapidjson::InsituStringStream> >(); }
TEST_F(Misc, itoa64_Writer2_InsituStringStreamVerify) { itoa64_Writer_InsituStringStreamVerify<Writer2<rapidjson::InsituStringStream> >(); }
TEST_F(Misc, itoa64_Writer3_InsituStringStreamVerify) { itoa64_Writer_InsituStringStreamVerify<Writer3<rapidjson::InsituStringStream> >(); }
TEST_F(Misc, itoa64_Writer4_InsituStringStreamVerify) { itoa64_Writer_InsituStringStreamVerify<Writer4<rapidjson::InsituStringStream> >(); }
TEST_F(Misc, itoa64_Writer_StringBuffer) { itoa64_Writer_StringBuffer<rapidjson::Writer<rapidjson::StringBuffer> >(); }
TEST_F(Misc, itoa64_Writer1_StringBuffer) { itoa64_Writer_StringBuffer<Writer1<rapidjson::StringBuffer> >(); }
TEST_F(Misc, itoa64_Writer2_StringBuffer) { itoa64_Writer_StringBuffer<Writer2<rapidjson::StringBuffer> >(); }
TEST_F(Misc, itoa64_Writer3_StringBuffer) { itoa64_Writer_StringBuffer<Writer3<rapidjson::StringBuffer> >(); }
TEST_F(Misc, itoa64_Writer4_StringBuffer) { itoa64_Writer_StringBuffer<Writer4<rapidjson::StringBuffer> >(); }
TEST_F(Misc, itoa64_Writer_InsituStringStream) { itoa64_Writer_InsituStringStream<rapidjson::Writer<rapidjson::InsituStringStream> >(); }
TEST_F(Misc, itoa64_Writer1_InsituStringStream) { itoa64_Writer_InsituStringStream<Writer1<rapidjson::InsituStringStream> >(); }
TEST_F(Misc, itoa64_Writer2_InsituStringStream) { itoa64_Writer_InsituStringStream<Writer2<rapidjson::InsituStringStream> >(); }
TEST_F(Misc, itoa64_Writer3_InsituStringStream) { itoa64_Writer_InsituStringStream<Writer3<rapidjson::InsituStringStream> >(); }
TEST_F(Misc, itoa64_Writer4_InsituStringStream) { itoa64_Writer_InsituStringStream<Writer4<rapidjson::InsituStringStream> >(); }
#endif // TEST_MISC

View File

@ -1,24 +0,0 @@
// Tencent is pleased to support the open source community by making RapidJSON available.
//
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
//
// Licensed under the MIT License (the "License"); you may not use this file except
// in compliance with the License. You may obtain a copy of the License at
//
// http://opensource.org/licenses/MIT
//
// Unless required by applicable law or agreed to in writing, software distributed
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
// specific language governing permissions and limitations under the License.
#include "perftest.h"
int main(int argc, char **argv) {
#if _MSC_VER
_CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );
//void *testWhetherMemoryLeakDetectionWorks = malloc(1);
#endif
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}

View File

@ -1,182 +0,0 @@
// Tencent is pleased to support the open source community by making RapidJSON available.
//
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
//
// Licensed under the MIT License (the "License"); you may not use this file except
// in compliance with the License. You may obtain a copy of the License at
//
// http://opensource.org/licenses/MIT
//
// Unless required by applicable law or agreed to in writing, software distributed
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
// specific language governing permissions and limitations under the License.
#ifndef PERFTEST_H_
#define PERFTEST_H_
#define TEST_RAPIDJSON 1
#define TEST_PLATFORM 0
#define TEST_MISC 0
#define TEST_VERSION_CODE(x,y,z) \
(((x)*100000) + ((y)*100) + (z))
// __SSE2__ and __SSE4_2__ are recognized by gcc, clang, and the Intel compiler.
// We use -march=native with gmake to enable -msse2 and -msse4.2, if supported.
#if defined(__SSE4_2__)
# define RAPIDJSON_SSE42
#elif defined(__SSE2__)
# define RAPIDJSON_SSE2
#endif
#define RAPIDJSON_HAS_STDSTRING 1
////////////////////////////////////////////////////////////////////////////////
// Google Test
#ifdef __cplusplus
// gtest indirectly included inttypes.h, without __STDC_CONSTANT_MACROS.
#ifndef __STDC_CONSTANT_MACROS
# define __STDC_CONSTANT_MACROS 1 // required by C++ standard
#endif
#if defined(__clang__) || defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 2))
#if defined(__clang__) || (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
#pragma GCC diagnostic push
#endif
#pragma GCC diagnostic ignored "-Weffc++"
#endif
#include "gtest/gtest.h"
#if defined(__clang__) || defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
#pragma GCC diagnostic pop
#endif
#ifdef _MSC_VER
#define _CRTDBG_MAP_ALLOC
#include <crtdbg.h>
#pragma warning(disable : 4996) // 'function': was declared deprecated
#endif
//! Base class for all performance tests
class PerfTest : public ::testing::Test {
public:
PerfTest() : filename_(), json_(), length_(), whitespace_(), whitespace_length_() {}
virtual void SetUp() {
{
const char *paths[] = {
"data/sample.json",
"bin/data/sample.json",
"../bin/data/sample.json",
"../../bin/data/sample.json",
"../../../bin/data/sample.json"
};
FILE *fp = 0;
for (size_t i = 0; i < sizeof(paths) / sizeof(paths[0]); i++) {
fp = fopen(filename_ = paths[i], "rb");
if (fp)
break;
}
ASSERT_TRUE(fp != 0);
fseek(fp, 0, SEEK_END);
length_ = (size_t)ftell(fp);
fseek(fp, 0, SEEK_SET);
json_ = (char*)malloc(length_ + 1);
ASSERT_EQ(length_, fread(json_, 1, length_, fp));
json_[length_] = '\0';
fclose(fp);
}
// whitespace test
{
whitespace_length_ = 1024 * 1024;
whitespace_ = (char *)malloc(whitespace_length_ + 4);
char *p = whitespace_;
for (size_t i = 0; i < whitespace_length_; i += 4) {
*p++ = ' ';
*p++ = '\n';
*p++ = '\r';
*p++ = '\t';
}
*p++ = '[';
*p++ = '0';
*p++ = ']';
*p++ = '\0';
}
// types test
{
const char *typespaths[] = {
"data/types",
"bin/types",
"../bin/types",
"../../bin/types/",
"../../../bin/types"
};
const char* typesfilenames[] = {
"booleans.json",
"floats.json",
"guids.json",
"integers.json",
"mixed.json",
"nulls.json",
"paragraphs.json"
};
for (size_t j = 0; j < sizeof(typesfilenames) / sizeof(typesfilenames[0]); j++) {
types_[j] = 0;
for (size_t i = 0; i < sizeof(typespaths) / sizeof(typespaths[0]); i++) {
char filename[256];
sprintf(filename, "%s/%s", typespaths[i], typesfilenames[j]);
if (FILE* fp = fopen(filename, "rb")) {
fseek(fp, 0, SEEK_END);
typesLength_[j] = (size_t)ftell(fp);
fseek(fp, 0, SEEK_SET);
types_[j] = (char*)malloc(typesLength_[j] + 1);
ASSERT_EQ(typesLength_[j], fread(types_[j], 1, typesLength_[j], fp));
types_[j][typesLength_[j]] = '\0';
fclose(fp);
break;
}
}
}
}
}
virtual void TearDown() {
free(json_);
free(whitespace_);
json_ = 0;
whitespace_ = 0;
for (size_t i = 0; i < 7; i++) {
free(types_[i]);
types_[i] = 0;
}
}
private:
PerfTest(const PerfTest&);
PerfTest& operator=(const PerfTest&);
protected:
const char* filename_;
char *json_;
size_t length_;
char *whitespace_;
size_t whitespace_length_;
char *types_[7];
size_t typesLength_[7];
static const size_t kTrialCount = 1000;
};
#endif // __cplusplus
#endif // PERFTEST_H_

View File

@ -1,166 +0,0 @@
// Tencent is pleased to support the open source community by making RapidJSON available.
//
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
//
// Licensed under the MIT License (the "License"); you may not use this file except
// in compliance with the License. You may obtain a copy of the License at
//
// http://opensource.org/licenses/MIT
//
// Unless required by applicable law or agreed to in writing, software distributed
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
// specific language governing permissions and limitations under the License.
#include "perftest.h"
// This file is for giving the performance characteristics of the platform (compiler/OS/CPU).
#if TEST_PLATFORM
#include <cmath>
#include <fcntl.h>
// Windows
#ifdef _WIN32
#include <windows.h>
#endif
// UNIX
#if defined(unix) || defined(__unix__) || defined(__unix)
#include <unistd.h>
#ifdef _POSIX_MAPPED_FILES
#include <sys/mman.h>
#endif
#endif
class Platform : public PerfTest {
public:
virtual void SetUp() {
PerfTest::SetUp();
// temp buffer for testing
temp_ = (char *)malloc(length_ + 1);
memcpy(temp_, json_, length_);
checkSum_ = CheckSum();
}
char CheckSum() {
char c = 0;
for (size_t i = 0; i < length_; ++i)
c += temp_[i];
return c;
}
virtual void TearDown() {
PerfTest::TearDown();
free(temp_);
}
protected:
char *temp_;
char checkSum_;
};
TEST_F(Platform, CheckSum) {
for (int i = 0; i < kTrialCount; i++)
EXPECT_EQ(checkSum_, CheckSum());
}
TEST_F(Platform, strlen) {
for (int i = 0; i < kTrialCount; i++) {
size_t l = strlen(json_);
EXPECT_EQ(length_, l);
}
}
TEST_F(Platform, memcmp) {
for (int i = 0; i < kTrialCount; i++) {
EXPECT_EQ(0, memcmp(temp_, json_, length_));
}
}
TEST_F(Platform, pow) {
double sum = 0;
for (int i = 0; i < kTrialCount * kTrialCount; i++)
sum += pow(10.0, i & 255);
EXPECT_GT(sum, 0.0);
}
TEST_F(Platform, Whitespace_strlen) {
for (int i = 0; i < kTrialCount; i++) {
size_t l = strlen(whitespace_);
EXPECT_GT(l, whitespace_length_);
}
}
TEST_F(Platform, Whitespace_strspn) {
for (int i = 0; i < kTrialCount; i++) {
size_t l = strspn(whitespace_, " \n\r\t");
EXPECT_EQ(whitespace_length_, l);
}
}
TEST_F(Platform, fread) {
for (int i = 0; i < kTrialCount; i++) {
FILE *fp = fopen(filename_, "rb");
ASSERT_EQ(length_, fread(temp_, 1, length_, fp));
EXPECT_EQ(checkSum_, CheckSum());
fclose(fp);
}
}
#ifdef _MSC_VER
TEST_F(Platform, read) {
for (int i = 0; i < kTrialCount; i++) {
int fd = _open(filename_, _O_BINARY | _O_RDONLY);
ASSERT_NE(-1, fd);
ASSERT_EQ(length_, _read(fd, temp_, length_));
EXPECT_EQ(checkSum_, CheckSum());
_close(fd);
}
}
#else
TEST_F(Platform, read) {
for (int i = 0; i < kTrialCount; i++) {
int fd = open(filename_, O_RDONLY);
ASSERT_NE(-1, fd);
ASSERT_EQ(length_, read(fd, temp_, length_));
EXPECT_EQ(checkSum_, CheckSum());
close(fd);
}
}
#endif
#ifdef _WIN32
TEST_F(Platform, MapViewOfFile) {
for (int i = 0; i < kTrialCount; i++) {
HANDLE file = CreateFile(filename_, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
ASSERT_NE(INVALID_HANDLE_VALUE, file);
HANDLE mapObject = CreateFileMapping(file, NULL, PAGE_READONLY, 0, length_, NULL);
ASSERT_NE(INVALID_HANDLE_VALUE, mapObject);
void *p = MapViewOfFile(mapObject, FILE_MAP_READ, 0, 0, length_);
ASSERT_TRUE(p != NULL);
EXPECT_EQ(checkSum_, CheckSum());
ASSERT_TRUE(UnmapViewOfFile(p) == TRUE);
ASSERT_TRUE(CloseHandle(mapObject) == TRUE);
ASSERT_TRUE(CloseHandle(file) == TRUE);
}
}
#endif
#ifdef _POSIX_MAPPED_FILES
TEST_F(Platform, mmap) {
for (int i = 0; i < kTrialCount; i++) {
int fd = open(filename_, O_RDONLY);
ASSERT_NE(-1, fd);
void *p = mmap(NULL, length_, PROT_READ, MAP_PRIVATE, fd, 0);
ASSERT_TRUE(p != NULL);
EXPECT_EQ(checkSum_, CheckSum());
munmap(p, length_);
close(fd);
}
}
#endif
#endif // TEST_PLATFORM

View File

@ -1,441 +0,0 @@
// Tencent is pleased to support the open source community by making RapidJSON available.
//
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
//
// Licensed under the MIT License (the "License"); you may not use this file except
// in compliance with the License. You may obtain a copy of the License at
//
// http://opensource.org/licenses/MIT
//
// Unless required by applicable law or agreed to in writing, software distributed
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
// specific language governing permissions and limitations under the License.
#include "perftest.h"
#if TEST_RAPIDJSON
#include "rapidjson/rapidjson.h"
#include "rapidjson/document.h"
#include "rapidjson/prettywriter.h"
#include "rapidjson/stringbuffer.h"
#include "rapidjson/filereadstream.h"
#include "rapidjson/encodedstream.h"
#include "rapidjson/memorystream.h"
#ifdef RAPIDJSON_SSE2
#define SIMD_SUFFIX(name) name##_SSE2
#elif defined(RAPIDJSON_SSE42)
#define SIMD_SUFFIX(name) name##_SSE42
#else
#define SIMD_SUFFIX(name) name
#endif
using namespace rapidjson;
class RapidJson : public PerfTest {
public:
RapidJson() : temp_(), doc_() {}
virtual void SetUp() {
PerfTest::SetUp();
// temp buffer for insitu parsing.
temp_ = (char *)malloc(length_ + 1);
// Parse as a document
EXPECT_FALSE(doc_.Parse(json_).HasParseError());
for (size_t i = 0; i < 7; i++)
EXPECT_FALSE(typesDoc_[i].Parse(types_[i]).HasParseError());
}
virtual void TearDown() {
PerfTest::TearDown();
free(temp_);
}
private:
RapidJson(const RapidJson&);
RapidJson& operator=(const RapidJson&);
protected:
char *temp_;
Document doc_;
Document typesDoc_[7];
};
TEST_F(RapidJson, SIMD_SUFFIX(ReaderParseInsitu_DummyHandler)) {
for (size_t i = 0; i < kTrialCount; i++) {
memcpy(temp_, json_, length_ + 1);
InsituStringStream s(temp_);
BaseReaderHandler<> h;
Reader reader;
EXPECT_TRUE(reader.Parse<kParseInsituFlag>(s, h));
}
}
TEST_F(RapidJson, SIMD_SUFFIX(ReaderParseInsitu_DummyHandler_ValidateEncoding)) {
for (size_t i = 0; i < kTrialCount; i++) {
memcpy(temp_, json_, length_ + 1);
InsituStringStream s(temp_);
BaseReaderHandler<> h;
Reader reader;
EXPECT_TRUE(reader.Parse<kParseInsituFlag | kParseValidateEncodingFlag>(s, h));
}
}
TEST_F(RapidJson, SIMD_SUFFIX(ReaderParse_DummyHandler)) {
for (size_t i = 0; i < kTrialCount; i++) {
StringStream s(json_);
BaseReaderHandler<> h;
Reader reader;
EXPECT_TRUE(reader.Parse(s, h));
}
}
#define TEST_TYPED(index, Name)\
TEST_F(RapidJson, SIMD_SUFFIX(ReaderParse_DummyHandler_##Name)) {\
for (size_t i = 0; i < kTrialCount * 10; i++) {\
StringStream s(types_[index]);\
BaseReaderHandler<> h;\
Reader reader;\
EXPECT_TRUE(reader.Parse(s, h));\
}\
}\
TEST_F(RapidJson, SIMD_SUFFIX(ReaderParseInsitu_DummyHandler_##Name)) {\
for (size_t i = 0; i < kTrialCount * 10; i++) {\
memcpy(temp_, types_[index], typesLength_[index] + 1);\
InsituStringStream s(temp_);\
BaseReaderHandler<> h;\
Reader reader;\
EXPECT_TRUE(reader.Parse<kParseInsituFlag>(s, h));\
}\
}
TEST_TYPED(0, Booleans)
TEST_TYPED(1, Floats)
TEST_TYPED(2, Guids)
TEST_TYPED(3, Integers)
TEST_TYPED(4, Mixed)
TEST_TYPED(5, Nulls)
TEST_TYPED(6, Paragraphs)
#undef TEST_TYPED
TEST_F(RapidJson, SIMD_SUFFIX(ReaderParse_DummyHandler_FullPrecision)) {
for (size_t i = 0; i < kTrialCount; i++) {
StringStream s(json_);
BaseReaderHandler<> h;
Reader reader;
EXPECT_TRUE(reader.Parse<kParseFullPrecisionFlag>(s, h));
}
}
TEST_F(RapidJson, SIMD_SUFFIX(ReaderParseIterative_DummyHandler)) {
for (size_t i = 0; i < kTrialCount; i++) {
StringStream s(json_);
BaseReaderHandler<> h;
Reader reader;
EXPECT_TRUE(reader.Parse<kParseIterativeFlag>(s, h));
}
}
TEST_F(RapidJson, SIMD_SUFFIX(ReaderParseIterativeInsitu_DummyHandler)) {
for (size_t i = 0; i < kTrialCount; i++) {
memcpy(temp_, json_, length_ + 1);
InsituStringStream s(temp_);
BaseReaderHandler<> h;
Reader reader;
EXPECT_TRUE(reader.Parse<kParseIterativeFlag|kParseInsituFlag>(s, h));
}
}
TEST_F(RapidJson, SIMD_SUFFIX(ReaderParse_DummyHandler_ValidateEncoding)) {
for (size_t i = 0; i < kTrialCount; i++) {
StringStream s(json_);
BaseReaderHandler<> h;
Reader reader;
EXPECT_TRUE(reader.Parse<kParseValidateEncodingFlag>(s, h));
}
}
TEST_F(RapidJson, SIMD_SUFFIX(DocumentParseInsitu_MemoryPoolAllocator)) {
for (size_t i = 0; i < kTrialCount; i++) {
memcpy(temp_, json_, length_ + 1);
Document doc;
doc.ParseInsitu(temp_);
ASSERT_TRUE(doc.IsObject());
}
}
TEST_F(RapidJson, SIMD_SUFFIX(DocumentParseIterativeInsitu_MemoryPoolAllocator)) {
for (size_t i = 0; i < kTrialCount; i++) {
memcpy(temp_, json_, length_ + 1);
Document doc;
doc.ParseInsitu<kParseIterativeFlag>(temp_);
ASSERT_TRUE(doc.IsObject());
}
}
TEST_F(RapidJson, SIMD_SUFFIX(DocumentParse_MemoryPoolAllocator)) {
for (size_t i = 0; i < kTrialCount; i++) {
Document doc;
doc.Parse(json_);
ASSERT_TRUE(doc.IsObject());
}
}
TEST_F(RapidJson, SIMD_SUFFIX(DocumentParseLength_MemoryPoolAllocator)) {
for (size_t i = 0; i < kTrialCount; i++) {
Document doc;
doc.Parse(json_, length_);
ASSERT_TRUE(doc.IsObject());
}
}
#if RAPIDJSON_HAS_STDSTRING
TEST_F(RapidJson, SIMD_SUFFIX(DocumentParseStdString_MemoryPoolAllocator)) {
const std::string s(json_, length_);
for (size_t i = 0; i < kTrialCount; i++) {
Document doc;
doc.Parse(s);
ASSERT_TRUE(doc.IsObject());
}
}
#endif
TEST_F(RapidJson, SIMD_SUFFIX(DocumentParseIterative_MemoryPoolAllocator)) {
for (size_t i = 0; i < kTrialCount; i++) {
Document doc;
doc.Parse<kParseIterativeFlag>(json_);
ASSERT_TRUE(doc.IsObject());
}
}
TEST_F(RapidJson, SIMD_SUFFIX(DocumentParse_CrtAllocator)) {
for (size_t i = 0; i < kTrialCount; i++) {
memcpy(temp_, json_, length_ + 1);
GenericDocument<UTF8<>, CrtAllocator> doc;
doc.Parse(temp_);
ASSERT_TRUE(doc.IsObject());
}
}
TEST_F(RapidJson, SIMD_SUFFIX(DocumentParseEncodedInputStream_MemoryStream)) {
for (size_t i = 0; i < kTrialCount; i++) {
MemoryStream ms(json_, length_);
EncodedInputStream<UTF8<>, MemoryStream> is(ms);
Document doc;
doc.ParseStream<0, UTF8<> >(is);
ASSERT_TRUE(doc.IsObject());
}
}
TEST_F(RapidJson, SIMD_SUFFIX(DocumentParseAutoUTFInputStream_MemoryStream)) {
for (size_t i = 0; i < kTrialCount; i++) {
MemoryStream ms(json_, length_);
AutoUTFInputStream<unsigned, MemoryStream> is(ms);
Document doc;
doc.ParseStream<0, AutoUTF<unsigned> >(is);
ASSERT_TRUE(doc.IsObject());
}
}
template<typename T>
size_t Traverse(const T& value) {
size_t count = 1;
switch(value.GetType()) {
case kObjectType:
for (typename T::ConstMemberIterator itr = value.MemberBegin(); itr != value.MemberEnd(); ++itr) {
count++; // name
count += Traverse(itr->value);
}
break;
case kArrayType:
for (typename T::ConstValueIterator itr = value.Begin(); itr != value.End(); ++itr)
count += Traverse(*itr);
break;
default:
// Do nothing.
break;
}
return count;
}
TEST_F(RapidJson, DocumentTraverse) {
for (size_t i = 0; i < kTrialCount; i++) {
size_t count = Traverse(doc_);
EXPECT_EQ(4339u, count);
//if (i == 0)
// std::cout << count << std::endl;
}
}
#ifdef __GNUC__
RAPIDJSON_DIAG_PUSH
RAPIDJSON_DIAG_OFF(effc++)
#endif
struct ValueCounter : public BaseReaderHandler<> {
ValueCounter() : count_(1) {} // root
bool EndObject(SizeType memberCount) { count_ += memberCount * 2; return true; }
bool EndArray(SizeType elementCount) { count_ += elementCount; return true; }
SizeType count_;
};
#ifdef __GNUC__
RAPIDJSON_DIAG_POP
#endif
TEST_F(RapidJson, DocumentAccept) {
for (size_t i = 0; i < kTrialCount; i++) {
ValueCounter counter;
doc_.Accept(counter);
EXPECT_EQ(4339u, counter.count_);
}
}
struct NullStream {
typedef char Ch;
NullStream() /*: length_(0)*/ {}
void Put(Ch) { /*++length_;*/ }
void Flush() {}
//size_t length_;
};
TEST_F(RapidJson, Writer_NullStream) {
for (size_t i = 0; i < kTrialCount; i++) {
NullStream s;
Writer<NullStream> writer(s);
doc_.Accept(writer);
//if (i == 0)
// std::cout << s.length_ << std::endl;
}
}
TEST_F(RapidJson, SIMD_SUFFIX(Writer_StringBuffer)) {
for (size_t i = 0; i < kTrialCount; i++) {
StringBuffer s(0, 1024 * 1024);
Writer<StringBuffer> writer(s);
doc_.Accept(writer);
const char* str = s.GetString();
(void)str;
//if (i == 0)
// std::cout << strlen(str) << std::endl;
}
}
#define TEST_TYPED(index, Name)\
TEST_F(RapidJson, SIMD_SUFFIX(Writer_StringBuffer_##Name)) {\
for (size_t i = 0; i < kTrialCount * 10; i++) {\
StringBuffer s(0, 1024 * 1024);\
Writer<StringBuffer> writer(s);\
typesDoc_[index].Accept(writer);\
const char* str = s.GetString();\
(void)str;\
}\
}
TEST_TYPED(0, Booleans)
TEST_TYPED(1, Floats)
TEST_TYPED(2, Guids)
TEST_TYPED(3, Integers)
TEST_TYPED(4, Mixed)
TEST_TYPED(5, Nulls)
TEST_TYPED(6, Paragraphs)
#undef TEST_TYPED
TEST_F(RapidJson, SIMD_SUFFIX(PrettyWriter_StringBuffer)) {
for (size_t i = 0; i < kTrialCount; i++) {
StringBuffer s(0, 2048 * 1024);
PrettyWriter<StringBuffer> writer(s);
writer.SetIndent(' ', 1);
doc_.Accept(writer);
const char* str = s.GetString();
(void)str;
//if (i == 0)
// std::cout << strlen(str) << std::endl;
}
}
TEST_F(RapidJson, internal_Pow10) {
double sum = 0;
for (size_t i = 0; i < kTrialCount * kTrialCount; i++)
sum += internal::Pow10(int(i & 255));
EXPECT_GT(sum, 0.0);
}
TEST_F(RapidJson, SkipWhitespace_Basic) {
for (size_t i = 0; i < kTrialCount; i++) {
rapidjson::StringStream s(whitespace_);
while (s.Peek() == ' ' || s.Peek() == '\n' || s.Peek() == '\r' || s.Peek() == '\t')
s.Take();
ASSERT_EQ('[', s.Peek());
}
}
TEST_F(RapidJson, SIMD_SUFFIX(SkipWhitespace)) {
for (size_t i = 0; i < kTrialCount; i++) {
rapidjson::StringStream s(whitespace_);
rapidjson::SkipWhitespace(s);
ASSERT_EQ('[', s.Peek());
}
}
TEST_F(RapidJson, SkipWhitespace_strspn) {
for (size_t i = 0; i < kTrialCount; i++) {
const char* s = whitespace_ + std::strspn(whitespace_, " \t\r\n");
ASSERT_EQ('[', *s);
}
}
TEST_F(RapidJson, UTF8_Validate) {
NullStream os;
for (size_t i = 0; i < kTrialCount; i++) {
StringStream is(json_);
bool result = true;
while (is.Peek() != '\0')
result &= UTF8<>::Validate(is, os);
EXPECT_TRUE(result);
}
}
TEST_F(RapidJson, FileReadStream) {
for (size_t i = 0; i < kTrialCount; i++) {
FILE *fp = fopen(filename_, "rb");
char buffer[65536];
FileReadStream s(fp, buffer, sizeof(buffer));
while (s.Take() != '\0')
;
fclose(fp);
}
}
TEST_F(RapidJson, SIMD_SUFFIX(ReaderParse_DummyHandler_FileReadStream)) {
for (size_t i = 0; i < kTrialCount; i++) {
FILE *fp = fopen(filename_, "rb");
char buffer[65536];
FileReadStream s(fp, buffer, sizeof(buffer));
BaseReaderHandler<> h;
Reader reader;
reader.Parse(s, h);
fclose(fp);
}
}
TEST_F(RapidJson, StringBuffer) {
StringBuffer sb;
for (int i = 0; i < 32 * 1024 * 1024; i++)
sb.Put(i & 0x7f);
}
#endif // TEST_RAPIDJSON

View File

@ -1,216 +0,0 @@
#include "perftest.h"
#if TEST_RAPIDJSON
#include "rapidjson/schema.h"
#include <ctime>
#include <string>
#include <vector>
#define ARRAY_SIZE(a) sizeof(a) / sizeof(a[0])
using namespace rapidjson;
template <typename Allocator>
static char* ReadFile(const char* filename, Allocator& allocator) {
const char *paths[] = {
"",
"bin/",
"../bin/",
"../../bin/",
"../../../bin/"
};
char buffer[1024];
FILE *fp = 0;
for (size_t i = 0; i < sizeof(paths) / sizeof(paths[0]); i++) {
sprintf(buffer, "%s%s", paths[i], filename);
fp = fopen(buffer, "rb");
if (fp)
break;
}
if (!fp)
return 0;
fseek(fp, 0, SEEK_END);
size_t length = static_cast<size_t>(ftell(fp));
fseek(fp, 0, SEEK_SET);
char* json = reinterpret_cast<char*>(allocator.Malloc(length + 1));
size_t readLength = fread(json, 1, length, fp);
json[readLength] = '\0';
fclose(fp);
return json;
}
class Schema : public PerfTest {
public:
Schema() {}
virtual void SetUp() {
PerfTest::SetUp();
const char* filenames[] = {
"additionalItems.json",
"additionalProperties.json",
"allOf.json",
"anyOf.json",
"default.json",
"definitions.json",
"dependencies.json",
"enum.json",
"items.json",
"maximum.json",
"maxItems.json",
"maxLength.json",
"maxProperties.json",
"minimum.json",
"minItems.json",
"minLength.json",
"minProperties.json",
"multipleOf.json",
"not.json",
"oneOf.json",
"pattern.json",
"patternProperties.json",
"properties.json",
"ref.json",
"refRemote.json",
"required.json",
"type.json",
"uniqueItems.json"
};
char jsonBuffer[65536];
MemoryPoolAllocator<> jsonAllocator(jsonBuffer, sizeof(jsonBuffer));
for (size_t i = 0; i < ARRAY_SIZE(filenames); i++) {
char filename[FILENAME_MAX];
sprintf(filename, "jsonschema/tests/draft4/%s", filenames[i]);
char* json = ReadFile(filename, jsonAllocator);
if (!json) {
printf("json test suite file %s not found", filename);
return;
}
Document d;
d.Parse(json);
if (d.HasParseError()) {
printf("json test suite file %s has parse error", filename);
return;
}
for (Value::ConstValueIterator schemaItr = d.Begin(); schemaItr != d.End(); ++schemaItr) {
std::string schemaDescription = (*schemaItr)["description"].GetString();
if (IsExcludeTestSuite(schemaDescription))
continue;
TestSuite* ts = new TestSuite;
ts->schema = new SchemaDocument((*schemaItr)["schema"]);
const Value& tests = (*schemaItr)["tests"];
for (Value::ConstValueIterator testItr = tests.Begin(); testItr != tests.End(); ++testItr) {
if (IsExcludeTest(schemaDescription + ", " + (*testItr)["description"].GetString()))
continue;
Document* d2 = new Document;
d2->CopyFrom((*testItr)["data"], d2->GetAllocator());
ts->tests.push_back(d2);
}
testSuites.push_back(ts);
}
}
}
virtual void TearDown() {
PerfTest::TearDown();
for (TestSuiteList::const_iterator itr = testSuites.begin(); itr != testSuites.end(); ++itr)
delete *itr;
testSuites.clear();
}
private:
// Using the same exclusion in https://github.com/json-schema/JSON-Schema-Test-Suite
static bool IsExcludeTestSuite(const std::string& description) {
const char* excludeTestSuites[] = {
//lost failing these tests
"remote ref",
"remote ref, containing refs itself",
"fragment within remote ref",
"ref within remote ref",
"change resolution scope",
// these below were added to get jsck in the benchmarks)
"uniqueItems validation",
"valid definition",
"invalid definition"
};
for (size_t i = 0; i < ARRAY_SIZE(excludeTestSuites); i++)
if (excludeTestSuites[i] == description)
return true;
return false;
}
// Using the same exclusion in https://github.com/json-schema/JSON-Schema-Test-Suite
static bool IsExcludeTest(const std::string& description) {
const char* excludeTests[] = {
//lots of validators fail these
"invalid definition, invalid definition schema",
"maxLength validation, two supplementary Unicode code points is long enough",
"minLength validation, one supplementary Unicode code point is not long enough",
//this is to get tv4 in the benchmarks
"heterogeneous enum validation, something else is invalid"
};
for (size_t i = 0; i < ARRAY_SIZE(excludeTests); i++)
if (excludeTests[i] == description)
return true;
return false;
}
Schema(const Schema&);
Schema& operator=(const Schema&);
protected:
typedef std::vector<Document*> DocumentList;
struct TestSuite {
TestSuite() : schema() {}
~TestSuite() {
delete schema;
for (DocumentList::iterator itr = tests.begin(); itr != tests.end(); ++itr)
delete *itr;
}
SchemaDocument* schema;
DocumentList tests;
};
typedef std::vector<TestSuite* > TestSuiteList;
TestSuiteList testSuites;
};
TEST_F(Schema, TestSuite) {
char validatorBuffer[65536];
MemoryPoolAllocator<> validatorAllocator(validatorBuffer, sizeof(validatorBuffer));
const int trialCount = 100000;
int testCount = 0;
clock_t start = clock();
for (int i = 0; i < trialCount; i++) {
for (TestSuiteList::const_iterator itr = testSuites.begin(); itr != testSuites.end(); ++itr) {
const TestSuite& ts = **itr;
GenericSchemaValidator<SchemaDocument, BaseReaderHandler<UTF8<> >, MemoryPoolAllocator<> > validator(*ts.schema, &validatorAllocator);
for (DocumentList::const_iterator testItr = ts.tests.begin(); testItr != ts.tests.end(); ++testItr) {
validator.Reset();
(*testItr)->Accept(validator);
testCount++;
}
validatorAllocator.Clear();
}
}
clock_t end = clock();
double duration = double(end - start) / CLOCKS_PER_SEC;
printf("%d trials in %f s -> %f trials per sec\n", trialCount, duration, trialCount / duration);
printf("%d tests per trial\n", testCount / trialCount);
}
#endif

View File

@ -1,92 +0,0 @@
include(CheckCXXCompilerFlag)
set(UNITTEST_SOURCES
allocatorstest.cpp
bigintegertest.cpp
documenttest.cpp
dtoatest.cpp
encodedstreamtest.cpp
encodingstest.cpp
fwdtest.cpp
filestreamtest.cpp
itoatest.cpp
istreamwrappertest.cpp
jsoncheckertest.cpp
namespacetest.cpp
pointertest.cpp
prettywritertest.cpp
ostreamwrappertest.cpp
readertest.cpp
regextest.cpp
schematest.cpp
simdtest.cpp
strfunctest.cpp
stringbuffertest.cpp
strtodtest.cpp
unittest.cpp
valuetest.cpp
writertest.cpp)
find_program(CCACHE_FOUND ccache)
if(CCACHE_FOUND)
set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ccache)
set_property(GLOBAL PROPERTY RULE_LAUNCH_LINK ccache)
if (CMAKE_CXX_COMPILER_ID MATCHES "Clang")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Qunused-arguments -fcolor-diagnostics")
endif()
endif(CCACHE_FOUND)
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror -Wall -Wextra -Weffc++ -Wswitch-default -Wfloat-equal")
elseif (CMAKE_CXX_COMPILER_ID MATCHES "Clang")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror -Wall -Wextra -Weffc++ -Wswitch-default -Wfloat-equal -Wimplicit-fallthrough -Weverything")
# If the user is running a newer version of Clang that includes the
# -Wdouble-promotion, we will ignore that warning.
if (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 3.7)
CHECK_CXX_COMPILER_FLAG("-Wno-double-promotion" HAS_NO_DOUBLE_PROMOTION)
if (HAS_NO_DOUBLE_PROMOTION)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-double-promotion")
endif()
endif()
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
# Force to always compile with /W4
if(CMAKE_CXX_FLAGS MATCHES "/W[0-4]")
string(REGEX REPLACE "/W[0-4]" "/W4" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
else()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4")
endif()
# Force to always compile with /WX
if(CMAKE_CXX_FLAGS MATCHES "/WX-")
string(REGEX REPLACE "/WX-" "/WX" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
else()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /WX")
endif()
endif()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DRAPIDJSON_HAS_STDSTRING=1")
add_library(namespacetest STATIC namespacetest.cpp)
add_executable(unittest ${UNITTEST_SOURCES})
target_link_libraries(unittest ${TEST_LIBRARIES} namespacetest)
add_dependencies(tests unittest)
add_test(NAME unittest
COMMAND ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/unittest
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/bin)
if(NOT MSVC)
# Not running SIMD.* unit test cases for Valgrind
add_test(NAME valgrind_unittest
COMMAND valgrind --leak-check=full --error-exitcode=1 ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/unittest --gtest_filter=-SIMD.*
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/bin)
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
add_test(NAME symbol_check
COMMAND sh -c "objdump -t -C libnamespacetest.a | grep rapidjson ; test $? -ne 0"
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
endif(CMAKE_BUILD_TYPE STREQUAL "Debug")
endif(NOT MSVC)

View File

@ -1,102 +0,0 @@
// Tencent is pleased to support the open source community by making RapidJSON available.
//
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
//
// Licensed under the MIT License (the "License"); you may not use this file except
// in compliance with the License. You may obtain a copy of the License at
//
// http://opensource.org/licenses/MIT
//
// Unless required by applicable law or agreed to in writing, software distributed
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
// specific language governing permissions and limitations under the License.
#include "unittest.h"
#include "rapidjson/allocators.h"
using namespace rapidjson;
template <typename Allocator>
void TestAllocator(Allocator& a) {
EXPECT_TRUE(a.Malloc(0) == 0);
uint8_t* p = static_cast<uint8_t*>(a.Malloc(100));
EXPECT_TRUE(p != 0);
for (size_t i = 0; i < 100; i++)
p[i] = static_cast<uint8_t>(i);
// Expand
uint8_t* q = static_cast<uint8_t*>(a.Realloc(p, 100, 200));
EXPECT_TRUE(q != 0);
for (size_t i = 0; i < 100; i++)
EXPECT_EQ(i, q[i]);
for (size_t i = 100; i < 200; i++)
q[i] = static_cast<uint8_t>(i);
// Shrink
uint8_t *r = static_cast<uint8_t*>(a.Realloc(q, 200, 150));
EXPECT_TRUE(r != 0);
for (size_t i = 0; i < 150; i++)
EXPECT_EQ(i, r[i]);
Allocator::Free(r);
// Realloc to zero size
EXPECT_TRUE(a.Realloc(a.Malloc(1), 1, 0) == 0);
}
TEST(Allocator, CrtAllocator) {
CrtAllocator a;
TestAllocator(a);
}
TEST(Allocator, MemoryPoolAllocator) {
MemoryPoolAllocator<> a;
TestAllocator(a);
for (size_t i = 1; i < 1000; i++) {
EXPECT_TRUE(a.Malloc(i) != 0);
EXPECT_LE(a.Size(), a.Capacity());
}
}
TEST(Allocator, Alignment) {
#if RAPIDJSON_64BIT == 1
EXPECT_EQ(RAPIDJSON_UINT64_C2(0x00000000, 0x00000000), RAPIDJSON_ALIGN(0));
for (uint64_t i = 1; i < 8; i++) {
EXPECT_EQ(RAPIDJSON_UINT64_C2(0x00000000, 0x00000008), RAPIDJSON_ALIGN(i));
EXPECT_EQ(RAPIDJSON_UINT64_C2(0x00000000, 0x00000010), RAPIDJSON_ALIGN(RAPIDJSON_UINT64_C2(0x00000000, 0x00000008) + i));
EXPECT_EQ(RAPIDJSON_UINT64_C2(0x00000001, 0x00000000), RAPIDJSON_ALIGN(RAPIDJSON_UINT64_C2(0x00000000, 0xFFFFFFF8) + i));
EXPECT_EQ(RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0xFFFFFFF8), RAPIDJSON_ALIGN(RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0xFFFFFFF0) + i));
}
#else
EXPECT_EQ(0u, RAPIDJSON_ALIGN(0u));
for (uint32_t i = 1; i < 4; i++) {
EXPECT_EQ(4u, RAPIDJSON_ALIGN(i));
EXPECT_EQ(8u, RAPIDJSON_ALIGN(4u + i));
EXPECT_EQ(0xFFFFFFF8u, RAPIDJSON_ALIGN(0xFFFFFFF4u + i));
EXPECT_EQ(0xFFFFFFFCu, RAPIDJSON_ALIGN(0xFFFFFFF8u + i));
}
#endif
}
TEST(Allocator, Issue399) {
MemoryPoolAllocator<> a;
void* p = a.Malloc(100);
void* q = a.Realloc(p, 100, 200);
EXPECT_EQ(p, q);
// exhuasive testing
for (size_t j = 1; j < 32; j++) {
a.Clear();
a.Malloc(j); // some unaligned size
p = a.Malloc(1);
for (size_t i = 1; i < 1024; i++) {
q = a.Realloc(p, i, i + 1);
EXPECT_EQ(p, q);
p = q;
}
}
}

View File

@ -1,133 +0,0 @@
// Tencent is pleased to support the open source community by making RapidJSON available.
//
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
//
// Licensed under the MIT License (the "License"); you may not use this file except
// in compliance with the License. You may obtain a copy of the License at
//
// http://opensource.org/licenses/MIT
//
// Unless required by applicable law or agreed to in writing, software distributed
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
// specific language governing permissions and limitations under the License.
#include "unittest.h"
#include "rapidjson/internal/biginteger.h"
using namespace rapidjson::internal;
#define BIGINTEGER_LITERAL(s) BigInteger(s, sizeof(s) - 1)
static const BigInteger kZero(0);
static const BigInteger kOne(1);
static const BigInteger kUint64Max = BIGINTEGER_LITERAL("18446744073709551615");
static const BigInteger kTwo64 = BIGINTEGER_LITERAL("18446744073709551616");
TEST(BigInteger, Constructor) {
EXPECT_TRUE(kZero.IsZero());
EXPECT_TRUE(kZero == kZero);
EXPECT_TRUE(kZero == BIGINTEGER_LITERAL("0"));
EXPECT_TRUE(kZero == BIGINTEGER_LITERAL("00"));
const BigInteger a(123);
EXPECT_TRUE(a == a);
EXPECT_TRUE(a == BIGINTEGER_LITERAL("123"));
EXPECT_TRUE(a == BIGINTEGER_LITERAL("0123"));
EXPECT_EQ(2u, kTwo64.GetCount());
EXPECT_EQ(0u, kTwo64.GetDigit(0));
EXPECT_EQ(1u, kTwo64.GetDigit(1));
}
TEST(BigInteger, AddUint64) {
BigInteger a = kZero;
a += 0u;
EXPECT_TRUE(kZero == a);
a += 1u;
EXPECT_TRUE(kOne == a);
a += 1u;
EXPECT_TRUE(BigInteger(2) == a);
EXPECT_TRUE(BigInteger(RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0xFFFFFFFF)) == kUint64Max);
BigInteger b = kUint64Max;
b += 1u;
EXPECT_TRUE(kTwo64 == b);
b += RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0xFFFFFFFF);
EXPECT_TRUE(BIGINTEGER_LITERAL("36893488147419103231") == b);
}
TEST(BigInteger, MultiplyUint64) {
BigInteger a = kZero;
a *= static_cast <uint64_t>(0);
EXPECT_TRUE(kZero == a);
a *= static_cast <uint64_t>(123);
EXPECT_TRUE(kZero == a);
BigInteger b = kOne;
b *= static_cast<uint64_t>(1);
EXPECT_TRUE(kOne == b);
b *= static_cast<uint64_t>(0);
EXPECT_TRUE(kZero == b);
BigInteger c(123);
c *= static_cast<uint64_t>(456u);
EXPECT_TRUE(BigInteger(123u * 456u) == c);
c *= RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0xFFFFFFFF);
EXPECT_TRUE(BIGINTEGER_LITERAL("1034640981606221330982120") == c);
c *= RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0xFFFFFFFF);
EXPECT_TRUE(BIGINTEGER_LITERAL("19085757395861596536664473018420572782123800") == c);
}
TEST(BigInteger, MultiplyUint32) {
BigInteger a = kZero;
a *= static_cast <uint32_t>(0);
EXPECT_TRUE(kZero == a);
a *= static_cast <uint32_t>(123);
EXPECT_TRUE(kZero == a);
BigInteger b = kOne;
b *= static_cast<uint32_t>(1);
EXPECT_TRUE(kOne == b);
b *= static_cast<uint32_t>(0);
EXPECT_TRUE(kZero == b);
BigInteger c(123);
c *= static_cast<uint32_t>(456u);
EXPECT_TRUE(BigInteger(123u * 456u) == c);
c *= 0xFFFFFFFFu;
EXPECT_TRUE(BIGINTEGER_LITERAL("240896125641960") == c);
c *= 0xFFFFFFFFu;
EXPECT_TRUE(BIGINTEGER_LITERAL("1034640981124429079698200") == c);
}
TEST(BigInteger, LeftShift) {
BigInteger a = kZero;
a <<= 1;
EXPECT_TRUE(kZero == a);
a <<= 64;
EXPECT_TRUE(kZero == a);
a = BigInteger(123);
a <<= 0;
EXPECT_TRUE(BigInteger(123) == a);
a <<= 1;
EXPECT_TRUE(BigInteger(246) == a);
a <<= 64;
EXPECT_TRUE(BIGINTEGER_LITERAL("4537899042132549697536") == a);
a <<= 99;
EXPECT_TRUE(BIGINTEGER_LITERAL("2876235222267216943024851750785644982682875244576768") == a);
}
TEST(BigInteger, Compare) {
EXPECT_EQ(0, kZero.Compare(kZero));
EXPECT_EQ(1, kOne.Compare(kZero));
EXPECT_EQ(-1, kZero.Compare(kOne));
EXPECT_EQ(0, kUint64Max.Compare(kUint64Max));
EXPECT_EQ(0, kTwo64.Compare(kTwo64));
EXPECT_EQ(-1, kUint64Max.Compare(kTwo64));
EXPECT_EQ(1, kTwo64.Compare(kUint64Max));
}

View File

@ -1,652 +0,0 @@
// Tencent is pleased to support the open source community by making RapidJSON available.
//
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
//
// Licensed under the MIT License (the "License"); you may not use this file except
// in compliance with the License. You may obtain a copy of the License at
//
// http://opensource.org/licenses/MIT
//
// Unless required by applicable law or agreed to in writing, software distributed
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
// specific language governing permissions and limitations under the License.
#include "unittest.h"
#include "rapidjson/document.h"
#include "rapidjson/writer.h"
#include "rapidjson/filereadstream.h"
#include "rapidjson/encodedstream.h"
#include "rapidjson/stringbuffer.h"
#include <sstream>
#include <algorithm>
#ifdef __clang__
RAPIDJSON_DIAG_PUSH
RAPIDJSON_DIAG_OFF(c++98-compat)
RAPIDJSON_DIAG_OFF(missing-variable-declarations)
#endif
using namespace rapidjson;
template <typename DocumentType>
void ParseCheck(DocumentType& doc) {
typedef typename DocumentType::ValueType ValueType;
EXPECT_FALSE(doc.HasParseError());
if (doc.HasParseError())
printf("Error: %d at %zu\n", static_cast<int>(doc.GetParseError()), doc.GetErrorOffset());
EXPECT_TRUE(static_cast<ParseResult>(doc));
EXPECT_TRUE(doc.IsObject());
EXPECT_TRUE(doc.HasMember("hello"));
const ValueType& hello = doc["hello"];
EXPECT_TRUE(hello.IsString());
EXPECT_STREQ("world", hello.GetString());
EXPECT_TRUE(doc.HasMember("t"));
const ValueType& t = doc["t"];
EXPECT_TRUE(t.IsTrue());
EXPECT_TRUE(doc.HasMember("f"));
const ValueType& f = doc["f"];
EXPECT_TRUE(f.IsFalse());
EXPECT_TRUE(doc.HasMember("n"));
const ValueType& n = doc["n"];
EXPECT_TRUE(n.IsNull());
EXPECT_TRUE(doc.HasMember("i"));
const ValueType& i = doc["i"];
EXPECT_TRUE(i.IsNumber());
EXPECT_EQ(123, i.GetInt());
EXPECT_TRUE(doc.HasMember("pi"));
const ValueType& pi = doc["pi"];
EXPECT_TRUE(pi.IsNumber());
EXPECT_DOUBLE_EQ(3.1416, pi.GetDouble());
EXPECT_TRUE(doc.HasMember("a"));
const ValueType& a = doc["a"];
EXPECT_TRUE(a.IsArray());
EXPECT_EQ(4u, a.Size());
for (SizeType j = 0; j < 4; j++)
EXPECT_EQ(j + 1, a[j].GetUint());
}
template <typename Allocator, typename StackAllocator>
void ParseTest() {
typedef GenericDocument<UTF8<>, Allocator, StackAllocator> DocumentType;
DocumentType doc;
const char* json = " { \"hello\" : \"world\", \"t\" : true , \"f\" : false, \"n\": null, \"i\":123, \"pi\": 3.1416, \"a\":[1, 2, 3, 4] } ";
doc.Parse(json);
ParseCheck(doc);
doc.SetNull();
StringStream s(json);
doc.template ParseStream<0>(s);
ParseCheck(doc);
doc.SetNull();
char *buffer = strdup(json);
doc.ParseInsitu(buffer);
ParseCheck(doc);
free(buffer);
// Parse(const Ch*, size_t)
size_t length = strlen(json);
buffer = reinterpret_cast<char*>(malloc(length * 2));
memcpy(buffer, json, length);
memset(buffer + length, 'X', length);
#if RAPIDJSON_HAS_STDSTRING
std::string s2(buffer, length); // backup buffer
#endif
doc.SetNull();
doc.Parse(buffer, length);
free(buffer);
ParseCheck(doc);
#if RAPIDJSON_HAS_STDSTRING
// Parse(std::string)
doc.SetNull();
doc.Parse(s2);
ParseCheck(doc);
#endif
}
TEST(Document, Parse) {
ParseTest<MemoryPoolAllocator<>, CrtAllocator>();
ParseTest<MemoryPoolAllocator<>, MemoryPoolAllocator<> >();
ParseTest<CrtAllocator, MemoryPoolAllocator<> >();
ParseTest<CrtAllocator, CrtAllocator>();
}
TEST(Document, UnchangedOnParseError) {
Document doc;
doc.SetArray().PushBack(0, doc.GetAllocator());
ParseResult err = doc.Parse("{]");
EXPECT_TRUE(doc.HasParseError());
EXPECT_EQ(err.Code(), doc.GetParseError());
EXPECT_EQ(err.Offset(), doc.GetErrorOffset());
EXPECT_TRUE(doc.IsArray());
EXPECT_EQ(doc.Size(), 1u);
err = doc.Parse("{}");
EXPECT_FALSE(doc.HasParseError());
EXPECT_FALSE(err.IsError());
EXPECT_EQ(err.Code(), doc.GetParseError());
EXPECT_EQ(err.Offset(), doc.GetErrorOffset());
EXPECT_TRUE(doc.IsObject());
EXPECT_EQ(doc.MemberCount(), 0u);
}
static FILE* OpenEncodedFile(const char* filename) {
const char *paths[] = {
"encodings",
"bin/encodings",
"../bin/encodings",
"../../bin/encodings",
"../../../bin/encodings"
};
char buffer[1024];
for (size_t i = 0; i < sizeof(paths) / sizeof(paths[0]); i++) {
sprintf(buffer, "%s/%s", paths[i], filename);
FILE *fp = fopen(buffer, "rb");
if (fp)
return fp;
}
return 0;
}
TEST(Document, Parse_Encoding) {
const char* json = " { \"hello\" : \"world\", \"t\" : true , \"f\" : false, \"n\": null, \"i\":123, \"pi\": 3.1416, \"a\":[1, 2, 3, 4] } ";
typedef GenericDocument<UTF16<> > DocumentType;
DocumentType doc;
// Parse<unsigned, SourceEncoding>(const SourceEncoding::Ch*)
// doc.Parse<kParseDefaultFlags, UTF8<> >(json);
// EXPECT_FALSE(doc.HasParseError());
// EXPECT_EQ(0, StrCmp(doc[L"hello"].GetString(), L"world"));
// Parse<unsigned, SourceEncoding>(const SourceEncoding::Ch*, size_t)
size_t length = strlen(json);
char* buffer = reinterpret_cast<char*>(malloc(length * 2));
memcpy(buffer, json, length);
memset(buffer + length, 'X', length);
#if RAPIDJSON_HAS_STDSTRING
std::string s2(buffer, length); // backup buffer
#endif
doc.SetNull();
doc.Parse<kParseDefaultFlags, UTF8<> >(buffer, length);
free(buffer);
EXPECT_FALSE(doc.HasParseError());
if (doc.HasParseError())
printf("Error: %d at %zu\n", static_cast<int>(doc.GetParseError()), doc.GetErrorOffset());
EXPECT_EQ(0, StrCmp(doc[L"hello"].GetString(), L"world"));
#if RAPIDJSON_HAS_STDSTRING
// Parse<unsigned, SourceEncoding>(std::string)
doc.SetNull();
#if defined(_MSC_VER) && _MSC_VER < 1800
doc.Parse<kParseDefaultFlags, UTF8<> >(s2.c_str()); // VS2010 or below cannot handle templated function overloading. Use const char* instead.
#else
doc.Parse<kParseDefaultFlags, UTF8<> >(s2);
#endif
EXPECT_FALSE(doc.HasParseError());
EXPECT_EQ(0, StrCmp(doc[L"hello"].GetString(), L"world"));
#endif
}
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.
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, Swap) {
Document d1;
Document::AllocatorType& a = d1.GetAllocator();
d1.SetArray().PushBack(1, a).PushBack(2, a);
Value o;
o.SetObject().AddMember("a", 1, a);
// Swap between Document and Value
// d1.Swap(o); // doesn't compile
o.Swap(d1);
EXPECT_TRUE(d1.IsObject());
EXPECT_TRUE(o.IsArray());
// Swap between Document and Document
Document d2;
d2.SetArray().PushBack(3, a);
d1.Swap(d2);
EXPECT_TRUE(d1.IsArray());
EXPECT_TRUE(d2.IsObject());
EXPECT_EQ(&d2.GetAllocator(), &a);
// reset value
Value().Swap(d1);
EXPECT_TRUE(d1.IsNull());
// reset document, including allocator
Document().Swap(d2);
EXPECT_TRUE(d2.IsNull());
EXPECT_NE(&d2.GetAllocator(), &a);
// testing std::swap compatibility
d1.SetBool(true);
using std::swap;
swap(d1, d2);
EXPECT_TRUE(d1.IsNull());
EXPECT_TRUE(d2.IsTrue());
swap(o, d2);
EXPECT_TRUE(o.IsTrue());
EXPECT_TRUE(d2.IsArray());
}
// This should be slow due to assignment in inner-loop.
struct OutputStringStream : public std::ostringstream {
typedef char Ch;
virtual ~OutputStringStream();
void Put(char c) {
put(c);
}
void Flush() {}
};
OutputStringStream::~OutputStringStream() {}
TEST(Document, AcceptWriter) {
Document doc;
doc.Parse(" { \"hello\" : \"world\", \"t\" : true , \"f\" : false, \"n\": null, \"i\":123, \"pi\": 3.1416, \"a\":[1, 2, 3, 4] } ");
OutputStringStream os;
Writer<OutputStringStream> writer(os);
doc.Accept(writer);
EXPECT_EQ("{\"hello\":\"world\",\"t\":true,\"f\":false,\"n\":null,\"i\":123,\"pi\":3.1416,\"a\":[1,2,3,4]}", os.str());
}
TEST(Document, UserBuffer) {
typedef GenericDocument<UTF8<>, MemoryPoolAllocator<>, MemoryPoolAllocator<> > DocumentType;
char valueBuffer[4096];
char parseBuffer[1024];
MemoryPoolAllocator<> valueAllocator(valueBuffer, sizeof(valueBuffer));
MemoryPoolAllocator<> parseAllocator(parseBuffer, sizeof(parseBuffer));
DocumentType doc(&valueAllocator, sizeof(parseBuffer) / 2, &parseAllocator);
doc.Parse(" { \"hello\" : \"world\", \"t\" : true , \"f\" : false, \"n\": null, \"i\":123, \"pi\": 3.1416, \"a\":[1, 2, 3, 4] } ");
EXPECT_FALSE(doc.HasParseError());
EXPECT_LE(valueAllocator.Size(), sizeof(valueBuffer));
EXPECT_LE(parseAllocator.Size(), sizeof(parseBuffer));
// Cover MemoryPoolAllocator::Capacity()
EXPECT_LE(valueAllocator.Size(), valueAllocator.Capacity());
EXPECT_LE(parseAllocator.Size(), parseAllocator.Capacity());
}
// Issue 226: Value of string type should not point to NULL
TEST(Document, AssertAcceptInvalidNameType) {
Document doc;
doc.SetObject();
doc.AddMember("a", 0, doc.GetAllocator());
doc.FindMember("a")->name.SetNull(); // Change name to non-string type.
OutputStringStream os;
Writer<OutputStringStream> writer(os);
ASSERT_THROW(doc.Accept(writer), AssertException);
}
// Issue 44: SetStringRaw doesn't work with wchar_t
TEST(Document, UTF16_Document) {
GenericDocument< UTF16<> > json;
json.Parse<kParseValidateEncodingFlag>(L"[{\"created_at\":\"Wed Oct 30 17:13:20 +0000 2012\"}]");
ASSERT_TRUE(json.IsArray());
GenericValue< UTF16<> >& v = json[0];
ASSERT_TRUE(v.IsObject());
GenericValue< UTF16<> >& s = v[L"created_at"];
ASSERT_TRUE(s.IsString());
EXPECT_EQ(0, memcmp(L"Wed Oct 30 17:13:20 +0000 2012", s.GetString(), (s.GetStringLength() + 1) * sizeof(wchar_t)));
}
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
#if 0 // Many old compiler does not support these. Turn it off temporaily.
#include <type_traits>
TEST(Document, Traits) {
static_assert(std::is_constructible<Document>::value, "");
static_assert(std::is_default_constructible<Document>::value, "");
#ifndef _MSC_VER
static_assert(!std::is_copy_constructible<Document>::value, "");
#endif
static_assert(std::is_move_constructible<Document>::value, "");
static_assert(!std::is_nothrow_constructible<Document>::value, "");
static_assert(!std::is_nothrow_default_constructible<Document>::value, "");
#ifndef _MSC_VER
static_assert(!std::is_nothrow_copy_constructible<Document>::value, "");
static_assert(std::is_nothrow_move_constructible<Document>::value, "");
#endif
static_assert(std::is_assignable<Document,Document>::value, "");
#ifndef _MSC_VER
static_assert(!std::is_copy_assignable<Document>::value, "");
#endif
static_assert(std::is_move_assignable<Document>::value, "");
#ifndef _MSC_VER
static_assert(std::is_nothrow_assignable<Document, Document>::value, "");
#endif
static_assert(!std::is_nothrow_copy_assignable<Document>::value, "");
#ifndef _MSC_VER
static_assert(std::is_nothrow_move_assignable<Document>::value, "");
#endif
static_assert( std::is_destructible<Document>::value, "");
#ifndef _MSC_VER
static_assert(std::is_nothrow_destructible<Document>::value, "");
#endif
}
#endif
template <typename Allocator>
struct DocumentMove: public ::testing::Test {
};
typedef ::testing::Types< CrtAllocator, MemoryPoolAllocator<> > MoveAllocatorTypes;
TYPED_TEST_CASE(DocumentMove, MoveAllocatorTypes);
TYPED_TEST(DocumentMove, MoveConstructor) {
typedef TypeParam Allocator;
typedef GenericDocument<UTF8<>, Allocator> D;
Allocator allocator;
D a(&allocator);
a.Parse("[\"one\", \"two\", \"three\"]");
EXPECT_FALSE(a.HasParseError());
EXPECT_TRUE(a.IsArray());
EXPECT_EQ(3u, a.Size());
EXPECT_EQ(&a.GetAllocator(), &allocator);
// Document b(a); // does not compile (!is_copy_constructible)
D b(std::move(a));
EXPECT_TRUE(a.IsNull());
EXPECT_TRUE(b.IsArray());
EXPECT_EQ(3u, b.Size());
EXPECT_THROW(a.GetAllocator(), AssertException);
EXPECT_EQ(&b.GetAllocator(), &allocator);
b.Parse("{\"Foo\": \"Bar\", \"Baz\": 42}");
EXPECT_FALSE(b.HasParseError());
EXPECT_TRUE(b.IsObject());
EXPECT_EQ(2u, b.MemberCount());
// Document c = a; // does not compile (!is_copy_constructible)
D c = std::move(b);
EXPECT_TRUE(b.IsNull());
EXPECT_TRUE(c.IsObject());
EXPECT_EQ(2u, c.MemberCount());
EXPECT_THROW(b.GetAllocator(), AssertException);
EXPECT_EQ(&c.GetAllocator(), &allocator);
}
TYPED_TEST(DocumentMove, MoveConstructorParseError) {
typedef TypeParam Allocator;
typedef GenericDocument<UTF8<>, Allocator> D;
ParseResult noError;
D a;
a.Parse("{ 4 = 4]");
ParseResult error(a.GetParseError(), a.GetErrorOffset());
EXPECT_TRUE(a.HasParseError());
EXPECT_NE(error.Code(), noError.Code());
EXPECT_NE(error.Offset(), noError.Offset());
D b(std::move(a));
EXPECT_FALSE(a.HasParseError());
EXPECT_TRUE(b.HasParseError());
EXPECT_EQ(a.GetParseError(), noError.Code());
EXPECT_EQ(b.GetParseError(), error.Code());
EXPECT_EQ(a.GetErrorOffset(), noError.Offset());
EXPECT_EQ(b.GetErrorOffset(), error.Offset());
D c(std::move(b));
EXPECT_FALSE(b.HasParseError());
EXPECT_TRUE(c.HasParseError());
EXPECT_EQ(b.GetParseError(), noError.Code());
EXPECT_EQ(c.GetParseError(), error.Code());
EXPECT_EQ(b.GetErrorOffset(), noError.Offset());
EXPECT_EQ(c.GetErrorOffset(), error.Offset());
}
// This test does not properly use parsing, just for testing.
// It must call ClearStack() explicitly to prevent memory leak.
// But here we cannot as ClearStack() is private.
#if 0
TYPED_TEST(DocumentMove, MoveConstructorStack) {
typedef TypeParam Allocator;
typedef UTF8<> Encoding;
typedef GenericDocument<Encoding, Allocator> Document;
Document a;
size_t defaultCapacity = a.GetStackCapacity();
// Trick Document into getting GetStackCapacity() to return non-zero
typedef GenericReader<Encoding, Encoding, Allocator> Reader;
Reader reader(&a.GetAllocator());
GenericStringStream<Encoding> is("[\"one\", \"two\", \"three\"]");
reader.template Parse<kParseDefaultFlags>(is, a);
size_t capacity = a.GetStackCapacity();
EXPECT_GT(capacity, 0u);
Document b(std::move(a));
EXPECT_EQ(a.GetStackCapacity(), defaultCapacity);
EXPECT_EQ(b.GetStackCapacity(), capacity);
Document c = std::move(b);
EXPECT_EQ(b.GetStackCapacity(), defaultCapacity);
EXPECT_EQ(c.GetStackCapacity(), capacity);
}
#endif
TYPED_TEST(DocumentMove, MoveAssignment) {
typedef TypeParam Allocator;
typedef GenericDocument<UTF8<>, Allocator> D;
Allocator allocator;
D a(&allocator);
a.Parse("[\"one\", \"two\", \"three\"]");
EXPECT_FALSE(a.HasParseError());
EXPECT_TRUE(a.IsArray());
EXPECT_EQ(3u, a.Size());
EXPECT_EQ(&a.GetAllocator(), &allocator);
// Document b; b = a; // does not compile (!is_copy_assignable)
D b;
b = std::move(a);
EXPECT_TRUE(a.IsNull());
EXPECT_TRUE(b.IsArray());
EXPECT_EQ(3u, b.Size());
EXPECT_THROW(a.GetAllocator(), AssertException);
EXPECT_EQ(&b.GetAllocator(), &allocator);
b.Parse("{\"Foo\": \"Bar\", \"Baz\": 42}");
EXPECT_FALSE(b.HasParseError());
EXPECT_TRUE(b.IsObject());
EXPECT_EQ(2u, b.MemberCount());
// Document c; c = a; // does not compile (see static_assert)
D c;
c = std::move(b);
EXPECT_TRUE(b.IsNull());
EXPECT_TRUE(c.IsObject());
EXPECT_EQ(2u, c.MemberCount());
EXPECT_THROW(b.GetAllocator(), AssertException);
EXPECT_EQ(&c.GetAllocator(), &allocator);
}
TYPED_TEST(DocumentMove, MoveAssignmentParseError) {
typedef TypeParam Allocator;
typedef GenericDocument<UTF8<>, Allocator> D;
ParseResult noError;
D a;
a.Parse("{ 4 = 4]");
ParseResult error(a.GetParseError(), a.GetErrorOffset());
EXPECT_TRUE(a.HasParseError());
EXPECT_NE(error.Code(), noError.Code());
EXPECT_NE(error.Offset(), noError.Offset());
D b;
b = std::move(a);
EXPECT_FALSE(a.HasParseError());
EXPECT_TRUE(b.HasParseError());
EXPECT_EQ(a.GetParseError(), noError.Code());
EXPECT_EQ(b.GetParseError(), error.Code());
EXPECT_EQ(a.GetErrorOffset(), noError.Offset());
EXPECT_EQ(b.GetErrorOffset(), error.Offset());
D c;
c = std::move(b);
EXPECT_FALSE(b.HasParseError());
EXPECT_TRUE(c.HasParseError());
EXPECT_EQ(b.GetParseError(), noError.Code());
EXPECT_EQ(c.GetParseError(), error.Code());
EXPECT_EQ(b.GetErrorOffset(), noError.Offset());
EXPECT_EQ(c.GetErrorOffset(), error.Offset());
}
// This test does not properly use parsing, just for testing.
// It must call ClearStack() explicitly to prevent memory leak.
// But here we cannot as ClearStack() is private.
#if 0
TYPED_TEST(DocumentMove, MoveAssignmentStack) {
typedef TypeParam Allocator;
typedef UTF8<> Encoding;
typedef GenericDocument<Encoding, Allocator> D;
D a;
size_t defaultCapacity = a.GetStackCapacity();
// Trick Document into getting GetStackCapacity() to return non-zero
typedef GenericReader<Encoding, Encoding, Allocator> Reader;
Reader reader(&a.GetAllocator());
GenericStringStream<Encoding> is("[\"one\", \"two\", \"three\"]");
reader.template Parse<kParseDefaultFlags>(is, a);
size_t capacity = a.GetStackCapacity();
EXPECT_GT(capacity, 0u);
D b;
b = std::move(a);
EXPECT_EQ(a.GetStackCapacity(), defaultCapacity);
EXPECT_EQ(b.GetStackCapacity(), capacity);
D c;
c = std::move(b);
EXPECT_EQ(b.GetStackCapacity(), defaultCapacity);
EXPECT_EQ(c.GetStackCapacity(), capacity);
}
#endif
#endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS
// Issue 22: Memory corruption via operator=
// Fixed by making unimplemented assignment operator private.
//TEST(Document, Assignment) {
// Document d1;
// Document d2;
// d1 = d2;
//}
#ifdef __clang__
RAPIDJSON_DIAG_POP
#endif

View File

@ -1,98 +0,0 @@
// Tencent is pleased to support the open source community by making RapidJSON available.
//
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
//
// Licensed under the MIT License (the "License"); you may not use this file except
// in compliance with the License. You may obtain a copy of the License at
//
// http://opensource.org/licenses/MIT
//
// Unless required by applicable law or agreed to in writing, software distributed
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
// specific language governing permissions and limitations under the License.
#include "unittest.h"
#include "rapidjson/internal/dtoa.h"
#ifdef __GNUC__
RAPIDJSON_DIAG_PUSH
RAPIDJSON_DIAG_OFF(type-limits)
#endif
using namespace rapidjson::internal;
TEST(dtoa, normal) {
char buffer[30];
#define TEST_DTOA(d, a)\
*dtoa(d, buffer) = '\0';\
EXPECT_STREQ(a, buffer)
TEST_DTOA(0.0, "0.0");
TEST_DTOA(-0.0, "-0.0");
TEST_DTOA(1.0, "1.0");
TEST_DTOA(-1.0, "-1.0");
TEST_DTOA(1.2345, "1.2345");
TEST_DTOA(1.2345678, "1.2345678");
TEST_DTOA(0.123456789012, "0.123456789012");
TEST_DTOA(1234567.8, "1234567.8");
TEST_DTOA(-79.39773355813419, "-79.39773355813419");
TEST_DTOA(0.000001, "0.000001");
TEST_DTOA(0.0000001, "1e-7");
TEST_DTOA(1e30, "1e30");
TEST_DTOA(1.234567890123456e30, "1.234567890123456e30");
TEST_DTOA(5e-324, "5e-324"); // Min subnormal positive double
TEST_DTOA(2.225073858507201e-308, "2.225073858507201e-308"); // Max subnormal positive double
TEST_DTOA(2.2250738585072014e-308, "2.2250738585072014e-308"); // Min normal positive double
TEST_DTOA(1.7976931348623157e308, "1.7976931348623157e308"); // Max double
#undef TEST_DTOA
}
TEST(dtoa, maxDecimalPlaces) {
char buffer[30];
#define TEST_DTOA(m, d, a)\
*dtoa(d, buffer, m) = '\0';\
EXPECT_STREQ(a, buffer)
TEST_DTOA(3, 0.0, "0.0");
TEST_DTOA(1, 0.0, "0.0");
TEST_DTOA(3, -0.0, "-0.0");
TEST_DTOA(3, 1.0, "1.0");
TEST_DTOA(3, -1.0, "-1.0");
TEST_DTOA(3, 1.2345, "1.234");
TEST_DTOA(2, 1.2345, "1.23");
TEST_DTOA(1, 1.2345, "1.2");
TEST_DTOA(3, 1.2345678, "1.234");
TEST_DTOA(3, 1.0001, "1.0");
TEST_DTOA(2, 1.0001, "1.0");
TEST_DTOA(1, 1.0001, "1.0");
TEST_DTOA(3, 0.123456789012, "0.123");
TEST_DTOA(2, 0.123456789012, "0.12");
TEST_DTOA(1, 0.123456789012, "0.1");
TEST_DTOA(4, 0.0001, "0.0001");
TEST_DTOA(3, 0.0001, "0.0");
TEST_DTOA(2, 0.0001, "0.0");
TEST_DTOA(1, 0.0001, "0.0");
TEST_DTOA(3, 1234567.8, "1234567.8");
TEST_DTOA(3, 1e30, "1e30");
TEST_DTOA(3, 5e-324, "0.0"); // Min subnormal positive double
TEST_DTOA(3, 2.225073858507201e-308, "0.0"); // Max subnormal positive double
TEST_DTOA(3, 2.2250738585072014e-308, "0.0"); // Min normal positive double
TEST_DTOA(3, 1.7976931348623157e308, "1.7976931348623157e308"); // Max double
TEST_DTOA(5, -0.14000000000000001, "-0.14");
TEST_DTOA(4, -0.14000000000000001, "-0.14");
TEST_DTOA(3, -0.14000000000000001, "-0.14");
TEST_DTOA(3, -0.10000000000000001, "-0.1");
TEST_DTOA(2, -0.10000000000000001, "-0.1");
TEST_DTOA(1, -0.10000000000000001, "-0.1");
#undef TEST_DTOA
}
#ifdef __GNUC__
RAPIDJSON_DIAG_POP
#endif

View File

@ -1,313 +0,0 @@
// Tencent is pleased to support the open source community by making RapidJSON available.
//
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
//
// Licensed under the MIT License (the "License"); you may not use this file except
// in compliance with the License. You may obtain a copy of the License at
//
// http://opensource.org/licenses/MIT
//
// Unless required by applicable law or agreed to in writing, software distributed
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
// specific language governing permissions and limitations under the License.
#include "unittest.h"
#include "rapidjson/filereadstream.h"
#include "rapidjson/filewritestream.h"
#include "rapidjson/encodedstream.h"
#include "rapidjson/stringbuffer.h"
#include "rapidjson/memorystream.h"
#include "rapidjson/memorybuffer.h"
using namespace rapidjson;
class EncodedStreamTest : public ::testing::Test {
public:
EncodedStreamTest() : json_(), length_() {}
virtual ~EncodedStreamTest();
virtual void SetUp() {
json_ = ReadFile("utf8.json", true, &length_);
}
virtual void TearDown() {
free(json_);
json_ = 0;
}
private:
EncodedStreamTest(const EncodedStreamTest&);
EncodedStreamTest& operator=(const EncodedStreamTest&);
protected:
static FILE* Open(const char* filename) {
const char *paths[] = {
"encodings",
"bin/encodings",
"../bin/encodings",
"../../bin/encodings",
"../../../bin/encodings"
};
char buffer[1024];
for (size_t i = 0; i < sizeof(paths) / sizeof(paths[0]); i++) {
sprintf(buffer, "%s/%s", paths[i], filename);
FILE *fp = fopen(buffer, "rb");
if (fp)
return fp;
}
return 0;
}
static char *ReadFile(const char* filename, bool appendPath, size_t* outLength) {
FILE *fp = appendPath ? Open(filename) : fopen(filename, "rb");
if (!fp) {
*outLength = 0;
return 0;
}
fseek(fp, 0, SEEK_END);
*outLength = static_cast<size_t>(ftell(fp));
fseek(fp, 0, SEEK_SET);
char* buffer = static_cast<char*>(malloc(*outLength + 1));
size_t readLength = fread(buffer, 1, *outLength, fp);
buffer[readLength] = '\0';
fclose(fp);
return buffer;
}
template <typename FileEncoding, typename MemoryEncoding>
void TestEncodedInputStream(const char* filename) {
// Test FileReadStream
{
char buffer[16];
FILE *fp = Open(filename);
ASSERT_TRUE(fp != 0);
FileReadStream fs(fp, buffer, sizeof(buffer));
EncodedInputStream<FileEncoding, FileReadStream> eis(fs);
StringStream s(json_);
while (eis.Peek() != '\0') {
unsigned expected, actual;
EXPECT_TRUE(UTF8<>::Decode(s, &expected));
EXPECT_TRUE(MemoryEncoding::Decode(eis, &actual));
EXPECT_EQ(expected, actual);
}
EXPECT_EQ('\0', s.Peek());
fclose(fp);
}
// Test MemoryStream
{
size_t size;
char* data = ReadFile(filename, true, &size);
MemoryStream ms(data, size);
EncodedInputStream<FileEncoding, MemoryStream> eis(ms);
StringStream s(json_);
while (eis.Peek() != '\0') {
unsigned expected, actual;
EXPECT_TRUE(UTF8<>::Decode(s, &expected));
EXPECT_TRUE(MemoryEncoding::Decode(eis, &actual));
EXPECT_EQ(expected, actual);
}
EXPECT_EQ('\0', s.Peek());
free(data);
EXPECT_EQ(size, eis.Tell());
}
}
void TestAutoUTFInputStream(const char *filename, bool expectHasBOM) {
// Test FileReadStream
{
char buffer[16];
FILE *fp = Open(filename);
ASSERT_TRUE(fp != 0);
FileReadStream fs(fp, buffer, sizeof(buffer));
AutoUTFInputStream<unsigned, FileReadStream> eis(fs);
EXPECT_EQ(expectHasBOM, eis.HasBOM());
StringStream s(json_);
while (eis.Peek() != '\0') {
unsigned expected, actual;
EXPECT_TRUE(UTF8<>::Decode(s, &expected));
EXPECT_TRUE(AutoUTF<unsigned>::Decode(eis, &actual));
EXPECT_EQ(expected, actual);
}
EXPECT_EQ('\0', s.Peek());
fclose(fp);
}
// Test MemoryStream
{
size_t size;
char* data = ReadFile(filename, true, &size);
MemoryStream ms(data, size);
AutoUTFInputStream<unsigned, MemoryStream> eis(ms);
EXPECT_EQ(expectHasBOM, eis.HasBOM());
StringStream s(json_);
while (eis.Peek() != '\0') {
unsigned expected, actual;
EXPECT_TRUE(UTF8<>::Decode(s, &expected));
EXPECT_TRUE(AutoUTF<unsigned>::Decode(eis, &actual));
EXPECT_EQ(expected, actual);
}
EXPECT_EQ('\0', s.Peek());
free(data);
EXPECT_EQ(size, eis.Tell());
}
}
template <typename FileEncoding, typename MemoryEncoding>
void TestEncodedOutputStream(const char* expectedFilename, bool putBOM) {
// Test FileWriteStream
{
char filename[L_tmpnam];
FILE* fp = TempFile(filename);
char buffer[16];
FileWriteStream os(fp, buffer, sizeof(buffer));
EncodedOutputStream<FileEncoding, FileWriteStream> eos(os, putBOM);
StringStream s(json_);
while (s.Peek() != '\0') {
bool success = Transcoder<UTF8<>, MemoryEncoding>::Transcode(s, eos);
EXPECT_TRUE(success);
}
eos.Flush();
fclose(fp);
EXPECT_TRUE(CompareFile(filename, expectedFilename));
remove(filename);
}
// Test MemoryBuffer
{
MemoryBuffer mb;
EncodedOutputStream<FileEncoding, MemoryBuffer> eos(mb, putBOM);
StringStream s(json_);
while (s.Peek() != '\0') {
bool success = Transcoder<UTF8<>, MemoryEncoding>::Transcode(s, eos);
EXPECT_TRUE(success);
}
eos.Flush();
EXPECT_TRUE(CompareBufferFile(mb.GetBuffer(), mb.GetSize(), expectedFilename));
}
}
void TestAutoUTFOutputStream(UTFType type, bool putBOM, const char *expectedFilename) {
// Test FileWriteStream
{
char filename[L_tmpnam];
FILE* fp = TempFile(filename);
char buffer[16];
FileWriteStream os(fp, buffer, sizeof(buffer));
AutoUTFOutputStream<unsigned, FileWriteStream> eos(os, type, putBOM);
StringStream s(json_);
while (s.Peek() != '\0') {
bool success = Transcoder<UTF8<>, AutoUTF<unsigned> >::Transcode(s, eos);
EXPECT_TRUE(success);
}
eos.Flush();
fclose(fp);
EXPECT_TRUE(CompareFile(filename, expectedFilename));
remove(filename);
}
// Test MemoryBuffer
{
MemoryBuffer mb;
AutoUTFOutputStream<unsigned, MemoryBuffer> eos(mb, type, putBOM);
StringStream s(json_);
while (s.Peek() != '\0') {
bool success = Transcoder<UTF8<>, AutoUTF<unsigned> >::Transcode(s, eos);
EXPECT_TRUE(success);
}
eos.Flush();
EXPECT_TRUE(CompareBufferFile(mb.GetBuffer(), mb.GetSize(), expectedFilename));
}
}
bool CompareFile(const char* filename, const char* expectedFilename) {
size_t actualLength, expectedLength;
char* actualBuffer = ReadFile(filename, false, &actualLength);
char* expectedBuffer = ReadFile(expectedFilename, true, &expectedLength);
bool ret = (expectedLength == actualLength) && memcmp(expectedBuffer, actualBuffer, actualLength) == 0;
free(actualBuffer);
free(expectedBuffer);
return ret;
}
bool CompareBufferFile(const char* actualBuffer, size_t actualLength, const char* expectedFilename) {
size_t expectedLength;
char* expectedBuffer = ReadFile(expectedFilename, true, &expectedLength);
bool ret = (expectedLength == actualLength) && memcmp(expectedBuffer, actualBuffer, actualLength) == 0;
free(expectedBuffer);
return ret;
}
char *json_;
size_t length_;
};
EncodedStreamTest::~EncodedStreamTest() {}
TEST_F(EncodedStreamTest, EncodedInputStream) {
TestEncodedInputStream<UTF8<>, UTF8<> >("utf8.json");
TestEncodedInputStream<UTF8<>, UTF8<> >("utf8bom.json");
TestEncodedInputStream<UTF16LE<>, UTF16<> >("utf16le.json");
TestEncodedInputStream<UTF16LE<>, UTF16<> >("utf16lebom.json");
TestEncodedInputStream<UTF16BE<>, UTF16<> >("utf16be.json");
TestEncodedInputStream<UTF16BE<>, UTF16<> >("utf16bebom.json");
TestEncodedInputStream<UTF32LE<>, UTF32<> >("utf32le.json");
TestEncodedInputStream<UTF32LE<>, UTF32<> >("utf32lebom.json");
TestEncodedInputStream<UTF32BE<>, UTF32<> >("utf32be.json");
TestEncodedInputStream<UTF32BE<>, UTF32<> >("utf32bebom.json");
}
TEST_F(EncodedStreamTest, AutoUTFInputStream) {
TestAutoUTFInputStream("utf8.json", false);
TestAutoUTFInputStream("utf8bom.json", true);
TestAutoUTFInputStream("utf16le.json", false);
TestAutoUTFInputStream("utf16lebom.json",true);
TestAutoUTFInputStream("utf16be.json", false);
TestAutoUTFInputStream("utf16bebom.json",true);
TestAutoUTFInputStream("utf32le.json", false);
TestAutoUTFInputStream("utf32lebom.json",true);
TestAutoUTFInputStream("utf32be.json", false);
TestAutoUTFInputStream("utf32bebom.json", true);
{
// Auto detection fail, use user defined UTF type
const char json[] = "{ }";
MemoryStream ms(json, sizeof(json));
AutoUTFInputStream<unsigned, MemoryStream> eis(ms, kUTF8);
EXPECT_FALSE(eis.HasBOM());
EXPECT_EQ(kUTF8, eis.GetType());
}
}
TEST_F(EncodedStreamTest, EncodedOutputStream) {
TestEncodedOutputStream<UTF8<>, UTF8<> >("utf8.json", false);
TestEncodedOutputStream<UTF8<>, UTF8<> >("utf8bom.json", true);
TestEncodedOutputStream<UTF16LE<>, UTF16<> >("utf16le.json", false);
TestEncodedOutputStream<UTF16LE<>, UTF16<> >("utf16lebom.json",true);
TestEncodedOutputStream<UTF16BE<>, UTF16<> >("utf16be.json", false);
TestEncodedOutputStream<UTF16BE<>, UTF16<> >("utf16bebom.json",true);
TestEncodedOutputStream<UTF32LE<>, UTF32<> >("utf32le.json", false);
TestEncodedOutputStream<UTF32LE<>, UTF32<> >("utf32lebom.json",true);
TestEncodedOutputStream<UTF32BE<>, UTF32<> >("utf32be.json", false);
TestEncodedOutputStream<UTF32BE<>, UTF32<> >("utf32bebom.json",true);
}
TEST_F(EncodedStreamTest, AutoUTFOutputStream) {
TestAutoUTFOutputStream(kUTF8, false, "utf8.json");
TestAutoUTFOutputStream(kUTF8, true, "utf8bom.json");
TestAutoUTFOutputStream(kUTF16LE, false, "utf16le.json");
TestAutoUTFOutputStream(kUTF16LE, true, "utf16lebom.json");
TestAutoUTFOutputStream(kUTF16BE, false, "utf16be.json");
TestAutoUTFOutputStream(kUTF16BE, true, "utf16bebom.json");
TestAutoUTFOutputStream(kUTF32LE, false, "utf32le.json");
TestAutoUTFOutputStream(kUTF32LE, true, "utf32lebom.json");
TestAutoUTFOutputStream(kUTF32BE, false, "utf32be.json");
TestAutoUTFOutputStream(kUTF32BE, true, "utf32bebom.json");
}

View File

@ -1,451 +0,0 @@
// Tencent is pleased to support the open source community by making RapidJSON available.
//
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
//
// Licensed under the MIT License (the "License"); you may not use this file except
// in compliance with the License. You may obtain a copy of the License at
//
// http://opensource.org/licenses/MIT
//
// Unless required by applicable law or agreed to in writing, software distributed
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
// specific language governing permissions and limitations under the License.
#include "unittest.h"
#include "rapidjson/filereadstream.h"
#include "rapidjson/filewritestream.h"
#include "rapidjson/encodedstream.h"
#include "rapidjson/stringbuffer.h"
using namespace rapidjson;
// Verification of encoders/decoders with Hoehrmann's UTF8 decoder
// http://www.unicode.org/Public/UNIDATA/Blocks.txt
static const unsigned kCodepointRanges[] = {
0x0000, 0x007F, // Basic Latin
0x0080, 0x00FF, // Latin-1 Supplement
0x0100, 0x017F, // Latin Extended-A
0x0180, 0x024F, // Latin Extended-B
0x0250, 0x02AF, // IPA Extensions
0x02B0, 0x02FF, // Spacing Modifier Letters
0x0300, 0x036F, // Combining Diacritical Marks
0x0370, 0x03FF, // Greek and Coptic
0x0400, 0x04FF, // Cyrillic
0x0500, 0x052F, // Cyrillic Supplement
0x0530, 0x058F, // Armenian
0x0590, 0x05FF, // Hebrew
0x0600, 0x06FF, // Arabic
0x0700, 0x074F, // Syriac
0x0750, 0x077F, // Arabic Supplement
0x0780, 0x07BF, // Thaana
0x07C0, 0x07FF, // NKo
0x0800, 0x083F, // Samaritan
0x0840, 0x085F, // Mandaic
0x0900, 0x097F, // Devanagari
0x0980, 0x09FF, // Bengali
0x0A00, 0x0A7F, // Gurmukhi
0x0A80, 0x0AFF, // Gujarati
0x0B00, 0x0B7F, // Oriya
0x0B80, 0x0BFF, // Tamil
0x0C00, 0x0C7F, // Telugu
0x0C80, 0x0CFF, // Kannada
0x0D00, 0x0D7F, // Malayalam
0x0D80, 0x0DFF, // Sinhala
0x0E00, 0x0E7F, // Thai
0x0E80, 0x0EFF, // Lao
0x0F00, 0x0FFF, // Tibetan
0x1000, 0x109F, // Myanmar
0x10A0, 0x10FF, // Georgian
0x1100, 0x11FF, // Hangul Jamo
0x1200, 0x137F, // Ethiopic
0x1380, 0x139F, // Ethiopic Supplement
0x13A0, 0x13FF, // Cherokee
0x1400, 0x167F, // Unified Canadian Aboriginal Syllabics
0x1680, 0x169F, // Ogham
0x16A0, 0x16FF, // Runic
0x1700, 0x171F, // Tagalog
0x1720, 0x173F, // Hanunoo
0x1740, 0x175F, // Buhid
0x1760, 0x177F, // Tagbanwa
0x1780, 0x17FF, // Khmer
0x1800, 0x18AF, // Mongolian
0x18B0, 0x18FF, // Unified Canadian Aboriginal Syllabics Extended
0x1900, 0x194F, // Limbu
0x1950, 0x197F, // Tai Le
0x1980, 0x19DF, // New Tai Lue
0x19E0, 0x19FF, // Khmer Symbols
0x1A00, 0x1A1F, // Buginese
0x1A20, 0x1AAF, // Tai Tham
0x1B00, 0x1B7F, // Balinese
0x1B80, 0x1BBF, // Sundanese
0x1BC0, 0x1BFF, // Batak
0x1C00, 0x1C4F, // Lepcha
0x1C50, 0x1C7F, // Ol Chiki
0x1CD0, 0x1CFF, // Vedic Extensions
0x1D00, 0x1D7F, // Phonetic Extensions
0x1D80, 0x1DBF, // Phonetic Extensions Supplement
0x1DC0, 0x1DFF, // Combining Diacritical Marks Supplement
0x1E00, 0x1EFF, // Latin Extended Additional
0x1F00, 0x1FFF, // Greek Extended
0x2000, 0x206F, // General Punctuation
0x2070, 0x209F, // Superscripts and Subscripts
0x20A0, 0x20CF, // Currency Symbols
0x20D0, 0x20FF, // Combining Diacritical Marks for Symbols
0x2100, 0x214F, // Letterlike Symbols
0x2150, 0x218F, // Number Forms
0x2190, 0x21FF, // Arrows
0x2200, 0x22FF, // Mathematical Operators
0x2300, 0x23FF, // Miscellaneous Technical
0x2400, 0x243F, // Control Pictures
0x2440, 0x245F, // Optical Character Recognition
0x2460, 0x24FF, // Enclosed Alphanumerics
0x2500, 0x257F, // Box Drawing
0x2580, 0x259F, // Block Elements
0x25A0, 0x25FF, // Geometric Shapes
0x2600, 0x26FF, // Miscellaneous Symbols
0x2700, 0x27BF, // Dingbats
0x27C0, 0x27EF, // Miscellaneous Mathematical Symbols-A
0x27F0, 0x27FF, // Supplemental Arrows-A
0x2800, 0x28FF, // Braille Patterns
0x2900, 0x297F, // Supplemental Arrows-B
0x2980, 0x29FF, // Miscellaneous Mathematical Symbols-B
0x2A00, 0x2AFF, // Supplemental Mathematical Operators
0x2B00, 0x2BFF, // Miscellaneous Symbols and Arrows
0x2C00, 0x2C5F, // Glagolitic
0x2C60, 0x2C7F, // Latin Extended-C
0x2C80, 0x2CFF, // Coptic
0x2D00, 0x2D2F, // Georgian Supplement
0x2D30, 0x2D7F, // Tifinagh
0x2D80, 0x2DDF, // Ethiopic Extended
0x2DE0, 0x2DFF, // Cyrillic Extended-A
0x2E00, 0x2E7F, // Supplemental Punctuation
0x2E80, 0x2EFF, // CJK Radicals Supplement
0x2F00, 0x2FDF, // Kangxi Radicals
0x2FF0, 0x2FFF, // Ideographic Description Characters
0x3000, 0x303F, // CJK Symbols and Punctuation
0x3040, 0x309F, // Hiragana
0x30A0, 0x30FF, // Katakana
0x3100, 0x312F, // Bopomofo
0x3130, 0x318F, // Hangul Compatibility Jamo
0x3190, 0x319F, // Kanbun
0x31A0, 0x31BF, // Bopomofo Extended
0x31C0, 0x31EF, // CJK Strokes
0x31F0, 0x31FF, // Katakana Phonetic Extensions
0x3200, 0x32FF, // Enclosed CJK Letters and Months
0x3300, 0x33FF, // CJK Compatibility
0x3400, 0x4DBF, // CJK Unified Ideographs Extension A
0x4DC0, 0x4DFF, // Yijing Hexagram Symbols
0x4E00, 0x9FFF, // CJK Unified Ideographs
0xA000, 0xA48F, // Yi Syllables
0xA490, 0xA4CF, // Yi Radicals
0xA4D0, 0xA4FF, // Lisu
0xA500, 0xA63F, // Vai
0xA640, 0xA69F, // Cyrillic Extended-B
0xA6A0, 0xA6FF, // Bamum
0xA700, 0xA71F, // Modifier Tone Letters
0xA720, 0xA7FF, // Latin Extended-D
0xA800, 0xA82F, // Syloti Nagri
0xA830, 0xA83F, // Common Indic Number Forms
0xA840, 0xA87F, // Phags-pa
0xA880, 0xA8DF, // Saurashtra
0xA8E0, 0xA8FF, // Devanagari Extended
0xA900, 0xA92F, // Kayah Li
0xA930, 0xA95F, // Rejang
0xA960, 0xA97F, // Hangul Jamo Extended-A
0xA980, 0xA9DF, // Javanese
0xAA00, 0xAA5F, // Cham
0xAA60, 0xAA7F, // Myanmar Extended-A
0xAA80, 0xAADF, // Tai Viet
0xAB00, 0xAB2F, // Ethiopic Extended-A
0xABC0, 0xABFF, // Meetei Mayek
0xAC00, 0xD7AF, // Hangul Syllables
0xD7B0, 0xD7FF, // Hangul Jamo Extended-B
//0xD800, 0xDB7F, // High Surrogates
//0xDB80, 0xDBFF, // High Private Use Surrogates
//0xDC00, 0xDFFF, // Low Surrogates
0xE000, 0xF8FF, // Private Use Area
0xF900, 0xFAFF, // CJK Compatibility Ideographs
0xFB00, 0xFB4F, // Alphabetic Presentation Forms
0xFB50, 0xFDFF, // Arabic Presentation Forms-A
0xFE00, 0xFE0F, // Variation Selectors
0xFE10, 0xFE1F, // Vertical Forms
0xFE20, 0xFE2F, // Combining Half Marks
0xFE30, 0xFE4F, // CJK Compatibility Forms
0xFE50, 0xFE6F, // Small Form Variants
0xFE70, 0xFEFF, // Arabic Presentation Forms-B
0xFF00, 0xFFEF, // Halfwidth and Fullwidth Forms
0xFFF0, 0xFFFF, // Specials
0x10000, 0x1007F, // Linear B Syllabary
0x10080, 0x100FF, // Linear B Ideograms
0x10100, 0x1013F, // Aegean Numbers
0x10140, 0x1018F, // Ancient Greek Numbers
0x10190, 0x101CF, // Ancient Symbols
0x101D0, 0x101FF, // Phaistos Disc
0x10280, 0x1029F, // Lycian
0x102A0, 0x102DF, // Carian
0x10300, 0x1032F, // Old Italic
0x10330, 0x1034F, // Gothic
0x10380, 0x1039F, // Ugaritic
0x103A0, 0x103DF, // Old Persian
0x10400, 0x1044F, // Deseret
0x10450, 0x1047F, // Shavian
0x10480, 0x104AF, // Osmanya
0x10800, 0x1083F, // Cypriot Syllabary
0x10840, 0x1085F, // Imperial Aramaic
0x10900, 0x1091F, // Phoenician
0x10920, 0x1093F, // Lydian
0x10A00, 0x10A5F, // Kharoshthi
0x10A60, 0x10A7F, // Old South Arabian
0x10B00, 0x10B3F, // Avestan
0x10B40, 0x10B5F, // Inscriptional Parthian
0x10B60, 0x10B7F, // Inscriptional Pahlavi
0x10C00, 0x10C4F, // Old Turkic
0x10E60, 0x10E7F, // Rumi Numeral Symbols
0x11000, 0x1107F, // Brahmi
0x11080, 0x110CF, // Kaithi
0x12000, 0x123FF, // Cuneiform
0x12400, 0x1247F, // Cuneiform Numbers and Punctuation
0x13000, 0x1342F, // Egyptian Hieroglyphs
0x16800, 0x16A3F, // Bamum Supplement
0x1B000, 0x1B0FF, // Kana Supplement
0x1D000, 0x1D0FF, // Byzantine Musical Symbols
0x1D100, 0x1D1FF, // Musical Symbols
0x1D200, 0x1D24F, // Ancient Greek Musical Notation
0x1D300, 0x1D35F, // Tai Xuan Jing Symbols
0x1D360, 0x1D37F, // Counting Rod Numerals
0x1D400, 0x1D7FF, // Mathematical Alphanumeric Symbols
0x1F000, 0x1F02F, // Mahjong Tiles
0x1F030, 0x1F09F, // Domino Tiles
0x1F0A0, 0x1F0FF, // Playing Cards
0x1F100, 0x1F1FF, // Enclosed Alphanumeric Supplement
0x1F200, 0x1F2FF, // Enclosed Ideographic Supplement
0x1F300, 0x1F5FF, // Miscellaneous Symbols And Pictographs
0x1F600, 0x1F64F, // Emoticons
0x1F680, 0x1F6FF, // Transport And Map Symbols
0x1F700, 0x1F77F, // Alchemical Symbols
0x20000, 0x2A6DF, // CJK Unified Ideographs Extension B
0x2A700, 0x2B73F, // CJK Unified Ideographs Extension C
0x2B740, 0x2B81F, // CJK Unified Ideographs Extension D
0x2F800, 0x2FA1F, // CJK Compatibility Ideographs Supplement
0xE0000, 0xE007F, // Tags
0xE0100, 0xE01EF, // Variation Selectors Supplement
0xF0000, 0xFFFFF, // Supplementary Private Use Area-A
0x100000, 0x10FFFF, // Supplementary Private Use Area-B
0xFFFFFFFF
};
// Copyright (c) 2008-2010 Bjoern Hoehrmann <bjoern@hoehrmann.de>
// See http://bjoern.hoehrmann.de/utf-8/decoder/dfa/ for details.
#define UTF8_ACCEPT 0u
static const unsigned char utf8d[] = {
// The first part of the table maps bytes to character classes that
// to reduce the size of the transition table and create bitmasks.
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
8,8,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
10,3,3,3,3,3,3,3,3,3,3,3,3,4,3,3, 11,6,6,6,5,8,8,8,8,8,8,8,8,8,8,8,
// The second part is a transition table that maps a combination
// of a state of the automaton and a character class to a state.
0,12,24,36,60,96,84,12,12,12,48,72, 12,12,12,12,12,12,12,12,12,12,12,12,
12, 0,12,12,12,12,12, 0,12, 0,12,12, 12,24,12,12,12,12,12,24,12,24,12,12,
12,12,12,12,12,12,12,24,12,12,12,12, 12,24,12,12,12,12,12,12,12,24,12,12,
12,12,12,12,12,12,12,36,12,36,12,12, 12,36,12,12,12,12,12,36,12,36,12,12,
12,36,12,12,12,12,12,12,12,12,12,12,
};
static unsigned inline decode(unsigned* state, unsigned* codep, unsigned byte) {
unsigned type = utf8d[byte];
*codep = (*state != UTF8_ACCEPT) ?
(byte & 0x3fu) | (*codep << 6) :
(0xff >> type) & (byte);
*state = utf8d[256 + *state + type];
return *state;
}
//static bool IsUTF8(unsigned char* s) {
// unsigned codepoint, state = 0;
//
// while (*s)
// decode(&state, &codepoint, *s++);
//
// return state == UTF8_ACCEPT;
//}
TEST(EncodingsTest, UTF8) {
StringBuffer os, os2;
for (const unsigned* range = kCodepointRanges; *range != 0xFFFFFFFF; range += 2) {
for (unsigned codepoint = range[0]; codepoint <= range[1]; ++codepoint) {
os.Clear();
UTF8<>::Encode(os, codepoint);
const char* encodedStr = os.GetString();
// Decode with Hoehrmann
{
unsigned decodedCodepoint = 0;
unsigned state = 0;
unsigned decodedCount = 0;
for (const char* s = encodedStr; *s; ++s)
if (!decode(&state, &decodedCodepoint, static_cast<unsigned char>(*s))) {
EXPECT_EQ(codepoint, decodedCodepoint);
decodedCount++;
}
if (*encodedStr) { // This decoder cannot handle U+0000
EXPECT_EQ(1u, decodedCount); // Should only contain one code point
}
EXPECT_EQ(UTF8_ACCEPT, state);
if (UTF8_ACCEPT != state)
std::cout << std::hex << codepoint << " " << decodedCodepoint << std::endl;
}
// Decode
{
StringStream is(encodedStr);
unsigned decodedCodepoint;
bool result = UTF8<>::Decode(is, &decodedCodepoint);
EXPECT_TRUE(result);
EXPECT_EQ(codepoint, decodedCodepoint);
if (!result || codepoint != decodedCodepoint)
std::cout << std::hex << codepoint << " " << decodedCodepoint << std::endl;
}
// Validate
{
StringStream is(encodedStr);
os2.Clear();
bool result = UTF8<>::Validate(is, os2);
EXPECT_TRUE(result);
EXPECT_EQ(0, StrCmp(encodedStr, os2.GetString()));
}
}
}
}
TEST(EncodingsTest, UTF16) {
GenericStringBuffer<UTF16<> > os, os2;
GenericStringBuffer<UTF8<> > utf8os;
for (const unsigned* range = kCodepointRanges; *range != 0xFFFFFFFF; range += 2) {
for (unsigned codepoint = range[0]; codepoint <= range[1]; ++codepoint) {
os.Clear();
UTF16<>::Encode(os, codepoint);
const UTF16<>::Ch* encodedStr = os.GetString();
// Encode with Hoehrmann's code
if (codepoint != 0) // cannot handle U+0000
{
// encode with UTF8<> first
utf8os.Clear();
UTF8<>::Encode(utf8os, codepoint);
// transcode from UTF8 to UTF16 with Hoehrmann's code
unsigned decodedCodepoint = 0;
unsigned state = 0;
UTF16<>::Ch buffer[3], *p = &buffer[0];
for (const char* s = utf8os.GetString(); *s; ++s) {
if (!decode(&state, &decodedCodepoint, static_cast<unsigned char>(*s)))
break;
}
if (codepoint <= 0xFFFF)
*p++ = static_cast<UTF16<>::Ch>(decodedCodepoint);
else {
// Encode code points above U+FFFF as surrogate pair.
*p++ = static_cast<UTF16<>::Ch>(0xD7C0 + (decodedCodepoint >> 10));
*p++ = static_cast<UTF16<>::Ch>(0xDC00 + (decodedCodepoint & 0x3FF));
}
*p++ = '\0';
EXPECT_EQ(0, StrCmp(buffer, encodedStr));
}
// Decode
{
GenericStringStream<UTF16<> > is(encodedStr);
unsigned decodedCodepoint;
bool result = UTF16<>::Decode(is, &decodedCodepoint);
EXPECT_TRUE(result);
EXPECT_EQ(codepoint, decodedCodepoint);
if (!result || codepoint != decodedCodepoint)
std::cout << std::hex << codepoint << " " << decodedCodepoint << std::endl;
}
// Validate
{
GenericStringStream<UTF16<> > is(encodedStr);
os2.Clear();
bool result = UTF16<>::Validate(is, os2);
EXPECT_TRUE(result);
EXPECT_EQ(0, StrCmp(encodedStr, os2.GetString()));
}
}
}
}
TEST(EncodingsTest, UTF32) {
GenericStringBuffer<UTF32<> > os, os2;
for (const unsigned* range = kCodepointRanges; *range != 0xFFFFFFFF; range += 2) {
for (unsigned codepoint = range[0]; codepoint <= range[1]; ++codepoint) {
os.Clear();
UTF32<>::Encode(os, codepoint);
const UTF32<>::Ch* encodedStr = os.GetString();
// Decode
{
GenericStringStream<UTF32<> > is(encodedStr);
unsigned decodedCodepoint;
bool result = UTF32<>::Decode(is, &decodedCodepoint);
EXPECT_TRUE(result);
EXPECT_EQ(codepoint, decodedCodepoint);
if (!result || codepoint != decodedCodepoint)
std::cout << std::hex << codepoint << " " << decodedCodepoint << std::endl;
}
// Validate
{
GenericStringStream<UTF32<> > is(encodedStr);
os2.Clear();
bool result = UTF32<>::Validate(is, os2);
EXPECT_TRUE(result);
EXPECT_EQ(0, StrCmp(encodedStr, os2.GetString()));
}
}
}
}
TEST(EncodingsTest, ASCII) {
StringBuffer os, os2;
for (unsigned codepoint = 0; codepoint < 128; codepoint++) {
os.Clear();
ASCII<>::Encode(os, codepoint);
const ASCII<>::Ch* encodedStr = os.GetString();
{
StringStream is(encodedStr);
unsigned decodedCodepoint;
bool result = ASCII<>::Decode(is, &decodedCodepoint);
if (!result || codepoint != decodedCodepoint)
std::cout << std::hex << codepoint << " " << decodedCodepoint << std::endl;
}
// Validate
{
StringStream is(encodedStr);
os2.Clear();
bool result = ASCII<>::Validate(is, os2);
EXPECT_TRUE(result);
EXPECT_EQ(0, StrCmp(encodedStr, os2.GetString()));
}
}
}

View File

@ -1,112 +0,0 @@
// Tencent is pleased to support the open source community by making RapidJSON available.
//
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
//
// Licensed under the MIT License (the "License"); you may not use this file except
// in compliance with the License. You may obtain a copy of the License at
//
// http://opensource.org/licenses/MIT
//
// Unless required by applicable law or agreed to in writing, software distributed
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
// specific language governing permissions and limitations under the License.
#include "unittest.h"
#include "rapidjson/filereadstream.h"
#include "rapidjson/filewritestream.h"
#include "rapidjson/encodedstream.h"
using namespace rapidjson;
class FileStreamTest : public ::testing::Test {
public:
FileStreamTest() : filename_(), json_(), length_() {}
virtual ~FileStreamTest();
virtual void SetUp() {
const char *paths[] = {
"data/sample.json",
"bin/data/sample.json",
"../bin/data/sample.json",
"../../bin/data/sample.json",
"../../../bin/data/sample.json"
};
FILE* fp = 0;
for (size_t i = 0; i < sizeof(paths) / sizeof(paths[0]); i++) {
fp = fopen(paths[i], "rb");
if (fp) {
filename_ = paths[i];
break;
}
}
ASSERT_TRUE(fp != 0);
fseek(fp, 0, SEEK_END);
length_ = static_cast<size_t>(ftell(fp));
fseek(fp, 0, SEEK_SET);
json_ = static_cast<char*>(malloc(length_ + 1));
size_t readLength = fread(json_, 1, length_, fp);
json_[readLength] = '\0';
fclose(fp);
}
virtual void TearDown() {
free(json_);
json_ = 0;
}
private:
FileStreamTest(const FileStreamTest&);
FileStreamTest& operator=(const FileStreamTest&);
protected:
const char* filename_;
char *json_;
size_t length_;
};
FileStreamTest::~FileStreamTest() {}
TEST_F(FileStreamTest, FileReadStream) {
FILE *fp = fopen(filename_, "rb");
ASSERT_TRUE(fp != 0);
char buffer[65536];
FileReadStream s(fp, buffer, sizeof(buffer));
for (size_t i = 0; i < length_; i++) {
EXPECT_EQ(json_[i], s.Peek());
EXPECT_EQ(json_[i], s.Peek()); // 2nd time should be the same
EXPECT_EQ(json_[i], s.Take());
}
EXPECT_EQ(length_, s.Tell());
EXPECT_EQ('\0', s.Peek());
fclose(fp);
}
TEST_F(FileStreamTest, FileWriteStream) {
char filename[L_tmpnam];
FILE* fp = TempFile(filename);
char buffer[65536];
FileWriteStream os(fp, buffer, sizeof(buffer));
for (size_t i = 0; i < length_; i++)
os.Put(json_[i]);
os.Flush();
fclose(fp);
// Read it back to verify
fp = fopen(filename, "rb");
FileReadStream is(fp, buffer, sizeof(buffer));
for (size_t i = 0; i < length_; i++)
EXPECT_EQ(json_[i], is.Take());
EXPECT_EQ(length_, is.Tell());
fclose(fp);
//std::cout << filename << std::endl;
remove(filename);
}

View File

@ -1,227 +0,0 @@
// Tencent is pleased to support the open source community by making RapidJSON available.
//
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
//
// Licensed under the MIT License (the "License"); you may not use this file except
// in compliance with the License. You may obtain a copy of the License at
//
// http://opensource.org/licenses/MIT
//
// Unless required by applicable law or agreed to in writing, software distributed
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
// specific language governing permissions and limitations under the License.
#include "unittest.h"
// Using forward declared types here.
#include "rapidjson/fwd.h"
#ifdef __GNUC__
RAPIDJSON_DIAG_PUSH
RAPIDJSON_DIAG_OFF(effc++)
#endif
using namespace rapidjson;
struct Foo {
Foo();
~Foo();
// encodings.h
UTF8<char>* utf8;
UTF16<wchar_t>* utf16;
UTF16BE<wchar_t>* utf16be;
UTF16LE<wchar_t>* utf16le;
UTF32<unsigned>* utf32;
UTF32BE<unsigned>* utf32be;
UTF32LE<unsigned>* utf32le;
ASCII<char>* ascii;
AutoUTF<unsigned>* autoutf;
Transcoder<UTF8<char>, UTF8<char> >* transcoder;
// allocators.h
CrtAllocator* crtallocator;
MemoryPoolAllocator<CrtAllocator>* memorypoolallocator;
// stream.h
StringStream* stringstream;
InsituStringStream* insitustringstream;
// stringbuffer.h
StringBuffer* stringbuffer;
// // filereadstream.h
// FileReadStream* filereadstream;
// // filewritestream.h
// FileWriteStream* filewritestream;
// memorybuffer.h
MemoryBuffer* memorybuffer;
// memorystream.h
MemoryStream* memorystream;
// reader.h
BaseReaderHandler<UTF8<char>, void>* basereaderhandler;
Reader* reader;
// writer.h
Writer<StringBuffer, UTF8<char>, UTF8<char>, CrtAllocator, 0>* writer;
// prettywriter.h
PrettyWriter<StringBuffer, UTF8<char>, UTF8<char>, CrtAllocator, 0>* prettywriter;
// document.h
Value* value;
Document* document;
// pointer.h
Pointer* pointer;
// schema.h
SchemaDocument* schemadocument;
SchemaValidator* schemavalidator;
// char buffer[16];
};
// Using type definitions here.
#include "rapidjson/stringbuffer.h"
#include "rapidjson/filereadstream.h"
#include "rapidjson/filewritestream.h"
#include "rapidjson/memorybuffer.h"
#include "rapidjson/memorystream.h"
#include "rapidjson/document.h" // -> reader.h
#include "rapidjson/writer.h"
#include "rapidjson/prettywriter.h"
#include "rapidjson/schema.h" // -> pointer.h
Foo::Foo() :
// encodings.h
utf8(RAPIDJSON_NEW(UTF8<>)),
utf16(RAPIDJSON_NEW(UTF16<>)),
utf16be(RAPIDJSON_NEW(UTF16BE<>)),
utf16le(RAPIDJSON_NEW(UTF16LE<>)),
utf32(RAPIDJSON_NEW(UTF32<>)),
utf32be(RAPIDJSON_NEW(UTF32BE<>)),
utf32le(RAPIDJSON_NEW(UTF32LE<>)),
ascii(RAPIDJSON_NEW(ASCII<>)),
autoutf(RAPIDJSON_NEW(AutoUTF<unsigned>)),
transcoder(RAPIDJSON_NEW((Transcoder<UTF8<>, UTF8<> >))),
// allocators.h
crtallocator(RAPIDJSON_NEW(CrtAllocator)),
memorypoolallocator(RAPIDJSON_NEW(MemoryPoolAllocator<>)),
// stream.h
stringstream(RAPIDJSON_NEW(StringStream(0))),
insitustringstream(RAPIDJSON_NEW(InsituStringStream(0))),
// stringbuffer.h
stringbuffer(RAPIDJSON_NEW(StringBuffer)),
// // filereadstream.h
// filereadstream(RAPIDJSON_NEW(FileReadStream(stdout, buffer, sizeof(buffer)))),
// // filewritestream.h
// filewritestream(RAPIDJSON_NEW(FileWriteStream(stdout, buffer, sizeof(buffer)))),
// memorybuffer.h
memorybuffer(RAPIDJSON_NEW(MemoryBuffer)),
// memorystream.h
memorystream(RAPIDJSON_NEW(MemoryStream(0, 0))),
// reader.h
basereaderhandler(RAPIDJSON_NEW((BaseReaderHandler<UTF8<>, void>))),
reader(RAPIDJSON_NEW(Reader)),
// writer.h
writer(RAPIDJSON_NEW((Writer<StringBuffer>))),
// prettywriter.h
prettywriter(RAPIDJSON_NEW((PrettyWriter<StringBuffer>))),
// document.h
value(RAPIDJSON_NEW(Value)),
document(RAPIDJSON_NEW(Document)),
// pointer.h
pointer(RAPIDJSON_NEW(Pointer)),
// schema.h
schemadocument(RAPIDJSON_NEW(SchemaDocument(*document))),
schemavalidator(RAPIDJSON_NEW(SchemaValidator(*schemadocument)))
{
}
Foo::~Foo() {
// encodings.h
RAPIDJSON_DELETE(utf8);
RAPIDJSON_DELETE(utf16);
RAPIDJSON_DELETE(utf16be);
RAPIDJSON_DELETE(utf16le);
RAPIDJSON_DELETE(utf32);
RAPIDJSON_DELETE(utf32be);
RAPIDJSON_DELETE(utf32le);
RAPIDJSON_DELETE(ascii);
RAPIDJSON_DELETE(autoutf);
RAPIDJSON_DELETE(transcoder);
// allocators.h
RAPIDJSON_DELETE(crtallocator);
RAPIDJSON_DELETE(memorypoolallocator);
// stream.h
RAPIDJSON_DELETE(stringstream);
RAPIDJSON_DELETE(insitustringstream);
// stringbuffer.h
RAPIDJSON_DELETE(stringbuffer);
// // filereadstream.h
// RAPIDJSON_DELETE(filereadstream);
// // filewritestream.h
// RAPIDJSON_DELETE(filewritestream);
// memorybuffer.h
RAPIDJSON_DELETE(memorybuffer);
// memorystream.h
RAPIDJSON_DELETE(memorystream);
// reader.h
RAPIDJSON_DELETE(basereaderhandler);
RAPIDJSON_DELETE(reader);
// writer.h
RAPIDJSON_DELETE(writer);
// prettywriter.h
RAPIDJSON_DELETE(prettywriter);
// document.h
RAPIDJSON_DELETE(value);
RAPIDJSON_DELETE(document);
// pointer.h
RAPIDJSON_DELETE(pointer);
// schema.h
RAPIDJSON_DELETE(schemadocument);
RAPIDJSON_DELETE(schemavalidator);
}
TEST(Fwd, Fwd) {
Foo f;
}
#ifdef __GNUC__
RAPIDJSON_DIAG_POP
#endif

View File

@ -1,181 +0,0 @@
// Tencent is pleased to support the open source community by making RapidJSON available.
//
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
//
// Licensed under the MIT License (the "License"); you may not use this file except
// in compliance with the License. You may obtain a copy of the License at
//
// http://opensource.org/licenses/MIT
//
// Unless required by applicable law or agreed to in writing, software distributed
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
// specific language governing permissions and limitations under the License.
#include "unittest.h"
#include "rapidjson/istreamwrapper.h"
#include "rapidjson/encodedstream.h"
#include "rapidjson/document.h"
#include <sstream>
#include <fstream>
#ifdef _MSC_VER
RAPIDJSON_DIAG_PUSH
RAPIDJSON_DIAG_OFF(4702) // unreachable code
#endif
using namespace rapidjson;
using namespace std;
template <typename StringStreamType>
static void TestStringStream() {
typedef typename StringStreamType::char_type Ch;
{
StringStreamType iss;
BasicIStreamWrapper<StringStreamType> is(iss);
EXPECT_EQ(0, is.Tell());
if (sizeof(Ch) == 1) {
EXPECT_EQ(0, is.Peek4());
EXPECT_EQ(0, is.Tell());
}
EXPECT_EQ(0, is.Peek());
EXPECT_EQ(0, is.Take());
EXPECT_EQ(0, is.Tell());
}
{
Ch s[] = { 'A', 'B', 'C', '\0' };
StringStreamType iss(s);
BasicIStreamWrapper<StringStreamType> is(iss);
EXPECT_EQ(0, is.Tell());
if (sizeof(Ch) == 1) {
EXPECT_EQ(0, is.Peek4()); // less than 4 bytes
}
for (int i = 0; i < 3; i++) {
EXPECT_EQ(static_cast<size_t>(i), is.Tell());
EXPECT_EQ('A' + i, is.Peek());
EXPECT_EQ('A' + i, is.Peek());
EXPECT_EQ('A' + i, is.Take());
}
EXPECT_EQ(3, is.Tell());
EXPECT_EQ(0, is.Peek());
EXPECT_EQ(0, is.Take());
}
{
Ch s[] = { 'A', 'B', 'C', 'D', 'E', '\0' };
StringStreamType iss(s);
BasicIStreamWrapper<StringStreamType> is(iss);
if (sizeof(Ch) == 1) {
const Ch* c = is.Peek4();
for (int i = 0; i < 4; i++)
EXPECT_EQ('A' + i, c[i]);
EXPECT_EQ(0, is.Tell());
}
for (int i = 0; i < 5; i++) {
EXPECT_EQ(static_cast<size_t>(i), is.Tell());
EXPECT_EQ('A' + i, is.Peek());
EXPECT_EQ('A' + i, is.Peek());
EXPECT_EQ('A' + i, is.Take());
}
EXPECT_EQ(5, is.Tell());
EXPECT_EQ(0, is.Peek());
EXPECT_EQ(0, is.Take());
}
}
TEST(IStreamWrapper, istringstream) {
TestStringStream<istringstream>();
}
TEST(IStreamWrapper, stringstream) {
TestStringStream<stringstream>();
}
TEST(IStreamWrapper, wistringstream) {
TestStringStream<wistringstream>();
}
TEST(IStreamWrapper, wstringstream) {
TestStringStream<wstringstream>();
}
template <typename FileStreamType>
static bool Open(FileStreamType& fs, const char* filename) {
const char *paths[] = {
"encodings",
"bin/encodings",
"../bin/encodings",
"../../bin/encodings",
"../../../bin/encodings"
};
char buffer[1024];
for (size_t i = 0; i < sizeof(paths) / sizeof(paths[0]); i++) {
sprintf(buffer, "%s/%s", paths[i], filename);
fs.open(buffer, ios_base::in | ios_base::binary);
if (fs.is_open())
return true;
}
return false;
}
TEST(IStreamWrapper, ifstream) {
ifstream ifs;
ASSERT_TRUE(Open(ifs, "utf8bom.json"));
IStreamWrapper isw(ifs);
EncodedInputStream<UTF8<>, IStreamWrapper> eis(isw);
Document d;
EXPECT_TRUE(!d.ParseStream(eis).HasParseError());
EXPECT_TRUE(d.IsObject());
EXPECT_EQ(5, d.MemberCount());
}
TEST(IStreamWrapper, fstream) {
fstream fs;
ASSERT_TRUE(Open(fs, "utf8bom.json"));
IStreamWrapper isw(fs);
EncodedInputStream<UTF8<>, IStreamWrapper> eis(isw);
Document d;
EXPECT_TRUE(!d.ParseStream(eis).HasParseError());
EXPECT_TRUE(d.IsObject());
EXPECT_EQ(5, d.MemberCount());
}
// wifstream/wfstream only works on C++11 with codecvt_utf16
// But many C++11 library still not have it.
#if 0
#include <codecvt>
TEST(IStreamWrapper, wifstream) {
wifstream ifs;
ASSERT_TRUE(Open(ifs, "utf16bebom.json"));
ifs.imbue(std::locale(ifs.getloc(),
new std::codecvt_utf16<wchar_t, 0x10ffff, std::consume_header>));
WIStreamWrapper isw(ifs);
GenericDocument<UTF16<> > d;
d.ParseStream<kParseDefaultFlags, UTF16<>, WIStreamWrapper>(isw);
EXPECT_TRUE(!d.HasParseError());
EXPECT_TRUE(d.IsObject());
EXPECT_EQ(5, d.MemberCount());
}
TEST(IStreamWrapper, wfstream) {
wfstream fs;
ASSERT_TRUE(Open(fs, "utf16bebom.json"));
fs.imbue(std::locale(fs.getloc(),
new std::codecvt_utf16<wchar_t, 0x10ffff, std::consume_header>));
WIStreamWrapper isw(fs);
GenericDocument<UTF16<> > d;
d.ParseStream<kParseDefaultFlags, UTF16<>, WIStreamWrapper>(isw);
EXPECT_TRUE(!d.HasParseError());
EXPECT_TRUE(d.IsObject());
EXPECT_EQ(5, d.MemberCount());
}
#endif
#ifdef _MSC_VER
RAPIDJSON_DIAG_POP
#endif

View File

@ -1,160 +0,0 @@
// Tencent is pleased to support the open source community by making RapidJSON available.
//
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
//
// Licensed under the MIT License (the "License"); you may not use this file except
// in compliance with the License. You may obtain a copy of the License at
//
// http://opensource.org/licenses/MIT
//
// Unless required by applicable law or agreed to in writing, software distributed
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
// specific language governing permissions and limitations under the License.
#include "unittest.h"
#include "rapidjson/internal/itoa.h"
#ifdef __GNUC__
RAPIDJSON_DIAG_PUSH
RAPIDJSON_DIAG_OFF(type-limits)
#endif
using namespace rapidjson::internal;
template <typename T>
struct Traits {
};
template <>
struct Traits<uint32_t> {
enum { kBufferSize = 11 };
enum { kMaxDigit = 10 };
static uint32_t Negate(uint32_t x) { return x; }
};
template <>
struct Traits<int32_t> {
enum { kBufferSize = 12 };
enum { kMaxDigit = 10 };
static int32_t Negate(int32_t x) { return -x; }
};
template <>
struct Traits<uint64_t> {
enum { kBufferSize = 21 };
enum { kMaxDigit = 20 };
static uint64_t Negate(uint64_t x) { return x; }
};
template <>
struct Traits<int64_t> {
enum { kBufferSize = 22 };
enum { kMaxDigit = 20 };
static int64_t Negate(int64_t x) { return -x; }
};
template <typename T>
static void VerifyValue(T value, void(*f)(T, char*), char* (*g)(T, char*)) {
char buffer1[Traits<T>::kBufferSize];
char buffer2[Traits<T>::kBufferSize];
f(value, buffer1);
*g(value, buffer2) = '\0';
EXPECT_STREQ(buffer1, buffer2);
}
template <typename T>
static void Verify(void(*f)(T, char*), char* (*g)(T, char*)) {
// Boundary cases
VerifyValue<T>(0, f, g);
VerifyValue<T>(std::numeric_limits<T>::min(), f, g);
VerifyValue<T>(std::numeric_limits<T>::max(), f, g);
// 2^n - 1, 2^n, 10^n - 1, 10^n until overflow
for (uint32_t power = 2; power <= 10; power += 8) {
T i = 1, last;
do {
VerifyValue<T>(i - 1, f, g);
VerifyValue<T>(i, f, g);
if (std::numeric_limits<T>::min() < 0) {
VerifyValue<T>(Traits<T>::Negate(i), f, g);
VerifyValue<T>(Traits<T>::Negate(i + 1), f, g);
}
last = i;
if (i > static_cast<T>(std::numeric_limits<T>::max() / static_cast<T>(power)))
break;
i *= power;
} while (last < i);
}
}
static void u32toa_naive(uint32_t value, char* buffer) {
char temp[10];
char *p = temp;
do {
*p++ = static_cast<char>(char(value % 10) + '0');
value /= 10;
} while (value > 0);
do {
*buffer++ = *--p;
} while (p != temp);
*buffer = '\0';
}
static void i32toa_naive(int32_t value, char* buffer) {
uint32_t u = static_cast<uint32_t>(value);
if (value < 0) {
*buffer++ = '-';
u = ~u + 1;
}
u32toa_naive(u, buffer);
}
static void u64toa_naive(uint64_t value, char* buffer) {
char temp[20];
char *p = temp;
do {
*p++ = static_cast<char>(char(value % 10) + '0');
value /= 10;
} while (value > 0);
do {
*buffer++ = *--p;
} while (p != temp);
*buffer = '\0';
}
static void i64toa_naive(int64_t value, char* buffer) {
uint64_t u = static_cast<uint64_t>(value);
if (value < 0) {
*buffer++ = '-';
u = ~u + 1;
}
u64toa_naive(u, buffer);
}
TEST(itoa, u32toa) {
Verify(u32toa_naive, u32toa);
}
TEST(itoa, i32toa) {
Verify(i32toa_naive, i32toa);
}
TEST(itoa, u64toa) {
Verify(u64toa_naive, u64toa);
}
TEST(itoa, i64toa) {
Verify(i64toa_naive, i64toa);
}
#ifdef __GNUC__
RAPIDJSON_DIAG_POP
#endif

View File

@ -1,99 +0,0 @@
// Tencent is pleased to support the open source community by making RapidJSON available.
//
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
//
// Licensed under the MIT License (the "License"); you may not use this file except
// in compliance with the License. You may obtain a copy of the License at
//
// http://opensource.org/licenses/MIT
//
// Unless required by applicable law or agreed to in writing, software distributed
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
// specific language governing permissions and limitations under the License.
#include "unittest.h"
#include "rapidjson/document.h"
using namespace rapidjson;
static char* ReadFile(const char* filename, size_t& length) {
const char *paths[] = {
"jsonchecker",
"bin/jsonchecker",
"../bin/jsonchecker",
"../../bin/jsonchecker",
"../../../bin/jsonchecker"
};
char buffer[1024];
FILE *fp = 0;
for (size_t i = 0; i < sizeof(paths) / sizeof(paths[0]); i++) {
sprintf(buffer, "%s/%s", paths[i], filename);
fp = fopen(buffer, "rb");
if (fp)
break;
}
if (!fp)
return 0;
fseek(fp, 0, SEEK_END);
length = static_cast<size_t>(ftell(fp));
fseek(fp, 0, SEEK_SET);
char* json = static_cast<char*>(malloc(length + 1));
size_t readLength = fread(json, 1, length, fp);
json[readLength] = '\0';
fclose(fp);
return json;
}
TEST(JsonChecker, Reader) {
char filename[256];
// jsonchecker/failXX.json
for (int i = 1; i <= 33; i++) {
if (i == 1) // fail1.json is valid in rapidjson, which has no limitation on type of root element (RFC 7159).
continue;
if (i == 18) // fail18.json is valid in rapidjson, which has no limitation on depth of nesting.
continue;
sprintf(filename, "fail%d.json", i);
size_t length;
char* json = ReadFile(filename, length);
if (!json) {
printf("jsonchecker file %s not found", filename);
ADD_FAILURE();
continue;
}
GenericDocument<UTF8<>, CrtAllocator> document; // Use Crt allocator to check exception-safety (no memory leak)
document.Parse(json);
EXPECT_TRUE(document.HasParseError());
document.Parse<kParseIterativeFlag>(json);
EXPECT_TRUE(document.HasParseError());
free(json);
}
// passX.json
for (int i = 1; i <= 3; i++) {
sprintf(filename, "pass%d.json", i);
size_t length;
char* json = ReadFile(filename, length);
if (!json) {
printf("jsonchecker file %s not found", filename);
continue;
}
GenericDocument<UTF8<>, CrtAllocator> document; // Use Crt allocator to check exception-safety (no memory leak)
document.Parse(json);
EXPECT_FALSE(document.HasParseError());
document.Parse<kParseIterativeFlag>(json);
EXPECT_FALSE(document.HasParseError());
free(json);
}
}

View File

@ -1,70 +0,0 @@
// Tencent is pleased to support the open source community by making RapidJSON available.
//
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
//
// Licensed under the MIT License (the "License"); you may not use this file except
// in compliance with the License. You may obtain a copy of the License at
//
// http://opensource.org/licenses/MIT
//
// Unless required by applicable law or agreed to in writing, software distributed
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
// specific language governing permissions and limitations under the License.
#include "unittest.h"
// test another instantiation of RapidJSON in a different namespace
#define RAPIDJSON_NAMESPACE my::rapid::json
#define RAPIDJSON_NAMESPACE_BEGIN namespace my { namespace rapid { namespace json {
#define RAPIDJSON_NAMESPACE_END } } }
// include lots of RapidJSON files
#include "rapidjson/document.h"
#include "rapidjson/writer.h"
#include "rapidjson/filereadstream.h"
#include "rapidjson/filewritestream.h"
#include "rapidjson/encodedstream.h"
#include "rapidjson/stringbuffer.h"
static const char json[] = "{\"hello\":\"world\",\"t\":true,\"f\":false,\"n\":null,\"i\":123,\"pi\":3.1416,\"a\":[1,2,3,4]}";
TEST(NamespaceTest,Using) {
using namespace RAPIDJSON_NAMESPACE;
typedef GenericDocument<UTF8<>, CrtAllocator> DocumentType;
DocumentType doc;
doc.Parse(json);
EXPECT_TRUE(!doc.HasParseError());
}
TEST(NamespaceTest,Direct) {
typedef RAPIDJSON_NAMESPACE::Document Document;
typedef RAPIDJSON_NAMESPACE::Reader Reader;
typedef RAPIDJSON_NAMESPACE::StringStream StringStream;
typedef RAPIDJSON_NAMESPACE::StringBuffer StringBuffer;
typedef RAPIDJSON_NAMESPACE::Writer<StringBuffer> WriterType;
StringStream s(json);
StringBuffer buffer;
WriterType writer(buffer);
buffer.ShrinkToFit();
Reader reader;
reader.Parse(s, writer);
EXPECT_STREQ(json, buffer.GetString());
EXPECT_EQ(sizeof(json)-1, buffer.GetSize());
EXPECT_TRUE(writer.IsComplete());
Document doc;
doc.Parse(buffer.GetString());
EXPECT_TRUE(!doc.HasParseError());
buffer.Clear();
writer.Reset(buffer);
doc.Accept(writer);
EXPECT_STREQ(json, buffer.GetString());
EXPECT_TRUE(writer.IsComplete());
}

View File

@ -1,91 +0,0 @@
// Tencent is pleased to support the open source community by making RapidJSON available.
//
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
//
// Licensed under the MIT License (the "License"); you may not use this file except
// in compliance with the License. You may obtain a copy of the License at
//
// http://opensource.org/licenses/MIT
//
// Unless required by applicable law or agreed to in writing, software distributed
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
// specific language governing permissions and limitations under the License.
#include "unittest.h"
#include "rapidjson/ostreamwrapper.h"
#include "rapidjson/encodedstream.h"
#include "rapidjson/document.h"
#include <sstream>
#include <fstream>
using namespace rapidjson;
using namespace std;
template <typename StringStreamType>
static void TestStringStream() {
typedef typename StringStreamType::char_type Ch;
Ch s[] = { 'A', 'B', 'C', '\0' };
StringStreamType oss(s);
BasicOStreamWrapper<StringStreamType> os(oss);
for (size_t i = 0; i < 3; i++)
os.Put(s[i]);
os.Flush();
for (size_t i = 0; i < 3; i++)
EXPECT_EQ(s[i], oss.str()[i]);
}
TEST(OStreamWrapper, ostringstream) {
TestStringStream<ostringstream>();
}
TEST(OStreamWrapper, stringstream) {
TestStringStream<stringstream>();
}
TEST(OStreamWrapper, wostringstream) {
TestStringStream<wostringstream>();
}
TEST(OStreamWrapper, wstringstream) {
TestStringStream<wstringstream>();
}
TEST(OStreamWrapper, cout) {
OStreamWrapper os(cout);
const char* s = "Hello World!\n";
while (*s)
os.Put(*s++);
os.Flush();
}
template <typename FileStreamType>
static void TestFileStream() {
char filename[L_tmpnam];
FILE* fp = TempFile(filename);
fclose(fp);
const char* s = "Hello World!\n";
{
ofstream ofs(filename, ios::out | ios::binary);
BasicOStreamWrapper<ofstream> osw(ofs);
for (const char* p = s; *p; p++)
osw.Put(*p);
osw.Flush();
}
fp = fopen(filename, "r");
for (const char* p = s; *p; p++)
EXPECT_EQ(*p, static_cast<char>(fgetc(fp)));
fclose(fp);
}
TEST(OStreamWrapper, ofstream) {
TestFileStream<ofstream>();
}
TEST(OStreamWrapper, fstream) {
TestFileStream<fstream>();
}

File diff suppressed because it is too large Load Diff

View File

@ -1,203 +0,0 @@
// Tencent is pleased to support the open source community by making RapidJSON available.
//
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
//
// Licensed under the MIT License (the "License"); you may not use this file except
// in compliance with the License. You may obtain a copy of the License at
//
// http://opensource.org/licenses/MIT
//
// Unless required by applicable law or agreed to in writing, software distributed
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
// specific language governing permissions and limitations under the License.
#include "unittest.h"
#include "rapidjson/reader.h"
#include "rapidjson/prettywriter.h"
#include "rapidjson/stringbuffer.h"
#include "rapidjson/filewritestream.h"
using namespace rapidjson;
static const char kJson[] = "{\"hello\":\"world\",\"t\":true,\"f\":false,\"n\":null,\"i\":123,\"pi\":3.1416,\"a\":[1,2,3,-1],\"u64\":1234567890123456789,\"i64\":-1234567890123456789}";
static const char kPrettyJson[] =
"{\n"
" \"hello\": \"world\",\n"
" \"t\": true,\n"
" \"f\": false,\n"
" \"n\": null,\n"
" \"i\": 123,\n"
" \"pi\": 3.1416,\n"
" \"a\": [\n"
" 1,\n"
" 2,\n"
" 3,\n"
" -1\n"
" ],\n"
" \"u64\": 1234567890123456789,\n"
" \"i64\": -1234567890123456789\n"
"}";
static const char kPrettyJson_FormatOptions_SLA[] =
"{\n"
" \"hello\": \"world\",\n"
" \"t\": true,\n"
" \"f\": false,\n"
" \"n\": null,\n"
" \"i\": 123,\n"
" \"pi\": 3.1416,\n"
" \"a\": [1, 2, 3, -1],\n"
" \"u64\": 1234567890123456789,\n"
" \"i64\": -1234567890123456789\n"
"}";
TEST(PrettyWriter, Basic) {
StringBuffer buffer;
PrettyWriter<StringBuffer> writer(buffer);
Reader reader;
StringStream s(kJson);
reader.Parse(s, writer);
EXPECT_STREQ(kPrettyJson, buffer.GetString());
}
TEST(PrettyWriter, FormatOptions) {
StringBuffer buffer;
PrettyWriter<StringBuffer> writer(buffer);
writer.SetFormatOptions(kFormatSingleLineArray);
Reader reader;
StringStream s(kJson);
reader.Parse(s, writer);
EXPECT_STREQ(kPrettyJson_FormatOptions_SLA, buffer.GetString());
}
TEST(PrettyWriter, SetIndent) {
StringBuffer buffer;
PrettyWriter<StringBuffer> writer(buffer);
writer.SetIndent('\t', 1);
Reader reader;
StringStream s(kJson);
reader.Parse(s, writer);
EXPECT_STREQ(
"{\n"
"\t\"hello\": \"world\",\n"
"\t\"t\": true,\n"
"\t\"f\": false,\n"
"\t\"n\": null,\n"
"\t\"i\": 123,\n"
"\t\"pi\": 3.1416,\n"
"\t\"a\": [\n"
"\t\t1,\n"
"\t\t2,\n"
"\t\t3,\n"
"\t\t-1\n"
"\t],\n"
"\t\"u64\": 1234567890123456789,\n"
"\t\"i64\": -1234567890123456789\n"
"}",
buffer.GetString());
}
TEST(PrettyWriter, String) {
StringBuffer buffer;
PrettyWriter<StringBuffer> writer(buffer);
EXPECT_TRUE(writer.StartArray());
EXPECT_TRUE(writer.String("Hello\n"));
EXPECT_TRUE(writer.EndArray());
EXPECT_STREQ("[\n \"Hello\\n\"\n]", buffer.GetString());
}
#if RAPIDJSON_HAS_STDSTRING
TEST(PrettyWriter, String_STDSTRING) {
StringBuffer buffer;
PrettyWriter<StringBuffer> writer(buffer);
EXPECT_TRUE(writer.StartArray());
EXPECT_TRUE(writer.String(std::string("Hello\n")));
EXPECT_TRUE(writer.EndArray());
EXPECT_STREQ("[\n \"Hello\\n\"\n]", buffer.GetString());
}
#endif
#include <sstream>
class OStreamWrapper {
public:
typedef char Ch;
OStreamWrapper(std::ostream& os) : os_(os) {}
Ch Peek() const { assert(false); return '\0'; }
Ch Take() { assert(false); return '\0'; }
size_t Tell() const { return 0; }
Ch* PutBegin() { assert(false); return 0; }
void Put(Ch c) { os_.put(c); }
void Flush() { os_.flush(); }
size_t PutEnd(Ch*) { assert(false); return 0; }
private:
OStreamWrapper(const OStreamWrapper&);
OStreamWrapper& operator=(const OStreamWrapper&);
std::ostream& os_;
};
// For covering PutN() generic version
TEST(PrettyWriter, OStreamWrapper) {
StringStream s(kJson);
std::stringstream ss;
OStreamWrapper os(ss);
PrettyWriter<OStreamWrapper> writer(os);
Reader reader;
reader.Parse(s, writer);
std::string actual = ss.str();
EXPECT_STREQ(kPrettyJson, actual.c_str());
}
// 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 = static_cast<size_t>(ftell(fp));
fseek(fp, 0, SEEK_SET);
char* json = static_cast<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(PrettyWriter, RawValue) {
StringBuffer buffer;
PrettyWriter<StringBuffer> writer(buffer);
writer.StartObject();
writer.Key("a");
writer.Int(1);
writer.Key("raw");
const char json[] = "[\"Hello\\nWorld\", 123.456]";
writer.RawValue(json, strlen(json), kArrayType);
writer.EndObject();
EXPECT_TRUE(writer.IsComplete());
EXPECT_STREQ(
"{\n"
" \"a\": 1,\n"
" \"raw\": [\"Hello\\nWorld\", 123.456]\n" // no indentation within raw value
"}",
buffer.GetString());
}

File diff suppressed because it is too large Load Diff

View File

@ -1,592 +0,0 @@
// Tencent is pleased to support the open source community by making RapidJSON available.
//
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
//
// Licensed under the MIT License (the "License"); you may not use this file except
// in compliance with the License. You may obtain a copy of the License at
//
// http://opensource.org/licenses/MIT
//
// Unless required by applicable law or agreed to in writing, software distributed
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
// specific language governing permissions and limitations under the License.
#include "unittest.h"
#include "rapidjson/internal/regex.h"
using namespace rapidjson::internal;
TEST(Regex, Single) {
Regex re("a");
ASSERT_TRUE(re.IsValid());
EXPECT_TRUE(re.Match("a"));
EXPECT_FALSE(re.Match(""));
EXPECT_FALSE(re.Match("b"));
}
TEST(Regex, Concatenation) {
Regex re("abc");
ASSERT_TRUE(re.IsValid());
EXPECT_TRUE(re.Match("abc"));
EXPECT_FALSE(re.Match(""));
EXPECT_FALSE(re.Match("a"));
EXPECT_FALSE(re.Match("b"));
EXPECT_FALSE(re.Match("ab"));
EXPECT_FALSE(re.Match("abcd"));
}
TEST(Regex, Alternation1) {
Regex re("abab|abbb");
ASSERT_TRUE(re.IsValid());
EXPECT_TRUE(re.Match("abab"));
EXPECT_TRUE(re.Match("abbb"));
EXPECT_FALSE(re.Match(""));
EXPECT_FALSE(re.Match("ab"));
EXPECT_FALSE(re.Match("ababa"));
EXPECT_FALSE(re.Match("abb"));
EXPECT_FALSE(re.Match("abbbb"));
}
TEST(Regex, Alternation2) {
Regex re("a|b|c");
ASSERT_TRUE(re.IsValid());
EXPECT_TRUE(re.Match("a"));
EXPECT_TRUE(re.Match("b"));
EXPECT_TRUE(re.Match("c"));
EXPECT_FALSE(re.Match(""));
EXPECT_FALSE(re.Match("aa"));
EXPECT_FALSE(re.Match("ab"));
}
TEST(Regex, Parenthesis1) {
Regex re("(ab)c");
ASSERT_TRUE(re.IsValid());
EXPECT_TRUE(re.Match("abc"));
EXPECT_FALSE(re.Match(""));
EXPECT_FALSE(re.Match("a"));
EXPECT_FALSE(re.Match("b"));
EXPECT_FALSE(re.Match("ab"));
EXPECT_FALSE(re.Match("abcd"));
}
TEST(Regex, Parenthesis2) {
Regex re("a(bc)");
ASSERT_TRUE(re.IsValid());
EXPECT_TRUE(re.Match("abc"));
EXPECT_FALSE(re.Match(""));
EXPECT_FALSE(re.Match("a"));
EXPECT_FALSE(re.Match("b"));
EXPECT_FALSE(re.Match("ab"));
EXPECT_FALSE(re.Match("abcd"));
}
TEST(Regex, Parenthesis3) {
Regex re("(a|b)(c|d)");
ASSERT_TRUE(re.IsValid());
EXPECT_TRUE(re.Match("ac"));
EXPECT_TRUE(re.Match("ad"));
EXPECT_TRUE(re.Match("bc"));
EXPECT_TRUE(re.Match("bd"));
EXPECT_FALSE(re.Match(""));
EXPECT_FALSE(re.Match("ab"));
EXPECT_FALSE(re.Match("cd"));
}
TEST(Regex, ZeroOrOne1) {
Regex re("a?");
ASSERT_TRUE(re.IsValid());
EXPECT_TRUE(re.Match(""));
EXPECT_TRUE(re.Match("a"));
EXPECT_FALSE(re.Match("aa"));
}
TEST(Regex, ZeroOrOne2) {
Regex re("a?b");
ASSERT_TRUE(re.IsValid());
EXPECT_TRUE(re.Match("b"));
EXPECT_TRUE(re.Match("ab"));
EXPECT_FALSE(re.Match("a"));
EXPECT_FALSE(re.Match("aa"));
EXPECT_FALSE(re.Match("bb"));
EXPECT_FALSE(re.Match("ba"));
}
TEST(Regex, ZeroOrOne3) {
Regex re("ab?");
ASSERT_TRUE(re.IsValid());
EXPECT_TRUE(re.Match("a"));
EXPECT_TRUE(re.Match("ab"));
EXPECT_FALSE(re.Match("b"));
EXPECT_FALSE(re.Match("aa"));
EXPECT_FALSE(re.Match("bb"));
EXPECT_FALSE(re.Match("ba"));
}
TEST(Regex, ZeroOrOne4) {
Regex re("a?b?");
ASSERT_TRUE(re.IsValid());
EXPECT_TRUE(re.Match(""));
EXPECT_TRUE(re.Match("a"));
EXPECT_TRUE(re.Match("b"));
EXPECT_TRUE(re.Match("ab"));
EXPECT_FALSE(re.Match("aa"));
EXPECT_FALSE(re.Match("bb"));
EXPECT_FALSE(re.Match("ba"));
EXPECT_FALSE(re.Match("abc"));
}
TEST(Regex, ZeroOrOne5) {
Regex re("a(ab)?b");
ASSERT_TRUE(re.IsValid());
EXPECT_TRUE(re.Match("ab"));
EXPECT_TRUE(re.Match("aabb"));
EXPECT_FALSE(re.Match("aab"));
EXPECT_FALSE(re.Match("abb"));
}
TEST(Regex, ZeroOrMore1) {
Regex re("a*");
ASSERT_TRUE(re.IsValid());
EXPECT_TRUE(re.Match(""));
EXPECT_TRUE(re.Match("a"));
EXPECT_TRUE(re.Match("aa"));
EXPECT_FALSE(re.Match("b"));
EXPECT_FALSE(re.Match("ab"));
}
TEST(Regex, ZeroOrMore2) {
Regex re("a*b");
ASSERT_TRUE(re.IsValid());
EXPECT_TRUE(re.Match("b"));
EXPECT_TRUE(re.Match("ab"));
EXPECT_TRUE(re.Match("aab"));
EXPECT_FALSE(re.Match(""));
EXPECT_FALSE(re.Match("bb"));
}
TEST(Regex, ZeroOrMore3) {
Regex re("a*b*");
ASSERT_TRUE(re.IsValid());
EXPECT_TRUE(re.Match(""));
EXPECT_TRUE(re.Match("a"));
EXPECT_TRUE(re.Match("aa"));
EXPECT_TRUE(re.Match("b"));
EXPECT_TRUE(re.Match("bb"));
EXPECT_TRUE(re.Match("ab"));
EXPECT_TRUE(re.Match("aabb"));
EXPECT_FALSE(re.Match("ba"));
}
TEST(Regex, ZeroOrMore4) {
Regex re("a(ab)*b");
ASSERT_TRUE(re.IsValid());
EXPECT_TRUE(re.Match("ab"));
EXPECT_TRUE(re.Match("aabb"));
EXPECT_TRUE(re.Match("aababb"));
EXPECT_FALSE(re.Match(""));
EXPECT_FALSE(re.Match("aa"));
}
TEST(Regex, OneOrMore1) {
Regex re("a+");
ASSERT_TRUE(re.IsValid());
EXPECT_TRUE(re.Match("a"));
EXPECT_TRUE(re.Match("aa"));
EXPECT_FALSE(re.Match(""));
EXPECT_FALSE(re.Match("b"));
EXPECT_FALSE(re.Match("ab"));
}
TEST(Regex, OneOrMore2) {
Regex re("a+b");
ASSERT_TRUE(re.IsValid());
EXPECT_TRUE(re.Match("ab"));
EXPECT_TRUE(re.Match("aab"));
EXPECT_FALSE(re.Match(""));
EXPECT_FALSE(re.Match("b"));
}
TEST(Regex, OneOrMore3) {
Regex re("a+b+");
ASSERT_TRUE(re.IsValid());
EXPECT_TRUE(re.Match("ab"));
EXPECT_TRUE(re.Match("aab"));
EXPECT_TRUE(re.Match("abb"));
EXPECT_TRUE(re.Match("aabb"));
EXPECT_FALSE(re.Match(""));
EXPECT_FALSE(re.Match("b"));
EXPECT_FALSE(re.Match("ba"));
}
TEST(Regex, OneOrMore4) {
Regex re("a(ab)+b");
ASSERT_TRUE(re.IsValid());
EXPECT_TRUE(re.Match("aabb"));
EXPECT_TRUE(re.Match("aababb"));
EXPECT_FALSE(re.Match(""));
EXPECT_FALSE(re.Match("ab"));
}
TEST(Regex, QuantifierExact1) {
Regex re("ab{3}c");
ASSERT_TRUE(re.IsValid());
EXPECT_TRUE(re.Match("abbbc"));
EXPECT_FALSE(re.Match("ac"));
EXPECT_FALSE(re.Match("abc"));
EXPECT_FALSE(re.Match("abbc"));
EXPECT_FALSE(re.Match("abbbbc"));
}
TEST(Regex, QuantifierExact2) {
Regex re("a(bc){3}d");
ASSERT_TRUE(re.IsValid());
EXPECT_TRUE(re.Match("abcbcbcd"));
EXPECT_FALSE(re.Match("ad"));
EXPECT_FALSE(re.Match("abcd"));
EXPECT_FALSE(re.Match("abcbcd"));
EXPECT_FALSE(re.Match("abcbcbcbcd"));
}
TEST(Regex, QuantifierExact3) {
Regex re("a(b|c){3}d");
ASSERT_TRUE(re.IsValid());
EXPECT_TRUE(re.Match("abbbd"));
EXPECT_TRUE(re.Match("acccd"));
EXPECT_TRUE(re.Match("abcbd"));
EXPECT_FALSE(re.Match("ad"));
EXPECT_FALSE(re.Match("abbd"));
EXPECT_FALSE(re.Match("accccd"));
EXPECT_FALSE(re.Match("abbbbd"));
}
TEST(Regex, QuantifierMin1) {
Regex re("ab{3,}c");
ASSERT_TRUE(re.IsValid());
EXPECT_TRUE(re.Match("abbbc"));
EXPECT_TRUE(re.Match("abbbbc"));
EXPECT_TRUE(re.Match("abbbbbc"));
EXPECT_FALSE(re.Match("ac"));
EXPECT_FALSE(re.Match("abc"));
EXPECT_FALSE(re.Match("abbc"));
}
TEST(Regex, QuantifierMin2) {
Regex re("a(bc){3,}d");
ASSERT_TRUE(re.IsValid());
EXPECT_TRUE(re.Match("abcbcbcd"));
EXPECT_TRUE(re.Match("abcbcbcbcd"));
EXPECT_FALSE(re.Match("ad"));
EXPECT_FALSE(re.Match("abcd"));
EXPECT_FALSE(re.Match("abcbcd"));
}
TEST(Regex, QuantifierMin3) {
Regex re("a(b|c){3,}d");
ASSERT_TRUE(re.IsValid());
EXPECT_TRUE(re.Match("abbbd"));
EXPECT_TRUE(re.Match("acccd"));
EXPECT_TRUE(re.Match("abcbd"));
EXPECT_TRUE(re.Match("accccd"));
EXPECT_TRUE(re.Match("abbbbd"));
EXPECT_FALSE(re.Match("ad"));
EXPECT_FALSE(re.Match("abbd"));
}
TEST(Regex, QuantifierMinMax1) {
Regex re("ab{3,5}c");
ASSERT_TRUE(re.IsValid());
EXPECT_TRUE(re.Match("abbbc"));
EXPECT_TRUE(re.Match("abbbbc"));
EXPECT_TRUE(re.Match("abbbbbc"));
EXPECT_FALSE(re.Match("ac"));
EXPECT_FALSE(re.Match("abc"));
EXPECT_FALSE(re.Match("abbc"));
EXPECT_FALSE(re.Match("abbbbbbc"));
}
TEST(Regex, QuantifierMinMax2) {
Regex re("a(bc){3,5}d");
ASSERT_TRUE(re.IsValid());
EXPECT_TRUE(re.Match("abcbcbcd"));
EXPECT_TRUE(re.Match("abcbcbcbcd"));
EXPECT_TRUE(re.Match("abcbcbcbcbcd"));
EXPECT_FALSE(re.Match("ad"));
EXPECT_FALSE(re.Match("abcd"));
EXPECT_FALSE(re.Match("abcbcd"));
EXPECT_FALSE(re.Match("abcbcbcbcbcbcd"));
}
TEST(Regex, QuantifierMinMax3) {
Regex re("a(b|c){3,5}d");
ASSERT_TRUE(re.IsValid());
EXPECT_TRUE(re.Match("abbbd"));
EXPECT_TRUE(re.Match("acccd"));
EXPECT_TRUE(re.Match("abcbd"));
EXPECT_TRUE(re.Match("accccd"));
EXPECT_TRUE(re.Match("abbbbd"));
EXPECT_TRUE(re.Match("acccccd"));
EXPECT_TRUE(re.Match("abbbbbd"));
EXPECT_FALSE(re.Match("ad"));
EXPECT_FALSE(re.Match("abbd"));
EXPECT_FALSE(re.Match("accccccd"));
EXPECT_FALSE(re.Match("abbbbbbd"));
}
// Issue538
TEST(Regex, QuantifierMinMax4) {
Regex re("a(b|c){0,3}d");
ASSERT_TRUE(re.IsValid());
EXPECT_TRUE(re.Match("ad"));
EXPECT_TRUE(re.Match("abd"));
EXPECT_TRUE(re.Match("acd"));
EXPECT_TRUE(re.Match("abbd"));
EXPECT_TRUE(re.Match("accd"));
EXPECT_TRUE(re.Match("abcd"));
EXPECT_TRUE(re.Match("abbbd"));
EXPECT_TRUE(re.Match("acccd"));
EXPECT_FALSE(re.Match("abbbbd"));
EXPECT_FALSE(re.Match("add"));
EXPECT_FALSE(re.Match("accccd"));
EXPECT_FALSE(re.Match("abcbcd"));
}
// Issue538
TEST(Regex, QuantifierMinMax5) {
Regex re("a(b|c){0,}d");
ASSERT_TRUE(re.IsValid());
EXPECT_TRUE(re.Match("ad"));
EXPECT_TRUE(re.Match("abd"));
EXPECT_TRUE(re.Match("acd"));
EXPECT_TRUE(re.Match("abbd"));
EXPECT_TRUE(re.Match("accd"));
EXPECT_TRUE(re.Match("abcd"));
EXPECT_TRUE(re.Match("abbbd"));
EXPECT_TRUE(re.Match("acccd"));
EXPECT_TRUE(re.Match("abbbbd"));
EXPECT_TRUE(re.Match("accccd"));
EXPECT_TRUE(re.Match("abcbcd"));
EXPECT_FALSE(re.Match("add"));
EXPECT_FALSE(re.Match("aad"));
}
#define EURO "\xE2\x82\xAC" // "\xE2\x82\xAC" is UTF-8 sequence of Euro sign U+20AC
TEST(Regex, Unicode) {
Regex re("a" EURO "+b");
ASSERT_TRUE(re.IsValid());
EXPECT_TRUE(re.Match("a" EURO "b"));
EXPECT_TRUE(re.Match("a" EURO EURO "b"));
EXPECT_FALSE(re.Match("a?b"));
EXPECT_FALSE(re.Match("a" EURO "\xAC" "b")); // unaware of UTF-8 will match
}
TEST(Regex, AnyCharacter) {
Regex re(".");
ASSERT_TRUE(re.IsValid());
EXPECT_TRUE(re.Match("a"));
EXPECT_TRUE(re.Match("b"));
EXPECT_TRUE(re.Match(EURO));
EXPECT_FALSE(re.Match(""));
EXPECT_FALSE(re.Match("aa"));
}
TEST(Regex, CharacterRange1) {
Regex re("[abc]");
ASSERT_TRUE(re.IsValid());
EXPECT_TRUE(re.Match("a"));
EXPECT_TRUE(re.Match("b"));
EXPECT_TRUE(re.Match("c"));
EXPECT_FALSE(re.Match(""));
EXPECT_FALSE(re.Match("`"));
EXPECT_FALSE(re.Match("d"));
EXPECT_FALSE(re.Match("aa"));
}
TEST(Regex, CharacterRange2) {
Regex re("[^abc]");
ASSERT_TRUE(re.IsValid());
EXPECT_TRUE(re.Match("`"));
EXPECT_TRUE(re.Match("d"));
EXPECT_FALSE(re.Match("a"));
EXPECT_FALSE(re.Match("b"));
EXPECT_FALSE(re.Match("c"));
EXPECT_FALSE(re.Match(""));
EXPECT_FALSE(re.Match("aa"));
}
TEST(Regex, CharacterRange3) {
Regex re("[a-c]");
ASSERT_TRUE(re.IsValid());
EXPECT_TRUE(re.Match("a"));
EXPECT_TRUE(re.Match("b"));
EXPECT_TRUE(re.Match("c"));
EXPECT_FALSE(re.Match(""));
EXPECT_FALSE(re.Match("`"));
EXPECT_FALSE(re.Match("d"));
EXPECT_FALSE(re.Match("aa"));
}
TEST(Regex, CharacterRange4) {
Regex re("[^a-c]");
ASSERT_TRUE(re.IsValid());
EXPECT_TRUE(re.Match("`"));
EXPECT_TRUE(re.Match("d"));
EXPECT_FALSE(re.Match("a"));
EXPECT_FALSE(re.Match("b"));
EXPECT_FALSE(re.Match("c"));
EXPECT_FALSE(re.Match(""));
EXPECT_FALSE(re.Match("aa"));
}
TEST(Regex, CharacterRange5) {
Regex re("[-]");
ASSERT_TRUE(re.IsValid());
EXPECT_TRUE(re.Match("-"));
EXPECT_FALSE(re.Match(""));
EXPECT_FALSE(re.Match("a"));
}
TEST(Regex, CharacterRange6) {
Regex re("[a-]");
ASSERT_TRUE(re.IsValid());
EXPECT_TRUE(re.Match("a"));
EXPECT_TRUE(re.Match("-"));
EXPECT_FALSE(re.Match(""));
EXPECT_FALSE(re.Match("`"));
EXPECT_FALSE(re.Match("b"));
}
TEST(Regex, CharacterRange7) {
Regex re("[-a]");
ASSERT_TRUE(re.IsValid());
EXPECT_TRUE(re.Match("a"));
EXPECT_TRUE(re.Match("-"));
EXPECT_FALSE(re.Match(""));
EXPECT_FALSE(re.Match("`"));
EXPECT_FALSE(re.Match("b"));
}
TEST(Regex, CharacterRange8) {
Regex re("[a-zA-Z0-9]*");
ASSERT_TRUE(re.IsValid());
EXPECT_TRUE(re.Match("Milo"));
EXPECT_TRUE(re.Match("MT19937"));
EXPECT_TRUE(re.Match("43"));
EXPECT_FALSE(re.Match("a_b"));
EXPECT_FALSE(re.Match("!"));
}
TEST(Regex, Search) {
Regex re("abc");
ASSERT_TRUE(re.IsValid());
EXPECT_TRUE(re.Search("abc"));
EXPECT_TRUE(re.Search("_abc"));
EXPECT_TRUE(re.Search("abc_"));
EXPECT_TRUE(re.Search("_abc_"));
EXPECT_TRUE(re.Search("__abc__"));
EXPECT_TRUE(re.Search("abcabc"));
EXPECT_FALSE(re.Search("a"));
EXPECT_FALSE(re.Search("ab"));
EXPECT_FALSE(re.Search("bc"));
EXPECT_FALSE(re.Search("cba"));
}
TEST(Regex, Search_BeginAnchor) {
Regex re("^abc");
ASSERT_TRUE(re.IsValid());
EXPECT_TRUE(re.Search("abc"));
EXPECT_TRUE(re.Search("abc_"));
EXPECT_TRUE(re.Search("abcabc"));
EXPECT_FALSE(re.Search("_abc"));
EXPECT_FALSE(re.Search("_abc_"));
EXPECT_FALSE(re.Search("a"));
EXPECT_FALSE(re.Search("ab"));
EXPECT_FALSE(re.Search("bc"));
EXPECT_FALSE(re.Search("cba"));
}
TEST(Regex, Search_EndAnchor) {
Regex re("abc$");
ASSERT_TRUE(re.IsValid());
EXPECT_TRUE(re.Search("abc"));
EXPECT_TRUE(re.Search("_abc"));
EXPECT_TRUE(re.Search("abcabc"));
EXPECT_FALSE(re.Search("abc_"));
EXPECT_FALSE(re.Search("_abc_"));
EXPECT_FALSE(re.Search("a"));
EXPECT_FALSE(re.Search("ab"));
EXPECT_FALSE(re.Search("bc"));
EXPECT_FALSE(re.Search("cba"));
}
TEST(Regex, Search_BothAnchor) {
Regex re("^abc$");
ASSERT_TRUE(re.IsValid());
EXPECT_TRUE(re.Search("abc"));
EXPECT_FALSE(re.Search(""));
EXPECT_FALSE(re.Search("a"));
EXPECT_FALSE(re.Search("b"));
EXPECT_FALSE(re.Search("ab"));
EXPECT_FALSE(re.Search("abcd"));
}
TEST(Regex, Escape) {
const char* s = "\\^\\$\\|\\(\\)\\?\\*\\+\\.\\[\\]\\{\\}\\\\\\f\\n\\r\\t\\v[\\b][\\[][\\]]";
Regex re(s);
ASSERT_TRUE(re.IsValid());
EXPECT_TRUE(re.Match("^$|()?*+.[]{}\\\x0C\n\r\t\x0B\b[]"));
EXPECT_FALSE(re.Match(s)); // Not escaping
}
TEST(Regex, Invalid) {
#define TEST_INVALID(s) \
{\
Regex re(s);\
EXPECT_FALSE(re.IsValid());\
}
TEST_INVALID("");
TEST_INVALID("a|");
TEST_INVALID("()");
TEST_INVALID(")");
TEST_INVALID("(a))");
TEST_INVALID("(a|)");
TEST_INVALID("(a||b)");
TEST_INVALID("(|b)");
TEST_INVALID("?");
TEST_INVALID("*");
TEST_INVALID("+");
TEST_INVALID("{");
TEST_INVALID("{}");
TEST_INVALID("a{a}");
TEST_INVALID("a{0}");
TEST_INVALID("a{-1}");
TEST_INVALID("a{}");
// TEST_INVALID("a{0,}"); // Support now
TEST_INVALID("a{,0}");
TEST_INVALID("a{1,0}");
TEST_INVALID("a{-1,0}");
TEST_INVALID("a{-1,1}");
TEST_INVALID("a{4294967296}"); // overflow of unsigned
TEST_INVALID("a{1a}");
TEST_INVALID("[");
TEST_INVALID("[]");
TEST_INVALID("[^]");
TEST_INVALID("[\\a]");
TEST_INVALID("\\a");
#undef TEST_INVALID
}
TEST(Regex, Issue538) {
Regex re("^[0-9]+(\\\\.[0-9]+){0,2}");
EXPECT_TRUE(re.IsValid());
}
TEST(Regex, Issue583) {
Regex re("[0-9]{99999}");
ASSERT_TRUE(re.IsValid());
}
#undef EURO

File diff suppressed because it is too large Load Diff

View File

@ -1,215 +0,0 @@
// Tencent is pleased to support the open source community by making RapidJSON available.
//
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
//
// Licensed under the MIT License (the "License"); you may not use this file except
// in compliance with the License. You may obtain a copy of the License at
//
// http://opensource.org/licenses/MIT
//
// Unless required by applicable law or agreed to in writing, software distributed
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
// specific language governing permissions and limitations under the License.
// Since Travis CI installs old Valgrind 3.7.0, which fails with some SSE4.2
// The unit tests prefix with SIMD should be skipped by Valgrind test
// __SSE2__ and __SSE4_2__ are recognized by gcc, clang, and the Intel compiler.
// We use -march=native with gmake to enable -msse2 and -msse4.2, if supported.
#if defined(__SSE4_2__)
# define RAPIDJSON_SSE42
#elif defined(__SSE2__)
# define RAPIDJSON_SSE2
#endif
#define RAPIDJSON_NAMESPACE rapidjson_simd
#include "unittest.h"
#include "rapidjson/reader.h"
#include "rapidjson/writer.h"
#ifdef __GNUC__
RAPIDJSON_DIAG_PUSH
RAPIDJSON_DIAG_OFF(effc++)
#endif
using namespace rapidjson_simd;
#ifdef RAPIDJSON_SSE2
#define SIMD_SUFFIX(name) name##_SSE2
#elif defined(RAPIDJSON_SSE42)
#define SIMD_SUFFIX(name) name##_SSE42
#else
#define SIMD_SUFFIX(name) name
#endif
template <typename StreamType>
void TestSkipWhitespace() {
for (size_t step = 1; step < 32; step++) {
char buffer[1025];
for (size_t i = 0; i < 1024; i++)
buffer[i] = " \t\r\n"[i % 4];
for (size_t i = 0; i < 1024; i += step)
buffer[i] = 'X';
buffer[1024] = '\0';
StreamType s(buffer);
size_t i = 0;
for (;;) {
SkipWhitespace(s);
if (s.Peek() == '\0')
break;
EXPECT_EQ(i, s.Tell());
EXPECT_EQ('X', s.Take());
i += step;
}
}
}
TEST(SIMD, SIMD_SUFFIX(SkipWhitespace)) {
TestSkipWhitespace<StringStream>();
TestSkipWhitespace<InsituStringStream>();
}
TEST(SIMD, SIMD_SUFFIX(SkipWhitespace_EncodedMemoryStream)) {
for (size_t step = 1; step < 32; step++) {
char buffer[1024];
for (size_t i = 0; i < 1024; i++)
buffer[i] = " \t\r\n"[i % 4];
for (size_t i = 0; i < 1024; i += step)
buffer[i] = 'X';
MemoryStream ms(buffer, 1024);
EncodedInputStream<UTF8<>, MemoryStream> s(ms);
size_t i = 0;
for (;;) {
SkipWhitespace(s);
if (s.Peek() == '\0')
break;
//EXPECT_EQ(i, s.Tell());
EXPECT_EQ('X', s.Take());
i += step;
}
}
}
struct ScanCopyUnescapedStringHandler : BaseReaderHandler<UTF8<>, ScanCopyUnescapedStringHandler> {
bool String(const char* str, size_t length, bool) {
memcpy(buffer, str, length + 1);
return true;
}
char buffer[1024 + 5 + 32];
};
template <unsigned parseFlags, typename StreamType>
void TestScanCopyUnescapedString() {
char buffer[1024 + 5 + 32];
char backup[1024 + 5 + 32];
// Test "ABCDABCD...\\"
for (size_t offset = 0; offset < 32; offset++) {
for (size_t step = 0; step < 1024; step++) {
char* json = buffer + offset;
char *p = json;
*p++ = '\"';
for (size_t i = 0; i < step; i++)
*p++ = "ABCD"[i % 4];
*p++ = '\\';
*p++ = '\\';
*p++ = '\"';
*p++ = '\0';
strcpy(backup, json); // insitu parsing will overwrite buffer, so need to backup first
StreamType s(json);
Reader reader;
ScanCopyUnescapedStringHandler h;
reader.Parse<parseFlags>(s, h);
EXPECT_TRUE(memcmp(h.buffer, backup + 1, step) == 0);
EXPECT_EQ('\\', h.buffer[step]); // escaped
EXPECT_EQ('\0', h.buffer[step + 1]);
}
}
// Test "\\ABCDABCD..."
for (size_t offset = 0; offset < 32; offset++) {
for (size_t step = 0; step < 1024; step++) {
char* json = buffer + offset;
char *p = json;
*p++ = '\"';
*p++ = '\\';
*p++ = '\\';
for (size_t i = 0; i < step; i++)
*p++ = "ABCD"[i % 4];
*p++ = '\"';
*p++ = '\0';
strcpy(backup, json); // insitu parsing will overwrite buffer, so need to backup first
StreamType s(json);
Reader reader;
ScanCopyUnescapedStringHandler h;
reader.Parse<parseFlags>(s, h);
EXPECT_TRUE(memcmp(h.buffer + 1, backup + 3, step) == 0);
EXPECT_EQ('\\', h.buffer[0]); // escaped
EXPECT_EQ('\0', h.buffer[step + 1]);
}
}
}
TEST(SIMD, SIMD_SUFFIX(ScanCopyUnescapedString)) {
TestScanCopyUnescapedString<kParseDefaultFlags, StringStream>();
TestScanCopyUnescapedString<kParseInsituFlag, InsituStringStream>();
}
TEST(SIMD, SIMD_SUFFIX(ScanWriteUnescapedString)) {
char buffer[2048 + 1 + 32];
for (size_t offset = 0; offset < 32; offset++) {
for (size_t step = 0; step < 1024; step++) {
char* s = buffer + offset;
char* p = s;
for (size_t i = 0; i < step; i++)
*p++ = "ABCD"[i % 4];
char escape = "\0\n\\\""[step % 4];
*p++ = escape;
for (size_t i = 0; i < step; i++)
*p++ = "ABCD"[i % 4];
StringBuffer sb;
Writer<StringBuffer> writer(sb);
writer.String(s, SizeType(step * 2 + 1));
const char* q = sb.GetString();
EXPECT_EQ('\"', *q++);
for (size_t i = 0; i < step; i++)
EXPECT_EQ("ABCD"[i % 4], *q++);
if (escape == '\0') {
EXPECT_EQ('\\', *q++);
EXPECT_EQ('u', *q++);
EXPECT_EQ('0', *q++);
EXPECT_EQ('0', *q++);
EXPECT_EQ('0', *q++);
EXPECT_EQ('0', *q++);
}
else if (escape == '\n') {
EXPECT_EQ('\\', *q++);
EXPECT_EQ('n', *q++);
}
else if (escape == '\\') {
EXPECT_EQ('\\', *q++);
EXPECT_EQ('\\', *q++);
}
else if (escape == '\"') {
EXPECT_EQ('\\', *q++);
EXPECT_EQ('\"', *q++);
}
for (size_t i = 0; i < step; i++)
EXPECT_EQ("ABCD"[i % 4], *q++);
EXPECT_EQ('\"', *q++);
EXPECT_EQ('\0', *q++);
}
}
}
#ifdef __GNUC__
RAPIDJSON_DIAG_POP
#endif

View File

@ -1,30 +0,0 @@
// Tencent is pleased to support the open source community by making RapidJSON available.
//
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
//
// Licensed under the MIT License (the "License"); you may not use this file except
// in compliance with the License. You may obtain a copy of the License at
//
// http://opensource.org/licenses/MIT
//
// Unless required by applicable law or agreed to in writing, software distributed
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
// specific language governing permissions and limitations under the License.
#include "unittest.h"
#include "rapidjson/internal/strfunc.h"
using namespace rapidjson;
using namespace rapidjson::internal;
TEST(StrFunc, CountStringCodePoint) {
SizeType count;
EXPECT_TRUE(CountStringCodePoint<UTF8<> >("", 0, &count));
EXPECT_EQ(0u, count);
EXPECT_TRUE(CountStringCodePoint<UTF8<> >("Hello", 5, &count));
EXPECT_EQ(5u, count);
EXPECT_TRUE(CountStringCodePoint<UTF8<> >("\xC2\xA2\xE2\x82\xAC\xF0\x9D\x84\x9E", 9, &count)); // cents euro G-clef
EXPECT_EQ(3u, count);
EXPECT_FALSE(CountStringCodePoint<UTF8<> >("\xC2\xA2\xE2\x82\xAC\xF0\x9D\x84\x9E\x80", 10, &count));
}

View File

@ -1,170 +0,0 @@
// Tencent is pleased to support the open source community by making RapidJSON available.
//
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
//
// Licensed under the MIT License (the "License"); you may not use this file except
// in compliance with the License. You may obtain a copy of the License at
//
// http://opensource.org/licenses/MIT
//
// Unless required by applicable law or agreed to in writing, software distributed
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
// specific language governing permissions and limitations under the License.
#include "unittest.h"
#include "rapidjson/stringbuffer.h"
#include "rapidjson/writer.h"
#ifdef __clang__
RAPIDJSON_DIAG_PUSH
RAPIDJSON_DIAG_OFF(c++98-compat)
#endif
using namespace rapidjson;
TEST(StringBuffer, InitialSize) {
StringBuffer buffer;
EXPECT_EQ(0u, buffer.GetSize());
EXPECT_STREQ("", buffer.GetString());
}
TEST(StringBuffer, Put) {
StringBuffer buffer;
buffer.Put('A');
EXPECT_EQ(1u, buffer.GetSize());
EXPECT_STREQ("A", buffer.GetString());
}
TEST(StringBuffer, PutN_Issue672) {
GenericStringBuffer<UTF8<>, MemoryPoolAllocator<> > buffer;
EXPECT_EQ(0, buffer.GetSize());
rapidjson::PutN(buffer, ' ', 1);
EXPECT_EQ(1, buffer.GetSize());
}
TEST(StringBuffer, Clear) {
StringBuffer buffer;
buffer.Put('A');
buffer.Put('B');
buffer.Put('C');
buffer.Clear();
EXPECT_EQ(0u, buffer.GetSize());
EXPECT_STREQ("", buffer.GetString());
}
TEST(StringBuffer, Push) {
StringBuffer buffer;
buffer.Push(5);
EXPECT_EQ(5u, buffer.GetSize());
// Causes sudden expansion to make the stack's capacity equal to size
buffer.Push(65536u);
EXPECT_EQ(5u + 65536u, buffer.GetSize());
}
TEST(StringBuffer, Pop) {
StringBuffer buffer;
buffer.Put('A');
buffer.Put('B');
buffer.Put('C');
buffer.Put('D');
buffer.Put('E');
buffer.Pop(3);
EXPECT_EQ(2u, buffer.GetSize());
EXPECT_STREQ("AB", buffer.GetString());
}
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
#if 0 // Many old compiler does not support these. Turn it off temporaily.
#include <type_traits>
TEST(StringBuffer, Traits) {
static_assert( std::is_constructible<StringBuffer>::value, "");
static_assert( std::is_default_constructible<StringBuffer>::value, "");
#ifndef _MSC_VER
static_assert(!std::is_copy_constructible<StringBuffer>::value, "");
#endif
static_assert( std::is_move_constructible<StringBuffer>::value, "");
static_assert(!std::is_nothrow_constructible<StringBuffer>::value, "");
static_assert(!std::is_nothrow_default_constructible<StringBuffer>::value, "");
#if !defined(_MSC_VER) || _MSC_VER >= 1800
static_assert(!std::is_nothrow_copy_constructible<StringBuffer>::value, "");
static_assert(!std::is_nothrow_move_constructible<StringBuffer>::value, "");
#endif
static_assert( std::is_assignable<StringBuffer,StringBuffer>::value, "");
#ifndef _MSC_VER
static_assert(!std::is_copy_assignable<StringBuffer>::value, "");
#endif
static_assert( std::is_move_assignable<StringBuffer>::value, "");
#if !defined(_MSC_VER) || _MSC_VER >= 1800
static_assert(!std::is_nothrow_assignable<StringBuffer, StringBuffer>::value, "");
#endif
static_assert(!std::is_nothrow_copy_assignable<StringBuffer>::value, "");
static_assert(!std::is_nothrow_move_assignable<StringBuffer>::value, "");
static_assert( std::is_destructible<StringBuffer>::value, "");
#ifndef _MSC_VER
static_assert(std::is_nothrow_destructible<StringBuffer>::value, "");
#endif
}
#endif
TEST(StringBuffer, MoveConstructor) {
StringBuffer x;
x.Put('A');
x.Put('B');
x.Put('C');
x.Put('D');
EXPECT_EQ(4u, x.GetSize());
EXPECT_STREQ("ABCD", x.GetString());
// StringBuffer y(x); // does not compile (!is_copy_constructible)
StringBuffer y(std::move(x));
EXPECT_EQ(0u, x.GetSize());
EXPECT_EQ(4u, y.GetSize());
EXPECT_STREQ("ABCD", y.GetString());
// StringBuffer z = y; // does not compile (!is_copy_assignable)
StringBuffer z = std::move(y);
EXPECT_EQ(0u, y.GetSize());
EXPECT_EQ(4u, z.GetSize());
EXPECT_STREQ("ABCD", z.GetString());
}
TEST(StringBuffer, MoveAssignment) {
StringBuffer x;
x.Put('A');
x.Put('B');
x.Put('C');
x.Put('D');
EXPECT_EQ(4u, x.GetSize());
EXPECT_STREQ("ABCD", x.GetString());
StringBuffer y;
// y = x; // does not compile (!is_copy_assignable)
y = std::move(x);
EXPECT_EQ(0u, x.GetSize());
EXPECT_EQ(4u, y.GetSize());
EXPECT_STREQ("ABCD", y.GetString());
}
#endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS
#ifdef __clang__
RAPIDJSON_DIAG_POP
#endif

View File

@ -1,132 +0,0 @@
// Tencent is pleased to support the open source community by making RapidJSON available.
//
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
//
// Licensed under the MIT License (the "License"); you may not use this file except
// in compliance with the License. You may obtain a copy of the License at
//
// http://opensource.org/licenses/MIT
//
// Unless required by applicable law or agreed to in writing, software distributed
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
// specific language governing permissions and limitations under the License.
#include "unittest.h"
#include "rapidjson/internal/strtod.h"
#ifdef __clang__
RAPIDJSON_DIAG_PUSH
RAPIDJSON_DIAG_OFF(unreachable-code)
#endif
#define BIGINTEGER_LITERAL(s) BigInteger(s, sizeof(s) - 1)
using namespace rapidjson::internal;
TEST(Strtod, CheckApproximationCase) {
static const int kSignificandSize = 52;
static const int kExponentBias = 0x3FF;
static const uint64_t kExponentMask = RAPIDJSON_UINT64_C2(0x7FF00000, 0x00000000);
static const uint64_t kSignificandMask = RAPIDJSON_UINT64_C2(0x000FFFFF, 0xFFFFFFFF);
static const uint64_t kHiddenBit = RAPIDJSON_UINT64_C2(0x00100000, 0x00000000);
// http://www.exploringbinary.com/using-integers-to-check-a-floating-point-approximation/
// Let b = 0x1.465a72e467d88p-149
// = 5741268244528520 x 2^-201
union {
double d;
uint64_t u;
}u;
u.u = 0x465a72e467d88 | ((static_cast<uint64_t>(-149 + kExponentBias)) << kSignificandSize);
const double b = u.d;
const uint64_t bInt = (u.u & kSignificandMask) | kHiddenBit;
const int bExp = static_cast<int>(((u.u & kExponentMask) >> kSignificandSize) - kExponentBias - kSignificandSize);
EXPECT_DOUBLE_EQ(1.7864e-45, b);
EXPECT_EQ(RAPIDJSON_UINT64_C2(0x001465a7, 0x2e467d88), bInt);
EXPECT_EQ(-201, bExp);
// Let d = 17864 x 10-49
const char dInt[] = "17864";
const int dExp = -49;
// Let h = 2^(bExp-1)
const int hExp = bExp - 1;
EXPECT_EQ(-202, hExp);
int dS_Exp2 = 0;
int dS_Exp5 = 0;
int bS_Exp2 = 0;
int bS_Exp5 = 0;
int hS_Exp2 = 0;
int hS_Exp5 = 0;
// Adjust for decimal exponent
if (dExp >= 0) {
dS_Exp2 += dExp;
dS_Exp5 += dExp;
}
else {
bS_Exp2 -= dExp;
bS_Exp5 -= dExp;
hS_Exp2 -= dExp;
hS_Exp5 -= dExp;
}
// Adjust for binary exponent
if (bExp >= 0)
bS_Exp2 += bExp;
else {
dS_Exp2 -= bExp;
hS_Exp2 -= bExp;
}
// Adjust for half ulp exponent
if (hExp >= 0)
hS_Exp2 += hExp;
else {
dS_Exp2 -= hExp;
bS_Exp2 -= hExp;
}
// Remove common power of two factor from all three scaled values
int common_Exp2 = std::min(dS_Exp2, std::min(bS_Exp2, hS_Exp2));
dS_Exp2 -= common_Exp2;
bS_Exp2 -= common_Exp2;
hS_Exp2 -= common_Exp2;
EXPECT_EQ(153, dS_Exp2);
EXPECT_EQ(0, dS_Exp5);
EXPECT_EQ(1, bS_Exp2);
EXPECT_EQ(49, bS_Exp5);
EXPECT_EQ(0, hS_Exp2);
EXPECT_EQ(49, hS_Exp5);
BigInteger dS = BIGINTEGER_LITERAL(dInt);
dS.MultiplyPow5(static_cast<unsigned>(dS_Exp5)) <<= static_cast<size_t>(dS_Exp2);
BigInteger bS(bInt);
bS.MultiplyPow5(static_cast<unsigned>(bS_Exp5)) <<= static_cast<size_t>(bS_Exp2);
BigInteger hS(1);
hS.MultiplyPow5(static_cast<unsigned>(hS_Exp5)) <<= static_cast<size_t>(hS_Exp2);
EXPECT_TRUE(BIGINTEGER_LITERAL("203970822259994138521801764465966248930731085529088") == dS);
EXPECT_TRUE(BIGINTEGER_LITERAL("203970822259994122305215569213032722473144531250000") == bS);
EXPECT_TRUE(BIGINTEGER_LITERAL("17763568394002504646778106689453125") == hS);
EXPECT_EQ(1, dS.Compare(bS));
BigInteger delta(0);
EXPECT_FALSE(dS.Difference(bS, &delta));
EXPECT_TRUE(BIGINTEGER_LITERAL("16216586195252933526457586554279088") == delta);
EXPECT_TRUE(bS.Difference(dS, &delta));
EXPECT_TRUE(BIGINTEGER_LITERAL("16216586195252933526457586554279088") == delta);
EXPECT_EQ(-1, delta.Compare(hS));
}
#ifdef __clang__
RAPIDJSON_DIAG_POP
#endif

View File

@ -1,51 +0,0 @@
// Tencent is pleased to support the open source community by making RapidJSON available.
//
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
//
// Licensed under the MIT License (the "License"); you may not use this file except
// in compliance with the License. You may obtain a copy of the License at
//
// http://opensource.org/licenses/MIT
//
// Unless required by applicable law or agreed to in writing, software distributed
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
// specific language governing permissions and limitations under the License.
#include "unittest.h"
#include "rapidjson/rapidjson.h"
#ifdef __clang__
#pragma GCC diagnostic push
#if __has_warning("-Wdeprecated")
#pragma GCC diagnostic ignored "-Wdeprecated"
#endif
#endif
AssertException::~AssertException() throw() {}
#ifdef __clang__
#pragma GCC diagnostic pop
#endif
int main(int argc, char **argv) {
::testing::InitGoogleTest(&argc, argv);
std::cout << "RapidJSON v" << RAPIDJSON_VERSION_STRING << std::endl;
#ifdef _MSC_VER
_CrtMemState memoryState = { 0 };
(void)memoryState;
_CrtMemCheckpoint(&memoryState);
//_CrtSetBreakAlloc(X);
//void *testWhetherMemoryLeakDetectionWorks = malloc(1);
#endif
int ret = RUN_ALL_TESTS();
#ifdef _MSC_VER
// Current gtest constantly leak 2 blocks at exit
_CrtMemDumpAllObjectsSince(&memoryState);
#endif
return ret;
}

View File

@ -1,135 +0,0 @@
// Tencent is pleased to support the open source community by making RapidJSON available.
//
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
//
// Licensed under the MIT License (the "License"); you may not use this file except
// in compliance with the License. You may obtain a copy of the License at
//
// http://opensource.org/licenses/MIT
//
// Unless required by applicable law or agreed to in writing, software distributed
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
// specific language governing permissions and limitations under the License.
#ifndef UNITTEST_H_
#define UNITTEST_H_
// gtest indirectly included inttypes.h, without __STDC_CONSTANT_MACROS.
#ifndef __STDC_CONSTANT_MACROS
#ifdef __clang__
#pragma GCC diagnostic push
#if __has_warning("-Wreserved-id-macro")
#pragma GCC diagnostic ignored "-Wreserved-id-macro"
#endif
#endif
# define __STDC_CONSTANT_MACROS 1 // required by C++ standard
#ifdef __clang__
#pragma GCC diagnostic pop
#endif
#endif
#ifdef _MSC_VER
#define _CRTDBG_MAP_ALLOC
#include <crtdbg.h>
#pragma warning(disable : 4996) // 'function': was declared deprecated
#endif
#if defined(__clang__) || defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 2))
#if defined(__clang__) || (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
#pragma GCC diagnostic push
#endif
#pragma GCC diagnostic ignored "-Weffc++"
#endif
#include "gtest/gtest.h"
#include <stdexcept>
#if defined(__clang__) || defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
#pragma GCC diagnostic pop
#endif
#ifdef __clang__
// All TEST() macro generated this warning, disable globally
#pragma GCC diagnostic ignored "-Wglobal-constructors"
#endif
template <typename Ch>
inline unsigned StrLen(const Ch* s) {
const Ch* p = s;
while (*p) p++;
return unsigned(p - s);
}
template<typename Ch>
inline int StrCmp(const Ch* s1, const Ch* s2) {
while(*s1 && (*s1 == *s2)) { s1++; s2++; }
return static_cast<unsigned>(*s1) < static_cast<unsigned>(*s2) ? -1 : static_cast<unsigned>(*s1) > static_cast<unsigned>(*s2);
}
template <typename Ch>
inline Ch* StrDup(const Ch* str) {
size_t bufferSize = sizeof(Ch) * (StrLen(str) + 1);
Ch* buffer = static_cast<Ch*>(malloc(bufferSize));
memcpy(buffer, str, bufferSize);
return buffer;
}
inline FILE* TempFile(char *filename) {
#ifdef _MSC_VER
filename = tmpnam(filename);
// For Visual Studio, tmpnam() adds a backslash in front. Remove it.
if (filename[0] == '\\')
for (int i = 0; filename[i] != '\0'; i++)
filename[i] = filename[i + 1];
return fopen(filename, "wb");
#else
strcpy(filename, "/tmp/fileXXXXXX");
int fd = mkstemp(filename);
return fdopen(fd, "w");
#endif
}
// Use exception for catching assert
#ifdef _MSC_VER
#pragma warning(disable : 4127)
#endif
#ifdef __clang__
#pragma GCC diagnostic push
#if __has_warning("-Wdeprecated")
#pragma GCC diagnostic ignored "-Wdeprecated"
#endif
#endif
class AssertException : public std::logic_error {
public:
AssertException(const char* w) : std::logic_error(w) {}
AssertException(const AssertException& rhs) : std::logic_error(rhs) {}
virtual ~AssertException() throw();
};
#ifdef __clang__
#pragma GCC diagnostic pop
#endif
#define RAPIDJSON_ASSERT(x) if (!(x)) throw AssertException(RAPIDJSON_STRINGIFY(x))
class Random {
public:
Random(unsigned seed = 0) : mSeed(seed) {}
unsigned operator()() {
mSeed = 214013 * mSeed + 2531011;
return mSeed;
}
private:
unsigned mSeed;
};
#endif // UNITTEST_H_

File diff suppressed because it is too large Load Diff

View File

@ -1,497 +0,0 @@
// Tencent is pleased to support the open source community by making RapidJSON available.
//
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
//
// Licensed under the MIT License (the "License"); you may not use this file except
// in compliance with the License. You may obtain a copy of the License at
//
// http://opensource.org/licenses/MIT
//
// Unless required by applicable law or agreed to in writing, software distributed
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
// specific language governing permissions and limitations under the License.
#include "unittest.h"
#include "rapidjson/document.h"
#include "rapidjson/reader.h"
#include "rapidjson/writer.h"
#include "rapidjson/stringbuffer.h"
#include "rapidjson/memorybuffer.h"
using namespace rapidjson;
TEST(Writer, Compact) {
StringStream s("{ \"hello\" : \"world\", \"t\" : true , \"f\" : false, \"n\": null, \"i\":123, \"pi\": 3.1416, \"a\":[1, 2, 3] } ");
StringBuffer buffer;
Writer<StringBuffer> writer(buffer);
buffer.ShrinkToFit();
Reader reader;
reader.Parse<0>(s, writer);
EXPECT_STREQ("{\"hello\":\"world\",\"t\":true,\"f\":false,\"n\":null,\"i\":123,\"pi\":3.1416,\"a\":[1,2,3]}", buffer.GetString());
EXPECT_EQ(77u, buffer.GetSize());
EXPECT_TRUE(writer.IsComplete());
}
// json -> parse -> writer -> json
#define TEST_ROUNDTRIP(json) \
{ \
StringStream s(json); \
StringBuffer buffer; \
Writer<StringBuffer> writer(buffer); \
Reader reader; \
reader.Parse<kParseFullPrecisionFlag>(s, writer); \
EXPECT_STREQ(json, buffer.GetString()); \
EXPECT_TRUE(writer.IsComplete()); \
}
TEST(Writer, Root) {
TEST_ROUNDTRIP("null");
TEST_ROUNDTRIP("true");
TEST_ROUNDTRIP("false");
TEST_ROUNDTRIP("0");
TEST_ROUNDTRIP("\"foo\"");
TEST_ROUNDTRIP("[]");
TEST_ROUNDTRIP("{}");
}
TEST(Writer, Int) {
TEST_ROUNDTRIP("[-1]");
TEST_ROUNDTRIP("[-123]");
TEST_ROUNDTRIP("[-2147483648]");
}
TEST(Writer, UInt) {
TEST_ROUNDTRIP("[0]");
TEST_ROUNDTRIP("[1]");
TEST_ROUNDTRIP("[123]");
TEST_ROUNDTRIP("[2147483647]");
TEST_ROUNDTRIP("[4294967295]");
}
TEST(Writer, Int64) {
TEST_ROUNDTRIP("[-1234567890123456789]");
TEST_ROUNDTRIP("[-9223372036854775808]");
}
TEST(Writer, Uint64) {
TEST_ROUNDTRIP("[1234567890123456789]");
TEST_ROUNDTRIP("[9223372036854775807]");
}
TEST(Writer, String) {
TEST_ROUNDTRIP("[\"Hello\"]");
TEST_ROUNDTRIP("[\"Hello\\u0000World\"]");
TEST_ROUNDTRIP("[\"\\\"\\\\/\\b\\f\\n\\r\\t\"]");
#if RAPIDJSON_HAS_STDSTRING
{
StringBuffer buffer;
Writer<StringBuffer> writer(buffer);
writer.String(std::string("Hello\n"));
EXPECT_STREQ("\"Hello\\n\"", buffer.GetString());
}
#endif
}
TEST(Writer, ScanWriteUnescapedString) {
const char json[] = "[\" \\\"0123456789ABCDEF\"]";
// ^ scanning stops here.
char buffer2[sizeof(json) + 32];
// Use different offset to test different alignments
for (int i = 0; i < 32; i++) {
char* p = buffer2 + i;
memcpy(p, json, sizeof(json));
TEST_ROUNDTRIP(p);
}
}
TEST(Writer, Double) {
TEST_ROUNDTRIP("[1.2345,1.2345678,0.123456789012,1234567.8]");
TEST_ROUNDTRIP("0.0");
TEST_ROUNDTRIP("-0.0"); // Issue #289
TEST_ROUNDTRIP("1e30");
TEST_ROUNDTRIP("1.0");
TEST_ROUNDTRIP("5e-324"); // Min subnormal positive double
TEST_ROUNDTRIP("2.225073858507201e-308"); // Max subnormal positive double
TEST_ROUNDTRIP("2.2250738585072014e-308"); // Min normal positive double
TEST_ROUNDTRIP("1.7976931348623157e308"); // Max double
}
// UTF8 -> TargetEncoding -> UTF8
template <typename TargetEncoding>
void TestTranscode(const char* json) {
StringStream s(json);
GenericStringBuffer<TargetEncoding> buffer;
Writer<GenericStringBuffer<TargetEncoding>, UTF8<>, TargetEncoding> writer(buffer);
Reader reader;
reader.Parse(s, writer);
StringBuffer buffer2;
Writer<StringBuffer> writer2(buffer2);
GenericReader<TargetEncoding, UTF8<> > reader2;
GenericStringStream<TargetEncoding> s2(buffer.GetString());
reader2.Parse(s2, writer2);
EXPECT_STREQ(json, buffer2.GetString());
}
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());
}
}
#include <sstream>
class OStreamWrapper {
public:
typedef char Ch;
OStreamWrapper(std::ostream& os) : os_(os) {}
Ch Peek() const { assert(false); return '\0'; }
Ch Take() { assert(false); return '\0'; }
size_t Tell() const { return 0; }
Ch* PutBegin() { assert(false); return 0; }
void Put(Ch c) { os_.put(c); }
void Flush() { os_.flush(); }
size_t PutEnd(Ch*) { assert(false); return 0; }
private:
OStreamWrapper(const OStreamWrapper&);
OStreamWrapper& operator=(const OStreamWrapper&);
std::ostream& os_;
};
TEST(Writer, OStreamWrapper) {
StringStream s("{ \"hello\" : \"world\", \"t\" : true , \"f\" : false, \"n\": null, \"i\":123, \"pi\": 3.1416, \"a\":[1, 2, 3], \"u64\": 1234567890123456789, \"i64\":-1234567890123456789 } ");
std::stringstream ss;
OStreamWrapper os(ss);
Writer<OStreamWrapper> writer(os);
Reader reader;
reader.Parse<0>(s, writer);
std::string actual = ss.str();
EXPECT_STREQ("{\"hello\":\"world\",\"t\":true,\"f\":false,\"n\":null,\"i\":123,\"pi\":3.1416,\"a\":[1,2,3],\"u64\":1234567890123456789,\"i64\":-1234567890123456789}", actual.c_str());
}
TEST(Writer, AssertRootMayBeAnyValue) {
#define T(x)\
{\
StringBuffer buffer;\
Writer<StringBuffer> writer(buffer);\
EXPECT_TRUE(x);\
}
T(writer.Bool(false));
T(writer.Bool(true));
T(writer.Null());
T(writer.Int(0));
T(writer.Uint(0));
T(writer.Int64(0));
T(writer.Uint64(0));
T(writer.Double(0));
T(writer.String("foo"));
#undef T
}
TEST(Writer, AssertIncorrectObjectLevel) {
StringBuffer buffer;
Writer<StringBuffer> writer(buffer);
writer.StartObject();
writer.EndObject();
ASSERT_THROW(writer.EndObject(), AssertException);
}
TEST(Writer, AssertIncorrectArrayLevel) {
StringBuffer buffer;
Writer<StringBuffer> writer(buffer);
writer.StartArray();
writer.EndArray();
ASSERT_THROW(writer.EndArray(), AssertException);
}
TEST(Writer, AssertIncorrectEndObject) {
StringBuffer buffer;
Writer<StringBuffer> writer(buffer);
writer.StartObject();
ASSERT_THROW(writer.EndArray(), AssertException);
}
TEST(Writer, AssertIncorrectEndArray) {
StringBuffer buffer;
Writer<StringBuffer> writer(buffer);
writer.StartObject();
ASSERT_THROW(writer.EndArray(), AssertException);
}
TEST(Writer, AssertObjectKeyNotString) {
#define T(x)\
{\
StringBuffer buffer;\
Writer<StringBuffer> writer(buffer);\
writer.StartObject();\
ASSERT_THROW(x, AssertException); \
}
T(writer.Bool(false));
T(writer.Bool(true));
T(writer.Null());
T(writer.Int(0));
T(writer.Uint(0));
T(writer.Int64(0));
T(writer.Uint64(0));
T(writer.Double(0));
T(writer.StartObject());
T(writer.StartArray());
#undef T
}
TEST(Writer, AssertMultipleRoot) {
StringBuffer buffer;
Writer<StringBuffer> writer(buffer);
writer.StartObject();
writer.EndObject();
ASSERT_THROW(writer.StartObject(), AssertException);
writer.Reset(buffer);
writer.Null();
ASSERT_THROW(writer.Int(0), AssertException);
writer.Reset(buffer);
writer.String("foo");
ASSERT_THROW(writer.StartArray(), AssertException);
writer.Reset(buffer);
writer.StartArray();
writer.EndArray();
//ASSERT_THROW(writer.Double(3.14), AssertException);
}
TEST(Writer, RootObjectIsComplete) {
StringBuffer buffer;
Writer<StringBuffer> writer(buffer);
EXPECT_FALSE(writer.IsComplete());
writer.StartObject();
EXPECT_FALSE(writer.IsComplete());
writer.String("foo");
EXPECT_FALSE(writer.IsComplete());
writer.Int(1);
EXPECT_FALSE(writer.IsComplete());
writer.EndObject();
EXPECT_TRUE(writer.IsComplete());
}
TEST(Writer, RootArrayIsComplete) {
StringBuffer buffer;
Writer<StringBuffer> writer(buffer);
EXPECT_FALSE(writer.IsComplete());
writer.StartArray();
EXPECT_FALSE(writer.IsComplete());
writer.String("foo");
EXPECT_FALSE(writer.IsComplete());
writer.Int(1);
EXPECT_FALSE(writer.IsComplete());
writer.EndArray();
EXPECT_TRUE(writer.IsComplete());
}
TEST(Writer, RootValueIsComplete) {
#define T(x)\
{\
StringBuffer buffer;\
Writer<StringBuffer> writer(buffer);\
EXPECT_FALSE(writer.IsComplete()); \
x; \
EXPECT_TRUE(writer.IsComplete()); \
}
T(writer.Null());
T(writer.Bool(true));
T(writer.Bool(false));
T(writer.Int(0));
T(writer.Uint(0));
T(writer.Int64(0));
T(writer.Uint64(0));
T(writer.Double(0));
T(writer.String(""));
#undef T
}
TEST(Writer, InvalidEncoding) {
// Fail in decoding invalid UTF-8 sequence http://www.cl.cam.ac.uk/~mgk25/ucs/examples/UTF-8-test.txt
{
GenericStringBuffer<UTF16<> > buffer;
Writer<GenericStringBuffer<UTF16<> >, UTF8<>, UTF16<> > writer(buffer);
writer.StartArray();
EXPECT_FALSE(writer.String("\xfe"));
EXPECT_FALSE(writer.String("\xff"));
EXPECT_FALSE(writer.String("\xfe\xfe\xff\xff"));
writer.EndArray();
}
// Fail in encoding
{
StringBuffer buffer;
Writer<StringBuffer, UTF32<> > writer(buffer);
static const UTF32<>::Ch s[] = { 0x110000, 0 }; // Out of U+0000 to U+10FFFF
EXPECT_FALSE(writer.String(s));
}
// Fail in unicode escaping in ASCII output
{
StringBuffer buffer;
Writer<StringBuffer, UTF32<>, ASCII<> > writer(buffer);
static const UTF32<>::Ch s[] = { 0x110000, 0 }; // Out of U+0000 to U+10FFFF
EXPECT_FALSE(writer.String(s));
}
}
TEST(Writer, ValidateEncoding) {
{
StringBuffer buffer;
Writer<StringBuffer, UTF8<>, UTF8<>, CrtAllocator, kWriteValidateEncodingFlag> writer(buffer);
writer.StartArray();
EXPECT_TRUE(writer.String("\x24")); // Dollar sign U+0024
EXPECT_TRUE(writer.String("\xC2\xA2")); // Cents sign U+00A2
EXPECT_TRUE(writer.String("\xE2\x82\xAC")); // Euro sign U+20AC
EXPECT_TRUE(writer.String("\xF0\x9D\x84\x9E")); // G clef sign U+1D11E
writer.EndArray();
EXPECT_STREQ("[\"\x24\",\"\xC2\xA2\",\"\xE2\x82\xAC\",\"\xF0\x9D\x84\x9E\"]", buffer.GetString());
}
// Fail in decoding invalid UTF-8 sequence http://www.cl.cam.ac.uk/~mgk25/ucs/examples/UTF-8-test.txt
{
StringBuffer buffer;
Writer<StringBuffer, UTF8<>, UTF8<>, CrtAllocator, kWriteValidateEncodingFlag> writer(buffer);
writer.StartArray();
EXPECT_FALSE(writer.String("\xfe"));
EXPECT_FALSE(writer.String("\xff"));
EXPECT_FALSE(writer.String("\xfe\xfe\xff\xff"));
writer.EndArray();
}
}
TEST(Writer, InvalidEventSequence) {
// {]
{
StringBuffer buffer;
Writer<StringBuffer> writer(buffer);
writer.StartObject();
EXPECT_THROW(writer.EndArray(), AssertException);
EXPECT_FALSE(writer.IsComplete());
}
// [}
{
StringBuffer buffer;
Writer<StringBuffer> writer(buffer);
writer.StartArray();
EXPECT_THROW(writer.EndObject(), AssertException);
EXPECT_FALSE(writer.IsComplete());
}
// { 1:
{
StringBuffer buffer;
Writer<StringBuffer> writer(buffer);
writer.StartObject();
EXPECT_THROW(writer.Int(1), AssertException);
EXPECT_FALSE(writer.IsComplete());
}
}
TEST(Writer, NaN) {
double nan = std::numeric_limits<double>::quiet_NaN();
EXPECT_TRUE(internal::Double(nan).IsNan());
StringBuffer buffer;
{
Writer<StringBuffer> writer(buffer);
EXPECT_FALSE(writer.Double(nan));
}
{
Writer<StringBuffer, UTF8<>, UTF8<>, CrtAllocator, kWriteNanAndInfFlag> writer(buffer);
EXPECT_TRUE(writer.Double(nan));
EXPECT_STREQ("NaN", buffer.GetString());
}
GenericStringBuffer<UTF16<> > buffer2;
Writer<GenericStringBuffer<UTF16<> > > writer2(buffer2);
EXPECT_FALSE(writer2.Double(nan));
}
TEST(Writer, Inf) {
double inf = std::numeric_limits<double>::infinity();
EXPECT_TRUE(internal::Double(inf).IsInf());
StringBuffer buffer;
{
Writer<StringBuffer> writer(buffer);
EXPECT_FALSE(writer.Double(inf));
}
{
Writer<StringBuffer> writer(buffer);
EXPECT_FALSE(writer.Double(-inf));
}
{
Writer<StringBuffer, UTF8<>, UTF8<>, CrtAllocator, kWriteNanAndInfFlag> writer(buffer);
EXPECT_TRUE(writer.Double(inf));
}
{
Writer<StringBuffer, UTF8<>, UTF8<>, CrtAllocator, kWriteNanAndInfFlag> writer(buffer);
EXPECT_TRUE(writer.Double(-inf));
}
EXPECT_STREQ("Infinity-Infinity", buffer.GetString());
}
TEST(Writer, RawValue) {
StringBuffer buffer;
Writer<StringBuffer> writer(buffer);
writer.StartObject();
writer.Key("a");
writer.Int(1);
writer.Key("raw");
const char json[] = "[\"Hello\\nWorld\", 123.456]";
writer.RawValue(json, strlen(json), kArrayType);
writer.EndObject();
EXPECT_TRUE(writer.IsComplete());
EXPECT_STREQ("{\"a\":1,\"raw\":[\"Hello\\nWorld\", 123.456]}", buffer.GetString());
}