• 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 <stdlib.h>
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 
142     if (converted > max_value) {
143         return Unexpected(Metadata::Error("Value is out of range", Metadata::Error::Type::INVALID_VALUE));
144     }
145 
146     return ScalarValue::Create<type>(converted);
147 }
148 
CreateValue(Value::Type type,std::string_view value,const std::unordered_map<std::string,std::unique_ptr<AnnotationData>> & annotation_id_map={})149 static Expected<ScalarValue, Metadata::Error> CreateValue(
150     Value::Type type, std::string_view value,
151     const std::unordered_map<std::string, std::unique_ptr<AnnotationData>> &annotation_id_map = {})
152 {
153     switch (type) {
154         case Value::Type::U1: {
155             return CreatePrimitiveValue<Value::Type::U1>(value, 1);
156         }
157         case Value::Type::I8: {
158             return CreatePrimitiveValue<Value::Type::I8>(value);
159         }
160         case Value::Type::U8: {
161             return CreatePrimitiveValue<Value::Type::U8>(value);
162         }
163         case Value::Type::I16: {
164             return CreatePrimitiveValue<Value::Type::I16>(value);
165         }
166         case Value::Type::U16: {
167             return CreatePrimitiveValue<Value::Type::U16>(value);
168         }
169         case Value::Type::I32: {
170             return CreatePrimitiveValue<Value::Type::I32>(value);
171         }
172         case Value::Type::U32: {
173             return CreatePrimitiveValue<Value::Type::U32>(value);
174         }
175         case Value::Type::I64: {
176             return CreatePrimitiveValue<Value::Type::I64>(value);
177         }
178         case Value::Type::U64: {
179             return CreatePrimitiveValue<Value::Type::U64>(value);
180         }
181         case Value::Type::F32: {
182             return CreatePrimitiveValue<Value::Type::F32>(value);
183         }
184         case Value::Type::F64: {
185             return CreatePrimitiveValue<Value::Type::F64>(value);
186         }
187         case Value::Type::STRING: {
188             return ScalarValue::Create<Value::Type::STRING>(value);
189         }
190         case Value::Type::RECORD: {
191             return ScalarValue::Create<Value::Type::RECORD>(Type::FromName(value));
192         }
193         case Value::Type::METHOD: {
194             return ScalarValue::Create<Value::Type::METHOD>(value);
195         }
196         case Value::Type::ENUM: {
197             return ScalarValue::Create<Value::Type::ENUM>(value);
198         }
199         case Value::Type::ANNOTATION: {
200             auto it = annotation_id_map.find(std::string(value));
201             if (it == annotation_id_map.cend()) {
202                 return Unexpected(Metadata::Error("Unknown annotation id", Metadata::Error::Type::INVALID_VALUE));
203             }
204 
205             auto annotation_value = it->second.get();
206             return ScalarValue::Create<Value::Type::ANNOTATION>(*annotation_value);
207         }
208         default: {
209             break;
210         }
211     }
212 
213     UNREACHABLE();
214 }
215 
AddValue(std::string_view value,const std::unordered_map<std::string,std::unique_ptr<AnnotationData>> & annotation_id_map)216 std::optional<Metadata::Error> AnnotationMetadata::AnnotationElementBuilder::AddValue(
217     std::string_view value, 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 
223     if (type == Value::Type::ARRAY) {
224         ASSERT(component_type_.has_value());
225         type = component_type_.value();
226     }
227 
228     auto res = CreateValue(type, value, annotation_id_map);
229     if (!res) {
230         return res.Error();
231     }
232 
233     values_.push_back(res.Value());
234 
235     return {};
236 }
237 
Store(std::string_view attribute)238 std::optional<Metadata::Error> AnnotationMetadata::Store(std::string_view attribute)
239 {
240     if (IsParseAnnotationElement() && !annotation_element_builder_.IsCompleted()) {
241         return Error(std::string("Unexpected attribute '").append(attribute) +
242                          "'. Annotation element isn't completely defined",
243                      Error::Type::UNEXPECTED_ATTRIBUTE);
244     }
245 
246     if (IsParseAnnotation()) {
247         ResetAnnotationBuilder();
248     }
249 
250     return Metadata::Store(attribute);
251 }
252 
MeetExpRecordAttribute(std::string_view attribute,std::string_view value)253 std::optional<Metadata::Error> AnnotationMetadata::MeetExpRecordAttribute(std::string_view attribute,
254                                                                           std::string_view value)
255 {
256     if (IsParseAnnotationElement() && !annotation_element_builder_.IsCompleted()) {
257         return Error(std::string("Unexpected attribute '").append(attribute) +
258                          "'. Annotation element isn't completely defined",
259                      Error::Type::UNEXPECTED_ATTRIBUTE);
260     }
261 
262     InitializeAnnotationBuilder(value);
263 
264     return {};
265 }
266 
MeetExpIdAttribute(std::string_view attribute,std::string_view value)267 std::optional<Metadata::Error> AnnotationMetadata::MeetExpIdAttribute(std::string_view attribute,
268                                                                       std::string_view value)
269 {
270     if (!IsParseAnnotation() || IsParseAnnotationElement()) {
271         return Error(std::string("Unexpected attribute '").append(attribute) +
272                          "'. Annotation record attribute must be defined first",
273                      Error::Type::UNEXPECTED_ATTRIBUTE);
274     }
275 
276     if (annotation_builder_.HasId()) {
277         return Error(std::string("Unexpected attribute '").append(attribute) +
278                          "'. Annotation id attribute already defined",
279                      Error::Type::UNEXPECTED_ATTRIBUTE);
280     }
281 
282     annotation_builder_.SetId(value);
283 
284     return {};
285 }
286 
MeetExpElementNameAttribute(std::string_view attribute,std::string_view value)287 std::optional<Metadata::Error> AnnotationMetadata::MeetExpElementNameAttribute(std::string_view attribute,
288                                                                                std::string_view value)
289 {
290     if (!IsParseAnnotation()) {
291         return Error(std::string("Unexpected attribute '").append(attribute) +
292                          "'. Annotation record attribute must be defined first",
293                      Error::Type::UNEXPECTED_ATTRIBUTE);
294     }
295 
296     if (IsParseAnnotationElement() && !annotation_element_builder_.IsCompleted()) {
297         return Error(std::string("Unexpected attribute '").append(attribute) +
298                          "'. Previous annotation element isn't defined completely",
299                      Error::Type::UNEXPECTED_ATTRIBUTE);
300     }
301 
302     InitializeAnnotationElementBuilder(value);
303 
304     return {};
305 }
306 
MeetExpElementTypeAttribute(std::string_view attribute,std::string_view value)307 std::optional<Metadata::Error> AnnotationMetadata::MeetExpElementTypeAttribute(std::string_view attribute,
308                                                                                std::string_view value)
309 {
310     if (!IsParseAnnotationElement()) {
311         return Error(std::string("Unexpected attribute '").append(attribute) +
312                          "'. Annotation element name attribute must be defined first",
313                      Error::Type::UNEXPECTED_ATTRIBUTE);
314     }
315 
316     if (annotation_element_builder_.IsTypeSet()) {
317         return Error(std::string("Unexpected attribute '").append(attribute) +
318                          "'. Annotation element type attribute already defined",
319                      Error::Type::UNEXPECTED_ATTRIBUTE);
320     }
321 
322     annotation_element_builder_.SetType(GetType(value));
323 
324     return {};
325 }
326 
MeetExpElementArrayComponentTypeAttribute(std::string_view attribute,std::string_view value)327 std::optional<Metadata::Error> AnnotationMetadata::MeetExpElementArrayComponentTypeAttribute(std::string_view attribute,
328                                                                                              std::string_view value)
329 {
330     if (!IsParseAnnotationElement()) {
331         return Error(std::string("Unexpected attribute '").append(attribute) +
332                          "'. Annotation element name attribute must be defined first",
333                      Error::Type::UNEXPECTED_ATTRIBUTE);
334     }
335 
336     if (!annotation_element_builder_.IsArray()) {
337         return Error(std::string("Unexpected attribute '").append(attribute) + "'. Annotation element type isn't array",
338                      Error::Type::UNEXPECTED_ATTRIBUTE);
339     }
340 
341     if (annotation_element_builder_.IsComponentTypeSet()) {
342         return Error(std::string("Unexpected attribute '").append(attribute) +
343                          "'. Annotation element array component type attribute already defined",
344                      Error::Type::UNEXPECTED_ATTRIBUTE);
345     }
346 
347     annotation_element_builder_.SetComponentType(GetType(value));
348 
349     return {};
350 }
351 
MeetExpElementValueAttribute(std::string_view attribute,std::string_view value)352 std::optional<Metadata::Error> AnnotationMetadata::MeetExpElementValueAttribute(std::string_view attribute,
353                                                                                 std::string_view value)
354 {
355     if (!IsParseAnnotationElement()) {
356         return Error(std::string("Unexpected attribute '").append(attribute) +
357                          "'. Annotation element name attribute must be defined first",
358                      Error::Type::UNEXPECTED_ATTRIBUTE);
359     }
360 
361     if (!annotation_element_builder_.IsTypeSet()) {
362         return Error(std::string("Unexpected attribute '").append(attribute) +
363                          "'. Annotation element type attribute isn't defined",
364                      Error::Type::UNEXPECTED_ATTRIBUTE);
365     }
366 
367     if (annotation_element_builder_.IsArray() && !annotation_element_builder_.IsComponentTypeSet()) {
368         return Error(std::string("Unexpected attribute '").append(attribute) +
369                          "'. Annotation element array component type attribute isn't defined",
370                      Error::Type::UNEXPECTED_ATTRIBUTE);
371     }
372 
373     if (!annotation_element_builder_.IsArray() && annotation_element_builder_.IsCompleted()) {
374         return Error(std::string("Unexpected attribute '").append(attribute) +
375                          "'. Annotation element is completely defined",
376                      Error::Type::UNEXPECTED_ATTRIBUTE);
377     }
378 
379     return annotation_element_builder_.AddValue(value, id_map_);
380 }
381 
StoreValue(std::string_view attribute,std::string_view value)382 std::optional<Metadata::Error> AnnotationMetadata::StoreValue(std::string_view attribute, 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(std::string_view attribute,std::string_view value)479 std::optional<Metadata::Error> FieldMetadata::StoreValue(std::string_view attribute, std::string_view value)
480 {
481     auto err = ItemMetadata::StoreValue(attribute, value);
482     if (err) {
483         return err;
484     }
485 
486     if (IsValueAttribute(attribute)) {
487         Value::Type value_type;
488         if (!field_type_.IsObject()) {
489             value_type = GetType(field_type_.GetName());
490         } else {
491             value_type = Value::Type::STRING;
492         }
493 
494         auto res = CreateValue(value_type, value);
495         if (!res) {
496             return res.Error();
497         }
498 
499         value_ = res.Value();
500     }
501 
502     return {};
503 }
504 
505 #include <meta_gen.h>
506 
507 }  // namespace panda::pandasm
508