03dbed0b5270bdc3157bbcd9c543610b318e92f9
[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 astring)
63   : mystring(0), mylength(0)
64 {
65   if (astring) {
66     mylength = Standard_Integer( strlen(astring) );
67     mystring = Allocate(mylength+1);
68     strncpy(mystring,astring,mylength);
69     mystring[mylength] = '\0';
70   }
71   else {
72     throw Standard_NullObject("TCollection_AsciiString : parameter 'astring'");
73   }
74 }
75
76 // ----------------------------------------------------------------------------
77 // Create an asciistring from a Standard_CString
78 // ----------------------------------------------------------------------------
79 TCollection_AsciiString::TCollection_AsciiString(const Standard_CString astring,
80                                                  const Standard_Integer aLen )
81   : mystring(0), mylength(aLen)
82 {
83   if (astring) {
84     mystring = Allocate(mylength+1);
85     strncpy( mystring , astring , mylength );
86     mystring [ mylength ] = '\0' ;
87   }
88   else {
89     throw Standard_NullObject("TCollection_AsciiString : parameter 'astring'");
90   }
91 }
92
93 // ----------------------------------------------------------------------------
94 // Create an asciistring from a Standard_Character
95 // ----------------------------------------------------------------------------
96 TCollection_AsciiString::TCollection_AsciiString(const Standard_Character aChar)
97      : mystring(0)
98 {
99   if ( aChar != '\0' ) {
100     mylength    = 1;
101     mystring    = Allocate(2);
102     mystring[0] = aChar;
103     mystring[1] = '\0';
104   }
105   else {
106     mylength = 0;
107     mystring = Allocate(mylength+1);
108     mystring[mylength] = '\0';
109   }
110 }
111
112 // ----------------------------------------------------------------------------
113 // Create an AsciiString from a filler
114 // ----------------------------------------------------------------------------
115 TCollection_AsciiString::TCollection_AsciiString(const Standard_Integer length,
116                                                  const Standard_Character filler )
117 {
118   mystring = Allocate(length+1);
119   mylength = length;
120   for (int i = 0 ; i < length ; i++) mystring[i] = filler;
121   mystring[length] = '\0';
122 }
123
124 // ----------------------------------------------------------------------------
125 // Create an AsciiString from an Integer
126 // ----------------------------------------------------------------------------
127 TCollection_AsciiString::TCollection_AsciiString(const Standard_Integer aValue)
128      : mystring(0)
129 {
130   char t [13];
131   mylength = Sprintf( t,"%d",aValue);
132   mystring = Allocate(mylength+1);
133   strncpy( mystring , t , mylength );
134   mystring[mylength] = '\0';
135 }
136
137 // ----------------------------------------------------------------------------
138 // Create an asciistring from a real
139 // ----------------------------------------------------------------------------
140 TCollection_AsciiString::TCollection_AsciiString(const Standard_Real aValue)
141      : mystring(0)
142 {
143   char t [50];
144   mylength = Sprintf( t,"%g",aValue);
145   mystring = Allocate(mylength+1);
146   strncpy( mystring , t , mylength );
147   mystring[mylength] = '\0';
148 }
149
150 // ----------------------------------------------------------------------------
151 // Create an asciistring from an asciistring
152 // ----------------------------------------------------------------------------
153 TCollection_AsciiString::TCollection_AsciiString(const TCollection_AsciiString& astring)
154      : mystring(0)
155 {
156   mylength = astring.mylength;
157   mystring = Allocate(mylength+1);
158   if ( mylength )
159     strncpy(mystring,astring.mystring,mylength);
160   mystring[mylength] = '\0';
161 }
162
163 // ----------------------------------------------------------------------------
164 // Create an asciistring from a character
165 // ----------------------------------------------------------------------------
166 TCollection_AsciiString::TCollection_AsciiString(
167                          const TCollection_AsciiString& astring ,
168                          const Standard_Character other )
169      : mystring(0)
170 {
171   mylength = astring.mylength + 1 ;
172   mystring = Allocate(mylength+1);
173   if ( astring.mylength ) {
174     strncpy( mystring , astring.mystring , astring.mylength ) ;
175   }
176   mystring[mylength-1] = other ;
177   mystring[mylength] = '\0' ;
178 }
179
180 // ----------------------------------------------------------------------------
181 // Create an asciistring from an asciistring
182 // ----------------------------------------------------------------------------
183 TCollection_AsciiString::TCollection_AsciiString(
184                          const TCollection_AsciiString& astring ,
185                          const Standard_CString other )
186      : mystring(0)
187 {
188   Standard_Integer otherlength = Standard_Integer( other ? strlen( other ) : 0 );
189   mylength = astring.mylength + otherlength ;
190   mystring = Allocate(mylength+1);
191   if ( astring.mylength ) {
192     strncpy( mystring , astring.mystring , astring.mylength ) ;
193   }
194   if ( otherlength ) {
195     strncpy( mystring + astring.mylength, other, otherlength );
196   }
197   mystring[ mylength ] = '\0';
198 }
199
200 // ----------------------------------------------------------------------------
201 // Create an asciistring from an asciistring
202 // ----------------------------------------------------------------------------
203 TCollection_AsciiString::TCollection_AsciiString(
204                          const TCollection_AsciiString& astring ,
205                          const TCollection_AsciiString& other )
206      : mystring(0)
207 {
208   mylength = astring.mylength + other.mylength ;
209   mystring = Allocate(mylength+1);
210   if ( astring.mylength ) {
211     strncpy( mystring , astring.mystring , astring.mylength ) ;
212   }
213   if ( other.mylength ) {
214     strncpy( mystring + astring.mylength, other.mystring , other.mylength ) ;
215   }
216   mystring[mylength] = '\0' ;
217 }
218
219 //---------------------------------------------------------------------------
220 //  Create an asciistring from an ExtendedString 
221 //---------------------------------------------------------------------------
222 TCollection_AsciiString::TCollection_AsciiString(const TCollection_ExtendedString& astring,
223                                                  const Standard_Character replaceNonAscii) 
224 : mystring (0)
225 {
226   if (replaceNonAscii)
227   {
228     mylength = astring.Length(); 
229     mystring = Allocate(mylength+1);
230     for(int i = 0; i < mylength; i++) {
231       Standard_ExtCharacter c = astring.Value(i+1);
232       mystring[i] = ( IsAnAscii(c) ? ToCharacter(c) : replaceNonAscii );
233     }
234     mystring[mylength] = '\0';
235   }
236   else {
237     // create UTF-8 string
238     mylength = astring.LengthOfCString();
239     mystring = Allocate(mylength+1);
240     astring.ToUTF8CString(mystring);
241   }
242 }
243
244 //---------------------------------------------------------------------------
245 //  Create an TCollection_AsciiString from a Standard_WideChar
246 //---------------------------------------------------------------------------
247 TCollection_AsciiString::TCollection_AsciiString (const Standard_WideChar* theStringUtf)
248 : mystring (NULL),
249   mylength (0)
250 {
251   for (NCollection_UtfWideIter anIter (theStringUtf); *anIter != 0; ++anIter)
252   {
253     mylength += anIter.AdvanceBytesUtf8();
254   }
255
256   mystring = Allocate (mylength + 1);
257   mystring[mylength] = '\0';
258   NCollection_UtfWideIter anIterRead (theStringUtf);
259   for (Standard_Utf8Char* anIterWrite = mystring; *anIterRead != 0; ++anIterRead)
260   {
261     anIterWrite = anIterRead.GetUtf(anIterWrite);
262   }
263 }
264
265 // ----------------------------------------------------------------------------
266 // AssignCat
267 // ----------------------------------------------------------------------------
268 void TCollection_AsciiString::AssignCat(const Standard_Integer other)
269 {
270
271   AssignCat(TCollection_AsciiString(other));
272
273 }
274
275 // ----------------------------------------------------------------------------
276 // AssignCat
277 // ----------------------------------------------------------------------------
278 void TCollection_AsciiString::AssignCat(const Standard_Real other)
279 {
280
281   AssignCat(TCollection_AsciiString(other));
282
283 }
284
285 // ----------------------------------------------------------------------------
286 // AssignCat
287 // ----------------------------------------------------------------------------
288 void TCollection_AsciiString::AssignCat(const Standard_Character other)
289 {
290   if (other != '\0') {
291     mystring = Reallocate (mystring, mylength + 2);
292     mystring[mylength] = other ;
293     mylength += 1;
294     mystring[mylength] = '\0';
295   }
296 }
297
298 // ----------------------------------------------------------------------------
299 // AssignCat
300 // ----------------------------------------------------------------------------
301 void TCollection_AsciiString::AssignCat(const Standard_CString other)
302 {
303   if (other) {
304     Standard_Integer otherlength = Standard_Integer( strlen( other ));
305     if ( otherlength ) {
306       Standard_Integer newlength = mylength+otherlength;
307       mystring = Reallocate (mystring, newlength + 1);
308       strncpy( mystring + mylength, other, otherlength+1 );
309       mylength = newlength;
310     }
311   }
312   else {
313     throw Standard_NullObject("TCollection_AsciiString::Operator += parameter other");
314   }
315 }
316
317 // ----------------------------------------------------------------------------
318 // AssignCat
319 // ----------------------------------------------------------------------------
320 void TCollection_AsciiString::AssignCat(const TCollection_AsciiString& other)
321 {
322
323   if (other.mylength) {
324     Standard_Integer newlength = mylength+other.mylength;
325     mystring = Reallocate (mystring, newlength + 1);
326     strncpy( mystring + mylength, other.mystring, other.mylength+1 );
327     mylength = newlength;
328   }
329 }
330
331 // ---------------------------------------------------------------------------
332 // Capitalize
333 // ----------------------------------------------------------------------------
334 void TCollection_AsciiString::Capitalize()
335 {
336   if ( mylength ) mystring[0] = ::UpperCase(mystring[0]);
337   for (int i = 1; i < mylength; i++ )
338     mystring[i] = ::LowerCase(mystring[i]);
339 }
340
341 // ---------------------------------------------------------------------------
342 // Center
343 // ----------------------------------------------------------------------------
344 void TCollection_AsciiString::Center(const Standard_Integer Width ,
345                                      const Standard_Character Filler) 
346 {
347   if(Width > mylength) {
348     Standard_Integer newlength = mylength + ((Width - mylength)/2);
349     LeftJustify(newlength,Filler);
350     RightJustify(Width,Filler);
351   }
352   else if (Width < 0) {
353     throw Standard_NegativeValue();
354   }
355 }
356
357 // ----------------------------------------------------------------------------
358 // ChangeAll
359 // ----------------------------------------------------------------------------
360 void TCollection_AsciiString::ChangeAll(const Standard_Character aChar,
361                                         const Standard_Character NewChar,
362                                         const Standard_Boolean CaseSensitive)
363 {
364   if (CaseSensitive){
365     for (int i=0; i < mylength; i++)
366       if (mystring[i] == aChar) mystring[i] = NewChar;
367   }
368   else{
369     Standard_Character anUpperChar = ::UpperCase(aChar);
370     for (int i=0; i < mylength; i++)
371       if (::UpperCase(mystring[i]) == anUpperChar) mystring[i] = NewChar;
372   }
373 }
374
375 // ----------------------------------------------------------------------------
376 // Clear
377 // ----------------------------------------------------------------------------
378 void TCollection_AsciiString::Clear()
379 {
380   if ( mylength > 0 )
381   {
382     Free (mystring);
383     mylength = 0;
384     mystring = Allocate(mylength+1);
385     mystring[mylength] = '\0';
386   }
387 }
388
389 // ----------------------------------------------------------------------------
390 // Copy
391 // ----------------------------------------------------------------------------
392 void TCollection_AsciiString::Copy(const Standard_CString fromwhere)
393 {
394   if (fromwhere) {
395     mylength = Standard_Integer( strlen( fromwhere ));
396     mystring = Reallocate (mystring, mylength + 1);
397     strncpy( mystring, fromwhere, mylength+1 );
398   }
399   else {
400     mylength = 0;
401     mystring[mylength] = '\0';
402   }
403 }
404
405 // ----------------------------------------------------------------------------
406 // Copy
407 // ----------------------------------------------------------------------------
408 void TCollection_AsciiString::Copy(const TCollection_AsciiString& fromwhere)
409 {
410   if (fromwhere.mystring) {
411     mylength = fromwhere.mylength;
412     mystring = Reallocate (mystring, mylength + 1);
413     strncpy( mystring, fromwhere.mystring, mylength+1 );
414   }
415   else {
416     mylength = 0;
417     mystring[mylength] = '\0';
418   }
419 }
420
421 // ----------------------------------------------------------------------------
422 // Swap
423 // ----------------------------------------------------------------------------
424 void TCollection_AsciiString::Swap (TCollection_AsciiString& theOther)
425 {
426   std::swap (mystring, theOther.mystring);
427   std::swap (mylength, theOther.mylength);
428 }
429
430 // ----------------------------------------------------------------------------
431 // Destroy
432 // ----------------------------------------------------------------------------
433 TCollection_AsciiString::~TCollection_AsciiString()
434 {
435   if (mystring) 
436     Free (mystring);
437   mystring = 0L;
438 }
439
440 // ----------------------------------------------------------------------------
441 // FirstLocationInSet
442 // ----------------------------------------------------------------------------
443 Standard_Integer TCollection_AsciiString::FirstLocationInSet
444                                 (const TCollection_AsciiString& Set,
445                                  const Standard_Integer         FromIndex,
446                                  const Standard_Integer         ToIndex) const
447 {
448   if (mylength == 0 || Set.mylength == 0) return 0;
449   if (FromIndex > 0 && ToIndex <= mylength && FromIndex <= ToIndex ) {
450     for(int i = FromIndex-1 ; i < ToIndex; i++)
451       for(int j = 0; j < Set.mylength; j++) 
452         if (mystring[i] == Set.mystring[j]) return i+1;
453     return 0;
454   }
455   throw Standard_OutOfRange();
456 }
457
458 // ----------------------------------------------------------------------------
459 // FirstLocationNotInSet
460 // ----------------------------------------------------------------------------
461 Standard_Integer TCollection_AsciiString::FirstLocationNotInSet
462                                  (const TCollection_AsciiString& Set,
463                                   const Standard_Integer         FromIndex,
464                                   const Standard_Integer         ToIndex) const
465 {
466   if (mylength == 0 || Set.mylength == 0) return 0;
467   if (FromIndex > 0 && ToIndex <= mylength && FromIndex <= ToIndex ) {
468     Standard_Boolean find;
469     for (int i = FromIndex-1 ; i < ToIndex; i++) {
470       find = Standard_False;
471       for(int j = 0; j < Set.mylength; j++)  
472         if (mystring[i] == Set.mystring[j]) find = Standard_True;
473       if (!find)  return i+1;
474     }
475     return 0;
476   }
477   throw Standard_OutOfRange();
478 }
479
480 //----------------------------------------------------------------------------
481 // Insert a character before 'where'th character
482 // ----------------------------------------------------------------------------
483 void TCollection_AsciiString::Insert(const Standard_Integer where,
484                                      const Standard_Character what)
485 {
486   if (where > mylength + 1 ) throw Standard_OutOfRange("TCollection_AsciiString::Insert : Parameter where is too big");
487   if (where < 1)             throw Standard_OutOfRange("TCollection_AsciiString::Insert : Parameter where is too small");
488   
489   mystring = Reallocate (mystring, mylength + 2);
490   if (where != mylength +1) {
491     for (int i=mylength-1; i >= where-1; i--)
492       mystring[i+1] = mystring[i];
493   }
494   mystring[where-1] = what;
495   mylength++;
496   mystring[mylength] = '\0';
497 }
498
499 // ----------------------------------------------------------------------------
500 // Insert
501 // ----------------------------------------------------------------------------
502 void TCollection_AsciiString::Insert(const Standard_Integer where,
503                                      const Standard_CString what)
504 {
505   if (where <= mylength + 1 && where > 0) {
506     if(what) {
507       Standard_Integer whatlength = Standard_Integer( strlen( what ) );
508       Standard_Integer newlength = mylength + whatlength;
509       
510       mystring = Reallocate (mystring, newlength + 1);
511       if (where != mylength +1) {
512         for (int i=mylength-1; i >= where-1; i--)
513           mystring[i+whatlength] = mystring[i];
514       }
515       for (int i=0; i < whatlength; i++)
516         mystring[where-1+i] = what[i];
517       
518       mylength = newlength;
519       mystring[mylength] = '\0';
520     }
521   }
522   else {
523     throw Standard_OutOfRange("TCollection_AsciiString::Insert : "
524                               "Parameter where is invalid");
525   }
526 }
527
528 // ----------------------------------------------------------------------------
529 // Insert
530 // ----------------------------------------------------------------------------
531 void TCollection_AsciiString::Insert(const Standard_Integer where,
532                                      const TCollection_AsciiString& what)
533 {
534   Standard_CString swhat = what.mystring;
535   if (where <= mylength + 1) {
536     Standard_Integer whatlength = what.mylength;
537     if(whatlength) {
538       Standard_Integer newlength = mylength + whatlength;
539       
540       mystring = Reallocate (mystring, newlength + 1);
541
542       if (where != mylength +1) {
543         for (int i=mylength-1; i >= where-1; i--)
544           mystring[i+whatlength] = mystring[i];
545       }
546       for (int i=0; i < whatlength; i++)
547         mystring[where-1+i] = swhat[i];
548       
549       mylength = newlength;
550       mystring[mylength] = '\0';
551     }
552   }
553   else {
554     throw Standard_OutOfRange("TCollection_AsciiString::Insert : "
555                               "Parameter where is too big");
556   }
557 }
558
559 //------------------------------------------------------------------------
560 //  InsertAfter
561 //------------------------------------------------------------------------
562 void TCollection_AsciiString::InsertAfter(const Standard_Integer Index,
563                                           const TCollection_AsciiString& what)
564 {
565    if (Index < 0 || Index > mylength) throw Standard_OutOfRange();
566    Insert(Index+1,what);
567 }
568
569 //------------------------------------------------------------------------
570 //  InsertBefore
571 //------------------------------------------------------------------------
572 void TCollection_AsciiString::InsertBefore(const Standard_Integer Index,
573                                            const TCollection_AsciiString& what)
574 {
575    if (Index < 1 || Index > mylength) throw Standard_OutOfRange();
576    Insert(Index,what);
577 }
578
579 // ----------------------------------------------------------------------------
580 // IsEqual
581 // ----------------------------------------------------------------------------
582 Standard_Boolean TCollection_AsciiString::IsEqual
583                                         (const Standard_CString other)const
584 {
585   if (other) {
586     return ( strncmp( other, mystring, mylength+1 ) == 0 );
587   }
588   throw Standard_NullObject("TCollection_AsciiString::Operator == "
589                              "Parameter 'other'");
590 }
591
592 // ----------------------------------------------------------------------------
593 // IsEqual
594 // ----------------------------------------------------------------------------
595 Standard_Boolean TCollection_AsciiString::IsEqual
596                                 (const TCollection_AsciiString& other)const
597 {
598   if (mylength != other.mylength) return Standard_False;
599   return ( strncmp( other.mystring, mystring, mylength ) == 0 );
600 }
601
602 // ----------------------------------------------------------------------------
603 // IsSameString
604 // ----------------------------------------------------------------------------
605 Standard_Boolean TCollection_AsciiString::IsSameString (const TCollection_AsciiString& theString1,
606                                                         const TCollection_AsciiString& theString2,
607                                                         const Standard_Boolean theIsCaseSensitive)
608 {
609   const Standard_Integer aSize1 = theString1.Length();
610   if (aSize1 != theString2.Length())
611   {
612     return Standard_False;
613   }
614
615   if (theIsCaseSensitive)
616   {
617     return (strncmp (theString1.ToCString(), theString2.ToCString(), aSize1) == 0);
618   }
619
620   for (Standard_Integer aCharIter = 1; aCharIter <= aSize1; ++aCharIter)
621   {
622     if (toupper (theString1.Value (aCharIter)) != toupper (theString2.Value (aCharIter)))
623     {
624       return Standard_False;
625     }
626   }
627   return Standard_True;
628 }
629
630 // ----------------------------------------------------------------------------
631 // IsDifferent
632 // ----------------------------------------------------------------------------
633 Standard_Boolean TCollection_AsciiString::IsDifferent
634                                         (const Standard_CString other)const
635 {
636   if (other) {
637     return ( strncmp( other, mystring, mylength+1 ) != 0 );
638   }
639   throw Standard_NullObject("TCollection_AsciiString::Operator != "
640                             "Parameter 'other'");
641 }
642
643 // ----------------------------------------------------------------------------
644 // IsDifferent
645 // ----------------------------------------------------------------------------
646 Standard_Boolean TCollection_AsciiString::IsDifferent
647                                 (const TCollection_AsciiString& other)const
648 {
649
650   if (mylength != other.mylength) return Standard_True;
651   return ( strncmp( other.mystring, mystring, mylength ) != 0 );
652 }
653
654 // ----------------------------------------------------------------------------
655 // IsLess
656 // ----------------------------------------------------------------------------
657 Standard_Boolean TCollection_AsciiString::IsLess
658                                         (const Standard_CString other)const
659 {
660   if (other) {
661     return ( strncmp( mystring, other, mylength+1 ) < 0 );
662   }
663   throw Standard_NullObject("TCollection_AsciiString::Operator < "
664                             "Parameter 'other'");
665 }
666
667 // ----------------------------------------------------------------------------
668 // IsLess
669 // ----------------------------------------------------------------------------
670 Standard_Boolean TCollection_AsciiString::IsLess
671                                 (const TCollection_AsciiString& other)const
672 {
673   return ( strncmp( mystring, other.mystring, mylength+1 ) < 0 );
674 }
675
676 // ----------------------------------------------------------------------------
677 // IsGreater
678 // ----------------------------------------------------------------------------
679 Standard_Boolean TCollection_AsciiString::IsGreater
680                                         (const Standard_CString other)const
681 {
682   if (other) {
683     return ( strncmp( mystring, other, mylength+1 ) > 0 );
684   }
685   throw Standard_NullObject("TCollection_AsciiString::Operator > "
686                             "Parameter 'other'");
687 }
688
689 // ----------------------------------------------------------------------------
690 // IsGreater
691 // ----------------------------------------------------------------------------
692 Standard_Boolean TCollection_AsciiString::IsGreater
693                                 (const TCollection_AsciiString& other)const
694 {
695   return ( strncmp( mystring, other.mystring, mylength+1 ) > 0 );
696 }
697
698 // ----------------------------------------------------------------------------
699 // StartsWith
700 // ----------------------------------------------------------------------------
701 Standard_Boolean TCollection_AsciiString::StartsWith (const TCollection_AsciiString& theStartString) const
702 {
703   if (this == &theStartString)
704   {
705     return true;
706   }
707
708   return mylength >= theStartString.mylength
709       && strncmp (theStartString.mystring, mystring, theStartString.mylength) == 0;
710 }
711
712 // ----------------------------------------------------------------------------
713 // EndsWith
714 // ----------------------------------------------------------------------------
715 Standard_Boolean TCollection_AsciiString::EndsWith (const TCollection_AsciiString& theEndString) const
716 {
717   if (this == &theEndString)
718   {
719     return true;
720   }
721
722   return mylength >= theEndString.mylength
723       && strncmp (theEndString.mystring, mystring + mylength - theEndString.mylength, theEndString.mylength) == 0;
724 }
725
726 // ----------------------------------------------------------------------------
727 // IntegerValue
728 // ----------------------------------------------------------------------------
729 Standard_Integer TCollection_AsciiString::IntegerValue()const
730 {
731   char *ptr;
732   Standard_Integer value = (Standard_Integer)strtol(mystring,&ptr,10); 
733   if (ptr != mystring) return value;
734
735   throw Standard_NumericError("TCollection_AsciiString::IntegerValue");
736 }
737
738 // ----------------------------------------------------------------------------
739 // IsIntegerValue
740 // ----------------------------------------------------------------------------
741 Standard_Boolean TCollection_AsciiString::IsIntegerValue()const
742 {
743   char *ptr;
744   strtol(mystring,&ptr,10);
745
746   if (ptr != mystring) {
747     for (int i=int(ptr-mystring); i < mylength; i++) {
748       if (mystring[i] == '.') return Standard_False; // what about 'e','x',etc ???
749     }
750     return Standard_True;
751   }
752   return Standard_False;
753 }
754
755 // ----------------------------------------------------------------------------
756 // IsRealValue
757 // ----------------------------------------------------------------------------
758 Standard_Boolean TCollection_AsciiString::IsRealValue()const
759 {
760   char *ptr;
761   Strtod(mystring,&ptr);
762   return (ptr != mystring);
763 }
764
765 // ----------------------------------------------------------------------------
766 // IsAscii
767 // ----------------------------------------------------------------------------
768 Standard_Boolean TCollection_AsciiString::IsAscii()const
769 {
770 // LD : Debuggee le 26/11/98
771 //      Cette fonction retournait TOUJOURS Standard_True !
772   for (int i=0; i < mylength; i++)
773     if (mystring[i] >= 127 || mystring[i] < ' ') return Standard_False;
774   return Standard_True;
775 }
776
777 //------------------------------------------------------------------------
778 //  LeftAdjust
779 //------------------------------------------------------------------------
780 void TCollection_AsciiString::LeftAdjust ()
781 {
782    Standard_Integer i ;
783    for( i = 0 ; i < mylength ; i ++) if(!IsSpace(mystring[i])) break;
784    if( i > 0 ) Remove(1,i);
785 }
786
787 //------------------------------------------------------------------------
788 //  LeftJustify
789 //------------------------------------------------------------------------
790 void TCollection_AsciiString::LeftJustify(const Standard_Integer Width,
791                                           const Standard_Character Filler)
792 {
793    if (Width > mylength) {
794        mystring = Reallocate (mystring, Width + 1);
795      for (int i = mylength; i < Width ; i++) mystring[i] = Filler;
796      mylength = Width;
797      mystring[mylength] = '\0';
798    }
799    else if (Width < 0) {
800      throw Standard_NegativeValue();
801    }
802 }
803
804 //------------------------------------------------------------------------
805 //  Location
806 //------------------------------------------------------------------------
807 Standard_Integer TCollection_AsciiString::Location
808                                    (const Standard_Integer   N        ,
809                                     const Standard_Character C        ,
810                                     const Standard_Integer   FromIndex,
811                                     const Standard_Integer   ToIndex  ) const
812 {
813    if (FromIndex > 0 && ToIndex <= mylength && FromIndex <= ToIndex ) {
814      for(int i = FromIndex-1, count = 0; i <= ToIndex-1; i++) {
815        if(mystring[i] == C) {
816          count++;
817          if ( count == N ) return i+1;
818        }
819      }
820      return 0 ;
821    }
822    throw Standard_OutOfRange();
823 }
824
825 //------------------------------------------------------------------------
826 //  Location
827 //------------------------------------------------------------------------
828 Standard_Integer TCollection_AsciiString::Location
829                                 (const TCollection_AsciiString& what,
830                                  const Standard_Integer         FromIndex,
831                                  const Standard_Integer         ToIndex) const
832 {
833   if (mylength == 0 || what.mylength == 0) return 0;
834   if (ToIndex <= mylength && FromIndex > 0 && FromIndex <= ToIndex ) {
835     Standard_Integer i = FromIndex-1;
836     Standard_Integer k = 1;
837     Standard_Integer l = FromIndex-2;
838     Standard_Boolean Find = Standard_False; 
839     while (!Find && i < ToIndex)  {
840       if (mystring[i] == what.Value(k)) {
841         k++;
842         if ( k > what.mylength) Find = Standard_True;
843       }
844       else {
845         if (k > 1) i--;    // si on est en cours de recherche 
846         k = 1;
847         l = i;
848       }
849       i++;
850     }
851     if (Find) return l+2;
852     else      return 0;
853   }
854   throw Standard_OutOfRange();
855 }
856
857 // ----------------------------------------------------------------------------
858 // LowerCase
859 // ----------------------------------------------------------------------------
860 void TCollection_AsciiString::LowerCase()
861 {
862   for (int i=0; i < mylength; i++)
863     mystring[i] = ::LowerCase(mystring[i]);
864 }
865
866 //------------------------------------------------------------------------
867 //  Prepend
868 //------------------------------------------------------------------------
869 void TCollection_AsciiString::Prepend(const TCollection_AsciiString& what)
870 {
871   Insert(1,what);
872 }
873
874 // ----------------------------------------------------------------------------
875 // RealValue
876 // ----------------------------------------------------------------------------
877 Standard_Real TCollection_AsciiString::RealValue()const
878 {
879   char *ptr;
880   Standard_Real value = Strtod(mystring,&ptr);
881   if (ptr != mystring) return value;
882
883   throw Standard_NumericError("TCollection_AsciiString::RealValue");
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   throw Standard_OutOfRange("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     throw Standard_NegativeValue();
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     throw Standard_OutOfRange("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    throw Standard_OutOfRange("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    throw Standard_OutOfRange("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   throw Standard_OutOfRange("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   throw Standard_OutOfRange("TCollection_AsciiString::Split index");
1197 }
1198
1199 // ----------------------------------------------------------------------------
1200 // SubString
1201 // Private
1202 // ----------------------------------------------------------------------------
1203 void TCollection_AsciiString::SubString(const Standard_Integer FromIndex,
1204                                         const Standard_Integer ToIndex,
1205                                         TCollection_AsciiString& res) const
1206 {
1207
1208   if (ToIndex > mylength || FromIndex <= 0 || FromIndex > ToIndex )
1209     throw Standard_OutOfRange();
1210   Standard_Integer newlength = ToIndex-FromIndex+1;
1211   res.mystring =Reallocate (res.mystring, newlength + 1);
1212   strncpy( res.mystring, mystring + FromIndex - 1, newlength );
1213   res.mystring[newlength] = '\0';
1214   res.mylength = newlength;
1215   return ;
1216 }
1217
1218 // ----------------------------------------------------------------------------
1219 // Token
1220 // Private
1221 // ----------------------------------------------------------------------------
1222 void TCollection_AsciiString::Token(const Standard_CString separators,
1223                                     const Standard_Integer whichone,
1224                                     TCollection_AsciiString& res)const
1225 {
1226   res = Token( separators , whichone ) ;
1227 }
1228
1229 // ----------------------------------------------------------------------------
1230 // Token
1231 // ----------------------------------------------------------------------------
1232 TCollection_AsciiString TCollection_AsciiString::Token
1233                                         (const Standard_CString separators,
1234                                          const Standard_Integer whichone) const
1235 {
1236   if (!separators)
1237     throw Standard_NullObject("TCollection_AsciiString::Token : "
1238                               "parameter 'separators'");
1239
1240   Standard_Integer theOne ;
1241   Standard_Integer StringIndex = 0 ;
1242   Standard_Integer SeparatorIndex ;
1243   Standard_Integer BeginIndex=0 ;
1244   Standard_Integer EndIndex=0 ;
1245
1246 //  cout << "'" << mystring <<  "'" << endl ;
1247   for ( theOne = 0 ; theOne < whichone ; theOne++ ) {
1248      BeginIndex = 0 ;
1249      EndIndex = 0 ;
1250 //     cout << "theOne " << theOne << endl ;
1251      if ( StringIndex == mylength )
1252        break ;
1253      for (; StringIndex < mylength && EndIndex == 0 ; StringIndex++ ) {
1254         SeparatorIndex = 0 ;
1255 //        cout << "StringIndex " << StringIndex << endl ;
1256         while ( separators [ SeparatorIndex ] ) {
1257              if ( mystring [ StringIndex ] == separators [ SeparatorIndex ] ) {
1258                break ;
1259              }
1260              SeparatorIndex += 1 ;
1261            }
1262         if ( separators [ SeparatorIndex ] != '\0' ) { // We have a Separator
1263           if ( BeginIndex && EndIndex == 0 ) {
1264             EndIndex = StringIndex ;
1265 //            cout << "EndIndex " << EndIndex << " '" << SubString( BeginIndex , EndIndex ).ToCString() << "'" << endl ;
1266             break ;
1267           }
1268         }
1269         else if ( BeginIndex == 0 ) {               // We have not a Separator
1270           BeginIndex = StringIndex + 1 ;
1271 //          cout << "BeginIndex " << BeginIndex << endl ;
1272         }
1273      }
1274 //     cout << "BeginIndex " << BeginIndex << " EndIndex " << EndIndex << endl ;
1275   }
1276   if ( BeginIndex == 0 )
1277     return TCollection_AsciiString("",0) ;
1278   if ( EndIndex == 0 )
1279     EndIndex = mylength ;
1280 //    cout << "'" << SubString( BeginIndex , EndIndex ).ToCString() << "'" << endl ;
1281   return TCollection_AsciiString( &mystring [ BeginIndex - 1 ] ,
1282                                   EndIndex - BeginIndex + 1 ) ;
1283 }
1284
1285 // ----------------------------------------------------------------------------
1286 // Trunc
1287 // ----------------------------------------------------------------------------
1288 void TCollection_AsciiString::Trunc(const Standard_Integer ahowmany)
1289 {
1290   if (ahowmany < 0 || ahowmany > mylength)
1291     throw Standard_OutOfRange("TCollection_AsciiString::Trunc : "
1292                               "parameter 'ahowmany'");
1293   mylength = ahowmany;
1294   mystring[mylength] = '\0';
1295 }
1296
1297 // ----------------------------------------------------------------------------
1298 // UpperCase
1299 // ----------------------------------------------------------------------------
1300 void TCollection_AsciiString::UpperCase()
1301 {
1302   for (int i=0; i < mylength; i++)
1303     mystring[i] = ::UpperCase(mystring[i]);
1304 }
1305
1306 //------------------------------------------------------------------------
1307 //  UsefullLength
1308 //------------------------------------------------------------------------
1309 Standard_Integer TCollection_AsciiString::UsefullLength () const
1310 {
1311   Standard_Integer i ;
1312   for ( i = mylength -1 ; i >= 0 ; i--) 
1313     if (IsGraphic(mystring[i])) break;
1314   return i+1;
1315 }
1316
1317 // ----------------------------------------------------------------------------
1318 // Value
1319 // ----------------------------------------------------------------------------
1320 Standard_Character TCollection_AsciiString::Value
1321                                         (const Standard_Integer where)const
1322 {
1323  if (where > 0 && where <= mylength) {
1324    return mystring[where-1];
1325  }
1326  throw Standard_OutOfRange("TCollection_AsciiString::Value : parameter where");
1327 }