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