#ifndef H_FIOBJ_NUMBERS_H #define H_FIOBJ_NUMBERS_H /* Copyright: Boaz Segev, 2017-2019 License: MIT */ #include #ifdef __cplusplus extern "C" { #endif /* ***************************************************************************** Numbers API (Integers) ***************************************************************************** */ /** Creates a Number object. Remember to use `fiobj_free`. */ FIO_INLINE FIOBJ fiobj_num_new(intptr_t num); /** Creates a temporary Number object. Avoid using `fiobj_free`. */ FIOBJ fiobj_num_tmp(intptr_t num); /* ***************************************************************************** Float API (Double) ***************************************************************************** */ /** Creates a Float object. Remember to use `fiobj_free`. */ FIOBJ fiobj_float_new(double num); /** Mutates a Float object's value. Effects every object's reference! */ void fiobj_float_set(FIOBJ obj, double num); /** Creates a temporary Float object. Avoid using `fiobj_free`. */ FIOBJ fiobj_float_tmp(double num); /* ***************************************************************************** Numerical Helpers: not FIOBJ specific, but included as part of the library ***************************************************************************** */ /** * A helper function that converts between String data to a signed int64_t. * * Numbers are assumed to be in base 10. * * The `0x##` (or `x##`) and `0b##` (or `b##`) are recognized as base 16 and * base 2 (binary MSB first) respectively. * * The pointer will be updated to point to the first byte after the number. */ int64_t fio_atol(char **pstr); /** A helper function that converts between String data to a signed double. */ double fio_atof(char **pstr); /** * A helper function that converts between a signed int64_t to a string. * * No overflow guard is provided, make sure there's at least 66 bytes available * (for base 2). * * Supports base 2, base 10 and base 16. An unsupported base will silently * default to base 10. Prefixes aren't added (i.e., no "0x" or "0b" at the * beginning of the string). * * Returns the number of bytes actually written (excluding the NUL terminator). */ size_t fio_ltoa(char *dest, int64_t num, uint8_t base); /** * A helper function that converts between a double to a string. * * No overflow guard is provided, make sure there's at least 130 bytes available * (for base 2). * * Supports base 2, base 10 and base 16. An unsupported base will silently * default to base 10. Prefixes aren't added (i.e., no "0x" or "0b" at the * beginning of the string). * * Returns the number of bytes actually written (excluding the NUL terminator). */ size_t fio_ftoa(char *dest, double num, uint8_t base); /** Converts a number to a temporary, thread safe, C string object */ fio_str_info_s __attribute__((deprecated("use local buffer with fio_ltoa"))) fio_ltocstr(long); /** Converts a float to a temporary, thread safe, C string object */ fio_str_info_s __attribute__((deprecated("use local buffer with fio_ftoa"))) fio_ftocstr(double); /* ***************************************************************************** Pointer Wrapping Helper MACROs (uses integers) ***************************************************************************** */ #define fiobj_ptr_wrap(ptr) fiobj_num_new((uintptr_t)(ptr)) #define fiobj_ptr_unwrap(obj) ((void *)fiobj_obj2num((obj))) /* ***************************************************************************** Inline Number Initialization ***************************************************************************** */ FIOBJ fiobj_num_new_bignum(intptr_t num); /** Creates a Number object. Remember to use `fiobj_free`. */ FIO_INLINE FIOBJ fiobj_num_new(intptr_t num) { if ((((uintptr_t)num & (FIOBJ_NUMBER_SIGN_BIT | FIOBJ_NUMBER_SIGN_EXCLUDE_BIT)) == 0) || (((uintptr_t)num & (FIOBJ_NUMBER_SIGN_BIT | FIOBJ_NUMBER_SIGN_EXCLUDE_BIT)) == (FIOBJ_NUMBER_SIGN_BIT | FIOBJ_NUMBER_SIGN_EXCLUDE_BIT))) { const uintptr_t num_abs = (uintptr_t)num & FIOBJ_NUMBER_SIGN_MASK; const uintptr_t num_sign = (uintptr_t)num & FIOBJ_NUMBER_SIGN_BIT; return ((num_abs << 1) | num_sign | FIOBJECT_NUMBER_FLAG); } return fiobj_num_new_bignum(num); } #if DEBUG void fiobj_test_numbers(void); #endif #ifdef __cplusplus } /* extern "C" */ #endif #endif