Implementation of JSON Streaming Parser
This change will introduce a streaming parser capability to Haiku. The existing functionality of writing the JSON data to a BMessage in-memory model is retained. The new parser implements a SAX-style listener based interface where the listener accepts parse events. Unit tests have been supplied for the JSON parser as well.
This commit is contained in:
@@ -39,6 +39,11 @@ for architectureObject in [ MultiArchSubDirSetup ] {
|
|||||||
HashString.cpp
|
HashString.cpp
|
||||||
IconButton.cpp
|
IconButton.cpp
|
||||||
IconView.cpp
|
IconView.cpp
|
||||||
|
JsonWriter.cpp
|
||||||
|
JsonEventListener.cpp
|
||||||
|
JsonMessageWriter.cpp
|
||||||
|
JsonTextWriter.cpp
|
||||||
|
JsonEvent.cpp
|
||||||
Json.cpp
|
Json.cpp
|
||||||
Keymap.cpp
|
Keymap.cpp
|
||||||
LongAndDragTrackingFilter.cpp
|
LongAndDragTrackingFilter.cpp
|
||||||
|
|||||||
+673
-385
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,127 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2017, Andrew Lindesay <[email protected]>
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
#include "JsonEvent.h"
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include <String.h>
|
||||||
|
|
||||||
|
|
||||||
|
BJsonEvent::BJsonEvent(json_event_type eventType, const char* content)
|
||||||
|
:
|
||||||
|
fEventType(eventType),
|
||||||
|
fContent(content),
|
||||||
|
fOwnedContent(NULL)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BJsonEvent::BJsonEvent(const char* content)
|
||||||
|
:
|
||||||
|
fEventType(B_JSON_STRING),
|
||||||
|
fContent(content),
|
||||||
|
fOwnedContent(NULL)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BJsonEvent::BJsonEvent(double content) {
|
||||||
|
fEventType = B_JSON_NUMBER;
|
||||||
|
fContent = NULL;
|
||||||
|
|
||||||
|
int actualLength = snprintf(0, 0, "%f", content) + 1;
|
||||||
|
char* buffer = (char*) malloc(sizeof(char) * actualLength);
|
||||||
|
|
||||||
|
if (buffer == NULL) {
|
||||||
|
fprintf(stderr, "memory exhaustion\n");
|
||||||
|
// given the risk, this is the only sensible thing to do here.
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
sprintf(buffer, "%f", content);
|
||||||
|
fOwnedContent = buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BJsonEvent::BJsonEvent(int64 content) {
|
||||||
|
fEventType = B_JSON_NUMBER;
|
||||||
|
fContent = NULL;
|
||||||
|
fOwnedContent = NULL;
|
||||||
|
|
||||||
|
static const char* zeroValue = "0";
|
||||||
|
static const char* oneValue = "1";
|
||||||
|
|
||||||
|
switch (content) {
|
||||||
|
case 0:
|
||||||
|
fContent = zeroValue;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
fContent = oneValue;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
int actualLength = snprintf(0, 0, "%" B_PRId64, content) + 1;
|
||||||
|
char* buffer = (char*) malloc(sizeof(char) * actualLength);
|
||||||
|
|
||||||
|
if (buffer == NULL) {
|
||||||
|
fprintf(stderr, "memory exhaustion\n");
|
||||||
|
// given the risk, this is the only sensible thing to do
|
||||||
|
// here.
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
sprintf(buffer, "%" B_PRId64, content);
|
||||||
|
fOwnedContent = buffer;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BJsonEvent::BJsonEvent(json_event_type eventType)
|
||||||
|
:
|
||||||
|
fEventType(eventType),
|
||||||
|
fContent(NULL),
|
||||||
|
fOwnedContent(NULL)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BJsonEvent::~BJsonEvent()
|
||||||
|
{
|
||||||
|
if (NULL != fOwnedContent)
|
||||||
|
free(fOwnedContent);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
json_event_type
|
||||||
|
BJsonEvent::EventType() const
|
||||||
|
{
|
||||||
|
return fEventType;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const char*
|
||||||
|
BJsonEvent::Content() const
|
||||||
|
{
|
||||||
|
if (NULL != fOwnedContent)
|
||||||
|
return fOwnedContent;
|
||||||
|
return fContent;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
double
|
||||||
|
BJsonEvent::ContentDouble() const
|
||||||
|
{
|
||||||
|
return strtod(Content(), NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int64
|
||||||
|
BJsonEvent::ContentInteger() const
|
||||||
|
{
|
||||||
|
return strtoll(Content(), NULL, 10);
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2017, Andrew Lindesay <[email protected]>
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "JsonEventListener.h"
|
||||||
|
|
||||||
|
|
||||||
|
BJsonEventListener::BJsonEventListener()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BJsonEventListener::~BJsonEventListener()
|
||||||
|
{
|
||||||
|
}
|
||||||
@@ -0,0 +1,520 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2017, Andrew Lindesay <[email protected]>
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "JsonMessageWriter.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace BPrivate {
|
||||||
|
|
||||||
|
/*! The class and sub-classes of it are used as a stack internal to the
|
||||||
|
BJsonMessageWriter class. As the JSON is parsed, the stack of these
|
||||||
|
internal listeners follows the stack of the JSON parsing in terms of
|
||||||
|
containers; arrays and objects.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class BStackedMessageEventListener : public BJsonEventListener {
|
||||||
|
public:
|
||||||
|
BStackedMessageEventListener(
|
||||||
|
BJsonMessageWriter* writer,
|
||||||
|
BStackedMessageEventListener* parent,
|
||||||
|
uint32 messageWhat);
|
||||||
|
BStackedMessageEventListener(
|
||||||
|
BJsonMessageWriter* writer,
|
||||||
|
BStackedMessageEventListener* parent,
|
||||||
|
BMessage* message);
|
||||||
|
~BStackedMessageEventListener();
|
||||||
|
|
||||||
|
bool Handle(const BJsonEvent& event);
|
||||||
|
void HandleError(status_t status, int32 line,
|
||||||
|
const char* message);
|
||||||
|
void Complete();
|
||||||
|
|
||||||
|
void AddMessage(BMessage* value);
|
||||||
|
|
||||||
|
status_t ErrorStatus();
|
||||||
|
virtual const char* NextItemName() = 0;
|
||||||
|
|
||||||
|
BStackedMessageEventListener*
|
||||||
|
Parent();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void AddBool(bool value);
|
||||||
|
void AddNull();
|
||||||
|
void AddDouble(double value);
|
||||||
|
void AddString(const char* value);
|
||||||
|
|
||||||
|
virtual bool WillAdd();
|
||||||
|
virtual void DidAdd();
|
||||||
|
|
||||||
|
void SetStackedListenerOnWriter(
|
||||||
|
BStackedMessageEventListener*
|
||||||
|
stackedListener);
|
||||||
|
|
||||||
|
BJsonMessageWriter* fWriter;
|
||||||
|
bool fOwnsMessage;
|
||||||
|
BStackedMessageEventListener
|
||||||
|
*fParent;
|
||||||
|
BMessage* fMessage;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class BStackedArrayMessageEventListener : public BStackedMessageEventListener {
|
||||||
|
public:
|
||||||
|
BStackedArrayMessageEventListener(
|
||||||
|
BJsonMessageWriter* writer,
|
||||||
|
BStackedMessageEventListener* parent);
|
||||||
|
BStackedArrayMessageEventListener(
|
||||||
|
BJsonMessageWriter* writer,
|
||||||
|
BStackedMessageEventListener* parent,
|
||||||
|
BMessage* message);
|
||||||
|
~BStackedArrayMessageEventListener();
|
||||||
|
|
||||||
|
bool Handle(const BJsonEvent& event);
|
||||||
|
|
||||||
|
const char* NextItemName();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void DidAdd();
|
||||||
|
|
||||||
|
private:
|
||||||
|
uint32 fCount;
|
||||||
|
BString fNextItemName;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class BStackedObjectMessageEventListener : public BStackedMessageEventListener {
|
||||||
|
public:
|
||||||
|
BStackedObjectMessageEventListener(
|
||||||
|
BJsonMessageWriter* writer,
|
||||||
|
BStackedMessageEventListener* parent);
|
||||||
|
BStackedObjectMessageEventListener(
|
||||||
|
BJsonMessageWriter* writer,
|
||||||
|
BStackedMessageEventListener* parent,
|
||||||
|
BMessage* message);
|
||||||
|
~BStackedObjectMessageEventListener();
|
||||||
|
|
||||||
|
bool Handle(const BJsonEvent& event);
|
||||||
|
|
||||||
|
const char* NextItemName();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool WillAdd();
|
||||||
|
void DidAdd();
|
||||||
|
private:
|
||||||
|
BString fNextItemName;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace BPrivate
|
||||||
|
|
||||||
|
using BPrivate::BStackedMessageEventListener;
|
||||||
|
using BPrivate::BStackedArrayMessageEventListener;
|
||||||
|
using BPrivate::BStackedObjectMessageEventListener;
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark - BStackedMessageEventListener
|
||||||
|
|
||||||
|
|
||||||
|
BStackedMessageEventListener::BStackedMessageEventListener(
|
||||||
|
BJsonMessageWriter* writer,
|
||||||
|
BStackedMessageEventListener* parent,
|
||||||
|
uint32 messageWhat)
|
||||||
|
{
|
||||||
|
fWriter = writer;
|
||||||
|
fParent = parent;
|
||||||
|
fOwnsMessage = true;
|
||||||
|
fMessage = new BMessage(messageWhat);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BStackedMessageEventListener::BStackedMessageEventListener(
|
||||||
|
BJsonMessageWriter* writer,
|
||||||
|
BStackedMessageEventListener* parent,
|
||||||
|
BMessage* message)
|
||||||
|
{
|
||||||
|
fWriter = writer;
|
||||||
|
fParent = parent;
|
||||||
|
fOwnsMessage = false;
|
||||||
|
fMessage = message;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BStackedMessageEventListener::~BStackedMessageEventListener()
|
||||||
|
{
|
||||||
|
if (fOwnsMessage)
|
||||||
|
delete fMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
BStackedMessageEventListener::Handle(const BJsonEvent& event)
|
||||||
|
{
|
||||||
|
if (fWriter->ErrorStatus() != B_OK)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
switch (event.EventType()) {
|
||||||
|
|
||||||
|
case B_JSON_NUMBER:
|
||||||
|
AddDouble(event.ContentDouble());
|
||||||
|
break;
|
||||||
|
|
||||||
|
case B_JSON_STRING:
|
||||||
|
AddString(event.Content());
|
||||||
|
break;
|
||||||
|
|
||||||
|
case B_JSON_TRUE:
|
||||||
|
AddBool(true);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case B_JSON_FALSE:
|
||||||
|
AddBool(false);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case B_JSON_NULL:
|
||||||
|
AddNull();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case B_JSON_OBJECT_START:
|
||||||
|
SetStackedListenerOnWriter(new BStackedObjectMessageEventListener(
|
||||||
|
fWriter, this));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case B_JSON_ARRAY_START:
|
||||||
|
SetStackedListenerOnWriter(new BStackedArrayMessageEventListener(
|
||||||
|
fWriter, this));
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
HandleError(B_NOT_ALLOWED, JSON_EVENT_LISTENER_ANY_LINE,
|
||||||
|
"unexpected type of json item to add to container");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ErrorStatus() == B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
BStackedMessageEventListener::HandleError(status_t status, int32 line,
|
||||||
|
const char* message)
|
||||||
|
{
|
||||||
|
fWriter->HandleError(status, line, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
BStackedMessageEventListener::Complete()
|
||||||
|
{
|
||||||
|
// illegal state.
|
||||||
|
HandleError(JSON_EVENT_LISTENER_ANY_LINE, B_NOT_ALLOWED,
|
||||||
|
"Complete() called on stacked message listener");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
BStackedMessageEventListener::AddMessage(BMessage* message)
|
||||||
|
{
|
||||||
|
if (WillAdd()) {
|
||||||
|
fMessage->AddMessage(NextItemName(), message);
|
||||||
|
DidAdd();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
BStackedMessageEventListener::ErrorStatus()
|
||||||
|
{
|
||||||
|
return fWriter->ErrorStatus();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BStackedMessageEventListener*
|
||||||
|
BStackedMessageEventListener::Parent()
|
||||||
|
{
|
||||||
|
return fParent;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
BStackedMessageEventListener::AddBool(bool value)
|
||||||
|
{
|
||||||
|
if (WillAdd()) {
|
||||||
|
fMessage->AddBool(NextItemName(), value);
|
||||||
|
DidAdd();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
BStackedMessageEventListener::AddNull()
|
||||||
|
{
|
||||||
|
if (WillAdd()) {
|
||||||
|
fMessage->AddPointer(NextItemName(), (void*)NULL);
|
||||||
|
DidAdd();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
BStackedMessageEventListener::AddDouble(double value)
|
||||||
|
{
|
||||||
|
if (WillAdd()) {
|
||||||
|
fMessage->AddDouble(NextItemName(), value);
|
||||||
|
DidAdd();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
BStackedMessageEventListener::AddString(const char* value)
|
||||||
|
{
|
||||||
|
if (WillAdd()) {
|
||||||
|
fMessage->AddString(NextItemName(), value);
|
||||||
|
DidAdd();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
BStackedMessageEventListener::WillAdd()
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
BStackedMessageEventListener::DidAdd()
|
||||||
|
{
|
||||||
|
// noop - present for overriding
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
BStackedMessageEventListener::SetStackedListenerOnWriter(
|
||||||
|
BStackedMessageEventListener* stackedListener)
|
||||||
|
{
|
||||||
|
fWriter->SetStackedListener(stackedListener);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark - BStackedArrayMessageEventListener
|
||||||
|
|
||||||
|
|
||||||
|
BStackedArrayMessageEventListener::BStackedArrayMessageEventListener(
|
||||||
|
BJsonMessageWriter* writer,
|
||||||
|
BStackedMessageEventListener* parent)
|
||||||
|
: BStackedMessageEventListener(writer, parent, B_JSON_MESSAGE_WHAT_ARRAY)
|
||||||
|
{
|
||||||
|
fCount = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BStackedArrayMessageEventListener::BStackedArrayMessageEventListener(
|
||||||
|
BJsonMessageWriter* writer,
|
||||||
|
BStackedMessageEventListener* parent,
|
||||||
|
BMessage* message)
|
||||||
|
: BStackedMessageEventListener(writer, parent, message)
|
||||||
|
{
|
||||||
|
message->what = B_JSON_MESSAGE_WHAT_ARRAY;
|
||||||
|
fCount = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BStackedArrayMessageEventListener::~BStackedArrayMessageEventListener()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
BStackedArrayMessageEventListener::Handle(const BJsonEvent& event)
|
||||||
|
{
|
||||||
|
if (fWriter->ErrorStatus() != B_OK)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
switch (event.EventType()) {
|
||||||
|
case B_JSON_ARRAY_END:
|
||||||
|
if (fParent != NULL)
|
||||||
|
fParent->AddMessage(fMessage);
|
||||||
|
SetStackedListenerOnWriter(fParent);
|
||||||
|
delete this;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return BStackedMessageEventListener::Handle(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const char*
|
||||||
|
BStackedArrayMessageEventListener::NextItemName()
|
||||||
|
{
|
||||||
|
fNextItemName.SetToFormat("%" B_PRIu32, fCount);
|
||||||
|
return fNextItemName.String();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
BStackedArrayMessageEventListener::DidAdd()
|
||||||
|
{
|
||||||
|
BStackedMessageEventListener::DidAdd();
|
||||||
|
fCount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark - BStackedObjectMessageEventListener
|
||||||
|
|
||||||
|
|
||||||
|
BStackedObjectMessageEventListener::BStackedObjectMessageEventListener(
|
||||||
|
BJsonMessageWriter* writer,
|
||||||
|
BStackedMessageEventListener* parent)
|
||||||
|
: BStackedMessageEventListener(writer, parent, B_JSON_MESSAGE_WHAT_OBJECT)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BStackedObjectMessageEventListener::BStackedObjectMessageEventListener(
|
||||||
|
BJsonMessageWriter* writer,
|
||||||
|
BStackedMessageEventListener* parent,
|
||||||
|
BMessage* message)
|
||||||
|
: BStackedMessageEventListener(writer, parent, message)
|
||||||
|
{
|
||||||
|
message->what = B_JSON_MESSAGE_WHAT_OBJECT;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BStackedObjectMessageEventListener::~BStackedObjectMessageEventListener()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
BStackedObjectMessageEventListener::Handle(const BJsonEvent& event)
|
||||||
|
{
|
||||||
|
if (fWriter->ErrorStatus() != B_OK)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
switch (event.EventType()) {
|
||||||
|
case B_JSON_OBJECT_END:
|
||||||
|
if (fParent != NULL)
|
||||||
|
fParent->AddMessage(fMessage);
|
||||||
|
SetStackedListenerOnWriter(fParent);
|
||||||
|
delete this;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case B_JSON_OBJECT_NAME:
|
||||||
|
fNextItemName.SetTo(event.Content());
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return BStackedMessageEventListener::Handle(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const char*
|
||||||
|
BStackedObjectMessageEventListener::NextItemName()
|
||||||
|
{
|
||||||
|
return fNextItemName.String();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
BStackedObjectMessageEventListener::WillAdd()
|
||||||
|
{
|
||||||
|
if (0 == fNextItemName.Length()) {
|
||||||
|
HandleError(B_NOT_ALLOWED, JSON_EVENT_LISTENER_ANY_LINE,
|
||||||
|
"missing name for adding value into an object");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
BStackedObjectMessageEventListener::DidAdd()
|
||||||
|
{
|
||||||
|
BStackedMessageEventListener::DidAdd();
|
||||||
|
fNextItemName.SetTo("", 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark - BJsonMessageWriter
|
||||||
|
|
||||||
|
|
||||||
|
BJsonMessageWriter::BJsonMessageWriter(BMessage& message)
|
||||||
|
{
|
||||||
|
fTopLevelMessage = &message;
|
||||||
|
fStackedListener = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BJsonMessageWriter::~BJsonMessageWriter()
|
||||||
|
{
|
||||||
|
BStackedMessageEventListener* listener = fStackedListener;
|
||||||
|
|
||||||
|
while (listener != NULL) {
|
||||||
|
BStackedMessageEventListener* nextListener = listener->Parent();
|
||||||
|
delete listener;
|
||||||
|
listener = nextListener;
|
||||||
|
}
|
||||||
|
|
||||||
|
fStackedListener = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
BJsonMessageWriter::Handle(const BJsonEvent& event)
|
||||||
|
{
|
||||||
|
if (fErrorStatus != B_OK)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (fStackedListener != NULL)
|
||||||
|
return fStackedListener->Handle(event);
|
||||||
|
else {
|
||||||
|
switch(event.EventType()) {
|
||||||
|
case B_JSON_OBJECT_START:
|
||||||
|
SetStackedListener(new BStackedObjectMessageEventListener(
|
||||||
|
this, NULL, fTopLevelMessage));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case B_JSON_ARRAY_START:
|
||||||
|
fTopLevelMessage->what = B_JSON_MESSAGE_WHAT_ARRAY;
|
||||||
|
SetStackedListener(new BStackedArrayMessageEventListener(
|
||||||
|
this, NULL, fTopLevelMessage));
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
HandleError(B_NOT_ALLOWED, JSON_EVENT_LISTENER_ANY_LINE,
|
||||||
|
"a message object can only handle an object or an array"
|
||||||
|
"at the top level");
|
||||||
|
return false;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true; // keep going
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
BJsonMessageWriter::Complete()
|
||||||
|
{
|
||||||
|
if (fStackedListener != NULL) {
|
||||||
|
HandleError(B_BAD_DATA, JSON_EVENT_LISTENER_ANY_LINE,
|
||||||
|
"unexpected end of input data processing structure");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
BJsonMessageWriter::SetStackedListener(
|
||||||
|
BStackedMessageEventListener* listener)
|
||||||
|
{
|
||||||
|
fStackedListener = listener;
|
||||||
|
}
|
||||||
@@ -0,0 +1,697 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2017, Andrew Lindesay <[email protected]>
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "JsonTextWriter.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include <UnicodeChar.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace BPrivate {
|
||||||
|
|
||||||
|
|
||||||
|
static bool
|
||||||
|
b_json_is_7bit_clean(uint8 c)
|
||||||
|
{
|
||||||
|
return c >= 0x20 && c < 0x7f;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static bool
|
||||||
|
b_json_is_illegal(uint8 c) {
|
||||||
|
return c < 0x20 || c == 0x7f;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static const char*
|
||||||
|
b_json_simple_esc_sequence(char c)
|
||||||
|
{
|
||||||
|
switch (c) {
|
||||||
|
case '"':
|
||||||
|
return "\\\"";
|
||||||
|
case '\\':
|
||||||
|
return "\\\\";
|
||||||
|
case '/':
|
||||||
|
return "\\/";
|
||||||
|
case '\b':
|
||||||
|
return "\\b";
|
||||||
|
case '\f':
|
||||||
|
return "\\f";
|
||||||
|
case '\n':
|
||||||
|
return "\\n";
|
||||||
|
case '\r':
|
||||||
|
return "\\r";
|
||||||
|
case '\t':
|
||||||
|
return "\\t";
|
||||||
|
default:
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*! The class and sub-classes of it are used as a stack internal to the
|
||||||
|
BJsonTextWriter class. As the JSON is parsed, the stack of these
|
||||||
|
internal listeners follows the stack of the JSON parsing in terms of
|
||||||
|
containers; arrays and objects.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class BJsonTextWriterStackedEventListener : public BJsonEventListener {
|
||||||
|
public:
|
||||||
|
BJsonTextWriterStackedEventListener(
|
||||||
|
BJsonTextWriter* writer,
|
||||||
|
BJsonTextWriterStackedEventListener* parent);
|
||||||
|
~BJsonTextWriterStackedEventListener();
|
||||||
|
|
||||||
|
bool Handle(const BJsonEvent& event);
|
||||||
|
void HandleError(status_t status, int32 line,
|
||||||
|
const char* message);
|
||||||
|
void Complete();
|
||||||
|
|
||||||
|
status_t ErrorStatus();
|
||||||
|
|
||||||
|
BJsonTextWriterStackedEventListener*
|
||||||
|
Parent();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
status_t StreamNumberNode(const BJsonEvent& event);
|
||||||
|
|
||||||
|
status_t StreamStringVerbatim(const char* string);
|
||||||
|
status_t StreamStringVerbatim(const char* string,
|
||||||
|
off_t offset, size_t length);
|
||||||
|
|
||||||
|
status_t StreamStringEncoded(const char* string);
|
||||||
|
status_t StreamStringEncoded(const char* string,
|
||||||
|
off_t offset, size_t length);
|
||||||
|
|
||||||
|
status_t StreamQuotedEncodedString(const char* string);
|
||||||
|
status_t StreamQuotedEncodedString(const char* string,
|
||||||
|
off_t offset, size_t length);
|
||||||
|
|
||||||
|
status_t StreamChar(char c);
|
||||||
|
|
||||||
|
virtual bool WillAdd();
|
||||||
|
virtual void DidAdd();
|
||||||
|
|
||||||
|
void SetStackedListenerOnWriter(
|
||||||
|
BJsonTextWriterStackedEventListener*
|
||||||
|
stackedListener);
|
||||||
|
|
||||||
|
BJsonTextWriter*
|
||||||
|
fWriter;
|
||||||
|
BJsonTextWriterStackedEventListener*
|
||||||
|
fParent;
|
||||||
|
uint32 fCount;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class BJsonTextWriterArrayStackedEventListener
|
||||||
|
: public BJsonTextWriterStackedEventListener {
|
||||||
|
public:
|
||||||
|
BJsonTextWriterArrayStackedEventListener(
|
||||||
|
BJsonTextWriter* writer,
|
||||||
|
BJsonTextWriterStackedEventListener* parent);
|
||||||
|
~BJsonTextWriterArrayStackedEventListener();
|
||||||
|
|
||||||
|
bool Handle(const BJsonEvent& event);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool WillAdd();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class BJsonTextWriterObjectStackedEventListener
|
||||||
|
: public BJsonTextWriterStackedEventListener {
|
||||||
|
public:
|
||||||
|
BJsonTextWriterObjectStackedEventListener(
|
||||||
|
BJsonTextWriter* writer,
|
||||||
|
BJsonTextWriterStackedEventListener* parent);
|
||||||
|
~BJsonTextWriterObjectStackedEventListener();
|
||||||
|
|
||||||
|
bool Handle(const BJsonEvent& event);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace BPrivate
|
||||||
|
|
||||||
|
|
||||||
|
using BPrivate::BJsonTextWriterStackedEventListener;
|
||||||
|
using BPrivate::BJsonTextWriterArrayStackedEventListener;
|
||||||
|
using BPrivate::BJsonTextWriterObjectStackedEventListener;
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark - BJsonTextWriterStackedEventListener
|
||||||
|
|
||||||
|
|
||||||
|
BJsonTextWriterStackedEventListener::BJsonTextWriterStackedEventListener(
|
||||||
|
BJsonTextWriter* writer,
|
||||||
|
BJsonTextWriterStackedEventListener* parent)
|
||||||
|
{
|
||||||
|
fWriter = writer;
|
||||||
|
fParent = parent;
|
||||||
|
fCount = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BJsonTextWriterStackedEventListener::~BJsonTextWriterStackedEventListener()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
BJsonTextWriterStackedEventListener::Handle(const BJsonEvent& event)
|
||||||
|
{
|
||||||
|
status_t writeResult = B_OK;
|
||||||
|
|
||||||
|
if (fWriter->ErrorStatus() != B_OK)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
switch (event.EventType()) {
|
||||||
|
|
||||||
|
case B_JSON_NUMBER:
|
||||||
|
case B_JSON_STRING:
|
||||||
|
case B_JSON_TRUE:
|
||||||
|
case B_JSON_FALSE:
|
||||||
|
case B_JSON_NULL:
|
||||||
|
case B_JSON_OBJECT_START:
|
||||||
|
case B_JSON_ARRAY_START:
|
||||||
|
if (!WillAdd())
|
||||||
|
return false;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (event.EventType()) {
|
||||||
|
|
||||||
|
case B_JSON_NUMBER:
|
||||||
|
writeResult = StreamNumberNode(event);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case B_JSON_STRING:
|
||||||
|
writeResult = StreamQuotedEncodedString(event.Content());
|
||||||
|
break;
|
||||||
|
|
||||||
|
case B_JSON_TRUE:
|
||||||
|
writeResult = StreamStringVerbatim("true", 0, 4);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case B_JSON_FALSE:
|
||||||
|
writeResult = StreamStringVerbatim("false", 0, 5);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case B_JSON_NULL:
|
||||||
|
writeResult = StreamStringVerbatim("null", 0, 4);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case B_JSON_OBJECT_START:
|
||||||
|
writeResult = StreamChar('{');
|
||||||
|
|
||||||
|
if (writeResult == B_OK) {
|
||||||
|
SetStackedListenerOnWriter(
|
||||||
|
new BJsonTextWriterObjectStackedEventListener(fWriter, this));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case B_JSON_ARRAY_START:
|
||||||
|
writeResult = StreamChar('[');
|
||||||
|
|
||||||
|
if (writeResult == B_OK) {
|
||||||
|
SetStackedListenerOnWriter(
|
||||||
|
new BJsonTextWriterArrayStackedEventListener(fWriter, this));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
HandleError(B_NOT_ALLOWED, JSON_EVENT_LISTENER_ANY_LINE,
|
||||||
|
"unexpected type of json item to add to container");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (writeResult == B_OK)
|
||||||
|
DidAdd();
|
||||||
|
else {
|
||||||
|
HandleError(writeResult, JSON_EVENT_LISTENER_ANY_LINE,
|
||||||
|
"error writing output");
|
||||||
|
}
|
||||||
|
|
||||||
|
return ErrorStatus() == B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
BJsonTextWriterStackedEventListener::HandleError(status_t status, int32 line,
|
||||||
|
const char* message)
|
||||||
|
{
|
||||||
|
fWriter->HandleError(status, line, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
BJsonTextWriterStackedEventListener::Complete()
|
||||||
|
{
|
||||||
|
// illegal state.
|
||||||
|
HandleError(JSON_EVENT_LISTENER_ANY_LINE, B_NOT_ALLOWED,
|
||||||
|
"Complete() called on stacked message listener");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
BJsonTextWriterStackedEventListener::ErrorStatus()
|
||||||
|
{
|
||||||
|
return fWriter->ErrorStatus();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BJsonTextWriterStackedEventListener*
|
||||||
|
BJsonTextWriterStackedEventListener::Parent()
|
||||||
|
{
|
||||||
|
return fParent;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
BJsonTextWriterStackedEventListener::StreamNumberNode(const BJsonEvent& event)
|
||||||
|
{
|
||||||
|
return fWriter->StreamNumberNode(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
BJsonTextWriterStackedEventListener::StreamStringVerbatim(const char* string)
|
||||||
|
{
|
||||||
|
return fWriter->StreamStringVerbatim(string);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
BJsonTextWriterStackedEventListener::StreamStringVerbatim(const char* string,
|
||||||
|
off_t offset, size_t length)
|
||||||
|
{
|
||||||
|
return fWriter->StreamStringVerbatim(string, offset, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
BJsonTextWriterStackedEventListener::StreamStringEncoded(const char* string)
|
||||||
|
{
|
||||||
|
return fWriter->StreamStringEncoded(string);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
BJsonTextWriterStackedEventListener::StreamStringEncoded(const char* string,
|
||||||
|
off_t offset, size_t length)
|
||||||
|
{
|
||||||
|
return fWriter->StreamStringEncoded(string, offset, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
BJsonTextWriterStackedEventListener::StreamQuotedEncodedString(const char* string)
|
||||||
|
{
|
||||||
|
return fWriter->StreamQuotedEncodedString(string);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
BJsonTextWriterStackedEventListener::StreamQuotedEncodedString(const char* string,
|
||||||
|
off_t offset, size_t length)
|
||||||
|
{
|
||||||
|
return fWriter->StreamQuotedEncodedString(string, offset, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
BJsonTextWriterStackedEventListener::StreamChar(char c)
|
||||||
|
{
|
||||||
|
return fWriter->StreamChar(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
BJsonTextWriterStackedEventListener::WillAdd()
|
||||||
|
{
|
||||||
|
return true; // carry on
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
BJsonTextWriterStackedEventListener::DidAdd()
|
||||||
|
{
|
||||||
|
fCount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
BJsonTextWriterStackedEventListener::SetStackedListenerOnWriter(
|
||||||
|
BJsonTextWriterStackedEventListener* stackedListener)
|
||||||
|
{
|
||||||
|
fWriter->SetStackedListener(stackedListener);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark - BJsonTextWriterArrayStackedEventListener
|
||||||
|
|
||||||
|
|
||||||
|
BJsonTextWriterArrayStackedEventListener::BJsonTextWriterArrayStackedEventListener(
|
||||||
|
BJsonTextWriter* writer,
|
||||||
|
BJsonTextWriterStackedEventListener* parent)
|
||||||
|
: BJsonTextWriterStackedEventListener(writer, parent)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BJsonTextWriterArrayStackedEventListener
|
||||||
|
::~BJsonTextWriterArrayStackedEventListener()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
BJsonTextWriterArrayStackedEventListener::Handle(const BJsonEvent& event)
|
||||||
|
{
|
||||||
|
status_t writeResult = B_OK;
|
||||||
|
|
||||||
|
if (fWriter->ErrorStatus() != B_OK)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
switch (event.EventType()) {
|
||||||
|
case B_JSON_ARRAY_END:
|
||||||
|
{
|
||||||
|
writeResult = StreamChar(']');
|
||||||
|
|
||||||
|
if (writeResult == B_OK) {
|
||||||
|
SetStackedListenerOnWriter(fParent);
|
||||||
|
delete this;
|
||||||
|
return true; // must exit immediately after delete this.
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
return BJsonTextWriterStackedEventListener::Handle(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(writeResult != B_OK) {
|
||||||
|
HandleError(writeResult, JSON_EVENT_LISTENER_ANY_LINE,
|
||||||
|
"error writing output");
|
||||||
|
}
|
||||||
|
|
||||||
|
return ErrorStatus() == B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
BJsonTextWriterArrayStackedEventListener::WillAdd()
|
||||||
|
{
|
||||||
|
status_t writeResult = B_OK;
|
||||||
|
|
||||||
|
if (writeResult == B_OK && fCount > 0)
|
||||||
|
writeResult = StreamChar(',');
|
||||||
|
|
||||||
|
if (writeResult != B_OK) {
|
||||||
|
HandleError(B_IO_ERROR, JSON_EVENT_LISTENER_ANY_LINE,
|
||||||
|
"error writing data");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return BJsonTextWriterStackedEventListener::WillAdd();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark - BJsonTextWriterObjectStackedEventListener
|
||||||
|
|
||||||
|
|
||||||
|
BJsonTextWriterObjectStackedEventListener::BJsonTextWriterObjectStackedEventListener(
|
||||||
|
BJsonTextWriter* writer,
|
||||||
|
BJsonTextWriterStackedEventListener* parent)
|
||||||
|
: BJsonTextWriterStackedEventListener(writer, parent)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BJsonTextWriterObjectStackedEventListener
|
||||||
|
::~BJsonTextWriterObjectStackedEventListener()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
BJsonTextWriterObjectStackedEventListener::Handle(const BJsonEvent& event)
|
||||||
|
{
|
||||||
|
status_t writeResult = B_OK;
|
||||||
|
|
||||||
|
if (fWriter->ErrorStatus() != B_OK)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
switch (event.EventType()) {
|
||||||
|
case B_JSON_OBJECT_END:
|
||||||
|
{
|
||||||
|
writeResult = StreamChar('}');
|
||||||
|
|
||||||
|
if (writeResult == B_OK) {
|
||||||
|
SetStackedListenerOnWriter(fParent);
|
||||||
|
delete this;
|
||||||
|
return true; // just exit after delete this.
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case B_JSON_OBJECT_NAME:
|
||||||
|
{
|
||||||
|
if (writeResult == B_OK && fCount > 0)
|
||||||
|
writeResult = StreamChar(',');
|
||||||
|
|
||||||
|
if (writeResult == B_OK)
|
||||||
|
writeResult = StreamQuotedEncodedString(event.Content());
|
||||||
|
|
||||||
|
if (writeResult == B_OK)
|
||||||
|
writeResult = StreamChar(':');
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
return BJsonTextWriterStackedEventListener::Handle(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (writeResult != B_OK) {
|
||||||
|
HandleError(writeResult, JSON_EVENT_LISTENER_ANY_LINE,
|
||||||
|
"error writing data");
|
||||||
|
}
|
||||||
|
|
||||||
|
return ErrorStatus() == B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark - BJsonTextWriter
|
||||||
|
|
||||||
|
|
||||||
|
BJsonTextWriter::BJsonTextWriter(
|
||||||
|
BDataIO* dataIO)
|
||||||
|
:
|
||||||
|
fDataIO(dataIO)
|
||||||
|
{
|
||||||
|
|
||||||
|
// this is a preparation for this buffer to easily be used later
|
||||||
|
// to efficiently output encoded unicode characters.
|
||||||
|
|
||||||
|
fUnicodeAssemblyBuffer[0] = '\\';
|
||||||
|
fUnicodeAssemblyBuffer[1] = 'u';
|
||||||
|
|
||||||
|
fStackedListener = new BJsonTextWriterStackedEventListener(this, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BJsonTextWriter::~BJsonTextWriter()
|
||||||
|
{
|
||||||
|
BJsonTextWriterStackedEventListener* listener = fStackedListener;
|
||||||
|
|
||||||
|
while (listener != NULL) {
|
||||||
|
BJsonTextWriterStackedEventListener* nextListener = listener->Parent();
|
||||||
|
delete listener;
|
||||||
|
listener = nextListener;
|
||||||
|
}
|
||||||
|
|
||||||
|
fStackedListener = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
BJsonTextWriter::Handle(const BJsonEvent& event)
|
||||||
|
{
|
||||||
|
return fStackedListener->Handle(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
BJsonTextWriter::Complete()
|
||||||
|
{
|
||||||
|
// upon construction, this object will add one listener to the
|
||||||
|
// stack. On complete, this listener should still be there;
|
||||||
|
// otherwise this implies an unterminated structure such as array
|
||||||
|
// / object.
|
||||||
|
|
||||||
|
if (fStackedListener->Parent() != NULL) {
|
||||||
|
HandleError(B_BAD_DATA, JSON_EVENT_LISTENER_ANY_LINE,
|
||||||
|
"unexpected end of input data");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
BJsonTextWriter::SetStackedListener(
|
||||||
|
BJsonTextWriterStackedEventListener* stackedListener)
|
||||||
|
{
|
||||||
|
fStackedListener = stackedListener;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
BJsonTextWriter::StreamNumberNode(const BJsonEvent& event)
|
||||||
|
{
|
||||||
|
return StreamStringVerbatim(event.Content());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
BJsonTextWriter::StreamStringVerbatim(const char* string)
|
||||||
|
{
|
||||||
|
return StreamStringVerbatim(string, 0, strlen(string));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
BJsonTextWriter::StreamStringVerbatim(const char* string,
|
||||||
|
off_t offset, size_t length)
|
||||||
|
{
|
||||||
|
return fDataIO->WriteExactly(&string[offset], length);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
BJsonTextWriter::StreamStringEncoded(const char* string)
|
||||||
|
{
|
||||||
|
return StreamStringEncoded(string, 0, strlen(string));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*! Note that this method will expect a UTF-8 encoded string. */
|
||||||
|
|
||||||
|
status_t
|
||||||
|
BJsonTextWriter::StreamStringEncoded(const char* string,
|
||||||
|
off_t offset, size_t length)
|
||||||
|
{
|
||||||
|
status_t writeResult = B_OK;
|
||||||
|
uint8* string8bit = (uint8*)string;
|
||||||
|
|
||||||
|
while (writeResult == B_OK && 0 != length) {
|
||||||
|
uint8 c = string8bit[offset];
|
||||||
|
const char* simpleEsc = b_json_simple_esc_sequence(c);
|
||||||
|
|
||||||
|
// simple escape sequence involving the backslash + one character.
|
||||||
|
|
||||||
|
if (simpleEsc != NULL) {
|
||||||
|
writeResult = StreamStringVerbatim(simpleEsc, 0, 2);
|
||||||
|
|
||||||
|
if (writeResult == B_OK) {
|
||||||
|
offset++;
|
||||||
|
length--;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
|
||||||
|
if (b_json_is_7bit_clean(c)) {
|
||||||
|
|
||||||
|
// roll forward while the characters are simple and then
|
||||||
|
// output them at as a block verbatim.
|
||||||
|
|
||||||
|
uint32 count7BitClean = 1;
|
||||||
|
|
||||||
|
while (count7BitClean < length
|
||||||
|
&& b_json_is_7bit_clean(
|
||||||
|
string8bit[offset + count7BitClean])) {
|
||||||
|
count7BitClean++;
|
||||||
|
}
|
||||||
|
|
||||||
|
writeResult = StreamStringVerbatim(&string[offset], 0,
|
||||||
|
count7BitClean);
|
||||||
|
|
||||||
|
if (writeResult == B_OK) {
|
||||||
|
offset += count7BitClean;
|
||||||
|
length -= count7BitClean;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (b_json_is_illegal(c)) {
|
||||||
|
fprintf(stderr, "! string encoding error - illegal "
|
||||||
|
"character [%" B_PRIu32 "]\n", static_cast<uint32>(c));
|
||||||
|
offset++;
|
||||||
|
length--;
|
||||||
|
} else {
|
||||||
|
|
||||||
|
// if the character is < 128 then it can be rendered
|
||||||
|
// verbatim - check how many are like this and then
|
||||||
|
// render those verbatim.
|
||||||
|
|
||||||
|
const char* stringInitial = &string[offset];
|
||||||
|
uint32 unicodeCharacter = BUnicodeChar::FromUTF8(
|
||||||
|
&stringInitial);
|
||||||
|
|
||||||
|
sprintf(&fUnicodeAssemblyBuffer[2], "%04" B_PRIx32,
|
||||||
|
unicodeCharacter);
|
||||||
|
writeResult = StreamStringVerbatim(fUnicodeAssemblyBuffer,
|
||||||
|
0, 6);
|
||||||
|
|
||||||
|
if (writeResult == B_OK) {
|
||||||
|
uint32 sequence_length
|
||||||
|
= (uint32)(stringInitial - &string[offset]);
|
||||||
|
offset += sequence_length;
|
||||||
|
length -= sequence_length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return writeResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
BJsonTextWriter::StreamQuotedEncodedString(const char* string)
|
||||||
|
{
|
||||||
|
return StreamQuotedEncodedString(string, 0, strlen(string));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
BJsonTextWriter::StreamQuotedEncodedString(const char* string,
|
||||||
|
off_t offset, size_t length)
|
||||||
|
{
|
||||||
|
status_t write_result = B_OK;
|
||||||
|
|
||||||
|
if (write_result == B_OK)
|
||||||
|
write_result = StreamChar('\"');
|
||||||
|
|
||||||
|
if (write_result == B_OK)
|
||||||
|
write_result = StreamStringEncoded(string, offset, length);
|
||||||
|
|
||||||
|
if (write_result == B_OK)
|
||||||
|
write_result = StreamChar('\"');
|
||||||
|
|
||||||
|
return write_result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
BJsonTextWriter::StreamChar(char c)
|
||||||
|
{
|
||||||
|
return fDataIO->WriteExactly(&c, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,144 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2017, Andrew Lindesay <[email protected]>
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "JsonWriter.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include <UnicodeChar.h>
|
||||||
|
|
||||||
|
|
||||||
|
BJsonWriter::BJsonWriter()
|
||||||
|
:
|
||||||
|
fErrorStatus(B_OK)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BJsonWriter::~BJsonWriter()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
BJsonWriter::HandleError(status_t status, int32 line,
|
||||||
|
const char* message)
|
||||||
|
{
|
||||||
|
if(fErrorStatus == B_OK) {
|
||||||
|
if (message == NULL)
|
||||||
|
message = "?";
|
||||||
|
|
||||||
|
fErrorStatus = status;
|
||||||
|
fprintf(stderr, "! json err @line %" B_PRIi32 " - %s : %s\n", line,
|
||||||
|
strerror(status), message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
BJsonWriter::ErrorStatus()
|
||||||
|
{
|
||||||
|
return fErrorStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
BJsonWriter::WriteBoolean(bool value)
|
||||||
|
{
|
||||||
|
if (value)
|
||||||
|
return WriteTrue();
|
||||||
|
|
||||||
|
return WriteFalse();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
BJsonWriter::WriteTrue()
|
||||||
|
{
|
||||||
|
Handle(BJsonEvent(B_JSON_TRUE));
|
||||||
|
return fErrorStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
BJsonWriter::WriteFalse()
|
||||||
|
{
|
||||||
|
Handle(BJsonEvent(B_JSON_FALSE));
|
||||||
|
return fErrorStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
BJsonWriter::WriteNull()
|
||||||
|
{
|
||||||
|
Handle(BJsonEvent(B_JSON_NULL));
|
||||||
|
return fErrorStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
BJsonWriter::WriteInteger(int64 value)
|
||||||
|
{
|
||||||
|
Handle(BJsonEvent(value));
|
||||||
|
return fErrorStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
BJsonWriter::WriteDouble(double value)
|
||||||
|
{
|
||||||
|
Handle(BJsonEvent(value));
|
||||||
|
return fErrorStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
BJsonWriter::WriteString(const char* value)
|
||||||
|
{
|
||||||
|
Handle(BJsonEvent(value));
|
||||||
|
return fErrorStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
BJsonWriter::WriteObjectStart()
|
||||||
|
{
|
||||||
|
Handle(BJsonEvent(B_JSON_OBJECT_START));
|
||||||
|
return fErrorStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
BJsonWriter::WriteObjectName(const char* value)
|
||||||
|
{
|
||||||
|
Handle(BJsonEvent(B_JSON_OBJECT_NAME, value));
|
||||||
|
return fErrorStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
BJsonWriter::WriteObjectEnd()
|
||||||
|
{
|
||||||
|
Handle(BJsonEvent(B_JSON_OBJECT_END));
|
||||||
|
return fErrorStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
BJsonWriter::WriteArrayStart()
|
||||||
|
{
|
||||||
|
Handle(BJsonEvent(B_JSON_ARRAY_START));
|
||||||
|
return fErrorStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
BJsonWriter::WriteArrayEnd()
|
||||||
|
{
|
||||||
|
Handle(BJsonEvent(B_JSON_ARRAY_END));
|
||||||
|
return fErrorStatus;
|
||||||
|
}
|
||||||
|
|
||||||
@@ -10,6 +10,10 @@ UnitTestLib libsharedtest.so :
|
|||||||
|
|
||||||
CalendarViewTest.cpp
|
CalendarViewTest.cpp
|
||||||
DriverSettingsMessageAdapterTest.cpp
|
DriverSettingsMessageAdapterTest.cpp
|
||||||
|
JsonEndToEndTest.cpp
|
||||||
|
JsonErrorHandlingTest.cpp
|
||||||
|
JsonTextWriterTest.cpp
|
||||||
|
JsonToMessageTest.cpp
|
||||||
GeolocationTest.cpp
|
GeolocationTest.cpp
|
||||||
NaturalCompareTest.cpp
|
NaturalCompareTest.cpp
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,215 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2017, Andrew Lindesay <[email protected]>
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
#include "JsonEndToEndTest.h"
|
||||||
|
|
||||||
|
#include <AutoDeleter.h>
|
||||||
|
|
||||||
|
#include <Json.h>
|
||||||
|
#include <JsonTextWriter.h>
|
||||||
|
|
||||||
|
#include <cppunit/TestCaller.h>
|
||||||
|
#include <cppunit/TestSuite.h>
|
||||||
|
|
||||||
|
#include "JsonSamples.h"
|
||||||
|
|
||||||
|
|
||||||
|
using namespace BPrivate;
|
||||||
|
|
||||||
|
|
||||||
|
JsonEndToEndTest::JsonEndToEndTest()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
JsonEndToEndTest::~JsonEndToEndTest()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
JsonEndToEndTest::TestParseAndWrite(char* input, char* expectedOutput)
|
||||||
|
{
|
||||||
|
BDataIO* inputData = new BMemoryIO(input, strlen(input));
|
||||||
|
ObjectDeleter<BDataIO> inputDataDeleter(inputData);
|
||||||
|
BMallocIO* outputData = new BMallocIO();
|
||||||
|
ObjectDeleter<BMallocIO> outputDataDeleter(outputData);
|
||||||
|
BPrivate::BJsonTextWriter* listener
|
||||||
|
= new BJsonTextWriter(outputData);
|
||||||
|
ObjectDeleter<BPrivate::BJsonTextWriter> listenerDeleter(listener);
|
||||||
|
|
||||||
|
// ----------------------
|
||||||
|
BPrivate::BJson::Parse(inputData, listener);
|
||||||
|
// ----------------------
|
||||||
|
|
||||||
|
CPPUNIT_ASSERT_EQUAL(B_OK, listener->ErrorStatus());
|
||||||
|
fprintf(stderr, "in >%s<\n", input);
|
||||||
|
fprintf(stderr, "expected out >%s<\n", expectedOutput);
|
||||||
|
fprintf(stderr, "actual out >%s<\n", (char*)outputData->Buffer());
|
||||||
|
CPPUNIT_ASSERT_MESSAGE("expected did no equal actual output",
|
||||||
|
0 == strncmp(expectedOutput, (char*)outputData->Buffer(),
|
||||||
|
strlen(expectedOutput)));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
JsonEndToEndTest::TestNullA()
|
||||||
|
{
|
||||||
|
TestParseAndWrite(JSON_SAMPLE_NULL_A_IN,
|
||||||
|
JSON_SAMPLE_NULL_A_EXPECTED_OUT);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
JsonEndToEndTest::TestTrueA()
|
||||||
|
{
|
||||||
|
TestParseAndWrite(JSON_SAMPLE_TRUE_A_IN,
|
||||||
|
JSON_SAMPLE_TRUE_A_EXPECTED_OUT);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
JsonEndToEndTest::TestFalseA()
|
||||||
|
{
|
||||||
|
TestParseAndWrite(JSON_SAMPLE_FALSE_A_IN,
|
||||||
|
JSON_SAMPLE_FALSE_A_EXPECTED_OUT);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
JsonEndToEndTest::TestNumberA()
|
||||||
|
{
|
||||||
|
TestParseAndWrite(JSON_SAMPLE_NUMBER_A_IN,
|
||||||
|
JSON_SAMPLE_NUMBER_A_EXPECTED_OUT);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
JsonEndToEndTest::TestStringA()
|
||||||
|
{
|
||||||
|
TestParseAndWrite(JSON_SAMPLE_STRING_A_IN,
|
||||||
|
JSON_SAMPLE_STRING_A_EXPECTED_OUT);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
JsonEndToEndTest::TestStringB()
|
||||||
|
{
|
||||||
|
TestParseAndWrite(JSON_SAMPLE_STRING_B_IN,
|
||||||
|
JSON_SAMPLE_STRING_B_EXPECTED_OUT);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* In this test, there are some UTF-8 characters. */
|
||||||
|
|
||||||
|
void
|
||||||
|
JsonEndToEndTest::TestStringA2()
|
||||||
|
{
|
||||||
|
TestParseAndWrite(JSON_SAMPLE_STRING_A2_IN,
|
||||||
|
JSON_SAMPLE_STRING_A_EXPECTED_OUT);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
JsonEndToEndTest::TestArrayA()
|
||||||
|
{
|
||||||
|
TestParseAndWrite(JSON_SAMPLE_ARRAY_A_IN, JSON_SAMPLE_ARRAY_A_EXPECTED_OUT);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
JsonEndToEndTest::TestArrayB()
|
||||||
|
{
|
||||||
|
TestParseAndWrite(JSON_SAMPLE_ARRAY_B_IN, JSON_SAMPLE_ARRAY_B_EXPECTED_OUT);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
JsonEndToEndTest::TestObjectA()
|
||||||
|
{
|
||||||
|
TestParseAndWrite(JSON_SAMPLE_OBJECT_A_IN,
|
||||||
|
JSON_SAMPLE_OBJECT_A_EXPECTED_OUT);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*! This method will test an element being unterminated; such an object that
|
||||||
|
is missing the terminating "}" symbol or a string that has no closing
|
||||||
|
quote. This is tested here because the writer
|
||||||
|
*/
|
||||||
|
|
||||||
|
void
|
||||||
|
JsonEndToEndTest::TestUnterminated(const char *input)
|
||||||
|
{
|
||||||
|
BDataIO* inputData = new BMemoryIO(input, strlen(input));
|
||||||
|
ObjectDeleter<BDataIO> inputDataDeleter(inputData);
|
||||||
|
BMallocIO* outputData = new BMallocIO();
|
||||||
|
ObjectDeleter<BMallocIO> outputDataDeleter(outputData);
|
||||||
|
BPrivate::BJsonTextWriter* listener
|
||||||
|
= new BJsonTextWriter(outputData);
|
||||||
|
ObjectDeleter<BPrivate::BJsonTextWriter> listenerDeleter(listener);
|
||||||
|
|
||||||
|
// ----------------------
|
||||||
|
BPrivate::BJson::Parse(inputData, listener);
|
||||||
|
// ----------------------
|
||||||
|
|
||||||
|
CPPUNIT_ASSERT_EQUAL(B_BAD_DATA, listener->ErrorStatus());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
JsonEndToEndTest::TestStringUnterminated()
|
||||||
|
{
|
||||||
|
TestUnterminated(JSON_SAMPLE_BROKEN_UNTERMINATED_STRING);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
JsonEndToEndTest::TestArrayUnterminated()
|
||||||
|
{
|
||||||
|
TestUnterminated(JSON_SAMPLE_BROKEN_UNTERMINATED_ARRAY);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
JsonEndToEndTest::TestObjectUnterminated()
|
||||||
|
{
|
||||||
|
TestUnterminated(JSON_SAMPLE_BROKEN_UNTERMINATED_OBJECT);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*static*/ void
|
||||||
|
JsonEndToEndTest::AddTests(BTestSuite& parent)
|
||||||
|
{
|
||||||
|
CppUnit::TestSuite& suite = *new CppUnit::TestSuite("JsonEndToEndTest");
|
||||||
|
|
||||||
|
suite.addTest(new CppUnit::TestCaller<JsonEndToEndTest>(
|
||||||
|
"JsonEndToEndTest::TestNullA", &JsonEndToEndTest::TestNullA));
|
||||||
|
suite.addTest(new CppUnit::TestCaller<JsonEndToEndTest>(
|
||||||
|
"JsonEndToEndTest::TestTrueA", &JsonEndToEndTest::TestTrueA));
|
||||||
|
suite.addTest(new CppUnit::TestCaller<JsonEndToEndTest>(
|
||||||
|
"JsonEndToEndTest::TestFalseA", &JsonEndToEndTest::TestFalseA));
|
||||||
|
suite.addTest(new CppUnit::TestCaller<JsonEndToEndTest>(
|
||||||
|
"JsonEndToEndTest::TestNumberA", &JsonEndToEndTest::TestNumberA));
|
||||||
|
suite.addTest(new CppUnit::TestCaller<JsonEndToEndTest>(
|
||||||
|
"JsonEndToEndTest::TestStringA", &JsonEndToEndTest::TestStringA));
|
||||||
|
suite.addTest(new CppUnit::TestCaller<JsonEndToEndTest>(
|
||||||
|
"JsonEndToEndTest::TestStringA2", &JsonEndToEndTest::TestStringA2));
|
||||||
|
suite.addTest(new CppUnit::TestCaller<JsonEndToEndTest>(
|
||||||
|
"JsonEndToEndTest::TestStringB", &JsonEndToEndTest::TestStringB));
|
||||||
|
suite.addTest(new CppUnit::TestCaller<JsonEndToEndTest>(
|
||||||
|
"JsonEndToEndTest::TestArrayA", &JsonEndToEndTest::TestArrayA));
|
||||||
|
suite.addTest(new CppUnit::TestCaller<JsonEndToEndTest>(
|
||||||
|
"JsonEndToEndTest::TestArrayB", &JsonEndToEndTest::TestArrayB));
|
||||||
|
suite.addTest(new CppUnit::TestCaller<JsonEndToEndTest>(
|
||||||
|
"JsonEndToEndTest::TestObjectA", &JsonEndToEndTest::TestObjectA));
|
||||||
|
suite.addTest(new CppUnit::TestCaller<JsonEndToEndTest>(
|
||||||
|
"JsonEndToEndTest::TestStringUnterminated",
|
||||||
|
&JsonEndToEndTest::TestStringUnterminated));
|
||||||
|
suite.addTest(new CppUnit::TestCaller<JsonEndToEndTest>(
|
||||||
|
"JsonEndToEndTest::TestArrayUnterminated",
|
||||||
|
&JsonEndToEndTest::TestArrayUnterminated));
|
||||||
|
suite.addTest(new CppUnit::TestCaller<JsonEndToEndTest>(
|
||||||
|
"JsonEndToEndTest::TestObjectUnterminated",
|
||||||
|
&JsonEndToEndTest::TestObjectUnterminated));
|
||||||
|
|
||||||
|
parent.addTest("JsonEndToEndTest", &suite);
|
||||||
|
}
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2017, Andrew Lindesay <[email protected]>
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
#ifndef JSON_END_TO_END_TEST_H
|
||||||
|
#define JSON_END_TO_END_TEST_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <TestCase.h>
|
||||||
|
#include <TestSuite.h>
|
||||||
|
|
||||||
|
|
||||||
|
class Sample;
|
||||||
|
|
||||||
|
|
||||||
|
class JsonEndToEndTest : public CppUnit::TestCase {
|
||||||
|
public:
|
||||||
|
JsonEndToEndTest();
|
||||||
|
virtual ~JsonEndToEndTest();
|
||||||
|
|
||||||
|
void TestNullA();
|
||||||
|
void TestTrueA();
|
||||||
|
void TestFalseA();
|
||||||
|
void TestNumberA();
|
||||||
|
void TestStringA();
|
||||||
|
void TestStringA2();
|
||||||
|
void TestStringB();
|
||||||
|
void TestArrayA();
|
||||||
|
void TestArrayB();
|
||||||
|
void TestObjectA();
|
||||||
|
|
||||||
|
void TestStringUnterminated();
|
||||||
|
void TestArrayUnterminated();
|
||||||
|
void TestObjectUnterminated();
|
||||||
|
|
||||||
|
static void AddTests(BTestSuite& suite);
|
||||||
|
private:
|
||||||
|
void TestUnterminated(const char* input);
|
||||||
|
|
||||||
|
void TestParseAndWrite(char* input,
|
||||||
|
char* expectedOutput);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif // JSON_END_TO_END_TEST_H
|
||||||
@@ -0,0 +1,354 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2017, Andrew Lindesay <[email protected]>
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
#include "JsonErrorHandlingTest.h"
|
||||||
|
|
||||||
|
#include <AutoDeleter.h>
|
||||||
|
|
||||||
|
#include <Json.h>
|
||||||
|
#include <JsonEventListener.h>
|
||||||
|
|
||||||
|
#include <cppunit/TestCaller.h>
|
||||||
|
#include <cppunit/TestSuite.h>
|
||||||
|
|
||||||
|
#include "JsonSamples.h"
|
||||||
|
|
||||||
|
|
||||||
|
using namespace BPrivate;
|
||||||
|
|
||||||
|
class ErrorCapturingListener : public BJsonEventListener {
|
||||||
|
public:
|
||||||
|
ErrorCapturingListener();
|
||||||
|
virtual ~ErrorCapturingListener();
|
||||||
|
|
||||||
|
bool Handle(const BJsonEvent& event);
|
||||||
|
void HandleError(status_t status, int32 line,
|
||||||
|
const char* message);
|
||||||
|
void Complete() {};
|
||||||
|
|
||||||
|
status_t ErrorStatus();
|
||||||
|
int32 GetErrorLine();
|
||||||
|
BString GetErrorMessage();
|
||||||
|
bool HasEventsAfterError();
|
||||||
|
json_event_type FirstEventTypeAfterError();
|
||||||
|
private:
|
||||||
|
status_t fErrorStatus;
|
||||||
|
int32 fErrorLine;
|
||||||
|
BString fErrorMessage;
|
||||||
|
json_event_type fFirstEventTypeAfterError;
|
||||||
|
int32 fEventCountAfterError;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/*! This DataIO concrete implementation is designed to open and then to fail
|
||||||
|
in order to simulate what might happen if there were an IO problem when
|
||||||
|
parsing some JSON.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class FailingDataIO : public BDataIO {
|
||||||
|
public:
|
||||||
|
FailingDataIO();
|
||||||
|
virtual ~FailingDataIO();
|
||||||
|
|
||||||
|
ssize_t Read(void* buffer, size_t size);
|
||||||
|
ssize_t Write(const void* buffer, size_t size);
|
||||||
|
|
||||||
|
status_t Flush();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark - FailingDataIO
|
||||||
|
|
||||||
|
|
||||||
|
FailingDataIO::FailingDataIO()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
FailingDataIO::~FailingDataIO()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ssize_t
|
||||||
|
FailingDataIO::Read(void* buffer, size_t size)
|
||||||
|
{
|
||||||
|
return B_IO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ssize_t
|
||||||
|
FailingDataIO::Write(const void* buffer, size_t size)
|
||||||
|
{
|
||||||
|
fprintf(stdout, "attempt to write");
|
||||||
|
return B_IO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
FailingDataIO::Flush()
|
||||||
|
{
|
||||||
|
return B_IO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark - ErrorCapturingListener
|
||||||
|
|
||||||
|
|
||||||
|
ErrorCapturingListener::ErrorCapturingListener()
|
||||||
|
{
|
||||||
|
fErrorStatus = B_OK;
|
||||||
|
fFirstEventTypeAfterError = B_JSON_NULL; // least likely
|
||||||
|
fEventCountAfterError = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ErrorCapturingListener::~ErrorCapturingListener()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
ErrorCapturingListener::Handle(const BJsonEvent& event)
|
||||||
|
{
|
||||||
|
if (fErrorStatus != B_OK) {
|
||||||
|
if (fEventCountAfterError == 0)
|
||||||
|
fFirstEventTypeAfterError = event.EventType();
|
||||||
|
|
||||||
|
fEventCountAfterError++;
|
||||||
|
}
|
||||||
|
return true; // keep going.
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
ErrorCapturingListener::HandleError(status_t status, int32 line,
|
||||||
|
const char *message)
|
||||||
|
{
|
||||||
|
fErrorStatus = status;
|
||||||
|
fErrorLine = line;
|
||||||
|
|
||||||
|
if (message != NULL)
|
||||||
|
fErrorMessage = BString(message);
|
||||||
|
else
|
||||||
|
fErrorMessage = BString();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
ErrorCapturingListener::ErrorStatus()
|
||||||
|
{
|
||||||
|
return fErrorStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int32
|
||||||
|
ErrorCapturingListener::GetErrorLine()
|
||||||
|
{
|
||||||
|
return fErrorLine;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BString
|
||||||
|
ErrorCapturingListener::GetErrorMessage()
|
||||||
|
{
|
||||||
|
return fErrorMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
json_event_type
|
||||||
|
ErrorCapturingListener::FirstEventTypeAfterError()
|
||||||
|
{
|
||||||
|
return fFirstEventTypeAfterError;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
ErrorCapturingListener::HasEventsAfterError()
|
||||||
|
{
|
||||||
|
return fEventCountAfterError > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
JsonErrorHandlingTest::JsonErrorHandlingTest()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
JsonErrorHandlingTest::~JsonErrorHandlingTest()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
JsonErrorHandlingTest::TestParseWithBadStringEscape(const char* input,
|
||||||
|
int32 line, status_t expectedStatus, char expectedBadEscapeChar)
|
||||||
|
{
|
||||||
|
BString expectedMessage;
|
||||||
|
expectedMessage.SetToFormat("unexpected escaped character [%c] "
|
||||||
|
"in string parsing", expectedBadEscapeChar);
|
||||||
|
|
||||||
|
TestParseWithErrorMessage(input, line, expectedStatus,
|
||||||
|
expectedMessage.String());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
JsonErrorHandlingTest::TestParseWithUnterminatedElement(const char* input,
|
||||||
|
int32 line, status_t expectedStatus)
|
||||||
|
{
|
||||||
|
BString expectedMessage;
|
||||||
|
expectedMessage.SetToFormat("unterminated element");
|
||||||
|
|
||||||
|
TestParseWithErrorMessage(input, line, expectedStatus,
|
||||||
|
expectedMessage.String());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
JsonErrorHandlingTest::TestParseWithUnexpectedCharacter(const char* input,
|
||||||
|
int32 line, status_t expectedStatus, char expectedChar)
|
||||||
|
{
|
||||||
|
BString expectedMessage;
|
||||||
|
expectedMessage.SetToFormat("unexpected character [%" B_PRIu8
|
||||||
|
"] (%c) when parsing element", static_cast<uint8>(expectedChar),
|
||||||
|
expectedChar);
|
||||||
|
|
||||||
|
TestParseWithErrorMessage(input, line, expectedStatus,
|
||||||
|
expectedMessage.String());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
JsonErrorHandlingTest::TestParseWithErrorMessage(const char* input, int32 line,
|
||||||
|
status_t expectedStatus, const char* expectedMessage)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "in >%s<\n", input);
|
||||||
|
BDataIO *inputData = new BMemoryIO(input, strlen(input));
|
||||||
|
ObjectDeleter<BDataIO> inputDataDeleter(inputData);
|
||||||
|
TestParseWithErrorMessage(inputData, line, expectedStatus, expectedMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
JsonErrorHandlingTest::TestParseWithErrorMessage(BDataIO* inputData, int32 line,
|
||||||
|
status_t expectedStatus, const char* expectedMessage)
|
||||||
|
{
|
||||||
|
ErrorCapturingListener* listener = new ErrorCapturingListener();
|
||||||
|
ObjectDeleter<ErrorCapturingListener> listenerDeleter(listener);
|
||||||
|
|
||||||
|
// ----------------------
|
||||||
|
BPrivate::BJson::Parse(inputData, listener);
|
||||||
|
// ----------------------
|
||||||
|
|
||||||
|
fprintf(stderr, "expected error at line %" B_PRIi32 " - %s : %s\n",
|
||||||
|
line,
|
||||||
|
strerror(expectedStatus),
|
||||||
|
expectedMessage);
|
||||||
|
|
||||||
|
fprintf(stderr, "actual error at line %" B_PRIi32 " - %s : %s\n",
|
||||||
|
listener->GetErrorLine(),
|
||||||
|
strerror(listener->ErrorStatus()),
|
||||||
|
listener->GetErrorMessage().String());
|
||||||
|
|
||||||
|
if (listener->HasEventsAfterError()) {
|
||||||
|
fprintf(stderr, "first event after error [%d]\n",
|
||||||
|
listener->FirstEventTypeAfterError());
|
||||||
|
}
|
||||||
|
|
||||||
|
CPPUNIT_ASSERT(!listener->HasEventsAfterError());
|
||||||
|
CPPUNIT_ASSERT_EQUAL(expectedStatus, listener->ErrorStatus());
|
||||||
|
CPPUNIT_ASSERT_EQUAL(line, listener->GetErrorLine());
|
||||||
|
CPPUNIT_ASSERT(0 == strcmp(expectedMessage,
|
||||||
|
listener->GetErrorMessage().String()));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
JsonErrorHandlingTest::TestCompletelyUnknown()
|
||||||
|
{
|
||||||
|
TestParseWithUnexpectedCharacter(
|
||||||
|
JSON_SAMPLE_BROKEN_COMPLETELY_UNKNOWN, 1, B_BAD_DATA, 'z');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
JsonErrorHandlingTest::TestObjectWithPrematureSeparator()
|
||||||
|
{
|
||||||
|
TestParseWithErrorMessage(JSON_SAMPLE_BROKEN_OBJECT_PREMATURE_SEPARATOR, 1,
|
||||||
|
B_BAD_DATA, "unexpected item separator when parsing start of object");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
JsonErrorHandlingTest::TestStringUnterminated()
|
||||||
|
{
|
||||||
|
TestParseWithErrorMessage(JSON_SAMPLE_BROKEN_UNTERMINATED_STRING, 1,
|
||||||
|
B_BAD_DATA, "unexpected end of input");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
JsonErrorHandlingTest::TestBadStringEscape()
|
||||||
|
{
|
||||||
|
TestParseWithBadStringEscape(
|
||||||
|
JSON_SAMPLE_BROKEN_BAD_STRING_ESCAPE, 1, B_BAD_DATA, 'v');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
JsonErrorHandlingTest::TestBadNumber()
|
||||||
|
{
|
||||||
|
BString expectedMessage;
|
||||||
|
expectedMessage.SetToFormat("malformed number",
|
||||||
|
JSON_SAMPLE_BROKEN_NUMBER);
|
||||||
|
|
||||||
|
TestParseWithErrorMessage(JSON_SAMPLE_BROKEN_NUMBER, 1, B_BAD_DATA,
|
||||||
|
expectedMessage.String());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
JsonErrorHandlingTest::TestIOIssue()
|
||||||
|
{
|
||||||
|
BDataIO *inputData = new FailingDataIO();
|
||||||
|
ObjectDeleter<BDataIO> inputDataDeleter(inputData);
|
||||||
|
TestParseWithErrorMessage(inputData, -1, B_IO_ERROR,
|
||||||
|
"io related read error");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*static*/ void
|
||||||
|
JsonErrorHandlingTest::AddTests(BTestSuite& parent)
|
||||||
|
{
|
||||||
|
CppUnit::TestSuite& suite = *new CppUnit::TestSuite(
|
||||||
|
"JsonErrorHandlingTest");
|
||||||
|
|
||||||
|
suite.addTest(new CppUnit::TestCaller<JsonErrorHandlingTest>(
|
||||||
|
"JsonErrorHandlingTest::TestCompletelyUnknown",
|
||||||
|
&JsonErrorHandlingTest::TestCompletelyUnknown));
|
||||||
|
|
||||||
|
suite.addTest(new CppUnit::TestCaller<JsonErrorHandlingTest>(
|
||||||
|
"JsonErrorHandlingTest::TestObjectWithPrematureSeparator",
|
||||||
|
&JsonErrorHandlingTest::TestObjectWithPrematureSeparator));
|
||||||
|
|
||||||
|
suite.addTest(new CppUnit::TestCaller<JsonErrorHandlingTest>(
|
||||||
|
"JsonErrorHandlingTest::TestStringUnterminated",
|
||||||
|
&JsonErrorHandlingTest::TestStringUnterminated));
|
||||||
|
|
||||||
|
suite.addTest(new CppUnit::TestCaller<JsonErrorHandlingTest>(
|
||||||
|
"JsonErrorHandlingTest::TestBadStringEscape",
|
||||||
|
&JsonErrorHandlingTest::TestBadStringEscape));
|
||||||
|
|
||||||
|
suite.addTest(new CppUnit::TestCaller<JsonErrorHandlingTest>(
|
||||||
|
"JsonErrorHandlingTest::TestBadNumber",
|
||||||
|
&JsonErrorHandlingTest::TestBadNumber));
|
||||||
|
|
||||||
|
suite.addTest(new CppUnit::TestCaller<JsonErrorHandlingTest>(
|
||||||
|
"JsonErrorHandlingTest::TestIOIssue",
|
||||||
|
&JsonErrorHandlingTest::TestIOIssue));
|
||||||
|
|
||||||
|
parent.addTest("JsonErrorHandlingTest", &suite);
|
||||||
|
}
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2017, Andrew Lindesay <[email protected]>
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
#ifndef JSON_ERROR_HANDLING_TEST_H
|
||||||
|
#define JSON_ERROR_HANDLING_TEST_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <TestCase.h>
|
||||||
|
#include <TestSuite.h>
|
||||||
|
|
||||||
|
#include <DataIO.h>
|
||||||
|
|
||||||
|
class Sample;
|
||||||
|
|
||||||
|
|
||||||
|
class JsonErrorHandlingTest : public CppUnit::TestCase {
|
||||||
|
public:
|
||||||
|
JsonErrorHandlingTest();
|
||||||
|
virtual ~JsonErrorHandlingTest();
|
||||||
|
|
||||||
|
void TestCompletelyUnknown();
|
||||||
|
void TestObjectWithPrematureSeparator();
|
||||||
|
|
||||||
|
void TestStringUnterminated();
|
||||||
|
|
||||||
|
void TestBadStringEscape();
|
||||||
|
|
||||||
|
void TestBadNumber();
|
||||||
|
|
||||||
|
void TestIOIssue();
|
||||||
|
|
||||||
|
static void AddTests(BTestSuite& suite);
|
||||||
|
private:
|
||||||
|
void TestParseWithUnexpectedCharacter(
|
||||||
|
const char* input, int32 line,
|
||||||
|
status_t expectedStatus, char expectedChar);
|
||||||
|
|
||||||
|
void TestParseWithUnterminatedElement(
|
||||||
|
const char* input, int32 line,
|
||||||
|
status_t expectedStatus);
|
||||||
|
|
||||||
|
void TestParseWithBadStringEscape(
|
||||||
|
const char* input,
|
||||||
|
int32 line, status_t expectedStatus,
|
||||||
|
char expectedBadEscapeChar);
|
||||||
|
|
||||||
|
void TestParseWithErrorMessage(
|
||||||
|
const char* input, int32 line,
|
||||||
|
status_t expectedStatus,
|
||||||
|
const char* expectedMessage);
|
||||||
|
|
||||||
|
void TestParseWithErrorMessage(
|
||||||
|
BDataIO* data, int32 line,
|
||||||
|
status_t expectedStatus,
|
||||||
|
const char* expectedMessage);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif // JSON_ERROR_HANDLING_TEST_H
|
||||||
@@ -0,0 +1,707 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2017, Andrew Lindesay <[email protected]>
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
#ifndef JSON_SAMPLES_H
|
||||||
|
#define JSON_SAMPLES_H
|
||||||
|
|
||||||
|
|
||||||
|
#define JSON_SAMPLE_FALSE_A_IN "false"
|
||||||
|
#define JSON_SAMPLE_FALSE_A_EXPECTED_OUT JSON_SAMPLE_FALSE_A_IN
|
||||||
|
|
||||||
|
#define JSON_SAMPLE_TRUE_A_IN "true"
|
||||||
|
#define JSON_SAMPLE_TRUE_A_EXPECTED_OUT JSON_SAMPLE_TRUE_A_IN
|
||||||
|
|
||||||
|
#define JSON_SAMPLE_NULL_A_IN "null"
|
||||||
|
#define JSON_SAMPLE_NULL_A_EXPECTED_OUT JSON_SAMPLE_NULL_A_IN
|
||||||
|
|
||||||
|
#define JSON_SAMPLE_NUMBER_A_LITERAL 3.142857142857143
|
||||||
|
#define JSON_SAMPLE_NUMBER_A_IN "3.142857142857143"
|
||||||
|
#define JSON_SAMPLE_NUMBER_A_EXPECTED_OUT JSON_SAMPLE_NUMBER_A_IN
|
||||||
|
|
||||||
|
#define JSON_SAMPLE_NUMBER_B_LITERAL 1122334455
|
||||||
|
#define JSON_SAMPLE_NUMBER_B_IN "1122334455"
|
||||||
|
#define JSON_SAMPLE_NUMBER_B_EXPECTED_OUT JSON_SAMPLE_NUMBER_B_IN
|
||||||
|
|
||||||
|
/*! This sample is a string that contains a newline in the middle as well as a
|
||||||
|
unicode character escaped with an "\x..." sequence. The second version 'A2'
|
||||||
|
has the same unicode character (non US-ASCII) represented as UTF-8 directly.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define JSON_SAMPLE_STRING_A_IN "\"Lake\\nTaup\\u014d\""
|
||||||
|
#define JSON_SAMPLE_STRING_A2_IN "\"Lake\\nTaup\xc5\x8d\""
|
||||||
|
#define JSON_SAMPLE_STRING_A_EXPECTED_OUT JSON_SAMPLE_STRING_A_IN
|
||||||
|
|
||||||
|
#define JSON_SAMPLE_STRING_B_IN "\"\\u21c8\""
|
||||||
|
#define JSON_SAMPLE_STRING_B_EXPECTED_OUT JSON_SAMPLE_STRING_B_IN
|
||||||
|
|
||||||
|
/*! This sample is an array containing other elements. */
|
||||||
|
|
||||||
|
#define JSON_SAMPLE_ARRAY_A_IN "[\"1234\", 4567 , \n" \
|
||||||
|
" [ \"A\" ,\"b\", \"C\\u00e9zanne\"] ]"
|
||||||
|
#define JSON_SAMPLE_ARRAY_A_EXPECTED_OUT "[\"1234\",4567," \
|
||||||
|
"[\"A\",\"b\",\"C\\u00e9zanne\"]]"
|
||||||
|
|
||||||
|
#define JSON_SAMPLE_ARRAY_B_IN "[\"Whirinaki\", \"Wellington\" , \n" \
|
||||||
|
" { \"key\" : [ \"value\" ] }\n" \
|
||||||
|
"]"
|
||||||
|
#define JSON_SAMPLE_ARRAY_B_EXPECTED_OUT "[\"Whirinaki\",\"Wellington\"," \
|
||||||
|
"{\"key\":[\"value\"]}]"
|
||||||
|
|
||||||
|
/*! This sample is an object type containing other elements. */
|
||||||
|
|
||||||
|
#define JSON_SAMPLE_OBJECT_A_IN "{\"weather\":\"raining\", \"humidity\" : " \
|
||||||
|
"\"too-high\", \"daysOfWeek\": [\"MON\", \"TUE\", \"WED\", \"THR\"," \
|
||||||
|
"\"FRI\"]}"
|
||||||
|
#define JSON_SAMPLE_OBJECT_A_EXPECTED_OUT "{\"weather\":\"raining\"," \
|
||||||
|
"\"humidity\":\"too-high\",\"daysOfWeek\":[\"MON\",\"TUE\",\"WED\",\"THR\"," \
|
||||||
|
"\"FRI\"]}"
|
||||||
|
|
||||||
|
/*! This sample contains some other types of JSON nodes such as true, false
|
||||||
|
and null.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define JSON_SAMPLE_OBJECT_B_IN "{\"testTrue\":true, \"testFalse\" : " \
|
||||||
|
"false, \"testNull\": null }"
|
||||||
|
|
||||||
|
/*! A very simple object that can be used to test basic functionality. */
|
||||||
|
|
||||||
|
#define JSON_SAMPLE_OBJECT_C_IN "{\"key\":\"value\"}"
|
||||||
|
|
||||||
|
/*! This sample has a key-value separator as the first character after
|
||||||
|
opening the object.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define JSON_SAMPLE_BROKEN_OBJECT_PREMATURE_SEPARATOR "{,\"key\":\"value\"}"
|
||||||
|
|
||||||
|
#define JSON_SAMPLE_BROKEN_COMPLETELY_UNKNOWN "zzz"
|
||||||
|
|
||||||
|
#define JSON_SAMPLE_BROKEN_UNTERMINATED_OBJECT "[ 123, {\"key\":\"value\""
|
||||||
|
|
||||||
|
#define JSON_SAMPLE_BROKEN_UNTERMINATED_ARRAY "{\"key\":\"value\",\n" \
|
||||||
|
"\"key2\":\n" \
|
||||||
|
"["
|
||||||
|
|
||||||
|
#define JSON_SAMPLE_BROKEN_UNTERMINATED_STRING "\"without end"
|
||||||
|
|
||||||
|
#define JSON_SAMPLE_BROKEN_BAD_STRING_ESCAPE "\"a dastardly \\v escape sequence\""
|
||||||
|
|
||||||
|
#define JSON_SAMPLE_BROKEN_NUMBER "-123e123E456e"
|
||||||
|
|
||||||
|
/*! This is a larger example and comes from the request-response
|
||||||
|
cycle of a JSON-RPC request from the HaikuDepot desktop application
|
||||||
|
into the HaikuDepotServer system.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define JSON_SAMPLE_HDS_FETCH_BATCH_PKGS { \
|
||||||
|
0x7b, 0x22, 0x6a, 0x73, 0x6f, 0x6e, 0x72, 0x70, 0x63, 0x22, 0x3a, 0x22, \
|
||||||
|
0x32, 0x2e, 0x30, 0x22, 0x2c, 0x22, 0x69, 0x64, 0x22, 0x3a, 0x36, 0x2c, \
|
||||||
|
0x22, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x22, 0x3a, 0x7b, 0x22, 0x70, \
|
||||||
|
0x6b, 0x67, 0x73, 0x22, 0x3a, 0x5b, 0x7b, 0x22, 0x6e, 0x61, 0x6d, 0x65, \
|
||||||
|
0x22, 0x3a, 0x22, 0x62, 0x65, 0x73, 0x68, 0x61, 0x72, 0x65, 0x5f, 0x73, \
|
||||||
|
0x65, 0x72, 0x76, 0x65, 0x72, 0x22, 0x2c, 0x22, 0x6d, 0x6f, 0x64, 0x69, \
|
||||||
|
0x66, 0x79, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x22, \
|
||||||
|
0x3a, 0x31, 0x34, 0x37, 0x36, 0x31, 0x39, 0x39, 0x33, 0x36, 0x34, 0x30, \
|
||||||
|
0x37, 0x30, 0x2c, 0x22, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, \
|
||||||
|
0x22, 0x3a, 0x5b, 0x7b, 0x22, 0x6d, 0x61, 0x6a, 0x6f, 0x72, 0x22, 0x3a, \
|
||||||
|
0x22, 0x32, 0x22, 0x2c, 0x22, 0x6d, 0x69, 0x6e, 0x6f, 0x72, 0x22, 0x3a, \
|
||||||
|
0x22, 0x34, 0x32, 0x22, 0x2c, 0x22, 0x6d, 0x69, 0x63, 0x72, 0x6f, 0x22, \
|
||||||
|
0x3a, 0x6e, 0x75, 0x6c, 0x6c, 0x2c, 0x22, 0x70, 0x72, 0x65, 0x52, 0x65, \
|
||||||
|
0x6c, 0x65, 0x61, 0x73, 0x65, 0x22, 0x3a, 0x6e, 0x75, 0x6c, 0x6c, 0x2c, \
|
||||||
|
0x22, 0x72, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x3a, 0x33, \
|
||||||
|
0x2c, 0x22, 0x61, 0x72, 0x63, 0x68, 0x69, 0x74, 0x65, 0x63, 0x74, 0x75, \
|
||||||
|
0x72, 0x65, 0x43, 0x6f, 0x64, 0x65, 0x22, 0x3a, 0x22, 0x78, 0x38, 0x36, \
|
||||||
|
0x5f, 0x67, 0x63, 0x63, 0x32, 0x22, 0x2c, 0x22, 0x74, 0x69, 0x74, 0x6c, \
|
||||||
|
0x65, 0x22, 0x3a, 0x6e, 0x75, 0x6c, 0x6c, 0x2c, 0x22, 0x72, 0x65, 0x70, \
|
||||||
|
0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x53, 0x6f, 0x75, 0x72, 0x63, \
|
||||||
|
0x65, 0x43, 0x6f, 0x64, 0x65, 0x22, 0x3a, 0x22, 0x66, 0x61, 0x74, 0x65, \
|
||||||
|
0x6c, 0x6b, 0x5f, 0x78, 0x38, 0x36, 0x5f, 0x67, 0x63, 0x63, 0x32, 0x22, \
|
||||||
|
0x2c, 0x22, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, \
|
||||||
|
0x43, 0x6f, 0x64, 0x65, 0x22, 0x3a, 0x22, 0x66, 0x61, 0x74, 0x65, 0x6c, \
|
||||||
|
0x6b, 0x22, 0x2c, 0x22, 0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x22, \
|
||||||
|
0x3a, 0x22, 0x42, 0x65, 0x53, 0x68, 0x61, 0x72, 0x65, 0x20, 0x53, 0x65, \
|
||||||
|
0x72, 0x76, 0x65, 0x72, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x41, 0x74, 0x72, \
|
||||||
|
0x75, 0x73, 0x20, 0x43, 0x68, 0x61, 0x74, 0x62, 0x6f, 0x74, 0x22, 0x2c, \
|
||||||
|
0x22, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, \
|
||||||
|
0x22, 0x3a, 0x22, 0x54, 0x68, 0x69, 0x73, 0x20, 0x70, 0x61, 0x63, 0x6b, \
|
||||||
|
0x61, 0x67, 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x73, \
|
||||||
|
0x20, 0x74, 0x68, 0x65, 0x20, 0x5c, 0x22, 0x6d, 0x75, 0x73, 0x63, 0x6c, \
|
||||||
|
0x65, 0x64, 0x5c, 0x22, 0x20, 0x28, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x20, \
|
||||||
|
0x55, 0x73, 0x65, 0x72, 0x20, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, \
|
||||||
|
0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x20, 0x4c, 0x69, 0x6e, 0x6b, 0x69, \
|
||||||
|
0x6e, 0x67, 0x20, 0x45, 0x6e, 0x76, 0x69, 0x72, 0x6f, 0x6e, 0x6d, 0x65, \
|
||||||
|
0x6e, 0x74, 0x20, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x29, 0x20, 0x73, \
|
||||||
|
0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x28, 0x76, 0x65, 0x72, 0x73, 0x69, \
|
||||||
|
0x6f, 0x6e, 0x20, 0x33, 0x2e, 0x32, 0x30, 0x20, 0x70, 0x6f, 0x72, 0x74, \
|
||||||
|
0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x48, 0x61, 0x69, 0x6b, 0x75, 0x20, \
|
||||||
|
0x47, 0x43, 0x43, 0x32, 0x20, 0x62, 0x79, 0x20, 0x41, 0x47, 0x4d, 0x53, \
|
||||||
|
0x20, 0x69, 0x6e, 0x20, 0x32, 0x30, 0x31, 0x36, 0x29, 0x20, 0x61, 0x6e, \
|
||||||
|
0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x41, 0x74, 0x72, 0x75, 0x73, 0x20, \
|
||||||
|
0x63, 0x68, 0x61, 0x74, 0x20, 0x72, 0x6f, 0x62, 0x6f, 0x74, 0x20, 0x32, \
|
||||||
|
0x2e, 0x34, 0x32, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x6d, 0x6f, \
|
||||||
|
0x6e, 0x69, 0x74, 0x6f, 0x72, 0x73, 0x20, 0x74, 0x65, 0x78, 0x74, 0x20, \
|
||||||
|
0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, \
|
||||||
|
0x73, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x65, 0x72, \
|
||||||
|
0x76, 0x65, 0x72, 0x2e, 0x20, 0x20, 0x54, 0x68, 0x61, 0x74, 0x20, 0x70, \
|
||||||
|
0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x73, 0x20, 0x65, 0x76, 0x65, 0x72, \
|
||||||
|
0x79, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x6e, \
|
||||||
|
0x65, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x73, 0x65, 0x74, 0x20, 0x75, \
|
||||||
|
0x70, 0x20, 0x79, 0x6f, 0x75, 0x72, 0x20, 0x6f, 0x77, 0x6e, 0x20, 0x42, \
|
||||||
|
0x65, 0x53, 0x68, 0x61, 0x72, 0x65, 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, \
|
||||||
|
0x72, 0x2e, 0x5c, 0x6e, 0x5c, 0x6e, 0x41, 0x66, 0x74, 0x65, 0x72, 0x20, \
|
||||||
|
0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x2c, 0x20, \
|
||||||
|
0x79, 0x6f, 0x75, 0x20, 0x6e, 0x65, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, \
|
||||||
|
0x64, 0x6f, 0x20, 0x61, 0x20, 0x66, 0x65, 0x77, 0x20, 0x74, 0x68, 0x69, \
|
||||||
|
0x6e, 0x67, 0x73, 0x3a, 0x5c, 0x6e, 0x5c, 0x6e, 0x31, 0x29, 0x20, 0x53, \
|
||||||
|
0x65, 0x65, 0x20, 0x69, 0x66, 0x20, 0x69, 0x74, 0x20, 0x69, 0x6e, 0x73, \
|
||||||
|
0x74, 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x2e, 0x20, 0x20, 0x49, 0x74, 0x20, \
|
||||||
|
0x73, 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, \
|
||||||
|
0x6e, 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x72, 0x69, 0x67, 0x68, 0x74, 0x20, \
|
||||||
|
0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, \
|
||||||
|
0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, \
|
||||||
|
0x61, 0x75, 0x74, 0x6f, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x6c, \
|
||||||
|
0x79, 0x20, 0x73, 0x74, 0x61, 0x72, 0x74, 0x20, 0x75, 0x70, 0x20, 0x61, \
|
||||||
|
0x66, 0x74, 0x65, 0x72, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x72, 0x65, 0x62, \
|
||||||
|
0x6f, 0x6f, 0x74, 0x2e, 0x20, 0x20, 0x49, 0x6e, 0x20, 0x50, 0x72, 0x6f, \
|
||||||
|
0x63, 0x65, 0x73, 0x73, 0x20, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, \
|
||||||
|
0x6c, 0x65, 0x72, 0x20, 0x75, 0x6e, 0x64, 0x65, 0x72, 0x20, 0x74, 0x68, \
|
||||||
|
0x65, 0x20, 0x5c, 0x22, 0x54, 0x68, 0x72, 0x65, 0x61, 0x64, 0x73, 0x20, \
|
||||||
|
0x61, 0x6e, 0x64, 0x20, 0x43, 0x50, 0x55, 0x20, 0x75, 0x73, 0x61, 0x67, \
|
||||||
|
0x65, 0x5c, 0x22, 0x20, 0x6d, 0x65, 0x6e, 0x75, 0x20, 0x79, 0x6f, 0x75, \
|
||||||
|
0x20, 0x73, 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x73, 0x65, 0x65, 0x20, \
|
||||||
|
0x65, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x20, 0x66, 0x6f, 0x72, 0x20, \
|
||||||
|
0x5c, 0x22, 0x2f, 0x62, 0x69, 0x6e, 0x2f, 0x6d, 0x75, 0x73, 0x63, 0x6c, \
|
||||||
|
0x65, 0x64, 0x5c, 0x22, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x5c, 0x22, 0x2f, \
|
||||||
|
0x62, 0x69, 0x6e, 0x41, 0x74, 0x72, 0x75, 0x73, 0x5c, 0x22, 0x2e, 0x5c, \
|
||||||
|
0x6e, 0x5c, 0x6e, 0x32, 0x29, 0x20, 0x54, 0x65, 0x73, 0x74, 0x20, 0x69, \
|
||||||
|
0x74, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x42, 0x65, 0x53, 0x68, 0x61, \
|
||||||
|
0x72, 0x65, 0x2e, 0x20, 0x20, 0x55, 0x73, 0x65, 0x20, 0x79, 0x6f, 0x75, \
|
||||||
|
0x72, 0x20, 0x63, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x72, 0x27, 0x73, \
|
||||||
|
0x20, 0x49, 0x50, 0x20, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x20, \
|
||||||
|
0x6f, 0x72, 0x20, 0x6c, 0x65, 0x73, 0x73, 0x20, 0x72, 0x65, 0x6c, 0x69, \
|
||||||
|
0x61, 0x62, 0x6c, 0x79, 0x20, 0x5c, 0x22, 0x6c, 0x6f, 0x63, 0x61, 0x6c, \
|
||||||
|
0x68, 0x6f, 0x73, 0x74, 0x5c, 0x22, 0x20, 0x61, 0x73, 0x20, 0x74, 0x68, \
|
||||||
|
0x65, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, \
|
||||||
|
0x65, 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x74, 0x6f, 0x20, \
|
||||||
|
0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x20, 0x74, 0x6f, 0x2e, 0x5c, \
|
||||||
|
0x6e, 0x5c, 0x6e, 0x33, 0x29, 0x20, 0x46, 0x6f, 0x72, 0x77, 0x61, 0x72, \
|
||||||
|
0x64, 0x20, 0x70, 0x6f, 0x72, 0x74, 0x20, 0x32, 0x39, 0x36, 0x30, 0x20, \
|
||||||
|
0x66, 0x72, 0x6f, 0x6d, 0x20, 0x79, 0x6f, 0x75, 0x72, 0x20, 0x72, 0x6f, \
|
||||||
|
0x75, 0x74, 0x65, 0x72, 0x20, 0x74, 0x6f, 0x20, 0x79, 0x6f, 0x75, 0x72, \
|
||||||
|
0x20, 0x63, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x72, 0x20, 0x28, 0x6f, \
|
||||||
|
0x74, 0x68, 0x65, 0x72, 0x77, 0x69, 0x73, 0x65, 0x20, 0x6e, 0x6f, 0x62, \
|
||||||
|
0x6f, 0x64, 0x79, 0x20, 0x6f, 0x75, 0x74, 0x73, 0x69, 0x64, 0x65, 0x20, \
|
||||||
|
0x63, 0x61, 0x6e, 0x20, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x20, 0x79, \
|
||||||
|
0x6f, 0x75, 0x72, 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x29, 0x2e, \
|
||||||
|
0x5c, 0x6e, 0x5c, 0x6e, 0x34, 0x29, 0x20, 0x55, 0x70, 0x6f, 0x6e, 0x20, \
|
||||||
|
0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, \
|
||||||
|
0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x6f, 0x6f, 0x74, 0x20, 0x73, 0x63, \
|
||||||
|
0x72, 0x69, 0x70, 0x74, 0x20, 0x69, 0x73, 0x20, 0x63, 0x6f, 0x70, 0x69, \
|
||||||
|
0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x2f, 0x62, 0x6f, 0x6f, 0x74, 0x2f, \
|
||||||
|
0x68, 0x6f, 0x6d, 0x65, 0x2f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2f, \
|
||||||
|
0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2f, 0x62, 0x6f, 0x6f, \
|
||||||
|
0x74, 0x2f, 0x6c, 0x61, 0x75, 0x6e, 0x63, 0x68, 0x2f, 0x62, 0x65, 0x73, \
|
||||||
|
0x68, 0x61, 0x72, 0x65, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, \
|
||||||
|
0x73, 0x68, 0x20, 0x77, 0x68, 0x65, 0x72, 0x65, 0x20, 0x79, 0x6f, 0x75, \
|
||||||
|
0x20, 0x63, 0x61, 0x6e, 0x20, 0x65, 0x64, 0x69, 0x74, 0x20, 0x74, 0x68, \
|
||||||
|
0x65, 0x20, 0x73, 0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x20, 0x6f, 0x70, \
|
||||||
|
0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2c, 0x20, 0x69, 0x6e, 0x63, 0x6c, 0x75, \
|
||||||
|
0x64, 0x69, 0x6e, 0x67, 0x20, 0x79, 0x6f, 0x75, 0x72, 0x20, 0x27, 0x62, \
|
||||||
|
0x6f, 0x74, 0x73, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x61, 0x6e, 0x64, \
|
||||||
|
0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, \
|
||||||
|
0x6c, 0x20, 0x49, 0x50, 0x20, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, \
|
||||||
|
0x20, 0x66, 0x6f, 0x72, 0x20, 0x4d, 0x75, 0x73, 0x63, 0x6c, 0x65, 0x20, \
|
||||||
|
0x74, 0x6f, 0x20, 0x75, 0x73, 0x65, 0x20, 0x28, 0x6f, 0x74, 0x68, 0x65, \
|
||||||
|
0x72, 0x77, 0x69, 0x73, 0x65, 0x20, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, \
|
||||||
|
0x61, 0x6c, 0x20, 0x75, 0x73, 0x65, 0x72, 0x73, 0x20, 0x77, 0x69, 0x6c, \
|
||||||
|
0x6c, 0x20, 0x68, 0x61, 0x76, 0x65, 0x20, 0x74, 0x72, 0x6f, 0x75, 0x62, \
|
||||||
|
0x6c, 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6e, \
|
||||||
|
0x67, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x64, 0x6f, 0x69, 0x6e, 0x67, 0x20, \
|
||||||
|
0x66, 0x69, 0x6c, 0x65, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x65, \
|
||||||
|
0x72, 0x73, 0x29, 0x2e, 0x20, 0x20, 0x54, 0x68, 0x65, 0x20, 0x6c, 0x6f, \
|
||||||
|
0x67, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x20, 0x61, 0x72, 0x65, 0x20, \
|
||||||
|
0x61, 0x6c, 0x73, 0x6f, 0x20, 0x73, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, \
|
||||||
|
0x65, 0x64, 0x20, 0x74, 0x68, 0x65, 0x72, 0x65, 0x2c, 0x20, 0x72, 0x65, \
|
||||||
|
0x6d, 0x6f, 0x76, 0x65, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x20, 0x69, 0x66, \
|
||||||
|
0x20, 0x79, 0x6f, 0x75, 0x27, 0x72, 0x65, 0x20, 0x75, 0x73, 0x69, 0x6e, \
|
||||||
|
0x67, 0x20, 0x61, 0x20, 0x72, 0x65, 0x61, 0x64, 0x2d, 0x6f, 0x6e, 0x6c, \
|
||||||
|
0x79, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x20, 0x73, 0x79, 0x73, 0x74, 0x65, \
|
||||||
|
0x6d, 0x2e, 0x5c, 0x6e, 0x5c, 0x6e, 0x35, 0x29, 0x20, 0x45, 0x64, 0x69, \
|
||||||
|
0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x42, 0x6f, 0x74, 0x44, 0x61, 0x74, \
|
||||||
|
0x61, 0x20, 0x74, 0x65, 0x78, 0x74, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x73, \
|
||||||
|
0x20, 0x69, 0x6e, 0x20, 0x2f, 0x62, 0x6f, 0x6f, 0x74, 0x2f, 0x68, 0x6f, \
|
||||||
|
0x6d, 0x65, 0x2f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2f, 0x73, 0x65, \
|
||||||
|
0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2f, 0x42, 0x6f, 0x74, 0x44, 0x61, \
|
||||||
|
0x74, 0x61, 0x20, 0x74, 0x6f, 0x20, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, \
|
||||||
|
0x69, 0x7a, 0x65, 0x20, 0x79, 0x6f, 0x75, 0x72, 0x20, 0x63, 0x68, 0x61, \
|
||||||
|
0x74, 0x62, 0x6f, 0x74, 0x27, 0x73, 0x20, 0x74, 0x65, 0x78, 0x74, 0x2e, \
|
||||||
|
0x5c, 0x6e, 0x5c, 0x6e, 0x48, 0x61, 0x70, 0x70, 0x79, 0x20, 0x42, 0x65, \
|
||||||
|
0x73, 0x68, 0x61, 0x72, 0x69, 0x6e, 0x67, 0x21, 0x22, 0x2c, 0x22, 0x70, \
|
||||||
|
0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, \
|
||||||
|
0x22, 0x3a, 0x34, 0x30, 0x33, 0x36, 0x33, 0x37, 0x33, 0x7d, 0x5d, 0x2c, \
|
||||||
|
0x22, 0x70, 0x6b, 0x67, 0x43, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, \
|
||||||
|
0x43, 0x6f, 0x64, 0x65, 0x73, 0x22, 0x3a, 0x5b, 0x22, 0x69, 0x6e, 0x74, \
|
||||||
|
0x65, 0x72, 0x6e, 0x65, 0x74, 0x61, 0x6e, 0x64, 0x6e, 0x65, 0x74, 0x77, \
|
||||||
|
0x6f, 0x72, 0x6b, 0x22, 0x5d, 0x2c, 0x22, 0x70, 0x6b, 0x67, 0x53, 0x63, \
|
||||||
|
0x72, 0x65, 0x65, 0x6e, 0x73, 0x68, 0x6f, 0x74, 0x73, 0x22, 0x3a, 0x5b, \
|
||||||
|
0x5d, 0x2c, 0x22, 0x70, 0x6b, 0x67, 0x49, 0x63, 0x6f, 0x6e, 0x73, 0x22, \
|
||||||
|
0x3a, 0x6e, 0x75, 0x6c, 0x6c, 0x2c, 0x22, 0x64, 0x65, 0x72, 0x69, 0x76, \
|
||||||
|
0x65, 0x64, 0x52, 0x61, 0x74, 0x69, 0x6e, 0x67, 0x22, 0x3a, 0x6e, 0x75, \
|
||||||
|
0x6c, 0x6c, 0x2c, 0x22, 0x70, 0x72, 0x6f, 0x6d, 0x69, 0x6e, 0x65, 0x6e, \
|
||||||
|
0x63, 0x65, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x22, 0x3a, \
|
||||||
|
0x31, 0x30, 0x30, 0x30, 0x2c, 0x22, 0x70, 0x6b, 0x67, 0x43, 0x68, 0x61, \
|
||||||
|
0x6e, 0x67, 0x65, 0x6c, 0x6f, 0x67, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, \
|
||||||
|
0x74, 0x22, 0x3a, 0x6e, 0x75, 0x6c, 0x6c, 0x7d, 0x2c, 0x7b, 0x22, 0x6e, \
|
||||||
|
0x61, 0x6d, 0x65, 0x22, 0x3a, 0x22, 0x62, 0x6f, 0x6f, 0x6b, 0x6d, 0x61, \
|
||||||
|
0x72, 0x6b, 0x65, 0x72, 0x22, 0x2c, 0x22, 0x6d, 0x6f, 0x64, 0x69, 0x66, \
|
||||||
|
0x79, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x22, 0x3a, \
|
||||||
|
0x31, 0x34, 0x38, 0x38, 0x37, 0x38, 0x35, 0x33, 0x33, 0x31, 0x36, 0x33, \
|
||||||
|
0x31, 0x2c, 0x22, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x22, \
|
||||||
|
0x3a, 0x5b, 0x7b, 0x22, 0x6d, 0x61, 0x6a, 0x6f, 0x72, 0x22, 0x3a, 0x22, \
|
||||||
|
0x31, 0x22, 0x2c, 0x22, 0x6d, 0x69, 0x6e, 0x6f, 0x72, 0x22, 0x3a, 0x22, \
|
||||||
|
0x33, 0x22, 0x2c, 0x22, 0x6d, 0x69, 0x63, 0x72, 0x6f, 0x22, 0x3a, 0x6e, \
|
||||||
|
0x75, 0x6c, 0x6c, 0x2c, 0x22, 0x70, 0x72, 0x65, 0x52, 0x65, 0x6c, 0x65, \
|
||||||
|
0x61, 0x73, 0x65, 0x22, 0x3a, 0x6e, 0x75, 0x6c, 0x6c, 0x2c, 0x22, 0x72, \
|
||||||
|
0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x3a, 0x32, 0x2c, 0x22, \
|
||||||
|
0x61, 0x72, 0x63, 0x68, 0x69, 0x74, 0x65, 0x63, 0x74, 0x75, 0x72, 0x65, \
|
||||||
|
0x43, 0x6f, 0x64, 0x65, 0x22, 0x3a, 0x22, 0x78, 0x38, 0x36, 0x5f, 0x67, \
|
||||||
|
0x63, 0x63, 0x32, 0x22, 0x2c, 0x22, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x22, \
|
||||||
|
0x3a, 0x22, 0x42, 0x6f, 0x6f, 0x6b, 0x6d, 0x61, 0x72, 0x6b, 0x65, 0x72, \
|
||||||
|
0x22, 0x2c, 0x22, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, \
|
||||||
|
0x79, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x6f, 0x64, 0x65, 0x22, \
|
||||||
|
0x3a, 0x22, 0x66, 0x61, 0x74, 0x65, 0x6c, 0x6b, 0x5f, 0x78, 0x38, 0x36, \
|
||||||
|
0x5f, 0x67, 0x63, 0x63, 0x32, 0x22, 0x2c, 0x22, 0x72, 0x65, 0x70, 0x6f, \
|
||||||
|
0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x43, 0x6f, 0x64, 0x65, 0x22, 0x3a, \
|
||||||
|
0x22, 0x66, 0x61, 0x74, 0x65, 0x6c, 0x6b, 0x22, 0x2c, 0x22, 0x73, 0x75, \
|
||||||
|
0x6d, 0x6d, 0x61, 0x72, 0x79, 0x22, 0x3a, 0x22, 0x42, 0x6f, 0x6f, 0x6b, \
|
||||||
|
0x6d, 0x61, 0x72, 0x6b, 0x20, 0x6d, 0x61, 0x6b, 0x65, 0x72, 0x22, 0x2c, \
|
||||||
|
0x22, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, \
|
||||||
|
0x22, 0x3a, 0x22, 0x42, 0x6f, 0x6f, 0x6b, 0x6d, 0x61, 0x72, 0x6b, 0x65, \
|
||||||
|
0x72, 0x20, 0x6d, 0x61, 0x6b, 0x65, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, \
|
||||||
|
0x73, 0x74, 0x6f, 0x72, 0x65, 0x73, 0x20, 0x62, 0x6f, 0x6f, 0x6b, 0x6d, \
|
||||||
|
0x61, 0x72, 0x6b, 0x73, 0x20, 0x28, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, \
|
||||||
|
0x20, 0x77, 0x69, 0x64, 0x65, 0x20, 0x6c, 0x69, 0x6e, 0x6b, 0x73, 0x20, \
|
||||||
|
0x74, 0x6f, 0x20, 0x77, 0x65, 0x62, 0x20, 0x73, 0x69, 0x74, 0x65, 0x73, \
|
||||||
|
0x29, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x48, 0x61, \
|
||||||
|
0x69, 0x6b, 0x75, 0x20, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6e, \
|
||||||
|
0x67, 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x2e, 0x20, 0x49, 0x74, \
|
||||||
|
0x61, 0x6c, 0x73, 0x6f, 0x20, 0x61, 0x64, 0x64, 0x73, 0x20, 0x74, 0x68, \
|
||||||
|
0x65, 0x20, 0x62, 0x6f, 0x6f, 0x6b, 0x6d, 0x61, 0x72, 0x6b, 0x73, 0x20, \
|
||||||
|
0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x44, 0x65, 0x73, 0x6b, 0x62, \
|
||||||
|
0x61, 0x72, 0x20, 0x6d, 0x65, 0x6e, 0x75, 0x2e, 0x22, 0x2c, 0x22, 0x70, \
|
||||||
|
0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, \
|
||||||
|
0x22, 0x3a, 0x36, 0x34, 0x34, 0x31, 0x35, 0x7d, 0x5d, 0x2c, 0x22, 0x70, \
|
||||||
|
0x6b, 0x67, 0x43, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, 0x43, 0x6f, \
|
||||||
|
0x64, 0x65, 0x73, 0x22, 0x3a, 0x5b, 0x22, 0x70, 0x72, 0x6f, 0x64, 0x75, \
|
||||||
|
0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x22, 0x2c, 0x22, 0x73, 0x79, \
|
||||||
|
0x73, 0x74, 0x65, 0x6d, 0x61, 0x6e, 0x64, 0x75, 0x74, 0x69, 0x6c, 0x69, \
|
||||||
|
0x74, 0x69, 0x65, 0x73, 0x22, 0x2c, 0x22, 0x69, 0x6e, 0x74, 0x65, 0x72, \
|
||||||
|
0x6e, 0x65, 0x74, 0x61, 0x6e, 0x64, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, \
|
||||||
|
0x6b, 0x22, 0x5d, 0x2c, 0x22, 0x70, 0x6b, 0x67, 0x53, 0x63, 0x72, 0x65, \
|
||||||
|
0x65, 0x6e, 0x73, 0x68, 0x6f, 0x74, 0x73, 0x22, 0x3a, 0x5b, 0x7b, 0x22, \
|
||||||
|
0x63, 0x6f, 0x64, 0x65, 0x22, 0x3a, 0x22, 0x37, 0x36, 0x35, 0x30, 0x39, \
|
||||||
|
0x64, 0x64, 0x36, 0x2d, 0x32, 0x35, 0x39, 0x36, 0x2d, 0x34, 0x32, 0x34, \
|
||||||
|
0x37, 0x2d, 0x61, 0x38, 0x65, 0x34, 0x2d, 0x34, 0x37, 0x36, 0x39, 0x65, \
|
||||||
|
0x34, 0x35, 0x61, 0x36, 0x66, 0x37, 0x35, 0x22, 0x2c, 0x22, 0x6c, 0x65, \
|
||||||
|
0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, 0x32, 0x32, 0x31, 0x32, 0x35, 0x2c, \
|
||||||
|
0x22, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x22, 0x3a, 0x34, 0x33, 0x32, \
|
||||||
|
0x2c, 0x22, 0x77, 0x69, 0x64, 0x74, 0x68, 0x22, 0x3a, 0x35, 0x31, 0x31, \
|
||||||
|
0x7d, 0x2c, 0x7b, 0x22, 0x63, 0x6f, 0x64, 0x65, 0x22, 0x3a, 0x22, 0x33, \
|
||||||
|
0x32, 0x32, 0x61, 0x62, 0x39, 0x66, 0x33, 0x2d, 0x65, 0x35, 0x36, 0x66, \
|
||||||
|
0x2d, 0x34, 0x64, 0x31, 0x61, 0x2d, 0x39, 0x37, 0x34, 0x33, 0x2d, 0x35, \
|
||||||
|
0x63, 0x65, 0x66, 0x65, 0x39, 0x39, 0x32, 0x38, 0x32, 0x37, 0x66, 0x22, \
|
||||||
|
0x2c, 0x22, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, 0x35, 0x34, \
|
||||||
|
0x31, 0x30, 0x34, 0x2c, 0x22, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x22, \
|
||||||
|
0x3a, 0x33, 0x30, 0x39, 0x2c, 0x22, 0x77, 0x69, 0x64, 0x74, 0x68, 0x22, \
|
||||||
|
0x3a, 0x33, 0x32, 0x36, 0x7d, 0x5d, 0x2c, 0x22, 0x70, 0x6b, 0x67, 0x49, \
|
||||||
|
0x63, 0x6f, 0x6e, 0x73, 0x22, 0x3a, 0x6e, 0x75, 0x6c, 0x6c, 0x2c, 0x22, \
|
||||||
|
0x64, 0x65, 0x72, 0x69, 0x76, 0x65, 0x64, 0x52, 0x61, 0x74, 0x69, 0x6e, \
|
||||||
|
0x67, 0x22, 0x3a, 0x32, 0x2e, 0x30, 0x2c, 0x22, 0x70, 0x72, 0x6f, 0x6d, \
|
||||||
|
0x69, 0x6e, 0x65, 0x6e, 0x63, 0x65, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x69, \
|
||||||
|
0x6e, 0x67, 0x22, 0x3a, 0x31, 0x30, 0x30, 0x30, 0x2c, 0x22, 0x70, 0x6b, \
|
||||||
|
0x67, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x6c, 0x6f, 0x67, 0x43, 0x6f, \
|
||||||
|
0x6e, 0x74, 0x65, 0x6e, 0x74, 0x22, 0x3a, 0x6e, 0x75, 0x6c, 0x6c, 0x7d, \
|
||||||
|
0x2c, 0x7b, 0x22, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x3a, 0x22, 0x66, 0x61, \
|
||||||
|
0x6c, 0x6c, 0x6c, 0x65, 0x61, 0x76, 0x65, 0x73, 0x22, 0x2c, 0x22, 0x6d, \
|
||||||
|
0x6f, 0x64, 0x69, 0x66, 0x79, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, \
|
||||||
|
0x6d, 0x70, 0x22, 0x3a, 0x31, 0x34, 0x36, 0x33, 0x36, 0x38, 0x34, 0x36, \
|
||||||
|
0x35, 0x38, 0x33, 0x39, 0x38, 0x2c, 0x22, 0x76, 0x65, 0x72, 0x73, 0x69, \
|
||||||
|
0x6f, 0x6e, 0x73, 0x22, 0x3a, 0x5b, 0x7b, 0x22, 0x6d, 0x61, 0x6a, 0x6f, \
|
||||||
|
0x72, 0x22, 0x3a, 0x22, 0x31, 0x22, 0x2c, 0x22, 0x6d, 0x69, 0x6e, 0x6f, \
|
||||||
|
0x72, 0x22, 0x3a, 0x22, 0x32, 0x22, 0x2c, 0x22, 0x6d, 0x69, 0x63, 0x72, \
|
||||||
|
0x6f, 0x22, 0x3a, 0x6e, 0x75, 0x6c, 0x6c, 0x2c, 0x22, 0x70, 0x72, 0x65, \
|
||||||
|
0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x22, 0x3a, 0x6e, 0x75, 0x6c, \
|
||||||
|
0x6c, 0x2c, 0x22, 0x72, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x22, \
|
||||||
|
0x3a, 0x31, 0x2c, 0x22, 0x61, 0x72, 0x63, 0x68, 0x69, 0x74, 0x65, 0x63, \
|
||||||
|
0x74, 0x75, 0x72, 0x65, 0x43, 0x6f, 0x64, 0x65, 0x22, 0x3a, 0x22, 0x78, \
|
||||||
|
0x38, 0x36, 0x5f, 0x67, 0x63, 0x63, 0x32, 0x22, 0x2c, 0x22, 0x74, 0x69, \
|
||||||
|
0x74, 0x6c, 0x65, 0x22, 0x3a, 0x22, 0x46, 0x61, 0x6c, 0x6c, 0x20, 0x4c, \
|
||||||
|
0x65, 0x61, 0x76, 0x65, 0x73, 0x22, 0x2c, 0x22, 0x72, 0x65, 0x70, 0x6f, \
|
||||||
|
0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, \
|
||||||
|
0x43, 0x6f, 0x64, 0x65, 0x22, 0x3a, 0x22, 0x66, 0x61, 0x74, 0x65, 0x6c, \
|
||||||
|
0x6b, 0x5f, 0x78, 0x38, 0x36, 0x5f, 0x67, 0x63, 0x63, 0x32, 0x22, 0x2c, \
|
||||||
|
0x22, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x43, \
|
||||||
|
0x6f, 0x64, 0x65, 0x22, 0x3a, 0x22, 0x66, 0x61, 0x74, 0x65, 0x6c, 0x6b, \
|
||||||
|
0x22, 0x2c, 0x22, 0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x22, 0x3a, \
|
||||||
|
0x22, 0x46, 0x61, 0x6c, 0x6c, 0x20, 0x4c, 0x65, 0x61, 0x76, 0x65, 0x73, \
|
||||||
|
0x20, 0x73, 0x63, 0x72, 0x65, 0x65, 0x6e, 0x73, 0x61, 0x76, 0x65, 0x72, \
|
||||||
|
0x22, 0x2c, 0x22, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, \
|
||||||
|
0x6f, 0x6e, 0x22, 0x3a, 0x22, 0x41, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x6c, \
|
||||||
|
0x79, 0x20, 0x73, 0x63, 0x72, 0x65, 0x65, 0x6e, 0x73, 0x61, 0x76, 0x65, \
|
||||||
|
0x72, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x66, 0x61, 0x6c, 0x6c, 0x69, \
|
||||||
|
0x6e, 0x67, 0x20, 0x48, 0x61, 0x69, 0x6b, 0x75, 0x20, 0x6c, 0x65, 0x61, \
|
||||||
|
0x76, 0x65, 0x73, 0x2e, 0x22, 0x2c, 0x22, 0x70, 0x61, 0x79, 0x6c, 0x6f, \
|
||||||
|
0x61, 0x64, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, 0x31, 0x32, \
|
||||||
|
0x34, 0x31, 0x32, 0x7d, 0x5d, 0x2c, 0x22, 0x70, 0x6b, 0x67, 0x43, 0x61, \
|
||||||
|
0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, 0x43, 0x6f, 0x64, 0x65, 0x73, 0x22, \
|
||||||
|
0x3a, 0x5b, 0x22, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x61, 0x6e, 0x64, \
|
||||||
|
0x75, 0x74, 0x69, 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x22, 0x5d, 0x2c, \
|
||||||
|
0x22, 0x70, 0x6b, 0x67, 0x53, 0x63, 0x72, 0x65, 0x65, 0x6e, 0x73, 0x68, \
|
||||||
|
0x6f, 0x74, 0x73, 0x22, 0x3a, 0x5b, 0x7b, 0x22, 0x63, 0x6f, 0x64, 0x65, \
|
||||||
|
0x22, 0x3a, 0x22, 0x64, 0x64, 0x62, 0x37, 0x62, 0x63, 0x66, 0x63, 0x2d, \
|
||||||
|
0x64, 0x35, 0x32, 0x31, 0x2d, 0x34, 0x61, 0x66, 0x36, 0x2d, 0x38, 0x32, \
|
||||||
|
0x38, 0x33, 0x2d, 0x34, 0x62, 0x30, 0x31, 0x66, 0x39, 0x36, 0x63, 0x63, \
|
||||||
|
0x31, 0x34, 0x39, 0x22, 0x2c, 0x22, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, \
|
||||||
|
0x22, 0x3a, 0x32, 0x36, 0x31, 0x33, 0x36, 0x35, 0x2c, 0x22, 0x68, 0x65, \
|
||||||
|
0x69, 0x67, 0x68, 0x74, 0x22, 0x3a, 0x31, 0x30, 0x32, 0x34, 0x2c, 0x22, \
|
||||||
|
0x77, 0x69, 0x64, 0x74, 0x68, 0x22, 0x3a, 0x31, 0x32, 0x38, 0x30, 0x7d, \
|
||||||
|
0x5d, 0x2c, 0x22, 0x70, 0x6b, 0x67, 0x49, 0x63, 0x6f, 0x6e, 0x73, 0x22, \
|
||||||
|
0x3a, 0x6e, 0x75, 0x6c, 0x6c, 0x2c, 0x22, 0x64, 0x65, 0x72, 0x69, 0x76, \
|
||||||
|
0x65, 0x64, 0x52, 0x61, 0x74, 0x69, 0x6e, 0x67, 0x22, 0x3a, 0x6e, 0x75, \
|
||||||
|
0x6c, 0x6c, 0x2c, 0x22, 0x70, 0x72, 0x6f, 0x6d, 0x69, 0x6e, 0x65, 0x6e, \
|
||||||
|
0x63, 0x65, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x22, 0x3a, \
|
||||||
|
0x31, 0x30, 0x30, 0x30, 0x2c, 0x22, 0x70, 0x6b, 0x67, 0x43, 0x68, 0x61, \
|
||||||
|
0x6e, 0x67, 0x65, 0x6c, 0x6f, 0x67, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, \
|
||||||
|
0x74, 0x22, 0x3a, 0x22, 0x31, 0x2e, 0x32, 0x20, 0x63, 0x68, 0x61, 0x6e, \
|
||||||
|
0x67, 0x65, 0x20, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x20, \
|
||||||
|
0x62, 0x79, 0x20, 0x68, 0x72, 0x65, 0x76, 0x35, 0x30, 0x32, 0x32, 0x36, \
|
||||||
|
0x20, 0x20, 0x74, 0x6f, 0x20, 0x75, 0x73, 0x65, 0x20, 0x42, 0x75, 0x69, \
|
||||||
|
0x6c, 0x64, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x53, 0x65, 0x74, \
|
||||||
|
0x74, 0x69, 0x6e, 0x67, 0x73, 0x56, 0x69, 0x65, 0x77, 0x5c, 0x6e, 0x5c, \
|
||||||
|
0x6e, 0x31, 0x2e, 0x31, 0x20, 0x6d, 0x61, 0x6b, 0x65, 0x20, 0x73, 0x6f, \
|
||||||
|
0x6d, 0x65, 0x20, 0x6c, 0x65, 0x76, 0x65, 0x73, 0x20, 0x63, 0x68, 0x61, \
|
||||||
|
0x6e, 0x67, 0x65, 0x20, 0x6f, 0x72, 0x69, 0x65, 0x6e, 0x74, 0x61, 0x74, \
|
||||||
|
0x69, 0x6f, 0x6e, 0x5c, 0x6e, 0x5c, 0x6e, 0x31, 0x2e, 0x30, 0x20, 0x6f, \
|
||||||
|
0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, 0x20, 0x72, 0x65, 0x6c, 0x65, \
|
||||||
|
0x61, 0x73, 0x65, 0x22, 0x7d, 0x2c, 0x7b, 0x22, 0x6e, 0x61, 0x6d, 0x65, \
|
||||||
|
0x22, 0x3a, 0x22, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x62, 0x75, \
|
||||||
|
0x69, 0x6c, 0x64, 0x65, 0x72, 0x22, 0x2c, 0x22, 0x6d, 0x6f, 0x64, 0x69, \
|
||||||
|
0x66, 0x79, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x22, \
|
||||||
|
0x3a, 0x31, 0x34, 0x38, 0x38, 0x38, 0x30, 0x34, 0x37, 0x30, 0x30, 0x36, \
|
||||||
|
0x33, 0x30, 0x2c, 0x22, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, \
|
||||||
|
0x22, 0x3a, 0x5b, 0x7b, 0x22, 0x6d, 0x61, 0x6a, 0x6f, 0x72, 0x22, 0x3a, \
|
||||||
|
0x22, 0x34, 0x22, 0x2c, 0x22, 0x6d, 0x69, 0x6e, 0x6f, 0x72, 0x22, 0x3a, \
|
||||||
|
0x22, 0x35, 0x22, 0x2c, 0x22, 0x6d, 0x69, 0x63, 0x72, 0x6f, 0x22, 0x3a, \
|
||||||
|
0x6e, 0x75, 0x6c, 0x6c, 0x2c, 0x22, 0x70, 0x72, 0x65, 0x52, 0x65, 0x6c, \
|
||||||
|
0x65, 0x61, 0x73, 0x65, 0x22, 0x3a, 0x6e, 0x75, 0x6c, 0x6c, 0x2c, 0x22, \
|
||||||
|
0x72, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x3a, 0x31, 0x2c, \
|
||||||
|
0x22, 0x61, 0x72, 0x63, 0x68, 0x69, 0x74, 0x65, 0x63, 0x74, 0x75, 0x72, \
|
||||||
|
0x65, 0x43, 0x6f, 0x64, 0x65, 0x22, 0x3a, 0x22, 0x78, 0x38, 0x36, 0x5f, \
|
||||||
|
0x67, 0x63, 0x63, 0x32, 0x22, 0x2c, 0x22, 0x74, 0x69, 0x74, 0x6c, 0x65, \
|
||||||
|
0x22, 0x3a, 0x22, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x42, 0x75, \
|
||||||
|
0x69, 0x6c, 0x64, 0x65, 0x72, 0x22, 0x2c, 0x22, 0x72, 0x65, 0x70, 0x6f, \
|
||||||
|
0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, \
|
||||||
|
0x43, 0x6f, 0x64, 0x65, 0x22, 0x3a, 0x22, 0x66, 0x61, 0x74, 0x65, 0x6c, \
|
||||||
|
0x6b, 0x5f, 0x78, 0x38, 0x36, 0x5f, 0x67, 0x63, 0x63, 0x32, 0x22, 0x2c, \
|
||||||
|
0x22, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x43, \
|
||||||
|
0x6f, 0x64, 0x65, 0x22, 0x3a, 0x22, 0x66, 0x61, 0x74, 0x65, 0x6c, 0x6b, \
|
||||||
|
0x22, 0x2c, 0x22, 0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x22, 0x3a, \
|
||||||
|
0x22, 0x55, 0x74, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x20, 0x74, 0x6f, 0x20, \
|
||||||
|
0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6f, \
|
||||||
|
0x70, 0x65, 0x6e, 0x20, 0x2e, 0x70, 0x6b, 0x67, 0x20, 0x66, 0x69, 0x6c, \
|
||||||
|
0x65, 0x73, 0x22, 0x2c, 0x22, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, \
|
||||||
|
0x74, 0x69, 0x6f, 0x6e, 0x22, 0x3a, 0x22, 0x54, 0x68, 0x69, 0x73, 0x20, \
|
||||||
|
0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, \
|
||||||
|
0x77, 0x61, 0x73, 0x20, 0x42, 0x65, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x27, \
|
||||||
|
0x73, 0x20, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x20, 0x6f, 0x66, 0x20, \
|
||||||
|
0x63, 0x72, 0x65, 0x61, 0x74, 0x69, 0x6e, 0x67, 0x20, 0x2e, 0x70, 0x6b, \
|
||||||
|
0x67, 0x20, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x61, 0x74, 0x69, \
|
||||||
|
0x6f, 0x6e, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x2e, 0x20, 0x49, 0x74, \
|
||||||
|
0x20, 0x77, 0x61, 0x73, 0x20, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, \
|
||||||
|
0x64, 0x20, 0x73, 0x65, 0x70, 0x61, 0x72, 0x61, 0x74, 0x65, 0x6c, 0x79, \
|
||||||
|
0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x42, 0x65, 0x4f, 0x53, 0x20, 0x61, \
|
||||||
|
0x73, 0x20, 0x70, 0x61, 0x72, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, \
|
||||||
|
0x65, 0x20, 0x64, 0x65, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x72, 0x20, \
|
||||||
|
0x74, 0x6f, 0x6f, 0x6c, 0x73, 0x2e, 0x20, 0x49, 0x74, 0x20, 0x69, 0x73, \
|
||||||
|
0x20, 0x75, 0x6e, 0x6c, 0x69, 0x6b, 0x65, 0x6c, 0x79, 0x20, 0x74, 0x68, \
|
||||||
|
0x61, 0x74, 0x20, 0x61, 0x6e, 0x79, 0x6f, 0x6e, 0x65, 0x20, 0x77, 0x69, \
|
||||||
|
0x6c, 0x6c, 0x20, 0x73, 0x74, 0x69, 0x6c, 0x6c, 0x20, 0x77, 0x61, 0x6e, \
|
||||||
|
0x74, 0x20, 0x74, 0x6f, 0x20, 0x6d, 0x61, 0x6b, 0x65, 0x20, 0x74, 0x68, \
|
||||||
|
0x65, 0x73, 0x65, 0x20, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, \
|
||||||
|
0x20, 0x6e, 0x6f, 0x77, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x77, 0x65, \
|
||||||
|
0x20, 0x61, 0x72, 0x65, 0x20, 0x6d, 0x6f, 0x76, 0x69, 0x6e, 0x67, 0x20, \
|
||||||
|
0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x27, 0x68, 0x70, 0x6b, 0x67, \
|
||||||
|
0x20, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x2e, 0x20, 0x42, 0x75, 0x74, \
|
||||||
|
0x20, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x42, 0x75, 0x69, 0x6c, \
|
||||||
|
0x64, 0x65, 0x72, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6f, \
|
||||||
|
0x6e, 0x6c, 0x79, 0x20, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x20, 0x77, 0x61, \
|
||||||
|
0x79, 0x20, 0x74, 0x6f, 0x20, 0x72, 0x69, 0x70, 0x20, 0x61, 0x20, 0x2e, \
|
||||||
|
0x70, 0x6b, 0x67, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x20, 0x61, 0x70, 0x61, \
|
||||||
|
0x72, 0x74, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x67, 0x65, 0x74, 0x20, 0x61, \
|
||||||
|
0x74, 0x20, 0x69, 0x74, 0x73, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, \
|
||||||
|
0x74, 0x73, 0x2e, 0x20, 0x49, 0x74, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, \
|
||||||
|
0x65, 0x72, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x20, 0x73, 0x74, 0x69, 0x6c, \
|
||||||
|
0x6c, 0x20, 0x6f, 0x66, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x65, 0x73, \
|
||||||
|
0x74, 0x20, 0x74, 0x6f, 0x20, 0x64, 0x65, 0x76, 0x65, 0x6c, 0x6f, 0x70, \
|
||||||
|
0x65, 0x72, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x70, 0x6f, 0x72, 0x74, \
|
||||||
|
0x65, 0x72, 0x73, 0x2e, 0x22, 0x2c, 0x22, 0x70, 0x61, 0x79, 0x6c, 0x6f, \
|
||||||
|
0x61, 0x64, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, 0x34, 0x39, \
|
||||||
|
0x38, 0x38, 0x38, 0x36, 0x7d, 0x5d, 0x2c, 0x22, 0x70, 0x6b, 0x67, 0x43, \
|
||||||
|
0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, 0x43, 0x6f, 0x64, 0x65, 0x73, \
|
||||||
|
0x22, 0x3a, 0x5b, 0x22, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x61, 0x6e, \
|
||||||
|
0x64, 0x75, 0x74, 0x69, 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x22, 0x2c, \
|
||||||
|
0x22, 0x64, 0x65, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x6d, 0x65, 0x6e, 0x74, \
|
||||||
|
0x22, 0x5d, 0x2c, 0x22, 0x70, 0x6b, 0x67, 0x53, 0x63, 0x72, 0x65, 0x65, \
|
||||||
|
0x6e, 0x73, 0x68, 0x6f, 0x74, 0x73, 0x22, 0x3a, 0x5b, 0x7b, 0x22, 0x63, \
|
||||||
|
0x6f, 0x64, 0x65, 0x22, 0x3a, 0x22, 0x65, 0x66, 0x62, 0x34, 0x32, 0x32, \
|
||||||
|
0x31, 0x34, 0x2d, 0x30, 0x31, 0x66, 0x36, 0x2d, 0x34, 0x38, 0x37, 0x63, \
|
||||||
|
0x2d, 0x61, 0x33, 0x39, 0x33, 0x2d, 0x36, 0x32, 0x61, 0x33, 0x61, 0x31, \
|
||||||
|
0x34, 0x64, 0x31, 0x36, 0x30, 0x31, 0x22, 0x2c, 0x22, 0x6c, 0x65, 0x6e, \
|
||||||
|
0x67, 0x74, 0x68, 0x22, 0x3a, 0x35, 0x34, 0x32, 0x31, 0x33, 0x2c, 0x22, \
|
||||||
|
0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x22, 0x3a, 0x33, 0x36, 0x30, 0x2c, \
|
||||||
|
0x22, 0x77, 0x69, 0x64, 0x74, 0x68, 0x22, 0x3a, 0x33, 0x32, 0x37, 0x7d, \
|
||||||
|
0x5d, 0x2c, 0x22, 0x70, 0x6b, 0x67, 0x49, 0x63, 0x6f, 0x6e, 0x73, 0x22, \
|
||||||
|
0x3a, 0x6e, 0x75, 0x6c, 0x6c, 0x2c, 0x22, 0x64, 0x65, 0x72, 0x69, 0x76, \
|
||||||
|
0x65, 0x64, 0x52, 0x61, 0x74, 0x69, 0x6e, 0x67, 0x22, 0x3a, 0x34, 0x2e, \
|
||||||
|
0x30, 0x2c, 0x22, 0x70, 0x72, 0x6f, 0x6d, 0x69, 0x6e, 0x65, 0x6e, 0x63, \
|
||||||
|
0x65, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x22, 0x3a, 0x31, \
|
||||||
|
0x30, 0x30, 0x2c, 0x22, 0x70, 0x6b, 0x67, 0x43, 0x68, 0x61, 0x6e, 0x67, \
|
||||||
|
0x65, 0x6c, 0x6f, 0x67, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x22, \
|
||||||
|
0x3a, 0x6e, 0x75, 0x6c, 0x6c, 0x7d, 0x2c, 0x7b, 0x22, 0x6e, 0x61, 0x6d, \
|
||||||
|
0x65, 0x22, 0x3a, 0x22, 0x72, 0x61, 0x77, 0x61, 0x65, 0x73, 0x22, 0x2c, \
|
||||||
|
0x22, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x54, 0x69, 0x6d, 0x65, 0x73, \
|
||||||
|
0x74, 0x61, 0x6d, 0x70, 0x22, 0x3a, 0x31, 0x34, 0x39, 0x31, 0x36, 0x35, \
|
||||||
|
0x32, 0x30, 0x33, 0x39, 0x30, 0x38, 0x39, 0x2c, 0x22, 0x76, 0x65, 0x72, \
|
||||||
|
0x73, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x3a, 0x5b, 0x7b, 0x22, 0x6d, 0x61, \
|
||||||
|
0x6a, 0x6f, 0x72, 0x22, 0x3a, 0x22, 0x31, 0x22, 0x2c, 0x22, 0x6d, 0x69, \
|
||||||
|
0x6e, 0x6f, 0x72, 0x22, 0x3a, 0x22, 0x31, 0x22, 0x2c, 0x22, 0x6d, 0x69, \
|
||||||
|
0x63, 0x72, 0x6f, 0x22, 0x3a, 0x6e, 0x75, 0x6c, 0x6c, 0x2c, 0x22, 0x70, \
|
||||||
|
0x72, 0x65, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x22, 0x3a, 0x6e, \
|
||||||
|
0x75, 0x6c, 0x6c, 0x2c, 0x22, 0x72, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, \
|
||||||
|
0x6e, 0x22, 0x3a, 0x31, 0x2c, 0x22, 0x61, 0x72, 0x63, 0x68, 0x69, 0x74, \
|
||||||
|
0x65, 0x63, 0x74, 0x75, 0x72, 0x65, 0x43, 0x6f, 0x64, 0x65, 0x22, 0x3a, \
|
||||||
|
0x22, 0x78, 0x38, 0x36, 0x5f, 0x67, 0x63, 0x63, 0x32, 0x22, 0x2c, 0x22, \
|
||||||
|
0x74, 0x69, 0x74, 0x6c, 0x65, 0x22, 0x3a, 0x6e, 0x75, 0x6c, 0x6c, 0x2c, \
|
||||||
|
0x22, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x53, \
|
||||||
|
0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x6f, 0x64, 0x65, 0x22, 0x3a, 0x22, \
|
||||||
|
0x66, 0x61, 0x74, 0x65, 0x6c, 0x6b, 0x5f, 0x78, 0x38, 0x36, 0x5f, 0x67, \
|
||||||
|
0x63, 0x63, 0x32, 0x22, 0x2c, 0x22, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, \
|
||||||
|
0x74, 0x6f, 0x72, 0x79, 0x43, 0x6f, 0x64, 0x65, 0x22, 0x3a, 0x22, 0x66, \
|
||||||
|
0x61, 0x74, 0x65, 0x6c, 0x6b, 0x22, 0x2c, 0x22, 0x73, 0x75, 0x6d, 0x6d, \
|
||||||
|
0x61, 0x72, 0x79, 0x22, 0x3a, 0x22, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, \
|
||||||
|
0x64, 0x2d, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x65, 0x6e, 0x63, 0x72, 0x79, \
|
||||||
|
0x70, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x75, 0x74, 0x69, 0x6c, 0x69, 0x74, \
|
||||||
|
0x79, 0x22, 0x2c, 0x22, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, \
|
||||||
|
0x69, 0x6f, 0x6e, 0x22, 0x3a, 0x22, 0x52, 0x61, 0x77, 0x61, 0x65, 0x73, \
|
||||||
|
0x20, 0x65, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x73, 0x20, 0x61, 0x20, \
|
||||||
|
0x66, 0x69, 0x6c, 0x65, 0x20, 0x75, 0x73, 0x69, 0x6e, 0x67, 0x20, 0x74, \
|
||||||
|
0x68, 0x65, 0x20, 0x41, 0x64, 0x76, 0x61, 0x6e, 0x64, 0x63, 0x65, 0x64, \
|
||||||
|
0x20, 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x20, \
|
||||||
|
0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x28, 0x41, 0x45, \
|
||||||
|
0x53, 0x29, 0x2e, 0x20, 0x20, 0x41, 0x45, 0x53, 0x20, 0x75, 0x73, 0x65, \
|
||||||
|
0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x52, 0x69, 0x6a, 0x6e, 0x64, 0x61, \
|
||||||
|
0x65, 0x6c, 0x20, 0x41, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, \
|
||||||
|
0x2c, 0x20, 0x61, 0x20, 0x31, 0x32, 0x38, 0x2d, 0x62, 0x69, 0x74, 0x20, \
|
||||||
|
0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x20, 0x63, 0x69, 0x70, 0x68, 0x65, 0x72, \
|
||||||
|
0x2c, 0x20, 0x74, 0x6f, 0x20, 0x65, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, \
|
||||||
|
0x2e, 0x20, 0x20, 0x53, 0x69, 0x6e, 0x63, 0x65, 0x20, 0x74, 0x68, 0x65, \
|
||||||
|
0x20, 0x65, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x20, \
|
||||||
|
0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x73, 0x20, 0x31, 0x36, 0x2d, \
|
||||||
|
0x62, 0x79, 0x74, 0x65, 0x20, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x2c, \
|
||||||
|
0x20, 0x72, 0x61, 0x77, 0x61, 0x65, 0x73, 0x20, 0x77, 0x69, 0x6c, 0x6c, \
|
||||||
|
0x20, 0x70, 0x61, 0x64, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x75, 0x6e, 0x65, \
|
||||||
|
0x76, 0x65, 0x6e, 0x20, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x20, 0x77, \
|
||||||
|
0x69, 0x74, 0x68, 0x20, 0x30, 0x73, 0x2c, 0x20, 0x70, 0x6f, 0x73, 0x73, \
|
||||||
|
0x69, 0x62, 0x6c, 0x79, 0x20, 0x69, 0x6e, 0x63, 0x72, 0x65, 0x61, 0x73, \
|
||||||
|
0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x69, 0x7a, 0x65, \
|
||||||
|
0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x6c, 0x65, \
|
||||||
|
0x20, 0x75, 0x70, 0x20, 0x74, 0x6f, 0x20, 0x31, 0x35, 0x20, 0x62, 0x79, \
|
||||||
|
0x74, 0x65, 0x73, 0x2e, 0x22, 0x2c, 0x22, 0x70, 0x61, 0x79, 0x6c, 0x6f, \
|
||||||
|
0x61, 0x64, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, 0x36, 0x32, \
|
||||||
|
0x37, 0x39, 0x33, 0x7d, 0x5d, 0x2c, 0x22, 0x70, 0x6b, 0x67, 0x43, 0x61, \
|
||||||
|
0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, 0x43, 0x6f, 0x64, 0x65, 0x73, 0x22, \
|
||||||
|
0x3a, 0x5b, 0x22, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x61, 0x6e, 0x64, \
|
||||||
|
0x75, 0x74, 0x69, 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x22, 0x2c, 0x22, \
|
||||||
|
0x73, 0x63, 0x69, 0x65, 0x6e, 0x63, 0x65, 0x61, 0x6e, 0x64, 0x6d, 0x61, \
|
||||||
|
0x74, 0x68, 0x65, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x73, 0x22, 0x5d, 0x2c, \
|
||||||
|
0x22, 0x70, 0x6b, 0x67, 0x53, 0x63, 0x72, 0x65, 0x65, 0x6e, 0x73, 0x68, \
|
||||||
|
0x6f, 0x74, 0x73, 0x22, 0x3a, 0x5b, 0x5d, 0x2c, 0x22, 0x70, 0x6b, 0x67, \
|
||||||
|
0x49, 0x63, 0x6f, 0x6e, 0x73, 0x22, 0x3a, 0x6e, 0x75, 0x6c, 0x6c, 0x2c, \
|
||||||
|
0x22, 0x64, 0x65, 0x72, 0x69, 0x76, 0x65, 0x64, 0x52, 0x61, 0x74, 0x69, \
|
||||||
|
0x6e, 0x67, 0x22, 0x3a, 0x6e, 0x75, 0x6c, 0x6c, 0x2c, 0x22, 0x70, 0x72, \
|
||||||
|
0x6f, 0x6d, 0x69, 0x6e, 0x65, 0x6e, 0x63, 0x65, 0x4f, 0x72, 0x64, 0x65, \
|
||||||
|
0x72, 0x69, 0x6e, 0x67, 0x22, 0x3a, 0x31, 0x30, 0x30, 0x30, 0x2c, 0x22, \
|
||||||
|
0x70, 0x6b, 0x67, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x6c, 0x6f, 0x67, \
|
||||||
|
0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x22, 0x3a, 0x6e, 0x75, 0x6c, \
|
||||||
|
0x6c, 0x7d, 0x2c, 0x7b, 0x22, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x3a, 0x22, \
|
||||||
|
0x74, 0x65, 0x78, 0x74, 0x73, 0x61, 0x76, 0x65, 0x72, 0x22, 0x2c, 0x22, \
|
||||||
|
0x6d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, \
|
||||||
|
0x61, 0x6d, 0x70, 0x22, 0x3a, 0x31, 0x34, 0x39, 0x31, 0x36, 0x35, 0x32, \
|
||||||
|
0x30, 0x33, 0x39, 0x38, 0x30, 0x39, 0x2c, 0x22, 0x76, 0x65, 0x72, 0x73, \
|
||||||
|
0x69, 0x6f, 0x6e, 0x73, 0x22, 0x3a, 0x5b, 0x7b, 0x22, 0x6d, 0x61, 0x6a, \
|
||||||
|
0x6f, 0x72, 0x22, 0x3a, 0x22, 0x31, 0x22, 0x2c, 0x22, 0x6d, 0x69, 0x6e, \
|
||||||
|
0x6f, 0x72, 0x22, 0x3a, 0x22, 0x30, 0x22, 0x2c, 0x22, 0x6d, 0x69, 0x63, \
|
||||||
|
0x72, 0x6f, 0x22, 0x3a, 0x6e, 0x75, 0x6c, 0x6c, 0x2c, 0x22, 0x70, 0x72, \
|
||||||
|
0x65, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x22, 0x3a, 0x6e, 0x75, \
|
||||||
|
0x6c, 0x6c, 0x2c, 0x22, 0x72, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, \
|
||||||
|
0x22, 0x3a, 0x31, 0x2c, 0x22, 0x61, 0x72, 0x63, 0x68, 0x69, 0x74, 0x65, \
|
||||||
|
0x63, 0x74, 0x75, 0x72, 0x65, 0x43, 0x6f, 0x64, 0x65, 0x22, 0x3a, 0x22, \
|
||||||
|
0x78, 0x38, 0x36, 0x5f, 0x67, 0x63, 0x63, 0x32, 0x22, 0x2c, 0x22, 0x74, \
|
||||||
|
0x69, 0x74, 0x6c, 0x65, 0x22, 0x3a, 0x22, 0x54, 0x65, 0x78, 0x74, 0x53, \
|
||||||
|
0x61, 0x76, 0x65, 0x72, 0x22, 0x2c, 0x22, 0x72, 0x65, 0x70, 0x6f, 0x73, \
|
||||||
|
0x69, 0x74, 0x6f, 0x72, 0x79, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, \
|
||||||
|
0x6f, 0x64, 0x65, 0x22, 0x3a, 0x22, 0x66, 0x61, 0x74, 0x65, 0x6c, 0x6b, \
|
||||||
|
0x5f, 0x78, 0x38, 0x36, 0x5f, 0x67, 0x63, 0x63, 0x32, 0x22, 0x2c, 0x22, \
|
||||||
|
0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x43, 0x6f, \
|
||||||
|
0x64, 0x65, 0x22, 0x3a, 0x22, 0x66, 0x61, 0x74, 0x65, 0x6c, 0x6b, 0x22, \
|
||||||
|
0x2c, 0x22, 0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x22, 0x3a, 0x22, \
|
||||||
|
0x54, 0x65, 0x78, 0x74, 0x53, 0x61, 0x76, 0x65, 0x72, 0x20, 0x73, 0x63, \
|
||||||
|
0x72, 0x65, 0x65, 0x6e, 0x73, 0x61, 0x76, 0x65, 0x72, 0x22, 0x2c, 0x22, \
|
||||||
|
0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x22, \
|
||||||
|
0x3a, 0x22, 0x44, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x73, 0x20, 0x79, \
|
||||||
|
0x6f, 0x75, 0x72, 0x20, 0x74, 0x65, 0x78, 0x74, 0x20, 0x61, 0x74, 0x20, \
|
||||||
|
0x72, 0x61, 0x6e, 0x64, 0x6f, 0x6d, 0x20, 0x6c, 0x6f, 0x63, 0x61, 0x74, \
|
||||||
|
0x69, 0x6f, 0x6e, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x72, 0x61, 0x6e, 0x64, \
|
||||||
|
0x6f, 0x6d, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x73, 0x2e, 0x22, 0x2c, \
|
||||||
|
0x22, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x4c, 0x65, 0x6e, 0x67, \
|
||||||
|
0x74, 0x68, 0x22, 0x3a, 0x31, 0x32, 0x31, 0x36, 0x38, 0x7d, 0x5d, 0x2c, \
|
||||||
|
0x22, 0x70, 0x6b, 0x67, 0x43, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, \
|
||||||
|
0x43, 0x6f, 0x64, 0x65, 0x73, 0x22, 0x3a, 0x5b, 0x22, 0x73, 0x79, 0x73, \
|
||||||
|
0x74, 0x65, 0x6d, 0x61, 0x6e, 0x64, 0x75, 0x74, 0x69, 0x6c, 0x69, 0x74, \
|
||||||
|
0x69, 0x65, 0x73, 0x22, 0x5d, 0x2c, 0x22, 0x70, 0x6b, 0x67, 0x53, 0x63, \
|
||||||
|
0x72, 0x65, 0x65, 0x6e, 0x73, 0x68, 0x6f, 0x74, 0x73, 0x22, 0x3a, 0x5b, \
|
||||||
|
0x5d, 0x2c, 0x22, 0x70, 0x6b, 0x67, 0x49, 0x63, 0x6f, 0x6e, 0x73, 0x22, \
|
||||||
|
0x3a, 0x6e, 0x75, 0x6c, 0x6c, 0x2c, 0x22, 0x64, 0x65, 0x72, 0x69, 0x76, \
|
||||||
|
0x65, 0x64, 0x52, 0x61, 0x74, 0x69, 0x6e, 0x67, 0x22, 0x3a, 0x6e, 0x75, \
|
||||||
|
0x6c, 0x6c, 0x2c, 0x22, 0x70, 0x72, 0x6f, 0x6d, 0x69, 0x6e, 0x65, 0x6e, \
|
||||||
|
0x63, 0x65, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x22, 0x3a, \
|
||||||
|
0x31, 0x30, 0x30, 0x30, 0x2c, 0x22, 0x70, 0x6b, 0x67, 0x43, 0x68, 0x61, \
|
||||||
|
0x6e, 0x67, 0x65, 0x6c, 0x6f, 0x67, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, \
|
||||||
|
0x74, 0x22, 0x3a, 0x6e, 0x75, 0x6c, 0x6c, 0x7d, 0x2c, 0x7b, 0x22, 0x6e, \
|
||||||
|
0x61, 0x6d, 0x65, 0x22, 0x3a, 0x22, 0x76, 0x6e, 0x63, 0x73, 0x65, 0x72, \
|
||||||
|
0x76, 0x65, 0x72, 0x22, 0x2c, 0x22, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x79, \
|
||||||
|
0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x22, 0x3a, 0x31, \
|
||||||
|
0x34, 0x39, 0x31, 0x36, 0x35, 0x32, 0x30, 0x34, 0x30, 0x32, 0x34, 0x34, \
|
||||||
|
0x2c, 0x22, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x3a, \
|
||||||
|
0x5b, 0x7b, 0x22, 0x6d, 0x61, 0x6a, 0x6f, 0x72, 0x22, 0x3a, 0x22, 0x76, \
|
||||||
|
0x6e, 0x63, 0x34, 0x5f, 0x30, 0x22, 0x2c, 0x22, 0x6d, 0x69, 0x6e, 0x6f, \
|
||||||
|
0x72, 0x22, 0x3a, 0x22, 0x61, 0x67, 0x6d, 0x73, 0x5f, 0x31, 0x22, 0x2c, \
|
||||||
|
0x22, 0x6d, 0x69, 0x63, 0x72, 0x6f, 0x22, 0x3a, 0x22, 0x32, 0x37, 0x22, \
|
||||||
|
0x2c, 0x22, 0x70, 0x72, 0x65, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, \
|
||||||
|
0x22, 0x3a, 0x6e, 0x75, 0x6c, 0x6c, 0x2c, 0x22, 0x72, 0x65, 0x76, 0x69, \
|
||||||
|
0x73, 0x69, 0x6f, 0x6e, 0x22, 0x3a, 0x32, 0x2c, 0x22, 0x61, 0x72, 0x63, \
|
||||||
|
0x68, 0x69, 0x74, 0x65, 0x63, 0x74, 0x75, 0x72, 0x65, 0x43, 0x6f, 0x64, \
|
||||||
|
0x65, 0x22, 0x3a, 0x22, 0x78, 0x38, 0x36, 0x5f, 0x67, 0x63, 0x63, 0x32, \
|
||||||
|
0x22, 0x2c, 0x22, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x22, 0x3a, 0x22, 0x56, \
|
||||||
|
0x4e, 0x43, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x22, 0x2c, 0x22, 0x72, \
|
||||||
|
0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x53, 0x6f, 0x75, \
|
||||||
|
0x72, 0x63, 0x65, 0x43, 0x6f, 0x64, 0x65, 0x22, 0x3a, 0x22, 0x66, 0x61, \
|
||||||
|
0x74, 0x65, 0x6c, 0x6b, 0x5f, 0x78, 0x38, 0x36, 0x5f, 0x67, 0x63, 0x63, \
|
||||||
|
0x32, 0x22, 0x2c, 0x22, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, \
|
||||||
|
0x72, 0x79, 0x43, 0x6f, 0x64, 0x65, 0x22, 0x3a, 0x22, 0x66, 0x61, 0x74, \
|
||||||
|
0x65, 0x6c, 0x6b, 0x22, 0x2c, 0x22, 0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72, \
|
||||||
|
0x79, 0x22, 0x3a, 0x22, 0x56, 0x4e, 0x43, 0x53, 0x65, 0x72, 0x76, 0x65, \
|
||||||
|
0x72, 0x20, 0x6c, 0x65, 0x74, 0x73, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x75, \
|
||||||
|
0x73, 0x65, 0x20, 0x79, 0x6f, 0x75, 0x72, 0x20, 0x42, 0x65, 0x4f, 0x53, \
|
||||||
|
0x20, 0x2f, 0x20, 0x48, 0x61, 0x69, 0x6b, 0x75, 0x20, 0x63, 0x6f, 0x6d, \
|
||||||
|
0x70, 0x75, 0x74, 0x65, 0x72, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x61, \
|
||||||
|
0x6e, 0x79, 0x77, 0x68, 0x65, 0x72, 0x65, 0x20, 0x74, 0x68, 0x65, 0x72, \
|
||||||
|
0x65, 0x20, 0x69, 0x73, 0x20, 0x61, 0x6e, 0x20, 0x49, 0x6e, 0x74, 0x65, \
|
||||||
|
0x72, 0x6e, 0x65, 0x74, 0x20, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, \
|
||||||
|
0x69, 0x6f, 0x6e, 0x2e, 0x20, 0x20, 0x59, 0x6f, 0x75, 0x20, 0x63, 0x61, \
|
||||||
|
0x6e, 0x20, 0x74, 0x68, 0x69, 0x6e, 0x6b, 0x20, 0x6f, 0x66, 0x20, 0x69, \
|
||||||
|
0x74, 0x20, 0x61, 0x73, 0x20, 0x61, 0x20, 0x72, 0x65, 0x61, 0x6c, 0x6c, \
|
||||||
|
0x79, 0x20, 0x6c, 0x6f, 0x6e, 0x67, 0x20, 0x6b, 0x65, 0x79, 0x62, 0x6f, \
|
||||||
|
0x61, 0x72, 0x64, 0x2c, 0x20, 0x6d, 0x6f, 0x75, 0x73, 0x65, 0x20, 0x61, \
|
||||||
|
0x6e, 0x64, 0x20, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x20, 0x63, 0x61, 0x62, \
|
||||||
|
0x6c, 0x65, 0x2e, 0x22, 0x2c, 0x22, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, \
|
||||||
|
0x70, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x3a, 0x22, 0x41, 0x20, 0x56, 0x4e, \
|
||||||
|
0x43, 0x20, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x20, 0x28, 0x61, 0x76, \
|
||||||
|
0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x65, 0x6c, 0x73, 0x65, \
|
||||||
|
0x77, 0x68, 0x65, 0x72, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x57, 0x69, \
|
||||||
|
0x6e, 0x64, 0x6f, 0x77, 0x73, 0x2c, 0x20, 0x4d, 0x61, 0x63, 0x2c, 0x20, \
|
||||||
|
0x4c, 0x69, 0x6e, 0x75, 0x78, 0x2c, 0x20, 0x6f, 0x74, 0x68, 0x65, 0x72, \
|
||||||
|
0x73, 0x29, 0x20, 0x73, 0x68, 0x6f, 0x77, 0x73, 0x20, 0x79, 0x6f, 0x75, \
|
||||||
|
0x20, 0x77, 0x68, 0x61, 0x74, 0x27, 0x73, 0x20, 0x6f, 0x6e, 0x20, 0x74, \
|
||||||
|
0x68, 0x65, 0x20, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x20, 0x42, 0x65, \
|
||||||
|
0x4f, 0x53, 0x20, 0x2f, 0x20, 0x48, 0x61, 0x69, 0x6b, 0x75, 0x20, 0x63, \
|
||||||
|
0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x72, 0x27, 0x73, 0x20, 0x73, 0x63, \
|
||||||
|
0x72, 0x65, 0x65, 0x6e, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x65, 0x6e, \
|
||||||
|
0x64, 0x73, 0x20, 0x6b, 0x65, 0x79, 0x73, 0x74, 0x72, 0x6f, 0x6b, 0x65, \
|
||||||
|
0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6d, 0x6f, 0x75, 0x73, 0x65, 0x20, \
|
||||||
|
0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x6f, 0x76, 0x65, 0x72, \
|
||||||
|
0x20, 0x74, 0x68, 0x65, 0x20, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, \
|
||||||
|
0x74, 0x2e, 0x20, 0x20, 0x54, 0x68, 0x65, 0x20, 0x56, 0x4e, 0x43, 0x53, \
|
||||||
|
0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x73, 0x6f, 0x66, 0x74, 0x77, 0x61, \
|
||||||
|
0x72, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x6f, \
|
||||||
|
0x6e, 0x20, 0x42, 0x65, 0x4f, 0x53, 0x20, 0x6f, 0x72, 0x20, 0x48, 0x61, \
|
||||||
|
0x69, 0x6b, 0x75, 0x20, 0x75, 0x73, 0x65, 0x73, 0x20, 0x74, 0x68, 0x61, \
|
||||||
|
0x74, 0x20, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x20, 0x64, 0x61, 0x74, \
|
||||||
|
0x61, 0x20, 0x74, 0x6f, 0x20, 0x73, 0x69, 0x6d, 0x75, 0x6c, 0x61, 0x74, \
|
||||||
|
0x65, 0x20, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x20, 0x70, 0x72, 0x65, \
|
||||||
|
0x73, 0x73, 0x65, 0x73, 0x20, 0x6f, 0x6e, 0x20, 0x61, 0x20, 0x66, 0x61, \
|
||||||
|
0x6b, 0x65, 0x20, 0x6b, 0x65, 0x79, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x20, \
|
||||||
|
0x61, 0x6e, 0x64, 0x20, 0x6d, 0x6f, 0x76, 0x65, 0x6d, 0x65, 0x6e, 0x74, \
|
||||||
|
0x73, 0x20, 0x6f, 0x66, 0x20, 0x61, 0x6e, 0x20, 0x69, 0x6d, 0x61, 0x67, \
|
||||||
|
0x69, 0x6e, 0x61, 0x72, 0x79, 0x20, 0x6d, 0x6f, 0x75, 0x73, 0x65, 0x2e, \
|
||||||
|
0x20, 0x20, 0x49, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6f, 0x70, 0x70, \
|
||||||
|
0x6f, 0x73, 0x69, 0x74, 0x65, 0x20, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, \
|
||||||
|
0x69, 0x6f, 0x6e, 0x2c, 0x20, 0x56, 0x4e, 0x43, 0x53, 0x65, 0x72, 0x76, \
|
||||||
|
0x65, 0x72, 0x20, 0x73, 0x63, 0x61, 0x6e, 0x73, 0x20, 0x79, 0x6f, 0x75, \
|
||||||
|
0x72, 0x20, 0x73, 0x63, 0x72, 0x65, 0x65, 0x6e, 0x20, 0x66, 0x6f, 0x72, \
|
||||||
|
0x20, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x2c, 0x20, 0x63, 0x6f, \
|
||||||
|
0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x20, 0x74, 0x68, 0x65, \
|
||||||
|
0x20, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x69, 0x6e, 0x67, 0x20, 0x67, \
|
||||||
|
0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x73, 0x20, 0x64, 0x61, 0x74, 0x61, \
|
||||||
|
0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x6d, 0x69, \
|
||||||
|
0x74, 0x73, 0x20, 0x69, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, \
|
||||||
|
0x20, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2e, 0x5c, 0x6e, 0x5c, 0x6e, \
|
||||||
|
0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x61, 0x20, 0x70, 0x6f, \
|
||||||
|
0x72, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x56, 0x4e, 0x43, 0x20, 0x75, 0x73, \
|
||||||
|
0x69, 0x6e, 0x67, 0x20, 0x52, 0x65, 0x61, 0x6c, 0x56, 0x4e, 0x43, 0x27, \
|
||||||
|
0x73, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x34, 0x2e, \
|
||||||
|
0x30, 0x20, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x20, 0x73, 0x6f, 0x75, 0x72, \
|
||||||
|
0x63, 0x65, 0x20, 0x63, 0x6f, 0x64, 0x65, 0x20, 0x28, 0x77, 0x68, 0x69, \
|
||||||
|
0x63, 0x68, 0x20, 0x68, 0x61, 0x73, 0x20, 0x61, 0x6e, 0x20, 0x65, 0x78, \
|
||||||
|
0x74, 0x72, 0x65, 0x6d, 0x65, 0x6c, 0x79, 0x20, 0x77, 0x65, 0x6c, 0x6c, \
|
||||||
|
0x20, 0x64, 0x65, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x20, 0x63, 0x6c, \
|
||||||
|
0x61, 0x73, 0x73, 0x20, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x75, 0x72, \
|
||||||
|
0x65, 0x2c, 0x20, 0x6d, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x20, 0x69, 0x74, \
|
||||||
|
0x20, 0x65, 0x61, 0x73, 0x79, 0x20, 0x74, 0x6f, 0x20, 0x64, 0x6f, 0x20, \
|
||||||
|
0x74, 0x68, 0x69, 0x73, 0x20, 0x70, 0x6f, 0x72, 0x74, 0x29, 0x2e, 0x20, \
|
||||||
|
0x20, 0x54, 0x68, 0x65, 0x72, 0x65, 0x20, 0x61, 0x72, 0x65, 0x20, 0x6c, \
|
||||||
|
0x6f, 0x74, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x56, 0x4e, 0x43, 0x20, 0x63, \
|
||||||
|
0x6c, 0x69, 0x65, 0x6e, 0x74, 0x73, 0x20, 0x6f, 0x75, 0x74, 0x20, 0x74, \
|
||||||
|
0x68, 0x65, 0x72, 0x65, 0x2c, 0x20, 0x62, 0x75, 0x74, 0x20, 0x49, 0x20, \
|
||||||
|
0x63, 0x61, 0x6e, 0x20, 0x72, 0x65, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, \
|
||||||
|
0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x52, 0x65, 0x61, 0x6c, 0x56, 0x4e, \
|
||||||
|
0x43, 0x20, 0x6f, 0x6e, 0x65, 0x73, 0x20, 0x61, 0x73, 0x20, 0x77, 0x6f, \
|
||||||
|
0x72, 0x6b, 0x69, 0x6e, 0x67, 0x20, 0x76, 0x65, 0x72, 0x79, 0x20, 0x77, \
|
||||||
|
0x65, 0x6c, 0x6c, 0x20, 0x75, 0x6e, 0x64, 0x65, 0x72, 0x20, 0x57, 0x69, \
|
||||||
|
0x6e, 0x64, 0x6f, 0x77, 0x73, 0x2e, 0x20, 0x20, 0x59, 0x6f, 0x75, 0x20, \
|
||||||
|
0x63, 0x61, 0x6e, 0x20, 0x67, 0x65, 0x74, 0x20, 0x74, 0x68, 0x65, 0x69, \
|
||||||
|
0x72, 0x20, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x73, 0x2c, 0x20, 0x73, \
|
||||||
|
0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, \
|
||||||
|
0x6f, 0x75, 0x72, 0x63, 0x65, 0x20, 0x63, 0x6f, 0x64, 0x65, 0x20, 0x61, \
|
||||||
|
0x74, 0x20, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, \
|
||||||
|
0x2e, 0x72, 0x65, 0x61, 0x6c, 0x76, 0x6e, 0x63, 0x2e, 0x63, 0x6f, 0x6d, \
|
||||||
|
0x2f, 0x22, 0x2c, 0x22, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x4c, \
|
||||||
|
0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, 0x32, 0x32, 0x34, 0x35, 0x37, \
|
||||||
|
0x32, 0x7d, 0x5d, 0x2c, 0x22, 0x70, 0x6b, 0x67, 0x43, 0x61, 0x74, 0x65, \
|
||||||
|
0x67, 0x6f, 0x72, 0x79, 0x43, 0x6f, 0x64, 0x65, 0x73, 0x22, 0x3a, 0x5b, \
|
||||||
|
0x22, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x61, 0x6e, 0x64, \
|
||||||
|
0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x22, 0x5d, 0x2c, 0x22, 0x70, \
|
||||||
|
0x6b, 0x67, 0x53, 0x63, 0x72, 0x65, 0x65, 0x6e, 0x73, 0x68, 0x6f, 0x74, \
|
||||||
|
0x73, 0x22, 0x3a, 0x5b, 0x5d, 0x2c, 0x22, 0x70, 0x6b, 0x67, 0x49, 0x63, \
|
||||||
|
0x6f, 0x6e, 0x73, 0x22, 0x3a, 0x6e, 0x75, 0x6c, 0x6c, 0x2c, 0x22, 0x64, \
|
||||||
|
0x65, 0x72, 0x69, 0x76, 0x65, 0x64, 0x52, 0x61, 0x74, 0x69, 0x6e, 0x67, \
|
||||||
|
0x22, 0x3a, 0x6e, 0x75, 0x6c, 0x6c, 0x2c, 0x22, 0x70, 0x72, 0x6f, 0x6d, \
|
||||||
|
0x69, 0x6e, 0x65, 0x6e, 0x63, 0x65, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x69, \
|
||||||
|
0x6e, 0x67, 0x22, 0x3a, 0x31, 0x30, 0x30, 0x30, 0x2c, 0x22, 0x70, 0x6b, \
|
||||||
|
0x67, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x6c, 0x6f, 0x67, 0x43, 0x6f, \
|
||||||
|
0x6e, 0x74, 0x65, 0x6e, 0x74, 0x22, 0x3a, 0x6e, 0x75, 0x6c, 0x6c, 0x7d, \
|
||||||
|
0x5d, 0x7d, 0x7d, 0x0a, 0x00 \
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif // JSON_SAMPLES_H
|
||||||
@@ -0,0 +1,207 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2017, Andrew Lindesay <[email protected]>
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
#include "JsonTextWriterTest.h"
|
||||||
|
|
||||||
|
#include <AutoDeleter.h>
|
||||||
|
|
||||||
|
#include <Json.h>
|
||||||
|
#include <JsonTextWriter.h>
|
||||||
|
|
||||||
|
#include <cppunit/TestCaller.h>
|
||||||
|
#include <cppunit/TestSuite.h>
|
||||||
|
|
||||||
|
#include "JsonSamples.h"
|
||||||
|
|
||||||
|
|
||||||
|
#define LOOPS_TEST_OBJECT_A_FOR_PERFORMANCE 100000
|
||||||
|
|
||||||
|
|
||||||
|
using namespace BPrivate;
|
||||||
|
|
||||||
|
|
||||||
|
JsonTextWriterTest::JsonTextWriterTest()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
JsonTextWriterTest::~JsonTextWriterTest()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
JsonTextWriterTest::TestArrayA()
|
||||||
|
{
|
||||||
|
BMallocIO* outputData = new BMallocIO();
|
||||||
|
ObjectDeleter<BMallocIO> outputDataDeleter(outputData);
|
||||||
|
BJsonTextWriter writer(outputData);
|
||||||
|
|
||||||
|
CPPUNIT_ASSERT_EQUAL(B_OK, writer.WriteArrayStart());
|
||||||
|
CPPUNIT_ASSERT_EQUAL(B_OK, writer.WriteString("1234"));
|
||||||
|
CPPUNIT_ASSERT_EQUAL(B_OK, writer.WriteInteger(4567));
|
||||||
|
CPPUNIT_ASSERT_EQUAL(B_OK, writer.WriteArrayStart());
|
||||||
|
CPPUNIT_ASSERT_EQUAL(B_OK, writer.WriteString("A"));
|
||||||
|
CPPUNIT_ASSERT_EQUAL(B_OK, writer.WriteString("b"));
|
||||||
|
CPPUNIT_ASSERT_EQUAL(B_OK, writer.WriteString("C\xc3\xa9zanne"));
|
||||||
|
CPPUNIT_ASSERT_EQUAL(B_OK, writer.WriteArrayEnd());
|
||||||
|
CPPUNIT_ASSERT_EQUAL(B_OK, writer.WriteArrayEnd());
|
||||||
|
writer.Complete();
|
||||||
|
|
||||||
|
BString outputString((char*)outputData->Buffer(),
|
||||||
|
outputData->BufferLength());
|
||||||
|
fprintf(stderr, "expected out >%s<\n", JSON_SAMPLE_ARRAY_A_EXPECTED_OUT);
|
||||||
|
fprintf(stderr, "actual out >%s< (%" B_PRIuSIZE ")\n", outputString.String(),
|
||||||
|
outputData->BufferLength());
|
||||||
|
|
||||||
|
CPPUNIT_ASSERT_EQUAL(BString(JSON_SAMPLE_ARRAY_A_EXPECTED_OUT),
|
||||||
|
outputString);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
JsonTextWriterTest::TestObjectA()
|
||||||
|
{
|
||||||
|
BMallocIO* outputData = new BMallocIO();
|
||||||
|
ObjectDeleter<BMallocIO> outputDataDeleter(outputData);
|
||||||
|
BJsonTextWriter writer(outputData);
|
||||||
|
|
||||||
|
CPPUNIT_ASSERT_EQUAL(B_OK, writer.WriteObjectStart());
|
||||||
|
CPPUNIT_ASSERT_EQUAL(B_OK, writer.WriteObjectName("weather"));
|
||||||
|
CPPUNIT_ASSERT_EQUAL(B_OK, writer.WriteString("raining"));
|
||||||
|
CPPUNIT_ASSERT_EQUAL(B_OK, writer.WriteObjectName("humidity"));
|
||||||
|
CPPUNIT_ASSERT_EQUAL(B_OK, writer.WriteString("too-high"));
|
||||||
|
CPPUNIT_ASSERT_EQUAL(B_OK, writer.WriteObjectName("daysOfWeek"));
|
||||||
|
CPPUNIT_ASSERT_EQUAL(B_OK, writer.WriteArrayStart());
|
||||||
|
CPPUNIT_ASSERT_EQUAL(B_OK, writer.WriteString("MON"));
|
||||||
|
CPPUNIT_ASSERT_EQUAL(B_OK, writer.WriteString("TUE"));
|
||||||
|
CPPUNIT_ASSERT_EQUAL(B_OK, writer.WriteString("WED"));
|
||||||
|
CPPUNIT_ASSERT_EQUAL(B_OK, writer.WriteString("THR"));
|
||||||
|
CPPUNIT_ASSERT_EQUAL(B_OK, writer.WriteString("FRI"));
|
||||||
|
CPPUNIT_ASSERT_EQUAL(B_OK, writer.WriteArrayEnd());
|
||||||
|
CPPUNIT_ASSERT_EQUAL(B_OK, writer.WriteObjectEnd());
|
||||||
|
writer.Complete();
|
||||||
|
|
||||||
|
BString outputString((char*)outputData->Buffer(),
|
||||||
|
outputData->BufferLength());
|
||||||
|
fprintf(stderr, "expected out >%s<\n", JSON_SAMPLE_OBJECT_A_EXPECTED_OUT);
|
||||||
|
fprintf(stderr, "actual out >%s< (%" B_PRIuSIZE ")\n", outputString.String(),
|
||||||
|
outputData->BufferLength());
|
||||||
|
|
||||||
|
CPPUNIT_ASSERT_EQUAL(BString(JSON_SAMPLE_OBJECT_A_EXPECTED_OUT),
|
||||||
|
outputString);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
JsonTextWriterTest::TestObjectAForPerformance()
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < LOOPS_TEST_OBJECT_A_FOR_PERFORMANCE; i++) {
|
||||||
|
TestObjectA();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
JsonTextWriterTest::TestInteger()
|
||||||
|
{
|
||||||
|
BMallocIO* outputData = new BMallocIO();
|
||||||
|
ObjectDeleter<BMallocIO> outputDataDeleter(outputData);
|
||||||
|
BJsonTextWriter writer(outputData);
|
||||||
|
static char* expectedOut = JSON_SAMPLE_NUMBER_B_EXPECTED_OUT;
|
||||||
|
|
||||||
|
CPPUNIT_ASSERT_EQUAL(B_OK,
|
||||||
|
writer.WriteInteger(JSON_SAMPLE_NUMBER_B_LITERAL));
|
||||||
|
writer.Complete();
|
||||||
|
|
||||||
|
BString outputString((char *)outputData->Buffer(),
|
||||||
|
outputData->BufferLength());
|
||||||
|
fprintf(stderr, "expected out >%s<\n", expectedOut);
|
||||||
|
fprintf(stderr, "actual out >%s< (%" B_PRIuSIZE ")\n", outputString.String(),
|
||||||
|
outputData->BufferLength());
|
||||||
|
|
||||||
|
CPPUNIT_ASSERT_EQUAL(BString(expectedOut),
|
||||||
|
outputString);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
JsonTextWriterTest::TestDouble()
|
||||||
|
{
|
||||||
|
BMallocIO* outputData = new BMallocIO();
|
||||||
|
ObjectDeleter<BMallocIO> outputDataDeleter(outputData);
|
||||||
|
BJsonTextWriter writer(outputData);
|
||||||
|
static char* expectedOut = "3.142857";
|
||||||
|
|
||||||
|
CPPUNIT_ASSERT_EQUAL(B_OK,
|
||||||
|
writer.WriteDouble(JSON_SAMPLE_NUMBER_A_LITERAL));
|
||||||
|
writer.Complete();
|
||||||
|
|
||||||
|
BString outputString((char *)outputData->Buffer(),
|
||||||
|
outputData->BufferLength());
|
||||||
|
fprintf(stderr, "expected out >%s<\n", expectedOut);
|
||||||
|
fprintf(stderr, "actual out >%s< (%" B_PRIuSIZE ")\n", outputString.String(),
|
||||||
|
outputData->BufferLength());
|
||||||
|
|
||||||
|
CPPUNIT_ASSERT_EQUAL(BString(expectedOut),
|
||||||
|
outputString);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
JsonTextWriterTest::TestFalse()
|
||||||
|
{
|
||||||
|
BMallocIO* outputData = new BMallocIO();
|
||||||
|
ObjectDeleter<BMallocIO> outputDataDeleter(outputData);
|
||||||
|
BJsonTextWriter writer(outputData);
|
||||||
|
static char* expectedOut = "false";
|
||||||
|
|
||||||
|
CPPUNIT_ASSERT_EQUAL(B_OK, writer.WriteFalse());
|
||||||
|
writer.Complete();
|
||||||
|
|
||||||
|
BString outputString((char*)outputData->Buffer(),
|
||||||
|
outputData->BufferLength());
|
||||||
|
fprintf(stderr, "expected out >%s<\n", expectedOut);
|
||||||
|
fprintf(stderr, "actual out >%s< (%" B_PRIuSIZE ")\n",
|
||||||
|
outputString.String(), outputData->BufferLength());
|
||||||
|
|
||||||
|
CPPUNIT_ASSERT_EQUAL(BString(expectedOut),
|
||||||
|
outputString);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*static*/ void
|
||||||
|
JsonTextWriterTest::AddTests(BTestSuite& parent)
|
||||||
|
{
|
||||||
|
CppUnit::TestSuite& suite = *new CppUnit::TestSuite(
|
||||||
|
"JsonTextWriterTest");
|
||||||
|
|
||||||
|
suite.addTest(new CppUnit::TestCaller<JsonTextWriterTest>(
|
||||||
|
"JsonTextWriterTest::TestDouble",
|
||||||
|
&JsonTextWriterTest::TestDouble));
|
||||||
|
|
||||||
|
suite.addTest(new CppUnit::TestCaller<JsonTextWriterTest>(
|
||||||
|
"JsonTextWriterTest::TestInteger",
|
||||||
|
&JsonTextWriterTest::TestInteger));
|
||||||
|
|
||||||
|
suite.addTest(new CppUnit::TestCaller<JsonTextWriterTest>(
|
||||||
|
"JsonTextWriterTest::TestFalse",
|
||||||
|
&JsonTextWriterTest::TestFalse));
|
||||||
|
|
||||||
|
suite.addTest(new CppUnit::TestCaller<JsonTextWriterTest>(
|
||||||
|
"JsonTextWriterTest::TestArrayA",
|
||||||
|
&JsonTextWriterTest::TestArrayA));
|
||||||
|
|
||||||
|
suite.addTest(new CppUnit::TestCaller<JsonTextWriterTest>(
|
||||||
|
"JsonTextWriterTest::TestObjectA",
|
||||||
|
&JsonTextWriterTest::TestObjectA));
|
||||||
|
|
||||||
|
// suite.addTest(new CppUnit::TestCaller<JsonTextWriterTest>(
|
||||||
|
// "JsonTextWriterTest::TestObjectAForPerformance",
|
||||||
|
// &JsonTextWriterTest::TestObjectAForPerformance));
|
||||||
|
|
||||||
|
parent.addTest("JsonTextWriterTest", &suite);
|
||||||
|
}
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2017, Andrew Lindesay <apl@lindesay.co.nz>
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
#ifndef JSON_WRITER_TEST_H
|
||||||
|
#define JSON_WRITER_TEST_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <TestCase.h>
|
||||||
|
#include <TestSuite.h>
|
||||||
|
|
||||||
|
#include <DataIO.h>
|
||||||
|
|
||||||
|
class Sample;
|
||||||
|
|
||||||
|
|
||||||
|
class JsonTextWriterTest : public CppUnit::TestCase {
|
||||||
|
public:
|
||||||
|
JsonTextWriterTest();
|
||||||
|
virtual ~JsonTextWriterTest();
|
||||||
|
|
||||||
|
void TestArrayA();
|
||||||
|
void TestObjectA();
|
||||||
|
void TestObjectAForPerformance();
|
||||||
|
void TestDouble();
|
||||||
|
void TestInteger();
|
||||||
|
void TestFalse();
|
||||||
|
|
||||||
|
static void AddTests(BTestSuite& suite);
|
||||||
|
private:
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif // JSON_WRITER_TEST_H
|
||||||
@@ -0,0 +1,292 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2017, Andrew Lindesay <apl@lindesay.co.nz>
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
#include "JsonToMessageTest.h"
|
||||||
|
|
||||||
|
#include <Json.h>
|
||||||
|
|
||||||
|
#include <cppunit/TestCaller.h>
|
||||||
|
#include <cppunit/TestSuite.h>
|
||||||
|
|
||||||
|
#include "JsonSamples.h"
|
||||||
|
|
||||||
|
|
||||||
|
#define LOOPS_TEST_OBJECT_A_FOR_PERFORMANCE 100000
|
||||||
|
|
||||||
|
using namespace BPrivate;
|
||||||
|
|
||||||
|
|
||||||
|
JsonToMessageTest::JsonToMessageTest()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
JsonToMessageTest::~JsonToMessageTest()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
JsonToMessageTest::TestArrayA()
|
||||||
|
{
|
||||||
|
BMessage message;
|
||||||
|
BMessage subMessage;
|
||||||
|
BString stringValue;
|
||||||
|
double doubleValue;
|
||||||
|
|
||||||
|
// ----------------------
|
||||||
|
BJson::Parse(JSON_SAMPLE_ARRAY_A_IN, message);
|
||||||
|
// ----------------------
|
||||||
|
|
||||||
|
CPPUNIT_ASSERT_EQUAL_MESSAGE("!find [0]", B_OK,
|
||||||
|
message.FindString("0", &stringValue));
|
||||||
|
CPPUNIT_ASSERT_EQUAL_MESSAGE("!eq [0]", BString("1234"), stringValue);
|
||||||
|
|
||||||
|
CPPUNIT_ASSERT_EQUAL_MESSAGE("!find [1]", B_OK,
|
||||||
|
message.FindDouble("1", &doubleValue));
|
||||||
|
CPPUNIT_ASSERT_EQUAL_MESSAGE("!eq [1]", 4567, doubleValue);
|
||||||
|
|
||||||
|
CPPUNIT_ASSERT_EQUAL_MESSAGE("!find [2]", B_OK,
|
||||||
|
message.FindMessage("2", &subMessage));
|
||||||
|
|
||||||
|
CPPUNIT_ASSERT_EQUAL_MESSAGE("!find [2.0]", B_OK,
|
||||||
|
subMessage.FindString("0", &stringValue));
|
||||||
|
CPPUNIT_ASSERT_EQUAL_MESSAGE("!eq [2.0]", BString("A"), stringValue);
|
||||||
|
|
||||||
|
CPPUNIT_ASSERT_EQUAL_MESSAGE("!find [2.1]", B_OK,
|
||||||
|
subMessage.FindString("1", &stringValue));
|
||||||
|
CPPUNIT_ASSERT_EQUAL_MESSAGE("!eq [2.1]", BString("b"), stringValue);
|
||||||
|
|
||||||
|
CPPUNIT_ASSERT_EQUAL_MESSAGE("!find [2.2]", B_OK,
|
||||||
|
subMessage.FindString("2", &stringValue));
|
||||||
|
CPPUNIT_ASSERT_EQUAL_MESSAGE("!eq [2.2]", BString("C\xc3\xa9zanne"),
|
||||||
|
stringValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
JsonToMessageTest::TestArrayB()
|
||||||
|
{
|
||||||
|
BMessage message;
|
||||||
|
BMessage subMessage;
|
||||||
|
BMessage subSubMessage;
|
||||||
|
BString stringValue;
|
||||||
|
|
||||||
|
// ----------------------
|
||||||
|
BJson::Parse(JSON_SAMPLE_ARRAY_B_IN, message);
|
||||||
|
// ----------------------
|
||||||
|
|
||||||
|
CPPUNIT_ASSERT_EQUAL_MESSAGE("!find [0]", B_OK,
|
||||||
|
message.FindString("0", &stringValue));
|
||||||
|
CPPUNIT_ASSERT_EQUAL_MESSAGE("!eq [0]", BString("Whirinaki"), stringValue);
|
||||||
|
|
||||||
|
CPPUNIT_ASSERT_EQUAL_MESSAGE("!find [1]", B_OK,
|
||||||
|
message.FindString("1", &stringValue));
|
||||||
|
CPPUNIT_ASSERT_EQUAL_MESSAGE("!eq [1]", BString("Wellington"), stringValue);
|
||||||
|
|
||||||
|
CPPUNIT_ASSERT_EQUAL_MESSAGE("!find [2]", B_OK,
|
||||||
|
message.FindMessage("2", &subMessage));
|
||||||
|
|
||||||
|
CPPUNIT_ASSERT_EQUAL_MESSAGE("!find [2.0]", B_OK,
|
||||||
|
subMessage.FindMessage("key", &subSubMessage));
|
||||||
|
|
||||||
|
CPPUNIT_ASSERT_EQUAL_MESSAGE("!find [2.0.0]", B_OK,
|
||||||
|
subSubMessage.FindString("0", &stringValue));
|
||||||
|
CPPUNIT_ASSERT_EQUAL_MESSAGE("!eq [2.0.0]", BString("value"), stringValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
JsonToMessageTest::TestObjectA()
|
||||||
|
{
|
||||||
|
BMessage message;
|
||||||
|
BMessage subMessage;
|
||||||
|
BString stringValue;
|
||||||
|
|
||||||
|
// ----------------------
|
||||||
|
BJson::Parse(JSON_SAMPLE_OBJECT_A_IN, message);
|
||||||
|
// ----------------------
|
||||||
|
|
||||||
|
CPPUNIT_ASSERT_EQUAL(B_OK, message.FindString("weather", &stringValue));
|
||||||
|
CPPUNIT_ASSERT_EQUAL(BString("raining"), stringValue);
|
||||||
|
|
||||||
|
CPPUNIT_ASSERT_EQUAL(B_OK, message.FindString("humidity", &stringValue));
|
||||||
|
CPPUNIT_ASSERT_EQUAL(BString("too-high"), stringValue);
|
||||||
|
|
||||||
|
CPPUNIT_ASSERT_EQUAL(B_OK, message.FindMessage("daysOfWeek", &subMessage));
|
||||||
|
|
||||||
|
CPPUNIT_ASSERT_EQUAL(B_OK, subMessage.FindString("0", &stringValue));
|
||||||
|
CPPUNIT_ASSERT_EQUAL(BString("MON"), stringValue);
|
||||||
|
|
||||||
|
CPPUNIT_ASSERT_EQUAL(B_OK, subMessage.FindString("1", &stringValue));
|
||||||
|
CPPUNIT_ASSERT_EQUAL(BString("TUE"), stringValue);
|
||||||
|
|
||||||
|
CPPUNIT_ASSERT_EQUAL(B_OK, subMessage.FindString("2", &stringValue));
|
||||||
|
CPPUNIT_ASSERT_EQUAL(BString("WED"), stringValue);
|
||||||
|
|
||||||
|
CPPUNIT_ASSERT_EQUAL(B_OK, subMessage.FindString("3", &stringValue));
|
||||||
|
CPPUNIT_ASSERT_EQUAL(BString("THR"), stringValue);
|
||||||
|
|
||||||
|
CPPUNIT_ASSERT_EQUAL(B_OK, subMessage.FindString("4", &stringValue));
|
||||||
|
CPPUNIT_ASSERT_EQUAL(BString("FRI"), stringValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*! This is not a real test, but is a convenient point at which to implement a
|
||||||
|
performance test.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void
|
||||||
|
JsonToMessageTest::TestObjectAForPerformance()
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i=0; i < LOOPS_TEST_OBJECT_A_FOR_PERFORMANCE; i++)
|
||||||
|
TestObjectA();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
JsonToMessageTest::TestObjectB()
|
||||||
|
{
|
||||||
|
BMessage message;
|
||||||
|
bool boolValue;
|
||||||
|
void *ptrValue; // this is how NULL is represented.
|
||||||
|
|
||||||
|
// ----------------------
|
||||||
|
BJson::Parse(JSON_SAMPLE_OBJECT_B_IN, message);
|
||||||
|
// ----------------------
|
||||||
|
|
||||||
|
CPPUNIT_ASSERT_EQUAL(B_OK, message.FindBool("testTrue", &boolValue));
|
||||||
|
CPPUNIT_ASSERT_EQUAL(true, boolValue);
|
||||||
|
|
||||||
|
CPPUNIT_ASSERT_EQUAL(B_OK, message.FindBool("testFalse", &boolValue));
|
||||||
|
CPPUNIT_ASSERT_EQUAL(false, boolValue);
|
||||||
|
|
||||||
|
CPPUNIT_ASSERT_EQUAL(B_OK, message.FindPointer("testNull", &ptrValue));
|
||||||
|
CPPUNIT_ASSERT_EQUAL(0, (uint32) ptrValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
JsonToMessageTest::TestObjectC()
|
||||||
|
{
|
||||||
|
BMessage message;
|
||||||
|
BMessage subMessage;
|
||||||
|
BString stringValue;
|
||||||
|
|
||||||
|
// ----------------------
|
||||||
|
BJson::Parse(JSON_SAMPLE_OBJECT_C_IN, message);
|
||||||
|
// ----------------------
|
||||||
|
|
||||||
|
CPPUNIT_ASSERT_EQUAL(B_OK, message.FindString("key", &stringValue));
|
||||||
|
CPPUNIT_ASSERT_EQUAL(BString("value"), stringValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
JsonToMessageTest::TestUnterminatedObject()
|
||||||
|
{
|
||||||
|
BMessage message;
|
||||||
|
|
||||||
|
// ----------------------
|
||||||
|
status_t result = BJson::Parse(JSON_SAMPLE_BROKEN_UNTERMINATED_OBJECT,
|
||||||
|
message);
|
||||||
|
// ----------------------
|
||||||
|
|
||||||
|
CPPUNIT_ASSERT_EQUAL(B_BAD_DATA, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
JsonToMessageTest::TestUnterminatedArray()
|
||||||
|
{
|
||||||
|
BMessage message;
|
||||||
|
|
||||||
|
// ----------------------
|
||||||
|
status_t result = BJson::Parse(JSON_SAMPLE_BROKEN_UNTERMINATED_ARRAY,
|
||||||
|
message);
|
||||||
|
// ----------------------
|
||||||
|
|
||||||
|
CPPUNIT_ASSERT_EQUAL(B_BAD_DATA, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void JsonToMessageTest::TestHaikuDepotFetchBatch()
|
||||||
|
{
|
||||||
|
const unsigned char input[] = JSON_SAMPLE_HDS_FETCH_BATCH_PKGS;
|
||||||
|
BMessage message;
|
||||||
|
BMessage resultMessage;
|
||||||
|
BMessage pkgsMessage;
|
||||||
|
BMessage pkgMessage1;
|
||||||
|
double modifyTimestampDouble;
|
||||||
|
double expectedModifyTimestampDouble = 1488785331631.0;
|
||||||
|
|
||||||
|
// ----------------------
|
||||||
|
status_t result = BJson::Parse((char*)input,
|
||||||
|
message);
|
||||||
|
// ----------------------
|
||||||
|
|
||||||
|
CPPUNIT_ASSERT_EQUAL(B_OK, result);
|
||||||
|
|
||||||
|
// this is quite a large test input so a random sample "thing to
|
||||||
|
// check" is chosen to indicate that the parse was successful.
|
||||||
|
|
||||||
|
CPPUNIT_ASSERT_EQUAL_MESSAGE("result", B_OK,
|
||||||
|
message.FindMessage("result", &resultMessage));
|
||||||
|
CPPUNIT_ASSERT_EQUAL_MESSAGE("pkgs", B_OK,
|
||||||
|
resultMessage.FindMessage("pkgs", &pkgsMessage));
|
||||||
|
CPPUNIT_ASSERT_EQUAL_MESSAGE("1", B_OK,
|
||||||
|
pkgsMessage.FindMessage("1", &pkgMessage1));
|
||||||
|
CPPUNIT_ASSERT_EQUAL_MESSAGE("modifyTimestamp", B_OK,
|
||||||
|
pkgMessage1.FindDouble("modifyTimestamp", &modifyTimestampDouble));
|
||||||
|
|
||||||
|
CPPUNIT_ASSERT_EQUAL(expectedModifyTimestampDouble, modifyTimestampDouble);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*static*/ void
|
||||||
|
JsonToMessageTest::AddTests(BTestSuite& parent)
|
||||||
|
{
|
||||||
|
CppUnit::TestSuite& suite = *new CppUnit::TestSuite(
|
||||||
|
"JsonToMessageTest");
|
||||||
|
|
||||||
|
suite.addTest(new CppUnit::TestCaller<JsonToMessageTest>(
|
||||||
|
"JsonToMessageTest::TestArrayA",
|
||||||
|
&JsonToMessageTest::TestArrayA));
|
||||||
|
|
||||||
|
suite.addTest(new CppUnit::TestCaller<JsonToMessageTest>(
|
||||||
|
"JsonToMessageTest::TestArrayB",
|
||||||
|
&JsonToMessageTest::TestArrayB));
|
||||||
|
|
||||||
|
suite.addTest(new CppUnit::TestCaller<JsonToMessageTest>(
|
||||||
|
"JsonToMessageTest::TestObjectA",
|
||||||
|
&JsonToMessageTest::TestObjectA));
|
||||||
|
|
||||||
|
suite.addTest(new CppUnit::TestCaller<JsonToMessageTest>(
|
||||||
|
"JsonToMessageTest::TestObjectB",
|
||||||
|
&JsonToMessageTest::TestObjectB));
|
||||||
|
|
||||||
|
suite.addTest(new CppUnit::TestCaller<JsonToMessageTest>(
|
||||||
|
"JsonToMessageTest::TestObjectC",
|
||||||
|
&JsonToMessageTest::TestObjectC));
|
||||||
|
|
||||||
|
suite.addTest(new CppUnit::TestCaller<JsonToMessageTest>(
|
||||||
|
"JsonToMessageTest::TestUnterminatedObject",
|
||||||
|
&JsonToMessageTest::TestUnterminatedObject));
|
||||||
|
|
||||||
|
suite.addTest(new CppUnit::TestCaller<JsonToMessageTest>(
|
||||||
|
"JsonToMessageTest::TestUnterminatedArray",
|
||||||
|
&JsonToMessageTest::TestUnterminatedArray));
|
||||||
|
|
||||||
|
suite.addTest(new CppUnit::TestCaller<JsonToMessageTest>(
|
||||||
|
"JsonToMessageTest::TestHaikuDepotFetchBatch",
|
||||||
|
&JsonToMessageTest::TestHaikuDepotFetchBatch));
|
||||||
|
|
||||||
|
// suite.addTest(new CppUnit::TestCaller<JsonToMessageTest>(
|
||||||
|
// "JsonToMessageTest::TestObjectAForPerformance",
|
||||||
|
// &JsonToMessageTest::TestObjectAForPerformance));
|
||||||
|
|
||||||
|
parent.addTest("JsonToMessageTest", &suite);
|
||||||
|
}
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2017, Andrew Lindesay <apl@lindesay.co.nz>
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
#ifndef JSON_TO_MESSAGE_TEST_H
|
||||||
|
#define JSON_TO_MESSAGE_TEST_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <TestCase.h>
|
||||||
|
#include <TestSuite.h>
|
||||||
|
|
||||||
|
#include <DataIO.h>
|
||||||
|
|
||||||
|
class Sample;
|
||||||
|
|
||||||
|
|
||||||
|
class JsonToMessageTest : public CppUnit::TestCase {
|
||||||
|
public:
|
||||||
|
JsonToMessageTest();
|
||||||
|
virtual ~JsonToMessageTest();
|
||||||
|
|
||||||
|
void TestArrayA();
|
||||||
|
void TestArrayB();
|
||||||
|
void TestObjectAForPerformance();
|
||||||
|
void TestObjectA();
|
||||||
|
void TestObjectB();
|
||||||
|
void TestObjectC();
|
||||||
|
void TestUnterminatedObject();
|
||||||
|
void TestUnterminatedArray();
|
||||||
|
void TestHaikuDepotFetchBatch();
|
||||||
|
|
||||||
|
static void AddTests(BTestSuite& suite);
|
||||||
|
private:
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif // JSON_TO_MESSAGE_TEST_H
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
|
* Copyright 2017, Andrew Lindesay, apl@lindesay.co.nz
|
||||||
* Copyright 2012-2015, Axel Dörfler, axeld@pinc-software.de.
|
* Copyright 2012-2015, Axel Dörfler, axeld@pinc-software.de.
|
||||||
* Distributed under the terms of the MIT License.
|
* Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
@@ -11,6 +12,10 @@
|
|||||||
#include "DriverSettingsMessageAdapterTest.h"
|
#include "DriverSettingsMessageAdapterTest.h"
|
||||||
#include "GeolocationTest.h"
|
#include "GeolocationTest.h"
|
||||||
#include "NaturalCompareTest.h"
|
#include "NaturalCompareTest.h"
|
||||||
|
#include "JsonEndToEndTest.h"
|
||||||
|
#include "JsonErrorHandlingTest.h"
|
||||||
|
#include "JsonTextWriterTest.h"
|
||||||
|
#include "JsonToMessageTest.h"
|
||||||
|
|
||||||
|
|
||||||
BTestSuite*
|
BTestSuite*
|
||||||
@@ -22,6 +27,10 @@ getTestSuite()
|
|||||||
DriverSettingsMessageAdapterTest::AddTests(*suite);
|
DriverSettingsMessageAdapterTest::AddTests(*suite);
|
||||||
GeolocationTest::AddTests(*suite);
|
GeolocationTest::AddTests(*suite);
|
||||||
NaturalCompareTest::AddTests(*suite);
|
NaturalCompareTest::AddTests(*suite);
|
||||||
|
JsonEndToEndTest::AddTests(*suite);
|
||||||
|
JsonErrorHandlingTest::AddTests(*suite);
|
||||||
|
JsonTextWriterTest::AddTests(*suite);
|
||||||
|
JsonToMessageTest::AddTests(*suite);
|
||||||
|
|
||||||
return suite;
|
return suite;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user