blob: d19447c3650e96293ebaf80119f1c921ed00cd8c [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
Jens Geyerb72bb942016-02-21 15:07:51 +010069 // 1) unions can't have required fields
70 // 2) union members are implicitly optional, otherwise bugs like THRIFT-3650 wait to happen
71 if (field->get_req() != t_field::T_OPTIONAL) {
72 // no warning on default requiredness, but do warn on anything else that is explicitly asked for
73 if(field->get_req() != t_field::T_OPT_IN_REQ_OUT) {
74 pwarning(1,
75 "Union %s field %s: union members must be optional, ignoring specified requiredness.\n",
76 name_.c_str(),
77 field->get_name().c_str());
78 }
Konrad Grochowski16a23a62014-11-13 15:33:38 +010079 field->set_req(t_field::T_OPTIONAL);
Jens Geyer04f70972012-12-17 22:41:21 +010080 }
81
82 // unions may have up to one member defaulted, but not more
Konrad Grochowski16a23a62014-11-13 15:33:38 +010083 if (field->get_value() != NULL) {
84 if (1 < ++members_with_value) {
85 throw "Error: Field " + field->get_name() + " provides another default value for union "
86 + name_;
Jens Geyer04f70972012-12-17 22:41:21 +010087 }
88 }
89 }
Jens Geyer04f70972012-12-17 22:41:21 +010090 }
91
92 void validate_union_members() {
Konrad Grochowski16a23a62014-11-13 15:33:38 +010093 if (is_union_ && (!name_.empty()) && (!members_validated)) {
Jens Geyer04f70972012-12-17 22:41:21 +010094 members_type::const_iterator m_iter;
95 for (m_iter = members_in_id_order_.begin(); m_iter != members_in_id_order_.end(); ++m_iter) {
Konrad Grochowski16a23a62014-11-13 15:33:38 +010096 validate_union_member(*m_iter);
Jens Geyer04f70972012-12-17 22:41:21 +010097 }
Roger Meier4f4b15b2014-11-05 16:51:04 +010098 members_validated = true;
Jens Geyer04f70972012-12-17 22:41:21 +010099 }
100 }
101
Bryan Duxburyab3666e2009-09-01 23:03:47 +0000102 void set_union(bool is_union) {
103 is_union_ = is_union;
Jens Geyer04f70972012-12-17 22:41:21 +0100104 validate_union_members();
Bryan Duxburyab3666e2009-09-01 23:03:47 +0000105 }
106
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100107 void set_xsd_all(bool xsd_all) { xsd_all_ = xsd_all; }
Mark Slee782abbb2007-01-19 00:17:02 +0000108
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100109 bool get_xsd_all() const { return xsd_all_; }
Mark Slee782abbb2007-01-19 00:17:02 +0000110
Bryan Duxburyff219ac2009-04-10 21:51:00 +0000111 bool append(t_field* elem) {
Bryan Duxburyff219ac2009-04-10 21:51:00 +0000112 typedef members_type::iterator iter_type;
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100113 std::pair<iter_type, iter_type> bounds = std::equal_range(members_in_id_order_.begin(),
114 members_in_id_order_.end(),
115 elem,
116 t_field::key_compare());
Bryan Duxburyff219ac2009-04-10 21:51:00 +0000117 if (bounds.first != bounds.second) {
118 return false;
119 }
Jens Geyer3a67c2f2013-02-03 22:30:41 +0100120 // returns false when there is a conflict of field names
121 if (get_field_by_name(elem->get_name()) != NULL) {
Roger Meier4f4b15b2014-11-05 16:51:04 +0100122 return false;
Jens Geyer3a67c2f2013-02-03 22:30:41 +0100123 }
124 members_.push_back(elem);
Bryan Duxburyff219ac2009-04-10 21:51:00 +0000125 members_in_id_order_.insert(bounds.second, elem);
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100126 validate_union_member(elem);
Bryan Duxburyff219ac2009-04-10 21:51:00 +0000127 return true;
Mark Slee9cb7c612006-09-01 22:17:45 +0000128 }
Mark Sleee8540632006-05-30 09:24:40 +0000129
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100130 const members_type& get_members() { return members_; }
Mark Slee9cb7c612006-09-01 22:17:45 +0000131
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100132 const members_type& get_sorted_members() { return members_in_id_order_; }
Bryan Duxburyff219ac2009-04-10 21:51:00 +0000133
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100134 bool is_struct() const { return !is_xception_; }
Mark Slee9cb7c612006-09-01 22:17:45 +0000135
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100136 bool is_xception() const { return is_xception_; }
Roger Meier4f4b15b2014-11-05 16:51:04 +0100137
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100138 bool is_union() const { return is_union_; }
Mark Slee31985722006-05-24 21:45:31 +0000139
Bryan Duxbury2d804702009-12-18 19:41:11 +0000140 t_field* get_field_by_name(std::string field_name) {
141 members_type::const_iterator m_iter;
142 for (m_iter = members_in_id_order_.begin(); m_iter != members_in_id_order_.end(); ++m_iter) {
143 if ((*m_iter)->get_name() == field_name) {
144 return *m_iter;
145 }
146 }
147 return NULL;
148 }
149
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100150private:
Bryan Duxburyff219ac2009-04-10 21:51:00 +0000151 members_type members_;
152 members_type members_in_id_order_;
Mark Slee9cb7c612006-09-01 22:17:45 +0000153 bool is_xception_;
Bryan Duxburyab3666e2009-09-01 23:03:47 +0000154 bool is_union_;
Jens Geyer04f70972012-12-17 22:41:21 +0100155 bool members_validated;
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100156 int members_with_value;
Mark Slee782abbb2007-01-19 00:17:02 +0000157
158 bool xsd_all_;
Mark Slee31985722006-05-24 21:45:31 +0000159};
160
161#endif