eis/inc/x2struct/bson_writer.h

269 lines
8.5 KiB
C++

/*
* Copyright (C) 2019 YY Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __X_BSON_WRITER_H
#define __X_BSON_WRITER_H
#include "xstdint.h"
#include <string>
#include <map>
#include <vector>
#include <list>
#include <set>
#include "thirdparty/libbson/include/libbson-1.0/bson.h"
#include "util.h"
#include "xtypes.h"
#include "traits.h"
struct _bson_t;
namespace x2struct {
class BsonWriter {
enum {
top,
doc,
array
};
public:
BsonWriter(const char*key="", _bson_t*parent=0, int type=top) {
_parent = parent;
_bson = new bson_t;
_type = type;
if (0 != parent) {
if (type == doc) {
bson_append_document_begin(parent, key, strlen(key), _bson);
} else {
bson_append_array_begin(parent, key, strlen(key), _bson);
}
} else {
bson_init(_bson);
}
}
BsonWriter(const BsonWriter&bs) {
*this = bs;
bs._parent = 0;
bs._bson = 0;
}
~BsonWriter() {
if (0 != _bson) {
if (_type == doc) {
bson_append_document_end(_parent, _bson);
} else if (_type == array) {
bson_append_array_end(_parent, _bson);
} else {
bson_destroy(_bson);
}
delete _bson;
}
}
public:
std::string toStr() const {
return std::string((const char*)bson_get_data(_bson), _bson->len);
}
std::string json() const {
size_t len;
char *jstr = bson_as_json(_bson, &len);
std::string ret(jstr);
bson_free(jstr);
return ret;
}
const std::string&type() {
static std::string t("bson");
return t;
}
BsonWriter& convert(const char*key, const BsonWriter& data){
bson_append_document(_bson, key, strlen(key), data._bson);
return *this;
}
BsonWriter& convert(const char*key, const char* data) {
std::string d(data);
return convert(key, d);
}
BsonWriter& convert(const char*key, const std::string& data) {
bson_append_utf8(_bson, key, strlen(key), (const char*)data.data(), data.length());
return *this;
}
BsonWriter& convert(const char*key, int16_t data) {
bson_append_int32(_bson, key, strlen(key), (int32_t)data);
return *this;
}
BsonWriter& convert(const char*key, uint16_t data) {
bson_append_int32(_bson, key, strlen(key), (int32_t)data);
return *this;
}
BsonWriter& convert(const char*key, int32_t data) {
bson_append_int32(_bson, key, strlen(key), (int32_t)data);
return *this;
}
BsonWriter& convert(const char*key, uint32_t data) {
bson_append_int32(_bson, key, strlen(key), (int32_t)data);
return *this;
}
BsonWriter& convert(const char*key, int64_t data) {
bson_append_int64(_bson, key, strlen(key), (int64_t)data);
return *this;
}
BsonWriter& convert(const char*key, uint64_t data) {
bson_append_int64(_bson, key, strlen(key), (int64_t)data);
return *this;
}
BsonWriter& convert(const char*key, float data) {
bson_append_double(_bson, key, strlen(key), (double)data);
return *this;
}
BsonWriter& convert(const char*key, double data) {
bson_append_double(_bson, key, strlen(key), (double)data);
return *this;
}
BsonWriter& convert(const char*key, bool data) {
bson_append_bool(_bson, key, strlen(key), data);
return *this;
}
template<typename T>
BsonWriter& convert(const char*key, const std::vector<T>&data) {
BsonWriter child(key, _bson, array);
for (size_t i=0; i<data.size(); ++i) {
child.convert(Util::tostr(i).c_str(), data[i]);
}
return *this;
}
template<typename T>
BsonWriter& convert(const char*key, const std::list<T>&data) {
BsonWriter child(key, _bson, array);
size_t i = 0;
for (typename std::list<T>::const_iterator iter=data.begin(); iter!=data.end(); ++iter,++i) {
child.convert(Util::tostr(i).c_str(), *iter);
}
return *this;
}
template<typename T>
BsonWriter& convert(const char*key, const std::set<T>&data) {
BsonWriter child(key, _bson, array);
size_t i = 0;
for (typename std::set<T>::const_iterator iter=data.begin(); iter!=data.end(); ++iter,++i) {
child.convert(Util::tostr(i).c_str(), *iter);
}
return *this;
}
template<typename T>
BsonWriter& convert(const char*key, const std::map<std::string, T>&data) {
if (_type!=top || key[0]!='\0') {
BsonWriter child(key, _bson, doc);
for (typename std::map<std::string, T>::const_iterator iter=data.begin(); iter!=data.end(); ++iter) {
child.convert(iter->first.c_str(), iter->second);
}
} else {
for (typename std::map<std::string, T>::const_iterator iter=data.begin(); iter!=data.end(); ++iter) {
this->convert(iter->first.c_str(), iter->second);
}
}
return *this;
}
template <typename K, typename T>
BsonWriter& convert(const char*key, const std::map<K, T> &data) {
if (_type!=top || key[0]!='\0') {
BsonWriter child(key, _bson, doc);
for (typename std::map<K, T>::const_iterator iter=data.begin(); iter!=data.end(); ++iter) {
child.convert(Util::tostr(iter->first).c_str(), iter->second);
}
} else {
for (typename std::map<K, T>::const_iterator iter=data.begin(); iter!=data.end(); ++iter) {
this->convert(Util::tostr(iter->first).c_str(), iter->second);
}
}
return *this;
}
#ifdef X_SUPPORT_C0X
// unordered_map
template<typename T>
BsonWriter& convert(const char*key, const std::unordered_map<std::string, T>&data) {
if (_type!=top || key[0]!='\0') {
BsonWriter child(key, _bson, doc);
for (typename std::unordered_map<std::string, T>::const_iterator iter=data.begin(); iter!=data.end(); ++iter) {
child.convert(iter->first.c_str(), iter->second);
}
} else {
for (typename std::unordered_map<std::string, T>::const_iterator iter=data.begin(); iter!=data.end(); ++iter) {
this->convert(iter->first.c_str(), iter->second);
}
}
return *this;
}
// shared_ptr
template <typename TYPE>
BsonWriter& convert(const char*key, const std::shared_ptr<TYPE>& val) {
if (NULL == val.get()) {
return *this;
}
return this->convert(key, *val);
}
// class/struct that not defined macro XTOSTRUCT
template <typename T, typename std::enable_if<!x_has_x2struct<T>::value, int>::type = 0>
BsonWriter& convert(const char*key, const T& data, x_for_class(T, int) *unused=0) {
(void)unused;
if (_type!=top || key[0]!='\0') {
BsonWriter child(key, _bson, doc);
x_struct_to_str(child, "", data);
} else {
x_struct_to_str(*this, "", data);
}
return *this;
}
// class/struct that defined macro XTOSTRUCT
template <typename T, typename std::enable_if<x_has_x2struct<T>::value, int>::type = 0>
BsonWriter& convert(const char*key, const T& data) {
#else
template <typename T>
BsonWriter& convert(const char*key, const T& data, x_for_class(T, int) *p=0) {
(void)p;
#endif
if (_type!=top || key[0]!='\0') {
BsonWriter child(key, _bson, doc);
data.__struct_to_str(child, "");
} else {
data.__struct_to_str(*this, "");
}
return *this;
}
template <typename T>
void convert(const char*key, const XType<T>& data) {
data.__struct_to_str(*this, key);
}
private:
mutable _bson_t* _parent;
mutable _bson_t* _bson;
int _type;
};
}
#endif