mirror of
https://github.com/theoludwig/libcproject.git
synced 2024-12-11 21:13:00 +01:00
443 lines
14 KiB
C
443 lines
14 KiB
C
#include "string.h"
|
|
|
|
size_t string_get_length(const string_t string) {
|
|
size_t length = 0;
|
|
while (string[length] != '\0') {
|
|
length++;
|
|
}
|
|
return length;
|
|
}
|
|
|
|
void string_to_uppercase(string_t string) {
|
|
size_t string_length = string_get_length(string);
|
|
for (size_t index = 0; index < string_length; index++) {
|
|
string[index] = character_to_upper(string[index]);
|
|
}
|
|
string[string_length] = '\0';
|
|
}
|
|
|
|
void string_to_lowercase(string_t string) {
|
|
size_t string_length = string_get_length(string);
|
|
for (size_t index = 0; index < string_length; index++) {
|
|
string[index] = character_to_lower(string[index]);
|
|
}
|
|
string[string_length] = '\0';
|
|
}
|
|
|
|
void string_replace(string_t string, char search, char replace) {
|
|
size_t string_length = string_get_length(string);
|
|
for (size_t index = 0; index < string_length; index++) {
|
|
bool is_search_value = search == string[index];
|
|
if (is_search_value) {
|
|
string[index] = replace;
|
|
} else {
|
|
string[index] = string[index];
|
|
}
|
|
}
|
|
string[string_length] = '\0';
|
|
}
|
|
|
|
void string_remove_character(string_t string, char search) {
|
|
size_t string_length = string_get_length(string);
|
|
for (size_t index = 0; index < string_length; index++) {
|
|
if (string[index] == search) {
|
|
for (size_t index_string = index; index_string < string_length; index_string++) {
|
|
string[index_string] = string[index_string + 1];
|
|
}
|
|
string_length--;
|
|
index--;
|
|
}
|
|
}
|
|
string[string_length] = '\0';
|
|
}
|
|
|
|
void string_trim_start(string_t string, char character) {
|
|
size_t string_length = string_get_length(string);
|
|
size_t index_space = 0;
|
|
while (string[index_space] == character) {
|
|
index_space++;
|
|
}
|
|
for (size_t index = 0; index < string_length - index_space; index++) {
|
|
string[index] = string[index + index_space];
|
|
}
|
|
string[string_length - index_space] = '\0';
|
|
}
|
|
|
|
void string_trim_end(string_t string, char character) {
|
|
size_t string_length = string_get_length(string);
|
|
size_t index_space = string_length - 1;
|
|
while (string[index_space] == character) {
|
|
index_space--;
|
|
}
|
|
string[index_space + 1] = '\0';
|
|
}
|
|
|
|
void string_trim(string_t string, char character) {
|
|
string_trim_start(string, character);
|
|
string_trim_end(string, character);
|
|
}
|
|
|
|
string_t string_copy(const string_t string) {
|
|
size_t source_length = string_get_length(string);
|
|
string_t copy = malloc(sizeof(char) * (source_length + 1));
|
|
if (copy == NULL) {
|
|
perror("Error (string_copy)");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
size_t index;
|
|
for (index = 0; index < source_length; index++) {
|
|
copy[index] = string[index];
|
|
}
|
|
copy[index] = '\0';
|
|
return copy;
|
|
}
|
|
|
|
void string_capitalize(string_t string) {
|
|
size_t string_length = string_get_length(string);
|
|
if (string_length == 0) {
|
|
return;
|
|
}
|
|
string[0] = character_to_upper(string[0]);
|
|
}
|
|
|
|
size_t string_total_occurrences_of_character(string_t string, char character) {
|
|
size_t result = 0;
|
|
size_t string_length = string_get_length(string);
|
|
for (size_t index = 0; index < string_length; index++) {
|
|
char current_character = string[index];
|
|
if (current_character == character) {
|
|
result += 1;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
void string_reverse(const string_t string) {
|
|
size_t string_length = string_get_length(string);
|
|
size_t index_start = 0;
|
|
size_t index_end = string_length - 1;
|
|
while (index_start < index_end) {
|
|
char temporary = string[index_start];
|
|
string[index_start] = string[index_end];
|
|
string[index_end] = temporary;
|
|
index_start++;
|
|
index_end--;
|
|
}
|
|
}
|
|
|
|
bool string_equals(const string_t string1, const string_t string2) {
|
|
size_t string1_length = string_get_length(string1);
|
|
size_t string2_length = string_get_length(string2);
|
|
bool is_equal = string1_length == string2_length;
|
|
for (size_t index = 0; index < string1_length && is_equal; index++) {
|
|
if (string1[index] != string2[index]) {
|
|
is_equal = false;
|
|
}
|
|
}
|
|
return is_equal;
|
|
}
|
|
|
|
bool string_get_is_integer(const string_t string) {
|
|
size_t index = 0;
|
|
size_t string_length = string_get_length(string);
|
|
bool is_integer = string_length >= 1;
|
|
if (is_integer && string[0] == '-') {
|
|
if (string_length == 1) {
|
|
is_integer = false;
|
|
} else {
|
|
index++;
|
|
}
|
|
}
|
|
while (index < string_length && is_integer) {
|
|
if (!character_get_is_digit(string[index])) {
|
|
is_integer = false;
|
|
}
|
|
index++;
|
|
}
|
|
return is_integer;
|
|
}
|
|
|
|
string_t* string_split(const string_t string, char separator, size_t* result_size) {
|
|
size_t string_length = string_get_length(string);
|
|
size_t index_string = 0;
|
|
size_t index_current = 0;
|
|
size_t index_result = 0;
|
|
string_t current = malloc(sizeof(char) * (string_length + 1));
|
|
string_t* result = NULL;
|
|
if (current == NULL) {
|
|
perror("Error (string_split)");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
while (index_string < string_length) {
|
|
if (string[index_string] == separator) {
|
|
current[index_current] = '\0';
|
|
result = realloc(result, sizeof(string_t) * (index_result + 1));
|
|
if (result == NULL) {
|
|
perror("Error (string_split)");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
result[index_result] = string_copy(current);
|
|
index_result++;
|
|
index_current = 0;
|
|
} else {
|
|
current[index_current] = string[index_string];
|
|
index_current++;
|
|
}
|
|
index_string++;
|
|
}
|
|
current[index_current] = '\0';
|
|
result = realloc(result, sizeof(string_t) * (index_result + 1));
|
|
if (result == NULL) {
|
|
perror("Error (string_split)");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
result[index_result] = string_copy(current);
|
|
free(current);
|
|
*result_size = index_result + 1;
|
|
return result;
|
|
}
|
|
|
|
string_t string_join(string_t* array, const char separator, size_t array_length) {
|
|
size_t total_length = 0;
|
|
for (size_t index_array = 0; index_array < array_length; index_array++) {
|
|
total_length += string_get_length(array[index_array]);
|
|
}
|
|
size_t string_length = total_length + (array_length - 1);
|
|
string_t string = malloc(sizeof(char) * (string_length + 1));
|
|
if (string == NULL) {
|
|
perror("Error (string_join)");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
size_t current_index = 0;
|
|
for (size_t index_array = 0; index_array < array_length; index_array++) {
|
|
string_t substring = array[index_array];
|
|
size_t substring_length = string_get_length(substring);
|
|
for (size_t index_substring = 0; index_substring < substring_length; index_substring++) {
|
|
string[current_index] = substring[index_substring];
|
|
current_index++;
|
|
}
|
|
bool is_last_character = index_array == (array_length - 1);
|
|
if (!is_last_character) {
|
|
string[current_index] = separator;
|
|
current_index++;
|
|
}
|
|
}
|
|
string[string_length] = '\0';
|
|
return string;
|
|
}
|
|
|
|
void string_concatenate(string_t* destination, string_t source) {
|
|
size_t destination_length = string_get_length(*destination);
|
|
size_t source_length = string_get_length(source);
|
|
size_t new_length = destination_length + source_length;
|
|
*destination = realloc(*destination, sizeof(char) * (new_length + 1));
|
|
if (*destination == NULL) {
|
|
perror("Error (string_concatenate)");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
size_t index_destination = destination_length;
|
|
for (size_t index_source = 0; index_source < source_length; index_source++) {
|
|
(*destination)[index_destination++] = source[index_source];
|
|
}
|
|
(*destination)[index_destination] = '\0';
|
|
}
|
|
|
|
bool string_get_has_unique_characters(const string_t string) {
|
|
bool has_unique = true;
|
|
size_t string_length = string_get_length(string);
|
|
struct hash_map* characters_already_seen = hash_map_initialization();
|
|
string_t* keys = malloc(sizeof(string_t) * string_length);
|
|
for (size_t index = 0; index < string_length; index++) {
|
|
keys[index] = NULL;
|
|
}
|
|
for (size_t index = 0; index < string_length && has_unique; index++) {
|
|
char character = string[index];
|
|
keys[index] = convert_character_to_string(character);
|
|
string_t key = keys[index];
|
|
if (hash_map_contains_key(characters_already_seen, key)) {
|
|
has_unique = false;
|
|
} else {
|
|
hash_map_add(characters_already_seen, key, (void*)true);
|
|
}
|
|
}
|
|
for (size_t index = 0; index < string_length; index++) {
|
|
if (keys[index] != NULL) {
|
|
free(keys[index]);
|
|
}
|
|
}
|
|
free(keys);
|
|
hash_map_free(characters_already_seen);
|
|
return has_unique;
|
|
}
|
|
|
|
string_t string_substring(const string_t string, size_t index_start, size_t index_end) {
|
|
size_t substring_length = index_end - index_start + 1;
|
|
string_t result = malloc(sizeof(char) * (substring_length + 1));
|
|
for (size_t index = 0; index < substring_length; index++) {
|
|
result[index] = string[index_start + index];
|
|
}
|
|
result[substring_length] = '\0';
|
|
return result;
|
|
}
|
|
|
|
bool string_get_is_substring(const string_t string, const string_t substring) {
|
|
bool is_substring = false;
|
|
size_t string_length = string_get_length(string);
|
|
size_t substring_length = string_get_length(substring);
|
|
for (size_t index_string = 0; index_string < string_length && !is_substring; index_string++) {
|
|
size_t index_substring = 0;
|
|
size_t index_considered = index_string;
|
|
while (index_substring < substring_length && string[index_considered] == substring[index_substring]) {
|
|
index_substring++;
|
|
index_considered++;
|
|
}
|
|
is_substring = index_substring == substring_length;
|
|
}
|
|
return is_substring;
|
|
}
|
|
|
|
string_t string_get_formatted_number(const int64_t number, string_t separator) {
|
|
string_t number_string_temp = convert_number_to_string(number);
|
|
string_t number_string = number_string_temp;
|
|
bool is_negative = number_string_temp[0] == '-';
|
|
if (is_negative) {
|
|
number_string = string_substring(number_string_temp, 1, string_get_length(number_string_temp));
|
|
free(number_string_temp);
|
|
}
|
|
size_t number_string_length = string_get_length(number_string);
|
|
size_t formatted_length = number_string_length + (number_string_length - 1) / 3;
|
|
string_t result = malloc(sizeof(char) * (formatted_length + 1));
|
|
if (result == NULL) {
|
|
perror("Error (string_get_formatted_number)");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
size_t count = 0;
|
|
size_t result_index = 0;
|
|
for (size_t index = 0; index < number_string_length; index++) {
|
|
size_t index_reversed = number_string_length - index - 1;
|
|
result[result_index] = number_string[index_reversed];
|
|
count++;
|
|
result_index++;
|
|
if (count == 3 && index != number_string_length - 1) {
|
|
for (size_t sep_index = 0; sep_index < string_get_length(separator); sep_index++) {
|
|
result[result_index] = separator[sep_index];
|
|
result_index++;
|
|
}
|
|
count = 0;
|
|
}
|
|
}
|
|
free(number_string);
|
|
result[formatted_length] = '\0';
|
|
string_reverse(result);
|
|
if (is_negative) {
|
|
string_t negative_result = convert_character_to_string('-');
|
|
string_concatenate(&negative_result, result);
|
|
free(result);
|
|
return negative_result;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
string_t string_get_last_occurence_of_character(const string_t string, char character) {
|
|
size_t string_length = string_get_length(string);
|
|
size_t index_last_occurrence = SIZE_MAX;
|
|
for (size_t index = 0; index < string_length; index++) {
|
|
if (string[index] == character) {
|
|
index_last_occurrence = index;
|
|
}
|
|
}
|
|
if (index_last_occurrence == SIZE_MAX) {
|
|
return "";
|
|
}
|
|
string_t result = malloc(sizeof(char) * (string_length - index_last_occurrence + 1));
|
|
if (result == NULL) {
|
|
perror("Error (string_get_last_occurence_of_character)");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
size_t index_result = 0;
|
|
for (size_t index = index_last_occurrence; index < string_length; index++) {
|
|
result[index_result++] = string[index];
|
|
}
|
|
result[index_result] = '\0';
|
|
return result;
|
|
}
|
|
|
|
bool string_starts_with(const string_t string, const string_t prefix) {
|
|
bool starts_with = true;
|
|
size_t prefix_length = string_get_length(prefix);
|
|
for (size_t index = 0; index < prefix_length && starts_with; index++) {
|
|
starts_with = string[index] == prefix[index];
|
|
}
|
|
return starts_with;
|
|
}
|
|
|
|
bool string_ends_with(const string_t string, const string_t prefix) {
|
|
bool ends_with = true;
|
|
size_t string_length = string_get_length(string);
|
|
size_t prefix_length = string_get_length(prefix);
|
|
size_t index_string = string_length - 1;
|
|
size_t index_prefix = prefix_length - 1;
|
|
while (index_prefix > 0 && ends_with) {
|
|
ends_with = string[index_string] == prefix[index_prefix];
|
|
index_string--;
|
|
index_prefix--;
|
|
}
|
|
return ends_with;
|
|
}
|
|
|
|
size_t string_position_of(const string_t string, const char character) {
|
|
size_t position_found = 0;
|
|
size_t string_length = string_get_length(string);
|
|
for (size_t index = 0; index < string_length && position_found == 0; index++) {
|
|
if (string[index] == character) {
|
|
position_found = index + 1;
|
|
}
|
|
}
|
|
return position_found;
|
|
}
|
|
|
|
size_t string_last_position_of(const string_t string, const char character) {
|
|
size_t position_found = 0;
|
|
size_t string_length = string_get_length(string);
|
|
while (string_length > 0 && position_found == 0) {
|
|
if (string[string_length - 1] == character) {
|
|
position_found = string_length;
|
|
}
|
|
string_length--;
|
|
}
|
|
return position_found;
|
|
}
|
|
|
|
string_t string_pad_start(const string_t string, const string_t pad_string, size_t target_length) {
|
|
string_t result = malloc(sizeof(char) * (target_length + 1));
|
|
size_t initial_length = string_get_length(string);
|
|
size_t left_length = target_length - initial_length;
|
|
if (target_length <= initial_length) {
|
|
left_length = 0;
|
|
}
|
|
size_t pad_length = string_get_length(pad_string);
|
|
size_t count_pad_string = 0;
|
|
size_t index_initial_string = 0;
|
|
for (size_t index = 0; index < target_length; index++) {
|
|
if (index < left_length) {
|
|
size_t index_pad_string = count_pad_string % pad_length;
|
|
result[index] = pad_string[index_pad_string];
|
|
count_pad_string += 1;
|
|
} else {
|
|
result[index] = string[index_initial_string];
|
|
index_initial_string += 1;
|
|
}
|
|
}
|
|
result[target_length] = '\0';
|
|
return result;
|
|
}
|
|
|
|
string_t string_zero_pad(uint64_t number, size_t places) {
|
|
string_t number_string = convert_number_to_string((int64_t)number);
|
|
string_t pad_string = string_copy("0");
|
|
string_t result = string_pad_start(number_string, pad_string, places);
|
|
free(pad_string);
|
|
free(number_string);
|
|
return result;
|
|
}
|