• 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 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