/* This software is licensed by the MIT License, see LICENSE file */ /* Copyright © 2022 Gregory Lirent */ #include "__internal/assert.h" #include "__internal/vnode.h" #include "../include/string.h" static vtype libcdsb_builtin_round(u64_t* x, ldbl_t v) { if (v > 0) { *x = (u64_t)(v + 0.5); return VTYPE_UINT64; } else { *x = (s64_t)(v - 0.5); return VTYPE_INT64; } } static vnode_t libcdsb_builtin_create_value(vtype xt, const void* v, vtype t) { var_t _; if (t == VTYPE_FLOAT) { t = libcdsb_builtin_round(&_.u64, *(fl_t*)v); } else if (t == VTYPE_DOUBLE) { t = libcdsb_builtin_round(&_.u64, *(dbl_t*)v); } else if (t == VTYPE_LDOUBLE) { t = libcdsb_builtin_round(&_.u64, *(ldbl_t*)v); } if (sizeof(void*) == 8) { if (t == VTYPE_UINT8 || t == VTYPE_BOOLEAN ) { _.u64 = *(u8_t*)v; } else if (t == VTYPE_UINT16) { _.u64 = *(u16_t*)v; } else if (t == VTYPE_UINT32 || (sizeof(void*) == 4 && t == VTYPE_POINTER)) { _.u64 = *(u32_t*)v; } else if (t == VTYPE_UINT64 || t == VTYPE_INT64 || (sizeof(void*) == 8 && t == VTYPE_POINTER)) { _.u64 = *(u64_t*)v; } else if (t == VTYPE_INT8) { _.u64 = *(s8_t*)v; } else if (t == VTYPE_INT16) { _.u64 = *(s16_t*)v; } else if (t == VTYPE_INT32) { _.u64 = *(s32_t*)v; } if (is_big_endian) { if (xt == VTYPE_BOOLEAN) _.u8 = (_.u64 == 0) ? 0 : 1; else if (xt == VTYPE_UINT8 || xt == VTYPE_INT8) { _.u64 <<= 56; } else if (xt == VTYPE_UINT16 || xt == VTYPE_INT16) { _.u64 <<= 48; } else if (xt == VTYPE_UINT32 || xt == VTYPE_INT32) { _.u64 <<= 32; } } else if (xt == VTYPE_BOOLEAN) _.u64 = (_.u64 == 0) ? 0 : 1; } else { if (t == VTYPE_UINT8 || t == VTYPE_INT8 || t == VTYPE_BOOLEAN ) { _.u64 = *(u8_t*)v; } else if (t == VTYPE_UINT16 || t == VTYPE_INT16) { _.u64 = *(u16_t*)v; } else if (t == VTYPE_UINT32 || t == VTYPE_INT32 || (sizeof(void*) == 4 && t == VTYPE_POINTER)) { _.u64 = *(u32_t*)v; } else if (t == VTYPE_UINT64 || t == VTYPE_INT64 || (sizeof(void*) == 8 && t == VTYPE_POINTER)) { _.u64 = *(u64_t*)v; } if (xt == VTYPE_UINT64 || xt == VTYPE_UINT32) { _.ptr = memndup(&_.u64, sizeof(_.u64)); } else if (is_big_endian) { _.u64 <<= 32; if (xt == VTYPE_BOOLEAN) _.u8 = (_.u32 == 0) ? 0 : 1; else if (xt == VTYPE_UINT8 || xt == VTYPE_INT8) { _.u32 <<= 24; } else if (xt == VTYPE_UINT16 || xt == VTYPE_INT16) { _.u32 <<= 16; } } else if (xt == VTYPE_BOOLEAN) _.u32 = (_.u32 == 0) ? 0 : 1; } return _.ptr; } static vnode_t libcdsb_builtin_create_float(vtype xt, const void* v, vtype t) { var_t _; if (t == VTYPE_UINT8 || t == VTYPE_BOOLEAN ) { _.ld = *(u8_t*)v; } else if (t == VTYPE_UINT16) { _.ld = *(u16_t*)v; } else if (t == VTYPE_UINT32 || (sizeof(void*) == 4 && t == VTYPE_POINTER)) { _.ld = *(u32_t*)v; } else if (t == VTYPE_UINT64 || (sizeof(void*) == 8 && t == VTYPE_POINTER)) { _.ld = *(u64_t*)v; } else if (t == VTYPE_INT8) { _.ld = *(s8_t*)v; } else if (t == VTYPE_INT16) { _.ld = *(s16_t*)v; } else if (t == VTYPE_INT32) { _.ld = *(s32_t*)v; } else if (t == VTYPE_INT64) { _.ld = *(s64_t*)v; } else if (t == VTYPE_FLOAT) { _.ld = *(fl_t*)v; } else if (t == VTYPE_DOUBLE) { _.ld = *(dbl_t*)v; } else { _.ld = *(ldbl_t*)v; } if (xt == VTYPE_FLOAT) { _.f = _.ld; if (!is_permissible(fl_t)) { _.ptr = memndup(&_.f, sizeof(_.f)); } } else if (xt == VTYPE_DOUBLE) { _.d = _.ld; if (!is_permissible(dbl_t)) { _.ptr = memndup(&_.d, sizeof(_.d)); } } else { if (!is_permissible(ldbl_t)) { _.ptr = memndup(&_.ld, sizeof(_.ld)); } } return _.ptr; } /*#####################################################################################################################*/ vnode_t libcdsb_builtin_vnode_create(const void* v, vtype t) { var_t _ = { .ptr = 0 }; switch (t) { default: abort(); case VTYPE_INT8: case VTYPE_UINT8: _.u8 = *(u8_t*)v; break; case VTYPE_INT16: case VTYPE_UINT16: _.u16 = *(u16_t*)v; break; case VTYPE_INT32: case VTYPE_UINT32: _.u32 = *(u32_t*)v; break; case VTYPE_INT64: case VTYPE_UINT64: if (is_x64) _.u64 = *(u64_t*)v; else _.ptr = memndup(v, sizeof(u64_t)); break; case VTYPE_FLOAT: if (is_permissible(fl_t)) _.f = *(fl_t*)v; else _.ptr = memndup(v, sizeof(fl_t)); break; case VTYPE_DOUBLE: if (is_permissible(dbl_t)) _.d = *(dbl_t*)v; else _.ptr = memndup(v, sizeof(dbl_t)); break; case VTYPE_LDOUBLE: if (is_permissible(ldbl_t)) _.ld = *(ldbl_t*)v; else _.ptr = memndup(v, sizeof(ldbl_t)); break; case VTYPE_BOOLEAN: _.b = *(bool*)v; break; case VTYPE_POINTER: _.ptr = *(void**)v; break; case VTYPE_STRING: if (sizeof(str_t) == sizeof(void*)) { _.ptr = strdup(*(char**)v); } else _.ptr = string_duplicate(v); break; case VTYPE_MAP: _.ptr = map_duplicate(v); break; case VTYPE_ARRAY: _.ptr = array_duplicate(v); break; case VTYPE_LIST: _.ptr = list_duplicate(v); break; case VTYPE_SET: _.ptr = vset_duplicate(v); break; } return _.ptr; } void* libcdsb_builtin_vnode_peek(const vnode_t* x, vtype t) { switch (t) { default: abort(); case VTYPE_FLOAT: if (is_permissible(fl_t)) goto vt_; else goto pt_; case VTYPE_DOUBLE: if (is_permissible(dbl_t)) goto vt_; else goto pt_; case VTYPE_LDOUBLE: if (is_permissible(ldbl_t)) goto vt_; else goto pt_; case VTYPE_INT64: case VTYPE_UINT64: if (!is_x64) goto pt_; case VTYPE_BOOLEAN: case VTYPE_POINTER: case VTYPE_INT8: case VTYPE_UINT8: case VTYPE_INT16: case VTYPE_UINT16: case VTYPE_INT32: case VTYPE_UINT32: vt_: return (void*)x; case VTYPE_STRING: if (sizeof(str_t) == sizeof(void*)) goto vt_; case VTYPE_MAP: case VTYPE_ARRAY: case VTYPE_LIST: case VTYPE_SET: case VTYPE_DICT: pt_: return *x; } } void libcdsb_builtin_vnode_free(vnode_t* x, vtype t) { switch (t) { default: abort(); case VTYPE_FLOAT: if (is_permissible(fl_t)) goto vt_; else goto pt_; case VTYPE_DOUBLE: if (is_permissible(dbl_t)) goto vt_; else goto pt_; case VTYPE_LDOUBLE: if (is_permissible(ldbl_t)) goto vt_; else goto pt_; case VTYPE_INT64: case VTYPE_UINT64: if (!is_x64) goto pt_; case VTYPE_BOOLEAN: case VTYPE_POINTER: case VTYPE_INT8: case VTYPE_UINT8: case VTYPE_INT16: case VTYPE_UINT16: case VTYPE_INT32: case VTYPE_UINT32: vt_: break; case VTYPE_STRING: if (sizeof(str_t) > sizeof(void*)) { string_free(*x); } goto pt_; case VTYPE_MAP: map_free(*x); goto pt_; case VTYPE_ARRAY: array_free(*x); goto pt_; case VTYPE_LIST: list_free(*x); goto pt_; case VTYPE_SET: vset_free(*x); goto pt_; case VTYPE_DICT: dict_free(*x); pt_: free(*x); break; } *x = 0; } vnode_t libcdsb_builtin_vnode_create_target(vtype xt, const void* v, vtype t) { var_t _ = { .ptr = 0 }; if (xt <= VTYPE_LDOUBLE) { if (t >= VTYPE_STRING) t = VTYPE_POINTER; if (xt <= VTYPE_INT64) return libcdsb_builtin_create_value(xt, v, t); return libcdsb_builtin_create_float(xt, v, t); } else if (t == VTYPE_POINTER && (t = xt) > VTYPE_STRING) { v = *(void**)v; } type_assert(xt, t); switch (xt) { default: abort(); case VTYPE_STRING: if (sizeof(str_t) == sizeof(void*)) { _.ptr = strdup(*(char**)v); } else _.ptr = string_duplicate(v); break; case VTYPE_MAP: _.ptr = map_duplicate(v); break; case VTYPE_ARRAY: _.ptr = array_duplicate(v); break; case VTYPE_LIST: _.ptr = list_duplicate(v); break; case VTYPE_SET: _.ptr = vset_duplicate(v); break; case VTYPE_DICT: _.ptr = dict_duplicate(v); break; } return _.ptr; }