replacemnt functions in string, should be memory safe

This commit is contained in:
herbglitch 2024-06-13 22:31:15 -06:00
parent 4d7ba1cf4e
commit 19d6120871
2 changed files with 203 additions and 24 deletions

View file

@ -1,5 +1,6 @@
#include "arc/std/string.h"
#include "arc/std/bool.h"
#include "arc/std/errno.h"
#include <stdint.h>
#include <string.h>
@ -7,7 +8,7 @@
void ARC_String_Create(ARC_String **string, char *data, uint64_t length){
*string = (ARC_String *)malloc(sizeof(ARC_String));
(*string)->data = (char *)malloc(length + 1);
(*string)->data = (char *)malloc(sizeof(char) * (length + 1));
(*string)->length = length;
strncpy((*string)->data, data, length);
@ -17,7 +18,7 @@ void ARC_String_Create(ARC_String **string, char *data, uint64_t length){
void ARC_String_CreateWithStrlen(ARC_String **string, char *data){
*string = (ARC_String *)malloc(sizeof(ARC_String));
(*string)->length = strlen(data);
(*string)->data = (char *)malloc((*string)->length + 1);
(*string)->data = (char *)malloc(sizeof(char) * ((*string)->length + 1));
strncpy((*string)->data, data, (*string)->length);
(*string)->data[(*string)->length] = '\0';
@ -78,44 +79,48 @@ void ARC_String_RemoveSubstring(ARC_String **newString, ARC_String *original, AR
ARC_String_RemoveSection(newString, original, index, original->length);
}
uint8_t ARC_String_Equals(ARC_String *first, ARC_String *second){
ARC_Bool ARC_String_Equals(ARC_String *first, ARC_String *second){
if(first->length != second->length){
return 0;
return ARC_False;
}
if(strncmp(first->data, second->data, first->length)){
return 0;
return ARC_False;
}
return 1;
return ARC_True;
}
uint8_t ARC_String_EqualsCString(ARC_String *string, const char *cstring, uint64_t length){
ARC_Bool ARC_String_EqualsCString(ARC_String *string, const char *cstring, uint64_t length){
if(string->length != length){
return 0;
return ARC_False;
}
if(strncmp(string->data, cstring, string->length)){
return 0;
return ARC_False;
}
return 1;
return ARC_True;
}
uint8_t ARC_String_EqualsCStringWithStrlen(ARC_String *string, const char *cstring){
ARC_Bool ARC_String_EqualsCStringWithStrlen(ARC_String *string, const char *cstring){
return ARC_String_EqualsCString(string, cstring, strlen(cstring));
}
uint8_t ARC_String_SubstringEqualsCString(ARC_String *string, uint64_t offset, const char *cstring, uint64_t length){
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){
if(string->length - offset < length){
return 0;
return ARC_False;
}
if(strncmp(string->data + offset, cstring, length)){
return 0;
return ARC_False;
}
return 1;
return ARC_True;
}
uint8_t ARC_String_Alpha(ARC_String *string){
@ -439,4 +444,120 @@ void ARC_String_RemoveSection(ARC_String **newString, ARC_String *original, uint
ARC_String_Destroy(first );
ARC_String_Destroy(second);
}
}
void ARC_String_ReplaceMatching(ARC_String **string, ARC_String *pattern, ARC_String *replacement){
ARC_String *copyReplaced;
ARC_String_CopyReplaceMatching(&copyReplaced, *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));
}