From 9885c6801dbd3b49591ea69544fdb03b1ce43642 Mon Sep 17 00:00:00 2001 From: David Reiss Date: Thu, 30 Aug 2007 23:12:37 +0000 Subject: [PATCH] Thrift: Generate fingerprints for non-structs. Summary: This is going to be needed to support TDenseProtocol. Reviewed By: mcslee Test Plan: Clean build of Thrift. Ran if/regen.sh. No change to generated C++ or Python. gdb thrift -cpp ThriftTest.thrift. Made sure they were being generated. Revert Plan: ok git-svn-id: https://svn.apache.org/repos/asf/incubator/thrift/trunk@665237 13f79535-47bb-0310-9956-ffa450edef68 --- compiler/cpp/src/generate/t_cpp_generator.cc | 4 +- compiler/cpp/src/parse/t_list.h | 5 ++ compiler/cpp/src/parse/t_map.h | 6 ++ compiler/cpp/src/parse/t_set.h | 5 ++ compiler/cpp/src/parse/t_struct.h | 62 ++------------------ compiler/cpp/src/parse/t_type.h | 62 ++++++++++++++++++++ 6 files changed, 85 insertions(+), 59 deletions(-) diff --git a/compiler/cpp/src/generate/t_cpp_generator.cc b/compiler/cpp/src/generate/t_cpp_generator.cc index 6218b0cb..2fa1ccdc 100644 --- a/compiler/cpp/src/generate/t_cpp_generator.cc +++ b/compiler/cpp/src/generate/t_cpp_generator.cc @@ -559,9 +559,9 @@ void t_cpp_generator::generate_struct_fingerprint(ofstream& out, << "ascii_fingerprint" << comment << "= \"" << tstruct->get_ascii_fingerprint() << "\";" << endl << indent() << stat << "char " << nspace << - "binary_fingerprint[" << t_struct::fingerprint_len << "]" << comment << "= {"; + "binary_fingerprint[" << t_type::fingerprint_len << "]" << comment << "= {"; char* comma = ""; - for (int i = 0; i < t_struct::fingerprint_len; i++) { + for (int i = 0; i < t_type::fingerprint_len; i++) { out << comma << "0x" << t_struct::byte_to_hex(tstruct->get_binary_fingerprint()[i]); comma = ","; } diff --git a/compiler/cpp/src/parse/t_list.h b/compiler/cpp/src/parse/t_list.h index 32dc90b6..23a006ab 100644 --- a/compiler/cpp/src/parse/t_list.h +++ b/compiler/cpp/src/parse/t_list.h @@ -31,6 +31,11 @@ class t_list : public t_container { return "list<" + elem_type_->get_fingerprint_material() + ">"; } + virtual void generate_fingerprint() { + t_type::generate_fingerprint(); + elem_type_->generate_fingerprint(); + } + private: t_type* elem_type_; }; diff --git a/compiler/cpp/src/parse/t_map.h b/compiler/cpp/src/parse/t_map.h index 8876858c..b5e051e8 100644 --- a/compiler/cpp/src/parse/t_map.h +++ b/compiler/cpp/src/parse/t_map.h @@ -38,6 +38,12 @@ class t_map : public t_container { "," + val_type_->get_fingerprint_material() + ">"; } + virtual void generate_fingerprint() { + t_type::generate_fingerprint(); + key_type_->generate_fingerprint(); + val_type_->generate_fingerprint(); + } + private: t_type* key_type_; t_type* val_type_; diff --git a/compiler/cpp/src/parse/t_set.h b/compiler/cpp/src/parse/t_set.h index 68a00298..c52421ae 100644 --- a/compiler/cpp/src/parse/t_set.h +++ b/compiler/cpp/src/parse/t_set.h @@ -31,6 +31,11 @@ class t_set : public t_container { return "set<" + elem_type_->get_fingerprint_material() + ">"; } + virtual void generate_fingerprint() { + t_type::generate_fingerprint(); + elem_type_->generate_fingerprint(); + } + private: t_type* elem_type_; }; diff --git a/compiler/cpp/src/parse/t_struct.h b/compiler/cpp/src/parse/t_struct.h index ad126778..d296473f 100644 --- a/compiler/cpp/src/parse/t_struct.h +++ b/compiler/cpp/src/parse/t_struct.h @@ -14,9 +14,6 @@ #include "t_type.h" #include "t_field.h" -// What's worse? This, or making a src/parse/non_inlined.cc? -#include "md5.h" - // Forward declare that puppy class t_program; @@ -87,69 +84,20 @@ class t_struct : public t_type { return rv; } - // Fingerprint should change whenever (and only when) - // the encoding via TDenseProtocol changes. - static const int fingerprint_len = 16; - - // Call this before trying get_*_fingerprint(). - void generate_fingerprint() { - std::string material = get_fingerprint_material(); - MD5_CTX ctx; - MD5Init(&ctx); - MD5Update(&ctx, (unsigned char*)(material.data()), material.size()); - MD5Final(fingerprint_, &ctx); - //std::cout << get_name() << std::endl; - //std::cout << material << std::endl; - //std::cout << get_ascii_fingerprint() << std::endl << std::endl; - } - - bool has_fingerprint() const { - for (int i = 0; i < fingerprint_len; i++) { - if (fingerprint_[i] != 0) { - return true; - } - } - return false; - } - - const uint8_t* get_binary_fingerprint() const { - return fingerprint_; - } - - std::string get_ascii_fingerprint() const { - std::string rv; - const uint8_t* fp = get_binary_fingerprint(); - for (int i = 0; i < fingerprint_len; i++) { - rv += byte_to_hex(fp[i]); - } - return rv; - } - - // This function will break (maybe badly) unless 0 <= num <= 16. - static char nybble_to_xdigit(int num) { - if (num < 10) { - return '0' + num; - } else { - return 'A' + num - 10; + virtual void generate_fingerprint() { + t_type::generate_fingerprint(); + std::vector::const_iterator m_iter; + for (m_iter = members_.begin(); m_iter != members_.end(); ++m_iter) { + (**m_iter).get_type()->generate_fingerprint(); } } - static std::string byte_to_hex(uint8_t byte) { - std::string rv; - rv += nybble_to_xdigit(byte >> 4); - rv += nybble_to_xdigit(byte & 0x0f); - return rv; - } - - private: std::vector members_; bool is_xception_; bool xsd_all_; - - uint8_t fingerprint_[fingerprint_len]; }; #endif diff --git a/compiler/cpp/src/parse/t_type.h b/compiler/cpp/src/parse/t_type.h index 44f7cc81..0a6fbbc0 100644 --- a/compiler/cpp/src/parse/t_type.h +++ b/compiler/cpp/src/parse/t_type.h @@ -10,6 +10,9 @@ #include #include "t_doc.h" +// What's worse? This, or making a src/parse/non_inlined.cc? +#include "md5.h" + class t_program; /** @@ -50,11 +53,69 @@ class t_type : public t_doc { return program_; } + // Return a string that uniquely identifies this type // from any other thrift type in the world, as far as // TDenseProtocol is concerned. + // We don't cache this, which is a little sloppy, + // but the compiler is so fast that it doesn't really matter. virtual std::string get_fingerprint_material() const = 0; + // Fingerprint should change whenever (and only when) + // the encoding via TDenseProtocol changes. + static const int fingerprint_len = 16; + + // Call this before trying get_*_fingerprint(). + virtual void generate_fingerprint() { + std::string material = get_fingerprint_material(); + MD5_CTX ctx; + MD5Init(&ctx); + MD5Update(&ctx, (unsigned char*)(material.data()), material.size()); + MD5Final(fingerprint_, &ctx); + //std::cout << get_name() << std::endl; + //std::cout << material << std::endl; + //std::cout << get_ascii_fingerprint() << std::endl << std::endl; + } + + bool has_fingerprint() const { + for (int i = 0; i < fingerprint_len; i++) { + if (fingerprint_[i] != 0) { + return true; + } + } + return false; + } + + const uint8_t* get_binary_fingerprint() const { + return fingerprint_; + } + + std::string get_ascii_fingerprint() const { + std::string rv; + const uint8_t* fp = get_binary_fingerprint(); + for (int i = 0; i < fingerprint_len; i++) { + rv += byte_to_hex(fp[i]); + } + return rv; + } + + // This function will break (maybe badly) unless 0 <= num <= 16. + static char nybble_to_xdigit(int num) { + if (num < 10) { + return '0' + num; + } else { + return 'A' + num - 10; + } + } + + static std::string byte_to_hex(uint8_t byte) { + std::string rv; + rv += nybble_to_xdigit(byte >> 4); + rv += nybble_to_xdigit(byte & 0x0f); + return rv; + } + + protected: t_type() {} @@ -71,6 +132,7 @@ class t_type : public t_doc { t_program* program_; std::string name_; + uint8_t fingerprint_[fingerprint_len]; }; #endif -- 2.17.1