| Mark Slee | e9ce01c | 2007-05-16 02:29:53 +0000 | [diff] [blame] | 1 | // Copyright (c) 2006- Facebook | 
|  | 2 | // Distributed under the Thrift Software License | 
|  | 3 | // | 
|  | 4 | // See accompanying file LICENSE or visit the Thrift site at: | 
|  | 5 | // http://developers.facebook.com/thrift/ | 
|  | 6 |  | 
| Mark Slee | 3198572 | 2006-05-24 21:45:31 +0000 | [diff] [blame] | 7 | #ifndef T_STRUCT_H | 
|  | 8 | #define T_STRUCT_H | 
|  | 9 |  | 
|  | 10 | #include <vector> | 
|  | 11 | #include <string> | 
| David Reiss | 18bf22d | 2007-08-28 20:49:17 +0000 | [diff] [blame] | 12 | #include <cstring> | 
| Mark Slee | 3198572 | 2006-05-24 21:45:31 +0000 | [diff] [blame] | 13 |  | 
|  | 14 | #include "t_type.h" | 
| Mark Slee | e854063 | 2006-05-30 09:24:40 +0000 | [diff] [blame] | 15 | #include "t_field.h" | 
| Mark Slee | 3198572 | 2006-05-24 21:45:31 +0000 | [diff] [blame] | 16 |  | 
| David Reiss | 18bf22d | 2007-08-28 20:49:17 +0000 | [diff] [blame] | 17 | // What's worse?  This, or making a src/parse/non_inlined.cc? | 
|  | 18 | #include "md5.h" | 
|  | 19 |  | 
| Mark Slee | f0712dc | 2006-10-25 19:03:57 +0000 | [diff] [blame] | 20 | // Forward declare that puppy | 
|  | 21 | class t_program; | 
|  | 22 |  | 
| Mark Slee | f5377b3 | 2006-10-10 01:42:59 +0000 | [diff] [blame] | 23 | /** | 
|  | 24 | * A struct is a container for a set of member fields that has a name. Structs | 
|  | 25 | * are also used to implement exception types. | 
|  | 26 | * | 
|  | 27 | * @author Mark Slee <mcslee@facebook.com> | 
|  | 28 | */ | 
| Mark Slee | 3198572 | 2006-05-24 21:45:31 +0000 | [diff] [blame] | 29 | class t_struct : public t_type { | 
|  | 30 | public: | 
| Mark Slee | f0712dc | 2006-10-25 19:03:57 +0000 | [diff] [blame] | 31 | t_struct(t_program* program) : | 
|  | 32 | t_type(program), | 
| Mark Slee | 782abbb | 2007-01-19 00:17:02 +0000 | [diff] [blame] | 33 | is_xception_(false), | 
| David Reiss | 18bf22d | 2007-08-28 20:49:17 +0000 | [diff] [blame] | 34 | xsd_all_(false) | 
|  | 35 | { | 
|  | 36 | memset(fingerprint_, 0, sizeof(fingerprint_)); | 
|  | 37 | } | 
| Mark Slee | b15a68b | 2006-06-07 06:46:24 +0000 | [diff] [blame] | 38 |  | 
| Mark Slee | f0712dc | 2006-10-25 19:03:57 +0000 | [diff] [blame] | 39 | t_struct(t_program* program, const std::string& name) : | 
|  | 40 | t_type(program, name), | 
| Mark Slee | 782abbb | 2007-01-19 00:17:02 +0000 | [diff] [blame] | 41 | is_xception_(false), | 
| David Reiss | 18bf22d | 2007-08-28 20:49:17 +0000 | [diff] [blame] | 42 | xsd_all_(false) | 
|  | 43 | { | 
|  | 44 | memset(fingerprint_, 0, sizeof(fingerprint_)); | 
|  | 45 | } | 
| Mark Slee | 3198572 | 2006-05-24 21:45:31 +0000 | [diff] [blame] | 46 |  | 
| Mark Slee | 9cb7c61 | 2006-09-01 22:17:45 +0000 | [diff] [blame] | 47 | void set_name(const std::string& name) { | 
|  | 48 | name_ = name; | 
|  | 49 | } | 
|  | 50 |  | 
| Mark Slee | 9cb7c61 | 2006-09-01 22:17:45 +0000 | [diff] [blame] | 51 | void set_xception(bool is_xception) { | 
|  | 52 | is_xception_ = is_xception; | 
|  | 53 | } | 
| Mark Slee | e854063 | 2006-05-30 09:24:40 +0000 | [diff] [blame] | 54 |  | 
| Mark Slee | 782abbb | 2007-01-19 00:17:02 +0000 | [diff] [blame] | 55 | void set_xsd_all(bool xsd_all) { | 
|  | 56 | xsd_all_ = xsd_all; | 
|  | 57 | } | 
|  | 58 |  | 
|  | 59 | bool get_xsd_all() const { | 
|  | 60 | return xsd_all_; | 
|  | 61 | } | 
|  | 62 |  | 
| Mark Slee | 9cb7c61 | 2006-09-01 22:17:45 +0000 | [diff] [blame] | 63 | void append(t_field* elem) { | 
|  | 64 | members_.push_back(elem); | 
|  | 65 | } | 
| Mark Slee | e854063 | 2006-05-30 09:24:40 +0000 | [diff] [blame] | 66 |  | 
| Mark Slee | 9cb7c61 | 2006-09-01 22:17:45 +0000 | [diff] [blame] | 67 | const std::vector<t_field*>& get_members() { | 
|  | 68 | return members_; | 
|  | 69 | } | 
|  | 70 |  | 
|  | 71 | bool is_struct() const { | 
|  | 72 | return !is_xception_; | 
|  | 73 | } | 
|  | 74 |  | 
|  | 75 | bool is_xception() const { | 
|  | 76 | return is_xception_; | 
|  | 77 | } | 
| Mark Slee | 3198572 | 2006-05-24 21:45:31 +0000 | [diff] [blame] | 78 |  | 
| David Reiss | 18bf22d | 2007-08-28 20:49:17 +0000 | [diff] [blame] | 79 | virtual std::string get_fingerprint_material() const { | 
|  | 80 | std::string rv = "{"; | 
|  | 81 | std::vector<t_field*>::const_iterator m_iter; | 
|  | 82 | for (m_iter = members_.begin(); m_iter != members_.end(); ++m_iter) { | 
|  | 83 | rv += (**m_iter).get_fingerprint_material(); | 
|  | 84 | rv += ";"; | 
|  | 85 | } | 
|  | 86 | rv += "}"; | 
|  | 87 | return rv; | 
|  | 88 | } | 
|  | 89 |  | 
|  | 90 | // Fingerprint should change whenever (and only when) | 
|  | 91 | // the encoding via TDenseProtocol changes. | 
|  | 92 | static const int fingerprint_len = 16; | 
|  | 93 |  | 
|  | 94 | // Call this before trying get_*_fingerprint(). | 
|  | 95 | void generate_fingerprint() { | 
|  | 96 | std::string material = get_fingerprint_material(); | 
|  | 97 | MD5_CTX ctx; | 
|  | 98 | MD5Init(&ctx); | 
|  | 99 | MD5Update(&ctx, (unsigned char*)(material.data()), material.size()); | 
|  | 100 | MD5Final(fingerprint_, &ctx); | 
|  | 101 | //std::cout << get_name() << std::endl; | 
|  | 102 | //std::cout << material << std::endl; | 
|  | 103 | //std::cout << get_ascii_fingerprint() << std::endl << std::endl; | 
|  | 104 | } | 
|  | 105 |  | 
|  | 106 | bool has_fingerprint() const { | 
|  | 107 | for (int i = 0; i < fingerprint_len; i++) { | 
|  | 108 | if (fingerprint_[i] != 0) { | 
|  | 109 | return true; | 
|  | 110 | } | 
|  | 111 | } | 
|  | 112 | return false; | 
|  | 113 | } | 
|  | 114 |  | 
|  | 115 | const uint8_t* get_binary_fingerprint() const { | 
|  | 116 | return fingerprint_; | 
|  | 117 | } | 
|  | 118 |  | 
|  | 119 | std::string get_ascii_fingerprint() const { | 
|  | 120 | std::string rv; | 
|  | 121 | const uint8_t* fp = get_binary_fingerprint(); | 
|  | 122 | for (int i = 0; i < fingerprint_len; i++) { | 
|  | 123 | rv += byte_to_hex(fp[i]); | 
|  | 124 | } | 
|  | 125 | return rv; | 
|  | 126 | } | 
|  | 127 |  | 
|  | 128 | // This function will break (maybe badly) unless 0 <= num <= 16. | 
|  | 129 | static char nybble_to_xdigit(int num) { | 
|  | 130 | if (num < 10) { | 
|  | 131 | return '0' + num; | 
|  | 132 | } else { | 
|  | 133 | return 'A' + num - 10; | 
|  | 134 | } | 
|  | 135 | } | 
|  | 136 |  | 
|  | 137 | static std::string byte_to_hex(uint8_t byte) { | 
|  | 138 | std::string rv; | 
|  | 139 | rv += nybble_to_xdigit(byte >> 4); | 
|  | 140 | rv += nybble_to_xdigit(byte & 0x0f); | 
|  | 141 | return rv; | 
|  | 142 | } | 
|  | 143 |  | 
|  | 144 |  | 
| Mark Slee | 3198572 | 2006-05-24 21:45:31 +0000 | [diff] [blame] | 145 | private: | 
| David Reiss | 18bf22d | 2007-08-28 20:49:17 +0000 | [diff] [blame] | 146 |  | 
| Mark Slee | e854063 | 2006-05-30 09:24:40 +0000 | [diff] [blame] | 147 | std::vector<t_field*> members_; | 
| Mark Slee | 9cb7c61 | 2006-09-01 22:17:45 +0000 | [diff] [blame] | 148 | bool is_xception_; | 
| Mark Slee | 782abbb | 2007-01-19 00:17:02 +0000 | [diff] [blame] | 149 |  | 
|  | 150 | bool xsd_all_; | 
|  | 151 |  | 
| David Reiss | 18bf22d | 2007-08-28 20:49:17 +0000 | [diff] [blame] | 152 | uint8_t fingerprint_[fingerprint_len]; | 
| Mark Slee | 3198572 | 2006-05-24 21:45:31 +0000 | [diff] [blame] | 153 | }; | 
|  | 154 |  | 
|  | 155 | #endif |