/* This software is licensed by the MIT License, see LICENSE file */ /* Copyright © 2022 Gregory Lirent */ #include "__internal/include.h" #define max_align _Alignof(max_align_t) #define max_size ((sizeof(ldbl_t) >= 8) ? sizeof(ldbl_t) : 8) /*#####################################################################################################################*/ ainline(vtype expandu8(u32_t* v)) { if (is_little_endian) { *v &= 0x000000ff; } else { *v >>= 24; } return VTYPE_UINT32; } ainline(vtype expandu16(u32_t* v)) { if (is_little_endian) { *v &= 0x0000ffff; } else { *v >>= 16; } return VTYPE_UINT32; } ainline(vtype expands8(u32_t* v)) { if (is_big_endian) *v >>= 24; *v |= 0xffffff00; return VTYPE_INT32; } ainline(vtype expands16(u32_t* v)) { if (is_big_endian) *v >>= 16; *v |= 0xffff0000; return VTYPE_INT32; } /*#####################################################################################################################*/ const size_t LIBCDSB_VTYPE_SIZES[18] = { sizeof(void*), sizeof(_Bool), sizeof(u8_t), sizeof(u16_t), sizeof(u32_t), sizeof(u64_t), sizeof(s8_t), sizeof(s16_t), sizeof(s32_t), sizeof(s64_t), sizeof(fl_t), sizeof(dbl_t), sizeof(ldbl_t), sizeof(str_t), sizeof(map_t), sizeof(arr_t), sizeof(list_t), sizeof(set_t) }; /*#####################################################################################################################*/ int libcdsb_vtype_compare_values(const void* s0, vtype t0, const void* s1, vtype t1) { int c; size_t _Alignas(max_align) v0[max_size/sizeof(size_t)]; size_t _Alignas(max_align) v1[max_size/sizeof(size_t)]; c = t0 - t1; if (t0 >= VTYPE_STRING || t1 >= VTYPE_STRING) { static int(*compare[5])(const void*,const void*) = { (void*)string_compare, (void*) map_compare, (void*) array_compare, (void*) list_compare, (void*) vset_compare }; if (c) return c; t0 -= VTYPE_STRING; return compare[t0](s0, s1); } if (t0 == VTYPE_POINTER) t0 = (sizeof(void*) == 8) ? VTYPE_UINT64 : VTYPE_UINT32; if (t1 == VTYPE_POINTER) t1 = (sizeof(void*) == 8) ? VTYPE_UINT64 : VTYPE_UINT32; if (t0 == VTYPE_BOOLEAN) t0 = VTYPE_UINT8; if (t1 == VTYPE_BOOLEAN) t1 = VTYPE_UINT8; if (!c) { if (s0 == s1) return 0; if (t0 == VTYPE_LDOUBLE) { *(ldbl_t*)v0 = *(ldbl_t*)s0 - *(ldbl_t*)s1; ldouble_: if (!*(ldbl_t*)v0) return 0; return *(ldbl_t*)v0 < 0 ? -1 : 1; } else if (t0 == VTYPE_DOUBLE) { *(ldbl_t*)v0 = *(dbl_t*)s0 - *(dbl_t*)s1; goto ldouble_; } else if (t0 == VTYPE_FLOAT) { *(ldbl_t*)v0 = *(fl_t*)s0 - *(fl_t*)s1; goto ldouble_; } if (t0 == VTYPE_UINT8) return *(u8_t*)s0 - *(u8_t*)s1; if (t0 == VTYPE_UINT16) return *(u16_t*)s0 - *(u16_t*)s1; if (t0 == VTYPE_UINT32) return *(u32_t*)s0 - *(u32_t*)s1; return *(u64_t*)s0 - *(u64_t*)s1; } else if (t0 >= VTYPE_FLOAT && t1 >= VTYPE_FLOAT) { if (t0 == VTYPE_FLOAT) { *(ldbl_t*)v0 = *(fl_t*)s0; } else if (t0 == VTYPE_DOUBLE) { *(ldbl_t*)v0 = *(dbl_t*)s0; } else if (t0 == VTYPE_LDOUBLE) { *(ldbl_t*)v0 = *(ldbl_t*)s0; } if (t1 == VTYPE_FLOAT) { *(ldbl_t*)v0 -= *(fl_t*)s1; } else if (t1 == VTYPE_DOUBLE) { *(ldbl_t*)v0 -= *(dbl_t*)s1; } else { *(ldbl_t*)v0 -= *(ldbl_t*)s1; } goto ldouble_; } memcpy(v0, s0, 8); memcpy(v1, s1, 8); if (t0 <= VTYPE_UINT64 && t1 <= VTYPE_UINT64) { if (t0 == VTYPE_UINT8) { t0 = expandu8((void*)v0); } else if (t0 == VTYPE_UINT16) { t0 = expandu16((void*)v0); } else if (t0 == VTYPE_UINT64 && *(u64_t*)v0 <= UINT32_MAX) { t0 = VTYPE_UINT32; } if (t1 == VTYPE_UINT8) { t1 = expandu8((void*)v1); } else if (t1 == VTYPE_UINT16) { t1 = expandu16((void*)v1); } else if (t1 == VTYPE_UINT64 && *(u64_t*)v1 <= UINT32_MAX) { t0 = VTYPE_UINT32; } unsigned_: c = t0 - t1; if (!c) return *(u32_t*)v0 - *(u32_t*)v1; } else if (t0 <= VTYPE_INT64 && t1 <= VTYPE_INT64) { if (t0 == VTYPE_INT8) { t0 = (*(u8_t*)v0 <= INT8_MAX) ? expandu8((void*)v0) : expands8((void*)v0); } else if (t0 == VTYPE_INT16) { t0 = (*(u16_t*)v0 <= INT16_MAX) ? expandu16((void*)v0) : expands16((void*)v0); } else if (t0 == VTYPE_INT32) { if (*(u32_t*)v0 <= INT32_MAX) { t0 = VTYPE_UINT32; } } else if (t0 == VTYPE_INT64) { if (*(u64_t*)v0 <= UINT32_MAX) { t0 = VTYPE_UINT32; } else if (*(u64_t*)v0 <= INT64_MAX) { t0 = VTYPE_UINT64; } } if (t1 == VTYPE_INT8) { t1 = (*(u8_t*)v1 <= INT8_MAX) ? expandu8((void*)v1) : expands8((void*)v1); } else if (t1 == VTYPE_INT16) { t1 = (*(u16_t*)v1 <= INT16_MAX) ? expandu16((void*)v1) : expands16((void*)v1); } else if (t1 == VTYPE_INT32) { if (*(u32_t*)v1 <= INT32_MAX) { t1 = VTYPE_UINT32; } } else if (t1 == VTYPE_INT64) { if (*(u64_t*)v1 <= UINT32_MAX) { t1 = VTYPE_UINT32; } else if (*(u64_t*)v1 <= INT64_MAX) { t1 = VTYPE_UINT64; } } if (t0 <= VTYPE_UINT64 && t1 <= VTYPE_UINT64) goto unsigned_; if (t0 <= VTYPE_UINT64) return 1; if (t1 <= VTYPE_UINT64) return -1; c = t0 - t1; if (!c) return *(u32_t*)v1 - *(u32_t*)v0; } return c; } /*#####################################################################################################################*/ int libcdsb_vtype_compare_values_eq(const void* s0, const void* s1, vtype t) { ldbl_t v[1]; if (s0 == s1) return 0; switch (t) { default: abort(); case VTYPE_INT8: return *(s8_t*)s0 - *(s8_t*)s1; case VTYPE_INT16: return *(s16_t*)s0 - *(s16_t*)s1; case VTYPE_INT32: return *(s32_t*)s0 - *(s32_t*)s1; case VTYPE_INT64: return *(s64_t*)s0 - *(s64_t*)s1; case VTYPE_BOOLEAN: case VTYPE_UINT8: return *(u8_t*)s0 - *(u8_t*)s1; case VTYPE_UINT16: return *(u16_t*)s0 - *(u16_t*)s1; case VTYPE_UINT32: u32_: return *(u32_t*)s0 - *(u32_t*)s1; case VTYPE_POINTER: if (sizeof(void*) != 8) goto u32_; case VTYPE_UINT64: return *(u64_t*)s0 - *(u64_t*)s1; case VTYPE_LDOUBLE: *(ldbl_t*)v = *(ldbl_t*)s0 - *(ldbl_t*)s1; if (!*(ldbl_t*)v) return 0; return *(ldbl_t*)v < 0 ? -1 : 1; case VTYPE_DOUBLE: *(dbl_t*)v = *(dbl_t*)s0 - *(dbl_t*)s1; if (!*(dbl_t*)v) return 0; return *(dbl_t*)v < 0 ? -1 : 1; case VTYPE_FLOAT: *(fl_t*)v = *(fl_t*)s0 - *(fl_t*)s1; if (!*(fl_t*)v) return 0; return *(fl_t*)v < 0 ? -1 : 1; case VTYPE_STRING: return string_compare(s0, s1); case VTYPE_ARRAY: return array_compare(s0, s1); case VTYPE_LIST: return list_compare(s0, s1); case VTYPE_MAP: return map_compare(s0, s1); case VTYPE_SET: return vset_compare(s0, s1); } }