• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2024 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 ark::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 ark::pandasm::Value::Type GetType(std::string_view value)
49 {
50     using VType = ark::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         {"record", 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     // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
120     if (end != value.data() + value.length()) {
121         return Unexpected(Metadata::Error("Excepted integer literal", Metadata::Error::Type::INVALID_VALUE));
122     }
123 
124     if (errno == ERANGE) {
125         errno = 0;
126         return Unexpected(Metadata::Error("Value is out of range", Metadata::Error::Type::INVALID_VALUE));
127     }
128 
129     return static_cast<T>(v);
130 }
131 
132 template <Value::Type TYPE, class T = ValueTypeHelperT<TYPE>>
CreatePrimitiveValue(std::string_view value,T maxValue=std::numeric_limits<T>::max ())133 static Expected<ScalarValue, Metadata::Error> CreatePrimitiveValue(std::string_view value,
134                                                                    T maxValue = std::numeric_limits<T>::max())
135 {
136     auto res = ConvertFromString<T>(value);
137     if (!res) {
138         return Unexpected(res.Error());
139     }
140 
141     auto converted = res.Value();
142     if (converted > maxValue) {
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 
149 // CC-OFFNXT(G.FUN.01-CPP, huge_method[C++]) big switch case
CreateValue(Value::Type type,std::string_view value,const std::unordered_map<std::string,std::unique_ptr<AnnotationData>> & annotationIdMap={})150 static Expected<ScalarValue, Metadata::Error> CreateValue(
151     Value::Type type, std::string_view value,
152     const std::unordered_map<std::string, std::unique_ptr<AnnotationData>> &annotationIdMap = {})
153 {
154     switch (type) {
155         case Value::Type::U1: {
156             return CreatePrimitiveValue<Value::Type::U1>(value, 1);
157         }
158         case Value::Type::I8: {
159             return CreatePrimitiveValue<Value::Type::I8>(value);
160         }
161         case Value::Type::U8: {
162             return CreatePrimitiveValue<Value::Type::U8>(value);
163         }
164         case Value::Type::I16: {
165             return CreatePrimitiveValue<Value::Type::I16>(value);
166         }
167         case Value::Type::U16: {
168             return CreatePrimitiveValue<Value::Type::U16>(value);
169         }
170         case Value::Type::I32: {
171             return CreatePrimitiveValue<Value::Type::I32>(value);
172         }
173         case Value::Type::U32: {
174             return CreatePrimitiveValue<Value::Type::U32>(value);
175         }
176         case Value::Type::I64: {
177             return CreatePrimitiveValue<Value::Type::I64>(value);
178         }
179         case Value::Type::U64: {
180             return CreatePrimitiveValue<Value::Type::U64>(value);
181         }
182         case Value::Type::F32: {
183             return CreatePrimitiveValue<Value::Type::F32>(value);
184         }
185         case Value::Type::F64: {
186             return CreatePrimitiveValue<Value::Type::F64>(value);
187         }
188         case Value::Type::STRING: {
189             return ScalarValue::Create<Value::Type::STRING>(value);
190         }
191         case Value::Type::RECORD: {
192             return ScalarValue::Create<Value::Type::RECORD>(Type::FromName(value));
193         }
194         case Value::Type::METHOD: {
195             return ScalarValue::Create<Value::Type::METHOD>(value);
196         }
197         case Value::Type::ENUM: {
198             return ScalarValue::Create<Value::Type::ENUM>(value);
199         }
200         case Value::Type::ANNOTATION: {
201             auto it = annotationIdMap.find(std::string(value));
202             if (it == annotationIdMap.cend()) {
203                 return Unexpected(Metadata::Error("Unknown annotation id", Metadata::Error::Type::INVALID_VALUE));
204             }
205 
206             auto annotationValue = it->second.get();
207             return ScalarValue::Create<Value::Type::ANNOTATION>(*annotationValue);
208         }
209         default: {
210             break;
211         }
212     }
213 
214     UNREACHABLE();
215 }
216 
AddValue(std::string_view value,const std::unordered_map<std::string,std::unique_ptr<AnnotationData>> & annotationIdMap)217 std::optional<Metadata::Error> AnnotationMetadata::AnnotationElementBuilder::AddValue(
218     std::string_view value, const std::unordered_map<std::string, std::unique_ptr<AnnotationData>> &annotationIdMap)
219 {
220     ASSERT(type_.has_value());
221 
222     auto type = type_.value();
223     if (type == Value::Type::ARRAY) {
224         ASSERT(componentType_.has_value());
225         type = componentType_.value();
226     }
227 
228     auto res = CreateValue(type, value, annotationIdMap);
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() && !annotationElementBuilder_.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() && !annotationElementBuilder_.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 (annotationBuilder_.HasId()) {
277         return Error(std::string("Unexpected attribute '").append(attribute) +
278                          "'. Annotation id attribute already defined",
279                      Error::Type::UNEXPECTED_ATTRIBUTE);
280     }
281 
282     annotationBuilder_.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() && !annotationElementBuilder_.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 (annotationElementBuilder_.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     annotationElementBuilder_.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 (!annotationElementBuilder_.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 (annotationElementBuilder_.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     annotationElementBuilder_.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 (!annotationElementBuilder_.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 (annotationElementBuilder_.IsArray() && !annotationElementBuilder_.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 (!annotationElementBuilder_.IsArray() && annotationElementBuilder_.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 annotationElementBuilder_.AddValue(value, idMap_);
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() && !annotationElementBuilder_.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() && !annotationElementBuilder_.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     auto base = GetAttributeValue("extends");
442     if (base) {
443         return base.value();
444     }
445 
446     return "";
447 }
448 
GetInterfaces() const449 std::vector<std::string> RecordMetadata::GetInterfaces() const
450 {
451     return {};
452 }
453 
IsAnnotation() const454 bool RecordMetadata::IsAnnotation() const
455 {
456     return false;
457 }
458 
IsRuntimeAnnotation() const459 bool RecordMetadata::IsRuntimeAnnotation() const
460 {
461     return false;
462 }
463 
IsTypeAnnotation() const464 bool RecordMetadata::IsTypeAnnotation() const
465 {
466     return false;
467 }
468 
IsRuntimeTypeAnnotation() const469 bool RecordMetadata::IsRuntimeTypeAnnotation() const
470 {
471     return false;
472 }
473 
HasImplementation() const474 bool FunctionMetadata::HasImplementation() const
475 {
476     return ((ACC_ABSTRACT & GetAccessFlags()) == 0) && ((ACC_NATIVE & GetAccessFlags()) == 0);
477 }
478 
IsCtor() const479 bool FunctionMetadata::IsCtor() const
480 {
481     return GetAttribute("ctor");
482 }
483 
IsCctor() const484 bool FunctionMetadata::IsCctor() const
485 {
486     return GetAttribute("cctor");
487 }
488 
StoreValue(std::string_view attribute,std::string_view value)489 std::optional<Metadata::Error> FieldMetadata::StoreValue(std::string_view attribute, std::string_view value)
490 {
491     auto err = ItemMetadata::StoreValue(attribute, value);
492     if (err) {
493         return err;
494     }
495 
496     if (IsValueAttribute(attribute)) {
497         Value::Type valueType;
498         if (!fieldType_.IsObject()) {
499             valueType = GetType(fieldType_.GetName());
500         } else {
501             valueType = Value::Type::STRING;
502         }
503 
504         auto res = CreateValue(valueType, value);
505         if (!res) {
506             return res.Error();
507         }
508 
509         value_ = res.Value();
510     }
511 
512     return {};
513 }
514 
515 #include <meta_gen.h>
516 
517 }  // namespace ark::pandasm
518