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
diff --git a/compiler/cpp/src/generate/t_cpp_generator.cc b/compiler/cpp/src/generate/t_cpp_generator.cc
index 6218b0c..2fa1ccd 100644
--- a/compiler/cpp/src/generate/t_cpp_generator.cc
+++ b/compiler/cpp/src/generate/t_cpp_generator.cc
@@ -559,9 +559,9 @@
<< "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 32dc90b..23a006a 100644
--- a/compiler/cpp/src/parse/t_list.h
+++ b/compiler/cpp/src/parse/t_list.h
@@ -31,6 +31,11 @@
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 8876858..b5e051e 100644
--- a/compiler/cpp/src/parse/t_map.h
+++ b/compiler/cpp/src/parse/t_map.h
@@ -38,6 +38,12 @@
"," + 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 68a0029..c52421a 100644
--- a/compiler/cpp/src/parse/t_set.h
+++ b/compiler/cpp/src/parse/t_set.h
@@ -31,6 +31,11 @@
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 ad12677..d296473 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 @@
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<t_field*>::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<t_field*> 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 44f7cc8..0a6fbbc 100644
--- a/compiler/cpp/src/parse/t_type.h
+++ b/compiler/cpp/src/parse/t_type.h
@@ -10,6 +10,9 @@
#include <string>
#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 @@
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 @@
t_program* program_;
std::string name_;
+ uint8_t fingerprint_[fingerprint_len];
};
#endif