xo-tokenizer2/xo-object/src/object/ObjectConverter.cpp

203 lines
6.2 KiB
C++

/** @file ObjectConverter.cpp
*
* @author Roland Conybeare, Nov 2025
**/
#include "ObjectConverter.hpp"
#include "Integer.hpp"
#include "Float.hpp"
#include "Boolean.hpp"
#include "String.hpp"
#include "TaggedPtr.hpp"
#include "xo/alloc/Blob.hpp"
namespace xo {
using xo::reflect::Reflect;
using xo::reflect::TaggedPtr;
using xo::reflect::TypeId;
using xo::gc::IAlloc;
namespace obj {
namespace {
template <typename T>
gp<Object>
int_to_object(IAlloc * mm, const TaggedPtr & src)
{
T * native = src.recover_native<T>();
assert(native);
return Integer::make(mm, *native);
}
template <typename T>
TaggedPtr
object_to_int(IAlloc * mm, gp<Object> obj)
{
/* mm cannot be GC allocator!
* That's Object-only
*/
gp<Integer> int_obj = Integer::from(obj);
if (!int_obj.get()) {
throw std::runtime_error(tostr("Object obj found where Integer expected",
xtag("obj", obj)));
}
/* allocate a Blob wrapper to satsify GC memory layout demands */
gp<Blob> tmp = Blob::make(mm, sizeof(T));
T * p = reinterpret_cast<T *>(tmp->data());
*p = int_obj->value();
/* WARNING: retval invalidated when *mm cleared/recycled/collected */
return Reflect::make_tp(p);
}
template <typename T>
gp<Object>
float_to_object(IAlloc * mm, const TaggedPtr & src)
{
T * native = src.recover_native<T>();
assert(native);
return Float::make(mm, *native);
}
template <typename T>
TaggedPtr
object_to_float(IAlloc * mm, gp<Object> obj)
{
/* mm cannot be GC allocator!
* That's Object-only
*/
gp<Float> float_obj = Float::from(obj);
if (!float_obj.get()) {
throw std::runtime_error(tostr("Object obj found where Float expected",
xtag("obj", obj)));
}
/* allocate a Blob wrapper to satsify GC memory layout demands */
gp<Blob> tmp = Blob::make(mm, sizeof(T));
T * p = reinterpret_cast<T *>(tmp->data());
*p = float_obj->value();
/* WARNING: retval invalidated when *mm cleared/recycled/collected */
return Reflect::make_tp(p);
}
gp<Object>
bool_to_object(IAlloc * /*mm*/, const TaggedPtr & src)
{
bool * native = src.recover_native<bool>();
assert(native);
return Boolean::boolean_obj(*native);
}
TaggedPtr
object_to_bool(IAlloc * /*mm*/, gp<Object> obj)
{
static bool s_true = true;
static bool s_false = false;
gp<Boolean> bool_obj = Boolean::from(obj);
if (!bool_obj.get()) {
throw std::runtime_error(tostr("Object obj found where Boolean expected",
xtag("obj", obj)));
}
return Reflect::make_tp(bool_obj->value() ? &s_true : &s_false);
}
gp<Object>
string_to_object(IAlloc * mm, const TaggedPtr & src)
{
std::string * native = src.recover_native<std::string>();
assert(native);
return String::copy(mm, native->c_str());
}
TaggedPtr
object_to_string(IAlloc * /*mm*/, gp<Object> obj)
{
gp<String> string_obj = String::from(obj);
if (!string_obj.get()) {
throw std::runtime_error(tostr("Object obj founcd where String expected",
xtag("obj", obj)));
}
// still don't have good solver for this yet
assert(false);
}
}
ObjectConverter::ObjectConverter()
{
this->establish_conversion<std::int32_t>(&int_to_object<std::int32_t>, &object_to_int<std::int32_t>);
this->establish_conversion<std::int64_t>(&int_to_object<std::int64_t>, &object_to_int<std::int64_t>);
this->establish_conversion<double>(&float_to_object<double>, &object_to_float<double>);
this->establish_conversion<bool>(&bool_to_object, &object_to_bool);
this->establish_conversion<std::string>(&string_to_object, &object_to_string);
}
gp<Object>
ObjectConverter::tp_to_object(IAlloc * mm, const TaggedPtr & x_tp, bool throw_flag)
{
using xo::reflect::Reflect;
using xo::reflect::TaggedPtr;
const Converter * cvt = cvt_.lookup(x_tp.td());
if (cvt) {
return (cvt->cvt_to_object_)(mm, x_tp);
} else {
if (throw_flag) {
throw std::runtime_error(tostr("no to-object-converter available for instance of type",
xtag("id", x_tp.td()->id()),
xtag("name", x_tp.td()->short_name())));
}
return nullptr;
}
}
TaggedPtr
ObjectConverter::tp_from_object(IAlloc * mm, gp<Object> & obj, TypeId target_id, bool throw_flag)
{
const Converter * cvt = cvt_.lookup(target_id);
if (cvt) {
return (cvt->cvt_from_object_)(mm, obj);
} else {
if (throw_flag) {
throw std::runtime_error(tostr("no from-object-converter available for instance of type",
xtag("id", target_id)));
}
return TaggedPtr::universal_null();
}
}
}
}
/* end ObjectConverter.cpp */