mirror of
https://gitee.com/openharmony/arkcompiler_runtime_core
synced 2024-11-23 23:00:08 +00:00
536154a11b
Signed-off-by: ah <liangahui@h-partners.com>
509 lines
16 KiB
C++
509 lines
16 KiB
C++
/**
|
|
* 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 <cstdlib>
|
|
|
|
#include <algorithm>
|
|
#include <limits>
|
|
|
|
#include "utils/expected.h"
|
|
|
|
namespace panda::pandasm {
|
|
|
|
std::optional<Metadata::Error> 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<std::string_view, VType> 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 <class T>
|
|
static T ConvertFromString(const std::string_view &value, char **end)
|
|
{
|
|
static_assert(std::is_integral_v<T>, "T must be integral type");
|
|
|
|
constexpr T MIN = std::numeric_limits<T>::min();
|
|
constexpr T MAX = std::numeric_limits<T>::max();
|
|
|
|
if constexpr (std::is_signed_v<T>) {
|
|
auto v = ConvertFromString<int64_t>(value, end);
|
|
if (v < MIN || v > MAX) {
|
|
errno = ERANGE;
|
|
}
|
|
return static_cast<T>(v);
|
|
}
|
|
|
|
if constexpr (!std::is_signed_v<T>) {
|
|
auto v = ConvertFromString<uint64_t>(value, end);
|
|
if (v < MIN || v > MAX) {
|
|
errno = ERANGE;
|
|
}
|
|
return static_cast<T>(v);
|
|
}
|
|
}
|
|
|
|
template <>
|
|
int64_t ConvertFromString(const std::string_view &value, char **end)
|
|
{
|
|
return static_cast<int64_t>(strtoll(value.data(), end, 0));
|
|
}
|
|
|
|
template <>
|
|
uint64_t ConvertFromString(const std::string_view &value, char **end)
|
|
{
|
|
return static_cast<uint64_t>(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 <class T>
|
|
static Expected<T, Metadata::Error> ConvertFromString(const std::string_view &value)
|
|
{
|
|
static_assert(std::is_arithmetic_v<T>, "T must be arithmetic type");
|
|
|
|
char *end = nullptr;
|
|
auto v = ConvertFromString<T>(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<T>(v);
|
|
}
|
|
|
|
template <Value::Type type, class T = ValueTypeHelperT<type>>
|
|
static Expected<ScalarValue, Metadata::Error> CreatePrimitiveValue(const std::string_view &value,
|
|
T max_value = std::numeric_limits<T>::max())
|
|
{
|
|
auto res = ConvertFromString<T>(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<type>(converted);
|
|
}
|
|
|
|
static Expected<ScalarValue, Metadata::Error> CreateValue(
|
|
Value::Type type, const std::string_view &value,
|
|
const std::unordered_map<std::string, std::unique_ptr<AnnotationData>> &annotation_id_map = {})
|
|
{
|
|
switch (type) {
|
|
case Value::Type::U1: {
|
|
return CreatePrimitiveValue<Value::Type::U1>(value, 1);
|
|
}
|
|
case Value::Type::I8: {
|
|
return CreatePrimitiveValue<Value::Type::I8>(value);
|
|
}
|
|
case Value::Type::U8: {
|
|
return CreatePrimitiveValue<Value::Type::U8>(value);
|
|
}
|
|
case Value::Type::I16: {
|
|
return CreatePrimitiveValue<Value::Type::I16>(value);
|
|
}
|
|
case Value::Type::U16: {
|
|
return CreatePrimitiveValue<Value::Type::U16>(value);
|
|
}
|
|
case Value::Type::I32: {
|
|
return CreatePrimitiveValue<Value::Type::I32>(value);
|
|
}
|
|
case Value::Type::U32: {
|
|
return CreatePrimitiveValue<Value::Type::U32>(value);
|
|
}
|
|
case Value::Type::I64: {
|
|
return CreatePrimitiveValue<Value::Type::I64>(value);
|
|
}
|
|
case Value::Type::U64: {
|
|
return CreatePrimitiveValue<Value::Type::U64>(value);
|
|
}
|
|
case Value::Type::F32: {
|
|
return CreatePrimitiveValue<Value::Type::F32>(value);
|
|
}
|
|
case Value::Type::F64: {
|
|
return CreatePrimitiveValue<Value::Type::F64>(value);
|
|
}
|
|
case Value::Type::STRING: {
|
|
return ScalarValue::Create<Value::Type::STRING>(value);
|
|
}
|
|
case Value::Type::RECORD: {
|
|
return ScalarValue::Create<Value::Type::RECORD>(Type::FromName(value));
|
|
}
|
|
case Value::Type::METHOD: {
|
|
return ScalarValue::Create<Value::Type::METHOD>(value);
|
|
}
|
|
case Value::Type::ENUM: {
|
|
return ScalarValue::Create<Value::Type::ENUM>(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<Value::Type::ANNOTATION>(*annotation_value);
|
|
}
|
|
default: {
|
|
break;
|
|
}
|
|
}
|
|
|
|
UNREACHABLE();
|
|
}
|
|
|
|
std::optional<Metadata::Error> AnnotationMetadata::AnnotationElementBuilder::AddValue(
|
|
const std::string_view &value,
|
|
const std::unordered_map<std::string, std::unique_ptr<AnnotationData>> &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<Metadata::Error> 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<Metadata::Error> 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<Metadata::Error> 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<Metadata::Error> 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<Metadata::Error> 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<Metadata::Error> 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<Metadata::Error> 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<Metadata::Error> 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<Metadata::Error> 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<std::string> 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<Metadata::Error> 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 <meta_gen.h>
|
|
|
|
} // namespace panda::pandasm
|