libcdsb/src/vtype.c

155 lines
5.4 KiB
C
Raw Normal View History

2022-06-02 14:22:19 +03:00
/* This software is licensed by the MIT License, see LICENSE file */
/* Copyright © 2022 Gregory Lirent */
2022-06-03 11:56:01 +03:00
#include "__internal/assert.h"
2022-06-02 14:22:19 +03:00
#include "__internal/include.h"
/*#####################################################################################################################*/
2022-06-05 18:32:57 +03:00
static ldbl_t normalize_value(const void* v, vtype t) {
2022-06-03 11:56:01 +03:00
if (t == VTYPE_BOOLEAN || t == VTYPE_UINT8) {
2022-06-05 18:32:57 +03:00
return *(u8_t*)v;
2022-06-03 11:56:01 +03:00
} else if (t == VTYPE_UINT16) {
2022-06-05 18:32:57 +03:00
return *(u16_t*)v;
2022-06-03 11:56:01 +03:00
} else if (t == VTYPE_UINT32 || (sizeof(void*) == 4 && t == VTYPE_POINTER)) {
2022-06-05 18:32:57 +03:00
return *(u32_t*)v;
2022-06-03 11:56:01 +03:00
} else if (t == VTYPE_UINT64 || (sizeof(void*) == 8 && t == VTYPE_POINTER)) {
2022-06-05 18:32:57 +03:00
return *(u64_t*)v;
2022-06-03 11:56:01 +03:00
} else if (t == VTYPE_INT8) {
2022-06-05 18:32:57 +03:00
return *(s8_t*)v;
2022-06-03 11:56:01 +03:00
} else if (t == VTYPE_INT16) {
2022-06-05 18:32:57 +03:00
return *(s16_t*)v;
2022-06-03 11:56:01 +03:00
} else if (t == VTYPE_INT32) {
2022-06-05 18:32:57 +03:00
return *(s32_t*)v;
2022-06-03 11:56:01 +03:00
} else if (t == VTYPE_INT64) {
2022-06-05 18:32:57 +03:00
return *(s64_t*)v;
} else if (t == VTYPE_FLOAT) {
return abs(*(fl_t*)v) <= FLT_EPSILON ? 0 : *(fl_t*)v;
} else if (t == VTYPE_DOUBLE) {
return abs(*(dbl_t*)v) <= DBL_EPSILON ? 0 : *(dbl_t*)v;
} else return abs(*(ldbl_t*)v) <= LDBL_EPSILON ? 0 : *(ldbl_t*)v;
2022-06-02 14:22:19 +03:00
}
2022-08-14 20:55:40 +03:00
static hash_t ldouble_hash(ldbl_t s) {
2022-08-15 17:29:33 +03:00
hash_t hash;
if (sizeof(hash_t) == sizeof(u64_t)) {
if (is_little_endian) {
hash = *((u64_t*)&s);
hash ^= *((u16_t*)(((u64_t*)&s) + 1));
} else {
memcpy(&hash, ((char*)&s) + sizeof(u16_t), sizeof(u64_t));
hash ^= *((u16_t*)&s);
}
} else {
if (is_little_endian) {
hash = *((u32_t*)&s) ^ *((u32_t*)&s + 1);
hash ^= *((u16_t*)(((u32_t*)&s) + 2));
} else {
u32_t x;
memcpy(&hash, ((char*)&s) + sizeof(u16_t), sizeof(u32_t));
memcpy(&x, ((char*)&s) + sizeof(u16_t) + sizeof(u32_t), sizeof(u32_t));
hash ^= x;
hash ^= *((u16_t*)&s);
}
}
2022-08-14 20:55:40 +03:00
2022-08-15 17:29:33 +03:00
return hash;
2022-08-14 20:55:40 +03:00
}
2022-06-06 23:43:18 +03:00
/*#####################################################################################################################*/
2022-06-02 14:22:19 +03:00
int libcdsb_vtype_compare_values(const void* s0, vtype t0, const void* s1, vtype t1) {
2022-06-03 11:56:01 +03:00
if (t0 == t1) return libcdsb_vtype_compare_values_eq(s0, s1, t0);
2022-06-02 14:22:19 +03:00
2022-06-05 18:32:57 +03:00
if (t0 <= VTYPE_LDOUBLE && t1 <= VTYPE_LDOUBLE) {
ldbl_t d0, d1;
2022-06-02 14:22:19 +03:00
2022-06-05 18:32:57 +03:00
d0 = normalize_value(s0, t0);
d1 = normalize_value(s1, t1);
2022-06-02 14:22:19 +03:00
2022-06-05 18:32:57 +03:00
return (abs(d0 - d1) <= LDBL_EPSILON) ? 0 : (d0 < d1 ? -1 : 1);
}
2022-06-02 14:22:19 +03:00
2022-06-05 18:32:57 +03:00
return t0 - t1;
2022-06-02 14:22:19 +03:00
}
int libcdsb_vtype_compare_values_eq(const void* s0, const void* s1, vtype t) {
2022-06-05 18:32:57 +03:00
#define compare(T, s0, s1) *(T*)s0 == *(T*)s1 ? 0 : (*(T*)s0 < *(T*)s1 ? -1 : 1)
2022-06-02 14:22:19 +03:00
if (s0 == s1)
return 0;
switch (t) { default: abort();
2022-06-05 18:32:57 +03:00
case VTYPE_INT8: return compare( s8_t, s0, s1);
case VTYPE_INT16: return compare(s16_t, s0, s1);
case VTYPE_INT32: return compare(s32_t, s0, s1);
case VTYPE_INT64: return compare(s64_t, s0, s1);
2022-06-02 14:22:19 +03:00
case VTYPE_BOOLEAN:
2022-06-05 18:32:57 +03:00
case VTYPE_UINT8: return compare( u8_t, s0, s1);
case VTYPE_UINT16: return compare(u16_t, s0, s1);
2022-06-02 14:22:19 +03:00
case VTYPE_UINT32:
2022-08-14 20:55:40 +03:00
x86_ptr: return compare(u32_t, s0, s1);
2022-06-02 14:22:19 +03:00
2022-08-14 20:55:40 +03:00
case VTYPE_POINTER: if (!is_x64) goto x86_ptr;
2022-06-05 18:32:57 +03:00
case VTYPE_UINT64: return compare(u64_t, s0, s1);
2022-06-02 14:22:19 +03:00
2022-06-05 18:32:57 +03:00
case VTYPE_LDOUBLE: return (abs(*(ldbl_t*)s0 - *(ldbl_t*)s1) <= LDBL_EPSILON) ? 0 : (*(ldbl_t*)s0 < *(ldbl_t*)s1 ? -1 : 1);
case VTYPE_DOUBLE: return (abs(*( dbl_t*)s0 - *( dbl_t*)s1) <= DBL_EPSILON) ? 0 : (*( dbl_t*)s0 < *( dbl_t*)s1 ? -1 : 1);
case VTYPE_FLOAT: return (abs(*( fl_t*)s0 - *( fl_t*)s1) <= FLT_EPSILON) ? 0 : (*( fl_t*)s0 < *( fl_t*)s1 ? -1 : 1);
2022-06-02 14:22:19 +03:00
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);
2022-08-14 20:55:40 +03:00
case VTYPE_DICT: return dict_compare(s0, s1);
2022-06-02 14:22:19 +03:00
}
2022-06-05 18:32:57 +03:00
#undef compare
2022-06-02 14:22:19 +03:00
}
2022-08-14 20:55:40 +03:00
/*#####################################################################################################################*/
2022-08-15 17:29:33 +03:00
hash_t libcdsb_vtype_hash(const void* v, vtype t) {
2022-08-14 20:55:40 +03:00
switch (t) { default: abort();
case VTYPE_BOOLEAN:
case VTYPE_INT8:
case VTYPE_UINT8: return (hash_t)(*(u8_t*)v);
case VTYPE_INT16:
case VTYPE_UINT16: return (hash_t)(*(u16_t*)v);
case VTYPE_INT32:
case VTYPE_UINT32:
x86_ptr: return (hash_t)(*(u32_t*)v);
case VTYPE_POINTER: if (!is_x64) goto x86_ptr;
case VTYPE_INT64:
2022-08-15 17:29:33 +03:00
case VTYPE_UINT64: if (sizeof(hash_t) == sizeof(u64_t)) {
return (hash_t)(*(u64_t*)v);
} else {
return (hash_t)(*(u32_t*)v) ^ (*((u32_t*)v + 1));
}
2022-08-14 20:55:40 +03:00
case VTYPE_STRING: return string_hash(v);
case VTYPE_ARRAY: return array_hash(v);
case VTYPE_LIST: return list_hash(v);
case VTYPE_MAP: return map_hash(v);
case VTYPE_SET: return vset_hash(v);
case VTYPE_DICT: return dict_hash(v);
case VTYPE_FLOAT: return ldouble_hash(*(fl_t*)v);
case VTYPE_DOUBLE: return ldouble_hash(*(dbl_t*)v);
case VTYPE_LDOUBLE: return ldouble_hash(*(ldbl_t*)v);
}
}