1
0
Files
wfassoc/wfassoc/wfassoc_utils.c

257 lines
7.0 KiB
C

#include "wfassoc_utils.h"
#pragma region WFString
WFERROR WFString_Alloc_Wchar(WFString** strl, const wchar_t* raw_data) {
if (raw_data == NULL) return WFERROR_NULLPTR;
WFERROR ec;
if ((ec = WFString_Alloc(strl)) != WFERROR_OK) return ec;
if ((ec = WFString_SetData(*strl, raw_data)) != WFERROR_OK) return ec;
return WFERROR_OK;
}
WFERROR WFString_Alloc_Char(WFString** strl, const char* raw_data, BOOL is_utf8) {
if (raw_data == NULL) return WFERROR_NULLPTR;
// init string
WFERROR ec;
if ((ec = WFString_Alloc(strl)) != WFERROR_OK) return ec;
// compute expected string length
uint32_t sourceLength = strlen(raw_data);
int destLength = MultiByteToWideChar(is_utf8 ? CP_UTF8 : CP_ACP, 0, raw_data, sourceLength, NULL, 0);
if (destLength <= 0) return WFERROR_CRT;
--destLength; // remove terminal char
// resize string
if ((ec = WFString_Resize(*strl, destLength)) != WFERROR_OK) return ec;
// clear buffer and write data
wchar_t* buffer;
if ((ec = WFString_GetData(*strl, &buffer)) != WFERROR_OK) return ec;
memset(buffer, 0, sizeof(WCHAR) * destLength);
int crt_error = MultiByteToWideChar(is_utf8 ? CP_UTF8 : CP_ACP, 0, raw_data, sourceLength, buffer, destLength);
if (crt_error <= 0) return WFERROR_CRT;
return WFERROR_OK;
}
WFERROR WFString_Alloc_Capacity(WFString** strl, uint32_t size) {
*strl = WFNEW(WFString);
if (*strl == NULL) return WFERROR_ALLOC;
// init struct data
(*strl)->mCapacity = size;
(*strl)->mRealCapacity = size + 1;
(*strl)->mLength = 0;
(*strl)->mRealLength = 1;
(*strl)->mRawData = malloc((*strl)->mRealCapacity * sizeof(wchar_t));
if ((*strl)->mRawData == NULL) return WFERROR_ALLOC;
(*strl)->mRawData[(*strl)->mRealLength - 1] = 0;
return WFERROR_OK;
}
WFERROR WFString_Alloc(WFString** strl) {
return WFString_Alloc_Capacity(strl, 256);
}
WFERROR WFString_Free(WFString* strl) {
if (strl == NULL) return WFERROR_OK;
if (strl->mRawData == NULL) return WFERROR_NULLPTR;
free(strl->mRawData);
free(strl);
return WFERROR_OK;
}
WFERROR WFString_Resize(WFString* strl, uint32_t new_size) {
// if remain data is not enough, we need alloc new one
if (new_size >= strl->mCapacity) {
strl->mCapacity = new_size * 2;
strl->mRealCapacity = strl->mCapacity + 1;
// alloc buffer
if (strl->mRawData != NULL)
strl->mRawData = realloc(strl->mRawData, strl->mRealCapacity * sizeof(wchar_t));
else
strl->mRawData = malloc(strl->mRealCapacity * sizeof(wchar_t));
if (strl->mRawData == NULL) return WFERROR_ALLOC;
}
// set length as new length
strl->mLength = new_size;
strl->mRealLength = strl->mLength + 1;
// set the last one is zero
strl->mRawData[strl->mRealLength - 1] = 0;
return WFERROR_OK;
}
WFERROR WFString_GetData(WFString* strl, wchar_t** pdata) {
if (strl == NULL) return WFERROR_NULLPTR;
*pdata = strl->mRawData;
return WFERROR_OK;
}
WFERROR WFString_SetData(WFString* strl, const wchar_t* data) {
if (strl == NULL || data == NULL) return WFERROR_NULLPTR;
// get length and resize buffer
WFERROR ec;
uint32_t size = wcslen(data);
ec = WFString_Resize(strl, size);
if (ec != WFERROR_OK) return ec;
// copy data
if (size != 0)
memcpy(strl->mRawData, data, sizeof(wchar_t) * size);
return WFERROR_OK;
}
WFERROR WFString_GetLength(WFString* strl, uint32_t* len) {
if (strl == NULL) return WFERROR_NULLPTR;
*len = strl->mLength;
return WFERROR_OK;
}
WFERROR WFString_Printf(WFString* strl, const wchar_t* format, ...) {
if (strl == NULL) return WFERROR_NULLPTR;
// get expected size
va_list argptr;
va_start(argptr, format);
uint32_t count = _vsnwprintf(NULL, 0, format, argptr);
//count++;
va_end(argptr);
// resize string and get buffer ptr
WFERROR ec;
wchar_t* buffer;
if ((ec = WFString_Resize(strl, count)) != WFERROR_OK) return ec;
if ((ec = WFString_GetData(strl, &buffer)) != WFERROR_OK) return ec;
// write data to buffer
buffer[count - 1] = L'\0';
va_start(argptr, format);
int write_result = _vsnwprintf(buffer, count, format, argptr);
va_end(argptr);
if (write_result < 0 || write_result >= count) return WFERROR_CRT;
return WFERROR_OK;
}
WFERROR WFString_Concat_Wchar(WFString* strl, const wchar_t* extra) {
if (strl == NULL) return WFERROR_NULLPTR;
if (extra == NULL) return WFERROR_OK;
uint32_t count = wcslen(extra);
uint32_t oldlen = strl->mLength;
// if extra strl count is 0, do not copy any data.
if (count == 0) return WFERROR_OK;
WFERROR ec;
if ((ec = WFString_Resize(strl, oldlen + count)) != WFERROR_OK) return ec;
memcpy(strl->mRawData + oldlen, extra, sizeof(wchar_t) * count);
return WFERROR_OK;
}
WFERROR WFString_Concat_String(WFString* strl, WFString* extra) {
if (strl == NULL) return WFERROR_NULLPTR;
if (extra == NULL) return WFERROR_OK;
return WFString_Concat_Wchar(strl, extra->mRawData);
}
WFERROR WFString_SubString(WFString* strl, WFString* substring, uint32_t start_index, uint32_t length) {
if (strl == NULL) return WFERROR_NULLPTR;
if (start_index >= strl->mLength || length > strl->mLength - start_index) return WFERROR_INVALID_ARGUMENTS;
WFERROR ec;
if ((ec = WFString_Resize(substring, length)) != WFERROR_OK) return ec;
if (length != 0) {
memcpy(substring->mRawData, strl->mRawData + start_index, sizeof(wchar_t) * length);
}
return WFERROR_OK;
}
#pragma endregion
#pragma region WFLinkedList
WFERROR WFLinkedList_Alloc(WFLinkedList** list) {
*list = WFNEW(WFLinkedList);
if (*list == NULL) return WFERROR_ALLOC;
return WFERROR_OK;
}
WFERROR WFLinkedList_Free(WFLinkedList* list) {
return WFLinkedList_Free_Full(list, NULL);
}
WFERROR WFLinkedList_Free_Full(WFLinkedList* list, WFLinkedListNode_FreeDataFunc free_func) {
if (list == NULL) return WFERROR_OK;
// iterate full list and remove data and node
WFLinkedListNode* node = list->mHead, * free_node = NULL;
while (node != NULL) {
// free raw data
if (free_func != NULL) (*free_func)(node->mRawData);
// move to next node and free current node
free_node = node;
node = node->mNext;
free(free_node);
}
// free list self
free(list);
return WFERROR_OK;
}
WFERROR WFLinkedList_Add(WFLinkedList* list, void* data) {
if (list == NULL) return WFERROR_NULLPTR;
WFLinkedListNode* new_item = WFNEW(WFLinkedListNode);
if (new_item == NULL) return WFERROR_ALLOC;
new_item->mNext = NULL;
new_item->mRawData = data;
if (list->mLength == 0) {
list->mHead = list->mTail = new_item;
} else {
list->mTail->mNext = new_item;
list->mTail = new_item;
}
++list->mLength;
return WFERROR_OK;
}
WFERROR WFLinkedList_NodeIterator(WFLinkedList* list, WFLinkedListNode** node_ptr) {
if (list == NULL) return WFERROR_NULLPTR;
if (*node_ptr == NULL) {
// if node_ptr is NULL, it mean that wo should iterate this list from head
*node_ptr = list->mHead;
} else {
// otherwise, move to next node
*node_ptr = (*node_ptr)->mNext;
}
// if the header is null, return end of tail error to notice caller stop iterate
if (*node_ptr == NULL) return WFERROR_END_OF_TAIL;
else return WFERROR_OK;
}
WFERROR WFLinkedListNode_GetData(WFLinkedListNode* node, void** pdata) {
if (node == NULL) return WFERROR_NULLPTR;
*pdata = node->mRawData;
return WFERROR_OK;
}
#pragma endregion