| David Reiss | ea2cba8 | 2009-03-30 21:35:00 +0000 | [diff] [blame] | 1 | /* | 
 | 2 |  * Licensed to the Apache Software Foundation (ASF) under one | 
 | 3 |  * or more contributor license agreements. See the NOTICE file | 
 | 4 |  * distributed with this work for additional information | 
 | 5 |  * regarding copyright ownership. The ASF licenses this file | 
 | 6 |  * to you under the Apache License, Version 2.0 (the | 
 | 7 |  * "License"); you may not use this file except in compliance | 
 | 8 |  * with the License. You may obtain a copy of the License at | 
 | 9 |  * | 
 | 10 |  *   http://www.apache.org/licenses/LICENSE-2.0 | 
 | 11 |  * | 
 | 12 |  * Unless required by applicable law or agreed to in writing, | 
 | 13 |  * software distributed under the License is distributed on an | 
 | 14 |  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | 
 | 15 |  * KIND, either express or implied. See the License for the | 
 | 16 |  * specific language governing permissions and limitations | 
 | 17 |  * under the License. | 
 | 18 |  */ | 
| Mark Slee | e9ce01c | 2007-05-16 02:29:53 +0000 | [diff] [blame] | 19 |  | 
| Mark Slee | 3198572 | 2006-05-24 21:45:31 +0000 | [diff] [blame] | 20 | #ifndef T_STRUCT_H | 
 | 21 | #define T_STRUCT_H | 
 | 22 |  | 
| Bryan Duxbury | ff219ac | 2009-04-10 21:51:00 +0000 | [diff] [blame] | 23 | #include <algorithm> | 
| Mark Slee | 3198572 | 2006-05-24 21:45:31 +0000 | [diff] [blame] | 24 | #include <vector> | 
| Bryan Duxbury | ff219ac | 2009-04-10 21:51:00 +0000 | [diff] [blame] | 25 | #include <utility> | 
| Mark Slee | 3198572 | 2006-05-24 21:45:31 +0000 | [diff] [blame] | 26 | #include <string> | 
 | 27 |  | 
 | 28 | #include "t_type.h" | 
| Mark Slee | e854063 | 2006-05-30 09:24:40 +0000 | [diff] [blame] | 29 | #include "t_field.h" | 
| Mark Slee | 3198572 | 2006-05-24 21:45:31 +0000 | [diff] [blame] | 30 |  | 
| Mark Slee | f0712dc | 2006-10-25 19:03:57 +0000 | [diff] [blame] | 31 | // Forward declare that puppy | 
 | 32 | class t_program; | 
 | 33 |  | 
| Mark Slee | f5377b3 | 2006-10-10 01:42:59 +0000 | [diff] [blame] | 34 | /** | 
 | 35 |  * A struct is a container for a set of member fields that has a name. Structs | 
 | 36 |  * are also used to implement exception types. | 
 | 37 |  * | 
| Mark Slee | f5377b3 | 2006-10-10 01:42:59 +0000 | [diff] [blame] | 38 |  */ | 
| Mark Slee | 3198572 | 2006-05-24 21:45:31 +0000 | [diff] [blame] | 39 | class t_struct : public t_type { | 
 | 40 |  public: | 
| Bryan Duxbury | ff219ac | 2009-04-10 21:51:00 +0000 | [diff] [blame] | 41 |   typedef std::vector<t_field*> members_type; | 
 | 42 |  | 
| Mark Slee | f0712dc | 2006-10-25 19:03:57 +0000 | [diff] [blame] | 43 |   t_struct(t_program* program) : | 
 | 44 |     t_type(program), | 
| Mark Slee | 782abbb | 2007-01-19 00:17:02 +0000 | [diff] [blame] | 45 |     is_xception_(false), | 
| Bryan Duxbury | d620328 | 2012-06-26 00:32:57 +0000 | [diff] [blame] | 46 |     is_union_(false), | 
| Jens Geyer | 04f7097 | 2012-12-17 22:41:21 +0100 | [diff] [blame] | 47 |     members_validated(false), | 
 | 48 |     members_with_value(0), | 
| David Reiss | f84b360 | 2007-09-17 21:16:32 +0000 | [diff] [blame] | 49 |     xsd_all_(false) {} | 
| Mark Slee | b15a68b | 2006-06-07 06:46:24 +0000 | [diff] [blame] | 50 |  | 
| Mark Slee | f0712dc | 2006-10-25 19:03:57 +0000 | [diff] [blame] | 51 |   t_struct(t_program* program, const std::string& name) : | 
 | 52 |     t_type(program, name), | 
| Mark Slee | 782abbb | 2007-01-19 00:17:02 +0000 | [diff] [blame] | 53 |     is_xception_(false), | 
| Bryan Duxbury | d620328 | 2012-06-26 00:32:57 +0000 | [diff] [blame] | 54 |     is_union_(false), | 
| Jens Geyer | 04f7097 | 2012-12-17 22:41:21 +0100 | [diff] [blame] | 55 |     members_validated(false), | 
 | 56 |     members_with_value(0), | 
| David Reiss | f84b360 | 2007-09-17 21:16:32 +0000 | [diff] [blame] | 57 |     xsd_all_(false) {} | 
| Mark Slee | 3198572 | 2006-05-24 21:45:31 +0000 | [diff] [blame] | 58 |  | 
| Mark Slee | 9cb7c61 | 2006-09-01 22:17:45 +0000 | [diff] [blame] | 59 |   void set_name(const std::string& name) { | 
 | 60 |     name_ = name; | 
| Jens Geyer | 04f7097 | 2012-12-17 22:41:21 +0100 | [diff] [blame] | 61 |     validate_union_members(); | 
| Mark Slee | 9cb7c61 | 2006-09-01 22:17:45 +0000 | [diff] [blame] | 62 |   } | 
 | 63 |  | 
| Mark Slee | 9cb7c61 | 2006-09-01 22:17:45 +0000 | [diff] [blame] | 64 |   void set_xception(bool is_xception) { | 
 | 65 |     is_xception_ = is_xception; | 
 | 66 |   } | 
| Mark Slee | e854063 | 2006-05-30 09:24:40 +0000 | [diff] [blame] | 67 |  | 
| Jens Geyer | 04f7097 | 2012-12-17 22:41:21 +0100 | [diff] [blame] | 68 |   void validate_union_member( t_field * field) { | 
 | 69 |     if( is_union_ && (! name_.empty())) { | 
 | 70 |  | 
 | 71 |       // unions can't have required fields | 
 | 72 |       if( field->get_req() == t_field::T_REQUIRED) { | 
 | 73 |         pwarning(  1, "Required field %s of union %s set to optional.\n", field->get_name().c_str(), name_.c_str()); | 
 | 74 |         field->set_req( t_field::T_OPTIONAL); | 
 | 75 |       } | 
 | 76 |  | 
 | 77 |       // unions may have up to one member defaulted, but not more | 
 | 78 |       if( field->get_value() != NULL) { | 
 | 79 |         if( 1 < ++members_with_value) { | 
 | 80 |           throw "Error: Field "+field->get_name()+" provides another default value for union "+name_; | 
 | 81 |         } | 
 | 82 |       } | 
 | 83 |     } | 
 | 84 |      | 
 | 85 |   } | 
 | 86 |  | 
 | 87 |   void validate_union_members() { | 
 | 88 |     if( is_union_ && (! name_.empty()) && (!members_validated)) { | 
 | 89 |       members_type::const_iterator m_iter; | 
 | 90 |       for (m_iter = members_in_id_order_.begin(); m_iter != members_in_id_order_.end(); ++m_iter) { | 
 | 91 |         validate_union_member( *m_iter); | 
 | 92 |       } | 
 | 93 |       members_validated = true;           | 
 | 94 |     } | 
 | 95 |   } | 
 | 96 |  | 
| Bryan Duxbury | ab3666e | 2009-09-01 23:03:47 +0000 | [diff] [blame] | 97 |   void set_union(bool is_union) { | 
 | 98 |     is_union_ = is_union; | 
| Jens Geyer | 04f7097 | 2012-12-17 22:41:21 +0100 | [diff] [blame] | 99 |     validate_union_members(); | 
| Bryan Duxbury | ab3666e | 2009-09-01 23:03:47 +0000 | [diff] [blame] | 100 |   } | 
 | 101 |  | 
| Mark Slee | 782abbb | 2007-01-19 00:17:02 +0000 | [diff] [blame] | 102 |   void set_xsd_all(bool xsd_all) { | 
 | 103 |     xsd_all_ = xsd_all; | 
 | 104 |   } | 
 | 105 |  | 
 | 106 |   bool get_xsd_all() const { | 
 | 107 |     return xsd_all_; | 
 | 108 |   } | 
 | 109 |  | 
| Bryan Duxbury | ff219ac | 2009-04-10 21:51:00 +0000 | [diff] [blame] | 110 |   bool append(t_field* elem) { | 
| Bryan Duxbury | ff219ac | 2009-04-10 21:51:00 +0000 | [diff] [blame] | 111 |     typedef members_type::iterator iter_type; | 
 | 112 |     std::pair<iter_type, iter_type> bounds = std::equal_range( | 
 | 113 |             members_in_id_order_.begin(), members_in_id_order_.end(), elem, t_field::key_compare() | 
 | 114 |         ); | 
 | 115 |     if (bounds.first != bounds.second) { | 
 | 116 |       return false; | 
 | 117 |     } | 
| Jens Geyer | 3a67c2f | 2013-02-03 22:30:41 +0100 | [diff] [blame^] | 118 |     // returns false when there is a conflict of field names | 
 | 119 |     if (get_field_by_name(elem->get_name()) != NULL) { | 
 | 120 |       return false;  | 
 | 121 |     } | 
 | 122 |     members_.push_back(elem); | 
| Bryan Duxbury | ff219ac | 2009-04-10 21:51:00 +0000 | [diff] [blame] | 123 |     members_in_id_order_.insert(bounds.second, elem); | 
| Jens Geyer | 04f7097 | 2012-12-17 22:41:21 +0100 | [diff] [blame] | 124 |     validate_union_member( elem); | 
| Bryan Duxbury | ff219ac | 2009-04-10 21:51:00 +0000 | [diff] [blame] | 125 |     return true; | 
| Mark Slee | 9cb7c61 | 2006-09-01 22:17:45 +0000 | [diff] [blame] | 126 |   } | 
| Mark Slee | e854063 | 2006-05-30 09:24:40 +0000 | [diff] [blame] | 127 |  | 
| Bryan Duxbury | ff219ac | 2009-04-10 21:51:00 +0000 | [diff] [blame] | 128 |   const members_type& get_members() { | 
| Mark Slee | 9cb7c61 | 2006-09-01 22:17:45 +0000 | [diff] [blame] | 129 |     return members_; | 
 | 130 |   } | 
 | 131 |  | 
| Bryan Duxbury | ff219ac | 2009-04-10 21:51:00 +0000 | [diff] [blame] | 132 |   const members_type& get_sorted_members() { | 
 | 133 |     return members_in_id_order_; | 
 | 134 |   } | 
 | 135 |  | 
| Mark Slee | 9cb7c61 | 2006-09-01 22:17:45 +0000 | [diff] [blame] | 136 |   bool is_struct() const { | 
 | 137 |     return !is_xception_; | 
 | 138 |   } | 
 | 139 |  | 
 | 140 |   bool is_xception() const { | 
 | 141 |     return is_xception_; | 
 | 142 |   } | 
| Bryan Duxbury | ab3666e | 2009-09-01 23:03:47 +0000 | [diff] [blame] | 143 |    | 
 | 144 |   bool is_union() const { | 
 | 145 |     return is_union_; | 
 | 146 |   } | 
| Mark Slee | 3198572 | 2006-05-24 21:45:31 +0000 | [diff] [blame] | 147 |  | 
| David Reiss | 18bf22d | 2007-08-28 20:49:17 +0000 | [diff] [blame] | 148 |   virtual std::string get_fingerprint_material() const { | 
 | 149 |     std::string rv = "{"; | 
| Bryan Duxbury | ff219ac | 2009-04-10 21:51:00 +0000 | [diff] [blame] | 150 |     members_type::const_iterator m_iter; | 
 | 151 |     for (m_iter = members_in_id_order_.begin(); m_iter != members_in_id_order_.end(); ++m_iter) { | 
| David Reiss | 6ce97e3 | 2007-08-30 23:18:31 +0000 | [diff] [blame] | 152 |       rv += (*m_iter)->get_fingerprint_material(); | 
| David Reiss | 18bf22d | 2007-08-28 20:49:17 +0000 | [diff] [blame] | 153 |       rv += ";"; | 
 | 154 |     } | 
 | 155 |     rv += "}"; | 
 | 156 |     return rv; | 
 | 157 |   } | 
 | 158 |  | 
| David Reiss | 9885c68 | 2007-08-30 23:12:37 +0000 | [diff] [blame] | 159 |   virtual void generate_fingerprint() { | 
 | 160 |     t_type::generate_fingerprint(); | 
| Bryan Duxbury | ff219ac | 2009-04-10 21:51:00 +0000 | [diff] [blame] | 161 |     members_type::const_iterator m_iter; | 
 | 162 |     for (m_iter = members_in_id_order_.begin(); m_iter != members_in_id_order_.end(); ++m_iter) { | 
| David Reiss | 6ce97e3 | 2007-08-30 23:18:31 +0000 | [diff] [blame] | 163 |       (*m_iter)->get_type()->generate_fingerprint(); | 
| David Reiss | 18bf22d | 2007-08-28 20:49:17 +0000 | [diff] [blame] | 164 |     } | 
 | 165 |   } | 
 | 166 |  | 
| Bryan Duxbury | 2d80470 | 2009-12-18 19:41:11 +0000 | [diff] [blame] | 167 |   t_field* get_field_by_name(std::string field_name) { | 
 | 168 |     members_type::const_iterator m_iter; | 
 | 169 |     for (m_iter = members_in_id_order_.begin(); m_iter != members_in_id_order_.end(); ++m_iter) { | 
 | 170 |       if ((*m_iter)->get_name() == field_name) { | 
 | 171 |         return *m_iter; | 
 | 172 |       } | 
 | 173 |     } | 
 | 174 |     return NULL; | 
 | 175 |   } | 
 | 176 |  | 
| Mark Slee | 3198572 | 2006-05-24 21:45:31 +0000 | [diff] [blame] | 177 |  private: | 
| David Reiss | 18bf22d | 2007-08-28 20:49:17 +0000 | [diff] [blame] | 178 |  | 
| Bryan Duxbury | ff219ac | 2009-04-10 21:51:00 +0000 | [diff] [blame] | 179 |   members_type members_; | 
 | 180 |   members_type members_in_id_order_; | 
| Mark Slee | 9cb7c61 | 2006-09-01 22:17:45 +0000 | [diff] [blame] | 181 |   bool is_xception_; | 
| Bryan Duxbury | ab3666e | 2009-09-01 23:03:47 +0000 | [diff] [blame] | 182 |   bool is_union_; | 
| Jens Geyer | 04f7097 | 2012-12-17 22:41:21 +0100 | [diff] [blame] | 183 |   bool members_validated; | 
 | 184 |   int  members_with_value; | 
| Mark Slee | 782abbb | 2007-01-19 00:17:02 +0000 | [diff] [blame] | 185 |  | 
 | 186 |   bool xsd_all_; | 
| Mark Slee | 3198572 | 2006-05-24 21:45:31 +0000 | [diff] [blame] | 187 | }; | 
 | 188 |  | 
 | 189 | #endif |