├── LICENSE ├── README.md ├── src ├── bin2ascii.h ├── pbjson.cpp ├── pbjson.hpp └── rapidjson │ ├── allocators.h │ ├── document.h │ ├── encodedstream.h │ ├── encodings.h │ ├── error │ ├── en.h │ └── error.h │ ├── filereadstream.h │ ├── filewritestream.h │ ├── internal │ ├── biginteger.h │ ├── diyfp.h │ ├── dtoa.h │ ├── ieee754.h │ ├── itoa.h │ ├── meta.h │ ├── pow10.h │ ├── stack.h │ ├── strfunc.h │ └── strtod.h │ ├── memorybuffer.h │ ├── memorystream.h │ ├── msinttypes │ ├── inttypes.h │ └── stdint.h │ ├── prettywriter.h │ ├── rapidjson.h │ ├── reader.h │ ├── stringbuffer.h │ └── writer.h └── test ├── Makefile ├── test.cpp ├── test.pb.cc ├── test.pb.h └── test.proto /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2013, yinqiwen 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | * Redistributions of source code must retain the above copyright 7 | notice, this list of conditions and the following disclaimer. 8 | * Redistributions in binary form must reproduce the above copyright 9 | notice, this list of conditions and the following disclaimer in the 10 | documentation and/or other materials provided with the distribution. 11 | * Neither the name of the Ardb nor the 12 | names of its contributors may be used to endorse or promote products 13 | derived from this software without specific prior written permission. 14 | 15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 16 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 | DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY 19 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 22 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | pbjson 2 | ====== 3 | 4 | A fast C++ serialization and de-serialization of Google's protobuf Messages into/from JSON format, which built on [rapidjson](https://code.google.com/p/rapidjson/), inspired from [json2pb](https://github.com/shramov/json2pb). 5 | 6 | ## Embedding pbjson 7 | 8 | Just copy all files in 'src' folder into your project. 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /src/bin2ascii.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013 Pavel Shramov 3 | * 4 | * json2pb is free software; you can redistribute it and/or modify 5 | * it under the terms of the MIT license. See LICENSE for details. 6 | */ 7 | 8 | #ifndef __BIN2ASCII_H__ 9 | #define __BIN2ASCII_H__ 10 | 11 | #include 12 | #include 13 | 14 | inline std::string hex2bin(const std::string &s) 15 | { 16 | if (s.size() % 2) 17 | throw std::runtime_error("Odd hex data size"); 18 | static const char lookup[] = "" 19 | "\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80" // 0x00 20 | "\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80" // 0x10 21 | "\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80" // 0x20 22 | "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x80\x80\x80\x80\x80\x80" // 0x30 23 | "\x80\x0a\x0b\x0c\x0d\x0e\x0f\x80\x80\x80\x80\x80\x80\x80\x80\x80" // 0x40 24 | "\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80" // 0x50 25 | "\x80\x0a\x0b\x0c\x0d\x0e\x0f\x80\x80\x80\x80\x80\x80\x80\x80\x80" // 0x60 26 | "\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80" // 0x70 27 | "\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80" // 0x80 28 | "\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80" // 0x90 29 | "\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80" // 0xa0 30 | "\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80" // 0xb0 31 | "\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80" // 0xc0 32 | "\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80" // 0xd0 33 | "\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80" // 0xe0 34 | "\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80" // 0xf0 35 | ""; 36 | std::string r; 37 | r.reserve(s.size() / 2); 38 | for (size_t i = 0; i < s.size(); i += 2) { 39 | char hi = lookup[static_cast(s[i])]; 40 | char lo = lookup[static_cast(s[i+1])]; 41 | if (0x80 & (hi | lo)) 42 | throw std::runtime_error("Invalid hex data: " + s.substr(i, 6)); 43 | r.push_back((hi << 4) | lo); 44 | } 45 | return r; 46 | } 47 | 48 | inline std::string bin2hex(const std::string &s) 49 | { 50 | static const char lookup[] = "0123456789abcdef"; 51 | std::string r; 52 | r.reserve(s.size() * 2); 53 | for (size_t i = 0; i < s.size(); i++) { 54 | unsigned char hi = s[i] >> 4; 55 | unsigned char lo = s[i] & 0xf; 56 | r.push_back(lookup[hi]); 57 | r.push_back(lookup[lo]); 58 | } 59 | return r; 60 | } 61 | 62 | inline std::string b64_encode(const std::string &s) 63 | { 64 | typedef unsigned char u1; 65 | static const char lookup[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; 66 | const u1 * data = (const u1 *) s.c_str(); 67 | std::string r; 68 | r.reserve(s.size() * 4 / 3 + 3); 69 | for (size_t i = 0; i < s.size(); i += 3) { 70 | unsigned n = data[i] << 16; 71 | if (i + 1 < s.size()) n |= data[i + 1] << 8; 72 | if (i + 2 < s.size()) n |= data[i + 2]; 73 | 74 | u1 n0 = (u1)(n >> 18) & 0x3f; 75 | u1 n1 = (u1)(n >> 12) & 0x3f; 76 | u1 n2 = (u1)(n >> 6) & 0x3f; 77 | u1 n3 = (u1)(n ) & 0x3f; 78 | 79 | r.push_back(lookup[n0]); 80 | r.push_back(lookup[n1]); 81 | if (i + 1 < s.size()) r.push_back(lookup[n2]); 82 | if (i + 2 < s.size()) r.push_back(lookup[n3]); 83 | } 84 | for (size_t i = 0; i < (3 - s.size() % 3) % 3; i++) 85 | r.push_back('='); 86 | return r; 87 | } 88 | 89 | inline std::string b64_decode(const std::string &s) 90 | { 91 | typedef unsigned char u1; 92 | static const char lookup[] = "" 93 | "\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80" // 0x00 94 | "\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80" // 0x10 95 | "\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x3e\x80\x80\x80\x3f" // 0x20 96 | "\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x80\x80\x80\x00\x80\x80" // 0x30 97 | "\x80\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e" // 0x40 98 | "\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x80\x80\x80\x80\x80" // 0x50 99 | "\x80\x1a\x1b\x1c\x1d\x1e\x1f\x20\x21\x22\x23\x24\x25\x26\x27\x28" // 0x60 100 | "\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30\x31\x32\x33\x80\x80\x80\x80\x80" // 0x70 101 | "\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80" // 0x80 102 | "\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80" // 0x90 103 | "\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80" // 0xa0 104 | "\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80" // 0xb0 105 | "\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80" // 0xc0 106 | "\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80" // 0xd0 107 | "\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80" // 0xe0 108 | "\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80" // 0xf0 109 | ""; 110 | std::string r; 111 | if (!s.size()) return r; 112 | if (s.size() % 4) 113 | throw std::runtime_error("Invalid base64 data size"); 114 | size_t pad = 0; 115 | if (s[s.size() - 1] == '=') pad++; 116 | if (s[s.size() - 2] == '=') pad++; 117 | 118 | r.reserve(s.size() * 3 / 4 + 3); 119 | for (size_t i = 0; i < s.size(); i += 4) { 120 | u1 n0 = lookup[(u1) s[i+0]]; 121 | u1 n1 = lookup[(u1) s[i+1]]; 122 | u1 n2 = lookup[(u1) s[i+2]]; 123 | u1 n3 = lookup[(u1) s[i+3]]; 124 | if (0x80 & (n0 | n1 | n2 | n3)) 125 | throw std::runtime_error("Invalid hex data: " + s.substr(i, 4)); 126 | unsigned n = (n0 << 18) | (n1 << 12) | (n2 << 6) | n3; 127 | r.push_back((n >> 16) & 0xff); 128 | if (s[i+2] != '=') r.push_back((n >> 8) & 0xff); 129 | if (s[i+3] != '=') r.push_back((n ) & 0xff); 130 | } 131 | return r; 132 | } 133 | 134 | #endif//__BIN2ASCII_H__ 135 | -------------------------------------------------------------------------------- /src/pbjson.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | *Copyright (c) 2013-2014, yinqiwen 3 | *All rights reserved. 4 | * 5 | *Redistribution and use in source and binary forms, with or without 6 | *modification, are permitted provided that the following conditions are met: 7 | * 8 | * * Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * * Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * * Neither the name of Redis nor the names of its contributors may be used 14 | * to endorse or promote products derived from this software without 15 | * specific prior written permission. 16 | * 17 | *THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 | *AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | *IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | *ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS 21 | *BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 | *CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 | *SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 | *INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25 | *CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26 | *ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 27 | *THE POSSIBILITY OF SUCH DAMAGE. 28 | */ 29 | 30 | #include "pbjson.hpp" 31 | #include "bin2ascii.h" 32 | #include "rapidjson/rapidjson.h" 33 | #include "rapidjson/writer.h" 34 | #include "rapidjson/stringbuffer.h" 35 | 36 | #define RETURN_ERR(id, cause) do{\ 37 | err = cause; \ 38 | return id; \ 39 | }while(0) 40 | using namespace google::protobuf; 41 | namespace pbjson 42 | { 43 | static rapidjson::Value *parse_msg(const Message *msg, rapidjson::Value::AllocatorType& allocator); 44 | static rapidjson::Value* field2json(const Message *msg, const FieldDescriptor *field, 45 | rapidjson::Value::AllocatorType& allocator) 46 | { 47 | const Reflection *ref = msg->GetReflection(); 48 | const bool repeated = field->is_repeated(); 49 | 50 | size_t array_size = 0; 51 | if (repeated) 52 | { 53 | array_size = ref->FieldSize(*msg, field); 54 | } 55 | rapidjson::Value* json = NULL; 56 | if (repeated) 57 | { 58 | json = new rapidjson::Value(rapidjson::kArrayType); 59 | } 60 | switch (field->cpp_type()) 61 | { 62 | case FieldDescriptor::CPPTYPE_DOUBLE: 63 | if (repeated) 64 | { 65 | for (size_t i = 0; i != array_size; ++i) 66 | { 67 | double value = ref->GetRepeatedDouble(*msg, field, i); 68 | rapidjson::Value v(value); 69 | json->PushBack(v, allocator); 70 | } 71 | } 72 | else 73 | { 74 | json = new rapidjson::Value(ref->GetDouble(*msg, field)); 75 | } 76 | break; 77 | case FieldDescriptor::CPPTYPE_FLOAT: 78 | if (repeated) 79 | { 80 | for (size_t i = 0; i != array_size; ++i) 81 | { 82 | float value = ref->GetRepeatedFloat(*msg, field, i); 83 | rapidjson::Value v(value); 84 | json->PushBack(v, allocator); 85 | } 86 | } 87 | else 88 | { 89 | json = new rapidjson::Value(ref->GetFloat(*msg, field)); 90 | } 91 | break; 92 | case FieldDescriptor::CPPTYPE_INT64: 93 | if (repeated) 94 | { 95 | for (size_t i = 0; i != array_size; ++i) 96 | { 97 | int64_t value = ref->GetRepeatedInt64(*msg, field, i); 98 | rapidjson::Value v(value); 99 | json->PushBack(v, allocator); 100 | } 101 | } 102 | else 103 | { 104 | json = new rapidjson::Value(static_cast(ref->GetInt64(*msg, field))); 105 | } 106 | break; 107 | case FieldDescriptor::CPPTYPE_UINT64: 108 | if (repeated) 109 | { 110 | for (size_t i = 0; i != array_size; ++i) 111 | { 112 | uint64_t value = ref->GetRepeatedUInt64(*msg, field, i); 113 | rapidjson::Value v(value); 114 | json->PushBack(v, allocator); 115 | } 116 | } 117 | else 118 | { 119 | json = new rapidjson::Value(static_cast(ref->GetUInt64(*msg, field))); 120 | } 121 | break; 122 | case FieldDescriptor::CPPTYPE_INT32: 123 | if (repeated) 124 | { 125 | for (size_t i = 0; i != array_size; ++i) 126 | { 127 | int32_t value = ref->GetRepeatedInt32(*msg, field, i); 128 | rapidjson::Value v(value); 129 | json->PushBack(v, allocator); 130 | } 131 | } 132 | else 133 | { 134 | json = new rapidjson::Value(ref->GetInt32(*msg, field)); 135 | } 136 | break; 137 | case FieldDescriptor::CPPTYPE_UINT32: 138 | if (repeated) 139 | { 140 | for (size_t i = 0; i != array_size; ++i) 141 | { 142 | uint32_t value = ref->GetRepeatedUInt32(*msg, field, i); 143 | rapidjson::Value v(value); 144 | json->PushBack(v, allocator); 145 | } 146 | } 147 | else 148 | { 149 | json = new rapidjson::Value(ref->GetUInt32(*msg, field)); 150 | } 151 | break; 152 | case FieldDescriptor::CPPTYPE_BOOL: 153 | if (repeated) 154 | { 155 | for (size_t i = 0; i != array_size; ++i) 156 | { 157 | bool value = ref->GetRepeatedBool(*msg, field, i); 158 | rapidjson::Value v(value); 159 | json->PushBack(v, allocator); 160 | } 161 | } 162 | else 163 | { 164 | json = new rapidjson::Value(ref->GetBool(*msg, field)); 165 | } 166 | break; 167 | case FieldDescriptor::CPPTYPE_STRING: 168 | { 169 | bool is_binary = field->type() == FieldDescriptor::TYPE_BYTES; 170 | if (repeated) 171 | { 172 | for (size_t i = 0; i != array_size; ++i) 173 | { 174 | std::string value = ref->GetRepeatedString(*msg, field, i); 175 | if (is_binary) 176 | { 177 | value = b64_encode(value); 178 | } 179 | rapidjson::Value v(value.c_str(), static_cast(value.size()), allocator); 180 | json->PushBack(v, allocator); 181 | } 182 | } 183 | else 184 | { 185 | std::string value = ref->GetString(*msg, field); 186 | if (is_binary) 187 | { 188 | value = b64_encode(value); 189 | } 190 | json = new rapidjson::Value(value.c_str(), value.size(), allocator); 191 | } 192 | break; 193 | } 194 | case FieldDescriptor::CPPTYPE_MESSAGE: 195 | if (repeated) 196 | { 197 | for (size_t i = 0; i != array_size; ++i) 198 | { 199 | const Message *value = &(ref->GetRepeatedMessage(*msg, field, i)); 200 | rapidjson::Value* v = parse_msg(value, allocator); 201 | json->PushBack(*v, allocator); 202 | delete v; 203 | } 204 | } 205 | else 206 | { 207 | const Message *value = &(ref->GetMessage(*msg, field)); 208 | json = parse_msg(value, allocator); 209 | } 210 | break; 211 | case FieldDescriptor::CPPTYPE_ENUM: 212 | if (repeated) 213 | { 214 | for (size_t i = 0; i != array_size; ++i) 215 | { 216 | const EnumValueDescriptor* value = ref->GetRepeatedEnum(*msg, field, i); 217 | rapidjson::Value v(value->number()); 218 | json->PushBack(v, allocator); 219 | } 220 | } 221 | else 222 | { 223 | json = new rapidjson::Value(ref->GetEnum(*msg, field)->number()); 224 | } 225 | break; 226 | default: 227 | break; 228 | } 229 | return json; 230 | } 231 | 232 | static rapidjson::Value* parse_msg(const Message *msg, rapidjson::Value::AllocatorType& allocator) 233 | { 234 | const Descriptor *d = msg->GetDescriptor(); 235 | if (!d) 236 | return NULL; 237 | size_t count = d->field_count(); 238 | rapidjson::Value* root = new rapidjson::Value(rapidjson::kObjectType); 239 | if (!root) 240 | return NULL; 241 | for (size_t i = 0; i != count; ++i) 242 | { 243 | const FieldDescriptor *field = d->field(i); 244 | if (!field){ 245 | delete root; 246 | return NULL; 247 | } 248 | 249 | const Reflection *ref = msg->GetReflection(); 250 | if (!ref) 251 | { 252 | delete root; 253 | return NULL; 254 | } 255 | if (field->is_optional() && !ref->HasField(*msg, field)) 256 | { 257 | //do nothing 258 | } 259 | else 260 | { 261 | rapidjson::Value* field_json = field2json(msg, field, allocator); 262 | rapidjson::Value field_name(field->name().c_str(), field->name().size()); 263 | root->AddMember(field_name, *field_json, allocator); 264 | delete field_json; 265 | } 266 | } 267 | return root; 268 | } 269 | static int parse_json(const rapidjson::Value* json, Message* msg, std::string& err); 270 | static int json2field(const rapidjson::Value* json, Message* msg, const FieldDescriptor *field, std::string& err) 271 | { 272 | const Reflection *ref = msg->GetReflection(); 273 | const bool repeated = field->is_repeated(); 274 | switch (field->cpp_type()) 275 | { 276 | case FieldDescriptor::CPPTYPE_INT32: 277 | { 278 | if (json->GetType() != rapidjson::kNumberType) 279 | { 280 | RETURN_ERR(ERR_INVALID_JSON, "Not a number"); 281 | } 282 | if (repeated) 283 | { 284 | ref->AddInt32(msg, field, (int32_t) json->GetInt()); 285 | } 286 | else 287 | { 288 | ref->SetInt32(msg, field, (int32_t) json->GetInt()); 289 | } 290 | break; 291 | } 292 | case FieldDescriptor::CPPTYPE_UINT32: 293 | { 294 | if (json->GetType() != rapidjson::kNumberType) 295 | { 296 | RETURN_ERR(ERR_INVALID_JSON, "Not a number"); 297 | } 298 | if (repeated) 299 | { 300 | ref->AddUInt32(msg, field, json->GetUint()); 301 | } 302 | else 303 | { 304 | ref->SetUInt32(msg, field, json->GetUint()); 305 | } 306 | break; 307 | } 308 | case FieldDescriptor::CPPTYPE_INT64: 309 | { 310 | if (json->GetType() != rapidjson::kNumberType) 311 | { 312 | RETURN_ERR(ERR_INVALID_JSON, "Not a number"); 313 | } 314 | if (repeated) 315 | { 316 | ref->AddInt64(msg, field, json->GetInt64()); 317 | } 318 | else 319 | { 320 | ref->SetInt64(msg, field, json->GetInt64()); 321 | } 322 | break; 323 | } 324 | case FieldDescriptor::CPPTYPE_UINT64: 325 | { 326 | if (json->GetType() != rapidjson::kNumberType) 327 | { 328 | RETURN_ERR(ERR_INVALID_JSON, "Not a number"); 329 | } 330 | if (repeated) 331 | { 332 | ref->AddUInt64(msg, field, json->GetUint64()); 333 | } 334 | else 335 | { 336 | ref->SetUInt64(msg, field, json->GetUint64()); 337 | } 338 | break; 339 | } 340 | case FieldDescriptor::CPPTYPE_DOUBLE: 341 | { 342 | if (json->GetType() != rapidjson::kNumberType) 343 | { 344 | RETURN_ERR(ERR_INVALID_JSON, "Not a number"); 345 | } 346 | if (repeated) 347 | { 348 | ref->AddDouble(msg, field, json->GetDouble()); 349 | } 350 | else 351 | { 352 | ref->SetDouble(msg, field, json->GetDouble()); 353 | } 354 | break; 355 | } 356 | case FieldDescriptor::CPPTYPE_FLOAT: 357 | { 358 | if (json->GetType() != rapidjson::kNumberType) 359 | { 360 | RETURN_ERR(ERR_INVALID_JSON, "Not a number"); 361 | } 362 | if (repeated) 363 | { 364 | ref->AddFloat(msg, field, json->GetDouble()); 365 | } 366 | else 367 | { 368 | ref->SetFloat(msg, field, json->GetDouble()); 369 | } 370 | break; 371 | } 372 | case FieldDescriptor::CPPTYPE_BOOL: 373 | { 374 | if (json->GetType() != rapidjson::kTrueType && json->GetType() != rapidjson::kFalseType) 375 | { 376 | RETURN_ERR(ERR_INVALID_JSON, "Not a bool"); 377 | } 378 | bool v = json->GetBool(); 379 | if (repeated) 380 | { 381 | ref->AddBool(msg, field, v); 382 | } 383 | else 384 | { 385 | ref->SetBool(msg, field, v); 386 | } 387 | break; 388 | } 389 | case FieldDescriptor::CPPTYPE_STRING: 390 | { 391 | if (json->GetType() != rapidjson::kStringType) 392 | { 393 | RETURN_ERR(ERR_INVALID_JSON, "Not a string"); 394 | } 395 | const char* value = json->GetString(); 396 | uint32_t str_size = json->GetStringLength(); 397 | std::string str_value(value, str_size); 398 | if (field->type() == FieldDescriptor::TYPE_BYTES) 399 | { 400 | if (repeated) 401 | { 402 | ref->AddString(msg, field, b64_decode(str_value)); 403 | } 404 | else 405 | { 406 | ref->SetString(msg, field, b64_decode(str_value)); 407 | } 408 | } 409 | else 410 | { 411 | if (repeated) 412 | { 413 | ref->AddString(msg, field, str_value); 414 | } 415 | else 416 | { 417 | ref->SetString(msg, field, str_value); 418 | } 419 | } 420 | break; 421 | } 422 | case FieldDescriptor::CPPTYPE_MESSAGE: 423 | { 424 | Message *mf = (repeated) ? ref->AddMessage(msg, field) : ref->MutableMessage(msg, field); 425 | return parse_json(json, mf, err); 426 | } 427 | case FieldDescriptor::CPPTYPE_ENUM: 428 | { 429 | const EnumDescriptor *ed = field->enum_type(); 430 | const EnumValueDescriptor *ev = 0; 431 | if (json->GetType() == rapidjson::kNumberType) 432 | { 433 | ev = ed->FindValueByNumber(json->GetInt()); 434 | } 435 | else if (json->GetType() == rapidjson::kStringType) 436 | { 437 | ev = ed->FindValueByName(json->GetString()); 438 | } 439 | else 440 | RETURN_ERR(ERR_INVALID_JSON, "Not an integer or string"); 441 | if (!ev) 442 | RETURN_ERR(ERR_INVALID_JSON, "Enum value not found"); 443 | if (repeated) 444 | { 445 | ref->AddEnum(msg, field, ev); 446 | } 447 | else 448 | { 449 | ref->SetEnum(msg, field, ev); 450 | } 451 | break; 452 | } 453 | default: 454 | break; 455 | } 456 | return 0; 457 | } 458 | 459 | static int parse_json(const rapidjson::Value* json, Message* msg, std::string& err) 460 | { 461 | if (NULL == json || json->GetType() != rapidjson::kObjectType) 462 | { 463 | return ERR_INVALID_ARG; 464 | } 465 | const Descriptor *d = msg->GetDescriptor(); 466 | const Reflection *ref = msg->GetReflection(); 467 | if (!d || !ref) 468 | { 469 | RETURN_ERR(ERR_INVALID_PB, "invalid pb object"); 470 | } 471 | for (rapidjson::Value::ConstMemberIterator itr = json->MemberBegin(); itr != json->MemberEnd(); ++itr) 472 | { 473 | const char* name = itr->name.GetString(); 474 | const FieldDescriptor *field = d->FindFieldByName(name); 475 | if (!field) 476 | field = ref->FindKnownExtensionByName(name); 477 | if (!field) 478 | continue; // TODO: we should not fail here, instead write this value into an unknown field 479 | if (itr->value.GetType() == rapidjson::kNullType) { 480 | ref->ClearField(msg, field); 481 | continue; 482 | } 483 | if (field->is_repeated()) 484 | { 485 | if (itr->value.GetType() != rapidjson::kArrayType) 486 | RETURN_ERR(ERR_INVALID_JSON, "Not array"); 487 | for (rapidjson::Value::ConstValueIterator ait = itr->value.Begin(); ait != itr->value.End(); ++ait) 488 | { 489 | int ret = json2field(ait, msg, field, err); 490 | if (ret != 0) 491 | { 492 | return ret; 493 | } 494 | } 495 | } 496 | else 497 | { 498 | int ret = json2field(&(itr->value), msg, field, err); 499 | if (ret != 0) 500 | { 501 | return ret; 502 | } 503 | } 504 | } 505 | return 0; 506 | } 507 | 508 | void json2string(const rapidjson::Value* json, std::string& str) 509 | { 510 | rapidjson::StringBuffer buffer; 511 | rapidjson::Writer writer(buffer); 512 | json->Accept(writer); 513 | str.append(buffer.GetString(), buffer.GetSize()); 514 | } 515 | 516 | void pb2json(const Message* msg, std::string& str) 517 | { 518 | rapidjson::Value::AllocatorType allocator; 519 | rapidjson::Value* json = parse_msg(msg, allocator); 520 | json2string(json, str); 521 | delete json; 522 | } 523 | 524 | rapidjson::Value* pb2jsonobject(const google::protobuf::Message* msg) 525 | { 526 | rapidjson::Value::AllocatorType allocator; 527 | return parse_msg(msg, allocator); 528 | } 529 | 530 | rapidjson::Value* pb2jsonobject(const google::protobuf::Message* msg, rapidjson::Value::AllocatorType& allocator) 531 | { 532 | return parse_msg(msg, allocator); 533 | } 534 | 535 | int json2pb(const std::string& json, google::protobuf::Message* msg, std::string& err) 536 | { 537 | rapidjson::Document d; 538 | d.Parse<0>(json.c_str()); 539 | if (d.HasParseError()) 540 | { 541 | err += d.GetParseError(); 542 | return ERR_INVALID_ARG; 543 | } 544 | int ret = jsonobject2pb(&d, msg, err); 545 | return ret; 546 | } 547 | int jsonobject2pb(const rapidjson::Value* json, google::protobuf::Message* msg, std::string& err) 548 | { 549 | return parse_json(json, msg, err); 550 | } 551 | 552 | } 553 | -------------------------------------------------------------------------------- /src/pbjson.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | *Copyright (c) 2013-2014, yinqiwen 3 | *All rights reserved. 4 | * 5 | *Redistribution and use in source and binary forms, with or without 6 | *modification, are permitted provided that the following conditions are met: 7 | * 8 | * * Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * * Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * * Neither the name of Redis nor the names of its contributors may be used 14 | * to endorse or promote products derived from this software without 15 | * specific prior written permission. 16 | * 17 | *THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 | *AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | *IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | *ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS 21 | *BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 | *CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 | *SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 | *INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25 | *CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26 | *ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 27 | *THE POSSIBILITY OF SUCH DAMAGE. 28 | */ 29 | 30 | #ifndef PBJSON_HPP_ 31 | #define PBJSON_HPP_ 32 | 33 | #include 34 | #include 35 | #include 36 | #include "rapidjson/document.h" 37 | 38 | #define ERR_INVALID_ARG -1 39 | #define ERR_INVALID_PB -2 40 | #define ERR_UNKNOWN_FIELD -3 41 | #define ERR_INVALID_JSON -4 42 | 43 | namespace pbjson 44 | { 45 | void pb2json(const google::protobuf::Message* msg, std::string& str); 46 | rapidjson::Value* pb2jsonobject(const google::protobuf::Message* msg); 47 | rapidjson::Value* pb2jsonobject(const google::protobuf::Message* msg, rapidjson::Value::AllocatorType& allocator); 48 | void json2string(const rapidjson::Value* json, std::string& str); 49 | 50 | int json2pb(const std::string& json, google::protobuf::Message* msg, std::string& err); 51 | int jsonobject2pb(const rapidjson::Value* json, google::protobuf::Message* msg, std::string& err); 52 | } 53 | 54 | 55 | #endif /* PBJSON_HPP_ */ 56 | -------------------------------------------------------------------------------- /src/rapidjson/allocators.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_ALLOCATORS_H_ 16 | #define RAPIDJSON_ALLOCATORS_H_ 17 | 18 | #include "rapidjson.h" 19 | 20 | RAPIDJSON_NAMESPACE_BEGIN 21 | 22 | /////////////////////////////////////////////////////////////////////////////// 23 | // Allocator 24 | 25 | /*! \class rapidjson::Allocator 26 | \brief Concept for allocating, resizing and freeing memory block. 27 | 28 | Note that Malloc() and Realloc() are non-static but Free() is static. 29 | 30 | So if an allocator need to support Free(), it needs to put its pointer in 31 | the header of memory block. 32 | 33 | \code 34 | concept Allocator { 35 | static const bool kNeedFree; //!< Whether this allocator needs to call Free(). 36 | 37 | // Allocate a memory block. 38 | // \param size of the memory block in bytes. 39 | // \returns pointer to the memory block. 40 | void* Malloc(size_t size); 41 | 42 | // Resize a memory block. 43 | // \param originalPtr The pointer to current memory block. Null pointer is permitted. 44 | // \param originalSize The current size in bytes. (Design issue: since some allocator may not book-keep this, explicitly pass to it can save memory.) 45 | // \param newSize the new size in bytes. 46 | void* Realloc(void* originalPtr, size_t originalSize, size_t newSize); 47 | 48 | // Free a memory block. 49 | // \param pointer to the memory block. Null pointer is permitted. 50 | static void Free(void *ptr); 51 | }; 52 | \endcode 53 | */ 54 | 55 | /////////////////////////////////////////////////////////////////////////////// 56 | // CrtAllocator 57 | 58 | //! C-runtime library allocator. 59 | /*! This class is just wrapper for standard C library memory routines. 60 | \note implements Allocator concept 61 | */ 62 | class CrtAllocator { 63 | public: 64 | static const bool kNeedFree = true; 65 | void* Malloc(size_t size) { 66 | if (size) // behavior of malloc(0) is implementation defined. 67 | return std::malloc(size); 68 | else 69 | return NULL; // standardize to returning NULL. 70 | } 71 | void* Realloc(void* originalPtr, size_t originalSize, size_t newSize) { (void)originalSize; return std::realloc(originalPtr, newSize); } 72 | static void Free(void *ptr) { std::free(ptr); } 73 | }; 74 | 75 | /////////////////////////////////////////////////////////////////////////////// 76 | // MemoryPoolAllocator 77 | 78 | //! Default memory allocator used by the parser and DOM. 79 | /*! This allocator allocate memory blocks from pre-allocated memory chunks. 80 | 81 | It does not free memory blocks. And Realloc() only allocate new memory. 82 | 83 | The memory chunks are allocated by BaseAllocator, which is CrtAllocator by default. 84 | 85 | User may also supply a buffer as the first chunk. 86 | 87 | If the user-buffer is full then additional chunks are allocated by BaseAllocator. 88 | 89 | The user-buffer is not deallocated by this allocator. 90 | 91 | \tparam BaseAllocator the allocator type for allocating memory chunks. Default is CrtAllocator. 92 | \note implements Allocator concept 93 | */ 94 | template 95 | class MemoryPoolAllocator { 96 | public: 97 | static const bool kNeedFree = false; //!< Tell users that no need to call Free() with this allocator. (concept Allocator) 98 | 99 | //! Constructor with chunkSize. 100 | /*! \param chunkSize The size of memory chunk. The default is kDefaultChunkSize. 101 | \param baseAllocator The allocator for allocating memory chunks. 102 | */ 103 | MemoryPoolAllocator(size_t chunkSize = kDefaultChunkCapacity, BaseAllocator* baseAllocator = 0) : 104 | chunkHead_(0), chunk_capacity_(chunkSize), userBuffer_(0), baseAllocator_(baseAllocator), ownBaseAllocator_(0) 105 | { 106 | } 107 | 108 | //! Constructor with user-supplied buffer. 109 | /*! The user buffer will be used firstly. When it is full, memory pool allocates new chunk with chunk size. 110 | 111 | The user buffer will not be deallocated when this allocator is destructed. 112 | 113 | \param buffer User supplied buffer. 114 | \param size Size of the buffer in bytes. It must at least larger than sizeof(ChunkHeader). 115 | \param chunkSize The size of memory chunk. The default is kDefaultChunkSize. 116 | \param baseAllocator The allocator for allocating memory chunks. 117 | */ 118 | MemoryPoolAllocator(void *buffer, size_t size, size_t chunkSize = kDefaultChunkCapacity, BaseAllocator* baseAllocator = 0) : 119 | chunkHead_(0), chunk_capacity_(chunkSize), userBuffer_(buffer), baseAllocator_(baseAllocator), ownBaseAllocator_(0) 120 | { 121 | RAPIDJSON_ASSERT(buffer != 0); 122 | RAPIDJSON_ASSERT(size > sizeof(ChunkHeader)); 123 | chunkHead_ = reinterpret_cast(buffer); 124 | chunkHead_->capacity = size - sizeof(ChunkHeader); 125 | chunkHead_->size = 0; 126 | chunkHead_->next = 0; 127 | } 128 | 129 | //! Destructor. 130 | /*! This deallocates all memory chunks, excluding the user-supplied buffer. 131 | */ 132 | ~MemoryPoolAllocator() { 133 | Clear(); 134 | RAPIDJSON_DELETE(ownBaseAllocator_); 135 | } 136 | 137 | //! Deallocates all memory chunks, excluding the user-supplied buffer. 138 | void Clear() { 139 | while(chunkHead_ != 0 && chunkHead_ != userBuffer_) { 140 | ChunkHeader* next = chunkHead_->next; 141 | baseAllocator_->Free(chunkHead_); 142 | chunkHead_ = next; 143 | } 144 | } 145 | 146 | //! Computes the total capacity of allocated memory chunks. 147 | /*! \return total capacity in bytes. 148 | */ 149 | size_t Capacity() const { 150 | size_t capacity = 0; 151 | for (ChunkHeader* c = chunkHead_; c != 0; c = c->next) 152 | capacity += c->capacity; 153 | return capacity; 154 | } 155 | 156 | //! Computes the memory blocks allocated. 157 | /*! \return total used bytes. 158 | */ 159 | size_t Size() const { 160 | size_t size = 0; 161 | for (ChunkHeader* c = chunkHead_; c != 0; c = c->next) 162 | size += c->size; 163 | return size; 164 | } 165 | 166 | //! Allocates a memory block. (concept Allocator) 167 | void* Malloc(size_t size) { 168 | if (!size) 169 | return NULL; 170 | 171 | size = RAPIDJSON_ALIGN(size); 172 | if (chunkHead_ == 0 || chunkHead_->size + size > chunkHead_->capacity) 173 | AddChunk(chunk_capacity_ > size ? chunk_capacity_ : size); 174 | 175 | void *buffer = reinterpret_cast(chunkHead_ + 1) + chunkHead_->size; 176 | chunkHead_->size += size; 177 | return buffer; 178 | } 179 | 180 | //! Resizes a memory block (concept Allocator) 181 | void* Realloc(void* originalPtr, size_t originalSize, size_t newSize) { 182 | if (originalPtr == 0) 183 | return Malloc(newSize); 184 | 185 | // Do not shrink if new size is smaller than original 186 | if (originalSize >= newSize) 187 | return originalPtr; 188 | 189 | // Simply expand it if it is the last allocation and there is sufficient space 190 | if (originalPtr == (char *)(chunkHead_ + 1) + chunkHead_->size - originalSize) { 191 | size_t increment = static_cast(newSize - originalSize); 192 | increment = RAPIDJSON_ALIGN(increment); 193 | if (chunkHead_->size + increment <= chunkHead_->capacity) { 194 | chunkHead_->size += increment; 195 | return originalPtr; 196 | } 197 | } 198 | 199 | // Realloc process: allocate and copy memory, do not free original buffer. 200 | void* newBuffer = Malloc(newSize); 201 | RAPIDJSON_ASSERT(newBuffer != 0); // Do not handle out-of-memory explicitly. 202 | if (originalSize) 203 | std::memcpy(newBuffer, originalPtr, originalSize); 204 | return newBuffer; 205 | } 206 | 207 | //! Frees a memory block (concept Allocator) 208 | static void Free(void *ptr) { (void)ptr; } // Do nothing 209 | 210 | private: 211 | //! Copy constructor is not permitted. 212 | MemoryPoolAllocator(const MemoryPoolAllocator& rhs) /* = delete */; 213 | //! Copy assignment operator is not permitted. 214 | MemoryPoolAllocator& operator=(const MemoryPoolAllocator& rhs) /* = delete */; 215 | 216 | //! Creates a new chunk. 217 | /*! \param capacity Capacity of the chunk in bytes. 218 | */ 219 | void AddChunk(size_t capacity) { 220 | if (!baseAllocator_) 221 | ownBaseAllocator_ = baseAllocator_ = RAPIDJSON_NEW(BaseAllocator()); 222 | ChunkHeader* chunk = reinterpret_cast(baseAllocator_->Malloc(sizeof(ChunkHeader) + capacity)); 223 | chunk->capacity = capacity; 224 | chunk->size = 0; 225 | chunk->next = chunkHead_; 226 | chunkHead_ = chunk; 227 | } 228 | 229 | static const int kDefaultChunkCapacity = 64 * 1024; //!< Default chunk capacity. 230 | 231 | //! Chunk header for perpending to each chunk. 232 | /*! Chunks are stored as a singly linked list. 233 | */ 234 | struct ChunkHeader { 235 | size_t capacity; //!< Capacity of the chunk in bytes (excluding the header itself). 236 | size_t size; //!< Current size of allocated memory in bytes. 237 | ChunkHeader *next; //!< Next chunk in the linked list. 238 | }; 239 | 240 | ChunkHeader *chunkHead_; //!< Head of the chunk linked-list. Only the head chunk serves allocation. 241 | size_t chunk_capacity_; //!< The minimum capacity of chunk when they are allocated. 242 | void *userBuffer_; //!< User supplied buffer. 243 | BaseAllocator* baseAllocator_; //!< base allocator for allocating memory chunks. 244 | BaseAllocator* ownBaseAllocator_; //!< base allocator created by this object. 245 | }; 246 | 247 | RAPIDJSON_NAMESPACE_END 248 | 249 | #endif // RAPIDJSON_ENCODINGS_H_ 250 | -------------------------------------------------------------------------------- /src/rapidjson/encodedstream.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_ENCODEDSTREAM_H_ 16 | #define RAPIDJSON_ENCODEDSTREAM_H_ 17 | 18 | #include "rapidjson.h" 19 | 20 | #ifdef __GNUC__ 21 | RAPIDJSON_DIAG_PUSH 22 | RAPIDJSON_DIAG_OFF(effc++) 23 | #endif 24 | 25 | RAPIDJSON_NAMESPACE_BEGIN 26 | 27 | //! Input byte stream wrapper with a statically bound encoding. 28 | /*! 29 | \tparam Encoding The interpretation of encoding of the stream. Either UTF8, UTF16LE, UTF16BE, UTF32LE, UTF32BE. 30 | \tparam InputByteStream Type of input byte stream. For example, FileReadStream. 31 | */ 32 | template 33 | class EncodedInputStream { 34 | RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); 35 | public: 36 | typedef typename Encoding::Ch Ch; 37 | 38 | EncodedInputStream(InputByteStream& is) : is_(is) { 39 | current_ = Encoding::TakeBOM(is_); 40 | } 41 | 42 | Ch Peek() const { return current_; } 43 | Ch Take() { Ch c = current_; current_ = Encoding::Take(is_); return c; } 44 | size_t Tell() const { return is_.Tell(); } 45 | 46 | // Not implemented 47 | void Put(Ch) { RAPIDJSON_ASSERT(false); } 48 | void Flush() { RAPIDJSON_ASSERT(false); } 49 | Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } 50 | size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; } 51 | 52 | private: 53 | EncodedInputStream(const EncodedInputStream&); 54 | EncodedInputStream& operator=(const EncodedInputStream&); 55 | 56 | InputByteStream& is_; 57 | Ch current_; 58 | }; 59 | 60 | //! Output byte stream wrapper with statically bound encoding. 61 | /*! 62 | \tparam Encoding The interpretation of encoding of the stream. Either UTF8, UTF16LE, UTF16BE, UTF32LE, UTF32BE. 63 | \tparam InputByteStream Type of input byte stream. For example, FileWriteStream. 64 | */ 65 | template 66 | class EncodedOutputStream { 67 | RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); 68 | public: 69 | typedef typename Encoding::Ch Ch; 70 | 71 | EncodedOutputStream(OutputByteStream& os, bool putBOM = true) : os_(os) { 72 | if (putBOM) 73 | Encoding::PutBOM(os_); 74 | } 75 | 76 | void Put(Ch c) { Encoding::Put(os_, c); } 77 | void Flush() { os_.Flush(); } 78 | 79 | // Not implemented 80 | Ch Peek() const { RAPIDJSON_ASSERT(false); } 81 | Ch Take() { RAPIDJSON_ASSERT(false); } 82 | size_t Tell() const { RAPIDJSON_ASSERT(false); return 0; } 83 | Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } 84 | size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; } 85 | 86 | private: 87 | EncodedOutputStream(const EncodedOutputStream&); 88 | EncodedOutputStream& operator=(const EncodedOutputStream&); 89 | 90 | OutputByteStream& os_; 91 | }; 92 | 93 | #define RAPIDJSON_ENCODINGS_FUNC(x) UTF8::x, UTF16LE::x, UTF16BE::x, UTF32LE::x, UTF32BE::x 94 | 95 | //! Input stream wrapper with dynamically bound encoding and automatic encoding detection. 96 | /*! 97 | \tparam CharType Type of character for reading. 98 | \tparam InputByteStream type of input byte stream to be wrapped. 99 | */ 100 | template 101 | class AutoUTFInputStream { 102 | RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); 103 | public: 104 | typedef CharType Ch; 105 | 106 | //! Constructor. 107 | /*! 108 | \param is input stream to be wrapped. 109 | \param type UTF encoding type if it is not detected from the stream. 110 | */ 111 | AutoUTFInputStream(InputByteStream& is, UTFType type = kUTF8) : is_(&is), type_(type), hasBOM_(false) { 112 | RAPIDJSON_ASSERT(type >= kUTF8 && type <= kUTF32BE); 113 | DetectType(); 114 | static const TakeFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Take) }; 115 | takeFunc_ = f[type_]; 116 | current_ = takeFunc_(*is_); 117 | } 118 | 119 | UTFType GetType() const { return type_; } 120 | bool HasBOM() const { return hasBOM_; } 121 | 122 | Ch Peek() const { return current_; } 123 | Ch Take() { Ch c = current_; current_ = takeFunc_(*is_); return c; } 124 | size_t Tell() const { return is_->Tell(); } 125 | 126 | // Not implemented 127 | void Put(Ch) { RAPIDJSON_ASSERT(false); } 128 | void Flush() { RAPIDJSON_ASSERT(false); } 129 | Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } 130 | size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; } 131 | 132 | private: 133 | AutoUTFInputStream(const AutoUTFInputStream&); 134 | AutoUTFInputStream& operator=(const AutoUTFInputStream&); 135 | 136 | // Detect encoding type with BOM or RFC 4627 137 | void DetectType() { 138 | // BOM (Byte Order Mark): 139 | // 00 00 FE FF UTF-32BE 140 | // FF FE 00 00 UTF-32LE 141 | // FE FF UTF-16BE 142 | // FF FE UTF-16LE 143 | // EF BB BF UTF-8 144 | 145 | const unsigned char* c = (const unsigned char *)is_->Peek4(); 146 | if (!c) 147 | return; 148 | 149 | unsigned bom = c[0] | (c[1] << 8) | (c[2] << 16) | (c[3] << 24); 150 | hasBOM_ = false; 151 | if (bom == 0xFFFE0000) { type_ = kUTF32BE; hasBOM_ = true; is_->Take(); is_->Take(); is_->Take(); is_->Take(); } 152 | else if (bom == 0x0000FEFF) { type_ = kUTF32LE; hasBOM_ = true; is_->Take(); is_->Take(); is_->Take(); is_->Take(); } 153 | else if ((bom & 0xFFFF) == 0xFFFE) { type_ = kUTF16BE; hasBOM_ = true; is_->Take(); is_->Take(); } 154 | else if ((bom & 0xFFFF) == 0xFEFF) { type_ = kUTF16LE; hasBOM_ = true; is_->Take(); is_->Take(); } 155 | else if ((bom & 0xFFFFFF) == 0xBFBBEF) { type_ = kUTF8; hasBOM_ = true; is_->Take(); is_->Take(); is_->Take(); } 156 | 157 | // RFC 4627: Section 3 158 | // "Since the first two characters of a JSON text will always be ASCII 159 | // characters [RFC0020], it is possible to determine whether an octet 160 | // stream is UTF-8, UTF-16 (BE or LE), or UTF-32 (BE or LE) by looking 161 | // at the pattern of nulls in the first four octets." 162 | // 00 00 00 xx UTF-32BE 163 | // 00 xx 00 xx UTF-16BE 164 | // xx 00 00 00 UTF-32LE 165 | // xx 00 xx 00 UTF-16LE 166 | // xx xx xx xx UTF-8 167 | 168 | if (!hasBOM_) { 169 | unsigned pattern = (c[0] ? 1 : 0) | (c[1] ? 2 : 0) | (c[2] ? 4 : 0) | (c[3] ? 8 : 0); 170 | switch (pattern) { 171 | case 0x08: type_ = kUTF32BE; break; 172 | case 0x0A: type_ = kUTF16BE; break; 173 | case 0x01: type_ = kUTF32LE; break; 174 | case 0x05: type_ = kUTF16LE; break; 175 | case 0x0F: type_ = kUTF8; break; 176 | default: break; // Use type defined by user. 177 | } 178 | } 179 | 180 | // Runtime check whether the size of character type is sufficient. It only perform checks with assertion. 181 | if (type_ == kUTF16LE || type_ == kUTF16BE) RAPIDJSON_ASSERT(sizeof(Ch) >= 2); 182 | if (type_ == kUTF32LE || type_ == kUTF32BE) RAPIDJSON_ASSERT(sizeof(Ch) >= 4); 183 | } 184 | 185 | typedef Ch (*TakeFunc)(InputByteStream& is); 186 | InputByteStream* is_; 187 | UTFType type_; 188 | Ch current_; 189 | TakeFunc takeFunc_; 190 | bool hasBOM_; 191 | }; 192 | 193 | //! Output stream wrapper with dynamically bound encoding and automatic encoding detection. 194 | /*! 195 | \tparam CharType Type of character for writing. 196 | \tparam InputByteStream type of output byte stream to be wrapped. 197 | */ 198 | template 199 | class AutoUTFOutputStream { 200 | RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); 201 | public: 202 | typedef CharType Ch; 203 | 204 | //! Constructor. 205 | /*! 206 | \param os output stream to be wrapped. 207 | \param type UTF encoding type. 208 | \param putBOM Whether to write BOM at the beginning of the stream. 209 | */ 210 | AutoUTFOutputStream(OutputByteStream& os, UTFType type, bool putBOM) : os_(&os), type_(type) { 211 | RAPIDJSON_ASSERT(type >= kUTF8 && type <= kUTF32BE); 212 | 213 | // Runtime check whether the size of character type is sufficient. It only perform checks with assertion. 214 | if (type_ == kUTF16LE || type_ == kUTF16BE) RAPIDJSON_ASSERT(sizeof(Ch) >= 2); 215 | if (type_ == kUTF32LE || type_ == kUTF32BE) RAPIDJSON_ASSERT(sizeof(Ch) >= 4); 216 | 217 | static const PutFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Put) }; 218 | putFunc_ = f[type_]; 219 | 220 | if (putBOM) 221 | PutBOM(); 222 | } 223 | 224 | UTFType GetType() const { return type_; } 225 | 226 | void Put(Ch c) { putFunc_(*os_, c); } 227 | void Flush() { os_->Flush(); } 228 | 229 | // Not implemented 230 | Ch Peek() const { RAPIDJSON_ASSERT(false); } 231 | Ch Take() { RAPIDJSON_ASSERT(false); } 232 | size_t Tell() const { RAPIDJSON_ASSERT(false); return 0; } 233 | Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } 234 | size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; } 235 | 236 | private: 237 | AutoUTFOutputStream(const AutoUTFOutputStream&); 238 | AutoUTFOutputStream& operator=(const AutoUTFOutputStream&); 239 | 240 | void PutBOM() { 241 | typedef void (*PutBOMFunc)(OutputByteStream&); 242 | static const PutBOMFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(PutBOM) }; 243 | f[type_](*os_); 244 | } 245 | 246 | typedef void (*PutFunc)(OutputByteStream&, Ch); 247 | 248 | OutputByteStream* os_; 249 | UTFType type_; 250 | PutFunc putFunc_; 251 | }; 252 | 253 | #undef RAPIDJSON_ENCODINGS_FUNC 254 | 255 | RAPIDJSON_NAMESPACE_END 256 | 257 | #ifdef __GNUC__ 258 | RAPIDJSON_DIAG_POP 259 | #endif 260 | 261 | #endif // RAPIDJSON_FILESTREAM_H_ 262 | -------------------------------------------------------------------------------- /src/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 | RAPIDJSON_NAMESPACE_BEGIN 21 | 22 | //! Maps error code of parsing into error message. 23 | /*! 24 | \ingroup RAPIDJSON_ERRORS 25 | \param parseErrorCode Error code obtained in parsing. 26 | \return the error message. 27 | \note User can make a copy of this function for localization. 28 | Using switch-case is safer for future modification of error codes. 29 | */ 30 | inline const RAPIDJSON_ERROR_CHARTYPE* GetParseError_En(ParseErrorCode parseErrorCode) { 31 | switch (parseErrorCode) { 32 | case kParseErrorNone: return RAPIDJSON_ERROR_STRING("No error."); 33 | 34 | case kParseErrorDocumentEmpty: return RAPIDJSON_ERROR_STRING("The document is empty."); 35 | case kParseErrorDocumentRootNotSingular: return RAPIDJSON_ERROR_STRING("The document root must not follow by other values."); 36 | 37 | case kParseErrorValueInvalid: return RAPIDJSON_ERROR_STRING("Invalid value."); 38 | 39 | case kParseErrorObjectMissName: return RAPIDJSON_ERROR_STRING("Missing a name for object member."); 40 | case kParseErrorObjectMissColon: return RAPIDJSON_ERROR_STRING("Missing a colon after a name of object member."); 41 | case kParseErrorObjectMissCommaOrCurlyBracket: return RAPIDJSON_ERROR_STRING("Missing a comma or '}' after an object member."); 42 | 43 | case kParseErrorArrayMissCommaOrSquareBracket: return RAPIDJSON_ERROR_STRING("Missing a comma or ']' after an array element."); 44 | 45 | case kParseErrorStringUnicodeEscapeInvalidHex: return RAPIDJSON_ERROR_STRING("Incorrect hex digit after \\u escape in string."); 46 | case kParseErrorStringUnicodeSurrogateInvalid: return RAPIDJSON_ERROR_STRING("The surrogate pair in string is invalid."); 47 | case kParseErrorStringEscapeInvalid: return RAPIDJSON_ERROR_STRING("Invalid escape character in string."); 48 | case kParseErrorStringMissQuotationMark: return RAPIDJSON_ERROR_STRING("Missing a closing quotation mark in string."); 49 | case kParseErrorStringInvalidEncoding: return RAPIDJSON_ERROR_STRING("Invalid encoding in string."); 50 | 51 | case kParseErrorNumberTooBig: return RAPIDJSON_ERROR_STRING("Number too big to be stored in double."); 52 | case kParseErrorNumberMissFraction: return RAPIDJSON_ERROR_STRING("Miss fraction part in number."); 53 | case kParseErrorNumberMissExponent: return RAPIDJSON_ERROR_STRING("Miss exponent in number."); 54 | 55 | case kParseErrorTermination: return RAPIDJSON_ERROR_STRING("Terminate parsing due to Handler error."); 56 | case kParseErrorUnspecificSyntaxError: return RAPIDJSON_ERROR_STRING("Unspecific syntax error."); 57 | 58 | default: 59 | return RAPIDJSON_ERROR_STRING("Unknown error."); 60 | } 61 | } 62 | 63 | RAPIDJSON_NAMESPACE_END 64 | 65 | #endif // RAPIDJSON_ERROR_EN_H__ 66 | -------------------------------------------------------------------------------- /src/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 | /*! \file error.h */ 19 | 20 | /*! \defgroup RAPIDJSON_ERRORS RapidJSON error handling */ 21 | 22 | /////////////////////////////////////////////////////////////////////////////// 23 | // RAPIDJSON_ERROR_CHARTYPE 24 | 25 | //! Character type of error messages. 26 | /*! \ingroup RAPIDJSON_ERRORS 27 | The default character type is \c char. 28 | On Windows, user can define this macro as \c TCHAR for supporting both 29 | unicode/non-unicode settings. 30 | */ 31 | #ifndef RAPIDJSON_ERROR_CHARTYPE 32 | #define RAPIDJSON_ERROR_CHARTYPE char 33 | #endif 34 | 35 | /////////////////////////////////////////////////////////////////////////////// 36 | // RAPIDJSON_ERROR_STRING 37 | 38 | //! Macro for converting string literial to \ref RAPIDJSON_ERROR_CHARTYPE[]. 39 | /*! \ingroup RAPIDJSON_ERRORS 40 | By default this conversion macro does nothing. 41 | On Windows, user can define this macro as \c _T(x) for supporting both 42 | unicode/non-unicode settings. 43 | */ 44 | #ifndef RAPIDJSON_ERROR_STRING 45 | #define RAPIDJSON_ERROR_STRING(x) x 46 | #endif 47 | 48 | RAPIDJSON_NAMESPACE_BEGIN 49 | 50 | /////////////////////////////////////////////////////////////////////////////// 51 | // ParseErrorCode 52 | 53 | //! Error code of parsing. 54 | /*! \ingroup RAPIDJSON_ERRORS 55 | \see GenericReader::Parse, GenericReader::GetParseErrorCode 56 | */ 57 | enum ParseErrorCode { 58 | kParseErrorNone = 0, //!< No error. 59 | 60 | kParseErrorDocumentEmpty, //!< The document is empty. 61 | kParseErrorDocumentRootNotSingular, //!< The document root must not follow by other values. 62 | 63 | kParseErrorValueInvalid, //!< Invalid value. 64 | 65 | kParseErrorObjectMissName, //!< Missing a name for object member. 66 | kParseErrorObjectMissColon, //!< Missing a colon after a name of object member. 67 | kParseErrorObjectMissCommaOrCurlyBracket, //!< Missing a comma or '}' after an object member. 68 | 69 | kParseErrorArrayMissCommaOrSquareBracket, //!< Missing a comma or ']' after an array element. 70 | 71 | kParseErrorStringUnicodeEscapeInvalidHex, //!< Incorrect hex digit after \\u escape in string. 72 | kParseErrorStringUnicodeSurrogateInvalid, //!< The surrogate pair in string is invalid. 73 | kParseErrorStringEscapeInvalid, //!< Invalid escape character in string. 74 | kParseErrorStringMissQuotationMark, //!< Missing a closing quotation mark in string. 75 | kParseErrorStringInvalidEncoding, //!< Invalid encoding in string. 76 | 77 | kParseErrorNumberTooBig, //!< Number too big to be stored in double. 78 | kParseErrorNumberMissFraction, //!< Miss fraction part in number. 79 | kParseErrorNumberMissExponent, //!< Miss exponent in number. 80 | 81 | kParseErrorTermination, //!< Parsing was terminated. 82 | kParseErrorUnspecificSyntaxError //!< Unspecific syntax error. 83 | }; 84 | 85 | //! Result of parsing (wraps ParseErrorCode) 86 | /*! 87 | \ingroup RAPIDJSON_ERRORS 88 | \code 89 | Document doc; 90 | ParseResult ok = doc.Parse("[42]"); 91 | if (!ok) { 92 | fprintf(stderr, "JSON parse error: %s (%u)", 93 | GetParseError_En(ok.Code()), ok.Offset()); 94 | exit(EXIT_FAILURE); 95 | } 96 | \endcode 97 | \see GenericReader::Parse, GenericDocument::Parse 98 | */ 99 | struct ParseResult { 100 | 101 | //! Default constructor, no error. 102 | ParseResult() : code_(kParseErrorNone), offset_(0) {} 103 | //! Constructor to set an error. 104 | ParseResult(ParseErrorCode code, size_t offset) : code_(code), offset_(offset) {} 105 | 106 | //! Get the error code. 107 | ParseErrorCode Code() const { return code_; } 108 | //! Get the error offset, if \ref IsError(), 0 otherwise. 109 | size_t Offset() const { return offset_; } 110 | 111 | //! Conversion to \c bool, returns \c true, iff !\ref IsError(). 112 | operator bool() const { return !IsError(); } 113 | //! Whether the result is an error. 114 | bool IsError() const { return code_ != kParseErrorNone; } 115 | 116 | bool operator==(const ParseResult& that) const { return code_ == that.code_; } 117 | bool operator==(ParseErrorCode code) const { return code_ == code; } 118 | friend bool operator==(ParseErrorCode code, const ParseResult & err) { return code == err.code_; } 119 | 120 | //! Reset error code. 121 | void Clear() { Set(kParseErrorNone); } 122 | //! Update error code and offset. 123 | void Set(ParseErrorCode code, size_t offset = 0) { code_ = code; offset_ = offset; } 124 | 125 | private: 126 | ParseErrorCode code_; 127 | size_t offset_; 128 | }; 129 | 130 | //! Function pointer type of GetParseError(). 131 | /*! \ingroup RAPIDJSON_ERRORS 132 | 133 | This is the prototype for \c GetParseError_X(), where \c X is a locale. 134 | User can dynamically change locale in runtime, e.g.: 135 | \code 136 | GetParseErrorFunc GetParseError = GetParseError_En; // or whatever 137 | const RAPIDJSON_ERROR_CHARTYPE* s = GetParseError(document.GetParseErrorCode()); 138 | \endcode 139 | */ 140 | typedef const RAPIDJSON_ERROR_CHARTYPE* (*GetParseErrorFunc)(ParseErrorCode); 141 | 142 | RAPIDJSON_NAMESPACE_END 143 | 144 | #endif // RAPIDJSON_ERROR_ERROR_H__ 145 | -------------------------------------------------------------------------------- /src/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 "rapidjson.h" 19 | #include 20 | 21 | RAPIDJSON_NAMESPACE_BEGIN 22 | 23 | //! File byte stream for input using fread(). 24 | /*! 25 | \note implements Stream concept 26 | */ 27 | class FileReadStream { 28 | public: 29 | typedef char Ch; //!< Character type (byte). 30 | 31 | //! Constructor. 32 | /*! 33 | \param fp File pointer opened for read. 34 | \param buffer user-supplied buffer. 35 | \param bufferSize size of buffer in bytes. Must >=4 bytes. 36 | */ 37 | 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) { 38 | RAPIDJSON_ASSERT(fp_ != 0); 39 | RAPIDJSON_ASSERT(bufferSize >= 4); 40 | Read(); 41 | } 42 | 43 | Ch Peek() const { return *current_; } 44 | Ch Take() { Ch c = *current_; Read(); return c; } 45 | size_t Tell() const { return count_ + static_cast(current_ - buffer_); } 46 | 47 | // Not implemented 48 | void Put(Ch) { RAPIDJSON_ASSERT(false); } 49 | void Flush() { RAPIDJSON_ASSERT(false); } 50 | Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } 51 | size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; } 52 | 53 | // For encoding detection only. 54 | const Ch* Peek4() const { 55 | return (current_ + 4 <= bufferLast_) ? current_ : 0; 56 | } 57 | 58 | private: 59 | void Read() { 60 | if (current_ < bufferLast_) 61 | ++current_; 62 | else if (!eof_) { 63 | count_ += readCount_; 64 | readCount_ = fread(buffer_, 1, bufferSize_, fp_); 65 | bufferLast_ = buffer_ + readCount_ - 1; 66 | current_ = buffer_; 67 | 68 | if (readCount_ < bufferSize_) { 69 | buffer_[readCount_] = '\0'; 70 | ++bufferLast_; 71 | eof_ = true; 72 | } 73 | } 74 | } 75 | 76 | std::FILE* fp_; 77 | Ch *buffer_; 78 | size_t bufferSize_; 79 | Ch *bufferLast_; 80 | Ch *current_; 81 | size_t readCount_; 82 | size_t count_; //!< Number of characters read 83 | bool eof_; 84 | }; 85 | 86 | RAPIDJSON_NAMESPACE_END 87 | 88 | #endif // RAPIDJSON_FILESTREAM_H_ 89 | -------------------------------------------------------------------------------- /src/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 "rapidjson.h" 19 | #include 20 | 21 | RAPIDJSON_NAMESPACE_BEGIN 22 | 23 | //! Wrapper of C file stream for input using fread(). 24 | /*! 25 | \note implements Stream concept 26 | */ 27 | class FileWriteStream { 28 | public: 29 | typedef char Ch; //!< Character type. Only support char. 30 | 31 | FileWriteStream(std::FILE* fp, char* buffer, size_t bufferSize) : fp_(fp), buffer_(buffer), bufferEnd_(buffer + bufferSize), current_(buffer_) { 32 | RAPIDJSON_ASSERT(fp_ != 0); 33 | } 34 | 35 | void Put(char c) { 36 | if (current_ >= bufferEnd_) 37 | Flush(); 38 | 39 | *current_++ = c; 40 | } 41 | 42 | void PutN(char c, size_t n) { 43 | size_t avail = static_cast(bufferEnd_ - current_); 44 | while (n > avail) { 45 | std::memset(current_, c, avail); 46 | current_ += avail; 47 | Flush(); 48 | n -= avail; 49 | avail = static_cast(bufferEnd_ - current_); 50 | } 51 | 52 | if (n > 0) { 53 | std::memset(current_, c, n); 54 | current_ += n; 55 | } 56 | } 57 | 58 | void Flush() { 59 | if (current_ != buffer_) { 60 | fwrite(buffer_, 1, static_cast(current_ - buffer_), fp_); 61 | current_ = buffer_; 62 | } 63 | } 64 | 65 | // Not implemented 66 | char Peek() const { RAPIDJSON_ASSERT(false); return 0; } 67 | char Take() { RAPIDJSON_ASSERT(false); return 0; } 68 | size_t Tell() const { RAPIDJSON_ASSERT(false); return 0; } 69 | char* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } 70 | size_t PutEnd(char*) { RAPIDJSON_ASSERT(false); return 0; } 71 | 72 | private: 73 | // Prohibit copy constructor & assignment operator. 74 | FileWriteStream(const FileWriteStream&); 75 | FileWriteStream& operator=(const FileWriteStream&); 76 | 77 | std::FILE* fp_; 78 | char *buffer_; 79 | char *bufferEnd_; 80 | char *current_; 81 | }; 82 | 83 | //! Implement specialized version of PutN() with memset() for better performance. 84 | template<> 85 | inline void PutN(FileWriteStream& stream, char c, size_t n) { 86 | stream.PutN(c, n); 87 | } 88 | 89 | RAPIDJSON_NAMESPACE_END 90 | 91 | #endif // RAPIDJSON_FILESTREAM_H_ 92 | -------------------------------------------------------------------------------- /src/rapidjson/internal/biginteger.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_BIGINTEGER_H_ 16 | #define RAPIDJSON_BIGINTEGER_H_ 17 | 18 | #include "../rapidjson.h" 19 | 20 | #if defined(_MSC_VER) && defined(_M_AMD64) 21 | #include // for _umul128 22 | #endif 23 | 24 | RAPIDJSON_NAMESPACE_BEGIN 25 | namespace internal { 26 | 27 | class BigInteger { 28 | public: 29 | typedef uint64_t Type; 30 | 31 | BigInteger(const BigInteger& rhs) : count_(rhs.count_) { 32 | std::memcpy(digits_, rhs.digits_, count_ * sizeof(Type)); 33 | } 34 | 35 | explicit BigInteger(uint64_t u) : count_(1) { 36 | digits_[0] = u; 37 | } 38 | 39 | BigInteger(const char* decimals, size_t length) : count_(1) { 40 | RAPIDJSON_ASSERT(length > 0); 41 | digits_[0] = 0; 42 | size_t i = 0; 43 | const size_t kMaxDigitPerIteration = 19; // 2^64 = 18446744073709551616 > 10^19 44 | while (length >= kMaxDigitPerIteration) { 45 | AppendDecimal64(decimals + i, decimals + i + kMaxDigitPerIteration); 46 | length -= kMaxDigitPerIteration; 47 | i += kMaxDigitPerIteration; 48 | } 49 | 50 | if (length > 0) 51 | AppendDecimal64(decimals + i, decimals + i + length); 52 | } 53 | 54 | BigInteger& operator=(uint64_t u) { 55 | digits_[0] = u; 56 | count_ = 1; 57 | return *this; 58 | } 59 | 60 | BigInteger& operator+=(uint64_t u) { 61 | Type backup = digits_[0]; 62 | digits_[0] += u; 63 | for (size_t i = 0; i < count_ - 1; i++) { 64 | if (digits_[i] >= backup) 65 | return *this; // no carry 66 | backup = digits_[i + 1]; 67 | digits_[i + 1] += 1; 68 | } 69 | 70 | // Last carry 71 | if (digits_[count_ - 1] < backup) 72 | PushBack(1); 73 | 74 | return *this; 75 | } 76 | 77 | BigInteger& operator*=(uint64_t u) { 78 | if (u == 0) return *this = 0; 79 | if (u == 1) return *this; 80 | if (*this == 1) return *this = u; 81 | 82 | uint64_t k = 0; 83 | for (size_t i = 0; i < count_; i++) { 84 | uint64_t hi; 85 | digits_[i] = MulAdd64(digits_[i], u, k, &hi); 86 | k = hi; 87 | } 88 | 89 | if (k > 0) 90 | PushBack(k); 91 | 92 | return *this; 93 | } 94 | 95 | BigInteger& operator*=(uint32_t u) { 96 | if (u == 0) return *this = 0; 97 | if (u == 1) return *this; 98 | if (*this == 1) return *this = u; 99 | 100 | uint32_t k = 0; 101 | for (size_t i = 0; i < count_; i++) { 102 | const uint64_t c = digits_[i] >> 32; 103 | const uint64_t d = digits_[i] & 0xFFFFFFFF; 104 | const uint64_t uc = u * c; 105 | const uint64_t ud = u * d; 106 | const uint64_t p0 = ud + k; 107 | const uint64_t p1 = uc + (p0 >> 32); 108 | digits_[i] = (p0 & 0xFFFFFFFF) | (p1 << 32); 109 | k = p1 >> 32; 110 | } 111 | 112 | if (k > 0) 113 | PushBack(k); 114 | 115 | return *this; 116 | } 117 | 118 | BigInteger& operator<<=(size_t shift) { 119 | if (IsZero() || shift == 0) return *this; 120 | 121 | size_t offset = shift / kTypeBit; 122 | size_t interShift = shift % kTypeBit; 123 | RAPIDJSON_ASSERT(count_ + offset <= kCapacity); 124 | 125 | if (interShift == 0) { 126 | std::memmove(&digits_[count_ - 1 + offset], &digits_[count_ - 1], count_ * sizeof(Type)); 127 | count_ += offset; 128 | } 129 | else { 130 | digits_[count_] = 0; 131 | for (size_t i = count_; i > 0; i--) 132 | digits_[i + offset] = (digits_[i] << interShift) | (digits_[i - 1] >> (kTypeBit - interShift)); 133 | digits_[offset] = digits_[0] << interShift; 134 | count_ += offset; 135 | if (digits_[count_]) 136 | count_++; 137 | } 138 | 139 | std::memset(digits_, 0, offset * sizeof(Type)); 140 | 141 | return *this; 142 | } 143 | 144 | bool operator==(const BigInteger& rhs) const { 145 | return count_ == rhs.count_ && std::memcmp(digits_, rhs.digits_, count_ * sizeof(Type)) == 0; 146 | } 147 | 148 | bool operator==(const Type rhs) const { 149 | return count_ == 1 && digits_[0] == rhs; 150 | } 151 | 152 | BigInteger& MultiplyPow5(unsigned exp) { 153 | static const uint32_t kPow5[12] = { 154 | 5, 155 | 5 * 5, 156 | 5 * 5 * 5, 157 | 5 * 5 * 5 * 5, 158 | 5 * 5 * 5 * 5 * 5, 159 | 5 * 5 * 5 * 5 * 5 * 5, 160 | 5 * 5 * 5 * 5 * 5 * 5 * 5, 161 | 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5, 162 | 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5, 163 | 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5, 164 | 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5, 165 | 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 166 | }; 167 | if (exp == 0) return *this; 168 | for (; exp >= 27; exp -= 27) *this *= RAPIDJSON_UINT64_C2(0X6765C793, 0XFA10079D); // 5^27 169 | for (; exp >= 13; exp -= 13) *this *= static_cast(1220703125u); // 5^13 170 | if (exp > 0) *this *= kPow5[exp - 1]; 171 | return *this; 172 | } 173 | 174 | // Compute absolute difference of this and rhs. 175 | // Assume this != rhs 176 | bool Difference(const BigInteger& rhs, BigInteger* out) const { 177 | int cmp = Compare(rhs); 178 | RAPIDJSON_ASSERT(cmp != 0); 179 | const BigInteger *a, *b; // Makes a > b 180 | bool ret; 181 | if (cmp < 0) { a = &rhs; b = this; ret = true; } 182 | else { a = this; b = &rhs; ret = false; } 183 | 184 | Type borrow = 0; 185 | for (size_t i = 0; i < a->count_; i++) { 186 | Type d = a->digits_[i] - borrow; 187 | if (i < b->count_) 188 | d -= b->digits_[i]; 189 | borrow = (d > a->digits_[i]) ? 1 : 0; 190 | out->digits_[i] = d; 191 | if (d != 0) 192 | out->count_ = i + 1; 193 | } 194 | 195 | return ret; 196 | } 197 | 198 | int Compare(const BigInteger& rhs) const { 199 | if (count_ != rhs.count_) 200 | return count_ < rhs.count_ ? -1 : 1; 201 | 202 | for (size_t i = count_; i-- > 0;) 203 | if (digits_[i] != rhs.digits_[i]) 204 | return digits_[i] < rhs.digits_[i] ? -1 : 1; 205 | 206 | return 0; 207 | } 208 | 209 | size_t GetCount() const { return count_; } 210 | Type GetDigit(size_t index) const { RAPIDJSON_ASSERT(index < count_); return digits_[index]; } 211 | bool IsZero() const { return count_ == 1 && digits_[0] == 0; } 212 | 213 | private: 214 | void AppendDecimal64(const char* begin, const char* end) { 215 | uint64_t u = ParseUint64(begin, end); 216 | if (IsZero()) 217 | *this = u; 218 | else { 219 | unsigned exp = static_cast(end - begin); 220 | (MultiplyPow5(exp) <<= exp) += u; // *this = *this * 10^exp + u 221 | } 222 | } 223 | 224 | void PushBack(Type digit) { 225 | RAPIDJSON_ASSERT(count_ < kCapacity); 226 | digits_[count_++] = digit; 227 | } 228 | 229 | static uint64_t ParseUint64(const char* begin, const char* end) { 230 | uint64_t r = 0; 231 | for (const char* p = begin; p != end; ++p) { 232 | RAPIDJSON_ASSERT(*p >= '0' && *p <= '9'); 233 | r = r * 10 + (*p - '0'); 234 | } 235 | return r; 236 | } 237 | 238 | // Assume a * b + k < 2^128 239 | static uint64_t MulAdd64(uint64_t a, uint64_t b, uint64_t k, uint64_t* outHigh) { 240 | #if defined(_MSC_VER) && defined(_M_AMD64) 241 | uint64_t low = _umul128(a, b, outHigh) + k; 242 | if (low < k) 243 | (*outHigh)++; 244 | return low; 245 | #elif (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) && defined(__x86_64__) 246 | __extension__ typedef unsigned __int128 uint128; 247 | uint128 p = static_cast(a) * static_cast(b); 248 | p += k; 249 | *outHigh = p >> 64; 250 | return static_cast(p); 251 | #else 252 | const uint64_t a0 = a & 0xFFFFFFFF, a1 = a >> 32, b0 = b & 0xFFFFFFFF, b1 = b >> 32; 253 | uint64_t x0 = a0 * b0, x1 = a0 * b1, x2 = a1 * b0, x3 = a1 * b1; 254 | x1 += (x0 >> 32); // can't give carry 255 | x1 += x2; 256 | if (x1 < x2) 257 | x3 += (static_cast(1) << 32); 258 | uint64_t lo = (x1 << 32) + (x0 & 0xFFFFFFFF); 259 | uint64_t hi = x3 + (x1 >> 32); 260 | 261 | lo += k; 262 | if (lo < k) 263 | hi++; 264 | *outHigh = hi; 265 | return lo; 266 | #endif 267 | } 268 | 269 | static const size_t kBitCount = 3328; // 64bit * 54 > 10^1000 270 | static const size_t kCapacity = kBitCount / sizeof(Type); 271 | static const size_t kTypeBit = sizeof(Type) * 8; 272 | 273 | Type digits_[kCapacity]; 274 | size_t count_; 275 | }; 276 | 277 | } // namespace internal 278 | RAPIDJSON_NAMESPACE_END 279 | 280 | #endif // RAPIDJSON_BIGINTEGER_H_ 281 | -------------------------------------------------------------------------------- /src/rapidjson/internal/diyfp.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 | // This is a C++ header-only implementation of Grisu2 algorithm from the publication: 16 | // Loitsch, Florian. "Printing floating-point numbers quickly and accurately with 17 | // integers." ACM Sigplan Notices 45.6 (2010): 233-243. 18 | 19 | #ifndef RAPIDJSON_DIYFP_H_ 20 | #define RAPIDJSON_DIYFP_H_ 21 | 22 | #if defined(_MSC_VER) 23 | #include 24 | #if defined(_M_AMD64) 25 | #pragma intrinsic(_BitScanReverse64) 26 | #endif 27 | #endif 28 | 29 | RAPIDJSON_NAMESPACE_BEGIN 30 | namespace internal { 31 | 32 | #ifdef __GNUC__ 33 | RAPIDJSON_DIAG_PUSH 34 | RAPIDJSON_DIAG_OFF(effc++) 35 | #endif 36 | 37 | struct DiyFp { 38 | DiyFp() {} 39 | 40 | DiyFp(uint64_t fp, int exp) : f(fp), e(exp) {} 41 | 42 | explicit DiyFp(double d) { 43 | union { 44 | double d; 45 | uint64_t u64; 46 | } u = { d }; 47 | 48 | int biased_e = (u.u64 & kDpExponentMask) >> kDpSignificandSize; 49 | uint64_t significand = (u.u64 & kDpSignificandMask); 50 | if (biased_e != 0) { 51 | f = significand + kDpHiddenBit; 52 | e = biased_e - kDpExponentBias; 53 | } 54 | else { 55 | f = significand; 56 | e = kDpMinExponent + 1; 57 | } 58 | } 59 | 60 | DiyFp operator-(const DiyFp& rhs) const { 61 | return DiyFp(f - rhs.f, e); 62 | } 63 | 64 | DiyFp operator*(const DiyFp& rhs) const { 65 | #if defined(_MSC_VER) && defined(_M_AMD64) 66 | uint64_t h; 67 | uint64_t l = _umul128(f, rhs.f, &h); 68 | if (l & (uint64_t(1) << 63)) // rounding 69 | h++; 70 | return DiyFp(h, e + rhs.e + 64); 71 | #elif (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) && defined(__x86_64__) 72 | __extension__ typedef unsigned __int128 uint128; 73 | uint128 p = static_cast(f) * static_cast(rhs.f); 74 | uint64_t h = p >> 64; 75 | uint64_t l = static_cast(p); 76 | if (l & (uint64_t(1) << 63)) // rounding 77 | h++; 78 | return DiyFp(h, e + rhs.e + 64); 79 | #else 80 | const uint64_t M32 = 0xFFFFFFFF; 81 | const uint64_t a = f >> 32; 82 | const uint64_t b = f & M32; 83 | const uint64_t c = rhs.f >> 32; 84 | const uint64_t d = rhs.f & M32; 85 | const uint64_t ac = a * c; 86 | const uint64_t bc = b * c; 87 | const uint64_t ad = a * d; 88 | const uint64_t bd = b * d; 89 | uint64_t tmp = (bd >> 32) + (ad & M32) + (bc & M32); 90 | tmp += 1U << 31; /// mult_round 91 | return DiyFp(ac + (ad >> 32) + (bc >> 32) + (tmp >> 32), e + rhs.e + 64); 92 | #endif 93 | } 94 | 95 | DiyFp Normalize() const { 96 | #if defined(_MSC_VER) && defined(_M_AMD64) 97 | unsigned long index; 98 | _BitScanReverse64(&index, f); 99 | return DiyFp(f << (63 - index), e - (63 - index)); 100 | #elif defined(__GNUC__) && __GNUC__ >= 4 101 | int s = __builtin_clzll(f); 102 | return DiyFp(f << s, e - s); 103 | #else 104 | DiyFp res = *this; 105 | while (!(res.f & (static_cast(1) << 63))) { 106 | res.f <<= 1; 107 | res.e--; 108 | } 109 | return res; 110 | #endif 111 | } 112 | 113 | DiyFp NormalizeBoundary() const { 114 | DiyFp res = *this; 115 | while (!(res.f & (kDpHiddenBit << 1))) { 116 | res.f <<= 1; 117 | res.e--; 118 | } 119 | res.f <<= (kDiySignificandSize - kDpSignificandSize - 2); 120 | res.e = res.e - (kDiySignificandSize - kDpSignificandSize - 2); 121 | return res; 122 | } 123 | 124 | void NormalizedBoundaries(DiyFp* minus, DiyFp* plus) const { 125 | DiyFp pl = DiyFp((f << 1) + 1, e - 1).NormalizeBoundary(); 126 | DiyFp mi = (f == kDpHiddenBit) ? DiyFp((f << 2) - 1, e - 2) : DiyFp((f << 1) - 1, e - 1); 127 | mi.f <<= mi.e - pl.e; 128 | mi.e = pl.e; 129 | *plus = pl; 130 | *minus = mi; 131 | } 132 | 133 | double ToDouble() const { 134 | union { 135 | double d; 136 | uint64_t u64; 137 | }u; 138 | const uint64_t be = (e == kDpDenormalExponent && (f & kDpHiddenBit) == 0) ? 0 : 139 | static_cast(e + kDpExponentBias); 140 | u.u64 = (f & kDpSignificandMask) | (be << kDpSignificandSize); 141 | return u.d; 142 | } 143 | 144 | static const int kDiySignificandSize = 64; 145 | static const int kDpSignificandSize = 52; 146 | static const int kDpExponentBias = 0x3FF + kDpSignificandSize; 147 | static const int kDpMaxExponent = 0x7FF - kDpExponentBias; 148 | static const int kDpMinExponent = -kDpExponentBias; 149 | static const int kDpDenormalExponent = -kDpExponentBias + 1; 150 | static const uint64_t kDpExponentMask = RAPIDJSON_UINT64_C2(0x7FF00000, 0x00000000); 151 | static const uint64_t kDpSignificandMask = RAPIDJSON_UINT64_C2(0x000FFFFF, 0xFFFFFFFF); 152 | static const uint64_t kDpHiddenBit = RAPIDJSON_UINT64_C2(0x00100000, 0x00000000); 153 | 154 | uint64_t f; 155 | int e; 156 | }; 157 | 158 | inline DiyFp GetCachedPowerByIndex(size_t index) { 159 | // 10^-348, 10^-340, ..., 10^340 160 | static const uint64_t kCachedPowers_F[] = { 161 | RAPIDJSON_UINT64_C2(0xfa8fd5a0, 0x081c0288), RAPIDJSON_UINT64_C2(0xbaaee17f, 0xa23ebf76), 162 | RAPIDJSON_UINT64_C2(0x8b16fb20, 0x3055ac76), RAPIDJSON_UINT64_C2(0xcf42894a, 0x5dce35ea), 163 | RAPIDJSON_UINT64_C2(0x9a6bb0aa, 0x55653b2d), RAPIDJSON_UINT64_C2(0xe61acf03, 0x3d1a45df), 164 | RAPIDJSON_UINT64_C2(0xab70fe17, 0xc79ac6ca), RAPIDJSON_UINT64_C2(0xff77b1fc, 0xbebcdc4f), 165 | RAPIDJSON_UINT64_C2(0xbe5691ef, 0x416bd60c), RAPIDJSON_UINT64_C2(0x8dd01fad, 0x907ffc3c), 166 | RAPIDJSON_UINT64_C2(0xd3515c28, 0x31559a83), RAPIDJSON_UINT64_C2(0x9d71ac8f, 0xada6c9b5), 167 | RAPIDJSON_UINT64_C2(0xea9c2277, 0x23ee8bcb), RAPIDJSON_UINT64_C2(0xaecc4991, 0x4078536d), 168 | RAPIDJSON_UINT64_C2(0x823c1279, 0x5db6ce57), RAPIDJSON_UINT64_C2(0xc2109436, 0x4dfb5637), 169 | RAPIDJSON_UINT64_C2(0x9096ea6f, 0x3848984f), RAPIDJSON_UINT64_C2(0xd77485cb, 0x25823ac7), 170 | RAPIDJSON_UINT64_C2(0xa086cfcd, 0x97bf97f4), RAPIDJSON_UINT64_C2(0xef340a98, 0x172aace5), 171 | RAPIDJSON_UINT64_C2(0xb23867fb, 0x2a35b28e), RAPIDJSON_UINT64_C2(0x84c8d4df, 0xd2c63f3b), 172 | RAPIDJSON_UINT64_C2(0xc5dd4427, 0x1ad3cdba), RAPIDJSON_UINT64_C2(0x936b9fce, 0xbb25c996), 173 | RAPIDJSON_UINT64_C2(0xdbac6c24, 0x7d62a584), RAPIDJSON_UINT64_C2(0xa3ab6658, 0x0d5fdaf6), 174 | RAPIDJSON_UINT64_C2(0xf3e2f893, 0xdec3f126), RAPIDJSON_UINT64_C2(0xb5b5ada8, 0xaaff80b8), 175 | RAPIDJSON_UINT64_C2(0x87625f05, 0x6c7c4a8b), RAPIDJSON_UINT64_C2(0xc9bcff60, 0x34c13053), 176 | RAPIDJSON_UINT64_C2(0x964e858c, 0x91ba2655), RAPIDJSON_UINT64_C2(0xdff97724, 0x70297ebd), 177 | RAPIDJSON_UINT64_C2(0xa6dfbd9f, 0xb8e5b88f), RAPIDJSON_UINT64_C2(0xf8a95fcf, 0x88747d94), 178 | RAPIDJSON_UINT64_C2(0xb9447093, 0x8fa89bcf), RAPIDJSON_UINT64_C2(0x8a08f0f8, 0xbf0f156b), 179 | RAPIDJSON_UINT64_C2(0xcdb02555, 0x653131b6), RAPIDJSON_UINT64_C2(0x993fe2c6, 0xd07b7fac), 180 | RAPIDJSON_UINT64_C2(0xe45c10c4, 0x2a2b3b06), RAPIDJSON_UINT64_C2(0xaa242499, 0x697392d3), 181 | RAPIDJSON_UINT64_C2(0xfd87b5f2, 0x8300ca0e), RAPIDJSON_UINT64_C2(0xbce50864, 0x92111aeb), 182 | RAPIDJSON_UINT64_C2(0x8cbccc09, 0x6f5088cc), RAPIDJSON_UINT64_C2(0xd1b71758, 0xe219652c), 183 | RAPIDJSON_UINT64_C2(0x9c400000, 0x00000000), RAPIDJSON_UINT64_C2(0xe8d4a510, 0x00000000), 184 | RAPIDJSON_UINT64_C2(0xad78ebc5, 0xac620000), RAPIDJSON_UINT64_C2(0x813f3978, 0xf8940984), 185 | RAPIDJSON_UINT64_C2(0xc097ce7b, 0xc90715b3), RAPIDJSON_UINT64_C2(0x8f7e32ce, 0x7bea5c70), 186 | RAPIDJSON_UINT64_C2(0xd5d238a4, 0xabe98068), RAPIDJSON_UINT64_C2(0x9f4f2726, 0x179a2245), 187 | RAPIDJSON_UINT64_C2(0xed63a231, 0xd4c4fb27), RAPIDJSON_UINT64_C2(0xb0de6538, 0x8cc8ada8), 188 | RAPIDJSON_UINT64_C2(0x83c7088e, 0x1aab65db), RAPIDJSON_UINT64_C2(0xc45d1df9, 0x42711d9a), 189 | RAPIDJSON_UINT64_C2(0x924d692c, 0xa61be758), RAPIDJSON_UINT64_C2(0xda01ee64, 0x1a708dea), 190 | RAPIDJSON_UINT64_C2(0xa26da399, 0x9aef774a), RAPIDJSON_UINT64_C2(0xf209787b, 0xb47d6b85), 191 | RAPIDJSON_UINT64_C2(0xb454e4a1, 0x79dd1877), RAPIDJSON_UINT64_C2(0x865b8692, 0x5b9bc5c2), 192 | RAPIDJSON_UINT64_C2(0xc83553c5, 0xc8965d3d), RAPIDJSON_UINT64_C2(0x952ab45c, 0xfa97a0b3), 193 | RAPIDJSON_UINT64_C2(0xde469fbd, 0x99a05fe3), RAPIDJSON_UINT64_C2(0xa59bc234, 0xdb398c25), 194 | RAPIDJSON_UINT64_C2(0xf6c69a72, 0xa3989f5c), RAPIDJSON_UINT64_C2(0xb7dcbf53, 0x54e9bece), 195 | RAPIDJSON_UINT64_C2(0x88fcf317, 0xf22241e2), RAPIDJSON_UINT64_C2(0xcc20ce9b, 0xd35c78a5), 196 | RAPIDJSON_UINT64_C2(0x98165af3, 0x7b2153df), RAPIDJSON_UINT64_C2(0xe2a0b5dc, 0x971f303a), 197 | RAPIDJSON_UINT64_C2(0xa8d9d153, 0x5ce3b396), RAPIDJSON_UINT64_C2(0xfb9b7cd9, 0xa4a7443c), 198 | RAPIDJSON_UINT64_C2(0xbb764c4c, 0xa7a44410), RAPIDJSON_UINT64_C2(0x8bab8eef, 0xb6409c1a), 199 | RAPIDJSON_UINT64_C2(0xd01fef10, 0xa657842c), RAPIDJSON_UINT64_C2(0x9b10a4e5, 0xe9913129), 200 | RAPIDJSON_UINT64_C2(0xe7109bfb, 0xa19c0c9d), RAPIDJSON_UINT64_C2(0xac2820d9, 0x623bf429), 201 | RAPIDJSON_UINT64_C2(0x80444b5e, 0x7aa7cf85), RAPIDJSON_UINT64_C2(0xbf21e440, 0x03acdd2d), 202 | RAPIDJSON_UINT64_C2(0x8e679c2f, 0x5e44ff8f), RAPIDJSON_UINT64_C2(0xd433179d, 0x9c8cb841), 203 | RAPIDJSON_UINT64_C2(0x9e19db92, 0xb4e31ba9), RAPIDJSON_UINT64_C2(0xeb96bf6e, 0xbadf77d9), 204 | RAPIDJSON_UINT64_C2(0xaf87023b, 0x9bf0ee6b) 205 | }; 206 | static const int16_t kCachedPowers_E[] = { 207 | -1220, -1193, -1166, -1140, -1113, -1087, -1060, -1034, -1007, -980, 208 | -954, -927, -901, -874, -847, -821, -794, -768, -741, -715, 209 | -688, -661, -635, -608, -582, -555, -529, -502, -475, -449, 210 | -422, -396, -369, -343, -316, -289, -263, -236, -210, -183, 211 | -157, -130, -103, -77, -50, -24, 3, 30, 56, 83, 212 | 109, 136, 162, 189, 216, 242, 269, 295, 322, 348, 213 | 375, 402, 428, 455, 481, 508, 534, 561, 588, 614, 214 | 641, 667, 694, 720, 747, 774, 800, 827, 853, 880, 215 | 907, 933, 960, 986, 1013, 1039, 1066 216 | }; 217 | return DiyFp(kCachedPowers_F[index], kCachedPowers_E[index]); 218 | } 219 | 220 | inline DiyFp GetCachedPower(int e, int* K) { 221 | 222 | //int k = static_cast(ceil((-61 - e) * 0.30102999566398114)) + 374; 223 | double dk = (-61 - e) * 0.30102999566398114 + 347; // dk must be positive, so can do ceiling in positive 224 | int k = static_cast(dk); 225 | if (dk - k > 0.0) 226 | k++; 227 | 228 | unsigned index = static_cast((k >> 3) + 1); 229 | *K = -(-348 + static_cast(index << 3)); // decimal exponent no need lookup table 230 | 231 | return GetCachedPowerByIndex(index); 232 | } 233 | 234 | inline DiyFp GetCachedPower10(int exp, int *outExp) { 235 | unsigned index = (exp + 348) / 8; 236 | *outExp = -348 + index * 8; 237 | return GetCachedPowerByIndex(index); 238 | } 239 | 240 | #ifdef __GNUC__ 241 | RAPIDJSON_DIAG_POP 242 | #endif 243 | 244 | } // namespace internal 245 | RAPIDJSON_NAMESPACE_END 246 | 247 | #endif // RAPIDJSON_DIYFP_H_ 248 | -------------------------------------------------------------------------------- /src/rapidjson/internal/dtoa.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 | // This is a C++ header-only implementation of Grisu2 algorithm from the publication: 16 | // Loitsch, Florian. "Printing floating-point numbers quickly and accurately with 17 | // integers." ACM Sigplan Notices 45.6 (2010): 233-243. 18 | 19 | #ifndef RAPIDJSON_DTOA_ 20 | #define RAPIDJSON_DTOA_ 21 | 22 | #include "itoa.h" // GetDigitsLut() 23 | #include "diyfp.h" 24 | #include "ieee754.h" 25 | 26 | RAPIDJSON_NAMESPACE_BEGIN 27 | namespace internal { 28 | 29 | #ifdef __GNUC__ 30 | RAPIDJSON_DIAG_PUSH 31 | RAPIDJSON_DIAG_OFF(effc++) 32 | #endif 33 | 34 | inline void GrisuRound(char* buffer, int len, uint64_t delta, uint64_t rest, uint64_t ten_kappa, uint64_t wp_w) { 35 | while (rest < wp_w && delta - rest >= ten_kappa && 36 | (rest + ten_kappa < wp_w || /// closer 37 | wp_w - rest > rest + ten_kappa - wp_w)) { 38 | buffer[len - 1]--; 39 | rest += ten_kappa; 40 | } 41 | } 42 | 43 | inline unsigned CountDecimalDigit32(uint32_t n) { 44 | // Simple pure C++ implementation was faster than __builtin_clz version in this situation. 45 | if (n < 10) return 1; 46 | if (n < 100) return 2; 47 | if (n < 1000) return 3; 48 | if (n < 10000) return 4; 49 | if (n < 100000) return 5; 50 | if (n < 1000000) return 6; 51 | if (n < 10000000) return 7; 52 | if (n < 100000000) return 8; 53 | // Will not reach 10 digits in DigitGen() 54 | //if (n < 1000000000) return 9; 55 | //return 10; 56 | return 9; 57 | } 58 | 59 | inline void DigitGen(const DiyFp& W, const DiyFp& Mp, uint64_t delta, char* buffer, int* len, int* K) { 60 | static const uint32_t kPow10[] = { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000 }; 61 | const DiyFp one(uint64_t(1) << -Mp.e, Mp.e); 62 | const DiyFp wp_w = Mp - W; 63 | uint32_t p1 = static_cast(Mp.f >> -one.e); 64 | uint64_t p2 = Mp.f & (one.f - 1); 65 | int kappa = CountDecimalDigit32(p1); // kappa in [0, 9] 66 | *len = 0; 67 | 68 | while (kappa > 0) { 69 | uint32_t d = 0; 70 | switch (kappa) { 71 | case 9: d = p1 / 100000000; p1 %= 100000000; break; 72 | case 8: d = p1 / 10000000; p1 %= 10000000; break; 73 | case 7: d = p1 / 1000000; p1 %= 1000000; break; 74 | case 6: d = p1 / 100000; p1 %= 100000; break; 75 | case 5: d = p1 / 10000; p1 %= 10000; break; 76 | case 4: d = p1 / 1000; p1 %= 1000; break; 77 | case 3: d = p1 / 100; p1 %= 100; break; 78 | case 2: d = p1 / 10; p1 %= 10; break; 79 | case 1: d = p1; p1 = 0; break; 80 | default:; 81 | } 82 | if (d || *len) 83 | buffer[(*len)++] = static_cast('0' + static_cast(d)); 84 | kappa--; 85 | uint64_t tmp = (static_cast(p1) << -one.e) + p2; 86 | if (tmp <= delta) { 87 | *K += kappa; 88 | GrisuRound(buffer, *len, delta, tmp, static_cast(kPow10[kappa]) << -one.e, wp_w.f); 89 | return; 90 | } 91 | } 92 | 93 | // kappa = 0 94 | for (;;) { 95 | p2 *= 10; 96 | delta *= 10; 97 | char d = static_cast(p2 >> -one.e); 98 | if (d || *len) 99 | buffer[(*len)++] = static_cast('0' + d); 100 | p2 &= one.f - 1; 101 | kappa--; 102 | if (p2 < delta) { 103 | *K += kappa; 104 | GrisuRound(buffer, *len, delta, p2, one.f, wp_w.f * kPow10[-kappa]); 105 | return; 106 | } 107 | } 108 | } 109 | 110 | inline void Grisu2(double value, char* buffer, int* length, int* K) { 111 | const DiyFp v(value); 112 | DiyFp w_m, w_p; 113 | v.NormalizedBoundaries(&w_m, &w_p); 114 | 115 | const DiyFp c_mk = GetCachedPower(w_p.e, K); 116 | const DiyFp W = v.Normalize() * c_mk; 117 | DiyFp Wp = w_p * c_mk; 118 | DiyFp Wm = w_m * c_mk; 119 | Wm.f++; 120 | Wp.f--; 121 | DigitGen(W, Wp, Wp.f - Wm.f, buffer, length, K); 122 | } 123 | 124 | inline char* WriteExponent(int K, char* buffer) { 125 | if (K < 0) { 126 | *buffer++ = '-'; 127 | K = -K; 128 | } 129 | 130 | if (K >= 100) { 131 | *buffer++ = static_cast('0' + static_cast(K / 100)); 132 | K %= 100; 133 | const char* d = GetDigitsLut() + K * 2; 134 | *buffer++ = d[0]; 135 | *buffer++ = d[1]; 136 | } 137 | else if (K >= 10) { 138 | const char* d = GetDigitsLut() + K * 2; 139 | *buffer++ = d[0]; 140 | *buffer++ = d[1]; 141 | } 142 | else 143 | *buffer++ = static_cast('0' + static_cast(K)); 144 | 145 | return buffer; 146 | } 147 | 148 | inline char* Prettify(char* buffer, int length, int k) { 149 | const int kk = length + k; // 10^(kk-1) <= v < 10^kk 150 | 151 | if (length <= kk && kk <= 21) { 152 | // 1234e7 -> 12340000000 153 | for (int i = length; i < kk; i++) 154 | buffer[i] = '0'; 155 | buffer[kk] = '.'; 156 | buffer[kk + 1] = '0'; 157 | return &buffer[kk + 2]; 158 | } 159 | else if (0 < kk && kk <= 21) { 160 | // 1234e-2 -> 12.34 161 | std::memmove(&buffer[kk + 1], &buffer[kk], length - kk); 162 | buffer[kk] = '.'; 163 | return &buffer[length + 1]; 164 | } 165 | else if (-6 < kk && kk <= 0) { 166 | // 1234e-6 -> 0.001234 167 | const int offset = 2 - kk; 168 | std::memmove(&buffer[offset], &buffer[0], length); 169 | buffer[0] = '0'; 170 | buffer[1] = '.'; 171 | for (int i = 2; i < offset; i++) 172 | buffer[i] = '0'; 173 | return &buffer[length + offset]; 174 | } 175 | else if (length == 1) { 176 | // 1e30 177 | buffer[1] = 'e'; 178 | return WriteExponent(kk - 1, &buffer[2]); 179 | } 180 | else { 181 | // 1234e30 -> 1.234e33 182 | std::memmove(&buffer[2], &buffer[1], length - 1); 183 | buffer[1] = '.'; 184 | buffer[length + 1] = 'e'; 185 | return WriteExponent(kk - 1, &buffer[0 + length + 2]); 186 | } 187 | } 188 | 189 | inline char* dtoa(double value, char* buffer) { 190 | Double d(value); 191 | if (d.IsZero()) { 192 | if (d.Sign()) 193 | *buffer++ = '-'; // -0.0, Issue #289 194 | buffer[0] = '0'; 195 | buffer[1] = '.'; 196 | buffer[2] = '0'; 197 | return &buffer[3]; 198 | } 199 | else { 200 | if (value < 0) { 201 | *buffer++ = '-'; 202 | value = -value; 203 | } 204 | int length, K; 205 | Grisu2(value, buffer, &length, &K); 206 | return Prettify(buffer, length, K); 207 | } 208 | } 209 | 210 | #ifdef __GNUC__ 211 | RAPIDJSON_DIAG_POP 212 | #endif 213 | 214 | } // namespace internal 215 | RAPIDJSON_NAMESPACE_END 216 | 217 | #endif // RAPIDJSON_DTOA_ 218 | -------------------------------------------------------------------------------- /src/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 ((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 IsNormal() const { return (u & kExponentMask) != 0 || Significand() == 0; } 44 | bool IsZero() const { return (u & (kExponentMask | kSignificandMask)) == 0; } 45 | 46 | uint64_t IntegerSignificand() const { return IsNormal() ? Significand() | kHiddenBit : Significand(); } 47 | int IntegerExponent() const { return (IsNormal() ? Exponent() : kDenormalExponent) - kSignificandSize; } 48 | uint64_t ToBias() const { return (u & kSignMask) ? ~u + 1 : u | kSignMask; } 49 | 50 | static unsigned EffectiveSignificandSize(int order) { 51 | if (order >= -1021) 52 | return 53; 53 | else if (order <= -1074) 54 | return 0; 55 | else 56 | return order + 1074; 57 | } 58 | 59 | private: 60 | static const int kSignificandSize = 52; 61 | static const int kExponentBias = 0x3FF; 62 | static const int kDenormalExponent = 1 - kExponentBias; 63 | static const uint64_t kSignMask = RAPIDJSON_UINT64_C2(0x80000000, 0x00000000); 64 | static const uint64_t kExponentMask = RAPIDJSON_UINT64_C2(0x7FF00000, 0x00000000); 65 | static const uint64_t kSignificandMask = RAPIDJSON_UINT64_C2(0x000FFFFF, 0xFFFFFFFF); 66 | static const uint64_t kHiddenBit = RAPIDJSON_UINT64_C2(0x00100000, 0x00000000); 67 | 68 | union { 69 | double d; 70 | uint64_t u; 71 | }; 72 | }; 73 | 74 | } // namespace internal 75 | RAPIDJSON_NAMESPACE_END 76 | 77 | #endif // RAPIDJSON_IEEE754_ 78 | -------------------------------------------------------------------------------- /src/rapidjson/internal/itoa.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_ITOA_ 16 | #define RAPIDJSON_ITOA_ 17 | 18 | #include "../rapidjson.h" 19 | 20 | RAPIDJSON_NAMESPACE_BEGIN 21 | namespace internal { 22 | 23 | inline const char* GetDigitsLut() { 24 | static const char cDigitsLut[200] = { 25 | '0','0','0','1','0','2','0','3','0','4','0','5','0','6','0','7','0','8','0','9', 26 | '1','0','1','1','1','2','1','3','1','4','1','5','1','6','1','7','1','8','1','9', 27 | '2','0','2','1','2','2','2','3','2','4','2','5','2','6','2','7','2','8','2','9', 28 | '3','0','3','1','3','2','3','3','3','4','3','5','3','6','3','7','3','8','3','9', 29 | '4','0','4','1','4','2','4','3','4','4','4','5','4','6','4','7','4','8','4','9', 30 | '5','0','5','1','5','2','5','3','5','4','5','5','5','6','5','7','5','8','5','9', 31 | '6','0','6','1','6','2','6','3','6','4','6','5','6','6','6','7','6','8','6','9', 32 | '7','0','7','1','7','2','7','3','7','4','7','5','7','6','7','7','7','8','7','9', 33 | '8','0','8','1','8','2','8','3','8','4','8','5','8','6','8','7','8','8','8','9', 34 | '9','0','9','1','9','2','9','3','9','4','9','5','9','6','9','7','9','8','9','9' 35 | }; 36 | return cDigitsLut; 37 | } 38 | 39 | inline char* u32toa(uint32_t value, char* buffer) { 40 | const char* cDigitsLut = GetDigitsLut(); 41 | 42 | if (value < 10000) { 43 | const uint32_t d1 = (value / 100) << 1; 44 | const uint32_t d2 = (value % 100) << 1; 45 | 46 | if (value >= 1000) 47 | *buffer++ = cDigitsLut[d1]; 48 | if (value >= 100) 49 | *buffer++ = cDigitsLut[d1 + 1]; 50 | if (value >= 10) 51 | *buffer++ = cDigitsLut[d2]; 52 | *buffer++ = cDigitsLut[d2 + 1]; 53 | } 54 | else if (value < 100000000) { 55 | // value = bbbbcccc 56 | const uint32_t b = value / 10000; 57 | const uint32_t c = value % 10000; 58 | 59 | const uint32_t d1 = (b / 100) << 1; 60 | const uint32_t d2 = (b % 100) << 1; 61 | 62 | const uint32_t d3 = (c / 100) << 1; 63 | const uint32_t d4 = (c % 100) << 1; 64 | 65 | if (value >= 10000000) 66 | *buffer++ = cDigitsLut[d1]; 67 | if (value >= 1000000) 68 | *buffer++ = cDigitsLut[d1 + 1]; 69 | if (value >= 100000) 70 | *buffer++ = cDigitsLut[d2]; 71 | *buffer++ = cDigitsLut[d2 + 1]; 72 | 73 | *buffer++ = cDigitsLut[d3]; 74 | *buffer++ = cDigitsLut[d3 + 1]; 75 | *buffer++ = cDigitsLut[d4]; 76 | *buffer++ = cDigitsLut[d4 + 1]; 77 | } 78 | else { 79 | // value = aabbbbcccc in decimal 80 | 81 | const uint32_t a = value / 100000000; // 1 to 42 82 | value %= 100000000; 83 | 84 | if (a >= 10) { 85 | const unsigned i = a << 1; 86 | *buffer++ = cDigitsLut[i]; 87 | *buffer++ = cDigitsLut[i + 1]; 88 | } 89 | else 90 | *buffer++ = static_cast('0' + static_cast(a)); 91 | 92 | const uint32_t b = value / 10000; // 0 to 9999 93 | const uint32_t c = value % 10000; // 0 to 9999 94 | 95 | const uint32_t d1 = (b / 100) << 1; 96 | const uint32_t d2 = (b % 100) << 1; 97 | 98 | const uint32_t d3 = (c / 100) << 1; 99 | const uint32_t d4 = (c % 100) << 1; 100 | 101 | *buffer++ = cDigitsLut[d1]; 102 | *buffer++ = cDigitsLut[d1 + 1]; 103 | *buffer++ = cDigitsLut[d2]; 104 | *buffer++ = cDigitsLut[d2 + 1]; 105 | *buffer++ = cDigitsLut[d3]; 106 | *buffer++ = cDigitsLut[d3 + 1]; 107 | *buffer++ = cDigitsLut[d4]; 108 | *buffer++ = cDigitsLut[d4 + 1]; 109 | } 110 | return buffer; 111 | } 112 | 113 | inline char* i32toa(int32_t value, char* buffer) { 114 | uint32_t u = static_cast(value); 115 | if (value < 0) { 116 | *buffer++ = '-'; 117 | u = ~u + 1; 118 | } 119 | 120 | return u32toa(u, buffer); 121 | } 122 | 123 | inline char* u64toa(uint64_t value, char* buffer) { 124 | const char* cDigitsLut = GetDigitsLut(); 125 | const uint64_t kTen8 = 100000000; 126 | const uint64_t kTen9 = kTen8 * 10; 127 | const uint64_t kTen10 = kTen8 * 100; 128 | const uint64_t kTen11 = kTen8 * 1000; 129 | const uint64_t kTen12 = kTen8 * 10000; 130 | const uint64_t kTen13 = kTen8 * 100000; 131 | const uint64_t kTen14 = kTen8 * 1000000; 132 | const uint64_t kTen15 = kTen8 * 10000000; 133 | const uint64_t kTen16 = kTen8 * kTen8; 134 | 135 | if (value < kTen8) { 136 | uint32_t v = static_cast(value); 137 | if (v < 10000) { 138 | const uint32_t d1 = (v / 100) << 1; 139 | const uint32_t d2 = (v % 100) << 1; 140 | 141 | if (v >= 1000) 142 | *buffer++ = cDigitsLut[d1]; 143 | if (v >= 100) 144 | *buffer++ = cDigitsLut[d1 + 1]; 145 | if (v >= 10) 146 | *buffer++ = cDigitsLut[d2]; 147 | *buffer++ = cDigitsLut[d2 + 1]; 148 | } 149 | else { 150 | // value = bbbbcccc 151 | const uint32_t b = v / 10000; 152 | const uint32_t c = v % 10000; 153 | 154 | const uint32_t d1 = (b / 100) << 1; 155 | const uint32_t d2 = (b % 100) << 1; 156 | 157 | const uint32_t d3 = (c / 100) << 1; 158 | const uint32_t d4 = (c % 100) << 1; 159 | 160 | if (value >= 10000000) 161 | *buffer++ = cDigitsLut[d1]; 162 | if (value >= 1000000) 163 | *buffer++ = cDigitsLut[d1 + 1]; 164 | if (value >= 100000) 165 | *buffer++ = cDigitsLut[d2]; 166 | *buffer++ = cDigitsLut[d2 + 1]; 167 | 168 | *buffer++ = cDigitsLut[d3]; 169 | *buffer++ = cDigitsLut[d3 + 1]; 170 | *buffer++ = cDigitsLut[d4]; 171 | *buffer++ = cDigitsLut[d4 + 1]; 172 | } 173 | } 174 | else if (value < kTen16) { 175 | const uint32_t v0 = static_cast(value / kTen8); 176 | const uint32_t v1 = static_cast(value % kTen8); 177 | 178 | const uint32_t b0 = v0 / 10000; 179 | const uint32_t c0 = v0 % 10000; 180 | 181 | const uint32_t d1 = (b0 / 100) << 1; 182 | const uint32_t d2 = (b0 % 100) << 1; 183 | 184 | const uint32_t d3 = (c0 / 100) << 1; 185 | const uint32_t d4 = (c0 % 100) << 1; 186 | 187 | const uint32_t b1 = v1 / 10000; 188 | const uint32_t c1 = v1 % 10000; 189 | 190 | const uint32_t d5 = (b1 / 100) << 1; 191 | const uint32_t d6 = (b1 % 100) << 1; 192 | 193 | const uint32_t d7 = (c1 / 100) << 1; 194 | const uint32_t d8 = (c1 % 100) << 1; 195 | 196 | if (value >= kTen15) 197 | *buffer++ = cDigitsLut[d1]; 198 | if (value >= kTen14) 199 | *buffer++ = cDigitsLut[d1 + 1]; 200 | if (value >= kTen13) 201 | *buffer++ = cDigitsLut[d2]; 202 | if (value >= kTen12) 203 | *buffer++ = cDigitsLut[d2 + 1]; 204 | if (value >= kTen11) 205 | *buffer++ = cDigitsLut[d3]; 206 | if (value >= kTen10) 207 | *buffer++ = cDigitsLut[d3 + 1]; 208 | if (value >= kTen9) 209 | *buffer++ = cDigitsLut[d4]; 210 | if (value >= kTen8) 211 | *buffer++ = cDigitsLut[d4 + 1]; 212 | 213 | *buffer++ = cDigitsLut[d5]; 214 | *buffer++ = cDigitsLut[d5 + 1]; 215 | *buffer++ = cDigitsLut[d6]; 216 | *buffer++ = cDigitsLut[d6 + 1]; 217 | *buffer++ = cDigitsLut[d7]; 218 | *buffer++ = cDigitsLut[d7 + 1]; 219 | *buffer++ = cDigitsLut[d8]; 220 | *buffer++ = cDigitsLut[d8 + 1]; 221 | } 222 | else { 223 | const uint32_t a = static_cast(value / kTen16); // 1 to 1844 224 | value %= kTen16; 225 | 226 | if (a < 10) 227 | *buffer++ = static_cast('0' + static_cast(a)); 228 | else if (a < 100) { 229 | const uint32_t i = a << 1; 230 | *buffer++ = cDigitsLut[i]; 231 | *buffer++ = cDigitsLut[i + 1]; 232 | } 233 | else if (a < 1000) { 234 | *buffer++ = static_cast('0' + static_cast(a / 100)); 235 | 236 | const uint32_t i = (a % 100) << 1; 237 | *buffer++ = cDigitsLut[i]; 238 | *buffer++ = cDigitsLut[i + 1]; 239 | } 240 | else { 241 | const uint32_t i = (a / 100) << 1; 242 | const uint32_t j = (a % 100) << 1; 243 | *buffer++ = cDigitsLut[i]; 244 | *buffer++ = cDigitsLut[i + 1]; 245 | *buffer++ = cDigitsLut[j]; 246 | *buffer++ = cDigitsLut[j + 1]; 247 | } 248 | 249 | const uint32_t v0 = static_cast(value / kTen8); 250 | const uint32_t v1 = static_cast(value % kTen8); 251 | 252 | const uint32_t b0 = v0 / 10000; 253 | const uint32_t c0 = v0 % 10000; 254 | 255 | const uint32_t d1 = (b0 / 100) << 1; 256 | const uint32_t d2 = (b0 % 100) << 1; 257 | 258 | const uint32_t d3 = (c0 / 100) << 1; 259 | const uint32_t d4 = (c0 % 100) << 1; 260 | 261 | const uint32_t b1 = v1 / 10000; 262 | const uint32_t c1 = v1 % 10000; 263 | 264 | const uint32_t d5 = (b1 / 100) << 1; 265 | const uint32_t d6 = (b1 % 100) << 1; 266 | 267 | const uint32_t d7 = (c1 / 100) << 1; 268 | const uint32_t d8 = (c1 % 100) << 1; 269 | 270 | *buffer++ = cDigitsLut[d1]; 271 | *buffer++ = cDigitsLut[d1 + 1]; 272 | *buffer++ = cDigitsLut[d2]; 273 | *buffer++ = cDigitsLut[d2 + 1]; 274 | *buffer++ = cDigitsLut[d3]; 275 | *buffer++ = cDigitsLut[d3 + 1]; 276 | *buffer++ = cDigitsLut[d4]; 277 | *buffer++ = cDigitsLut[d4 + 1]; 278 | *buffer++ = cDigitsLut[d5]; 279 | *buffer++ = cDigitsLut[d5 + 1]; 280 | *buffer++ = cDigitsLut[d6]; 281 | *buffer++ = cDigitsLut[d6 + 1]; 282 | *buffer++ = cDigitsLut[d7]; 283 | *buffer++ = cDigitsLut[d7 + 1]; 284 | *buffer++ = cDigitsLut[d8]; 285 | *buffer++ = cDigitsLut[d8 + 1]; 286 | } 287 | 288 | return buffer; 289 | } 290 | 291 | inline char* i64toa(int64_t value, char* buffer) { 292 | uint64_t u = static_cast(value); 293 | if (value < 0) { 294 | *buffer++ = '-'; 295 | u = ~u + 1; 296 | } 297 | 298 | return u64toa(u, buffer); 299 | } 300 | 301 | } // namespace internal 302 | RAPIDJSON_NAMESPACE_END 303 | 304 | #endif // RAPIDJSON_ITOA_ 305 | -------------------------------------------------------------------------------- /src/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 | #ifndef RAPIDJSON_RAPIDJSON_H_ 19 | #error not yet included. Do not include this file directly. 20 | #endif 21 | 22 | #ifdef __GNUC__ 23 | RAPIDJSON_DIAG_PUSH 24 | RAPIDJSON_DIAG_OFF(effc++) 25 | #endif 26 | #if defined(_MSC_VER) 27 | RAPIDJSON_DIAG_PUSH 28 | RAPIDJSON_DIAG_OFF(6334) 29 | #endif 30 | 31 | #if RAPIDJSON_HAS_CXX11_TYPETRAITS 32 | #include 33 | #endif 34 | 35 | //@cond RAPIDJSON_INTERNAL 36 | RAPIDJSON_NAMESPACE_BEGIN 37 | namespace internal { 38 | 39 | // Helper to wrap/convert arbitrary types to void, useful for arbitrary type matching 40 | template struct Void { typedef void Type; }; 41 | 42 | /////////////////////////////////////////////////////////////////////////////// 43 | // BoolType, TrueType, FalseType 44 | // 45 | template struct BoolType { 46 | static const bool Value = Cond; 47 | typedef BoolType Type; 48 | }; 49 | typedef BoolType TrueType; 50 | typedef BoolType FalseType; 51 | 52 | 53 | /////////////////////////////////////////////////////////////////////////////// 54 | // SelectIf, BoolExpr, NotExpr, AndExpr, OrExpr 55 | // 56 | 57 | template struct SelectIfImpl { template struct Apply { typedef T1 Type; }; }; 58 | template <> struct SelectIfImpl { template struct Apply { typedef T2 Type; }; }; 59 | template struct SelectIfCond : SelectIfImpl::template Apply {}; 60 | template struct SelectIf : SelectIfCond {}; 61 | 62 | template struct AndExprCond : FalseType {}; 63 | template <> struct AndExprCond : TrueType {}; 64 | template struct OrExprCond : TrueType {}; 65 | template <> struct OrExprCond : FalseType {}; 66 | 67 | template struct BoolExpr : SelectIf::Type {}; 68 | template struct NotExpr : SelectIf::Type {}; 69 | template struct AndExpr : AndExprCond::Type {}; 70 | template struct OrExpr : OrExprCond::Type {}; 71 | 72 | 73 | /////////////////////////////////////////////////////////////////////////////// 74 | // AddConst, MaybeAddConst, RemoveConst 75 | template struct AddConst { typedef const T Type; }; 76 | template struct MaybeAddConst : SelectIfCond {}; 77 | template struct RemoveConst { typedef T Type; }; 78 | template struct RemoveConst { typedef T Type; }; 79 | 80 | 81 | /////////////////////////////////////////////////////////////////////////////// 82 | // IsSame, IsConst, IsMoreConst, IsPointer 83 | // 84 | template struct IsSame : FalseType {}; 85 | template struct IsSame : TrueType {}; 86 | 87 | template struct IsConst : FalseType {}; 88 | template struct IsConst : TrueType {}; 89 | 90 | template 91 | struct IsMoreConst 92 | : AndExpr::Type, typename RemoveConst::Type>, 93 | BoolType::Value >= IsConst::Value> >::Type {}; 94 | 95 | template struct IsPointer : FalseType {}; 96 | template struct IsPointer : TrueType {}; 97 | 98 | /////////////////////////////////////////////////////////////////////////////// 99 | // IsBaseOf 100 | // 101 | #if RAPIDJSON_HAS_CXX11_TYPETRAITS 102 | 103 | template struct IsBaseOf 104 | : BoolType< ::std::is_base_of::value> {}; 105 | 106 | #else // simplified version adopted from Boost 107 | 108 | template struct IsBaseOfImpl { 109 | RAPIDJSON_STATIC_ASSERT(sizeof(B) != 0); 110 | RAPIDJSON_STATIC_ASSERT(sizeof(D) != 0); 111 | 112 | typedef char (&Yes)[1]; 113 | typedef char (&No) [2]; 114 | 115 | template 116 | static Yes Check(const D*, T); 117 | static No Check(const B*, int); 118 | 119 | struct Host { 120 | operator const B*() const; 121 | operator const D*(); 122 | }; 123 | 124 | enum { Value = (sizeof(Check(Host(), 0)) == sizeof(Yes)) }; 125 | }; 126 | 127 | template struct IsBaseOf 128 | : OrExpr, BoolExpr > >::Type {}; 129 | 130 | #endif // RAPIDJSON_HAS_CXX11_TYPETRAITS 131 | 132 | 133 | ////////////////////////////////////////////////////////////////////////// 134 | // EnableIf / DisableIf 135 | // 136 | template struct EnableIfCond { typedef T Type; }; 137 | template struct EnableIfCond { /* empty */ }; 138 | 139 | template struct DisableIfCond { typedef T Type; }; 140 | template struct DisableIfCond { /* empty */ }; 141 | 142 | template 143 | struct EnableIf : EnableIfCond {}; 144 | 145 | template 146 | struct DisableIf : DisableIfCond {}; 147 | 148 | // SFINAE helpers 149 | struct SfinaeTag {}; 150 | template struct RemoveSfinaeTag; 151 | template struct RemoveSfinaeTag { typedef T Type; }; 152 | 153 | #define RAPIDJSON_REMOVEFPTR_(type) \ 154 | typename ::RAPIDJSON_NAMESPACE::internal::RemoveSfinaeTag \ 155 | < ::RAPIDJSON_NAMESPACE::internal::SfinaeTag&(*) type>::Type 156 | 157 | #define RAPIDJSON_ENABLEIF(cond) \ 158 | typename ::RAPIDJSON_NAMESPACE::internal::EnableIf \ 159 | ::Type * = NULL 160 | 161 | #define RAPIDJSON_DISABLEIF(cond) \ 162 | typename ::RAPIDJSON_NAMESPACE::internal::DisableIf \ 163 | ::Type * = NULL 164 | 165 | #define RAPIDJSON_ENABLEIF_RETURN(cond,returntype) \ 166 | typename ::RAPIDJSON_NAMESPACE::internal::EnableIf \ 167 | ::Type 169 | 170 | #define RAPIDJSON_DISABLEIF_RETURN(cond,returntype) \ 171 | typename ::RAPIDJSON_NAMESPACE::internal::DisableIf \ 172 | ::Type 174 | 175 | } // namespace internal 176 | RAPIDJSON_NAMESPACE_END 177 | //@endcond 178 | 179 | #if defined(__GNUC__) || defined(_MSC_VER) 180 | RAPIDJSON_DIAG_POP 181 | #endif 182 | 183 | #endif // RAPIDJSON_INTERNAL_META_H_ 184 | -------------------------------------------------------------------------------- /src/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 | RAPIDJSON_NAMESPACE_BEGIN 19 | namespace internal { 20 | 21 | //! Computes integer powers of 10 in double (10.0^n). 22 | /*! This function uses lookup table for fast and accurate results. 23 | \param n non-negative exponent. Must <= 308. 24 | \return 10.0^n 25 | */ 26 | inline double Pow10(int n) { 27 | static const double e[] = { // 1e-0...1e308: 309 * 8 bytes = 2472 bytes 28 | 1e+0, 29 | 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, 30 | 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, 31 | 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, 32 | 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, 33 | 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, 34 | 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, 35 | 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, 36 | 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, 37 | 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, 38 | 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, 39 | 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, 40 | 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, 41 | 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, 42 | 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, 43 | 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, 44 | 1e+301,1e+302,1e+303,1e+304,1e+305,1e+306,1e+307,1e+308 45 | }; 46 | RAPIDJSON_ASSERT(n >= 0 && n <= 308); 47 | return e[n]; 48 | } 49 | 50 | } // namespace internal 51 | RAPIDJSON_NAMESPACE_END 52 | 53 | #endif // RAPIDJSON_POW10_ 54 | -------------------------------------------------------------------------------- /src/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 | RAPIDJSON_NAMESPACE_BEGIN 19 | namespace internal { 20 | 21 | /////////////////////////////////////////////////////////////////////////////// 22 | // Stack 23 | 24 | //! A type-unsafe stack for storing different types of data. 25 | /*! \tparam Allocator Allocator for allocating stack memory. 26 | */ 27 | template 28 | class Stack { 29 | public: 30 | // Optimization note: Do not allocate memory for stack_ in constructor. 31 | // Do it lazily when first Push() -> Expand() -> Resize(). 32 | Stack(Allocator* allocator, size_t stackCapacity) : allocator_(allocator), ownAllocator_(0), stack_(0), stackTop_(0), stackEnd_(0), initialCapacity_(stackCapacity) { 33 | RAPIDJSON_ASSERT(stackCapacity > 0); 34 | } 35 | 36 | #if RAPIDJSON_HAS_CXX11_RVALUE_REFS 37 | Stack(Stack&& rhs) 38 | : allocator_(rhs.allocator_), 39 | ownAllocator_(rhs.ownAllocator_), 40 | stack_(rhs.stack_), 41 | stackTop_(rhs.stackTop_), 42 | stackEnd_(rhs.stackEnd_), 43 | initialCapacity_(rhs.initialCapacity_) 44 | { 45 | rhs.allocator_ = 0; 46 | rhs.ownAllocator_ = 0; 47 | rhs.stack_ = 0; 48 | rhs.stackTop_ = 0; 49 | rhs.stackEnd_ = 0; 50 | rhs.initialCapacity_ = 0; 51 | } 52 | #endif 53 | 54 | ~Stack() { 55 | Destroy(); 56 | } 57 | 58 | #if RAPIDJSON_HAS_CXX11_RVALUE_REFS 59 | Stack& operator=(Stack&& rhs) { 60 | if (&rhs != this) 61 | { 62 | Destroy(); 63 | 64 | allocator_ = rhs.allocator_; 65 | ownAllocator_ = rhs.ownAllocator_; 66 | stack_ = rhs.stack_; 67 | stackTop_ = rhs.stackTop_; 68 | stackEnd_ = rhs.stackEnd_; 69 | initialCapacity_ = rhs.initialCapacity_; 70 | 71 | rhs.allocator_ = 0; 72 | rhs.ownAllocator_ = 0; 73 | rhs.stack_ = 0; 74 | rhs.stackTop_ = 0; 75 | rhs.stackEnd_ = 0; 76 | rhs.initialCapacity_ = 0; 77 | } 78 | return *this; 79 | } 80 | #endif 81 | 82 | void Clear() { stackTop_ = stack_; } 83 | 84 | void ShrinkToFit() { 85 | if (Empty()) { 86 | // If the stack is empty, completely deallocate the memory. 87 | Allocator::Free(stack_); 88 | stack_ = 0; 89 | stackTop_ = 0; 90 | stackEnd_ = 0; 91 | } 92 | else 93 | Resize(GetSize()); 94 | } 95 | 96 | // Optimization note: try to minimize the size of this function for force inline. 97 | // Expansion is run very infrequently, so it is moved to another (probably non-inline) function. 98 | template 99 | RAPIDJSON_FORCEINLINE T* Push(size_t count = 1) { 100 | // Expand the stack if needed 101 | if (stackTop_ + sizeof(T) * count >= stackEnd_) 102 | Expand(count); 103 | 104 | T* ret = reinterpret_cast(stackTop_); 105 | stackTop_ += sizeof(T) * count; 106 | return ret; 107 | } 108 | 109 | template 110 | T* Pop(size_t count) { 111 | RAPIDJSON_ASSERT(GetSize() >= count * sizeof(T)); 112 | stackTop_ -= count * sizeof(T); 113 | return reinterpret_cast(stackTop_); 114 | } 115 | 116 | template 117 | T* Top() { 118 | RAPIDJSON_ASSERT(GetSize() >= sizeof(T)); 119 | return reinterpret_cast(stackTop_ - sizeof(T)); 120 | } 121 | 122 | template 123 | T* Bottom() { return (T*)stack_; } 124 | 125 | Allocator& GetAllocator() { return *allocator_; } 126 | bool Empty() const { return stackTop_ == stack_; } 127 | size_t GetSize() const { return static_cast(stackTop_ - stack_); } 128 | size_t GetCapacity() const { return static_cast(stackEnd_ - stack_); } 129 | 130 | private: 131 | template 132 | void Expand(size_t count) { 133 | // Only expand the capacity if the current stack exists. Otherwise just create a stack with initial capacity. 134 | size_t newCapacity; 135 | if (stack_ == 0) { 136 | if (!allocator_) 137 | ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator()); 138 | newCapacity = initialCapacity_; 139 | } else { 140 | newCapacity = GetCapacity(); 141 | newCapacity += (newCapacity + 1) / 2; 142 | } 143 | size_t newSize = GetSize() + sizeof(T) * count; 144 | if (newCapacity < newSize) 145 | newCapacity = newSize; 146 | 147 | Resize(newCapacity); 148 | } 149 | 150 | void Resize(size_t newCapacity) { 151 | const size_t size = GetSize(); // Backup the current size 152 | stack_ = (char*)allocator_->Realloc(stack_, GetCapacity(), newCapacity); 153 | stackTop_ = stack_ + size; 154 | stackEnd_ = stack_ + newCapacity; 155 | } 156 | 157 | void Destroy() { 158 | Allocator::Free(stack_); 159 | RAPIDJSON_DELETE(ownAllocator_); // Only delete if it is owned by the stack 160 | } 161 | 162 | // Prohibit copy constructor & assignment operator. 163 | Stack(const Stack&); 164 | Stack& operator=(const Stack&); 165 | 166 | Allocator* allocator_; 167 | Allocator* ownAllocator_; 168 | char *stack_; 169 | char *stackTop_; 170 | char *stackEnd_; 171 | size_t initialCapacity_; 172 | }; 173 | 174 | } // namespace internal 175 | RAPIDJSON_NAMESPACE_END 176 | 177 | #endif // RAPIDJSON_STACK_H_ 178 | -------------------------------------------------------------------------------- /src/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 | RAPIDJSON_NAMESPACE_BEGIN 19 | namespace internal { 20 | 21 | //! Custom strlen() which works on different character types. 22 | /*! \tparam Ch Character type (e.g. char, wchar_t, short) 23 | \param s Null-terminated input string. 24 | \return Number of characters in the string. 25 | \note This has the same semantics as strlen(), the return value is not number of Unicode codepoints. 26 | */ 27 | template 28 | inline SizeType StrLen(const Ch* s) { 29 | const Ch* p = s; 30 | while (*p) ++p; 31 | return SizeType(p - s); 32 | } 33 | 34 | } // namespace internal 35 | RAPIDJSON_NAMESPACE_END 36 | 37 | #endif // RAPIDJSON_INTERNAL_STRFUNC_H_ 38 | -------------------------------------------------------------------------------- /src/rapidjson/internal/strtod.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_STRTOD_ 16 | #define RAPIDJSON_STRTOD_ 17 | 18 | #include "../rapidjson.h" 19 | #include "ieee754.h" 20 | #include "biginteger.h" 21 | #include "diyfp.h" 22 | #include "pow10.h" 23 | 24 | RAPIDJSON_NAMESPACE_BEGIN 25 | namespace internal { 26 | 27 | inline double FastPath(double significand, int exp) { 28 | if (exp < -308) 29 | return 0.0; 30 | else if (exp >= 0) 31 | return significand * internal::Pow10(exp); 32 | else 33 | return significand / internal::Pow10(-exp); 34 | } 35 | 36 | inline double StrtodNormalPrecision(double d, int p) { 37 | if (p < -308) { 38 | // Prevent expSum < -308, making Pow10(p) = 0 39 | d = FastPath(d, -308); 40 | d = FastPath(d, p + 308); 41 | } 42 | else 43 | d = FastPath(d, p); 44 | return d; 45 | } 46 | 47 | template 48 | inline T Min3(T a, T b, T c) { 49 | T m = a; 50 | if (m > b) m = b; 51 | if (m > c) m = c; 52 | return m; 53 | } 54 | 55 | inline int CheckWithinHalfULP(double b, const BigInteger& d, int dExp) { 56 | const Double db(b); 57 | const uint64_t bInt = db.IntegerSignificand(); 58 | const int bExp = db.IntegerExponent(); 59 | const int hExp = bExp - 1; 60 | 61 | int dS_Exp2 = 0, dS_Exp5 = 0, bS_Exp2 = 0, bS_Exp5 = 0, hS_Exp2 = 0, hS_Exp5 = 0; 62 | 63 | // Adjust for decimal exponent 64 | if (dExp >= 0) { 65 | dS_Exp2 += dExp; 66 | dS_Exp5 += dExp; 67 | } 68 | else { 69 | bS_Exp2 -= dExp; 70 | bS_Exp5 -= dExp; 71 | hS_Exp2 -= dExp; 72 | hS_Exp5 -= dExp; 73 | } 74 | 75 | // Adjust for binary exponent 76 | if (bExp >= 0) 77 | bS_Exp2 += bExp; 78 | else { 79 | dS_Exp2 -= bExp; 80 | hS_Exp2 -= bExp; 81 | } 82 | 83 | // Adjust for half ulp exponent 84 | if (hExp >= 0) 85 | hS_Exp2 += hExp; 86 | else { 87 | dS_Exp2 -= hExp; 88 | bS_Exp2 -= hExp; 89 | } 90 | 91 | // Remove common power of two factor from all three scaled values 92 | int common_Exp2 = Min3(dS_Exp2, bS_Exp2, hS_Exp2); 93 | dS_Exp2 -= common_Exp2; 94 | bS_Exp2 -= common_Exp2; 95 | hS_Exp2 -= common_Exp2; 96 | 97 | BigInteger dS = d; 98 | dS.MultiplyPow5(dS_Exp5) <<= dS_Exp2; 99 | 100 | BigInteger bS(bInt); 101 | bS.MultiplyPow5(bS_Exp5) <<= bS_Exp2; 102 | 103 | BigInteger hS(1); 104 | hS.MultiplyPow5(hS_Exp5) <<= hS_Exp2; 105 | 106 | BigInteger delta(0); 107 | dS.Difference(bS, &delta); 108 | 109 | return delta.Compare(hS); 110 | } 111 | 112 | inline bool StrtodFast(double d, int p, double* result) { 113 | // Use fast path for string-to-double conversion if possible 114 | // see http://www.exploringbinary.com/fast-path-decimal-to-floating-point-conversion/ 115 | if (p > 22 && p < 22 + 16) { 116 | // Fast Path Cases In Disguise 117 | d *= internal::Pow10(p - 22); 118 | p = 22; 119 | } 120 | 121 | if (p >= -22 && p <= 22 && d <= 9007199254740991.0) { // 2^53 - 1 122 | *result = FastPath(d, p); 123 | return true; 124 | } 125 | else 126 | return false; 127 | } 128 | 129 | // Compute an approximation and see if it is within 1/2 ULP 130 | inline bool StrtodDiyFp(const char* decimals, size_t length, size_t decimalPosition, int exp, double* result) { 131 | uint64_t significand = 0; 132 | size_t i = 0; // 2^64 - 1 = 18446744073709551615, 1844674407370955161 = 0x1999999999999999 133 | for (; i < length; i++) { 134 | if (significand > RAPIDJSON_UINT64_C2(0x19999999, 0x99999999) || 135 | (significand == RAPIDJSON_UINT64_C2(0x19999999, 0x99999999) && decimals[i] > '5')) 136 | break; 137 | significand = significand * 10 + (decimals[i] - '0'); 138 | } 139 | 140 | if (i < length && decimals[i] >= '5') // Rounding 141 | significand++; 142 | 143 | size_t remaining = length - i; 144 | const unsigned kUlpShift = 3; 145 | const unsigned kUlp = 1 << kUlpShift; 146 | int error = (remaining == 0) ? 0 : kUlp / 2; 147 | 148 | DiyFp v(significand, 0); 149 | v = v.Normalize(); 150 | error <<= -v.e; 151 | 152 | const int dExp = (int)decimalPosition - (int)i + exp; 153 | 154 | int actualExp; 155 | DiyFp cachedPower = GetCachedPower10(dExp, &actualExp); 156 | if (actualExp != dExp) { 157 | static const DiyFp kPow10[] = { 158 | DiyFp(RAPIDJSON_UINT64_C2(0xa0000000, 00000000), -60), // 10^1 159 | DiyFp(RAPIDJSON_UINT64_C2(0xc8000000, 00000000), -57), // 10^2 160 | DiyFp(RAPIDJSON_UINT64_C2(0xfa000000, 00000000), -54), // 10^3 161 | DiyFp(RAPIDJSON_UINT64_C2(0x9c400000, 00000000), -50), // 10^4 162 | DiyFp(RAPIDJSON_UINT64_C2(0xc3500000, 00000000), -47), // 10^5 163 | DiyFp(RAPIDJSON_UINT64_C2(0xf4240000, 00000000), -44), // 10^6 164 | DiyFp(RAPIDJSON_UINT64_C2(0x98968000, 00000000), -40) // 10^7 165 | }; 166 | int adjustment = dExp - actualExp - 1; 167 | RAPIDJSON_ASSERT(adjustment >= 0 && adjustment < 7); 168 | v = v * kPow10[adjustment]; 169 | if (length + adjustment > 19) // has more digits than decimal digits in 64-bit 170 | error += kUlp / 2; 171 | } 172 | 173 | v = v * cachedPower; 174 | 175 | error += kUlp + (error == 0 ? 0 : 1); 176 | 177 | const int oldExp = v.e; 178 | v = v.Normalize(); 179 | error <<= oldExp - v.e; 180 | 181 | const unsigned effectiveSignificandSize = Double::EffectiveSignificandSize(64 + v.e); 182 | unsigned precisionSize = 64 - effectiveSignificandSize; 183 | if (precisionSize + kUlpShift >= 64) { 184 | unsigned scaleExp = (precisionSize + kUlpShift) - 63; 185 | v.f >>= scaleExp; 186 | v.e += scaleExp; 187 | error = (error >> scaleExp) + 1 + kUlp; 188 | precisionSize -= scaleExp; 189 | } 190 | 191 | DiyFp rounded(v.f >> precisionSize, v.e + precisionSize); 192 | const uint64_t precisionBits = (v.f & ((uint64_t(1) << precisionSize) - 1)) * kUlp; 193 | const uint64_t halfWay = (uint64_t(1) << (precisionSize - 1)) * kUlp; 194 | if (precisionBits >= halfWay + error) 195 | rounded.f++; 196 | 197 | *result = rounded.ToDouble(); 198 | 199 | return halfWay - error >= precisionBits || precisionBits >= halfWay + error; 200 | } 201 | 202 | inline double StrtodBigInteger(double approx, const char* decimals, size_t length, size_t decimalPosition, int exp) { 203 | const BigInteger dInt(decimals, length); 204 | const int dExp = (int)decimalPosition - (int)length + exp; 205 | Double a(approx); 206 | int cmp = CheckWithinHalfULP(a.Value(), dInt, dExp); 207 | if (cmp < 0) 208 | return a.Value(); // within half ULP 209 | else if (cmp == 0) { 210 | // Round towards even 211 | if (a.Significand() & 1) 212 | return a.NextPositiveDouble(); 213 | else 214 | return a.Value(); 215 | } 216 | else // adjustment 217 | return a.NextPositiveDouble(); 218 | } 219 | 220 | inline double StrtodFullPrecision(double d, int p, const char* decimals, size_t length, size_t decimalPosition, int exp) { 221 | RAPIDJSON_ASSERT(d >= 0.0); 222 | RAPIDJSON_ASSERT(length >= 1); 223 | 224 | double result; 225 | if (StrtodFast(d, p, &result)) 226 | return result; 227 | 228 | // Trim leading zeros 229 | while (*decimals == '0' && length > 1) { 230 | length--; 231 | decimals++; 232 | decimalPosition--; 233 | } 234 | 235 | // Trim trailing zeros 236 | while (decimals[length - 1] == '0' && length > 1) { 237 | length--; 238 | decimalPosition--; 239 | exp++; 240 | } 241 | 242 | // Trim right-most digits 243 | const int kMaxDecimalDigit = 780; 244 | if ((int)length > kMaxDecimalDigit) { 245 | int delta = (int(length) - kMaxDecimalDigit); 246 | exp += delta; 247 | decimalPosition -= delta; 248 | length = kMaxDecimalDigit; 249 | } 250 | 251 | // If too small, underflow to zero 252 | if (int(length) + exp < -324) 253 | return 0.0; 254 | 255 | if (StrtodDiyFp(decimals, length, decimalPosition, exp, &result)) 256 | return result; 257 | 258 | // Use approximation from StrtodDiyFp and make adjustment with BigInteger comparison 259 | return StrtodBigInteger(result, decimals, length, decimalPosition, exp); 260 | } 261 | 262 | } // namespace internal 263 | RAPIDJSON_NAMESPACE_END 264 | 265 | #endif // RAPIDJSON_STRTOD_ 266 | -------------------------------------------------------------------------------- /src/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 "rapidjson.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 | -------------------------------------------------------------------------------- /src/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 "rapidjson.h" 19 | 20 | RAPIDJSON_NAMESPACE_BEGIN 21 | 22 | //! Represents an in-memory input byte stream. 23 | /*! 24 | This class is mainly for being wrapped by EncodedInputStream or AutoUTFInputStream. 25 | 26 | It is similar to FileReadBuffer but the source is an in-memory buffer instead of a file. 27 | 28 | Differences between MemoryStream and StringStream: 29 | 1. StringStream has encoding but MemoryStream is a byte stream. 30 | 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. 31 | 3. MemoryStream supports Peek4() for encoding detection. StringStream is specified with an encoding so it should not have Peek4(). 32 | \note implements Stream concept 33 | */ 34 | struct MemoryStream { 35 | typedef char Ch; // byte 36 | 37 | MemoryStream(const Ch *src, size_t size) : src_(src), begin_(src), end_(src + size), size_(size) {} 38 | 39 | Ch Peek() const { return (src_ == end_) ? '\0' : *src_; } 40 | Ch Take() { return (src_ == end_) ? '\0' : *src_++; } 41 | size_t Tell() const { return static_cast(src_ - begin_); } 42 | 43 | Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } 44 | void Put(Ch) { RAPIDJSON_ASSERT(false); } 45 | void Flush() { RAPIDJSON_ASSERT(false); } 46 | size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; } 47 | 48 | // For encoding detection only. 49 | const Ch* Peek4() const { 50 | return Tell() + 4 <= size_ ? src_ : 0; 51 | } 52 | 53 | const Ch* src_; //!< Current read position. 54 | const Ch* begin_; //!< Original head of the string. 55 | const Ch* end_; //!< End of stream. 56 | size_t size_; //!< Size of the stream. 57 | }; 58 | 59 | RAPIDJSON_NAMESPACE_END 60 | 61 | #endif // RAPIDJSON_MEMORYBUFFER_H_ 62 | -------------------------------------------------------------------------------- /src/rapidjson/msinttypes/inttypes.h: -------------------------------------------------------------------------------- 1 | // ISO C9x compliant inttypes.h for Microsoft Visual Studio 2 | // Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124 3 | // 4 | // Copyright (c) 2006-2013 Alexander Chemeris 5 | // 6 | // Redistribution and use in source and binary forms, with or without 7 | // modification, are permitted provided that the following conditions are met: 8 | // 9 | // 1. Redistributions of source code must retain the above copyright notice, 10 | // this list of conditions and the following disclaimer. 11 | // 12 | // 2. Redistributions in binary form must reproduce the above copyright 13 | // notice, this list of conditions and the following disclaimer in the 14 | // documentation and/or other materials provided with the distribution. 15 | // 16 | // 3. Neither the name of the product nor the names of its contributors may 17 | // be used to endorse or promote products derived from this software 18 | // without specific prior written permission. 19 | // 20 | // THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 21 | // WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 22 | // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 23 | // EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 25 | // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 26 | // OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 27 | // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 28 | // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 29 | // ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | // 31 | /////////////////////////////////////////////////////////////////////////////// 32 | 33 | // The above software in this distribution may have been modified by 34 | // THL A29 Limited ("Tencent Modifications"). 35 | // All Tencent Modifications are Copyright (C) 2015 THL A29 Limited. 36 | 37 | #ifndef _MSC_VER // [ 38 | #error "Use this header only with Microsoft Visual C++ compilers!" 39 | #endif // _MSC_VER ] 40 | 41 | #ifndef _MSC_INTTYPES_H_ // [ 42 | #define _MSC_INTTYPES_H_ 43 | 44 | #if _MSC_VER > 1000 45 | #pragma once 46 | #endif 47 | 48 | #include "stdint.h" 49 | 50 | // miloyip: VC supports inttypes.h since VC2013 51 | #if _MSC_VER >= 1800 52 | #include 53 | #else 54 | 55 | // 7.8 Format conversion of integer types 56 | 57 | typedef struct { 58 | intmax_t quot; 59 | intmax_t rem; 60 | } imaxdiv_t; 61 | 62 | // 7.8.1 Macros for format specifiers 63 | 64 | #if !defined(__cplusplus) || defined(__STDC_FORMAT_MACROS) // [ See footnote 185 at page 198 65 | 66 | // The fprintf macros for signed integers are: 67 | #define PRId8 "d" 68 | #define PRIi8 "i" 69 | #define PRIdLEAST8 "d" 70 | #define PRIiLEAST8 "i" 71 | #define PRIdFAST8 "d" 72 | #define PRIiFAST8 "i" 73 | 74 | #define PRId16 "hd" 75 | #define PRIi16 "hi" 76 | #define PRIdLEAST16 "hd" 77 | #define PRIiLEAST16 "hi" 78 | #define PRIdFAST16 "hd" 79 | #define PRIiFAST16 "hi" 80 | 81 | #define PRId32 "I32d" 82 | #define PRIi32 "I32i" 83 | #define PRIdLEAST32 "I32d" 84 | #define PRIiLEAST32 "I32i" 85 | #define PRIdFAST32 "I32d" 86 | #define PRIiFAST32 "I32i" 87 | 88 | #define PRId64 "I64d" 89 | #define PRIi64 "I64i" 90 | #define PRIdLEAST64 "I64d" 91 | #define PRIiLEAST64 "I64i" 92 | #define PRIdFAST64 "I64d" 93 | #define PRIiFAST64 "I64i" 94 | 95 | #define PRIdMAX "I64d" 96 | #define PRIiMAX "I64i" 97 | 98 | #define PRIdPTR "Id" 99 | #define PRIiPTR "Ii" 100 | 101 | // The fprintf macros for unsigned integers are: 102 | #define PRIo8 "o" 103 | #define PRIu8 "u" 104 | #define PRIx8 "x" 105 | #define PRIX8 "X" 106 | #define PRIoLEAST8 "o" 107 | #define PRIuLEAST8 "u" 108 | #define PRIxLEAST8 "x" 109 | #define PRIXLEAST8 "X" 110 | #define PRIoFAST8 "o" 111 | #define PRIuFAST8 "u" 112 | #define PRIxFAST8 "x" 113 | #define PRIXFAST8 "X" 114 | 115 | #define PRIo16 "ho" 116 | #define PRIu16 "hu" 117 | #define PRIx16 "hx" 118 | #define PRIX16 "hX" 119 | #define PRIoLEAST16 "ho" 120 | #define PRIuLEAST16 "hu" 121 | #define PRIxLEAST16 "hx" 122 | #define PRIXLEAST16 "hX" 123 | #define PRIoFAST16 "ho" 124 | #define PRIuFAST16 "hu" 125 | #define PRIxFAST16 "hx" 126 | #define PRIXFAST16 "hX" 127 | 128 | #define PRIo32 "I32o" 129 | #define PRIu32 "I32u" 130 | #define PRIx32 "I32x" 131 | #define PRIX32 "I32X" 132 | #define PRIoLEAST32 "I32o" 133 | #define PRIuLEAST32 "I32u" 134 | #define PRIxLEAST32 "I32x" 135 | #define PRIXLEAST32 "I32X" 136 | #define PRIoFAST32 "I32o" 137 | #define PRIuFAST32 "I32u" 138 | #define PRIxFAST32 "I32x" 139 | #define PRIXFAST32 "I32X" 140 | 141 | #define PRIo64 "I64o" 142 | #define PRIu64 "I64u" 143 | #define PRIx64 "I64x" 144 | #define PRIX64 "I64X" 145 | #define PRIoLEAST64 "I64o" 146 | #define PRIuLEAST64 "I64u" 147 | #define PRIxLEAST64 "I64x" 148 | #define PRIXLEAST64 "I64X" 149 | #define PRIoFAST64 "I64o" 150 | #define PRIuFAST64 "I64u" 151 | #define PRIxFAST64 "I64x" 152 | #define PRIXFAST64 "I64X" 153 | 154 | #define PRIoMAX "I64o" 155 | #define PRIuMAX "I64u" 156 | #define PRIxMAX "I64x" 157 | #define PRIXMAX "I64X" 158 | 159 | #define PRIoPTR "Io" 160 | #define PRIuPTR "Iu" 161 | #define PRIxPTR "Ix" 162 | #define PRIXPTR "IX" 163 | 164 | // The fscanf macros for signed integers are: 165 | #define SCNd8 "d" 166 | #define SCNi8 "i" 167 | #define SCNdLEAST8 "d" 168 | #define SCNiLEAST8 "i" 169 | #define SCNdFAST8 "d" 170 | #define SCNiFAST8 "i" 171 | 172 | #define SCNd16 "hd" 173 | #define SCNi16 "hi" 174 | #define SCNdLEAST16 "hd" 175 | #define SCNiLEAST16 "hi" 176 | #define SCNdFAST16 "hd" 177 | #define SCNiFAST16 "hi" 178 | 179 | #define SCNd32 "ld" 180 | #define SCNi32 "li" 181 | #define SCNdLEAST32 "ld" 182 | #define SCNiLEAST32 "li" 183 | #define SCNdFAST32 "ld" 184 | #define SCNiFAST32 "li" 185 | 186 | #define SCNd64 "I64d" 187 | #define SCNi64 "I64i" 188 | #define SCNdLEAST64 "I64d" 189 | #define SCNiLEAST64 "I64i" 190 | #define SCNdFAST64 "I64d" 191 | #define SCNiFAST64 "I64i" 192 | 193 | #define SCNdMAX "I64d" 194 | #define SCNiMAX "I64i" 195 | 196 | #ifdef _WIN64 // [ 197 | # define SCNdPTR "I64d" 198 | # define SCNiPTR "I64i" 199 | #else // _WIN64 ][ 200 | # define SCNdPTR "ld" 201 | # define SCNiPTR "li" 202 | #endif // _WIN64 ] 203 | 204 | // The fscanf macros for unsigned integers are: 205 | #define SCNo8 "o" 206 | #define SCNu8 "u" 207 | #define SCNx8 "x" 208 | #define SCNX8 "X" 209 | #define SCNoLEAST8 "o" 210 | #define SCNuLEAST8 "u" 211 | #define SCNxLEAST8 "x" 212 | #define SCNXLEAST8 "X" 213 | #define SCNoFAST8 "o" 214 | #define SCNuFAST8 "u" 215 | #define SCNxFAST8 "x" 216 | #define SCNXFAST8 "X" 217 | 218 | #define SCNo16 "ho" 219 | #define SCNu16 "hu" 220 | #define SCNx16 "hx" 221 | #define SCNX16 "hX" 222 | #define SCNoLEAST16 "ho" 223 | #define SCNuLEAST16 "hu" 224 | #define SCNxLEAST16 "hx" 225 | #define SCNXLEAST16 "hX" 226 | #define SCNoFAST16 "ho" 227 | #define SCNuFAST16 "hu" 228 | #define SCNxFAST16 "hx" 229 | #define SCNXFAST16 "hX" 230 | 231 | #define SCNo32 "lo" 232 | #define SCNu32 "lu" 233 | #define SCNx32 "lx" 234 | #define SCNX32 "lX" 235 | #define SCNoLEAST32 "lo" 236 | #define SCNuLEAST32 "lu" 237 | #define SCNxLEAST32 "lx" 238 | #define SCNXLEAST32 "lX" 239 | #define SCNoFAST32 "lo" 240 | #define SCNuFAST32 "lu" 241 | #define SCNxFAST32 "lx" 242 | #define SCNXFAST32 "lX" 243 | 244 | #define SCNo64 "I64o" 245 | #define SCNu64 "I64u" 246 | #define SCNx64 "I64x" 247 | #define SCNX64 "I64X" 248 | #define SCNoLEAST64 "I64o" 249 | #define SCNuLEAST64 "I64u" 250 | #define SCNxLEAST64 "I64x" 251 | #define SCNXLEAST64 "I64X" 252 | #define SCNoFAST64 "I64o" 253 | #define SCNuFAST64 "I64u" 254 | #define SCNxFAST64 "I64x" 255 | #define SCNXFAST64 "I64X" 256 | 257 | #define SCNoMAX "I64o" 258 | #define SCNuMAX "I64u" 259 | #define SCNxMAX "I64x" 260 | #define SCNXMAX "I64X" 261 | 262 | #ifdef _WIN64 // [ 263 | # define SCNoPTR "I64o" 264 | # define SCNuPTR "I64u" 265 | # define SCNxPTR "I64x" 266 | # define SCNXPTR "I64X" 267 | #else // _WIN64 ][ 268 | # define SCNoPTR "lo" 269 | # define SCNuPTR "lu" 270 | # define SCNxPTR "lx" 271 | # define SCNXPTR "lX" 272 | #endif // _WIN64 ] 273 | 274 | #endif // __STDC_FORMAT_MACROS ] 275 | 276 | // 7.8.2 Functions for greatest-width integer types 277 | 278 | // 7.8.2.1 The imaxabs function 279 | #define imaxabs _abs64 280 | 281 | // 7.8.2.2 The imaxdiv function 282 | 283 | // This is modified version of div() function from Microsoft's div.c found 284 | // in %MSVC.NET%\crt\src\div.c 285 | #ifdef STATIC_IMAXDIV // [ 286 | static 287 | #else // STATIC_IMAXDIV ][ 288 | _inline 289 | #endif // STATIC_IMAXDIV ] 290 | imaxdiv_t __cdecl imaxdiv(intmax_t numer, intmax_t denom) 291 | { 292 | imaxdiv_t result; 293 | 294 | result.quot = numer / denom; 295 | result.rem = numer % denom; 296 | 297 | if (numer < 0 && result.rem > 0) { 298 | // did division wrong; must fix up 299 | ++result.quot; 300 | result.rem -= denom; 301 | } 302 | 303 | return result; 304 | } 305 | 306 | // 7.8.2.3 The strtoimax and strtoumax functions 307 | #define strtoimax _strtoi64 308 | #define strtoumax _strtoui64 309 | 310 | // 7.8.2.4 The wcstoimax and wcstoumax functions 311 | #define wcstoimax _wcstoi64 312 | #define wcstoumax _wcstoui64 313 | 314 | #endif // _MSC_VER >= 1800 315 | 316 | #endif // _MSC_INTTYPES_H_ ] 317 | -------------------------------------------------------------------------------- /src/rapidjson/msinttypes/stdint.h: -------------------------------------------------------------------------------- 1 | // ISO C9x compliant stdint.h for Microsoft Visual Studio 2 | // Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124 3 | // 4 | // Copyright (c) 2006-2013 Alexander Chemeris 5 | // 6 | // Redistribution and use in source and binary forms, with or without 7 | // modification, are permitted provided that the following conditions are met: 8 | // 9 | // 1. Redistributions of source code must retain the above copyright notice, 10 | // this list of conditions and the following disclaimer. 11 | // 12 | // 2. Redistributions in binary form must reproduce the above copyright 13 | // notice, this list of conditions and the following disclaimer in the 14 | // documentation and/or other materials provided with the distribution. 15 | // 16 | // 3. Neither the name of the product nor the names of its contributors may 17 | // be used to endorse or promote products derived from this software 18 | // without specific prior written permission. 19 | // 20 | // THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 21 | // WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 22 | // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 23 | // EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 25 | // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 26 | // OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 27 | // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 28 | // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 29 | // ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | // 31 | /////////////////////////////////////////////////////////////////////////////// 32 | 33 | // The above software in this distribution may have been modified by 34 | // THL A29 Limited ("Tencent Modifications"). 35 | // All Tencent Modifications are Copyright (C) 2015 THL A29 Limited. 36 | 37 | #ifndef _MSC_VER // [ 38 | #error "Use this header only with Microsoft Visual C++ compilers!" 39 | #endif // _MSC_VER ] 40 | 41 | #ifndef _MSC_STDINT_H_ // [ 42 | #define _MSC_STDINT_H_ 43 | 44 | #if _MSC_VER > 1000 45 | #pragma once 46 | #endif 47 | 48 | // miloyip: Originally Visual Studio 2010 uses its own stdint.h. However it generates warning with INT64_C(), so change to use this file for vs2010. 49 | #if _MSC_VER >= 1600 // [ 50 | #include 51 | 52 | #if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) // [ See footnote 224 at page 260 53 | 54 | #undef INT8_C 55 | #undef INT16_C 56 | #undef INT32_C 57 | #undef INT64_C 58 | #undef UINT8_C 59 | #undef UINT16_C 60 | #undef UINT32_C 61 | #undef UINT64_C 62 | 63 | // 7.18.4.1 Macros for minimum-width integer constants 64 | 65 | #define INT8_C(val) val##i8 66 | #define INT16_C(val) val##i16 67 | #define INT32_C(val) val##i32 68 | #define INT64_C(val) val##i64 69 | 70 | #define UINT8_C(val) val##ui8 71 | #define UINT16_C(val) val##ui16 72 | #define UINT32_C(val) val##ui32 73 | #define UINT64_C(val) val##ui64 74 | 75 | // 7.18.4.2 Macros for greatest-width integer constants 76 | // These #ifndef's are needed to prevent collisions with . 77 | // Check out Issue 9 for the details. 78 | #ifndef INTMAX_C // [ 79 | # define INTMAX_C INT64_C 80 | #endif // INTMAX_C ] 81 | #ifndef UINTMAX_C // [ 82 | # define UINTMAX_C UINT64_C 83 | #endif // UINTMAX_C ] 84 | 85 | #endif // __STDC_CONSTANT_MACROS ] 86 | 87 | #else // ] _MSC_VER >= 1700 [ 88 | 89 | #include 90 | 91 | // For Visual Studio 6 in C++ mode and for many Visual Studio versions when 92 | // compiling for ARM we should wrap include with 'extern "C++" {}' 93 | // or compiler give many errors like this: 94 | // error C2733: second C linkage of overloaded function 'wmemchr' not allowed 95 | #ifdef __cplusplus 96 | extern "C" { 97 | #endif 98 | # include 99 | #ifdef __cplusplus 100 | } 101 | #endif 102 | 103 | // Define _W64 macros to mark types changing their size, like intptr_t. 104 | #ifndef _W64 105 | # if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && _MSC_VER >= 1300 106 | # define _W64 __w64 107 | # else 108 | # define _W64 109 | # endif 110 | #endif 111 | 112 | 113 | // 7.18.1 Integer types 114 | 115 | // 7.18.1.1 Exact-width integer types 116 | 117 | // Visual Studio 6 and Embedded Visual C++ 4 doesn't 118 | // realize that, e.g. char has the same size as __int8 119 | // so we give up on __intX for them. 120 | #if (_MSC_VER < 1300) 121 | typedef signed char int8_t; 122 | typedef signed short int16_t; 123 | typedef signed int int32_t; 124 | typedef unsigned char uint8_t; 125 | typedef unsigned short uint16_t; 126 | typedef unsigned int uint32_t; 127 | #else 128 | typedef signed __int8 int8_t; 129 | typedef signed __int16 int16_t; 130 | typedef signed __int32 int32_t; 131 | typedef unsigned __int8 uint8_t; 132 | typedef unsigned __int16 uint16_t; 133 | typedef unsigned __int32 uint32_t; 134 | #endif 135 | typedef signed __int64 int64_t; 136 | typedef unsigned __int64 uint64_t; 137 | 138 | 139 | // 7.18.1.2 Minimum-width integer types 140 | typedef int8_t int_least8_t; 141 | typedef int16_t int_least16_t; 142 | typedef int32_t int_least32_t; 143 | typedef int64_t int_least64_t; 144 | typedef uint8_t uint_least8_t; 145 | typedef uint16_t uint_least16_t; 146 | typedef uint32_t uint_least32_t; 147 | typedef uint64_t uint_least64_t; 148 | 149 | // 7.18.1.3 Fastest minimum-width integer types 150 | typedef int8_t int_fast8_t; 151 | typedef int16_t int_fast16_t; 152 | typedef int32_t int_fast32_t; 153 | typedef int64_t int_fast64_t; 154 | typedef uint8_t uint_fast8_t; 155 | typedef uint16_t uint_fast16_t; 156 | typedef uint32_t uint_fast32_t; 157 | typedef uint64_t uint_fast64_t; 158 | 159 | // 7.18.1.4 Integer types capable of holding object pointers 160 | #ifdef _WIN64 // [ 161 | typedef signed __int64 intptr_t; 162 | typedef unsigned __int64 uintptr_t; 163 | #else // _WIN64 ][ 164 | typedef _W64 signed int intptr_t; 165 | typedef _W64 unsigned int uintptr_t; 166 | #endif // _WIN64 ] 167 | 168 | // 7.18.1.5 Greatest-width integer types 169 | typedef int64_t intmax_t; 170 | typedef uint64_t uintmax_t; 171 | 172 | 173 | // 7.18.2 Limits of specified-width integer types 174 | 175 | #if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) // [ See footnote 220 at page 257 and footnote 221 at page 259 176 | 177 | // 7.18.2.1 Limits of exact-width integer types 178 | #define INT8_MIN ((int8_t)_I8_MIN) 179 | #define INT8_MAX _I8_MAX 180 | #define INT16_MIN ((int16_t)_I16_MIN) 181 | #define INT16_MAX _I16_MAX 182 | #define INT32_MIN ((int32_t)_I32_MIN) 183 | #define INT32_MAX _I32_MAX 184 | #define INT64_MIN ((int64_t)_I64_MIN) 185 | #define INT64_MAX _I64_MAX 186 | #define UINT8_MAX _UI8_MAX 187 | #define UINT16_MAX _UI16_MAX 188 | #define UINT32_MAX _UI32_MAX 189 | #define UINT64_MAX _UI64_MAX 190 | 191 | // 7.18.2.2 Limits of minimum-width integer types 192 | #define INT_LEAST8_MIN INT8_MIN 193 | #define INT_LEAST8_MAX INT8_MAX 194 | #define INT_LEAST16_MIN INT16_MIN 195 | #define INT_LEAST16_MAX INT16_MAX 196 | #define INT_LEAST32_MIN INT32_MIN 197 | #define INT_LEAST32_MAX INT32_MAX 198 | #define INT_LEAST64_MIN INT64_MIN 199 | #define INT_LEAST64_MAX INT64_MAX 200 | #define UINT_LEAST8_MAX UINT8_MAX 201 | #define UINT_LEAST16_MAX UINT16_MAX 202 | #define UINT_LEAST32_MAX UINT32_MAX 203 | #define UINT_LEAST64_MAX UINT64_MAX 204 | 205 | // 7.18.2.3 Limits of fastest minimum-width integer types 206 | #define INT_FAST8_MIN INT8_MIN 207 | #define INT_FAST8_MAX INT8_MAX 208 | #define INT_FAST16_MIN INT16_MIN 209 | #define INT_FAST16_MAX INT16_MAX 210 | #define INT_FAST32_MIN INT32_MIN 211 | #define INT_FAST32_MAX INT32_MAX 212 | #define INT_FAST64_MIN INT64_MIN 213 | #define INT_FAST64_MAX INT64_MAX 214 | #define UINT_FAST8_MAX UINT8_MAX 215 | #define UINT_FAST16_MAX UINT16_MAX 216 | #define UINT_FAST32_MAX UINT32_MAX 217 | #define UINT_FAST64_MAX UINT64_MAX 218 | 219 | // 7.18.2.4 Limits of integer types capable of holding object pointers 220 | #ifdef _WIN64 // [ 221 | # define INTPTR_MIN INT64_MIN 222 | # define INTPTR_MAX INT64_MAX 223 | # define UINTPTR_MAX UINT64_MAX 224 | #else // _WIN64 ][ 225 | # define INTPTR_MIN INT32_MIN 226 | # define INTPTR_MAX INT32_MAX 227 | # define UINTPTR_MAX UINT32_MAX 228 | #endif // _WIN64 ] 229 | 230 | // 7.18.2.5 Limits of greatest-width integer types 231 | #define INTMAX_MIN INT64_MIN 232 | #define INTMAX_MAX INT64_MAX 233 | #define UINTMAX_MAX UINT64_MAX 234 | 235 | // 7.18.3 Limits of other integer types 236 | 237 | #ifdef _WIN64 // [ 238 | # define PTRDIFF_MIN _I64_MIN 239 | # define PTRDIFF_MAX _I64_MAX 240 | #else // _WIN64 ][ 241 | # define PTRDIFF_MIN _I32_MIN 242 | # define PTRDIFF_MAX _I32_MAX 243 | #endif // _WIN64 ] 244 | 245 | #define SIG_ATOMIC_MIN INT_MIN 246 | #define SIG_ATOMIC_MAX INT_MAX 247 | 248 | #ifndef SIZE_MAX // [ 249 | # ifdef _WIN64 // [ 250 | # define SIZE_MAX _UI64_MAX 251 | # else // _WIN64 ][ 252 | # define SIZE_MAX _UI32_MAX 253 | # endif // _WIN64 ] 254 | #endif // SIZE_MAX ] 255 | 256 | // WCHAR_MIN and WCHAR_MAX are also defined in 257 | #ifndef WCHAR_MIN // [ 258 | # define WCHAR_MIN 0 259 | #endif // WCHAR_MIN ] 260 | #ifndef WCHAR_MAX // [ 261 | # define WCHAR_MAX _UI16_MAX 262 | #endif // WCHAR_MAX ] 263 | 264 | #define WINT_MIN 0 265 | #define WINT_MAX _UI16_MAX 266 | 267 | #endif // __STDC_LIMIT_MACROS ] 268 | 269 | 270 | // 7.18.4 Limits of other integer types 271 | 272 | #if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) // [ See footnote 224 at page 260 273 | 274 | // 7.18.4.1 Macros for minimum-width integer constants 275 | 276 | #define INT8_C(val) val##i8 277 | #define INT16_C(val) val##i16 278 | #define INT32_C(val) val##i32 279 | #define INT64_C(val) val##i64 280 | 281 | #define UINT8_C(val) val##ui8 282 | #define UINT16_C(val) val##ui16 283 | #define UINT32_C(val) val##ui32 284 | #define UINT64_C(val) val##ui64 285 | 286 | // 7.18.4.2 Macros for greatest-width integer constants 287 | // These #ifndef's are needed to prevent collisions with . 288 | // Check out Issue 9 for the details. 289 | #ifndef INTMAX_C // [ 290 | # define INTMAX_C INT64_C 291 | #endif // INTMAX_C ] 292 | #ifndef UINTMAX_C // [ 293 | # define UINTMAX_C UINT64_C 294 | #endif // UINTMAX_C ] 295 | 296 | #endif // __STDC_CONSTANT_MACROS ] 297 | 298 | #endif // _MSC_VER >= 1600 ] 299 | 300 | #endif // _MSC_STDINT_H_ ] 301 | -------------------------------------------------------------------------------- /src/rapidjson/prettywriter.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_PRETTYWRITER_H_ 16 | #define RAPIDJSON_PRETTYWRITER_H_ 17 | 18 | #include "writer.h" 19 | 20 | #ifdef __GNUC__ 21 | RAPIDJSON_DIAG_PUSH 22 | RAPIDJSON_DIAG_OFF(effc++) 23 | #endif 24 | 25 | RAPIDJSON_NAMESPACE_BEGIN 26 | 27 | //! Writer with indentation and spacing. 28 | /*! 29 | \tparam OutputStream Type of ouptut os. 30 | \tparam SourceEncoding Encoding of source string. 31 | \tparam TargetEncoding Encoding of output stream. 32 | \tparam StackAllocator Type of allocator for allocating memory of stack. 33 | */ 34 | template, typename TargetEncoding = UTF8<>, typename StackAllocator = CrtAllocator> 35 | class PrettyWriter : public Writer { 36 | public: 37 | typedef Writer Base; 38 | typedef typename Base::Ch Ch; 39 | 40 | //! Constructor 41 | /*! \param os Output stream. 42 | \param allocator User supplied allocator. If it is null, it will create a private one. 43 | \param levelDepth Initial capacity of stack. 44 | */ 45 | PrettyWriter(OutputStream& os, StackAllocator* allocator = 0, size_t levelDepth = Base::kDefaultLevelDepth) : 46 | Base(os, allocator, levelDepth), indentChar_(' '), indentCharCount_(4) {} 47 | 48 | //! Set custom indentation. 49 | /*! \param indentChar Character for indentation. Must be whitespace character (' ', '\\t', '\\n', '\\r'). 50 | \param indentCharCount Number of indent characters for each indentation level. 51 | \note The default indentation is 4 spaces. 52 | */ 53 | PrettyWriter& SetIndent(Ch indentChar, unsigned indentCharCount) { 54 | RAPIDJSON_ASSERT(indentChar == ' ' || indentChar == '\t' || indentChar == '\n' || indentChar == '\r'); 55 | indentChar_ = indentChar; 56 | indentCharCount_ = indentCharCount; 57 | return *this; 58 | } 59 | 60 | /*! @name Implementation of Handler 61 | \see Handler 62 | */ 63 | //@{ 64 | 65 | bool Null() { PrettyPrefix(kNullType); return Base::WriteNull(); } 66 | bool Bool(bool b) { PrettyPrefix(b ? kTrueType : kFalseType); return Base::WriteBool(b); } 67 | bool Int(int i) { PrettyPrefix(kNumberType); return Base::WriteInt(i); } 68 | bool Uint(unsigned u) { PrettyPrefix(kNumberType); return Base::WriteUint(u); } 69 | bool Int64(int64_t i64) { PrettyPrefix(kNumberType); return Base::WriteInt64(i64); } 70 | bool Uint64(uint64_t u64) { PrettyPrefix(kNumberType); return Base::WriteUint64(u64); } 71 | bool Double(double d) { PrettyPrefix(kNumberType); return Base::WriteDouble(d); } 72 | 73 | bool String(const Ch* str, SizeType length, bool copy = false) { 74 | (void)copy; 75 | PrettyPrefix(kStringType); 76 | return Base::WriteString(str, length); 77 | } 78 | 79 | #if RAPIDJSON_HAS_STDSTRING 80 | bool String(const std::basic_string& str) { 81 | return String(str.data(), SizeType(str.size())); 82 | } 83 | #endif 84 | 85 | bool StartObject() { 86 | PrettyPrefix(kObjectType); 87 | new (Base::level_stack_.template Push()) typename Base::Level(false); 88 | return Base::WriteStartObject(); 89 | } 90 | 91 | bool Key(const Ch* str, SizeType length, bool copy = false) { return String(str, length, copy); } 92 | 93 | bool EndObject(SizeType memberCount = 0) { 94 | (void)memberCount; 95 | RAPIDJSON_ASSERT(Base::level_stack_.GetSize() >= sizeof(typename Base::Level)); 96 | RAPIDJSON_ASSERT(!Base::level_stack_.template Top()->inArray); 97 | bool empty = Base::level_stack_.template Pop(1)->valueCount == 0; 98 | 99 | if (!empty) { 100 | Base::os_->Put('\n'); 101 | WriteIndent(); 102 | } 103 | bool ret = Base::WriteEndObject(); 104 | (void)ret; 105 | RAPIDJSON_ASSERT(ret == true); 106 | if (Base::level_stack_.Empty()) // end of json text 107 | Base::os_->Flush(); 108 | return true; 109 | } 110 | 111 | bool StartArray() { 112 | PrettyPrefix(kArrayType); 113 | new (Base::level_stack_.template Push()) typename Base::Level(true); 114 | return Base::WriteStartArray(); 115 | } 116 | 117 | bool EndArray(SizeType memberCount = 0) { 118 | (void)memberCount; 119 | RAPIDJSON_ASSERT(Base::level_stack_.GetSize() >= sizeof(typename Base::Level)); 120 | RAPIDJSON_ASSERT(Base::level_stack_.template Top()->inArray); 121 | bool empty = Base::level_stack_.template Pop(1)->valueCount == 0; 122 | 123 | if (!empty) { 124 | Base::os_->Put('\n'); 125 | WriteIndent(); 126 | } 127 | bool ret = Base::WriteEndArray(); 128 | (void)ret; 129 | RAPIDJSON_ASSERT(ret == true); 130 | if (Base::level_stack_.Empty()) // end of json text 131 | Base::os_->Flush(); 132 | return true; 133 | } 134 | 135 | //@} 136 | 137 | /*! @name Convenience extensions */ 138 | //@{ 139 | 140 | //! Simpler but slower overload. 141 | bool String(const Ch* str) { return String(str, internal::StrLen(str)); } 142 | bool Key(const Ch* str) { return Key(str, internal::StrLen(str)); } 143 | 144 | //@} 145 | protected: 146 | void PrettyPrefix(Type type) { 147 | (void)type; 148 | if (Base::level_stack_.GetSize() != 0) { // this value is not at root 149 | typename Base::Level* level = Base::level_stack_.template Top(); 150 | 151 | if (level->inArray) { 152 | if (level->valueCount > 0) { 153 | Base::os_->Put(','); // add comma if it is not the first element in array 154 | Base::os_->Put('\n'); 155 | } 156 | else 157 | Base::os_->Put('\n'); 158 | WriteIndent(); 159 | } 160 | else { // in object 161 | if (level->valueCount > 0) { 162 | if (level->valueCount % 2 == 0) { 163 | Base::os_->Put(','); 164 | Base::os_->Put('\n'); 165 | } 166 | else { 167 | Base::os_->Put(':'); 168 | Base::os_->Put(' '); 169 | } 170 | } 171 | else 172 | Base::os_->Put('\n'); 173 | 174 | if (level->valueCount % 2 == 0) 175 | WriteIndent(); 176 | } 177 | if (!level->inArray && level->valueCount % 2 == 0) 178 | RAPIDJSON_ASSERT(type == kStringType); // if it's in object, then even number should be a name 179 | level->valueCount++; 180 | } 181 | else { 182 | RAPIDJSON_ASSERT(!Base::hasRoot_); // Should only has one and only one root. 183 | Base::hasRoot_ = true; 184 | } 185 | } 186 | 187 | void WriteIndent() { 188 | size_t count = (Base::level_stack_.GetSize() / sizeof(typename Base::Level)) * indentCharCount_; 189 | PutN(*Base::os_, indentChar_, count); 190 | } 191 | 192 | Ch indentChar_; 193 | unsigned indentCharCount_; 194 | 195 | private: 196 | // Prohibit copy constructor & assignment operator. 197 | PrettyWriter(const PrettyWriter&); 198 | PrettyWriter& operator=(const PrettyWriter&); 199 | }; 200 | 201 | RAPIDJSON_NAMESPACE_END 202 | 203 | #ifdef __GNUC__ 204 | RAPIDJSON_DIAG_POP 205 | #endif 206 | 207 | #endif // RAPIDJSON_RAPIDJSON_H_ 208 | -------------------------------------------------------------------------------- /src/rapidjson/rapidjson.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_RAPIDJSON_H_ 16 | #define RAPIDJSON_RAPIDJSON_H_ 17 | 18 | /*!\file rapidjson.h 19 | \brief common definitions and configuration 20 | 21 | \see RAPIDJSON_CONFIG 22 | */ 23 | 24 | /*! \defgroup RAPIDJSON_CONFIG RapidJSON configuration 25 | \brief Configuration macros for library features 26 | 27 | Some RapidJSON features are configurable to adapt the library to a wide 28 | variety of platforms, environments and usage scenarios. Most of the 29 | features can be configured in terms of overriden or predefined 30 | preprocessor macros at compile-time. 31 | 32 | Some additional customization is available in the \ref RAPIDJSON_ERRORS APIs. 33 | 34 | \note These macros should be given on the compiler command-line 35 | (where applicable) to avoid inconsistent values when compiling 36 | different translation units of a single application. 37 | */ 38 | 39 | #include // malloc(), realloc(), free(), size_t 40 | #include // memset(), memcpy(), memmove(), memcmp() 41 | 42 | /////////////////////////////////////////////////////////////////////////////// 43 | // RAPIDJSON_VERSION_STRING 44 | // 45 | // ALWAYS synchronize the following 3 macros with corresponding variables in /CMakeLists.txt. 46 | // 47 | 48 | //!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN 49 | // token stringification 50 | #define RAPIDJSON_STRINGIFY(x) RAPIDJSON_DO_STRINGIFY(x) 51 | #define RAPIDJSON_DO_STRINGIFY(x) #x 52 | //!@endcond 53 | 54 | /*! \def RAPIDJSON_MAJOR_VERSION 55 | \ingroup RAPIDJSON_CONFIG 56 | \brief Major version of RapidJSON in integer. 57 | */ 58 | /*! \def RAPIDJSON_MINOR_VERSION 59 | \ingroup RAPIDJSON_CONFIG 60 | \brief Minor version of RapidJSON in integer. 61 | */ 62 | /*! \def RAPIDJSON_PATCH_VERSION 63 | \ingroup RAPIDJSON_CONFIG 64 | \brief Patch version of RapidJSON in integer. 65 | */ 66 | /*! \def RAPIDJSON_VERSION_STRING 67 | \ingroup RAPIDJSON_CONFIG 68 | \brief Version of RapidJSON in ".." string format. 69 | */ 70 | #define RAPIDJSON_MAJOR_VERSION 1 71 | #define RAPIDJSON_MINOR_VERSION 0 72 | #define RAPIDJSON_PATCH_VERSION 0 73 | #define RAPIDJSON_VERSION_STRING \ 74 | RAPIDJSON_STRINGIFY(RAPIDJSON_MAJOR_VERSION.RAPIDJSON_MINOR_VERSION.RAPIDJSON_PATCH_VERSION) 75 | 76 | /////////////////////////////////////////////////////////////////////////////// 77 | // RAPIDJSON_NAMESPACE_(BEGIN|END) 78 | /*! \def RAPIDJSON_NAMESPACE 79 | \ingroup RAPIDJSON_CONFIG 80 | \brief provide custom rapidjson namespace 81 | 82 | In order to avoid symbol clashes and/or "One Definition Rule" errors 83 | between multiple inclusions of (different versions of) RapidJSON in 84 | a single binary, users can customize the name of the main RapidJSON 85 | namespace. 86 | 87 | In case of a single nesting level, defining \c RAPIDJSON_NAMESPACE 88 | to a custom name (e.g. \c MyRapidJSON) is sufficient. If multiple 89 | levels are needed, both \ref RAPIDJSON_NAMESPACE_BEGIN and \ref 90 | RAPIDJSON_NAMESPACE_END need to be defined as well: 91 | 92 | \code 93 | // in some .cpp file 94 | #define RAPIDJSON_NAMESPACE my::rapidjson 95 | #define RAPIDJSON_NAMESPACE_BEGIN namespace my { namespace rapidjson { 96 | #define RAPIDJSON_NAMESPACE_END } } 97 | #include "rapidjson/..." 98 | \endcode 99 | 100 | \see rapidjson 101 | */ 102 | /*! \def RAPIDJSON_NAMESPACE_BEGIN 103 | \ingroup RAPIDJSON_CONFIG 104 | \brief provide custom rapidjson namespace (opening expression) 105 | \see RAPIDJSON_NAMESPACE 106 | */ 107 | /*! \def RAPIDJSON_NAMESPACE_END 108 | \ingroup RAPIDJSON_CONFIG 109 | \brief provide custom rapidjson namespace (closing expression) 110 | \see RAPIDJSON_NAMESPACE 111 | */ 112 | #ifndef RAPIDJSON_NAMESPACE 113 | #define RAPIDJSON_NAMESPACE rapidjson 114 | #endif 115 | #ifndef RAPIDJSON_NAMESPACE_BEGIN 116 | #define RAPIDJSON_NAMESPACE_BEGIN namespace RAPIDJSON_NAMESPACE { 117 | #endif 118 | #ifndef RAPIDJSON_NAMESPACE_END 119 | #define RAPIDJSON_NAMESPACE_END } 120 | #endif 121 | 122 | /////////////////////////////////////////////////////////////////////////////// 123 | // RAPIDJSON_NO_INT64DEFINE 124 | 125 | /*! \def RAPIDJSON_NO_INT64DEFINE 126 | \ingroup RAPIDJSON_CONFIG 127 | \brief Use external 64-bit integer types. 128 | 129 | RapidJSON requires the 64-bit integer types \c int64_t and \c uint64_t types 130 | to be available at global scope. 131 | 132 | If users have their own definition, define RAPIDJSON_NO_INT64DEFINE to 133 | prevent RapidJSON from defining its own types. 134 | */ 135 | #ifndef RAPIDJSON_NO_INT64DEFINE 136 | //!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN 137 | #ifdef _MSC_VER 138 | #include "msinttypes/stdint.h" 139 | #include "msinttypes/inttypes.h" 140 | #else 141 | // Other compilers should have this. 142 | #include 143 | #include 144 | #endif 145 | //!@endcond 146 | #ifdef RAPIDJSON_DOXYGEN_RUNNING 147 | #define RAPIDJSON_NO_INT64DEFINE 148 | #endif 149 | #endif // RAPIDJSON_NO_INT64TYPEDEF 150 | 151 | /////////////////////////////////////////////////////////////////////////////// 152 | // RAPIDJSON_FORCEINLINE 153 | 154 | #ifndef RAPIDJSON_FORCEINLINE 155 | //!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN 156 | #if defined(_MSC_VER) && !defined(NDEBUG) 157 | #define RAPIDJSON_FORCEINLINE __forceinline 158 | #elif defined(__GNUC__) && __GNUC__ >= 4 && !defined(NDEBUG) 159 | #define RAPIDJSON_FORCEINLINE __attribute__((always_inline)) 160 | #else 161 | #define RAPIDJSON_FORCEINLINE 162 | #endif 163 | //!@endcond 164 | #endif // RAPIDJSON_FORCEINLINE 165 | 166 | /////////////////////////////////////////////////////////////////////////////// 167 | // RAPIDJSON_ENDIAN 168 | #define RAPIDJSON_LITTLEENDIAN 0 //!< Little endian machine 169 | #define RAPIDJSON_BIGENDIAN 1 //!< Big endian machine 170 | 171 | //! Endianness of the machine. 172 | /*! 173 | \def RAPIDJSON_ENDIAN 174 | \ingroup RAPIDJSON_CONFIG 175 | 176 | GCC 4.6 provided macro for detecting endianness of the target machine. But other 177 | compilers may not have this. User can define RAPIDJSON_ENDIAN to either 178 | \ref RAPIDJSON_LITTLEENDIAN or \ref RAPIDJSON_BIGENDIAN. 179 | 180 | Default detection implemented with reference to 181 | \li https://gcc.gnu.org/onlinedocs/gcc-4.6.0/cpp/Common-Predefined-Macros.html 182 | \li http://www.boost.org/doc/libs/1_42_0/boost/detail/endian.hpp 183 | */ 184 | #ifndef RAPIDJSON_ENDIAN 185 | // Detect with GCC 4.6's macro 186 | # ifdef __BYTE_ORDER__ 187 | # if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ 188 | # define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN 189 | # elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ 190 | # define RAPIDJSON_ENDIAN RAPIDJSON_BIGENDIAN 191 | # else 192 | # error Unknown machine endianess detected. User needs to define RAPIDJSON_ENDIAN. 193 | # endif // __BYTE_ORDER__ 194 | // Detect with GLIBC's endian.h 195 | # elif defined(__GLIBC__) 196 | # include 197 | # if (__BYTE_ORDER == __LITTLE_ENDIAN) 198 | # define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN 199 | # elif (__BYTE_ORDER == __BIG_ENDIAN) 200 | # define RAPIDJSON_ENDIAN RAPIDJSON_BIGENDIAN 201 | # else 202 | # error Unknown machine endianess detected. User needs to define RAPIDJSON_ENDIAN. 203 | # endif // __GLIBC__ 204 | // Detect with _LITTLE_ENDIAN and _BIG_ENDIAN macro 205 | # elif defined(_LITTLE_ENDIAN) && !defined(_BIG_ENDIAN) 206 | # define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN 207 | # elif defined(_BIG_ENDIAN) && !defined(_LITTLE_ENDIAN) 208 | # define RAPIDJSON_ENDIAN RAPIDJSON_BIGENDIAN 209 | // Detect with architecture macros 210 | # elif defined(__sparc) || defined(__sparc__) || defined(_POWER) || defined(__powerpc__) || defined(__ppc__) || defined(__hpux) || defined(__hppa) || defined(_MIPSEB) || defined(_POWER) || defined(__s390__) 211 | # define RAPIDJSON_ENDIAN RAPIDJSON_BIGENDIAN 212 | # elif defined(__i386__) || defined(__alpha__) || defined(__ia64) || defined(__ia64__) || defined(_M_IX86) || defined(_M_IA64) || defined(_M_ALPHA) || defined(__amd64) || defined(__amd64__) || defined(_M_AMD64) || defined(__x86_64) || defined(__x86_64__) || defined(_M_X64) || defined(__bfin__) 213 | # define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN 214 | # elif defined(RAPIDJSON_DOXYGEN_RUNNING) 215 | # define RAPIDJSON_ENDIAN 216 | # else 217 | # error Unknown machine endianess detected. User needs to define RAPIDJSON_ENDIAN. 218 | # endif 219 | #endif // RAPIDJSON_ENDIAN 220 | 221 | /////////////////////////////////////////////////////////////////////////////// 222 | // RAPIDJSON_64BIT 223 | 224 | //! Whether using 64-bit architecture 225 | #ifndef RAPIDJSON_64BIT 226 | #if defined(__LP64__) || defined(_WIN64) 227 | #define RAPIDJSON_64BIT 1 228 | #else 229 | #define RAPIDJSON_64BIT 0 230 | #endif 231 | #endif // RAPIDJSON_64BIT 232 | 233 | /////////////////////////////////////////////////////////////////////////////// 234 | // RAPIDJSON_ALIGN 235 | 236 | //! Data alignment of the machine. 237 | /*! \ingroup RAPIDJSON_CONFIG 238 | \param x pointer to align 239 | 240 | Some machines require strict data alignment. Currently the default uses 4 bytes 241 | alignment. User can customize by defining the RAPIDJSON_ALIGN function macro., 242 | */ 243 | #ifndef RAPIDJSON_ALIGN 244 | #define RAPIDJSON_ALIGN(x) ((x + 3u) & ~3u) 245 | #endif 246 | 247 | /////////////////////////////////////////////////////////////////////////////// 248 | // RAPIDJSON_UINT64_C2 249 | 250 | //! Construct a 64-bit literal by a pair of 32-bit integer. 251 | /*! 252 | 64-bit literal with or without ULL suffix is prone to compiler warnings. 253 | UINT64_C() is C macro which cause compilation problems. 254 | Use this macro to define 64-bit constants by a pair of 32-bit integer. 255 | */ 256 | #ifndef RAPIDJSON_UINT64_C2 257 | #define RAPIDJSON_UINT64_C2(high32, low32) ((static_cast(high32) << 32) | static_cast(low32)) 258 | #endif 259 | 260 | /////////////////////////////////////////////////////////////////////////////// 261 | // RAPIDJSON_SSE2/RAPIDJSON_SSE42/RAPIDJSON_SIMD 262 | 263 | /*! \def RAPIDJSON_SIMD 264 | \ingroup RAPIDJSON_CONFIG 265 | \brief Enable SSE2/SSE4.2 optimization. 266 | 267 | RapidJSON supports optimized implementations for some parsing operations 268 | based on the SSE2 or SSE4.2 SIMD extensions on modern Intel-compatible 269 | processors. 270 | 271 | To enable these optimizations, two different symbols can be defined; 272 | \code 273 | // Enable SSE2 optimization. 274 | #define RAPIDJSON_SSE2 275 | 276 | // Enable SSE4.2 optimization. 277 | #define RAPIDJSON_SSE42 278 | \endcode 279 | 280 | \c RAPIDJSON_SSE42 takes precedence, if both are defined. 281 | 282 | If any of these symbols is defined, RapidJSON defines the macro 283 | \c RAPIDJSON_SIMD to indicate the availability of the optimized code. 284 | */ 285 | #if defined(RAPIDJSON_SSE2) || defined(RAPIDJSON_SSE42) \ 286 | || defined(RAPIDJSON_DOXYGEN_RUNNING) 287 | #define RAPIDJSON_SIMD 288 | #endif 289 | 290 | /////////////////////////////////////////////////////////////////////////////// 291 | // RAPIDJSON_NO_SIZETYPEDEFINE 292 | 293 | #ifndef RAPIDJSON_NO_SIZETYPEDEFINE 294 | /*! \def RAPIDJSON_NO_SIZETYPEDEFINE 295 | \ingroup RAPIDJSON_CONFIG 296 | \brief User-provided \c SizeType definition. 297 | 298 | In order to avoid using 32-bit size types for indexing strings and arrays, 299 | define this preprocessor symbol and provide the type rapidjson::SizeType 300 | before including RapidJSON: 301 | \code 302 | #define RAPIDJSON_NO_SIZETYPEDEFINE 303 | namespace rapidjson { typedef ::std::size_t SizeType; } 304 | #include "rapidjson/..." 305 | \endcode 306 | 307 | \see rapidjson::SizeType 308 | */ 309 | #ifdef RAPIDJSON_DOXYGEN_RUNNING 310 | #define RAPIDJSON_NO_SIZETYPEDEFINE 311 | #endif 312 | RAPIDJSON_NAMESPACE_BEGIN 313 | //! Size type (for string lengths, array sizes, etc.) 314 | /*! RapidJSON uses 32-bit array/string indices even on 64-bit platforms, 315 | instead of using \c size_t. Users may override the SizeType by defining 316 | \ref RAPIDJSON_NO_SIZETYPEDEFINE. 317 | */ 318 | typedef unsigned SizeType; 319 | RAPIDJSON_NAMESPACE_END 320 | #endif 321 | 322 | // always import std::size_t to rapidjson namespace 323 | RAPIDJSON_NAMESPACE_BEGIN 324 | using std::size_t; 325 | RAPIDJSON_NAMESPACE_END 326 | 327 | /////////////////////////////////////////////////////////////////////////////// 328 | // RAPIDJSON_ASSERT 329 | 330 | //! Assertion. 331 | /*! \ingroup RAPIDJSON_CONFIG 332 | By default, rapidjson uses C \c assert() for internal assertions. 333 | User can override it by defining RAPIDJSON_ASSERT(x) macro. 334 | 335 | \note Parsing errors are handled and can be customized by the 336 | \ref RAPIDJSON_ERRORS APIs. 337 | */ 338 | #ifndef RAPIDJSON_ASSERT 339 | #include 340 | #define RAPIDJSON_ASSERT(x) assert(x) 341 | #endif // RAPIDJSON_ASSERT 342 | 343 | /////////////////////////////////////////////////////////////////////////////// 344 | // RAPIDJSON_STATIC_ASSERT 345 | 346 | // Adopt from boost 347 | #ifndef RAPIDJSON_STATIC_ASSERT 348 | //!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN 349 | RAPIDJSON_NAMESPACE_BEGIN 350 | template struct STATIC_ASSERTION_FAILURE; 351 | template <> struct STATIC_ASSERTION_FAILURE { enum { value = 1 }; }; 352 | template struct StaticAssertTest {}; 353 | RAPIDJSON_NAMESPACE_END 354 | 355 | #define RAPIDJSON_JOIN(X, Y) RAPIDJSON_DO_JOIN(X, Y) 356 | #define RAPIDJSON_DO_JOIN(X, Y) RAPIDJSON_DO_JOIN2(X, Y) 357 | #define RAPIDJSON_DO_JOIN2(X, Y) X##Y 358 | 359 | #if defined(__GNUC__) 360 | #define RAPIDJSON_STATIC_ASSERT_UNUSED_ATTRIBUTE __attribute__((unused)) 361 | #else 362 | #define RAPIDJSON_STATIC_ASSERT_UNUSED_ATTRIBUTE 363 | #endif 364 | //!@endcond 365 | 366 | /*! \def RAPIDJSON_STATIC_ASSERT 367 | \brief (Internal) macro to check for conditions at compile-time 368 | \param x compile-time condition 369 | \hideinitializer 370 | */ 371 | #define RAPIDJSON_STATIC_ASSERT(x) \ 372 | typedef ::RAPIDJSON_NAMESPACE::StaticAssertTest< \ 373 | sizeof(::RAPIDJSON_NAMESPACE::STATIC_ASSERTION_FAILURE)> \ 374 | RAPIDJSON_JOIN(StaticAssertTypedef, __LINE__) RAPIDJSON_STATIC_ASSERT_UNUSED_ATTRIBUTE 375 | #endif 376 | 377 | /////////////////////////////////////////////////////////////////////////////// 378 | // Helpers 379 | 380 | //!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN 381 | 382 | #define RAPIDJSON_MULTILINEMACRO_BEGIN do { 383 | #define RAPIDJSON_MULTILINEMACRO_END \ 384 | } while((void)0, 0) 385 | 386 | // adopted from Boost 387 | #define RAPIDJSON_VERSION_CODE(x,y,z) \ 388 | (((x)*100000) + ((y)*100) + (z)) 389 | 390 | /////////////////////////////////////////////////////////////////////////////// 391 | // RAPIDJSON_DIAG_PUSH/POP, RAPIDJSON_DIAG_OFF 392 | 393 | #if defined(__GNUC__) 394 | #define RAPIDJSON_GNUC \ 395 | RAPIDJSON_VERSION_CODE(__GNUC__,__GNUC_MINOR__,__GNUC_PATCHLEVEL__) 396 | #endif 397 | 398 | #if defined(__clang__) || (defined(RAPIDJSON_GNUC) && RAPIDJSON_GNUC >= RAPIDJSON_VERSION_CODE(4,2,0)) 399 | 400 | #define RAPIDJSON_PRAGMA(x) _Pragma(RAPIDJSON_STRINGIFY(x)) 401 | #define RAPIDJSON_DIAG_PRAGMA(x) RAPIDJSON_PRAGMA(GCC diagnostic x) 402 | #define RAPIDJSON_DIAG_OFF(x) \ 403 | RAPIDJSON_DIAG_PRAGMA(ignored RAPIDJSON_STRINGIFY(RAPIDJSON_JOIN(-W,x))) 404 | 405 | // push/pop support in Clang and GCC>=4.6 406 | #if defined(__clang__) || (defined(RAPIDJSON_GNUC) && RAPIDJSON_GNUC >= RAPIDJSON_VERSION_CODE(4,6,0)) 407 | #define RAPIDJSON_DIAG_PUSH RAPIDJSON_DIAG_PRAGMA(push) 408 | #define RAPIDJSON_DIAG_POP RAPIDJSON_DIAG_PRAGMA(pop) 409 | #else // GCC >= 4.2, < 4.6 410 | #define RAPIDJSON_DIAG_PUSH /* ignored */ 411 | #define RAPIDJSON_DIAG_POP /* ignored */ 412 | #endif 413 | 414 | #elif defined(_MSC_VER) 415 | 416 | // pragma (MSVC specific) 417 | #define RAPIDJSON_PRAGMA(x) __pragma(x) 418 | #define RAPIDJSON_DIAG_PRAGMA(x) RAPIDJSON_PRAGMA(warning(x)) 419 | 420 | #define RAPIDJSON_DIAG_OFF(x) RAPIDJSON_DIAG_PRAGMA(disable: x) 421 | #define RAPIDJSON_DIAG_PUSH RAPIDJSON_DIAG_PRAGMA(push) 422 | #define RAPIDJSON_DIAG_POP RAPIDJSON_DIAG_PRAGMA(pop) 423 | 424 | #else 425 | 426 | #define RAPIDJSON_DIAG_OFF(x) /* ignored */ 427 | #define RAPIDJSON_DIAG_PUSH /* ignored */ 428 | #define RAPIDJSON_DIAG_POP /* ignored */ 429 | 430 | #endif // RAPIDJSON_DIAG_* 431 | 432 | /////////////////////////////////////////////////////////////////////////////// 433 | // C++11 features 434 | 435 | #ifndef RAPIDJSON_HAS_CXX11_RVALUE_REFS 436 | #if defined(__clang__) 437 | #define RAPIDJSON_HAS_CXX11_RVALUE_REFS __has_feature(cxx_rvalue_references) && \ 438 | (defined(_LIBCPP_VERSION) || defined(__GLIBCXX__) && __GLIBCXX__ >= 20080306) 439 | #elif (defined(RAPIDJSON_GNUC) && (RAPIDJSON_GNUC >= RAPIDJSON_VERSION_CODE(4,3,0)) && defined(__GXX_EXPERIMENTAL_CXX0X__)) || \ 440 | (defined(_MSC_VER) && _MSC_VER >= 1600) 441 | 442 | #define RAPIDJSON_HAS_CXX11_RVALUE_REFS 1 443 | #else 444 | #define RAPIDJSON_HAS_CXX11_RVALUE_REFS 0 445 | #endif 446 | #endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS 447 | 448 | #ifndef RAPIDJSON_HAS_CXX11_NOEXCEPT 449 | #if defined(__clang__) 450 | #define RAPIDJSON_HAS_CXX11_NOEXCEPT __has_feature(cxx_noexcept) 451 | #elif (defined(RAPIDJSON_GNUC) && (RAPIDJSON_GNUC >= RAPIDJSON_VERSION_CODE(4,6,0)) && defined(__GXX_EXPERIMENTAL_CXX0X__)) 452 | // (defined(_MSC_VER) && _MSC_VER >= ????) // not yet supported 453 | #define RAPIDJSON_HAS_CXX11_NOEXCEPT 1 454 | #else 455 | #define RAPIDJSON_HAS_CXX11_NOEXCEPT 0 456 | #endif 457 | #endif 458 | #if RAPIDJSON_HAS_CXX11_NOEXCEPT 459 | #define RAPIDJSON_NOEXCEPT noexcept 460 | #else 461 | #define RAPIDJSON_NOEXCEPT /* noexcept */ 462 | #endif // RAPIDJSON_HAS_CXX11_NOEXCEPT 463 | 464 | // no automatic detection, yet 465 | #ifndef RAPIDJSON_HAS_CXX11_TYPETRAITS 466 | #define RAPIDJSON_HAS_CXX11_TYPETRAITS 0 467 | #endif 468 | 469 | //!@endcond 470 | 471 | /////////////////////////////////////////////////////////////////////////////// 472 | // new/delete 473 | 474 | #ifndef RAPIDJSON_NEW 475 | ///! customization point for global \c new 476 | #define RAPIDJSON_NEW(x) new x 477 | #endif 478 | #ifndef RAPIDJSON_DELETE 479 | ///! customization point for global \c delete 480 | #define RAPIDJSON_DELETE(x) delete x 481 | #endif 482 | 483 | /////////////////////////////////////////////////////////////////////////////// 484 | // Allocators and Encodings 485 | 486 | #include "allocators.h" 487 | #include "encodings.h" 488 | 489 | /*! \namespace rapidjson 490 | \brief main RapidJSON namespace 491 | \see RAPIDJSON_NAMESPACE 492 | */ 493 | RAPIDJSON_NAMESPACE_BEGIN 494 | 495 | /////////////////////////////////////////////////////////////////////////////// 496 | // Stream 497 | 498 | /*! \class rapidjson::Stream 499 | \brief Concept for reading and writing characters. 500 | 501 | For read-only stream, no need to implement PutBegin(), Put(), Flush() and PutEnd(). 502 | 503 | For write-only stream, only need to implement Put() and Flush(). 504 | 505 | \code 506 | concept Stream { 507 | typename Ch; //!< Character type of the stream. 508 | 509 | //! Read the current character from stream without moving the read cursor. 510 | Ch Peek() const; 511 | 512 | //! Read the current character from stream and moving the read cursor to next character. 513 | Ch Take(); 514 | 515 | //! Get the current read cursor. 516 | //! \return Number of characters read from start. 517 | size_t Tell(); 518 | 519 | //! Begin writing operation at the current read pointer. 520 | //! \return The begin writer pointer. 521 | Ch* PutBegin(); 522 | 523 | //! Write a character. 524 | void Put(Ch c); 525 | 526 | //! Flush the buffer. 527 | void Flush(); 528 | 529 | //! End the writing operation. 530 | //! \param begin The begin write pointer returned by PutBegin(). 531 | //! \return Number of characters written. 532 | size_t PutEnd(Ch* begin); 533 | } 534 | \endcode 535 | */ 536 | 537 | //! Provides additional information for stream. 538 | /*! 539 | By using traits pattern, this type provides a default configuration for stream. 540 | For custom stream, this type can be specialized for other configuration. 541 | See TEST(Reader, CustomStringStream) in readertest.cpp for example. 542 | */ 543 | template 544 | struct StreamTraits { 545 | //! Whether to make local copy of stream for optimization during parsing. 546 | /*! 547 | By default, for safety, streams do not use local copy optimization. 548 | Stream that can be copied fast should specialize this, like StreamTraits. 549 | */ 550 | enum { copyOptimization = 0 }; 551 | }; 552 | 553 | //! Put N copies of a character to a stream. 554 | template 555 | inline void PutN(Stream& stream, Ch c, size_t n) { 556 | for (size_t i = 0; i < n; i++) 557 | stream.Put(c); 558 | } 559 | 560 | /////////////////////////////////////////////////////////////////////////////// 561 | // StringStream 562 | 563 | //! Read-only string stream. 564 | /*! \note implements Stream concept 565 | */ 566 | template 567 | struct GenericStringStream { 568 | typedef typename Encoding::Ch Ch; 569 | 570 | GenericStringStream(const Ch *src) : src_(src), head_(src) {} 571 | 572 | Ch Peek() const { return *src_; } 573 | Ch Take() { return *src_++; } 574 | size_t Tell() const { return static_cast(src_ - head_); } 575 | 576 | Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } 577 | void Put(Ch) { RAPIDJSON_ASSERT(false); } 578 | void Flush() { RAPIDJSON_ASSERT(false); } 579 | size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; } 580 | 581 | const Ch* src_; //!< Current read position. 582 | const Ch* head_; //!< Original head of the string. 583 | }; 584 | 585 | template 586 | struct StreamTraits > { 587 | enum { copyOptimization = 1 }; 588 | }; 589 | 590 | //! String stream with UTF8 encoding. 591 | typedef GenericStringStream > StringStream; 592 | 593 | /////////////////////////////////////////////////////////////////////////////// 594 | // InsituStringStream 595 | 596 | //! A read-write string stream. 597 | /*! This string stream is particularly designed for in-situ parsing. 598 | \note implements Stream concept 599 | */ 600 | template 601 | struct GenericInsituStringStream { 602 | typedef typename Encoding::Ch Ch; 603 | 604 | GenericInsituStringStream(Ch *src) : src_(src), dst_(0), head_(src) {} 605 | 606 | // Read 607 | Ch Peek() { return *src_; } 608 | Ch Take() { return *src_++; } 609 | size_t Tell() { return static_cast(src_ - head_); } 610 | 611 | // Write 612 | void Put(Ch c) { RAPIDJSON_ASSERT(dst_ != 0); *dst_++ = c; } 613 | 614 | Ch* PutBegin() { return dst_ = src_; } 615 | size_t PutEnd(Ch* begin) { return static_cast(dst_ - begin); } 616 | void Flush() {} 617 | 618 | Ch* Push(size_t count) { Ch* begin = dst_; dst_ += count; return begin; } 619 | void Pop(size_t count) { dst_ -= count; } 620 | 621 | Ch* src_; 622 | Ch* dst_; 623 | Ch* head_; 624 | }; 625 | 626 | template 627 | struct StreamTraits > { 628 | enum { copyOptimization = 1 }; 629 | }; 630 | 631 | //! Insitu string stream with UTF8 encoding. 632 | typedef GenericInsituStringStream > InsituStringStream; 633 | 634 | /////////////////////////////////////////////////////////////////////////////// 635 | // Type 636 | 637 | //! Type of JSON value 638 | enum Type { 639 | kNullType = 0, //!< null 640 | kFalseType = 1, //!< false 641 | kTrueType = 2, //!< true 642 | kObjectType = 3, //!< object 643 | kArrayType = 4, //!< array 644 | kStringType = 5, //!< string 645 | kNumberType = 6 //!< number 646 | }; 647 | 648 | RAPIDJSON_NAMESPACE_END 649 | 650 | #endif // RAPIDJSON_RAPIDJSON_H_ 651 | -------------------------------------------------------------------------------- /src/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 "rapidjson.h" 19 | 20 | #if RAPIDJSON_HAS_CXX11_RVALUE_REFS 21 | #include // std::move 22 | #endif 23 | 24 | #include "internal/stack.h" 25 | 26 | RAPIDJSON_NAMESPACE_BEGIN 27 | 28 | //! Represents an in-memory output stream. 29 | /*! 30 | \tparam Encoding Encoding of the stream. 31 | \tparam Allocator type for allocating memory buffer. 32 | \note implements Stream concept 33 | */ 34 | template 35 | class GenericStringBuffer { 36 | public: 37 | typedef typename Encoding::Ch Ch; 38 | 39 | GenericStringBuffer(Allocator* allocator = 0, size_t capacity = kDefaultCapacity) : stack_(allocator, capacity) {} 40 | 41 | #if RAPIDJSON_HAS_CXX11_RVALUE_REFS 42 | GenericStringBuffer(GenericStringBuffer&& rhs) : stack_(std::move(rhs.stack_)) {} 43 | GenericStringBuffer& operator=(GenericStringBuffer&& rhs) { 44 | if (&rhs != this) 45 | stack_ = std::move(rhs.stack_); 46 | return *this; 47 | } 48 | #endif 49 | 50 | void Put(Ch c) { *stack_.template Push() = c; } 51 | void Flush() {} 52 | 53 | void Clear() { stack_.Clear(); } 54 | void ShrinkToFit() { 55 | // Push and pop a null terminator. This is safe. 56 | *stack_.template Push() = '\0'; 57 | stack_.ShrinkToFit(); 58 | stack_.template Pop(1); 59 | } 60 | Ch* Push(size_t count) { return stack_.template Push(count); } 61 | void Pop(size_t count) { stack_.template Pop(count); } 62 | 63 | const Ch* GetString() const { 64 | // Push and pop a null terminator. This is safe. 65 | *stack_.template Push() = '\0'; 66 | stack_.template Pop(1); 67 | 68 | return stack_.template Bottom(); 69 | } 70 | 71 | size_t GetSize() const { return stack_.GetSize(); } 72 | 73 | static const size_t kDefaultCapacity = 256; 74 | mutable internal::Stack stack_; 75 | 76 | private: 77 | // Prohibit copy constructor & assignment operator. 78 | GenericStringBuffer(const GenericStringBuffer&); 79 | GenericStringBuffer& operator=(const GenericStringBuffer&); 80 | }; 81 | 82 | //! String buffer with UTF8 encoding 83 | typedef GenericStringBuffer > StringBuffer; 84 | 85 | //! Implement specialized version of PutN() with memset() for better performance. 86 | template<> 87 | inline void PutN(GenericStringBuffer >& stream, char c, size_t n) { 88 | std::memset(stream.stack_.Push(n), c, n * sizeof(c)); 89 | } 90 | 91 | RAPIDJSON_NAMESPACE_END 92 | 93 | #endif // RAPIDJSON_STRINGBUFFER_H_ 94 | -------------------------------------------------------------------------------- /src/rapidjson/writer.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_WRITER_H_ 16 | #define RAPIDJSON_WRITER_H_ 17 | 18 | #include "rapidjson.h" 19 | #include "internal/stack.h" 20 | #include "internal/strfunc.h" 21 | #include "internal/dtoa.h" 22 | #include "internal/itoa.h" 23 | #include "stringbuffer.h" 24 | #include // placement new 25 | 26 | #if RAPIDJSON_HAS_STDSTRING 27 | #include 28 | #endif 29 | 30 | #ifdef _MSC_VER 31 | RAPIDJSON_DIAG_PUSH 32 | RAPIDJSON_DIAG_OFF(4127) // conditional expression is constant 33 | #endif 34 | 35 | RAPIDJSON_NAMESPACE_BEGIN 36 | 37 | //! JSON writer 38 | /*! Writer implements the concept Handler. 39 | It generates JSON text by events to an output os. 40 | 41 | User may programmatically calls the functions of a writer to generate JSON text. 42 | 43 | On the other side, a writer can also be passed to objects that generates events, 44 | 45 | for example Reader::Parse() and Document::Accept(). 46 | 47 | \tparam OutputStream Type of output stream. 48 | \tparam SourceEncoding Encoding of source string. 49 | \tparam TargetEncoding Encoding of output stream. 50 | \tparam StackAllocator Type of allocator for allocating memory of stack. 51 | \note implements Handler concept 52 | */ 53 | template, typename TargetEncoding = UTF8<>, typename StackAllocator = CrtAllocator> 54 | class Writer { 55 | public: 56 | typedef typename SourceEncoding::Ch Ch; 57 | 58 | //! Constructor 59 | /*! \param os Output stream. 60 | \param stackAllocator User supplied allocator. If it is null, it will create a private one. 61 | \param levelDepth Initial capacity of stack. 62 | */ 63 | explicit 64 | Writer(OutputStream& os, StackAllocator* stackAllocator = 0, size_t levelDepth = kDefaultLevelDepth) : 65 | os_(&os), level_stack_(stackAllocator, levelDepth * sizeof(Level)), hasRoot_(false) {} 66 | 67 | explicit 68 | Writer(StackAllocator* allocator = 0, size_t levelDepth = kDefaultLevelDepth) : 69 | os_(0), level_stack_(allocator, levelDepth * sizeof(Level)), hasRoot_(false) {} 70 | 71 | //! Reset the writer with a new stream. 72 | /*! 73 | This function reset the writer with a new stream and default settings, 74 | in order to make a Writer object reusable for output multiple JSONs. 75 | 76 | \param os New output stream. 77 | \code 78 | Writer writer(os1); 79 | writer.StartObject(); 80 | // ... 81 | writer.EndObject(); 82 | 83 | writer.Reset(os2); 84 | writer.StartObject(); 85 | // ... 86 | writer.EndObject(); 87 | \endcode 88 | */ 89 | void Reset(OutputStream& os) { 90 | os_ = &os; 91 | hasRoot_ = false; 92 | level_stack_.Clear(); 93 | } 94 | 95 | //! Checks whether the output is a complete JSON. 96 | /*! 97 | A complete JSON has a complete root object or array. 98 | */ 99 | bool IsComplete() const { 100 | return hasRoot_ && level_stack_.Empty(); 101 | } 102 | 103 | /*!@name Implementation of Handler 104 | \see Handler 105 | */ 106 | //@{ 107 | 108 | bool Null() { Prefix(kNullType); return WriteNull(); } 109 | bool Bool(bool b) { Prefix(b ? kTrueType : kFalseType); return WriteBool(b); } 110 | bool Int(int i) { Prefix(kNumberType); return WriteInt(i); } 111 | bool Uint(unsigned u) { Prefix(kNumberType); return WriteUint(u); } 112 | bool Int64(int64_t i64) { Prefix(kNumberType); return WriteInt64(i64); } 113 | bool Uint64(uint64_t u64) { Prefix(kNumberType); return WriteUint64(u64); } 114 | 115 | //! Writes the given \c double value to the stream 116 | /*! 117 | \param d The value to be written. 118 | \return Whether it is succeed. 119 | */ 120 | bool Double(double d) { Prefix(kNumberType); return WriteDouble(d); } 121 | 122 | bool String(const Ch* str, SizeType length, bool copy = false) { 123 | (void)copy; 124 | Prefix(kStringType); 125 | return WriteString(str, length); 126 | } 127 | 128 | #if RAPIDJSON_HAS_STDSTRING 129 | bool String(const std::basic_string& str) { 130 | return String(str.data(), SizeType(str.size())); 131 | } 132 | #endif 133 | 134 | bool StartObject() { 135 | Prefix(kObjectType); 136 | new (level_stack_.template Push()) Level(false); 137 | return WriteStartObject(); 138 | } 139 | 140 | bool Key(const Ch* str, SizeType length, bool copy = false) { return String(str, length, copy); } 141 | 142 | bool EndObject(SizeType memberCount = 0) { 143 | (void)memberCount; 144 | RAPIDJSON_ASSERT(level_stack_.GetSize() >= sizeof(Level)); 145 | RAPIDJSON_ASSERT(!level_stack_.template Top()->inArray); 146 | level_stack_.template Pop(1); 147 | bool ret = WriteEndObject(); 148 | if (level_stack_.Empty()) // end of json text 149 | os_->Flush(); 150 | return ret; 151 | } 152 | 153 | bool StartArray() { 154 | Prefix(kArrayType); 155 | new (level_stack_.template Push()) Level(true); 156 | return WriteStartArray(); 157 | } 158 | 159 | bool EndArray(SizeType elementCount = 0) { 160 | (void)elementCount; 161 | RAPIDJSON_ASSERT(level_stack_.GetSize() >= sizeof(Level)); 162 | RAPIDJSON_ASSERT(level_stack_.template Top()->inArray); 163 | level_stack_.template Pop(1); 164 | bool ret = WriteEndArray(); 165 | if (level_stack_.Empty()) // end of json text 166 | os_->Flush(); 167 | return ret; 168 | } 169 | //@} 170 | 171 | /*! @name Convenience extensions */ 172 | //@{ 173 | 174 | //! Simpler but slower overload. 175 | bool String(const Ch* str) { return String(str, internal::StrLen(str)); } 176 | bool Key(const Ch* str) { return Key(str, internal::StrLen(str)); } 177 | 178 | //@} 179 | 180 | protected: 181 | //! Information for each nested level 182 | struct Level { 183 | Level(bool inArray_) : valueCount(0), inArray(inArray_) {} 184 | size_t valueCount; //!< number of values in this level 185 | bool inArray; //!< true if in array, otherwise in object 186 | }; 187 | 188 | static const size_t kDefaultLevelDepth = 32; 189 | 190 | bool WriteNull() { 191 | os_->Put('n'); os_->Put('u'); os_->Put('l'); os_->Put('l'); return true; 192 | } 193 | 194 | bool WriteBool(bool b) { 195 | if (b) { 196 | os_->Put('t'); os_->Put('r'); os_->Put('u'); os_->Put('e'); 197 | } 198 | else { 199 | os_->Put('f'); os_->Put('a'); os_->Put('l'); os_->Put('s'); os_->Put('e'); 200 | } 201 | return true; 202 | } 203 | 204 | bool WriteInt(int i) { 205 | char buffer[11]; 206 | const char* end = internal::i32toa(i, buffer); 207 | for (const char* p = buffer; p != end; ++p) 208 | os_->Put(*p); 209 | return true; 210 | } 211 | 212 | bool WriteUint(unsigned u) { 213 | char buffer[10]; 214 | const char* end = internal::u32toa(u, buffer); 215 | for (const char* p = buffer; p != end; ++p) 216 | os_->Put(*p); 217 | return true; 218 | } 219 | 220 | bool WriteInt64(int64_t i64) { 221 | char buffer[21]; 222 | const char* end = internal::i64toa(i64, buffer); 223 | for (const char* p = buffer; p != end; ++p) 224 | os_->Put(*p); 225 | return true; 226 | } 227 | 228 | bool WriteUint64(uint64_t u64) { 229 | char buffer[20]; 230 | char* end = internal::u64toa(u64, buffer); 231 | for (char* p = buffer; p != end; ++p) 232 | os_->Put(*p); 233 | return true; 234 | } 235 | 236 | bool WriteDouble(double d) { 237 | char buffer[25]; 238 | char* end = internal::dtoa(d, buffer); 239 | for (char* p = buffer; p != end; ++p) 240 | os_->Put(*p); 241 | return true; 242 | } 243 | 244 | bool WriteString(const Ch* str, SizeType length) { 245 | static const char hexDigits[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; 246 | static const char escape[256] = { 247 | #define Z16 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 248 | //0 1 2 3 4 5 6 7 8 9 A B C D E F 249 | 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'b', 't', 'n', 'u', 'f', 'r', 'u', 'u', // 00 250 | 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', // 10 251 | 0, 0, '"', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 20 252 | Z16, Z16, // 30~4F 253 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,'\\', 0, 0, 0, // 50 254 | Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16 // 60~FF 255 | #undef Z16 256 | }; 257 | 258 | os_->Put('\"'); 259 | GenericStringStream is(str); 260 | while (is.Tell() < length) { 261 | const Ch c = is.Peek(); 262 | if (!TargetEncoding::supportUnicode && (unsigned)c >= 0x80) { 263 | // Unicode escaping 264 | unsigned codepoint; 265 | if (!SourceEncoding::Decode(is, &codepoint)) 266 | return false; 267 | os_->Put('\\'); 268 | os_->Put('u'); 269 | if (codepoint <= 0xD7FF || (codepoint >= 0xE000 && codepoint <= 0xFFFF)) { 270 | os_->Put(hexDigits[(codepoint >> 12) & 15]); 271 | os_->Put(hexDigits[(codepoint >> 8) & 15]); 272 | os_->Put(hexDigits[(codepoint >> 4) & 15]); 273 | os_->Put(hexDigits[(codepoint ) & 15]); 274 | } 275 | else { 276 | RAPIDJSON_ASSERT(codepoint >= 0x010000 && codepoint <= 0x10FFFF); 277 | // Surrogate pair 278 | unsigned s = codepoint - 0x010000; 279 | unsigned lead = (s >> 10) + 0xD800; 280 | unsigned trail = (s & 0x3FF) + 0xDC00; 281 | os_->Put(hexDigits[(lead >> 12) & 15]); 282 | os_->Put(hexDigits[(lead >> 8) & 15]); 283 | os_->Put(hexDigits[(lead >> 4) & 15]); 284 | os_->Put(hexDigits[(lead ) & 15]); 285 | os_->Put('\\'); 286 | os_->Put('u'); 287 | os_->Put(hexDigits[(trail >> 12) & 15]); 288 | os_->Put(hexDigits[(trail >> 8) & 15]); 289 | os_->Put(hexDigits[(trail >> 4) & 15]); 290 | os_->Put(hexDigits[(trail ) & 15]); 291 | } 292 | } 293 | else if ((sizeof(Ch) == 1 || (unsigned)c < 256) && escape[(unsigned char)c]) { 294 | is.Take(); 295 | os_->Put('\\'); 296 | os_->Put(escape[(unsigned char)c]); 297 | if (escape[(unsigned char)c] == 'u') { 298 | os_->Put('0'); 299 | os_->Put('0'); 300 | os_->Put(hexDigits[(unsigned char)c >> 4]); 301 | os_->Put(hexDigits[(unsigned char)c & 0xF]); 302 | } 303 | } 304 | else 305 | if (!Transcoder::Transcode(is, *os_)) 306 | return false; 307 | } 308 | os_->Put('\"'); 309 | return true; 310 | } 311 | 312 | bool WriteStartObject() { os_->Put('{'); return true; } 313 | bool WriteEndObject() { os_->Put('}'); return true; } 314 | bool WriteStartArray() { os_->Put('['); return true; } 315 | bool WriteEndArray() { os_->Put(']'); return true; } 316 | 317 | void Prefix(Type type) { 318 | (void)type; 319 | if (level_stack_.GetSize() != 0) { // this value is not at root 320 | Level* level = level_stack_.template Top(); 321 | if (level->valueCount > 0) { 322 | if (level->inArray) 323 | os_->Put(','); // add comma if it is not the first element in array 324 | else // in object 325 | os_->Put((level->valueCount % 2 == 0) ? ',' : ':'); 326 | } 327 | if (!level->inArray && level->valueCount % 2 == 0) 328 | RAPIDJSON_ASSERT(type == kStringType); // if it's in object, then even number should be a name 329 | level->valueCount++; 330 | } 331 | else { 332 | RAPIDJSON_ASSERT(!hasRoot_); // Should only has one and only one root. 333 | hasRoot_ = true; 334 | } 335 | } 336 | 337 | OutputStream* os_; 338 | internal::Stack level_stack_; 339 | bool hasRoot_; 340 | 341 | private: 342 | // Prohibit copy constructor & assignment operator. 343 | Writer(const Writer&); 344 | Writer& operator=(const Writer&); 345 | }; 346 | 347 | // Full specialization for StringStream to prevent memory copying 348 | 349 | template<> 350 | inline bool Writer::WriteInt(int i) { 351 | char *buffer = os_->Push(11); 352 | const char* end = internal::i32toa(i, buffer); 353 | os_->Pop(11 - (end - buffer)); 354 | return true; 355 | } 356 | 357 | template<> 358 | inline bool Writer::WriteUint(unsigned u) { 359 | char *buffer = os_->Push(10); 360 | const char* end = internal::u32toa(u, buffer); 361 | os_->Pop(10 - (end - buffer)); 362 | return true; 363 | } 364 | 365 | template<> 366 | inline bool Writer::WriteInt64(int64_t i64) { 367 | char *buffer = os_->Push(21); 368 | const char* end = internal::i64toa(i64, buffer); 369 | os_->Pop(21 - (end - buffer)); 370 | return true; 371 | } 372 | 373 | template<> 374 | inline bool Writer::WriteUint64(uint64_t u) { 375 | char *buffer = os_->Push(20); 376 | const char* end = internal::u64toa(u, buffer); 377 | os_->Pop(20 - (end - buffer)); 378 | return true; 379 | } 380 | 381 | template<> 382 | inline bool Writer::WriteDouble(double d) { 383 | char *buffer = os_->Push(25); 384 | char* end = internal::dtoa(d, buffer); 385 | os_->Pop(25 - (end - buffer)); 386 | return true; 387 | } 388 | 389 | RAPIDJSON_NAMESPACE_END 390 | 391 | #ifdef _MSC_VER 392 | RAPIDJSON_DIAG_POP 393 | #endif 394 | 395 | #endif // RAPIDJSON_RAPIDJSON_H_ 396 | -------------------------------------------------------------------------------- /test/Makefile: -------------------------------------------------------------------------------- 1 | 2 | CXX=g++ 3 | 4 | CXXFLAGS=-Wall -g 5 | 6 | PBINC=/usr/local/include 7 | PBLIB=/usr/local/lib/libprotobuf.a 8 | 9 | INCS=-I./ -I../src -I${PBINC} 10 | LIBS=${PBLIB} -lpthread 11 | 12 | %.o : %.cpp 13 | ${CXX} -c ${CXXFLAGS} ${INCS} $< -o $@ 14 | 15 | %.o : %.cc 16 | ${CXX} -c ${CCFLAGS} ${INCS} $< -o $@ 17 | 18 | CORE_OBJECTS := test.o test.pb.o ../src/pbjson.o 19 | 20 | all: exe 21 | 22 | exe: ${CORE_OBJECTS} 23 | ${CXX} -o pbjson_test ${CORE_OBJECTS} $(LIBS) -------------------------------------------------------------------------------- /test/test.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * test.cpp 3 | * 4 | * Created on: Feb 11, 2014 5 | * Author: wangqiying 6 | */ 7 | #include "test.pb.h" 8 | #include "pbjson.hpp" 9 | #include 10 | 11 | int main() 12 | { 13 | Request request; 14 | request.mutable_header()->set_user("test_user"); 15 | request.mutable_header()->set_passwd("test_passwd"); 16 | request.set_arg1(101); 17 | request.add_arg2(10100000000000001LL); 18 | request.add_arg2(1022222201LL); 19 | request.set_arg3(3.1415926); 20 | 21 | Arg* arg = request.add_args(); 22 | arg->set_f1("xf1"); 23 | arg->set_f2("xf2"); 24 | arg = request.add_args(); 25 | arg->set_f1("xff1"); 26 | arg->set_f2("xff2"); 27 | 28 | std::string str; 29 | pbjson::pb2json(&request, str); 30 | printf("PB2Json result:\n%s\n", str.c_str()); 31 | 32 | Request new_request; 33 | std::string err; 34 | int ret = pbjson::json2pb(str, &new_request, err); 35 | printf("Json2PB result:\%d\n", ret); 36 | 37 | return 0; 38 | } 39 | 40 | -------------------------------------------------------------------------------- /test/test.proto: -------------------------------------------------------------------------------- 1 | 2 | message Header 3 | { 4 | required string user = 1; 5 | required string passwd = 2; 6 | } 7 | 8 | message Arg 9 | { 10 | optional string f1 = 1; 11 | optional string f2 = 2; 12 | } 13 | 14 | message Request 15 | { 16 | required Header header = 1; 17 | required int32 arg1 = 2; 18 | repeated int64 arg2 = 3; 19 | optional double arg3 = 4; 20 | repeated Arg args = 5; 21 | } --------------------------------------------------------------------------------