Added `string_{get_at,set_at,to_lower,to_upper,reverse}
Some checks failed
clang-build / clang-build (push) Failing after 18s
gcc-build / gcc-build (push) Successful in 19s

This commit is contained in:
2026-03-13 17:16:02 +01:00
parent 086446039b
commit b4a704f1b4

View File

@@ -294,6 +294,8 @@ string_result_t string_concat(const string_t *x, const string_t *y) {
result = string_new(buf);
free(buf);
SET_MSG(result, "String successfully concatenated");
return result;
}
@@ -468,3 +470,282 @@ string_result_t string_eq(const string_t *x, const string_t *y, bool case_sensit
return result;
}
/**
* string_get_at
* @str: a non-null string
* @position: the position of the symbol to read
*
* Gets symbol indexed by @position from @str
*
* Returns a string_result_t containing the symbol as a C string
*/
string_result_t string_get_at(const string_t *str, size_t position) {
string_result_t result = {0};
if (str == NULL) {
result.status = STRING_ERR_INVALID;
SET_MSG(result, "Invalid string");
return result;
}
if (position >= str->char_count) {
result.status = STRING_ERR_OVERFLOW;
SET_MSG(result, "Index out of bounds");
return result;
}
const char *ptr = str->data;
for (size_t idx = 0; idx < position; idx++) {
ptr += utf8_char_len((unsigned char)*ptr);
}
int char_len = utf8_char_len((unsigned char)*ptr);
char *utf8_char = malloc(char_len + 1);
if (utf8_char == NULL) {
result.status = STRING_ERR_ALLOCATE;
SET_MSG(result, "Cannot allocate memory");
return result;
}
memcpy(utf8_char, ptr, char_len);
utf8_char[char_len] = '\0';
result.value.symbol = utf8_char;
result.status = STRING_OK;
SET_MSG(result, "Symbol successfully retrieved");
return result;
}
/**
* string_set_at
* @str: a non-null string
* @position: the position to write into
* @utf8_char: an UTF8 symbol
*
* Writes @utf8_char into @str at index @position
*
* Returns a string_result_t data type
*/
string_result_t string_set_at(const string_t *str, size_t position, const char *utf8_char) {
string_result_t result = {0};
if (str == NULL) {
result.status = STRING_ERR_INVALID;
SET_MSG(result, "Invalid string");
return result;
}
int new_char_bytes;
if (utf8_is_char_valid(utf8_char, &new_char_bytes) == 0) {
result.status = STRING_ERR_INVALID_UTF8;
SET_MSG(result, "Invalid UTF-8 character");
return result;
}
if (position >= str->char_count) {
result.status = STRING_ERR_OVERFLOW;
SET_MSG(result, "Index out of bounds");
return result;
}
// Locate the byte offset of the character to replace
const char *pos = str->data;
for (size_t idx = 0; idx < position; idx++) {
pos += utf8_char_len((unsigned char)*pos);
}
const size_t prefix_len = pos - str->data;
const int old_char_bytes = utf8_char_len((unsigned char)*pos);
const size_t suffix_len = str->byte_size - prefix_len - old_char_bytes;
const size_t new_total_bytes = prefix_len + new_char_bytes + suffix_len;
string_t *new_str = malloc(sizeof(string_t));
if (new_str == NULL) {
result.status = STRING_ERR_ALLOCATE;
SET_MSG(result, "Cannot allocate memory");
return result;
}
new_str->data = malloc(new_total_bytes + 1);
if (new_str->data == NULL) {
free(new_str);
result.status = STRING_ERR_ALLOCATE;
SET_MSG(result, "Cannot allocate memory");
return result;
}
// Copy prefix data from original string
memcpy(new_str->data, str->data, prefix_len);
// Copy the new character at requested index
memcpy(new_str->data + prefix_len, utf8_char, new_char_bytes);
// Copy suffix data from the original string by skipping the overwritten character
memcpy(new_str->data + prefix_len + new_char_bytes, pos + old_char_bytes, suffix_len);
new_str->data[new_total_bytes] = '\0';
new_str->byte_size = new_total_bytes;
new_str->byte_capacity = new_total_bytes + 1;
new_str->char_count = str->char_count;
result.status = STRING_OK;
result.value.string = new_str;
SET_MSG(result, "Symbol successfully set");
return result;
}
/**
* string_to_lower
* @str: a non-null string
*
* Converts a String to lowercase
*
* Returns a string_result_t containing a new string
*/
string_result_t string_to_lower(const string_t *str) {
string_result_t result = {0};
if (str == NULL) {
result.status = STRING_ERR_INVALID;
SET_MSG(result, "Invalid string");
return result;
}
char *buf = malloc(str->byte_capacity);
if (buf == NULL) {
result.status = STRING_ERR_ALLOCATE;
SET_MSG(result, "Cannot allocate memory");
return result;
}
const char *src = str->data;
char *dst = buf;
while (*src) {
int len;
uint32_t codepoint = utf8_decode(src, &len);
uint32_t lower = (codepoint >= 'A' && codepoint <= 'Z') ? codepoint + 32 : codepoint;
dst += utf8_encode(lower, dst);
src += len;
}
*dst = '\0';
result = string_new(buf);
free(buf);
SET_MSG(result, "String successfully converted to lowercase");
return result;
}
/**
* string_to_upper
* @str: a non-null string
*
* Converts a String to uppercase
*
* Returns a string_result_t containing a new string
*/
string_result_t string_to_upper(const string_t *str) {
string_result_t result = {0};
if (str == NULL) {
result.status = STRING_ERR_INVALID;
SET_MSG(result, "Invalid string");
return result;
}
char *buf = malloc(str->byte_capacity);
if (buf == NULL) {
result.status = STRING_ERR_ALLOCATE;
SET_MSG(result, "Cannot allocate memory");
return result;
}
const char *src = str->data;
char *dst = buf;
while (*src) {
int len;
uint32_t codepoint = utf8_decode(src, &len);
uint32_t upper = (codepoint >= 'a' && codepoint <= 'z') ? codepoint - 32 : codepoint;
dst += utf8_encode(upper, dst);
src += len;
}
*dst = '\0';
result = string_new(buf);
free(buf);
SET_MSG(result, "String successfully converted to uppercase");
return result;
}
/**
* string_reverse
* @str: a non-null string
*
* Reverses @str
*
* Returns a new string_result_t containing the reversed string
*/
string_result_t string_reverse(const string_t *str) {
string_result_t result = {0};
if (str == NULL) {
result.status = STRING_ERR_INVALID;
SET_MSG(result, "Invalid string");
return result;
}
char *buf = malloc(str->byte_capacity);
if (buf == NULL) {
result.status = STRING_ERR_ALLOCATE;
SET_MSG(result, "Cannot allocate memory");
return result;
}
const char **pos = malloc(str->char_count * sizeof(char *));
if (pos == NULL) {
free(buf);
result.status = STRING_ERR_ALLOCATE;
SET_MSG(result, "Cannot allocate memory");
return result;
}
const char *ptr = str->data;
for (size_t idx = 0; idx < str->char_count; idx++) {
pos[idx] = ptr;
ptr += utf8_char_len((unsigned char)*ptr);
}
char *dst = buf;
for (int64_t idx = (int64_t)str->char_count - 1; idx >= 0; idx--) {
int len = utf8_char_len((unsigned char)*pos[idx]);
memcpy(dst, pos[idx], len);
dst += len;
}
*dst = '\0';
free(pos);
result = string_new(buf);
free(buf);
SET_MSG(result, "String successfully reversed");
return result;
}