| // Copyright 2019 Google LLC |
| // |
| // 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 |
| // |
| // https://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 SANDBOXED_API_VAR_REG_H_ |
| #define SANDBOXED_API_VAR_REG_H_ |
| |
| #include <algorithm> |
| #include <cstring> |
| #include <iostream> |
| #include <string> |
| #include <type_traits> |
| |
| #include "absl/strings/str_format.h" |
| #include "sandboxed_api/var_abstract.h" |
| |
| namespace sapi::v { |
| |
| // The super-class for Reg. Specified as a class, so it can be used as a |
| // type specifier in methods. |
| class Callable : public Var { |
| public: |
| // Get pointer to the stored data. |
| virtual const void* GetDataPtr() = 0; |
| |
| // Set internal data from ptr. |
| virtual void SetDataFromPtr(const void* ptr, size_t max_sz) = 0; |
| |
| // Get data from internal ptr. |
| void GetDataFromPtr(void* ptr, size_t max_sz) { |
| size_t min_sz = std::min<size_t>(GetSize(), max_sz); |
| memcpy(ptr, GetDataPtr(), min_sz); |
| } |
| |
| protected: |
| Callable() = default; |
| }; |
| |
| // class Reg represents register-sized variables. |
| template <typename T> |
| class Reg : public Callable { |
| public: |
| static_assert(std::is_integral_v<T> || std::is_floating_point_v<T> || |
| std::is_pointer_v<T> || std::is_enum_v<T>, |
| "Only register-sized types are allowed as template argument " |
| "for class Reg."); |
| |
| explicit Reg(const T value = {}) { |
| value_ = value; |
| SetLocal(&value_); |
| } |
| |
| // Getter/Setter for the stored value. |
| virtual T GetValue() const { return value_; } |
| virtual void SetValue(T value) { value_ = value; } |
| |
| const void* GetDataPtr() override { |
| return reinterpret_cast<const void*>(&value_); |
| } |
| void SetDataFromPtr(const void* ptr, size_t max_sz) override { |
| memcpy(&value_, ptr, std::min(GetSize(), max_sz)); |
| } |
| |
| size_t GetSize() const override { return sizeof(T); } |
| |
| Type GetType() const override; |
| |
| std::string GetTypeString() const override; |
| |
| std::string ToString() const override; |
| |
| protected: |
| // The stored value. |
| T value_; |
| }; |
| |
| template <typename T> |
| Type Reg<T>::GetType() const { |
| if constexpr (std::is_integral_v<T> || std::is_enum_v<T>) { |
| return Type::kInt; |
| } |
| if constexpr (std::is_floating_point_v<T>) { |
| return Type::kFloat; |
| } |
| if constexpr (std::is_pointer_v<T>) { |
| return Type::kPointer; |
| } |
| // Not reached |
| } |
| |
| template <typename T> |
| std::string Reg<T>::GetTypeString() const { |
| if constexpr (std::is_integral_v<T> || std::is_enum_v<T>) { |
| return "Integer"; |
| } |
| if constexpr (std::is_floating_point_v<T>) { |
| return "Floating-point"; |
| } |
| if constexpr (std::is_pointer_v<T>) { |
| return "Pointer"; |
| } |
| // Not reached |
| } |
| |
| template <typename T> |
| std::string Reg<T>::ToString() const { |
| if constexpr (std::is_integral_v<T>) { |
| return std::to_string(value_); |
| } |
| if constexpr (std::is_enum_v<T>) { |
| return std::to_string(static_cast<std::underlying_type_t<T>>(value_)); |
| } |
| if constexpr (std::is_floating_point_v<T>) { |
| return absl::StrFormat("%.10f", value_); |
| } |
| if constexpr (std::is_pointer<T>::value) { |
| return absl::StrFormat("%p", value_); |
| } |
| // Not reached. |
| } |
| |
| } // namespace sapi::v |
| |
| #endif // SANDBOXED_API_VAR_REG_H_ |