├── .gitignore ├── LICENSE ├── README-bson.md ├── README-en.md ├── README.md ├── bson.h ├── bson_builder.h ├── bson_decoder.h ├── bson_encoder.h ├── bson_type.h ├── config.h ├── example ├── alias.cpp ├── bitfield.cpp ├── char_array.cpp ├── custom.cpp ├── encoder.cpp ├── enum.cpp ├── inherit.cpp ├── json-data.cpp ├── makefile ├── msvc.make ├── my_decoder.cpp ├── mysql.cpp ├── sharedptr.cpp ├── sqlite.cpp ├── union1.cpp ├── xml-content.cpp ├── xml.cpp ├── xpack_out.cpp ├── xtype.cpp ├── xtype_advance.cpp └── yaml.cpp ├── extend.h ├── gtest ├── bson_test.cpp ├── gtest_stub.h ├── makefile ├── msvc.make └── test.cpp ├── json.h ├── json_data.h ├── json_decoder.h ├── json_encoder.h ├── l1l2_expand.h ├── mysql.h ├── mysql_decoder.h ├── numeric.h ├── rapidjson ├── allocators.h ├── cursorstreamwrapper.h ├── document.h ├── encodedstream.h ├── encodings.h ├── error │ ├── en.h │ └── error.h ├── filereadstream.h ├── filewritestream.h ├── fwd.h ├── internal │ ├── biginteger.h │ ├── diyfp.h │ ├── dtoa.h │ ├── ieee754.h │ ├── itoa.h │ ├── meta.h │ ├── pow10.h │ ├── regex.h │ ├── stack.h │ ├── strfunc.h │ ├── strtod.h │ └── swap.h ├── istreamwrapper.h ├── memorybuffer.h ├── memorystream.h ├── msinttypes │ ├── inttypes.h │ └── stdint.h ├── ostreamwrapper.h ├── pointer.h ├── prettywriter.h ├── rapidjson.h ├── reader.h ├── schema.h ├── stream.h ├── stringbuffer.h └── writer.h ├── rapidjson_custom.h ├── rapidxml ├── license.txt ├── manual.html ├── rapidxml.hpp ├── rapidxml_iterators.hpp ├── rapidxml_print.hpp └── rapidxml_utils.hpp ├── sqlite.h ├── sqlite_decoder.h ├── traits.h ├── util.h ├── xdecoder.h ├── xencoder.h ├── xml.h ├── xml_decoder.h ├── xml_encoder.h ├── xpack.h ├── xpack.pri ├── yaml.h ├── yaml_decoder.h └── yaml_encoder.h /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | mytest 3 | */vgcore* 4 | example/*.json 5 | example/*.db 6 | example/*.yml 7 | example/core 8 | example/mysql 9 | example/sqlite 10 | -------------------------------------------------------------------------------- /README-bson.md: -------------------------------------------------------------------------------- 1 | * 用于在C++结构体和bson之间互相转换 2 | * 这个库可以配合[mongoxclient](https://github.com/xyz347/mongoxclient)使用 3 | 4 | # 目录 5 | - [encoder](#encoder) 6 | - [decoder](#decoder) 7 | - [bson types](#bsontypes) 8 | - [builder](#builder) 9 | - [重要说明](#重要说明) 10 | 11 | ## encoder 12 | 用于将结构体转成bson格式。范例: 13 | ```C++ 14 | struct Test { 15 | int64_t id; 16 | std::string name; 17 | std::string email; 18 | XPACK(A(id, "bson:_id"), O(name, email)); 19 | }; 20 | 21 | Test t; 22 | std::string data = xpack::bson::encode(t); // data就是t转成bson的数据 23 | ``` 24 | 25 | ## decoder 26 | 用于将bson数据转成结构体 27 | 用于将结构体转成bson格式。范例: 28 | ```C++ 29 | struct Test { 30 | int64_t id; 31 | std::string name; 32 | std::string email; 33 | XPACK(A(id, "bson:_id"), O(name, email)); 34 | }; 35 | 36 | std::string data; 37 | // data = xxxx; data存储了相应的bson数据 38 | Test t; 39 | xpack::bson::decode(data, t); 40 | // xpack::bson::decode 还有另一个参数方式:static void decode(const uint8_t* data, size_t len, T &val) 41 | ``` 42 | 43 | ## bsontypes 44 | - date time: `bson_date_time_t` 45 | - timestamp: `bson_timestamp_t` 46 | - binary: `bson_binary_t` 47 | - regex: `bson_regex_t` 48 | - oid: `bson_oid_t` 49 | - decimal128: `bson_decimal128_t` 50 | 51 | 前4种是xbson额外定义的,后面两种是定义在libbson内的,为了统一,前4种也是定义在全局命名空间。 52 | 53 | ## builder 54 | **需要C++11或以上版本支持**。用json的格式来构造bson数据。查询接口中的query,一般只需要指定很少几个字段,这个场景用结构体表达不是很方便。用builder就会简单很多。基本用法是: 55 | 1. 定义一个BsonBuilder: 56 | - 参数是一个json格式的字符串 57 | - 里面的双引号用单引号替代 58 | - 变量用问号作为占位符,问号后面可以加一个单词用来作为助记符,比如"?"和"?uid"是等效的 59 | - key也可以是变量,key作为变量,问号不用加引号 60 | - BsonBuilder是线程安全的,建议定义为static变量,这样json字符串只需解析一次 61 | 范例: 62 | ```C++ 63 | static xpack::BsonBuilder bd("{'_id':?, ?:?}"); // 带占位符的builder 64 | static xpack::BsonBuilder empty("{}"); // 空bson 65 | static xpack::BsonBuilder student("{'type':'student'}"); // 不带占位符的builder 66 | ``` 67 | 68 | 2. 调用Encode函数来构造bson数据,Encode的参数对应的是各个占位符,因此参数个数应该和占位符一致 69 | 比如对于上述的BsonBuilder 70 | ```C++ 71 | std::string data1 = bd.Encode(12345, "type", "master"); 72 | std::string data2 = empty.Encode(); 73 | std::string data3 = student.Encode(); 74 | // 这些bson的数据可以用在mongoxclient的各个接口中 75 | ``` 76 | 77 | 3. 其他的一些API 78 | - EncodeAsJson 和Encode类似,但是输出的是json格式的数据,可以用于调试等场景(所以这个其实也是个JsonBuilder) 79 | - Error 如果构造BsonBuilder的json字符串有误,这个接口可以返回错误信息 80 | - static std::string En(const std::string&fmt, Args... args)。这个是把构造BsonBuilder和Encode合在一起了,不是很建议使用,建议用于调试,因为每次都要构造一次BsonBuilder 81 | 82 | 83 | ## 重要说明 84 | - 依赖于[libbson](https://github.com/mongodb/libbson/tree/1.0.0),需自行安装 85 | -------------------------------------------------------------------------------- /bson.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2021 Duowan Inc. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, 11 | * software distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #ifndef __X_PACK_BSON_H 18 | #define __X_PACK_BSON_H 19 | 20 | #include "bson_decoder.h" 21 | #include "bson_encoder.h" 22 | #include "xpack.h" 23 | 24 | #ifdef X_PACK_SUPPORT_CXX0X // support c++11 or later 25 | #include "bson_builder.h" 26 | #endif 27 | 28 | 29 | namespace xpack { 30 | 31 | class bson { 32 | public: 33 | template 34 | static void decode(const std::string &data, T &val) { 35 | BsonDecoder de; 36 | de.decode(data, val); 37 | } 38 | 39 | template 40 | static void decode(const uint8_t* data, size_t len, T &val) { 41 | BsonDecoder de; 42 | de.decode(data, len, val); 43 | } 44 | 45 | template 46 | static std::string encode(const T &val) { 47 | BsonEncoder en; 48 | return en.encode(val); 49 | } 50 | }; 51 | 52 | } 53 | 54 | #endif 55 | -------------------------------------------------------------------------------- /bson_decoder.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2021 Duowan Inc. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, 11 | * software distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #ifndef __X_PACK_BSON_DECODER_H 18 | #define __X_PACK_BSON_DECODER_H 19 | 20 | #include 21 | #include 22 | 23 | #include "util.h" 24 | #include "xdecoder.h" 25 | #include "bson_type.h" 26 | 27 | namespace xpack { 28 | 29 | 30 | class BsonNode { 31 | typedef XDecoder decoder; 32 | friend class BsonDecoder; 33 | public: 34 | typedef size_t Iterator; 35 | 36 | BsonNode(const bson_iter_t* iter = NULL):it(iter),inited(false) { 37 | if (NULL != it) { 38 | type = bson_iter_type(it); 39 | } 40 | } 41 | 42 | inline static const char * Name() { 43 | return "bson"; 44 | } 45 | operator bool () const { 46 | return it != NULL; 47 | } 48 | bool IsNull() const { 49 | return NULL!=it && BSON_TYPE_NULL==bson_iter_type(it); 50 | } 51 | BsonNode Find(decoder&de, const char*key, const Extend *ext) { 52 | (void)de; 53 | (void)ext; 54 | 55 | if (!inited) { 56 | this->init(); 57 | } 58 | 59 | if (BSON_TYPE_DOCUMENT != type) { 60 | de.decode_exception("not document", NULL); 61 | } 62 | 63 | node_index::iterator iter = _childs_index.find(key); 64 | if (iter != _childs_index.end()) { 65 | return BsonNode(&_childs[iter->second]); 66 | } else { 67 | return BsonNode(); 68 | } 69 | } 70 | size_t Size(decoder&de) { 71 | (void)de; 72 | if (!inited) { 73 | this->init(); 74 | } 75 | 76 | if (BSON_TYPE_ARRAY == type) { 77 | return _childs.size(); 78 | } else { 79 | de.decode_exception("not array", NULL); 80 | return 0; 81 | } 82 | } 83 | BsonNode At(size_t index) const { // no exception 84 | return BsonNode(&(_childs[index])); 85 | } 86 | BsonNode Next(decoder&de, BsonNode&p, Iterator&iter, std::string&key) { 87 | (void)de; 88 | if (!p.inited) { 89 | p.init(); 90 | } 91 | if (BSON_TYPE_DOCUMENT != p.type) { 92 | de.decode_exception("not document", NULL); 93 | } 94 | 95 | if (it != p.it) { 96 | ++iter; 97 | } else { 98 | iter = 0; 99 | } 100 | 101 | if (iter != p._childs.size()) { 102 | bson_iter_t *t = &p._childs[iter]; 103 | key = bson_iter_key(t); 104 | return BsonNode(t); 105 | } 106 | 107 | return BsonNode(); 108 | } 109 | 110 | bool Get(decoder&de, std::string&val, const Extend*ext) { 111 | (void)ext; 112 | 113 | if (BSON_TYPE_UTF8 == type) { 114 | uint32_t length; 115 | const char* data = bson_iter_utf8(it, &length); 116 | if (NULL != data) { 117 | val = std::string(data, length); 118 | } 119 | } else if (BSON_TYPE_NULL != type) { 120 | de.decode_exception("not string", NULL); 121 | } 122 | return true; 123 | } 124 | bool Get(decoder&de, bool &val, const Extend*ext) { 125 | (void)de; 126 | (void)ext; 127 | val = bson_iter_as_bool(it); 128 | return true; 129 | } 130 | template 131 | typename x_enable_if::is_integer, bool>::type Get(decoder&de, T &val, const Extend*ext){ 132 | (void)de; 133 | (void)ext; 134 | val = (T)bson_iter_as_int64(it); 135 | return true; 136 | } 137 | template 138 | typename x_enable_if::is_float, bool>::type Get(decoder&de, T &val, const Extend*ext){ 139 | (void)de; 140 | (void)ext; 141 | val = (T)bson_iter_double(it); 142 | return true; 143 | } 144 | 145 | /*std::string json() const { 146 | if (NULL == _data) { 147 | return ""; 148 | } 149 | size_t length=BSON_UINT32_TO_LE(*(int32_t*)_data); 150 | bson_t b; // local is ok 151 | bson_init_static(&b, _data, length); 152 | 153 | size_t s; 154 | char *jstr = bson_as_json(&b, &s); 155 | if (jstr) { 156 | std::string j(jstr); 157 | bson_free(jstr); 158 | return j; 159 | } else { 160 | return ""; 161 | } 162 | }*/ 163 | 164 | // bson type 165 | bool decode_type_spec(bson_oid_t &val, const Extend *ext) { 166 | (void)ext; 167 | const bson_oid_t *t = bson_iter_oid(it); 168 | if (t != NULL) { 169 | bson_oid_init_from_data(&val, t->bytes); 170 | return true; 171 | } else { 172 | return false; 173 | } 174 | } 175 | bool decode_type_spec(bson_date_time_t &val, const Extend *ext) { 176 | (void)ext; 177 | val.ts = bson_iter_date_time(it); 178 | return true; 179 | } 180 | bool decode_type_spec(bson_timestamp_t &val, const Extend *ext) { 181 | (void)ext; 182 | bson_iter_timestamp(it, &val.timestamp, &val.increment); 183 | return true; 184 | } 185 | bool decode_type_spec(bson_decimal128_t &val, const Extend *ext) { 186 | (void)ext; 187 | return bson_iter_decimal128(it, &val); 188 | } 189 | bool decode_type_spec(bson_regex_t &val, const Extend *ext) { 190 | (void)ext; 191 | const char *options = NULL; 192 | const char *regex = bson_iter_regex(it, &options); 193 | if (NULL != regex) { 194 | val.pattern = regex; 195 | } 196 | if (NULL != options) { 197 | val.options = options; 198 | } 199 | return true; 200 | } 201 | bool decode_type_spec(bson_binary_t &val, const Extend *ext) { 202 | (void)ext; 203 | uint32_t len = 0; 204 | const uint8_t *data = NULL; 205 | bson_iter_binary(it, &val.subType, &len, &data); 206 | if (data != NULL && len > 0) { 207 | val.data = std::string((const char*)data, size_t(len)); 208 | } 209 | return true; 210 | } 211 | 212 | 213 | private: 214 | typedef std::map node_index; // index of _childs 215 | 216 | // get object or array info 217 | void init(bool top = false) { 218 | inited = true; 219 | 220 | bson_iter_t sub; 221 | if (NULL != it) { 222 | if (top) { 223 | type = BSON_TYPE_DOCUMENT; 224 | memcpy((void*)&sub, (void*)it, sizeof(sub)); 225 | } else if (!bson_iter_recurse(it, &sub)) { 226 | return; 227 | } 228 | 229 | size_t i = 0; 230 | while (bson_iter_next(&sub)) { 231 | _childs.push_back(sub); 232 | if (type == BSON_TYPE_DOCUMENT) { 233 | _childs_index[bson_iter_key(&sub)] = i++; 234 | } 235 | } 236 | } 237 | } 238 | 239 | const bson_iter_t* it; 240 | bson_type_t type; 241 | bool inited; 242 | std::vector _childs; // childs 243 | node_index _childs_index; 244 | }; 245 | 246 | 247 | class BsonDecoder { 248 | public: 249 | // if length==0, length will get from data 250 | template 251 | bool decode(const uint8_t*data, size_t length, T&val) { 252 | length = (length>0)?length:BSON_UINT32_TO_LE(*(int32_t*)data); 253 | 254 | bson_t b; 255 | bson_iter_t it; 256 | bson_init_static(&b, data, length); 257 | bson_iter_init(&it, &b); 258 | 259 | BsonNode node(&it); 260 | node.init(true); 261 | return XDecoder(NULL, (const char*)NULL, node).decode(val, NULL); 262 | } 263 | 264 | template 265 | bool decode(const std::string&data, T&val) { 266 | return decode((const uint8_t*)data.data(), data.length(), val); 267 | } 268 | }; 269 | 270 | template<>struct is_xpack_type_spec {static bool const value = true;}; 271 | template<>struct is_xpack_type_spec {static bool const value = true;}; 272 | template<>struct is_xpack_type_spec {static bool const value = true;}; 273 | template<>struct is_xpack_type_spec {static bool const value = true;}; 274 | template<>struct is_xpack_type_spec {static bool const value = true;}; 275 | template<>struct is_xpack_type_spec {static bool const value = true;}; 276 | 277 | } 278 | 279 | #endif 280 | -------------------------------------------------------------------------------- /config.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2021 Duowan Inc. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, 11 | * software distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | 18 | #ifndef __X_PACK_CONFIG_H 19 | #define __X_PACK_CONFIG_H 20 | 21 | // support qt 22 | //#define XPACK_SUPPORT_QT 23 | 24 | 25 | #endif 26 | -------------------------------------------------------------------------------- /example/alias.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "xpack/json.h" 3 | #include "xpack/xml.h" 4 | 5 | using namespace std; 6 | 7 | struct Test { 8 | long uid; 9 | string name; 10 | XPACK(A(uid, "id xml:xid"), O(name)); // xml use 'xid' and others use 'id' 11 | }; 12 | 13 | int main() { 14 | Test t; 15 | string json="{\"id\":123, \"name\":\"Pony\"}"; 16 | 17 | xpack::json::decode(json, t); 18 | cout< 2 | #include "xpack/json.h" 3 | #include "xpack/xml.h" 4 | 5 | using namespace std; 6 | 7 | struct Test { 8 | short ver:8; 9 | short len:8; 10 | string name; 11 | XPACK(B(F(0), ver, len), O(name)); 12 | }; 13 | 14 | int main() { 15 | Test t; 16 | string json="{\"ver\":4, \"len\":20, \"name\":\"IPv4\"}"; 17 | 18 | xpack::json::decode(json, t); 19 | cout< 18 | #include "xpack/json.h" 19 | 20 | using namespace std; 21 | 22 | 23 | struct Test { 24 | char name[64]; 25 | char email[64]; 26 | XPACK(O(name, email)); 27 | }; 28 | 29 | int main(int argc, char *argv[]) { 30 | (void)argc; 31 | (void)argv; 32 | 33 | Test t; 34 | string json="{\"name\":\"Pony\", \"email\":\"pony@xpack.com\"}"; 35 | 36 | xpack::json::decode(json, t); 37 | cout< 18 | #include 19 | #include "xpack/json.h" 20 | 21 | using namespace std; 22 | 23 | struct Test { 24 | unsigned int uid; 25 | string name; 26 | XPACK(C(hexint, F(0), uid), O(name)); 27 | }; 28 | 29 | namespace xpack { 30 | 31 | template 32 | bool hexint_decode(Decoder&de, Test&t, const char *name, unsigned int&data, const xpack::Extend *ext) { 33 | (void)t; 34 | string raw; 35 | bool ret = de.decode(name, raw, ext); 36 | if (ret) { 37 | sscanf(raw.c_str(), "%x", &data); 38 | } 39 | return ret; 40 | } 41 | 42 | template 43 | bool hexint_encode(Encoder&en, const Test&t, const char *name, const unsigned &data, const xpack::Extend *ext) { 44 | (void)t; 45 | char buf[64]; 46 | sprintf(buf, "%x", data); 47 | bool ret = en.encode(name, buf, ext); 48 | return ret; 49 | } 50 | } 51 | 52 | int main(int argc, char *argv[]) { 53 | (void)argc; 54 | (void)argv; 55 | Test t; 56 | t.uid = 127; 57 | t.name = "PonyJack"; 58 | 59 | string str = xpack::json::encode(t); 60 | cout< 18 | #include "xpack/json.h" 19 | #include "xpack/xml.h" 20 | 21 | using namespace std; 22 | 23 | int main(int argc, char *argv[]) { 24 | (void)argc; 25 | (void)argv; 26 | 27 | vector vi(3); 28 | vi[0] = 1; 29 | vi[1] = 2; 30 | vi[2] = 3; 31 | 32 | xpack::JsonWriter jw; 33 | xpack::XEncoder je(jw); 34 | 35 | xpack::XmlWriter xw; 36 | xpack::XEncoder xe(xw); 37 | 38 | je.ob(NULL).add("vv", vi).add("i",10).add("s","hello").oe(); 39 | xe.ob("root").add("vv", vi).add("i",10).add("s","hello").oe(); 40 | 41 | cout< 18 | #include "xpack/json.h" 19 | 20 | using namespace std; 21 | 22 | enum Enum { 23 | X = 0, 24 | Y = 1, 25 | Z = 2, 26 | }; 27 | 28 | enum class Enum1 { 29 | X = 0, 30 | Y = 1, 31 | Z = 2, 32 | }; 33 | 34 | enum class Enum2:int64_t { 35 | X = 0, 36 | Y = 1, 37 | Z = 2, 38 | }; 39 | 40 | struct Test { 41 | string name; 42 | Enum e; 43 | Enum1 e1; 44 | Enum2 e2; 45 | XPACK(O(name), E(F(0), e), O(e1, e2)); 46 | }; 47 | 48 | int main(int argc, char *argv[]) { 49 | (void)argc; 50 | (void)argv; 51 | 52 | Test t; 53 | string json="{\"name\":\"IPv4\", \"e\":1, \"e1\":2, \"e2\":2}"; 54 | 55 | xpack::json::decode(json, t); 56 | cout< 18 | #include "xpack/json.h" 19 | 20 | using namespace std; 21 | 22 | struct P1 { 23 | string mail; 24 | XPACK(O(mail)); 25 | }; 26 | 27 | struct P2 { 28 | long version; 29 | XPACK(O(version)); 30 | }; 31 | 32 | struct Test:public P1, public P2 { 33 | long uid; 34 | string name; 35 | XPACK(I(P1, P2), A(uid, "id"), O(name)); 36 | }; 37 | 38 | struct Pa { 39 | string mail; 40 | XPACK(O(mail)); 41 | }; 42 | 43 | struct Pb: public Pa { 44 | long version; 45 | XPACK(I(Pa), O(version)); 46 | }; 47 | 48 | struct Pc:public Pb { 49 | long uid; 50 | string name; 51 | XPACK(I(Pb), A(uid, "id"), O(name)); 52 | }; 53 | 54 | int main(int argc, char *argv[]) { 55 | (void)argc; 56 | (void)argv; 57 | 58 | Test t; 59 | string json="{\"mail\":\"pony@xpack.com\", \"version\":2019, \"id\":123, \"name\":\"Pony\"}"; 60 | 61 | xpack::json::decode(json, t); 62 | cout< 18 | #include "xpack/json.h" 19 | 20 | using namespace std; 21 | 22 | struct Example { 23 | string type; 24 | xpack::JsonData data; 25 | XPACK(O(type, data)); 26 | }; 27 | 28 | struct Range { 29 | int min; 30 | int max; 31 | XPACK(O(min, max)); 32 | }; 33 | 34 | struct User { 35 | int id; 36 | string name; 37 | XPACK(O(id, name)); 38 | }; 39 | 40 | static void test(const std::string &data) { 41 | Example e; 42 | xpack::json::decode(data, e); 43 | if (e.type == "range") { 44 | Range r; 45 | e.data.Get(r); 46 | cout<<"min in r:"<()<()<()<()< 2 | #include 3 | #include "xpack/json.h" 4 | 5 | using namespace std; 6 | 7 | 8 | // assign value by name 9 | class AssignDecoder { 10 | public: 11 | AssignDecoder(const std::vector&vs, const unsigned char *src, unsigned char *dst) { 12 | for (size_t i=0; isrc = src; 16 | this->dst = dst; 17 | } 18 | 19 | // decoder need implemetion decode function 20 | template 21 | bool decode(const char *key, T&val, const xpack::Extend *ext) { 22 | (void)ext; 23 | // set value by offset 24 | if (fields.end() != fields.find(key)) { 25 | unsigned int offset = (unsigned int)((unsigned char*)&val - dst); 26 | val = *((T*)(src+offset)); 27 | } 28 | return true; 29 | } 30 | private: 31 | std::set fields; 32 | const unsigned char *src; 33 | unsigned char *dst; 34 | }; 35 | 36 | // SetFields(src, dst, "a,b") means dst.a = src.a; dst.b = src.b; 37 | template 38 | void SetFields(const T&src, T&dst, const std::string&fields) { 39 | std::vector vs; 40 | xpack::Util::split(vs, fields, ','); 41 | if (vs.size() == 0) { 42 | return; 43 | } 44 | 45 | AssignDecoder de(vs, (unsigned char*)(&src), (unsigned char*)(&dst)); 46 | dst.__x_pack_decode(de, dst, NULL); 47 | } 48 | 49 | struct Data { 50 | int a; 51 | int b; 52 | std::string c; 53 | XPACK(O(a,b,c)); 54 | }; 55 | 56 | 57 | int main(int argc, char *argv[]) { 58 | (void)argc; 59 | (void)argv; 60 | 61 | Data d1; 62 | Data d2; 63 | d1.a = 5; 64 | d1.b = 10; 65 | d1.c = "hello"; 66 | d2.b = 9; 67 | SetFields(d1, d2, "a,c"); 68 | cout< 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace std; 7 | 8 | struct VID { 9 | int64_t Vid; 10 | int64_t vlen; 11 | string sid; 12 | int64_t level; 13 | XPACK(A(Vid, "db:vid"), O(vlen, sid, level)); 14 | }; 15 | 16 | typedef char cfgstr[64]; 17 | struct config { 18 | cfgstr host; 19 | uint32_t port; 20 | cfgstr user; 21 | cfgstr password; 22 | cfgstr dbname; 23 | XPACK(M(host, port, user, password, dbname)) 24 | }; 25 | 26 | int main(int argc, char **argv) { 27 | MYSQL *mysql = NULL; 28 | 29 | if (mysql_library_init(argc, argv, NULL)) { 30 | cout<<"could not initialize MySQL client library"< vids; 66 | xpack::mysql::decode(result, vids);// decode all rows 67 | 68 | vector ids; 69 | xpack::mysql::decode(result, "vid", ids); // decode vid column of all rows 70 | 71 | int64_t id; 72 | xpack::mysql::decode(result, "vid", id); // decode vid column of first row 73 | 74 | cout< 18 | #include "xpack/json.h" 19 | #include "xpack/xml.h" 20 | 21 | using namespace std; 22 | 23 | struct User { 24 | int64_t id; 25 | string name; 26 | string mail; 27 | std::shared_ptr bio; 28 | User(int64_t i=0, const string& n="", const string& m=""):id(i),name(n),mail(m){} 29 | XPACK(O(id, name, mail, bio)); 30 | }; 31 | 32 | 33 | int main(int argc, char *argv[]) { 34 | (void)argc; 35 | (void)argv; 36 | 37 | User u1(1, "Jack", "jack@xpack.com"); 38 | User u2; 39 | User u3; 40 | 41 | string json = xpack::json::encode(u1); 42 | string xml = xpack::xml::encode(u1, "root"); 43 | cout<<"========================"< 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | 7 | struct VID { 8 | int64_t Vid; 9 | int64_t vlen; 10 | string sid; 11 | int64_t level; 12 | XPACK(A(Vid, "db:vid"), O(vlen, sid, level)); 13 | }; 14 | 15 | int main(int argc, char **argv) { 16 | (void)argc; 17 | char *errMsg = NULL; 18 | sqlite *pDB = sqlite_open("./test.db", 0, &errMsg); 19 | if (NULL == pDB) { 20 | cout<<"open sqlite db fail:"< 18 | #include 19 | #include "xpack/json.h" 20 | 21 | using namespace std; 22 | 23 | struct Base { 24 | int a; 25 | int b; 26 | XPACK(O(a, b)); 27 | }; 28 | 29 | struct Data { 30 | int type; 31 | union { 32 | Base b; 33 | int i; 34 | char s[10]; 35 | }; 36 | string email; 37 | string birthday; 38 | // 'type' determines which member of the union to use, so we put type in 'C' 39 | // union does not need to be put into XPACK, we will handled it in 'type' 40 | XPACK(C(data_uinon, F(0), type), O(email, birthday)); 41 | }; 42 | 43 | struct User { 44 | string name; 45 | Data data; 46 | XPACK(O(name, data)); 47 | }; 48 | 49 | namespace xpack { // must define in namespace xpack 50 | 51 | template 52 | bool data_uinon_decode(OBJ &obj, Data &d, const char*key, int &type, const Extend *ext) { 53 | (void)ext; 54 | obj.decode(key, type, ext); 55 | switch (type) { 56 | case 1: 57 | obj.decode("b", d.b, NULL); // key("b") should same as encode 58 | break; 59 | case 2: 60 | obj.decode("i", d.i, NULL); 61 | break; 62 | case 3: 63 | obj.decode("s", d.s, NULL); 64 | break; 65 | } 66 | return true; 67 | } 68 | 69 | template 70 | bool data_uinon_encode(OBJ &obj, const Data &d, const char*key, const int &type, const Extend *ext) { 71 | (void)ext; 72 | obj.encode(key, type, NULL); 73 | switch (type) { 74 | case 1: 75 | obj.encode("b", d.b, NULL); 76 | break; 77 | case 2: 78 | obj.encode("i", d.i, NULL); 79 | break; 80 | case 3: 81 | obj.encode("s", d.s, NULL); 82 | break; 83 | } 84 | return true; 85 | } 86 | 87 | } 88 | 89 | int main(int argc, char *argv[]) { 90 | (void)argc; 91 | (void)argv; 92 | 93 | User u; 94 | u.name = "Pony"; 95 | u.data.type = 1; 96 | u.data.b.a = 10; 97 | u.data.b.b = 12; 98 | u.data.email = "Pony@xpack.com"; 99 | u.data.birthday = "20200202"; 100 | 101 | string s = xpack::json::encode(u); 102 | cout< 2 | #include 3 | 4 | using namespace std; 5 | 6 | struct Base { 7 | int a; 8 | int b; 9 | string c; 10 | XPACK(X(F(ATTR), a, b), X(F(XML_CONTENT), c)); 11 | }; 12 | 13 | struct Root { 14 | Base root; 15 | XPACK(O(root)); 16 | }; 17 | 18 | 19 | int main() { 20 | Root r; 21 | r.root.a = 1; 22 | r.root.b = 2; 23 | r.root.c = "hello"; 24 | string s = xpack::xml::encode(r, "root", 0, 4, ' '); 25 | cout< 2 | #include 3 | 4 | using namespace std; 5 | 6 | struct Base { 7 | int a; 8 | int b; 9 | XPACK(O(a, b));//, X(F(ATTR), b)); 10 | }; 11 | 12 | struct Root { 13 | Base root; 14 | XPACK(O(root)); 15 | }; 16 | 17 | struct Top { 18 | int k; 19 | string n; 20 | vector > bs; 21 | vector vi; 22 | float f; 23 | std::string name; // cdata 24 | XPACK(O(k, n, f), A(bs, "xml:base,sbs", vi, "xml:vi,vl@x", name, "xml:name,cdata")); 25 | }; 26 | 27 | int main() { 28 | Top t; 29 | t.k = 666; 30 | t.n = "你好"; 31 | t.f = 1.23333; 32 | t.vi.resize(2); 33 | t.vi[0] = 1; 34 | t.vi[1] = 2; 35 | t.bs.resize(2); 36 | t.bs[0].resize(2); 37 | t.bs[1].resize(2); 38 | t.bs[0][0].a = 100; 39 | t.bs[0][0].b = 200; 40 | t.bs[0][1].a = 101; 41 | t.bs[0][1].b = 201; 42 | t.bs[1][0].a = 110; 43 | t.bs[1][0].b = 210; 44 | t.bs[1][1].a = 111; 45 | t.bs[1][1].b = 211; 46 | t.name = "好好学习,天天向上"; 47 | string s = xpack::xml::encode(t, "root", 0, 4, ' '); 48 | cout<12", b1); 60 | cout<12", r1, true); 64 | cout< linux only 18 | #include 19 | #include "xpack/json.h" 20 | #ifndef _MSC_VER 21 | #include 22 | #endif 23 | 24 | using namespace std; 25 | 26 | #ifdef _MSC_VER 27 | struct timeval { 28 | long tv_sec; 29 | long tv_usec; 30 | }; 31 | #endif 32 | 33 | // timeval is thirdparty struct 34 | XPACK_OUT(timeval, O(tv_sec, tv_usec)); 35 | 36 | struct T { 37 | int a; 38 | string b; 39 | timeval t; 40 | XPACK(O(a, b, t)); 41 | }; 42 | 43 | 44 | int main(int argc, char *argv[]) { 45 | (void)argc; 46 | (void)argv; 47 | 48 | T t; 49 | T r; 50 | t.a = 123; 51 | t.b = "xpack"; 52 | t.t.tv_sec = 888; 53 | t.t.tv_usec = 999; 54 | string s = xpack::json::encode(t); 55 | cout< 18 | #include "xpack/json.h" 19 | #include "xpack/xml.h" 20 | 21 | using namespace std; 22 | 23 | struct Date { 24 | long unix_time; 25 | }; 26 | 27 | namespace xpack { // must define in namespace xpack 28 | 29 | template<> 30 | struct is_xpack_xtype {static bool const value = true;}; 31 | 32 | // implement decode 33 | template 34 | bool xpack_xtype_decode(OBJ &obj, Date &val, const Extend *ext) { 35 | std::string str; 36 | obj.decode(str, ext); 37 | if (str.empty()) { 38 | return false; 39 | } 40 | 41 | #ifndef _MSC_VER 42 | tm ttm; 43 | 44 | if (0 != strptime(str.c_str(), "%Y-%m-%d %H:%M:%S", &ttm)) { 45 | val.unix_time = mktime(&ttm); 46 | } else { 47 | val.unix_time = 0; 48 | } 49 | #else 50 | static int days[]={31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 32}; 51 | struct tm ttm={0}; 52 | sscanf_s(str.c_str(), "%d-%d-%d %d:%d:%d", &ttm.tm_year, &ttm.tm_mon, &ttm.tm_mday, &ttm.tm_hour, &ttm.tm_min, &ttm.tm_sec); 53 | ttm.tm_mon-=1; // mon[0-11] 54 | ttm.tm_year-=1900; // since 1900 55 | val.unix_time = mktime(&ttm); 56 | #endif 57 | return true; 58 | } 59 | 60 | // implement encode 61 | template 62 | bool xpack_xtype_encode(OBJ &obj, const char*key, const Date &val, const Extend *ext) { 63 | time_t tt = (time_t)val.unix_time; 64 | tm ttm; 65 | 66 | #ifndef _MSC_VER 67 | localtime_r(&tt, &ttm); 68 | #else 69 | localtime_s(&ttm, &tt); 70 | #endif 71 | 72 | char buf[64]; 73 | strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", &ttm); 74 | return obj.encode(key, buf, ext); 75 | } 76 | 77 | } 78 | 79 | struct User { 80 | int64_t id; 81 | string name; 82 | string mail; 83 | Date d; 84 | User(int64_t i=0, const string& n="", const string& m="", long _d=0):id(i),name(n),mail(m){d.unix_time = _d;} 85 | XPACK(O(id, name, mail, d)); 86 | }; 87 | 88 | struct Group { 89 | string name; 90 | int64_t master; 91 | vector members; 92 | XPACK(O(name, master, members)); 93 | }; 94 | 95 | int main(int argc, char *argv[]) { 96 | (void)argc; 97 | (void)argv; 98 | 99 | Group g; 100 | g.name = "C++"; 101 | g.master = 2019; 102 | g.members.resize(2); 103 | g.members[0] = User(1, "Jack", "jack@xpack.com", 1); 104 | g.members[1] = User(2, "Pony", "pony@xpack.com", 1609249232); 105 | 106 | string json = xpack::json::encode(g, 0, 2, ' '); 107 | cout< 18 | #include 19 | #include "xpack/json.h" 20 | 21 | using namespace std; 22 | 23 | // The requirement is to encode seq1 when type==1, and encode seq2 when type==2 24 | struct Sub { 25 | int type; 26 | string seq1; 27 | string seq2; 28 | XPACK(O(type, seq1, seq2)); 29 | }; 30 | 31 | 32 | struct Test { 33 | unsigned int uid; 34 | string name; 35 | Sub sub; 36 | XPACK(O(uid, name, sub)); 37 | }; 38 | 39 | namespace xpack { 40 | 41 | template<> 42 | struct is_xpack_xtype {static bool const value = true;}; 43 | 44 | template 45 | bool xpack_xtype_decode(Decoder& de, Sub &data, const xpack::Extend *ext) { 46 | de.decode_struct(data, ext); 47 | return true; 48 | } 49 | 50 | template 51 | class MyEncoder { 52 | public: 53 | MyEncoder(BaseEncoder&b, const Sub&sub):_b(&b), _s(&sub){} 54 | template 55 | bool encode(const char*key, const T&val, const xpack::Extend *ext) { 56 | if (strcmp(key, "seq1") == 0) { 57 | if (_s->type == 1) { 58 | return _b->encode(key, val, ext); 59 | } else { 60 | return false; 61 | } 62 | } else if (strcmp(key, "seq2") == 0) { 63 | if (_s->type == 2) { 64 | return _b->encode(key, val, ext); 65 | } else { 66 | return false; 67 | } 68 | } else { 69 | return _b->encode(key, val, ext); 70 | } 71 | } 72 | private: 73 | BaseEncoder *_b; 74 | const Sub *_s; 75 | }; 76 | 77 | template 78 | bool xpack_xtype_encode(Encoder &en, const char *name, const Sub &data, const xpack::Extend *ext) { 79 | (void)name; 80 | MyEncoder my(en, data); 81 | data.__x_pack_encode(my, data, ext); 82 | return true; 83 | } 84 | 85 | } 86 | 87 | int main(int argc, char *argv[]) { 88 | (void)argc; 89 | (void)argv; 90 | Test t; 91 | t.uid = 127; 92 | t.name = "PonyJack"; 93 | t.sub.type = 1; 94 | t.sub.seq1 = "10086"; 95 | t.sub.seq2 = "10001"; 96 | 97 | string str = xpack::json::encode(t); 98 | cout< 18 | #include "xpack/yaml.h" 19 | #include "xpack/json.h" 20 | 21 | using namespace std; 22 | 23 | struct User { 24 | int64_t id; 25 | string name; 26 | string mail; 27 | User(int64_t i=0, const string& n="", const string& m=""):id(i),name(n),mail(m){} 28 | XPACK(O(id, name, mail)); 29 | }; 30 | 31 | struct Group { 32 | string name; 33 | int64_t master; 34 | map flags; 35 | vector members; 36 | User arrays[2]; 37 | XPACK(O(name, master, flags, members, arrays)); 38 | }; 39 | 40 | int main() { 41 | User u; 42 | xpack::yaml::decode_file("./test.yml", u); 43 | string json = xpack::json::encode(u); 44 | cout<<"json:"< 22 | 23 | #include 24 | #include 25 | #include "config.h" 26 | #include "util.h" 27 | 28 | namespace xpack { 29 | 30 | // user flag 31 | #define X_PACK_FLAG_0 0 32 | #define X_PACK_FLAG_OE (1<<0) // omitempty, in encode 33 | #define X_PACK_FLAG_M (1<<1) // mandatory, in decode 34 | #define X_PACK_FLAG_EN (1<<2) // empty as null, in json encode 35 | #define X_PACK_FLAG_SL (1<<3) // encode as one line, currently only supports json vector 36 | 37 | #define X_PACK_FLAG_ATTR (1<<15) // for xml encode, encode in attribute 38 | 39 | // for xml encode/decode: 40 | // CONTENT flag for decode and encode content 41 | // A structure can only have one CONTENT flag. If multiple ones are defined, the behavior is undefined. 42 | #define X_PACK_FLAG_XML_CONTENT (1<<16) 43 | 44 | // control flag 45 | #define X_PACK_CTRL_FLAG_INHERIT (1<<0) 46 | 47 | // Alias name. [def ][type:name[,flag,key@value,flag]] def not support flag 48 | struct Alias { 49 | const char *raw; // raw name 50 | const char *alias; // alias define 51 | 52 | struct Type { 53 | std::string name; 54 | std::set flags; 55 | std::map kv_flags; 56 | }; 57 | 58 | Alias(const char *_raw, const char *_alias):raw(_raw), alias(_alias) { 59 | std::vector tps; 60 | Util::split(tps, alias, ' '); 61 | 62 | for (size_t i=0; i typeFlag; 64 | Util::split(typeFlag, tps[i], ':', 1); 65 | 66 | if (typeFlag.size() == 1) { // no ':', default name 67 | def = tps[i]; 68 | } else { // type:name[,flags] 69 | Type tp; 70 | 71 | std::vector nameFlags; 72 | Util::split(nameFlags, typeFlag[1], ','); 73 | tp.name = nameFlags[0]; 74 | if (nameFlags.size() > 1) { 75 | for (size_t j=1; j kvFlag; 77 | Util::split(kvFlag, nameFlags[j], '@', 1); 78 | if (kvFlag.size() == 1) { 79 | tp.flags.insert(nameFlags[j]); 80 | } else { 81 | tp.kv_flags[kvFlag[0]] = kvFlag[1]; 82 | } 83 | } 84 | } 85 | 86 | types[typeFlag[0]] = tp; 87 | } 88 | } 89 | } 90 | 91 | const char *Name(const char *type) const { 92 | std::map::const_iterator iter = types.find(type); 93 | if (iter == types.end()) { 94 | if (def.empty()) { 95 | return raw; 96 | } else { 97 | return def.c_str(); 98 | } 99 | } else { 100 | return iter->second.name.c_str(); 101 | } 102 | } 103 | 104 | bool Flag(const std::string&type, const std::string& flag, std::string *value=NULL) const { 105 | std::map::const_iterator it1 = types.find(type); 106 | if (it1 != types.end()) { 107 | if (it1->second.flags.find(flag) != it1->second.flags.end()) { 108 | return true; 109 | } 110 | std::map::const_iterator it2 = it1->second.kv_flags.find(flag); 111 | if (it2 != it1->second.kv_flags.end()) { 112 | if (NULL != value) { 113 | *value = it2->second; 114 | } 115 | return true; 116 | } 117 | } 118 | return false; 119 | } 120 | private: 121 | std::string def; // default name 122 | std::map types; 123 | }; 124 | 125 | struct Extend { 126 | int flag; 127 | int ctrl_flag; 128 | const Alias *alias; 129 | 130 | Extend(int _flag, const Alias *_alias):flag(_flag), ctrl_flag(0), alias(_alias) { 131 | } 132 | 133 | Extend(const Extend *ext) { 134 | if (NULL != ext) { 135 | flag = ext->flag; 136 | ctrl_flag = ext->ctrl_flag; 137 | alias = ext->alias; 138 | } else { 139 | flag = 0; 140 | ctrl_flag = 0; 141 | alias = NULL; 142 | } 143 | } 144 | 145 | static int Flag(const Extend *ext) { 146 | if (NULL == ext) { 147 | return 0; 148 | } else { 149 | return ext->flag; 150 | } 151 | } 152 | 153 | static int CtrlFlag(const Extend *ext) { 154 | if (NULL == ext) { 155 | return 0; 156 | } else { 157 | return ext->ctrl_flag; 158 | } 159 | } 160 | 161 | static bool AliasFlag(const Extend *ext, const std::string&type, const std::string& flag, std::string *value=NULL) { 162 | if (NULL==ext || NULL==ext->alias) { 163 | return false; 164 | } 165 | return ext->alias->Flag(type, flag, value); 166 | } 167 | 168 | static bool OmitEmpty(const Extend *ext) { 169 | return NULL!=ext && (ext->flag&X_PACK_FLAG_OE); 170 | } 171 | static bool EmptyNull(const Extend *ext) { 172 | return NULL!=ext && (ext->flag&X_PACK_FLAG_EN); 173 | } 174 | static bool Mandatory(const Extend *ext) { 175 | return NULL!=ext && (ext->flag&X_PACK_FLAG_M); 176 | } 177 | static bool Attribute(const Extend *ext) { 178 | return NULL!=ext && (ext->flag&X_PACK_FLAG_ATTR); 179 | } 180 | static bool XmlContent(const Extend *ext) { 181 | return NULL!=ext && (ext->flag&X_PACK_FLAG_XML_CONTENT); 182 | } 183 | }; 184 | 185 | } 186 | 187 | #endif 188 | 189 | -------------------------------------------------------------------------------- /gtest/gtest_stub.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2021 Duowan Inc. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, 11 | * software distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | 18 | 19 | #ifndef __X_GTEST_STUB_H 20 | #define __X_GTEST_STUB_H 21 | 22 | #include 23 | #include 24 | 25 | #ifdef XPACK_SUPPORT_QT 26 | #include 27 | #endif 28 | 29 | #include 30 | #include 31 | 32 | // test callback function 33 | typedef void(*test_case)(); 34 | 35 | // a test case 36 | struct text_ctx { 37 | const char *group; 38 | const char *name; 39 | test_case tc; 40 | }; 41 | 42 | class Status { 43 | public: 44 | static int&c() { 45 | static int _c; 46 | return _c; 47 | } 48 | }; 49 | 50 | // to collect all test 51 | class TC_CONTAINER { 52 | public: 53 | // add a test case to container 54 | static void add(test_case tc, const char* g, const char*n) { 55 | text_ctx tx; 56 | tx.group = g; 57 | tx.name = n; 58 | tx.tc = tc; 59 | I()._tcs.push_back(tx); 60 | } 61 | 62 | // run all test case 63 | static void RUN() { 64 | const std::vector& tcs = I()._tcs; 65 | for (size_t i=0; i"< _tcs; 85 | }; 86 | 87 | // add test case in ctor 88 | class AUTO_ADD_TC { 89 | public: 90 | AUTO_ADD_TC(test_case tc, const char* g, const char*n) { 91 | TC_CONTAINER::add(tc, g, n); 92 | } 93 | }; 94 | 95 | 96 | // type convert to support std::cout 97 | class TV { 98 | public: 99 | #ifdef X_PACK_SUPPORT_CXX0X 100 | template 101 | static typename std::enable_if::value, int64_t>::type tv(const TYPE &d) { 102 | return (int64_t)d; 103 | } 104 | template 105 | static typename std::enable_if::value, TYPE>::type tv(const TYPE &d) { 106 | return d; 107 | } 108 | static const char* tv(const char* d) { 109 | return d; 110 | } 111 | #else 112 | template 113 | static const TYPE& tv(const TYPE&d) { 114 | return d; 115 | } 116 | #endif 117 | 118 | #ifdef XPACK_SUPPORT_QT 119 | static std::string tv(const QString &d) { 120 | return d.toStdString(); 121 | } 122 | #endif 123 | }; 124 | 125 | #define expect_eq_float(a,b,delta) \ 126 | do {\ 127 | if (!((a)>=(b)-delta && (a)<=(b)+delta)) {\ 128 | std::cout< 32 | static void decode(const std::string &data, T &val) { 33 | JsonDecoder de; 34 | de.decode(data, val); 35 | } 36 | template 37 | static void decode(const rapidjson::Value &data, T &val) { 38 | JsonNode node(&data); 39 | XDecoder(NULL, (const char*)NULL, node).decode(val, NULL); 40 | } 41 | template 42 | static void decode_file(const std::string &file_name, T &val) { 43 | JsonDecoder de; 44 | de.decode_file(file_name, val); 45 | } 46 | 47 | template 48 | static std::string encode(const T &val) { 49 | JsonEncoder en; 50 | return en.encode(val); 51 | } 52 | 53 | template 54 | static std::string encode(const T &val, int flag, int indentCount, char indentChar) { 55 | (void)flag; 56 | JsonEncoder en(indentCount, indentChar); 57 | return en.encode(val); 58 | } 59 | }; 60 | 61 | } 62 | 63 | #endif 64 | -------------------------------------------------------------------------------- /json_data.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2021 Duowan Inc. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, 11 | * software distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #ifndef __X_PACK_JSON_DATA_H 18 | #define __X_PACK_JSON_DATA_H 19 | 20 | 21 | #include "rapidjson_custom.h" 22 | #include "rapidjson/document.h" 23 | #include "util.h" 24 | #include "traits.h" 25 | 26 | namespace xpack { 27 | 28 | // wrapper for rapidjson::Value. 29 | // If we use other json parser someday, users won't have to modify the code. 30 | // Most of the code is copied from rapidjson. 31 | enum JsonType { 32 | kNullType = 0, //!< null 33 | kFalseType = 1, //!< false 34 | kTrueType = 2, //!< true 35 | kObjectType = 3, //!< object 36 | kArrayType = 4, //!< array 37 | kStringType = 5, //!< string 38 | kNumberType = 6 //!< number 39 | }; 40 | 41 | class JsonData { 42 | friend class JsonNode; 43 | friend class JsonWriter; 44 | public: 45 | JsonData():current(NULL){} 46 | 47 | // check is valid JsonData 48 | operator bool() const { 49 | return NULL != current; 50 | } 51 | JsonType Type() const { 52 | if (NULL != current) { 53 | return static_cast(current->GetType()); 54 | } 55 | return kNullType; // ? 56 | } 57 | bool IsNull() const { return NULL==current||current->IsNull(); } 58 | bool IsBool() const { return NULL!=current && current->IsBool(); } 59 | bool IsObject() const { return NULL!=current && current->IsObject(); } 60 | bool IsArray() const { return NULL!=current && current->IsArray(); } 61 | bool IsNumber() const { return NULL!=current && current->IsNumber(); } 62 | bool IsDouble() const { return NULL!=current && current->IsDouble(); } 63 | bool IsString() const { return NULL!=current && current->IsString(); } 64 | size_t Size() const {return (size_t)current->Size();} 65 | 66 | JsonData operator [](const char *key) const { 67 | if (NULL != current && current->IsObject()) { 68 | rapidjson::Value::ConstMemberIterator iter = current->FindMember(key); 69 | if (iter != current->MemberEnd()) { 70 | return JsonData(&iter->value); 71 | } // no exception ? 72 | } 73 | return JsonData(); 74 | } 75 | JsonData operator [](size_t index) const { 76 | if (NULL != current && current->IsArray() && index < (size_t)current->Size()) { 77 | return JsonData(&(*current)[(rapidjson::SizeType)index]); 78 | } 79 | return JsonData(); 80 | } 81 | 82 | std::string String() const; // Implementation in json_encoder.h 83 | 84 | template // For base byte(integer/float/double/bool/std::string), implementation in json_decoder.h 85 | T Get() const; 86 | 87 | template // struct, implementation in json_decoder.h 88 | bool Get(T &val) const; 89 | 90 | private: 91 | JsonData(const rapidjson::Value*v):current(v){} 92 | 93 | void reset(const rapidjson::Value *v) { 94 | node.reset(); 95 | allocator.reset(); 96 | current = NULL; 97 | if (NULL != v) { 98 | if (v->IsNull()) { 99 | node.reset(new rapidjson::Value()); 100 | } else { 101 | allocator.reset(new rapidjson::MemoryPoolAllocator<>()); 102 | node.reset(new rapidjson::Value(*v, *allocator, true)); 103 | } 104 | current = node.get(); 105 | } 106 | } 107 | x_shared_ptr > allocator; 108 | x_shared_ptr node; // release node first 109 | 110 | const rapidjson::Value* current; 111 | }; 112 | 113 | } 114 | 115 | #endif 116 | -------------------------------------------------------------------------------- /json_decoder.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2021 Duowan Inc. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, 11 | * software distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #ifndef __X_PACK_JSON_DECODER_H 18 | #define __X_PACK_JSON_DECODER_H 19 | 20 | #include 21 | 22 | #include "rapidjson_custom.h" 23 | #include "rapidjson/document.h" 24 | #include "rapidjson/error/en.h" 25 | 26 | #include "xdecoder.h" 27 | #include "json_data.h" 28 | 29 | 30 | namespace xpack { 31 | 32 | 33 | class JsonNode { 34 | typedef XDecoder decoder; 35 | public: 36 | typedef rapidjson::Value::ConstMemberIterator Iterator; 37 | 38 | JsonNode(const rapidjson::Value* val=NULL):v(val){} 39 | 40 | // convert JsonData to JsonNode 41 | // The life cycle of jd cannot be shorter than JsonNode 42 | JsonNode(const JsonData&jd):v(jd.current){} 43 | 44 | inline static const char * Name() { 45 | return "json"; 46 | } 47 | operator bool() const { 48 | return v != NULL; 49 | } 50 | bool IsNull() const { 51 | return v!=NULL && v->IsNull(); 52 | } 53 | JsonNode Find(decoder&de, const char*key, const Extend *ext) const { 54 | (void)ext; 55 | if (v->IsNull()) { 56 | return JsonNode(); 57 | } else if (!v->IsObject()) { 58 | de.decode_exception("not object", NULL); 59 | } 60 | rapidjson::Value::ConstMemberIterator iter = v->FindMember(key); 61 | if (iter != v->MemberEnd()) { 62 | return JsonNode(&iter->value); 63 | } else { 64 | return JsonNode(); 65 | } 66 | } 67 | size_t Size(decoder&de) const { 68 | if (v->IsNull()) { 69 | return 0; 70 | } else if (!v->IsArray()) { 71 | de.decode_exception("not array", NULL); 72 | } 73 | return (size_t)v->Size(); 74 | } 75 | JsonNode At(size_t index) const { // no exception 76 | return JsonNode(&(*v)[(rapidjson::SizeType)index]); 77 | } 78 | JsonNode Next(decoder&de, const JsonNode&parent, Iterator&iter, std::string&key) const { 79 | if (!parent.v->IsObject()) { 80 | de.decode_exception("not object", NULL); 81 | } 82 | 83 | if (v != parent.v) { 84 | ++iter; 85 | } else { 86 | iter = parent.v->MemberBegin(); 87 | } 88 | 89 | if (iter != parent.v->MemberEnd()) { 90 | key = iter->name.GetString(); 91 | return JsonNode(&iter->value); 92 | } 93 | 94 | return JsonNode(); 95 | } 96 | 97 | bool Get(decoder&de, std::string&val, const Extend*ext) { 98 | (void)ext; 99 | if (v->IsString()) { 100 | val = std::string(v->GetString(), v->GetStringLength()); 101 | } else if (!v->IsNull()) { 102 | de.decode_exception("not string", NULL); 103 | } 104 | return true; 105 | } 106 | bool Get(decoder&de, bool &val, const Extend*ext) { 107 | (void)ext; 108 | if (v->IsBool()) { 109 | val = v->GetBool(); 110 | } else if (v->IsInt64()) { 111 | val = (0 != (v->GetInt64())); 112 | } else if (v->IsNull()) { 113 | val = false; 114 | } else { 115 | de.decode_exception("not bool or integer", NULL); 116 | } 117 | return true; 118 | } 119 | template 120 | typename x_enable_if::is_integer, bool>::type Get(decoder&de, T &val, const Extend*ext){ 121 | (void)ext; 122 | if (v->IsInt()) { 123 | val = (T)v->GetInt(); 124 | } else if (v->IsUint()) { 125 | val = (T)v->GetUint(); 126 | } else if (v->IsInt64()) { 127 | val = (T)v->GetInt64(); 128 | } else if (v->IsUint64()) { 129 | val = (T)v->GetUint64(); 130 | } else if (v->IsNull()) { 131 | val = 0; 132 | } else { 133 | de.decode_exception("not integer", NULL); 134 | } 135 | return true; 136 | } 137 | template 138 | typename x_enable_if::is_float, bool>::type Get(decoder&de, T &val, const Extend*ext){ 139 | (void)ext; 140 | if (v->IsNumber()) { 141 | val = (T)v->GetDouble(); 142 | } else if (v->IsNull()) { 143 | val = 0; 144 | } else { 145 | de.decode_exception("not number", NULL); 146 | } 147 | return true; 148 | } 149 | 150 | ////////////// for JsonData /////////////////////// 151 | bool decode_type_spec(JsonData& val, const Extend *ext) { 152 | (void)ext; 153 | val.reset(v); 154 | return true; 155 | } 156 | 157 | private: 158 | const rapidjson::Value* v; 159 | rapidjson::Value::ConstMemberIterator iter; 160 | }; 161 | 162 | class JsonDecoder { 163 | public: 164 | template 165 | bool decode(const std::string&str, T&val) { 166 | rapidjson::Document doc; 167 | if (this->parse(str, doc)) { 168 | JsonNode node(&doc); 169 | return XDecoder(NULL, (const char*)NULL, node).decode(val, NULL); 170 | } 171 | return false; 172 | } 173 | template 174 | bool decode_file(const std::string&fname, T&val) { 175 | std::string data; 176 | bool ret = Util::readfile(fname, data); 177 | if (ret) { 178 | ret = this->decode(data, val); 179 | } 180 | return ret; 181 | } 182 | private: 183 | bool parse(const std::string&data, rapidjson::Document &doc) { 184 | std::string err; 185 | 186 | const unsigned int parseFlags = rapidjson::kParseNanAndInfFlag; 187 | doc.Parse(data.data(), data.length()); 188 | 189 | if (doc.HasParseError()) { 190 | size_t offset = doc.GetErrorOffset(); 191 | std::string parse_err(rapidjson::GetParseError_En(doc.GetParseError())); 192 | std::string err_data = data.substr(offset, 32); 193 | err = "Parse json fail. err="+parse_err+". offset="+err_data; 194 | throw std::runtime_error(err); 195 | } 196 | return true; 197 | } 198 | }; 199 | 200 | // /////////////// JsonData /////////////////// 201 | template<>struct is_xpack_type_spec {static bool const value = true;}; 202 | 203 | template 204 | inline T JsonData::Get() const { 205 | JsonNode node(*this); 206 | T t; 207 | XDecoder(NULL, (const char*)NULL, node).decode(t, NULL); 208 | return t; 209 | } 210 | template 211 | inline bool JsonData::Get(T&val) const { 212 | JsonNode node(*this); 213 | return XDecoder(NULL, (const char*)NULL, node).decode(val, NULL); 214 | } 215 | 216 | } 217 | 218 | #endif 219 | -------------------------------------------------------------------------------- /mysql.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2021 Duowan Inc. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, 11 | * software distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #ifndef __X_PACK_MYSQL_H 18 | #define __X_PACK_MYSQL_H 19 | 20 | #include "mysql_decoder.h" 21 | #include "xpack.h" 22 | 23 | namespace xpack { 24 | 25 | class mysql { 26 | public: 27 | // convert MYSQL_RES to a struct or vector 28 | template 29 | static void decode(MYSQL_RES *result, T &val) { 30 | MySQLDecoder de(result); 31 | de.decode_top(val, NULL); 32 | } 33 | 34 | // select name from test where id = 1; // just want to get name, did not want to use a struct 35 | template 36 | static void decode(MYSQL_RES *result, const std::string&field, T &val) { 37 | MySQLDecoder de(result); 38 | de.decode_column(field.c_str(), val, NULL); 39 | } 40 | }; 41 | 42 | } 43 | 44 | #endif -------------------------------------------------------------------------------- /mysql_decoder.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2021 Duowan Inc. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, 11 | * software distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | 18 | #ifndef __X_PACK_MYSQL_DECODER_H 19 | #define __X_PACK_MYSQL_DECODER_H 20 | 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | #include 27 | 28 | #include "extend.h" 29 | #include "traits.h" 30 | #include "json.h" 31 | 32 | #include "string.h" 33 | #include "time.h" 34 | 35 | namespace xpack { 36 | 37 | // for mysql types not list here 38 | // if true we will call xpack_mysql_decode(MYSQL_FIELD *field, char *column, T&val, const Extend *ext) 39 | template 40 | struct is_xpack_mysql_xtype {static bool const value = false;}; 41 | 42 | class MySQLDecoder { 43 | friend class mysql; 44 | public: 45 | template 46 | bool decode(const char*key, T&val, const Extend *ext) { 47 | int idx = find(key); 48 | if (idx >= 0) { 49 | return this->decode_type(idx, val, ext); 50 | } 51 | return false; 52 | } 53 | const char *Name() const { 54 | return "db"; 55 | } 56 | 57 | private: 58 | MYSQL_RES *_res; 59 | MYSQL_ROW _row; 60 | std::map _index; 61 | 62 | MySQLDecoder(MYSQL_RES *result):_res(result), _row(NULL) { 63 | mysql_data_seek(_res, 0); // reset cursor to head 64 | for (int i=0; ifield_count); ++i) { 65 | _index[result->fields[i].name] = i; 66 | } 67 | } 68 | 69 | // decode to struct 70 | template 71 | inline XPACK_IS_XPACK(T) decode_top(T& val, const Extend *ext) { 72 | if (NULL != (_row = mysql_fetch_row(_res))) { 73 | val.__x_pack_decode(*this, val, ext); 74 | return true; 75 | } 76 | return false; 77 | } 78 | template 79 | inline XPACK_IS_XPACK(T) decode_top(std::vector& val, const Extend *ext) { 80 | while (NULL != (_row = mysql_fetch_row(_res))) { 81 | val.push_back(T()); 82 | T& tmp = val.back(); 83 | tmp.__x_pack_decode(*this, tmp, ext); 84 | } 85 | return true; 86 | } 87 | template 88 | inline XPACK_IS_XOUT(T) decode_top(T& val, const Extend *ext) { 89 | if (NULL != (_row = mysql_fetch_row(_res))) { 90 | __x_pack_decode_out(*this, val, ext); 91 | } 92 | return true; 93 | } 94 | template 95 | inline XPACK_IS_XOUT(T) decode_top(std::vector& val, const Extend *ext) { 96 | while (NULL != (_row = mysql_fetch_row(_res))) { 97 | val.push_back(T()); 98 | __x_pack_decode_out(*this, val.back(), ext); 99 | } 100 | return true; 101 | } 102 | 103 | // decode special column of first row 104 | template 105 | bool decode_column(const char*field, T&val, const Extend *ext) { 106 | int idx; 107 | if (NULL==_row && NULL == (_row = mysql_fetch_row(_res)) && (0 > (idx = find(field)))) { 108 | return false; 109 | } 110 | return decode_type(idx, val, ext); 111 | } 112 | // decode special column of rows 113 | template 114 | bool decode_column(const char*field, std::vector&val, const Extend *ext) { 115 | int idx; 116 | if (0 > (idx = find(field))) { 117 | return false; 118 | } 119 | while (NULL != (_row = mysql_fetch_row(_res))) { 120 | T t; 121 | decode_type(idx, t, ext); 122 | val.push_back(t); 123 | } 124 | return true; 125 | } 126 | 127 | 128 | int find(const char*field) const { 129 | std::map::const_iterator it = _index.find(field); 130 | if (it != _index.end()) { 131 | return it->second; 132 | } 133 | return -1; 134 | } 135 | 136 | // std::string 137 | bool decode_type(const int idx, std::string &val, const Extend *ext) { 138 | val = _row[idx]; 139 | return true; 140 | } 141 | // bool 142 | bool decode_type(const int idx, bool &val, const Extend *ext) { 143 | int tmp; 144 | if (decode_type(idx, tmp, ext)) { 145 | val = tmp != 0; 146 | return true; 147 | } 148 | return false; 149 | } 150 | // unsigned integer. DATE and TIME use signed plz 151 | template 152 | typename x_enable_if::is_integer && !numeric::is_signed, bool>::type decode_type(const int idx, T &val, const Extend *ext) { 153 | val = (T)std::strtoul(_row[idx], NULL, 10); 154 | return true; 155 | } 156 | // signed integer 157 | template 158 | typename x_enable_if::is_integer && numeric::is_signed, bool>::type decode_type(const int idx, T &val, const Extend *ext) { 159 | const char *str = _row[idx]; 160 | if (str==NULL || str[0]=='\0') { 161 | val = 0; 162 | return true; 163 | } 164 | switch (_res->fields[idx].type) { 165 | case MYSQL_TYPE_TIME: { 166 | std::vector ss; 167 | if (3 == Util::split(ss, str, ':')) { 168 | long int s0 = std::strtol(ss[0].c_str(), NULL, 10); 169 | long int s1 = std::strtol(ss[1].c_str(), NULL, 10); 170 | long int s2 = std::strtol(ss[2].c_str(), NULL, 10); 171 | if (s0 >= 0) { 172 | val = 1; 173 | } else { 174 | val = -1; 175 | s0 *= -1; 176 | } 177 | val *= (T)(s0*3600 + s1*60 +s2); 178 | } 179 | } 180 | break; 181 | case MYSQL_TYPE_DATETIME: 182 | case MYSQL_TYPE_TIMESTAMP:{ // parse to unix timestamp, seconds, discard fractional part 183 | tm t; 184 | strptime(str, "%F %T", &t); 185 | val = (T)mktime(&t); 186 | } 187 | break; 188 | default: 189 | val = (T)std::strtol(str, NULL, 10); 190 | } 191 | return true; 192 | } 193 | // float 194 | template 195 | typename x_enable_if::is_float, bool>::type decode_type(const int idx, T &val, const Extend *ext) { 196 | val = (T)std::strtod(_row[idx], NULL); 197 | return true; 198 | } 199 | 200 | // mysql covert type 201 | template 202 | inline typename x_enable_if::value, bool>::type decode_type(const int idx, T &val, const Extend *ext) { 203 | return xpack_mysql_decode(&_res->fields[idx], _row[idx], val, ext); 204 | } 205 | 206 | // class/struct defined XPACK/XPACK_OUT, default use json to parse, if use other, use xpack_mysql_decode 207 | template 208 | inline XPACK_IS_XOUT(T) decode_type(const int idx, T &val, const Extend *ext) { 209 | (void)ext; 210 | return xpack::json::decode(_row[idx], val); 211 | } 212 | template 213 | inline XPACK_IS_XPACK(T) decode_type(const int idx, T &val, const Extend *ext) { 214 | (void)ext; 215 | return xpack::json::decode(_row[idx], val); 216 | } 217 | }; 218 | 219 | 220 | } 221 | 222 | #endif 223 | -------------------------------------------------------------------------------- /numeric.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2021 Duowan Inc. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, 11 | * software distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #ifndef __X_PACK_NUMERIC_H 18 | #define __X_PACK_NUMERIC_H 19 | 20 | namespace xpack { 21 | 22 | template 23 | struct numeric{static bool const value = false; static bool const is_integer = false;static bool const is_float = false;static bool const is_signed = false;}; 24 | 25 | template<> 26 | struct numeric{static bool const value = true; static bool const is_integer = true;static bool const is_signed = true;}; 27 | 28 | template<> 29 | struct numeric{static bool const value = true; static bool const is_integer = true;static bool const is_signed = true;}; 30 | 31 | template<> 32 | struct numeric{static bool const value = true; static bool const is_integer = true;;static bool const is_signed = false;}; 33 | 34 | template<> 35 | struct numeric{static bool const value = true; static bool const is_integer = true;static bool const is_signed = true;}; 36 | 37 | template<> 38 | struct numeric{static bool const value = true; static bool const is_integer = true;;static bool const is_signed = false;}; 39 | 40 | template<> 41 | struct numeric{static bool const value = true; static bool const is_integer = true;static bool const is_signed = true;}; 42 | 43 | template<> 44 | struct numeric{static bool const value = true; static bool const is_integer = true;;static bool const is_signed = false;}; 45 | 46 | template<> 47 | struct numeric{static bool const value = true; static bool const is_integer = true;static bool const is_signed = true;}; 48 | 49 | template<> 50 | struct numeric{static bool const value = true; static bool const is_integer = true;;static bool const is_signed = false;}; 51 | 52 | template<> 53 | struct numeric{static bool const value = true; static bool const is_integer = true;static bool const is_signed = true;}; 54 | 55 | template<> 56 | struct numeric{static bool const value = true; static bool const is_integer = true;;static bool const is_signed = false;}; 57 | 58 | template<> 59 | struct numeric{static bool const value = true;static bool const is_float = true;}; 60 | 61 | template<> 62 | struct numeric{static bool const value = true;static bool const is_float = true;}; 63 | 64 | template<> 65 | struct numeric{static bool const value = true;static bool const is_float = true;}; 66 | 67 | } 68 | 69 | #endif 70 | -------------------------------------------------------------------------------- /rapidjson/cursorstreamwrapper.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making RapidJSON available. 2 | // 3 | // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. 4 | // 5 | // Licensed under the MIT License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // http://opensource.org/licenses/MIT 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #ifndef RAPIDJSON_CURSORSTREAMWRAPPER_H_ 16 | #define RAPIDJSON_CURSORSTREAMWRAPPER_H_ 17 | 18 | #include "stream.h" 19 | 20 | #if defined(__GNUC__) 21 | RAPIDJSON_DIAG_PUSH 22 | RAPIDJSON_DIAG_OFF(effc++) 23 | #endif 24 | 25 | #if defined(_MSC_VER) && _MSC_VER <= 1800 26 | RAPIDJSON_DIAG_PUSH 27 | RAPIDJSON_DIAG_OFF(4702) // unreachable code 28 | RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated 29 | #endif 30 | 31 | RAPIDJSON_NAMESPACE_BEGIN 32 | 33 | 34 | //! Cursor stream wrapper for counting line and column number if error exists. 35 | /*! 36 | \tparam InputStream Any stream that implements Stream Concept 37 | */ 38 | template > 39 | class CursorStreamWrapper : public GenericStreamWrapper { 40 | public: 41 | typedef typename Encoding::Ch Ch; 42 | 43 | CursorStreamWrapper(InputStream& is): 44 | GenericStreamWrapper(is), line_(1), col_(0) {} 45 | 46 | // counting line and column number 47 | Ch Take() { 48 | Ch ch = this->is_.Take(); 49 | if(ch == '\n') { 50 | line_ ++; 51 | col_ = 0; 52 | } else { 53 | col_ ++; 54 | } 55 | return ch; 56 | } 57 | 58 | //! Get the error line number, if error exists. 59 | size_t GetLine() const { return line_; } 60 | //! Get the error column number, if error exists. 61 | size_t GetColumn() const { return col_; } 62 | 63 | private: 64 | size_t line_; //!< Current Line 65 | size_t col_; //!< Current Column 66 | }; 67 | 68 | #if defined(_MSC_VER) && _MSC_VER <= 1800 69 | RAPIDJSON_DIAG_POP 70 | #endif 71 | 72 | #if defined(__GNUC__) 73 | RAPIDJSON_DIAG_POP 74 | #endif 75 | 76 | RAPIDJSON_NAMESPACE_END 77 | 78 | #endif // RAPIDJSON_CURSORSTREAMWRAPPER_H_ 79 | -------------------------------------------------------------------------------- /rapidjson/error/en.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making RapidJSON available. 2 | // 3 | // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. 4 | // 5 | // Licensed under the MIT License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // http://opensource.org/licenses/MIT 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #ifndef RAPIDJSON_ERROR_EN_H_ 16 | #define RAPIDJSON_ERROR_EN_H_ 17 | 18 | #include "error.h" 19 | 20 | #ifdef __clang__ 21 | RAPIDJSON_DIAG_PUSH 22 | RAPIDJSON_DIAG_OFF(switch-enum) 23 | RAPIDJSON_DIAG_OFF(covered-switch-default) 24 | #endif 25 | 26 | RAPIDJSON_NAMESPACE_BEGIN 27 | 28 | //! Maps error code of parsing into error message. 29 | /*! 30 | \ingroup RAPIDJSON_ERRORS 31 | \param parseErrorCode Error code obtained in parsing. 32 | \return the error message. 33 | \note User can make a copy of this function for localization. 34 | Using switch-case is safer for future modification of error codes. 35 | */ 36 | inline const RAPIDJSON_ERROR_CHARTYPE* GetParseError_En(ParseErrorCode parseErrorCode) { 37 | switch (parseErrorCode) { 38 | case kParseErrorNone: return RAPIDJSON_ERROR_STRING("No error."); 39 | 40 | case kParseErrorDocumentEmpty: return RAPIDJSON_ERROR_STRING("The document is empty."); 41 | case kParseErrorDocumentRootNotSingular: return RAPIDJSON_ERROR_STRING("The document root must not be followed by other values."); 42 | 43 | case kParseErrorValueInvalid: return RAPIDJSON_ERROR_STRING("Invalid value."); 44 | 45 | case kParseErrorObjectMissName: return RAPIDJSON_ERROR_STRING("Missing a name for object member."); 46 | case kParseErrorObjectMissColon: return RAPIDJSON_ERROR_STRING("Missing a colon after a name of object member."); 47 | case kParseErrorObjectMissCommaOrCurlyBracket: return RAPIDJSON_ERROR_STRING("Missing a comma or '}' after an object member."); 48 | 49 | case kParseErrorArrayMissCommaOrSquareBracket: return RAPIDJSON_ERROR_STRING("Missing a comma or ']' after an array element."); 50 | 51 | case kParseErrorStringUnicodeEscapeInvalidHex: return RAPIDJSON_ERROR_STRING("Incorrect hex digit after \\u escape in string."); 52 | case kParseErrorStringUnicodeSurrogateInvalid: return RAPIDJSON_ERROR_STRING("The surrogate pair in string is invalid."); 53 | case kParseErrorStringEscapeInvalid: return RAPIDJSON_ERROR_STRING("Invalid escape character in string."); 54 | case kParseErrorStringMissQuotationMark: return RAPIDJSON_ERROR_STRING("Missing a closing quotation mark in string."); 55 | case kParseErrorStringInvalidEncoding: return RAPIDJSON_ERROR_STRING("Invalid encoding in string."); 56 | 57 | case kParseErrorNumberTooBig: return RAPIDJSON_ERROR_STRING("Number too big to be stored in double."); 58 | case kParseErrorNumberMissFraction: return RAPIDJSON_ERROR_STRING("Miss fraction part in number."); 59 | case kParseErrorNumberMissExponent: return RAPIDJSON_ERROR_STRING("Miss exponent in number."); 60 | 61 | case kParseErrorTermination: return RAPIDJSON_ERROR_STRING("Terminate parsing due to Handler error."); 62 | case kParseErrorUnspecificSyntaxError: return RAPIDJSON_ERROR_STRING("Unspecific syntax error."); 63 | 64 | default: return RAPIDJSON_ERROR_STRING("Unknown error."); 65 | } 66 | } 67 | 68 | RAPIDJSON_NAMESPACE_END 69 | 70 | #ifdef __clang__ 71 | RAPIDJSON_DIAG_POP 72 | #endif 73 | 74 | #endif // RAPIDJSON_ERROR_EN_H_ 75 | -------------------------------------------------------------------------------- /rapidjson/error/error.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making RapidJSON available. 2 | // 3 | // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. 4 | // 5 | // Licensed under the MIT License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // http://opensource.org/licenses/MIT 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #ifndef RAPIDJSON_ERROR_ERROR_H_ 16 | #define RAPIDJSON_ERROR_ERROR_H_ 17 | 18 | #include "../rapidjson.h" 19 | 20 | #ifdef __clang__ 21 | RAPIDJSON_DIAG_PUSH 22 | RAPIDJSON_DIAG_OFF(padded) 23 | #endif 24 | 25 | /*! \file error.h */ 26 | 27 | /*! \defgroup RAPIDJSON_ERRORS RapidJSON error handling */ 28 | 29 | /////////////////////////////////////////////////////////////////////////////// 30 | // RAPIDJSON_ERROR_CHARTYPE 31 | 32 | //! Character type of error messages. 33 | /*! \ingroup RAPIDJSON_ERRORS 34 | The default character type is \c char. 35 | On Windows, user can define this macro as \c TCHAR for supporting both 36 | unicode/non-unicode settings. 37 | */ 38 | #ifndef RAPIDJSON_ERROR_CHARTYPE 39 | #define RAPIDJSON_ERROR_CHARTYPE char 40 | #endif 41 | 42 | /////////////////////////////////////////////////////////////////////////////// 43 | // RAPIDJSON_ERROR_STRING 44 | 45 | //! Macro for converting string literial to \ref RAPIDJSON_ERROR_CHARTYPE[]. 46 | /*! \ingroup RAPIDJSON_ERRORS 47 | By default this conversion macro does nothing. 48 | On Windows, user can define this macro as \c _T(x) for supporting both 49 | unicode/non-unicode settings. 50 | */ 51 | #ifndef RAPIDJSON_ERROR_STRING 52 | #define RAPIDJSON_ERROR_STRING(x) x 53 | #endif 54 | 55 | RAPIDJSON_NAMESPACE_BEGIN 56 | 57 | /////////////////////////////////////////////////////////////////////////////// 58 | // ParseErrorCode 59 | 60 | //! Error code of parsing. 61 | /*! \ingroup RAPIDJSON_ERRORS 62 | \see GenericReader::Parse, GenericReader::GetParseErrorCode 63 | */ 64 | enum ParseErrorCode { 65 | kParseErrorNone = 0, //!< No error. 66 | 67 | kParseErrorDocumentEmpty, //!< The document is empty. 68 | kParseErrorDocumentRootNotSingular, //!< The document root must not follow by other values. 69 | 70 | kParseErrorValueInvalid, //!< Invalid value. 71 | 72 | kParseErrorObjectMissName, //!< Missing a name for object member. 73 | kParseErrorObjectMissColon, //!< Missing a colon after a name of object member. 74 | kParseErrorObjectMissCommaOrCurlyBracket, //!< Missing a comma or '}' after an object member. 75 | 76 | kParseErrorArrayMissCommaOrSquareBracket, //!< Missing a comma or ']' after an array element. 77 | 78 | kParseErrorStringUnicodeEscapeInvalidHex, //!< Incorrect hex digit after \\u escape in string. 79 | kParseErrorStringUnicodeSurrogateInvalid, //!< The surrogate pair in string is invalid. 80 | kParseErrorStringEscapeInvalid, //!< Invalid escape character in string. 81 | kParseErrorStringMissQuotationMark, //!< Missing a closing quotation mark in string. 82 | kParseErrorStringInvalidEncoding, //!< Invalid encoding in string. 83 | 84 | kParseErrorNumberTooBig, //!< Number too big to be stored in double. 85 | kParseErrorNumberMissFraction, //!< Miss fraction part in number. 86 | kParseErrorNumberMissExponent, //!< Miss exponent in number. 87 | 88 | kParseErrorTermination, //!< Parsing was terminated. 89 | kParseErrorUnspecificSyntaxError //!< Unspecific syntax error. 90 | }; 91 | 92 | //! Result of parsing (wraps ParseErrorCode) 93 | /*! 94 | \ingroup RAPIDJSON_ERRORS 95 | \code 96 | Document doc; 97 | ParseResult ok = doc.Parse("[42]"); 98 | if (!ok) { 99 | fprintf(stderr, "JSON parse error: %s (%u)", 100 | GetParseError_En(ok.Code()), ok.Offset()); 101 | exit(EXIT_FAILURE); 102 | } 103 | \endcode 104 | \see GenericReader::Parse, GenericDocument::Parse 105 | */ 106 | struct ParseResult { 107 | //!! Unspecified boolean type 108 | typedef bool (ParseResult::*BooleanType)() const; 109 | public: 110 | //! Default constructor, no error. 111 | ParseResult() : code_(kParseErrorNone), offset_(0) {} 112 | //! Constructor to set an error. 113 | ParseResult(ParseErrorCode code, size_t offset) : code_(code), offset_(offset) {} 114 | 115 | //! Get the error code. 116 | ParseErrorCode Code() const { return code_; } 117 | //! Get the error offset, if \ref IsError(), 0 otherwise. 118 | size_t Offset() const { return offset_; } 119 | 120 | //! Explicit conversion to \c bool, returns \c true, iff !\ref IsError(). 121 | operator BooleanType() const { return !IsError() ? &ParseResult::IsError : NULL; } 122 | //! Whether the result is an error. 123 | bool IsError() const { return code_ != kParseErrorNone; } 124 | 125 | bool operator==(const ParseResult& that) const { return code_ == that.code_; } 126 | bool operator==(ParseErrorCode code) const { return code_ == code; } 127 | friend bool operator==(ParseErrorCode code, const ParseResult & err) { return code == err.code_; } 128 | 129 | bool operator!=(const ParseResult& that) const { return !(*this == that); } 130 | bool operator!=(ParseErrorCode code) const { return !(*this == code); } 131 | friend bool operator!=(ParseErrorCode code, const ParseResult & err) { return err != code; } 132 | 133 | //! Reset error code. 134 | void Clear() { Set(kParseErrorNone); } 135 | //! Update error code and offset. 136 | void Set(ParseErrorCode code, size_t offset = 0) { code_ = code; offset_ = offset; } 137 | 138 | private: 139 | ParseErrorCode code_; 140 | size_t offset_; 141 | }; 142 | 143 | //! Function pointer type of GetParseError(). 144 | /*! \ingroup RAPIDJSON_ERRORS 145 | 146 | This is the prototype for \c GetParseError_X(), where \c X is a locale. 147 | User can dynamically change locale in runtime, e.g.: 148 | \code 149 | GetParseErrorFunc GetParseError = GetParseError_En; // or whatever 150 | const RAPIDJSON_ERROR_CHARTYPE* s = GetParseError(document.GetParseErrorCode()); 151 | \endcode 152 | */ 153 | typedef const RAPIDJSON_ERROR_CHARTYPE* (*GetParseErrorFunc)(ParseErrorCode); 154 | 155 | RAPIDJSON_NAMESPACE_END 156 | 157 | #ifdef __clang__ 158 | RAPIDJSON_DIAG_POP 159 | #endif 160 | 161 | #endif // RAPIDJSON_ERROR_ERROR_H_ 162 | -------------------------------------------------------------------------------- /rapidjson/filereadstream.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making RapidJSON available. 2 | // 3 | // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. 4 | // 5 | // Licensed under the MIT License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // http://opensource.org/licenses/MIT 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #ifndef RAPIDJSON_FILEREADSTREAM_H_ 16 | #define RAPIDJSON_FILEREADSTREAM_H_ 17 | 18 | #include "stream.h" 19 | #include 20 | 21 | #ifdef __clang__ 22 | RAPIDJSON_DIAG_PUSH 23 | RAPIDJSON_DIAG_OFF(padded) 24 | RAPIDJSON_DIAG_OFF(unreachable-code) 25 | RAPIDJSON_DIAG_OFF(missing-noreturn) 26 | #endif 27 | 28 | RAPIDJSON_NAMESPACE_BEGIN 29 | 30 | //! File byte stream for input using fread(). 31 | /*! 32 | \note implements Stream concept 33 | */ 34 | class FileReadStream { 35 | public: 36 | typedef char Ch; //!< Character type (byte). 37 | 38 | //! Constructor. 39 | /*! 40 | \param fp File pointer opened for read. 41 | \param buffer user-supplied buffer. 42 | \param bufferSize size of buffer in bytes. Must >=4 bytes. 43 | */ 44 | FileReadStream(std::FILE* fp, char* buffer, size_t bufferSize) : fp_(fp), buffer_(buffer), bufferSize_(bufferSize), bufferLast_(0), current_(buffer_), readCount_(0), count_(0), eof_(false) { 45 | RAPIDJSON_ASSERT(fp_ != 0); 46 | RAPIDJSON_ASSERT(bufferSize >= 4); 47 | Read(); 48 | } 49 | 50 | Ch Peek() const { return *current_; } 51 | Ch Take() { Ch c = *current_; Read(); return c; } 52 | size_t Tell() const { return count_ + static_cast(current_ - buffer_); } 53 | 54 | // Not implemented 55 | void Put(Ch) { RAPIDJSON_ASSERT(false); } 56 | void Flush() { RAPIDJSON_ASSERT(false); } 57 | Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } 58 | size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; } 59 | 60 | // For encoding detection only. 61 | const Ch* Peek4() const { 62 | return (current_ + 4 - !eof_ <= bufferLast_) ? current_ : 0; 63 | } 64 | 65 | private: 66 | void Read() { 67 | if (current_ < bufferLast_) 68 | ++current_; 69 | else if (!eof_) { 70 | count_ += readCount_; 71 | readCount_ = std::fread(buffer_, 1, bufferSize_, fp_); 72 | bufferLast_ = buffer_ + readCount_ - 1; 73 | current_ = buffer_; 74 | 75 | if (readCount_ < bufferSize_) { 76 | buffer_[readCount_] = '\0'; 77 | ++bufferLast_; 78 | eof_ = true; 79 | } 80 | } 81 | } 82 | 83 | std::FILE* fp_; 84 | Ch *buffer_; 85 | size_t bufferSize_; 86 | Ch *bufferLast_; 87 | Ch *current_; 88 | size_t readCount_; 89 | size_t count_; //!< Number of characters read 90 | bool eof_; 91 | }; 92 | 93 | RAPIDJSON_NAMESPACE_END 94 | 95 | #ifdef __clang__ 96 | RAPIDJSON_DIAG_POP 97 | #endif 98 | 99 | #endif // RAPIDJSON_FILESTREAM_H_ 100 | -------------------------------------------------------------------------------- /rapidjson/filewritestream.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making RapidJSON available. 2 | // 3 | // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. 4 | // 5 | // Licensed under the MIT License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // http://opensource.org/licenses/MIT 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #ifndef RAPIDJSON_FILEWRITESTREAM_H_ 16 | #define RAPIDJSON_FILEWRITESTREAM_H_ 17 | 18 | #include "stream.h" 19 | #include 20 | 21 | #ifdef __clang__ 22 | RAPIDJSON_DIAG_PUSH 23 | RAPIDJSON_DIAG_OFF(unreachable-code) 24 | #endif 25 | 26 | RAPIDJSON_NAMESPACE_BEGIN 27 | 28 | //! Wrapper of C file stream for output using fwrite(). 29 | /*! 30 | \note implements Stream concept 31 | */ 32 | class FileWriteStream { 33 | public: 34 | typedef char Ch; //!< Character type. Only support char. 35 | 36 | FileWriteStream(std::FILE* fp, char* buffer, size_t bufferSize) : fp_(fp), buffer_(buffer), bufferEnd_(buffer + bufferSize), current_(buffer_) { 37 | RAPIDJSON_ASSERT(fp_ != 0); 38 | } 39 | 40 | void Put(char c) { 41 | if (current_ >= bufferEnd_) 42 | Flush(); 43 | 44 | *current_++ = c; 45 | } 46 | 47 | void PutN(char c, size_t n) { 48 | size_t avail = static_cast(bufferEnd_ - current_); 49 | while (n > avail) { 50 | std::memset(current_, c, avail); 51 | current_ += avail; 52 | Flush(); 53 | n -= avail; 54 | avail = static_cast(bufferEnd_ - current_); 55 | } 56 | 57 | if (n > 0) { 58 | std::memset(current_, c, n); 59 | current_ += n; 60 | } 61 | } 62 | 63 | void Flush() { 64 | if (current_ != buffer_) { 65 | size_t result = std::fwrite(buffer_, 1, static_cast(current_ - buffer_), fp_); 66 | if (result < static_cast(current_ - buffer_)) { 67 | // failure deliberately ignored at this time 68 | // added to avoid warn_unused_result build errors 69 | } 70 | current_ = buffer_; 71 | } 72 | } 73 | 74 | // Not implemented 75 | char Peek() const { RAPIDJSON_ASSERT(false); return 0; } 76 | char Take() { RAPIDJSON_ASSERT(false); return 0; } 77 | size_t Tell() const { RAPIDJSON_ASSERT(false); return 0; } 78 | char* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } 79 | size_t PutEnd(char*) { RAPIDJSON_ASSERT(false); return 0; } 80 | 81 | private: 82 | // Prohibit copy constructor & assignment operator. 83 | FileWriteStream(const FileWriteStream&); 84 | FileWriteStream& operator=(const FileWriteStream&); 85 | 86 | std::FILE* fp_; 87 | char *buffer_; 88 | char *bufferEnd_; 89 | char *current_; 90 | }; 91 | 92 | //! Implement specialized version of PutN() with memset() for better performance. 93 | template<> 94 | inline void PutN(FileWriteStream& stream, char c, size_t n) { 95 | stream.PutN(c, n); 96 | } 97 | 98 | RAPIDJSON_NAMESPACE_END 99 | 100 | #ifdef __clang__ 101 | RAPIDJSON_DIAG_POP 102 | #endif 103 | 104 | #endif // RAPIDJSON_FILESTREAM_H_ 105 | -------------------------------------------------------------------------------- /rapidjson/fwd.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making RapidJSON available. 2 | // 3 | // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. 4 | // 5 | // Licensed under the MIT License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // http://opensource.org/licenses/MIT 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #ifndef RAPIDJSON_FWD_H_ 16 | #define RAPIDJSON_FWD_H_ 17 | 18 | #include "rapidjson.h" 19 | 20 | RAPIDJSON_NAMESPACE_BEGIN 21 | 22 | // encodings.h 23 | 24 | template struct UTF8; 25 | template struct UTF16; 26 | template struct UTF16BE; 27 | template struct UTF16LE; 28 | template struct UTF32; 29 | template struct UTF32BE; 30 | template struct UTF32LE; 31 | template struct ASCII; 32 | template struct AutoUTF; 33 | 34 | template 35 | struct Transcoder; 36 | 37 | // allocators.h 38 | 39 | class CrtAllocator; 40 | 41 | template 42 | class MemoryPoolAllocator; 43 | 44 | // stream.h 45 | 46 | template 47 | struct GenericStringStream; 48 | 49 | typedef GenericStringStream > StringStream; 50 | 51 | template 52 | struct GenericInsituStringStream; 53 | 54 | typedef GenericInsituStringStream > InsituStringStream; 55 | 56 | // stringbuffer.h 57 | 58 | template 59 | class GenericStringBuffer; 60 | 61 | typedef GenericStringBuffer, CrtAllocator> StringBuffer; 62 | 63 | // filereadstream.h 64 | 65 | class FileReadStream; 66 | 67 | // filewritestream.h 68 | 69 | class FileWriteStream; 70 | 71 | // memorybuffer.h 72 | 73 | template 74 | struct GenericMemoryBuffer; 75 | 76 | typedef GenericMemoryBuffer MemoryBuffer; 77 | 78 | // memorystream.h 79 | 80 | struct MemoryStream; 81 | 82 | // reader.h 83 | 84 | template 85 | struct BaseReaderHandler; 86 | 87 | template 88 | class GenericReader; 89 | 90 | typedef GenericReader, UTF8, CrtAllocator> Reader; 91 | 92 | // writer.h 93 | 94 | template 95 | class Writer; 96 | 97 | // prettywriter.h 98 | 99 | template 100 | class PrettyWriter; 101 | 102 | // document.h 103 | 104 | template 105 | struct GenericMember; 106 | 107 | template 108 | class GenericMemberIterator; 109 | 110 | template 111 | struct GenericStringRef; 112 | 113 | template 114 | class GenericValue; 115 | 116 | typedef GenericValue, MemoryPoolAllocator > Value; 117 | 118 | template 119 | class GenericDocument; 120 | 121 | typedef GenericDocument, MemoryPoolAllocator, CrtAllocator> Document; 122 | 123 | // pointer.h 124 | 125 | template 126 | class GenericPointer; 127 | 128 | typedef GenericPointer Pointer; 129 | 130 | // schema.h 131 | 132 | template 133 | class IGenericRemoteSchemaDocumentProvider; 134 | 135 | template 136 | class GenericSchemaDocument; 137 | 138 | typedef GenericSchemaDocument SchemaDocument; 139 | typedef IGenericRemoteSchemaDocumentProvider IRemoteSchemaDocumentProvider; 140 | 141 | template < 142 | typename SchemaDocumentType, 143 | typename OutputHandler, 144 | typename StateAllocator> 145 | class GenericSchemaValidator; 146 | 147 | typedef GenericSchemaValidator, void>, CrtAllocator> SchemaValidator; 148 | 149 | RAPIDJSON_NAMESPACE_END 150 | 151 | #endif // RAPIDJSON_RAPIDJSONFWD_H_ 152 | -------------------------------------------------------------------------------- /rapidjson/internal/ieee754.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making RapidJSON available. 2 | // 3 | // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. 4 | // 5 | // Licensed under the MIT License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // http://opensource.org/licenses/MIT 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #ifndef RAPIDJSON_IEEE754_ 16 | #define RAPIDJSON_IEEE754_ 17 | 18 | #include "../rapidjson.h" 19 | 20 | RAPIDJSON_NAMESPACE_BEGIN 21 | namespace internal { 22 | 23 | class Double { 24 | public: 25 | Double() {} 26 | Double(double d) : d_(d) {} 27 | Double(uint64_t u) : u_(u) {} 28 | 29 | double Value() const { return d_; } 30 | uint64_t Uint64Value() const { return u_; } 31 | 32 | double NextPositiveDouble() const { 33 | RAPIDJSON_ASSERT(!Sign()); 34 | return Double(u_ + 1).Value(); 35 | } 36 | 37 | bool Sign() const { return (u_ & kSignMask) != 0; } 38 | uint64_t Significand() const { return u_ & kSignificandMask; } 39 | int Exponent() const { return static_cast(((u_ & kExponentMask) >> kSignificandSize) - kExponentBias); } 40 | 41 | bool IsNan() const { return (u_ & kExponentMask) == kExponentMask && Significand() != 0; } 42 | bool IsInf() const { return (u_ & kExponentMask) == kExponentMask && Significand() == 0; } 43 | bool IsNanOrInf() const { return (u_ & kExponentMask) == kExponentMask; } 44 | bool IsNormal() const { return (u_ & kExponentMask) != 0 || Significand() == 0; } 45 | bool IsZero() const { return (u_ & (kExponentMask | kSignificandMask)) == 0; } 46 | 47 | uint64_t IntegerSignificand() const { return IsNormal() ? Significand() | kHiddenBit : Significand(); } 48 | int IntegerExponent() const { return (IsNormal() ? Exponent() : kDenormalExponent) - kSignificandSize; } 49 | uint64_t ToBias() const { return (u_ & kSignMask) ? ~u_ + 1 : u_ | kSignMask; } 50 | 51 | static int EffectiveSignificandSize(int order) { 52 | if (order >= -1021) 53 | return 53; 54 | else if (order <= -1074) 55 | return 0; 56 | else 57 | return order + 1074; 58 | } 59 | 60 | private: 61 | static const int kSignificandSize = 52; 62 | static const int kExponentBias = 0x3FF; 63 | static const int kDenormalExponent = 1 - kExponentBias; 64 | static const uint64_t kSignMask = RAPIDJSON_UINT64_C2(0x80000000, 0x00000000); 65 | static const uint64_t kExponentMask = RAPIDJSON_UINT64_C2(0x7FF00000, 0x00000000); 66 | static const uint64_t kSignificandMask = RAPIDJSON_UINT64_C2(0x000FFFFF, 0xFFFFFFFF); 67 | static const uint64_t kHiddenBit = RAPIDJSON_UINT64_C2(0x00100000, 0x00000000); 68 | 69 | union { 70 | double d_; 71 | uint64_t u_; 72 | }; 73 | }; 74 | 75 | } // namespace internal 76 | RAPIDJSON_NAMESPACE_END 77 | 78 | #endif // RAPIDJSON_IEEE754_ 79 | -------------------------------------------------------------------------------- /rapidjson/internal/meta.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making RapidJSON available. 2 | // 3 | // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. 4 | // 5 | // Licensed under the MIT License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // http://opensource.org/licenses/MIT 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #ifndef RAPIDJSON_INTERNAL_META_H_ 16 | #define RAPIDJSON_INTERNAL_META_H_ 17 | 18 | #include "../rapidjson.h" 19 | 20 | #ifdef __GNUC__ 21 | RAPIDJSON_DIAG_PUSH 22 | RAPIDJSON_DIAG_OFF(effc++) 23 | #endif 24 | 25 | #if defined(_MSC_VER) && !defined(__clang__) 26 | RAPIDJSON_DIAG_PUSH 27 | RAPIDJSON_DIAG_OFF(6334) 28 | #endif 29 | 30 | #if RAPIDJSON_HAS_CXX11_TYPETRAITS 31 | #include 32 | #endif 33 | 34 | //@cond RAPIDJSON_INTERNAL 35 | RAPIDJSON_NAMESPACE_BEGIN 36 | namespace internal { 37 | 38 | // Helper to wrap/convert arbitrary types to void, useful for arbitrary type matching 39 | template struct Void { typedef void Type; }; 40 | 41 | /////////////////////////////////////////////////////////////////////////////// 42 | // BoolType, TrueType, FalseType 43 | // 44 | template struct BoolType { 45 | static const bool Value = Cond; 46 | typedef BoolType Type; 47 | }; 48 | typedef BoolType TrueType; 49 | typedef BoolType FalseType; 50 | 51 | 52 | /////////////////////////////////////////////////////////////////////////////// 53 | // SelectIf, BoolExpr, NotExpr, AndExpr, OrExpr 54 | // 55 | 56 | template struct SelectIfImpl { template struct Apply { typedef T1 Type; }; }; 57 | template <> struct SelectIfImpl { template struct Apply { typedef T2 Type; }; }; 58 | template struct SelectIfCond : SelectIfImpl::template Apply {}; 59 | template struct SelectIf : SelectIfCond {}; 60 | 61 | template struct AndExprCond : FalseType {}; 62 | template <> struct AndExprCond : TrueType {}; 63 | template struct OrExprCond : TrueType {}; 64 | template <> struct OrExprCond : FalseType {}; 65 | 66 | template struct BoolExpr : SelectIf::Type {}; 67 | template struct NotExpr : SelectIf::Type {}; 68 | template struct AndExpr : AndExprCond::Type {}; 69 | template struct OrExpr : OrExprCond::Type {}; 70 | 71 | 72 | /////////////////////////////////////////////////////////////////////////////// 73 | // AddConst, MaybeAddConst, RemoveConst 74 | template struct AddConst { typedef const T Type; }; 75 | template struct MaybeAddConst : SelectIfCond {}; 76 | template struct RemoveConst { typedef T Type; }; 77 | template struct RemoveConst { typedef T Type; }; 78 | 79 | 80 | /////////////////////////////////////////////////////////////////////////////// 81 | // IsSame, IsConst, IsMoreConst, IsPointer 82 | // 83 | template struct IsSame : FalseType {}; 84 | template struct IsSame : TrueType {}; 85 | 86 | template struct IsConst : FalseType {}; 87 | template struct IsConst : TrueType {}; 88 | 89 | template 90 | struct IsMoreConst 91 | : AndExpr::Type, typename RemoveConst::Type>, 92 | BoolType::Value >= IsConst::Value> >::Type {}; 93 | 94 | template struct IsPointer : FalseType {}; 95 | template struct IsPointer : TrueType {}; 96 | 97 | /////////////////////////////////////////////////////////////////////////////// 98 | // IsBaseOf 99 | // 100 | #if RAPIDJSON_HAS_CXX11_TYPETRAITS 101 | 102 | template struct IsBaseOf 103 | : BoolType< ::std::is_base_of::value> {}; 104 | 105 | #else // simplified version adopted from Boost 106 | 107 | template struct IsBaseOfImpl { 108 | RAPIDJSON_STATIC_ASSERT(sizeof(B) != 0); 109 | RAPIDJSON_STATIC_ASSERT(sizeof(D) != 0); 110 | 111 | typedef char (&Yes)[1]; 112 | typedef char (&No) [2]; 113 | 114 | template 115 | static Yes Check(const D*, T); 116 | static No Check(const B*, int); 117 | 118 | struct Host { 119 | operator const B*() const; 120 | operator const D*(); 121 | }; 122 | 123 | enum { Value = (sizeof(Check(Host(), 0)) == sizeof(Yes)) }; 124 | }; 125 | 126 | template struct IsBaseOf 127 | : OrExpr, BoolExpr > >::Type {}; 128 | 129 | #endif // RAPIDJSON_HAS_CXX11_TYPETRAITS 130 | 131 | 132 | ////////////////////////////////////////////////////////////////////////// 133 | // EnableIf / DisableIf 134 | // 135 | template struct EnableIfCond { typedef T Type; }; 136 | template struct EnableIfCond { /* empty */ }; 137 | 138 | template struct DisableIfCond { typedef T Type; }; 139 | template struct DisableIfCond { /* empty */ }; 140 | 141 | template 142 | struct EnableIf : EnableIfCond {}; 143 | 144 | template 145 | struct DisableIf : DisableIfCond {}; 146 | 147 | // SFINAE helpers 148 | struct SfinaeTag {}; 149 | template struct RemoveSfinaeTag; 150 | template struct RemoveSfinaeTag { typedef T Type; }; 151 | 152 | #define RAPIDJSON_REMOVEFPTR_(type) \ 153 | typename ::RAPIDJSON_NAMESPACE::internal::RemoveSfinaeTag \ 154 | < ::RAPIDJSON_NAMESPACE::internal::SfinaeTag&(*) type>::Type 155 | 156 | #define RAPIDJSON_ENABLEIF(cond) \ 157 | typename ::RAPIDJSON_NAMESPACE::internal::EnableIf \ 158 | ::Type * = NULL 159 | 160 | #define RAPIDJSON_DISABLEIF(cond) \ 161 | typename ::RAPIDJSON_NAMESPACE::internal::DisableIf \ 162 | ::Type * = NULL 163 | 164 | #define RAPIDJSON_ENABLEIF_RETURN(cond,returntype) \ 165 | typename ::RAPIDJSON_NAMESPACE::internal::EnableIf \ 166 | ::Type 168 | 169 | #define RAPIDJSON_DISABLEIF_RETURN(cond,returntype) \ 170 | typename ::RAPIDJSON_NAMESPACE::internal::DisableIf \ 171 | ::Type 173 | 174 | } // namespace internal 175 | RAPIDJSON_NAMESPACE_END 176 | //@endcond 177 | 178 | #if defined(_MSC_VER) && !defined(__clang__) 179 | RAPIDJSON_DIAG_POP 180 | #endif 181 | 182 | #ifdef __GNUC__ 183 | RAPIDJSON_DIAG_POP 184 | #endif 185 | 186 | #endif // RAPIDJSON_INTERNAL_META_H_ 187 | -------------------------------------------------------------------------------- /rapidjson/internal/pow10.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making RapidJSON available. 2 | // 3 | // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. 4 | // 5 | // Licensed under the MIT License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // http://opensource.org/licenses/MIT 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #ifndef RAPIDJSON_POW10_ 16 | #define RAPIDJSON_POW10_ 17 | 18 | #include "../rapidjson.h" 19 | 20 | RAPIDJSON_NAMESPACE_BEGIN 21 | namespace internal { 22 | 23 | //! Computes integer powers of 10 in double (10.0^n). 24 | /*! This function uses lookup table for fast and accurate results. 25 | \param n non-negative exponent. Must <= 308. 26 | \return 10.0^n 27 | */ 28 | inline double Pow10(int n) { 29 | static const double e[] = { // 1e-0...1e308: 309 * 8 bytes = 2472 bytes 30 | 1e+0, 31 | 1e+1, 1e+2, 1e+3, 1e+4, 1e+5, 1e+6, 1e+7, 1e+8, 1e+9, 1e+10, 1e+11, 1e+12, 1e+13, 1e+14, 1e+15, 1e+16, 1e+17, 1e+18, 1e+19, 1e+20, 32 | 1e+21, 1e+22, 1e+23, 1e+24, 1e+25, 1e+26, 1e+27, 1e+28, 1e+29, 1e+30, 1e+31, 1e+32, 1e+33, 1e+34, 1e+35, 1e+36, 1e+37, 1e+38, 1e+39, 1e+40, 33 | 1e+41, 1e+42, 1e+43, 1e+44, 1e+45, 1e+46, 1e+47, 1e+48, 1e+49, 1e+50, 1e+51, 1e+52, 1e+53, 1e+54, 1e+55, 1e+56, 1e+57, 1e+58, 1e+59, 1e+60, 34 | 1e+61, 1e+62, 1e+63, 1e+64, 1e+65, 1e+66, 1e+67, 1e+68, 1e+69, 1e+70, 1e+71, 1e+72, 1e+73, 1e+74, 1e+75, 1e+76, 1e+77, 1e+78, 1e+79, 1e+80, 35 | 1e+81, 1e+82, 1e+83, 1e+84, 1e+85, 1e+86, 1e+87, 1e+88, 1e+89, 1e+90, 1e+91, 1e+92, 1e+93, 1e+94, 1e+95, 1e+96, 1e+97, 1e+98, 1e+99, 1e+100, 36 | 1e+101,1e+102,1e+103,1e+104,1e+105,1e+106,1e+107,1e+108,1e+109,1e+110,1e+111,1e+112,1e+113,1e+114,1e+115,1e+116,1e+117,1e+118,1e+119,1e+120, 37 | 1e+121,1e+122,1e+123,1e+124,1e+125,1e+126,1e+127,1e+128,1e+129,1e+130,1e+131,1e+132,1e+133,1e+134,1e+135,1e+136,1e+137,1e+138,1e+139,1e+140, 38 | 1e+141,1e+142,1e+143,1e+144,1e+145,1e+146,1e+147,1e+148,1e+149,1e+150,1e+151,1e+152,1e+153,1e+154,1e+155,1e+156,1e+157,1e+158,1e+159,1e+160, 39 | 1e+161,1e+162,1e+163,1e+164,1e+165,1e+166,1e+167,1e+168,1e+169,1e+170,1e+171,1e+172,1e+173,1e+174,1e+175,1e+176,1e+177,1e+178,1e+179,1e+180, 40 | 1e+181,1e+182,1e+183,1e+184,1e+185,1e+186,1e+187,1e+188,1e+189,1e+190,1e+191,1e+192,1e+193,1e+194,1e+195,1e+196,1e+197,1e+198,1e+199,1e+200, 41 | 1e+201,1e+202,1e+203,1e+204,1e+205,1e+206,1e+207,1e+208,1e+209,1e+210,1e+211,1e+212,1e+213,1e+214,1e+215,1e+216,1e+217,1e+218,1e+219,1e+220, 42 | 1e+221,1e+222,1e+223,1e+224,1e+225,1e+226,1e+227,1e+228,1e+229,1e+230,1e+231,1e+232,1e+233,1e+234,1e+235,1e+236,1e+237,1e+238,1e+239,1e+240, 43 | 1e+241,1e+242,1e+243,1e+244,1e+245,1e+246,1e+247,1e+248,1e+249,1e+250,1e+251,1e+252,1e+253,1e+254,1e+255,1e+256,1e+257,1e+258,1e+259,1e+260, 44 | 1e+261,1e+262,1e+263,1e+264,1e+265,1e+266,1e+267,1e+268,1e+269,1e+270,1e+271,1e+272,1e+273,1e+274,1e+275,1e+276,1e+277,1e+278,1e+279,1e+280, 45 | 1e+281,1e+282,1e+283,1e+284,1e+285,1e+286,1e+287,1e+288,1e+289,1e+290,1e+291,1e+292,1e+293,1e+294,1e+295,1e+296,1e+297,1e+298,1e+299,1e+300, 46 | 1e+301,1e+302,1e+303,1e+304,1e+305,1e+306,1e+307,1e+308 47 | }; 48 | RAPIDJSON_ASSERT(n >= 0 && n <= 308); 49 | return e[n]; 50 | } 51 | 52 | } // namespace internal 53 | RAPIDJSON_NAMESPACE_END 54 | 55 | #endif // RAPIDJSON_POW10_ 56 | -------------------------------------------------------------------------------- /rapidjson/internal/stack.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making RapidJSON available. 2 | // 3 | // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. 4 | // 5 | // Licensed under the MIT License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // http://opensource.org/licenses/MIT 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #ifndef RAPIDJSON_INTERNAL_STACK_H_ 16 | #define RAPIDJSON_INTERNAL_STACK_H_ 17 | 18 | #include "../allocators.h" 19 | #include "swap.h" 20 | #include 21 | 22 | #if defined(__clang__) 23 | RAPIDJSON_DIAG_PUSH 24 | RAPIDJSON_DIAG_OFF(c++98-compat) 25 | #endif 26 | 27 | RAPIDJSON_NAMESPACE_BEGIN 28 | namespace internal { 29 | 30 | /////////////////////////////////////////////////////////////////////////////// 31 | // Stack 32 | 33 | //! A type-unsafe stack for storing different types of data. 34 | /*! \tparam Allocator Allocator for allocating stack memory. 35 | */ 36 | template 37 | class Stack { 38 | public: 39 | // Optimization note: Do not allocate memory for stack_ in constructor. 40 | // Do it lazily when first Push() -> Expand() -> Resize(). 41 | Stack(Allocator* allocator, size_t stackCapacity) : allocator_(allocator), ownAllocator_(0), stack_(0), stackTop_(0), stackEnd_(0), initialCapacity_(stackCapacity) { 42 | } 43 | 44 | #if RAPIDJSON_HAS_CXX11_RVALUE_REFS 45 | Stack(Stack&& rhs) 46 | : allocator_(rhs.allocator_), 47 | ownAllocator_(rhs.ownAllocator_), 48 | stack_(rhs.stack_), 49 | stackTop_(rhs.stackTop_), 50 | stackEnd_(rhs.stackEnd_), 51 | initialCapacity_(rhs.initialCapacity_) 52 | { 53 | rhs.allocator_ = 0; 54 | rhs.ownAllocator_ = 0; 55 | rhs.stack_ = 0; 56 | rhs.stackTop_ = 0; 57 | rhs.stackEnd_ = 0; 58 | rhs.initialCapacity_ = 0; 59 | } 60 | #endif 61 | 62 | ~Stack() { 63 | Destroy(); 64 | } 65 | 66 | #if RAPIDJSON_HAS_CXX11_RVALUE_REFS 67 | Stack& operator=(Stack&& rhs) { 68 | if (&rhs != this) 69 | { 70 | Destroy(); 71 | 72 | allocator_ = rhs.allocator_; 73 | ownAllocator_ = rhs.ownAllocator_; 74 | stack_ = rhs.stack_; 75 | stackTop_ = rhs.stackTop_; 76 | stackEnd_ = rhs.stackEnd_; 77 | initialCapacity_ = rhs.initialCapacity_; 78 | 79 | rhs.allocator_ = 0; 80 | rhs.ownAllocator_ = 0; 81 | rhs.stack_ = 0; 82 | rhs.stackTop_ = 0; 83 | rhs.stackEnd_ = 0; 84 | rhs.initialCapacity_ = 0; 85 | } 86 | return *this; 87 | } 88 | #endif 89 | 90 | void Swap(Stack& rhs) RAPIDJSON_NOEXCEPT { 91 | internal::Swap(allocator_, rhs.allocator_); 92 | internal::Swap(ownAllocator_, rhs.ownAllocator_); 93 | internal::Swap(stack_, rhs.stack_); 94 | internal::Swap(stackTop_, rhs.stackTop_); 95 | internal::Swap(stackEnd_, rhs.stackEnd_); 96 | internal::Swap(initialCapacity_, rhs.initialCapacity_); 97 | } 98 | 99 | void Clear() { stackTop_ = stack_; } 100 | 101 | void ShrinkToFit() { 102 | if (Empty()) { 103 | // If the stack is empty, completely deallocate the memory. 104 | Allocator::Free(stack_); // NOLINT (+clang-analyzer-unix.Malloc) 105 | stack_ = 0; 106 | stackTop_ = 0; 107 | stackEnd_ = 0; 108 | } 109 | else 110 | Resize(GetSize()); 111 | } 112 | 113 | // Optimization note: try to minimize the size of this function for force inline. 114 | // Expansion is run very infrequently, so it is moved to another (probably non-inline) function. 115 | template 116 | RAPIDJSON_FORCEINLINE void Reserve(size_t count = 1) { 117 | // Expand the stack if needed 118 | if (RAPIDJSON_UNLIKELY(static_cast(sizeof(T) * count) > (stackEnd_ - stackTop_))) 119 | Expand(count); 120 | } 121 | 122 | template 123 | RAPIDJSON_FORCEINLINE T* Push(size_t count = 1) { 124 | Reserve(count); 125 | return PushUnsafe(count); 126 | } 127 | 128 | template 129 | RAPIDJSON_FORCEINLINE T* PushUnsafe(size_t count = 1) { 130 | RAPIDJSON_ASSERT(stackTop_); 131 | RAPIDJSON_ASSERT(static_cast(sizeof(T) * count) <= (stackEnd_ - stackTop_)); 132 | T* ret = reinterpret_cast(stackTop_); 133 | stackTop_ += sizeof(T) * count; 134 | return ret; 135 | } 136 | 137 | template 138 | T* Pop(size_t count) { 139 | RAPIDJSON_ASSERT(GetSize() >= count * sizeof(T)); 140 | stackTop_ -= count * sizeof(T); 141 | return reinterpret_cast(stackTop_); 142 | } 143 | 144 | template 145 | T* Top() { 146 | RAPIDJSON_ASSERT(GetSize() >= sizeof(T)); 147 | return reinterpret_cast(stackTop_ - sizeof(T)); 148 | } 149 | 150 | template 151 | const T* Top() const { 152 | RAPIDJSON_ASSERT(GetSize() >= sizeof(T)); 153 | return reinterpret_cast(stackTop_ - sizeof(T)); 154 | } 155 | 156 | template 157 | T* End() { return reinterpret_cast(stackTop_); } 158 | 159 | template 160 | const T* End() const { return reinterpret_cast(stackTop_); } 161 | 162 | template 163 | T* Bottom() { return reinterpret_cast(stack_); } 164 | 165 | template 166 | const T* Bottom() const { return reinterpret_cast(stack_); } 167 | 168 | bool HasAllocator() const { 169 | return allocator_ != 0; 170 | } 171 | 172 | Allocator& GetAllocator() { 173 | RAPIDJSON_ASSERT(allocator_); 174 | return *allocator_; 175 | } 176 | 177 | bool Empty() const { return stackTop_ == stack_; } 178 | size_t GetSize() const { return static_cast(stackTop_ - stack_); } 179 | size_t GetCapacity() const { return static_cast(stackEnd_ - stack_); } 180 | 181 | private: 182 | template 183 | void Expand(size_t count) { 184 | // Only expand the capacity if the current stack exists. Otherwise just create a stack with initial capacity. 185 | size_t newCapacity; 186 | if (stack_ == 0) { 187 | if (!allocator_) 188 | ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator)(); 189 | newCapacity = initialCapacity_; 190 | } else { 191 | newCapacity = GetCapacity(); 192 | newCapacity += (newCapacity + 1) / 2; 193 | } 194 | size_t newSize = GetSize() + sizeof(T) * count; 195 | if (newCapacity < newSize) 196 | newCapacity = newSize; 197 | 198 | Resize(newCapacity); 199 | } 200 | 201 | void Resize(size_t newCapacity) { 202 | const size_t size = GetSize(); // Backup the current size 203 | stack_ = static_cast(allocator_->Realloc(stack_, GetCapacity(), newCapacity)); 204 | stackTop_ = stack_ + size; 205 | stackEnd_ = stack_ + newCapacity; 206 | } 207 | 208 | void Destroy() { 209 | Allocator::Free(stack_); 210 | RAPIDJSON_DELETE(ownAllocator_); // Only delete if it is owned by the stack 211 | } 212 | 213 | // Prohibit copy constructor & assignment operator. 214 | Stack(const Stack&); 215 | Stack& operator=(const Stack&); 216 | 217 | Allocator* allocator_; 218 | Allocator* ownAllocator_; 219 | char *stack_; 220 | char *stackTop_; 221 | char *stackEnd_; 222 | size_t initialCapacity_; 223 | }; 224 | 225 | } // namespace internal 226 | RAPIDJSON_NAMESPACE_END 227 | 228 | #if defined(__clang__) 229 | RAPIDJSON_DIAG_POP 230 | #endif 231 | 232 | #endif // RAPIDJSON_STACK_H_ 233 | -------------------------------------------------------------------------------- /rapidjson/internal/strfunc.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making RapidJSON available. 2 | // 3 | // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. 4 | // 5 | // Licensed under the MIT License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // http://opensource.org/licenses/MIT 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #ifndef RAPIDJSON_INTERNAL_STRFUNC_H_ 16 | #define RAPIDJSON_INTERNAL_STRFUNC_H_ 17 | 18 | #include "../stream.h" 19 | #include 20 | 21 | RAPIDJSON_NAMESPACE_BEGIN 22 | namespace internal { 23 | 24 | //! Custom strlen() which works on different character types. 25 | /*! \tparam Ch Character type (e.g. char, wchar_t, short) 26 | \param s Null-terminated input string. 27 | \return Number of characters in the string. 28 | \note This has the same semantics as strlen(), the return value is not number of Unicode codepoints. 29 | */ 30 | template 31 | inline SizeType StrLen(const Ch* s) { 32 | RAPIDJSON_ASSERT(s != 0); 33 | const Ch* p = s; 34 | while (*p) ++p; 35 | return SizeType(p - s); 36 | } 37 | 38 | template <> 39 | inline SizeType StrLen(const char* s) { 40 | return SizeType(std::strlen(s)); 41 | } 42 | 43 | template <> 44 | inline SizeType StrLen(const wchar_t* s) { 45 | return SizeType(std::wcslen(s)); 46 | } 47 | 48 | //! Returns number of code points in a encoded string. 49 | template 50 | bool CountStringCodePoint(const typename Encoding::Ch* s, SizeType length, SizeType* outCount) { 51 | RAPIDJSON_ASSERT(s != 0); 52 | RAPIDJSON_ASSERT(outCount != 0); 53 | GenericStringStream is(s); 54 | const typename Encoding::Ch* end = s + length; 55 | SizeType count = 0; 56 | while (is.src_ < end) { 57 | unsigned codepoint; 58 | if (!Encoding::Decode(is, &codepoint)) 59 | return false; 60 | count++; 61 | } 62 | *outCount = count; 63 | return true; 64 | } 65 | 66 | } // namespace internal 67 | RAPIDJSON_NAMESPACE_END 68 | 69 | #endif // RAPIDJSON_INTERNAL_STRFUNC_H_ 70 | -------------------------------------------------------------------------------- /rapidjson/internal/swap.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making RapidJSON available. 2 | // 3 | // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. 4 | // 5 | // Licensed under the MIT License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // http://opensource.org/licenses/MIT 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #ifndef RAPIDJSON_INTERNAL_SWAP_H_ 16 | #define RAPIDJSON_INTERNAL_SWAP_H_ 17 | 18 | #include "../rapidjson.h" 19 | 20 | #if defined(__clang__) 21 | RAPIDJSON_DIAG_PUSH 22 | RAPIDJSON_DIAG_OFF(c++98-compat) 23 | #endif 24 | 25 | RAPIDJSON_NAMESPACE_BEGIN 26 | namespace internal { 27 | 28 | //! Custom swap() to avoid dependency on C++ header 29 | /*! \tparam T Type of the arguments to swap, should be instantiated with primitive C++ types only. 30 | \note This has the same semantics as std::swap(). 31 | */ 32 | template 33 | inline void Swap(T& a, T& b) RAPIDJSON_NOEXCEPT { 34 | T tmp = a; 35 | a = b; 36 | b = tmp; 37 | } 38 | 39 | } // namespace internal 40 | RAPIDJSON_NAMESPACE_END 41 | 42 | #if defined(__clang__) 43 | RAPIDJSON_DIAG_POP 44 | #endif 45 | 46 | #endif // RAPIDJSON_INTERNAL_SWAP_H_ 47 | -------------------------------------------------------------------------------- /rapidjson/istreamwrapper.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making RapidJSON available. 2 | // 3 | // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. 4 | // 5 | // Licensed under the MIT License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // http://opensource.org/licenses/MIT 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #ifndef RAPIDJSON_ISTREAMWRAPPER_H_ 16 | #define RAPIDJSON_ISTREAMWRAPPER_H_ 17 | 18 | #include "stream.h" 19 | #include 20 | 21 | #ifdef __clang__ 22 | RAPIDJSON_DIAG_PUSH 23 | RAPIDJSON_DIAG_OFF(padded) 24 | #elif defined(_MSC_VER) 25 | RAPIDJSON_DIAG_PUSH 26 | RAPIDJSON_DIAG_OFF(4351) // new behavior: elements of array 'array' will be default initialized 27 | #endif 28 | 29 | RAPIDJSON_NAMESPACE_BEGIN 30 | 31 | //! Wrapper of \c std::basic_istream into RapidJSON's Stream concept. 32 | /*! 33 | The classes can be wrapped including but not limited to: 34 | 35 | - \c std::istringstream 36 | - \c std::stringstream 37 | - \c std::wistringstream 38 | - \c std::wstringstream 39 | - \c std::ifstream 40 | - \c std::fstream 41 | - \c std::wifstream 42 | - \c std::wfstream 43 | 44 | \tparam StreamType Class derived from \c std::basic_istream. 45 | */ 46 | 47 | template 48 | class BasicIStreamWrapper { 49 | public: 50 | typedef typename StreamType::char_type Ch; 51 | 52 | //! Constructor. 53 | /*! 54 | \param stream stream opened for read. 55 | */ 56 | BasicIStreamWrapper(StreamType &stream) : stream_(stream), buffer_(peekBuffer_), bufferSize_(4), bufferLast_(0), current_(buffer_), readCount_(0), count_(0), eof_(false) { 57 | Read(); 58 | } 59 | 60 | //! Constructor. 61 | /*! 62 | \param stream stream opened for read. 63 | \param buffer user-supplied buffer. 64 | \param bufferSize size of buffer in bytes. Must >=4 bytes. 65 | */ 66 | BasicIStreamWrapper(StreamType &stream, char* buffer, size_t bufferSize) : stream_(stream), buffer_(buffer), bufferSize_(bufferSize), bufferLast_(0), current_(buffer_), readCount_(0), count_(0), eof_(false) { 67 | RAPIDJSON_ASSERT(bufferSize >= 4); 68 | Read(); 69 | } 70 | 71 | Ch Peek() const { return *current_; } 72 | Ch Take() { Ch c = *current_; Read(); return c; } 73 | size_t Tell() const { return count_ + static_cast(current_ - buffer_); } 74 | 75 | // Not implemented 76 | void Put(Ch) { RAPIDJSON_ASSERT(false); } 77 | void Flush() { RAPIDJSON_ASSERT(false); } 78 | Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } 79 | size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; } 80 | 81 | // For encoding detection only. 82 | const Ch* Peek4() const { 83 | return (current_ + 4 - !eof_ <= bufferLast_) ? current_ : 0; 84 | } 85 | 86 | private: 87 | BasicIStreamWrapper(); 88 | BasicIStreamWrapper(const BasicIStreamWrapper&); 89 | BasicIStreamWrapper& operator=(const BasicIStreamWrapper&); 90 | 91 | void Read() { 92 | if (current_ < bufferLast_) 93 | ++current_; 94 | else if (!eof_) { 95 | count_ += readCount_; 96 | readCount_ = bufferSize_; 97 | bufferLast_ = buffer_ + readCount_ - 1; 98 | current_ = buffer_; 99 | 100 | if (!stream_.read(buffer_, static_cast(bufferSize_))) { 101 | readCount_ = static_cast(stream_.gcount()); 102 | *(bufferLast_ = buffer_ + readCount_) = '\0'; 103 | eof_ = true; 104 | } 105 | } 106 | } 107 | 108 | StreamType &stream_; 109 | Ch peekBuffer_[4], *buffer_; 110 | size_t bufferSize_; 111 | Ch *bufferLast_; 112 | Ch *current_; 113 | size_t readCount_; 114 | size_t count_; //!< Number of characters read 115 | bool eof_; 116 | }; 117 | 118 | typedef BasicIStreamWrapper IStreamWrapper; 119 | typedef BasicIStreamWrapper WIStreamWrapper; 120 | 121 | #if defined(__clang__) || defined(_MSC_VER) 122 | RAPIDJSON_DIAG_POP 123 | #endif 124 | 125 | RAPIDJSON_NAMESPACE_END 126 | 127 | #endif // RAPIDJSON_ISTREAMWRAPPER_H_ 128 | -------------------------------------------------------------------------------- /rapidjson/memorybuffer.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making RapidJSON available. 2 | // 3 | // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. 4 | // 5 | // Licensed under the MIT License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // http://opensource.org/licenses/MIT 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #ifndef RAPIDJSON_MEMORYBUFFER_H_ 16 | #define RAPIDJSON_MEMORYBUFFER_H_ 17 | 18 | #include "stream.h" 19 | #include "internal/stack.h" 20 | 21 | RAPIDJSON_NAMESPACE_BEGIN 22 | 23 | //! Represents an in-memory output byte stream. 24 | /*! 25 | This class is mainly for being wrapped by EncodedOutputStream or AutoUTFOutputStream. 26 | 27 | It is similar to FileWriteBuffer but the destination is an in-memory buffer instead of a file. 28 | 29 | Differences between MemoryBuffer and StringBuffer: 30 | 1. StringBuffer has Encoding but MemoryBuffer is only a byte buffer. 31 | 2. StringBuffer::GetString() returns a null-terminated string. MemoryBuffer::GetBuffer() returns a buffer without terminator. 32 | 33 | \tparam Allocator type for allocating memory buffer. 34 | \note implements Stream concept 35 | */ 36 | template 37 | struct GenericMemoryBuffer { 38 | typedef char Ch; // byte 39 | 40 | GenericMemoryBuffer(Allocator* allocator = 0, size_t capacity = kDefaultCapacity) : stack_(allocator, capacity) {} 41 | 42 | void Put(Ch c) { *stack_.template Push() = c; } 43 | void Flush() {} 44 | 45 | void Clear() { stack_.Clear(); } 46 | void ShrinkToFit() { stack_.ShrinkToFit(); } 47 | Ch* Push(size_t count) { return stack_.template Push(count); } 48 | void Pop(size_t count) { stack_.template Pop(count); } 49 | 50 | const Ch* GetBuffer() const { 51 | return stack_.template Bottom(); 52 | } 53 | 54 | size_t GetSize() const { return stack_.GetSize(); } 55 | 56 | static const size_t kDefaultCapacity = 256; 57 | mutable internal::Stack stack_; 58 | }; 59 | 60 | typedef GenericMemoryBuffer<> MemoryBuffer; 61 | 62 | //! Implement specialized version of PutN() with memset() for better performance. 63 | template<> 64 | inline void PutN(MemoryBuffer& memoryBuffer, char c, size_t n) { 65 | std::memset(memoryBuffer.stack_.Push(n), c, n * sizeof(c)); 66 | } 67 | 68 | RAPIDJSON_NAMESPACE_END 69 | 70 | #endif // RAPIDJSON_MEMORYBUFFER_H_ 71 | -------------------------------------------------------------------------------- /rapidjson/memorystream.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making RapidJSON available. 2 | // 3 | // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. 4 | // 5 | // Licensed under the MIT License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // http://opensource.org/licenses/MIT 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #ifndef RAPIDJSON_MEMORYSTREAM_H_ 16 | #define RAPIDJSON_MEMORYSTREAM_H_ 17 | 18 | #include "stream.h" 19 | 20 | #ifdef __clang__ 21 | RAPIDJSON_DIAG_PUSH 22 | RAPIDJSON_DIAG_OFF(unreachable-code) 23 | RAPIDJSON_DIAG_OFF(missing-noreturn) 24 | #endif 25 | 26 | RAPIDJSON_NAMESPACE_BEGIN 27 | 28 | //! Represents an in-memory input byte stream. 29 | /*! 30 | This class is mainly for being wrapped by EncodedInputStream or AutoUTFInputStream. 31 | 32 | It is similar to FileReadBuffer but the source is an in-memory buffer instead of a file. 33 | 34 | Differences between MemoryStream and StringStream: 35 | 1. StringStream has encoding but MemoryStream is a byte stream. 36 | 2. MemoryStream needs size of the source buffer and the buffer don't need to be null terminated. StringStream assume null-terminated string as source. 37 | 3. MemoryStream supports Peek4() for encoding detection. StringStream is specified with an encoding so it should not have Peek4(). 38 | \note implements Stream concept 39 | */ 40 | struct MemoryStream { 41 | typedef char Ch; // byte 42 | 43 | MemoryStream(const Ch *src, size_t size) : src_(src), begin_(src), end_(src + size), size_(size) {} 44 | 45 | Ch Peek() const { return RAPIDJSON_UNLIKELY(src_ == end_) ? '\0' : *src_; } 46 | Ch Take() { return RAPIDJSON_UNLIKELY(src_ == end_) ? '\0' : *src_++; } 47 | size_t Tell() const { return static_cast(src_ - begin_); } 48 | 49 | Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } 50 | void Put(Ch) { RAPIDJSON_ASSERT(false); } 51 | void Flush() { RAPIDJSON_ASSERT(false); } 52 | size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; } 53 | 54 | // For encoding detection only. 55 | const Ch* Peek4() const { 56 | return Tell() + 4 <= size_ ? src_ : 0; 57 | } 58 | 59 | const Ch* src_; //!< Current read position. 60 | const Ch* begin_; //!< Original head of the string. 61 | const Ch* end_; //!< End of stream. 62 | size_t size_; //!< Size of the stream. 63 | }; 64 | 65 | RAPIDJSON_NAMESPACE_END 66 | 67 | #ifdef __clang__ 68 | RAPIDJSON_DIAG_POP 69 | #endif 70 | 71 | #endif // RAPIDJSON_MEMORYBUFFER_H_ 72 | -------------------------------------------------------------------------------- /rapidjson/ostreamwrapper.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making RapidJSON available. 2 | // 3 | // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. 4 | // 5 | // Licensed under the MIT License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // http://opensource.org/licenses/MIT 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #ifndef RAPIDJSON_OSTREAMWRAPPER_H_ 16 | #define RAPIDJSON_OSTREAMWRAPPER_H_ 17 | 18 | #include "stream.h" 19 | #include 20 | 21 | #ifdef __clang__ 22 | RAPIDJSON_DIAG_PUSH 23 | RAPIDJSON_DIAG_OFF(padded) 24 | #endif 25 | 26 | RAPIDJSON_NAMESPACE_BEGIN 27 | 28 | //! Wrapper of \c std::basic_ostream into RapidJSON's Stream concept. 29 | /*! 30 | The classes can be wrapped including but not limited to: 31 | 32 | - \c std::ostringstream 33 | - \c std::stringstream 34 | - \c std::wpstringstream 35 | - \c std::wstringstream 36 | - \c std::ifstream 37 | - \c std::fstream 38 | - \c std::wofstream 39 | - \c std::wfstream 40 | 41 | \tparam StreamType Class derived from \c std::basic_ostream. 42 | */ 43 | 44 | template 45 | class BasicOStreamWrapper { 46 | public: 47 | typedef typename StreamType::char_type Ch; 48 | BasicOStreamWrapper(StreamType& stream) : stream_(stream) {} 49 | 50 | void Put(Ch c) { 51 | stream_.put(c); 52 | } 53 | 54 | void Flush() { 55 | stream_.flush(); 56 | } 57 | 58 | // Not implemented 59 | char Peek() const { RAPIDJSON_ASSERT(false); return 0; } 60 | char Take() { RAPIDJSON_ASSERT(false); return 0; } 61 | size_t Tell() const { RAPIDJSON_ASSERT(false); return 0; } 62 | char* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } 63 | size_t PutEnd(char*) { RAPIDJSON_ASSERT(false); return 0; } 64 | 65 | private: 66 | BasicOStreamWrapper(const BasicOStreamWrapper&); 67 | BasicOStreamWrapper& operator=(const BasicOStreamWrapper&); 68 | 69 | StreamType& stream_; 70 | }; 71 | 72 | typedef BasicOStreamWrapper OStreamWrapper; 73 | typedef BasicOStreamWrapper WOStreamWrapper; 74 | 75 | #ifdef __clang__ 76 | RAPIDJSON_DIAG_POP 77 | #endif 78 | 79 | RAPIDJSON_NAMESPACE_END 80 | 81 | #endif // RAPIDJSON_OSTREAMWRAPPER_H_ 82 | -------------------------------------------------------------------------------- /rapidjson/stream.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making RapidJSON available. 2 | // 3 | // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. 4 | // 5 | // Licensed under the MIT License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // http://opensource.org/licenses/MIT 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #include "rapidjson.h" 16 | 17 | #ifndef RAPIDJSON_STREAM_H_ 18 | #define RAPIDJSON_STREAM_H_ 19 | 20 | #include "encodings.h" 21 | 22 | RAPIDJSON_NAMESPACE_BEGIN 23 | 24 | /////////////////////////////////////////////////////////////////////////////// 25 | // Stream 26 | 27 | /*! \class rapidjson::Stream 28 | \brief Concept for reading and writing characters. 29 | 30 | For read-only stream, no need to implement PutBegin(), Put(), Flush() and PutEnd(). 31 | 32 | For write-only stream, only need to implement Put() and Flush(). 33 | 34 | \code 35 | concept Stream { 36 | typename Ch; //!< Character type of the stream. 37 | 38 | //! Read the current character from stream without moving the read cursor. 39 | Ch Peek() const; 40 | 41 | //! Read the current character from stream and moving the read cursor to next character. 42 | Ch Take(); 43 | 44 | //! Get the current read cursor. 45 | //! \return Number of characters read from start. 46 | size_t Tell(); 47 | 48 | //! Begin writing operation at the current read pointer. 49 | //! \return The begin writer pointer. 50 | Ch* PutBegin(); 51 | 52 | //! Write a character. 53 | void Put(Ch c); 54 | 55 | //! Flush the buffer. 56 | void Flush(); 57 | 58 | //! End the writing operation. 59 | //! \param begin The begin write pointer returned by PutBegin(). 60 | //! \return Number of characters written. 61 | size_t PutEnd(Ch* begin); 62 | } 63 | \endcode 64 | */ 65 | 66 | //! Provides additional information for stream. 67 | /*! 68 | By using traits pattern, this type provides a default configuration for stream. 69 | For custom stream, this type can be specialized for other configuration. 70 | See TEST(Reader, CustomStringStream) in readertest.cpp for example. 71 | */ 72 | template 73 | struct StreamTraits { 74 | //! Whether to make local copy of stream for optimization during parsing. 75 | /*! 76 | By default, for safety, streams do not use local copy optimization. 77 | Stream that can be copied fast should specialize this, like StreamTraits. 78 | */ 79 | enum { copyOptimization = 0 }; 80 | }; 81 | 82 | //! Reserve n characters for writing to a stream. 83 | template 84 | inline void PutReserve(Stream& stream, size_t count) { 85 | (void)stream; 86 | (void)count; 87 | } 88 | 89 | //! Write character to a stream, presuming buffer is reserved. 90 | template 91 | inline void PutUnsafe(Stream& stream, typename Stream::Ch c) { 92 | stream.Put(c); 93 | } 94 | 95 | //! Put N copies of a character to a stream. 96 | template 97 | inline void PutN(Stream& stream, Ch c, size_t n) { 98 | PutReserve(stream, n); 99 | for (size_t i = 0; i < n; i++) 100 | PutUnsafe(stream, c); 101 | } 102 | 103 | /////////////////////////////////////////////////////////////////////////////// 104 | // GenericStreamWrapper 105 | 106 | //! A Stream Wrapper 107 | /*! \tThis string stream is a wrapper for any stream by just forwarding any 108 | \treceived message to the origin stream. 109 | \note implements Stream concept 110 | */ 111 | 112 | #if defined(_MSC_VER) && _MSC_VER <= 1800 113 | RAPIDJSON_DIAG_PUSH 114 | RAPIDJSON_DIAG_OFF(4702) // unreachable code 115 | RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated 116 | #endif 117 | 118 | template > 119 | class GenericStreamWrapper { 120 | public: 121 | typedef typename Encoding::Ch Ch; 122 | GenericStreamWrapper(InputStream& is): is_(is) {} 123 | 124 | Ch Peek() const { return is_.Peek(); } 125 | Ch Take() { return is_.Take(); } 126 | size_t Tell() { return is_.Tell(); } 127 | Ch* PutBegin() { return is_.PutBegin(); } 128 | void Put(Ch ch) { is_.Put(ch); } 129 | void Flush() { is_.Flush(); } 130 | size_t PutEnd(Ch* ch) { return is_.PutEnd(ch); } 131 | 132 | // wrapper for MemoryStream 133 | const Ch* Peek4() const { return is_.Peek4(); } 134 | 135 | // wrapper for AutoUTFInputStream 136 | UTFType GetType() const { return is_.GetType(); } 137 | bool HasBOM() const { return is_.HasBOM(); } 138 | 139 | protected: 140 | InputStream& is_; 141 | }; 142 | 143 | #if defined(_MSC_VER) && _MSC_VER <= 1800 144 | RAPIDJSON_DIAG_POP 145 | #endif 146 | 147 | /////////////////////////////////////////////////////////////////////////////// 148 | // StringStream 149 | 150 | //! Read-only string stream. 151 | /*! \note implements Stream concept 152 | */ 153 | template 154 | struct GenericStringStream { 155 | typedef typename Encoding::Ch Ch; 156 | 157 | GenericStringStream(const Ch *src) : src_(src), head_(src) {} 158 | 159 | Ch Peek() const { return *src_; } 160 | Ch Take() { return *src_++; } 161 | size_t Tell() const { return static_cast(src_ - head_); } 162 | 163 | Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } 164 | void Put(Ch) { RAPIDJSON_ASSERT(false); } 165 | void Flush() { RAPIDJSON_ASSERT(false); } 166 | size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; } 167 | 168 | const Ch* src_; //!< Current read position. 169 | const Ch* head_; //!< Original head of the string. 170 | }; 171 | 172 | template 173 | struct StreamTraits > { 174 | enum { copyOptimization = 1 }; 175 | }; 176 | 177 | //! String stream with UTF8 encoding. 178 | typedef GenericStringStream > StringStream; 179 | 180 | /////////////////////////////////////////////////////////////////////////////// 181 | // InsituStringStream 182 | 183 | //! A read-write string stream. 184 | /*! This string stream is particularly designed for in-situ parsing. 185 | \note implements Stream concept 186 | */ 187 | template 188 | struct GenericInsituStringStream { 189 | typedef typename Encoding::Ch Ch; 190 | 191 | GenericInsituStringStream(Ch *src) : src_(src), dst_(0), head_(src) {} 192 | 193 | // Read 194 | Ch Peek() { return *src_; } 195 | Ch Take() { return *src_++; } 196 | size_t Tell() { return static_cast(src_ - head_); } 197 | 198 | // Write 199 | void Put(Ch c) { RAPIDJSON_ASSERT(dst_ != 0); *dst_++ = c; } 200 | 201 | Ch* PutBegin() { return dst_ = src_; } 202 | size_t PutEnd(Ch* begin) { return static_cast(dst_ - begin); } 203 | void Flush() {} 204 | 205 | Ch* Push(size_t count) { Ch* begin = dst_; dst_ += count; return begin; } 206 | void Pop(size_t count) { dst_ -= count; } 207 | 208 | Ch* src_; 209 | Ch* dst_; 210 | Ch* head_; 211 | }; 212 | 213 | template 214 | struct StreamTraits > { 215 | enum { copyOptimization = 1 }; 216 | }; 217 | 218 | //! Insitu string stream with UTF8 encoding. 219 | typedef GenericInsituStringStream > InsituStringStream; 220 | 221 | RAPIDJSON_NAMESPACE_END 222 | 223 | #endif // RAPIDJSON_STREAM_H_ 224 | -------------------------------------------------------------------------------- /rapidjson/stringbuffer.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making RapidJSON available. 2 | // 3 | // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. 4 | // 5 | // Licensed under the MIT License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // http://opensource.org/licenses/MIT 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #ifndef RAPIDJSON_STRINGBUFFER_H_ 16 | #define RAPIDJSON_STRINGBUFFER_H_ 17 | 18 | #include "stream.h" 19 | #include "internal/stack.h" 20 | 21 | #if RAPIDJSON_HAS_CXX11_RVALUE_REFS 22 | #include // std::move 23 | #endif 24 | 25 | #include "internal/stack.h" 26 | 27 | #if defined(__clang__) 28 | RAPIDJSON_DIAG_PUSH 29 | RAPIDJSON_DIAG_OFF(c++98-compat) 30 | #endif 31 | 32 | RAPIDJSON_NAMESPACE_BEGIN 33 | 34 | //! Represents an in-memory output stream. 35 | /*! 36 | \tparam Encoding Encoding of the stream. 37 | \tparam Allocator type for allocating memory buffer. 38 | \note implements Stream concept 39 | */ 40 | template 41 | class GenericStringBuffer { 42 | public: 43 | typedef typename Encoding::Ch Ch; 44 | 45 | GenericStringBuffer(Allocator* allocator = 0, size_t capacity = kDefaultCapacity) : stack_(allocator, capacity) {} 46 | 47 | #if RAPIDJSON_HAS_CXX11_RVALUE_REFS 48 | GenericStringBuffer(GenericStringBuffer&& rhs) : stack_(std::move(rhs.stack_)) {} 49 | GenericStringBuffer& operator=(GenericStringBuffer&& rhs) { 50 | if (&rhs != this) 51 | stack_ = std::move(rhs.stack_); 52 | return *this; 53 | } 54 | #endif 55 | 56 | void Put(Ch c) { *stack_.template Push() = c; } 57 | void PutUnsafe(Ch c) { *stack_.template PushUnsafe() = c; } 58 | void Flush() {} 59 | 60 | void Clear() { stack_.Clear(); } 61 | void ShrinkToFit() { 62 | // Push and pop a null terminator. This is safe. 63 | *stack_.template Push() = '\0'; 64 | stack_.ShrinkToFit(); 65 | stack_.template Pop(1); 66 | } 67 | 68 | void Reserve(size_t count) { stack_.template Reserve(count); } 69 | Ch* Push(size_t count) { return stack_.template Push(count); } 70 | Ch* PushUnsafe(size_t count) { return stack_.template PushUnsafe(count); } 71 | void Pop(size_t count) { stack_.template Pop(count); } 72 | 73 | const Ch* GetString() const { 74 | // Push and pop a null terminator. This is safe. 75 | *stack_.template Push() = '\0'; 76 | stack_.template Pop(1); 77 | 78 | return stack_.template Bottom(); 79 | } 80 | 81 | //! Get the size of string in bytes in the string buffer. 82 | size_t GetSize() const { return stack_.GetSize(); } 83 | 84 | //! Get the length of string in Ch in the string buffer. 85 | size_t GetLength() const { return stack_.GetSize() / sizeof(Ch); } 86 | 87 | static const size_t kDefaultCapacity = 256; 88 | mutable internal::Stack stack_; 89 | 90 | private: 91 | // Prohibit copy constructor & assignment operator. 92 | GenericStringBuffer(const GenericStringBuffer&); 93 | GenericStringBuffer& operator=(const GenericStringBuffer&); 94 | }; 95 | 96 | //! String buffer with UTF8 encoding 97 | typedef GenericStringBuffer > StringBuffer; 98 | 99 | template 100 | inline void PutReserve(GenericStringBuffer& stream, size_t count) { 101 | stream.Reserve(count); 102 | } 103 | 104 | template 105 | inline void PutUnsafe(GenericStringBuffer& stream, typename Encoding::Ch c) { 106 | stream.PutUnsafe(c); 107 | } 108 | 109 | //! Implement specialized version of PutN() with memset() for better performance. 110 | template<> 111 | inline void PutN(GenericStringBuffer >& stream, char c, size_t n) { 112 | std::memset(stream.stack_.Push(n), c, n * sizeof(c)); 113 | } 114 | 115 | RAPIDJSON_NAMESPACE_END 116 | 117 | #if defined(__clang__) 118 | RAPIDJSON_DIAG_POP 119 | #endif 120 | 121 | #endif // RAPIDJSON_STRINGBUFFER_H_ 122 | -------------------------------------------------------------------------------- /rapidjson_custom.h: -------------------------------------------------------------------------------- 1 | #ifndef __X_PACK_RAPIDJSON_CUSTOME_H 2 | #define __X_PACK_RAPIDJSON_CUSTOME_H 3 | 4 | #ifndef RAPIDJSON_NOEXCEPT_ASSERT 5 | #include 6 | #define RAPIDJSON_NOEXCEPT_ASSERT(x) assert(x) 7 | #endif 8 | 9 | #ifndef RAPIDJSON_ASSERT 10 | #include 11 | #define RAPIDJSON_ASSERT(x) if(!(x)) throw std::runtime_error(#x) 12 | #endif 13 | 14 | #ifndef RAPIDJSON_WRITE_DEFAULT_FLAGS 15 | #define RAPIDJSON_WRITE_DEFAULT_FLAGS kWriteNanAndInfFlag 16 | #endif 17 | 18 | #endif 19 | 20 | -------------------------------------------------------------------------------- /rapidxml/license.txt: -------------------------------------------------------------------------------- 1 | Use of this software is granted under one of the following two licenses, 2 | to be chosen freely by the user. 3 | 4 | 1. Boost Software License - Version 1.0 - August 17th, 2003 5 | =============================================================================== 6 | 7 | Copyright (c) 2006, 2007 Marcin Kalicinski 8 | 9 | Permission is hereby granted, free of charge, to any person or organization 10 | obtaining a copy of the software and accompanying documentation covered by 11 | this license (the "Software") to use, reproduce, display, distribute, 12 | execute, and transmit the Software, and to prepare derivative works of the 13 | Software, and to permit third-parties to whom the Software is furnished to 14 | do so, all subject to the following: 15 | 16 | The copyright notices in the Software and this entire statement, including 17 | the above license grant, this restriction and the following disclaimer, 18 | must be included in all copies of the Software, in whole or in part, and 19 | all derivative works of the Software, unless such copies or derivative 20 | works are solely in the form of machine-executable object code generated by 21 | a source language processor. 22 | 23 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 24 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 25 | FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT 26 | SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE 27 | FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, 28 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 29 | DEALINGS IN THE SOFTWARE. 30 | 31 | 2. The MIT License 32 | =============================================================================== 33 | 34 | Copyright (c) 2006, 2007 Marcin Kalicinski 35 | 36 | Permission is hereby granted, free of charge, to any person obtaining a copy 37 | of this software and associated documentation files (the "Software"), to deal 38 | in the Software without restriction, including without limitation the rights 39 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 40 | of the Software, and to permit persons to whom the Software is furnished to do so, 41 | subject to the following conditions: 42 | 43 | The above copyright notice and this permission notice shall be included in all 44 | copies or substantial portions of the Software. 45 | 46 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 47 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 48 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 49 | THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 50 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 51 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 52 | IN THE SOFTWARE. 53 | -------------------------------------------------------------------------------- /rapidxml/rapidxml_iterators.hpp: -------------------------------------------------------------------------------- 1 | #ifndef RAPIDXML_ITERATORS_HPP_INCLUDED 2 | #define RAPIDXML_ITERATORS_HPP_INCLUDED 3 | 4 | // Copyright (C) 2006, 2009 Marcin Kalicinski 5 | // Version 1.13 6 | // Revision $DateTime: 2009/05/13 01:46:17 $ 7 | //! \file rapidxml_iterators.hpp This file contains rapidxml iterators 8 | 9 | #include "rapidxml.hpp" 10 | 11 | namespace rapidxml 12 | { 13 | 14 | //! Iterator of child nodes of xml_node 15 | template 16 | class node_iterator 17 | { 18 | 19 | public: 20 | 21 | typedef typename xml_node value_type; 22 | typedef typename xml_node &reference; 23 | typedef typename xml_node *pointer; 24 | typedef std::ptrdiff_t difference_type; 25 | typedef std::bidirectional_iterator_tag iterator_category; 26 | 27 | node_iterator() 28 | : m_node(0) 29 | { 30 | } 31 | 32 | node_iterator(xml_node *node) 33 | : m_node(node->first_node()) 34 | { 35 | } 36 | 37 | reference operator *() const 38 | { 39 | assert(m_node); 40 | return *m_node; 41 | } 42 | 43 | pointer operator->() const 44 | { 45 | assert(m_node); 46 | return m_node; 47 | } 48 | 49 | node_iterator& operator++() 50 | { 51 | assert(m_node); 52 | m_node = m_node->next_sibling(); 53 | return *this; 54 | } 55 | 56 | node_iterator operator++(int) 57 | { 58 | node_iterator tmp = *this; 59 | ++this; 60 | return tmp; 61 | } 62 | 63 | node_iterator& operator--() 64 | { 65 | assert(m_node && m_node->previous_sibling()); 66 | m_node = m_node->previous_sibling(); 67 | return *this; 68 | } 69 | 70 | node_iterator operator--(int) 71 | { 72 | node_iterator tmp = *this; 73 | ++this; 74 | return tmp; 75 | } 76 | 77 | bool operator ==(const node_iterator &rhs) 78 | { 79 | return m_node == rhs.m_node; 80 | } 81 | 82 | bool operator !=(const node_iterator &rhs) 83 | { 84 | return m_node != rhs.m_node; 85 | } 86 | 87 | private: 88 | 89 | xml_node *m_node; 90 | 91 | }; 92 | 93 | //! Iterator of child attributes of xml_node 94 | template 95 | class attribute_iterator 96 | { 97 | 98 | public: 99 | 100 | typedef typename xml_attribute value_type; 101 | typedef typename xml_attribute &reference; 102 | typedef typename xml_attribute *pointer; 103 | typedef std::ptrdiff_t difference_type; 104 | typedef std::bidirectional_iterator_tag iterator_category; 105 | 106 | attribute_iterator() 107 | : m_attribute(0) 108 | { 109 | } 110 | 111 | attribute_iterator(xml_node *node) 112 | : m_attribute(node->first_attribute()) 113 | { 114 | } 115 | 116 | reference operator *() const 117 | { 118 | assert(m_attribute); 119 | return *m_attribute; 120 | } 121 | 122 | pointer operator->() const 123 | { 124 | assert(m_attribute); 125 | return m_attribute; 126 | } 127 | 128 | attribute_iterator& operator++() 129 | { 130 | assert(m_attribute); 131 | m_attribute = m_attribute->next_attribute(); 132 | return *this; 133 | } 134 | 135 | attribute_iterator operator++(int) 136 | { 137 | attribute_iterator tmp = *this; 138 | ++this; 139 | return tmp; 140 | } 141 | 142 | attribute_iterator& operator--() 143 | { 144 | assert(m_attribute && m_attribute->previous_attribute()); 145 | m_attribute = m_attribute->previous_attribute(); 146 | return *this; 147 | } 148 | 149 | attribute_iterator operator--(int) 150 | { 151 | attribute_iterator tmp = *this; 152 | ++this; 153 | return tmp; 154 | } 155 | 156 | bool operator ==(const attribute_iterator &rhs) 157 | { 158 | return m_attribute == rhs.m_attribute; 159 | } 160 | 161 | bool operator !=(const attribute_iterator &rhs) 162 | { 163 | return m_attribute != rhs.m_attribute; 164 | } 165 | 166 | private: 167 | 168 | xml_attribute *m_attribute; 169 | 170 | }; 171 | 172 | } 173 | 174 | #endif 175 | -------------------------------------------------------------------------------- /rapidxml/rapidxml_utils.hpp: -------------------------------------------------------------------------------- 1 | #ifndef RAPIDXML_UTILS_HPP_INCLUDED 2 | #define RAPIDXML_UTILS_HPP_INCLUDED 3 | 4 | // Copyright (C) 2006, 2009 Marcin Kalicinski 5 | // Version 1.13 6 | // Revision $DateTime: 2009/05/13 01:46:17 $ 7 | //! \file rapidxml_utils.hpp This file contains high-level rapidxml utilities that can be useful 8 | //! in certain simple scenarios. They should probably not be used if maximizing performance is the main objective. 9 | 10 | #include "rapidxml.hpp" 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | namespace rapidxml 17 | { 18 | 19 | //! Represents data loaded from a file 20 | template 21 | class file 22 | { 23 | 24 | public: 25 | 26 | //! Loads file into the memory. Data will be automatically destroyed by the destructor. 27 | //! \param filename Filename to load. 28 | file(const char *filename) 29 | { 30 | using namespace std; 31 | 32 | // Open stream 33 | basic_ifstream stream(filename, ios::binary); 34 | if (!stream) 35 | throw runtime_error(string("cannot open file ") + filename); 36 | stream.unsetf(ios::skipws); 37 | 38 | // Determine stream size 39 | stream.seekg(0, ios::end); 40 | size_t size = stream.tellg(); 41 | stream.seekg(0); 42 | 43 | // Load data and add terminating 0 44 | m_data.resize(size + 1); 45 | stream.read(&m_data.front(), static_cast(size)); 46 | m_data[size] = 0; 47 | } 48 | 49 | //! Loads file into the memory. Data will be automatically destroyed by the destructor 50 | //! \param stream Stream to load from 51 | file(std::basic_istream &stream) 52 | { 53 | using namespace std; 54 | 55 | // Load data and add terminating 0 56 | stream.unsetf(ios::skipws); 57 | m_data.assign(istreambuf_iterator(stream), istreambuf_iterator()); 58 | if (stream.fail() || stream.bad()) 59 | throw runtime_error("error reading stream"); 60 | m_data.push_back(0); 61 | } 62 | 63 | //! Gets file data. 64 | //! \return Pointer to data of file. 65 | Ch *data() 66 | { 67 | return &m_data.front(); 68 | } 69 | 70 | //! Gets file data. 71 | //! \return Pointer to data of file. 72 | const Ch *data() const 73 | { 74 | return &m_data.front(); 75 | } 76 | 77 | //! Gets file data size. 78 | //! \return Size of file data, in characters. 79 | std::size_t size() const 80 | { 81 | return m_data.size(); 82 | } 83 | 84 | private: 85 | 86 | std::vector m_data; // File data 87 | 88 | }; 89 | 90 | //! Counts children of node. Time complexity is O(n). 91 | //! \return Number of children of node 92 | template 93 | inline std::size_t count_children(xml_node *node) 94 | { 95 | xml_node *child = node->first_node(); 96 | std::size_t count = 0; 97 | while (child) 98 | { 99 | ++count; 100 | child = child->next_sibling(); 101 | } 102 | return count; 103 | } 104 | 105 | //! Counts attributes of node. Time complexity is O(n). 106 | //! \return Number of attributes of node 107 | template 108 | inline std::size_t count_attributes(xml_node *node) 109 | { 110 | xml_attribute *attr = node->first_attribute(); 111 | std::size_t count = 0; 112 | while (attr) 113 | { 114 | ++count; 115 | attr = attr->next_attribute(); 116 | } 117 | return count; 118 | } 119 | 120 | } 121 | 122 | #endif 123 | -------------------------------------------------------------------------------- /sqlite.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2021 Duowan Inc. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, 11 | * software distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #ifndef __X_PACK_SQLITE_H 18 | #define __X_PACK_SQLITE_H 19 | 20 | #include "sqlite_decoder.h" 21 | #include "xpack.h" 22 | 23 | namespace xpack { 24 | 25 | class sqlite { 26 | public: 27 | // convert result of sqlite_get_table to a struct or vector 28 | template 29 | static void decode(const char **result, int rows, int cols, T &val) { 30 | SQLiteDecoder de(result, rows, cols); 31 | de.decode_top(val, NULL); 32 | } 33 | 34 | // select name from test where id = 1; // just want to get name, did not want to use a struct 35 | template 36 | static void decode(const char **result, int rows, int cols, const std::string&field, T &val) { 37 | SQLiteDecoder de(result, rows, cols); 38 | de.decode_column(field.c_str(), val, NULL); 39 | } 40 | }; 41 | 42 | } 43 | 44 | #endif -------------------------------------------------------------------------------- /sqlite_decoder.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2021 Duowan Inc. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, 11 | * software distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | 18 | #ifndef __X_PACK_SQLITE_DECODER_H 19 | #define __X_PACK_SQLITE_DECODER_H 20 | 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | #include 27 | 28 | #include "extend.h" 29 | #include "traits.h" 30 | #include "json.h" 31 | 32 | #include "string.h" 33 | #include "time.h" 34 | 35 | namespace xpack { 36 | 37 | class SQLiteDecoder { 38 | friend class sqlite; 39 | public: 40 | template 41 | bool decode(const char*key, T&val, const Extend *ext) { 42 | int idx = find(key); 43 | if (idx >= 0) { 44 | return this->decode_type(idx, val, ext); 45 | } 46 | return false; 47 | } 48 | const char *Name() const { // mysql and sqlite use db 49 | return "db"; 50 | } 51 | 52 | private: 53 | const char **_res; 54 | const int _rows; 55 | const int _cols; 56 | int _offset; 57 | std::map _index; 58 | 59 | SQLiteDecoder(const char**result, int rows, int cols):_res(result), _rows(rows), _cols(cols) { 60 | for (int i=0; i 68 | inline XPACK_IS_XPACK(T) decode_top(T& val, const Extend *ext) { 69 | if (_rows > 0) { 70 | val.__x_pack_decode(*this, val, ext); 71 | return true; 72 | } 73 | return false; 74 | } 75 | template 76 | inline XPACK_IS_XPACK(T) decode_top(std::vector& val, const Extend *ext) { 77 | for (int i=0; i<_rows; ++i) { 78 | val.push_back(T()); 79 | T& tmp = val.back(); 80 | tmp.__x_pack_decode(*this, tmp, ext); 81 | _offset += _cols; 82 | } 83 | return true; 84 | } 85 | template 86 | inline XPACK_IS_XOUT(T) decode_top(T& val, const Extend *ext) { 87 | if (_rows > 0) { 88 | __x_pack_decode_out(*this, val, ext); 89 | } 90 | return true; 91 | } 92 | template 93 | inline XPACK_IS_XOUT(T) decode_top(std::vector& val, const Extend *ext) { 94 | for (int i=0; i<_rows; ++i) { 95 | val.push_back(T()); 96 | __x_pack_decode_out(*this, val.back(), ext); 97 | _offset += _cols; 98 | } 99 | return true; 100 | } 101 | 102 | // decode special column of first row 103 | template 104 | bool decode_column(const char*field, T&val, const Extend *ext) { 105 | int idx; 106 | if (_rows>0 && (0 <= (idx = find(field)))) { 107 | return decode_type(idx, val, ext); 108 | } 109 | return false; 110 | } 111 | // decode special column of rows 112 | template 113 | bool decode_column(const char*field, std::vector&val, const Extend *ext) { 114 | int idx; 115 | if (0 > (idx = find(field))) { 116 | return false; 117 | } 118 | for (int i=0; i<_rows; ++i) { 119 | T t; 120 | decode_type(idx, t, ext); 121 | val.push_back(t); 122 | _offset += _cols; 123 | } 124 | return true; 125 | } 126 | 127 | 128 | int find(const char*field) const { 129 | std::map::const_iterator it = _index.find(field); 130 | if (it != _index.end()) { 131 | return it->second; 132 | } 133 | return -1; 134 | } 135 | 136 | // std::string 137 | bool decode_type(const int idx, std::string &val, const Extend *ext) { 138 | const char* s; 139 | if (NULL != (s = _res[idx + _offset])) { 140 | val = s; 141 | } 142 | return true; 143 | } 144 | // bool 145 | bool decode_type(const int idx, bool &val, const Extend *ext) { 146 | int tmp; 147 | if (decode_type(idx, tmp, ext)) { 148 | val = tmp != 0; 149 | return true; 150 | } 151 | return false; 152 | } 153 | // integer 154 | template 155 | typename x_enable_if::is_integer, bool>::type decode_type(const int idx, T &val, const Extend *ext) { 156 | const char* s; 157 | if (NULL != (s = _res[idx + _offset])) { 158 | val = (T)std::strtoul(s, NULL, 10); 159 | } // else val = 0 ??? 160 | return true; 161 | } 162 | // float 163 | template 164 | typename x_enable_if::is_float, bool>::type decode_type(const int idx, T &val, const Extend *ext) { 165 | const char* s; 166 | if (NULL != (s = _res[idx + _offset])) { 167 | val = (T)std::strtod(s, NULL); 168 | } 169 | return true; 170 | } 171 | // class/struct defined XPACK/XPACK_OUT, default use json to parse 172 | template 173 | inline XPACK_IS_XOUT(T) decode_type(const int idx, T &val, const Extend *ext) { 174 | (void)ext; 175 | const char* s; 176 | if (NULL != (s = _res[idx + _offset])) { 177 | return xpack::json::decode(s, val); 178 | } 179 | return true; 180 | } 181 | template 182 | inline XPACK_IS_XPACK(T) decode_type(const int idx, T &val, const Extend *ext) { 183 | (void)ext; 184 | const char* s; 185 | if (NULL != (s = _res[idx + _offset])) { 186 | return xpack::json::decode(s, val); 187 | } 188 | return true; 189 | } 190 | }; 191 | 192 | 193 | } 194 | 195 | #endif 196 | -------------------------------------------------------------------------------- /traits.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2021 Duowan Inc. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, 11 | * software distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | 18 | #ifndef __X_PACK_TRAITS_H 19 | #define __X_PACK_TRAITS_H 20 | 21 | #if __GXX_EXPERIMENTAL_CXX0X__ || _MSC_VER>=1700 22 | #define X_PACK_SUPPORT_CXX0X 1 23 | #endif 24 | 25 | namespace xpack { 26 | 27 | // implement std::enable_if 28 | template 29 | struct x_enable_if {}; 30 | template 31 | struct x_enable_if { typedef T type; }; 32 | 33 | // mark XPACK_OUT 34 | template 35 | struct is_xpack_out{static bool const value = false;}; 36 | 37 | template 38 | struct is_xpack_xtype {static bool const value = false;}; 39 | 40 | template 41 | struct is_xpack_type_spec {static bool const value = false;}; 42 | 43 | 44 | // for bitfield, declare raw type. thx https://stackoverflow.com/a/12199635/5845104 45 | template struct x_size { char value[N]; }; 46 | x_size<1> x_decltype_encode(char); 47 | x_size<2> x_decltype_encode(signed char); 48 | x_size<3> x_decltype_encode(unsigned char); 49 | x_size<4> x_decltype_encode(short); 50 | x_size<5> x_decltype_encode(unsigned short); 51 | x_size<6> x_decltype_encode(int); 52 | x_size<7> x_decltype_encode(unsigned int); 53 | x_size<8> x_decltype_encode(long); 54 | x_size<9> x_decltype_encode(unsigned long); 55 | x_size<10> x_decltype_encode(long long); 56 | x_size<11> x_decltype_encode(unsigned long long); 57 | 58 | template struct x_decltype_decode {}; 59 | template <> struct x_decltype_decode<1> {typedef char type;}; 60 | template <> struct x_decltype_decode<2> {typedef signed char type;}; 61 | template <> struct x_decltype_decode<3> {typedef unsigned char type;}; 62 | template <> struct x_decltype_decode<4> {typedef short type;}; 63 | template <> struct x_decltype_decode<5> {typedef unsigned short type;}; 64 | template <> struct x_decltype_decode<6> {typedef int type;}; 65 | template <> struct x_decltype_decode<7> {typedef unsigned int type;}; 66 | template <> struct x_decltype_decode<8> {typedef long type;}; 67 | template <> struct x_decltype_decode<9> {typedef unsigned long type;}; 68 | template <> struct x_decltype_decode<10> {typedef long long type;}; 69 | template <> struct x_decltype_decode<11> {typedef unsigned long long type;}; 70 | 71 | class noncopyable { 72 | public: 73 | noncopyable(){} 74 | ~noncopyable(){} 75 | private: 76 | noncopyable(const noncopyable&v); 77 | noncopyable& operator = (const noncopyable&v); 78 | }; 79 | 80 | } 81 | 82 | #define x_pack_decltype(T) typename xpack::x_decltype_decode::type 83 | 84 | 85 | // fix SFINAE bug of vs2005, so vs2005(or pre version) not support XPACK_OUT define xtype. 86 | // can use custom 87 | // The priority of xtype is the highest 88 | #if defined _MSC_VER && _MSC_VER<=1400 89 | #define XPACK_IS_XTYPE(Coder, T) typename x_enable_if::value && !is_xpack_type_spec::value && !is_xpack_out::value, bool>::type 90 | #else 91 | #define XPACK_IS_XTYPE(Coder, T) typename x_enable_if::value && !is_xpack_type_spec::value, bool>::type 92 | #endif 93 | 94 | /* 95 | struct A { 96 | XPACK(...); 97 | }; 98 | struct B : public A{ 99 | }; 100 | XPACK_OUT(B, ...); 101 | 102 | in this case, B::__x_pack_value is true and should hit xpack_out, so 103 | XPACK_IS_XPACK need to add !is_xpack_out::value 104 | */ 105 | 106 | #define XPACK_IS_XOUT(T) typename x_enable_if::value && !is_xpack_xtype::value, bool>::type 107 | #define XPACK_IS_XPACK(T) typename x_enable_if::value && !is_xpack_xtype::value, bool>::type 108 | 109 | 110 | #endif 111 | 112 | -------------------------------------------------------------------------------- /util.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2021 Duowan Inc. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, 11 | * software distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #ifndef __X_PACK_UTIL_H 18 | #define __X_PACK_UTIL_H 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | #include 27 | #include 28 | 29 | #include "traits.h" 30 | #include "numeric.h" 31 | 32 | namespace xpack { 33 | 34 | struct cmp_str { 35 | bool operator()(char const *a, char const *b) const { 36 | return strcmp(a, b) < 0; 37 | } 38 | }; 39 | 40 | class Util { 41 | public: 42 | static bool readfile(const std::string&fname, std::string&data) { 43 | std::ifstream fs(fname.c_str(), std::ifstream::binary); 44 | if (!fs) { 45 | std::string err = "Open file["+fname+"] fail."; 46 | throw std::runtime_error(err); 47 | } 48 | std::string _tmp((std::istreambuf_iterator(fs)), std::istreambuf_iterator()); 49 | data.swap(_tmp); 50 | return true; 51 | } 52 | // if n<0 will split all 53 | static size_t split(std::vector&slice, const std::string&str, char c, int n = -1) { 54 | size_t last = 0; 55 | size_t pos = 0; 56 | int cnt = 0; 57 | while (std::string::npos != (pos=str.find(c, last))) { 58 | slice.push_back(str.substr(last, pos-last)); 59 | last = pos+1; 60 | ++cnt; 61 | if (n>0 && n>=cnt) { 62 | break; 63 | } 64 | } 65 | 66 | slice.push_back(str.substr(last)); 67 | return slice.size(); 68 | } 69 | 70 | static size_t split(std::vector&slice, const std::string&str, const std::string& sp, int n =-1) { 71 | size_t last = 0; 72 | size_t pos = 0; 73 | size_t len = sp.length(); 74 | if (len == 0) { 75 | slice.push_back(str); 76 | return 1; 77 | } 78 | int cnt = 0; 79 | while (std::string::npos != (pos=str.find(sp, last))) { 80 | slice.push_back(str.substr(last, pos-last)); 81 | last = pos+len; 82 | ++cnt; 83 | if (n>0 && n>=cnt) { 84 | break; 85 | } 86 | } 87 | 88 | slice.push_back(str.substr(last)); 89 | return slice.size(); 90 | } 91 | 92 | // not support float. 93 | template 94 | static typename x_enable_if::is_integer, std::string>::type itoa(const T&val) { 95 | #ifdef X_PACK_SUPPORT_CXX0X 96 | return std::to_string(val); 97 | #else 98 | char buf[128]; 99 | size_t i = sizeof(buf)-1; 100 | 101 | if (val == 0) { 102 | return std::string("0"); 103 | } 104 | 105 | T _tmp = val>=0?val:val*-1; 106 | while (_tmp > 0) { 107 | buf[i--] = char(int('0')+int(_tmp%10)); 108 | _tmp /= 10; 109 | } 110 | if (val < 0) { 111 | buf[i--] = '-'; 112 | } 113 | return std::string(&buf[i+1], sizeof(buf)-i-1); 114 | #endif 115 | } 116 | 117 | #ifdef X_PACK_SUPPORT_CXX0X 118 | template 119 | inline static typename x_enable_if::value, std::string>::type itoa(const E& val) { 120 | return itoa((typename std::underlying_type::type)val); 121 | } 122 | template 123 | static typename x_enable_if::value, bool>::type atoi(const std::string& key, E& val) { 124 | typename std::underlying_type::type tmp; 125 | bool ret = atoi(key, tmp); 126 | if (ret) { 127 | val = (E)tmp; 128 | } 129 | return ret; 130 | } 131 | #endif 132 | 133 | // not support float. and only decimal 134 | template 135 | static typename x_enable_if::is_integer, bool>::type atoi(const std::string&s, T&val) { 136 | if (s.empty()) { 137 | return false; 138 | } 139 | 140 | T _tmp = 0; 141 | size_t i = 0; 142 | if (s[0] == '-') { 143 | if (s.length() == 1) { 144 | return false; 145 | } else if (s.length()>2 && s[1]=='0') { 146 | return false; 147 | } 148 | 149 | for (i=1; i='0' && s[i]<='9') { 151 | T _c = _tmp*10 - (s[i]-'0'); 152 | if (_c < _tmp) { 153 | _tmp = _c; 154 | } else if (i > 0) { 155 | return false; // overflow 156 | } 157 | } else { 158 | return false; 159 | } 160 | } 161 | } else { 162 | if (s[0] == '+') { 163 | ++i; 164 | } 165 | if (s[i]=='0' && i+1='0' && s[i]<='9') { 170 | T _c = _tmp*10 + (s[i]-'0'); 171 | if (_c > _tmp) { 172 | _tmp = _c; 173 | } else if (i > 0) { 174 | return false; // overflow 175 | } 176 | } else { 177 | return false; 178 | } 179 | } 180 | } 181 | 182 | val = _tmp; 183 | return true; 184 | } 185 | template 186 | static typename x_enable_if::is_integer, bool>::type atoi(const char*s, T&val) { 187 | if (NULL == s) { 188 | return false; 189 | } 190 | std::string _t(s); 191 | return atoi(_t, val); 192 | } 193 | }; 194 | 195 | 196 | #if defined(X_PACK_SUPPORT_CXX0X) 197 | template 198 | using x_shared_ptr = std::shared_ptr; 199 | #elif defined(_GNU_SOURCE) 200 | // A very crude implementation of shared_ptr 201 | template 202 | class x_shared_ptr { 203 | public: 204 | x_shared_ptr(T *p = NULL):ptr(p) { 205 | if (NULL != p) { 206 | counter = new int; 207 | *counter = 1; 208 | } else { 209 | counter = NULL; 210 | } 211 | } 212 | x_shared_ptr(const x_shared_ptr &src) { 213 | ptr = src.ptr; 214 | counter = src.counter; 215 | add_ref(1); 216 | } 217 | ~x_shared_ptr() { 218 | add_ref(-1); 219 | } 220 | x_shared_ptr& operator = (const x_shared_ptr &src) { 221 | add_ref(-1); 222 | ptr = src.ptr; 223 | counter = src.counter; 224 | add_ref(1); 225 | return *this; 226 | } 227 | void reset(T *p = NULL) { 228 | *this = x_shared_ptr(p); 229 | } 230 | T* operator ->() { 231 | return ptr; 232 | } 233 | T* get() { 234 | return ptr; 235 | } 236 | T& operator *() { 237 | return *ptr; 238 | } 239 | private: 240 | void add_ref(int cnt) { 241 | if (counter == NULL) { 242 | return; 243 | } 244 | int ncnt = __sync_add_and_fetch(counter, cnt); 245 | if (0 == ncnt) { 246 | delete counter; 247 | delete ptr; 248 | } 249 | } 250 | T *ptr; 251 | mutable int *counter; 252 | }; 253 | #endif 254 | 255 | } 256 | 257 | #endif 258 | -------------------------------------------------------------------------------- /xml.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2021 Duowan Inc. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, 11 | * software distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #ifndef __X_PACK_XML_H 18 | #define __X_PACK_XML_H 19 | 20 | #include "xml_decoder.h" 21 | #include "xml_encoder.h" 22 | #include "xpack.h" 23 | 24 | namespace xpack { 25 | /* 26 | for xml like 27 | 28 | Pony 29 | 20 30 | 31 | 32 | Just define such a structure 33 | struct User { 34 | string name; 35 | int age; 36 | XPACK(O(name, age)); 37 | }; 38 | 39 | !!!!NO NEED!!! to define: 40 | struct Data { 41 | User user; 42 | XPACK(O(user)); 43 | }; 44 | 45 | xml::decode will skip the root node, so for the xml defined above, 46 | it only needs to be decode like this: 47 | User u; 48 | xpack::xml::decode(str, u); 49 | */ 50 | 51 | class xml { 52 | public: 53 | template 54 | static void decode(const std::string &data, T &val) { 55 | XmlDecoder de; 56 | de.decode(data, val); 57 | } 58 | template 59 | static void decode_file(const std::string &file_name, T &val) { 60 | XmlDecoder de; 61 | de.decode_file(file_name, val); 62 | } 63 | template 64 | static std::string encode(const T &val, const std::string&root) { 65 | XmlEncoder en; 66 | return en.encode(val, root); 67 | } 68 | 69 | template 70 | static std::string encode(const T &val, const std::string&root, int flag, int indentCount, char indentChar) { 71 | (void)flag; 72 | XmlEncoder en(indentCount, indentChar); 73 | return en.encode(val, root); 74 | } 75 | }; 76 | 77 | } 78 | 79 | #endif -------------------------------------------------------------------------------- /xml_decoder.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2021 Duowan Inc. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, 11 | * software distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #ifndef __X_PACK_XML_DECODER_H 18 | #define __X_PACK_XML_DECODER_H 19 | 20 | #include 21 | #include 22 | #include 23 | 24 | #include 25 | #include 26 | 27 | #include "rapidxml/rapidxml.hpp" 28 | 29 | #include "xdecoder.h" 30 | 31 | namespace xpack { 32 | 33 | class XmlNode { 34 | typedef rapidxml::xml_node<> Node; 35 | typedef XDecoder decoder; 36 | public: 37 | typedef size_t Iterator; 38 | 39 | public: 40 | XmlNode(Node *n=NULL):node(n), attr(NULL), inited(false) {} 41 | 42 | inline static const char * Name() { 43 | return "xml"; 44 | } 45 | operator bool() const { 46 | return node != NULL; 47 | } 48 | bool IsNull() const { 49 | return false; 50 | } 51 | XmlNode Find(decoder&de, const char*key, const Extend *ext) { 52 | (void)de; 53 | if (!inited) { 54 | this->init(); 55 | } 56 | if (Extend::XmlContent(ext)) { 57 | return *this; 58 | } 59 | 60 | node_index::iterator iter; 61 | if (_childs_index.end() != (iter=_childs_index.find(key))) { 62 | bool sbs = Extend::AliasFlag(ext, "xml", "sbs"); 63 | if (!sbs) { 64 | return XmlNode(_childs[iter->second]); 65 | } else { 66 | XmlNode node(_childs[iter->second]); 67 | node.initsbs(*this, key); 68 | return node; 69 | } 70 | } else { // sbs not support attribute 71 | XmlNode tmp; 72 | tmp.attr = node->first_attribute(key); 73 | if (NULL != tmp.attr) { 74 | tmp.node = this->node; 75 | } 76 | return tmp; 77 | } 78 | } 79 | size_t Size(decoder&de) { 80 | (void)de; 81 | if (!inited) { 82 | this->init(); 83 | } 84 | return _childs.size(); 85 | } 86 | XmlNode At(size_t index) const { // no exception 87 | return XmlNode(_childs[index]); 88 | } 89 | // if child node defined sbs, results can be confusing 90 | XmlNode Next(decoder&de, XmlNode&p, Iterator&iter, std::string&key) { 91 | (void)de; 92 | if (!p.inited) { 93 | p.init(); 94 | } 95 | if (node != NULL) { 96 | if (node != p.node) { 97 | ++iter; 98 | } else { 99 | iter = 0; 100 | } 101 | 102 | if (iter < p._childs.size()) { 103 | key = p._childs[iter]->name(); 104 | return XmlNode(p._childs[iter]); 105 | } 106 | } 107 | return XmlNode(); 108 | } 109 | bool Get(decoder&de, std::string&val, const Extend*ext) { 110 | if (!Extend::AliasFlag(ext, "xml", "cdata")) { 111 | val = get_val(Extend::XmlContent(ext)); 112 | } else { 113 | const Node *tmp = node->first_node(); 114 | if (NULL != tmp) { 115 | if (tmp->type() == rapidxml::node_cdata || tmp->type() == rapidxml::node_data) { 116 | val = tmp->value(); 117 | } else { 118 | de.decode_exception("not cdata type", NULL); 119 | } 120 | } else { // if node contain text not CDATA, get it 121 | val = node->value(); 122 | } 123 | } 124 | return true; 125 | } 126 | bool Get(decoder&de, bool &val, const Extend*ext) { 127 | (void)ext; 128 | std::string v = get_val(Extend::XmlContent(ext)); 129 | if (v=="1" || v=="true" || v=="TRUE" || v=="True") { 130 | val = true; 131 | } else if (v=="0" || v=="false" || v=="FALSE" || v=="False") { 132 | val = false; 133 | } else { 134 | de.decode_exception("parse bool fail.", NULL); 135 | } 136 | return true; 137 | } 138 | template 139 | typename x_enable_if::is_integer, bool>::type Get(decoder&de, T &val, const Extend*ext){ 140 | (void)ext; 141 | std::string v = get_val(Extend::XmlContent(ext)); 142 | if (Util::atoi(v, val)) { 143 | return true; 144 | } else { 145 | de.decode_exception("parse int fail. not integer or overflow", NULL); 146 | return false; 147 | } 148 | } 149 | template 150 | typename x_enable_if::is_float, bool>::type Get(decoder&de, T &val, const Extend*ext){ 151 | (void)ext; 152 | std::string v = get_val(Extend::XmlContent(ext)); 153 | if (1==v.length() && v[0]=='-') { 154 | return false; 155 | } 156 | 157 | const char *data = v.c_str(); 158 | char *end; 159 | double d = strtod(data, &end); 160 | if ((size_t)(end-data) == v.length()) { 161 | val = (T)d; 162 | return true; 163 | } 164 | de.decode_exception("parse double fail.", NULL); 165 | return false; 166 | } 167 | 168 | private: 169 | typedef std::map node_index; // index of _childs 170 | 171 | void init() { 172 | inited = true; 173 | if (NULL != node) { 174 | Node *tmp = node->first_node(); 175 | for (size_t i=0; tmp; tmp=tmp->next_sibling(), ++i) { 176 | _childs.push_back(tmp); 177 | _childs_index[tmp->name()] = i; 178 | } 179 | } 180 | } 181 | void initsbs(const XmlNode&parent, const char *key) { 182 | inited = true; 183 | for (size_t i=0; iname())) { 185 | _childs.push_back(parent._childs[i]); 186 | } 187 | } 188 | } 189 | 190 | std::string get_val(bool forceContent=false) { 191 | if (forceContent || attr==NULL) { 192 | return node->value(); 193 | } else if (attr != NULL) { 194 | return attr->value(); 195 | } else { 196 | return ""; 197 | } 198 | } 199 | 200 | const Node* node; // current node 201 | rapidxml::xml_attribute *attr; 202 | bool inited; // delay init to avoid copy _childs and _childs_index 203 | 204 | std::vector _childs; // childs 205 | node_index _childs_index; 206 | }; 207 | 208 | 209 | class XmlDecoder { 210 | public: 211 | template 212 | bool decode(const std::string&str, T&val, bool with_root=false) { 213 | std::string tmp = str; 214 | return this->decode_indata(tmp, val, with_root); 215 | } 216 | template 217 | bool decode_file(const std::string&fname, T&val, bool with_root=false) { 218 | std::string data; 219 | bool ret = Util::readfile(fname, data); 220 | if (ret) { 221 | ret = this->decode_indata(data, val, with_root); 222 | } 223 | return ret; 224 | } 225 | private: 226 | template 227 | bool decode_indata(std::string&str, T&val, bool with_root=false) { 228 | rapidxml::xml_document<> de; 229 | std::string err; 230 | try { 231 | de.parse<0>((char*)str.c_str()); 232 | } catch (const rapidxml::parse_error&e) { 233 | err = std::string("parse xml fail. err=")+e.what()+". "+std::string(e.where()).substr(0, 32); 234 | } catch (const std::exception&e) { 235 | err = std::string("parse xml fail. unknow exception. err=")+e.what(); 236 | } 237 | 238 | if (!err.empty()) { 239 | throw std::runtime_error(err); 240 | } 241 | 242 | if (!with_root) { 243 | XmlNode node(de.first_node()); 244 | return XDecoder(NULL, (const char*)NULL, node).decode(val, NULL); 245 | } else { 246 | XmlNode node(&de); 247 | return XDecoder(NULL, (const char*)NULL, node).decode(val, NULL); 248 | } 249 | } 250 | }; 251 | 252 | } 253 | 254 | #endif 255 | -------------------------------------------------------------------------------- /xpack.pri: -------------------------------------------------------------------------------- 1 | INCLUDEPATH += $$PWD 2 | DEFINES += XPACK_SUPPORT_QT 3 | HEADERS += xpack.h 4 | -------------------------------------------------------------------------------- /yaml.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2021 Duowan Inc. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, 11 | * software distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #ifndef __X_PACK_YAML_H 18 | #define __X_PACK_YAML_H 19 | 20 | #include "yaml_decoder.h" 21 | #include "yaml_encoder.h" 22 | #include "xpack.h" 23 | 24 | namespace xpack { 25 | 26 | class yaml { 27 | public: 28 | template 29 | static void decode(const std::string &data, T &val) { 30 | YamlDecoder de; 31 | de.decode(data, val); 32 | } 33 | template 34 | static void decode_file(const std::string &file_name, T &val) { 35 | YamlDecoder de; 36 | de.decode_file(file_name, val); 37 | } 38 | 39 | template 40 | static std::string encode(const T &val) { 41 | YamlEncoder en; 42 | return en.encode(val); 43 | } 44 | }; 45 | 46 | } 47 | 48 | #endif 49 | -------------------------------------------------------------------------------- /yaml_decoder.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2021 Duowan Inc. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, 11 | * software distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #ifndef __X_PACK_YAML_DECODER_H 18 | #define __X_PACK_YAML_DECODER_H 19 | 20 | #include "yaml-cpp/yaml.h" 21 | #include "xdecoder.h" 22 | 23 | namespace xpack { 24 | 25 | 26 | class YamlNode { 27 | typedef XDecoder decoder; 28 | public: 29 | typedef YAML::const_iterator Iterator; 30 | 31 | YamlNode(const YAML::Node& node):n(node),valid(true){} 32 | YamlNode():valid(false){} 33 | 34 | inline static const char * Name() { 35 | return "yaml"; 36 | } 37 | operator bool() const { 38 | return valid; 39 | } 40 | bool IsNull() const { 41 | return valid && n.IsNull(); 42 | } 43 | YamlNode Find(decoder&de, const char*key, const Extend *ext) const { 44 | (void)ext; 45 | if (n.IsNull()) { 46 | return YamlNode(); 47 | } else if (!n.IsMap()) { 48 | de.decode_exception("not map", NULL); 49 | } 50 | return YamlNode(n[key]); 51 | } 52 | size_t Size(decoder&de) const { 53 | if (!n.IsSequence()) { 54 | de.decode_exception("not sequence", NULL); 55 | } 56 | return (size_t)n.size(); 57 | } 58 | YamlNode At(size_t index) const { // no exception 59 | return YamlNode(n[index]); 60 | } 61 | YamlNode Next(decoder&de, const YamlNode&parent, Iterator&iter, std::string&key) const { 62 | if (parent.n.IsMap()) { 63 | if ((void*)this != (void*)(&parent)) { 64 | ++iter; 65 | } else { 66 | iter = parent.n.begin(); 67 | } 68 | if (iter != parent.n.end()) { 69 | key = iter->first.as(); 70 | return YamlNode(iter->second); 71 | } 72 | } else { 73 | de.decode_exception("not map", NULL); 74 | } 75 | return YamlNode(); 76 | } 77 | 78 | template 79 | bool Get(decoder&de, T &val, const Extend*ext){ 80 | (void)de; 81 | (void)ext; 82 | try { 83 | val = n.as(); 84 | return true; 85 | } catch (const std::exception&e) { 86 | de.decode_exception(e.what(), NULL); 87 | } catch (...) { 88 | de.decode_exception("type unmatch", NULL); 89 | } 90 | return false; 91 | } 92 | 93 | private: 94 | YAML::Node n; 95 | bool valid; 96 | }; 97 | 98 | class YamlDecoder { 99 | public: 100 | template 101 | bool decode(const std::string&str, T&val) { 102 | YAML::Node n = YAML::Load(str); 103 | if (n) { 104 | YamlNode node(n); 105 | return XDecoder(NULL, (const char*)NULL, node).decode(val, NULL); 106 | } 107 | return false; 108 | } 109 | template 110 | bool decode_file(const std::string&fname, T&val) { 111 | YAML::Node n = YAML::LoadFile(fname); 112 | if (n) { 113 | YamlNode node(n); 114 | return XDecoder(NULL, (const char*)NULL, node).decode(val, NULL); 115 | } 116 | return false; 117 | } 118 | }; 119 | 120 | 121 | } 122 | 123 | #endif 124 | -------------------------------------------------------------------------------- /yaml_encoder.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2021 Duowan Inc. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, 11 | * software distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #ifndef __X_PACK_YAML_ENCODER_H 18 | #define __X_PACK_YAML_ENCODER_H 19 | 20 | #include 21 | 22 | #include "yaml-cpp/yaml.h" 23 | 24 | #include "xencoder.h" 25 | 26 | namespace xpack { 27 | 28 | class YamlWriter:private noncopyable { 29 | friend class XEncoder; 30 | friend class YamlEncoder; 31 | 32 | const static bool support_null = true; 33 | public: 34 | YamlWriter(size_t indent = 2, int maxDecimalPlaces = -1) { 35 | e.SetIndent(indent); 36 | if (maxDecimalPlaces > 0) { 37 | e.SetFloatPrecision((size_t)maxDecimalPlaces); 38 | e.SetDoublePrecision((size_t)maxDecimalPlaces); 39 | } 40 | } 41 | ~YamlWriter() { 42 | } 43 | private: 44 | inline static const char *Name() { 45 | return "yaml"; 46 | } 47 | inline const char *IndexKey(size_t index) { 48 | (void)index; 49 | return NULL; 50 | } 51 | std::string String() { 52 | return std::string(e.c_str(), e.size()); 53 | } 54 | 55 | void ArrayBegin(const char *key, const Extend *ext) { 56 | (void)ext; 57 | xpack_set_key(key); 58 | e << YAML::Value << YAML::BeginSeq; 59 | } 60 | void ArrayEnd(const char *key, const Extend *ext) { 61 | (void)key; 62 | (void)ext; 63 | e << YAML::EndSeq; 64 | } 65 | void ObjectBegin(const char *key, const Extend *ext) { 66 | (void)ext; 67 | xpack_set_key(key); 68 | e << YAML::Value << YAML::BeginMap; 69 | } 70 | void ObjectEnd(const char *key, const Extend *ext) { 71 | (void)key; 72 | (void)ext; 73 | e << YAML::EndMap; 74 | } 75 | bool WriteNull(const char*key, const Extend *ext) { 76 | (void)ext; 77 | xpack_set_key(key); 78 | e << YAML::Value << YAML::Null; 79 | return true; 80 | } 81 | bool encode_bool(const char*key, const bool&val, const Extend *ext) { 82 | (void)ext; 83 | xpack_set_key(key); 84 | e << YAML::Value << val; 85 | return true; 86 | } 87 | bool encode_string(const char*key, const std::string&val, const Extend *ext) { 88 | (void)ext; 89 | xpack_set_key(key); 90 | if (!val.empty()) { 91 | e << YAML::Value << val; 92 | } else { 93 | e << YAML::Value << YAML::Null; 94 | } 95 | return true; 96 | } 97 | template 98 | typename x_enable_if::value, bool>::type encode_number(const char*key, const T&val, const Extend *ext) { 99 | (void)ext; 100 | xpack_set_key(key); 101 | e << YAML::Value << val; 102 | return true; 103 | } 104 | 105 | void xpack_set_key(const char*key) { // openssl defined set_key macro, so we named it xpack_set_key 106 | if (NULL!=key && key[0]!='\0') { 107 | e << YAML::Key << key; 108 | } 109 | } 110 | 111 | YAML::Emitter e; 112 | }; 113 | 114 | class YamlEncoder { 115 | public: 116 | YamlEncoder() { 117 | indentCount = 2; 118 | maxDecimalPlaces = -1; 119 | } 120 | 121 | YamlEncoder& SetIndent(size_t indent) { 122 | indentCount = indent; 123 | return *this; 124 | } 125 | YamlEncoder& SetMaxDecimalPlaces(int _maxDecimalPlaces) { 126 | maxDecimalPlaces = _maxDecimalPlaces; 127 | return *this; 128 | } 129 | 130 | template 131 | std::string encode(const T&val) { 132 | YamlWriter wr(indentCount, maxDecimalPlaces); 133 | XEncoder en(wr); 134 | en.encode(NULL, val, NULL); 135 | return wr.String(); 136 | } 137 | 138 | private: 139 | size_t indentCount; 140 | int maxDecimalPlaces; 141 | }; 142 | 143 | 144 | } 145 | 146 | #endif 147 | --------------------------------------------------------------------------------