replacemnt functions in string, should be memory safe
This commit is contained in:
parent
4d7ba1cf4e
commit
19d6120871
2 changed files with 203 additions and 24 deletions
|
|
@ -6,6 +6,7 @@ extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include "bool.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief substring position within a string
|
* @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 first string to check against second
|
||||||
* @param second string to check against first
|
* @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
|
* @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 cstring cstring to check
|
||||||
* @param length length of cstring
|
* @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
|
* @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 string ARC_string to check
|
||||||
* @param cstring cstring 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
|
* @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 cstring cstring to check
|
||||||
* @param length length of cstring
|
* @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
|
* @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);
|
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
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
151
src/std/string.c
151
src/std/string.c
|
|
@ -1,5 +1,6 @@
|
||||||
#include "arc/std/string.h"
|
#include "arc/std/string.h"
|
||||||
|
|
||||||
|
#include "arc/std/bool.h"
|
||||||
#include "arc/std/errno.h"
|
#include "arc/std/errno.h"
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
@ -7,7 +8,7 @@
|
||||||
|
|
||||||
void ARC_String_Create(ARC_String **string, char *data, uint64_t length){
|
void ARC_String_Create(ARC_String **string, char *data, uint64_t length){
|
||||||
*string = (ARC_String *)malloc(sizeof(ARC_String));
|
*string = (ARC_String *)malloc(sizeof(ARC_String));
|
||||||
(*string)->data = (char *)malloc(length + 1);
|
(*string)->data = (char *)malloc(sizeof(char) * (length + 1));
|
||||||
(*string)->length = length;
|
(*string)->length = length;
|
||||||
|
|
||||||
strncpy((*string)->data, data, 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){
|
void ARC_String_CreateWithStrlen(ARC_String **string, char *data){
|
||||||
*string = (ARC_String *)malloc(sizeof(ARC_String));
|
*string = (ARC_String *)malloc(sizeof(ARC_String));
|
||||||
(*string)->length = strlen(data);
|
(*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);
|
strncpy((*string)->data, data, (*string)->length);
|
||||||
(*string)->data[(*string)->length] = '\0';
|
(*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);
|
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){
|
if(first->length != second->length){
|
||||||
return 0;
|
return ARC_False;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(strncmp(first->data, second->data, first->length)){
|
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){
|
if(string->length != length){
|
||||||
return 0;
|
return ARC_False;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(strncmp(string->data, cstring, string->length)){
|
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));
|
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){
|
if(string->length - offset < length){
|
||||||
return 0;
|
return ARC_False;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(strncmp(string->data + offset, cstring, length)){
|
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){
|
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(first );
|
||||||
ARC_String_Destroy(second);
|
ARC_String_Destroy(second);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue