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
10 * http://www.apache.org/licenses/LICENSE-2.0
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
28 #include "thrift/parse/t_type.h"
29 #include "thrift/parse/t_field.h"
31 // Forward declare that puppy
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.
39 class t_struct
: public t_type
{
41 typedef std::vector
<t_field
*> members_type
;
43 t_struct(t_program
* program
)
47 members_validated(false),
48 members_with_value(0),
51 t_struct(t_program
* program
, const std::string
& name
)
52 : t_type(program
, name
),
55 members_validated(false),
56 members_with_value(0),
59 void set_name(const std::string
& name
) override
{
61 validate_union_members();
64 void set_xception(bool is_xception
) { is_xception_
= is_xception
; }
66 void validate_union_member(t_field
* field
) {
67 if (is_union_
&& (!name_
.empty())) {
69 // 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
) {
75 "Union %s field %s: union members must be optional, ignoring specified requiredness.\n",
77 field
->get_name().c_str());
79 field
->set_req(t_field::T_OPTIONAL
);
82 // unions may have up to one member defaulted, but not more
83 if (field
->get_value() != nullptr) {
84 if (1 < ++members_with_value
) {
85 throw "Error: Field " + field
->get_name() + " provides another default value for union "
92 void validate_union_members() {
93 if (is_union_
&& (!name_
.empty()) && (!members_validated
)) {
94 members_type::const_iterator m_iter
;
95 for (m_iter
= members_in_id_order_
.begin(); m_iter
!= members_in_id_order_
.end(); ++m_iter
) {
96 validate_union_member(*m_iter
);
98 members_validated
= true;
102 void set_union(bool is_union
) {
103 is_union_
= is_union
;
104 validate_union_members();
107 void set_xsd_all(bool xsd_all
) { xsd_all_
= xsd_all
; }
109 bool get_xsd_all() const { return xsd_all_
; }
111 bool append(t_field
* elem
) {
112 typedef members_type::iterator iter_type
;
113 std::pair
<iter_type
, iter_type
> bounds
= std::equal_range(members_in_id_order_
.begin(),
114 members_in_id_order_
.end(),
116 t_field::key_compare());
117 if (bounds
.first
!= bounds
.second
) {
120 // returns false when there is a conflict of field names
121 if (get_field_by_name(elem
->get_name()) != nullptr) {
124 members_
.push_back(elem
);
125 members_in_id_order_
.insert(bounds
.second
, elem
);
126 validate_union_member(elem
);
130 const members_type
& get_members() const { return members_
; }
132 const members_type
& get_sorted_members() const { return members_in_id_order_
; }
134 bool is_struct() const override
{ return !is_xception_
; }
136 bool is_xception() const override
{ return is_xception_
; }
138 bool is_union() const { return is_union_
; }
140 t_field
* get_field_by_name(std::string field_name
) {
141 return const_cast<t_field
*>(const_cast<const t_struct
&>(*this).get_field_by_name(field_name
));
144 const t_field
* get_field_by_name(std::string field_name
) const {
145 members_type::const_iterator m_iter
;
146 for (m_iter
= members_in_id_order_
.begin(); m_iter
!= members_in_id_order_
.end(); ++m_iter
) {
147 if ((*m_iter
)->get_name() == field_name
) {
155 members_type members_
;
156 members_type members_in_id_order_
;
159 bool members_validated
;
160 int members_with_value
;