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#ifndef LIBPANDAFILE_VALUE_H
17#define LIBPANDAFILE_VALUE_H
18
19#include <type_traits>
20
21#include "file.h"
22#include "helpers.h"
23
24namespace panda::panda_file {
25
26class ScalarValue {
27public:
28    ScalarValue(const File &panda_file, uint32_t value) : panda_file_(panda_file), value_(value) {}
29
30    ~ScalarValue() = default;
31
32    NO_COPY_SEMANTIC(ScalarValue);
33    NO_MOVE_SEMANTIC(ScalarValue);
34
35    template <class T>
36    T Get() const
37    {
38        static_assert(std::is_arithmetic_v<T> || std::is_same_v<T, File::EntityId>);
39
40        if constexpr (std::is_same_v<T, float>) {  // NOLINT
41            return bit_cast<float>(value_);
42        }
43
44        constexpr size_t T_SIZE = sizeof(T);
45
46        // NOLINTNEXTLINE(readability-braces-around-statements, bugprone-suspicious-semicolon)
47        if constexpr (T_SIZE <= sizeof(uint32_t)) {
48            return static_cast<T>(value_);
49        }
50
51        File::EntityId id(value_);
52        auto sp = panda_file_.GetSpanFromId(id);
53        auto res = helpers::Read<T_SIZE>(&sp);
54
55        if constexpr (std::is_floating_point_v<T>) {  // NOLINT
56            return bit_cast<T>(res);
57        }
58
59        return static_cast<T>(res);
60    }
61
62    uint32_t GetValue() const
63    {
64        return value_;
65    }
66
67private:
68    const File &panda_file_;
69    uint32_t value_;
70};
71
72class ArrayValue {
73public:
74    ArrayValue(const File &panda_file, File::EntityId id) : panda_file_(panda_file), id_(id)
75    {
76        auto sp = panda_file_.GetSpanFromId(id_);
77        count_ = helpers::ReadULeb128(&sp);
78        data_ = sp;
79    }
80
81    ~ArrayValue() = default;
82
83    NO_COPY_SEMANTIC(ArrayValue);
84    NO_MOVE_SEMANTIC(ArrayValue);
85
86    template <class T>
87    T Get(size_t idx) const
88    {
89        static_assert(std::is_arithmetic_v<T> || std::is_same_v<T, File::EntityId>);
90
91        constexpr size_t T_SIZE = sizeof(T);
92
93        auto sp = data_.SubSpan(T_SIZE * idx);
94        auto res = helpers::Read<T_SIZE>(&sp);
95
96        if constexpr (std::is_floating_point_v<T>) {  // NOLINT
97            return bit_cast<T>(res);
98        }
99
100        return static_cast<T>(res);
101    }
102
103    uint32_t GetCount() const
104    {
105        return count_;
106    }
107
108    File::EntityId GetId() const
109    {
110        return id_;
111    }
112
113private:
114    static constexpr size_t COUNT_SIZE = sizeof(uint32_t);
115
116    const File &panda_file_;
117    File::EntityId id_;
118    uint32_t count_;
119    Span<const uint8_t> data_ {nullptr, nullptr};
120};
121
122}  // namespace panda::panda_file
123
124#endif  // LIBPANDAFILE_VALUE_H
125