• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2025 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() && !GetOrCreateAnnotationElementBuilder()->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() && !GetOrCreateAnnotationElementBuilder()->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 (GetOrCreateAnnotationBuilder()->HasId()) {
277         return Error(std::string("Unexpected attribute '").append(attribute) +
278                          "'. Annotation id attribute already defined",
279                      Error::Type::UNEXPECTED_ATTRIBUTE);
280     }
281 
282     GetOrCreateAnnotationBuilder()->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() && !GetOrCreateAnnotationElementBuilder()->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 (GetOrCreateAnnotationElementBuilder()->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     GetOrCreateAnnotationElementBuilder()->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 (!GetOrCreateAnnotationElementBuilder()->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 (GetOrCreateAnnotationElementBuilder()->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     GetOrCreateAnnotationElementBuilder()->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 (!GetOrCreateAnnotationElementBuilder()->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 (GetOrCreateAnnotationElementBuilder()->IsArray() &&
368         !GetOrCreateAnnotationElementBuilder()->IsComponentTypeSet()) {
369         return Error(std::string("Unexpected attribute '").append(attribute) +
370                          "'. Annotation element array component type attribute isn't defined",
371                      Error::Type::UNEXPECTED_ATTRIBUTE);
372     }
373 
374     if (!GetOrCreateAnnotationElementBuilder()->IsArray() && GetOrCreateAnnotationElementBuilder()->IsCompleted()) {
375         return Error(std::string("Unexpected attribute '").append(attribute) +
376                          "'. Annotation element is completely defined",
377                      Error::Type::UNEXPECTED_ATTRIBUTE);
378     }
379 
380     return GetOrCreateAnnotationElementBuilder()->AddValue(value, idMap_);
381 }
382 
StoreValue(std::string_view attribute,std::string_view value)383 std::optional<Metadata::Error> AnnotationMetadata::StoreValue(std::string_view attribute, std::string_view value)
384 {
385     auto err = Metadata::StoreValue(attribute, value);
386     if (err) {
387         return err;
388     }
389 
390     if (IsAnnotationRecordAttribute(attribute)) {
391         return MeetExpRecordAttribute(attribute, value);
392     }
393 
394     if (IsAnnotationIdAttribute(attribute)) {
395         return MeetExpIdAttribute(attribute, value);
396     }
397 
398     if (IsAnnotationElementNameAttribute(attribute)) {
399         return MeetExpElementNameAttribute(attribute, value);
400     }
401 
402     if (IsAnnotationElementTypeAttribute(attribute)) {
403         return MeetExpElementTypeAttribute(attribute, value);
404     }
405 
406     if (IsAnnotationElementArrayComponentTypeAttribute(attribute)) {
407         return MeetExpElementArrayComponentTypeAttribute(attribute, value);
408     }
409 
410     if (IsAnnotationElementValueAttribute(attribute)) {
411         return MeetExpElementValueAttribute(attribute, value);
412     }
413 
414     if (IsParseAnnotationElement() && !GetOrCreateAnnotationElementBuilder()->IsCompleted()) {
415         return Error(std::string("Unexpected attribute '").append(attribute) +
416                          "'. Annotation element isn't completely defined",
417                      Error::Type::UNEXPECTED_ATTRIBUTE);
418     }
419 
420     if (IsParseAnnotation()) {
421         ResetAnnotationBuilder();
422     }
423 
424     return {};
425 }
426 
ValidateData()427 std::optional<Metadata::Error> AnnotationMetadata::ValidateData()
428 {
429     if (IsParseAnnotationElement() && !GetOrCreateAnnotationElementBuilder()->IsCompleted()) {
430         return Error("Annotation element isn't completely defined", Error::Type::MISSING_ATTRIBUTE);
431     }
432 
433     if (IsParseAnnotation()) {
434         ResetAnnotationBuilder();
435     }
436 
437     return Metadata::ValidateData();
438 }
439 
GetBase() const440 std::string RecordMetadata::GetBase() const
441 {
442     auto base = GetAttributeValue("extends");
443     if (base) {
444         return base.value();
445     }
446 
447     return "";
448 }
449 
GetInterfaces() const450 std::vector<std::string> RecordMetadata::GetInterfaces() const
451 {
452     return {};
453 }
454 
IsAnnotation() const455 bool RecordMetadata::IsAnnotation() const
456 {
457     return false;
458 }
459 
IsRuntimeAnnotation() const460 bool RecordMetadata::IsRuntimeAnnotation() const
461 {
462     return false;
463 }
464 
IsTypeAnnotation() const465 bool RecordMetadata::IsTypeAnnotation() const
466 {
467     return false;
468 }
469 
IsRuntimeTypeAnnotation() const470 bool RecordMetadata::IsRuntimeTypeAnnotation() const
471 {
472     return false;
473 }
474 
HasImplementation() const475 bool FunctionMetadata::HasImplementation() const
476 {
477     return ((ACC_ABSTRACT & GetAccessFlags()) == 0) && ((ACC_NATIVE & GetAccessFlags()) == 0);
478 }
479 
IsCtor() const480 bool FunctionMetadata::IsCtor() const
481 {
482     return GetAttribute("ctor");
483 }
484 
IsCctor() const485 bool FunctionMetadata::IsCctor() const
486 {
487     return GetAttribute("cctor");
488 }
489 
StoreValue(std::string_view attribute,std::string_view value)490 std::optional<Metadata::Error> FieldMetadata::StoreValue(std::string_view attribute, std::string_view value)
491 {
492     auto err = ItemMetadata::StoreValue(attribute, value);
493     if (err) {
494         return err;
495     }
496 
497     if (IsValueAttribute(attribute)) {
498         Value::Type valueType;
499         if (!fieldType_.IsObject()) {
500             valueType = GetType(fieldType_.GetName());
501         } else {
502             valueType = Value::Type::STRING;
503         }
504 
505         auto res = CreateValue(valueType, value);
506         if (!res) {
507             return res.Error();
508         }
509 
510         value_ = res.Value();
511     }
512 
513     return {};
514 }
515 
516 #include <meta_gen.h>
517 
518 }  // namespace ark::pandasm
519