1 /*
2 * Copyright (c) 2009-2021, Google LLC
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of Google LLC nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL Google LLC BE LIABLE FOR ANY DIRECT,
20 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27 #include "protos_generator/gen_repeated_fields.h"
28
29 #include <string>
30 #include <vector>
31
32 #include "google/protobuf/descriptor.pb.h"
33 #include "google/protobuf/descriptor.h"
34 #include "protos_generator/gen_accessors.h"
35 #include "protos_generator/gen_enums.h"
36 #include "protos_generator/gen_extensions.h"
37 #include "protos_generator/gen_utils.h"
38 #include "protos_generator/output.h"
39 #include "upbc/common.h"
40 #include "upbc/file_layout.h"
41
42 namespace protos_generator {
43 namespace protobuf = ::google::protobuf;
44
45 // Adds using accessors to reuse base Access class members from a Proxy/CProxy.
WriteRepeatedFieldUsingAccessors(const protobuf::FieldDescriptor * field,absl::string_view class_name,absl::string_view resolved_field_name,Output & output,bool read_only)46 void WriteRepeatedFieldUsingAccessors(const protobuf::FieldDescriptor* field,
47 absl::string_view class_name,
48 absl::string_view resolved_field_name,
49 Output& output, bool read_only) {
50 if (field->cpp_type() == protobuf::FieldDescriptor::CPPTYPE_MESSAGE) {
51 output(
52 R"cc(
53 using $0Access::$1;
54 using $0Access::$1_size;
55 using $0Access::mutable_$1;
56 )cc",
57 class_name, resolved_field_name);
58 if (!read_only) {
59 output(
60 R"cc(
61 using $0Access::add_$1;
62 using $0Access::clear_$1;
63 )cc",
64 class_name, resolved_field_name);
65 }
66 } else {
67 output(
68 R"cc(
69 using $0Access::$1;
70 using $0Access::$1_size;
71 )cc",
72 class_name, resolved_field_name);
73 if (!read_only) {
74 output(
75 R"cc(
76 using $0Access::add_$1;
77 using $0Access::clear_$1;
78 using $0Access::resize_$1;
79 using $0Access::set_$1;
80 )cc",
81 class_name, resolved_field_name);
82 }
83 }
84 }
85
WriteRepeatedFieldsInMessageHeader(const protobuf::Descriptor * desc,const protobuf::FieldDescriptor * field,absl::string_view resolved_field_name,absl::string_view resolved_upbc_name,Output & output)86 void WriteRepeatedFieldsInMessageHeader(const protobuf::Descriptor* desc,
87 const protobuf::FieldDescriptor* field,
88 absl::string_view resolved_field_name,
89 absl::string_view resolved_upbc_name,
90 Output& output) {
91 output(
92 R"cc(
93 inline size_t $1_size() const {
94 size_t len;
95 $0_$2(msg_, &len);
96 return len;
97 }
98
99 inline void clear_$1() { $0_clear_$2(msg_); }
100 )cc",
101 MessageName(desc), resolved_field_name, resolved_upbc_name);
102
103 if (field->cpp_type() == protobuf::FieldDescriptor::CPPTYPE_MESSAGE) {
104 output(
105 R"cc(
106 $1 $2(size_t index) const;
107 absl::StatusOr<$0> add_$2();
108 $0 mutable_$2(size_t index) const;
109 )cc",
110 MessagePtrConstType(field, /* const */ false),
111 MessagePtrConstType(field, /* const */ true), resolved_field_name,
112 resolved_upbc_name);
113 } else {
114 output(
115 R"cc(
116 $0 $1(size_t index) const;
117 bool add_$1($0 val);
118 void set_$1(size_t index, $0 val);
119 bool resize_$1(size_t len);
120 )cc",
121 CppConstType(field), resolved_field_name);
122 }
123 }
124
WriteRepeatedMessageAccessor(const protobuf::Descriptor * message,const protobuf::FieldDescriptor * field,const absl::string_view resolved_field_name,const absl::string_view class_name,Output & output)125 void WriteRepeatedMessageAccessor(const protobuf::Descriptor* message,
126 const protobuf::FieldDescriptor* field,
127 const absl::string_view resolved_field_name,
128 const absl::string_view class_name,
129 Output& output) {
130 const char arena_expression[] = "arena_";
131 absl::string_view upbc_name = field->name();
132 output(
133 R"cc(
134 $1 $0::$2(size_t index) const {
135 size_t len;
136 auto* ptr = $3_$5(msg_, &len);
137 assert(index < len);
138 return ::protos::internal::CreateMessage<$4>((upb_Message*)*(ptr + index));
139 }
140 )cc",
141 class_name, MessagePtrConstType(field, /* is_const */ true),
142 resolved_field_name, MessageName(message),
143 MessageBaseType(field, /* maybe_const */ false), upbc_name);
144 output(
145 R"cc(
146 absl::StatusOr<$1> $0::add_$2() {
147 auto new_msg = $3_add_$6(msg_, $5);
148 if (!new_msg) {
149 return ::protos::MessageAllocationError();
150 }
151 return ::protos::internal::CreateMessageProxy<$4>((upb_Message*)new_msg, $5);
152 }
153 )cc",
154 class_name, MessagePtrConstType(field, /* const */ false),
155 resolved_field_name, MessageName(message),
156 MessageBaseType(field, /* maybe_const */ false), arena_expression,
157 upbc_name);
158 output(
159 R"cc(
160 $1 $0::mutable_$2(size_t index) const {
161 size_t len;
162 auto* ptr = $3_$6(msg_, &len);
163 assert(index < len);
164 return ::protos::internal::CreateMessageProxy<$4>(
165 (upb_Message*)*(ptr + index), $5);
166 }
167 )cc",
168 class_name, MessagePtrConstType(field, /* is_const */ false),
169 resolved_field_name, MessageName(message),
170 MessageBaseType(field, /* maybe_const */ false), arena_expression,
171 upbc_name);
172 }
173
WriteRepeatedStringAccessor(const protobuf::Descriptor * message,const protobuf::FieldDescriptor * field,const absl::string_view resolved_field_name,const absl::string_view class_name,Output & output)174 void WriteRepeatedStringAccessor(const protobuf::Descriptor* message,
175 const protobuf::FieldDescriptor* field,
176 const absl::string_view resolved_field_name,
177 const absl::string_view class_name,
178 Output& output) {
179 absl::string_view upbc_name = field->name();
180 output(
181 R"cc(
182 $1 $0::$2(size_t index) const {
183 size_t len;
184 auto* ptr = $3_mutable_$4(msg_, &len);
185 assert(index < len);
186 return ::protos::UpbStrToStringView(*(ptr + index));
187 }
188 )cc",
189 class_name, CppConstType(field), resolved_field_name,
190 MessageName(message), upbc_name);
191 output(
192 R"cc(
193 bool $0::resize_$1(size_t len) {
194 return $2_resize_$3(msg_, len, arena_);
195 }
196 )cc",
197 class_name, resolved_field_name, MessageName(message), upbc_name);
198 output(
199 R"cc(
200 bool $0::add_$2($1 val) {
201 return $3_add_$4(msg_, ::protos::UpbStrFromStringView(val, arena_), arena_);
202 }
203 )cc",
204 class_name, CppConstType(field), resolved_field_name,
205 MessageName(message), upbc_name);
206 output(
207 R"cc(
208 void $0::set_$2(size_t index, $1 val) {
209 size_t len;
210 auto* ptr = $3_mutable_$4(msg_, &len);
211 assert(index < len);
212 *(ptr + index) = ::protos::UpbStrFromStringView(val, arena_);
213 }
214 )cc",
215 class_name, CppConstType(field), resolved_field_name,
216 MessageName(message), upbc_name);
217 }
218
WriteRepeatedScalarAccessor(const protobuf::Descriptor * message,const protobuf::FieldDescriptor * field,const absl::string_view resolved_field_name,const absl::string_view class_name,Output & output)219 void WriteRepeatedScalarAccessor(const protobuf::Descriptor* message,
220 const protobuf::FieldDescriptor* field,
221 const absl::string_view resolved_field_name,
222 const absl::string_view class_name,
223 Output& output) {
224 absl::string_view upbc_name = field->name();
225 output(
226 R"cc(
227 $1 $0::$2(size_t index) const {
228 size_t len;
229 auto* ptr = $3_mutable_$4(msg_, &len);
230 assert(index < len);
231 return *(ptr + index);
232 }
233 )cc",
234 class_name, CppConstType(field), resolved_field_name,
235 MessageName(message), upbc_name);
236 output(
237 R"cc(
238 bool $0::resize_$1(size_t len) {
239 return $2_resize_$3(msg_, len, arena_);
240 }
241 )cc",
242 class_name, resolved_field_name, MessageName(message), upbc_name);
243 output(
244 R"cc(
245 bool $0::add_$2($1 val) { return $3_add_$4(msg_, val, arena_); }
246 )cc",
247 class_name, CppConstType(field), resolved_field_name,
248 MessageName(message), upbc_name);
249 output(
250 R"cc(
251 void $0::set_$2(size_t index, $1 val) {
252 size_t len;
253 auto* ptr = $3_mutable_$4(msg_, &len);
254 assert(index < len);
255 *(ptr + index) = val;
256 }
257 )cc",
258 class_name, CppConstType(field), resolved_field_name,
259 MessageName(message), upbc_name);
260 }
261
262 } // namespace protos_generator
263