moo/lib/moo-cmn.h

1110 lines
39 KiB
C

/*
* $Id$
*
Copyright (c) 2014-2019 Chung, Hyung-Hwan. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _MOO_CMN_H_
#define _MOO_CMN_H_
/* WARNING: NEVER CHANGE/DELETE THE FOLLOWING MOO_HAVE_CFG_H DEFINITION.
* IT IS USED FOR DEPLOYMENT BY MAKEFILE.AM */
/*#define MOO_HAVE_CFG_H*/
#if defined(MOO_HAVE_CFG_H)
# include <moo-cfg.h>
#elif defined(_WIN32)
# include <moo-msw.h>
#elif defined(__OS2__)
# include <moo-os2.h>
#elif defined(__DOS__)
# include <moo-dos.h>
#elif defined(macintosh)
# include <moo-mac.h> /* class mac os */
#else
# error UNSUPPORTED SYSTEM
#endif
/* =========================================================================
* ARCHITECTURE/COMPILER TWEAKS
* ========================================================================= */
#if defined(EMSCRIPTEN)
# if defined(MOO_SIZEOF___INT128)
# undef MOO_SIZEOF___INT128
# define MOO_SIZEOF___INT128 0
# endif
# if defined(MOO_SIZEOF_LONG) && defined(MOO_SIZEOF_INT) && (MOO_SIZEOF_LONG > MOO_SIZEOF_INT)
/* autoconf doesn't seem to match actual emscripten */
# undef MOO_SIZEOF_LONG
# define MOO_SIZEOF_LONG MOO_SIZEOF_INT
# endif
# include <emscripten/emscripten.h> /* EMSCRIPTEN_KEEPALIVE */
#endif
#if defined(__GNUC__) && defined(__arm__) && !defined(__ARM_ARCH)
# if defined(__ARM_ARCH_8__)
# define __ARM_ARCH 8
# elif defined(__ARM_ARCH_7__)
# define __ARM_ARCH 7
# elif defined(__ARM_ARCH_6__)
# define __ARM_ARCH 6
# elif defined(__ARM_ARCH_5__)
# define __ARM_ARCH 5
# elif defined(__ARM_ARCH_4__)
# define __ARM_ARCH 4
# endif
#endif
/* =========================================================================
* PRIMITIVE TYPE DEFINTIONS
* ========================================================================= */
/* moo_int8_t */
#if defined(MOO_SIZEOF_CHAR) && (MOO_SIZEOF_CHAR == 1)
# define MOO_HAVE_UINT8_T
# define MOO_HAVE_INT8_T
# define MOO_SIZEOF_UINT8_T (MOO_SIZEOF_CHAR)
# define MOO_SIZEOF_INT8_T (MOO_SIZEOF_CHAR)
typedef unsigned char moo_uint8_t;
typedef signed char moo_int8_t;
#elif defined(MOO_SIZEOF___INT8) && (MOO_SIZEOF___INT8 == 1)
# define MOO_HAVE_UINT8_T
# define MOO_HAVE_INT8_T
# define MOO_SIZEOF_UINT8_T (MOO_SIZEOF___INT8)
# define MOO_SIZEOF_INT8_T (MOO_SIZEOF___INT8)
typedef unsigned __int8 moo_uint8_t;
typedef signed __int8 moo_int8_t;
#elif defined(MOO_SIZEOF___INT8_T) && (MOO_SIZEOF___INT8_T == 1)
# define MOO_HAVE_UINT8_T
# define MOO_HAVE_INT8_T
# define MOO_SIZEOF_UINT8_T (MOO_SIZEOF___INT8_T)
# define MOO_SIZEOF_INT8_T (MOO_SIZEOF___INT8_T)
typedef unsigned __int8_t moo_uint8_t;
typedef signed __int8_t moo_int8_t;
#else
# define MOO_HAVE_UINT8_T
# define MOO_HAVE_INT8_T
# define MOO_SIZEOF_UINT8_T (1)
# define MOO_SIZEOF_INT8_T (1)
typedef unsigned char moo_uint8_t;
typedef signed char moo_int8_t;
#endif
/* moo_int16_t */
#if defined(MOO_SIZEOF_SHORT) && (MOO_SIZEOF_SHORT == 2)
# define MOO_HAVE_UINT16_T
# define MOO_HAVE_INT16_T
# define MOO_SIZEOF_UINT16_T (MOO_SIZEOF_SHORT)
# define MOO_SIZEOF_INT16_T (MOO_SIZEOF_SHORT)
typedef unsigned short int moo_uint16_t;
typedef signed short int moo_int16_t;
#elif defined(MOO_SIZEOF___INT16) && (MOO_SIZEOF___INT16 == 2)
# define MOO_HAVE_UINT16_T
# define MOO_HAVE_INT16_T
# define MOO_SIZEOF_UINT16_T (MOO_SIZEOF___INT16)
# define MOO_SIZEOF_INT16_T (MOO_SIZEOF___INT16)
typedef unsigned __int16 moo_uint16_t;
typedef signed __int16 moo_int16_t;
#elif defined(MOO_SIZEOF___INT16_T) && (MOO_SIZEOF___INT16_T == 2)
# define MOO_HAVE_UINT16_T
# define MOO_HAVE_INT16_T
# define MOO_SIZEOF_UINT16_T (MOO_SIZEOF___INT16_T)
# define MOO_SIZEOF_INT16_T (MOO_SIZEOF___INT16_T)
typedef unsigned __int16_t moo_uint16_t;
typedef signed __int16_t moo_int16_t;
#else
# define MOO_HAVE_UINT16_T
# define MOO_HAVE_INT16_T
# define MOO_SIZEOF_UINT16_T (2)
# define MOO_SIZEOF_INT16_T (2)
typedef unsigned short int moo_uint16_t;
typedef signed short int moo_int16_t;
#endif
/* moo_int32_t */
#if defined(MOO_SIZEOF_INT) && (MOO_SIZEOF_INT == 4)
# define MOO_HAVE_UINT32_T
# define MOO_HAVE_INT32_T
# define MOO_SIZEOF_UINT32_T (MOO_SIZEOF_INT)
# define MOO_SIZEOF_INT32_T (MOO_SIZEOF_INT)
typedef unsigned int moo_uint32_t;
typedef signed int moo_int32_t;
#elif defined(MOO_SIZEOF_LONG) && (MOO_SIZEOF_LONG == 4)
# define MOO_HAVE_UINT32_T
# define MOO_HAVE_INT32_T
# define MOO_SIZEOF_UINT32_T (MOO_SIZEOF_LONG)
# define MOO_SIZEOF_INT32_T (MOO_SIZEOF_LONG)
typedef unsigned long int moo_uint32_t;
typedef signed long int moo_int32_t;
#elif defined(MOO_SIZEOF___INT32) && (MOO_SIZEOF___INT32 == 4)
# define MOO_HAVE_UINT32_T
# define MOO_HAVE_INT32_T
# define MOO_SIZEOF_UINT32_T (MOO_SIZEOF___INT32)
# define MOO_SIZEOF_INT32_T (MOO_SIZEOF___INT32)
typedef unsigned __int32 moo_uint32_t;
typedef signed __int32 moo_int32_t;
#elif defined(MOO_SIZEOF___INT32_T) && (MOO_SIZEOF___INT32_T == 4)
# define MOO_HAVE_UINT32_T
# define MOO_HAVE_INT32_T
# define MOO_SIZEOF_UINT32_T (MOO_SIZEOF___INT32_T)
# define MOO_SIZEOF_INT32_T (MOO_SIZEOF___INT32_T)
typedef unsigned __int32_t moo_uint32_t;
typedef signed __int32_t moo_int32_t;
#elif defined(__DOS__)
# define MOO_HAVE_UINT32_T
# define MOO_HAVE_INT32_T
# define MOO_SIZEOF_UINT32_T (4)
# define MOO_SIZEOF_INT32_T (4)
typedef unsigned long int moo_uint32_t;
typedef signed long int moo_int32_t;
#else
# define MOO_HAVE_UINT32_T
# define MOO_HAVE_INT32_T
# define MOO_SIZEOF_UINT32_T (4)
# define MOO_SIZEOF_INT32_T (4)
typedef unsigned int moo_uint32_t;
typedef signed int moo_int32_t;
#endif
/* moo_int64_t */
#if defined(MOO_SIZEOF_INT) && (MOO_SIZEOF_INT == 8)
# define MOO_HAVE_UINT64_T
# define MOO_HAVE_INT64_T
# define MOO_SIZEOF_UINT64_T (MOO_SIZEOF_INT)
# define MOO_SIZEOF_INT64_T (MOO_SIZEOF_INT)
typedef unsigned int moo_uint64_t;
typedef signed int moo_int64_t;
#elif defined(MOO_SIZEOF_LONG) && (MOO_SIZEOF_LONG == 8)
# define MOO_HAVE_UINT64_T
# define MOO_HAVE_INT64_T
# define MOO_SIZEOF_UINT64_T (MOO_SIZEOF_LONG)
# define MOO_SIZEOF_INT64_T (MOO_SIZEOF_LONG)
typedef unsigned long int moo_uint64_t;
typedef signed long int moo_int64_t;
#elif defined(MOO_SIZEOF_LONG_LONG) && (MOO_SIZEOF_LONG_LONG == 8)
# define MOO_HAVE_UINT64_T
# define MOO_HAVE_INT64_T
# define MOO_SIZEOF_UINT64_T (MOO_SIZEOF_LONG_LONG)
# define MOO_SIZEOF_INT64_T (MOO_SIZEOF_LONG_LONG)
typedef unsigned long long int moo_uint64_t;
typedef signed long long int moo_int64_t;
#elif defined(MOO_SIZEOF___INT64) && (MOO_SIZEOF___INT64 == 8)
# define MOO_HAVE_UINT64_T
# define MOO_HAVE_INT64_T
# define MOO_SIZEOF_UINT64_T (MOO_SIZEOF_LONG___INT64)
# define MOO_SIZEOF_INT64_T (MOO_SIZEOF_LONG___INT64)
typedef unsigned __int64 moo_uint64_t;
typedef signed __int64 moo_int64_t;
#elif defined(MOO_SIZEOF___INT64_T) && (MOO_SIZEOF___INT64_T == 8)
# define MOO_HAVE_UINT64_T
# define MOO_HAVE_INT64_T
# define MOO_SIZEOF_UINT64_T (MOO_SIZEOF_LONG___INT64_T)
# define MOO_SIZEOF_INT64_T (MOO_SIZEOF_LONG___INT64_T)
typedef unsigned __int64_t moo_uint64_t;
typedef signed __int64_t moo_int64_t;
#else
/* no 64-bit integer */
#endif
/* moo_int128_t */
#if defined(MOO_SIZEOF_INT) && (MOO_SIZEOF_INT == 16)
# define MOO_HAVE_UINT128_T
# define MOO_HAVE_INT128_T
# define MOO_SIZEOF_UINT128_T (MOO_SIZEOF_INT)
# define MOO_SIZEOF_INT128_T (MOO_SIZEOF_INT)
typedef unsigned int moo_uint128_t;
typedef signed int moo_int128_t;
#elif defined(MOO_SIZEOF_LONG) && (MOO_SIZEOF_LONG == 16)
# define MOO_HAVE_UINT128_T
# define MOO_HAVE_INT128_T
# define MOO_SIZEOF_UINT128_T (MOO_SIZEOF_LONG)
# define MOO_SIZEOF_INT128_T (MOO_SIZEOF_LONG)
typedef unsigned long int moo_uint128_t;
typedef signed long int moo_int128_t;
#elif defined(MOO_SIZEOF_LONG_LONG) && (MOO_SIZEOF_LONG_LONG == 16)
# define MOO_HAVE_UINT128_T
# define MOO_HAVE_INT128_T
# define MOO_SIZEOF_UINT128_T (MOO_SIZEOF_LONG_LONG)
# define MOO_SIZEOF_INT128_T (MOO_SIZEOF_LONG_LONG)
typedef unsigned long long int moo_uint128_t;
typedef signed long long int moo_int128_t;
#elif defined(MOO_SIZEOF___INT128) && (MOO_SIZEOF___INT128 == 16)
# define MOO_HAVE_UINT128_T
# define MOO_HAVE_INT128_T
# define MOO_SIZEOF_UINT128_T (MOO_SIZEOF___INT128)
# define MOO_SIZEOF_INT128_T (MOO_SIZEOF___INT128)
typedef unsigned __int128 moo_uint128_t;
typedef signed __int128 moo_int128_t;
#elif defined(MOO_SIZEOF___INT128_T) && (MOO_SIZEOF___INT128_T == 16)
# define MOO_HAVE_UINT128_T
# define MOO_HAVE_INT128_T
# define MOO_SIZEOF_UINT128_T (MOO_SIZEOF___INT128_T)
# define MOO_SIZEOF_INT128_T (MOO_SIZEOF___INT128_T)
#if defined(MOO_SIZEOF___UINT128_T) && (MOO_SIZEOF___UINT128_T == MOO_SIZEOF___INT128_T)
typedef __uint128_t moo_uint128_t;
typedef __int128_t moo_int128_t;
#elif defined(__clang__)
typedef __uint128_t moo_uint128_t;
typedef __int128_t moo_int128_t;
#else
typedef unsigned __int128_t moo_uint128_t;
typedef signed __int128_t moo_int128_t;
#endif
#else
/* no 128-bit integer */
#endif
#if defined(MOO_HAVE_UINT8_T) && (MOO_SIZEOF_VOID_P == 1)
# error UNSUPPORTED POINTER SIZE
#elif defined(MOO_HAVE_UINT16_T) && (MOO_SIZEOF_VOID_P == 2)
typedef moo_uint16_t moo_uintptr_t;
typedef moo_int16_t moo_intptr_t;
typedef moo_uint8_t moo_ushortptr_t;
typedef moo_int8_t moo_shortptr_t;
#elif defined(MOO_HAVE_UINT32_T) && (MOO_SIZEOF_VOID_P == 4)
typedef moo_uint32_t moo_uintptr_t;
typedef moo_int32_t moo_intptr_t;
typedef moo_uint16_t moo_ushortptr_t;
typedef moo_int16_t moo_shortptr_t;
#elif defined(MOO_HAVE_UINT64_T) && (MOO_SIZEOF_VOID_P == 8)
typedef moo_uint64_t moo_uintptr_t;
typedef moo_int64_t moo_intptr_t;
typedef moo_uint32_t moo_ushortptr_t;
typedef moo_int32_t moo_shortptr_t;
#elif defined(MOO_HAVE_UINT128_T) && (MOO_SIZEOF_VOID_P == 16)
typedef moo_uint128_t moo_uintptr_t;
typedef moo_int128_t moo_intptr_t;
typedef moo_uint64_t moo_ushortptr_t;
typedef moo_int64_t moo_shortptr_t;
#else
# error UNKNOWN POINTER SIZE
#endif
#define MOO_SIZEOF_INTPTR_T MOO_SIZEOF_VOID_P
#define MOO_SIZEOF_UINTPTR_T MOO_SIZEOF_VOID_P
#define MOO_SIZEOF_SHORTPTR_T (MOO_SIZEOF_VOID_P / 2)
#define MOO_SIZEOF_USHORTPTR_T (MOO_SIZEOF_VOID_P / 2)
#if defined(MOO_HAVE_INT128_T)
# define MOO_SIZEOF_INTMAX_T 16
# define MOO_SIZEOF_UINTMAX_T 16
typedef moo_int128_t moo_intmax_t;
typedef moo_uint128_t moo_uintmax_t;
#elif defined(MOO_HAVE_INT64_T)
# define MOO_SIZEOF_INTMAX_T 8
# define MOO_SIZEOF_UINTMAX_T 8
typedef moo_int64_t moo_intmax_t;
typedef moo_uint64_t moo_uintmax_t;
#elif defined(MOO_HAVE_INT32_T)
# define MOO_SIZEOF_INTMAX_T 4
# define MOO_SIZEOF_UINTMAX_T 4
typedef moo_int32_t moo_intmax_t;
typedef moo_uint32_t moo_uintmax_t;
#elif defined(MOO_HAVE_INT16_T)
# define MOO_SIZEOF_INTMAX_T 2
# define MOO_SIZEOF_UINTMAX_T 2
typedef moo_int16_t moo_intmax_t;
typedef moo_uint16_t moo_uintmax_t;
#elif defined(MOO_HAVE_INT8_T)
# define MOO_SIZEOF_INTMAX_T 1
# define MOO_SIZEOF_UINTMAX_T 1
typedef moo_int8_t moo_intmax_t;
typedef moo_uint8_t moo_uintmax_t;
#else
# error UNKNOWN INTMAX SIZE
#endif
/* =========================================================================
* FLOATING-POINT TYPE
* ========================================================================= */
/** \typedef moo_fltbas_t
* The moo_fltbas_t type defines the largest floating-pointer number type
* naturally supported.
*/
#if defined(__FreeBSD__) || defined(__MINGW32__)
/* TODO: check if the support for long double is complete.
* if so, use long double for moo_flt_t */
typedef double moo_fltbas_t;
# define MOO_SIZEOF_FLTBAS_T MOO_SIZEOF_DOUBLE
#elif MOO_SIZEOF_LONG_DOUBLE > MOO_SIZEOF_DOUBLE
typedef long double moo_fltbas_t;
# define MOO_SIZEOF_FLTBAS_T MOO_SIZEOF_LONG_DOUBLE
#else
typedef double moo_fltbas_t;
# define MOO_SIZEOF_FLTBAS_T MOO_SIZEOF_DOUBLE
#endif
/** \typedef moo_fltmax_t
* The moo_fltmax_t type defines the largest floating-pointer number type
* ever supported.
*/
#if MOO_SIZEOF___FLOAT128 >= MOO_SIZEOF_FLTBAS_T
/* the size of long double may be equal to the size of __float128
* for alignment on some platforms */
typedef __float128 moo_fltmax_t;
# define MOO_SIZEOF_FLTMAX_T MOO_SIZEOF___FLOAT128
# define MOO_FLTMAX_REQUIRE_QUADMATH 1
#else
typedef moo_fltbas_t moo_fltmax_t;
# define MOO_SIZEOF_FLTMAX_T MOO_SIZEOF_FLTBAS_T
# undef MOO_FLTMAX_REQUIRE_QUADMATH
#endif
#if defined(MOO_USE_FLTMAX)
typedef moo_fltmax_t moo_flt_t;
#define MOO_SIZEOF_FLT_T MOO_SIZEOF_FLTMAX_T
#else
typedef moo_fltbas_t moo_flt_t;
#define MOO_SIZEOF_FLT_T MOO_SIZEOF_FLTBAS_T
#endif
/* =========================================================================
* BASIC HARD-CODED DEFINES
* ========================================================================= */
#define MOO_BITS_PER_BYTE (8)
/* the maximum number of bch charaters to represent a single uch character */
#define MOO_BCSIZE_MAX 6
/* =========================================================================
* BASIC MOO TYPES
* ========================================================================= */
typedef char moo_bch_t;
typedef int moo_bci_t;
typedef unsigned int moo_bcu_t;
typedef unsigned char moo_bchu_t; /* unsigned version of moo_bch_t for inner working */
#define MOO_SIZEOF_BCH_T MOO_SIZEOF_CHAR
#define MOO_SIZEOF_BCI_T MOO_SIZEOF_INT
#if defined(MOO_WIDE_CHAR_SIZE) && (MOO_WIDE_CHAR_SIZE >= 4)
# if defined(__GNUC__) && defined(__CHAR32_TYPE__)
typedef __CHAR32_TYPE__ moo_uch_t;
# else
typedef moo_uint32_t moo_uch_t;
# endif
typedef moo_uint32_t moo_uchu_t; /* same as moo_uch_t as it is already unsigned */
# define MOO_SIZEOF_UCH_T 4
#elif defined(__GNUC__) && defined(__CHAR16_TYPE__)
typedef __CHAR16_TYPE__ moo_uch_t;
typedef moo_uint16_t moo_uchu_t; /* same as moo_uch_t as it is already unsigned */
# define MOO_SIZEOF_UCH_T 2
#else
typedef moo_uint16_t moo_uch_t;
typedef moo_uint16_t moo_uchu_t; /* same as moo_uch_t as it is already unsigned */
# define MOO_SIZEOF_UCH_T 2
#endif
typedef moo_int32_t moo_uci_t;
typedef moo_uint32_t moo_ucu_t;
#define MOO_SIZEOF_UCI_T 4
typedef moo_uint8_t moo_oob_t;
/* [NOTE] sizeof(moo_oop_t) must be equal to sizeof(moo_oow_t) */
typedef moo_uintptr_t moo_oow_t;
typedef moo_intptr_t moo_ooi_t;
#define MOO_SIZEOF_OOW_T MOO_SIZEOF_UINTPTR_T
#define MOO_SIZEOF_OOI_T MOO_SIZEOF_INTPTR_T
#define MOO_OOW_BITS (MOO_SIZEOF_OOW_T * MOO_BITS_PER_BYTE)
#define MOO_OOI_BITS (MOO_SIZEOF_OOI_T * MOO_BITS_PER_BYTE)
typedef moo_ushortptr_t moo_oohw_t; /* half word - half word */
typedef moo_shortptr_t moo_oohi_t; /* signed half word */
#define MOO_SIZEOF_OOHW_T MOO_SIZEOF_USHORTPTR_T
#define MOO_SIZEOF_OOHI_T MOO_SIZEOF_SHORTPTR_T
#define MOO_OOHW_BITS (MOO_SIZEOF_OOHW_T * MOO_BITS_PER_BYTE)
#define MOO_OOHI_BITS (MOO_SIZEOF_OOHI_T * MOO_BITS_PER_BYTE)
struct moo_ucs_t
{
moo_uch_t* ptr;
moo_oow_t len;
};
typedef struct moo_ucs_t moo_ucs_t;
struct moo_bcs_t
{
moo_bch_t* ptr;
moo_oow_t len;
};
typedef struct moo_bcs_t moo_bcs_t;
#if defined(MOO_ENABLE_WIDE_CHAR)
typedef moo_uch_t moo_ooch_t;
typedef moo_uchu_t moo_oochu_t;
typedef moo_uci_t moo_ooci_t;
typedef moo_ucu_t moo_oocu_t;
typedef moo_ucs_t moo_oocs_t;
# define MOO_OOCH_IS_UCH
# define MOO_SIZEOF_OOCH_T MOO_SIZEOF_UCH_T
#else
typedef moo_bch_t moo_ooch_t;
typedef moo_bchu_t moo_oochu_t;
typedef moo_bci_t moo_ooci_t;
typedef moo_bcu_t moo_oocu_t;
typedef moo_bcs_t moo_oocs_t;
# define MOO_OOCH_IS_BCH
# define MOO_SIZEOF_OOCH_T MOO_SIZEOF_BCH_T
#endif
typedef unsigned int moo_bitmask_t;
/* =========================================================================
* BASIC OOP ENCODING
* ========================================================================= */
/* actual structure defined in moo.h */
typedef struct moo_obj_t moo_obj_t;
typedef struct moo_obj_t* moo_oop_t;
/*
* An object pointer(OOP) is an ordinary pointer value to an object.
* but some simple numeric values are also encoded into OOP using a simple
* bit-shifting and masking.
*
* A real OOP is stored without any bit-shifting while a non-pointer value encoded
* in an OOP is bit-shifted to the left by 2 and the 2 least-significant bits
* are set to 1 or 2.
*
* This scheme works because the object allocators aligns the object size to
* a multiple of sizeof(moo_oop_t). This way, the 2 least-significant bits
* of a real OOP are always 0s.
*
* With 2 bits, i can encode only 3 special types except object pointers.
* Since I need more than 3 special types, I extend the tag bits up to 4 bits
* to represent a special data type that doesn't require a range as wide
* as a small integer. A unicode character, for instance, only requires 21
* bits at most. An error doesn't need to be as diverse as a small integer.
*/
#define MOO_OOP_TAG_BITS_LO 2
#define MOO_OOP_TAG_BITS_HI 2
#define MOO_OOP_TAG_SMOOI 1 /* 01 */
#define MOO_OOP_TAG_SMPTR 2 /* 10 */
#define MOO_OOP_TAG_EXTENDED 3 /* 11 - internal use only */
#define MOO_OOP_TAG_CHAR 3 /* 0011 */
#define MOO_OOP_TAG_ERROR 7 /* 0111 */
#define MOO_OOP_TAG_RESERVED0 11 /* 1011 */
#define MOO_OOP_TAG_RESERVED1 15 /* 1111 */
#define MOO_OOP_GET_TAG_LO(oop) (((moo_oow_t)oop) & MOO_LBMASK(moo_oow_t, MOO_OOP_TAG_BITS_LO))
#define MOO_OOP_GET_TAG_LOHI(oop) (((moo_oow_t)oop) & MOO_LBMASK(moo_oow_t, MOO_OOP_TAG_BITS_LO + MOO_OOP_TAG_BITS_HI))
#define MOO_OOP_GET_TAG(oop) (MOO_OOP_GET_TAG_LO(oop) == MOO_OOP_TAG_EXTENDED? MOO_OOP_GET_TAG_LOHI(oop): MOO_OOP_GET_TAG_LO(oop))
#define MOO_OOP_IS_NUMERIC(oop) (MOO_OOP_GET_TAG_LO(oop) != 0)
#define MOO_OOP_IS_POINTER(oop) (MOO_OOP_GET_TAG_LO(oop) == 0)
#define MOO_OOP_IS_SMOOI(oop) (MOO_OOP_GET_TAG_LO(oop) == MOO_OOP_TAG_SMOOI)
#define MOO_OOP_IS_SMPTR(oop) (MOO_OOP_GET_TAG_LO(oop) == MOO_OOP_TAG_SMPTR)
#define MOO_SMOOI_TO_OOP(num) ((moo_oop_t)((((moo_oow_t)(moo_ooi_t)(num)) << MOO_OOP_TAG_BITS_LO) | MOO_OOP_TAG_SMOOI))
#define MOO_OOP_TO_SMOOI(oop) (((moo_ooi_t)oop) >> MOO_OOP_TAG_BITS_LO)
/*
#define MOO_SMPTR_TO_OOP(ptr) ((moo_oop_t)((((moo_oow_t)(ptr)) << MOO_OOP_TAG_BITS_LO) | MOO_OOP_TAG_SMPTR))
#define MOO_OOP_TO_SMPTR(oop) (((moo_ooi_t)oop) >> MOO_OOP_TAG_BITS_LO)
*/
#define MOO_SMPTR_TO_OOP(ptr) ((moo_oop_t)(((moo_oow_t)ptr) | MOO_OOP_TAG_SMPTR))
#define MOO_OOP_TO_SMPTR(oop) ((void*)(((moo_oow_t)oop) & ~MOO_LBMASK(moo_oow_t, MOO_OOP_TAG_BITS_LO)))
#define MOO_OOP_IS_CHAR(oop) (MOO_OOP_GET_TAG(oop) == MOO_OOP_TAG_CHAR)
#define MOO_OOP_IS_ERROR(oop) (MOO_OOP_GET_TAG(oop) == MOO_OOP_TAG_ERROR)
#define MOO_OOP_TO_CHAR(oop) (((moo_oow_t)oop) >> (MOO_OOP_TAG_BITS_LO + MOO_OOP_TAG_BITS_LO))
#define MOO_CHAR_TO_OOP(num) ((moo_oop_t)((((moo_oow_t)(num)) << (MOO_OOP_TAG_BITS_LO + MOO_OOP_TAG_BITS_LO)) | MOO_OOP_TAG_CHAR))
#define MOO_OOP_TO_ERROR(oop) (((moo_oow_t)oop) >> (MOO_OOP_TAG_BITS_LO + MOO_OOP_TAG_BITS_LO))
#define MOO_ERROR_TO_OOP(num) ((moo_oop_t)((((moo_oow_t)(num)) << (MOO_OOP_TAG_BITS_LO + MOO_OOP_TAG_BITS_LO)) | MOO_OOP_TAG_ERROR))
/* -------------------------------- */
/* SMOOI takes up 62 bits on a 64-bit architecture and 30 bits
* on a 32-bit architecture. The absolute value takes up 61 bits and 29 bits
* respectively for the sign bit. */
#define MOO_SMOOI_BITS (MOO_OOI_BITS - MOO_OOP_TAG_BITS_LO)
#define MOO_SMOOI_ABS_BITS (MOO_SMOOI_BITS - 1)
#define MOO_SMOOI_MAX ((moo_ooi_t)(~((moo_oow_t)0) >> (MOO_OOP_TAG_BITS_LO + 1)))
/* Sacrificing 1 bit pattern for a negative SMOOI makes
* implementation a lot eaisier in many aspects. */
/*#define MOO_SMOOI_MIN (-MOO_SMOOI_MAX - 1)*/
#define MOO_SMOOI_MIN (-MOO_SMOOI_MAX)
#define MOO_IN_SMOOI_RANGE(ooi) ((ooi) >= MOO_SMOOI_MIN && (ooi) <= MOO_SMOOI_MAX)
/* SMPTR is a special value which has been devised to encode an address value
* whose low MOO_OOP_TAG_BITS_LO bits are 0. its class is SmallPointer. A pointer
* returned by most of system functions would be aligned to the pointer size.
* you can use the followings macros when converting such a pointer without loss. */
#define MOO_IN_SMPTR_RANGE(ptr) ((((moo_oow_t)ptr) & MOO_LBMASK(moo_oow_t, MOO_OOP_TAG_BITS_LO)) == 0)
#define MOO_CHAR_BITS (MOO_OOI_BITS - MOO_OOP_TAG_BITS_LO - MOO_OOP_TAG_BITS_HI)
#define MOO_CHAR_MIN 0
#define MOO_CHAR_MAX (~((moo_oow_t)0) >> (MOO_OOP_TAG_BITS_LO + MOO_OOP_TAG_BITS_HI))
#define MOO_ERROR_BITS (MOO_OOI_BITS - MOO_OOP_TAG_BITS_LO - MOO_OOP_TAG_BITS_HI)
#define MOO_ERROR_MIN 0
#define MOO_ERROR_MAX (~((moo_oow_t)0) >> (MOO_OOP_TAG_BITS_LO + MOO_OOP_TAG_BITS_HI))
/* TODO: There are untested code where a small integer is converted to moo_oow_t.
* for example, the spec making macro treats the number as moo_oow_t instead of moo_ooi_t.
* as of this writing, i skip testing that part with the spec value exceeding MOO_SMOOI_MAX.
* later, please verify it works, probably by limiting the value ranges in such macros
*/
/* =========================================================================
* TIME-RELATED TYPES
* =========================================================================*/
#define MOO_MSECS_PER_SEC (1000)
#define MOO_MSECS_PER_MIN (MOO_MSECS_PER_SEC * MOO_SECS_PER_MIN)
#define MOO_MSECS_PER_HOUR (MOO_MSECS_PER_SEC * MOO_SECS_PER_HOUR)
#define MOO_MSECS_PER_DAY (MOO_MSECS_PER_SEC * MOO_SECS_PER_DAY)
#define MOO_USECS_PER_MSEC (1000)
#define MOO_NSECS_PER_USEC (1000)
#define MOO_NSECS_PER_MSEC (MOO_NSECS_PER_USEC * MOO_USECS_PER_MSEC)
#define MOO_USECS_PER_SEC (MOO_USECS_PER_MSEC * MOO_MSECS_PER_SEC)
#define MOO_NSECS_PER_SEC (MOO_NSECS_PER_USEC * MOO_USECS_PER_MSEC * MOO_MSECS_PER_SEC)
#define MOO_SECNSEC_TO_MSEC(sec,nsec) \
(((moo_intptr_t)(sec) * MOO_MSECS_PER_SEC) + ((moo_intptr_t)(nsec) / MOO_NSECS_PER_MSEC))
#define MOO_SECNSEC_TO_USEC(sec,nsec) \
(((moo_intptr_t)(sec) * MOO_USECS_PER_SEC) + ((moo_intptr_t)(nsec) / MOO_NSECS_PER_USEC))
#define MOO_SECNSEC_TO_NSEC(sec,nsec) \
(((moo_intptr_t)(sec) * MOO_NSECS_PER_SEC) + (moo_intptr_t)(nsec))
#define MOO_SEC_TO_MSEC(sec) ((sec) * MOO_MSECS_PER_SEC)
#define MOO_MSEC_TO_SEC(sec) ((sec) / MOO_MSECS_PER_SEC)
#define MOO_USEC_TO_NSEC(usec) ((usec) * MOO_NSECS_PER_USEC)
#define MOO_NSEC_TO_USEC(nsec) ((nsec) / MOO_NSECS_PER_USEC)
#define MOO_MSEC_TO_NSEC(msec) ((msec) * MOO_NSECS_PER_MSEC)
#define MOO_NSEC_TO_MSEC(nsec) ((nsec) / MOO_NSECS_PER_MSEC)
#define MOO_MSEC_TO_USEC(msec) ((msec) * MOO_USECS_PER_MSEC)
#define MOO_USEC_TO_MSEC(usec) ((usec) / MOO_USECS_PER_MSEC)
#define MOO_SEC_TO_NSEC(sec) ((sec) * MOO_NSECS_PER_SEC)
#define MOO_NSEC_TO_SEC(nsec) ((nsec) / MOO_NSECS_PER_SEC)
#define MOO_SEC_TO_USEC(sec) ((sec) * MOO_USECS_PER_SEC)
#define MOO_USEC_TO_SEC(usec) ((usec) / MOO_USECS_PER_SEC)
#if defined(MOO_SIZEOF_INT64_T) && (MOO_SIZEOF_INT64_T > 0)
typedef moo_int64_t moo_ntime_sec_t;
#else
typedef moo_int32_t moo_ntime_sec_t;
#endif
typedef moo_int32_t moo_ntime_nsec_t;
typedef struct moo_ntime_t moo_ntime_t;
struct moo_ntime_t
{
moo_ntime_sec_t sec;
moo_ntime_nsec_t nsec; /* nanoseconds */
};
#define MOO_INIT_NTIME(c,s,ns) (((c)->sec = (s)), ((c)->nsec = (ns)))
#define MOO_CLEAR_NTIME(c) MOO_INIT_NTIME(c, 0, 0)
#define MOO_ADD_NTIME(c,a,b) \
do { \
(c)->sec = (a)->sec + (b)->sec; \
(c)->nsec = (a)->nsec + (b)->nsec; \
while ((c)->nsec >= MOO_NSECS_PER_SEC) { (c)->sec++; (c)->nsec -= MOO_NSECS_PER_SEC; } \
} while(0)
#define MOO_ADD_NTIME_SNS(c,a,s,ns) \
do { \
(c)->sec = (a)->sec + (s); \
(c)->nsec = (a)->nsec + (ns); \
while ((c)->nsec >= MOO_NSECS_PER_SEC) { (c)->sec++; (c)->nsec -= MOO_NSECS_PER_SEC; } \
} while(0)
#define MOO_SUB_NTIME(c,a,b) \
do { \
(c)->sec = (a)->sec - (b)->sec; \
(c)->nsec = (a)->nsec - (b)->nsec; \
while ((c)->nsec < 0) { (c)->sec--; (c)->nsec += MOO_NSECS_PER_SEC; } \
} while(0)
#define MOO_SUB_NTIME_SNS(c,a,s,ns) \
do { \
(c)->sec = (a)->sec - s; \
(c)->nsec = (a)->nsec - ns; \
while ((c)->nsec < 0) { (c)->sec--; (c)->nsec += MOO_NSECS_PER_SEC; } \
} while(0)
#define MOO_CMP_NTIME(a,b) (((a)->sec == (b)->sec)? ((a)->nsec - (b)->nsec): ((a)->sec - (b)->sec))
/* if time has been normalized properly, nsec must be equal to or
* greater than 0. */
#define MOO_IS_NEG_NTIME(x) ((x)->sec < 0)
#define MOO_IS_POS_NTIME(x) ((x)->sec > 0 || ((x)->sec == 0 && (x)->nsec > 0))
#define MOO_IS_ZERO_NTIME(x) ((x)->sec == 0 && (x)->nsec == 0)
/* =========================================================================
* PRIMITIVE MACROS
* ========================================================================= */
#define MOO_UCI_EOF ((moo_uci_t)-1)
#define MOO_BCI_EOF ((moo_bci_t)-1)
#define MOO_OOCI_EOF ((moo_ooci_t)-1)
#define MOO_SIZEOF(x) (sizeof(x))
#define MOO_COUNTOF(x) (sizeof(x) / sizeof((x)[0]))
#define MOO_BITSOF(x) (sizeof(x) * MOO_BITS_PER_BYTE)
/**
* The MOO_OFFSETOF() macro returns the offset of a field from the beginning
* of a structure.
*/
#define MOO_OFFSETOF(type,member) ((moo_uintptr_t)&((type*)0)->member)
/**
* The MOO_ALIGNOF() macro returns the alignment size of a structure.
* Note that this macro may not work reliably depending on the type given.
*/
#define MOO_ALIGNOF(type) MOO_OFFSETOF(struct { moo_uint8_t d1; type d2; }, d2)
/*(sizeof(struct { moo_uint8_t d1; type d2; }) - sizeof(type))*/
#if defined(__cplusplus)
# if (__cplusplus >= 201103L) /* C++11 */
# define MOO_NULL nullptr
# else
# define MOO_NULL (0)
# endif
#else
# define MOO_NULL ((void*)0)
#endif
/* make a bit mask that can mask off low n bits */
#define MOO_LBMASK(type,n) (~(~((type)0) << (n)))
#define MOO_LBMASK_SAFE(type,n) (((n) < MOO_BITSOF(type))? MOO_LBMASK(type,n): ~(type)0)
/* make a bit mask that can mask off hig n bits */
#define MOO_HBMASK(type,n) (~(~((type)0) >> (n)))
#define MOO_HBMASK_SAFE(type,n) (((n) < MOO_BITSOF(type))? MOO_HBMASK(type,n): ~(type)0)
/* get 'length' bits starting from the bit at the 'offset' */
#define MOO_GETBITS(type,value,offset,length) \
((((type)(value)) >> (offset)) & MOO_LBMASK(type,length))
#define MOO_CLEARBITS(type,value,offset,length) \
(((type)(value)) & ~(MOO_LBMASK(type,length) << (offset)))
#define MOO_SETBITS(type,value,offset,length,bits) \
(value = (MOO_CLEARBITS(type,value,offset,length) | (((bits) & MOO_LBMASK(type,length)) << (offset))))
#define MOO_FLIPBITS(type,value,offset,length) \
(((type)(value)) ^ (MOO_LBMASK(type,length) << (offset)))
#define MOO_ORBITS(type,value,offset,length,bits) \
(value = (((type)(value)) | (((bits) & MOO_LBMASK(type,length)) << (offset))))
/**
* The MOO_BITS_MAX() macros calculates the maximum value that the 'nbits'
* bits of an unsigned integer of the given 'type' can hold.
* \code
* printf ("%u", MOO_BITS_MAX(unsigned int, 5));
* \endcode
*/
/*#define MOO_BITS_MAX(type,nbits) ((((type)1) << (nbits)) - 1)*/
#define MOO_BITS_MAX(type,nbits) ((~(type)0) >> (MOO_BITSOF(type) - (nbits)))
/* =========================================================================
* MMGR
* ========================================================================= */
typedef struct moo_mmgr_t moo_mmgr_t;
/**
* allocate a memory chunk of the size \a n.
* \return pointer to a memory chunk on success, #MOO_NULL on failure.
*/
typedef void* (*moo_mmgr_alloc_t) (moo_mmgr_t* mmgr, moo_oow_t n);
/**
* resize a memory chunk pointed to by \a ptr to the size \a n.
* \return pointer to a memory chunk on success, #MOO_NULL on failure.
*/
typedef void* (*moo_mmgr_realloc_t) (moo_mmgr_t* mmgr, void* ptr, moo_oow_t n);
/**
* free a memory chunk pointed to by \a ptr.
*/
typedef void (*moo_mmgr_free_t) (moo_mmgr_t* mmgr, void* ptr);
/**
* The moo_mmgr_t type defines the memory management interface.
* As the type is merely a structure, it is just used as a single container
* for memory management functions with a pointer to user-defined data.
* The user-defined data pointer \a ctx is passed to each memory management
* function whenever it is called. You can allocate, reallocate, and free
* a memory chunk.
*
* For example, a moo_xxx_open() function accepts a pointer of the moo_mmgr_t
* type and the xxx object uses it to manage dynamic data within the object.
*/
struct moo_mmgr_t
{
moo_mmgr_alloc_t alloc; /**< allocation function */
moo_mmgr_realloc_t realloc; /**< resizing function */
moo_mmgr_free_t free; /**< disposal function */
void* ctx; /**< user-defined data pointer */
};
/**
* The MOO_MMGR_ALLOC() macro allocates a memory block of the \a size bytes
* using the \a mmgr memory manager.
*/
#define MOO_MMGR_ALLOC(mmgr,size) ((mmgr)->alloc(mmgr,size))
/**
* The MOO_MMGR_REALLOC() macro resizes a memory block pointed to by \a ptr
* to the \a size bytes using the \a mmgr memory manager.
*/
#define MOO_MMGR_REALLOC(mmgr,ptr,size) ((mmgr)->realloc(mmgr,ptr,size))
/**
* The MOO_MMGR_FREE() macro deallocates the memory block pointed to by \a ptr.
*/
#define MOO_MMGR_FREE(mmgr,ptr) ((mmgr)->free(mmgr,ptr))
/* =========================================================================
* CMGR
* =========================================================================*/
typedef struct moo_cmgr_t moo_cmgr_t;
typedef moo_oow_t (*moo_cmgr_bctouc_t) (
const moo_bch_t* mb,
moo_oow_t size,
moo_uch_t* wc
);
typedef moo_oow_t (*moo_cmgr_uctobc_t) (
moo_uch_t wc,
moo_bch_t* mb,
moo_oow_t size
);
/**
* The moo_cmgr_t type defines the character-level interface to
* multibyte/wide-character conversion. This interface doesn't
* provide any facility to store conversion state in a context
* independent manner. This leads to the limitation that it can
* handle a stateless multibyte encoding only.
*/
struct moo_cmgr_t
{
moo_cmgr_bctouc_t bctouc;
moo_cmgr_uctobc_t uctobc;
};
/* =========================================================================
* FORWARD DECLARATION FOR MAIN MOO STRUCTURE
* =========================================================================*/
typedef struct moo_t moo_t;
/* =========================================================================
* MACROS THAT CHANGES THE BEHAVIORS OF THE C COMPILER/LINKER
* =========================================================================*/
#if defined(EMSCRIPTEN)
# define MOO_IMPORT
# define MOO_EXPORT EMSCRIPTEN_KEEPALIVE
# define MOO_PRIVATE
#elif defined(__BORLANDC__) && (__BORLANDC__ < 0x500)
# define MOO_IMPORT
# define MOO_EXPORT
# define MOO_PRIVATE
#elif defined(_WIN32) || (defined(__WATCOMC__) && (__WATCOMC__ >= 1000) && !defined(__WINDOWS_386__))
# define MOO_IMPORT __declspec(dllimport)
# define MOO_EXPORT __declspec(dllexport)
# define MOO_PRIVATE
#elif defined(__GNUC__) && ((__GNUC__>= 4) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3))
# define MOO_IMPORT __attribute__((visibility("default")))
# define MOO_EXPORT __attribute__((visibility("default")))
# define MOO_PRIVATE __attribute__((visibility("hidden")))
/*# define MOO_PRIVATE __attribute__((visibility("internal")))*/
#else
# define MOO_IMPORT
# define MOO_EXPORT
# define MOO_PRIVATE
#endif
#if defined(__cplusplus) || (defined(__STDC_VERSION__) && (__STDC_VERSION__>=199901L))
/* C++/C99 has inline */
# define MOO_INLINE inline
# define MOO_HAVE_INLINE
#elif defined(__GNUC__) && defined(__GNUC_GNU_INLINE__)
/* gcc disables inline when -std=c89 or -ansi is used.
* so use __inline__ supported by gcc regardless of the options */
# define MOO_INLINE /*extern*/ __inline__
# define MOO_HAVE_INLINE
#else
# define MOO_INLINE
# undef MOO_HAVE_INLINE
#endif
#if defined(__GNUC__) && (__GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ > 4))
# define MOO_UNUSED __attribute__((__unused__))
#else
# define MOO_UNUSED
#endif
/**
* The MOO_TYPE_IS_SIGNED() macro determines if a type is signed.
* \code
* printf ("%d\n", (int)MOO_TYPE_IS_SIGNED(int));
* printf ("%d\n", (int)MOO_TYPE_IS_SIGNED(unsigned int));
* \endcode
*/
#define MOO_TYPE_IS_SIGNED(type) (((type)0) > ((type)-1))
/**
* The MOO_TYPE_IS_SIGNED() macro determines if a type is unsigned.
* \code
* printf ("%d\n", MOO_TYPE_IS_UNSIGNED(int));
* printf ("%d\n", MOO_TYPE_IS_UNSIGNED(unsigned int));
* \endcode
*/
#define MOO_TYPE_IS_UNSIGNED(type) (((type)0) < ((type)-1))
#define MOO_TYPE_SIGNED_MAX(type) \
((type)~((type)1 << ((type)MOO_BITSOF(type) - 1)))
#define MOO_TYPE_UNSIGNED_MAX(type) ((type)(~(type)0))
#define MOO_TYPE_SIGNED_MIN(type) \
((type)((type)1 << ((type)MOO_BITSOF(type) - 1)))
#define MOO_TYPE_UNSIGNED_MIN(type) ((type)0)
#define MOO_TYPE_MAX(type) \
((MOO_TYPE_IS_SIGNED(type)? MOO_TYPE_SIGNED_MAX(type): MOO_TYPE_UNSIGNED_MAX(type)))
#define MOO_TYPE_MIN(type) \
((MOO_TYPE_IS_SIGNED(type)? MOO_TYPE_SIGNED_MIN(type): MOO_TYPE_UNSIGNED_MIN(type)))
/* round up a positive integer x to the nearst multiple of y */
#define MOO_ALIGN(x,y) ((((x) + (y) - 1) / (y)) * (y))
/* round up a positive integer x to the nearst multiple of y where
* y must be a multiple of a power of 2*/
#define MOO_ALIGN_POW2(x,y) ((((x) + (y) - 1)) & ~((y) - 1))
#define MOO_IS_UNALIGNED_POW2(x,y) ((x) & ((y) - 1))
#define MOO_IS_ALIGNED_POW2(x,y) (!MOO_IS_UNALIGNED_POW2(x,y))
/* =========================================================================
* COMPILER FEATURE TEST MACROS
* =========================================================================*/
#if !defined(__has_builtin) && defined(_INTELC32_)
/* intel c code builder 1.0 ended up with an error without this override */
#define __has_builtin(x) 0
#endif
/*
#if !defined(__is_identifier)
#define __is_identifier(x) 0
#endif
#if !defined(__has_attribute)
#define __has_attribute(x) 0
#endif
*/
#if defined(__has_builtin)
#if __has_builtin(__builtin_ctz)
#define MOO_HAVE_BUILTIN_CTZ
#endif
#if __has_builtin(__builtin_ctzl)
#define MOO_HAVE_BUILTIN_CTZL
#endif
#if __has_builtin(__builtin_ctzll)
#define MOO_HAVE_BUILTIN_CTZLL
#endif
#if __has_builtin(__builtin_clz)
#define MOO_HAVE_BUILTIN_CLZ
#endif
#if __has_builtin(__builtin_clzl)
#define MOO_HAVE_BUILTIN_CLZL
#endif
#if __has_builtin(__builtin_clzll)
#define MOO_HAVE_BUILTIN_CLZLL
#endif
#if __has_builtin(__builtin_uadd_overflow)
#define MOO_HAVE_BUILTIN_UADD_OVERFLOW
#endif
#if __has_builtin(__builtin_uaddl_overflow)
#define MOO_HAVE_BUILTIN_UADDL_OVERFLOW
#endif
#if __has_builtin(__builtin_uaddll_overflow)
#define MOO_HAVE_BUILTIN_UADDLL_OVERFLOW
#endif
#if __has_builtin(__builtin_umul_overflow)
#define MOO_HAVE_BUILTIN_UMUL_OVERFLOW
#endif
#if __has_builtin(__builtin_umull_overflow)
#define MOO_HAVE_BUILTIN_UMULL_OVERFLOW
#endif
#if __has_builtin(__builtin_umulll_overflow)
#define MOO_HAVE_BUILTIN_UMULLL_OVERFLOW
#endif
#if __has_builtin(__builtin_sadd_overflow)
#define MOO_HAVE_BUILTIN_SADD_OVERFLOW
#endif
#if __has_builtin(__builtin_saddl_overflow)
#define MOO_HAVE_BUILTIN_SADDL_OVERFLOW
#endif
#if __has_builtin(__builtin_saddll_overflow)
#define MOO_HAVE_BUILTIN_SADDLL_OVERFLOW
#endif
#if __has_builtin(__builtin_smul_overflow)
#define MOO_HAVE_BUILTIN_SMUL_OVERFLOW
#endif
#if __has_builtin(__builtin_smull_overflow)
#define MOO_HAVE_BUILTIN_SMULL_OVERFLOW
#endif
#if __has_builtin(__builtin_smulll_overflow)
#define MOO_HAVE_BUILTIN_SMULLL_OVERFLOW
#endif
#if __has_builtin(__builtin_expect)
#define MOO_HAVE_BUILTIN_EXPECT
#endif
#if __has_builtin(__sync_lock_test_and_set)
#define MOO_HAVE_SYNC_LOCK_TEST_AND_SET
#endif
#if __has_builtin(__sync_lock_release)
#define MOO_HAVE_SYNC_LOCK_RELEASE
#endif
#if __has_builtin(__sync_synchronize)
#define MOO_HAVE_SYNC_SYNCHRONIZE
#endif
#if __has_builtin(__sync_bool_compare_and_swap)
#define MOO_HAVE_SYNC_BOOL_COMPARE_AND_SWAP
#endif
#if __has_builtin(__sync_val_compare_and_swap)
#define MOO_HAVE_SYNC_VAL_COMPARE_AND_SWAP
#endif
#if __has_builtin(__builtin_bswap16)
#define MOO_HAVE_BUILTIN_BSWAP16
#endif
#if __has_builtin(__builtin_bswap32)
#define MOO_HAVE_BUILTIN_BSWAP32
#endif
#if __has_builtin(__builtin_bswap64)
#define MOO_HAVE_BUILTIN_BSWAP64
#endif
#if __has_builtin(__builtin_bswap128)
#define MOO_HAVE_BUILTIN_BSWAP128
#endif
#elif defined(__GNUC__) && defined(__GNUC_MINOR__)
#if (__GNUC__ >= 4)
#define MOO_HAVE_SYNC_LOCK_TEST_AND_SET
#define MOO_HAVE_SYNC_LOCK_RELEASE
#define MOO_HAVE_SYNC_SYNCHRONIZE
#define MOO_HAVE_SYNC_BOOL_COMPARE_AND_SWAP
#define MOO_HAVE_SYNC_VAL_COMPARE_AND_SWAP
#endif
#if (__GNUC__ >= 4) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
#define MOO_HAVE_BUILTIN_CTZ
#define MOO_HAVE_BUILTIN_CTZL
#define MOO_HAVE_BUILTIN_CTZLL
#define MOO_HAVE_BUILTIN_CLZ
#define MOO_HAVE_BUILTIN_CLZL
#define MOO_HAVE_BUILTIN_CLZLL
#define MOO_HAVE_BUILTIN_EXPECT
#endif
#if (__GNUC__ >= 5)
#define MOO_HAVE_BUILTIN_UADD_OVERFLOW
#define MOO_HAVE_BUILTIN_UADDL_OVERFLOW
#define MOO_HAVE_BUILTIN_UADDLL_OVERFLOW
#define MOO_HAVE_BUILTIN_UMUL_OVERFLOW
#define MOO_HAVE_BUILTIN_UMULL_OVERFLOW
#define MOO_HAVE_BUILTIN_UMULLL_OVERFLOW
#define MOO_HAVE_BUILTIN_SADD_OVERFLOW
#define MOO_HAVE_BUILTIN_SADDL_OVERFLOW
#define MOO_HAVE_BUILTIN_SADDLL_OVERFLOW
#define MOO_HAVE_BUILTIN_SMUL_OVERFLOW
#define MOO_HAVE_BUILTIN_SMULL_OVERFLOW
#define MOO_HAVE_BUILTIN_SMULLL_OVERFLOW
#endif
#if (__GNUC__ >= 5) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)
/* 4.8.0 or later */
#define MOO_HAVE_BUILTIN_BSWAP16
#endif
#if (__GNUC__ >= 5) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)
/* 4.3.0 or later */
#define MOO_HAVE_BUILTIN_BSWAP32
#define MOO_HAVE_BUILTIN_BSWAP64
/*#define MOO_HAVE_BUILTIN_BSWAP128*/
#endif
#endif
#if defined(MOO_HAVE_BUILTIN_EXPECT)
# define MOO_LIKELY(x) (__builtin_expect(!!(x),1))
# define MOO_UNLIKELY(x) (__builtin_expect(!!(x),0))
#else
# define MOO_LIKELY(x) (x)
# define MOO_UNLIKELY(x) (x)
#endif
/* =========================================================================
* STATIC ASSERTION
* =========================================================================*/
#define MOO_STATIC_JOIN_INNER(x, y) x ## y
#define MOO_STATIC_JOIN(x, y) MOO_STATIC_JOIN_INNER(x, y)
#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)
# define MOO_STATIC_ASSERT(expr) _Static_assert (expr, "invalid assertion")
#elif defined(__cplusplus) && (__cplusplus >= 201103L)
# define MOO_STATIC_ASSERT(expr) static_assert (expr, "invalid assertion")
#elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
# define MOO_STATIC_ASSERT(expr) typedef char MOO_STATIC_JOIN(MOO_STATIC_ASSERT_T_, __LINE__)[(expr)? 1: -1] MOO_UNUSED
#else
# define MOO_STATIC_ASSERT(expr) do { typedef char MOO_STATIC_JOIN(MOO_STATIC_ASSERT_T_, __LINE__)[(expr)? 1: -1] MOO_UNUSED; } while(0)
#endif
#define MOO_STATIC_ASSERT_EXPR(expr) ((void)MOO_SIZEOF(char[(expr)? 1: -1]))
#endif