/** * Copyright (c) 2021-2022 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "meta.h" #include #include #include #include "utils/expected.h" namespace panda::pandasm { std::optional Metadata::ValidateSize(const std::string_view &value) const { constexpr size_t SIZE = 10; if (!std::all_of(value.cbegin(), value.cend(), ::isdigit)) { return Error("Unsigned integer value expected", Error::Type::INVALID_VALUE); } strtoul(value.data(), nullptr, SIZE); if (errno == ERANGE) { return Error("Value is out of range", Error::Type::INVALID_VALUE); } return {}; } bool ItemMetadata::IsForeign() const { return GetAttribute("external"); } static panda::pandasm::Value::Type GetType(const std::string_view &value) { using VType = panda::pandasm::Value::Type; static std::unordered_map types { {"u1", VType::U1}, {"i8", VType::I8}, {"u8", VType::U8}, {"i16", VType::I16}, {"u16", VType::U16}, {"i32", VType::I32}, {"u32", VType::U32}, {"i64", VType::I64}, {"u64", VType::U64}, {"f32", VType::F32}, {"f64", VType::F64}, {"string", VType::STRING}, {"class", VType::RECORD}, {"enum", VType::ENUM}, {"annotation", VType::ANNOTATION}, {"array", VType::ARRAY}, {"method", VType::METHOD}}; return types[value]; } template static T ConvertFromString(const std::string_view &value, char **end) { static_assert(std::is_integral_v, "T must be integral type"); constexpr T MIN = std::numeric_limits::min(); constexpr T MAX = std::numeric_limits::max(); if constexpr (std::is_signed_v) { auto v = ConvertFromString(value, end); if (v < MIN || v > MAX) { errno = ERANGE; } return static_cast(v); } if constexpr (!std::is_signed_v) { auto v = ConvertFromString(value, end); if (v < MIN || v > MAX) { errno = ERANGE; } return static_cast(v); } } template <> int64_t ConvertFromString(const std::string_view &value, char **end) { return static_cast(strtoll(value.data(), end, 0)); } template <> uint64_t ConvertFromString(const std::string_view &value, char **end) { return static_cast(strtoull(value.data(), end, 0)); } template <> float ConvertFromString(const std::string_view &value, char **end) { return strtof(value.data(), end); } template <> double ConvertFromString(const std::string_view &value, char **end) { return strtod(value.data(), end); } template static Expected ConvertFromString(const std::string_view &value) { static_assert(std::is_arithmetic_v, "T must be arithmetic type"); char *end = nullptr; auto v = ConvertFromString(value, &end); if (end != value.data() + value.length()) { return Unexpected(Metadata::Error("Excepted integer literal", Metadata::Error::Type::INVALID_VALUE)); } if (errno == ERANGE) { errno = 0; return Unexpected(Metadata::Error("Value is out of range", Metadata::Error::Type::INVALID_VALUE)); } return static_cast(v); } template > static Expected CreatePrimitiveValue(const std::string_view &value, T max_value = std::numeric_limits::max()) { auto res = ConvertFromString(value); if (!res) { return Unexpected(res.Error()); } auto converted = res.Value(); if (converted > max_value) { return Unexpected(Metadata::Error("Value is out of range", Metadata::Error::Type::INVALID_VALUE)); } return ScalarValue::Create(converted); } static Expected CreateValue( Value::Type type, const std::string_view &value, const std::unordered_map> &annotation_id_map = {}) { switch (type) { case Value::Type::U1: { return CreatePrimitiveValue(value, 1); } case Value::Type::I8: { return CreatePrimitiveValue(value); } case Value::Type::U8: { return CreatePrimitiveValue(value); } case Value::Type::I16: { return CreatePrimitiveValue(value); } case Value::Type::U16: { return CreatePrimitiveValue(value); } case Value::Type::I32: { return CreatePrimitiveValue(value); } case Value::Type::U32: { return CreatePrimitiveValue(value); } case Value::Type::I64: { return CreatePrimitiveValue(value); } case Value::Type::U64: { return CreatePrimitiveValue(value); } case Value::Type::F32: { return CreatePrimitiveValue(value); } case Value::Type::F64: { return CreatePrimitiveValue(value); } case Value::Type::STRING: { return ScalarValue::Create(value); } case Value::Type::RECORD: { return ScalarValue::Create(Type::FromName(value)); } case Value::Type::METHOD: { return ScalarValue::Create(value); } case Value::Type::ENUM: { return ScalarValue::Create(value); } case Value::Type::ANNOTATION: { auto it = annotation_id_map.find(std::string(value)); if (it == annotation_id_map.cend()) { return Unexpected(Metadata::Error("Unknown annotation id", Metadata::Error::Type::INVALID_VALUE)); } auto annotation_value = it->second.get(); return ScalarValue::Create(*annotation_value); } default: { break; } } UNREACHABLE(); } std::optional AnnotationMetadata::AnnotationElementBuilder::AddValue( const std::string_view &value, const std::unordered_map> &annotation_id_map) { ASSERT(type_.has_value()); auto type = type_.value(); if (type == Value::Type::ARRAY) { ASSERT(component_type_.has_value()); type = component_type_.value(); } auto res = CreateValue(type, value, annotation_id_map); if (!res) { return res.Error(); } values_.push_back(res.Value()); return {}; } std::optional AnnotationMetadata::Store(const std::string_view &attribute) { if (IsParseAnnotationElement() && !annotation_element_builder_.IsCompleted()) { return Error(std::string("Unexpected attribute '").append(attribute) + "'. Annotation element isn't completely defined", Error::Type::UNEXPECTED_ATTRIBUTE); } if (IsParseAnnotation()) { ResetAnnotationBuilder(); } return Metadata::Store(attribute); } std::optional AnnotationMetadata::MeetExpRecordAttribute(const std::string_view &attribute, const std::string_view &value) { if (IsParseAnnotationElement() && !annotation_element_builder_.IsCompleted()) { return Error(std::string("Unexpected attribute '").append(attribute) + "'. Annotation element isn't completely defined", Error::Type::UNEXPECTED_ATTRIBUTE); } InitializeAnnotationBuilder(value); return {}; } std::optional AnnotationMetadata::MeetExpIdAttribute(const std::string_view &attribute, const std::string_view &value) { if (!IsParseAnnotation() || IsParseAnnotationElement()) { return Error(std::string("Unexpected attribute '").append(attribute) + "'. Annotation record attribute must be defined first", Error::Type::UNEXPECTED_ATTRIBUTE); } if (annotation_builder_.HasId()) { return Error(std::string("Unexpected attribute '").append(attribute) + "'. Annotation id attribute already defined", Error::Type::UNEXPECTED_ATTRIBUTE); } annotation_builder_.SetId(value); return {}; } std::optional AnnotationMetadata::MeetExpElementNameAttribute(const std::string_view &attribute, const std::string_view &value) { if (!IsParseAnnotation()) { return Error(std::string("Unexpected attribute '").append(attribute) + "'. Annotation record attribute must be defined first", Error::Type::UNEXPECTED_ATTRIBUTE); } if (IsParseAnnotationElement() && !annotation_element_builder_.IsCompleted()) { return Error(std::string("Unexpected attribute '").append(attribute) + "'. Previous annotation element isn't defined completely", Error::Type::UNEXPECTED_ATTRIBUTE); } InitializeAnnotationElementBuilder(value); return {}; } std::optional AnnotationMetadata::MeetExpElementTypeAttribute( const std::string_view &attribute, const std::string_view &value) { if (!IsParseAnnotationElement()) { return Error(std::string("Unexpected attribute '").append(attribute) + "'. Annotation element name attribute must be defined first", Error::Type::UNEXPECTED_ATTRIBUTE); } if (annotation_element_builder_.IsTypeSet()) { return Error(std::string("Unexpected attribute '").append(attribute) + "'. Annotation element type attribute already defined", Error::Type::UNEXPECTED_ATTRIBUTE); } annotation_element_builder_.SetType(GetType(value)); return {}; } std::optional AnnotationMetadata::MeetExpElementArrayComponentTypeAttribute( const std::string_view &attribute, const std::string_view &value) { if (!IsParseAnnotationElement()) { return Error(std::string("Unexpected attribute '").append(attribute) + "'. Annotation element name attribute must be defined first", Error::Type::UNEXPECTED_ATTRIBUTE); } if (!annotation_element_builder_.IsArray()) { return Error(std::string("Unexpected attribute '").append(attribute) + "'. Annotation element type isn't array", Error::Type::UNEXPECTED_ATTRIBUTE); } if (annotation_element_builder_.IsComponentTypeSet()) { return Error(std::string("Unexpected attribute '").append(attribute) + "'. Annotation element array component type attribute already defined", Error::Type::UNEXPECTED_ATTRIBUTE); } annotation_element_builder_.SetComponentType(GetType(value)); return {}; } std::optional AnnotationMetadata::MeetExpElementValueAttribute(const std::string_view &attribute, const std::string_view &value) { if (!IsParseAnnotationElement()) { return Error(std::string("Unexpected attribute '").append(attribute) + "'. Annotation element name attribute must be defined first", Error::Type::UNEXPECTED_ATTRIBUTE); } if (!annotation_element_builder_.IsTypeSet()) { return Error(std::string("Unexpected attribute '").append(attribute) + "'. Annotation element type attribute isn't defined", Error::Type::UNEXPECTED_ATTRIBUTE); } if (annotation_element_builder_.IsArray() && !annotation_element_builder_.IsComponentTypeSet()) { return Error(std::string("Unexpected attribute '").append(attribute) + "'. Annotation element array component type attribute isn't defined", Error::Type::UNEXPECTED_ATTRIBUTE); } if (!annotation_element_builder_.IsArray() && annotation_element_builder_.IsCompleted()) { return Error(std::string("Unexpected attribute '").append(attribute) + "'. Annotation element is completely defined", Error::Type::UNEXPECTED_ATTRIBUTE); } return annotation_element_builder_.AddValue(value, id_map_); } std::optional AnnotationMetadata::StoreValue(const std::string_view &attribute, const std::string_view &value) { auto err = Metadata::StoreValue(attribute, value); if (err) { return err; } if (IsAnnotationRecordAttribute(attribute)) { return MeetExpRecordAttribute(attribute, value); } if (IsAnnotationIdAttribute(attribute)) { return MeetExpIdAttribute(attribute, value); } if (IsAnnotationElementNameAttribute(attribute)) { return MeetExpElementNameAttribute(attribute, value); } if (IsAnnotationElementTypeAttribute(attribute)) { return MeetExpElementTypeAttribute(attribute, value); } if (IsAnnotationElementArrayComponentTypeAttribute(attribute)) { return MeetExpElementArrayComponentTypeAttribute(attribute, value); } if (IsAnnotationElementValueAttribute(attribute)) { return MeetExpElementValueAttribute(attribute, value); } if (IsParseAnnotationElement() && !annotation_element_builder_.IsCompleted()) { return Error(std::string("Unexpected attribute '").append(attribute) + "'. Annotation element isn't completely defined", Error::Type::UNEXPECTED_ATTRIBUTE); } if (IsParseAnnotation()) { ResetAnnotationBuilder(); } return {}; } std::optional AnnotationMetadata::ValidateData() { if (IsParseAnnotationElement() && !annotation_element_builder_.IsCompleted()) { return Error("Annotation element isn't completely defined", Error::Type::MISSING_ATTRIBUTE); } if (IsParseAnnotation()) { ResetAnnotationBuilder(); } return Metadata::ValidateData(); } std::string RecordMetadata::GetBase() const { return ""; } std::vector RecordMetadata::GetInterfaces() const { return {}; } bool RecordMetadata::IsAnnotation() const { return false; } bool RecordMetadata::IsRuntimeAnnotation() const { return false; } bool RecordMetadata::IsTypeAnnotation() const { return false; } bool RecordMetadata::IsRuntimeTypeAnnotation() const { return false; } bool FunctionMetadata::IsCtor() const { return GetAttribute("ctor"); } bool FunctionMetadata::IsCctor() const { return GetAttribute("cctor"); } std::optional FieldMetadata::StoreValue(const std::string_view &attribute, const std::string_view &value) { auto err = ItemMetadata::StoreValue(attribute, value); if (err) { return err; } if (IsValueAttribute(attribute)) { Value::Type value_type; if (!field_type_.IsObject()) { value_type = GetType(field_type_.GetName()); } else { value_type = Value::Type::STRING; } auto res = CreateValue(value_type, value); if (!res) { return res.Error(); } value_ = res.Value(); } return {}; } #include } // namespace panda::pandasm