18 #include "StringBasics.h" 21 #include "MathConstant.h" 28 #define SWP(A,B) {int tmp=a; a=b; b=tmp;} 32 #define vsnprintf _vsnprintf 33 #define snprintf _snprintf 41 #define NATURAL_ORDERING 1 43 int String::alloc = 8;
44 bool String::caseSensitive =
true;
46 void String::NewString(
int startsize)
49 size = (startsize + alloc) / alloc * alloc;
50 buffer =
new char [size];
54 String::String(
const char * s)
56 int clen = s == NULL ? 0 : strlen(s);
61 memcpy(buffer, s, len + 1);
65 String::String(
char ch,
int count)
68 memset(buffer, ch, count);
73 String::String(
const String & s)
76 size = (s.len + alloc) / alloc * alloc;;
77 buffer =
new char [size];
78 memcpy(buffer, s.buffer, len + 1);
81 void String::Grow(
int newSize)
85 if ((newSize >> 1) >= size)
86 size = (newSize + alloc) / alloc * alloc;
90 while (size <= newSize)
94 char * tmp =
new char [size];
97 memcpy(tmp, buffer, len);
104 void String::Swap(
String & s)
106 char * temp = s.buffer;
123 memcpy(buffer, s.buffer, len + 1);
127 String & String::Copy(
const String & s,
int start,
int n)
129 if (s.len <= start)
return Clear();
130 if (s.len < start + n) n = s.len - start;
132 memcpy(buffer, s.buffer + start, n);
137 String & String::Copy(
const char * s)
146 int clen = strlen(s);
149 memcpy(buffer, s, len + 1);
154 String & String::ToUpper()
156 for (
int i = 0; i < len; i++)
157 buffer[i] = (
char) toupper(buffer[i]);
161 String & String::ToLower()
163 for (
int i = 0; i < len; i++)
164 buffer[i] = (
char) tolower(buffer[i]);
172 return temp.ToUpper();
179 return temp.ToLower();
182 String String::Capitalize()
186 temp.buffer[0] = (char) toupper(temp.buffer[0]);
196 String & String::operator = (
const char * rhs)
205 memcpy(buffer + len, rhs.buffer, rhs.len + 1);
210 String & String::operator += (
const char * rhs)
214 int clen = strlen(rhs);
216 memcpy(buffer + len, rhs, clen + 1);
224 String result(len + rhs.len);
225 memcpy(result.buffer, buffer, len);
226 memcpy(result.buffer + len, rhs.buffer, rhs.len + 1);
227 result.len = len + rhs.len;
231 String String::operator + (
const char * rhs)
const 235 int clen = strlen(rhs);
236 String result(len + clen);
237 memcpy(result.buffer, buffer, len);
238 memcpy(result.buffer + len, rhs, clen + 1);
239 result.len = len + clen;
245 String & String::operator = (
char ch)
259 String & String::operator += (
char ch)
270 String String::operator + (
char ch)
const 277 String & String::operator = (
int rhs)
284 *
this += (
unsigned int) -rhs;
287 *
this = (
unsigned int) rhs;
291 String & String::operator = (
unsigned int rhs)
295 unsigned long long base = 10;
308 char ch = char(rhs / base);
309 rhs = rhs - ch * base;
310 buffer[len++] = char(ch +
'0');
316 String String::operator + (
int rhs)
const 323 String String::operator + (
unsigned int rhs)
const 330 String & String::operator += (
int rhs)
334 return *
this += temp;
337 String & String::operator += (
unsigned int rhs)
341 return *
this += temp;
344 String & String::operator *= (
unsigned int rhs)
354 for (
unsigned int i = 1; i < rhs; i++)
360 String & String::operator = (
double rhs)
363 sprintf(buffer,
"%.3f", rhs);
368 String String::operator + (
double rhs)
const 375 String & String::operator += (
double rhs)
379 return *
this += temp;
383 void String::appendFullFloat(
float rhs)
385 std::ostringstream os;
387 *
this += os.str().c_str();
390 char * String::LockBuffer(
int min)
392 if (min > 0) Grow(min);
396 String & String::UnlockBuffer()
398 for (len = 0; len < size; len++)
399 if (buffer[len] == 0)
401 error(
"BasicString - direct access overflowed buffer");
405 int String::Compare(
const String & s)
const 408 return String::FastCompare(s);
410 return String::SlowCompare(s);
413 int String::Compare(
const char * s)
const 415 return caseSensitive ? FastCompare(s) : SlowCompare(s);
418 int String::FastCompare(
const String & s)
const 420 for (
int i = 0; i <= len; i++)
421 if (buffer[i] - s.buffer[i])
423 #ifdef NATURAL_ORDERING 425 while (isdigit(buffer[d]) && isdigit(s.buffer[d]))
427 if (isdigit(buffer[d]))
429 if (isdigit(s.buffer[d]))
432 return buffer[i] - s.buffer[i];
437 int String::FastCompare(
const char * s)
const 442 for (
int i = 0; i <= len; i++)
443 if (buffer[i] - s[i])
445 #ifdef NATURAL_ORDERING 447 while (isdigit(buffer[d]) && isdigit(s[d]))
449 if (isdigit(buffer[d]))
454 return buffer[i] - s[i];
459 int String::SlowCompare(
const String & s)
const 461 for (
int i = 0; i <= len; i++)
462 if (toupper(buffer[i]) - toupper(s.buffer[i]))
464 #ifdef NATURAL_ORDERING 466 while (isdigit(buffer[d]) && isdigit(s[d]))
468 if (isdigit(buffer[d]))
470 if (isdigit(s.buffer[d]))
473 return toupper(buffer[i]) - toupper(s.buffer[i]);
478 int String::SlowCompare(
const char * s)
const 483 for (
int i = 0; i <= len; i++)
484 if (toupper(buffer[i]) - toupper(s[i]))
486 #ifdef NATURAL_ORDERING 488 while (isdigit(buffer[d]) && isdigit(s[d]))
490 if (isdigit(buffer[d]))
495 return toupper(buffer[i]) - toupper(s[i]);
500 int String::ReadLine(FILE * f)
505 if (f == NULL)
return -1;
508 char check[2] = {0, 0};
511 String format(
"%128[^\n\r]%1[\n\r]");
517 while (check[0] !=
'\n' && check[0] !=
'\r')
522 format.printf(
"%%%d%s", step,
"[^\n\r]%1[\n\r]");
526 io = fscanf(f, format, LockBuffer(clen) + len, check);
529 if (io == 0 && check[0] !=
'\n' && check[0] !=
'\r')
530 io = fscanf(f,
"%1[\n\r]", check);
531 if (io == 0 || io == EOF)
539 if (check[0] ==
'\n') io = fscanf(f,
"%*1[\r]");
540 if (check[0] ==
'\r') io = fscanf(f,
"%*1[\n]");
546 String & String::Read(FILE * f)
551 if (f == NULL)
return *
this;
554 char check[2] = {
'G', 0};
556 while (strchr(WHITESPACE, check[0]) == NULL)
559 int io = fscanf(f,
" %" READBUFSTR
"[^" WHITESPACE
"]" 560 "%1[" WHITESPACE
"]", LockBuffer(clen) + len, check);
561 if (io == 0 || io == EOF)
break;
578 if (f == NULL)
return *
this;
588 if (strchr(WHITESPACE, ch) != NULL)
603 buffer[len++] = (char) ch;
612 int String::ReadLine()
663 buffer[len++] = (char) last;
667 if ((ch == EOF) && (len == 0))
681 int String::ReadLine(
IFILE & f)
732 buffer[len++] = (char) last;
736 if ((ch == EOF) && (len == 0))
744 int String::ReadLine(
IFILE & f)
748 char *endBuffer = buffer + size;
751 while ( ((ch = f->
ifgetc()) != EOF) && (ch !=
'\n'))
753 if (ptr >= endBuffer - 1)
758 endBuffer = buffer + size;
769 if ((ch == EOF) && (len == 0))
778 void String::Write(FILE * f)
780 fprintf(f,
"%s", buffer);
788 void String::WriteLine()
793 void String::WriteLine(FILE * f)
795 if (f == NULL)
return;
796 fprintf(f,
"%s\n", buffer);
801 return os << s.c_str();
804 String String::Left(
int n)
const 807 if (len < n) n = len;
809 memcpy(result.buffer, buffer, n);
810 result.buffer[result.len = n] = 0;
814 String String::Right(
int n)
const 817 if (len < n) n = len;
819 memcpy(result.buffer, buffer + len - n, n);
820 result.buffer[result.len = n] = 0;
824 String String::SubStr(
int start,
int n)
const 831 n = min(len - start, n);
834 if (start > len)
return result;
835 memcpy(result.buffer, buffer + start, n);
836 result.buffer[result.len = n] = 0;
840 String String::SubStr(
int start)
const 842 return SubStr(start, len - start);
845 String String::Mid(
int start,
int end)
const 847 return SubStr(start, end - start + 1);
850 int String::FindChar(
char ch,
int start)
const 852 return caseSensitive ? FastFindChar(ch, start) : SlowFindChar(ch, start);
855 int String::FastFindChar(
char ch,
int start)
const 857 for (; start < len; start++)
858 if (buffer[start] == ch)
863 int String::SlowFindChar(
char ch,
int start)
const 865 ch = (char) toupper(ch);
866 for (; start < len; start++)
867 if (toupper(buffer[start]) == ch)
872 int String::FindLastChar(
char ch)
const 874 return caseSensitive ? FastFindLastChar(ch) : SlowFindLastChar(ch);
877 int String::FastFindLastChar(
char ch)
const 879 for (
int start = len-1; start >= 0; start--)
880 if (buffer[start] == ch)
885 int String::SlowFindLastChar(
char ch)
const 887 ch = (char) toupper(ch);
888 for (
int start = len-1 ; start >= 0; start--)
889 if (toupper(buffer[start]) == ch)
894 int String::Find(
const String & pattern,
int start)
const 896 return caseSensitive ? FastFind(pattern, start) : SlowFind(pattern, start);
901 int String::FastFind(
const String & pattern,
int start)
const 903 for (
int i ; start <= len - pattern.Length(); start++)
904 if (buffer[start] == pattern[0])
906 for (i = 1; i < pattern.Length(); i++)
907 if (pattern[i] != buffer[start + i])
909 if (i == pattern.Length())
return start;
914 int String::SlowFind(
const String & pattern,
int start)
const 916 int firstchar = toupper(pattern[0]);
918 for (
int i ; start <= len - pattern.Length(); start++)
919 if (toupper(buffer[start]) == firstchar)
921 for (i = 1; i < pattern.Length(); i++)
922 if (toupper(pattern[i]) != toupper(buffer[start + i]))
924 if (i == pattern.Length())
return start;
929 int String::SetLength(
int newlen)
934 memset(buffer + len,
' ', newlen - len);
943 for (
int from = 0; from < len; from++)
944 if (s.FindChar(buffer[from]) != -1)
945 buffer[to++] = buffer[from];
946 buffer[len = to] = 0;
950 String & String::Filter(
const char * s)
953 return Filter(filter);
959 for (
int from = 0; from < len; from++)
960 if (s.FindChar(buffer[from]) == -1)
961 buffer[to++] = buffer[from];
962 buffer[len = to] = 0;
966 String & String::ExcludeCharacters(
const char * s)
969 return ExcludeCharacters(excluded);
972 String operator + (
const char * lhs,
const String & rhs)
994 String operator + (
unsigned int lhs,
const String & rhs)
1002 long String::AsInteger()
const 1004 long returnValue = 0;
1005 if(!AsInteger(returnValue))
1009 return(returnValue);
1015 bool String::AsInteger(
long& intValue)
const 1029 if (buffer[pos] ==
'-')
1034 if ((len > pos + 2) && (buffer[pos] ==
'0') &&
1035 ((buffer[pos+1] ==
'x') || (buffer[pos+1] ==
'X')))
1037 base = 16, pos += 2;
1046 for (; pos < len; pos++)
1048 char digit = (char) toupper(buffer[pos]);
1050 if (digit >=
'0' && digit <=
'9')
1052 integer = integer * base + digit -
'0';
1054 else if (digit >=
'A' && digit <=
'F' && base == 16)
1056 integer = integer * base + digit -
'A' + 10;
1065 intValue = sign*integer;
1073 bool String::AsInteger(
int& intValue)
const 1087 if (buffer[pos] ==
'-')
1092 if ((len > pos + 2) && (buffer[pos] ==
'0') &&
1093 ((buffer[pos+1] ==
'x') || (buffer[pos+1] ==
'X')))
1095 base = 16, pos += 2;
1104 for (; pos < len; pos++)
1106 char digit = (char) toupper(buffer[pos]);
1108 if (digit >=
'0' && digit <=
'9')
1110 integer = integer * base + digit -
'0';
1112 else if (digit >=
'A' && digit <=
'F' && base == 16)
1114 integer = integer * base + digit -
'A' + 10;
1123 intValue = sign*integer;
1129 String & String::Invert()
1131 for (
int i = 0, j = len - 1; i < j; i++, j--)
1133 char tmp = buffer[i];
1134 buffer[i] = buffer[j];
1140 String String::RightToLeft()
1153 int String::CompareToStem(
const String & stem)
const 1156 return String::FastCompareToStem(stem);
1158 return String::SlowCompareToStem(stem);
1161 int String::FastCompareToStem(
const String & stem)
const 1163 for (
int i = 0; i < stem.len; i++)
1164 if (buffer[i] - stem.buffer[i])
1166 #ifdef NATURAL_ORDERING 1168 while (isdigit(buffer[d]) && isdigit(stem.buffer[d]) && d < stem.len)
1170 if (isdigit(buffer[d]) && d < stem.len)
1172 if (isdigit(stem.buffer[d]))
1175 return buffer[i] - stem.buffer[i];
1180 int String::SlowCompareToStem(
const String & stem)
const 1182 for (
int i = 0; i < stem.len; i++)
1183 if (toupper(buffer[i]) - toupper(stem.buffer[i]))
1185 #ifdef NATURAL_ORDERING 1187 while (isdigit(buffer[d]) && isdigit(stem.buffer[d]) && d < stem.len)
1189 if (isdigit(buffer[d]) && d < stem.len)
1191 if (isdigit(stem.buffer[d]))
1194 return toupper(buffer[i]) - toupper(stem.buffer[i]);
1199 int String::CompareToStem(
const char * stem)
const 1202 return String::FastCompareToStem(stem);
1204 return String::SlowCompareToStem(stem);
1207 int String::FastCompareToStem(
const char * stem)
const 1209 for (
int i = 0; stem[i] != 0; i++)
1210 if (buffer[i] - stem[i])
1211 return buffer[i] - stem[i];
1215 int String::SlowCompareToStem(
const char * stem)
const 1217 for (
int i = 0; stem[i] != 0; i++)
1218 if (toupper(buffer[i]) - toupper(stem[i]))
1219 return toupper(buffer[i]) - toupper(stem[i]);
1223 int String::MatchesBeginningOf(
const String & stem)
const 1226 return String::FastMatchesBeginningOf(stem);
1228 return String::SlowMatchesBeginningOf(stem);
1231 int String::FastMatchesBeginningOf(
const String & stem)
const 1233 for (
int i = 0; i < len; i++)
1234 if (buffer[i] - stem.buffer[i])
1235 return buffer[i] - stem.buffer[i];
1239 int String::SlowMatchesBeginningOf(
const String & stem)
const 1241 for (
int i = 0; i < len; i++)
1242 if (toupper(buffer[i]) - toupper(stem.buffer[i]))
1243 return toupper(buffer[i]) - toupper(stem.buffer[i]);
1247 int String::MatchesBeginningOf(
const char * stem)
const 1250 return String::FastMatchesBeginningOf(stem);
1252 return String::SlowMatchesBeginningOf(stem);
1255 int String::FastMatchesBeginningOf(
const char * stem)
const 1257 for (
int i = 0; i < len; i++)
1258 if (buffer[i] - stem[i])
1259 return buffer[i] - stem[i];
1263 int String::SlowMatchesBeginningOf(
const char * stem)
const 1265 for (
int i = 0; i < len; i++)
1266 if (toupper(buffer[i]) - toupper(stem[i]))
1267 return toupper(buffer[i]) - toupper(stem[i]);
1271 String & String::Trim(
char character)
1274 while (buffer[first] && buffer[first] == character)
1278 while (last >= 0 && buffer[last] == character)
1282 while (first <= last)
1283 buffer[out++] = buffer[first++];
1285 buffer[len = out] = 0;
1293 while (buffer[first] && isspace(buffer[first]))
1297 while (last >= 0 && isspace(buffer[last]))
1301 while (first <= last)
1302 buffer[out++] = buffer[first++];
1304 buffer[len = out] = 0;
1309 vector<String> *String::Split(
char splitChar)
1311 vector<String> *result =
new vector<String>;
1314 for (
int i = 0; i<Length(); i++)
1316 if ((*
this)[i]==splitChar)
1318 result->push_back(word);
1322 word.Add((*
this)[i]);
1324 if (word.Length()>0) result->push_back(word);
1329 #define VSNPRINTF_NOT_CHECKED 0 1330 #define VSNPRINTF_IS_OK 1 1331 #define VSNPRINTF_NOT_OK 2 1333 int String::vsnprintfChecked = 0;
1335 int String::printf(
const char * format, ...)
1338 va_start(ap, format);
1340 vprintf(format, ap);
1346 int String::catprintf(
const char * format, ...)
1349 va_start(ap, format);
1351 vcatprintf(format, ap);
1357 int String::vprintf(
const char * format, va_list ap)
1366 va_copy(arguments, ap);
1368 va_list & arguments = ap;
1371 if (vsnprintfChecked == VSNPRINTF_IS_OK)
1372 bytes_needed = vsnprintf(buffer, size, format, arguments);
1374 bytes_needed = my_vsnprintf(buffer, size, format, arguments);
1380 if (bytes_needed >= size)
1382 else if (bytes_needed == -1)
1386 return len = bytes_needed;
1391 void String::check_vsnprintf()
1393 if (vsnprintfChecked == VSNPRINTF_NOT_CHECKED)
1397 memset(temp, 0, 100);
1398 int check = snprintf(temp, 5,
"%5s",
"VSNPRINTF");
1400 if (temp[6] != 0 || temp[7] != 0 || (check != 9 && check != -1))
1407 vsnprintfChecked = VSNPRINTF_NOT_OK;
1409 vsnprintfChecked = VSNPRINTF_IS_OK;
1413 int String::vcatprintf(
const char * format, va_list ap)
1425 va_copy(arguments, ap);
1427 va_list & arguments = ap;
1430 if (vsnprintfChecked == VSNPRINTF_IS_OK)
1431 bytes_needed = len + vsnprintf(buffer + len, size - len, format, arguments);
1433 bytes_needed = len + my_vsnprintf(buffer + len, size - len, format, arguments);
1439 if (bytes_needed >= size)
1441 else if (bytes_needed < len)
1445 return len = bytes_needed;
1450 FILE * String::my_vsnprintf_file = NULL;
1452 int String::my_vsnprintf(
char * buffer,
int bufsize,
const char * format, va_list args)
1454 if (my_vsnprintf_file == NULL)
1456 my_vsnprintf_file = tmpfile();
1457 atexit(my_vsnprintf_close_file);
1460 rewind(my_vsnprintf_file);
1462 int len = vfprintf(my_vsnprintf_file, format, args);
1464 rewind(my_vsnprintf_file);
1467 buffer[bufsize = len] = 0;
1468 int numRead = fread(buffer, 1, bufsize, my_vsnprintf_file);
1469 if(numRead != bufsize)
1472 <<
"Warning, StringBasics failed reading stream in my_vsnprintf\n";
1477 int String::my_snprintf(
char * buffer,
int bufsize,
const char * format, ...)
1480 va_start(ap, format);
1482 int bytes = my_vsnprintf(buffer, bufsize, format, ap);
1489 void String::my_vsnprintf_close_file()
1491 fclose(my_vsnprintf_file);
1494 bool String::IsNumber()
1497 bool digits =
false;
1500 if (buffer[pos] ==
'-' || buffer[pos] ==
'+')
1504 while (buffer[pos] >=
'0' && buffer[pos] <=
'9')
1505 pos++, digits =
true;
1508 if (buffer[pos] ==
'.')
1513 while (buffer[pos] >=
'0' && buffer[pos] <=
'9')
1514 pos++, digits =
true;
1517 if (!digits)
return false;
1520 if (buffer[pos] ==
'E' || buffer[pos] ==
'e')
1525 if (buffer[pos] ==
'-' || buffer[pos] ==
'+')
1531 while (buffer[pos] >=
'0' && buffer[pos] <=
'9')
1532 pos++, digits =
true;
1535 return (pos == len) && digits;
1538 void String::Fill(
char ch,
int length)
1543 for (
int i = 0; i < len; i++)
1547 String & String::Reverse()
1549 for (
int i = 0, j = len - 1; i < j; i++, j--)
1551 int tmp = buffer[i];
1552 buffer[i] = buffer[j];
1561 String & String::LeftClip(
int clipAmount)
1563 if (clipAmount == 0)
1566 if (clipAmount > Length())
1573 memmove(buffer, buffer + clipAmount, len - clipAmount);
1574 buffer[len -= clipAmount] = 0;
1579 String & String::RightClip(
int clipAmount)
1581 if (clipAmount == 0)
return *
this;
1583 if (clipAmount > Length())
1598 String::operator
long double()
const 1600 return strtold(buffer, NULL);
1604 String::operator
long double()
const 1606 return _strtold(buffer, NULL);
1609 String::operator
long double()
const 1611 return atof(buffer);