[RELEASE] u22-v03
This version is submitted to U22 breau.
This commit is contained in:
11
util/container/CMakeLists.txt
Normal file
11
util/container/CMakeLists.txt
Normal file
@@ -0,0 +1,11 @@
|
||||
add_library(container
|
||||
array.c
|
||||
)
|
||||
target_link_libraries(container memory)
|
||||
|
||||
if (BUILD_TESTING)
|
||||
add_executable(container-test test.c)
|
||||
target_link_libraries(container-test container)
|
||||
|
||||
add_test(container-test container-test)
|
||||
endif()
|
90
util/container/array.c
Normal file
90
util/container/array.c
Normal file
@@ -0,0 +1,90 @@
|
||||
#include "./array.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "util/memory/memory.h"
|
||||
|
||||
typedef struct {
|
||||
size_t length;
|
||||
size_t reserved;
|
||||
} container_array_header_t;
|
||||
|
||||
void container_array_delete(void* array) {
|
||||
if (array == NULL) return;
|
||||
memory_delete(array - sizeof(container_array_header_t));
|
||||
}
|
||||
|
||||
void container_array_reserve_(void** array, size_t elmlen, size_t len) {
|
||||
assert(array != NULL);
|
||||
|
||||
if (len == 0) return;
|
||||
|
||||
container_array_header_t* ptr;
|
||||
if (*array == NULL) {
|
||||
ptr = memory_new(sizeof(*ptr) + len*elmlen);
|
||||
*ptr = (typeof(*ptr)) {
|
||||
.length = 0,
|
||||
.reserved = len,
|
||||
};
|
||||
} else {
|
||||
ptr = *array - sizeof(*ptr);
|
||||
if (ptr->reserved >= len) return;
|
||||
|
||||
ptr = memory_resize(ptr, sizeof(*ptr) + len*elmlen);
|
||||
ptr->reserved = len;
|
||||
}
|
||||
*array = ptr + 1;
|
||||
}
|
||||
|
||||
void container_array_resize_(void** array, size_t elmlen, size_t len) {
|
||||
assert(array != NULL);
|
||||
|
||||
container_array_reserve_(array, elmlen, len);
|
||||
if (*array == NULL) return;
|
||||
|
||||
container_array_header_t* ptr = *array - sizeof(*ptr);
|
||||
ptr->length = len;
|
||||
}
|
||||
|
||||
void container_array_insert_(void** array, size_t elmlen, size_t index) {
|
||||
assert(array != NULL);
|
||||
|
||||
const size_t len = container_array_get_length(*array) + 1;
|
||||
assert(index < len);
|
||||
container_array_resize_(array, elmlen, len);
|
||||
|
||||
uint8_t* src = *array + (index)*elmlen;
|
||||
memmove(src + elmlen, src, (len-index-1)*elmlen);
|
||||
}
|
||||
|
||||
void container_array_remove_(void** array, size_t elmlen, size_t index) {
|
||||
const size_t oldlen = container_array_get_length(*array);
|
||||
assert(index < oldlen);
|
||||
|
||||
const size_t len = oldlen-1;
|
||||
|
||||
uint8_t* dst = *array + index*elmlen;
|
||||
memmove(dst, dst + elmlen, (len-index)*elmlen);
|
||||
container_array_resize_(array, elmlen, len);
|
||||
}
|
||||
|
||||
void* container_array_duplicate_(const void* array, size_t elmlen) {
|
||||
if (array == NULL) return NULL;
|
||||
const container_array_header_t* ptr = array - sizeof(*ptr);
|
||||
|
||||
const size_t sz = sizeof(*ptr) + ptr->length*elmlen;
|
||||
|
||||
container_array_header_t* ptrdup = memory_new(sz);
|
||||
memcpy(ptrdup, ptr, sz);
|
||||
ptrdup->reserved = ptr->length;
|
||||
return (void*) (ptrdup + 1);
|
||||
}
|
||||
|
||||
size_t container_array_get_length_(const void* array) {
|
||||
if (array == NULL) return 0;
|
||||
const container_array_header_t* ptr = array - sizeof(*ptr);
|
||||
return ptr->length;
|
||||
}
|
31
util/container/array.h
Normal file
31
util/container/array.h
Normal file
@@ -0,0 +1,31 @@
|
||||
#pragma once
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#define CONTAINER_ARRAY
|
||||
|
||||
void container_array_delete(void* array);
|
||||
|
||||
#define container_array_reserve(array, len) \
|
||||
container_array_reserve_((void**) &array, sizeof(*array), len)
|
||||
void container_array_reserve_(void** array, size_t elmlen, size_t len);
|
||||
|
||||
#define container_array_resize(array, len) \
|
||||
container_array_resize_((void**) &array, sizeof(*array), len)
|
||||
void container_array_resize_(void** array, size_t elmlen, size_t len);
|
||||
|
||||
#define container_array_insert(array, index) \
|
||||
container_array_insert_((void**) &array, sizeof(*array), index)
|
||||
void container_array_insert_(void** array, size_t elmlen, size_t index);
|
||||
|
||||
#define container_array_remove(array, index) \
|
||||
container_array_remove_((void**) &array, sizeof(*array), index)
|
||||
void container_array_remove_(void** array, size_t elmlen, size_t index);
|
||||
|
||||
#define container_array_duplicate(array) \
|
||||
(typeof(array)) container_array_duplicate_( \
|
||||
(const void*) array, sizeof(*array))
|
||||
void* container_array_duplicate_(const void* array, size_t elmlen);
|
||||
|
||||
#define container_array_get_length(array) container_array_get_length_(array)
|
||||
size_t container_array_get_length_(const void* array);
|
48
util/container/test.c
Normal file
48
util/container/test.c
Normal file
@@ -0,0 +1,48 @@
|
||||
#undef NDEBUG
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "./array.h"
|
||||
static void test_array() {
|
||||
int32_t* numbers = NULL;
|
||||
assert(container_array_get_length(numbers) == 0);
|
||||
|
||||
container_array_reserve(numbers, 10);
|
||||
for (int32_t i = 50; i < 100; ++i) {
|
||||
container_array_insert(numbers, i-50);
|
||||
numbers[i-50] = i;
|
||||
}
|
||||
container_array_reserve(numbers, 10);
|
||||
for (int32_t i = 0; i < 50; ++i) {
|
||||
container_array_insert(numbers, i);
|
||||
numbers[i] = i;
|
||||
}
|
||||
for (int32_t i = 0; i < 100; ++i) {
|
||||
assert(numbers[i] == i);
|
||||
}
|
||||
|
||||
for (int32_t i = 99; i >= 0; i-=2) {
|
||||
container_array_remove(numbers, i);
|
||||
}
|
||||
for (int32_t i = 0; i < 100; i+=2) {
|
||||
assert(numbers[i/2] == i);
|
||||
}
|
||||
assert(container_array_get_length(numbers) == 50);
|
||||
|
||||
container_array_resize(numbers, 25);
|
||||
assert(container_array_get_length(numbers) == 25);
|
||||
|
||||
int32_t* dup = container_array_duplicate(numbers);
|
||||
for (int32_t i = 0; i < 25; ++i) {
|
||||
assert(numbers[i] == dup[i]);
|
||||
}
|
||||
container_array_delete(dup);
|
||||
|
||||
container_array_delete(numbers);
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
test_array();
|
||||
return 0;
|
||||
}
|
Reference in New Issue
Block a user