18bf80f4bSopenharmony_ci/*
28bf80f4bSopenharmony_ci * Copyright (C) 2023-2024 Huawei Device Co., Ltd.
38bf80f4bSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
48bf80f4bSopenharmony_ci * you may not use this file except in compliance with the License.
58bf80f4bSopenharmony_ci * You may obtain a copy of the License at
68bf80f4bSopenharmony_ci *
78bf80f4bSopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
88bf80f4bSopenharmony_ci *
98bf80f4bSopenharmony_ci * Unless required by applicable law or agreed to in writing, software
108bf80f4bSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
118bf80f4bSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
128bf80f4bSopenharmony_ci * See the License for the specific language governing permissions and
138bf80f4bSopenharmony_ci * limitations under the License.
148bf80f4bSopenharmony_ci */
158bf80f4bSopenharmony_ci
168bf80f4bSopenharmony_ci#ifndef CORE__ECS_HELPER__PROPERTY_TOOLS__PROPERTY_VALUE_H
178bf80f4bSopenharmony_ci#define CORE__ECS_HELPER__PROPERTY_TOOLS__PROPERTY_VALUE_H
188bf80f4bSopenharmony_ci
198bf80f4bSopenharmony_ci#include <cassert>
208bf80f4bSopenharmony_ci#include <cstddef>
218bf80f4bSopenharmony_ci#include <cstdint>
228bf80f4bSopenharmony_ci
238bf80f4bSopenharmony_ci#include <base/containers/array_view.h>
248bf80f4bSopenharmony_ci#include <base/containers/iterator.h>
258bf80f4bSopenharmony_ci#include <base/containers/string_view.h>
268bf80f4bSopenharmony_ci#include <base/namespace.h>
278bf80f4bSopenharmony_ci#include <core/namespace.h>
288bf80f4bSopenharmony_ci#include <core/property/property.h>
298bf80f4bSopenharmony_ci#include <base/util/log.h>
308bf80f4bSopenharmony_ci#include <base/containers/type_traits.h>
318bf80f4bSopenharmony_ci#include <core/property/property_types.h>
328bf80f4bSopenharmony_ci
338bf80f4bSopenharmony_ciCORE_BEGIN_NAMESPACE()
348bf80f4bSopenharmony_ciclass PropertyValue {
358bf80f4bSopenharmony_cipublic:
368bf80f4bSopenharmony_ci    PropertyValue() noexcept : count_(0), data_(nullptr), index_(0) {}
378bf80f4bSopenharmony_ci    ~PropertyValue() = default;
388bf80f4bSopenharmony_ci    PropertyValue(const PropertyValue& other) noexcept = default;
398bf80f4bSopenharmony_ci
408bf80f4bSopenharmony_ci    PropertyValue(PropertyValue&& other) noexcept
418bf80f4bSopenharmony_ci        : type_(other.type_), // exchange(other.type_, PropertyType::INVALID)),
428bf80f4bSopenharmony_ci          count_(BASE_NS::exchange(other.count_, 0U)), data_(BASE_NS::exchange(other.data_, nullptr)),
438bf80f4bSopenharmony_ci          index_(BASE_NS::exchange(other.index_, 0U))
448bf80f4bSopenharmony_ci    {}
458bf80f4bSopenharmony_ci    explicit constexpr PropertyValue(const Property* type, void* rawData, size_t cnt) noexcept
468bf80f4bSopenharmony_ci        : type_(type), count_(cnt), data_(rawData), index_(0U)
478bf80f4bSopenharmony_ci    {}
488bf80f4bSopenharmony_ci
498bf80f4bSopenharmony_ci    constexpr size_t Size() const
508bf80f4bSopenharmony_ci    {
518bf80f4bSopenharmony_ci        return count_;
528bf80f4bSopenharmony_ci    }
538bf80f4bSopenharmony_ci    constexpr PropertyTypeDecl GetType() const
548bf80f4bSopenharmony_ci    {
558bf80f4bSopenharmony_ci        return type_->type;
568bf80f4bSopenharmony_ci    }
578bf80f4bSopenharmony_ci    constexpr operator PropertyTypeDecl() const
588bf80f4bSopenharmony_ci    {
598bf80f4bSopenharmony_ci        return type_->type;
608bf80f4bSopenharmony_ci    }
618bf80f4bSopenharmony_ci    constexpr bool operator==(const PropertyTypeDecl& other) const
628bf80f4bSopenharmony_ci    {
638bf80f4bSopenharmony_ci        return type_->type.compareHash == other.compareHash;
648bf80f4bSopenharmony_ci    }
658bf80f4bSopenharmony_ci
668bf80f4bSopenharmony_ci    BASE_NS::array_view<const Property> MetaData() const
678bf80f4bSopenharmony_ci    {
688bf80f4bSopenharmony_ci        if (type_) {
698bf80f4bSopenharmony_ci            return type_->metaData.memberProperties;
708bf80f4bSopenharmony_ci        }
718bf80f4bSopenharmony_ci        return {};
728bf80f4bSopenharmony_ci    }
738bf80f4bSopenharmony_ci    const Property* MetaData(size_t index) const
748bf80f4bSopenharmony_ci    {
758bf80f4bSopenharmony_ci        if (type_) {
768bf80f4bSopenharmony_ci            const auto& meta = type_->metaData.memberProperties;
778bf80f4bSopenharmony_ci            if (index < meta.size()) {
788bf80f4bSopenharmony_ci                return &meta[index];
798bf80f4bSopenharmony_ci            }
808bf80f4bSopenharmony_ci        }
818bf80f4bSopenharmony_ci        return nullptr;
828bf80f4bSopenharmony_ci    }
838bf80f4bSopenharmony_ci
848bf80f4bSopenharmony_ci    // void* access
858bf80f4bSopenharmony_ci    explicit constexpr operator void*()
868bf80f4bSopenharmony_ci    {
878bf80f4bSopenharmony_ci        return data_;
888bf80f4bSopenharmony_ci    }
898bf80f4bSopenharmony_ci    explicit constexpr operator void const*() const
908bf80f4bSopenharmony_ci    {
918bf80f4bSopenharmony_ci        return data_;
928bf80f4bSopenharmony_ci    }
938bf80f4bSopenharmony_ci
948bf80f4bSopenharmony_ci    // safe
958bf80f4bSopenharmony_ci    PropertyValue operator[](const size_t index) const
968bf80f4bSopenharmony_ci    {
978bf80f4bSopenharmony_ci        BASE_ASSERT(type_->type.isArray); // This accessor type is valid only for arrays.
988bf80f4bSopenharmony_ci        BASE_ASSERT(index < type_->count);
998bf80f4bSopenharmony_ci        return PropertyValue(type_, data_, 1, index);
1008bf80f4bSopenharmony_ci    }
1018bf80f4bSopenharmony_ci    PropertyValue operator[](const size_t index)
1028bf80f4bSopenharmony_ci    {
1038bf80f4bSopenharmony_ci        BASE_ASSERT(type_->type.isArray); // This accessor type is valid only for arrays.
1048bf80f4bSopenharmony_ci        BASE_ASSERT(index < type_->count);
1058bf80f4bSopenharmony_ci        return PropertyValue(type_, data_, 1, index);
1068bf80f4bSopenharmony_ci    }
1078bf80f4bSopenharmony_ci
1088bf80f4bSopenharmony_ci    PropertyValue operator[](BASE_NS::string_view name) const
1098bf80f4bSopenharmony_ci    {
1108bf80f4bSopenharmony_ci        uintptr_t offset = reinterpret_cast<uintptr_t>(data_);
1118bf80f4bSopenharmony_ci        const auto nameHash = BASE_NS::FNV1aHash(name.data(), name.size());
1128bf80f4bSopenharmony_ci        for (const auto& p : type_->metaData.memberProperties) {
1138bf80f4bSopenharmony_ci            if ((nameHash == p.hash) && (p.name == name)) {
1148bf80f4bSopenharmony_ci                return PropertyValue(&p, reinterpret_cast<void*>(offset + p.offset), p.count);
1158bf80f4bSopenharmony_ci            }
1168bf80f4bSopenharmony_ci        }
1178bf80f4bSopenharmony_ci        // no such member property
1188bf80f4bSopenharmony_ci        return {};
1198bf80f4bSopenharmony_ci    }
1208bf80f4bSopenharmony_ci
1218bf80f4bSopenharmony_ci    // unsafe
1228bf80f4bSopenharmony_ci    template<typename T>
1238bf80f4bSopenharmony_ci    [[deprecated]] constexpr operator T() const
1248bf80f4bSopenharmony_ci    {
1258bf80f4bSopenharmony_ci        return reinterpret_cast<T*>(data_)[index_];
1268bf80f4bSopenharmony_ci    }
1278bf80f4bSopenharmony_ci
1288bf80f4bSopenharmony_ci    template<typename T>
1298bf80f4bSopenharmony_ci    [[deprecated]] constexpr operator T&()
1308bf80f4bSopenharmony_ci    {
1318bf80f4bSopenharmony_ci        return reinterpret_cast<T*>(data_)[index_];
1328bf80f4bSopenharmony_ci    }
1338bf80f4bSopenharmony_ci
1348bf80f4bSopenharmony_ci    template<typename T>
1358bf80f4bSopenharmony_ci    [[deprecated]] PropertyValue& operator=(T v)
1368bf80f4bSopenharmony_ci    {
1378bf80f4bSopenharmony_ci        reinterpret_cast<T*>(data_)[index_] = v;
1388bf80f4bSopenharmony_ci        return *this;
1398bf80f4bSopenharmony_ci    }
1408bf80f4bSopenharmony_ci
1418bf80f4bSopenharmony_ci    PropertyValue& operator=(const PropertyValue& other) noexcept = default;
1428bf80f4bSopenharmony_ci
1438bf80f4bSopenharmony_ci    PropertyValue& operator=(PropertyValue&& other) noexcept
1448bf80f4bSopenharmony_ci    {
1458bf80f4bSopenharmony_ci        if (this != &other) {
1468bf80f4bSopenharmony_ci            type_ = BASE_NS::exchange(other.type_, {});
1478bf80f4bSopenharmony_ci            count_ = BASE_NS::exchange(other.count_, 0U);
1488bf80f4bSopenharmony_ci            data_ = BASE_NS::exchange(other.data_, nullptr);
1498bf80f4bSopenharmony_ci            index_ = BASE_NS::exchange(other.index_, 0U);
1508bf80f4bSopenharmony_ci        }
1518bf80f4bSopenharmony_ci        return *this;
1528bf80f4bSopenharmony_ci    }
1538bf80f4bSopenharmony_ci
1548bf80f4bSopenharmony_ciprivate:
1558bf80f4bSopenharmony_ci    const Property* type_ { nullptr };
1568bf80f4bSopenharmony_ci    size_t count_;
1578bf80f4bSopenharmony_ci    void* data_;
1588bf80f4bSopenharmony_ci    size_t index_;
1598bf80f4bSopenharmony_ci    explicit constexpr PropertyValue(const Property* type, void* rawData, size_t cnt, size_t index)
1608bf80f4bSopenharmony_ci        : type_(type), count_(cnt), data_(rawData), index_(index)
1618bf80f4bSopenharmony_ci    {}
1628bf80f4bSopenharmony_ci};
1638bf80f4bSopenharmony_ciCORE_END_NAMESPACE()
1648bf80f4bSopenharmony_ci
1658bf80f4bSopenharmony_ci#endif // CORE__ECS_HELPER__PROPERTY_TOOLS__PROPERTY_VALUE_H
166