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