Files
Nuake-custom/Nuake/Vendors/katana-parser/foundation.c
2025-01-30 22:41:17 -05:00

237 lines
7.4 KiB
C

//
// foundation.c
// Katana
//
// Created by QFish on 3/19/15.
// Copyright (c) 2015 QFish. All rights reserved.
//
#include "foundation.h"
#include "parser.h"
#include <string.h>
#include <stdbool.h>
#include <assert.h>
//#undef assert
//#define assert(x)
struct KatanaInternalParser;
const KatanaParserString kKatanaAsteriskString = {"*", 1};
static const size_t kDefaultStringBufferSize = 12;
static void maybe_resize_string(struct KatanaInternalParser* parser,
size_t additional_chars,
KatanaParserString* str) {
size_t new_length = str->length + additional_chars;
size_t new_capacity = str->capacity;
while (new_capacity < new_length) {
new_capacity *= 2;
}
if (new_capacity != str->capacity) {
char* new_data = katana_parser_allocate(parser, new_capacity);
memset(new_data, 0, str->length);
memcpy(new_data, str->data, str->length);
katana_parser_deallocate(parser, str->data);
str->data = new_data;
str->capacity = new_capacity;
}
}
void katana_string_init(struct KatanaInternalParser* parser,
KatanaParserString* output) {
output->data = katana_parser_allocate(parser, kDefaultStringBufferSize);
memset( output->data, 0, sizeof(kDefaultStringBufferSize) );
output->length = 0;
output->capacity = kDefaultStringBufferSize;
}
void katana_string_append_characters(struct KatanaInternalParser* parser,
const char* str, KatanaParserString* output)
{
size_t len = strlen(str);
maybe_resize_string(parser, len, output);
memcpy(output->data + output->length, str, len);
output->length += len;
}
void katana_string_prepend_characters(struct KatanaInternalParser* parser,
const char* str,
KatanaParserString* output)
{
size_t len = strlen(str);
size_t new_length = output->length + len;
char* new_data = katana_parser_allocate(parser, new_length);
memcpy(new_data, str, len);
memcpy(new_data+len, output->data, output->length);
katana_parser_deallocate(parser, output->data);
output->data = new_data;
output->length = new_length;
output->capacity = new_length;
}
void katana_string_append_string(struct KatanaInternalParser* parser,
KatanaParserString* str,
KatanaParserString* output) {
maybe_resize_string(parser, str->length, output);
memcpy(output->data + output->length, str->data, str->length);
output->length += str->length;
}
bool katana_string_has_prefix(const char* str, const char* prefix)
{
size_t pre_len = strlen(prefix);
size_t str_len = strlen(str);
return pre_len <= str_len && stricmp(prefix, str);
}
void katana_string_to_lowercase(struct KatanaInternalParser* parser,
KatanaParserString* str)
{
if ( !str )
return;
// FIXME: @(QFish) the char* in string piece is const, to find a better way
char *c = (char*)str->data;
for (int i=0; i < str->length; i++) {
*c = tolower(*c);
c++;
}
}
const char* katana_string_to_characters(struct KatanaInternalParser * parser, const KatanaParserString* str)
{
assert(NULL != str);
if (NULL == str)
return NULL;
char* buffer = katana_parser_allocate(parser, sizeof(char) * (str->length + 1));
memcpy(buffer, str->data, str->length);
buffer[str->length] = '\0';
return buffer;
}
const char* katana_string_to_characters_with_prefix_char(struct KatanaInternalParser * parser, const KatanaParserString* str, const char prefix)
{
assert(str);
if (NULL == str)
return NULL;
char* buffer = katana_parser_allocate(parser, sizeof(char) * (str->length + 2));
memcpy((buffer + 1), str->data, str->length);
buffer[0] = prefix;
buffer[str->length] = '\0';
return buffer;
}
/**
* Array
*/
void katana_array_init(struct KatanaInternalParser* parser,
size_t initial_capacity, KatanaArray* array) {
array->length = 0;
array->capacity = (unsigned int)initial_capacity;
if (initial_capacity > 0) {
array->data = katana_parser_allocate(parser, sizeof(void*) * initial_capacity);
} else {
array->data = NULL;
}
}
void katana_array_destroy(struct KatanaInternalParser* parser,
KatanaArray* array) {
if (array->capacity > 0) {
katana_parser_deallocate(parser, array->data);
}
}
static void enlarge_array_if_full(struct KatanaInternalParser* parser,
KatanaArray* array) {
if (array->length >= array->capacity) {
if (array->capacity) {
size_t old_num_bytes = sizeof(void*) * array->capacity;
array->capacity *= 2;
size_t num_bytes = sizeof(void*) * array->capacity;
void** temp = katana_parser_allocate(parser, num_bytes);
memcpy(temp, array->data, old_num_bytes);
katana_parser_deallocate(parser, array->data);
array->data = temp;
} else {
// 0-capacity array; no previous array to deallocate.
array->capacity = 2;
array->data = katana_parser_allocate(parser, sizeof(void*) * array->capacity);
}
}
}
void katana_array_add(struct KatanaInternalParser* parser,
void* element, KatanaArray* array) {
enlarge_array_if_full(parser, array);
assert(array->data);
assert(array->length < array->capacity);
array->data[array->length++] = element;
}
void* katana_array_pop(struct KatanaInternalParser* parser,
KatanaArray* array) {
if (array->length == 0) {
return NULL;
}
return array->data[--array->length];
}
int katana_array_index_of(KatanaArray* array, void* element) {
for (int i = 0; i < array->length; ++i) {
if (array->data[i] == element) {
return i;
}
}
return -1;
}
void katana_array_insert_at(struct KatanaInternalParser* parser,
void* element, int index,
KatanaArray* array) {
assert(index >= 0);
assert(index <= array->length);
enlarge_array_if_full(parser, array);
++array->length;
memmove(&array->data[index + 1], &array->data[index],
sizeof(void*) * (array->length - index - 1));
array->data[index] = element;
}
void katana_array_remove(struct KatanaInternalParser* parser,
void* node, KatanaArray* array) {
int index = katana_array_index_of(array, node);
if (index == -1) {
return;
}
katana_array_remove_at(parser, index, array);
}
void* katana_array_remove_at(struct KatanaInternalParser* parser,
int index, KatanaArray* array) {
assert(index >= 0);
assert(index < array->length);
void* result = array->data[index];
memmove(&array->data[index], &array->data[index + 1],
sizeof(void*) * (array->length - index - 1));
--array->length;
return result;
}
/**
* An alloc / free method
*/
void* katana_parser_allocate(struct KatanaInternalParser* parser, size_t size) {
return parser->options->allocator(parser->options->userdata, size);
}
void katana_parser_deallocate(struct KatanaInternalParser* parser, void* ptr) {
parser->options->deallocator(parser->options->userdata, ptr);
}