Thrift now a TLP - INFRA-3116

git-svn-id: https://svn.apache.org/repos/asf/thrift/branches/0.1.x@1028168 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/lib/cpp/src/protocol/TDenseProtocol.h b/lib/cpp/src/protocol/TDenseProtocol.h
new file mode 100644
index 0000000..7655a47
--- /dev/null
+++ b/lib/cpp/src/protocol/TDenseProtocol.h
@@ -0,0 +1,253 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#ifndef _THRIFT_PROTOCOL_TDENSEPROTOCOL_H_
+#define _THRIFT_PROTOCOL_TDENSEPROTOCOL_H_ 1
+
+#include "TBinaryProtocol.h"
+
+namespace apache { namespace thrift { namespace protocol {
+
+/**
+ * !!!WARNING!!!
+ * This class is still highly experimental.  Incompatible changes
+ * WILL be made to it without notice.  DO NOT USE IT YET unless
+ * you are coordinating your testing with the author.
+ *
+ * The dense protocol is designed to use as little space as possible.
+ *
+ * There are two types of dense protocol instances.  Standalone instances
+ * are not used for RPC and just encoded and decode structures of
+ * a predetermined type.  Non-standalone instances are used for RPC.
+ * Currently, only standalone instances exist.
+ *
+ * To use a standalone dense protocol object, you must set the type_spec
+ * property (either in the constructor, or with setTypeSpec) to the local
+ * reflection TypeSpec of the structures you will write to (or read from) the
+ * protocol instance.
+ *
+ * BEST PRACTICES:
+ * - Never use optional for primitives or containers.
+ * - Only use optional for structures if they are very big and very rarely set.
+ * - All integers are variable-length, so you can use i64 without bloating.
+ * - NEVER EVER change the struct definitions IN ANY WAY without either
+ *   changing your cache keys or talking to dreiss.
+ *
+ * TODO(dreiss): New class write with old meta.
+ *
+ * We override all of TBinaryProtocol's methods.
+ * We inherit so that we can can explicitly call TBPs's primitive-writing
+ * methods within our versions.
+ *
+ */
+class TDenseProtocol : public TBinaryProtocol {
+ protected:
+  static const int32_t VERSION_MASK = 0xffff0000;
+  // VERSION_1 (0x80010000)  is taken by TBinaryProtocol.
+  static const int32_t VERSION_2 = 0x80020000;
+
+ public:
+  typedef apache::thrift::reflection::local::TypeSpec TypeSpec;
+  static const int FP_PREFIX_LEN;
+
+  /**
+   * @param tran       The transport to use.
+   * @param type_spec  The TypeSpec of the structures using this protocol.
+   */
+  TDenseProtocol(boost::shared_ptr<TTransport> trans,
+                 TypeSpec* type_spec = NULL) :
+    TBinaryProtocol(trans),
+    type_spec_(type_spec),
+    standalone_(true)
+  {}
+
+  void setTypeSpec(TypeSpec* type_spec) {
+    type_spec_ = type_spec;
+  }
+  TypeSpec* getTypeSpec() {
+    return type_spec_;
+  }
+
+
+  /*
+   * Writing functions.
+   */
+
+  virtual uint32_t writeMessageBegin(const std::string& name,
+                                     const TMessageType messageType,
+                                     const int32_t seqid);
+
+  virtual uint32_t writeMessageEnd();
+
+
+  virtual uint32_t writeStructBegin(const char* name);
+
+  virtual uint32_t writeStructEnd();
+
+  virtual uint32_t writeFieldBegin(const char* name,
+                                   const TType fieldType,
+                                   const int16_t fieldId);
+
+  virtual uint32_t writeFieldEnd();
+
+  virtual uint32_t writeFieldStop();
+
+  virtual uint32_t writeMapBegin(const TType keyType,
+                                 const TType valType,
+                                 const uint32_t size);
+
+  virtual uint32_t writeMapEnd();
+
+  virtual uint32_t writeListBegin(const TType elemType,
+                                  const uint32_t size);
+
+  virtual uint32_t writeListEnd();
+
+  virtual uint32_t writeSetBegin(const TType elemType,
+                                 const uint32_t size);
+
+  virtual uint32_t writeSetEnd();
+
+  virtual uint32_t writeBool(const bool value);
+
+  virtual uint32_t writeByte(const int8_t byte);
+
+  virtual uint32_t writeI16(const int16_t i16);
+
+  virtual uint32_t writeI32(const int32_t i32);
+
+  virtual uint32_t writeI64(const int64_t i64);
+
+  virtual uint32_t writeDouble(const double dub);
+
+  virtual uint32_t writeString(const std::string& str);
+
+  virtual uint32_t writeBinary(const std::string& str);
+
+
+  /*
+   * Helper writing functions (don't do state transitions).
+   */
+  inline uint32_t subWriteI32(const int32_t i32);
+
+  inline uint32_t subWriteString(const std::string& str);
+
+  uint32_t subWriteBool(const bool value) {
+    return TBinaryProtocol::writeBool(value);
+  }
+
+
+  /*
+   * Reading functions
+   */
+
+  uint32_t readMessageBegin(std::string& name,
+                            TMessageType& messageType,
+                            int32_t& seqid);
+
+  uint32_t readMessageEnd();
+
+  uint32_t readStructBegin(std::string& name);
+
+  uint32_t readStructEnd();
+
+  uint32_t readFieldBegin(std::string& name,
+                          TType& fieldType,
+                          int16_t& fieldId);
+
+  uint32_t readFieldEnd();
+
+  uint32_t readMapBegin(TType& keyType,
+                        TType& valType,
+                        uint32_t& size);
+
+  uint32_t readMapEnd();
+
+  uint32_t readListBegin(TType& elemType,
+                         uint32_t& size);
+
+  uint32_t readListEnd();
+
+  uint32_t readSetBegin(TType& elemType,
+                        uint32_t& size);
+
+  uint32_t readSetEnd();
+
+  uint32_t readBool(bool& value);
+
+  uint32_t readByte(int8_t& byte);
+
+  uint32_t readI16(int16_t& i16);
+
+  uint32_t readI32(int32_t& i32);
+
+  uint32_t readI64(int64_t& i64);
+
+  uint32_t readDouble(double& dub);
+
+  uint32_t readString(std::string& str);
+
+  uint32_t readBinary(std::string& str);
+
+  /*
+   * Helper reading functions (don't do state transitions).
+   */
+  inline uint32_t subReadI32(int32_t& i32);
+
+  inline uint32_t subReadString(std::string& str);
+
+  uint32_t subReadBool(bool& value) {
+    return TBinaryProtocol::readBool(value);
+  }
+
+
+ private:
+
+  // Implementation functions, documented in the .cpp.
+  inline void checkTType(const TType ttype);
+  inline void stateTransition();
+
+  // Read and write variable-length integers.
+  // Uses the same technique as the MIDI file format.
+  inline uint32_t vlqRead(uint64_t& vlq);
+  inline uint32_t vlqWrite(uint64_t vlq);
+
+  // Called before throwing an exception to make the object reusable.
+  void resetState() {
+    ts_stack_.clear();
+    idx_stack_.clear();
+    mkv_stack_.clear();
+  }
+
+  // TypeSpec of the top-level structure to write,
+  // for standalone protocol objects.
+  TypeSpec* type_spec_;
+
+  std::vector<TypeSpec*> ts_stack_;   // TypeSpec stack.
+  std::vector<int>       idx_stack_;  // InDeX stack.
+  std::vector<bool>      mkv_stack_;  // Map Key/Vlue stack.
+                                      // True = key, False = value.
+
+  // True iff this is a standalone instance (no RPC).
+  bool standalone_;
+};
+
+}}} // apache::thrift::protocol
+
+#endif // #ifndef _THRIFT_PROTOCOL_TDENSEPROTOCOL_H_