sandboxed-api/sandboxed_api/var_reg.h

182 lines
5.3 KiB
C
Raw Normal View History

// 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
//
// 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 <inttypes.h>
#include <iostream>
#include <glog/logging.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:
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<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 {
static_assert(std::is_integral<T>() || std::is_floating_point<T>() ||
std::is_pointer<T>() || std::is_enum<T>(),
"Only register-sized types are allowed as template argument "
"for class Reg.");
public:
Reg() : Reg(static_cast<T>(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<const void*>(&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<T>() || std::is_enum<T>()) {
return Type::kInt;
}
if (std::is_floating_point<T>()) {
return Type::kFloat;
}
if (std::is_pointer<T>()) {
return Type::kPointer;
}
LOG(FATAL) << "Incorrect type";
}
std::string GetTypeString() const override {
if (std::is_integral<T>() || std::is_enum<T>()) {
return "Integer";
}
if (std::is_floating_point<T>()) {
return "Floating-point";
}
if (std::is_pointer<T>()) {
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<T>::value || std::is_enum<T>::value) {
if (std::is_integral<T>::value) {
signd = std::is_signed<T>::value;
}
switch (sizeof(T)) {
case 1:
if (signd) {
snprintf(buf, sizeof(buf), "%" PRId8,
*(reinterpret_cast<const uint8_t*>(&val_)));
} else {
snprintf(buf, sizeof(buf), "%" PRIu8,
*(reinterpret_cast<const uint8_t*>(&val_)));
}
break;
case 2:
if (signd) {
snprintf(buf, sizeof(buf), "%" PRId16,
*(reinterpret_cast<const uint16_t*>(&val_)));
} else {
snprintf(buf, sizeof(buf), "%" PRIu16,
*(reinterpret_cast<const uint16_t*>(&val_)));
}
break;
case 4:
if (signd) {
snprintf(buf, sizeof(buf), "%" PRId32,
*(reinterpret_cast<const uint32_t*>(&val_)));
} else {
snprintf(buf, sizeof(buf), "%" PRIu32,
*(reinterpret_cast<const uint32_t*>(&val_)));
}
break;
case 8:
if (signd) {
snprintf(buf, sizeof(buf), "%" PRId64,
*(reinterpret_cast<const uint64_t*>(&val_)));
} else {
snprintf(buf, sizeof(buf), "%" PRIu64,
*(reinterpret_cast<const uint64_t*>(&val_)));
}
break;
default:
LOG(FATAL) << "Incorrect type";
break;
}
} else if (std::is_floating_point<T>::value) {
if (std::is_same<T, float>::value) {
snprintf(buf, sizeof(buf), "%.10f",
*(reinterpret_cast<const float*>(&val_)));
} else if (std::is_same<T, double>::value) {
snprintf(buf, sizeof(buf), "%.10lf",
*(reinterpret_cast<const double*>(&val_)));
} else if (std::is_same<T, long double>::value) {
snprintf(buf, sizeof(buf), "%.10Lf",
*(reinterpret_cast<const long double*>(&val_)));
}
} else if (std::is_pointer<T>::value) {
snprintf(buf, sizeof(buf), "%p", *reinterpret_cast<void* const*>(&val_));
} else {
LOG(FATAL) << "Incorrect type";
}
return std::string(buf);
}
};
} // namespace sapi::v
#endif // SANDBOXED_API_VAR_REG_H_