00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include <ctype.h>
00018 #include <stdio.h>
00019 #include <spl/Double.h>
00020 #include <spl/Exception.h>
00021 #include <spl/Int32.h>
00022 #include <spl/math/Math.h>
00023 #include <spl/String.h>
00024 #include <spl/text/StringBuffer.h>
00025
00026 using namespace spl;
00027
00028 const char eos = '\0';
00029
00030 char String::m_empty[2] = {'\0', 0xC};
00031
00032 namespace spl
00033 {
00034 int IndexofchfromWithLen( const char *str, const char ch, int start, const int len )
00035 {
00036 int pos;
00037
00038 for ( pos = start; pos < len; pos++ )
00039 {
00040 if ( str[pos] == ch )
00041 {
00042 return pos;
00043 }
00044 }
00045 return -1;
00046 }
00047
00048 char *StrCat(const char *cstr, const int cstrlen, const char *arg, const int arglen)
00049 {
00050 int len = cstrlen + arglen + 1;
00051 char *buf = (char *)malloc(len);
00052 if ( NULL == buf )
00053 {
00054 throw OutOfMemoryException();
00055 }
00056 StrCpyLen(buf, cstr, len);
00057 strcat(buf, arg);
00058 return buf;
00059 }
00060
00061 int StrCmpNoCase( const char *str1, int str1len, const char *str2 )
00062 {
00063 while ( *str1 != '\0' && *str2 != '\0' && str1len-- >= 0 )
00064 {
00065 if ( toupper(*str1) != toupper(*str2) )
00066 {
00067 if ( *str1 > *str2 )
00068 {
00069 return 1;
00070 }
00071 return -1;
00072 }
00073 str1++;
00074 str2++;
00075 }
00076 if ( *str1 != '\0' )
00077 {
00078 return 1;
00079 }
00080 if ( *str2 != '\0' )
00081 {
00082 return -1;
00083 }
00084 return 0;
00085 }
00086
00087 int StrCmp( const char *str1, const char *str2, int maxlen )
00088 {
00089 while ( *str1 != '\0' && *str2 != '\0' && maxlen-- >= 0 )
00090 {
00091 if ( *str1 != *str2 )
00092 {
00093 if ( *str1 > *str2 )
00094 {
00095 return 1;
00096 }
00097 return -1;
00098 }
00099 str1++;
00100 str2++;
00101 }
00102 if ( *str1 != '\0' )
00103 {
00104 return 1;
00105 }
00106 if ( *str2 != '\0' )
00107 {
00108 return -1;
00109 }
00110 return 0;
00111 }
00112
00113 int StrCpyLen( char *str1, const char *str2, const int maxlen )
00114 {
00115 int len = maxlen;
00116 while ( *str2 != '\0' && len-- > 0 )
00117 {
00118 *(str1++) = *(str2++);
00119 }
00120 *str1 = '\0';
00121 return -(len - maxlen);
00122 }
00123
00124 int StrCpy( char *str1, const char *str2 )
00125 {
00126 return StrCpyLen(str1, str2, Int32::MaxValue());
00127 }
00128 };
00129
00130 String::String()
00131 : m_cstr(m_empty),
00132 m_isintern(true),
00133 m_len(0)
00134
00135 {
00136 }
00137
00138 void String::InitWith( const char *str, const int offset, const int len )
00139 {
00140 m_len = len;
00141 char *cp;
00142 if ( NULL == (cp = (char *)malloc(m_len+1)) )
00143 {
00144 throw OutOfMemoryException();
00145 }
00146 m_isintern = false;
00147 StrCpyLen(cp, &str[offset], len);
00148 m_cstr = cp;
00149 }
00150
00151 String::String( const String& str )
00152 {
00153 m_len = str.Length();
00154 if ( str.m_isintern )
00155 {
00156 m_cstr = str.m_cstr;
00157 }
00158 else
00159 {
00160 char *cp;
00161 if ( NULL == (cp = (char *)malloc(m_len+1)) )
00162 {
00163 throw OutOfMemoryException();
00164 }
00165 StrCpyLen(cp, str.m_cstr, m_len);
00166 m_cstr = cp;
00167 }
00168 m_isintern = str.m_isintern;
00169 }
00170
00171 String::~String()
00172 {
00173 if ( !m_isintern )
00174 {
00175 free((char *)m_cstr);
00176 }
00177 }
00178
00179 void String::Set( const String &str )
00180 {
00181 ValidateMem();
00182 if ( m_isintern )
00183 {
00184 m_isintern = false;
00185 }
00186 else
00187 {
00188 free( (char *)m_cstr );
00189 }
00190
00191 m_len = str.Length();
00192 char *cp;
00193 cp = (char *)malloc( m_len + 1 );
00194 if ( NULL == cp )
00195 {
00196 throw OutOfMemoryException();
00197 }
00198 StrCpyLen(cp, str.m_cstr, m_len);
00199 m_cstr = cp;
00200 }
00201
00202 StringPtr String::PadRight( char ch, int count )
00203 {
00204 char *buf = (char *)malloc(count + 1);
00205 if ( NULL == buf )
00206 {
00207 throw OutOfMemoryException();
00208 }
00209 for ( int x = 0; x < count; x++ )
00210 {
00211 buf[x] = ch;
00212 }
00213 buf[count] = '\0';
00214 StringPtr ret = Cat(buf);
00215 free( buf );
00216 return ret;
00217 }
00218
00219 StringPtr String::Fill( char ch, int length )
00220 {
00221 StringBuffer buf;
00222 buf.Fill(ch, length);
00223 return buf.ToString();
00224 }
00225
00226 char String::CharAt( const int idx ) const
00227 {
00228 if ( idx > m_len )
00229 {
00230 throw new IndexOutOfBoundsException();
00231 }
00232 return m_cstr[idx];
00233 }
00234
00235 char String::operator[] (const int idx) const
00236 {
00237 if ( idx > m_len )
00238 {
00239 throw new IndexOutOfBoundsException();
00240 }
00241 return m_cstr[idx];
00242 }
00243
00244 StringPtr String::Substring( int start, int len ) const
00245 {
00246 char *ret;
00247 const char *cpstart;
00248
00249 if ( len == 0 )
00250 {
00251 return StringPtr(new String());
00252 }
00253
00254 ASSERT ( len > 0 );
00255
00256 if( start > m_len )
00257 {
00258 start = m_len;
00259 }
00260 if ( start + len > m_len )
00261 {
00262 len = m_len - start;
00263 }
00264 if ( len < 0 )
00265 {
00266 len = 0;
00267 }
00268 cpstart = &m_cstr[start];
00269 ASSERT_PTR( cpstart );
00270
00271 if ( NULL == (ret = (char *)malloc( len+1 )) )
00272 {
00273 throw OutOfMemoryException();
00274 }
00275 StrCpyLen( ret, cpstart, len );
00276 ret[len] = eos;
00277 ASSERT_MEM( ret, len+1 );
00278
00279 StringPtr strret = StringPtr(new String(ret));
00280 free(ret);
00281 return strret;
00282 }
00283
00284 RefCountPtr<Vector<RefCountPtr<String> > > String::Split( const String& cp ) const
00285 {
00286 RefCountPtr<Vector<RefCountPtr<String> > > tvec(new Vector<StringPtr>);
00287 int delimlen = cp.Length();
00288 int delimpos = IndexOf( cp );
00289 int pos = 0;
00290
00291 StringPtr span;
00292
00293 if ( delimpos < 0 )
00294 {
00295 tvec->Add( StringPtr(new String(m_cstr)) );
00296 return tvec;
00297 }
00298 while ( pos < m_len )
00299 {
00300 span = Mid( pos, delimpos );
00301 pos = delimpos + delimlen;
00302 tvec->Add( span );
00303
00304 delimpos = IndexOf( cp, delimpos+1 );
00305 if ( delimpos < 0 )
00306 {
00307 break;
00308 }
00309 }
00310 pos = m_len - pos;
00311 ASSERT( pos >- 0 );
00312 if ( pos > 0 )
00313 {
00314 span = Right( pos );
00315 tvec->Add( span );
00316 }
00317
00318 return tvec;
00319 }
00320
00321 int String::IndexOfAny( const String& cp ) const
00322 {
00323 int ret;
00324 int cplen = cp.Length();
00325 for ( int x = 0; x < m_len; x++ )
00326 {
00327 for ( int y = 0; y < cplen; y++ )
00328 {
00329 if ( 0 <= (ret = IndexofchfromWithLen(m_cstr, cp[y], 0, m_len)) )
00330 {
00331 return ret;
00332 }
00333 }
00334 }
00335 return -1;
00336 }
00337
00338 StringPtr String::Replace(const char from, const char to) const
00339 {
00340 StringBuffer buf(m_cstr);
00341 buf.Replace(from, to);
00342 return buf.ToString();
00343 }
00344
00345 StringPtr String::Replace(const char *from, const char *to) const
00346 {
00347 int start = 0;
00348 int pos = IndexOf( from );
00349 if ( 0 > pos )
00350 {
00351 return StringPtr(new String(*this));
00352 }
00353
00354 int fromlen = (int)strlen(from);
00355 StringBuffer buf(m_len + 10);
00356
00357 while (start < m_len)
00358 {
00359 buf.Append(m_cstr, start, pos-start);
00360 start = pos;
00361 buf.Append(to);
00362 start += fromlen;
00363
00364 if ( 0 > (pos = IndexOf( from, start )) )
00365 {
00366 buf.Append(m_cstr, start, m_len - start);
00367 start = m_len;
00368 }
00369 }
00370 return buf.ToString();
00371 }
00372
00373 StringPtr String::Cat( const String& cp, const int len ) const
00374 {
00375 char *buf = StrCat(m_cstr, m_len, cp.m_cstr, len);
00376 StringPtr ret = StringPtr(new String(buf));
00377 free(buf);
00378 return ret;
00379 }
00380
00381 StringPtr String::Right( int len ) const
00382 {
00383 if ( len > m_len )
00384 {
00385 len = m_len;
00386 }
00387 return Substring( m_len - len );
00388 }
00389
00390 StringPtr String::Left( int len ) const
00391 {
00392 if ( len > m_len )
00393 {
00394 len = m_len;
00395 }
00396 return Substring(0, len);
00397 }
00398
00399 StringPtr String::Mid( int start, int stop ) const
00400 {
00401 return Substring( start, stop - start );
00402 }
00403
00404 StringPtr String::RTrim(char ch) const
00405 {
00406 StringBuffer buf(m_len+1);
00407
00408 int endpos;
00409 for ( endpos = m_len-1; m_cstr[endpos] == ch && endpos >= 0; endpos-- )
00410 {
00411 }
00412 for ( int x = 0; x <= endpos; x++ )
00413 {
00414 ASSERT(m_cstr[x] != '\0');
00415 buf.Append(m_cstr[x]);
00416 }
00417 return buf.ToString();
00418 }
00419
00420 StringPtr String::LTrim(char ch) const
00421 {
00422 if (m_cstr[0] != ch)
00423 {
00424 return StringPtr(new String(*this));
00425 }
00426
00427 int pos;
00428 StringBuffer buf(m_len);
00429 for ( pos = 0; pos < m_len; pos++ )
00430 {
00431 if (m_cstr[pos] != ch)
00432 {
00433 break;
00434 }
00435 }
00436 for ( int x = pos; x < m_len; x++ )
00437 {
00438 buf.Append(m_cstr[x]);
00439 }
00440
00441 return buf.ToString();
00442 }
00443
00444 StringPtr String::Trim() const
00445 {
00446 StringBuffer buf(m_len);
00447
00448 int pos;
00449 for ( pos = 0; m_cstr[pos] == ' ' && pos < m_len; pos++ )
00450 {
00451 }
00452 int endpos;
00453 for ( endpos = m_len-1; m_cstr[endpos] == ' ' && endpos >= 0; endpos-- )
00454 {
00455 }
00456 for ( int x = pos; x <= endpos; x++ )
00457 {
00458 buf.Append(m_cstr[x]);
00459 }
00460 return buf.ToString();
00461 }
00462
00463 void String::UnIntern()
00464 {
00465 char *buf = (char *)malloc(m_len+1);
00466 StrCpyLen(buf, m_cstr, m_len);
00467 m_isintern = false;
00468 m_cstr = buf;
00469 }
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517 int String::IndexOf( const String& cp, const int start ) const
00518 {
00519 for ( int pos = start; pos < m_len; pos++ )
00520 {
00521 int end;
00522 int cppos = 1;
00523
00524 if ( m_cstr[pos] == cp[0] )
00525 {
00526 for( end = pos+1; end < m_len && cp[cppos] != '\0'; end++ )
00527 {
00528 if ( m_cstr[end] != cp[cppos] )
00529 {
00530 break;
00531 }
00532 cppos++;
00533 }
00534 if ( cp[cppos] == '\0' )
00535 {
00536 return pos;
00537 }
00538 }
00539 }
00540 return -1;
00541 }
00542
00543 StringPtr String::Intern( const char *str )
00544 {
00545 String *s = new String();
00546 ASSERT(s->m_isintern);
00547
00548 s->m_cstr = str;
00549 s->m_isintern = true;
00550 s->m_len = (int)strlen(str);
00551 return StringPtr(s);
00552 }
00553
00554 int32 String::HashCode() const
00555 {
00556 return Math::Hash( m_cstr );
00557 }
00558
00559 int String::Compare( const IComparable *istr ) const
00560 {
00561 if (istr->MajicNumber() != MajicNumber())
00562 {
00563 return 1;
00564 }
00565 const String *str = static_cast<const String *>(istr);
00566 str->ValidateMem();
00567 return Compare( str );
00568 }
00569
00570 bool String::Equals( const IComparable *istr ) const
00571 {
00572 if (istr->MajicNumber() != MajicNumber())
00573 {
00574 return false;
00575 }
00576 const String *str = static_cast<const String *>(istr);
00577 str->ValidateMem();
00578 return Equals( str );
00579 }
00580
00581 int String::Compare( const IComparable& istr ) const
00582 {
00583 if (istr.MajicNumber() != MajicNumber())
00584 {
00585 return 1;
00586 }
00587 const String& str = static_cast<const String&>(istr);
00588 str.ValidateMem();
00589 return Compare( str );
00590 }
00591
00592 bool String::Equals( const IComparable& istr ) const
00593 {
00594 if (istr.MajicNumber() != MajicNumber())
00595 {
00596 return false;
00597 }
00598 const String& str = static_cast<const String&>(istr);
00599 str.ValidateMem();
00600 return Equals( str );
00601 }
00602
00603 int32 String::MajicNumber() const
00604 {
00605 return STRING_MAJIC;
00606 }
00607
00608 static const char *base64_chars =
00609 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
00610 "abcdefghijklmnopqrstuvwxyz"
00611 "0123456789+/";
00612
00613 #define is_base64(c) ((isalnum(c) || (c == '+') || (c == '/')))
00614
00615 RefCountPtr<String> String::Base64Encode( const char *cp, int len )
00616 {
00617 return Base64Encode(RefCountPtr<Array<byte> >(new Array<byte>((const byte *)cp, len)));
00618 }
00619
00620 RefCountPtr<String> String::Base64Encode( RefCountPtr<Array<byte> > rcp )
00621 {
00622 StringBuffer ret(256);
00623 int i = 0;
00624 int j = 0;
00625 int in_len = rcp->Length();
00626 byte *cp = rcp->Data();
00627 unsigned char char_array_3[3];
00628 unsigned char char_array_4[4];
00629
00630 while (in_len--)
00631 {
00632 char_array_3[i++] = *(cp++);
00633 if (i == 3)
00634 {
00635 char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
00636 char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
00637 char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
00638 char_array_4[3] = char_array_3[2] & 0x3f;
00639
00640 for(i = 0; (i <4) ; i++)
00641 {
00642 ret.Append(base64_chars[char_array_4[i]]);
00643 }
00644 i = 0;
00645 }
00646 }
00647 if (i)
00648 {
00649 for(j = i; j < 3; j++)
00650 {
00651 char_array_3[j] = '\0';
00652 }
00653 char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
00654 char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
00655 char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
00656 char_array_4[3] = char_array_3[2] & 0x3f;
00657
00658 for (j = 0; (j < i + 1); j++)
00659 {
00660 ret.Append(base64_chars[char_array_4[j]]);
00661 }
00662 while((i++ < 3))
00663 {
00664 ret.Append('=');
00665 }
00666 }
00667 return ret.ToString();
00668 }
00669
00670 RefCountPtr<Array<byte> > String::Base64Decode( const String& s )
00671 {
00672 int in_len = s.Length();
00673 int i = 0;
00674 int j = 0;
00675 int in_ = 0;
00676 unsigned char char_array_4[4], char_array_3[3];
00677 Vector<byte> ret(256);
00678
00679 while (in_len-- && ( s[in_] != '=') && is_base64(s[in_]))
00680 {
00681 char_array_4[i++] = s[in_];
00682 in_++;
00683 if (i ==4)
00684 {
00685 for (i = 0; i <4; i++)
00686 {
00687 char_array_4[i] = IndexOfCh(base64_chars, char_array_4[i]);
00688 }
00689 char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
00690 char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
00691 char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];
00692
00693 for (i = 0; (i < 3); i++)
00694 {
00695 ret.Add(char_array_3[i]);
00696 }
00697 i = 0;
00698 }
00699 }
00700
00701 if (i)
00702 {
00703 for (j = i; j <4; j++)
00704 {
00705 char_array_4[j] = 0;
00706 }
00707 for (j = 0; j <4; j++)
00708 {
00709 char_array_4[j] = IndexOfCh(base64_chars, char_array_4[j]);
00710 }
00711
00712 char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
00713 char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
00714 char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];
00715
00716 for (j = 0; (j < i - 1); j++)
00717 {
00718 ret.Add(char_array_3[j]);
00719 }
00720 }
00721 return ret.ToArray();
00722 }
00723
00724 #define PAD_RIGHT 1
00725 #define PAD_ZERO 2
00726
00727 static void _prints(StringBuffer *out, const char *string, int width, int pad)
00728 {
00729 int padchar = ' ';
00730
00731 if (width > 0)
00732 {
00733 register int len = 0;
00734 register const char *ptr;
00735 for (ptr = string; *ptr; ++ptr)
00736 ++len;
00737 if (len >= width)
00738 width = 0;
00739 else
00740 width -= len;
00741 if (pad & PAD_ZERO)
00742 padchar = '0';
00743 }
00744 if (!(pad & PAD_RIGHT))
00745 {
00746 for ( ; width > 0; --width)
00747 {
00748 out->Append((char) padchar);
00749 }
00750 }
00751 for ( ; *string ; ++string)
00752 {
00753 out->Append((char) *string);
00754 }
00755 for ( ; width > 0; --width)
00756 {
00757 out->Append((char) padchar);
00758 }
00759 }
00760
00761
00762 #define PRINT_BUF_LEN 12
00763
00764 static void _printi(StringBuffer *out, int i, int b, int sg, int width, int pad, int letbase)
00765 {
00766 char print_buf[PRINT_BUF_LEN];
00767 register char *s;
00768 register int t, neg = 0;
00769 register unsigned int u = i;
00770
00771 if (i == 0)
00772 {
00773 print_buf[0] = '0';
00774 print_buf[1] = '\0';
00775 _prints (out, print_buf, width, pad);
00776 return;
00777 }
00778
00779 if (sg && b == 10 && i < 0)
00780 {
00781 neg = 1;
00782 u = -i;
00783 }
00784
00785 s = print_buf + PRINT_BUF_LEN-1;
00786 *s = '\0';
00787
00788 while (u)
00789 {
00790 t = u % b;
00791 if( t >= 10 )
00792 t += letbase - '0' - 10;
00793 *--s = t + '0';
00794 u /= b;
00795 }
00796
00797 if (neg)
00798 {
00799 if( width && (pad & PAD_ZERO) )
00800 {
00801 out->Append((char) '-');
00802 --width;
00803 }
00804 else
00805 {
00806 *--s = '-';
00807 }
00808 }
00809
00810 _prints (out, s, width, pad);
00811 }
00812
00813 static int _round_(char *bytes, int nDigits, int roundPos, bool roundDown)
00814 {
00815 int next = roundPos + 1;
00816 if (next >= nDigits || bytes[next] < '5' ||
00817
00818
00819 (roundDown && bytes[next] == '5' && next == nDigits - 1))
00820 {
00821 return nDigits;
00822 }
00823 if (roundPos < 0)
00824 {
00825 memcpy(bytes, &bytes[1], sizeof(char) * nDigits);
00826 bytes[0] = '1';
00827 return nDigits + 1;
00828 }
00829 bytes[roundPos] += 1;
00830 while (bytes[roundPos] > '9')
00831 {
00832 bytes[roundPos] = '0';
00833 roundPos--;
00834 if (roundPos >= 0)
00835 {
00836 bytes[roundPos] += 1;
00837 }
00838 else
00839 {
00840 memcpy(bytes, &bytes[1], sizeof(char) * nDigits);
00841 bytes[0] = '1';
00842 return nDigits + 1;
00843 }
00844 }
00845 return nDigits;
00846 }
00847
00848
00849 static void _printdf(StringBuffer *out, char fchar, double d, int width, int pad)
00850 {
00851
00852
00853
00854 int precision = 0;
00855 double dval = d;
00856 bool nan = Math::IsNaN(dval);
00857 bool inf = Math::IsINF(dval);
00858
00859 bool negative = dval < 0.0;
00860 int nDigits = 0;
00861 int exponent = 0;
00862 bool expForm = false;
00863
00864 int len = 0;
00865 char signChar;
00866
00867 if (nan || inf)
00868 {
00869 const char *cdigits = NULL;
00870 if (nan)
00871 {
00872 cdigits = "NaN";
00873 len = 3;
00874 }
00875 else
00876 {
00877 cdigits = "Inf";
00878 len = 3;
00879 }
00880 if (negative)
00881 {
00882 signChar = '-';
00883 width--;
00884 }
00885
00886
00887
00888
00889
00890 else
00891 {
00892 signChar = 0;
00893 }
00894 width -= len;
00895
00896 if (width > 0 && (pad & PAD_RIGHT) == 0)
00897 {
00898 out->Fill(' ', width);
00899 width = 0;
00900 }
00901 if (signChar != 0)
00902 {
00903 out->Append(signChar);
00904 }
00905
00906 if (width > 0 && (pad & PAD_ZERO) == 0)
00907 {
00908 out->Fill('0', width);
00909 width = 0;
00910 }
00911
00912 out->Append(cdigits);
00913
00914 if (width > 0)
00915 {
00916 out->Fill(' ', width);
00917 }
00918
00919 return;
00920 }
00921
00922 StringPtr str = Double::ToString(dval);
00923 int strlen = str->Length();
00924 char *digits = new char[strlen];
00925 int nTrailingZeroes = 0;
00926 int i = negative ? 1 : 0;
00927 int decPos = 0;
00928 char ival;
00929 bool decfound = false;
00930 while( i < strlen && !decfound )
00931 {
00932 switch (ival = (byte) str->CharAt(i++))
00933 {
00934 case '0':
00935 if (nDigits > 0)
00936 nTrailingZeroes++;
00937
00938 break;
00939 case '1':
00940 case '2':
00941 case '3':
00942 case '4':
00943 case '5':
00944 case '6':
00945 case '7':
00946 case '8':
00947 case '9':
00948 if (nTrailingZeroes > 0)
00949 {
00950 for (; nTrailingZeroes > 0; nTrailingZeroes--)
00951 {
00952 digits[nDigits++] = '0';
00953 }
00954 }
00955 digits[nDigits++] = ival;
00956 break;
00957 case '.':
00958 decfound = true;
00959 break;
00960 }
00961 }
00962 decPos = nDigits + nTrailingZeroes;
00963 decfound = false;
00964 while(i < strlen && !decfound)
00965 {
00966 switch (ival = (byte) str->CharAt(i++))
00967 {
00968 case '0':
00969 if (nDigits > 0)
00970 {
00971 nTrailingZeroes++;
00972 }
00973 else
00974 {
00975 exponent--;
00976 }
00977 break;
00978 case '1':
00979 case '2':
00980 case '3':
00981 case '4':
00982 case '5':
00983 case '6':
00984 case '7':
00985 case '8':
00986 case '9':
00987 if (nTrailingZeroes > 0)
00988 {
00989 for (; nTrailingZeroes > 0; nTrailingZeroes--)
00990 {
00991 digits[nDigits++] = '0';
00992 }
00993 }
00994 digits[nDigits++] = ival;
00995 break;
00996 case 'E':
00997 decfound = true;
00998 break;
00999 }
01000 }
01001 if (i < strlen)
01002 {
01003 int expSign;
01004 int expVal = 0;
01005 if (str->CharAt(i) == '-')
01006 {
01007 expSign = -1;
01008 i++;
01009 }
01010 else
01011 {
01012 expSign = 1;
01013 }
01014 for (; i < strlen;)
01015 {
01016 expVal = expVal
01017 * 10
01018 + ((int) str->CharAt(i++) - (int) '0');
01019 }
01020 exponent += expVal * expSign;
01021 }
01022 exponent += decPos - nDigits;
01023
01024
01025 if (nDigits == 0)
01026 {
01027 digits[0] = '0';
01028 nDigits = 1;
01029 exponent = 0;
01030 }
01031
01032
01033
01034
01035 int intDigits, intZeroes, intLength;
01036 int decDigits, decZeroes, decLength;
01037 char expChar;
01038
01039 if (negative)
01040 {
01041 signChar = '-';
01042 width--;
01043 }
01044
01045
01046
01047
01048
01049
01050
01051
01052
01053
01054 else
01055 {
01056 signChar = 0;
01057 }
01058
01059
01060 precision = 6;
01061
01062
01063 switch (fchar)
01064 {
01065 case 'E':
01066 case 'G':
01067 expChar = 'E';
01068 break;
01069 case 'e':
01070 case 'g':
01071 expChar = 'e';
01072 break;
01073 default:
01074 expChar = 0;
01075 }
01076
01077 switch (fchar)
01078 {
01079 case 'g':
01080 case 'G':
01081
01082
01083
01084
01085
01086
01087
01088
01089 expForm = (exponent + nDigits - 1 < -4 || exponent
01090 + nDigits > (precision == 0 ? 1
01091 : precision));
01092
01093
01094
01095 if (expForm)
01096 {
01097
01098
01099 decDigits = nDigits - 1;
01100
01101 precision = Math::Max(0, precision - 1);
01102
01103 if (precision < decDigits)
01104 {
01105 int n = _round_(digits, nDigits, precision, precision != 0);
01106 ASSERT_MEM(digits, strlen*sizeof(char));
01107 if (n > nDigits)
01108 {
01109 nDigits = n;
01110 }
01111 decDigits = Math::Min(nDigits - 1, precision);
01112 }
01113 exponent += nDigits - 1;
01114 if (precision > 0)
01115 {
01116 len += 1 + precision;
01117 }
01118 else
01119 {
01120 len += 1;
01121
01122
01123
01124
01125 }
01126
01127 width -= len + 5;
01128
01129 if (width > 0 && (pad & (PAD_ZERO)) == 0)
01130 {
01131 out->Fill(' ', width);
01132 width = 0;
01133 }
01134 if (signChar != 0)
01135 {
01136 out->Append(signChar);
01137 }
01138
01139
01140
01141
01142
01143
01144 out->Append(digits[0]);
01145 if (precision > 0)
01146 {
01147 out->Append('.');
01148 if (decDigits > 0)
01149 {
01150 out->Append(digits, 1, decDigits);
01151 precision -= decDigits;
01152 }
01153 }
01154
01155
01156
01157
01158 out->Append(expChar);
01159 if ( exponent >= 0 )
01160 out->Append('-');
01161 if (exponent < 0)
01162 {
01163 exponent = -exponent;
01164 }
01165 out->Append((char)(exponent / 100 + '0'));
01166 out->Append((char)(exponent % 100 / 10 + '0'));
01167 out->Append((char)(exponent % 10 + '0'));
01168 if (width > 0)
01169 {
01170 out->Fill(' ', width);
01171 }
01172 }
01173 else
01174 {
01175 intDigits = Math::Max(0, Math::Min(nDigits + exponent, nDigits));
01176 intZeroes = Math::Max(0, exponent);
01177 intLength = intDigits + intZeroes;
01178 decDigits = nDigits - intDigits;
01179 decZeroes = Math::Max(0, -(decDigits + exponent));
01180 decLength = decZeroes + decDigits;
01181 precision = Math::Max(0, precision - intLength);
01182
01183 if (precision < decDigits)
01184 {
01185 int n = _round_(digits, nDigits,
01186 intDigits + precision - 1,
01187 precision != 0);
01188 ASSERT_MEM(digits, strlen*sizeof(char));
01189 if (n > nDigits)
01190 {
01191
01192 nDigits = n;
01193 intDigits = Math::Max(0, Math::Min(nDigits + exponent, nDigits));
01194 intLength = intDigits + intZeroes;
01195 decDigits = nDigits - intDigits;
01196 decZeroes = Math::Max(0, -(decDigits + exponent));
01197 precision = Math::Max(0, precision - 1);
01198 }
01199 decDigits = precision;
01200 decLength = decZeroes + decDigits;
01201 }
01202 len += intLength;
01203 if (decLength > 0)
01204 {
01205 len += decLength + 1;
01206 }
01207 else
01208 {
01209
01210
01211
01212
01213
01214
01215
01216
01217 }
01218
01219 width -= len;
01220
01221 if (width > 0 && (pad & (PAD_ZERO)) == 0)
01222 {
01223 out->Fill(' ', width);
01224 width = 0;
01225 }
01226 if (signChar != 0)
01227 {
01228 out->Append(signChar);
01229 }
01230
01231
01232
01233
01234
01235
01236 if (intLength > 0)
01237 {
01238 if (intDigits > 0)
01239 {
01240 out->Append(digits, 0, intDigits);
01241 }
01242 if (intZeroes > 0)
01243 {
01244 out->Fill('0', intZeroes);
01245 }
01246 }
01247 else
01248 {
01249
01250 out->Append('0');
01251 }
01252 if (decLength > 0 )
01253 {
01254 out->Append('.');
01255 }
01256 if (decLength > 0)
01257 {
01258 if (decZeroes > 0)
01259 {
01260 out->Fill('0', decZeroes);
01261 precision -= decZeroes;
01262 }
01263 if (decDigits > 0)
01264 {
01265 out->Append(digits, intDigits, decDigits);
01266 precision -= decDigits;
01267 }
01268
01269
01270
01271
01272 }
01273
01274
01275
01276
01277 if (width > 0)
01278 {
01279 out->Fill(' ', width);
01280 }
01281 }
01282 break;
01283
01284 case 'f':
01285 intDigits = Math::Max(0, Math::Min(nDigits + exponent, nDigits));
01286 intZeroes = Math::Max(0, exponent);
01287 intLength = intDigits + intZeroes;
01288 decDigits = nDigits - intDigits;
01289 decZeroes = Math::Max(0, -(decDigits + exponent));
01290 decLength = decZeroes + decDigits;
01291
01292 if (precision < decLength)
01293 {
01294 if (precision < decZeroes)
01295 {
01296 decDigits = 0;
01297 decZeroes = precision;
01298 }
01299 else
01300 {
01301 int n = _round_(digits, nDigits, intDigits + precision - decZeroes - 1, precision != 0);
01302 ASSERT_MEM(digits, strlen*sizeof(char));
01303 if (n > nDigits)
01304 {
01305
01306 nDigits = n;
01307 intDigits = Math::Max(0, Math::Min(nDigits + exponent, nDigits));
01308 intLength = intDigits + intZeroes;
01309 decDigits = nDigits - intDigits;
01310 decZeroes = Math::Max(0, -(decDigits + exponent));
01311 decLength = decZeroes + decDigits;
01312 }
01313 decDigits = precision - decZeroes;
01314 }
01315 decLength = decZeroes + decDigits;
01316 }
01317 if (precision > 0)
01318 {
01319 len += Math::Max(1, intLength) + 1 + precision;
01320
01321 }
01322 else
01323 {
01324 len += Math::Max(1, intLength);
01325
01326
01327
01328
01329
01330 }
01331
01332 width -= len;
01333
01334 if (width > 0 && (pad & (PAD_ZERO)) == 0)
01335 {
01336 out->Fill(' ', width);
01337 width = 0;
01338 }
01339 if (signChar != 0)
01340 {
01341 out->Append(signChar);
01342 }
01343
01344
01345
01346
01347
01348
01349 if (intLength > 0)
01350 {
01351 if (intDigits > 0)
01352 {
01353 out->Append(digits, 0, intDigits);
01354 }
01355 if (intZeroes > 0)
01356 {
01357 out->Fill('0', intZeroes);
01358 }
01359 }
01360 else
01361 {
01362
01363 out->Append('0');
01364 }
01365 if (precision > 0 )
01366 {
01367 out->Append('.');
01368 }
01369 if (precision > 0)
01370 {
01371 if (decZeroes > 0)
01372 {
01373 out->Fill('0', decZeroes);
01374 precision -= decZeroes;
01375 }
01376 if (decDigits > 0)
01377 {
01378 out->Append(digits, intDigits, decDigits);
01379 precision -= decDigits;
01380 }
01381
01382 if (precision > 0)
01383 {
01384 out->Fill('0', precision);
01385 }
01386 }
01387 if (width > 0)
01388 {
01389 out->Fill(' ', width);
01390 }
01391 break;
01392 case 'E':
01393 case 'e':
01394
01395
01396 decDigits = nDigits - 1;
01397
01398 if (precision < decDigits)
01399 {
01400 int n = _round_(digits, nDigits, precision, precision != 0);
01401 if (n > nDigits)
01402 {
01403 nDigits = n;
01404 }
01405 decDigits = Math::Min(nDigits - 1, precision);
01406 }
01407 exponent += nDigits - 1;
01408 if (precision > 0)
01409 {
01410 len += 2 + precision;
01411 }
01412 else
01413 {
01414 len += 1;
01415
01416
01417
01418
01419 }
01420
01421 width -= len + 5;
01422
01423 if (width > 0 && (pad & (PAD_ZERO)) == 0)
01424 {
01425 out->Fill(' ', width);
01426 width = 0;
01427 }
01428 if (signChar != 0)
01429 {
01430 out->Append(signChar);
01431 }
01432
01433
01434
01435
01436
01437
01438 out->Append(digits[0]);
01439 if (precision > 0)
01440 {
01441 out->Append('.');
01442 if (decDigits > 0)
01443 {
01444 out->Append(digits, 1, decDigits);
01445 precision -= decDigits;
01446 }
01447 if (precision > 0)
01448 {
01449 out->Fill('0', precision);
01450 }
01451
01452 }
01453
01454
01455
01456
01457 out->Append(expChar);
01458 out->Append(exponent >= 0 ? '+' : '-');
01459 if (exponent < 0)
01460 {
01461 exponent = -exponent;
01462 }
01463 out->Append((char)(exponent / 100 + '0'));
01464 out->Append((char)(exponent % 100 / 10 + '0'));
01465 out->Append((char)(exponent % 10 + '0'));
01466 if (width > 0)
01467 {
01468 out->Fill(' ', width);
01469 }
01470 break;
01471 }
01472
01473 delete [] digits;
01474 }
01475
01476
01477 StringPtr String::FormatVA(const String sformat, va_list args)
01478 {
01479 StringBuffer out;
01480 const char *format = sformat.GetChars();
01481
01482 register int width = 0, pad = 0;
01483 char scr[2];
01484
01485 for (; *format != 0; ++format)
01486 {
01487 if (*format == '%')
01488 {
01489 ++format;
01490 width = pad = 0;
01491 if (*format == '\0')
01492 break;
01493 if (*format == '%')
01494 {
01495 out.Append((char)*format);
01496 continue;
01497 }
01498 if (*format == '-')
01499 {
01500 ++format;
01501 pad = PAD_RIGHT;
01502 }
01503 while (*format == '0')
01504 {
01505 ++format;
01506 pad |= PAD_ZERO;
01507 }
01508 for ( ; *format >= '0' && *format <= '9'; ++format)
01509 {
01510 width *= 10;
01511 width += *format - '0';
01512 }
01513 if( *format == 's' )
01514 {
01515 register char *s = (char *)va_arg( args, char * );
01516 _prints (&out, s?s:"(null)", width, pad);
01517 continue;
01518 }
01519 if( *format == 'd' )
01520 {
01521 _printi (&out, va_arg( args, int ), 10, 1, width, pad, 'a');
01522 continue;
01523 }
01524 if( *format == 'x' )
01525 {
01526 _printi (&out, va_arg( args, int ), 16, 0, width, pad, 'a');
01527 continue;
01528 }
01529 if( *format == 'X' )
01530 {
01531 _printi (&out, va_arg( args, int ), 16, 0, width, pad, 'A');
01532 continue;
01533 }
01534 if( *format == 'u' )
01535 {
01536 _printi (&out, va_arg( args, int ), 10, 0, width, pad, 'a');
01537 continue;
01538 }
01539 if( *format == 'c' )
01540 {
01541
01542 scr[0] = (char)va_arg( args, int );
01543 scr[1] = '\0';
01544 _prints (&out, scr, width, pad);
01545 continue;
01546 }
01547 if ( *format == 'f' )
01548 {
01549 _printdf(&out, *format, va_arg(args, double), width, pad);
01550 continue;
01551 }
01552 if ( *format == 'e' || *format == 'E')
01553 {
01554 _printdf(&out, *format, va_arg(args, double), width, pad);
01555 continue;
01556 }
01557 if ( *format == 'g' || *format == 'G' )
01558 {
01559 _printdf(&out, *format, va_arg(args, double), width, pad);
01560 continue;
01561 }
01562 }
01563 else
01564 {
01565 out.Append((char) *format);
01566 }
01567 }
01568 return out.ToString();
01569 }
01570
01571
01572 StringPtr String::Format(const String format, ...)
01573 {
01574 va_list args;
01575 va_start(args, format);
01576
01577 StringPtr ret = FormatVA(format, args);
01578
01579 va_end( args );
01580 return ret;
01581 }
01582
01583 StringPtr String::StripQuotes()
01584 {
01585 if ( CharAt(0) == '"' && CharAt( Length() -1 ) == '"' )
01586 {
01587 StringBuffer buf(m_cstr);
01588 buf.RemoveCharAt(0);
01589 buf.RemoveCharAt(buf.Length() - 1);
01590 return buf.ToString();
01591 }
01592 else
01593 {
01594 return StringPtr(new String(*this));
01595 }
01596 }
01597
01598 StringPtr String::ToUpper() const
01599 {
01600 StringBuffer buf(m_len+1);
01601 for (int x = 0; x < m_len; x++)
01602 {
01603 buf.Append((char)toupper(m_cstr[x]));
01604 }
01605 return buf.ToString();
01606 }
01607
01608 StringPtr String::ToLower() const
01609 {
01610 StringBuffer buf(m_len+1);
01611 for (int x = 0; x < m_len; x++)
01612 {
01613 buf.Append((char)tolower(m_cstr[x]));
01614 }
01615 return buf.ToString();
01616 }
01617
01618 bool String::EndsWith( const String& scp ) const
01619 {
01620 int pos = m_len - scp.Length();
01621 const char *cp = scp.m_cstr;
01622 int x;
01623
01624 if ( pos <= 0 )
01625 {
01626 return false;
01627 }
01628 for ( x = pos; x < m_len; x++ )
01629 {
01630 if ( m_cstr[x] != *cp++ )
01631 {
01632 return false;
01633 }
01634 }
01635 return true;
01636 }
01637
01638 bool String::StartsWith( const String& cp ) const
01639 {
01640 int len = cp.Length();
01641 int x;
01642
01643 if ( len > m_len )
01644 {
01645 return false;
01646 }
01647 for ( x = 0; x < len; x++ )
01648 {
01649 if ( m_cstr[x] != cp[x] )
01650 {
01651 return false;
01652 }
01653 }
01654 return true;
01655 }
01656
01657 int String::LastIndexOf( const char ch ) const
01658 {
01659 for ( int pos = m_len-1; pos > -1; pos-- )
01660 {
01661 if ( m_cstr[pos] == ch )
01662 {
01663 return pos;
01664 }
01665 }
01666 return -1;
01667 }
01668
01669 int String::CountChar( const char *str, const int len, const char ch )
01670 {
01671 int count = 0;
01672 for ( int x = 0; x < len; x++ )
01673 {
01674 if ( ch == str[x] )
01675 {
01676 count++;
01677 }
01678 }
01679 return count;
01680 }
01681
01682 RefCountPtr<Array<byte> > String::ToByteArray() const
01683 {
01684 RefCountPtr<Array<byte> > bytes(new Array<byte>(m_len));
01685 for ( int x = 0; x < m_len; x++ )
01686 {
01687 (*bytes)[x] = m_cstr[x];
01688 }
01689
01690 return bytes;
01691 }
01692
01693 String operator +(const char *cp, const String& str)
01694 {
01695 return *String(cp).Cat(str);
01696 }
01697
01698 #if defined(DEBUG) || defined(_DEBUG)
01699 void String::CheckMem() const
01700 {
01701 if ( ! m_isintern )
01702 {
01703 DEBUG_NOTE_MEM_ALLOCATION( m_cstr );
01704 }
01705 }
01706
01707 void String::ValidateMem() const
01708 {
01709 if ( ! m_isintern )
01710 {
01711 ASSERT_MEM( m_cstr, m_len );
01712 }
01713 }
01714 #endif