/* This software is licensed by the MIT License, see LICENSE file */ /* Copyright © 2022 Gregory Lirent */ #include "__internal/assert.h" #include "__internal/vnode.h" /*#####################################################################################################################*/ static vnode_t create_value(vtype xt, const void* v, vtype t) { var_t _; if (sizeof(void*) == 8) { 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 (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 create_float(vtype xt, const void* v, vtype t) { var_t _; if (t == VTYPE_FLOAT) { _.ld = *(fl_t*)v; } else if (t == VTYPE_DOUBLE) { _.ld = *(dbl_t*)v; } else { // (t == VTYPE_LDOUBLE) _.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) { _.f = _.d; if (!is_permissible(dbl_t)) { _.ptr = memndup(&_.d, sizeof(_.d)); } } else { // (xt == VTYPE_LDOUBLE) if (!is_permissible(ldbl_t)) { _.ptr = memndup(&_.ld, sizeof(_.ld)); } } return _.ptr; } /*#####################################################################################################################*/ vnode_t libcdsb_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)) _.ld = *(fl_t*)v; else _.ptr = memndup(v, sizeof(fl_t)); break; case VTYPE_DOUBLE: if (is_permissible(dbl_t)) _.ld = *(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: _.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_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: case VTYPE_MAP: case VTYPE_ARRAY: case VTYPE_LIST: case VTYPE_SET: pt_: return *x; } } void libcdsb_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: 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); pt_: free(*x); break; } *x = 0; } /*#####################################################################################################################*/ vnode_t libcdsb_vnode_create_target(vtype xt, const void* v, vtype t) { var_t _ = { .ptr = 0 }; if (is_integer(xt)) { tvalue_assert(t); return create_value(xt, v, t); } else if (is_float(xt)) { tfloat_assert(t); return create_float(xt, v, t); } type_assert(xt, t); switch (xt) { default: abort(); case VTYPE_STRING: _.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; }