/* * 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 #include #include #include #include #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 BsonWriter& convert(const char*key, const std::vector&data) { BsonWriter child(key, _bson, array); for (size_t i=0; i BsonWriter& convert(const char*key, const std::list&data) { BsonWriter child(key, _bson, array); size_t i = 0; for (typename std::list::const_iterator iter=data.begin(); iter!=data.end(); ++iter,++i) { child.convert(Util::tostr(i).c_str(), *iter); } return *this; } template BsonWriter& convert(const char*key, const std::set&data) { BsonWriter child(key, _bson, array); size_t i = 0; for (typename std::set::const_iterator iter=data.begin(); iter!=data.end(); ++iter,++i) { child.convert(Util::tostr(i).c_str(), *iter); } return *this; } template BsonWriter& convert(const char*key, const std::map&data) { if (_type!=top || key[0]!='\0') { BsonWriter child(key, _bson, doc); for (typename std::map::const_iterator iter=data.begin(); iter!=data.end(); ++iter) { child.convert(iter->first.c_str(), iter->second); } } else { for (typename std::map::const_iterator iter=data.begin(); iter!=data.end(); ++iter) { this->convert(iter->first.c_str(), iter->second); } } return *this; } template BsonWriter& convert(const char*key, const std::map &data) { if (_type!=top || key[0]!='\0') { BsonWriter child(key, _bson, doc); for (typename std::map::const_iterator iter=data.begin(); iter!=data.end(); ++iter) { child.convert(Util::tostr(iter->first).c_str(), iter->second); } } else { for (typename std::map::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 BsonWriter& convert(const char*key, const std::unordered_map&data) { if (_type!=top || key[0]!='\0') { BsonWriter child(key, _bson, doc); for (typename std::unordered_map::const_iterator iter=data.begin(); iter!=data.end(); ++iter) { child.convert(iter->first.c_str(), iter->second); } } else { for (typename std::unordered_map::const_iterator iter=data.begin(); iter!=data.end(); ++iter) { this->convert(iter->first.c_str(), iter->second); } } return *this; } // shared_ptr template BsonWriter& convert(const char*key, const std::shared_ptr& val) { if (NULL == val.get()) { return *this; } return this->convert(key, *val); } // class/struct that not defined macro XTOSTRUCT template ::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 ::value, int>::type = 0> BsonWriter& convert(const char*key, const T& data) { #else template 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 void convert(const char*key, const XType& data) { data.__struct_to_str(*this, key); } private: mutable _bson_t* _parent; mutable _bson_t* _bson; int _type; }; } #endif