Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-04-17 08:35:02

0001 /*
0002  * Licensed to the Apache Software Foundation (ASF) under one
0003  * or more contributor license agreements. See the NOTICE file
0004  * distributed with this work for additional information
0005  * regarding copyright ownership. The ASF licenses this file
0006  * to you under the Apache License, Version 2.0 (the
0007  * "License"); you may not use this file except in compliance
0008  * with the License. You may obtain a copy of the License at
0009  *
0010  *   http://www.apache.org/licenses/LICENSE-2.0
0011  *
0012  * Unless required by applicable law or agreed to in writing,
0013  * software distributed under the License is distributed on an
0014  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
0015  * KIND, either express or implied. See the License for the
0016  * specific language governing permissions and limitations
0017  * under the License.
0018  */
0019 
0020 #ifndef _THRIFT_PROTOCOL_TJSONPROTOCOL_H_
0021 #define _THRIFT_PROTOCOL_TJSONPROTOCOL_H_ 1
0022 
0023 #include <thrift/protocol/TVirtualProtocol.h>
0024 
0025 #include <stack>
0026 
0027 namespace apache {
0028 namespace thrift {
0029 namespace protocol {
0030 
0031 // Forward declaration
0032 class TJSONContext;
0033 
0034 /**
0035  * JSON protocol for Thrift.
0036  *
0037  * Implements a protocol which uses JSON as the wire-format.
0038  *
0039  * Thrift types are represented as described below:
0040  *
0041  * 1. Every Thrift integer type is represented as a JSON number.
0042  *
0043  * 2. Thrift doubles are represented as JSON numbers. Some special values are
0044  *    represented as strings:
0045  *    a. "NaN" for not-a-number values
0046  *    b. "Infinity" for positive infinity
0047  *    c. "-Infinity" for negative infinity
0048  *
0049  * 3. Thrift string values are emitted as JSON strings, with appropriate
0050  *    escaping.
0051  *
0052  * 4. Thrift binary values are encoded into Base64 and emitted as JSON strings.
0053  *    The readBinary() method is written such that it will properly skip if
0054  *    called on a Thrift string (although it will decode garbage data).
0055  *
0056  *    NOTE: Base64 padding is optional for Thrift binary value encoding. So
0057  *    the readBinary() method needs to decode both input strings with padding
0058  *    and those without one.
0059  *
0060  * 5. Thrift structs are represented as JSON objects, with the field ID as the
0061  *    key, and the field value represented as a JSON object with a single
0062  *    key-value pair. The key is a short string identifier for that type,
0063  *    followed by the value. The valid type identifiers are: "tf" for bool,
0064  *    "i8" for byte, "i16" for 16-bit integer, "i32" for 32-bit integer, "i64"
0065  *    for 64-bit integer, "dbl" for double-precision loating point, "str" for
0066  *    string (including binary), "rec" for struct ("records"), "map" for map,
0067  *    "lst" for list, "set" for set.
0068  *
0069  * 6. Thrift lists and sets are represented as JSON arrays, with the first
0070  *    element of the JSON array being the string identifier for the Thrift
0071  *    element type and the second element of the JSON array being the count of
0072  *    the Thrift elements. The Thrift elements then follow.
0073  *
0074  * 7. Thrift maps are represented as JSON arrays, with the first two elements
0075  *    of the JSON array being the string identifiers for the Thrift key type
0076  *    and value type, followed by the count of the Thrift pairs, followed by a
0077  *    JSON object containing the key-value pairs. Note that JSON keys can only
0078  *    be strings, which means that the key type of the Thrift map should be
0079  *    restricted to numeric or string types -- in the case of numerics, they
0080  *    are serialized as strings.
0081  *
0082  * 8. Thrift messages are represented as JSON arrays, with the protocol
0083  *    version #, the message name, the message type, and the sequence ID as
0084  *    the first 4 elements.
0085  *
0086  * More discussion of the double handling is probably warranted. The aim of
0087  * the current implementation is to match as closely as possible the behavior
0088  * of Java's Double.toString(), which has no precision loss.  Implementors in
0089  * other languages should strive to achieve that where possible. I have not
0090  * yet verified whether std::istringstream::operator>>, which is doing that
0091  * work for me in C++, loses any precision, but I am leaving this as a future
0092  * improvement. I may try to provide a C component for this, so that other
0093  * languages could bind to the same underlying implementation for maximum
0094  * consistency.
0095  *
0096  */
0097 class TJSONProtocol : public TVirtualProtocol<TJSONProtocol> {
0098 public:
0099   TJSONProtocol(std::shared_ptr<TTransport> ptrans);
0100 
0101   ~TJSONProtocol() override;
0102 
0103 private:
0104   void pushContext(std::shared_ptr<TJSONContext> c);
0105 
0106   void popContext();
0107 
0108   uint32_t writeJSONEscapeChar(uint8_t ch);
0109 
0110   uint32_t writeJSONChar(uint8_t ch);
0111 
0112   uint32_t writeJSONString(const std::string& str);
0113 
0114   uint32_t writeJSONBase64(const std::string& str);
0115 
0116   template <typename NumberType>
0117   uint32_t writeJSONInteger(NumberType num);
0118 
0119   uint32_t writeJSONDouble(double num);
0120 
0121   uint32_t writeJSONObjectStart();
0122 
0123   uint32_t writeJSONObjectEnd();
0124 
0125   uint32_t writeJSONArrayStart();
0126 
0127   uint32_t writeJSONArrayEnd();
0128 
0129   uint32_t readJSONSyntaxChar(uint8_t ch);
0130 
0131   uint32_t readJSONEscapeChar(uint16_t* out);
0132 
0133   uint32_t readJSONString(std::string& str, bool skipContext = false);
0134 
0135   uint32_t readJSONBase64(std::string& str);
0136 
0137   uint32_t readJSONNumericChars(std::string& str);
0138 
0139   template <typename NumberType>
0140   uint32_t readJSONInteger(NumberType& num);
0141 
0142   uint32_t readJSONDouble(double& num);
0143 
0144   uint32_t readJSONObjectStart();
0145 
0146   uint32_t readJSONObjectEnd();
0147 
0148   uint32_t readJSONArrayStart();
0149 
0150   uint32_t readJSONArrayEnd();
0151 
0152 public:
0153   /**
0154    * Writing functions.
0155    */
0156 
0157   uint32_t writeMessageBegin(const std::string& name,
0158                              const TMessageType messageType,
0159                              const int32_t seqid);
0160 
0161   uint32_t writeMessageEnd();
0162 
0163   uint32_t writeStructBegin(const char* name);
0164 
0165   uint32_t writeStructEnd();
0166 
0167   uint32_t writeFieldBegin(const char* name, const TType fieldType, const int16_t fieldId);
0168 
0169   uint32_t writeFieldEnd();
0170 
0171   uint32_t writeFieldStop();
0172 
0173   uint32_t writeMapBegin(const TType keyType, const TType valType, const uint32_t size);
0174 
0175   uint32_t writeMapEnd();
0176 
0177   uint32_t writeListBegin(const TType elemType, const uint32_t size);
0178 
0179   uint32_t writeListEnd();
0180 
0181   uint32_t writeSetBegin(const TType elemType, const uint32_t size);
0182 
0183   uint32_t writeSetEnd();
0184 
0185   uint32_t writeBool(const bool value);
0186 
0187   uint32_t writeByte(const int8_t byte);
0188 
0189   uint32_t writeI16(const int16_t i16);
0190 
0191   uint32_t writeI32(const int32_t i32);
0192 
0193   uint32_t writeI64(const int64_t i64);
0194 
0195   uint32_t writeDouble(const double dub);
0196 
0197   uint32_t writeString(const std::string& str);
0198 
0199   uint32_t writeBinary(const std::string& str);
0200 
0201   uint32_t writeUUID(const TUuid& uuid);
0202 
0203   /**
0204    * Reading functions
0205    */
0206 
0207   uint32_t readMessageBegin(std::string& name, TMessageType& messageType, int32_t& seqid);
0208 
0209   uint32_t readMessageEnd();
0210 
0211   uint32_t readStructBegin(std::string& name);
0212 
0213   uint32_t readStructEnd();
0214 
0215   uint32_t readFieldBegin(std::string& name, TType& fieldType, int16_t& fieldId);
0216 
0217   uint32_t readFieldEnd();
0218 
0219   uint32_t readMapBegin(TType& keyType, TType& valType, uint32_t& size);
0220 
0221   uint32_t readMapEnd();
0222 
0223   uint32_t readListBegin(TType& elemType, uint32_t& size);
0224 
0225   uint32_t readListEnd();
0226 
0227   uint32_t readSetBegin(TType& elemType, uint32_t& size);
0228 
0229   uint32_t readSetEnd();
0230 
0231   uint32_t readBool(bool& value);
0232 
0233   // Provide the default readBool() implementation for std::vector<bool>
0234   using TVirtualProtocol<TJSONProtocol>::readBool;
0235 
0236   uint32_t readByte(int8_t& byte);
0237 
0238   uint32_t readI16(int16_t& i16);
0239 
0240   uint32_t readI32(int32_t& i32);
0241 
0242   uint32_t readI64(int64_t& i64);
0243 
0244   uint32_t readDouble(double& dub);
0245 
0246   uint32_t readString(std::string& str);
0247 
0248   uint32_t readBinary(std::string& str);
0249 
0250   uint32_t readUUID(TUuid& uuid);
0251 
0252   int getMinSerializedSize(TType type) override;
0253 
0254   void checkReadBytesAvailable(TSet& set) override
0255   {
0256       trans_->checkReadBytesAvailable(set.size_ * getMinSerializedSize(set.elemType_));
0257   }
0258 
0259   void checkReadBytesAvailable(TList& list) override
0260   {
0261       trans_->checkReadBytesAvailable(list.size_ * getMinSerializedSize(list.elemType_));
0262   }
0263 
0264   void checkReadBytesAvailable(TMap& map) override
0265   {
0266       int elmSize = getMinSerializedSize(map.keyType_) + getMinSerializedSize(map.valueType_);
0267       trans_->checkReadBytesAvailable(map.size_ * elmSize);
0268   }
0269 
0270   class LookaheadReader {
0271 
0272   public:
0273     LookaheadReader(TTransport& trans) : trans_(&trans), hasData_(false), data_(0) {}
0274 
0275     uint8_t read() {
0276       if (hasData_) {
0277         hasData_ = false;
0278       } else {
0279         trans_->readAll(&data_, 1);
0280       }
0281       return data_;
0282     }
0283 
0284     uint8_t peek() {
0285       if (!hasData_) {
0286         trans_->readAll(&data_, 1);
0287       }
0288       hasData_ = true;
0289       return data_;
0290     }
0291 
0292   private:
0293     TTransport* trans_;
0294     bool hasData_;
0295     uint8_t data_;
0296   };
0297 
0298 private:
0299   TTransport* trans_;
0300 
0301   std::stack<std::shared_ptr<TJSONContext> > contexts_;
0302   std::shared_ptr<TJSONContext> context_;
0303   LookaheadReader reader_;
0304 };
0305 
0306 /**
0307  * Constructs input and output protocol objects given transports.
0308  */
0309 class TJSONProtocolFactory : public TProtocolFactory {
0310 public:
0311   TJSONProtocolFactory() = default;
0312 
0313   ~TJSONProtocolFactory() override = default;
0314 
0315   std::shared_ptr<TProtocol> getProtocol(std::shared_ptr<TTransport> trans) override {
0316     return std::shared_ptr<TProtocol>(new TJSONProtocol(trans));
0317   }
0318 };
0319 }
0320 }
0321 } // apache::thrift::protocol
0322 
0323 // TODO(dreiss): Move part of ThriftJSONString into a .cpp file and remove this.
0324 #include <thrift/transport/TBufferTransports.h>
0325 
0326 namespace apache {
0327 namespace thrift {
0328 
0329 template <typename ThriftStruct>
0330 std::string ThriftJSONString(const ThriftStruct& ts) {
0331   using namespace apache::thrift::transport;
0332   using namespace apache::thrift::protocol;
0333   auto* buffer = new TMemoryBuffer;
0334   std::shared_ptr<TTransport> trans(buffer);
0335   TJSONProtocol protocol(trans);
0336 
0337   ts.write(&protocol);
0338 
0339   uint8_t* buf;
0340   uint32_t size;
0341   buffer->getBuffer(&buf, &size);
0342   return std::string((char*)buf, (unsigned int)size);
0343 }
0344 }
0345 } // apache::thrift
0346 
0347 #endif // #define _THRIFT_PROTOCOL_TJSONPROTOCOL_H_ 1