2022-10-27 15:16:54 -06:00
|
|
|
#include "arc/std/string.h"
|
|
|
|
|
|
2024-06-13 22:31:15 -06:00
|
|
|
#include "arc/std/bool.h"
|
2022-10-27 15:16:54 -06:00
|
|
|
#include "arc/std/errno.h"
|
2023-01-17 01:59:08 -07:00
|
|
|
#include <stdint.h>
|
2022-10-27 15:16:54 -06:00
|
|
|
#include <string.h>
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
|
2023-01-17 01:59:08 -07:00
|
|
|
void ARC_String_Create(ARC_String **string, char *data, uint64_t length){
|
|
|
|
|
*string = (ARC_String *)malloc(sizeof(ARC_String));
|
2024-06-13 22:31:15 -06:00
|
|
|
(*string)->data = (char *)malloc(sizeof(char) * (length + 1));
|
2023-01-17 01:59:08 -07:00
|
|
|
(*string)->length = length;
|
|
|
|
|
|
|
|
|
|
strncpy((*string)->data, data, length);
|
|
|
|
|
(*string)->data[length] = '\0';
|
|
|
|
|
}
|
|
|
|
|
|
2023-01-20 22:38:29 -07:00
|
|
|
void ARC_String_CreateWithStrlen(ARC_String **string, char *data){
|
|
|
|
|
*string = (ARC_String *)malloc(sizeof(ARC_String));
|
|
|
|
|
(*string)->length = strlen(data);
|
2024-06-13 22:31:15 -06:00
|
|
|
(*string)->data = (char *)malloc(sizeof(char) * ((*string)->length + 1));
|
2023-01-20 22:38:29 -07:00
|
|
|
|
|
|
|
|
strncpy((*string)->data, data, (*string)->length);
|
|
|
|
|
(*string)->data[(*string)->length] = '\0';
|
|
|
|
|
}
|
|
|
|
|
|
2023-01-17 01:59:08 -07:00
|
|
|
void ARC_String_Destroy(ARC_String *string){
|
2024-06-12 02:54:54 -06:00
|
|
|
if(string->data){
|
|
|
|
|
free(string->data);
|
|
|
|
|
}
|
2023-01-17 01:59:08 -07:00
|
|
|
free(string);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ARC_String_Copy(ARC_String **copy, ARC_String *original){
|
|
|
|
|
if(!original){
|
|
|
|
|
arc_errno = ARC_ERRNO_NULL;
|
|
|
|
|
*copy = NULL;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ARC_String_Create(copy, original->data, original->length);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ARC_String_CopySubstring(ARC_String **substring, ARC_String *original, uint64_t start, uint64_t length){
|
|
|
|
|
if(!original){
|
|
|
|
|
arc_errno = ARC_ERRNO_NULL;
|
|
|
|
|
*substring = NULL;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(length == 0){
|
|
|
|
|
*substring = NULL;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(start + length > original->length){
|
|
|
|
|
arc_errno = ARC_ERRNO_DATA;
|
|
|
|
|
*substring = NULL;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
char data[length];
|
|
|
|
|
for(uint32_t i = 0; i < length; i++){
|
|
|
|
|
data[i] = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
strncpy(data, original->data + start, length);
|
|
|
|
|
|
|
|
|
|
ARC_String_Create(substring, data, length);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ARC_String_RemoveSubstring(ARC_String **newString, ARC_String *original, ARC_String *substring){
|
|
|
|
|
uint64_t index = ARC_String_Find(original, substring);
|
|
|
|
|
if(arc_errno){
|
|
|
|
|
newString = NULL;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ARC_String_RemoveSection(newString, original, index, original->length);
|
|
|
|
|
}
|
|
|
|
|
|
2024-06-13 22:31:15 -06:00
|
|
|
ARC_Bool ARC_String_Equals(ARC_String *first, ARC_String *second){
|
2023-01-17 01:59:08 -07:00
|
|
|
if(first->length != second->length){
|
2024-06-13 22:31:15 -06:00
|
|
|
return ARC_False;
|
2023-01-17 01:59:08 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(strncmp(first->data, second->data, first->length)){
|
2024-06-13 22:31:15 -06:00
|
|
|
return ARC_False;
|
2023-01-17 01:59:08 -07:00
|
|
|
}
|
|
|
|
|
|
2024-06-13 22:31:15 -06:00
|
|
|
return ARC_True;
|
2023-01-17 01:59:08 -07:00
|
|
|
}
|
|
|
|
|
|
2024-06-13 22:31:15 -06:00
|
|
|
ARC_Bool ARC_String_EqualsCString(ARC_String *string, const char *cstring, uint64_t length){
|
2023-01-17 01:59:08 -07:00
|
|
|
if(string->length != length){
|
2024-06-13 22:31:15 -06:00
|
|
|
return ARC_False;
|
2023-01-17 01:59:08 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(strncmp(string->data, cstring, string->length)){
|
2024-06-13 22:31:15 -06:00
|
|
|
return ARC_False;
|
2023-01-17 01:59:08 -07:00
|
|
|
}
|
|
|
|
|
|
2024-06-13 22:31:15 -06:00
|
|
|
return ARC_True;
|
2023-01-17 01:59:08 -07:00
|
|
|
}
|
|
|
|
|
|
2024-06-13 22:31:15 -06:00
|
|
|
ARC_Bool ARC_String_EqualsCStringWithStrlen(ARC_String *string, const char *cstring){
|
2024-06-12 02:54:54 -06:00
|
|
|
return ARC_String_EqualsCString(string, cstring, strlen(cstring));
|
|
|
|
|
}
|
|
|
|
|
|
2024-06-13 22:31:15 -06:00
|
|
|
ARC_Bool ARC_String_SubstringEquals(ARC_String *first, uint64_t offset, ARC_String *second){
|
|
|
|
|
return ARC_String_SubstringEqualsCString(first, offset, second->data, second->length);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ARC_Bool ARC_String_SubstringEqualsCString(ARC_String *string, uint64_t offset, const char *cstring, uint64_t length){
|
2024-01-15 02:14:35 -07:00
|
|
|
if(string->length - offset < length){
|
2024-06-13 22:31:15 -06:00
|
|
|
return ARC_False;
|
2024-01-15 02:14:35 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(strncmp(string->data + offset, cstring, length)){
|
2024-06-13 22:31:15 -06:00
|
|
|
return ARC_False;
|
2024-01-15 02:14:35 -07:00
|
|
|
}
|
|
|
|
|
|
2024-06-13 22:31:15 -06:00
|
|
|
return ARC_True;
|
2024-01-15 02:14:35 -07:00
|
|
|
}
|
|
|
|
|
|
2023-01-17 01:59:08 -07:00
|
|
|
uint8_t ARC_String_Alpha(ARC_String *string){
|
|
|
|
|
for(uint64_t length = string->length; length; length--){
|
|
|
|
|
if(string->data[length - 1] >= 'a' && string->data[length - 1] <= 'z'){
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(string->data[length - 1] >= 'A' && string->data[length - 1] <= 'Z'){
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
2022-10-27 15:16:54 -06:00
|
|
|
return 1;
|
|
|
|
|
}
|
2023-01-17 01:59:08 -07:00
|
|
|
|
2022-10-27 15:16:54 -06:00
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2023-01-17 01:59:08 -07:00
|
|
|
uint64_t ARC_String_ToUint64_t(ARC_String *string){
|
2023-01-20 22:38:29 -07:00
|
|
|
return (uint64_t) strtoul(string->data, NULL, 10);
|
|
|
|
|
}
|
2022-10-27 15:16:54 -06:00
|
|
|
|
2023-01-20 22:38:29 -07:00
|
|
|
int64_t ARC_String_ToInt64_t(ARC_String *string){
|
|
|
|
|
return (int64_t) strtol(string->data, NULL, 10);
|
2022-10-27 15:16:54 -06:00
|
|
|
}
|
|
|
|
|
|
2023-01-20 22:38:29 -07:00
|
|
|
double ARC_String_ToDouble(ARC_String *string){
|
|
|
|
|
return strtod(string->data, NULL);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2023-01-17 01:59:08 -07:00
|
|
|
uint64_t ARC_String_Find(ARC_String *string, ARC_String *substring){
|
|
|
|
|
if(!string || !substring){
|
2024-01-15 02:14:35 -07:00
|
|
|
ARC_DEBUG_ERR("ARC_String_Find(string, substring), string or substring was null");
|
2023-01-17 01:59:08 -07:00
|
|
|
arc_errno = ARC_ERRNO_NULL;
|
|
|
|
|
return ~(uint64_t)0;
|
|
|
|
|
}
|
2022-10-27 15:16:54 -06:00
|
|
|
|
2023-01-17 01:59:08 -07:00
|
|
|
if(substring->length > string->length){
|
|
|
|
|
return ~(uint64_t)0;
|
|
|
|
|
}
|
2022-10-27 15:16:54 -06:00
|
|
|
|
2023-01-17 01:59:08 -07:00
|
|
|
uint64_t max = string->length - (substring->length - 1);
|
2022-10-27 15:16:54 -06:00
|
|
|
for(uint64_t i = 0; max; i++, max--){
|
2023-01-17 01:59:08 -07:00
|
|
|
if(!strncmp(string->data + i, substring->data, substring->length)){
|
2023-01-20 22:38:29 -07:00
|
|
|
return i;
|
2022-10-27 15:16:54 -06:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-01-17 01:59:08 -07:00
|
|
|
return ~(uint64_t)0;
|
2022-10-27 15:16:54 -06:00
|
|
|
}
|
|
|
|
|
|
2023-01-17 01:59:08 -07:00
|
|
|
uint64_t ARC_String_FindCString(ARC_String *string, const char *cstring, uint64_t length){
|
|
|
|
|
if(!string || !cstring){
|
|
|
|
|
arc_errno = ARC_ERRNO_NULL;
|
2024-01-15 02:14:35 -07:00
|
|
|
ARC_DEBUG_ERR("ARC_String_FindCString(string, cstring, length), string or cstring was null");
|
2023-01-17 01:59:08 -07:00
|
|
|
return ~(uint64_t)0;
|
|
|
|
|
}
|
2022-10-27 15:16:54 -06:00
|
|
|
|
2023-01-17 01:59:08 -07:00
|
|
|
if(string->length < length){
|
|
|
|
|
return ~(uint64_t)0;
|
|
|
|
|
}
|
2022-10-27 15:16:54 -06:00
|
|
|
|
2023-01-17 01:59:08 -07:00
|
|
|
uint64_t max = string->length - (length - 1);
|
|
|
|
|
for(uint64_t i = 0; i < max; i++){
|
|
|
|
|
if(!strncmp(string->data + i, cstring, length)){
|
|
|
|
|
return i + 1;
|
2022-10-27 15:16:54 -06:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-01-17 01:59:08 -07:00
|
|
|
return ~(uint64_t)0;
|
2022-10-27 15:16:54 -06:00
|
|
|
}
|
|
|
|
|
|
2024-06-12 02:54:54 -06:00
|
|
|
uint64_t ARC_String_FindCStringWithStrlen(ARC_String *string, const char *cstring){
|
|
|
|
|
return ARC_String_FindCString(string, cstring, strlen(cstring));
|
|
|
|
|
}
|
|
|
|
|
|
2023-01-17 01:59:08 -07:00
|
|
|
uint64_t ARC_String_FindBack(ARC_String *string, ARC_String *substring){
|
|
|
|
|
if(!string || !substring){
|
|
|
|
|
arc_errno = ARC_ERRNO_NULL;
|
2024-01-15 02:14:35 -07:00
|
|
|
ARC_DEBUG_ERR("ARC_String_FindBack(string, substring), string or substring was null");
|
2023-01-17 01:59:08 -07:00
|
|
|
return ~(uint64_t)0;
|
|
|
|
|
}
|
2022-10-27 15:16:54 -06:00
|
|
|
|
2023-01-17 01:59:08 -07:00
|
|
|
if(substring->length > string->length){
|
|
|
|
|
return ~(uint64_t)0;
|
|
|
|
|
}
|
2022-10-27 15:16:54 -06:00
|
|
|
|
2023-01-17 01:59:08 -07:00
|
|
|
uint64_t max = string->length - (substring->length - 1);
|
2022-10-27 15:16:54 -06:00
|
|
|
for(; max; max--){
|
2023-01-17 01:59:08 -07:00
|
|
|
if(!strncmp(string->data + (max - 1), substring->data, substring->length)){
|
|
|
|
|
return max;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ~(uint64_t)0;
|
|
|
|
|
}
|
|
|
|
|
|
2024-02-22 02:50:06 -07:00
|
|
|
uint64_t ARC_String_FindBackCString(ARC_String *string, const char *cstring, uint64_t length){
|
|
|
|
|
if(!string || !cstring){
|
|
|
|
|
arc_errno = ARC_ERRNO_NULL;
|
|
|
|
|
ARC_DEBUG_ERR("ARC_String_FindBack(string, substring), string or substring was null");
|
|
|
|
|
return ~(uint64_t)0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(length > string->length){
|
|
|
|
|
return ~(uint64_t)0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uint64_t max = string->length - (length - 1);
|
|
|
|
|
for(; max; max--){
|
|
|
|
|
if(!strncmp(string->data + (max - 1), cstring, length)){
|
|
|
|
|
return max;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ~(uint64_t)0;
|
|
|
|
|
}
|
|
|
|
|
|
2024-06-12 02:54:54 -06:00
|
|
|
uint64_t ARC_String_FindBackCStringWithStrlen(ARC_String *string, const char *cstring){
|
|
|
|
|
return ARC_String_FindBackCString(string, cstring, strlen(cstring));
|
|
|
|
|
}
|
|
|
|
|
|
2024-01-16 23:58:31 -07:00
|
|
|
void ARC_String_StripEnds(ARC_String **stripped, ARC_String *original, char charToStrip){
|
2023-01-17 01:59:08 -07:00
|
|
|
if(!original){
|
|
|
|
|
arc_errno = ARC_ERRNO_NULL;
|
|
|
|
|
*stripped = NULL;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(!original->length){
|
|
|
|
|
arc_errno = ARC_ERRNO_DATA;
|
|
|
|
|
*stripped = NULL;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uint64_t length = original->length - 1;
|
|
|
|
|
for(; length; length--){
|
|
|
|
|
if(strncmp(original->data + (length - 1), &charToStrip, 1)){
|
2022-10-27 15:16:54 -06:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-01-17 01:59:08 -07:00
|
|
|
if(!length){
|
|
|
|
|
arc_errno = ARC_ERRNO_DATA;
|
|
|
|
|
*stripped = NULL;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uint64_t start = 0;
|
|
|
|
|
for(; start <= length; start++){
|
|
|
|
|
if(strncmp(original->data + start, &charToStrip, 1)){
|
|
|
|
|
break;
|
2022-10-27 15:16:54 -06:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-01-17 01:59:08 -07:00
|
|
|
if(start == length){
|
|
|
|
|
arc_errno = ARC_ERRNO_DATA;
|
|
|
|
|
*stripped = NULL;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
length -= start;
|
|
|
|
|
ARC_String_Create(stripped, original->data + start, length);
|
2022-10-27 15:16:54 -06:00
|
|
|
}
|
|
|
|
|
|
2024-01-16 23:58:31 -07:00
|
|
|
void ARC_String_StripWhitespace(ARC_String **stripped, ARC_String *original){
|
2023-01-17 01:59:08 -07:00
|
|
|
if(!original){
|
|
|
|
|
arc_errno = ARC_ERRNO_NULL;
|
|
|
|
|
*stripped = NULL;
|
|
|
|
|
return;
|
|
|
|
|
}
|
2022-10-27 15:16:54 -06:00
|
|
|
|
2023-01-17 01:59:08 -07:00
|
|
|
if(!original->length){
|
|
|
|
|
arc_errno = ARC_ERRNO_DATA;
|
|
|
|
|
*stripped = NULL;
|
|
|
|
|
return;
|
|
|
|
|
}
|
2022-10-27 15:16:54 -06:00
|
|
|
|
2023-01-17 01:59:08 -07:00
|
|
|
uint64_t length = 0;
|
|
|
|
|
for(uint64_t i = 0; i < original->length; i++){
|
|
|
|
|
if(original->data[i] == ' '){
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(original->data[i] == '\n'){
|
|
|
|
|
continue;
|
2022-10-27 15:16:54 -06:00
|
|
|
}
|
2023-01-17 01:59:08 -07:00
|
|
|
|
|
|
|
|
if(original->data[i] == '\t'){
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(original->data[i] == '\r'){
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
length++;
|
2022-10-27 15:16:54 -06:00
|
|
|
}
|
|
|
|
|
|
2023-01-17 01:59:08 -07:00
|
|
|
if(!length){
|
|
|
|
|
arc_errno = ARC_ERRNO_DATA;
|
|
|
|
|
*stripped = NULL;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
length++;
|
|
|
|
|
char data[length];
|
|
|
|
|
for(uint32_t i = 0; i < length; i++){
|
|
|
|
|
data[i] = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uint64_t start = 0;
|
|
|
|
|
for(uint64_t i = 0; i < length; i++){
|
|
|
|
|
if(original->data[i] == ' '){
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(original->data[i] == '\n'){
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(original->data[i] == '\t'){
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(original->data[i] == '\r'){
|
|
|
|
|
continue;
|
2022-10-27 15:16:54 -06:00
|
|
|
}
|
2023-01-17 01:59:08 -07:00
|
|
|
|
|
|
|
|
data[start] = original->data[i];
|
|
|
|
|
start++;
|
2022-10-27 15:16:54 -06:00
|
|
|
}
|
|
|
|
|
|
2023-01-17 01:59:08 -07:00
|
|
|
ARC_String_Create(stripped, data, length);
|
2022-10-27 15:16:54 -06:00
|
|
|
}
|
2023-01-17 01:59:08 -07:00
|
|
|
|
2024-01-16 23:58:31 -07:00
|
|
|
void ARC_String_StripEndsWhitespace(ARC_String **stripped, ARC_String *original){
|
2023-01-17 01:59:08 -07:00
|
|
|
uint64_t index;
|
|
|
|
|
for(uint64_t i = 0; i < original->length; i++){
|
|
|
|
|
if(original->data[i] == ' '){
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(original->data[i] == '\n'){
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(original->data[i] == '\t'){
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(original->data[i] == '\r'){
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
index = i;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uint64_t endIndex;
|
2023-08-22 04:08:53 +00:00
|
|
|
for(uint64_t i = original->length;; i--){
|
2023-01-17 01:59:08 -07:00
|
|
|
if(original->data[i - 1] == ' '){
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(original->data[i - 1] == '\n'){
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(original->data[i - 1] == '\t'){
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(original->data[i - 1] == '\r'){
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
endIndex = i;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ARC_String_CopySubstring(stripped, original, index, endIndex - index);
|
|
|
|
|
}
|
|
|
|
|
|
2024-01-16 23:58:31 -07:00
|
|
|
void ARC_String_Merge(ARC_String **combined, ARC_String *first, ARC_String *second){
|
2023-01-17 01:59:08 -07:00
|
|
|
char data[first->length + second->length];
|
|
|
|
|
for(uint32_t i = 0; i < first->length; i++){
|
|
|
|
|
data[i] = first->data[i];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for(uint32_t i = 0; i < second->length; i++){
|
|
|
|
|
data[i + first->length] = second->data[i];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ARC_String_Create(combined, data, first->length + second->length);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void ARC_String_RemoveSection(ARC_String **newString, ARC_String *original, uint64_t removeIndex, uint64_t removeLength){
|
|
|
|
|
if(removeIndex == 0 && removeIndex + removeLength >= original->length){
|
|
|
|
|
ARC_String_Copy(newString, original);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(removeIndex == 0){
|
|
|
|
|
ARC_String_CopySubstring(newString, original, removeLength, original->length - removeLength);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(removeIndex + removeLength >= original->length){
|
|
|
|
|
ARC_String_CopySubstring(newString, original, 0, removeIndex);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ARC_String *first, *second;
|
|
|
|
|
ARC_String_CopySubstring(&first , original, 0 , removeIndex );
|
|
|
|
|
ARC_String_CopySubstring(&second, original, removeIndex + removeLength, original->length - (removeIndex + removeLength));
|
|
|
|
|
|
2024-01-16 23:58:31 -07:00
|
|
|
ARC_String_Merge(newString, first, second);
|
2023-01-17 01:59:08 -07:00
|
|
|
|
|
|
|
|
ARC_String_Destroy(first );
|
|
|
|
|
ARC_String_Destroy(second);
|
2024-06-13 22:31:15 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ARC_String_ReplaceMatching(ARC_String **string, ARC_String *pattern, ARC_String *replacement){
|
|
|
|
|
ARC_String *copyReplaced;
|
|
|
|
|
ARC_String_CopyReplaceMatching(©Replaced, *string, pattern, replacement);
|
|
|
|
|
|
|
|
|
|
if(arc_errno != 0 || copyReplaced == NULL){
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ARC_String_Destroy(*string);
|
|
|
|
|
*string = copyReplaced;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ARC_String_CopyReplaceMatching(ARC_String **newString, ARC_String *original, ARC_String *pattern, ARC_String *replacement){
|
|
|
|
|
//TODO: probs want to check if the replacement goes over a uint64_t size
|
|
|
|
|
if(original == NULL || pattern == NULL || replacement == NULL){
|
|
|
|
|
arc_errno = ARC_ERRNO_NULL;
|
|
|
|
|
ARC_DEBUG_ERR("ARC_String_CopyReplaceMatching(newString, original, pattern, replacement), original, pattern, or replacement was null");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uint64_t numberOfMatches = 0;
|
|
|
|
|
for(uint64_t originalIndex = 0; originalIndex < original->length; originalIndex++){
|
|
|
|
|
if(ARC_String_SubstringEquals(original, originalIndex, pattern)){
|
|
|
|
|
numberOfMatches++;
|
|
|
|
|
originalIndex += pattern->length - 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//no matches were found, but that isn't an error, so copy and return
|
|
|
|
|
if(numberOfMatches == 0){
|
|
|
|
|
ARC_String_Copy(newString, original);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
(*newString) = (ARC_String *)malloc(sizeof(ARC_String));
|
|
|
|
|
(*newString)->length = original->length + (replacement->length - pattern->length);
|
|
|
|
|
(*newString)->data = (char *)malloc(sizeof(char *) * original->length + 1);
|
|
|
|
|
|
|
|
|
|
for(uint64_t originalIndex = 0, newIndex = 0; originalIndex < original->length; originalIndex++, newIndex++){
|
|
|
|
|
if(ARC_String_SubstringEquals(original, originalIndex, pattern)){
|
|
|
|
|
for(uint64_t replacementIndex = 0; replacementIndex < replacement->length; replacementIndex++){
|
|
|
|
|
(*newString)->data[newIndex + replacementIndex] = replacement->data[replacementIndex];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
originalIndex += pattern->length - 1;
|
|
|
|
|
newIndex += replacement->length - 1;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
(*newString)->data[newIndex] = original->data[originalIndex];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
(*newString)->data[(*newString)->length] = '\0';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief replaces characters in string matching the given pattern
|
|
|
|
|
*
|
|
|
|
|
* @param string the string that will be modified, will discard changes and set arc_errno on fail
|
|
|
|
|
* @param patternCString the cstring pattern to replace in the string on match
|
|
|
|
|
* @param patternLength the lenght of the cstring pattern
|
|
|
|
|
* @param replacementCstring the cstring that will replace the matched pattern
|
|
|
|
|
* @param replacementLength the length of the cstring replacement
|
|
|
|
|
*/
|
|
|
|
|
void ARC_String_ReplaceMatchingCString(ARC_String **string, char *patternCString, uint64_t patternLength, char *replacementCString, uint64_t replacementLength){
|
|
|
|
|
//TODO: probs want to check if the replacement goes over a uint64_t size
|
|
|
|
|
if(*string == NULL || patternCString == NULL || replacementCString == NULL){
|
|
|
|
|
arc_errno = ARC_ERRNO_NULL;
|
|
|
|
|
ARC_DEBUG_ERR("ARC_String_ReplaceMatchingCString(string, patternCString, patternLength, replacementCString, replacementLength), *string, patternCString, or replacementCString was null");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ARC_String *original = *string;
|
|
|
|
|
|
|
|
|
|
uint64_t numberOfMatches = 0;
|
|
|
|
|
for(uint64_t originalIndex = 0; originalIndex < original->length; originalIndex++){
|
|
|
|
|
if(ARC_String_SubstringEqualsCString(original, originalIndex, patternCString, patternLength)){
|
|
|
|
|
numberOfMatches++;
|
|
|
|
|
originalIndex += patternLength - 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//no matches were found, but that isn't an error, so nothing to do, return
|
|
|
|
|
if(numberOfMatches == 0){
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
(*string) = (ARC_String *)malloc(sizeof(ARC_String));
|
|
|
|
|
(*string)->length = original->length + (replacementLength - patternLength);
|
|
|
|
|
(*string)->data = (char *)malloc(sizeof(char *) * original->length + 1);
|
|
|
|
|
|
|
|
|
|
for(uint64_t originalIndex = 0, newIndex = 0; originalIndex < original->length; originalIndex++, newIndex++){
|
|
|
|
|
if(ARC_String_SubstringEqualsCString(original, originalIndex, patternCString, patternLength)){
|
|
|
|
|
for(uint64_t replacementIndex = 0; replacementIndex < replacementLength; replacementIndex++){
|
|
|
|
|
(*string)->data[newIndex + replacementIndex] = replacementCString[replacementIndex];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
originalIndex += patternLength - 1;
|
|
|
|
|
newIndex += replacementLength - 1;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
(*string)->data[newIndex] = original->data[originalIndex];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
(*string)->data[(*string)->length] = '\0';
|
|
|
|
|
|
|
|
|
|
//cleanup
|
|
|
|
|
ARC_String_Destroy(original);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ARC_String_ReplaceMatchingCStringWithStrlen(ARC_String **string, char *patternCString, char *replacementCString){
|
|
|
|
|
ARC_String_ReplaceMatchingCString(string, patternCString, strlen(patternCString), replacementCString, strlen(replacementCString));
|
|
|
|
|
}
|
|
|
|
|
|