From 141466b6ace107541a9d17310dddd6679a480802 Mon Sep 17 00:00:00 2001 From: Petr Kubica Date: Sun, 7 Jul 2024 13:37:13 +0200 Subject: [PATCH] implement conversions for up to uint64_t --- src/jac/machine/traits.h | 91 +++++++++++++++++++++++----------------- tests/values.cpp | 16 ++++--- 2 files changed, 59 insertions(+), 48 deletions(-) diff --git a/src/jac/machine/traits.h b/src/jac/machine/traits.h index 4002779..09051f6 100644 --- a/src/jac/machine/traits.h +++ b/src/jac/machine/traits.h @@ -1,5 +1,6 @@ #pragma once +#include #include #include "context.h" @@ -33,59 +34,71 @@ struct ConvTraits { }; namespace detail { - template - struct IntConvBase { - static T from(ContextRef ctx, ValueWeak val) { - int32_t res; - int ex = JS_ToInt32(ctx, &res, val.getVal()); - if (ex < 0) { - throw Exception::create(Exception::Type::TypeError, "Failed to convert to int"); - } - return res; - } - - static Value to(ContextRef ctx, T val) { - return Value(ctx, JS_NewInt32(ctx, val)); - } - }; template - struct FloatConvBase { - static T from(ContextRef ctx, ValueWeak val) { - double res; - int ex = JS_ToFloat64(ctx, &res, val.getVal()); - if (ex < 0) { - throw Exception::create(Exception::Type::TypeError, "Failed to convert to double"); - } - return res; - } + constexpr bool is_leq_i32 = (std::is_signed_v && sizeof(T) <= sizeof(int32_t)) + || (std::is_unsigned_v && sizeof(T) < sizeof(int32_t)); - static Value to(ContextRef ctx, T val) { - return Value(ctx, JS_NewFloat64(ctx, val)); - } - }; } // namespace detail template struct ConvTraits - && std::is_signed_v - && sizeof(T) <= sizeof(int32_t) -, T>> : public detail::IntConvBase {}; + std::is_integral_v + && detail::is_leq_i32 +, T>> { + static T from(ContextRef ctx, ValueWeak val) { + int32_t res; + int ex = JS_ToInt32(ctx, &res, val.getVal()); + if (ex < 0) { + throw Exception::create(Exception::Type::TypeError, "Failed to convert to int"); + } + return res; + } + + static Value to(ContextRef ctx, T val) { + return Value(ctx, JS_NewInt32(ctx, val)); + } +}; template struct ConvTraits - && std::is_unsigned_v - && sizeof(T) < sizeof(int32_t) -, T>> : public detail::IntConvBase {}; + std::is_floating_point_v + && sizeof(T) <= sizeof(double) +, T>> { + static T from(ContextRef ctx, ValueWeak val) { + double res; + int ex = JS_ToFloat64(ctx, &res, val.getVal()); + if (ex < 0) { + throw Exception::create(Exception::Type::TypeError, "Failed to convert to double"); + } + return res; + } + + static Value to(ContextRef ctx, T val) { + return Value(ctx, JS_NewFloat64(ctx, val)); + } +}; template struct ConvTraits - && sizeof(T) <= sizeof(double) -, T>> : public detail::FloatConvBase {}; + std::is_integral_v + && sizeof(T) <= sizeof(int64_t) + && !detail::is_leq_i32 +, T>> { + static T from(ContextRef ctx, ValueWeak val) { + int64_t res = 0; + int ex = JS_ToInt64(ctx, &res, val.getVal()); + if (ex < 0) { + throw Exception::create(Exception::Type::TypeError, "Failed to convert to int"); + } + return res; + } + + static Value to(ContextRef ctx, T val) { + return Value(ctx, JS_NewInt64(ctx, val)); + } +}; template<> struct ConvTraits { diff --git a/tests/values.cpp b/tests/values.cpp index fb83954..50183c5 100644 --- a/tests/values.cpp +++ b/tests/values.cpp @@ -1,7 +1,9 @@ #include #include +#include #include +#include #include #include #include @@ -32,7 +34,11 @@ TEST_CASE("To JS value", "[base]") { val{"uint8_t", [](jac::ContextRef ctx) { return jac::Value::from(ctx, uint8_t(42)); }, "number", "42"}, val{"int16_t", [](jac::ContextRef ctx) { return jac::Value::from(ctx, int16_t(-42)); }, "number", "-42"}, val{"uint16_t", [](jac::ContextRef ctx) { return jac::Value::from(ctx, uint16_t(42)); }, "number", "42"}, - val{"int32_t", [](jac::ContextRef ctx) { return jac::Value::from(ctx, int32_t(-42)); }, "number", "-42"}, + val{"int32_t", [](jac::ContextRef ctx) { return jac::Value::from(ctx, int32_t(std::numeric_limits::max())); }, "number", std::to_string(std::numeric_limits::max())}, + val{"int32_t", [](jac::ContextRef ctx) { return jac::Value::from(ctx, int32_t(std::numeric_limits::min())); }, "number", std::to_string(std::numeric_limits::min())}, + val{"uint32_t", [](jac::ContextRef ctx) { return jac::Value::from(ctx, std::numeric_limits::max()); }, "number", std::to_string(std::numeric_limits::max())}, + val{"int64_t", [](jac::ContextRef ctx) { return jac::Value::from(ctx, int64_t(-0xf00000000)); }, "number", std::to_string(-0xf00000000)}, + val{"uint64_t", [](jac::ContextRef ctx) { return jac::Value::from(ctx, uint64_t(0xf00000000)); }, "number", std::to_string(0xf00000000)}, val{"const c string", [](jac::ContextRef ctx) { return jac::Value::from(ctx, "Hello World"); }, "string", "Hello World"}, val{"non const c string", [](jac::ContextRef ctx) { std::string_view str = "Hello World"; @@ -82,14 +88,6 @@ TEST_CASE("To JS value", "[base]") { REQUIRE(reports[0] == "number"); REQUIRE(reports[1].substr(0, 4) == "42.7"); } - - SECTION("Invalid types") { - static_assert(std::is_void_v::from(std::declval(), std::declval()))>, "Invalid type"); - static_assert(std::is_void_v::to(std::declval(), std::declval()))>, "Invalid type"); - - static_assert(std::is_void_v::from(std::declval(), std::declval()))>, "Invalid type"); - static_assert(std::is_void_v::to(std::declval(), std::declval()))>, "Invalid type"); - } }