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

@ -6,6 +6,7 @@ extern "C" {
#endif
#include <stdint.h>
#include "bool.h"
/**
* @brief substring position within a string
@ -72,9 +73,9 @@ void ARC_String_RemoveSubstring(ARC_String **newString, ARC_String *original, AR
* @param first string to check against second
* @param second string to check against first
*
* @return 1 if match, 0 if they don't match
* @return ARC_True if match, ARC_False if they don't match
*/
uint8_t ARC_String_Equals(ARC_String *first, ARC_String *second);
ARC_Bool ARC_String_Equals(ARC_String *first, ARC_String *second);
/**
* @brief check if ARC_String and cstring match
@ -83,9 +84,9 @@ uint8_t ARC_String_Equals(ARC_String *first, ARC_String *second);
* @param cstring cstring to check
* @param length length of cstring
*
* @return 1 if match, 0 if they don't match
* @return ARC_True if match, ARC_False if they don't match
*/
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);
/**
* @brief check if ARC_String and cstring match
@ -95,9 +96,20 @@ uint8_t ARC_String_EqualsCString(ARC_String *string, const char *cstring, uint64
* @param string ARC_string to check
* @param cstring cstring to check
*
* @return 1 if match, 0 if they don't match
* @return ARC_True if match, ARC_False if they don't match
*/
uint8_t ARC_String_EqualsCStringWithStrlen(ARC_String *string, const char *cstring);
ARC_Bool ARC_String_EqualsCStringWithStrlen(ARC_String *string, const char *cstring);
/**
* @brief check if substring of first equals second string
*
* @param first string to check against second
* @param offset postion based on first to start comparing against second
* @param second string to check against first
*
* @return ARC_True if match, ARC_False if they don't match
*/
ARC_Bool ARC_String_SubstringEquals(ARC_String *first, uint64_t offset, ARC_String *second);
/**
* @brief check if ARC_String and cstring match
@ -107,9 +119,9 @@ uint8_t ARC_String_EqualsCStringWithStrlen(ARC_String *string, const char *cstri
* @param cstring cstring to check
* @param length length of cstring
*
* @return 1 if match, 0 if they don't match
* @return ARC_True if match, ARC_False if they don't match
*/
uint8_t ARC_String_SubstringEqualsCString(ARC_String *string, uint64_t offset, const char *cstring, uint64_t length);
ARC_Bool ARC_String_SubstringEqualsCString(ARC_String *string, uint64_t offset, const char *cstring, uint64_t length);
/**
* @brief checks if string is alphabetic
@ -260,6 +272,52 @@ void ARC_String_Merge(ARC_String **combined, ARC_String *first, ARC_String *seco
*/
void ARC_String_RemoveSection(ARC_String **newString, ARC_String *original, uint64_t removeIndex, uint64_t removeLength);
/**
* @brief replaces characters in string matching the given pattern
*
* @note this uses ARC_String_CopyReplaceMatching, so debug logs will be thrown in that function not this one
*
* @param string the string that will be modified, will discard changes and set arc_errno on fail
* @param pattern the pattern to replace in the string on match
* @param replacement the string that will replace the matched pattern
*/
void ARC_String_ReplaceMatching(ARC_String **string, ARC_String *pattern, ARC_String *replacement);
/**
* @brief replaces characters in a copy of a string matching the given pattern
*
* @note original will not be modified
* @note newString will need to be destroyed if it is not set to NULL
*
* @param newString an empty string that this function will fill with a copy with replacements, will be set to NULL and arc_errno set on fail
* @param original the original string that will be copied
* @param pattern the pattern to replace in the string on match
* @param replacement the string that will replace the matched pattern
*/
void ARC_String_CopyReplaceMatching(ARC_String **newString, ARC_String *original, ARC_String *pattern, ARC_String *replacement);
/**
* @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);
/**
* @brief replaces characters in string matching the given pattern
*
* @note this uses ARC_String_ReplaceMatchingCString, so debug logs will be thrown in that function not this one
*
* @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 replacementCstring the cstring that will replace the matched pattern
*/
void ARC_String_ReplaceMatchingCStringWithStrlen(ARC_String **string, char *patternCString, char *replacement);
#ifdef __cplusplus
}
#endif

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){
@ -440,3 +445,119 @@ 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));
}