0027838: Foundation Classes - support wchar_t* input within TCollection_AsciiString...
[occt.git] / src / TCollection / TCollection_AsciiString.cxx
1 // Copyright (c) 1993-1999 Matra Datavision
2 // Copyright (c) 1999-2014 OPEN CASCADE SAS
3 //
4 // This file is part of Open CASCADE Technology software library.
5 //
6 // This library is free software; you can redistribute it and/or modify it under
7 // the terms of the GNU Lesser General Public License version 2.1 as published
8 // by the Free Software Foundation, with special exception defined in the file
9 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
10 // distribution for complete text of the license and disclaimer of any warranty.
11 //
12 // Alternatively, this file may be used under the terms of Open CASCADE
13 // commercial license or contractual agreement.
14
15 #include <TCollection_AsciiString.hxx>
16
17 #include <NCollection_UtfIterator.hxx>
18 #include <Standard.hxx>
19 #include <Standard_NegativeValue.hxx>
20 #include <Standard_NullObject.hxx>
21 #include <Standard_NumericError.hxx>
22 #include <Standard_OutOfRange.hxx>
23 #include <TCollection_ExtendedString.hxx>
24 #include <TCollection_HAsciiString.hxx>
25
26 #include <cctype>
27 #include <cstdio>
28 #include <cstring>
29 // Shortcuts to standard allocate and reallocate functions
30 static inline Standard_PCharacter Allocate(const Standard_Size aLength)
31 {
32   return (Standard_PCharacter)Standard::Allocate (aLength);
33 }
34 static inline Standard_PCharacter Reallocate (Standard_Address aAddr,
35                                               const Standard_Size aLength)
36 {
37   return (Standard_PCharacter)Standard::Reallocate (aAddr, aLength);
38 }
39 static inline void Free (Standard_PCharacter aAddr)
40 {
41   Standard_Address aPtr = aAddr;
42   Standard::Free (aPtr);
43 }
44
45 // ----------------------------------------------------------------------------
46 // Create an empty AsciiString
47 // ----------------------------------------------------------------------------
48 TCollection_AsciiString::TCollection_AsciiString()
49 {
50   mylength = 0;
51   
52   mystring = Allocate(mylength+1);
53   mystring[mylength] = '\0';
54 }
55
56
57 // ----------------------------------------------------------------------------
58 // Create an asciistring from a Standard_CString
59 // ----------------------------------------------------------------------------
60 TCollection_AsciiString::TCollection_AsciiString(const Standard_CString astring)
61   : mystring(0), mylength(0)
62 {
63   if (astring) {
64     mylength = Standard_Integer( strlen(astring) );
65     mystring = Allocate(mylength+1);
66     strncpy(mystring,astring,mylength);
67     mystring[mylength] = '\0';
68   }
69   else {
70     Standard_NullObject::Raise("TCollection_AsciiString : parameter 'astring'");
71   }
72 }
73
74 // ----------------------------------------------------------------------------
75 // Create an asciistring from a Standard_CString
76 // ----------------------------------------------------------------------------
77 TCollection_AsciiString::TCollection_AsciiString(const Standard_CString astring,
78                                                  const Standard_Integer aLen )
79   : mystring(0), mylength(aLen)
80 {
81   if (astring) {
82     mystring = Allocate(mylength+1);
83     strncpy( mystring , astring , mylength );
84     mystring [ mylength ] = '\0' ;
85   }
86   else {
87     Standard_NullObject::Raise("TCollection_AsciiString : parameter 'astring'");
88   }
89 }
90
91 // ----------------------------------------------------------------------------
92 // Create an asciistring from a Standard_Character
93 // ----------------------------------------------------------------------------
94 TCollection_AsciiString::TCollection_AsciiString(const Standard_Character aChar)
95      : mystring(0)
96 {
97   if ( aChar != '\0' ) {
98     mylength    = 1;
99     mystring    = Allocate(2);
100     mystring[0] = aChar;
101     mystring[1] = '\0';
102   }
103   else {
104     mylength = 0;
105     mystring = Allocate(mylength+1);
106     mystring[mylength] = '\0';
107   }
108 }
109
110 // ----------------------------------------------------------------------------
111 // Create an AsciiString from a filler
112 // ----------------------------------------------------------------------------
113 TCollection_AsciiString::TCollection_AsciiString(const Standard_Integer length,
114                                                  const Standard_Character filler )
115 {
116   mystring = Allocate(length+1);
117   mylength = length;
118   for (int i = 0 ; i < length ; i++) mystring[i] = filler;
119   mystring[length] = '\0';
120 }
121
122 // ----------------------------------------------------------------------------
123 // Create an AsciiString from an Integer
124 // ----------------------------------------------------------------------------
125 TCollection_AsciiString::TCollection_AsciiString(const Standard_Integer aValue)
126      : mystring(0)
127 {
128   char t [13];
129   mylength = Sprintf( t,"%d",aValue);
130   mystring = Allocate(mylength+1);
131   strncpy( mystring , t , mylength );
132   mystring[mylength] = '\0';
133 }
134
135 // ----------------------------------------------------------------------------
136 // Create an asciistring from a real
137 // ----------------------------------------------------------------------------
138 TCollection_AsciiString::TCollection_AsciiString(const Standard_Real aValue)
139      : mystring(0)
140 {
141   char t [50];
142   mylength = Sprintf( t,"%g",aValue);
143   mystring = Allocate(mylength+1);
144   strncpy( mystring , t , mylength );
145   mystring[mylength] = '\0';
146 }
147
148 // ----------------------------------------------------------------------------
149 // Create an asciistring from an asciistring
150 // ----------------------------------------------------------------------------
151 TCollection_AsciiString::TCollection_AsciiString(const TCollection_AsciiString& astring)
152      : mystring(0)
153 {
154   mylength = astring.mylength;
155   mystring = Allocate(mylength+1);
156   if ( mylength )
157     strncpy(mystring,astring.mystring,mylength);
158   mystring[mylength] = '\0';
159 }
160
161 // ----------------------------------------------------------------------------
162 // Create an asciistring from a character
163 // ----------------------------------------------------------------------------
164 TCollection_AsciiString::TCollection_AsciiString(
165                          const TCollection_AsciiString& astring ,
166                          const Standard_Character other )
167      : mystring(0)
168 {
169   mylength = astring.mylength + 1 ;
170   mystring = Allocate(mylength+1);
171   if ( astring.mylength ) {
172     strncpy( mystring , astring.mystring , astring.mylength ) ;
173   }
174   mystring[mylength-1] = other ;
175   mystring[mylength] = '\0' ;
176 }
177
178 // ----------------------------------------------------------------------------
179 // Create an asciistring from an asciistring
180 // ----------------------------------------------------------------------------
181 TCollection_AsciiString::TCollection_AsciiString(
182                          const TCollection_AsciiString& astring ,
183                          const Standard_CString other )
184      : mystring(0)
185 {
186   Standard_Integer otherlength = Standard_Integer( other ? strlen( other ) : 0 );
187   mylength = astring.mylength + otherlength ;
188   mystring = Allocate(mylength+1);
189   if ( astring.mylength ) {
190     strncpy( mystring , astring.mystring , astring.mylength ) ;
191   }
192   if ( otherlength ) {
193     strncpy( mystring + astring.mylength, other, otherlength );
194   }
195   mystring[ mylength ] = '\0';
196 }
197
198 // ----------------------------------------------------------------------------
199 // Create an asciistring from an asciistring
200 // ----------------------------------------------------------------------------
201 TCollection_AsciiString::TCollection_AsciiString(
202                          const TCollection_AsciiString& astring ,
203                          const TCollection_AsciiString& other )
204      : mystring(0)
205 {
206   mylength = astring.mylength + other.mylength ;
207   mystring = Allocate(mylength+1);
208   if ( astring.mylength ) {
209     strncpy( mystring , astring.mystring , astring.mylength ) ;
210   }
211   if ( other.mylength ) {
212     strncpy( mystring + astring.mylength, other.mystring , other.mylength ) ;
213   }
214   mystring[mylength] = '\0' ;
215 }
216
217 //---------------------------------------------------------------------------
218 //  Create an asciistring from an ExtendedString 
219 //---------------------------------------------------------------------------
220 TCollection_AsciiString::TCollection_AsciiString(const TCollection_ExtendedString& astring,
221                                                  const Standard_Character replaceNonAscii) 
222      : mystring(0)
223 {
224   if (replaceNonAscii || astring.IsAscii()) {
225     mylength = astring.Length(); 
226     mystring = Allocate(mylength+1);
227     for(int i = 0; i < mylength; i++) {
228       Standard_ExtCharacter c = astring.Value(i+1);
229       mystring[i] = ( IsAnAscii(c) ? ToCharacter(c) : replaceNonAscii );
230     }
231     mystring[mylength] = '\0';
232   }
233   else {
234     // create UTF-8 string
235     mylength = astring.LengthOfCString();
236     mystring = Allocate(mylength+1);
237     astring.ToUTF8CString(mystring);
238   }
239 }
240
241 //---------------------------------------------------------------------------
242 //  Create an TCollection_AsciiString from a Standard_WideChar
243 //---------------------------------------------------------------------------
244 TCollection_AsciiString::TCollection_AsciiString (const Standard_WideChar* theStringUtf)
245 : mystring (NULL),
246   mylength (0)
247 {
248   for (NCollection_UtfWideIter anIter (theStringUtf); *anIter != 0; ++anIter)
249   {
250     mylength += anIter.AdvanceBytesUtf8();
251   }
252
253   mystring = Allocate (mylength + 1);
254   mystring[mylength] = '\0';
255   NCollection_UtfWideIter anIterRead (theStringUtf);
256   for (Standard_Utf8Char* anIterWrite = mystring; *anIterRead != 0; ++anIterRead)
257   {
258     anIterWrite = anIterRead.GetUtf(anIterWrite);
259   }
260 }
261
262 // ----------------------------------------------------------------------------
263 // AssignCat
264 // ----------------------------------------------------------------------------
265 void TCollection_AsciiString::AssignCat(const Standard_Integer other)
266 {
267
268   AssignCat(TCollection_AsciiString(other));
269
270 }
271
272 // ----------------------------------------------------------------------------
273 // AssignCat
274 // ----------------------------------------------------------------------------
275 void TCollection_AsciiString::AssignCat(const Standard_Real other)
276 {
277
278   AssignCat(TCollection_AsciiString(other));
279
280 }
281
282 // ----------------------------------------------------------------------------
283 // AssignCat
284 // ----------------------------------------------------------------------------
285 void TCollection_AsciiString::AssignCat(const Standard_Character other)
286 {
287   if (other != '\0') {
288     mystring = Reallocate (mystring, mylength + 2);
289     mystring[mylength] = other ;
290     mylength += 1;
291     mystring[mylength] = '\0';
292   }
293 }
294
295 // ----------------------------------------------------------------------------
296 // AssignCat
297 // ----------------------------------------------------------------------------
298 void TCollection_AsciiString::AssignCat(const Standard_CString other)
299 {
300   if (other) {
301     Standard_Integer otherlength = Standard_Integer( strlen( other ));
302     if ( otherlength ) {
303       Standard_Integer newlength = mylength+otherlength;
304       mystring = Reallocate (mystring, newlength + 1);
305       strncpy( mystring + mylength, other, otherlength+1 );
306       mylength = newlength;
307     }
308   }
309   else {
310     Standard_NullObject::Raise("TCollection_AsciiString::Operator += parameter other");
311   }
312 }
313
314 // ----------------------------------------------------------------------------
315 // AssignCat
316 // ----------------------------------------------------------------------------
317 void TCollection_AsciiString::AssignCat(const TCollection_AsciiString& other)
318 {
319
320   if (other.mylength) {
321     Standard_Integer newlength = mylength+other.mylength;
322     mystring = Reallocate (mystring, newlength + 1);
323     strncpy( mystring + mylength, other.mystring, other.mylength+1 );
324     mylength = newlength;
325   }
326 }
327
328 // ---------------------------------------------------------------------------
329 // Capitalize
330 // ----------------------------------------------------------------------------
331 void TCollection_AsciiString::Capitalize()
332 {
333   if ( mylength ) mystring[0] = ::UpperCase(mystring[0]);
334   for (int i = 1; i < mylength; i++ )
335     mystring[i] = ::LowerCase(mystring[i]);
336 }
337
338 // ---------------------------------------------------------------------------
339 // Center
340 // ----------------------------------------------------------------------------
341 void TCollection_AsciiString::Center(const Standard_Integer Width ,
342                                      const Standard_Character Filler) 
343 {
344   if(Width > mylength) {
345     Standard_Integer newlength = mylength + ((Width - mylength)/2);
346     LeftJustify(newlength,Filler);
347     RightJustify(Width,Filler);
348   }
349   else if (Width < 0) {
350     Standard_NegativeValue::Raise();
351   }
352 }
353
354 // ----------------------------------------------------------------------------
355 // ChangeAll
356 // ----------------------------------------------------------------------------
357 void TCollection_AsciiString::ChangeAll(const Standard_Character aChar,
358                                         const Standard_Character NewChar,
359                                         const Standard_Boolean CaseSensitive)
360 {
361   if (CaseSensitive){
362     for (int i=0; i < mylength; i++)
363       if (mystring[i] == aChar) mystring[i] = NewChar;
364   }
365   else{
366     Standard_Character anUpperChar = ::UpperCase(aChar);
367     for (int i=0; i < mylength; i++)
368       if (::UpperCase(mystring[i]) == anUpperChar) mystring[i] = NewChar;
369   }
370 }
371
372 // ----------------------------------------------------------------------------
373 // Clear
374 // ----------------------------------------------------------------------------
375 void TCollection_AsciiString::Clear()
376 {
377   if ( mylength > 0 )
378   {
379     Free (mystring);
380     mylength = 0;
381     mystring = Allocate(mylength+1);
382     mystring[mylength] = '\0';
383   }
384 }
385
386 // ----------------------------------------------------------------------------
387 // Copy
388 // ----------------------------------------------------------------------------
389 void TCollection_AsciiString::Copy(const Standard_CString fromwhere)
390 {
391   if (fromwhere) {
392     mylength = Standard_Integer( strlen( fromwhere ));
393     mystring = Reallocate (mystring, mylength + 1);
394     strncpy( mystring, fromwhere, mylength+1 );
395   }
396   else {
397     mylength = 0;
398     mystring[mylength] = '\0';
399   }
400 }
401
402 // ----------------------------------------------------------------------------
403 // Copy
404 // ----------------------------------------------------------------------------
405 void TCollection_AsciiString::Copy(const TCollection_AsciiString& fromwhere)
406 {
407   if (fromwhere.mystring) {
408     mylength = fromwhere.mylength;
409     mystring = Reallocate (mystring, mylength + 1);
410     strncpy( mystring, fromwhere.mystring, mylength+1 );
411   }
412   else {
413     mylength = 0;
414     mystring[mylength] = '\0';
415   }
416 }
417
418 // ----------------------------------------------------------------------------
419 // Destroy
420 // ----------------------------------------------------------------------------
421 TCollection_AsciiString::~TCollection_AsciiString()
422 {
423   if (mystring) 
424     Free (mystring);
425   mystring = 0L;
426 }
427
428 // ----------------------------------------------------------------------------
429 // FirstLocationInSet
430 // ----------------------------------------------------------------------------
431 Standard_Integer TCollection_AsciiString::FirstLocationInSet
432                                 (const TCollection_AsciiString& Set,
433                                  const Standard_Integer         FromIndex,
434                                  const Standard_Integer         ToIndex) const
435 {
436   if (mylength == 0 || Set.mylength == 0) return 0;
437   if (FromIndex > 0 && ToIndex <= mylength && FromIndex <= ToIndex ) {
438     for(int i = FromIndex-1 ; i < ToIndex; i++)
439       for(int j = 0; j < Set.mylength; j++) 
440         if (mystring[i] == Set.mystring[j]) return i+1;
441     return 0;
442   }
443   Standard_OutOfRange::Raise();
444   return 0;
445 }
446
447 // ----------------------------------------------------------------------------
448 // FirstLocationNotInSet
449 // ----------------------------------------------------------------------------
450 Standard_Integer TCollection_AsciiString::FirstLocationNotInSet
451                                  (const TCollection_AsciiString& Set,
452                                   const Standard_Integer         FromIndex,
453                                   const Standard_Integer         ToIndex) const
454 {
455   if (mylength == 0 || Set.mylength == 0) return 0;
456   if (FromIndex > 0 && ToIndex <= mylength && FromIndex <= ToIndex ) {
457     Standard_Boolean find;
458     for (int i = FromIndex-1 ; i < ToIndex; i++) {
459       find = Standard_False;
460       for(int j = 0; j < Set.mylength; j++)  
461         if (mystring[i] == Set.mystring[j]) find = Standard_True;
462       if (!find)  return i+1;
463     }
464     return 0;
465   }
466   Standard_OutOfRange::Raise();
467   return 0;
468 }
469
470 //----------------------------------------------------------------------------
471 // Insert a character before 'where'th character
472 // ----------------------------------------------------------------------------
473 void TCollection_AsciiString::Insert(const Standard_Integer where,
474                                      const Standard_Character what)
475 {
476   if (where > mylength + 1 ) Standard_OutOfRange::Raise
477         ("TCollection_AsciiString::Insert : Parameter where is too big");
478   if (where < 1)             Standard_OutOfRange::Raise
479         ("TCollection_AsciiString::Insert : Parameter where is too small");
480   
481   mystring = Reallocate (mystring, mylength + 2);
482   if (where != mylength +1) {
483     for (int i=mylength-1; i >= where-1; i--)
484       mystring[i+1] = mystring[i];
485   }
486   mystring[where-1] = what;
487   mylength++;
488   mystring[mylength] = '\0';
489 }
490
491 // ----------------------------------------------------------------------------
492 // Insert
493 // ----------------------------------------------------------------------------
494 void TCollection_AsciiString::Insert(const Standard_Integer where,
495                                      const Standard_CString what)
496 {
497   if (where <= mylength + 1 && where > 0) {
498     if(what) {
499       Standard_Integer whatlength = Standard_Integer( strlen( what ) );
500       Standard_Integer newlength = mylength + whatlength;
501       
502       mystring = Reallocate (mystring, newlength + 1);
503       if (where != mylength +1) {
504         for (int i=mylength-1; i >= where-1; i--)
505           mystring[i+whatlength] = mystring[i];
506       }
507       for (int i=0; i < whatlength; i++)
508         mystring[where-1+i] = what[i];
509       
510       mylength = newlength;
511       mystring[mylength] = '\0';
512     }
513   }
514   else {
515     Standard_OutOfRange::Raise("TCollection_AsciiString::Insert : "
516                                "Parameter where is invalid");
517   }
518 }
519
520 // ----------------------------------------------------------------------------
521 // Insert
522 // ----------------------------------------------------------------------------
523 void TCollection_AsciiString::Insert(const Standard_Integer where,
524                                      const TCollection_AsciiString& what)
525 {
526   Standard_CString swhat = what.mystring;
527   if (where <= mylength + 1) {
528     Standard_Integer whatlength = what.mylength;
529     if(whatlength) {
530       Standard_Integer newlength = mylength + whatlength;
531       
532       mystring = Reallocate (mystring, newlength + 1);
533
534       if (where != mylength +1) {
535         for (int i=mylength-1; i >= where-1; i--)
536           mystring[i+whatlength] = mystring[i];
537       }
538       for (int i=0; i < whatlength; i++)
539         mystring[where-1+i] = swhat[i];
540       
541       mylength = newlength;
542       mystring[mylength] = '\0';
543     }
544   }
545   else {
546     Standard_OutOfRange::Raise("TCollection_AsciiString::Insert : "
547                                "Parameter where is too big");
548   }
549 }
550
551 //------------------------------------------------------------------------
552 //  InsertAfter
553 //------------------------------------------------------------------------
554 void TCollection_AsciiString::InsertAfter(const Standard_Integer Index,
555                                           const TCollection_AsciiString& what)
556 {
557    if (Index < 0 || Index > mylength) Standard_OutOfRange::Raise();
558    Insert(Index+1,what);
559 }
560
561 //------------------------------------------------------------------------
562 //  InsertBefore
563 //------------------------------------------------------------------------
564 void TCollection_AsciiString::InsertBefore(const Standard_Integer Index,
565                                            const TCollection_AsciiString& what)
566 {
567    if (Index < 1 || Index > mylength) Standard_OutOfRange::Raise();
568    Insert(Index,what);
569 }
570
571 // ----------------------------------------------------------------------------
572 // IsEqual
573 // ----------------------------------------------------------------------------
574 Standard_Boolean TCollection_AsciiString::IsEqual
575                                         (const Standard_CString other)const
576 {
577   if (other) {
578     return ( strncmp( other, mystring, mylength+1 ) == 0 );
579   }
580   Standard_NullObject::Raise("TCollection_AsciiString::Operator == "
581                              "Parameter 'other'");
582   return Standard_False;
583 }
584
585 // ----------------------------------------------------------------------------
586 // IsEqual
587 // ----------------------------------------------------------------------------
588 Standard_Boolean TCollection_AsciiString::IsEqual
589                                 (const TCollection_AsciiString& other)const
590 {
591   if (mylength != other.mylength) return Standard_False;
592   return ( strncmp( other.mystring, mystring, mylength ) == 0 );
593 }
594
595 // ----------------------------------------------------------------------------
596 // IsSameString
597 // ----------------------------------------------------------------------------
598 Standard_Boolean TCollection_AsciiString::IsSameString (const TCollection_AsciiString& theString1,
599                                                         const TCollection_AsciiString& theString2,
600                                                         const Standard_Boolean theIsCaseSensitive)
601 {
602   const Standard_Integer aSize1 = theString1.Length();
603   if (aSize1 != theString2.Length())
604   {
605     return Standard_False;
606   }
607
608   if (theIsCaseSensitive)
609   {
610     return (strncmp (theString1.ToCString(), theString2.ToCString(), aSize1) == 0);
611   }
612
613   for (Standard_Integer aCharIter = 1; aCharIter <= aSize1; ++aCharIter)
614   {
615     if (toupper (theString1.Value (aCharIter)) != toupper (theString2.Value (aCharIter)))
616     {
617       return Standard_False;
618     }
619   }
620   return Standard_True;
621 }
622
623 // ----------------------------------------------------------------------------
624 // IsDifferent
625 // ----------------------------------------------------------------------------
626 Standard_Boolean TCollection_AsciiString::IsDifferent
627                                         (const Standard_CString other)const
628 {
629   if (other) {
630     return ( strncmp( other, mystring, mylength+1 ) != 0 );
631   }
632   Standard_NullObject::Raise("TCollection_AsciiString::Operator != "
633                             "Parameter 'other'");
634   return Standard_False;
635 }
636
637 // ----------------------------------------------------------------------------
638 // IsDifferent
639 // ----------------------------------------------------------------------------
640 Standard_Boolean TCollection_AsciiString::IsDifferent
641                                 (const TCollection_AsciiString& other)const
642 {
643
644   if (mylength != other.mylength) return Standard_True;
645   return ( strncmp( other.mystring, mystring, mylength ) != 0 );
646 }
647
648 // ----------------------------------------------------------------------------
649 // IsLess
650 // ----------------------------------------------------------------------------
651 Standard_Boolean TCollection_AsciiString::IsLess
652                                         (const Standard_CString other)const
653 {
654   if (other) {
655     return ( strncmp( mystring, other, mylength+1 ) < 0 );
656   }
657   Standard_NullObject::Raise("TCollection_AsciiString::Operator < "
658                              "Parameter 'other'");
659   return Standard_False;
660 }
661
662 // ----------------------------------------------------------------------------
663 // IsLess
664 // ----------------------------------------------------------------------------
665 Standard_Boolean TCollection_AsciiString::IsLess
666                                 (const TCollection_AsciiString& other)const
667 {
668   return ( strncmp( mystring, other.mystring, mylength+1 ) < 0 );
669 }
670
671 // ----------------------------------------------------------------------------
672 // IsGreater
673 // ----------------------------------------------------------------------------
674 Standard_Boolean TCollection_AsciiString::IsGreater
675                                         (const Standard_CString other)const
676 {
677   if (other) {
678     return ( strncmp( mystring, other, mylength+1 ) > 0 );
679   }
680   Standard_NullObject::Raise("TCollection_AsciiString::Operator > "
681                              "Parameter 'other'");
682   return Standard_False;
683 }
684
685 // ----------------------------------------------------------------------------
686 // IsGreater
687 // ----------------------------------------------------------------------------
688 Standard_Boolean TCollection_AsciiString::IsGreater
689                                 (const TCollection_AsciiString& other)const
690 {
691   return ( strncmp( mystring, other.mystring, mylength+1 ) > 0 );
692 }
693
694 // ----------------------------------------------------------------------------
695 // StartsWith
696 // ----------------------------------------------------------------------------
697 Standard_Boolean TCollection_AsciiString::StartsWith (const TCollection_AsciiString& theStartString) const
698 {
699   if (this == &theStartString)
700   {
701     return true;
702   }
703
704   return mylength >= theStartString.mylength
705       && strncmp (theStartString.mystring, mystring, theStartString.mylength) == 0;
706 }
707
708 // ----------------------------------------------------------------------------
709 // EndsWith
710 // ----------------------------------------------------------------------------
711 Standard_Boolean TCollection_AsciiString::EndsWith (const TCollection_AsciiString& theEndString) const
712 {
713   if (this == &theEndString)
714   {
715     return true;
716   }
717
718   return mylength >= theEndString.mylength
719       && strncmp (theEndString.mystring, mystring + mylength - theEndString.mylength, theEndString.mylength) == 0;
720 }
721
722 // ----------------------------------------------------------------------------
723 // IntegerValue
724 // ----------------------------------------------------------------------------
725 Standard_Integer TCollection_AsciiString::IntegerValue()const
726 {
727   char *ptr;
728   Standard_Integer value = (Standard_Integer)strtol(mystring,&ptr,10); 
729   if (ptr != mystring) return value;
730
731   Standard_NumericError::Raise("TCollection_AsciiString::IntegerValue");
732   return 0;
733 }
734
735 // ----------------------------------------------------------------------------
736 // IsIntegerValue
737 // ----------------------------------------------------------------------------
738 Standard_Boolean TCollection_AsciiString::IsIntegerValue()const
739 {
740   char *ptr;
741   strtol(mystring,&ptr,10);
742
743   if (ptr != mystring) {
744     for (int i=int(ptr-mystring); i < mylength; i++) {
745       if (mystring[i] == '.') return Standard_False; // what about 'e','x',etc ???
746     }
747     return Standard_True;
748   }
749   return Standard_False;
750 }
751
752 // ----------------------------------------------------------------------------
753 // IsRealValue
754 // ----------------------------------------------------------------------------
755 Standard_Boolean TCollection_AsciiString::IsRealValue()const
756 {
757   char *ptr;
758   Strtod(mystring,&ptr);
759   return (ptr != mystring);
760 }
761
762 // ----------------------------------------------------------------------------
763 // IsAscii
764 // ----------------------------------------------------------------------------
765 Standard_Boolean TCollection_AsciiString::IsAscii()const
766 {
767 // LD : Debuggee le 26/11/98
768 //      Cette fonction retournait TOUJOURS Standard_True !
769   for (int i=0; i < mylength; i++)
770     if (mystring[i] >= 127 || mystring[i] < ' ') return Standard_False;
771   return Standard_True;
772 }
773
774 //------------------------------------------------------------------------
775 //  LeftAdjust
776 //------------------------------------------------------------------------
777 void TCollection_AsciiString::LeftAdjust ()
778 {
779    Standard_Integer i ;
780    for( i = 0 ; i < mylength ; i ++) if(!IsSpace(mystring[i])) break;
781    if( i > 0 ) Remove(1,i);
782 }
783
784 //------------------------------------------------------------------------
785 //  LeftJustify
786 //------------------------------------------------------------------------
787 void TCollection_AsciiString::LeftJustify(const Standard_Integer Width,
788                                           const Standard_Character Filler)
789 {
790    if (Width > mylength) {
791        mystring = Reallocate (mystring, Width + 1);
792      for (int i = mylength; i < Width ; i++) mystring[i] = Filler;
793      mylength = Width;
794      mystring[mylength] = '\0';
795    }
796    else if (Width < 0) {
797      Standard_NegativeValue::Raise();
798    }
799 }
800
801 //------------------------------------------------------------------------
802 //  Location
803 //------------------------------------------------------------------------
804 Standard_Integer TCollection_AsciiString::Location
805                                    (const Standard_Integer   N        ,
806                                     const Standard_Character C        ,
807                                     const Standard_Integer   FromIndex,
808                                     const Standard_Integer   ToIndex  ) const
809 {
810    if (FromIndex > 0 && ToIndex <= mylength && FromIndex <= ToIndex ) {
811      for(int i = FromIndex-1, count = 0; i <= ToIndex-1; i++) {
812        if(mystring[i] == C) {
813          count++;
814          if ( count == N ) return i+1;
815        }
816      }
817      return 0 ;
818    }
819    Standard_OutOfRange::Raise();
820    return 0 ;
821 }
822
823 //------------------------------------------------------------------------
824 //  Location
825 //------------------------------------------------------------------------
826 Standard_Integer TCollection_AsciiString::Location
827                                 (const TCollection_AsciiString& what,
828                                  const Standard_Integer         FromIndex,
829                                  const Standard_Integer         ToIndex) const
830 {
831   if (mylength == 0 || what.mylength == 0) return 0;
832   if (ToIndex <= mylength && FromIndex > 0 && FromIndex <= ToIndex ) {
833     Standard_Integer i = FromIndex-1;
834     Standard_Integer k = 1;
835     Standard_Integer l = FromIndex-2;
836     Standard_Boolean Find = Standard_False; 
837     while (!Find && i < ToIndex)  {
838       if (mystring[i] == what.Value(k)) {
839         k++;
840         if ( k > what.mylength) Find = Standard_True;
841       }
842       else {
843         if (k > 1) i--;    // si on est en cours de recherche 
844         k = 1;
845         l = i;
846       }
847       i++;
848     }
849     if (Find) return l+2;
850     else      return 0;
851   }
852   Standard_OutOfRange::Raise();
853   return 0;
854 }
855
856 // ----------------------------------------------------------------------------
857 // LowerCase
858 // ----------------------------------------------------------------------------
859 void TCollection_AsciiString::LowerCase()
860 {
861   for (int i=0; i < mylength; i++)
862     mystring[i] = ::LowerCase(mystring[i]);
863 }
864
865 //------------------------------------------------------------------------
866 //  Prepend
867 //------------------------------------------------------------------------
868 void TCollection_AsciiString::Prepend(const TCollection_AsciiString& what)
869 {
870   Insert(1,what);
871 }
872
873 // ----------------------------------------------------------------------------
874 // RealValue
875 // ----------------------------------------------------------------------------
876 Standard_Real TCollection_AsciiString::RealValue()const
877 {
878   char *ptr;
879   Standard_Real value = Strtod(mystring,&ptr);
880   if (ptr != mystring) return value;
881
882   Standard_NumericError::Raise("TCollection_AsciiString::RealValue");
883   return value;
884 }
885
886 // ----------------------------------------------------------------------------
887 // Read
888 //--------------------------------------------------------------------------
889 void TCollection_AsciiString::Read(Standard_IStream& astream)
890 {
891   // get characters from astream
892   const Standard_Integer bufSize = 8190;
893   Standard_Character buffer[bufSize];
894   std::streamsize oldWidth = astream.width (bufSize);
895   astream >> buffer;
896   astream.width( oldWidth );
897
898   // put to string
899   mylength = Standard_Integer( strlen( buffer ));
900   mystring = Reallocate (mystring, mylength + 1);
901   strncpy(mystring,buffer,mylength);
902   mystring[mylength] = '\0';
903 }
904
905
906 //---------------------------------------------------------------------------
907 Standard_IStream& operator >> (Standard_IStream& astream,
908                                TCollection_AsciiString& astring)
909 {
910   astring.Read(astream);
911   return astream;
912 }
913
914
915 // ----------------------------------------------------------------------------
916 // Print
917 // ----------------------------------------------------------------------------
918 void TCollection_AsciiString::Print(Standard_OStream& astream)const
919 {
920   if(mystring) astream << mystring;
921 }
922
923
924 // ----------------------------------------------------------------------------
925 Standard_OStream& operator << (Standard_OStream& astream,
926                                const TCollection_AsciiString& astring)
927 {
928   astring.Print(astream);
929   return astream;
930 }
931
932 // ----------------------------------------------------------------------------
933 // RemoveAll
934 // ----------------------------------------------------------------------------
935 void TCollection_AsciiString::RemoveAll(const Standard_Character what,
936                                         const Standard_Boolean CaseSensitive)
937 {   
938   if (mylength == 0) return;
939   int c = 0;
940   if (CaseSensitive) {
941     for (int i=0; i < mylength; i++)
942       if (mystring[i] != what) mystring[c++] = mystring[i];
943   }
944   else {
945     Standard_Character upperwhat = ::UpperCase(what);
946     for (int i=0; i < mylength; i++) { 
947       if (::UpperCase(mystring[i]) != upperwhat) mystring[c++] = mystring[i];
948     }
949   }
950   mylength = c;
951   mystring[mylength] = '\0';
952 }
953
954 // ----------------------------------------------------------------------------
955 // RemoveAll
956 // ----------------------------------------------------------------------------
957 void TCollection_AsciiString::RemoveAll(const Standard_Character what)
958 {
959   if (mylength == 0) return;
960   int c = 0;
961   for (int i=0; i < mylength; i++)
962     if (mystring[i] != what) mystring[c++] = mystring[i];
963   mylength = c;
964   mystring[mylength] = '\0';
965 }
966
967 // ----------------------------------------------------------------------------
968 // Remove
969 // ----------------------------------------------------------------------------
970 void TCollection_AsciiString::Remove (const Standard_Integer where,
971                                       const Standard_Integer ahowmany)
972 {
973  if (where+ahowmany <= mylength+1) {
974    int i,j;
975    for(i = where+ahowmany-1, j = where-1; i < mylength; i++, j++)
976      mystring[j] = mystring[i];
977    mylength -= ahowmany;
978    mystring[mylength] = '\0';
979  }
980  else {
981   Standard_OutOfRange::Raise("TCollection_AsciiString::Remove: "
982                              "Too many characters to erase or invalid "
983                              "starting value.");
984  }
985 }
986
987 //------------------------------------------------------------------------
988 //  RightAdjust
989 //------------------------------------------------------------------------
990 void TCollection_AsciiString::RightAdjust ()
991 {
992   Standard_Integer i ;
993   for ( i = mylength-1 ; i >= 0 ; i--)
994     if(!IsSpace(mystring[i]))
995       break;
996   if( i < mylength-1 )
997     Remove(i+2,mylength-(i+2)+1);
998 }
999
1000 //------------------------------------------------------------------------
1001 //  RightJustify
1002 //------------------------------------------------------------------------
1003 void TCollection_AsciiString::RightJustify(const Standard_Integer Width,
1004                                            const Standard_Character Filler)
1005 {
1006   Standard_Integer i ;
1007   Standard_Integer k ;
1008   if (Width > mylength) {
1009     mystring = Reallocate (mystring, Width + 1);
1010
1011     for ( i = mylength-1, k = Width-1 ; i >= 0 ; i--, k--) 
1012       mystring[k] = mystring[i];
1013     for(; k >= 0 ; k--) mystring[k] = Filler;
1014     mylength = Width;
1015     mystring[mylength] = '\0';
1016   }
1017   else if (Width < 0) {
1018     Standard_NegativeValue::Raise();
1019   }
1020 }
1021
1022 // ----------------------------------------------------------------------------
1023 // Search
1024 // ----------------------------------------------------------------------------
1025 Standard_Integer TCollection_AsciiString::Search
1026                                         (const Standard_CString what)const
1027 {
1028   Standard_Integer size = Standard_Integer( what ? strlen( what ) : 0 );
1029   if (size) {
1030     int k,j;
1031     int i = 0;
1032     while ( i < mylength-size+1 ) {
1033       k = i++;
1034       j = 0;
1035       while (j < size && mystring[k++] == what[j++])
1036         if (j == size) return i;
1037     }
1038   }
1039   return -1;
1040 }
1041
1042
1043 // ----------------------------------------------------------------------------
1044 // Search
1045 // ----------------------------------------------------------------------------
1046 Standard_Integer TCollection_AsciiString::Search
1047                                 (const TCollection_AsciiString& what) const
1048 {
1049   Standard_Integer size = what.mylength;
1050   Standard_CString swhat = what.mystring;  
1051   if (size) {
1052     int k,j;
1053     int i = 0;
1054     while ( i < mylength-size+1 ) {
1055       k = i++;
1056       j = 0;
1057       while (j < size && mystring[k++] == swhat[j++])
1058         if (j == size) return i;
1059     }
1060   }
1061   return -1;
1062 }
1063
1064
1065 // ----------------------------------------------------------------------------
1066 // SearchFromEnd
1067 // ----------------------------------------------------------------------------
1068 Standard_Integer TCollection_AsciiString::SearchFromEnd
1069                                         (const Standard_CString what)const
1070 {
1071   Standard_Integer size = Standard_Integer( what ? strlen( what ) : 0 );
1072   if (size) {
1073     int k,j;
1074     int i = mylength-1;
1075     while ( i >= size-1 ) {
1076       k = i--;
1077       j = size-1;
1078       while (j >= 0 && mystring[k--] == what[j--])
1079         if (j == -1) return i-size+3;
1080     }
1081   }
1082   return -1;
1083 }
1084
1085
1086 // ----------------------------------------------------------------------------
1087 // SearchFromEnd
1088 // ----------------------------------------------------------------------------
1089 Standard_Integer TCollection_AsciiString::SearchFromEnd
1090                                 (const TCollection_AsciiString& what)const
1091 {
1092   int size = what.mylength;
1093   if (size) {
1094     Standard_CString swhat = what.mystring;  
1095     int k,j;
1096     int i = mylength-1;
1097     while ( i >= size-1 ) {
1098       k = i--;
1099       j = size-1;
1100       while (j >= 0 && mystring[k--] == swhat[j--])
1101         if (j == -1) return i-size+3;
1102     }
1103   }
1104   return -1;
1105 }
1106
1107 // ----------------------------------------------------------------------------
1108 // SetValue
1109 // ----------------------------------------------------------------------------
1110 void TCollection_AsciiString::SetValue(const Standard_Integer where,
1111                                        const Standard_Character what)
1112 {
1113   if (where > 0 && where <= mylength) {
1114     mystring[where-1] = what;
1115   }
1116   else {
1117     Standard_OutOfRange::Raise("TCollection_AsciiString::SetValue : "
1118                                "parameter where");
1119   }
1120 }
1121
1122 // ----------------------------------------------------------------------------
1123 // SetValue
1124 // ----------------------------------------------------------------------------
1125 void TCollection_AsciiString::SetValue(const Standard_Integer where,
1126                                        const Standard_CString what)
1127 {
1128  if (where > 0 && where <= mylength+1) {
1129    Standard_Integer size = Standard_Integer( what ? strlen( what ) : 0 );
1130    size += (where - 1);  
1131    if (size >= mylength) {
1132      mystring = Reallocate (mystring, size + 1);
1133      mylength = size;
1134    } 
1135    for (int i = where-1; i < size; i++)
1136      mystring[i] = what[i-(where-1)];
1137    mystring[mylength] = '\0';
1138  }
1139  else {
1140    Standard_OutOfRange::Raise("TCollection_AsciiString::SetValue : "
1141                               "parameter where");
1142  }
1143 }
1144
1145 // ----------------------------------------------------------------------------
1146 // SetValue
1147 // ----------------------------------------------------------------------------
1148 void TCollection_AsciiString::SetValue(const Standard_Integer where,
1149                                        const TCollection_AsciiString& what)
1150 {
1151  if (where > 0 && where <= mylength+1) {
1152    Standard_Integer size = what.mylength;
1153    Standard_CString swhat = what.mystring;  
1154    size += (where - 1);  
1155    if (size >= mylength) {
1156      mystring = Reallocate (mystring, size + 1);
1157      mylength = size;
1158    } 
1159    for (int i = where-1; i < size; i++)
1160      mystring[i] = swhat[i-(where-1)];
1161    mystring[mylength] = '\0';
1162  }
1163  else {
1164    Standard_OutOfRange::Raise("TCollection_AsciiString::SetValue : "
1165                               "parameter where");
1166  }
1167 }
1168
1169 // ----------------------------------------------------------------------------
1170 // Split
1171 // Private
1172 // ----------------------------------------------------------------------------
1173 void TCollection_AsciiString::Split(const Standard_Integer where,
1174                                     TCollection_AsciiString& res)
1175 {
1176   if (where >= 0 && where <= mylength) {
1177     res = &mystring[where] ;
1178     Trunc(where);
1179     return ;
1180   }
1181   Standard_OutOfRange::Raise("TCollection_AsciiString::Split index");
1182   return ;
1183 }
1184
1185 // ----------------------------------------------------------------------------
1186 // Split
1187 // ----------------------------------------------------------------------------
1188 TCollection_AsciiString TCollection_AsciiString::Split
1189                                                 (const Standard_Integer where)
1190 {
1191   if (where >= 0 && where <= mylength) {
1192     TCollection_AsciiString res( &mystring[where] , mylength - where );
1193     Trunc(where);
1194     return res;
1195   }
1196   Standard_OutOfRange::Raise("TCollection_AsciiString::Split index");
1197   TCollection_AsciiString res;
1198   return res;
1199 }
1200
1201 // ----------------------------------------------------------------------------
1202 // SubString
1203 // Private
1204 // ----------------------------------------------------------------------------
1205 void TCollection_AsciiString::SubString(const Standard_Integer FromIndex,
1206                                         const Standard_Integer ToIndex,
1207                                         TCollection_AsciiString& res) const
1208 {
1209
1210   if (ToIndex > mylength || FromIndex <= 0 || FromIndex > ToIndex )
1211     Standard_OutOfRange::Raise();
1212   Standard_Integer newlength = ToIndex-FromIndex+1;
1213   res.mystring =Reallocate (res.mystring, newlength + 1);
1214   strncpy( res.mystring, mystring + FromIndex - 1, newlength );
1215   res.mystring[newlength] = '\0';
1216   res.mylength = newlength;
1217   return ;
1218 }
1219
1220 // ----------------------------------------------------------------------------
1221 // Token
1222 // Private
1223 // ----------------------------------------------------------------------------
1224 void TCollection_AsciiString::Token(const Standard_CString separators,
1225                                     const Standard_Integer whichone,
1226                                     TCollection_AsciiString& res)const
1227 {
1228   res = Token( separators , whichone ) ;
1229 }
1230
1231 // ----------------------------------------------------------------------------
1232 // Token
1233 // ----------------------------------------------------------------------------
1234 TCollection_AsciiString TCollection_AsciiString::Token
1235                                         (const Standard_CString separators,
1236                                          const Standard_Integer whichone) const
1237 {
1238   if (!separators)
1239     Standard_NullObject::Raise("TCollection_AsciiString::Token : "
1240                                "parameter 'separators'");
1241
1242   Standard_Integer theOne ;
1243   Standard_Integer StringIndex = 0 ;
1244   Standard_Integer SeparatorIndex ;
1245   Standard_Integer BeginIndex=0 ;
1246   Standard_Integer EndIndex=0 ;
1247
1248 //  cout << "'" << mystring <<  "'" << endl ;
1249   for ( theOne = 0 ; theOne < whichone ; theOne++ ) {
1250      BeginIndex = 0 ;
1251      EndIndex = 0 ;
1252 //     cout << "theOne " << theOne << endl ;
1253      if ( StringIndex == mylength )
1254        break ;
1255      for (; StringIndex < mylength && EndIndex == 0 ; StringIndex++ ) {
1256         SeparatorIndex = 0 ;
1257 //        cout << "StringIndex " << StringIndex << endl ;
1258         while ( separators [ SeparatorIndex ] ) {
1259              if ( mystring [ StringIndex ] == separators [ SeparatorIndex ] ) {
1260                break ;
1261              }
1262              SeparatorIndex += 1 ;
1263            }
1264         if ( separators [ SeparatorIndex ] != '\0' ) { // We have a Separator
1265           if ( BeginIndex && EndIndex == 0 ) {
1266             EndIndex = StringIndex ;
1267 //            cout << "EndIndex " << EndIndex << " '" << SubString( BeginIndex , EndIndex ).ToCString() << "'" << endl ;
1268             break ;
1269           }
1270         }
1271         else if ( BeginIndex == 0 ) {               // We have not a Separator
1272           BeginIndex = StringIndex + 1 ;
1273 //          cout << "BeginIndex " << BeginIndex << endl ;
1274         }
1275      }
1276 //     cout << "BeginIndex " << BeginIndex << " EndIndex " << EndIndex << endl ;
1277   }
1278   if ( BeginIndex == 0 )
1279     return TCollection_AsciiString("",0) ;
1280   if ( EndIndex == 0 )
1281     EndIndex = mylength ;
1282 //    cout << "'" << SubString( BeginIndex , EndIndex ).ToCString() << "'" << endl ;
1283   return TCollection_AsciiString( &mystring [ BeginIndex - 1 ] ,
1284                                   EndIndex - BeginIndex + 1 ) ;
1285 }
1286
1287 // ----------------------------------------------------------------------------
1288 // Trunc
1289 // ----------------------------------------------------------------------------
1290 void TCollection_AsciiString::Trunc(const Standard_Integer ahowmany)
1291 {
1292   if (ahowmany < 0 || ahowmany > mylength)
1293     Standard_OutOfRange::Raise("TCollection_AsciiString::Trunc : "
1294                                "parameter 'ahowmany'");
1295   mylength = ahowmany;
1296   mystring[mylength] = '\0';
1297 }
1298
1299 // ----------------------------------------------------------------------------
1300 // UpperCase
1301 // ----------------------------------------------------------------------------
1302 void TCollection_AsciiString::UpperCase()
1303 {
1304   for (int i=0; i < mylength; i++)
1305     mystring[i] = ::UpperCase(mystring[i]);
1306 }
1307
1308 //------------------------------------------------------------------------
1309 //  UsefullLength
1310 //------------------------------------------------------------------------
1311 Standard_Integer TCollection_AsciiString::UsefullLength () const
1312 {
1313   Standard_Integer i ;
1314   for ( i = mylength -1 ; i >= 0 ; i--) 
1315     if (IsGraphic(mystring[i])) break;
1316   return i+1;
1317 }
1318
1319 // ----------------------------------------------------------------------------
1320 // Value
1321 // ----------------------------------------------------------------------------
1322 Standard_Character TCollection_AsciiString::Value
1323                                         (const Standard_Integer where)const
1324 {
1325  if (where > 0 && where <= mylength) {
1326    return mystring[where-1];
1327  }
1328  Standard_OutOfRange::Raise("TCollection_AsciiString::Value : parameter where");
1329  return '\0';
1330 }