/******************************************************************************* * * Helper functions. * ******************************************************************************/ static enum sl_error ensure_allocated(struct sl_vector* vec, size_t capacity, bool keep_data) { void* buffer = NULL; enum sl_error sl_err = SL_NO_ERROR; ASSERT(vec); if(capacity > vec->capacity) { size_t new_capacity = 0; NEXT_POWER_OF_2(capacity, new_capacity); buffer = MEM_ALIGNED_ALLOC (vec->allocator, new_capacity * vec->data_size, vec->data_alignment); if(!buffer) { sl_err = SL_MEMORY_ERROR; goto error; } if(keep_data) { buffer = memcpy(buffer, vec->buffer, vec->capacity * vec->data_size); } MEM_FREE(vec->allocator, vec->buffer); vec->buffer = buffer; vec->capacity = new_capacity; buffer = NULL; } exit: return sl_err; error: if(buffer) { MEM_FREE(vec->allocator, buffer); buffer = NULL; } goto exit; }
hwfont Tutf_UTF_32_to_CP437(hwfont c) { #define EL(x) +1 enum { n = T_NLIST(CP437,EL) + 1, /* +1 to manually map T_UTF_32_CHECK_MARK -> T_CP437_SQUARE_ROOT below */ n_power_of_2 = NEXT_POWER_OF_2(n) }; #undef EL static utf32_hash_table * table = NULL; /* Codepage 437 (VGA) obviously cannot contain all unicode chars. this is just a best effort. */ if (!table) { table = utf32_hash_create(Tutf_CP437_to_UTF_32, n, n_power_of_2); /* manually map T_UTF_32_CHECK_MARK -> T_CP437_SQUARE_ROOT */ utf32_hash_insert_at(table, n - 1, T_UTF_32_CHECK_MARK, T_CP437_SQUARE_ROOT); } return utf32_hash_search(table, c, ttrue); }
hwfont T_CAT(Tutf_UTF_16_to_,T_TEMPLATE) (hwfont c) { #define EL(x) +1 enum { n = T_NLIST(T_TEMPLATE,EL) + 0, /* +0 in case T_NLIST() expands to nothing */ n_power_of_2 = NEXT_POWER_OF_2(n) }; #undef EL static utf16_hash_table * table = NULL; /* a single 8-bit charset obviously cannot contain all unicode chars. this is just a best effort. */ if (!table) table = utf16_hash_create(T_CAT3(Tutf_,T_TEMPLATE,_to_UTF_16), n, n_power_of_2); #ifdef TEMPLATE_REDEFINES_ASCII return utf16_hash_search(table, c, FALSE); #else return utf16_hash_search(table, c, TRUE); #endif }
EXPORT_SYM enum sl_error sl_vector_insert_n (struct sl_vector* vec, size_t id, size_t count, const void* data) { void* buffer = NULL; const void* src = NULL; void* dst = NULL; size_t i = 0; enum sl_error err = SL_NO_ERROR; if(!vec || (id > vec->length) || !data) { err = SL_INVALID_ARGUMENT; goto error; } if(0 == count) { goto exit; } if(!IS_ALIGNED(data, vec->data_alignment)) { err = SL_ALIGNMENT_ERROR; goto error; } if(vec->length == SIZE_MAX) { err = SL_OVERFLOW_ERROR; goto error; } if(id == vec->length) { err = ensure_allocated(vec, vec->length + count, true); if(err != SL_NO_ERROR) goto error; dst = (void*)((uintptr_t)(vec->buffer) + vec->data_size * id); src = data; for(i = 0; i < count; ++i) { dst = memcpy(dst, src, vec->data_size); dst = (void*)((uintptr_t)(dst) + vec->data_size); } } else { if(vec->length + count >= vec->capacity) { size_t new_capacity = 0; NEXT_POWER_OF_2(vec->length + count, new_capacity); buffer = MEM_ALIGNED_ALLOC (vec->allocator, new_capacity * vec->data_size, vec->data_alignment); if(!buffer) { err = SL_MEMORY_ERROR; goto error; } /* Copy the vector data ranging from [0, id[ into the new buffer. */ if(id > 0) memcpy(buffer, vec->buffer, vec->data_size * id); if(id < vec->length) { /* Copy from the vector data [id, length[ to the new buffer * [id+count, length + count[. */ src = (void*)((uintptr_t)(vec->buffer) + vec->data_size * id); dst = (void*)((uintptr_t)(buffer) + vec->data_size * (id + count)); dst = memcpy(dst, src, vec->data_size * (vec->length - id)); } /* Set the src/dst pointer of the data insertion process. */ dst = (void*)((uintptr_t)(buffer) + vec->data_size * id); src = data; for(i = 0; i < count; ++i) { dst = memcpy(dst, src, vec->data_size); dst = (void*)((uintptr_t)(dst) + vec->data_size); } /* The data to insert may be contained in vec, i.e. free vec->buffer * *AFTER* the insertion. */ if(vec->buffer) MEM_FREE(vec->allocator, vec->buffer); vec->buffer = buffer; vec->capacity = new_capacity; buffer = NULL; } else { if(id < vec->length) { src = (void*)((uintptr_t)(vec->buffer) + vec->data_size * id); dst = (void*)((uintptr_t)(vec->buffer) + vec->data_size * (id + count)); dst = memmove(dst, src, vec->data_size * (vec->length - id)); } /* Set the src/dst pointer of the data insertion process. Note that If the * data to insert lies in the vector range [id, vec.length[ then it was * previously memoved. Its new address is offseted by count * data_size * bytes. */ dst = (void*)((uintptr_t)(vec->buffer) + vec->data_size * id); if(IS_MEMORY_OVERLAPPED (data, vec->data_size, (void*)((uintptr_t)(vec->buffer) + vec->data_size * id), (vec->length - id) * vec->data_size)) { src = (void*)((uintptr_t)data + count * vec->data_size); } else { src = data; } for(i = 0; i < count; ++i) { dst = memcpy(dst, src, vec->data_size); dst = (void*)((uintptr_t)(dst) + vec->data_size); } } } vec->length += count; exit: return err; error: if(buffer) MEM_FREE(vec->allocator, buffer); goto exit; }