blob: fe9de4fa8daacc17454f3398480b834d1f1b6aa4 [file] [log] [blame]
/*
* object_header.h
*
* Created on: 21.02.2019
* Author: psota
*/
#ifndef BASYX_object_object_header_H
#define BASYX_object_object_header_H
#include <cstddef>
#include <memory>
#include <string>
#include <typeinfo>
#include <nlohmann/json.hpp>
#include <BaSyx/shared/object/obj_placeholder.h>
#include <vector>
#include <unordered_map>
namespace basyx {
// basyx::object
// Type-safe wrapper class for holding vab primitives
// The actual value is passed at construction time and stored inside a templated placeholder
// Stores its held value inside its own unique_ptr, thus resource will be freed automatically at destruction time
// Values can be retrieved type-safely using the basyx::object_cast function
class object
{
public:
enum class error
{
None,
PropertyNotFound,
IndexOutOfBounds,
NotInvokable,
ObjectAlreadyExists,
MalformedRequest,
};
public: // Type definitions
template<typename T>
using list_t = std::vector<T>;
template<typename T>
using hash_map_t = std::unordered_map<std::string, T>;
using object_list_t = list_t<basyx::object>;
using object_map_t = object::hash_map_t<basyx::object>;
using function_t = std::function<basyx::object(basyx::object*)>;
public: // Constructors
object();
object(const char *);
template <typename T>
object(const T& t);
//template<typename T>
//object(T && t)
// : content{ std::make_shared< Holder< typename std::remove_cv< typename std::decay<const T>::type>::type>>(std::forward<T>(t)) }
//{};
object(const object& other) = default;
object& operator=(const object& other) = default;
object(object&& other) = default;
object& operator=(object&& other) = default;
public: // Generic functions
const std::type_info& type() const
{
return content->type();
}
std::string Typename() const
{
return std::string{ content->type().name() };
}
basyx::type::objectType GetObjectType() const { return this->content->object_type(); };
basyx::type::valueType GetValueType() const { return this->content->value_type(); };
template <typename T>
bool InstanceOf() const noexcept
{
if (this->content == nullptr)
return false;
if (this->IsError())
return false;
return this->content->object_type() == basyx::type::basyx_type<T>::object_type
&& this->content->value_type() == basyx::type::basyx_type<T>::value_type;
};
template <typename T>
T Get()
{
return object_cast<T>(*this);
};
std::string & GetStringContent()
{
return this->Get<std::string&>();
}
template <typename T>
T* GetPtr()
{
// using non_ptr_t = std::remove_pointer<T>::type;
return object_cast_ptr<T>(this);
};
bool IsInvokable() const noexcept
{
return this->GetObjectType() == basyx::type::objectType::Function;
};
bool IsNull() const noexcept
{
return this->content == nullptr || this->InstanceOf<std::nullptr_t>() || this->IsError();
}
bool IsError() const noexcept
{
return this->GetObjectType() == basyx::type::objectType::Error;
};
error getError() const;
const std::string & getErrorMessage() const;
private: // Private type definitions
// PlaceHolder:
// Interface class for the actual value to be stored by the object object
// Allows introspection of type
using PlaceHolder = basyx::detail::objPlaceHolder;
private:
// The actual object holding the value
// std::unique_ptr<PlaceHolder> content;
std::shared_ptr<PlaceHolder> content;
public:
bool insert(basyx::object obj);
template<typename T>
bool insert(const T & t);
template<typename T>
bool insertKey(const std::string & key, const T & t, bool override = true);
std::size_t size();
template<typename T>
bool remove(const T & t);
bool remove(basyx::object & obj);
bool removeProperty(const std::string & propertyName);
bool hasProperty(const std::string & propertyName);
basyx::object getProperty(const std::string & propertyName);
basyx::object invoke();
basyx::object invoke(basyx::object & object);
bool empty();
public: // Object casting functions
// object_cast:
// Cast a basyx::object object to the desired type
// If the cast itself is not allowed on the held object, basyx::bad_object_cast exception will be thrown
template <typename T>
static T object_cast(object& operand);
template <typename T>
static T* object_cast_ptr(object * operand);
template <typename T>
static T* object_cast(object* operand) noexcept;
template <typename T>
static inline const T* object_cast(const object* operand);
public: // Factories
static object make_null();
static object make_error(error error_code);
static object make_error(error error_code, const std::string & message);
template<typename T>
static object make_object_ref(T* t);
template<typename T, typename... Args>
static object make_list(Args && ... args);
template<typename... Args>
static object make_object_list(Args && ... args);
template<typename T>
static object make_list(std::initializer_list<T>);
template<typename... Args>
static object make_map(Args && ... args);
template<typename... Args>
static object make_function(Args && ... args);
public: // operator overloads
template <typename T>
bool operator!=(const T& rhs) const;
template <typename T>
bool operator==(const T& rhs) const;
bool operator==(const basyx::object& rhs) const;
public:
friend void to_json(nlohmann::json& json, const basyx::object& object);
friend struct std::hash<basyx::object>;
};
void to_json(nlohmann::json& json, const basyx::object& object);
};
#include <functional>
namespace std
{
template<>
struct hash<basyx::object>
{
std::size_t operator()(basyx::object const & o) const noexcept
{
return reinterpret_cast<std::size_t>(o.content->get_address());
};
};
};
#endif /* BASYX_object_object_H */