#ifndef RAVA_NANBOX_H #define RAVA_NANBOX_H #include #include #include #include typedef uint64_t RavaNanboxValue_t; #define RAVA_SIGN_BIT 0x8000000000000000ULL #define RAVA_EXPONENT_MASK 0x7FF0000000000000ULL #define RAVA_QNAN 0x7FF8000000000000ULL #define RAVA_TAG_MASK 0xFFFF000000000000ULL #define RAVA_PAYLOAD_MASK 0x0000FFFFFFFFFFFFULL #define RAVA_TAG_INT (RAVA_QNAN | 0x0001000000000000ULL) #define RAVA_TAG_LONG (RAVA_QNAN | 0x0002000000000000ULL) #define RAVA_TAG_BOOL (RAVA_QNAN | 0x0003000000000000ULL) #define RAVA_TAG_NULL (RAVA_QNAN | 0x0004000000000000ULL) #define RAVA_TAG_OBJECT (RAVA_QNAN | 0x0005000000000000ULL) #define RAVA_TAG_STRING (RAVA_QNAN | 0x0006000000000000ULL) #define RAVA_TAG_ARRAY (RAVA_QNAN | 0x0007000000000000ULL) static inline RavaNanboxValue_t rava_nanbox_int(int64_t v) { return RAVA_TAG_LONG | ((uint64_t)v & RAVA_PAYLOAD_MASK); } static inline RavaNanboxValue_t rava_nanbox_long(int64_t v) { return RAVA_TAG_LONG | ((uint64_t)v & RAVA_PAYLOAD_MASK); } static inline RavaNanboxValue_t rava_nanbox_bool(bool v) { return RAVA_TAG_BOOL | (v ? 1ULL : 0ULL); } static inline RavaNanboxValue_t rava_nanbox_null(void) { return RAVA_TAG_NULL; } static inline RavaNanboxValue_t rava_nanbox_double(double v) { union { double d; uint64_t u; } u = {.d = v}; return u.u; } static inline RavaNanboxValue_t rava_nanbox_object(void* ptr) { return RAVA_TAG_OBJECT | ((uint64_t)(uintptr_t)ptr & RAVA_PAYLOAD_MASK); } static inline RavaNanboxValue_t rava_nanbox_string(const char* ptr) { return RAVA_TAG_STRING | ((uint64_t)(uintptr_t)ptr & RAVA_PAYLOAD_MASK); } static inline RavaNanboxValue_t rava_nanbox_array(void* ptr) { return RAVA_TAG_ARRAY | ((uint64_t)(uintptr_t)ptr & RAVA_PAYLOAD_MASK); } static inline bool rava_nanbox_is_int(RavaNanboxValue_t v) { return (v & RAVA_TAG_MASK) == RAVA_TAG_LONG; } static inline bool rava_nanbox_is_long(RavaNanboxValue_t v) { return (v & RAVA_TAG_MASK) == RAVA_TAG_LONG; } static inline bool rava_nanbox_is_bool(RavaNanboxValue_t v) { return (v & RAVA_TAG_MASK) == RAVA_TAG_BOOL; } static inline bool rava_nanbox_is_null(RavaNanboxValue_t v) { return v == RAVA_TAG_NULL; } static inline bool rava_nanbox_is_object(RavaNanboxValue_t v) { return (v & RAVA_TAG_MASK) == RAVA_TAG_OBJECT; } static inline bool rava_nanbox_is_string(RavaNanboxValue_t v) { return (v & RAVA_TAG_MASK) == RAVA_TAG_STRING; } static inline bool rava_nanbox_is_array(RavaNanboxValue_t v) { return (v & RAVA_TAG_MASK) == RAVA_TAG_ARRAY; } static inline bool rava_nanbox_is_double(RavaNanboxValue_t v) { return (v & RAVA_QNAN) != RAVA_QNAN; } static inline int64_t rava_nanbox_as_int(RavaNanboxValue_t v) { int64_t payload = (int64_t)(v & RAVA_PAYLOAD_MASK); if (payload & 0x800000000000ULL) { payload |= (int64_t)0xFFFF000000000000ULL; } return payload; } static inline int64_t rava_nanbox_as_long(RavaNanboxValue_t v) { int64_t payload = (int64_t)(v & RAVA_PAYLOAD_MASK); if (payload & 0x800000000000ULL) { payload |= (int64_t)0xFFFF000000000000ULL; } return payload; } static inline bool rava_nanbox_as_bool(RavaNanboxValue_t v) { return (v & 1) != 0; } static inline double rava_nanbox_as_double(RavaNanboxValue_t v) { union { double d; uint64_t u; } u = {.u = v}; return u.d; } static inline void* rava_nanbox_as_object(RavaNanboxValue_t v) { return (void*)(uintptr_t)(v & RAVA_PAYLOAD_MASK); } static inline const char* rava_nanbox_as_string(RavaNanboxValue_t v) { return (const char*)(uintptr_t)(v & RAVA_PAYLOAD_MASK); } static inline void* rava_nanbox_as_array(RavaNanboxValue_t v) { return (void*)(uintptr_t)(v & RAVA_PAYLOAD_MASK); } static inline int64_t rava_nanbox_to_int(RavaNanboxValue_t v) { if (rava_nanbox_is_int(v)) return rava_nanbox_as_int(v); if (rava_nanbox_is_long(v)) return rava_nanbox_as_long(v); if (rava_nanbox_is_bool(v)) return rava_nanbox_as_bool(v) ? 1 : 0; if (rava_nanbox_is_double(v)) return (int64_t)rava_nanbox_as_double(v); return 0; } static inline int64_t rava_nanbox_to_long(RavaNanboxValue_t v) { if (rava_nanbox_is_int(v)) return (int64_t)rava_nanbox_as_int(v); if (rava_nanbox_is_long(v)) return rava_nanbox_as_long(v); if (rava_nanbox_is_bool(v)) return rava_nanbox_as_bool(v) ? 1 : 0; if (rava_nanbox_is_double(v)) return (int64_t)rava_nanbox_as_double(v); return 0; } static inline double rava_nanbox_to_double(RavaNanboxValue_t v) { if (rava_nanbox_is_double(v)) return rava_nanbox_as_double(v); if (rava_nanbox_is_int(v)) return (double)rava_nanbox_as_int(v); if (rava_nanbox_is_long(v)) return (double)rava_nanbox_as_long(v); if (rava_nanbox_is_bool(v)) return rava_nanbox_as_bool(v) ? 1.0 : 0.0; return 0.0; } static inline bool rava_nanbox_to_bool(RavaNanboxValue_t v) { if (rava_nanbox_is_null(v)) return false; if (rava_nanbox_is_bool(v)) return rava_nanbox_as_bool(v); if (rava_nanbox_is_int(v)) return rava_nanbox_as_int(v) != 0; if (rava_nanbox_is_long(v)) return rava_nanbox_as_long(v) != 0; if (rava_nanbox_is_double(v)) return rava_nanbox_as_double(v) != 0.0; return true; } #endif