00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include <ctype.h>
00026 #include <stdio.h>
00027
00028 #ifdef SunOS
00029 #include <sys/varargs.h>
00030 #else
00031 #include <stdarg.h>
00032 #endif
00033
00034 #include "magic/mobject.h"
00035 #include "magic/mstring.h"
00036 #include "magic/mclass.h"
00037 #include "magic/mregexp.h"
00038
00039
00040 impl_dynamic (String, {Comparable});
00041
00042
00044
00045
00046
00047
00048
00049
00051
00052 MagiC::String::String () {
00053 mLen = 0;
00054 mMaxLen = 0;
00055 mData = NULL;
00056 mChkSum = 0;
00057 }
00058
00060 MagiC::String::String (const String& orig) {
00061 if (&orig == NULL || orig.mData==NULL) {
00062 mLen = 0;
00063 mMaxLen = 0;
00064 mData = NULL;
00065 return;
00066 }
00067 mLen = orig.mLen;
00068 mMaxLen = orig.mMaxLen;
00069 mData = new char [mMaxLen+1];
00070 memcpy (mData, orig.mData, mMaxLen+1);
00071 mChkSum = 0;
00072 }
00073
00075 MagiC::String::String (const char* chrp) {
00076 if (chrp) {
00077 mLen = strlen (chrp);
00078 mMaxLen = mLen;
00079 mData = new char [mMaxLen+1];
00080 memcpy (mData, chrp, mLen+1);
00081 } else {
00082 mLen = mMaxLen = 0;
00083 mData = NULL;
00084 }
00085 mChkSum = 0;
00086 }
00087
00093 MagiC::String::String (char* str, bool own) {
00094 mData = str;
00095 mLen = mMaxLen = str? strlen (str) : 0;
00096 mChkSum = 0;
00097 }
00098
00101 MagiC::String::String (const char* chrp, int n) {
00102 if (chrp && n) {
00103 mLen = n;
00104 mMaxLen = mLen;
00105 mData = new char [mMaxLen+1];
00106 memcpy (mData, chrp, mLen);
00107 mData [mMaxLen] = 0x00;
00108 } else {
00109 mLen = mMaxLen = 0;
00110 mData = NULL;
00111 }
00112 mChkSum = 0;
00113 }
00114
00123 MagiC::String::String (char* str, uint maxLen, bool own) {
00124 if (own)
00125 mData = str;
00126 else
00127 mData = strdup (str);
00128 mData[maxLen] = '\0';
00129 mLen = str? strlen (str) : 0;
00130 mMaxLen = maxLen;
00131 mChkSum = 0;
00132 }
00133
00134 MagiC::String::~String () {
00135 if (mData) delete mData;
00136 mData = (char*) 0xdddddddd;
00137 }
00138
00139 template<class TYPE>
00140 inline char* intToString(TYPE value, uint base) {
00141 const char digits[] = "0123456789abcdefghijklmnopqrstuvwxyz";
00142 if (base > sizeof(digits))
00143 throw Exception (strformat ("Too large base %d for integer-to-String conversion", base));
00144
00145 const int maxintlen = 40;
00146 char buf[maxintlen];
00147 char* loc = buf + (maxintlen-1);
00148 *(loc--) = '\x00';
00149
00150 bool isNeg = false;
00151 if (value < 0) {
00152 isNeg = true;
00153 value = -value;
00154 }
00155
00156 do {
00157 *(loc--) = digits [value % base];
00158 value /= base;
00159 } while (value);
00160
00161 if (isNeg)
00162 *(loc--) = '-';
00163
00164 return strdup (loc+1);
00165 }
00166
00168 MagiC::String::String (int i, int base) {
00169 mData = intToString<int> (i, base);
00170 mLen = mMaxLen = strlen(mData);
00171 mChkSum = 0;
00172 }
00173
00175 MagiC::String::String (uint i, int base) {
00176 mData = intToString<uint> (i, base);
00177 mLen = mMaxLen = strlen(mData);
00178 mChkSum = 0;
00179 }
00180
00182 MagiC::String::String (long i, int base) {
00183 mData = intToString<long> (i, base);
00184 mLen = mMaxLen = strlen(mData);
00185 mChkSum = 0;
00186 }
00187
00188 template <class TYPE>
00189 inline char* formatFloat(TYPE f, char fmt, int prec) {
00190
00191 char formatBuf [20];
00192 if (prec >= 0)
00193 sprintf (formatBuf, "%%.%d%c", prec, fmt);
00194 else
00195 sprintf (formatBuf, "%%%c", fmt);
00196
00197
00198 char buf [80+prec];
00199 sprintf (buf, formatBuf, f);
00200
00201 return strdup (buf);
00202 }
00203
00205 MagiC::String::String (float f, char fmt, int prec) {
00206 mData = formatFloat<float> (f, fmt, prec);
00207 mLen = mMaxLen = strlen(mData);
00208 mChkSum = 0;
00209 }
00210
00212 MagiC::String::String (double f, char fmt, int prec) {
00213 mData = formatFloat<double> (f, fmt, prec);
00214 mLen = mMaxLen = strlen(mData);
00215 mChkSum = 0;
00216 }
00217
00219 String& MagiC::String::assign (char c) {
00220 if (!mData)
00221 mData = new char [2];
00222 mData[0] = c;
00223 mData[1] = '\x00';
00224 mLen = 1;
00225 mChkSum = 0;
00226 return *this;
00227 }
00228
00233 String& MagiC::String::operator= (const String& other) {
00234 if (&other == NULL || other.mData==NULL || other.mLen==0) {
00235
00236 if (mData) {
00237 mLen = 0;
00238 mMaxLen = 0;
00239 *mData = '\x00';
00240 }
00241 } else {
00242
00243 mLen = other.mLen;
00244 if (mLen > mMaxLen) {
00245 if (mData)
00246 delete mData;
00247 mMaxLen = mLen;
00248 mData = new char [mMaxLen+1];
00249 }
00250 memcpy (mData, other.mData, mLen+1);
00251 }
00252 mChkSum = other.mChkSum;
00253 return *this;
00254 }
00255
00260 String& MagiC::String::operator= (const char* chrp) {
00261 if (!chrp || !*chrp) {
00262
00263 if (mData) {
00264 mLen = 0;
00265 mMaxLen = 0;
00266 *mData = '\x00';
00267 }
00268 } else {
00269
00270 mLen = strlen (chrp);
00271 if (mLen > mMaxLen) {
00272 if (mData)
00273 delete mData;
00274 mMaxLen = mLen;
00275 mData = new char [mMaxLen+1];
00276 }
00277 memcpy (mData, chrp, mLen+1);
00278 }
00279 mChkSum = 0;
00280 return *this;
00281 }
00282
00283 ostream& MagiC::String::dump (ostream& out) const {
00284 out << format ("String #0x%x\n");
00285 out << "mData=" << mData << "\n";
00286 out << "mLen=" << mLen << "\n";
00287 out << "mMaxLen=" << mMaxLen << "\n";
00288 return out;
00289 }
00290
00296 ostream& MagiC::String::operator>> (ostream& out) const {
00297
00298 out << mData;
00299 return out;
00300 }
00301
00307 istream& MagiC::String::operator<< (istream& is) {
00308 mLen = 0;
00309 if (mData)
00310 mData[0] = '\x00';
00311 ensure_spontane (80);
00312
00313 int w = is.width (0);
00314 if (is.ipfx0 ()) {
00315 register streambuf *sb = is.rdbuf ();
00316 while (1) {
00317 int ch = sb->sbumpc ();
00318 if (ch == EOF) {
00319 is.setstate (ios::eofbit);
00320 break;
00321 } else if (isspace (ch)) {
00322 sb->sungetc ();
00323 break;
00324 }
00325 (*this) += ch;
00326 if (--w == 1)
00327 break;
00328 }
00329 }
00330 is.isfx ();
00331 if (mLen == 0)
00332 is.setstate (ios::failbit);
00333
00334 return is;
00335 }
00336
00337 CArchive& MagiC::String::operator>> (CArchive& arc) const {
00338 arc.name ("mLen") << mLen;
00339 arc.name ("mMaxLen") << mMaxLen;
00340 if (mLen)
00341 arc.name ("mData").write (mData, mLen+1);
00342 else
00343 arc.name ("mData").write (mData, 0);
00344 return arc;
00345 }
00346
00347 IStream& MagiC::String::operator<< (IStream& arc) {
00348 arc >> mLen;
00349 arc >> mMaxLen;
00350 delete mData;
00351 mData=NULL;
00352 mChkSum = 0;
00353 if (mLen) {
00354 mData = new char [mMaxLen+1];
00355 arc.read (mData, mLen+1);
00356 }
00357 mChkSum=0;
00358 return arc;
00359 }
00360
00362 String MagiC::String::operator+ (const String& other) const {
00363 String result = *this;
00364 result += other;
00365 return result;
00366 }
00367
00369 String MagiC::String::operator+ (const char* str) const {
00370 String result = *this;
00371 result += String(str);
00372 return result;
00373 }
00374
00378 bool findLowestNum (const String& str, uint& start, uint& end) {
00379
00380 enum states {NORMAL=0, FOUNDPERCENT};
00381 int state = NORMAL;
00382 int number = 0;
00383 int curPos = 0;
00384 int lowest = 999999;
00385 start = 0;
00386 end = 0;
00387
00388 for (int i=0; i<str.length(); i++) {
00389 switch (state) {
00390 case NORMAL:
00391 if (str[i] == '%') {
00392 state = FOUNDPERCENT;
00393 number = 0;
00394 curPos = i;
00395 }
00396 break;
00397 case FOUNDPERCENT:
00398 if (isdigit(str[i]))
00399 number = number*10 + int(str[i]-'0');
00400 else {
00401 if (number < lowest) {
00402
00403 lowest = number;
00404 start = curPos;
00405 end = i;
00406 }
00407 state = NORMAL;
00408 }
00409 break;
00410 }
00411 }
00412 if (state == FOUNDPERCENT && number < lowest) {
00413
00414 start = curPos;
00415 end = str.length();
00416 lowest = 0;
00417 }
00418
00419 return (lowest!=999999);
00420 }
00421
00423 String MagiC::String::arg (const String& replacement, int fieldwidth) const {
00424 uint start, end;
00425 if (findLowestNum (*this, start, end)) {
00426 int realwidth = (replacement.length()>fieldwidth)? replacement.length() : fieldwidth;
00427 int maxLen = start + realwidth + (length()-end);
00428 char* buf = new char[maxLen + 1];
00429 char* resultPos = buf;
00430
00431
00432 if (start>0) {
00433 memcpy (resultPos, mData, start);
00434 resultPos += start;
00435 }
00436
00437
00438 if (realwidth>0) {
00439 for (int padding = (realwidth>fieldwidth)? 0 : fieldwidth-replacement.length(); padding>0; padding--)
00440 *(resultPos++) = ' ';
00441 memcpy (resultPos, replacement.mData, replacement.length());
00442 resultPos += replacement.length();
00443 }
00444
00445
00446 if (end < mLen) {
00447 memcpy (resultPos, mData+end, mLen-end);
00448 resultPos += mLen-end;
00449 }
00450 *resultPos = '\x00';
00451
00452
00453 return String (buf, maxLen, true);
00454 } else
00455
00456 return *this;
00457 }
00458
00470 String& MagiC::String::dellast (uint n) {
00471 if (!mData)
00472 return *this;
00473
00474
00475 if (n>=mLen)
00476 n = mLen;
00477 mLen -= n;
00478 mData[mLen] = 0;
00479 mChkSum = 0;
00480 return *this;
00481 }
00482
00484 void MagiC::String::chop () {
00485 while (mLen>0 && isspace(mData[mLen-1]))
00486 dellast (1);
00487 mChkSum=0;
00488 }
00489
00495 int MagiC::String::fast_isequal (const String& other) const {
00496 if (other.mChkSum == mChkSum)
00497 return operator== (other.mData);
00498 else
00499 return 0;
00500 }
00501
00508 String& MagiC::String::hexcode (const String& other) {
00509 const char hexcodes[] = "0123456789abcdef";
00510 int otherlen = other.length();
00511 ensure (otherlen*2);
00512 for (int i=0; i<otherlen; i++) {
00513 *this += hexcodes [((unsigned int) other.mData[i])/16];
00514 *this += hexcodes [((unsigned int) other.mData[i])%16];
00515 }
00516 mChkSum=0;
00517 return *this;
00518 }
00519
00526 void MagiC::String::quote (char quotechar='%', int flags=0) {
00527 FORBIDDEN;
00528 }
00529
00537 void MagiC::String::unquote (char quotechar, int flags) {
00538 enum {Waiting, GotEqual, GotFirst, GotSoftLinebreak};
00539 String hextable = "0123456789ABCDEF";
00540 int state = Waiting,
00541 value = 0,
00542 respos = 0;
00543
00544
00545
00546 String tmp;
00547 tmp.reserve (mLen);
00548
00549
00550 for (int i=0 ; i<mLen ; i++) {
00551 char c=(*this)[i];
00552 switch (state) {
00553 case Waiting:
00554 if (c == quotechar)
00555 state=GotEqual;
00556 else
00557 if (c=='+' && (flags"E_HTML))
00558 tmp += ' ';
00559 else
00560 tmp += c;
00561 break;
00562 case GotEqual:
00563 if ((value=hextable.find(c)) != -1) {
00564 state=GotFirst;
00565 value*=16;
00566 } else {
00567 if (c=='\r') {
00568 state = GotSoftLinebreak;
00569 } else {
00570
00571
00572 state = Waiting;
00573 tmp += quotechar;
00574 tmp += c;
00575 }
00576 }
00577 break;
00578 case GotFirst:
00579 if (hextable.find(c) != -1) {
00580 value+=hextable.find (c);
00581 tmp += char(value);
00582 state=Waiting;
00583 } else {
00584
00585 tmp += quotechar;
00586 tmp += char(value);
00587 tmp += c;
00588 state = Waiting;
00589 }
00590 break;
00591 case GotSoftLinebreak:
00592
00593 if (c!='\n')
00594
00595 tmp += c;
00596 state=Waiting;
00597 break;
00598 };
00599 }
00600
00601 if (state!= Waiting) {
00602
00603 tmp += '=';
00604 if (state==GotFirst)
00605
00606
00607 tmp += char(hextable[state/16]);
00608 }
00609
00610
00611
00612
00613
00614 (*this) = tmp;
00615 }
00616
00618 String MagiC::String::mid (uint from, int n) const {
00619 String result;
00620
00621
00622 if (n==-1)
00623 n = mLen-from;
00624
00625
00626 if (from >= mLen || mLen==0)
00627 return "";
00628
00629
00630 if (((from + n) > mLen))
00631 n = mLen-from;
00632
00633 ASSERT (mMaxLen>=n);
00634
00635
00636 result.mLen = n;
00637 result.mMaxLen = mMaxLen;
00638 result.mData = new char [mMaxLen+1];
00639 strncpy (result.mData, mData+from, n);
00640 result.mData [n] = 0;
00641
00642 return result;
00643 }
00644
00646 String MagiC::String::left (uint n) const {
00647 return mid (0, n);
00648 }
00649
00651 String MagiC::String::right (uint n) const {
00652 String result;
00653
00654 if (n < mLen)
00655 result = mid (mLen-n);
00656 else
00657 result = *this;
00658
00659 return result;
00660 }
00661
00666 int MagiC::String::find (const String& subs, uint n) const {
00667 for (int i=n; i <= (mLen-subs.mLen); i++)
00668 if (!strncmp (mData+i, subs.mData, subs.mLen))
00669 return i;
00670 return -1;
00671 }
00672
00677 int MagiC::String::find (const char c, uint n) const {
00678 char* pos = (char*) memchr (mData+n, c, mLen);
00679 return pos? pos-mData : -1;
00680 }
00681
00689 int MagiC::String::findRev (const String& subs, int n) const {
00690 if (n<0)
00691 n += mLen;
00692 for (int i=n; i>=0; i--)
00693 if (!strncmp (mData+i, subs.mData, subs.mLen))
00694 return i;
00695 return -1;
00696 }
00697
00698 String* MagiC::String::clone () const {
00699 return new String (*this);
00700 }
00701
00703 String& MagiC::String::operator+= (const String& other) {
00704
00705 if (!other.mLen)
00706 return *this;
00707
00708
00709 if (mLen+other.mLen > mMaxLen)
00710 ensure (mLen + other.mLen + 1);
00711
00712 memcpy (mData+mLen, other.mData, other.mLen+1);
00713 mLen += other.mLen;
00714 mData[mLen]='\x00';
00715 mChkSum=0;
00716 return *this;
00717 }
00718
00720 int MagiC::String::operator== (const char* other) const {
00721 if (!this)
00722 return 0;
00723 if (mData && other)
00724 return (!strcmp (mData, other));
00725 if ((!mData) && (!other))
00726 return 1;
00727 return 0;
00728 }
00729
00734 int MagiC::String::operator== (const Comparable& other) const {
00735 if (getclass().issameclass (other))
00736 return operator== ((const String&) other);
00737 else
00738 return 0;
00739 }
00740
00746 String& MagiC::String::operator+= (char c) {
00747 ensure_spontane (mLen+1);
00748 mData [mLen++] = c;
00749 mData [mLen] = 0;
00750 mChkSum=0;
00751 return *this;
00752 }
00753
00757 void MagiC::String::reserve (int amount) {
00758 if (mData) {
00759 char* newmData = new char [amount+1];
00760 if (!newmData)
00761 throw runtime_error ("Out of memory or something in MagiC::String::reserve()");
00762 memcpy (newmData, mData, mLen+1);
00763 delete mData;
00764 mData = newmData;
00765 mData [amount] = 0x00;
00766 } else {
00767 mData = new char[amount+1];
00768 if (!mData)
00769 throw runtime_error ("Out of memory or something in MagiC::String::reserve()");
00770 *mData = 0x00;
00771 }
00772 mMaxLen = amount;
00773 }
00774
00792
00793
00794
00795
00796
00797
00798
00799
00800
00802
00803
00804
00805
00806
00807
00808
00809
00810
00811
00812
00816 void MagiC::String::split (Array<String>& trg, const char delim) const {
00817 if (!this || !mLen)
00818 return;
00819 char* tmp = new char [mLen+1];
00820 memcpy (tmp, mData, mLen+1);
00821 tmp[mLen]=0;
00822 for (int i=0; i<mLen; i++)
00823 if (tmp[i]==delim)
00824 tmp[i]=0;
00825 trg.empty ();
00826 for (int pos = 0, i=0; pos<mLen; pos+=strlen (tmp+pos)+1, i++) {
00827 String tmps = tmp+pos;
00828 trg.put (tmps, i);
00829 }
00830 delete tmp;
00831 }
00832
00836 void MagiC::String::join (const Array<String>& src, const char delim) {
00837
00838 int newlen = src.size-1;
00839 for (int i=0; i<src.size; i++)
00840 newlen += src[i].length();
00841
00842
00843 reserve (newlen);
00844 *this = "";
00845
00846
00847 for (int i=0; i<src.size; i++)
00848 if (!src[i].isEmpty ()) {
00849 *this += src[i];
00850 if (i<src.size-1)
00851 *this += delim;
00852 }
00853
00854 mChkSum=0;
00855 }
00856
00860 String MagiC::String::stripWhiteSpace () const {
00861 int s=0, e=mLen;
00862 while (s<mLen && strchr (" \t\r\n",(*this)[s]))
00863 s++;
00864 while (e>s && strchr (" \t\r\n",(*this)[e-1]))
00865 e--;
00866 return mid (s, e-s);
00867 }
00868
00873 String MagiC::String::simplifyWhiteSpace () const {
00874 if (mLen == 0)
00875 return String();
00876
00877 char* buffer = new char[mLen+1];
00878 char* trgPos = buffer;
00879 int pos = 0;
00880
00881
00882 for (pos=0; pos<mLen; pos++)
00883 if (!isspace(mData[pos]))
00884 break;
00885
00886
00887 bool oneWhitespace=false;
00888 for (; pos<mLen; pos++) {
00889 if (isspace(mData[pos])) {
00890 if (!oneWhitespace)
00891 *(trgPos++) = mData[pos];
00892 oneWhitespace = true;
00893 } else {
00894 *(trgPos++) = mData[pos];
00895 oneWhitespace = false;
00896 }
00897 }
00898
00899
00900 if (isspace (*(trgPos-1)))
00901 trgPos--;
00902 *trgPos = '\x00';
00903
00904 if (trgPos > buffer)
00905
00906 return String (buffer, mLen+1, true);
00907 else {
00908
00909 delete buffer;
00910 return String ();
00911 }
00912 }
00913
00914 void MagiC::String::upper() const {
00915 for (int i=0; i<mLen; i++)
00916 mData[i] = toupper (mData[i]);
00917 }
00918
00919 void MagiC::String::lower() const {
00920 for (int i=0; i<mLen; i++)
00921 mData[i] = tolower (mData[i]);
00922 }
00923
00929 int MagiC::String::regmatch (const char* expr) const {
00930 if (!mData)
00931 return 0;
00932 RegExp rexp (expr);
00933 return rexp.match (mData);
00934 }
00935
00946 int MagiC::String::regmatch (const char* expr, Array<String>& target) const {
00947 if (!mData)
00948 return 0;
00949 RegExp rexp (expr);
00950 return rexp.match (*this, target);
00951 }
00952
00955 int MagiC::String::regmatch (RegExp& compiled, Array<String>& target) const {
00956 if (!mData)
00957 return 0;
00958 return compiled.match (*this, target);
00959 }
00960
00973 char MagiC::String::checksum () {
00974 mChkSum=0;
00975 hashfunc (256);
00976 return mChkSum;
00977 }
00978
00992 int MagiC::String::hashfunc (int hashsize) const {
00993 ASSERTWITH (hashsize<=256, format ("String hash size maximum is 256 slots",
00994 " (hashsize was %d)", hashsize));
00995
00996
00997 if (mChkSum)
00998 return mChkSum % hashsize;
00999
01000 int sum=0;
01001 if (!mLen)
01002 return 0;
01003
01004 if (mLen < 10) {
01005
01006
01007 for (int i=0; i<mLen; i++)
01008 sum += mData[i];
01009
01010 (unsigned char&) mChkSum = sum % 256;
01011 } else {
01012
01013
01014
01015 sum = int(mData[0]) + int(mData[mLen/2]) + mLen*int(mData[mLen-1]);
01016
01017 (unsigned char&) mChkSum = sum % 256;
01018 }
01019
01020
01021 return mChkSum % hashsize;
01022 }
01023
01029
01030
01031
01032
01033
01034
01035
01036
01037
01038
01039
01040
01041
01042
01043
01044
01046
01047
01048
01049
01050
01051
01053
01055 const String MagiC::emptystring;
01056
01066 char* MagiC::strnchr (const char* str, int mLen, char c) {
01067 const char* pos=str;
01068 for (int i=0; i<mLen; i++, pos++)
01069 if (*pos == c)
01070 return (char*) pos;
01071 return NULL;
01072 }
01073
01082 char* safedup (const char* orig, int maxlen=-1) {
01083 if (orig) {
01084
01085
01086 int len = strlen (orig)+1;
01087 char* result = new char [len];
01088 memcpy (result, orig, len);
01089 return result;
01090 } else
01091 return (char*) NULL;
01092 }
01093
01098 int MagiC::fgetS (FILE* in, String& str) {
01099 char cbuff [4097],
01100 *nlpos;
01101 int mLen=0;
01102
01103 str = "";
01104
01105 do {
01106
01107 fgets (cbuff, 4096, in);
01108
01109
01110 nlpos = strnchr (cbuff, 4096, '\n');
01111
01112
01113 mLen = nlpos? nlpos-cbuff+1 : 4096;
01114
01115
01116 String tmp (cbuff, mLen);
01117
01118
01119 str += tmp;
01120
01121
01122 } while (!nlpos && !feof (in));
01123
01124 if (feof (in))
01125 mLen = -1;
01126
01127 return mLen;
01128 }
01129
01134 istream& MagiC::getS (istream& is, String& str, char term) {
01135 str = "";
01136 str.ensure_spontane (80);
01137
01138 register streambuf *sb = is.rdbuf ();
01139 bool eof=false;
01140 while (true) {
01141 int ch = sb->sbumpc ();
01142 if (ch == EOF) {
01143 eof = true;
01144 is.setstate (ios::eofbit);
01145 break;
01146
01147
01148
01149 } else if ((term!='\xff' && ch==term) || (term=='\xff' && isspace (ch)))
01150 break;
01151
01152
01153 else if (term!='\n' || ch!='\r')
01154 str += char(ch);
01155 }
01156
01157 if (eof && str.length()==0)
01158 is.setstate (ios::failbit);
01159
01160 return is;
01161 }
01162
01163 void nullcharspace (int charspace [256]) {
01164 for (int i=0; i<256; i++)
01165 charspace [i]=0;
01166 }
01167
01169 void MagiC::loadString (String& str, const String& filename) {
01170 FILE* in = fopen (filename, "rb");
01171 if (!in)
01172 return;
01173 str = "";
01174 String buff;
01175 buff.reserve (200);
01176 while (!feof(in)) {
01177 fgetS (in, buff);
01178 str += buff;
01179 }
01180 fclose (in);
01181 }
01182
01191 String MagiC::strformat (const char* sformat, ...) {
01192 char format_buff[1024];
01193 va_list args;
01194
01195 va_start (args, sformat);
01196
01197 int i=vsprintf (format_buff, sformat, args);
01198 va_end (args);
01199
01200 ASSERTWITH (i<1024, "String format result exceeded buffer size (1024 bytes)");
01201 return format_buff;
01202 }
01203
01204