1 /**
2 * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "meta.h"
17
18 namespace panda::pandasm {
19
ValidateSize(const std::string_view & value) const20 std::optional<Metadata::Error> Metadata::ValidateSize(const std::string_view &value) const
21 {
22 constexpr size_t SIZE = 10;
23
24 if (!std::all_of(value.cbegin(), value.cend(), ::isdigit)) {
25 return Error("Unsigned integer value expected", Error::Type::INVALID_VALUE);
26 }
27
28 strtoul(value.data(), nullptr, SIZE);
29 if (errno == ERANGE) {
30 return Error("Value is out of range", Error::Type::INVALID_VALUE);
31 }
32
33 return {};
34 }
35
IsForeign() const36 bool ItemMetadata::IsForeign() const
37 {
38 return GetAttribute("external");
39 }
40
GetType(const std::string_view & value)41 static panda::pandasm::Value::Type GetType(const std::string_view &value)
42 {
43 using VType = panda::pandasm::Value::Type;
44 static std::unordered_map<std::string_view, VType> types {
45 {"u1", VType::U1}, {"i8", VType::I8}, {"u8", VType::U8},
46 {"i16", VType::I16}, {"u16", VType::U16}, {"i32", VType::I32},
47 {"u32", VType::U32}, {"i64", VType::I64}, {"u64", VType::U64},
48 {"f32", VType::F32}, {"f64", VType::F64}, {"string", VType::STRING},
49 {"class", VType::RECORD}, {"enum", VType::ENUM}, {"annotation", VType::ANNOTATION},
50 {"array", VType::ARRAY}, {"method", VType::METHOD}};
51
52 return types[value];
53 }
54
55 template <class T>
ConvertFromString(const std::string_view & value,char ** end)56 static T ConvertFromString(const std::string_view &value, char **end)
57 {
58 static_assert(std::is_integral_v<T>, "T must be integral type");
59
60 constexpr T MIN = std::numeric_limits<T>::min();
61 constexpr T MAX = std::numeric_limits<T>::max();
62
63 if constexpr (std::is_signed_v<T>) {
64 auto v = ConvertFromString<int64_t>(value, end);
65 if (v < MIN || v > MAX) {
66 errno = ERANGE;
67 }
68 return static_cast<T>(v);
69 }
70
71 if constexpr (!std::is_signed_v<T>) {
72 auto v = ConvertFromString<uint64_t>(value, end);
73 if (v < MIN || v > MAX) {
74 errno = ERANGE;
75 }
76 return static_cast<T>(v);
77 }
78 }
79
80 template <>
ConvertFromString(const std::string_view & value,char ** end)81 int64_t ConvertFromString(const std::string_view &value, char **end)
82 {
83 return static_cast<int64_t>(strtoll(value.data(), end, 0));
84 }
85
86 template <>
ConvertFromString(const std::string_view & value,char ** end)87 uint64_t ConvertFromString(const std::string_view &value, char **end)
88 {
89 return static_cast<uint64_t>(strtoull(value.data(), end, 0));
90 }
91
92 template <>
ConvertFromString(const std::string_view & value,char ** end)93 float ConvertFromString(const std::string_view &value, char **end)
94 {
95 return strtof(value.data(), end);
96 }
97
98 template <>
ConvertFromString(const std::string_view & value,char ** end)99 double ConvertFromString(const std::string_view &value, char **end)
100 {
101 return strtod(value.data(), end);
102 }
103
104 template <class T>
ConvertFromString(const std::string_view & value)105 static Expected<T, Metadata::Error> ConvertFromString(const std::string_view &value)
106 {
107 static_assert(std::is_arithmetic_v<T>, "T must be arithmetic type");
108
109 char *end = nullptr;
110 auto v = ConvertFromString<T>(value, &end);
111
112 if (end != value.data() + value.length()) {
113 return Unexpected(Metadata::Error("Excepted integer literal", Metadata::Error::Type::INVALID_VALUE));
114 }
115
116 if (errno == ERANGE) {
117 errno = 0;
118 return Unexpected(Metadata::Error("Value is out of range", Metadata::Error::Type::INVALID_VALUE));
119 }
120
121 return static_cast<T>(v);
122 }
123
124 template <Value::Type type, class T = ValueTypeHelperT<type>>
CreatePrimitiveValue(const std::string_view & value,T max_value=std::numeric_limits<T>::max ())125 static Expected<ScalarValue, Metadata::Error> CreatePrimitiveValue(const std::string_view &value,
126 T max_value = std::numeric_limits<T>::max())
127 {
128 auto res = ConvertFromString<T>(value);
129 if (!res) {
130 return Unexpected(res.Error());
131 }
132
133 auto converted = res.Value();
134 if (converted > max_value) {
135 return Unexpected(Metadata::Error("Value is out of range", Metadata::Error::Type::INVALID_VALUE));
136 }
137
138 return ScalarValue::Create<type>(converted);
139 }
140
CreateValue(Value::Type type,const std::string_view & value,const std::unordered_map<std::string,std::unique_ptr<AnnotationData>> & annotation_id_map={})141 static Expected<ScalarValue, Metadata::Error> CreateValue(
142 Value::Type type, const std::string_view &value,
143 const std::unordered_map<std::string, std::unique_ptr<AnnotationData>> &annotation_id_map = {})
144 {
145 switch (type) {
146 case Value::Type::U1: {
147 return CreatePrimitiveValue<Value::Type::U1>(value, 1);
148 }
149 case Value::Type::I8: {
150 return CreatePrimitiveValue<Value::Type::I8>(value);
151 }
152 case Value::Type::U8: {
153 return CreatePrimitiveValue<Value::Type::U8>(value);
154 }
155 case Value::Type::I16: {
156 return CreatePrimitiveValue<Value::Type::I16>(value);
157 }
158 case Value::Type::U16: {
159 return CreatePrimitiveValue<Value::Type::U16>(value);
160 }
161 case Value::Type::I32: {
162 return CreatePrimitiveValue<Value::Type::I32>(value);
163 }
164 case Value::Type::U32: {
165 return CreatePrimitiveValue<Value::Type::U32>(value);
166 }
167 case Value::Type::I64: {
168 return CreatePrimitiveValue<Value::Type::I64>(value);
169 }
170 case Value::Type::U64: {
171 return CreatePrimitiveValue<Value::Type::U64>(value);
172 }
173 case Value::Type::F32: {
174 return CreatePrimitiveValue<Value::Type::F32>(value);
175 }
176 case Value::Type::F64: {
177 return CreatePrimitiveValue<Value::Type::F64>(value);
178 }
179 case Value::Type::STRING: {
180 return ScalarValue::Create<Value::Type::STRING>(value);
181 }
182 case Value::Type::RECORD: {
183 return ScalarValue::Create<Value::Type::RECORD>(Type::FromName(value));
184 }
185 case Value::Type::METHOD: {
186 return ScalarValue::Create<Value::Type::METHOD>(value);
187 }
188 case Value::Type::ENUM: {
189 return ScalarValue::Create<Value::Type::ENUM>(value);
190 }
191 case Value::Type::ANNOTATION: {
192 auto it = annotation_id_map.find(std::string(value));
193 if (it == annotation_id_map.cend()) {
194 return Unexpected(Metadata::Error("Unknown annotation id", Metadata::Error::Type::INVALID_VALUE));
195 }
196
197 auto annotation_value = it->second.get();
198 return ScalarValue::Create<Value::Type::ANNOTATION>(*annotation_value);
199 }
200 default: {
201 break;
202 }
203 }
204
205 UNREACHABLE();
206 }
207
AddValue(const std::string_view & value,const std::unordered_map<std::string,std::unique_ptr<AnnotationData>> & annotation_id_map)208 std::optional<Metadata::Error> AnnotationMetadata::AnnotationElementBuilder::AddValue(
209 const std::string_view &value,
210 const std::unordered_map<std::string, std::unique_ptr<AnnotationData>> &annotation_id_map)
211 {
212 ASSERT(type_.has_value());
213
214 auto type = type_.value();
215 if (type == Value::Type::ARRAY) {
216 ASSERT(component_type_.has_value());
217 type = component_type_.value();
218 }
219
220 auto res = CreateValue(type, value, annotation_id_map);
221 if (!res) {
222 return res.Error();
223 }
224
225 values_.push_back(res.Value());
226
227 return {};
228 }
229
Store(const std::string_view & attribute)230 std::optional<Metadata::Error> AnnotationMetadata::Store(const std::string_view &attribute)
231 {
232 if (IsParseAnnotationElement() && !annotation_element_builder_.IsCompleted()) {
233 return Error(std::string("Unexpected attribute '").append(attribute) +
234 "'. Annotation element isn't completely defined",
235 Error::Type::UNEXPECTED_ATTRIBUTE);
236 }
237
238 if (IsParseAnnotation()) {
239 ResetAnnotationBuilder();
240 }
241
242 return Metadata::Store(attribute);
243 }
244
MeetExpRecordAttribute(const std::string_view & attribute,const std::string_view & value)245 std::optional<Metadata::Error> AnnotationMetadata::MeetExpRecordAttribute(const std::string_view &attribute,
246 const std::string_view &value)
247 {
248 if (IsParseAnnotationElement() && !annotation_element_builder_.IsCompleted()) {
249 return Error(std::string("Unexpected attribute '").append(attribute) +
250 "'. Annotation element isn't completely defined",
251 Error::Type::UNEXPECTED_ATTRIBUTE);
252 }
253
254 InitializeAnnotationBuilder(value);
255
256 return {};
257 }
258
MeetExpIdAttribute(const std::string_view & attribute,const std::string_view & value)259 std::optional<Metadata::Error> AnnotationMetadata::MeetExpIdAttribute(const std::string_view &attribute,
260 const std::string_view &value)
261 {
262 if (!IsParseAnnotation() || IsParseAnnotationElement()) {
263 return Error(std::string("Unexpected attribute '").append(attribute) +
264 "'. Annotation record attribute must be defined first",
265 Error::Type::UNEXPECTED_ATTRIBUTE);
266 }
267
268 if (annotation_builder_.HasId()) {
269 return Error(std::string("Unexpected attribute '").append(attribute) +
270 "'. Annotation id attribute already defined",
271 Error::Type::UNEXPECTED_ATTRIBUTE);
272 }
273
274 annotation_builder_.SetId(value);
275
276 return {};
277 }
278
MeetExpElementNameAttribute(const std::string_view & attribute,const std::string_view & value)279 std::optional<Metadata::Error> AnnotationMetadata::MeetExpElementNameAttribute(const std::string_view &attribute,
280 const std::string_view &value)
281 {
282 if (!IsParseAnnotation()) {
283 return Error(std::string("Unexpected attribute '").append(attribute) +
284 "'. Annotation record attribute must be defined first",
285 Error::Type::UNEXPECTED_ATTRIBUTE);
286 }
287
288 if (IsParseAnnotationElement() && !annotation_element_builder_.IsCompleted()) {
289 return Error(std::string("Unexpected attribute '").append(attribute) +
290 "'. Previous annotation element isn't defined completely",
291 Error::Type::UNEXPECTED_ATTRIBUTE);
292 }
293
294 InitializeAnnotationElementBuilder(value);
295
296 return {};
297 }
298
MeetExpElementTypeAttribute(const std::string_view & attribute,const std::string_view & value)299 std::optional<Metadata::Error> AnnotationMetadata::MeetExpElementTypeAttribute(
300 const std::string_view &attribute, const std::string_view &value)
301 {
302 if (!IsParseAnnotationElement()) {
303 return Error(std::string("Unexpected attribute '").append(attribute) +
304 "'. Annotation element name attribute must be defined first",
305 Error::Type::UNEXPECTED_ATTRIBUTE);
306 }
307
308 if (annotation_element_builder_.IsTypeSet()) {
309 return Error(std::string("Unexpected attribute '").append(attribute) +
310 "'. Annotation element type attribute already defined",
311 Error::Type::UNEXPECTED_ATTRIBUTE);
312 }
313
314 annotation_element_builder_.SetType(GetType(value));
315
316 return {};
317 }
318
MeetExpElementArrayComponentTypeAttribute(const std::string_view & attribute,const std::string_view & value)319 std::optional<Metadata::Error> AnnotationMetadata::MeetExpElementArrayComponentTypeAttribute(
320 const std::string_view &attribute, const std::string_view &value)
321 {
322 if (!IsParseAnnotationElement()) {
323 return Error(std::string("Unexpected attribute '").append(attribute) +
324 "'. Annotation element name attribute must be defined first",
325 Error::Type::UNEXPECTED_ATTRIBUTE);
326 }
327
328 if (!annotation_element_builder_.IsArray()) {
329 return Error(std::string("Unexpected attribute '").append(attribute) + "'. Annotation element type isn't array",
330 Error::Type::UNEXPECTED_ATTRIBUTE);
331 }
332
333 if (annotation_element_builder_.IsComponentTypeSet()) {
334 return Error(std::string("Unexpected attribute '").append(attribute) +
335 "'. Annotation element array component type attribute already defined",
336 Error::Type::UNEXPECTED_ATTRIBUTE);
337 }
338
339 annotation_element_builder_.SetComponentType(GetType(value));
340
341 return {};
342 }
343
MeetExpElementValueAttribute(const std::string_view & attribute,const std::string_view & value)344 std::optional<Metadata::Error> AnnotationMetadata::MeetExpElementValueAttribute(const std::string_view &attribute,
345 const std::string_view &value)
346 {
347 if (!IsParseAnnotationElement()) {
348 return Error(std::string("Unexpected attribute '").append(attribute) +
349 "'. Annotation element name attribute must be defined first",
350 Error::Type::UNEXPECTED_ATTRIBUTE);
351 }
352
353 if (!annotation_element_builder_.IsTypeSet()) {
354 return Error(std::string("Unexpected attribute '").append(attribute) +
355 "'. Annotation element type attribute isn't defined",
356 Error::Type::UNEXPECTED_ATTRIBUTE);
357 }
358
359 if (annotation_element_builder_.IsArray() && !annotation_element_builder_.IsComponentTypeSet()) {
360 return Error(std::string("Unexpected attribute '").append(attribute) +
361 "'. Annotation element array component type attribute isn't defined",
362 Error::Type::UNEXPECTED_ATTRIBUTE);
363 }
364
365 if (!annotation_element_builder_.IsArray() && annotation_element_builder_.IsCompleted()) {
366 return Error(std::string("Unexpected attribute '").append(attribute) +
367 "'. Annotation element is completely defined",
368 Error::Type::UNEXPECTED_ATTRIBUTE);
369 }
370
371 return annotation_element_builder_.AddValue(value, id_map_);
372 }
373
StoreValue(const std::string_view & attribute,const std::string_view & value)374 std::optional<Metadata::Error> AnnotationMetadata::StoreValue(const std::string_view &attribute,
375 const std::string_view &value)
376 {
377 auto err = Metadata::StoreValue(attribute, value);
378 if (err) {
379 return err;
380 }
381
382 if (IsAnnotationRecordAttribute(attribute)) {
383 return MeetExpRecordAttribute(attribute, value);
384 }
385
386 if (IsAnnotationIdAttribute(attribute)) {
387 return MeetExpIdAttribute(attribute, value);
388 }
389
390 if (IsAnnotationElementNameAttribute(attribute)) {
391 return MeetExpElementNameAttribute(attribute, value);
392 }
393
394 if (IsAnnotationElementTypeAttribute(attribute)) {
395 return MeetExpElementTypeAttribute(attribute, value);
396 }
397
398 if (IsAnnotationElementArrayComponentTypeAttribute(attribute)) {
399 return MeetExpElementArrayComponentTypeAttribute(attribute, value);
400 }
401
402 if (IsAnnotationElementValueAttribute(attribute)) {
403 return MeetExpElementValueAttribute(attribute, value);
404 }
405
406 if (IsParseAnnotationElement() && !annotation_element_builder_.IsCompleted()) {
407 return Error(std::string("Unexpected attribute '").append(attribute) +
408 "'. Annotation element isn't completely defined",
409 Error::Type::UNEXPECTED_ATTRIBUTE);
410 }
411
412 if (IsParseAnnotation()) {
413 ResetAnnotationBuilder();
414 }
415
416 return {};
417 }
418
ValidateData()419 std::optional<Metadata::Error> AnnotationMetadata::ValidateData()
420 {
421 if (IsParseAnnotationElement() && !annotation_element_builder_.IsCompleted()) {
422 return Error("Annotation element isn't completely defined", Error::Type::MISSING_ATTRIBUTE);
423 }
424
425 if (IsParseAnnotation()) {
426 ResetAnnotationBuilder();
427 }
428
429 return Metadata::ValidateData();
430 }
431
GetBase() const432 std::string RecordMetadata::GetBase() const
433 {
434 return "";
435 }
436
GetInterfaces() const437 std::vector<std::string> RecordMetadata::GetInterfaces() const
438 {
439 return {};
440 }
441
IsAnnotation() const442 bool RecordMetadata::IsAnnotation() const
443 {
444 return false;
445 }
446
IsRuntimeAnnotation() const447 bool RecordMetadata::IsRuntimeAnnotation() const
448 {
449 return false;
450 }
451
IsTypeAnnotation() const452 bool RecordMetadata::IsTypeAnnotation() const
453 {
454 return false;
455 }
456
IsRuntimeTypeAnnotation() const457 bool RecordMetadata::IsRuntimeTypeAnnotation() const
458 {
459 return false;
460 }
461
IsCtor() const462 bool FunctionMetadata::IsCtor() const
463 {
464 return GetAttribute("ctor");
465 }
466
IsCctor() const467 bool FunctionMetadata::IsCctor() const
468 {
469 return GetAttribute("cctor");
470 }
471
StoreValue(const std::string_view & attribute,const std::string_view & value)472 std::optional<Metadata::Error> FieldMetadata::StoreValue(const std::string_view &attribute,
473 const std::string_view &value)
474 {
475 auto err = ItemMetadata::StoreValue(attribute, value);
476 if (err) {
477 return err;
478 }
479
480 if (IsValueAttribute(attribute)) {
481 Value::Type value_type;
482 if (!field_type_.IsObject()) {
483 value_type = GetType(field_type_.GetName());
484 } else {
485 value_type = Value::Type::STRING;
486 }
487
488 auto res = CreateValue(value_type, value);
489 if (!res) {
490 return res.Error();
491 }
492
493 value_ = res.Value();
494 }
495
496 return {};
497 }
498
499 #include <meta_gen.h>
500
501 } // namespace panda::pandasm
502