• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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(std::string_view value) const27 std::optional<Metadata::Error> Metadata::ValidateSize(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(std::string_view value)48 static panda::pandasm::Value::Type GetType(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(std::string_view value,char ** end)63 static T ConvertFromString(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(std::string_view value,char ** end)88 int64_t ConvertFromString(std::string_view value, char **end)
89 {
90     return static_cast<int64_t>(strtoll(value.data(), end, 0));
91 }
92 
93 template <>
ConvertFromString(std::string_view value,char ** end)94 uint64_t ConvertFromString(std::string_view value, char **end)
95 {
96     return static_cast<uint64_t>(strtoull(value.data(), end, 0));
97 }
98 
99 template <>
ConvertFromString(std::string_view value,char ** end)100 float ConvertFromString(std::string_view value, char **end)
101 {
102     return strtof(value.data(), end);
103 }
104 
105 template <>
ConvertFromString(std::string_view value,char ** end)106 double ConvertFromString(std::string_view value, char **end)
107 {
108     return strtod(value.data(), end);
109 }
110 
111 template <class T>
ConvertFromString(std::string_view value)112 static Expected<T, Metadata::Error> ConvertFromString(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(std::string_view value,T max_value=std::numeric_limits<T>::max ())132 static Expected<ScalarValue, Metadata::Error> CreatePrimitiveValue(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,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, 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(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     std::string_view value, const std::unordered_map<std::string, std::unique_ptr<AnnotationData>> &annotation_id_map)
217 {
218     ASSERT(type_.has_value());
219 
220     auto type = type_.value();
221     if (type == Value::Type::ARRAY) {
222         ASSERT(component_type_.has_value());
223         type = component_type_.value();
224     }
225 
226     auto res = CreateValue(type, value, annotation_id_map);
227     if (!res) {
228         return res.Error();
229     }
230 
231     values_.push_back(res.Value());
232 
233     return {};
234 }
235 
Store(std::string_view attribute)236 std::optional<Metadata::Error> AnnotationMetadata::Store(std::string_view attribute)
237 {
238     if (IsParseAnnotationElement() && !annotation_element_builder_.IsCompleted()) {
239         return Error(std::string("Unexpected attribute '").append(attribute) +
240                          "'. Annotation element isn't completely defined",
241                      Error::Type::UNEXPECTED_ATTRIBUTE);
242     }
243 
244     if (IsParseAnnotation()) {
245         ResetAnnotationBuilder();
246     }
247 
248     return Metadata::Store(attribute);
249 }
250 
MeetExpRecordAttribute(std::string_view attribute,std::string_view value)251 std::optional<Metadata::Error> AnnotationMetadata::MeetExpRecordAttribute(std::string_view attribute,
252                                                                           std::string_view value)
253 {
254     if (IsParseAnnotationElement() && !annotation_element_builder_.IsCompleted()) {
255         return Error(std::string("Unexpected attribute '").append(attribute) +
256                          "'. Annotation element isn't completely defined",
257                      Error::Type::UNEXPECTED_ATTRIBUTE);
258     }
259 
260     InitializeAnnotationBuilder(value);
261 
262     return {};
263 }
264 
MeetExpIdAttribute(std::string_view attribute,std::string_view value)265 std::optional<Metadata::Error> AnnotationMetadata::MeetExpIdAttribute(std::string_view attribute,
266                                                                       std::string_view value)
267 {
268     if (!IsParseAnnotation() || IsParseAnnotationElement()) {
269         return Error(std::string("Unexpected attribute '").append(attribute) +
270                          "'. Annotation record attribute must be defined first",
271                      Error::Type::UNEXPECTED_ATTRIBUTE);
272     }
273 
274     if (annotation_builder_.HasId()) {
275         return Error(std::string("Unexpected attribute '").append(attribute) +
276                          "'. Annotation id attribute already defined",
277                      Error::Type::UNEXPECTED_ATTRIBUTE);
278     }
279 
280     annotation_builder_.SetId(value);
281 
282     return {};
283 }
284 
MeetExpElementNameAttribute(std::string_view attribute,std::string_view value)285 std::optional<Metadata::Error> AnnotationMetadata::MeetExpElementNameAttribute(std::string_view attribute,
286                                                                                std::string_view value)
287 {
288     if (!IsParseAnnotation()) {
289         return Error(std::string("Unexpected attribute '").append(attribute) +
290                          "'. Annotation record attribute must be defined first",
291                      Error::Type::UNEXPECTED_ATTRIBUTE);
292     }
293 
294     if (IsParseAnnotationElement() && !annotation_element_builder_.IsCompleted()) {
295         return Error(std::string("Unexpected attribute '").append(attribute) +
296                          "'. Previous annotation element isn't defined completely",
297                      Error::Type::UNEXPECTED_ATTRIBUTE);
298     }
299 
300     InitializeAnnotationElementBuilder(value);
301 
302     return {};
303 }
304 
MeetExpElementTypeAttribute(std::string_view attribute,std::string_view value)305 std::optional<Metadata::Error> AnnotationMetadata::MeetExpElementTypeAttribute(std::string_view attribute,
306                                                                                std::string_view value)
307 {
308     if (!IsParseAnnotationElement()) {
309         return Error(std::string("Unexpected attribute '").append(attribute) +
310                          "'. Annotation element name attribute must be defined first",
311                      Error::Type::UNEXPECTED_ATTRIBUTE);
312     }
313 
314     if (annotation_element_builder_.IsTypeSet()) {
315         return Error(std::string("Unexpected attribute '").append(attribute) +
316                          "'. Annotation element type attribute already defined",
317                      Error::Type::UNEXPECTED_ATTRIBUTE);
318     }
319 
320     annotation_element_builder_.SetType(GetType(value));
321 
322     return {};
323 }
324 
MeetExpElementArrayComponentTypeAttribute(std::string_view attribute,std::string_view value)325 std::optional<Metadata::Error> AnnotationMetadata::MeetExpElementArrayComponentTypeAttribute(std::string_view attribute,
326                                                                                              std::string_view value)
327 {
328     if (!IsParseAnnotationElement()) {
329         return Error(std::string("Unexpected attribute '").append(attribute) +
330                          "'. Annotation element name attribute must be defined first",
331                      Error::Type::UNEXPECTED_ATTRIBUTE);
332     }
333 
334     if (!annotation_element_builder_.IsArray()) {
335         return Error(std::string("Unexpected attribute '").append(attribute) + "'. Annotation element type isn't array",
336                      Error::Type::UNEXPECTED_ATTRIBUTE);
337     }
338 
339     if (annotation_element_builder_.IsComponentTypeSet()) {
340         return Error(std::string("Unexpected attribute '").append(attribute) +
341                          "'. Annotation element array component type attribute already defined",
342                      Error::Type::UNEXPECTED_ATTRIBUTE);
343     }
344 
345     annotation_element_builder_.SetComponentType(GetType(value));
346 
347     return {};
348 }
349 
MeetExpElementValueAttribute(std::string_view attribute,std::string_view value)350 std::optional<Metadata::Error> AnnotationMetadata::MeetExpElementValueAttribute(std::string_view attribute,
351                                                                                 std::string_view value)
352 {
353     if (!IsParseAnnotationElement()) {
354         return Error(std::string("Unexpected attribute '").append(attribute) +
355                          "'. Annotation element name attribute must be defined first",
356                      Error::Type::UNEXPECTED_ATTRIBUTE);
357     }
358 
359     if (!annotation_element_builder_.IsTypeSet()) {
360         return Error(std::string("Unexpected attribute '").append(attribute) +
361                          "'. Annotation element type attribute isn't defined",
362                      Error::Type::UNEXPECTED_ATTRIBUTE);
363     }
364 
365     if (annotation_element_builder_.IsArray() && !annotation_element_builder_.IsComponentTypeSet()) {
366         return Error(std::string("Unexpected attribute '").append(attribute) +
367                          "'. Annotation element array component type attribute isn't defined",
368                      Error::Type::UNEXPECTED_ATTRIBUTE);
369     }
370 
371     if (!annotation_element_builder_.IsArray() && annotation_element_builder_.IsCompleted()) {
372         return Error(std::string("Unexpected attribute '").append(attribute) +
373                          "'. Annotation element is completely defined",
374                      Error::Type::UNEXPECTED_ATTRIBUTE);
375     }
376 
377     return annotation_element_builder_.AddValue(value, id_map_);
378 }
379 
StoreValue(std::string_view attribute,std::string_view value)380 std::optional<Metadata::Error> AnnotationMetadata::StoreValue(std::string_view attribute, std::string_view value)
381 {
382     auto err = Metadata::StoreValue(attribute, value);
383     if (err) {
384         return err;
385     }
386 
387     if (IsAnnotationRecordAttribute(attribute)) {
388         return MeetExpRecordAttribute(attribute, value);
389     }
390 
391     if (IsAnnotationIdAttribute(attribute)) {
392         return MeetExpIdAttribute(attribute, value);
393     }
394 
395     if (IsAnnotationElementNameAttribute(attribute)) {
396         return MeetExpElementNameAttribute(attribute, value);
397     }
398 
399     if (IsAnnotationElementTypeAttribute(attribute)) {
400         return MeetExpElementTypeAttribute(attribute, value);
401     }
402 
403     if (IsAnnotationElementArrayComponentTypeAttribute(attribute)) {
404         return MeetExpElementArrayComponentTypeAttribute(attribute, value);
405     }
406 
407     if (IsAnnotationElementValueAttribute(attribute)) {
408         return MeetExpElementValueAttribute(attribute, value);
409     }
410 
411     if (IsParseAnnotationElement() && !annotation_element_builder_.IsCompleted()) {
412         return Error(std::string("Unexpected attribute '").append(attribute) +
413                          "'. Annotation element isn't completely defined",
414                      Error::Type::UNEXPECTED_ATTRIBUTE);
415     }
416 
417     if (IsParseAnnotation()) {
418         ResetAnnotationBuilder();
419     }
420 
421     return {};
422 }
423 
ValidateData()424 std::optional<Metadata::Error> AnnotationMetadata::ValidateData()
425 {
426     if (IsParseAnnotationElement() && !annotation_element_builder_.IsCompleted()) {
427         return Error("Annotation element isn't completely defined", Error::Type::MISSING_ATTRIBUTE);
428     }
429 
430     if (IsParseAnnotation()) {
431         ResetAnnotationBuilder();
432     }
433 
434     return Metadata::ValidateData();
435 }
436 
GetBase() const437 std::string RecordMetadata::GetBase() const
438 {
439     return "";
440 }
441 
GetInterfaces() const442 std::vector<std::string> RecordMetadata::GetInterfaces() const
443 {
444     return {};
445 }
446 
IsAnnotation() const447 bool RecordMetadata::IsAnnotation() const
448 {
449     return false;
450 }
451 
IsRuntimeAnnotation() const452 bool RecordMetadata::IsRuntimeAnnotation() const
453 {
454     return false;
455 }
456 
IsTypeAnnotation() const457 bool RecordMetadata::IsTypeAnnotation() const
458 {
459     return false;
460 }
461 
IsRuntimeTypeAnnotation() const462 bool RecordMetadata::IsRuntimeTypeAnnotation() const
463 {
464     return false;
465 }
466 
IsCtor() const467 bool FunctionMetadata::IsCtor() const
468 {
469     return GetAttribute("ctor");
470 }
471 
IsCctor() const472 bool FunctionMetadata::IsCctor() const
473 {
474     return GetAttribute("cctor");
475 }
476 
StoreValue(std::string_view attribute,std::string_view value)477 std::optional<Metadata::Error> FieldMetadata::StoreValue(std::string_view attribute, std::string_view value)
478 {
479     auto err = ItemMetadata::StoreValue(attribute, value);
480     if (err) {
481         return err;
482     }
483 
484     if (IsValueAttribute(attribute)) {
485         Value::Type value_type;
486         if (!field_type_.IsObject()) {
487             value_type = GetType(field_type_.GetName());
488         } else {
489             value_type = Value::Type::STRING;
490         }
491 
492         auto res = CreateValue(value_type, value);
493         if (!res) {
494             return res.Error();
495         }
496 
497         value_ = res.Value();
498     }
499 
500     return {};
501 }
502 
503 #include <meta_gen.h>
504 
505 }  // namespace panda::pandasm
506