/*
* Copyright (C) 2023 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.
*/
#ifndef CORE__ECS_HELPER__PROPERTY_TOOLS__PROPERTY_VALUE_H
#define CORE__ECS_HELPER__PROPERTY_TOOLS__PROPERTY_VALUE_H
#include
#include
#include
CORE_BEGIN_NAMESPACE()
class PropertyValue {
public:
PropertyValue() noexcept : count_(0), data_(nullptr), index_(0) {}
~PropertyValue() = default;
PropertyValue(const PropertyValue& other) noexcept
: type_(other.type_), count_(other.count_), data_(other.data_), index_(other.index_)
{}
PropertyValue(PropertyValue&& other) noexcept
: type_(other.type_), // exchange(other.type_, PropertyType::INVALID)),
count_(BASE_NS::exchange(other.count_, 0)), data_(BASE_NS::exchange(other.data_, nullptr)),
index_(BASE_NS::exchange(other.index_, 0))
{}
explicit constexpr PropertyValue(const Property* type, void* rawData, size_t cnt) noexcept
: type_(type), count_(cnt), data_(rawData), index_(0)
{}
constexpr size_t Size() const
{
return count_;
}
constexpr PropertyTypeDecl GetType() const
{
return type_->type;
}
constexpr operator PropertyTypeDecl() const
{
return type_->type;
}
constexpr bool operator==(const PropertyTypeDecl& other) const
{
return type_->type.compareHash == other.compareHash;
}
BASE_NS::array_view MetaData() const
{
if (type_) {
return type_->metaData.memberProperties;
}
return {};
}
const Property* MetaData(size_t index) const
{
if (type_) {
const auto& meta = type_->metaData.memberProperties;
if (index < meta.size()) {
return &meta[index];
}
}
return nullptr;
}
// void* access
explicit constexpr operator void*()
{
return data_;
}
explicit constexpr operator void const*() const
{
return data_;
}
// safe
const PropertyValue operator[](const size_t index) const
{
BASE_ASSERT(type_->type.isArray); // This accessor type is valid only for arrays.
BASE_ASSERT(index < type_->count);
return PropertyValue(type_, data_, 1, index);
}
PropertyValue operator[](const size_t index)
{
BASE_ASSERT(type_->type.isArray); // This accessor type is valid only for arrays.
BASE_ASSERT(index < type_->count);
return PropertyValue(type_, data_, 1, index);
}
const PropertyValue operator[](BASE_NS::string_view name) const
{
uintptr_t offset = (uintptr_t)data_;
const auto nameHash = BASE_NS::FNV1aHash(name.data(), name.size());
for (const auto& p : type_->metaData.memberProperties) {
if ((nameHash == p.hash) && (p.name == name)) {
return PropertyValue(&p, (void*)(offset + p.offset), p.count);
}
}
// no such member property
return {};
}
// unsafe
template
[[deprecated]] constexpr operator T() const
{
return reinterpret_cast(data_)[index_];
}
template
[[deprecated]] constexpr operator T&()
{
return reinterpret_cast(data_)[index_];
}
template
[[deprecated]] PropertyValue& operator=(T v)
{
reinterpret_cast(data_)[index_] = v;
return *this;
}
PropertyValue& operator=(const PropertyValue& other) noexcept
{
if (this != &other) {
type_ = other.type_;
count_ = other.count_;
data_ = other.data_;
index_ = other.index_;
}
return *this;
}
PropertyValue& operator=(PropertyValue&& other) noexcept
{
if (this != &other) {
type_ = BASE_NS::exchange(other.type_, {});
count_ = BASE_NS::exchange(other.count_, 0);
data_ = BASE_NS::exchange(other.data_, nullptr);
index_ = BASE_NS::exchange(other.index_, 0);
}
return *this;
}
private:
const Property* type_ { nullptr };
size_t count_;
void* data_;
size_t index_;
explicit constexpr PropertyValue(const Property* type, void* rawData, size_t cnt, size_t index)
: type_(type), count_(cnt), data_(rawData), index_(index)
{}
};
CORE_END_NAMESPACE()
#endif // CORE__ECS_HELPER__PROPERTY_TOOLS__PROPERTY_VALUE_H