|
|
|
// Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
|
|
|
|
// This source code is licensed under both the GPLv2 (found in the
|
|
|
|
// COPYING file in the root directory) and Apache 2.0 License
|
|
|
|
// (found in the LICENSE.Apache file in the root directory).
|
|
|
|
|
|
|
|
/*
|
|
|
|
* This header file defines miscellaneous utility classes.
|
|
|
|
*
|
|
|
|
* @author Tian Xia <tianx@fb.com>
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef FBSON_FBSONUTIL_H
|
|
|
|
#define FBSON_FBSONUTIL_H
|
|
|
|
|
|
|
|
#include <sstream>
|
|
|
|
#include "FbsonDocument.h"
|
|
|
|
|
|
|
|
namespace fbson {
|
|
|
|
|
|
|
|
#define OUT_BUF_SIZE 1024
|
|
|
|
|
|
|
|
/*
|
|
|
|
* FbsonToJson converts an FbsonValue object to a JSON string.
|
|
|
|
*/
|
|
|
|
class FbsonToJson {
|
|
|
|
public:
|
|
|
|
FbsonToJson() : os_(buffer_, OUT_BUF_SIZE) {}
|
|
|
|
|
|
|
|
// get json string
|
|
|
|
const char* json(const FbsonValue* pval) {
|
|
|
|
os_.clear();
|
|
|
|
os_.seekp(0);
|
|
|
|
|
|
|
|
if (pval) {
|
|
|
|
intern_json(pval);
|
|
|
|
}
|
|
|
|
|
|
|
|
os_.put(0);
|
|
|
|
return os_.getBuffer();
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
// recursively convert FbsonValue
|
|
|
|
void intern_json(const FbsonValue* val) {
|
|
|
|
switch (val->type()) {
|
|
|
|
case FbsonType::T_Null: {
|
|
|
|
os_.write("null", 4);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case FbsonType::T_True: {
|
|
|
|
os_.write("true", 4);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case FbsonType::T_False: {
|
|
|
|
os_.write("false", 5);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case FbsonType::T_Int8: {
|
|
|
|
os_.write(((Int8Val*)val)->val());
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case FbsonType::T_Int16: {
|
|
|
|
os_.write(((Int16Val*)val)->val());
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case FbsonType::T_Int32: {
|
|
|
|
os_.write(((Int32Val*)val)->val());
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case FbsonType::T_Int64: {
|
|
|
|
os_.write(((Int64Val*)val)->val());
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case FbsonType::T_Double: {
|
|
|
|
os_.write(((DoubleVal*)val)->val());
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case FbsonType::T_String: {
|
|
|
|
os_.put('"');
|
|
|
|
os_.write(((StringVal*)val)->getBlob(), ((StringVal*)val)->getBlobLen());
|
|
|
|
os_.put('"');
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case FbsonType::T_Binary: {
|
|
|
|
os_.write("\"<BINARY>", 9);
|
|
|
|
os_.write(((BinaryVal*)val)->getBlob(), ((BinaryVal*)val)->getBlobLen());
|
|
|
|
os_.write("<BINARY>\"", 9);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case FbsonType::T_Object: {
|
|
|
|
object_to_json((ObjectVal*)val);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case FbsonType::T_Array: {
|
|
|
|
array_to_json((ArrayVal*)val);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// convert object
|
|
|
|
void object_to_json(const ObjectVal* val) {
|
|
|
|
os_.put('{');
|
|
|
|
|
|
|
|
auto iter = val->begin();
|
|
|
|
auto iter_fence = val->end();
|
|
|
|
|
|
|
|
while (iter < iter_fence) {
|
|
|
|
// write key
|
|
|
|
if (iter->klen()) {
|
|
|
|
os_.put('"');
|
|
|
|
os_.write(iter->getKeyStr(), iter->klen());
|
|
|
|
os_.put('"');
|
|
|
|
} else {
|
|
|
|
os_.write(iter->getKeyId());
|
|
|
|
}
|
|
|
|
os_.put(':');
|
|
|
|
|
|
|
|
// convert value
|
|
|
|
intern_json(iter->value());
|
|
|
|
|
|
|
|
++iter;
|
|
|
|
if (iter != iter_fence) {
|
|
|
|
os_.put(',');
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
assert(iter == iter_fence);
|
|
|
|
|
|
|
|
os_.put('}');
|
|
|
|
}
|
|
|
|
|
|
|
|
// convert array to json
|
|
|
|
void array_to_json(const ArrayVal* val) {
|
|
|
|
os_.put('[');
|
|
|
|
|
|
|
|
auto iter = val->begin();
|
|
|
|
auto iter_fence = val->end();
|
|
|
|
|
|
|
|
while (iter != iter_fence) {
|
|
|
|
// convert value
|
|
|
|
intern_json((const FbsonValue*)iter);
|
|
|
|
++iter;
|
|
|
|
if (iter != iter_fence) {
|
|
|
|
os_.put(',');
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
assert(iter == iter_fence);
|
|
|
|
|
|
|
|
os_.put(']');
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
FbsonOutStream os_;
|
|
|
|
char buffer_[OUT_BUF_SIZE];
|
|
|
|
};
|
|
|
|
|
|
|
|
} // namespace fbson
|
|
|
|
|
|
|
|
#endif // FBSON_FBSONUTIL_H
|