blob: ad1267788deb2dc2573986752f0b7fe1013fe7d3 [file] [log] [blame]
Mark Sleee9ce01c2007-05-16 02:29:53 +00001// 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 Slee31985722006-05-24 21:45:31 +00007#ifndef T_STRUCT_H
8#define T_STRUCT_H
9
10#include <vector>
11#include <string>
David Reiss18bf22d2007-08-28 20:49:17 +000012#include <cstring>
Mark Slee31985722006-05-24 21:45:31 +000013
14#include "t_type.h"
Mark Sleee8540632006-05-30 09:24:40 +000015#include "t_field.h"
Mark Slee31985722006-05-24 21:45:31 +000016
David Reiss18bf22d2007-08-28 20:49:17 +000017// What's worse? This, or making a src/parse/non_inlined.cc?
18#include "md5.h"
19
Mark Sleef0712dc2006-10-25 19:03:57 +000020// Forward declare that puppy
21class t_program;
22
Mark Sleef5377b32006-10-10 01:42:59 +000023/**
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 Slee31985722006-05-24 21:45:31 +000029class t_struct : public t_type {
30 public:
Mark Sleef0712dc2006-10-25 19:03:57 +000031 t_struct(t_program* program) :
32 t_type(program),
Mark Slee782abbb2007-01-19 00:17:02 +000033 is_xception_(false),
David Reiss18bf22d2007-08-28 20:49:17 +000034 xsd_all_(false)
35 {
36 memset(fingerprint_, 0, sizeof(fingerprint_));
37 }
Mark Sleeb15a68b2006-06-07 06:46:24 +000038
Mark Sleef0712dc2006-10-25 19:03:57 +000039 t_struct(t_program* program, const std::string& name) :
40 t_type(program, name),
Mark Slee782abbb2007-01-19 00:17:02 +000041 is_xception_(false),
David Reiss18bf22d2007-08-28 20:49:17 +000042 xsd_all_(false)
43 {
44 memset(fingerprint_, 0, sizeof(fingerprint_));
45 }
Mark Slee31985722006-05-24 21:45:31 +000046
Mark Slee9cb7c612006-09-01 22:17:45 +000047 void set_name(const std::string& name) {
48 name_ = name;
49 }
50
Mark Slee9cb7c612006-09-01 22:17:45 +000051 void set_xception(bool is_xception) {
52 is_xception_ = is_xception;
53 }
Mark Sleee8540632006-05-30 09:24:40 +000054
Mark Slee782abbb2007-01-19 00:17:02 +000055 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 Slee9cb7c612006-09-01 22:17:45 +000063 void append(t_field* elem) {
64 members_.push_back(elem);
65 }
Mark Sleee8540632006-05-30 09:24:40 +000066
Mark Slee9cb7c612006-09-01 22:17:45 +000067 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 Slee31985722006-05-24 21:45:31 +000078
David Reiss18bf22d2007-08-28 20:49:17 +000079 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 Slee31985722006-05-24 21:45:31 +0000145 private:
David Reiss18bf22d2007-08-28 20:49:17 +0000146
Mark Sleee8540632006-05-30 09:24:40 +0000147 std::vector<t_field*> members_;
Mark Slee9cb7c612006-09-01 22:17:45 +0000148 bool is_xception_;
Mark Slee782abbb2007-01-19 00:17:02 +0000149
150 bool xsd_all_;
151
David Reiss18bf22d2007-08-28 20:49:17 +0000152 uint8_t fingerprint_[fingerprint_len];
Mark Slee31985722006-05-24 21:45:31 +0000153};
154
155#endif