master
Aaron 5 days ago
parent eb9ae4316f
commit b791fdf841

Binary file not shown.

@ -17,6 +17,9 @@
namespace ams namespace ams
{ {
static const int amsstring_success = 1;
static const int amsstring_failure = -1;
//wraps the functions strcpy_s and strncpy in a portable manner //wraps the functions strcpy_s and strncpy in a portable manner
//between linux and microsoft standard C libraries. //between linux and microsoft standard C libraries.
int amsstrcpy_s(char *dest, int size, const char *src); int amsstrcpy_s(char *dest, int size, const char *src);
@ -39,9 +42,8 @@ static const ams_chartype ams_char_nt = (ams_chartype) '\0'; //null terminator
class amsstring class amsstring
{ {
public: public:
ams_chartype blank; // null terminator returned for accessing index out of bounds
ams_chartype *cstring; ams_chartype *cstring;
ams_chartype blank; // null terminator returned for accessing index out of bounds
int length; int length;
//length will be set to the length of the cstring not including the null terminating char //length will be set to the length of the cstring not including the null terminating char
@ -49,20 +51,13 @@ public:
amsstring(); amsstring();
~amsstring(); ~amsstring();
amsstring(amsstring &other);
amsstring& operator=(amsstring &other);
amsstring(const amsstring &other); amsstring(const amsstring &other);
const amsstring& operator=(const amsstring &other); amsstring& operator=(const amsstring& other);
amsstring(amsstring &&other) noexcept;
amsstring(ams_chartype *other); amsstring& operator=(amsstring &&other) noexcept;
amsstring(const ams_chartype *other); amsstring(const ams_chartype *other);
const amsstring& operator=(const ams_chartype *other);
amsstring& operator=(ams_chartype *other);
const amsstring& operator=(const ams_chartype *other); //assign string constant to amsstring
//const amsstring& operator=(const ams_chartype *other) const; //assign string constant to amsstring
//const is a disease!
//
//amsstring(int length); //amsstring(int length);
//amsstring(int length, const ams_chartype initchar); //amsstring(int length, const ams_chartype initchar);

@ -4,20 +4,20 @@
namespace ams namespace ams
{ {
void amsstring3_basic_string_test1(); void amsstring4_basic_string_test1();
void amsstring3_sscanf_test1(); void amsstring4_sscanf_test1();
void amsstring3_basic_string_test2(); void amsstring4_basic_string_test2();
void amsstring3_memoryleakcheck1(); void amsstring4_memoryleakcheck1();
void amsstring3_memoryleakcheck2(); void amsstring4_memoryleakcheck2();
void amsstring3_stringtests2(); void amsstring4_stringtests2();
void amsstring3_test_find(); void amsstring4_test_find();
void amsstring3_test_splitlines(); void amsstring4_test_splitlines();
void amsstring3_test_split(); void amsstring4_test_split();
void amsstring3_test_strip(); void amsstring4_test_strip();
void amsstring3_test_freadwrite(); void amsstring4_test_freadwrite();
void amsstring3_test_concatenation_operators(); void amsstring4_test_concatenation_operators();

@ -528,7 +528,7 @@ void test_base64encode_fuzztest()
bytes.resize(I); bytes.resize(I);
for(J=0;J<bytes.size();J++) for(J=0;J<bytes.size();J++)
{ {
bytes.data[J] = randd()*255; bytes.data[J] = ams::rand::rand()*255;
} }
base64encode(&bytes,&str); base64encode(&bytes,&str);
base64decode(&str,&bytes2,1); base64decode(&str,&bytes2,1);

@ -33,7 +33,7 @@ namespace ams
return ret; return ret;
} }
static int localstrlen(const ams_chartype *c) static int amsstring_strlen(const ams_chartype *c)
{ {
int I; int I;
if(c!=NULL) if(c!=NULL)
@ -46,7 +46,6 @@ namespace ams
return I; return I;
//return strlen((const char*) c); //return strlen((const char*) c);
} }
else else
return 0; return 0;
} }
@ -54,8 +53,8 @@ namespace ams
bool amsstrneq(const ams_chartype *s1, const ams_chartype *s2, const bool casesens=1) bool amsstrneq(const ams_chartype *s1, const ams_chartype *s2, const bool casesens=1)
{ {
bool ret = 0; bool ret = 0;
int N1 = localstrlen(s1); int N1 = amsstring_strlen(s1);
int N2 = localstrlen(s2); int N2 = amsstring_strlen(s2);
bool b1,b2; bool b1,b2;
if(N1==N2) if(N1==N2)
@ -85,25 +84,29 @@ namespace ams
} }
static void amsstring_init(amsstring* str) void _amsstring_init(amsstring* str)
{ {
str->blank = (ams_chartype) '\0'; str->blank = (ams_chartype) '\0';
str->cstring = NULL; str->cstring = NULL;
str->length = 0;
str->cstring = new(std::nothrow) ams_chartype[1]; str->cstring = new(std::nothrow) ams_chartype[1];
if(str->cstring==NULL)
{
printf("_amsstring_init error: cstring buffer failed to initialize.\n");
}
else
{
str->cstring[0] = (ams_chartype) '\0'; str->cstring[0] = (ams_chartype) '\0';
str->length = 0; }
return; return;
} }
amsstring::amsstring() amsstring::amsstring()
{ {
//amsstring_init(this); _amsstring_init(this);
blank = (ams_chartype) '\0';
cstring = NULL;
cstring = new(std::nothrow) ams_chartype[1];
cstring[0] = (ams_chartype) '\0';
length = 0;
return; return;
} }
@ -126,320 +129,173 @@ namespace ams
return length; return length;
} }
//Rewrite amsstring::resize() - valgrind is still complaining! int amsstring::resize(int _newlen)
int amsstring::resize(const int newlen)
{ {
int ret = 0; int ret = amsstring_success;
int I = 0; ams_chartype *newcstring = NULL;
ams_chartype *newbuff = NULL; int I;
_newlen = (_newlen<0) ? 0 : _newlen;
if(newlen == length) newcstring = new(std::nothrow) ams_chartype[_newlen+1];
if(newcstring==NULL)
{ {
//sizes are the same, do nothing ret = amsstring_failure;
ret = 1;
return ret; return ret;
} }
if(newlen<=0) //if new length <0 if(cstring!=NULL)
{ {
newbuff = new(std::nothrow) ams_chartype[1]; for(I=0;I<(_newlen+1) && I<(length+1);I++)
if(newbuff==NULL)
{ {
ret = -1; newcstring[I] = cstring[I];
return ret;
} }
newbuff[0] = '\0';
if(cstring!=NULL) {delete[] cstring; cstring = NULL;}
cstring = newbuff;
length = 0;
ret = 1;
return ret;
} }
for(I=length;I<_newlen+1;I++)
newbuff = new(std::nothrow) ams_chartype[newlen+1];
if(newbuff==NULL)
{ {
ret = -1; newcstring[I] = (ams_chartype) '\0';
return ret;
} }
//Copy old data newcstring[_newlen] = '\0';
for(I=0;I<length && I<newlen;I++)
{
if(cstring!=NULL) if(cstring!=NULL)
{ {
newbuff[I] = cstring[I]; delete[] cstring;
} cstring=NULL;
else
{
newbuff[I] = '\0';
}
}
for(I=length;I<newlen;I++)
{
newbuff[I] = '\0';
} }
newbuff[newlen] = '\0';
if(cstring!=NULL) {delete[] cstring; cstring = NULL;}
cstring = newbuff;
length = newlen;
ret = 1; blank = (ams_chartype) '\0';
cstring = newcstring;
length = _newlen;
return ret; return ret;
} }
// int amsstring::resize(const int newlen)
// {
// int ret = 0;
// int I = 0;
// ams_chartype *newbuf = NULL;
// //printf("DEBUG: cstring=%ld,newbuf=%ld, cstring='%s'\n",cstring,newbuf,cstring);
// //printf("DEBUG: length=%d, newlen=%d\n",length,newlen);
// if(newlen>=0)
// {
// newbuf = new(std::nothrow) ams_chartype[newlen+1];
// if(newbuf==NULL)
// {
// ret = -1; //new buffer would not allocate
// }
// else
// {
// for(I=0;I<newlen+1;I++)
// {
// newbuf[I] = (ams_chartype) '\0';
// }
// if(cstring!=NULL)
// {
// amsstrcpy_s(newbuf,newlen+1,cstring);
// for(I=length;I<newlen+1;I++) //pad additional spaces with 0
// {
// newbuf[I] = (ams_chartype) '\0';
// }
// //newbuf[newlen] = (ams_chartype) '\0';
// if(cstring!=NULL) {delete[] cstring; cstring = NULL;}
// cstring = newbuf;
// length = newlen;
// ret = 1;
// }
// else
// {
// cstring = newbuf;
// length = newlen;
// ret = 1;
// }
// } //if newbuf!=NULL
// }
// else //if(newlen>=0)
// {
// ret = this->resize(0);
// }
// //printf("DEBUG: ret = %d\n",ret);
// return ret;
// }
amsstring::amsstring(const amsstring &other) amsstring::amsstring(const amsstring &other)
{ {
//amsstring_init(this); int I;
blank = (ams_chartype) '\0'; int res;
cstring = NULL; _amsstring_init(this);
cstring = new(std::nothrow) ams_chartype[1];
cstring[0] = (ams_chartype) '\0';
length = 0;
if(this!=&other) if(this!=&other)
{ {
*this=other; res = this->resize(other.length);
if(res==amsstring_success)
{
for(I=0;I<other.length;I++)
{
this->cstring[I] = other.cstring[I];
} }
this->cstring[length] = '\0';
blank = '\0';
}
}
return; return;
} }
amsstring::amsstring(amsstring &other) amsstring& amsstring::operator=(const amsstring& other)
{ {
//amsstring_init(this); int I;
int res;
blank = (ams_chartype) '\0';
cstring = NULL;
cstring = new(std::nothrow) ams_chartype[1];
cstring[0] = (ams_chartype) '\0';
length = 0;
if(this!=&other) if(this!=&other)
{ {
*this=other; res = this->resize(other.length);
} if(res==amsstring_success)
return;
}
const amsstring& amsstring::operator=(const amsstring &other)
{ {
if(this!=&other) for(I=0;I<other.length;I++)
{ {
this->resize(other.length); this->cstring[I] = other.cstring[I];
amsstrcpy_s(cstring,length+1,other.cstring);
cstring[length] = (ams_chartype) '\0';
shrinktofit(); //shrinks if the other cstring was corrupted with internal null terminators
// N = strlen(cstring); //if string is actually shorter (contains null terminating character elsewhere than at the end)
// //then resize to string's size
// if(N<length)
// {
// this->resize(N);
// }
} }
return *this; this->cstring[length] = '\0';
blank = '\0';
} }
amsstring& amsstring::operator=(amsstring &other)
{
if(this!=&other)
{
this->resize(other.length);
amsstrcpy_s(cstring,length+1,other.cstring);
cstring[length] = (ams_chartype) '\0';
shrinktofit(); //shrinks if the other cstring was corrupted with internal null terminators
// N = strlen(cstring); //if string is actually shorter (contains null terminating character elsewhere than at the end)
// //then resize to string's size
// if(N<length)
// {
// this->resize(N);
// }
} }
return *this; return *this;
} }
amsstring::amsstring(ams_chartype *other) amsstring::amsstring(amsstring &&other) noexcept
{ {
//amsstring_init(this);
blank = (ams_chartype) '\0';
cstring = NULL;
cstring = new(std::nothrow) ams_chartype[1];
cstring[0] = (ams_chartype) '\0';
length = 0;
*this = other; this->length = 0;
this->blank = '\0';
this->cstring = NULL;
return; if(this!=&other)
}
amsstring::amsstring(const ams_chartype *other)
{ {
//amsstring_init(this); this->length = other.length;
blank = (ams_chartype) '\0'; this->blank = other.blank;
cstring = NULL; this->cstring = other.cstring;
cstring = new(std::nothrow) ams_chartype[1];
cstring[0] = (ams_chartype) '\0';
length = 0;
*this = other; other.length = 0;
other.blank = '\0';
other.cstring = NULL;
}
return; return;
} }
const amsstring& amsstring::operator=(const ams_chartype *other) amsstring& amsstring::operator=(amsstring &&other) noexcept
{ {
//amsstring_init(this); <-- init only on a constructor, otherwise memory leak
int nl,q; if(this!=&other)
nl = localstrlen(other);
if(nl>=0)
{
q = this->resize(nl);
if(q>=0)
{
//printf("DEBUG: q=%d, length=%d",q,length);
amsstrcpy_s(cstring,length+1,other);
cstring[length] = (ams_chartype) '\0';
}
else
{
this->resize(0);
}
}
else
{ {
//already of zero size this->length = other.length;
this->blank = other.blank;
this->cstring = other.cstring;
other.length = 0;
other.blank = '\0';
other.cstring = NULL;
} }
return *this; return *this;
} }
amsstring& amsstring::operator=(ams_chartype *other) amsstring::amsstring(const ams_chartype *other)
{ {
//amsstring_init(this); <-- init only on a constructor, otherwise memory leak int len = amsstring_strlen(other);
int res;
int I;
int nl,q; _amsstring_init(this);
nl = localstrlen(other);
if(nl>=0) len = amsstring_strlen(other);
{ res = this->resize(len);
q = this->resize(nl); if(res==amsstring_success)
if(q>=0)
{
//printf("DEBUG: q=%d, length=%d",q,length);
amsstrcpy_s(cstring,length+1,other);
cstring[length] = (ams_chartype) '\0';
}
else
{ {
this->resize(0); for(I=0;I<length;I++) cstring[I] = other[I];
cstring[length] = '\0';
blank = '\0';
} }
return;
} }
else
const amsstring& amsstring::operator=(const ams_chartype *other)
{
int len = amsstring_strlen(other);
int res;
int I;
len = amsstring_strlen(other);
res = this->resize(len);
if(res==amsstring_success)
{ {
//already of zero size for(I=0;I<length;I++) cstring[I] = other[I];
cstring[length] = '\0';
blank = '\0';
} }
return *this; return *this;
} }
// const amsstring& amsstring::operator=(const ams_chartype *other) const
// {
// amsstring_init(this);
// int nl,q;
// nl = strlen(other);
// if(nl>=0)
// {
// q = this->resize(nl);
// if(q>=0)
// {
// printf("DEBUG: q=%d, length=%d",q,length);
// amsstrcpy_s(cstring,length+1,other);
// cstring[length] = (ams_chartype) '\0';
// }
// else
// {
// this->resize(0);
// }
// }
// else
// {
// //already of zero size
// }
// return *this;
// }
ams_chartype& amsstring::operator[](const int ind) ams_chartype& amsstring::operator[](const int ind)
{ {
// if(ind<0 || ind>length-1)
// {
// blank = (ams_chartype) '\0';
// return blank;
// }
// else
// {
// return cstring[ind];
// }
if(ind<0 || ind>=(length+1)) if(ind<0 || ind>=(length+1))
{ {
blank = (ams_chartype) '\0'; blank = (ams_chartype) '\0';
@ -514,7 +370,7 @@ namespace ams
//to the null terminator (actual c string length) //to the null terminator (actual c string length)
void amsstring::shrinktofit() void amsstring::shrinktofit()
{ {
int N = localstrlen(cstring); int N = amsstring_strlen(cstring);
this->resize(N); this->resize(N);
return; return;
} }
@ -841,7 +697,7 @@ namespace ams
int I; int I;
int ret = -1; int ret = -1;
int J = 0; int J = 0;
int N = ams::localstrlen(str); int N = ams::amsstring_strlen(str);
bool cs; bool cs;
ams_chartype c1,c2; ams_chartype c1,c2;
@ -934,7 +790,7 @@ namespace ams
vsnprintf(buff,bufflen,formatstring,varargs); vsnprintf(buff,bufflen,formatstring,varargs);
va_end(varargs); va_end(varargs);
buff[bufflen] = '\0'; buff[bufflen] = '\0';
//int N = ams::localstrlen(buff); //int N = ams::amsstring_strlen(buff);
*this = buff; *this = buff;
delete[] buff; buff=NULL; delete[] buff; buff=NULL;
@ -1219,7 +1075,7 @@ namespace ams
int cs; int cs;
int cnt; int cnt;
ams_chartype c; ams_chartype c;
int N = localstrlen(delimitstr); int N = amsstring_strlen(delimitstr);
if(lns!=NULL && delimitstr!=NULL) if(lns!=NULL && delimitstr!=NULL)
{ {
@ -1297,7 +1153,7 @@ namespace ams
int cs; int cs;
int cnt; int cnt;
ams_chartype c; ams_chartype c;
int N = localstrlen(delimitstr); int N = amsstring_strlen(delimitstr);
if(lns!=NULL && delimitstr!=NULL) if(lns!=NULL && delimitstr!=NULL)
{ {
@ -1548,7 +1404,7 @@ namespace ams
if(!feof(fp)) if(!feof(fp))
{ {
fgets(buff,BUFFSZ,fp); fgets(buff,BUFFSZ,fp);
N = ams::localstrlen(buff); N = ams::amsstring_strlen(buff);
if((N-1)>=0&&(buff[N-1]=='\n')) if((N-1)>=0&&(buff[N-1]=='\n'))
{ {
buff[N-1] = '\0'; buff[N-1] = '\0';
@ -1559,7 +1415,7 @@ namespace ams
buff[N-1] = '\0'; buff[N-1] = '\0';
N = N-1; N = N-1;
} }
N = ams::localstrlen(buff); N = ams::amsstring_strlen(buff);
*s = buff; //s->copy(buff); *s = buff; //s->copy(buff);
} }
else else

@ -3,7 +3,7 @@
namespace ams namespace ams
{ {
void amsstring3_basic_string_test1() void amsstring4_basic_string_test1()
{ {
char q1,c; char q1,c;
unsigned char q2; unsigned char q2;
@ -23,7 +23,7 @@ namespace ams
printf("\nLF: %c After LF %c After LF2 \n",q2,q2); printf("\nLF: %c After LF %c After LF2 \n",q2,q2);
} }
void amsstring3_sscanf_test1() void amsstring4_sscanf_test1()
{ {
char buf[500]; char buf[500];
double d; double d;
@ -104,7 +104,7 @@ namespace ams
printf("String %s reads as %1.4g\n",buf,d); printf("String %s reads as %1.4g\n",buf,d);
} }
void amsstring3_basic_string_test2() void amsstring4_basic_string_test2()
{ {
amsstring s1,s2; amsstring s1,s2;
//const amsstring s3; //don't do this - just accept that strings must be mutable //const amsstring s3; //don't do this - just accept that strings must be mutable
@ -156,7 +156,7 @@ namespace ams
} }
void amsstring3_memoryleakcheck1() void amsstring4_memoryleakcheck1()
{ {
amsstring q1,q2,q3; amsstring q1,q2,q3;
int I; int I;
@ -186,7 +186,7 @@ namespace ams
return; return;
} }
void amsstring3_memoryleakcheck2() void amsstring4_memoryleakcheck2()
{ {
int I; int I;
amsstring q1; amsstring q1;
@ -198,7 +198,7 @@ namespace ams
printf("q1=%s\n",q1.cstring); printf("q1=%s\n",q1.cstring);
} }
void amsstring3_stringtests2() void amsstring4_stringtests2()
{ {
amsstring q1,q2; amsstring q1,q2;
int I; int I;
@ -272,7 +272,7 @@ namespace ams
return; return;
} }
void amsstring3_test_find() void amsstring4_test_find()
{ {
amsstring q1,q2,q3; amsstring q1,q2,q3;
int I; int I;
@ -308,7 +308,7 @@ namespace ams
return; return;
} }
void amsstring3_test_splitlines() void amsstring4_test_splitlines()
{ {
int I; int I;
amsstring q1; amsstring q1;
@ -328,7 +328,7 @@ namespace ams
return; return;
} }
void amsstring3_test_split() void amsstring4_test_split()
{ {
amsstring q1; amsstring q1;
std::vector<amsstring> strs; std::vector<amsstring> strs;
@ -393,7 +393,7 @@ namespace ams
return; return;
} }
void amsstring3_test_strip() void amsstring4_test_strip()
{ {
amsstring q1; amsstring q1;
std::vector<amsstring> strs; std::vector<amsstring> strs;
@ -419,7 +419,7 @@ namespace ams
return; return;
} }
void amsstring3_test_freadwrite() void amsstring4_test_freadwrite()
{ {
FILE *fp = NULL; FILE *fp = NULL;
FILE *fp2 = NULL; FILE *fp2 = NULL;
@ -457,7 +457,7 @@ namespace ams
return; return;
} }
void amsstring3_test_concatenation_operators() void amsstring4_test_concatenation_operators()
{ {
ams::amsstring a,b,c,d; ams::amsstring a,b,c,d;

@ -579,7 +579,7 @@ namespace ams
cp->resize(len+1); cp->resize(len+1);
for(I=0;I<len;I++) for(I=0;I<len;I++)
{ {
cp->at(I) = ams::randi(1,0x0010FFFF); cp->at(I) = ams::rand::randint(1,0x0010FFFF+1);
} }
cp->at(len) = 0; cp->at(len) = 0;

@ -1,9 +1,26 @@
#include <amsstring4/amsstring4.hpp> #include <amsstring4/amsstring4.hpp>
using namespace ams;
int main(int argc, char* argv[]) int main(int argc, char* argv[])
{ {
int ret = 0; int ret = 0;
printf("ams string4 library tests.\n"); printf("ams string4 library tests.\n");
amsstring4_basic_string_test1();
amsstring4_sscanf_test1();
amsstring4_basic_string_test2();
amsstring4_memoryleakcheck1();
amsstring4_memoryleakcheck2();
amsstring4_stringtests2();
amsstring4_test_find();
amsstring4_test_splitlines();
amsstring4_test_split();
amsstring4_test_strip();
//amsstring4_test_freadwrite();
amsstring4_test_concatenation_operators();
return ret; return ret;
} }
Loading…
Cancel
Save