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