98 lines
2.8 KiB
C
98 lines
2.8 KiB
C
#include <c_ArrayQueue.h>
|
|||
|
|
#include <c_Memory.h>
|
||
|
|
|
||
|
|
#define DEFAULT_INITIAL_CAPACITY 4
|
||
|
|
|
||
|
|
/* ------------------------------------------------------------------------------------------------------------------ */
|
||
|
|
/* */
|
||
|
|
|
||
|
|
c_err_t c_ArrayQueue_Init(c_ArrayQueue_t* self, int obj_size, c_size_t capacity) {
|
||
|
|
if (!self || obj_size == 0) return C_ERR_PARAM;
|
||
|
|
|
||
|
|
self->obj_size = obj_size;
|
||
|
|
self->capacity = (capacity > 0) ? capacity : DEFAULT_INITIAL_CAPACITY;
|
||
|
|
self->size = 0;
|
||
|
|
|
||
|
|
self->array = C_ALLOC(self->capacity * self->obj_size);
|
||
|
|
if (!self->array) {
|
||
|
|
self->capacity = 0;
|
||
|
|
return C_ERR_NOMEM;
|
||
|
|
}
|
||
|
|
|
||
|
|
return C_ERR_SUCCESS;
|
||
|
|
}
|
||
|
|
|
||
|
|
void c_ArrayQueue_Destroy(c_ArrayQueue_t* self) {
|
||
|
|
if (!self) return;
|
||
|
|
|
||
|
|
C_FREE(self->array);
|
||
|
|
|
||
|
|
self->capacity = 0;
|
||
|
|
self->size = 0;
|
||
|
|
self->obj_size = 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
c_err_t c_ArrayQueue_Push(c_ArrayQueue_t* self, void* obj) {
|
||
|
|
if (!self || !self->array || !obj) return C_ERR_PARAM;
|
||
|
|
|
||
|
|
if (self->size >= self->capacity) {
|
||
|
|
const c_size_t new_capacity = self->capacity << 1;
|
||
|
|
void* new_array = C_REALLOC(self->array, new_capacity * self->obj_size);
|
||
|
|
if (!new_array) {
|
||
|
|
return C_ERR_NOMEM;
|
||
|
|
}
|
||
|
|
self->array = new_array;
|
||
|
|
self->capacity = new_capacity;
|
||
|
|
}
|
||
|
|
|
||
|
|
char* target = (char*)self->array + (self->size * self->obj_size);
|
||
|
|
memcpy(target, obj, self->obj_size);
|
||
|
|
self->size++;
|
||
|
|
|
||
|
|
return C_ERR_SUCCESS;
|
||
|
|
}
|
||
|
|
|
||
|
|
c_err_t c_ArrayQueue_Pop(c_ArrayQueue_t* self, void* obj) {
|
||
|
|
if (!self || !self->array ) return C_ERR_PARAM;
|
||
|
|
if (self->size == 0) return C_ERR_EMPTY; // 佇列已空
|
||
|
|
|
||
|
|
char* pop_src = (char*)self->array; // 最前端索引 0 的地址
|
||
|
|
|
||
|
|
// 1. 直接值複製到呼叫端提供的記憶體中
|
||
|
|
if (obj) {
|
||
|
|
memcpy(obj, pop_src, self->obj_size);
|
||
|
|
}
|
||
|
|
|
||
|
|
// 2. 如果佇列內還有其他元素,將它們向前平移一個單位
|
||
|
|
if (self->size > 1) {
|
||
|
|
char* dest = pop_src;
|
||
|
|
const char* src = pop_src + self->obj_size;
|
||
|
|
const c_size_t num_elements_to_move = self->size - 1;
|
||
|
|
memmove(dest, src, num_elements_to_move * self->obj_size);
|
||
|
|
}
|
||
|
|
|
||
|
|
self->size--;
|
||
|
|
return C_ERR_SUCCESS;
|
||
|
|
}
|
||
|
|
|
||
|
|
c_err_t c_ArrayQueue_Remove(c_ArrayQueue_t* self, c_size_t index) {
|
||
|
|
if (!self || !self->array) return C_ERR_PARAM;
|
||
|
|
if (index >= self->size) return C_ERR_INDEX;
|
||
|
|
|
||
|
|
if (index < self->size - 1) {
|
||
|
|
char* dest = (char*)self->array + (index * self->obj_size);
|
||
|
|
const char* src = dest + self->obj_size;
|
||
|
|
const c_size_t num_elements_to_move = self->size - index - 1;
|
||
|
|
memmove(dest, src, num_elements_to_move * self->obj_size);
|
||
|
|
}
|
||
|
|
|
||
|
|
self->size--;
|
||
|
|
return C_ERR_SUCCESS;
|
||
|
|
}
|
||
|
|
|
||
|
|
void* c_ArrayQueue_Peek(c_ArrayQueue_t* self) {
|
||
|
|
if (!self || !self->array || self->size == 0) return NULL;
|
||
|
|
return self->array; // 最前端索引 0 的起始地址即是 array 本身
|
||
|
|
}
|
||
|
|
|