rewrite of cptr functions

This commit is contained in:
Timerix22 2023-05-27 22:05:25 +06:00
parent 3a408735fb
commit 176cdb2d62
5 changed files with 342 additions and 87 deletions

View File

@ -86,7 +86,7 @@ Unitype* Hashtable_getPtr(Hashtable* ht, char* key){
u32 arlen=Autoarr_length(ar); u32 arlen=Autoarr_length(ar);
for(u32 i=0;i<arlen;i++){ for(u32 i=0;i<arlen;i++){
KVPair* p=Autoarr_getPtr(ar,i); KVPair* p=Autoarr_getPtr(ar,i);
if(cptr_compare(key,p->key)) return &p->value; if(cptr_equals(key,p->key)) return &p->value;
} }
return NULL; return NULL;
} }
@ -96,7 +96,7 @@ Unitype Hashtable_get(Hashtable* ht, char* key){
u32 arlen=Autoarr_length(ar); u32 arlen=Autoarr_length(ar);
for(u32 i=0;i<arlen;i++){ for(u32 i=0;i<arlen;i++){
KVPair p=Autoarr_get(ar,i); KVPair p=Autoarr_get(ar,i);
if(cptr_compare(key,p.key)) return p.value; if(cptr_equals(key,p.key)) return p.value;
} }
return UniNull; return UniNull;
} }

View File

@ -1,15 +1,17 @@
#include "base.h" #include "base.h"
#include "../String/StringBuilder.h"
#include <ctype.h> #include <ctype.h>
// returns length of char buffer (without \0) // returns length of char buffer (without \0)
u32 cptr_length(char* str){ u32 cptr_length(const char* str){
u32 len=0; const char *const str_first=str;
while(*(str++)) len++; while(*str)
return len; str++;
return str-str_first;
} }
// allocates new char[] and copies src there // allocates new char[] and copies src there
char* cptr_copy(char* src){ char* cptr_copy(const char* src){
u32 len=cptr_length(src)+1; u32 len=cptr_length(src)+1;
char* dst=malloc(len); char* dst=malloc(len);
while(len--!=0) while(len--!=0)
@ -17,16 +19,6 @@ char* cptr_copy(char* src){
return dst; return dst;
} }
// compares two char buffers, NullPtr-friendly
bool cptr_compare(char* key0, char* key1){
if(!key0) return key1 ? false : true;
if(!key1) return false;
while(*key0&&*key1)
if(*key0++ != *key1++)
return false;
return true;
}
// multiplies char n times // multiplies char n times
char* char_multiply(char c, u32 n){ char* char_multiply(char c, u32 n){
char* rez=malloc(n+1); char* rez=malloc(n+1);
@ -36,64 +28,106 @@ char* char_multiply(char c, u32 n){
return rez; return rez;
} }
bool cptr_startsWith(char* ptr, char* fragment){ bool cptr_equals(const char* key0, const char* key1){
for(char cs=*ptr, cf=*fragment; cf; cs=*++ptr, cf=*++fragment) char c0=*key0;
if(cs!=cf) return false; char c1=*key1;
return true; bool eq=c0==c1;
while(c0 && c1 && eq) {
c0=*++key0;
c1=*++key1;
eq=c0==c1;
}
return eq;
} }
bool cptr_endsWith(char* ptr, char* fragment){ bool cptr_startsWith(const char* src, const char* fragment){
ptr+=cptr_length(ptr)-cptr_length(fragment); char c0=*src;
for(char cs=*ptr, cf=*fragment; cf; cs=*++ptr, cf=*++fragment) char c1=*fragment;
if(cs!=cf) return false; bool eq=c0==c1 && c0 !=0 && c1!=0;
while(c0 && c1 && eq) {
c0=*++src;
c1=*++fragment;
eq=c0==c1;
if(c1==0)
return true; return true;
} }
return eq;
}
u32 cptr_indexOf(char* ptr, char* fragment){ bool cptr_endsWith(const char* src, const char* fragment){
char sc=*ptr; u32 src_len=cptr_length(src);
for(u32 si=0, fi=0; sc!='\0'; si++){ u32 fr_len=cptr_length(fragment);
sc=ptr[si]; if(src_len<fr_len || src_len==0 || fr_len==0)
if(sc==fragment[fi]){ return false;
fi++; src+=src_len-fr_len;
if(fragment[fi]==0) return cptr_equals(src, fragment);
return si-fi+1;
} }
else fi=0;
i32 cptr_seek(const char* src, const char* fragment, u32 startIndex, u32 seekLength){
char sc=*src, fc=*fragment;
if(sc==0 || fc==0)
return -1;
u32 fr_start=startIndex;
for(u32 si=startIndex; si-startIndex<seekLength && sc!=0; si++){
sc=src[si];
fc=fragment[si-fr_start];
if(fc==0)
return fr_start;
if(sc!=fc)
fr_start++;
} }
return -1; return -1;
} }
u32 cptr_indexOfChar(char* ptr, char fragment){
char sc=*ptr; i32 cptr_seekReverse(const char* src, const char* fragment, u32 startIndex, u32 seekLength){
for(u32 si=0; sc!='\0'; si++){ char sc=*src, fc=*fragment;
sc=ptr[si]; if(sc==0 || fc==0)
if(sc==fragment){ return -1;
return si; i32 len=cptr_length(src);
if(startIndex==(u32)-1)
startIndex=len-1;
u32 fr_len=cptr_length(fragment);
for(u32 si=startIndex; si<(u32)-1 && si!=len-1-seekLength; si--){
if(si+1<fr_len)
return -1;
sc=src[si];
fc=fragment[0];
u32 fr_start=si;
for(u32 fi=0; fc==sc ; fi++){
if(fi==fr_len)
return fr_start;
fc=fragment[fi];
sc=src[si--];
} }
} }
return -1; return -1;
} }
u32 cptr_lastIndexOf(char* ptr, char* fragment){
char sc; i32 cptr_seekChar(const char* src, char fragment, u32 startIndex, u32 seekLength){
u32 fi_last=cptr_length(fragment)-1; char sc=*src;
for(i32 si=cptr_length(ptr)-1, fi=fi_last; si>=0; si--){ if(sc==0 || fragment==0)
sc=ptr[si]; return -1;
if(sc==fragment[fi]){ for(u32 si=startIndex; si-startIndex<seekLength && sc!=0; si++){
if(fi==0) sc=src[si];
if(sc==fragment)
return si; return si;
fi--;
}
else fi=fi_last;
} }
return -1; return -1;
} }
u32 cptr_lastIndexOfChar(char* ptr, char fragment){
char sc; i32 cptr_seekCharReverse(const char* src, char fragment, u32 startIndex, u32 seekLength){
for(i32 si=cptr_length(ptr)-1; si>=0; si--){ char sc=*src;
sc=ptr[si]; if(sc==0 || fragment==0)
if(sc==fragment){ return -1;
i32 len=cptr_length(src);
if(startIndex==(u32)-1)
startIndex=len-1;
for(u32 si=startIndex; si<(u32)-1 && si!=len-1-seekLength; si--){
sc=src[si];
if(sc==fragment)
return si; return si;
} }
}
return -1; return -1;
} }
@ -123,7 +157,7 @@ char* __cptr_concat(u32 n, ...){
// allocating memory for output value // allocating memory for output value
char* totality=malloc(totalLength+1); char* totality=malloc(totalLength+1);
const char* output=totality; char* output=totality;
totality[totalLength]=0; totality[totalLength]=0;
// copying content of all strings to rezult // copying content of all strings to rezult
@ -137,7 +171,7 @@ char* __cptr_concat(u32 n, ...){
return output; return output;
} }
char* cptr_toLower(char* src) { char* cptr_toLower(const char* src) {
u32 length=cptr_length(src); u32 length=cptr_length(src);
char *p=malloc(length+1); char *p=malloc(length+1);
p[length]=0; p[length]=0;
@ -146,7 +180,7 @@ char* cptr_toLower(char* src) {
return p; return p;
} }
char* cptr_toUpper(char* src) { char* cptr_toUpper(const char* src) {
u32 length=cptr_length(src); u32 length=cptr_length(src);
char *p=malloc(length+1); char *p=malloc(length+1);
p[length]=0; p[length]=0;
@ -154,3 +188,28 @@ char* cptr_toUpper(char* src) {
p[i]=toupper(src[i]); p[i]=toupper(src[i]);
return p; return p;
} }
char* cptr_replaceChar(const char* src, char c_old, char c_new, u32 startIndex, u32 seekLength){
char* rzlt=cptr_copy(src);
char c=*src;
for(u32 i=startIndex; i<seekLength && c!=0; i++, src++){
if(c==c_old)
*rzlt=c_new;
}
return rzlt;
}
char* cptr_replace(const char* src, char* str_old, char* str_new, u32 startIndex, u32 seekLength){
StringBuilder* sb=StringBuilder_create();
const u32 str_old_len=cptr_length(str_old);
const u32 str_new_len=cptr_length(str_new);
i32 i=startIndex;
while( (i=cptr_seek(src, str_old, i, -1)) !=-1 ){
if(i!=0)
StringBuilder_append_string(sb, (string){.ptr=(char*)src, .length=i});
StringBuilder_append_string(sb, (string){.ptr=str_new, .length=str_new_len});
src+=i+str_old_len;
}
string rezult=StringBuilder_build(sb);
return rezult.ptr;
}

View File

@ -7,39 +7,63 @@ extern "C" {
#include "std.h" #include "std.h"
// returns length of char buffer (without \0) // returns length of char buffer (without \0)
u32 cptr_length(char* str); u32 cptr_length(const char* str);
// allocates new char[] and copies src there // allocates new char[] and copies src there
char* cptr_copy(char* src); char* cptr_copy(const char* src);
// compares two char buffers, NullPtr-friendly bool cptr_equals(const char* key0, const char* key1);
bool cptr_compare(char* key0, char* key1);
bool cptr_startsWith(const char* src, const char* fragment);
bool cptr_endsWith(const char* src, const char* fragment);
// multiplies char n times // multiplies char n times
char* char_multiply(char c, u32 n); char* char_multiply(char c, u32 n);
bool cptr_startsWith(char* ptr, char* fragment); /// @param startIndex 0 ... src length
/// @param seekLength 0 ... -1
/// @return pos of first <fragment> inclusion in <src> or -1 if not found
i32 cptr_seek(const char* src, const char* fragment, u32 startIndex, u32 seekLength);
bool cptr_endsWith(char* ptr, char* fragment); /// @param startIndex -1 ... src length
/// @param seekLength 0 ... -1
/// @return pos of first <fragment> inclusion in <src> or -1 if not found
i32 cptr_seekReverse(const char* src, const char* fragment, u32 startIndex, u32 seekLength);
/// @param startIndex 0 ... src length
/// @param seekLength 0 ... -1
/// @return pos of first <fragment> inclusion in <src> or -1 if not found
i32 cptr_seekChar(const char* src, char fragment, u32 startIndex, u32 seekLength);
/// @param startIndex -1 ... src length
/// @param seekLength 0 ... -1
/// @return pos of first <fragment> inclusion in <src> or -1 if not found
i32 cptr_seekCharReverse(const char* src, char fragment, u32 startIndex, u32 seekLength);
/// @brief search for <fragment> in <ptr> /// @brief search for <fragment> in <ptr>
/// @return index of first <fragment> inclusion or -1 if not found /// @return index of first <fragment> inclusion or -1 if not found
u32 cptr_indexOf(char* ptr, char* fragment); static inline i32 cptr_indexOf(const char* src, const char* fragment)
{ return cptr_seek(src, fragment, 0, -1); }
/// @brief search for <fragment> in <ptr> /// @brief search for <fragment> in <ptr>
/// @return index of first <fragment> inclusion or -1 if not found /// @return index of first <fragment> inclusion or -1 if not found
u32 cptr_indexOfChar(char* ptr, char fragment); static inline i32 cptr_indexOfChar(const char* src, char fragment)
/// @brief search for <fragment> in <ptr> { return cptr_seekChar(src, fragment, 0, -1); }
/// @return index of last <fragment> inclusion or -1 if not found
u32 cptr_lastIndexOf(char* ptr, char* fragment);
/// @brief search for <fragment> in <ptr>
/// @return index of last <fragment> inclusion or -1 if not found
u32 cptr_lastIndexOfChar(char* ptr, char fragment);
static inline bool cptr_contains(char* ptr, char* fragment){ /// @brief search for <fragment> in <ptr>
// if(cptr_indexOf(ptr, fragment)==-1) /// @return index of last <fragment> inclusion or -1 if not found
// return false; static inline i32 cptr_lastIndexOf(const char* src, const char* fragment)
// return true; { return cptr_seekReverse(src, fragment, -1, -1); }
return cptr_indexOf(ptr, fragment) +1;
/// @brief search for <fragment> in <ptr>
/// @return index of last <fragment> inclusion or -1 if not found
static inline i32 cptr_lastIndexOfChar(const char* src, char fragment)
{ return cptr_seekCharReverse(src, fragment, -1, -1); }
static inline bool cptr_contains(const char* src, const char* fragment){
return cptr_seek(src, fragment, 0, -1) +1;
} }
void memcopy(void* from, void* to, u32 size); void memcopy(void* from, void* to, u32 size);
@ -47,8 +71,17 @@ void memcopy(void* from, void* to, u32 size);
char* __cptr_concat(u32 n, ...); char* __cptr_concat(u32 n, ...);
#define cptr_concat(STR...) __cptr_concat(count_args(STR), STR) #define cptr_concat(STR...) __cptr_concat(count_args(STR), STR)
char* cptr_toLower(char* src); char* cptr_toLower(const char* src);
char* cptr_toUpper(char* src); char* cptr_toUpper(const char* src);
/// @param startIndex 0 ... src length
/// @param seekLength 0 ... -1
/// @return <src> with <str_old> replaced by <str_new> or empty cstring if <str_old> not found
char* cptr_replace(const char* src, char* str_old, char* str_new, u32 startIndex, u32 seekLength);
/// @param startIndex 0 ... src length
/// @param seekLength 0 ... -1
/// @return <src> with <c_old> replaced by <c_new> or empty cstring if <str_old> not found
char* cptr_replaceChar(const char* src, char c_old, char c_new, u32 startIndex, u32 seekLength);
#if __cplusplus #if __cplusplus
} }

161
tests/test_cptr.c Normal file
View File

@ -0,0 +1,161 @@
#include "tests.h"
/*
TODO
test cptr_seek...
test cptr_...indexOf...
test cptr_replace...
cases:
*/
const char* strings[]={
"",
"abab",
"ab_ab",
"abab_",
"_abab",
"_ab_ab_",
"_ab_ab",
"_abab_",
"_ab_ab_",
"str_not_containing_a_b",
""
};
#define test_startsWith(str, fragm) \
kprintf("\e[37m'"str"' starts with '"fragm"'"); \
if(cptr_startsWith(str,fragm)) kprintf("\e[92m true\n"); \
else { kprintf("\e[91m false\n"); throw(ERR_UNEXPECTEDVAL); }
#define test_DoesntStartWith(str, fragm) \
kprintf("\e[37m'"str"' doesnt start with '"fragm"'"); \
if(!cptr_startsWith(str,fragm)) kprintf("\e[92m true\n"); \
else { kprintf("\e[91m false\n"); throw(ERR_UNEXPECTEDVAL); }
#define test_endsWith(str, fragm) \
kprintf("\e[37m'"str"' ends with '"fragm"'"); \
if(cptr_endsWith(str,fragm)) kprintf("\e[92m true\n"); \
else { kprintf("\e[91m false\n"); throw(ERR_UNEXPECTEDVAL); }
#define test_DoesntEndWith(str, fragm) \
kprintf("\e[37m'"str"' doesnt end with '"fragm"'"); \
if(!cptr_endsWith(str,fragm)) kprintf("\e[92m true\n"); \
else { kprintf("\e[91m false\n"); throw(ERR_UNEXPECTEDVAL); }
#define test_seekChar(str, fragm, start, count, expected) \
kprintf("\e[37mseek "#fragm" in '"str"' startIndex "#start" count "#count); \
pos=cptr_seekChar(str, fragm, start, count); \
if(pos == expected) kprintf("\e[92m %i\n", pos); \
else { kprintf("\e[91m %i\n", pos); throw(ERR_UNEXPECTEDVAL); }
#define test_seekCharReverse(str, fragm, start, count, expected) \
kprintf("\e[37mseek reverse "#fragm" in '"str"' startIndex "#start" count "#count); \
pos=cptr_seekCharReverse(str, fragm, start, count); \
if(pos == expected) kprintf("\e[92m %i\n", pos); \
else { kprintf("\e[91m %i\n", pos); throw(ERR_UNEXPECTEDVAL); }
#define test_seek(str, fragm, start, count, expected) \
kprintf("\e[37mseek '"fragm"' in '"str"' startIndex "#start" count "#count); \
pos=cptr_seek(str, fragm, start, count); \
if(pos == expected) kprintf("\e[92m %i\n", pos); \
else { kprintf("\e[91m %i\n", pos); throw(ERR_UNEXPECTEDVAL); }
#define test_seekReverse(str, fragm, start, count, expected) \
kprintf("\e[37mseek reverse '"fragm"' in '"str"' startIndex "#start" count "#count); \
pos=cptr_seekReverse(str, fragm, start, count); \
if(pos == expected) kprintf("\e[92m %i\n", pos); \
else { kprintf("\e[91m %i\n", pos); throw(ERR_UNEXPECTEDVAL); }
const int strings_len=sizeof(strings)/sizeof(strings[0]);
void test_cptr(){
// optime(__func__,1,
kprintf("\e[96m-------------[test_cptr]--------------\n");
// compare
kprintf("\e[94m--------------[compare]---------------\n");
for(int i=0; i<strings_len-1; i++){
// != next
kprintf("\e[37m'%s'!='%s'", strings[i], strings[i+1]);
bool not_eq= ! cptr_equals(strings[i],strings[i+1]);
if(not_eq) kprintf("\e[92m true\n");
else {
kprintf("\e[91m false\n");
throw(ERR_UNEXPECTEDVAL);
}
// == self
kprintf("\e[37m'%s'=='%s'", strings[i], strings[i]);
bool eq=cptr_equals(strings[i],strings[i]);
if(eq) kprintf("\e[92m true\n");
else {
kprintf("\e[91m false\n");
throw(ERR_UNEXPECTEDVAL);
}
}
kprintf("\e[94m-------------[startsWith]-------------\n");
test_startsWith("abab","ab");
test_startsWith("abab","abab");
test_DoesntStartWith("","");
test_DoesntStartWith("abab","ababc");
test_DoesntStartWith("abab","");
test_DoesntStartWith("","abab");
kprintf("\e[94m--------------[endsWith]--------------\n");
test_endsWith("cab","ab");
test_endsWith("abab","abab");
test_DoesntEndWith("","");
test_DoesntEndWith("abab","ababc");
test_DoesntEndWith("abab","");
test_DoesntEndWith("","abab");
i32 pos=-1;
kprintf("\e[94m--------------[seekChar]--------------\n");
test_seekChar("", '\0', 0, -1, -1)
test_seekChar("", 'u', 0, -1, -1)
test_seekChar("ab", '\0', 0, -1, -1)
test_seekChar("ab", 'u', 0, -1, -1)
test_seekChar("ab", 'a', 0, -1, 0)
test_seekChar("ab", 'b', 0, -1, 1)
test_seekChar("ab", '\0', 0, 2, -1)
test_seekChar("ab", 'b', 1, 2, 1)
test_seekChar("ab", 'b', 1, 1, 1)
kprintf("\e[94m----------[seekCharReverse]-----------\n");
test_seekCharReverse("", 'u', 0, -1, -1)
test_seekCharReverse("ab", 'u', 0, -1, -1)
test_seekCharReverse("ab", 'a', 0, -1, 0)
test_seekCharReverse("ab", 'b', 1, -1, 1)
test_seekCharReverse("ab", 'a', -1, -1, 0)
test_seekCharReverse("ab", 'b', -1, -1, 1)
test_seekCharReverse("ab", '\0', -1, -1, -1)
test_seekCharReverse("ab", '\0', 2, 2, -1)
test_seekCharReverse("ab", 'b', 1, 2, 1)
test_seekCharReverse("ab", 'b', 1, 1, 1)
kprintf("\e[94m----------------[seek]----------------\n");
test_seek("", "", 0, -1, -1)
test_seek("", "u", 0, -1, -1)
test_seek("ab", "", 0, -1, -1)
test_seek("ab", "u", 0, -1, -1)
test_seek("ab", "a", 0, -1, 0)
test_seek("ab", "b", 0, -1, 1)
test_seek("ab", "ab", 0, -1, 0)
test_seek("ab_ab", "ab", 0, -1, 0)
test_seek("ab_ab", "ab", 1, -1, 3)
test_seek("ab_ab", "ab", 1, 5, 3)
test_seek("ab_ab", "ab", 1, 4, -1)
kprintf("\e[94m------------[seekReverse]-------------\n");
test_seekReverse("", "u", 0, -1, -1)
test_seekReverse("ab", "u", 0, -1, -1)
test_seekReverse("ab", "a", 0, -1, 0)
test_seekReverse("ab", "b", 1, -1, 1)
test_seekReverse("ab", "a", -1, -1, 0)
test_seekReverse("ab", "b", -1, -1, 1)
test_seekReverse("ab", "", -1, -1, -1)
test_seekReverse("ab", "", 2, 2, -1)
test_seekReverse("ab", "b", 1, 2, 1)
test_seekReverse("ab", "b", 1, 1, 1)
// );
}

View File

@ -6,6 +6,7 @@
extern "C" { extern "C" {
#endif #endif
void test_cptr();
void test_string(); void test_string();
void test_safethrow(); void test_safethrow();
void test_searchtree(); void test_searchtree();
@ -22,6 +23,7 @@ void test_type_system();
inline void test_all(){ inline void test_all(){
kprintf("\e[97mkerep tests are starting!\n"); kprintf("\e[97mkerep tests are starting!\n");
optime(__func__, 1, optime(__func__, 1,
test_cptr();
test_type_system(); test_type_system();
test_string(); test_string();
test_safethrow(); test_safethrow();