Improve opp string library
This commit is contained in:
parent
66631c915b
commit
00ded29b35
|
@ -1,5 +1,8 @@
|
||||||
rem @echo off
|
rem @echo off
|
||||||
|
|
||||||
|
@call :test opp_string.cpp
|
||||||
|
@if %errorlevel% neq 0 goto :error
|
||||||
|
|
||||||
@call :test operatoroverload.cpp
|
@call :test operatoroverload.cpp
|
||||||
@if %errorlevel% neq 0 goto :error
|
@if %errorlevel% neq 0 goto :error
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,96 @@
|
||||||
|
#include <opp/string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
static const char HelloWorld[] = "Hello World";
|
||||||
|
static const char AndBeyond[] = "And Beyond";
|
||||||
|
static const char And[] = "And";
|
||||||
|
static const char HelloWorldAndBeyond[] = "Hello World And Beyond";
|
||||||
|
|
||||||
|
void test_create(void)
|
||||||
|
{
|
||||||
|
string s1();
|
||||||
|
string s2(HelloWorld);
|
||||||
|
string s3(s2);
|
||||||
|
string s4('a');
|
||||||
|
|
||||||
|
assert(!strcmp(s2.tocstr(), HelloWorld));
|
||||||
|
assert(!strcmp(s3.tocstr(), HelloWorld));
|
||||||
|
assert(s4.size() == 1 && s4[0] == 'a');
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_concat(void)
|
||||||
|
{
|
||||||
|
string s1();
|
||||||
|
string s2(HelloWorld);
|
||||||
|
string s3(AndBeyond);
|
||||||
|
|
||||||
|
string s4 = s1 + s2;
|
||||||
|
string s5 = s2 + " " + s3;
|
||||||
|
string s6 = s2 + " " + AndBeyond;
|
||||||
|
|
||||||
|
assert(!strcmp(s4.tocstr(), HelloWorld));
|
||||||
|
assert(!strcmp(s5.tocstr(), HelloWorldAndBeyond));
|
||||||
|
assert(!strcmp(s6.tocstr(), HelloWorldAndBeyond));
|
||||||
|
}
|
||||||
|
|
||||||
|
__noinline void test_find(void)
|
||||||
|
{
|
||||||
|
string s1(HelloWorldAndBeyond);
|
||||||
|
string s2(And);
|
||||||
|
|
||||||
|
assert(s1.find(HelloWorld) == 0);
|
||||||
|
assert(s1.find(AndBeyond) == 12);
|
||||||
|
assert(s1.find(And) == 12);
|
||||||
|
assert(s1.find(s2) == 12);
|
||||||
|
|
||||||
|
assert(s1.find(' ') == 5);
|
||||||
|
assert(s1.find(' ', 6) == 11);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_assign(void)
|
||||||
|
{
|
||||||
|
string s1(HelloWorld);
|
||||||
|
string s2(AndBeyond);
|
||||||
|
string s3;
|
||||||
|
s3 = s1;
|
||||||
|
s3 = s2;
|
||||||
|
s3 = s1;
|
||||||
|
s3 += " ";
|
||||||
|
s3 += s2;
|
||||||
|
|
||||||
|
assert(!strcmp(s3.tocstr(), HelloWorldAndBeyond));
|
||||||
|
|
||||||
|
s3 <<= 12;
|
||||||
|
|
||||||
|
assert(!strcmp(s3.tocstr(), AndBeyond));
|
||||||
|
|
||||||
|
s3 = HelloWorldAndBeyond;
|
||||||
|
|
||||||
|
assert(!strcmp(s3.tocstr(), HelloWorldAndBeyond));
|
||||||
|
|
||||||
|
s3 >>= 11;
|
||||||
|
|
||||||
|
assert(!strcmp(s3.tocstr(), HelloWorld));
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
char * p = new char;
|
||||||
|
unsigned avail = heapfree();
|
||||||
|
|
||||||
|
test_create();
|
||||||
|
assert(avail == heapfree());
|
||||||
|
|
||||||
|
test_concat();
|
||||||
|
assert(avail == heapfree());
|
||||||
|
|
||||||
|
test_find();
|
||||||
|
assert(avail == heapfree());
|
||||||
|
|
||||||
|
test_assign();
|
||||||
|
assert(avail == heapfree());
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -2,26 +2,53 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
static inline void smemcpy(char * dp, const char * sp, char s)
|
||||||
|
{
|
||||||
|
for(char i=0; i<s; i++)
|
||||||
|
dp[i] = sp[i];
|
||||||
|
}
|
||||||
|
|
||||||
string::string(void) : cstr(nullptr)
|
string::string(void) : cstr(nullptr)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
string::string(const string & s)
|
string::string(const string & s)
|
||||||
{
|
{
|
||||||
cstr = malloc(strlen(s.cstr) + 1);
|
if (s.cstr)
|
||||||
strcpy(cstr, s.cstr);
|
{
|
||||||
|
char l = s.cstr[0];
|
||||||
|
cstr = malloc(l + 2);
|
||||||
|
smemcpy(cstr, s.cstr, l + 2);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
cstr = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
string::string(const char * s)
|
string::string(const char * s)
|
||||||
{
|
{
|
||||||
cstr = malloc(strlen(s) + 1);
|
char l = strlen(s);
|
||||||
strcpy(cstr, s);
|
if (l)
|
||||||
|
{
|
||||||
|
cstr = malloc(l + 2);
|
||||||
|
cstr[0] = l;
|
||||||
|
smemcpy(cstr + 1, s, l + 1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
cstr = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
string::string(const char * s1, const char * s2)
|
string::string(char c)
|
||||||
{
|
{
|
||||||
cstr = malloc(strlen(s1) + strlen(s2) + 1);
|
cstr = malloc(3);
|
||||||
strcpy(cstr, s1);
|
cstr[0] = 1;
|
||||||
strcat(cstr, s2);
|
cstr[1] = c;
|
||||||
|
cstr[2] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
string::string(char l, char * b)
|
||||||
|
: cstr(b)
|
||||||
|
{
|
||||||
|
b[0] = l;
|
||||||
|
b[l + 1] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
string::~string(void)
|
string::~string(void)
|
||||||
|
@ -34,8 +61,14 @@ string & string::operator=(const string & s)
|
||||||
if (cstr != s.cstr)
|
if (cstr != s.cstr)
|
||||||
{
|
{
|
||||||
free(cstr);
|
free(cstr);
|
||||||
cstr = malloc(strlen(s.cstr) + 1);
|
if (s.cstr)
|
||||||
strcpy(cstr, s.cstr);
|
{
|
||||||
|
char l = s.cstr[0];
|
||||||
|
cstr = malloc(l + 2);
|
||||||
|
smemcpy(cstr, s.cstr, l + 2);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
cstr = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
|
@ -44,119 +77,433 @@ string & string::operator=(const string & s)
|
||||||
string & string::operator=(const char * s)
|
string & string::operator=(const char * s)
|
||||||
{
|
{
|
||||||
free(cstr);
|
free(cstr);
|
||||||
cstr = malloc(strlen(s) + 1);
|
char l = strlen(s);
|
||||||
strcpy(cstr, s);
|
if (l)
|
||||||
|
{
|
||||||
|
cstr = malloc(l + 2);
|
||||||
|
cstr[0] = l;
|
||||||
|
smemcpy(cstr + 1, s, l + 1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
cstr = nullptr;
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
string & string::operator+=(const string & s)
|
string & string::operator+=(const string & s)
|
||||||
{
|
{
|
||||||
char * nstr = malloc(strlen(cstr) + strlen(s.cstr) + 1);
|
if (s.cstr)
|
||||||
strcpy(nstr, cstr);
|
{
|
||||||
strcat(nstr, s.cstr);
|
if (cstr)
|
||||||
free(cstr);
|
{
|
||||||
cstr = nstr;
|
char l = cstr[0] + s.cstr[0];
|
||||||
|
char * c = malloc(l + 2);
|
||||||
|
c[0] = l;
|
||||||
|
smemcpy(c + 1, cstr + 1, cstr[0]);
|
||||||
|
smemcpy(c + 1 + cstr[0], s.cstr + 1, s.cstr[0] + 1);
|
||||||
|
free(cstr);
|
||||||
|
cstr = c;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
char l = s.cstr[0];
|
||||||
|
cstr = malloc(l + 2);
|
||||||
|
smemcpy(cstr, s.cstr, l + 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
string & string::operator+=(const char * s)
|
string & string::operator+=(const char * s)
|
||||||
{
|
{
|
||||||
char * nstr = malloc(strlen(cstr) + strlen(s) + 1);
|
char sl = strlen(s);
|
||||||
strcpy(nstr, cstr);
|
if (sl)
|
||||||
strcat(nstr, s);
|
{
|
||||||
free(cstr);
|
if (cstr)
|
||||||
cstr = nstr;
|
{
|
||||||
|
char l = sl + cstr[0];
|
||||||
|
char * c = malloc(l + 2);
|
||||||
|
c[0] = l;
|
||||||
|
smemcpy(c + 1, cstr + 1, cstr[0]);
|
||||||
|
smemcpy(c + 1 + cstr[0], s, sl + 1);
|
||||||
|
free(cstr);
|
||||||
|
cstr = c;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cstr = malloc(sl + 2);
|
||||||
|
cstr[0] = sl;
|
||||||
|
smemcpy(cstr + 1, s, sl + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
string & string::operator+=(char c)
|
||||||
|
{
|
||||||
|
if (cstr)
|
||||||
|
{
|
||||||
|
char l = cstr[0] + 1;
|
||||||
|
char * p = malloc(l + 2);
|
||||||
|
p[0] = l;
|
||||||
|
smemcpy(p + 1, cstr + 1, cstr[0]);
|
||||||
|
p[l] = c;
|
||||||
|
p[l + 1] = 0;
|
||||||
|
free(cstr);
|
||||||
|
cstr = c;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cstr = malloc(3);
|
||||||
|
cstr[0] = 1;
|
||||||
|
cstr[1] = c;
|
||||||
|
cstr[2] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
inline const char * string::tocstr(void) const
|
inline const char * string::tocstr(void) const
|
||||||
{
|
{
|
||||||
return cstr;
|
if (cstr)
|
||||||
|
return cstr + 1;
|
||||||
|
else
|
||||||
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
inline unsigned string::size(void) const
|
inline unsigned string::size(void) const
|
||||||
{
|
{
|
||||||
return strlen(cstr);
|
if (cstr)
|
||||||
|
return cstr[0];
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
string string::operator+(const string & s)
|
string string::operator+(const string & s) const
|
||||||
{
|
{
|
||||||
return string(cstr, s.cstr);
|
if (cstr)
|
||||||
|
{
|
||||||
|
if (s.cstr)
|
||||||
|
{
|
||||||
|
char l = cstr[0] + s.cstr[0];
|
||||||
|
char * p = malloc(l + 2);
|
||||||
|
smemcpy(p + 1, cstr + 1, cstr[0]);
|
||||||
|
smemcpy(p + 1 + cstr[0], s.cstr + 1, s.cstr[0]);
|
||||||
|
return string(l, p);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
string string::operator+(const char * s)
|
string string::operator+(const char * s) const
|
||||||
{
|
{
|
||||||
return string(cstr, s);
|
if (cstr)
|
||||||
|
{
|
||||||
|
char sl = strlen(s);
|
||||||
|
if (sl)
|
||||||
|
{
|
||||||
|
char l = cstr[0] + sl;
|
||||||
|
char * p = malloc(l + 2);
|
||||||
|
smemcpy(p + 1, cstr + 1, cstr[0]);
|
||||||
|
smemcpy(p + 1 + cstr[0], s, sl);
|
||||||
|
return string(l, p);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return string(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
string string::operator+(char c) const
|
||||||
|
{
|
||||||
|
if (cstr)
|
||||||
|
{
|
||||||
|
char l = cstr[0] + 1;
|
||||||
|
char * p = malloc(l + 2);
|
||||||
|
smemcpy(p + 1, cstr + 1, cstr[0]);
|
||||||
|
p[l] = c;
|
||||||
|
return string(l, p);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return string(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
string & string::operator<<=(char n)
|
||||||
|
{
|
||||||
|
if (n > 0 && cstr)
|
||||||
|
{
|
||||||
|
if (n >= cstr[0])
|
||||||
|
{
|
||||||
|
free(cstr);
|
||||||
|
cstr = nullptr;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
char i = 1;
|
||||||
|
n++;
|
||||||
|
while (cstr[n])
|
||||||
|
cstr[i++] = cstr[n++];
|
||||||
|
cstr[i] = 0;
|
||||||
|
cstr[0] = i - 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
string & string::operator>>=(char n)
|
||||||
|
{
|
||||||
|
if (n > 0 && cstr)
|
||||||
|
{
|
||||||
|
if (n >= cstr[0])
|
||||||
|
{
|
||||||
|
free(cstr);
|
||||||
|
cstr = nullptr;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cstr[0] -= n;
|
||||||
|
cstr[n + 1] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
string string::operator<<(char n) const
|
||||||
|
{
|
||||||
|
if (n > 0 && cstr)
|
||||||
|
{
|
||||||
|
if (n >= cstr[0])
|
||||||
|
return string();
|
||||||
|
else
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
string string::operator>>(char n) const
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static int scmp(const char * s1, const char * s2)
|
||||||
|
{
|
||||||
|
char n = 0;
|
||||||
|
while (s1[n])
|
||||||
|
{
|
||||||
|
if (s1[n] != s2[n])
|
||||||
|
return s1[n] - s2[n];
|
||||||
|
n++;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
inline bool string::operator==(const string & s) const
|
inline bool string::operator==(const string & s) const
|
||||||
{
|
{
|
||||||
return strcmp(cstr, s.cstr) == 0;
|
if (cstr && s.cstr)
|
||||||
|
return scmp(cstr + 1, s.cstr + 1) == 0;
|
||||||
|
else
|
||||||
|
return !cstr && !s.cstr;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool string::operator==(const char * s) const
|
inline bool string::operator==(const char * s) const
|
||||||
{
|
{
|
||||||
return strcmp(cstr, s) == 0;
|
if (cstr)
|
||||||
|
return scmp(cstr + 1, s) == 0;
|
||||||
|
else
|
||||||
|
return s[0] == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool string::operator!=(const string & s) const
|
inline bool string::operator!=(const string & s) const
|
||||||
{
|
{
|
||||||
return strcmp(cstr, s.cstr) != 0;
|
if (cstr && s.cstr)
|
||||||
|
return scmp(cstr + 1, s.cstr + 1) != 0;
|
||||||
|
else
|
||||||
|
return cstr || s.cstr;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool string::operator!=(const char * s) const
|
inline bool string::operator!=(const char * s) const
|
||||||
{
|
{
|
||||||
return strcmp(cstr, s) == 0;
|
if (cstr)
|
||||||
|
return scmp(cstr + 1, s) == 0;
|
||||||
|
else
|
||||||
|
return s[0] != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool string::operator<(const string & s) const
|
inline bool string::operator<(const string & s) const
|
||||||
{
|
{
|
||||||
return strcmp(cstr, s.cstr) < 0;
|
if (cstr && s.cstr)
|
||||||
|
return scmp(cstr + 1, s.cstr + 1) < 0;
|
||||||
|
else
|
||||||
|
return s.cstr;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool string::operator<(const char * s) const
|
inline bool string::operator<(const char * s) const
|
||||||
{
|
{
|
||||||
return strcmp(cstr, s) < 0;
|
if (cstr)
|
||||||
|
return scmp(cstr + 1, s) < 0;
|
||||||
|
else
|
||||||
|
return s[0] != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool string::operator<=(const string & s) const
|
inline bool string::operator<=(const string & s) const
|
||||||
{
|
{
|
||||||
return strcmp(cstr, s.cstr) <= 0;
|
if (cstr && s.cstr)
|
||||||
|
return scmp(cstr + 1, s.cstr + 1) <= 0;
|
||||||
|
else
|
||||||
|
return !cstr || s.cstr;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool string::operator<=(const char * s) const
|
inline bool string::operator<=(const char * s) const
|
||||||
{
|
{
|
||||||
return strcmp(cstr, s) <= 0;
|
if (cstr)
|
||||||
|
return scmp(cstr + 1, s) <= 0;
|
||||||
|
else
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool string::operator>(const string & s) const
|
inline bool string::operator>(const string & s) const
|
||||||
{
|
{
|
||||||
return strcmp(cstr, s.cstr) > 0;
|
if (cstr && s.cstr)
|
||||||
|
return scmp(cstr + 1, s.cstr + 1) > 0;
|
||||||
|
else
|
||||||
|
return cstr;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool string::operator>(const char * s) const
|
inline bool string::operator>(const char * s) const
|
||||||
{
|
{
|
||||||
return strcmp(cstr, s) > 0;
|
if (cstr)
|
||||||
|
return scmp(cstr + 1, s) > 0;
|
||||||
|
else
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool string::operator>=(const string & s) const
|
inline bool string::operator>=(const string & s) const
|
||||||
{
|
{
|
||||||
return strcmp(cstr, s.cstr) >= 0;
|
if (cstr && s.cstr)
|
||||||
|
return scmp(cstr + 1, s.cstr + 1) >= 0;
|
||||||
|
else
|
||||||
|
return cstr || !s.cstr;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool string::operator>=(const char * s) const
|
inline bool string::operator>=(const char * s) const
|
||||||
{
|
{
|
||||||
return strcmp(cstr, s) >= 0;
|
if (cstr)
|
||||||
|
return scmp(cstr + 1, s) >= 0;
|
||||||
|
else
|
||||||
|
return s[0] == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline char & string::operator[](unsigned t)
|
inline char & string::operator[](char t)
|
||||||
{
|
{
|
||||||
return cstr[t];
|
return cstr[t + 1];
|
||||||
}
|
}
|
||||||
|
|
||||||
inline char string::operator[](unsigned t) const
|
inline char string::operator[](char t) const
|
||||||
{
|
{
|
||||||
return cstr[t];
|
return cstr[t + 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
string string::substr(char pos, char len) const
|
||||||
|
{
|
||||||
|
if (!cstr || len == 0 || pos >= cstr[0])
|
||||||
|
return string;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
char l = cstr[0];
|
||||||
|
if (pos + len > l)
|
||||||
|
len = l - pos;
|
||||||
|
|
||||||
|
char * p = malloc(len + 2);
|
||||||
|
memcpy(p + 1, cstr + 1 + pos, len);
|
||||||
|
return string(len, p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int string::find(const string & s) const
|
||||||
|
{
|
||||||
|
return find(s, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int string::find(const char * s) const
|
||||||
|
{
|
||||||
|
return find(s, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int string::find(char c) const
|
||||||
|
{
|
||||||
|
return find(c, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int string::find(const string & s, char pos) const
|
||||||
|
{
|
||||||
|
if (!s.cstr)
|
||||||
|
return pos;
|
||||||
|
if (cstr)
|
||||||
|
{
|
||||||
|
char l = cstr[0];
|
||||||
|
char sl = s.cstr[0];
|
||||||
|
if (sl <= l)
|
||||||
|
{
|
||||||
|
l -= sl;
|
||||||
|
|
||||||
|
while (pos <= l)
|
||||||
|
{
|
||||||
|
char i = 1;
|
||||||
|
while (s.cstr[i] && s.cstr[i] == cstr[pos + i])
|
||||||
|
i++;
|
||||||
|
if (!s.cstr[i])
|
||||||
|
return pos;
|
||||||
|
pos++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int string::find(const char * s, char pos) const
|
||||||
|
{
|
||||||
|
if (cstr)
|
||||||
|
{
|
||||||
|
char l = cstr[0];
|
||||||
|
char sl = strlen(s);
|
||||||
|
if (sl <= l)
|
||||||
|
{
|
||||||
|
l -= sl;
|
||||||
|
|
||||||
|
while (pos <= l)
|
||||||
|
{
|
||||||
|
char i = 0;
|
||||||
|
while (s[i] && s[i] == cstr[pos + i + 1])
|
||||||
|
i++;
|
||||||
|
if (!s[i])
|
||||||
|
return pos;
|
||||||
|
pos++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int string::find(char c, char pos) const
|
||||||
|
{
|
||||||
|
if (cstr)
|
||||||
|
{
|
||||||
|
char l = cstr[0];
|
||||||
|
while (pos < l)
|
||||||
|
{
|
||||||
|
if (cstr[pos + 1] == c)
|
||||||
|
return pos;
|
||||||
|
pos++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,8 +9,8 @@ private:
|
||||||
public:
|
public:
|
||||||
string(void);
|
string(void);
|
||||||
string(const string & s);
|
string(const string & s);
|
||||||
string(const char * s);
|
__noinline string(const char * s);
|
||||||
string(const char * s1, const char * s2);
|
string(char c);
|
||||||
~string(void);
|
~string(void);
|
||||||
|
|
||||||
unsigned size(void) const;
|
unsigned size(void) const;
|
||||||
|
@ -20,9 +20,17 @@ public:
|
||||||
|
|
||||||
string & operator+=(const string & s);
|
string & operator+=(const string & s);
|
||||||
string & operator+=(const char * s);
|
string & operator+=(const char * s);
|
||||||
|
string & operator+=(char c);
|
||||||
|
|
||||||
string operator+(const string & s);
|
string operator+(const string & s) const;
|
||||||
string operator+(const char * s);
|
string operator+(const char * s) const;
|
||||||
|
string operator+(char c) const;
|
||||||
|
|
||||||
|
string & operator<<=(char n);
|
||||||
|
string & operator>>=(char n);
|
||||||
|
|
||||||
|
string operator<<(char n) const;
|
||||||
|
string operator>>(char n) const;
|
||||||
|
|
||||||
bool operator==(const string & s) const;
|
bool operator==(const string & s) const;
|
||||||
bool operator==(const char * s) const;
|
bool operator==(const char * s) const;
|
||||||
|
@ -39,10 +47,22 @@ public:
|
||||||
bool operator>=(const string & s) const;
|
bool operator>=(const string & s) const;
|
||||||
bool operator>=(const char * s) const;
|
bool operator>=(const char * s) const;
|
||||||
|
|
||||||
char & operator[](unsigned t);
|
char & operator[](char t);
|
||||||
char operator[](unsigned t) const;
|
char operator[](char t) const;
|
||||||
|
|
||||||
const char * tocstr(void) const;
|
const char * tocstr(void) const;
|
||||||
|
|
||||||
|
string substr(char pos, char len) const;
|
||||||
|
|
||||||
|
int find(const string & s) const;
|
||||||
|
int find(const char * s) const;
|
||||||
|
int find(char c) const;
|
||||||
|
|
||||||
|
int find(const string & s, char pos) const;
|
||||||
|
int find(const char * s, char pos) const;
|
||||||
|
int find(char c, char pos) const;
|
||||||
|
protected:
|
||||||
|
string(char l, char * b);
|
||||||
};
|
};
|
||||||
|
|
||||||
#pragma compile("string.cpp")
|
#pragma compile("string.cpp")
|
||||||
|
|
|
@ -524,6 +524,22 @@ void exit(int status)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern struct Heap {
|
||||||
|
Heap * next, * end;
|
||||||
|
} HeapNode;
|
||||||
|
|
||||||
|
unsigned heapfree(void)
|
||||||
|
{
|
||||||
|
unsigned avail = 0;
|
||||||
|
Heap * h = HeapNode.next;
|
||||||
|
while (h)
|
||||||
|
{
|
||||||
|
avail += (h->end - h) * sizeof(Heap);
|
||||||
|
h = h->next;
|
||||||
|
}
|
||||||
|
return avail;
|
||||||
|
}
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
struct Heap {
|
struct Heap {
|
||||||
unsigned int size;
|
unsigned int size;
|
||||||
|
|
|
@ -43,6 +43,8 @@ void free(void * ptr);
|
||||||
|
|
||||||
void * calloc(int num, int size);
|
void * calloc(int num, int size);
|
||||||
|
|
||||||
|
unsigned heapfree(void);
|
||||||
|
|
||||||
unsigned int rand(void);
|
unsigned int rand(void);
|
||||||
|
|
||||||
void srand(unsigned int seed);
|
void srand(unsigned int seed);
|
||||||
|
|
|
@ -4428,6 +4428,9 @@ void InterCodeBasicBlock::Append(InterInstruction * code)
|
||||||
assert(code->mSrc[1].mType != IT_POINTER);
|
assert(code->mSrc[1].mType != IT_POINTER);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < code->mNumOperands; i++)
|
||||||
|
assert(code->mSrc[i].mType != IT_NONE);
|
||||||
|
|
||||||
assert(!(code->mInUse));
|
assert(!(code->mInUse));
|
||||||
code->mInUse = true;
|
code->mInUse = true;
|
||||||
this->mInstructions.Push(code);
|
this->mInstructions.Push(code);
|
||||||
|
@ -16126,7 +16129,7 @@ void InterCodeProcedure::Close(void)
|
||||||
{
|
{
|
||||||
GrowingTypeArray tstack(IT_NONE);
|
GrowingTypeArray tstack(IT_NONE);
|
||||||
|
|
||||||
CheckFunc = !strcmp(mIdent->mString, "setspr");
|
CheckFunc = !strcmp(mIdent->mString, "test_find");
|
||||||
|
|
||||||
mEntryBlock = mBlocks[0];
|
mEntryBlock = mBlocks[0];
|
||||||
|
|
||||||
|
|
|
@ -1007,8 +1007,9 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateInline(Declaration* pro
|
||||||
|
|
||||||
InterInstruction* wins = new InterInstruction(texp->mLocation, IC_STORE);
|
InterInstruction* wins = new InterInstruction(texp->mLocation, IC_STORE);
|
||||||
wins->mSrc[1].mMemory = IM_INDIRECT;
|
wins->mSrc[1].mMemory = IM_INDIRECT;
|
||||||
wins->mSrc[0].mType = InterTypeOf(vr.mType);;
|
wins->mSrc[0].mType = vr.mReference > 0 ? IT_POINTER : InterTypeOf(vr.mType);
|
||||||
wins->mSrc[0].mTemp = vr.mTemp;
|
wins->mSrc[0].mTemp = vr.mTemp;
|
||||||
|
assert(wins->mSrc[0].mType != IT_NONE);
|
||||||
wins->mSrc[1].mType = IT_POINTER;
|
wins->mSrc[1].mType = IT_POINTER;
|
||||||
wins->mSrc[1].mTemp = ains->mDst.mTemp;
|
wins->mSrc[1].mTemp = ains->mDst.mTemp;
|
||||||
if (pdec)
|
if (pdec)
|
||||||
|
@ -3195,6 +3196,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration*
|
||||||
block->Append(defins[i]);
|
block->Append(defins[i]);
|
||||||
|
|
||||||
InterInstruction * cins = new InterInstruction(exp->mLocation, IC_CALL);
|
InterInstruction * cins = new InterInstruction(exp->mLocation, IC_CALL);
|
||||||
|
cins->mNumOperands = 1;
|
||||||
if (funcexp->mDecValue && (funcexp->mDecValue->mFlags & DTF_NATIVE))
|
if (funcexp->mDecValue && (funcexp->mDecValue->mFlags & DTF_NATIVE))
|
||||||
cins->mCode = IC_CALL_NATIVE;
|
cins->mCode = IC_CALL_NATIVE;
|
||||||
else
|
else
|
||||||
|
|
|
@ -28951,7 +28951,7 @@ bool NativeCodeBasicBlock::OptimizeSimpleLoopInvariant(NativeCodeProcedure* proc
|
||||||
i++;
|
i++;
|
||||||
while (i < mIns.Size() && !mIns[i].ReferencesZeroPage(mIns[si].mAddress))
|
while (i < mIns.Size() && !mIns[i].ReferencesZeroPage(mIns[si].mAddress))
|
||||||
i++;
|
i++;
|
||||||
if (i < mIns.Size() && (mIns[i].mType == ASMIT_DEC || mIns[i].mType == ASMIT_INC))
|
if (i < mIns.Size() && (mIns[i].mType == ASMIT_DEC || mIns[i].mType == ASMIT_INC) && (!(mIns[ei].mLive & LIVE_CPU_REG_Z) || mIns[ei].ChangesAccuAndFlag()))
|
||||||
{
|
{
|
||||||
int j = i + 1;
|
int j = i + 1;
|
||||||
while (j < mIns.Size() && !mIns[j].ReferencesZeroPage(mIns[si].mAddress))
|
while (j < mIns.Size() && !mIns[j].ReferencesZeroPage(mIns[si].mAddress))
|
||||||
|
@ -28961,6 +28961,9 @@ bool NativeCodeBasicBlock::OptimizeSimpleLoopInvariant(NativeCodeProcedure* proc
|
||||||
// So we have an LDX from ZP, and exactly one INC/DECof this ZP and X never changes in the loop
|
// So we have an LDX from ZP, and exactly one INC/DECof this ZP and X never changes in the loop
|
||||||
if (!prevBlock)
|
if (!prevBlock)
|
||||||
return OptimizeSimpleLoopInvariant(proc, full);
|
return OptimizeSimpleLoopInvariant(proc, full);
|
||||||
|
|
||||||
|
bool needRecheck = mIns[ei].mLive & LIVE_CPU_REG_Z;
|
||||||
|
|
||||||
prevBlock->mIns.Push(mIns[si]);
|
prevBlock->mIns.Push(mIns[si]);
|
||||||
exitBlock->mIns.Insert(0, NativeCodeInstruction(mIns[si].mIns, ASMIT_STX, mIns[si]));
|
exitBlock->mIns.Insert(0, NativeCodeInstruction(mIns[si].mIns, ASMIT_STX, mIns[si]));
|
||||||
mIns[si].mType = ASMIT_NOP;
|
mIns[si].mType = ASMIT_NOP;
|
||||||
|
@ -28975,6 +28978,12 @@ bool NativeCodeBasicBlock::OptimizeSimpleLoopInvariant(NativeCodeProcedure* proc
|
||||||
mIns[i].mType = ASMIT_NOP;
|
mIns[i].mType = ASMIT_NOP;
|
||||||
mIns[i].mMode = ASMIM_IMPLIED;
|
mIns[i].mMode = ASMIM_IMPLIED;
|
||||||
|
|
||||||
|
if (needRecheck)
|
||||||
|
{
|
||||||
|
mIns[ei].mLive |= LIVE_CPU_REG_A;
|
||||||
|
mIns.Insert(ei + 1, NativeCodeInstruction(mIns[ei].mIns, ASMIT_ORA, ASMIM_IMMEDIATE, 0));
|
||||||
|
}
|
||||||
|
|
||||||
mIns.Insert(ei + 1, NativeCodeInstruction(mIns[i].mIns, t));
|
mIns.Insert(ei + 1, NativeCodeInstruction(mIns[i].mIns, t));
|
||||||
|
|
||||||
for (int i = 0; i < mIns.Size(); i++)
|
for (int i = 0; i < mIns.Size(); i++)
|
||||||
|
@ -31171,6 +31180,7 @@ bool NativeCodeBasicBlock::OptimizeGenericLoop(NativeCodeProcedure* proc)
|
||||||
NativeCodeBasicBlock* block = lblocks[i];
|
NativeCodeBasicBlock* block = lblocks[i];
|
||||||
|
|
||||||
int yoffset = 0, xoffset = 0, aoffset = 0;
|
int yoffset = 0, xoffset = 0, aoffset = 0;
|
||||||
|
int yskew = 0, xskew = 0;
|
||||||
|
|
||||||
for (int j = 0; j < block->mIns.Size(); j++)
|
for (int j = 0; j < block->mIns.Size(); j++)
|
||||||
{
|
{
|
||||||
|
@ -31189,6 +31199,7 @@ bool NativeCodeBasicBlock::OptimizeGenericLoop(NativeCodeProcedure* proc)
|
||||||
zareg[ins.mAddress] = -1;
|
zareg[ins.mAddress] = -1;
|
||||||
}
|
}
|
||||||
yoffset = 0;
|
yoffset = 0;
|
||||||
|
yskew = 0;
|
||||||
zareg[CPU_REG_Y] = -1;
|
zareg[CPU_REG_Y] = -1;
|
||||||
break;
|
break;
|
||||||
case ASMIT_LDX:
|
case ASMIT_LDX:
|
||||||
|
@ -31202,6 +31213,7 @@ bool NativeCodeBasicBlock::OptimizeGenericLoop(NativeCodeProcedure* proc)
|
||||||
zareg[ins.mAddress] = -1;
|
zareg[ins.mAddress] = -1;
|
||||||
}
|
}
|
||||||
xoffset = 0;
|
xoffset = 0;
|
||||||
|
xskew = 0;
|
||||||
zareg[CPU_REG_X] = -1;
|
zareg[CPU_REG_X] = -1;
|
||||||
break;
|
break;
|
||||||
case ASMIT_STY:
|
case ASMIT_STY:
|
||||||
|
@ -31235,13 +31247,35 @@ bool NativeCodeBasicBlock::OptimizeGenericLoop(NativeCodeProcedure* proc)
|
||||||
zareg[CPU_REG_X] = -1;
|
zareg[CPU_REG_X] = -1;
|
||||||
break;
|
break;
|
||||||
case ASMIT_INC:
|
case ASMIT_INC:
|
||||||
|
if (ins.mMode == ASMIM_ZERO_PAGE)
|
||||||
|
{
|
||||||
|
if (zxreg[ins.mAddress] >= 0)
|
||||||
|
{
|
||||||
|
zxreg[ins.mAddress] += 3;
|
||||||
|
xskew++;
|
||||||
|
}
|
||||||
|
if (zyreg[ins.mAddress] >= 0)
|
||||||
|
{
|
||||||
|
zyreg[ins.mAddress] += 3;
|
||||||
|
yskew++;
|
||||||
|
}
|
||||||
|
|
||||||
|
zareg[ins.mAddress] = -1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
case ASMIT_DEC:
|
case ASMIT_DEC:
|
||||||
if (ins.mMode == ASMIM_ZERO_PAGE)
|
if (ins.mMode == ASMIM_ZERO_PAGE)
|
||||||
{
|
{
|
||||||
if (zxreg[ins.mAddress] >= 0)
|
if (zxreg[ins.mAddress] >= 0)
|
||||||
|
{
|
||||||
zxreg[ins.mAddress] += 3;
|
zxreg[ins.mAddress] += 3;
|
||||||
|
xskew--;
|
||||||
|
}
|
||||||
if (zyreg[ins.mAddress] >= 0)
|
if (zyreg[ins.mAddress] >= 0)
|
||||||
|
{
|
||||||
zyreg[ins.mAddress] += 3;
|
zyreg[ins.mAddress] += 3;
|
||||||
|
yskew--;
|
||||||
|
}
|
||||||
|
|
||||||
zareg[ins.mAddress] = -1;
|
zareg[ins.mAddress] = -1;
|
||||||
}
|
}
|
||||||
|
@ -31335,6 +31369,11 @@ bool NativeCodeBasicBlock::OptimizeGenericLoop(NativeCodeProcedure* proc)
|
||||||
areg = -2;
|
areg = -2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (xreg >= 0 && ins.mMode == ASMIM_ABSOLUTE_X && xskew != xoffset)
|
||||||
|
zxreg[xreg] = -1;
|
||||||
|
if (yreg >= 0 && (ins.mMode == ASMIM_ABSOLUTE_Y || ins.mMode == ASMIM_INDIRECT_Y) && yskew != yoffset)
|
||||||
|
zyreg[yreg] = -1;
|
||||||
|
|
||||||
if (!(ins.mLive & LIVE_CPU_REG_Y))
|
if (!(ins.mLive & LIVE_CPU_REG_Y))
|
||||||
yoffset = 0;
|
yoffset = 0;
|
||||||
if (!(ins.mLive & LIVE_CPU_REG_X))
|
if (!(ins.mLive & LIVE_CPU_REG_X))
|
||||||
|
@ -40154,7 +40193,7 @@ void NativeCodeProcedure::Compile(InterCodeProcedure* proc)
|
||||||
{
|
{
|
||||||
mInterProc = proc;
|
mInterProc = proc;
|
||||||
|
|
||||||
CheckFunc = !strcmp(mInterProc->mIdent->mString, "heapcheck");
|
CheckFunc = !strcmp(mInterProc->mIdent->mString, "test_find");
|
||||||
|
|
||||||
int nblocks = proc->mBlocks.Size();
|
int nblocks = proc->mBlocks.Size();
|
||||||
tblocks = new NativeCodeBasicBlock * [nblocks];
|
tblocks = new NativeCodeBasicBlock * [nblocks];
|
||||||
|
|
Loading…
Reference in New Issue