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 <cstdlib>
19
20 #include <algorithm>
21 #include <limits>
22
23 #include "utils/expected.h"
24
25 namespace panda::pandasm {
26
ValidateSize(const std::string_view &value) const27 std::optional<Metadata::Error> Metadata::ValidateSize(const 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(const std::string_view &value)48 static panda::pandasm::Value::Type GetType(const 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(const std::string_view &value, char **end)63 static T ConvertFromString(const 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(const std::string_view &value, char **end)88 int64_t ConvertFromString(const std::string_view &value, char **end)
89 {
90 return static_cast<int64_t>(strtoll(value.data(), end, 0));
91 }
92
93 template <>
ConvertFromString(const std::string_view &value, char **end)94 uint64_t ConvertFromString(const std::string_view &value, char **end)
95 {
96 return static_cast<uint64_t>(strtoull(value.data(), end, 0));
97 }
98
99 template <>
ConvertFromString(const std::string_view &value, char **end)100 float ConvertFromString(const std::string_view &value, char **end)
101 {
102 return strtof(value.data(), end);
103 }
104
105 template <>
ConvertFromString(const std::string_view &value, char **end)106 double ConvertFromString(const std::string_view &value, char **end)
107 {
108 return strtod(value.data(), end);
109 }
110
111 template <class T>
ConvertFromString(const std::string_view &value)112 static Expected<T, Metadata::Error> ConvertFromString(const 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(const std::string_view &value, T max_value = std::numeric_limits<T>::max())132 static Expected<ScalarValue, Metadata::Error> CreatePrimitiveValue(const 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 if (converted > max_value) {
142 return Unexpected(Metadata::Error("Value is out of range", Metadata::Error::Type::INVALID_VALUE));
143 }
144
145 return ScalarValue::Create<type>(converted);
146 }
147
CreateValue( Value::Type type, const std::string_view &value, const std::unordered_map<std::string, std::unique_ptr<AnnotationData>> &annotation_id_map = {})148 static Expected<ScalarValue, Metadata::Error> CreateValue(
149 Value::Type type, const std::string_view &value,
150 const std::unordered_map<std::string, std::unique_ptr<AnnotationData>> &annotation_id_map = {})
151 {
152 switch (type) {
153 case Value::Type::U1: {
154 return CreatePrimitiveValue<Value::Type::U1>(value, 1);
155 }
156 case Value::Type::I8: {
157 return CreatePrimitiveValue<Value::Type::I8>(value);
158 }
159 case Value::Type::U8: {
160 return CreatePrimitiveValue<Value::Type::U8>(value);
161 }
162 case Value::Type::I16: {
163 return CreatePrimitiveValue<Value::Type::I16>(value);
164 }
165 case Value::Type::U16: {
166 return CreatePrimitiveValue<Value::Type::U16>(value);
167 }
168 case Value::Type::I32: {
169 return CreatePrimitiveValue<Value::Type::I32>(value);
170 }
171 case Value::Type::U32: {
172 return CreatePrimitiveValue<Value::Type::U32>(value);
173 }
174 case Value::Type::I64: {
175 return CreatePrimitiveValue<Value::Type::I64>(value);
176 }
177 case Value::Type::U64: {
178 return CreatePrimitiveValue<Value::Type::U64>(value);
179 }
180 case Value::Type::F32: {
181 return CreatePrimitiveValue<Value::Type::F32>(value);
182 }
183 case Value::Type::F64: {
184 return CreatePrimitiveValue<Value::Type::F64>(value);
185 }
186 case Value::Type::STRING: {
187 return ScalarValue::Create<Value::Type::STRING>(value);
188 }
189 case Value::Type::RECORD: {
190 return ScalarValue::Create<Value::Type::RECORD>(Type::FromName(value));
191 }
192 case Value::Type::METHOD: {
193 return ScalarValue::Create<Value::Type::METHOD>(value);
194 }
195 case Value::Type::ENUM: {
196 return ScalarValue::Create<Value::Type::ENUM>(value);
197 }
198 case Value::Type::ANNOTATION: {
199 auto it = annotation_id_map.find(std::string(value));
200 if (it == annotation_id_map.cend()) {
201 return Unexpected(Metadata::Error("Unknown annotation id", Metadata::Error::Type::INVALID_VALUE));
202 }
203
204 auto annotation_value = it->second.get();
205 return ScalarValue::Create<Value::Type::ANNOTATION>(*annotation_value);
206 }
207 default: {
208 break;
209 }
210 }
211
212 UNREACHABLE();
213 }
214
AddValue( const std::string_view &value, const std::unordered_map<std::string, std::unique_ptr<AnnotationData>> &annotation_id_map)215 std::optional<Metadata::Error> AnnotationMetadata::AnnotationElementBuilder::AddValue(
216 const std::string_view &value,
217 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 if (type == Value::Type::ARRAY) {
223 ASSERT(component_type_.has_value());
224 type = component_type_.value();
225 }
226
227 auto res = CreateValue(type, value, annotation_id_map);
228 if (!res) {
229 return res.Error();
230 }
231
232 values_.push_back(res.Value());
233
234 return {};
235 }
236
Store(const std::string_view &attribute)237 std::optional<Metadata::Error> AnnotationMetadata::Store(const std::string_view &attribute)
238 {
239 if (IsParseAnnotationElement() && !annotation_element_builder_.IsCompleted()) {
240 return Error(std::string("Unexpected attribute '").append(attribute) +
241 "'. Annotation element isn't completely defined",
242 Error::Type::UNEXPECTED_ATTRIBUTE);
243 }
244
245 if (IsParseAnnotation()) {
246 ResetAnnotationBuilder();
247 }
248
249 return Metadata::Store(attribute);
250 }
251
MeetExpRecordAttribute(const std::string_view &attribute, const std::string_view &value)252 std::optional<Metadata::Error> AnnotationMetadata::MeetExpRecordAttribute(const std::string_view &attribute,
253 const std::string_view &value)
254 {
255 if (IsParseAnnotationElement() && !annotation_element_builder_.IsCompleted()) {
256 return Error(std::string("Unexpected attribute '").append(attribute) +
257 "'. Annotation element isn't completely defined",
258 Error::Type::UNEXPECTED_ATTRIBUTE);
259 }
260
261 InitializeAnnotationBuilder(value);
262
263 return {};
264 }
265
MeetExpIdAttribute(const std::string_view &attribute, const std::string_view &value)266 std::optional<Metadata::Error> AnnotationMetadata::MeetExpIdAttribute(const std::string_view &attribute,
267 const std::string_view &value)
268 {
269 if (!IsParseAnnotation() || IsParseAnnotationElement()) {
270 return Error(std::string("Unexpected attribute '").append(attribute) +
271 "'. Annotation record attribute must be defined first",
272 Error::Type::UNEXPECTED_ATTRIBUTE);
273 }
274
275 if (annotation_builder_.HasId()) {
276 return Error(std::string("Unexpected attribute '").append(attribute) +
277 "'. Annotation id attribute already defined",
278 Error::Type::UNEXPECTED_ATTRIBUTE);
279 }
280
281 annotation_builder_.SetId(value);
282
283 return {};
284 }
285
MeetExpElementNameAttribute(const std::string_view &attribute, const std::string_view &value)286 std::optional<Metadata::Error> AnnotationMetadata::MeetExpElementNameAttribute(const std::string_view &attribute,
287 const std::string_view &value)
288 {
289 if (!IsParseAnnotation()) {
290 return Error(std::string("Unexpected attribute '").append(attribute) +
291 "'. Annotation record attribute must be defined first",
292 Error::Type::UNEXPECTED_ATTRIBUTE);
293 }
294
295 if (IsParseAnnotationElement() && !annotation_element_builder_.IsCompleted()) {
296 return Error(std::string("Unexpected attribute '").append(attribute) +
297 "'. Previous annotation element isn't defined completely",
298 Error::Type::UNEXPECTED_ATTRIBUTE);
299 }
300
301 InitializeAnnotationElementBuilder(value);
302
303 return {};
304 }
305
MeetExpElementTypeAttribute( const std::string_view &attribute, const std::string_view &value)306 std::optional<Metadata::Error> AnnotationMetadata::MeetExpElementTypeAttribute(
307 const std::string_view &attribute, const std::string_view &value)
308 {
309 if (!IsParseAnnotationElement()) {
310 return Error(std::string("Unexpected attribute '").append(attribute) +
311 "'. Annotation element name attribute must be defined first",
312 Error::Type::UNEXPECTED_ATTRIBUTE);
313 }
314
315 if (annotation_element_builder_.IsTypeSet()) {
316 return Error(std::string("Unexpected attribute '").append(attribute) +
317 "'. Annotation element type attribute already defined",
318 Error::Type::UNEXPECTED_ATTRIBUTE);
319 }
320
321 annotation_element_builder_.SetType(GetType(value));
322
323 return {};
324 }
325
MeetExpElementArrayComponentTypeAttribute( const std::string_view &attribute, const std::string_view &value)326 std::optional<Metadata::Error> AnnotationMetadata::MeetExpElementArrayComponentTypeAttribute(
327 const std::string_view &attribute, const std::string_view &value)
328 {
329 if (!IsParseAnnotationElement()) {
330 return Error(std::string("Unexpected attribute '").append(attribute) +
331 "'. Annotation element name attribute must be defined first",
332 Error::Type::UNEXPECTED_ATTRIBUTE);
333 }
334
335 if (!annotation_element_builder_.IsArray()) {
336 return Error(std::string("Unexpected attribute '").append(attribute) + "'. Annotation element type isn't array",
337 Error::Type::UNEXPECTED_ATTRIBUTE);
338 }
339
340 if (annotation_element_builder_.IsComponentTypeSet()) {
341 return Error(std::string("Unexpected attribute '").append(attribute) +
342 "'. Annotation element array component type attribute already defined",
343 Error::Type::UNEXPECTED_ATTRIBUTE);
344 }
345
346 annotation_element_builder_.SetComponentType(GetType(value));
347
348 return {};
349 }
350
MeetExpElementValueAttribute(const std::string_view &attribute, const std::string_view &value)351 std::optional<Metadata::Error> AnnotationMetadata::MeetExpElementValueAttribute(const std::string_view &attribute,
352 const std::string_view &value)
353 {
354 if (!IsParseAnnotationElement()) {
355 return Error(std::string("Unexpected attribute '").append(attribute) +
356 "'. Annotation element name attribute must be defined first",
357 Error::Type::UNEXPECTED_ATTRIBUTE);
358 }
359
360 if (!annotation_element_builder_.IsTypeSet()) {
361 return Error(std::string("Unexpected attribute '").append(attribute) +
362 "'. Annotation element type attribute isn't defined",
363 Error::Type::UNEXPECTED_ATTRIBUTE);
364 }
365
366 if (annotation_element_builder_.IsArray() && !annotation_element_builder_.IsComponentTypeSet()) {
367 return Error(std::string("Unexpected attribute '").append(attribute) +
368 "'. Annotation element array component type attribute isn't defined",
369 Error::Type::UNEXPECTED_ATTRIBUTE);
370 }
371
372 if (!annotation_element_builder_.IsArray() && annotation_element_builder_.IsCompleted()) {
373 return Error(std::string("Unexpected attribute '").append(attribute) +
374 "'. Annotation element is completely defined",
375 Error::Type::UNEXPECTED_ATTRIBUTE);
376 }
377
378 return annotation_element_builder_.AddValue(value, id_map_);
379 }
380
StoreValue(const std::string_view &attribute, const std::string_view &value)381 std::optional<Metadata::Error> AnnotationMetadata::StoreValue(const std::string_view &attribute,
382 const 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(const std::string_view &attribute, const std::string_view &value)479 std::optional<Metadata::Error> FieldMetadata::StoreValue(const std::string_view &attribute,
480 const std::string_view &value)
481 {
482 auto err = ItemMetadata::StoreValue(attribute, value);
483 if (err) {
484 return err;
485 }
486
487 if (IsValueAttribute(attribute)) {
488 Value::Type value_type;
489 if (!field_type_.IsObject()) {
490 value_type = GetType(field_type_.GetName());
491 } else {
492 value_type = Value::Type::STRING;
493 }
494
495 auto res = CreateValue(value_type, value);
496 if (!res) {
497 return res.Error();
498 }
499
500 value_ = res.Value();
501 }
502
503 return {};
504 }
505
506 #include <meta_gen.h>
507
508 } // namespace panda::pandasm
509