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