1 // Copyright 2019 Google LLC
2 //
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 // https://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 #ifndef SANDBOXED_API_VAR_REG_H_
16 #define SANDBOXED_API_VAR_REG_H_
17
18 #include <algorithm>
19 #include <cstring>
20 #include <iostream>
21 #include <string>
22 #include <type_traits>
23
24 #include "absl/strings/str_format.h"
25 #include "sandboxed_api/var_abstract.h"
26
27 namespace sapi::v {
28
29 // The super-class for Reg. Specified as a class, so it can be used as a
30 // type specifier in methods.
31 class Callable : public Var {
32 public:
33 // Get pointer to the stored data.
34 virtual const void* GetDataPtr() = 0;
35
36 // Set internal data from ptr.
37 virtual void SetDataFromPtr(const void* ptr, size_t max_sz) = 0;
38
39 // Get data from internal ptr.
GetDataFromPtr(void * ptr,size_t max_sz)40 void GetDataFromPtr(void* ptr, size_t max_sz) {
41 size_t min_sz = std::min<size_t>(GetSize(), max_sz);
42 memcpy(ptr, GetDataPtr(), min_sz);
43 }
44
45 protected:
46 Callable() = default;
47 };
48
49 // class Reg represents register-sized variables.
50 template <typename T>
51 class Reg : public Callable {
52 public:
53 static_assert(std::is_integral_v<T> || std::is_floating_point_v<T> ||
54 std::is_pointer_v<T> || std::is_enum_v<T>,
55 "Only register-sized types are allowed as template argument "
56 "for class Reg.");
57
58 explicit Reg(const T value = {}) {
59 value_ = value;
60 SetLocal(&value_);
61 }
62
63 // Getter/Setter for the stored value.
GetValue()64 virtual T GetValue() const { return value_; }
SetValue(T value)65 virtual void SetValue(T value) { value_ = value; }
66
GetDataPtr()67 const void* GetDataPtr() override {
68 return reinterpret_cast<const void*>(&value_);
69 }
SetDataFromPtr(const void * ptr,size_t max_sz)70 void SetDataFromPtr(const void* ptr, size_t max_sz) override {
71 memcpy(&value_, ptr, std::min(GetSize(), max_sz));
72 }
73
GetSize()74 size_t GetSize() const override { return sizeof(T); }
75
76 Type GetType() const override;
77
78 std::string GetTypeString() const override;
79
80 std::string ToString() const override;
81
82 protected:
83 // The stored value.
84 T value_;
85 };
86
87 template <typename T>
GetType()88 Type Reg<T>::GetType() const {
89 if constexpr (std::is_integral_v<T> || std::is_enum_v<T>) {
90 return Type::kInt;
91 }
92 if constexpr (std::is_floating_point_v<T>) {
93 return Type::kFloat;
94 }
95 if constexpr (std::is_pointer_v<T>) {
96 return Type::kPointer;
97 }
98 // Not reached
99 }
100
101 template <typename T>
GetTypeString()102 std::string Reg<T>::GetTypeString() const {
103 if constexpr (std::is_integral_v<T> || std::is_enum_v<T>) {
104 return "Integer";
105 }
106 if constexpr (std::is_floating_point_v<T>) {
107 return "Floating-point";
108 }
109 if constexpr (std::is_pointer_v<T>) {
110 return "Pointer";
111 }
112 // Not reached
113 }
114
115 template <typename T>
ToString()116 std::string Reg<T>::ToString() const {
117 if constexpr (std::is_integral_v<T>) {
118 return std::to_string(value_);
119 }
120 if constexpr (std::is_enum_v<T>) {
121 return std::to_string(static_cast<std::underlying_type_t<T>>(value_));
122 }
123 if constexpr (std::is_floating_point_v<T>) {
124 return absl::StrFormat("%.10f", value_);
125 }
126 if constexpr (std::is_pointer<T>::value) {
127 return absl::StrFormat("%p", value_);
128 }
129 // Not reached.
130 }
131
132 } // namespace sapi::v
133
134 #endif // SANDBOXED_API_VAR_REG_H_
135