Loading...
Searching...
No Matches
string.c
Go to the documentation of this file.
#include "arc/std/string.h"
#include "arc/std/bool.h"
#include "arc/std/errno.h"
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
void ARC_String_Create(ARC_String **string, char *data, uint64_t length){
//check if the size is too big to create and error if so
if(length == ~(uint64_t)0){
arc_errno = ARC_ERRNO_OVERFLOW;
ARC_DEBUG_LOG_ERROR("ARC_String_Create(string, data, length), length was max uint64_t which is bigger than allowed");
*string = NULL;
return;
}
//create the string container and malloc the char array (this will allways be bigger than zero so there will be no issue if zero is passed in)
*string = (ARC_String *)malloc(sizeof(ARC_String));
(*string)->data = (char *)malloc(sizeof(char) * (length + 1));
(*string)->length = length;
//if the string has a size, copy the string
if(length > 0){
strncpy((*string)->data, data, length);
}
//set the end of the string to \0 (to mirror how cstrings work)
(*string)->data[length] = '\0';
}
void ARC_String_CreateWithStrlen(ARC_String **string, char *data){
//create the string passing in the strlen of data for the length
ARC_String_Create(string, data, strlen(data));
}
void ARC_String_CreateEmpty(ARC_String **string, uint64_t length){
//check if the size is too big to create and error if so
if(length == ~(uint64_t)0){
arc_errno = ARC_ERRNO_OVERFLOW;
ARC_DEBUG_LOG_ERROR("ARC_String_Create(string, data, length), length was max uint64_t which is bigger than allowed");
*string = NULL;
return;
}
//create the string container and initialize data with all 0s for the size
*string = (ARC_String *)malloc(sizeof(ARC_String));
(*string)->data = (char *)calloc(sizeof(char), length + 1);
(*string)->length = length;
}
void ARC_String_Destroy(ARC_String *string){
//check if the string's data exists and if so free it
if(string->data != NULL){
free(string->data);
}
//free the string itself
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_ReplaceWithSubstring(ARC_String **string, uint64_t start, uint64_t length){
ARC_String *substring;
ARC_String_CopySubstring(&substring, *string, start, length);
//if error or substring is null free memory and return
if(arc_errno || substring == NULL){
if(substring != NULL){
ARC_String_Destroy(substring);
}
return;
}
ARC_String_Destroy(*string);
*string = substring;
}
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);
}
void ARC_String_Append(ARC_String **string, ARC_String *append){
ARC_String_AppendCString(string, append->data, append->length);
}
void ARC_String_AppendCString(ARC_String **string, const char *cstring, uint64_t length){
char *data = (char *)malloc(sizeof(char) * ((*string)->length + length + 1));
strncpy(data, (*string)->data, (*string)->length);
strncpy(data + (*string)->length, cstring, length);
data[(*string)->length + length] = '\0';
free((*string)->data);
(*string)->data = data;
(*string)->length = (*string)->length + length;
}
void ARC_String_AppendCStringWithStrlen(ARC_String **string, const char *cstring){
ARC_String_AppendCString(string, cstring, strlen(cstring));
}
ARC_Bool ARC_String_Equals(ARC_String *first, ARC_String *second){
if(first->length != second->length){
return ARC_False;
}
if(strncmp(first->data, second->data, first->length)){
return ARC_False;
}
return ARC_True;
}
ARC_Bool ARC_String_EqualsCString(ARC_String *string, const char *cstring, uint64_t length){
if(string->length != length){
return ARC_False;
}
if(strncmp(string->data, cstring, string->length)){
return ARC_False;
}
return ARC_True;
}
ARC_Bool ARC_String_EqualsCStringWithStrlen(ARC_String *string, const char *cstring){
return ARC_String_EqualsCString(string, cstring, strlen(cstring));
}
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 ARC_False;
}
if(strncmp(string->data + offset, cstring, length)){
return ARC_False;
}
return ARC_True;
}
//TODO: fix this
ARC_Bool ARC_String_IsAlpha(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;
}
return ARC_True;
}
return ARC_False;
}
ARC_Bool ARC_String_IsNumeric(ARC_String *string){
for(uint64_t index = 0; index < string->length; index++){
if(string->data[index] < '0' || string->data[index] > '9'){
return ARC_False;
}
}
return ARC_True;
}
uint64_t ARC_String_ToUint64_t(ARC_String *string){
return (uint64_t) strtoul(string->data, NULL, 10);
}
int64_t ARC_String_ToInt64_t(ARC_String *string){
return (int64_t) strtol(string->data, NULL, 10);
}
double ARC_String_ToDouble(ARC_String *string){
return strtod(string->data, NULL);
}
uint64_t ARC_String_Find(ARC_String *string, ARC_String *substring){
if(!string || !substring){
ARC_DEBUG_LOG_ERROR("ARC_String_Find(string, substring), string or substring was null");
arc_errno = ARC_ERRNO_NULL;
return ~(uint64_t)0;
}
if(substring->length > string->length){
return ~(uint64_t)0;
}
uint64_t max = string->length - (substring->length - 1);
for(uint64_t i = 0; max; i++, max--){
if(!strncmp(string->data + i, substring->data, substring->length)){
return i;
}
}
return ~(uint64_t)0;
}
uint64_t ARC_String_FindCString(ARC_String *string, const char *cstring, uint64_t length){
if(!string || !cstring){
arc_errno = ARC_ERRNO_NULL;
ARC_DEBUG_LOG_ERROR("ARC_String_FindCString(string, cstring, length), string or cstring was null");
return ~(uint64_t)0;
}
if(string->length < length){
return ~(uint64_t)0;
}
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;
}
}
return ~(uint64_t)0;
}
uint64_t ARC_String_FindCStringWithStrlen(ARC_String *string, const char *cstring){
return ARC_String_FindCString(string, cstring, strlen(cstring));
}
uint64_t ARC_String_FindBack(ARC_String *string, ARC_String *substring){
if(!string || !substring){
arc_errno = ARC_ERRNO_NULL;
ARC_DEBUG_LOG_ERROR("ARC_String_FindBack(string, substring), string or substring was null");
return ~(uint64_t)0;
}
if(substring->length > string->length){
return ~(uint64_t)0;
}
uint64_t max = string->length - (substring->length - 1);
for(; max; max--){
if(!strncmp(string->data + (max - 1), substring->data, substring->length)){
return max;
}
}
return ~(uint64_t)0;
}
uint64_t ARC_String_FindBackCString(ARC_String *string, const char *cstring, uint64_t length){
if(!string || !cstring){
arc_errno = ARC_ERRNO_NULL;
ARC_DEBUG_LOG_ERROR("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;
}
uint64_t ARC_String_FindBackCStringWithStrlen(ARC_String *string, const char *cstring){
return ARC_String_FindBackCString(string, cstring, strlen(cstring));
}
void ARC_String_StripEnds(ARC_String **stripped, ARC_String *original, char charToStrip){
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)){
break;
}
}
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;
}
}
if(start == length){
arc_errno = ARC_ERRNO_DATA;
*stripped = NULL;
return;
}
length -= start;
ARC_String_Create(stripped, original->data + start, length);
}
void ARC_String_StripWhitespace(ARC_String **stripped, ARC_String *original){
if(!original){
arc_errno = ARC_ERRNO_NULL;
*stripped = NULL;
return;
}
if(!original->length){
arc_errno = ARC_ERRNO_DATA;
*stripped = NULL;
return;
}
uint64_t length = 0;
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;
}
length++;
}
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;
}
data[start] = original->data[i];
start++;
}
ARC_String_Create(stripped, data, length);
}
void ARC_String_StripEndsWhitespace(ARC_String **stripped, ARC_String *original){
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;
for(uint64_t i = original->length;; i--){
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);
}
void ARC_String_Merge(ARC_String **combined, ARC_String *first, ARC_String *second){
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));
ARC_String_Merge(newString, first, second);
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_LOG_ERROR("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';
}
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_LOG_ERROR("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));
}
bool.h
ARC_False
#define ARC_False
Definition bool.h:12
ARC_True
#define ARC_True
Definition bool.h:11
ARC_Bool
#define ARC_Bool
Definition bool.h:10
errno.h
arc_errno
int32_t arc_errno
Definition errno.c:5
ARC_ERRNO_OVERFLOW
#define ARC_ERRNO_OVERFLOW
Definition errno.h:10
ARC_ERRNO_NULL
#define ARC_ERRNO_NULL
Definition errno.h:6
ARC_DEBUG_LOG_ERROR
#define ARC_DEBUG_LOG_ERROR(STR)
Definition errno.h:39
ARC_ERRNO_DATA
#define ARC_ERRNO_DATA
Definition errno.h:7
ARC_String_ToUint64_t
uint64_t ARC_String_ToUint64_t(ARC_String *string)
converst substring from string to uint64_t
Definition string.c:218
ARC_String_StripEndsWhitespace
void ARC_String_StripEndsWhitespace(ARC_String **stripped, ARC_String *original)
strips the whitespace from the ends of a string
Definition string.c:437
ARC_String_RemoveSubstring
void ARC_String_RemoveSubstring(ARC_String **newString, ARC_String *original, ARC_String *substring)
copy a subtring from a givin ARC_String
Definition string.c:116
ARC_String_ToInt64_t
int64_t ARC_String_ToInt64_t(ARC_String *string)
converst substring from string to int64_t
Definition string.c:222
ARC_String_AppendCStringWithStrlen
void ARC_String_AppendCStringWithStrlen(ARC_String **string, const char *cstring)
appends to an ARC_String with an ARC_String
Definition string.c:143
ARC_String_Merge
void ARC_String_Merge(ARC_String **combined, ARC_String *first, ARC_String *second)
merges two strings together
Definition string.c:485
ARC_String_FindCStringWithStrlen
uint64_t ARC_String_FindCStringWithStrlen(ARC_String *string, const char *cstring)
takes given cstring and gives position of first matching
Definition string.c:273
ARC_String_EqualsCString
ARC_Bool ARC_String_EqualsCString(ARC_String *string, const char *cstring, uint64_t length)
check if ARC_String and cstring match
Definition string.c:159
ARC_String_CopySubstring
void ARC_String_CopySubstring(ARC_String **substring, ARC_String *original, uint64_t start, uint64_t length)
copy a subtring from a givin ARC_String
Definition string.c:72
ARC_String_FindBack
uint64_t ARC_String_FindBack(ARC_String *string, ARC_String *substring)
takes a given string, and assigns index and length for position of last matching substring
Definition string.c:277
ARC_String_FindBackCStringWithStrlen
uint64_t ARC_String_FindBackCStringWithStrlen(ARC_String *string, const char *cstring)
takes a given cstring and give position of last matching
Definition string.c:319
ARC_String_CreateWithStrlen
void ARC_String_CreateWithStrlen(ARC_String **string, char *data)
creates ARC_String type with strinlen
Definition string.c:32
ARC_String_AppendCString
void ARC_String_AppendCString(ARC_String **string, const char *cstring, uint64_t length)
appends to an ARC_String with an ARC_String
Definition string.c:130
ARC_String_Create
void ARC_String_Create(ARC_String **string, char *data, uint64_t length)
creates ARC_String type
Definition string.c:9
ARC_String_CopyReplaceMatching
void ARC_String_CopyReplaceMatching(ARC_String **newString, ARC_String *original, ARC_String *pattern, ARC_String *replacement)
replaces characters in a copy of a string matching the given pattern
Definition string.c:537
ARC_String_FindBackCString
uint64_t ARC_String_FindBackCString(ARC_String *string, const char *cstring, uint64_t length)
takes a given cstring and give position of last matching
Definition string.c:298
ARC_String_EqualsCStringWithStrlen
ARC_Bool ARC_String_EqualsCStringWithStrlen(ARC_String *string, const char *cstring)
check if ARC_String and cstring match
Definition string.c:171
ARC_String_Copy
void ARC_String_Copy(ARC_String **copy, ARC_String *original)
copy a ARC_String
Definition string.c:62
ARC_String_ReplaceMatchingCStringWithStrlen
void ARC_String_ReplaceMatchingCStringWithStrlen(ARC_String **string, char *patternCString, char *replacementCString)
replaces characters in string matching the given pattern
Definition string.c:627
ARC_String_SubstringEquals
ARC_Bool ARC_String_SubstringEquals(ARC_String *first, uint64_t offset, ARC_String *second)
check if substring of first equals second string
Definition string.c:175
ARC_String_Append
void ARC_String_Append(ARC_String **string, ARC_String *append)
appends to an ARC_String with an ARC_String
Definition string.c:126
ARC_String_SubstringEqualsCString
ARC_Bool ARC_String_SubstringEqualsCString(ARC_String *string, uint64_t offset, const char *cstring, uint64_t length)
check if ARC_String and cstring match
Definition string.c:179
ARC_String_FindCString
uint64_t ARC_String_FindCString(ARC_String *string, const char *cstring, uint64_t length)
takes given cstring and gives position of first matching
Definition string.c:252
ARC_String_CreateEmpty
void ARC_String_CreateEmpty(ARC_String **string, uint64_t length)
creates an empty ARC_String type, useful if you want to add to the string over time without having to...
Definition string.c:37
ARC_String_StripWhitespace
void ARC_String_StripWhitespace(ARC_String **stripped, ARC_String *original)
strips whitespace from a ARC_String
Definition string.c:366
ARC_String_Equals
ARC_Bool ARC_String_Equals(ARC_String *first, ARC_String *second)
checks if two strings are the same
Definition string.c:147
ARC_String_IsAlpha
ARC_Bool ARC_String_IsAlpha(ARC_String *string)
checks if string is alphabetic
Definition string.c:192
ARC_String_Destroy
void ARC_String_Destroy(ARC_String *string)
destroys ARC_String type
Definition string.c:52
ARC_String_Find
uint64_t ARC_String_Find(ARC_String *string, ARC_String *substring)
takes a given string, and assigns index and length for position of first matching substring
Definition string.c:231
ARC_String_ReplaceMatchingCString
void ARC_String_ReplaceMatchingCString(ARC_String **string, char *patternCString, uint64_t patternLength, char *replacementCString, uint64_t replacementLength)
replaces characters in string matching the given pattern
Definition string.c:580
ARC_String_ToDouble
double ARC_String_ToDouble(ARC_String *string)
converst substring from string to double
Definition string.c:226
ARC_String_ReplaceWithSubstring
void ARC_String_ReplaceWithSubstring(ARC_String **string, uint64_t start, uint64_t length)
replaces a string with a section of itself
Definition string.c:100
ARC_String_StripEnds
void ARC_String_StripEnds(ARC_String **stripped, ARC_String *original, char charToStrip)
strips the ends based on a given char
Definition string.c:323
ARC_String_RemoveSection
void ARC_String_RemoveSection(ARC_String **newString, ARC_String *original, uint64_t removeIndex, uint64_t removeLength)
copy a subtring from a givin ARC_String
Definition string.c:499
ARC_String_IsNumeric
ARC_Bool ARC_String_IsNumeric(ARC_String *string)
checks if string is made out of only numbers
Definition string.c:208
ARC_String_ReplaceMatching
void ARC_String_ReplaceMatching(ARC_String **string, ARC_String *pattern, ARC_String *replacement)
replaces characters in string matching the given pattern
Definition string.c:525
string.h
ARC_String
substring position within a string
Definition string.h:14
ARC_String::length
uint64_t length
Definition string.h:16
ARC_String::data
char * data
Definition string.h:15