// Copyright 2019 Google LLC. All Rights Reserved. // // 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 SANDBOXED_API_VAR_REG_H_ #define SANDBOXED_API_VAR_REG_H_ #include #include #include #include "sandboxed_api/var_abstract.h" namespace sapi { namespace 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: Callable(const Callable&) = delete; Callable& operator=(const Callable&) = delete; // 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 inernal ptr. void GetDataFromPtr(void* ptr, size_t max_sz) { size_t min_sz = std::min(GetSize(), max_sz); memcpy(ptr, GetDataPtr(), min_sz); } protected: Callable() = default; }; // class Reg represents register-sized variables. template class Reg : public Callable { static_assert(std::is_integral() || std::is_floating_point() || std::is_pointer() || std::is_enum(), "Only register-sized types are allowed as template argument " "for class Reg."); public: Reg() : Reg(static_cast(0)) {} explicit Reg(const T val) { val_ = val; SetLocal(&val_); } // Getter/Setter for the stored value. virtual T GetValue() const { return val_; } virtual void SetValue(T val) { val_ = val; } const void* GetDataPtr() override { return reinterpret_cast(&val_); } void SetDataFromPtr(const void* ptr, size_t max_sz) override { memcpy(&val_, ptr, std::min(GetSize(), max_sz)); } size_t GetSize() const override { return sizeof(T); } Type GetType() const override { if (std::is_integral() || std::is_enum()) { return Type::kInt; } if (std::is_floating_point()) { return Type::kFloat; } if (std::is_pointer()) { return Type::kPointer; } LOG(FATAL) << "Incorrect type"; } std::string GetTypeString() const override { if (std::is_integral() || std::is_enum()) { return "Integer"; } if (std::is_floating_point()) { return "Floating-point"; } if (std::is_pointer()) { return "Pointer"; } LOG(FATAL) << "Incorrect type"; } std::string ToString() const override { return ValToString(); } protected: // The stored value. T val_; private: std::string ValToString() const { char buf[32]; bool signd = true; if (std::is_integral::value || std::is_enum::value) { if (std::is_integral::value) { signd = std::is_signed::value; } switch (sizeof(T)) { case 1: if (signd) { snprintf(buf, sizeof(buf), "%" PRId8, *(reinterpret_cast(&val_))); } else { snprintf(buf, sizeof(buf), "%" PRIu8, *(reinterpret_cast(&val_))); } break; case 2: if (signd) { snprintf(buf, sizeof(buf), "%" PRId16, *(reinterpret_cast(&val_))); } else { snprintf(buf, sizeof(buf), "%" PRIu16, *(reinterpret_cast(&val_))); } break; case 4: if (signd) { snprintf(buf, sizeof(buf), "%" PRId32, *(reinterpret_cast(&val_))); } else { snprintf(buf, sizeof(buf), "%" PRIu32, *(reinterpret_cast(&val_))); } break; case 8: if (signd) { snprintf(buf, sizeof(buf), "%" PRId64, *(reinterpret_cast(&val_))); } else { snprintf(buf, sizeof(buf), "%" PRIu64, *(reinterpret_cast(&val_))); } break; default: LOG(FATAL) << "Incorrect type"; break; } } else if (std::is_floating_point::value) { if (std::is_same::value) { snprintf(buf, sizeof(buf), "%.10f", *(reinterpret_cast(&val_))); } else if (std::is_same::value) { snprintf(buf, sizeof(buf), "%.10lf", *(reinterpret_cast(&val_))); } else if (std::is_same::value) { snprintf(buf, sizeof(buf), "%.10Lf", *(reinterpret_cast(&val_))); } } else if (std::is_pointer::value) { snprintf(buf, sizeof(buf), "%p", *reinterpret_cast(&val_)); } else { LOG(FATAL) << "Incorrect type"; } return std::string(buf); } }; } // namespace v } // namespace sapi #endif // SANDBOXED_API_VAR_REG_H_