blob: 22826767342d110da284bfc798ff45097209f54e [file] [log] [blame]
David Reissea2cba82009-03-30 21:35:00 +00001/*
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 Sleee9ce01c2007-05-16 02:29:53 +000019
Mark Slee31985722006-05-24 21:45:31 +000020#ifndef T_STRUCT_H
21#define T_STRUCT_H
22
Bryan Duxburyff219ac2009-04-10 21:51:00 +000023#include <algorithm>
Mark Slee31985722006-05-24 21:45:31 +000024#include <vector>
Bryan Duxburyff219ac2009-04-10 21:51:00 +000025#include <utility>
Mark Slee31985722006-05-24 21:45:31 +000026#include <string>
27
28#include "t_type.h"
Mark Sleee8540632006-05-30 09:24:40 +000029#include "t_field.h"
Mark Slee31985722006-05-24 21:45:31 +000030
Mark Sleef0712dc2006-10-25 19:03:57 +000031// Forward declare that puppy
32class t_program;
33
Mark Sleef5377b32006-10-10 01:42:59 +000034/**
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 Sleef5377b32006-10-10 01:42:59 +000038 */
Mark Slee31985722006-05-24 21:45:31 +000039class t_struct : public t_type {
Konrad Grochowski16a23a62014-11-13 15:33:38 +010040public:
Bryan Duxburyff219ac2009-04-10 21:51:00 +000041 typedef std::vector<t_field*> members_type;
42
Konrad Grochowski16a23a62014-11-13 15:33:38 +010043 t_struct(t_program* program)
44 : t_type(program),
45 is_xception_(false),
46 is_union_(false),
47 members_validated(false),
48 members_with_value(0),
49 xsd_all_(false) {}
Mark Sleeb15a68b2006-06-07 06:46:24 +000050
Konrad Grochowski16a23a62014-11-13 15:33:38 +010051 t_struct(t_program* program, const std::string& name)
52 : t_type(program, name),
53 is_xception_(false),
54 is_union_(false),
55 members_validated(false),
56 members_with_value(0),
57 xsd_all_(false) {}
Mark Slee31985722006-05-24 21:45:31 +000058
Mark Slee9cb7c612006-09-01 22:17:45 +000059 void set_name(const std::string& name) {
60 name_ = name;
Jens Geyer04f70972012-12-17 22:41:21 +010061 validate_union_members();
Mark Slee9cb7c612006-09-01 22:17:45 +000062 }
63
Konrad Grochowski16a23a62014-11-13 15:33:38 +010064 void set_xception(bool is_xception) { is_xception_ = is_xception; }
Mark Sleee8540632006-05-30 09:24:40 +000065
Konrad Grochowski16a23a62014-11-13 15:33:38 +010066 void validate_union_member(t_field* field) {
67 if (is_union_ && (!name_.empty())) {
Jens Geyer04f70972012-12-17 22:41:21 +010068
69 // unions can't have required fields
Konrad Grochowski16a23a62014-11-13 15:33:38 +010070 if (field->get_req() == t_field::T_REQUIRED) {
71 pwarning(1,
72 "Required field %s of union %s set to optional.\n",
73 field->get_name().c_str(),
74 name_.c_str());
75 field->set_req(t_field::T_OPTIONAL);
Jens Geyer04f70972012-12-17 22:41:21 +010076 }
77
78 // unions may have up to one member defaulted, but not more
Konrad Grochowski16a23a62014-11-13 15:33:38 +010079 if (field->get_value() != NULL) {
80 if (1 < ++members_with_value) {
81 throw "Error: Field " + field->get_name() + " provides another default value for union "
82 + name_;
Jens Geyer04f70972012-12-17 22:41:21 +010083 }
84 }
85 }
Jens Geyer04f70972012-12-17 22:41:21 +010086 }
87
88 void validate_union_members() {
Konrad Grochowski16a23a62014-11-13 15:33:38 +010089 if (is_union_ && (!name_.empty()) && (!members_validated)) {
Jens Geyer04f70972012-12-17 22:41:21 +010090 members_type::const_iterator m_iter;
91 for (m_iter = members_in_id_order_.begin(); m_iter != members_in_id_order_.end(); ++m_iter) {
Konrad Grochowski16a23a62014-11-13 15:33:38 +010092 validate_union_member(*m_iter);
Jens Geyer04f70972012-12-17 22:41:21 +010093 }
Roger Meier4f4b15b2014-11-05 16:51:04 +010094 members_validated = true;
Jens Geyer04f70972012-12-17 22:41:21 +010095 }
96 }
97
Bryan Duxburyab3666e2009-09-01 23:03:47 +000098 void set_union(bool is_union) {
99 is_union_ = is_union;
Jens Geyer04f70972012-12-17 22:41:21 +0100100 validate_union_members();
Bryan Duxburyab3666e2009-09-01 23:03:47 +0000101 }
102
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100103 void set_xsd_all(bool xsd_all) { xsd_all_ = xsd_all; }
Mark Slee782abbb2007-01-19 00:17:02 +0000104
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100105 bool get_xsd_all() const { return xsd_all_; }
Mark Slee782abbb2007-01-19 00:17:02 +0000106
Bryan Duxburyff219ac2009-04-10 21:51:00 +0000107 bool append(t_field* elem) {
Bryan Duxburyff219ac2009-04-10 21:51:00 +0000108 typedef members_type::iterator iter_type;
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100109 std::pair<iter_type, iter_type> bounds = std::equal_range(members_in_id_order_.begin(),
110 members_in_id_order_.end(),
111 elem,
112 t_field::key_compare());
Bryan Duxburyff219ac2009-04-10 21:51:00 +0000113 if (bounds.first != bounds.second) {
114 return false;
115 }
Jens Geyer3a67c2f2013-02-03 22:30:41 +0100116 // returns false when there is a conflict of field names
117 if (get_field_by_name(elem->get_name()) != NULL) {
Roger Meier4f4b15b2014-11-05 16:51:04 +0100118 return false;
Jens Geyer3a67c2f2013-02-03 22:30:41 +0100119 }
120 members_.push_back(elem);
Bryan Duxburyff219ac2009-04-10 21:51:00 +0000121 members_in_id_order_.insert(bounds.second, elem);
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100122 validate_union_member(elem);
Bryan Duxburyff219ac2009-04-10 21:51:00 +0000123 return true;
Mark Slee9cb7c612006-09-01 22:17:45 +0000124 }
Mark Sleee8540632006-05-30 09:24:40 +0000125
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100126 const members_type& get_members() { return members_; }
Mark Slee9cb7c612006-09-01 22:17:45 +0000127
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100128 const members_type& get_sorted_members() { return members_in_id_order_; }
Bryan Duxburyff219ac2009-04-10 21:51:00 +0000129
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100130 bool is_struct() const { return !is_xception_; }
Mark Slee9cb7c612006-09-01 22:17:45 +0000131
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100132 bool is_xception() const { return is_xception_; }
Roger Meier4f4b15b2014-11-05 16:51:04 +0100133
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100134 bool is_union() const { return is_union_; }
Mark Slee31985722006-05-24 21:45:31 +0000135
David Reiss18bf22d2007-08-28 20:49:17 +0000136 virtual std::string get_fingerprint_material() const {
137 std::string rv = "{";
Jens Geyer83767a72013-09-23 22:09:12 +0200138 bool do_reserve = (members_in_id_order_.size() > 1);
139 size_t estimation = 0;
Bryan Duxburyff219ac2009-04-10 21:51:00 +0000140 members_type::const_iterator m_iter;
141 for (m_iter = members_in_id_order_.begin(); m_iter != members_in_id_order_.end(); ++m_iter) {
David Reiss6ce97e32007-08-30 23:18:31 +0000142 rv += (*m_iter)->get_fingerprint_material();
David Reiss18bf22d2007-08-28 20:49:17 +0000143 rv += ";";
Roger Meier4f4b15b2014-11-05 16:51:04 +0100144
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100145 if (do_reserve) {
Jens Geyer83767a72013-09-23 22:09:12 +0200146 estimation = members_in_id_order_.size() * rv.size() + 16;
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100147 rv.reserve(estimation);
Jens Geyer83767a72013-09-23 22:09:12 +0200148 do_reserve = false;
149 }
David Reiss18bf22d2007-08-28 20:49:17 +0000150 }
151 rv += "}";
152 return rv;
153 }
154
David Reiss9885c682007-08-30 23:12:37 +0000155 virtual void generate_fingerprint() {
156 t_type::generate_fingerprint();
Bryan Duxburyff219ac2009-04-10 21:51:00 +0000157 members_type::const_iterator m_iter;
158 for (m_iter = members_in_id_order_.begin(); m_iter != members_in_id_order_.end(); ++m_iter) {
David Reiss6ce97e32007-08-30 23:18:31 +0000159 (*m_iter)->get_type()->generate_fingerprint();
David Reiss18bf22d2007-08-28 20:49:17 +0000160 }
161 }
162
Bryan Duxbury2d804702009-12-18 19:41:11 +0000163 t_field* get_field_by_name(std::string field_name) {
164 members_type::const_iterator m_iter;
165 for (m_iter = members_in_id_order_.begin(); m_iter != members_in_id_order_.end(); ++m_iter) {
166 if ((*m_iter)->get_name() == field_name) {
167 return *m_iter;
168 }
169 }
170 return NULL;
171 }
172
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100173private:
Bryan Duxburyff219ac2009-04-10 21:51:00 +0000174 members_type members_;
175 members_type members_in_id_order_;
Mark Slee9cb7c612006-09-01 22:17:45 +0000176 bool is_xception_;
Bryan Duxburyab3666e2009-09-01 23:03:47 +0000177 bool is_union_;
Jens Geyer04f70972012-12-17 22:41:21 +0100178 bool members_validated;
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100179 int members_with_value;
Mark Slee782abbb2007-01-19 00:17:02 +0000180
181 bool xsd_all_;
Mark Slee31985722006-05-24 21:45:31 +0000182};
183
184#endif