00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00015
00016
00017 #include "pcl/surface/3rdparty/opennurbs/opennurbs.h"
00018
00020
00021
00022
00023 struct ON_aStringHeader
00024 {
00025 int ref_count;
00026 int string_length;
00027 int string_capacity;
00028 char* string_array() {return (char*)(this+1);}
00029 };
00030
00031 static struct {
00032 ON_aStringHeader header;
00033 char s;
00034 } empty_astring = { {-1, 0, 0}, 0 };
00035 static ON_aStringHeader* pEmptyStringHeader = &empty_astring.header;
00036 static const char* pEmptyaString = &empty_astring.s;
00037
00039
00040
00041 void ON_String::Create()
00042 {
00043 m_s = (char*)pEmptyaString;
00044 }
00045
00046 void ON_String::Destroy()
00047 {
00048 ON_aStringHeader* p = Header();
00049 if ( p != pEmptyStringHeader && p->ref_count > 0 ) {
00050 p->ref_count--;
00051 if ( p->ref_count == 0 )
00052 onfree(p);
00053 }
00054 Create();
00055 }
00056
00057 void ON_String::Empty()
00058 {
00059 ON_aStringHeader* p = Header();
00060 if ( p != pEmptyStringHeader ) {
00061 if ( p->ref_count > 1 ) {
00062
00063 p->ref_count--;
00064 Create();
00065 }
00066 else if ( p->ref_count == 1 ) {
00067
00068 if (m_s && p->string_capacity>0)
00069 *m_s = 0;
00070 p->string_length = 0;
00071 }
00072 else {
00073
00074 ON_ERROR("ON_String::Empty() encountered invalid header - fixed.");
00075 Create();
00076 }
00077 }
00078 else {
00079
00080 Create();
00081 }
00082 }
00083
00084 void ON_String::EmergencyDestroy()
00085 {
00086 Create();
00087 }
00088
00089 void ON_String::EnableReferenceCounting( bool bEnable )
00090 {
00091
00092 }
00093
00094 bool ON_String::IsReferenceCounted() const
00095 {
00096 return true;
00097 }
00098
00099
00100 ON_aStringHeader* ON_String::Header() const
00101 {
00102 ON_aStringHeader* p = (ON_aStringHeader*)m_s;
00103 if (p)
00104 p--;
00105 else
00106 p = pEmptyStringHeader;
00107 return p;
00108 }
00109
00110 void ON_String::CreateArray( int capacity )
00111 {
00112 Destroy();
00113 if ( capacity > 0 ) {
00114 ON_aStringHeader* p =
00115 (ON_aStringHeader*)onmalloc( sizeof(ON_aStringHeader) + (capacity+1)*sizeof(*m_s) );
00116 p->ref_count = 1;
00117 p->string_length = 0;
00118 p->string_capacity = capacity;
00119 m_s = p->string_array();
00120 memset( m_s, 0, (capacity+1)*sizeof(*m_s) );
00121 }
00122 }
00123
00124 void ON_String::CopyArray()
00125 {
00126
00127
00128 ON_aStringHeader* p = Header();
00129 if ( p != pEmptyStringHeader && p && p->ref_count > 1 )
00130 {
00131 const char* s = m_s;
00132
00133
00134
00135 Destroy();
00136 CopyToArray( p->string_capacity, s );
00137 if ( p->string_length < p->string_capacity )
00138 {
00139 Header()->string_length = p->string_length;
00140 }
00141 }
00142 }
00143
00144 void ON_String::ReserveArray( size_t array_capacity )
00145 {
00146 ON_aStringHeader* p = Header();
00147 const int capacity = (int) array_capacity;
00148 if ( p == pEmptyStringHeader )
00149 {
00150 CreateArray(capacity);
00151 }
00152 else if ( p->ref_count > 1 )
00153 {
00154 CreateArray(capacity);
00155 ON_aStringHeader* p1 = Header();
00156 const int size = (capacity < p->string_length) ? capacity : p->string_length;
00157 if ( size > 0 )
00158 {
00159 memcpy( p1->string_array(), p->string_array(), size*sizeof(*m_s) );
00160 p1->string_length = size;
00161 }
00162 }
00163 else if ( capacity > p->string_capacity )
00164 {
00165 p = (ON_aStringHeader*)onrealloc( p, sizeof(ON_aStringHeader) + (capacity+1)*sizeof(*m_s) );
00166 m_s = p->string_array();
00167 memset( &m_s[p->string_capacity], 0, (1+capacity-p->string_capacity)*sizeof(*m_s) );
00168 p->string_capacity = capacity;
00169 }
00170 }
00171
00172 void ON_String::ShrinkArray()
00173 {
00174 ON_aStringHeader* p = Header();
00175 if ( p != pEmptyStringHeader ) {
00176 if ( p->string_length < 1 ) {
00177 Destroy();
00178 }
00179 else if ( p->ref_count > 1 ) {
00180
00181 CreateArray(p->string_length);
00182 ON_aStringHeader* p1 = Header();
00183 memcpy( m_s, p->string_array(), p->string_length*sizeof(*m_s));
00184 p1->string_length = p->string_length;
00185 m_s[p1->string_length] = 0;
00186 }
00187 else if ( p->string_length < p->string_capacity ) {
00188
00189 p = (ON_aStringHeader*)onrealloc( p, sizeof(ON_aStringHeader) + (p->string_length+1)*sizeof(*m_s) );
00190 p->string_capacity = p->string_length;
00191 m_s = p->string_array();
00192 m_s[p->string_length] = 0;
00193 }
00194 }
00195 }
00196
00197 void ON_String::CopyToArray( const ON_String& s )
00198 {
00199 CopyToArray( s.Length(), s.Array() );
00200 }
00201
00202 void ON_String::CopyToArray( int size, const char* s )
00203 {
00204 if ( size > 0 && s && s[0] ) {
00205 ReserveArray(size);
00206 memcpy(m_s, s, size*sizeof(*m_s));
00207 Header()->string_length = size;
00208 m_s[Header()->string_length] = 0;
00209 }
00210 else {
00211 if ( Header()->ref_count > 1 )
00212 Destroy();
00213 else {
00214 Header()->string_length = 0;
00215 m_s[0] = 0;
00216 }
00217 }
00218 }
00219
00220 void ON_String::CopyToArray( int size, const unsigned char* s )
00221 {
00222 CopyToArray( size, ((char*)s) );
00223 }
00224
00225 void ON_String::AppendToArray( const ON_String& s )
00226 {
00227 AppendToArray( s.Length(), s.Array() );
00228 }
00229
00230 void ON_String::AppendToArray( int size, const char* s )
00231 {
00232 if ( size > 0 && s && s[0] ) {
00233 ReserveArray(size + Header()->string_length );
00234
00235 memcpy(&m_s[Header()->string_length], s, size*sizeof(*m_s));
00236 Header()->string_length += size;
00237 m_s[Header()->string_length] = 0;
00238 }
00239 }
00240
00241 void ON_String::AppendToArray( int size, const unsigned char* s )
00242 {
00243 AppendToArray( size, ((char*)s) );
00244 }
00245
00246 int ON_String::Length( const char* s )
00247 {
00248 size_t slen = s ? strlen(s) : 0;
00249 int n = ((0 < slen && slen <= 2147483645) ?((int)slen) : 0);
00250 return n;
00251 }
00252
00253 int ON_String::Length( const unsigned char* s )
00254 {
00255 return ON_String::Length((const char*)s);
00256 }
00257
00259
00260
00261 ON_String::ON_String()
00262 {
00263 Create();
00264 }
00265
00266 ON_String::~ON_String()
00267 {
00268 Destroy();
00269 }
00270
00271 ON_String::ON_String(const ON_String& src)
00272 {
00273 if ( src.Header()->ref_count > 0
00274 && 0 == ON_WorkerMemoryPool()
00275 )
00276 {
00277 m_s = src.m_s;
00278 src.Header()->ref_count++;
00279 }
00280 else
00281 {
00282 Create();
00283 *this = src.m_s;
00284 }
00285 }
00286
00287 ON_String::ON_String( const char* s )
00288 {
00289 Create();
00290 if ( s && s[0] ) {
00291 CopyToArray( (int)strlen(s), s );
00292 }
00293 }
00294
00295 ON_String::ON_String( const char* s, int length )
00296 {
00297 Create();
00298 if ( s && length > 0 ) {
00299 CopyToArray(length,s);
00300 }
00301 }
00302
00303 ON_String::ON_String( char c, int repeat_count )
00304 {
00305 Create();
00306 if ( repeat_count > 0 ) {
00307 ReserveArray(repeat_count);
00308 memset( m_s, c, repeat_count*sizeof(*m_s) );
00309 m_s[repeat_count] = 0;
00310 Header()->string_length = repeat_count;
00311 }
00312 }
00313
00314 ON_String::ON_String( const unsigned char* s )
00315 {
00316 Create();
00317 if ( s && s[0] )
00318 {
00319 CopyToArray( (int)strlen((const char*)s), (const char*)s );
00320 }
00321 }
00322
00323 ON_String::ON_String( const unsigned char* s, int length )
00324 {
00325 Create();
00326 if ( s && length > 0 ) {
00327 CopyToArray(length,s);
00328 }
00329 }
00330
00331 ON_String::ON_String( unsigned char c, int repeat_count )
00332 {
00333 Create();
00334 if ( repeat_count > 0 ) {
00335 ReserveArray(repeat_count);
00336 memset( m_s, c, repeat_count*sizeof(*m_s) );
00337 m_s[repeat_count] = 0;
00338 Header()->string_length = repeat_count;
00339 }
00340 }
00341
00342
00343 ON_String::ON_String( const wchar_t* w)
00344 {
00345 Create();
00346 if ( w && w[0] ) {
00347 *this = w;
00348 }
00349 }
00350
00351 ON_String::ON_String( const wchar_t* w, int w_length )
00352 {
00353
00354 Create();
00355 if ( w && w[0] ) {
00356 CopyToArray( w_length, w );
00357 }
00358 }
00359
00360
00361 ON_String::ON_String( const ON_wString& w )
00362 {
00363 Create();
00364 *this = w;
00365 }
00366
00367
00368
00369 #if defined (ON_OS_WINDOWS)
00370 bool ON_String::LoadResourceString( HINSTANCE instance, UINT id )
00371 {
00372 char s[2048];
00373 int length;
00374
00375 Destroy();
00376 length = ::LoadStringA( instance, id, s, 2047 );
00377 if ( length > 0 && length < 2048 ) {
00378 CopyToArray( length, s );
00379 }
00380 return (length > 0 );
00381 }
00382 #endif
00383
00384 int ON_String::Length() const
00385 {
00386 return Header()->string_length;
00387 }
00388
00389
00390
00391
00392
00393
00394
00395 char& ON_String::operator[](int i)
00396 {
00397 CopyArray();
00398 return m_s[i];
00399 }
00400
00401 char ON_String::operator[](int i) const
00402 {
00403 return m_s[i];
00404 }
00405
00406 bool ON_String::IsEmpty() const
00407 {
00408 return (Header()->string_length <= 0 ) ? true : false;
00409 }
00410
00411 ON_String& ON_String::operator=(const ON_String& src)
00412 {
00413 if (m_s != src.m_s)
00414 {
00415 if ( src.IsEmpty() )
00416 {
00417 Destroy();
00418 Create();
00419 }
00420 else if ( src.Header()->ref_count > 0
00421 && 0 == ON_WorkerMemoryPool()
00422 )
00423 {
00424 Destroy();
00425 src.Header()->ref_count++;
00426 m_s = src.m_s;
00427 }
00428 else
00429 {
00430 ReserveArray(src.Length());
00431 memcpy( m_s, src.Array(), src.Length()*sizeof(*m_s));
00432 Header()->string_length = src.Length();
00433 }
00434 }
00435 return *this;
00436 }
00437
00438 ON_String& ON_String::operator=( char c )
00439 {
00440 CopyToArray( 1, &c );
00441 return *this;
00442 }
00443
00444 ON_String& ON_String::operator=( const char* s )
00445 {
00446 if ( (void*)s != (void*)m_s )
00447 CopyToArray( Length(s), s);
00448 return *this;
00449 }
00450
00451 ON_String& ON_String::operator=( unsigned char c )
00452 {
00453 CopyToArray( 1, &c );
00454 return *this;
00455 }
00456
00457 ON_String& ON_String::operator=( const unsigned char* s )
00458 {
00459 if ( (void*)s != (void*)m_s )
00460 CopyToArray( Length(s), s);
00461 return *this;
00462 }
00463
00464 ON_String& ON_String::operator=( const wchar_t* w )
00465 {
00466
00467 int w_length = 0;
00468 if ( w ) while ( w[w_length] ) w_length++;
00469 CopyToArray( w_length, w);
00470 return *this;
00471 }
00472
00473 ON_String& ON_String::operator=( const ON_wString& w )
00474 {
00475 *this = w.Array();
00476 return *this;
00477 }
00478
00479
00480 ON_String ON_String::operator+(const ON_String& s2) const
00481 {
00482 ON_String s(*this);
00483 s.AppendToArray( s2 );
00484 return s;
00485 }
00486
00487 ON_String ON_String::operator+( char s2 ) const
00488 {
00489 ON_String s(*this);
00490 s.AppendToArray( 1, &s2 );
00491 return s;
00492 }
00493
00494 ON_String ON_String::operator+( unsigned char s2 ) const
00495 {
00496 ON_String s(*this);
00497 s.AppendToArray( 1, &s2 );
00498 return s;
00499 }
00500
00501 ON_String ON_String::operator+(const char* s2) const
00502 {
00503 ON_String s(*this);
00504 s.AppendToArray( ON_String::Length(s2), s2 );
00505 return s;
00506 }
00507
00508 ON_String ON_String::operator+( const unsigned char* s2) const
00509 {
00510 ON_String s(*this);
00511 s.AppendToArray( ON_String::Length(s2), s2 );
00512 return s;
00513 }
00514
00516
00517
00518
00519 void ON_String::Append( const char* s , int count )
00520 {
00521
00522 if ( s && count > 0 )
00523 AppendToArray(count,s);
00524 }
00525
00526 void ON_String::Append( const unsigned char* s , int count )
00527 {
00528
00529 if ( s && count > 0 )
00530 AppendToArray(count,s);
00531 }
00532
00533
00534 const ON_String& ON_String::operator+=(const ON_String& s)
00535 {
00536 AppendToArray(s);
00537 return *this;
00538 }
00539
00540 const ON_String& ON_String::operator+=( char s )
00541 {
00542 AppendToArray(1,&s);
00543 return *this;
00544 }
00545
00546 const ON_String& ON_String::operator+=( unsigned char s )
00547 {
00548 AppendToArray(1,&s);
00549 return *this;
00550 }
00551
00552 const ON_String& ON_String::operator+=( const char* s )
00553 {
00554 AppendToArray(Length(s),s);
00555 return *this;
00556 }
00557
00558 const ON_String& ON_String::operator+=( const unsigned char* s )
00559 {
00560 AppendToArray(Length(s),s);
00561 return *this;
00562 }
00563
00564 void ON_String::SetLength(size_t string_length)
00565 {
00566 int length = (int)string_length;
00567 if ( length >= Header()->string_capacity ) {
00568 ReserveArray(length);
00569 }
00570 if ( length >= 0 && length <= Header()->string_capacity ) {
00571 CopyArray();
00572 Header()->string_length = length;
00573 m_s[length] = 0;
00574 }
00575 }
00576
00577 char* ON_String::Array()
00578 {
00579 CopyArray();
00580 return ( Header()->string_capacity > 0 ) ? m_s : 0;
00581 }
00582
00583 const char* ON_String::Array() const
00584 {
00585 return ( Header()->string_capacity > 0 ) ? m_s : 0;
00586 }
00587
00588
00589
00590
00591
00592
00593 unsigned int ON_String::SizeOf() const
00594 {
00595 size_t sz = sizeof(*this);
00596 if ( ((const void*)m_s) != ((const void*)pEmptyaString) )
00597 sz += (sizeof(ON_aStringHeader) + (Header()->string_capacity+1));
00598 return (unsigned int)sz;
00599 }
00600
00601 ON__UINT32 ON_String::DataCRC(ON__UINT32 current_remainder) const
00602 {
00603 int string_length = Header()->string_length;
00604 if ( string_length > 0 )
00605 {
00606 current_remainder = ON_CRC32(current_remainder,string_length*sizeof(*m_s),m_s);
00607 }
00608 return current_remainder;
00609 }
00610
00611 int ON_String::Compare( const char* s ) const
00612 {
00613 int rc = 0;
00614 if ( s && s[0] ) {
00615 if ( IsEmpty() ) {
00616 rc = -1;
00617 }
00618 else {
00619 rc = strcmp( m_s, s );
00620 }
00621 }
00622 else {
00623 rc = IsEmpty() ? 0 : 1;
00624 }
00625 return rc;
00626 }
00627
00628 int ON_String::Compare( const unsigned char* s) const
00629 {
00630 return ON_String::Compare((const char*)s);
00631 }
00632
00633 int ON_String::CompareNoCase( const char* s) const
00634 {
00635 int rc = 0;
00636 if ( s && s[0] ) {
00637 if ( IsEmpty() ) {
00638 rc = -1;
00639 }
00640 else {
00641 rc = on_stricmp( m_s, s );
00642 }
00643 }
00644 else {
00645 rc = IsEmpty() ? 0 : 1;
00646 }
00647 return rc;
00648 }
00649
00650 int ON_String::CompareNoCase( const unsigned char* s) const
00651 {
00652 return ON_String::CompareNoCase((const char*)s);
00653 }
00654
00655 ON_String::operator const char*() const
00656 {
00657 return ( m_s == pEmptyaString ) ? NULL : m_s;
00658 }
00659
00660
00661 bool ON_WildCardMatch(const char* s, const char* pattern)
00662 {
00663 if ( !pattern || !pattern[0] ) {
00664 return ( !s || !s[0] ) ? true : false;
00665 }
00666
00667 if ( *pattern == '*' ) {
00668 pattern++;
00669 while ( *pattern == '*' )
00670 pattern++;
00671
00672 if ( !pattern[0] )
00673 return true;
00674
00675 while (*s) {
00676 if ( ON_WildCardMatch(s,pattern) )
00677 return true;
00678 s++;
00679 }
00680
00681 return false;
00682 }
00683
00684 while ( *pattern != '*' )
00685 {
00686 if ( *pattern == '?' ) {
00687 if ( *s) {
00688 pattern++;
00689 s++;
00690 continue;
00691 }
00692 return false;
00693 }
00694
00695 if ( *pattern == '\\' ) {
00696 switch( pattern[1] )
00697 {
00698 case '*':
00699 case '?':
00700 pattern++;
00701 break;
00702 }
00703 }
00704 if ( *pattern != *s ) {
00705 return false;
00706 }
00707
00708 if ( *s == 0 )
00709 return true;
00710
00711 pattern++;
00712 s++;
00713 }
00714
00715 return ON_WildCardMatch(s,pattern);
00716 }
00717
00718
00719 bool ON_WildCardMatchNoCase(const char* s, const char* pattern)
00720 {
00721 if ( !pattern || !pattern[0] ) {
00722 return ( !s || !s[0] ) ? true : false;
00723 }
00724
00725 if ( *pattern == '*' )
00726 {
00727 pattern++;
00728 while ( *pattern == '*' )
00729 pattern++;
00730
00731 if ( !pattern[0] )
00732 return true;
00733
00734 while (*s) {
00735 if ( ON_WildCardMatchNoCase(s,pattern) )
00736 return true;
00737 s++;
00738 }
00739
00740 return false;
00741 }
00742
00743 while ( *pattern != '*' )
00744 {
00745 if ( *pattern == '?' ) {
00746 if ( *s) {
00747 pattern++;
00748 s++;
00749 continue;
00750 }
00751 return false;
00752 }
00753
00754 if ( *pattern == '\\' ) {
00755 switch( pattern[1] )
00756 {
00757 case '*':
00758 case '?':
00759 pattern++;
00760 break;
00761 }
00762 }
00763 if ( toupper(*pattern) != toupper(*s) ) {
00764 return false;
00765 }
00766
00767 if ( *s == 0 )
00768 return true;
00769
00770 pattern++;
00771 s++;
00772 }
00773
00774 return ON_WildCardMatchNoCase(s,pattern);
00775 }
00776
00777 bool ON_String::WildCardMatch( const char* pattern) const
00778 {
00779 return ON_WildCardMatch(m_s,pattern);
00780 }
00781
00782 bool ON_String::WildCardMatch( const unsigned char* pattern ) const
00783 {
00784 return ON_WildCardMatch(m_s,(const char*)pattern);
00785 }
00786
00787 bool ON_String::WildCardMatchNoCase( const char* pattern) const
00788 {
00789 return ON_WildCardMatchNoCase(m_s,pattern);
00790 }
00791
00792 bool ON_String::WildCardMatchNoCase( const unsigned char* pattern ) const
00793 {
00794 return ON_WildCardMatchNoCase(m_s,(const char*)pattern);
00795 }
00796
00797 int ON_String::Replace( const char* token1, const char* token2 )
00798 {
00799 int count = 0;
00800
00801 if ( 0 != token1 && 0 != token1[0] )
00802 {
00803 if ( 0 == token2 )
00804 token2 = "";
00805 const int len1 = (int)strlen(token1);
00806 if ( len1 > 0 )
00807 {
00808 const int len2 = (int)strlen(token2);
00809 int len = Length();
00810 if ( len >= len1 )
00811 {
00812
00813 ON_SimpleArray<int> n(32);
00814 const char* s = m_s;
00815 int i;
00816 for ( i = 0; i <= len-len1; )
00817 {
00818 if ( strncmp(s,token1,len1) )
00819 {
00820 s++;
00821 i++;
00822 }
00823 else
00824 {
00825 n.Append(i);
00826 i += len1;
00827 s += len1;
00828 }
00829 }
00830
00831 count = n.Count();
00832
00833
00834
00835 const int newlen = len + (count*(len2-len1));
00836 if ( 0 == newlen )
00837 {
00838 Destroy();
00839 return count;
00840 }
00841
00842 CopyArray();
00843
00844
00845
00846
00847
00848
00849
00850 ReserveArray( ((newlen<len) ? len : newlen) );
00851
00852 int i0, i1, ni, j;
00853
00854 if ( len2 > len1 )
00855 {
00856
00857 i1 = newlen;
00858 i0 = len;
00859 for ( ni =0; ni < count; ni++ )
00860 n[ni] = n[ni] + len1;
00861 for ( ni = count-1; ni >= 0; ni-- )
00862 {
00863 j = n[ni];
00864 while ( i0 > j )
00865 {
00866 i0--;
00867 i1--;
00868 m_s[i1] = m_s[i0];
00869 }
00870 i1 -= len2;
00871 i0 -= len1;
00872 memcpy(&m_s[i1],token2,len2*sizeof(m_s[0]));
00873 }
00874 }
00875 else
00876 {
00877
00878 i0 = i1 = n[0];
00879 n.Append(len);
00880 for ( ni = 0; ni < count; ni++ )
00881 {
00882 if ( len2 > 0 )
00883 {
00884 memcpy(&m_s[i1],token2,len2*sizeof(m_s[0]));
00885 i1 += len2;
00886 }
00887 i0 += len1;
00888 j = n[ni+1];
00889 while ( i0 < j )
00890 {
00891 m_s[i1++] = m_s[i0++];
00892 }
00893 }
00894 }
00895 Header()->string_length = newlen;
00896 m_s[newlen] = 0;
00897 }
00898 }
00899 }
00900
00901 return count;
00902 }
00903
00904 int ON_String::Replace( const unsigned char* token1, const unsigned char* token2 )
00905 {
00906 return Replace((const char*)token1, (const char*)token2);
00907 }
00908
00909 int ON_String::Replace( char token1, char token2 )
00910 {
00911 int count = 0;
00912 int i = Length();
00913 while (i--)
00914 {
00915 if ( token1 == m_s[i] )
00916 {
00917 if ( 0 == count )
00918 CopyArray();
00919 m_s[i] = token2;
00920 count++;
00921 }
00922 }
00923 return count;
00924 }
00925
00926 int ON_String::Replace( unsigned char token1, unsigned char token2 )
00927 {
00928 return Replace((const char)token1, (const char)token2);
00929 }
00930
00931
00933
00934 int ON_String::Find( char c ) const
00935 {
00936
00937 char s[2];
00938 s[0] = c;
00939 s[1] = 0;
00940 return Find( s );
00941 }
00942
00943 int ON_String::Find( unsigned char c ) const
00944 {
00945 return Find( (char)c );
00946 }
00947
00948 int ON_String::ReverseFind( char c ) const
00949 {
00950
00951 if ( IsEmpty() )
00952 return -1;
00953 int i;
00954 const int length = Length();
00955 for ( i = length-1; i >= 0; i-- ) {
00956 if ( c == m_s[i] )
00957 return i;
00958 }
00959 return -1;
00960 }
00961
00962 int ON_String::ReverseFind( unsigned char c ) const
00963 {
00964 return ReverseFind( (char)c );
00965 }
00966
00967 int ON_String::Find( const char* s ) const
00968 {
00969 int rc = -1;
00970 if ( s && s[0] && !IsEmpty() ) {
00971 const char* p;
00972 p = strstr( m_s, s );
00973 if ( p )
00974 {
00975 rc = ((int)(p-m_s));
00976 }
00977 }
00978 return rc;
00979 }
00980
00981 int ON_String::Find( const unsigned char* s ) const
00982 {
00983 return Find( (const char*)s );
00984 }
00985
00986 void ON_String::MakeUpper()
00987 {
00988 if ( !IsEmpty() ) {
00989 CopyArray();
00990 on_strupr(m_s);
00991 }
00992 }
00993
00994 void ON_String::MakeLower()
00995 {
00996 if ( !IsEmpty() ) {
00997 CopyArray();
00998 on_strlwr(m_s);
00999 }
01000 }
01001
01002 void ON_String::MakeReverse()
01003 {
01004 if ( !IsEmpty() ) {
01005 CopyArray();
01006 on_strrev(m_s);
01007 }
01008 }
01009
01010 void ON_String::TrimLeft(const char* s)
01011 {
01012 char c;
01013 const char* sc;
01014 char* dc;
01015 int i;
01016 if ( !IsEmpty() ) {
01017 if ( !s )
01018 s = " \t\n";
01019 for ( i = 0; 0 != (c=m_s[i]); i++ )
01020 {
01021 for (sc = s;*sc;sc++) {
01022 if ( *sc == c )
01023 break;
01024 }
01025 if (!(*sc))
01026 break;
01027 }
01028 if ( i > 0 ) {
01029 if ( m_s[i] ) {
01030 CopyArray();
01031 dc = m_s;
01032 sc = m_s+i;
01033 while( 0 != (*dc++ = *sc++) );
01034 Header()->string_length -= i;
01035 }
01036 else
01037 Destroy();
01038 }
01039 }
01040 }
01041
01042 void ON_String::TrimRight(const char* s)
01043 {
01044 char c;
01045 const char* sc;
01046 int i = Header()->string_length;
01047 if ( i > 0 ) {
01048 if ( !s )
01049 s = " \t\n";
01050 for (i--; i >= 0 && 0 != (c=m_s[i]); i-- )
01051 {
01052 for (sc = s;*sc;sc++) {
01053 if ( *sc == c )
01054 break;
01055 }
01056 if (!(*sc))
01057 break;
01058 }
01059 if ( i < 0 )
01060 Destroy();
01061 else if ( m_s[i+1] ) {
01062 CopyArray();
01063 m_s[i+1] = 0;
01064 Header()->string_length = i+1;
01065 }
01066 }
01067 }
01068
01069 void ON_String::TrimLeftAndRight(const char* s)
01070 {
01071 TrimRight(s);
01072 TrimLeft(s);
01073 }
01074
01075 int ON_String::Remove( const char chRemove)
01076 {
01077 CopyArray();
01078
01079 char* pstrSource = m_s;
01080 char* pstrDest = m_s;
01081 char* pstrEnd = m_s + Length();
01082
01083 while( pstrSource && pstrSource < pstrEnd)
01084 {
01085 if (*pstrSource != chRemove)
01086 {
01087 *pstrDest = *pstrSource;
01088 pstrDest++;
01089 }
01090 pstrSource++;
01091 }
01092
01093 *pstrDest = 0;
01094 int nCount = (int)(pstrSource - pstrDest);
01095
01096 Header()->string_length -= nCount;
01097
01098 return nCount;
01099 }
01100
01101 char ON_String::GetAt( int i ) const
01102 {
01103
01104 return m_s[i];
01105 }
01106
01107 void ON_String::SetAt( int i, char c )
01108 {
01109 if ( i >= 0 && i < Header()->string_length ) {
01110 CopyArray();
01111 m_s[i] = c;
01112 }
01113 }
01114
01115 void ON_String::SetAt( int i, unsigned char c )
01116 {
01117 SetAt( i, (char)c );
01118 }
01119
01120 ON_String ON_String::Mid(int i, int count) const
01121 {
01122 ON_String(s);
01123 if ( i >= 0 && i < Length() && count > 0 ) {
01124 if ( count > Length() - i )
01125 count = Length() - i;
01126 s.CopyToArray( count, &m_s[i] );
01127 }
01128 return s;
01129 }
01130
01131 ON_String ON_String::Mid(int i) const
01132 {
01133 return Mid( i, Length() - i );
01134 }
01135
01136 ON_String ON_String::Left(int count) const
01137 {
01138 ON_String s;
01139 if ( count > Length() )
01140 count = Length();
01141 if ( count > 0 ) {
01142 s.CopyToArray( count, m_s );
01143 }
01144 return s;
01145 }
01146
01147 ON_String ON_String::Right(int count) const
01148 {
01149 ON_String s;
01150 if ( count > Length() )
01151 count = Length();
01152 if ( count > 0 ) {
01153 s.CopyToArray( count, &m_s[Length()-count] );
01154 }
01155 return s;
01156 }
01157
01158 void ON_MSC_CDECL ON_String::Format( const char* sFormat, ...)
01159 {
01160 #define MAX_MSG_LENGTH 2048
01161 char sMessage[MAX_MSG_LENGTH];
01162 va_list args;
01163
01164
01165 memset(sMessage,0,sizeof(sMessage));
01166 if (sFormat) {
01167 va_start(args, sFormat);
01168 on_vsnprintf(sMessage, MAX_MSG_LENGTH-1, sFormat, args);
01169 sMessage[MAX_MSG_LENGTH-1] = 0;
01170 va_end(args);
01171 }
01172 const int len = Length(sMessage);
01173 if ( len < 1 ) {
01174 Destroy();
01175 Create();
01176 }
01177 else {
01178 ReserveArray( len );
01179 CopyToArray( len, sMessage );
01180 }
01181 }
01182
01183 void ON_MSC_CDECL ON_String::Format( const unsigned char* sFormat, ...)
01184 {
01185 #define MAX_MSG_LENGTH 2048
01186 char sMessage[MAX_MSG_LENGTH];
01187 va_list args;
01188
01189
01190 memset(sMessage,0,sizeof(sMessage));
01191 if (sFormat) {
01192 va_start(args, sFormat);
01193 on_vsnprintf(sMessage, MAX_MSG_LENGTH-1, (const char*)sFormat, args);
01194 sMessage[MAX_MSG_LENGTH-1] = 0;
01195 va_end(args);
01196 }
01197 const int len = Length(sMessage);
01198 if ( len < 1 ) {
01199 Destroy();
01200 Create();
01201 }
01202 else {
01203 ReserveArray( len );
01204 CopyToArray( len, sMessage );
01205 }
01206 }
01207
01209
01210 bool ON_String::operator==(const ON_String& s2) const
01211 {
01212 return (Compare(s2) == 0) ? true : false;
01213 }
01214
01215 bool ON_String::operator==(const char* s2) const
01216 {
01217 return (Compare(s2) == 0) ? true : false;
01218 }
01219
01220 bool ON_String::operator!=(const ON_String& s2) const
01221 {
01222 return (Compare(s2) != 0) ? true : false;
01223 }
01224
01225 bool ON_String::operator!=(const char* s2) const
01226 {
01227 return (Compare(s2) != 0) ? true : false;
01228 }
01229
01230 bool ON_String::operator<(const ON_String& s2) const
01231 {
01232 return (Compare(s2) < 0) ? true : false;
01233 }
01234
01235 bool ON_String::operator<(const char* s2) const
01236 {
01237 return (Compare(s2) < 0) ? true : false;
01238 }
01239
01240 bool ON_String::operator>(const ON_String& s2) const
01241 {
01242 return (Compare(s2) > 0) ? true : false;
01243 }
01244
01245 bool ON_String::operator>(const char* s2) const
01246 {
01247 return (Compare(s2) > 0) ? true : false;
01248 }
01249
01250 bool ON_String::operator<=(const ON_String& s2) const
01251 {
01252 return (Compare(s2) <= 0) ? true : false;
01253 }
01254
01255 bool ON_String::operator<=(const char* s2) const
01256 {
01257 return (Compare(s2) <= 0) ? true : false;
01258 }
01259
01260 bool ON_String::operator>=(const ON_String& s2) const
01261 {
01262 return (Compare(s2) >= 0) ? true : false;
01263 }
01264
01265 bool ON_String::operator>=(const char* s2) const
01266 {
01267 return (Compare(s2) >= 0) ? true : false;
01268 }
01269
01270
01271 ON_CheckSum::ON_CheckSum()
01272 {
01273 Zero();
01274 }
01275
01276 ON_CheckSum::~ON_CheckSum()
01277 {
01278 Zero();
01279 }
01280
01281 void ON_CheckSum::Zero()
01282 {
01283 m_size = 0;
01284 m_time = 0;
01285 for ( int i = 0; i < 8; i++ )
01286 m_crc[i] = 0;
01287 }
01288
01289 const ON_CheckSum ON_CheckSum::UnsetCheckSum;
01290
01291 bool ON_CheckSum::IsSet() const
01292 {
01293 return ( 0 != m_size
01294 || 0 != m_time
01295 || 0 != m_crc[0]
01296 || 0 != m_crc[1]
01297 || 0 != m_crc[2]
01298 || 0 != m_crc[3]
01299 || 0 != m_crc[4]
01300 || 0 != m_crc[5]
01301 || 0 != m_crc[6]
01302 || 0 != m_crc[7]
01303 );
01304 }
01305
01306 bool ON_CheckSum::SetBufferCheckSum(
01307 size_t size,
01308 const void* buffer,
01309 time_t time
01310 )
01311 {
01312 bool rc = false;
01313 Zero();
01314 if ( size != 0 && buffer != 0 )
01315 {
01316 m_size = (unsigned int)size;
01317
01318 ON__INT32 crc = 0;
01319 size_t sz, maxsize = 0x40000;
01320 const unsigned char* p = (const unsigned char*)buffer;
01321 for ( int i = 0; i < 7; i++ )
01322 {
01323 if ( size > 0 )
01324 {
01325 sz = (size > maxsize) ? maxsize : size;
01326 crc = ON_CRC32(crc,sz,p);
01327 p += sz;
01328 size -= sz;
01329 maxsize *= 2;
01330 }
01331 m_crc[i] = crc;
01332 }
01333 if ( size > 0 )
01334 {
01335 crc = ON_CRC32(crc,size,p);
01336 }
01337 m_crc[7] = crc;
01338 rc = true;
01339 }
01340 else if ( 0 == size )
01341 {
01342 rc = true;
01343 }
01344 m_time = time;
01345 return rc;
01346 }
01347
01348 bool ON::GetFileStats( const wchar_t* filename,
01349 size_t* filesize,
01350 time_t* create_time,
01351 time_t* lastmodify_time
01352 )
01353 {
01354 bool rc = false;
01355
01356 if (filesize)
01357 *filesize = 0;
01358 if (create_time)
01359 *create_time = 0;
01360 if (lastmodify_time)
01361 *lastmodify_time = 0;
01362
01363 if ( filename && filename[0] )
01364 {
01365 FILE* fp = ON::OpenFile(filename,L"rb");
01366 if ( fp )
01367 {
01368 rc = ON::GetFileStats(fp,filesize,create_time,lastmodify_time);
01369 ON::CloseFile(fp);
01370 }
01371 }
01372
01373 return rc;
01374 }
01375
01376 bool ON::GetFileStats( FILE* fp,
01377 size_t* filesize,
01378 time_t* create_time,
01379 time_t* lastmodify_time
01380 )
01381 {
01382 bool rc = false;
01383
01384 if (filesize)
01385 *filesize = 0;
01386 if (create_time)
01387 *create_time = 0;
01388 if (lastmodify_time)
01389 *lastmodify_time = 0;
01390
01391 if ( fp )
01392 {
01393
01394 #if defined(ON_COMPILER_MSC)
01395
01396
01397 int fd = _fileno(fp);
01398 #if (_MSC_VER >= 1400)
01399
01400
01401
01402 struct _stat64 sb;
01403 memset(&sb,0,sizeof(sb));
01404 int fstat_rc = _fstat64(fd, &sb);
01405 #else
01406
01407
01408 struct _stat sb;
01409 memset(&sb,0,sizeof(sb));
01410 int fstat_rc = _fstat(fd, &sb);
01411 #endif
01412
01413 #else
01414
01415 int fd = fileno(fp);
01416 struct stat sb;
01417 memset(&sb,0,sizeof(sb));
01418 int fstat_rc = fstat(fd, &sb);
01419 #endif
01420
01421
01422 if (0 == fstat_rc)
01423 {
01424 if (filesize)
01425 *filesize = (size_t)sb.st_size;
01426 if (create_time)
01427 *create_time = (time_t)sb.st_ctime;
01428 if (lastmodify_time)
01429 *lastmodify_time = (time_t)sb.st_mtime;
01430 rc = true;
01431 }
01432 }
01433
01434 return rc;
01435 }
01436
01437 bool ON::IsDirectory( const wchar_t* pathname )
01438 {
01439 bool rc = false;
01440
01441 if ( 0 != pathname && 0 != pathname[0] )
01442 {
01443 ON_wString buffer;
01444 const wchar_t* stail = pathname;
01445 while ( 0 != *stail )
01446 stail++;
01447 stail--;
01448 if ( '\\' == *stail || '/' == *stail )
01449 {
01450 const wchar_t trim[2] = {*stail,0};
01451 buffer = pathname;
01452 buffer.TrimRight(trim);
01453 if ( buffer.Length() > 0 )
01454 pathname = buffer;
01455 }
01456 #if defined(ON_COMPILER_MSC)
01457
01458 struct _stat64 buf;
01459 memset(&buf,0,sizeof(buf));
01460 int stat_errno = _wstat64( pathname, &buf );
01461 if ( 0 == stat_errno && 0 != (_S_IFDIR & buf.st_mode) )
01462 {
01463 rc = true;
01464 }
01465 #else
01466 ON_String s = pathname;
01467 const char* utf8pathname = s;
01468 rc = ON::IsDirectory(utf8pathname);
01469 #endif
01470 }
01471
01472 return rc;
01473 }
01474
01475 bool ON::IsDirectory( const char* utf8pathname )
01476 {
01477 bool rc = false;
01478
01479 if ( 0 != utf8pathname && 0 != utf8pathname[0] )
01480 {
01481 ON_String buffer;
01482 const char* stail = utf8pathname;
01483 while ( 0 != *stail )
01484 stail++;
01485 stail--;
01486 if ( '\\' == *stail || '/' == *stail )
01487 {
01488 const char trim[2] = {*stail,0};
01489 buffer = utf8pathname;
01490 buffer.TrimRight(trim);
01491 if ( buffer.Length() > 0 )
01492 utf8pathname = buffer;
01493 }
01494 #if defined(ON_COMPILER_MSC)
01495
01496 struct _stat64 buf;
01497 memset(&buf,0,sizeof(buf));
01498 int stat_errno = _stat64( utf8pathname, &buf );
01499 if ( 0 == stat_errno && 0 != (_S_IFDIR & buf.st_mode) )
01500 {
01501 rc = true;
01502 }
01503 #else
01504
01505 struct stat buf;
01506 memset(&buf,0,sizeof(buf));
01507 int stat_errno = stat( utf8pathname, &buf );
01508 if ( 0 == stat_errno && S_ISDIR(buf.st_mode) )
01509 {
01510 rc = true;
01511 }
01512 #endif
01513 }
01514
01515 return rc;
01516 }
01517
01518
01519 int ON::IsOpenNURBSFile( FILE* fp )
01520 {
01521 ON_String sStartSectionComment;
01522 int version = 0;
01523 if ( 0 != fp )
01524 {
01525 ON_BinaryFile archive(ON::read3dm,fp);
01526 if ( !archive.Read3dmStartSection(&version,sStartSectionComment) )
01527 version = 0;
01528 }
01529 return version;
01530 }
01531
01532 int ON::IsOpenNURBSFile( const wchar_t* pathname )
01533 {
01534 int version = 0;
01535 if ( 0 != pathname && 0 != pathname[0] )
01536 {
01537 FILE* fp = ON::OpenFile(pathname,L"rb");
01538 if ( 0 != fp )
01539 {
01540 version = ON::IsOpenNURBSFile(fp);
01541 ON::CloseFile(fp);
01542 }
01543 }
01544 return version;
01545 }
01546
01547 int ON::IsOpenNURBSFile( const char* utf8pathname )
01548 {
01549 int version = 0;
01550 if ( 0 != utf8pathname && 0 != utf8pathname[0] )
01551 {
01552 FILE* fp = ON::OpenFile(utf8pathname,"rb");
01553 if ( 0 != fp )
01554 {
01555 version = ON::IsOpenNURBSFile(fp);
01556 ON::CloseFile(fp);
01557 }
01558 }
01559 return version;
01560 }
01561
01562 bool ON_CheckSum::SetFileCheckSum( FILE* fp )
01563 {
01564 bool rc = false;
01565 Zero();
01566 if ( fp )
01567 {
01568 size_t filesize = 0;
01569 time_t filetime = 0;
01570 if ( ON::GetFileStats(fp,&filesize,NULL,&filetime) )
01571 {
01572 m_time = filetime;
01573 }
01574
01575 unsigned char buffer[1024];
01576 int count=1024;
01577 ON__INT32 crc = 0;
01578 size_t sz0 = 0, maxsize = 0x40000;
01579
01580 for( int i = 0; i < 7; i++ )
01581 {
01582 sz0 += maxsize;
01583 while(1024 == count && m_size < sz0)
01584 {
01585 count = (int)fread( buffer, 1, 1024, fp );
01586 if ( count > 0 )
01587 {
01588 m_size += count;
01589 crc = ON_CRC32( crc, count, buffer );
01590 }
01591 }
01592 maxsize *= 2;
01593 m_crc[i] = crc;
01594 }
01595
01596 while(1024 == count)
01597 {
01598 count = (int)fread( buffer, 1, 1024, fp );
01599 if ( count > 0 )
01600 {
01601 m_size += count;
01602 crc = ON_CRC32( crc, count, buffer );
01603 }
01604 }
01605 m_crc[7] = crc;
01606
01607 rc = (filesize == m_size);
01608 }
01609 return rc;
01610 }
01611
01612 bool ON_CheckSum::Write(ON_BinaryArchive& archive) const
01613 {
01614 bool rc = false;
01615 if ( archive.Archive3dmVersion() < 4 )
01616 {
01617
01618
01619 unsigned char b[48];
01620 memset(b,0,sizeof(b));
01621 rc = archive.WriteByte(48,b);
01622 }
01623 else
01624 {
01625 rc = archive.WriteBigSize(m_size);
01626 if (rc)
01627 rc = archive.WriteBigTime(m_time);
01628 if (rc)
01629 rc = archive.WriteInt(8,&m_crc[0]);
01630 }
01631 return rc;
01632 }
01633
01634 bool ON_CheckSum::Read(ON_BinaryArchive& archive)
01635 {
01636 bool rc;
01637
01638 Zero();
01639
01640 rc = archive.ReadBigSize(&m_size);
01641 if (rc)
01642 rc = archive.ReadBigTime(&m_time);
01643 if (rc)
01644 rc = archive.ReadInt(8,&m_crc[0]);
01645
01646 if ( archive.ArchiveOpenNURBSVersion() < 200603100
01647 || archive.Archive3dmVersion() < 4
01648 )
01649 {
01650
01651
01652
01653 Zero();
01654 }
01655
01656 return rc;
01657 }
01658
01659
01660 bool ON_CheckSum::SetFileCheckSum( const wchar_t* filename )
01661 {
01662 bool rc = false;
01663 Zero();
01664 if ( 0 == filename || 0 == filename[0] )
01665 {
01666 rc = true;
01667 }
01668 else
01669 {
01670 FILE* fp = ON::OpenFile(filename,L"rb");
01671 if ( fp )
01672 {
01673 rc = SetFileCheckSum(fp);
01674 ON::CloseFile(fp);
01675 }
01676 }
01677 return rc;
01678 }
01679
01680 bool ON_CheckSum::CheckBuffer(
01681 size_t size,
01682 const void* buffer
01683 ) const
01684 {
01685 if ( m_size != size )
01686 return false;
01687 if ( 0 == size )
01688 return true;
01689 if ( 0 == buffer )
01690 return false;
01691
01692 ON__UINT32 crc = 0;
01693 size_t sz, maxsize = 0x40000;
01694 const unsigned char* p = (const unsigned char*)buffer;
01695 for ( int i = 0; i < 7; i++ )
01696 {
01697 if ( size > 0 )
01698 {
01699 sz = (size > maxsize) ? maxsize : size;
01700 crc = ON_CRC32(crc,sz,p);
01701 p += sz;
01702 size -= sz;
01703 maxsize *= 2;
01704 }
01705 if ( m_crc[i] != crc )
01706 return false;
01707 }
01708 if ( size > 0 )
01709 {
01710 crc = ON_CRC32(crc,size,p);
01711 }
01712 if ( m_crc[7] != crc )
01713 return false;
01714
01715 return true;
01716 }
01717
01718 bool ON_CheckSum::CheckFile(
01719 FILE* fp,
01720 bool bSkipTimeCheck
01721 ) const
01722 {
01723 if ( !fp )
01724 return false;
01725
01726 size_t filesize=0;
01727 time_t filetime=0;
01728 if ( ON::GetFileStats( fp, &filesize, NULL, &filetime ) )
01729 {
01730 if ( m_size != filesize )
01731 {
01732 return false;
01733 }
01734
01735 if ( !bSkipTimeCheck && m_time != filetime)
01736 {
01737 return false;
01738 }
01739 }
01740
01741 unsigned char buffer[1024];
01742 int count=1024;
01743 ON__UINT32 crc = 0;
01744 size_t sz0 = 0, maxsize = 0x40000;
01745 size_t sz = 0;
01746
01747 for( int i = 0; i < 7; i++ )
01748 {
01749 sz0 += maxsize;
01750 while(1024 == count && sz < sz0)
01751 {
01752 count = (int)fread( buffer, 1, 1024, fp );
01753 if ( count > 0 )
01754 {
01755 sz += count;
01756 crc = ON_CRC32( crc, count, buffer );
01757 }
01758 }
01759 maxsize *= 2;
01760 if ( m_crc[i] != crc )
01761 return false;
01762 }
01763
01764 while(1024 == count)
01765 {
01766 count = (int)fread( buffer, 1, 1024, fp );
01767 if ( count > 0 )
01768 {
01769 sz += count;
01770 crc = ON_CRC32( crc, count, buffer );
01771 }
01772 }
01773 if (m_crc[7] != crc)
01774 return false;
01775
01776 if ( sz != m_size )
01777 return false;
01778
01779 return true;
01780 }
01781
01782 bool ON_CheckSum::CheckFile(
01783 const wchar_t* filename,
01784 bool bSkipTimeCheck
01785 ) const
01786 {
01787 bool rc = false;
01788 if ( filename && filename[0] )
01789 {
01790 FILE* fp = ON::OpenFile(filename,L"rb");
01791 if ( fp )
01792 {
01793 rc = CheckFile(fp,bSkipTimeCheck);
01794 ON::CloseFile(fp);
01795 }
01796 }
01797 return rc;
01798 }
01799
01800 void ON_CheckSum::Dump(ON_TextLog& text_log) const
01801 {
01802
01803
01804
01805 unsigned long long u;
01806
01807
01808 text_log.Print("Checksum:");
01809 if ( !IsSet() )
01810 text_log.Print("zero (not set)\n");
01811 else
01812 {
01813 text_log.PushIndent();
01814 text_log.Print("\n");
01815 u = (unsigned long long)m_size;
01816 text_log.Print("Size: %llu bytes\n",u);
01817 u = (unsigned long long)m_time;
01818 text_log.Print("Last Modified Time: %u (seconds since January 1, 1970, UCT)\n",u);
01819 text_log.Print("CRC List: %08x, %08x, %08x, %08x, %08x, %08x, %08x, %08x\n",
01820 m_crc[0],m_crc[1],m_crc[2],m_crc[3],m_crc[4],m_crc[5],m_crc[6],m_crc[7]
01821 );
01822 text_log.PopIndent();
01823 }
01824 }