blob: 5e1d42befa523af3479430724d45f009f87e912b [file] [log] [blame]
David Reissea2cba82009-03-30 21:35:00 +00001/*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
David Reissdb0ea152008-02-18 01:49:37 +000019
Roger Meier4285ba22013-06-10 21:17:23 +020020#include <thrift/protocol/TJSONProtocol.h>
David Reissdb0ea152008-02-18 01:49:37 +000021
Konrad Grochowski12b06e42015-02-21 13:48:56 +010022#include <limits>
23#include <locale>
24#include <sstream>
25#include <cmath>
26
27#include <boost/math/special_functions/fpclassify.hpp>
David Reissa1771092008-04-11 22:36:31 +000028#include <boost/lexical_cast.hpp>
Konrad Grochowski12b06e42015-02-21 13:48:56 +010029
Roger Meier4285ba22013-06-10 21:17:23 +020030#include <thrift/protocol/TBase64Utils.h>
Roger Meier49ff8b12012-04-13 09:12:31 +000031#include <thrift/transport/TTransportException.h>
David Reissdb0ea152008-02-18 01:49:37 +000032
T Jake Lucianib5e62212009-01-31 22:36:20 +000033using namespace apache::thrift::transport;
David Reissdb0ea152008-02-18 01:49:37 +000034
Konrad Grochowski16a23a62014-11-13 15:33:38 +010035namespace apache {
36namespace thrift {
37namespace protocol {
David Reissdb0ea152008-02-18 01:49:37 +000038
39// Static data
40
41static const uint8_t kJSONObjectStart = '{';
42static const uint8_t kJSONObjectEnd = '}';
43static const uint8_t kJSONArrayStart = '[';
44static const uint8_t kJSONArrayEnd = ']';
45static const uint8_t kJSONNewline = '\n';
46static const uint8_t kJSONPairSeparator = ':';
47static const uint8_t kJSONElemSeparator = ',';
48static const uint8_t kJSONBackslash = '\\';
49static const uint8_t kJSONStringDelimiter = '"';
50static const uint8_t kJSONZeroChar = '0';
51static const uint8_t kJSONEscapeChar = 'u';
52
53static const std::string kJSONEscapePrefix("\\u00");
54
David Reiss6713e1b2009-01-15 23:56:19 +000055static const uint32_t kThriftVersion1 = 1;
David Reissdb0ea152008-02-18 01:49:37 +000056
57static const std::string kThriftNan("NaN");
58static const std::string kThriftInfinity("Infinity");
59static const std::string kThriftNegativeInfinity("-Infinity");
60
61static const std::string kTypeNameBool("tf");
62static const std::string kTypeNameByte("i8");
63static const std::string kTypeNameI16("i16");
64static const std::string kTypeNameI32("i32");
65static const std::string kTypeNameI64("i64");
66static const std::string kTypeNameDouble("dbl");
67static const std::string kTypeNameStruct("rec");
68static const std::string kTypeNameString("str");
69static const std::string kTypeNameMap("map");
70static const std::string kTypeNameList("lst");
71static const std::string kTypeNameSet("set");
72
Konrad Grochowski16a23a62014-11-13 15:33:38 +010073static const std::string& getTypeNameForTypeID(TType typeID) {
David Reissdb0ea152008-02-18 01:49:37 +000074 switch (typeID) {
75 case T_BOOL:
76 return kTypeNameBool;
77 case T_BYTE:
78 return kTypeNameByte;
79 case T_I16:
80 return kTypeNameI16;
81 case T_I32:
82 return kTypeNameI32;
83 case T_I64:
84 return kTypeNameI64;
85 case T_DOUBLE:
86 return kTypeNameDouble;
87 case T_STRING:
88 return kTypeNameString;
89 case T_STRUCT:
90 return kTypeNameStruct;
91 case T_MAP:
92 return kTypeNameMap;
93 case T_SET:
94 return kTypeNameSet;
95 case T_LIST:
96 return kTypeNameList;
97 default:
Konrad Grochowski16a23a62014-11-13 15:33:38 +010098 throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, "Unrecognized type");
David Reissdb0ea152008-02-18 01:49:37 +000099 }
100}
101
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100102static TType getTypeIDForTypeName(const std::string& name) {
David Reissdb0ea152008-02-18 01:49:37 +0000103 TType result = T_STOP; // Sentinel value
David Reiss2c9824c2008-03-02 00:20:47 +0000104 if (name.length() > 1) {
David Reiss1e62ab42008-02-21 22:37:45 +0000105 switch (name[0]) {
106 case 'd':
107 result = T_DOUBLE;
David Reissdb0ea152008-02-18 01:49:37 +0000108 break;
David Reiss1e62ab42008-02-21 22:37:45 +0000109 case 'i':
110 switch (name[1]) {
111 case '8':
112 result = T_BYTE;
113 break;
114 case '1':
115 result = T_I16;
116 break;
117 case '3':
118 result = T_I32;
119 break;
120 case '6':
121 result = T_I64;
122 break;
123 }
David Reissdb0ea152008-02-18 01:49:37 +0000124 break;
David Reiss1e62ab42008-02-21 22:37:45 +0000125 case 'l':
126 result = T_LIST;
David Reissdb0ea152008-02-18 01:49:37 +0000127 break;
David Reiss1e62ab42008-02-21 22:37:45 +0000128 case 'm':
129 result = T_MAP;
130 break;
131 case 'r':
132 result = T_STRUCT;
133 break;
134 case 's':
135 if (name[1] == 't') {
136 result = T_STRING;
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100137 } else if (name[1] == 'e') {
David Reiss1e62ab42008-02-21 22:37:45 +0000138 result = T_SET;
139 }
140 break;
141 case 't':
142 result = T_BOOL;
David Reissdb0ea152008-02-18 01:49:37 +0000143 break;
144 }
David Reissdb0ea152008-02-18 01:49:37 +0000145 }
146 if (result == T_STOP) {
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100147 throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, "Unrecognized type");
David Reissdb0ea152008-02-18 01:49:37 +0000148 }
149 return result;
150}
151
David Reissdb0ea152008-02-18 01:49:37 +0000152// This table describes the handling for the first 0x30 characters
153// 0 : escape using "\u00xx" notation
154// 1 : just output index
155// <other> : escape using "\<other>" notation
156static const uint8_t kJSONCharTable[0x30] = {
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100157 // 0 1 2 3 4 5 6 7 8 9 A B C D E F
158 0,
159 0,
160 0,
161 0,
162 0,
163 0,
164 0,
165 0,
166 'b',
167 't',
168 'n',
169 0,
170 'f',
171 'r',
172 0,
173 0, // 0
174 0,
175 0,
176 0,
177 0,
178 0,
179 0,
180 0,
181 0,
182 0,
183 0,
184 0,
185 0,
186 0,
187 0,
188 0,
189 0, // 1
190 1,
191 1,
192 '"',
193 1,
194 1,
195 1,
196 1,
197 1,
198 1,
199 1,
200 1,
201 1,
202 1,
203 1,
204 1,
205 1, // 2
David Reissdb0ea152008-02-18 01:49:37 +0000206};
207
David Reissdb0ea152008-02-18 01:49:37 +0000208// This string's characters must match up with the elements in kEscapeCharVals.
209// I don't have '/' on this list even though it appears on www.json.org --
210// it is not in the RFC
211const static std::string kEscapeChars("\"\\bfnrt");
212
213// The elements of this array must match up with the sequence of characters in
214// kEscapeChars
215const static uint8_t kEscapeCharVals[7] = {
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100216 '"',
217 '\\',
218 '\b',
219 '\f',
220 '\n',
221 '\r',
222 '\t',
David Reissdb0ea152008-02-18 01:49:37 +0000223};
224
David Reissdb0ea152008-02-18 01:49:37 +0000225// Static helper functions
226
227// Read 1 character from the transport trans and verify that it is the
228// expected character ch.
229// Throw a protocol exception if it is not.
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100230static uint32_t readSyntaxChar(TJSONProtocol::LookaheadReader& reader, uint8_t ch) {
David Reiss1e62ab42008-02-21 22:37:45 +0000231 uint8_t ch2 = reader.read();
232 if (ch2 != ch) {
David Reissdb0ea152008-02-18 01:49:37 +0000233 throw TProtocolException(TProtocolException::INVALID_DATA,
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100234 "Expected \'" + std::string((char*)&ch, 1) + "\'; got \'"
235 + std::string((char*)&ch2, 1) + "\'.");
David Reissdb0ea152008-02-18 01:49:37 +0000236 }
237 return 1;
238}
239
David Reissdb0ea152008-02-18 01:49:37 +0000240// Return the integer value of a hex character ch.
241// Throw a protocol exception if the character is not [0-9a-f].
242static uint8_t hexVal(uint8_t ch) {
243 if ((ch >= '0') && (ch <= '9')) {
244 return ch - '0';
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100245 } else if ((ch >= 'a') && (ch <= 'f')) {
Bryan Duxbury4a2bc1b2010-11-03 17:57:38 +0000246 return ch - 'a' + 10;
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100247 } else {
David Reissdb0ea152008-02-18 01:49:37 +0000248 throw TProtocolException(TProtocolException::INVALID_DATA,
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100249 "Expected hex val ([0-9a-f]); got \'" + std::string((char*)&ch, 1)
250 + "\'.");
David Reissdb0ea152008-02-18 01:49:37 +0000251 }
252}
253
254// Return the hex character representing the integer val. The value is masked
255// to make sure it is in the correct range.
256static uint8_t hexChar(uint8_t val) {
257 val &= 0x0F;
258 if (val < 10) {
259 return val + '0';
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100260 } else {
Bryan Duxbury4a2bc1b2010-11-03 17:57:38 +0000261 return val - 10 + 'a';
David Reissdb0ea152008-02-18 01:49:37 +0000262 }
263}
264
265// Return true if the character ch is in [-+0-9.Ee]; false otherwise
266static bool isJSONNumeric(uint8_t ch) {
267 switch (ch) {
268 case '+':
269 case '-':
270 case '.':
271 case '0':
272 case '1':
273 case '2':
274 case '3':
275 case '4':
276 case '5':
277 case '6':
278 case '7':
279 case '8':
280 case '9':
281 case 'E':
282 case 'e':
283 return true;
284 }
285 return false;
286}
287
David Reissdb0ea152008-02-18 01:49:37 +0000288/**
David Reiss1e62ab42008-02-21 22:37:45 +0000289 * Class to serve as base JSON context and as base class for other context
David Reissdb0ea152008-02-18 01:49:37 +0000290 * implementations
291 */
292class TJSONContext {
293
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100294public:
295 TJSONContext(){};
David Reissdb0ea152008-02-18 01:49:37 +0000296
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100297 virtual ~TJSONContext(){};
David Reissdb0ea152008-02-18 01:49:37 +0000298
299 /**
300 * Write context data to the transport. Default is to do nothing.
301 */
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100302 virtual uint32_t write(TTransport& trans) {
303 (void)trans;
David Reissdb0ea152008-02-18 01:49:37 +0000304 return 0;
305 };
306
307 /**
308 * Read context data from the transport. Default is to do nothing.
309 */
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100310 virtual uint32_t read(TJSONProtocol::LookaheadReader& reader) {
311 (void)reader;
David Reissdb0ea152008-02-18 01:49:37 +0000312 return 0;
313 };
314
315 /**
316 * Return true if numbers need to be escaped as strings in this context.
317 * Default behavior is to return false.
318 */
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100319 virtual bool escapeNum() { return false; }
David Reissdb0ea152008-02-18 01:49:37 +0000320};
321
322// Context class for object member key-value pairs
323class JSONPairContext : public TJSONContext {
324
325public:
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100326 JSONPairContext() : first_(true), colon_(true) {}
David Reissdb0ea152008-02-18 01:49:37 +0000327
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100328 uint32_t write(TTransport& trans) {
David Reissdb0ea152008-02-18 01:49:37 +0000329 if (first_) {
330 first_ = false;
331 colon_ = true;
332 return 0;
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100333 } else {
David Reissdb0ea152008-02-18 01:49:37 +0000334 trans.write(colon_ ? &kJSONPairSeparator : &kJSONElemSeparator, 1);
335 colon_ = !colon_;
336 return 1;
337 }
338 }
339
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100340 uint32_t read(TJSONProtocol::LookaheadReader& reader) {
David Reissdb0ea152008-02-18 01:49:37 +0000341 if (first_) {
342 first_ = false;
343 colon_ = true;
344 return 0;
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100345 } else {
David Reissdb0ea152008-02-18 01:49:37 +0000346 uint8_t ch = (colon_ ? kJSONPairSeparator : kJSONElemSeparator);
347 colon_ = !colon_;
David Reiss1e62ab42008-02-21 22:37:45 +0000348 return readSyntaxChar(reader, ch);
David Reissdb0ea152008-02-18 01:49:37 +0000349 }
350 }
351
352 // Numbers must be turned into strings if they are the key part of a pair
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100353 virtual bool escapeNum() { return colon_; }
David Reissdb0ea152008-02-18 01:49:37 +0000354
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100355private:
356 bool first_;
357 bool colon_;
David Reissdb0ea152008-02-18 01:49:37 +0000358};
359
360// Context class for lists
361class JSONListContext : public TJSONContext {
362
363public:
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100364 JSONListContext() : first_(true) {}
David Reissdb0ea152008-02-18 01:49:37 +0000365
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100366 uint32_t write(TTransport& trans) {
David Reissdb0ea152008-02-18 01:49:37 +0000367 if (first_) {
368 first_ = false;
369 return 0;
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100370 } else {
David Reissdb0ea152008-02-18 01:49:37 +0000371 trans.write(&kJSONElemSeparator, 1);
372 return 1;
373 }
374 }
375
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100376 uint32_t read(TJSONProtocol::LookaheadReader& reader) {
David Reissdb0ea152008-02-18 01:49:37 +0000377 if (first_) {
378 first_ = false;
379 return 0;
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100380 } else {
David Reiss1e62ab42008-02-21 22:37:45 +0000381 return readSyntaxChar(reader, kJSONElemSeparator);
David Reissdb0ea152008-02-18 01:49:37 +0000382 }
383 }
384
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100385private:
386 bool first_;
David Reissdb0ea152008-02-18 01:49:37 +0000387};
388
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100389TJSONProtocol::TJSONProtocol(boost::shared_ptr<TTransport> ptrans)
390 : TVirtualProtocol<TJSONProtocol>(ptrans),
391 trans_(ptrans.get()),
392 context_(new TJSONContext()),
393 reader_(*ptrans) {
David Reissdb0ea152008-02-18 01:49:37 +0000394}
395
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100396TJSONProtocol::~TJSONProtocol() {
397}
David Reissdb0ea152008-02-18 01:49:37 +0000398
399void TJSONProtocol::pushContext(boost::shared_ptr<TJSONContext> c) {
400 contexts_.push(context_);
401 context_ = c;
402}
403
404void TJSONProtocol::popContext() {
405 context_ = contexts_.top();
406 contexts_.pop();
407}
408
409// Write the character ch as a JSON escape sequence ("\u00xx")
410uint32_t TJSONProtocol::writeJSONEscapeChar(uint8_t ch) {
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100411 trans_->write((const uint8_t*)kJSONEscapePrefix.c_str(),
Roger Meierb69d24d2012-10-04 18:02:15 +0000412 static_cast<uint32_t>(kJSONEscapePrefix.length()));
David Reissdb0ea152008-02-18 01:49:37 +0000413 uint8_t outCh = hexChar(ch >> 4);
414 trans_->write(&outCh, 1);
415 outCh = hexChar(ch);
416 trans_->write(&outCh, 1);
417 return 6;
418}
419
420// Write the character ch as part of a JSON string, escaping as appropriate.
421uint32_t TJSONProtocol::writeJSONChar(uint8_t ch) {
422 if (ch >= 0x30) {
423 if (ch == kJSONBackslash) { // Only special character >= 0x30 is '\'
424 trans_->write(&kJSONBackslash, 1);
425 trans_->write(&kJSONBackslash, 1);
426 return 2;
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100427 } else {
David Reissdb0ea152008-02-18 01:49:37 +0000428 trans_->write(&ch, 1);
429 return 1;
430 }
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100431 } else {
David Reissdb0ea152008-02-18 01:49:37 +0000432 uint8_t outCh = kJSONCharTable[ch];
433 // Check if regular character, backslash escaped, or JSON escaped
434 if (outCh == 1) {
435 trans_->write(&ch, 1);
436 return 1;
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100437 } else if (outCh > 1) {
David Reissdb0ea152008-02-18 01:49:37 +0000438 trans_->write(&kJSONBackslash, 1);
439 trans_->write(&outCh, 1);
440 return 2;
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100441 } else {
David Reissdb0ea152008-02-18 01:49:37 +0000442 return writeJSONEscapeChar(ch);
443 }
444 }
445}
446
447// Write out the contents of the string str as a JSON string, escaping
448// characters as appropriate.
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100449uint32_t TJSONProtocol::writeJSONString(const std::string& str) {
David Reissdb0ea152008-02-18 01:49:37 +0000450 uint32_t result = context_->write(*trans_);
451 result += 2; // For quotes
452 trans_->write(&kJSONStringDelimiter, 1);
453 std::string::const_iterator iter(str.begin());
454 std::string::const_iterator end(str.end());
455 while (iter != end) {
456 result += writeJSONChar(*iter++);
457 }
458 trans_->write(&kJSONStringDelimiter, 1);
459 return result;
460}
461
462// Write out the contents of the string as JSON string, base64-encoding
463// the string's contents, and escaping as appropriate
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100464uint32_t TJSONProtocol::writeJSONBase64(const std::string& str) {
David Reissdb0ea152008-02-18 01:49:37 +0000465 uint32_t result = context_->write(*trans_);
466 result += 2; // For quotes
467 trans_->write(&kJSONStringDelimiter, 1);
468 uint8_t b[4];
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100469 const uint8_t* bytes = (const uint8_t*)str.c_str();
470 if (str.length() > (std::numeric_limits<uint32_t>::max)())
Roger Meierb69d24d2012-10-04 18:02:15 +0000471 throw TProtocolException(TProtocolException::SIZE_LIMIT);
472 uint32_t len = static_cast<uint32_t>(str.length());
David Reissdb0ea152008-02-18 01:49:37 +0000473 while (len >= 3) {
474 // Encode 3 bytes at a time
475 base64_encode(bytes, 3, b);
476 trans_->write(b, 4);
477 result += 4;
478 bytes += 3;
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100479 len -= 3;
David Reissdb0ea152008-02-18 01:49:37 +0000480 }
481 if (len) { // Handle remainder
482 base64_encode(bytes, len, b);
483 trans_->write(b, len + 1);
484 result += len + 1;
485 }
486 trans_->write(&kJSONStringDelimiter, 1);
487 return result;
488}
489
490// Convert the given integer type to a JSON number, or a string
491// if the context requires it (eg: key in a map pair).
492template <typename NumberType>
493uint32_t TJSONProtocol::writeJSONInteger(NumberType num) {
494 uint32_t result = context_->write(*trans_);
495 std::string val(boost::lexical_cast<std::string>(num));
496 bool escapeNum = context_->escapeNum();
497 if (escapeNum) {
498 trans_->write(&kJSONStringDelimiter, 1);
499 result += 1;
500 }
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100501 if (val.length() > (std::numeric_limits<uint32_t>::max)())
Roger Meierb69d24d2012-10-04 18:02:15 +0000502 throw TProtocolException(TProtocolException::SIZE_LIMIT);
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100503 trans_->write((const uint8_t*)val.c_str(), static_cast<uint32_t>(val.length()));
Roger Meierb69d24d2012-10-04 18:02:15 +0000504 result += static_cast<uint32_t>(val.length());
David Reissdb0ea152008-02-18 01:49:37 +0000505 if (escapeNum) {
506 trans_->write(&kJSONStringDelimiter, 1);
507 result += 1;
508 }
509 return result;
510}
511
Konrad Grochowski12b06e42015-02-21 13:48:56 +0100512namespace
513{
514std::string doubleToString(double d)
515{
516 std::ostringstream str;
517 str.imbue(std::locale::classic());
518 str.precision(std::numeric_limits<double>::digits10 + 1);
519 str << d;
520 return str.str();
521}
522}
523
David Reissdb0ea152008-02-18 01:49:37 +0000524// Convert the given double to a JSON string, which is either the number,
525// "NaN" or "Infinity" or "-Infinity".
526uint32_t TJSONProtocol::writeJSONDouble(double num) {
527 uint32_t result = context_->write(*trans_);
Konrad Grochowski12b06e42015-02-21 13:48:56 +0100528 std::string val;
David Reissdb0ea152008-02-18 01:49:37 +0000529
David Reissdb0ea152008-02-18 01:49:37 +0000530 bool special = false;
Konrad Grochowski12b06e42015-02-21 13:48:56 +0100531 switch (boost::math::fpclassify(num)) {
532 case FP_INFINITE:
533 if (boost::math::signbit(num)) {
534 val = kThriftNegativeInfinity;
535 } else {
536 val = kThriftInfinity;
537 }
538 special = true;
539 break;
540 case FP_NAN:
David Reissdb0ea152008-02-18 01:49:37 +0000541 val = kThriftNan;
542 special = true;
543 break;
Konrad Grochowski12b06e42015-02-21 13:48:56 +0100544 default:
545 val = doubleToString(num);
David Reissdb0ea152008-02-18 01:49:37 +0000546 break;
547 }
548
549 bool escapeNum = special || context_->escapeNum();
550 if (escapeNum) {
551 trans_->write(&kJSONStringDelimiter, 1);
552 result += 1;
553 }
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100554 if (val.length() > (std::numeric_limits<uint32_t>::max)())
Roger Meierb69d24d2012-10-04 18:02:15 +0000555 throw TProtocolException(TProtocolException::SIZE_LIMIT);
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100556 trans_->write((const uint8_t*)val.c_str(), static_cast<uint32_t>(val.length()));
Roger Meierb69d24d2012-10-04 18:02:15 +0000557 result += static_cast<uint32_t>(val.length());
David Reissdb0ea152008-02-18 01:49:37 +0000558 if (escapeNum) {
559 trans_->write(&kJSONStringDelimiter, 1);
560 result += 1;
561 }
562 return result;
563}
564
565uint32_t TJSONProtocol::writeJSONObjectStart() {
566 uint32_t result = context_->write(*trans_);
567 trans_->write(&kJSONObjectStart, 1);
568 pushContext(boost::shared_ptr<TJSONContext>(new JSONPairContext()));
569 return result + 1;
570}
571
572uint32_t TJSONProtocol::writeJSONObjectEnd() {
573 popContext();
574 trans_->write(&kJSONObjectEnd, 1);
575 return 1;
576}
577
578uint32_t TJSONProtocol::writeJSONArrayStart() {
579 uint32_t result = context_->write(*trans_);
580 trans_->write(&kJSONArrayStart, 1);
581 pushContext(boost::shared_ptr<TJSONContext>(new JSONListContext()));
582 return result + 1;
583}
584
585uint32_t TJSONProtocol::writeJSONArrayEnd() {
586 popContext();
587 trans_->write(&kJSONArrayEnd, 1);
588 return 1;
589}
590
591uint32_t TJSONProtocol::writeMessageBegin(const std::string& name,
592 const TMessageType messageType,
593 const int32_t seqid) {
594 uint32_t result = writeJSONArrayStart();
595 result += writeJSONInteger(kThriftVersion1);
596 result += writeJSONString(name);
597 result += writeJSONInteger(messageType);
598 result += writeJSONInteger(seqid);
599 return result;
600}
601
602uint32_t TJSONProtocol::writeMessageEnd() {
603 return writeJSONArrayEnd();
604}
605
David Reiss64120002008-04-29 23:12:24 +0000606uint32_t TJSONProtocol::writeStructBegin(const char* name) {
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100607 (void)name;
David Reissdb0ea152008-02-18 01:49:37 +0000608 return writeJSONObjectStart();
609}
610
611uint32_t TJSONProtocol::writeStructEnd() {
612 return writeJSONObjectEnd();
613}
614
David Reiss64120002008-04-29 23:12:24 +0000615uint32_t TJSONProtocol::writeFieldBegin(const char* name,
David Reissdb0ea152008-02-18 01:49:37 +0000616 const TType fieldType,
617 const int16_t fieldId) {
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100618 (void)name;
David Reissdb0ea152008-02-18 01:49:37 +0000619 uint32_t result = writeJSONInteger(fieldId);
620 result += writeJSONObjectStart();
621 result += writeJSONString(getTypeNameForTypeID(fieldType));
622 return result;
623}
624
625uint32_t TJSONProtocol::writeFieldEnd() {
626 return writeJSONObjectEnd();
627}
628
629uint32_t TJSONProtocol::writeFieldStop() {
630 return 0;
631}
632
633uint32_t TJSONProtocol::writeMapBegin(const TType keyType,
634 const TType valType,
635 const uint32_t size) {
636 uint32_t result = writeJSONArrayStart();
637 result += writeJSONString(getTypeNameForTypeID(keyType));
638 result += writeJSONString(getTypeNameForTypeID(valType));
639 result += writeJSONInteger((int64_t)size);
640 result += writeJSONObjectStart();
641 return result;
642}
643
644uint32_t TJSONProtocol::writeMapEnd() {
645 return writeJSONObjectEnd() + writeJSONArrayEnd();
646}
647
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100648uint32_t TJSONProtocol::writeListBegin(const TType elemType, const uint32_t size) {
David Reissdb0ea152008-02-18 01:49:37 +0000649 uint32_t result = writeJSONArrayStart();
650 result += writeJSONString(getTypeNameForTypeID(elemType));
651 result += writeJSONInteger((int64_t)size);
652 return result;
653}
654
655uint32_t TJSONProtocol::writeListEnd() {
656 return writeJSONArrayEnd();
657}
658
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100659uint32_t TJSONProtocol::writeSetBegin(const TType elemType, const uint32_t size) {
David Reissdb0ea152008-02-18 01:49:37 +0000660 uint32_t result = writeJSONArrayStart();
661 result += writeJSONString(getTypeNameForTypeID(elemType));
662 result += writeJSONInteger((int64_t)size);
663 return result;
664}
665
666uint32_t TJSONProtocol::writeSetEnd() {
667 return writeJSONArrayEnd();
668}
669
670uint32_t TJSONProtocol::writeBool(const bool value) {
671 return writeJSONInteger(value);
672}
673
674uint32_t TJSONProtocol::writeByte(const int8_t byte) {
Konrad Grochowski3b5dacb2014-11-24 10:55:31 +0100675 // writeByte() must be handled specially because boost::lexical cast sees
David Reissdb0ea152008-02-18 01:49:37 +0000676 // int8_t as a text type instead of an integer type
677 return writeJSONInteger((int16_t)byte);
678}
679
680uint32_t TJSONProtocol::writeI16(const int16_t i16) {
681 return writeJSONInteger(i16);
682}
683
684uint32_t TJSONProtocol::writeI32(const int32_t i32) {
685 return writeJSONInteger(i32);
686}
687
688uint32_t TJSONProtocol::writeI64(const int64_t i64) {
689 return writeJSONInteger(i64);
690}
691
692uint32_t TJSONProtocol::writeDouble(const double dub) {
693 return writeJSONDouble(dub);
694}
695
696uint32_t TJSONProtocol::writeString(const std::string& str) {
697 return writeJSONString(str);
698}
699
700uint32_t TJSONProtocol::writeBinary(const std::string& str) {
701 return writeJSONBase64(str);
702}
703
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100704/**
705 * Reading functions
706 */
David Reissdb0ea152008-02-18 01:49:37 +0000707
David Reiss1e62ab42008-02-21 22:37:45 +0000708// Reads 1 byte and verifies that it matches ch.
David Reissdb0ea152008-02-18 01:49:37 +0000709uint32_t TJSONProtocol::readJSONSyntaxChar(uint8_t ch) {
David Reiss1e62ab42008-02-21 22:37:45 +0000710 return readSyntaxChar(reader_, ch);
David Reissdb0ea152008-02-18 01:49:37 +0000711}
712
713// Decodes the four hex parts of a JSON escaped string character and returns
714// the character via out. The first two characters must be "00".
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100715uint32_t TJSONProtocol::readJSONEscapeChar(uint8_t* out) {
David Reissdb0ea152008-02-18 01:49:37 +0000716 uint8_t b[2];
717 readJSONSyntaxChar(kJSONZeroChar);
718 readJSONSyntaxChar(kJSONZeroChar);
David Reiss1e62ab42008-02-21 22:37:45 +0000719 b[0] = reader_.read();
720 b[1] = reader_.read();
David Reissdb0ea152008-02-18 01:49:37 +0000721 *out = (hexVal(b[0]) << 4) + hexVal(b[1]);
722 return 4;
723}
724
725// Decodes a JSON string, including unescaping, and returns the string via str
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100726uint32_t TJSONProtocol::readJSONString(std::string& str, bool skipContext) {
David Reiss1e62ab42008-02-21 22:37:45 +0000727 uint32_t result = (skipContext ? 0 : context_->read(reader_));
David Reissdb0ea152008-02-18 01:49:37 +0000728 result += readJSONSyntaxChar(kJSONStringDelimiter);
David Reiss1e62ab42008-02-21 22:37:45 +0000729 uint8_t ch;
David Reiss91630732008-02-28 21:11:39 +0000730 str.clear();
David Reissdb0ea152008-02-18 01:49:37 +0000731 while (true) {
David Reiss1e62ab42008-02-21 22:37:45 +0000732 ch = reader_.read();
733 ++result;
734 if (ch == kJSONStringDelimiter) {
David Reissdb0ea152008-02-18 01:49:37 +0000735 break;
736 }
David Reiss1e62ab42008-02-21 22:37:45 +0000737 if (ch == kJSONBackslash) {
738 ch = reader_.read();
739 ++result;
740 if (ch == kJSONEscapeChar) {
741 result += readJSONEscapeChar(&ch);
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100742 } else {
David Reiss1e62ab42008-02-21 22:37:45 +0000743 size_t pos = kEscapeChars.find(ch);
David Reissdb0ea152008-02-18 01:49:37 +0000744 if (pos == std::string::npos) {
745 throw TProtocolException(TProtocolException::INVALID_DATA,
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100746 "Expected control char, got '" + std::string((const char*)&ch, 1)
747 + "'.");
David Reissdb0ea152008-02-18 01:49:37 +0000748 }
David Reiss1e62ab42008-02-21 22:37:45 +0000749 ch = kEscapeCharVals[pos];
David Reissdb0ea152008-02-18 01:49:37 +0000750 }
751 }
David Reiss1e62ab42008-02-21 22:37:45 +0000752 str += ch;
David Reissdb0ea152008-02-18 01:49:37 +0000753 }
754 return result;
755}
756
757// Reads a block of base64 characters, decoding it, and returns via str
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100758uint32_t TJSONProtocol::readJSONBase64(std::string& str) {
David Reissdb0ea152008-02-18 01:49:37 +0000759 std::string tmp;
760 uint32_t result = readJSONString(tmp);
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100761 uint8_t* b = (uint8_t*)tmp.c_str();
762 if (tmp.length() > (std::numeric_limits<uint32_t>::max)())
Roger Meierb69d24d2012-10-04 18:02:15 +0000763 throw TProtocolException(TProtocolException::SIZE_LIMIT);
764 uint32_t len = static_cast<uint32_t>(tmp.length());
David Reiss91630732008-02-28 21:11:39 +0000765 str.clear();
David Reissdb0ea152008-02-18 01:49:37 +0000766 while (len >= 4) {
767 base64_decode(b, 4);
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100768 str.append((const char*)b, 3);
David Reissdb0ea152008-02-18 01:49:37 +0000769 b += 4;
770 len -= 4;
771 }
772 // Don't decode if we hit the end or got a single leftover byte (invalid
773 // base64 but legal for skip of regular string type)
774 if (len > 1) {
775 base64_decode(b, len);
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100776 str.append((const char*)b, len - 1);
David Reissdb0ea152008-02-18 01:49:37 +0000777 }
778 return result;
779}
780
781// Reads a sequence of characters, stopping at the first one that is not
782// a valid JSON numeric character.
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100783uint32_t TJSONProtocol::readJSONNumericChars(std::string& str) {
David Reissdb0ea152008-02-18 01:49:37 +0000784 uint32_t result = 0;
David Reiss91630732008-02-28 21:11:39 +0000785 str.clear();
David Reissdb0ea152008-02-18 01:49:37 +0000786 while (true) {
David Reiss1e62ab42008-02-21 22:37:45 +0000787 uint8_t ch = reader_.peek();
David Reissdb0ea152008-02-18 01:49:37 +0000788 if (!isJSONNumeric(ch)) {
789 break;
790 }
David Reiss1e62ab42008-02-21 22:37:45 +0000791 reader_.read();
David Reissdb0ea152008-02-18 01:49:37 +0000792 str += ch;
793 ++result;
794 }
795 return result;
796}
797
798// Reads a sequence of characters and assembles them into a number,
799// returning them via num
800template <typename NumberType>
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100801uint32_t TJSONProtocol::readJSONInteger(NumberType& num) {
David Reiss1e62ab42008-02-21 22:37:45 +0000802 uint32_t result = context_->read(reader_);
David Reissdb0ea152008-02-18 01:49:37 +0000803 if (context_->escapeNum()) {
804 result += readJSONSyntaxChar(kJSONStringDelimiter);
805 }
806 std::string str;
807 result += readJSONNumericChars(str);
808 try {
809 num = boost::lexical_cast<NumberType>(str);
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100810 } catch (boost::bad_lexical_cast e) {
David Reissdb0ea152008-02-18 01:49:37 +0000811 throw new TProtocolException(TProtocolException::INVALID_DATA,
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100812 "Expected numeric value; got \"" + str + "\"");
David Reissdb0ea152008-02-18 01:49:37 +0000813 }
814 if (context_->escapeNum()) {
815 result += readJSONSyntaxChar(kJSONStringDelimiter);
816 }
817 return result;
818}
819
Konrad Grochowski12b06e42015-02-21 13:48:56 +0100820namespace
821{
822double stringToDouble(const std::string& s)
823{
824 double d;
825 std::istringstream str(s);
826 str.imbue(std::locale::classic());
827 str >> d;
828 if (str.bad() || !str.eof())
829 throw std::runtime_error(s);
830 return d;
831}
832}
833
David Reissdb0ea152008-02-18 01:49:37 +0000834// Reads a JSON number or string and interprets it as a double.
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100835uint32_t TJSONProtocol::readJSONDouble(double& num) {
David Reiss1e62ab42008-02-21 22:37:45 +0000836 uint32_t result = context_->read(reader_);
David Reissdb0ea152008-02-18 01:49:37 +0000837 std::string str;
David Reiss1e62ab42008-02-21 22:37:45 +0000838 if (reader_.peek() == kJSONStringDelimiter) {
David Reissdb0ea152008-02-18 01:49:37 +0000839 result += readJSONString(str, true);
840 // Check for NaN, Infinity and -Infinity
841 if (str == kThriftNan) {
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100842 num = HUGE_VAL / HUGE_VAL; // generates NaN
843 } else if (str == kThriftInfinity) {
David Reissdb0ea152008-02-18 01:49:37 +0000844 num = HUGE_VAL;
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100845 } else if (str == kThriftNegativeInfinity) {
David Reissdb0ea152008-02-18 01:49:37 +0000846 num = -HUGE_VAL;
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100847 } else {
David Reissdb0ea152008-02-18 01:49:37 +0000848 if (!context_->escapeNum()) {
849 // Throw exception -- we should not be in a string in this case
850 throw new TProtocolException(TProtocolException::INVALID_DATA,
851 "Numeric data unexpectedly quoted");
852 }
853 try {
Konrad Grochowski12b06e42015-02-21 13:48:56 +0100854 num = stringToDouble(str);
855 } catch (std::runtime_error e) {
David Reissdb0ea152008-02-18 01:49:37 +0000856 throw new TProtocolException(TProtocolException::INVALID_DATA,
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100857 "Expected numeric value; got \"" + str + "\"");
David Reissdb0ea152008-02-18 01:49:37 +0000858 }
859 }
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100860 } else {
David Reissdb0ea152008-02-18 01:49:37 +0000861 if (context_->escapeNum()) {
862 // This will throw - we should have had a quote if escapeNum == true
863 readJSONSyntaxChar(kJSONStringDelimiter);
864 }
865 result += readJSONNumericChars(str);
866 try {
Konrad Grochowski12b06e42015-02-21 13:48:56 +0100867 num = stringToDouble(str);
868 } catch (std::runtime_error e) {
David Reissdb0ea152008-02-18 01:49:37 +0000869 throw new TProtocolException(TProtocolException::INVALID_DATA,
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100870 "Expected numeric value; got \"" + str + "\"");
David Reissdb0ea152008-02-18 01:49:37 +0000871 }
872 }
873 return result;
874}
875
876uint32_t TJSONProtocol::readJSONObjectStart() {
David Reiss1e62ab42008-02-21 22:37:45 +0000877 uint32_t result = context_->read(reader_);
David Reissdb0ea152008-02-18 01:49:37 +0000878 result += readJSONSyntaxChar(kJSONObjectStart);
879 pushContext(boost::shared_ptr<TJSONContext>(new JSONPairContext()));
880 return result;
881}
882
883uint32_t TJSONProtocol::readJSONObjectEnd() {
884 uint32_t result = readJSONSyntaxChar(kJSONObjectEnd);
885 popContext();
886 return result;
887}
888
889uint32_t TJSONProtocol::readJSONArrayStart() {
David Reiss1e62ab42008-02-21 22:37:45 +0000890 uint32_t result = context_->read(reader_);
David Reissdb0ea152008-02-18 01:49:37 +0000891 result += readJSONSyntaxChar(kJSONArrayStart);
892 pushContext(boost::shared_ptr<TJSONContext>(new JSONListContext()));
893 return result;
894}
895
896uint32_t TJSONProtocol::readJSONArrayEnd() {
897 uint32_t result = readJSONSyntaxChar(kJSONArrayEnd);
898 popContext();
899 return result;
900}
901
902uint32_t TJSONProtocol::readMessageBegin(std::string& name,
903 TMessageType& messageType,
904 int32_t& seqid) {
905 uint32_t result = readJSONArrayStart();
David Reissdb0ea152008-02-18 01:49:37 +0000906 uint64_t tmpVal = 0;
907 result += readJSONInteger(tmpVal);
908 if (tmpVal != kThriftVersion1) {
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100909 throw TProtocolException(TProtocolException::BAD_VERSION, "Message contained bad version.");
David Reissdb0ea152008-02-18 01:49:37 +0000910 }
911 result += readJSONString(name);
912 result += readJSONInteger(tmpVal);
913 messageType = (TMessageType)tmpVal;
914 result += readJSONInteger(tmpVal);
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100915 if (tmpVal > static_cast<uint64_t>((std::numeric_limits<int32_t>::max)()))
Roger Meierb69d24d2012-10-04 18:02:15 +0000916 throw TProtocolException(TProtocolException::SIZE_LIMIT);
917 seqid = static_cast<int32_t>(tmpVal);
David Reissdb0ea152008-02-18 01:49:37 +0000918 return result;
919}
920
921uint32_t TJSONProtocol::readMessageEnd() {
922 return readJSONArrayEnd();
923}
924
925uint32_t TJSONProtocol::readStructBegin(std::string& name) {
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100926 (void)name;
David Reissdb0ea152008-02-18 01:49:37 +0000927 return readJSONObjectStart();
928}
929
930uint32_t TJSONProtocol::readStructEnd() {
931 return readJSONObjectEnd();
932}
933
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100934uint32_t TJSONProtocol::readFieldBegin(std::string& name, TType& fieldType, int16_t& fieldId) {
935 (void)name;
David Reissdb0ea152008-02-18 01:49:37 +0000936 uint32_t result = 0;
David Reiss1e62ab42008-02-21 22:37:45 +0000937 // Check if we hit the end of the list
938 uint8_t ch = reader_.peek();
939 if (ch == kJSONObjectEnd) {
T Jake Lucianib5e62212009-01-31 22:36:20 +0000940 fieldType = apache::thrift::protocol::T_STOP;
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100941 } else {
David Reissdb0ea152008-02-18 01:49:37 +0000942 uint64_t tmpVal = 0;
943 std::string tmpStr;
944 result += readJSONInteger(tmpVal);
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100945 if (tmpVal > static_cast<uint32_t>((std::numeric_limits<int16_t>::max)()))
Roger Meierb69d24d2012-10-04 18:02:15 +0000946 throw TProtocolException(TProtocolException::SIZE_LIMIT);
947 fieldId = static_cast<int16_t>(tmpVal);
David Reissdb0ea152008-02-18 01:49:37 +0000948 result += readJSONObjectStart();
949 result += readJSONString(tmpStr);
950 fieldType = getTypeIDForTypeName(tmpStr);
951 }
952 return result;
953}
954
955uint32_t TJSONProtocol::readFieldEnd() {
956 return readJSONObjectEnd();
957}
958
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100959uint32_t TJSONProtocol::readMapBegin(TType& keyType, TType& valType, uint32_t& size) {
David Reissdb0ea152008-02-18 01:49:37 +0000960 uint64_t tmpVal = 0;
961 std::string tmpStr;
962 uint32_t result = readJSONArrayStart();
963 result += readJSONString(tmpStr);
964 keyType = getTypeIDForTypeName(tmpStr);
965 result += readJSONString(tmpStr);
966 valType = getTypeIDForTypeName(tmpStr);
967 result += readJSONInteger(tmpVal);
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100968 if (tmpVal > (std::numeric_limits<uint32_t>::max)())
Roger Meierb69d24d2012-10-04 18:02:15 +0000969 throw TProtocolException(TProtocolException::SIZE_LIMIT);
970 size = static_cast<uint32_t>(tmpVal);
David Reissdb0ea152008-02-18 01:49:37 +0000971 result += readJSONObjectStart();
972 return result;
973}
974
975uint32_t TJSONProtocol::readMapEnd() {
976 return readJSONObjectEnd() + readJSONArrayEnd();
977}
978
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100979uint32_t TJSONProtocol::readListBegin(TType& elemType, uint32_t& size) {
David Reissdb0ea152008-02-18 01:49:37 +0000980 uint64_t tmpVal = 0;
981 std::string tmpStr;
982 uint32_t result = readJSONArrayStart();
983 result += readJSONString(tmpStr);
984 elemType = getTypeIDForTypeName(tmpStr);
985 result += readJSONInteger(tmpVal);
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100986 if (tmpVal > (std::numeric_limits<uint32_t>::max)())
Roger Meierb69d24d2012-10-04 18:02:15 +0000987 throw TProtocolException(TProtocolException::SIZE_LIMIT);
988 size = static_cast<uint32_t>(tmpVal);
David Reissdb0ea152008-02-18 01:49:37 +0000989 return result;
990}
991
992uint32_t TJSONProtocol::readListEnd() {
993 return readJSONArrayEnd();
994}
995
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100996uint32_t TJSONProtocol::readSetBegin(TType& elemType, uint32_t& size) {
David Reissdb0ea152008-02-18 01:49:37 +0000997 uint64_t tmpVal = 0;
998 std::string tmpStr;
999 uint32_t result = readJSONArrayStart();
1000 result += readJSONString(tmpStr);
1001 elemType = getTypeIDForTypeName(tmpStr);
1002 result += readJSONInteger(tmpVal);
Konrad Grochowski16a23a62014-11-13 15:33:38 +01001003 if (tmpVal > (std::numeric_limits<uint32_t>::max)())
Roger Meierb69d24d2012-10-04 18:02:15 +00001004 throw TProtocolException(TProtocolException::SIZE_LIMIT);
1005 size = static_cast<uint32_t>(tmpVal);
David Reissdb0ea152008-02-18 01:49:37 +00001006 return result;
1007}
1008
1009uint32_t TJSONProtocol::readSetEnd() {
1010 return readJSONArrayEnd();
1011}
1012
1013uint32_t TJSONProtocol::readBool(bool& value) {
1014 return readJSONInteger(value);
1015}
1016
Konrad Grochowski3b5dacb2014-11-24 10:55:31 +01001017// readByte() must be handled properly because boost::lexical cast sees int8_t
David Reissdb0ea152008-02-18 01:49:37 +00001018// as a text type instead of an integer type
1019uint32_t TJSONProtocol::readByte(int8_t& byte) {
Konrad Grochowski16a23a62014-11-13 15:33:38 +01001020 int16_t tmp = (int16_t)byte;
1021 uint32_t result = readJSONInteger(tmp);
David Reissdb0ea152008-02-18 01:49:37 +00001022 assert(tmp < 256);
1023 byte = (int8_t)tmp;
1024 return result;
1025}
1026
1027uint32_t TJSONProtocol::readI16(int16_t& i16) {
1028 return readJSONInteger(i16);
1029}
1030
1031uint32_t TJSONProtocol::readI32(int32_t& i32) {
1032 return readJSONInteger(i32);
1033}
1034
1035uint32_t TJSONProtocol::readI64(int64_t& i64) {
1036 return readJSONInteger(i64);
1037}
1038
1039uint32_t TJSONProtocol::readDouble(double& dub) {
1040 return readJSONDouble(dub);
1041}
1042
Konrad Grochowski16a23a62014-11-13 15:33:38 +01001043uint32_t TJSONProtocol::readString(std::string& str) {
David Reissdb0ea152008-02-18 01:49:37 +00001044 return readJSONString(str);
1045}
1046
Konrad Grochowski16a23a62014-11-13 15:33:38 +01001047uint32_t TJSONProtocol::readBinary(std::string& str) {
David Reissdb0ea152008-02-18 01:49:37 +00001048 return readJSONBase64(str);
1049}
Konrad Grochowski16a23a62014-11-13 15:33:38 +01001050}
1051}
1052} // apache::thrift::protocol