0030981: Foundation Classes - heap-buffer-overflow reported by Clang address sanitize...
[occt.git] / src / TCollection / TCollection_ExtendedString.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_ExtendedString.hxx>
16
17 #include <NCollection_UtfIterator.hxx>
18 #include <Standard.hxx>
19 #include <Standard_ExtString.hxx>
20 #include <Standard_NegativeValue.hxx>
21 #include <Standard_NullObject.hxx>
22 #include <Standard_NumericError.hxx>
23 #include <Standard_OutOfRange.hxx>
24 #include <TCollection_AsciiString.hxx>
25
26 #include <algorithm>
27 #include <cctype>
28 #include <cstdio>
29
30 namespace
31 {
32   //! Allocate string buffer (automatically adding extra symbol for NULL-termination).
33   static Standard_ExtCharacter* allocateExtChars (const Standard_Size theLength)
34   {
35     return (Standard_ExtCharacter* )Standard::Allocate ((theLength + 1) * sizeof(Standard_ExtCharacter));
36   }
37
38   //! Re-allocate string buffer (automatically adding extra symbol for NULL-termination).
39   static Standard_ExtCharacter* reallocateExtChars (Standard_Address theAddr,
40                                                     const Standard_Size theLength)
41   {
42     return (Standard_ExtCharacter* )Standard::Reallocate (theAddr, (theLength + 1) * sizeof(Standard_ExtCharacter));
43   }
44
45   static const Standard_ExtCharacter NULL_EXTSTRING[1] = {0};
46
47   //! Returns the number of 16-bit code units in Unicode string
48   template<typename T>
49   static Standard_Integer nbSymbols (const T* theUtfString)
50   {
51     Standard_Integer aNbCodeUnits = 0;
52     for (NCollection_UtfIterator<T> anIter (theUtfString); *anIter != 0; ++anIter)
53     {
54       aNbCodeUnits += anIter.AdvanceCodeUnitsUtf16();
55     }
56     return aNbCodeUnits;
57   }
58
59   //! Convert from wchar_t* to extended string.
60   //! Default implementation when size of wchar_t and extended char is different (e.g. Linux / UNIX).
61   template<size_t CharSize>
62   inline Standard_ExtCharacter* Standard_UNUSED fromWideString (const Standard_WideChar* theUtfString,
63                                                                 Standard_Integer& theLength)
64   {
65     theLength = nbSymbols (theUtfString);
66     Standard_ExtCharacter* aString = allocateExtChars (theLength);
67     NCollection_UtfWideIter anIterRead (theUtfString);
68     for (Standard_ExtCharacter* anIterWrite = aString; *anIterRead != 0; ++anIterRead)
69     {
70       anIterWrite = anIterRead.GetUtf (anIterWrite);
71     }
72     aString[theLength] = 0;
73     return aString;
74   }
75
76   //! Use memcpy() conversion when size is the same (e.g. on Windows).
77   template<>
78   inline Standard_ExtCharacter* Standard_UNUSED fromWideString<sizeof(Standard_ExtCharacter)> (const Standard_WideChar* theUtfString,
79                                                                                                Standard_Integer& theLength)
80   {
81     for (theLength = 0; theUtfString[theLength] != 0; ++theLength) {}
82     Standard_ExtCharacter* aString = allocateExtChars (theLength);
83     const Standard_Integer aSize = theLength * sizeof(Standard_ExtCharacter);
84     memcpy (aString, theUtfString, aSize);
85     aString[theLength] = 0;
86     return aString;
87   }
88
89 }
90
91 //-----------------------------------------------------------------------------
92 // Create an empty ExtendedString
93 // ----------------------------------------------------------------------------
94 TCollection_ExtendedString::TCollection_ExtendedString()
95 : mystring (allocateExtChars (0)),
96   mylength (0)
97 {
98   mystring[0] = 0;
99 }
100
101 //----------------------------------------------------------------------------
102 // Create an ExtendedString from a Standard_CString
103 //----------------------------------------------------------------------------
104 TCollection_ExtendedString::TCollection_ExtendedString
105                                           (const Standard_CString theString,
106                                            const Standard_Boolean isMultiByte) 
107 : mystring (NULL),
108   mylength (0)
109 {
110   if (theString == NULL)
111   {
112     throw Standard_NullObject("TCollection_ExtendedString : null parameter ");
113   }
114
115   if (isMultiByte)
116   {
117     mylength = nbSymbols (theString);
118     mystring = allocateExtChars (mylength);
119     mystring[mylength] = 0;
120     if (ConvertToUnicode (theString))
121     {
122       return;
123     }
124   }
125
126   mylength = (int)strlen(theString);
127   mystring = reallocateExtChars (mystring, mylength);
128   for (int aCharIter = 0; aCharIter < mylength; ++aCharIter)
129   {
130     mystring[aCharIter] = ToExtCharacter (theString[aCharIter]);
131   }
132   mystring[mylength] = 0;
133 }
134
135 //---------------------------------------------------------------------------
136 // Create an ExtendedString from an ExtString
137 //--------------------------------------------------------------------------
138 TCollection_ExtendedString::TCollection_ExtendedString (const Standard_ExtString theString)
139 : mystring (NULL),
140   mylength (0)
141 {
142   if (theString == NULL)
143   {
144     throw Standard_NullObject("TCollection_ExtendedString : null parameter ");
145   }
146
147   for (mylength = 0; theString[mylength] != 0; ++mylength) {}
148   mystring = allocateExtChars (mylength);
149   const Standard_Integer aSizeBytes = mylength * sizeof(Standard_ExtCharacter);
150   memcpy (mystring, theString, aSizeBytes);
151   mystring[mylength] = 0;
152 }
153
154 // ----------------------------------------------------------------------------
155 // TCollection_ExtendedString
156 // ----------------------------------------------------------------------------
157 TCollection_ExtendedString::TCollection_ExtendedString (const Standard_WideChar* theStringUtf)
158 : mystring (NULL),
159   mylength (0)
160 {
161   if (theStringUtf == NULL)
162   {
163     throw Standard_NullObject("TCollection_ExtendedString : null parameter ");
164   }
165
166   mystring = fromWideString<sizeof(Standard_WideChar)> (theStringUtf, mylength);
167 }
168
169 // ----------------------------------------------------------------------------
170 // Create an asciistring from a Standard_Character
171 // ----------------------------------------------------------------------------
172 TCollection_ExtendedString::TCollection_ExtendedString
173                                         (const Standard_Character aChar)
174 {
175   if ( aChar != '\0' ) {
176     mylength    = 1;
177     mystring    = allocateExtChars (1);
178     mystring[0] = ToExtCharacter(aChar);
179     mystring[1] = 0;
180   }
181   else {
182     //    mystring = 0L;
183     mylength = 0;
184     mystring = allocateExtChars (0);
185     mystring[0] = 0;
186   }
187 }
188
189 //--------------------------------------------------------------------------
190 // Create a string from a ExtCharacter
191 // ----------------------------------------------------------------------------
192 TCollection_ExtendedString::TCollection_ExtendedString
193                                         (const Standard_ExtCharacter aChar)
194 {
195   mylength    = 1;
196   mystring    = allocateExtChars (1);
197   mystring[0] = aChar;
198   mystring[1] = 0;
199 }
200
201 // ----------------------------------------------------------------------------
202 // Create an AsciiString from a filler
203 // ----------------------------------------------------------------------------
204 TCollection_ExtendedString::TCollection_ExtendedString
205                                         (const Standard_Integer      length,
206                                          const Standard_ExtCharacter filler )
207 {
208   mystring = allocateExtChars (length);
209   mylength = length;
210   for (int i = 0 ; i < length ; i++) mystring[i] = filler;
211   mystring[mylength] = 0;
212 }
213
214 // ----------------------------------------------------------------------------
215 // Create a String from an Integer
216 // ----------------------------------------------------------------------------
217 TCollection_ExtendedString::TCollection_ExtendedString
218                                         (const Standard_Integer aValue)
219 {
220   union {int bid ;
221          char t [13];} CHN ;
222   Sprintf(&CHN.t[0],"%d",aValue);
223   mylength = (int)strlen(CHN.t);
224   mystring = allocateExtChars (mylength);
225   for (int i = 0 ; i < mylength ; i++) mystring[i] = ToExtCharacter(CHN.t[i]);
226   mystring[mylength] = 0;
227 }
228
229 // ----------------------------------------------------------------------------
230 // Create a String from a real
231 // ----------------------------------------------------------------------------
232 TCollection_ExtendedString::TCollection_ExtendedString
233                                         (const Standard_Real aValue)
234 {
235   union {int bid ;
236          char t [50];} CHN ;
237   Sprintf(&CHN.t[0],"%g",aValue);
238   mylength = (int)strlen( CHN.t );
239   mystring = allocateExtChars (mylength);
240   for (int i = 0 ; i < mylength ; i++) mystring[i] = ToExtCharacter(CHN.t[i]);
241   mystring[mylength] = 0;
242 }
243
244 //-----------------------------------------------------------------------------
245 // create an extendedstring from an extendedstring
246 // ----------------------------------------------------------------------------
247 TCollection_ExtendedString::TCollection_ExtendedString
248                                 (const TCollection_ExtendedString& astring)
249 {
250   const Standard_Integer aSizeBytes = astring.mylength * sizeof(Standard_ExtCharacter);
251   mylength = astring.mylength;
252   mystring = allocateExtChars (astring.mylength);
253   memcpy (mystring, astring.mystring, aSizeBytes);
254   mystring[mylength] = 0;
255 }
256
257 //---------------------------------------------------------------------------
258 //  Create an extendedstring from an AsciiString 
259 //---------------------------------------------------------------------------
260 TCollection_ExtendedString::TCollection_ExtendedString
261                                 (const TCollection_AsciiString& theString)
262 {
263   mylength = nbSymbols (theString.ToCString());
264   mystring = allocateExtChars (mylength);
265   mystring[mylength] = 0;
266   if (ConvertToUnicode (theString.ToCString()))
267   {
268     return;
269   }
270
271   mylength = theString.Length();
272   mystring = reallocateExtChars (mystring, mylength);
273   Standard_CString aCString = theString.ToCString();
274   for (Standard_Integer aCharIter = 0; aCharIter <= mylength; ++aCharIter)
275   {
276     mystring[aCharIter] = ToExtCharacter (aCString[aCharIter]);
277   }
278   mystring[mylength] = 0;
279 }
280
281 // ----------------------------------------------------------------------------
282 //  AssignCat
283 // ----------------------------------------------------------------------------
284 void TCollection_ExtendedString::AssignCat (const TCollection_ExtendedString& theOther)
285 {
286   if (theOther.mylength == 0)
287   {
288     return;
289   }
290
291   const Standard_Integer anOtherLength = theOther.mylength;
292   const Standard_Integer aNewlength    = mylength + anOtherLength;
293   if (mystring != NULL)
294   {
295     mystring = reallocateExtChars (mystring, aNewlength);
296     memcpy (mystring + mylength, theOther.mystring, anOtherLength * sizeof(Standard_ExtCharacter));
297   }
298   else
299   {
300     mystring = allocateExtChars (aNewlength);
301     memcpy (mystring, theOther.mystring, anOtherLength * sizeof(Standard_ExtCharacter));
302   }
303   mylength = aNewlength;
304   mystring[mylength] = 0;
305 }
306
307 // ----------------------------------------------------------------------------
308 // Cat
309 // ----------------------------------------------------------------------------
310 TCollection_ExtendedString TCollection_ExtendedString::Cat
311                                 (const TCollection_ExtendedString& other) const 
312 {
313   TCollection_ExtendedString res( mylength + other.mylength, 0 );
314   if ( mylength > 0 )
315     memcpy (res.mystring, mystring, mylength * sizeof(Standard_ExtCharacter));
316   if ( other.mylength > 0 )
317     memcpy (res.mystring + mylength, other.mystring, other.mylength * sizeof(Standard_ExtCharacter));
318   return res;
319 }
320
321 // ----------------------------------------------------------------------------
322 // ChangeAll
323 // ----------------------------------------------------------------------------
324 void TCollection_ExtendedString::ChangeAll(const Standard_ExtCharacter aChar,
325                                            const Standard_ExtCharacter NewChar)
326 {
327   for (int i = 0 ; i < mylength; i++)
328     if (mystring[i] == aChar) mystring[i] = NewChar;
329 }
330
331 // ----------------------------------------------------------------------------
332 // Clear
333 // ----------------------------------------------------------------------------
334 void TCollection_ExtendedString::Clear()
335 {
336   if (mylength == 0)
337   {
338     return;
339   }
340
341   Standard::Free (mystring);
342   mylength = 0;
343   mystring = allocateExtChars (mylength);
344   mystring[0] = 0;
345 }
346
347 // ----------------------------------------------------------------------------
348 // Copy
349 // ----------------------------------------------------------------------------
350 void TCollection_ExtendedString::Copy (const TCollection_ExtendedString& fromwhere)
351 {
352
353   if (fromwhere.mystring) {
354     const Standard_Integer newlength  = fromwhere.mylength;
355     const Standard_Integer aSizeBytes = newlength * sizeof(Standard_ExtCharacter);
356     if (mystring != NULL)
357     {
358       mystring = reallocateExtChars (mystring, newlength);
359     }
360     else {
361       mystring = allocateExtChars (newlength);
362     }
363     mylength = newlength;
364     memcpy (mystring, fromwhere.mystring, aSizeBytes);
365     mystring[mylength] = 0;
366   }
367   else
368   {
369     if (mystring != 0)
370     {
371       mylength = 0;
372       mystring[0] = 0;
373     }
374   }
375 }
376
377 // ----------------------------------------------------------------------------
378 // Swap
379 // ----------------------------------------------------------------------------
380 void TCollection_ExtendedString::Swap (TCollection_ExtendedString& theOther)
381 {
382   std::swap (mystring, theOther.mystring);
383   std::swap (mylength, theOther.mylength);
384 }
385
386 // ----------------------------------------------------------------------------
387 // Destroy
388 // ----------------------------------------------------------------------------
389 TCollection_ExtendedString::~TCollection_ExtendedString()
390 {
391   if (mystring) Standard::Free(mystring);
392   mystring = 0L;
393 }
394
395 //----------------------------------------------------------------------------
396 // Insert a character before 'where'th character
397 // ----------------------------------------------------------------------------
398 void TCollection_ExtendedString::Insert(const Standard_Integer where,
399                                         const Standard_ExtCharacter what)
400 {
401   if (where > mylength + 1 )
402     throw Standard_OutOfRange("TCollection_ExtendedString::Insert : "
403                               "Parameter where is too big");
404   if (where < 0)
405     throw Standard_OutOfRange("TCollection_ExtendedString::Insert : "
406                               "Parameter where is negative");
407
408   if (mystring != NULL)
409   {
410     mystring = reallocateExtChars (mystring, mylength + 1);
411   }
412   else {
413     mystring = allocateExtChars (mylength + 1);
414   }
415   if (where != mylength +1) {
416     for (int i=mylength-1; i >= where-1; i--)
417       mystring[i+1] = mystring[i];
418   }
419   mystring[where-1] = what;
420   mylength++;
421   mystring[mylength] = 0;
422 }
423
424 // ----------------------------------------------------------------------------
425 // Insert
426 // ----------------------------------------------------------------------------
427 void TCollection_ExtendedString::Insert(const Standard_Integer            where,
428                                         const TCollection_ExtendedString& what)
429 {
430   Standard_ExtString swhat = what.mystring;
431   if (where <= mylength + 1) {
432     Standard_Integer whatlength = what.mylength;
433     if(whatlength) {
434       Standard_Integer newlength = mylength + whatlength;
435       
436       if (mystring) {
437           mystring = reallocateExtChars (mystring, newlength);
438       }
439       else {
440         mystring = allocateExtChars (newlength);
441       }
442       if (where != mylength +1) {
443         for (int i=mylength-1; i >= where-1; i--)
444           mystring[i+whatlength] = mystring[i];
445       }
446       for (int i=0; i < whatlength; i++)
447         mystring[where-1+i] = swhat[i];
448       
449       mylength = newlength;
450       mystring[mylength] = 0;
451     }
452   }
453   else {
454     throw Standard_OutOfRange("TCollection_ExtendedString::Insert : "
455                               "Parameter where is too big");
456   }
457 }
458
459 // ----------------------------------------------------------------------------
460 // ExtStrCmp: strcmp for 16-bit chars
461 // ----------------------------------------------------------------------------
462 static int ExtStrCmp (const Standard_ExtString theStr1, const Standard_ExtString theStr2)
463 {
464   const Standard_ExtCharacter* aStr1 = theStr1;
465   const Standard_ExtCharacter* aStr2 = theStr2;
466   while (*aStr1 != 0 && *aStr1 == *aStr2)
467   {
468     aStr1++;
469     aStr2++;
470   }
471   // Standard_ExtCharacter is char16_t which is 2-byte unsigned int, it will be promoted 
472   // to plain 4-byte int for calculation
473   return *aStr1 - *aStr2;
474 }
475
476 // ----------------------------------------------------------------------------
477 // IsEqual
478 // ----------------------------------------------------------------------------
479 Standard_Boolean TCollection_ExtendedString::IsEqual
480                                 (const Standard_ExtString other) const
481 {
482   return ExtStrCmp (mystring, other) == 0;
483 }
484
485 // ----------------------------------------------------------------------------
486 // IsEqual
487 // ----------------------------------------------------------------------------
488 Standard_Boolean TCollection_ExtendedString::IsEqual
489                                 (const TCollection_ExtendedString& other) const
490 {
491   return mylength == other.mylength &&
492          memcmp (mystring, other.mystring, (mylength + 1) * sizeof(Standard_ExtCharacter)) == 0;
493 }
494
495 // ----------------------------------------------------------------------------
496 // IsDifferent
497 // ----------------------------------------------------------------------------
498 Standard_Boolean TCollection_ExtendedString::IsDifferent
499                                 (const Standard_ExtString other ) const
500 {
501   return ExtStrCmp (mystring, other) != 0;
502 }
503
504 // ----------------------------------------------------------------------------
505 // IsDifferent
506 // ----------------------------------------------------------------------------
507 Standard_Boolean TCollection_ExtendedString::IsDifferent
508                                 (const TCollection_ExtendedString& other) const
509 {
510   return mylength != other.mylength ||
511          memcmp (mystring, other.mystring, (mylength + 1) * sizeof(Standard_ExtCharacter)) != 0;
512 }
513
514 // ----------------------------------------------------------------------------
515 // IsLess
516 // ----------------------------------------------------------------------------
517 Standard_Boolean TCollection_ExtendedString::IsLess
518                                 (const Standard_ExtString other) const
519 {
520   return ExtStrCmp (mystring, other) < 0;
521 }
522
523 // ----------------------------------------------------------------------------
524 // IsLess
525 // ----------------------------------------------------------------------------
526 Standard_Boolean TCollection_ExtendedString::IsLess
527                                 (const TCollection_ExtendedString& other) const
528 {
529   return ExtStrCmp (mystring, other.mystring) < 0;
530 }
531
532 // ----------------------------------------------------------------------------
533 // IsGreater
534 // ----------------------------------------------------------------------------
535 Standard_Boolean TCollection_ExtendedString::IsGreater
536                                 (const Standard_ExtString other) const
537 {
538   return ExtStrCmp (mystring, other) > 0;
539 }
540
541 // ----------------------------------------------------------------------------
542 // IsGreater
543 // ----------------------------------------------------------------------------
544 Standard_Boolean TCollection_ExtendedString::IsGreater
545                                 (const TCollection_ExtendedString& other) const
546 {
547   return ExtStrCmp (mystring, other.mystring) > 0;
548 }
549
550 // ----------------------------------------------------------------------------
551 // StartsWith
552 // ----------------------------------------------------------------------------
553 Standard_Boolean TCollection_ExtendedString::StartsWith (const TCollection_ExtendedString& theStartString) const
554 {
555   if (this == &theStartString)
556   {
557     return true;
558   }
559
560   return mylength >= theStartString.mylength
561       && memcmp (theStartString.mystring, mystring, theStartString.mylength * sizeof(Standard_ExtCharacter)) == 0;
562 }
563
564 // ----------------------------------------------------------------------------
565 // EndsWith
566 // ----------------------------------------------------------------------------
567 Standard_Boolean TCollection_ExtendedString::EndsWith (const TCollection_ExtendedString& theEndString) const
568 {
569   if (this == &theEndString)
570   {
571     return true;
572   }
573
574   return mylength >= theEndString.mylength
575       && memcmp (theEndString.mystring, mystring + mylength - theEndString.mylength, theEndString.mylength * sizeof(Standard_ExtCharacter)) == 0;
576 }
577
578 // ----------------------------------------------------------------------------
579 // IsAscii
580 // ----------------------------------------------------------------------------
581 Standard_Boolean TCollection_ExtendedString::IsAscii()  const 
582 {
583   for( Standard_Integer i = 0 ; i < mylength ; i++)
584     if (!IsAnAscii(mystring[i])) return Standard_False;
585   return Standard_True;
586 }
587
588 //------------------------------------------------------------------------
589 //  Length
590 // ----------------------------------------------------------------------------
591 Standard_Integer TCollection_ExtendedString::Length()  const
592 {
593   return mylength;
594 }
595
596 // ----------------------------------------------------------------------------
597 // Print
598 // ----------------------------------------------------------------------------
599 void TCollection_ExtendedString::Print(Standard_OStream& astream) const 
600
601   // ASCII symbols (including extended Ascii) are printed as is;
602   // other Unicode characters are encoded as SGML numeric character references
603   for (Standard_Integer i = 0 ; i < mylength ; i++) {
604     Standard_ExtCharacter c = mystring[i];
605     if ( IsAnAscii(c) )
606       astream << ToCharacter(c);
607     else 
608       astream << "&#" << c << ";";
609   }
610 }
611
612
613 // ----------------------------------------------------------------------------
614 Standard_OStream& operator << (Standard_OStream& astream,
615                                const TCollection_ExtendedString& astring)
616 {
617   astring.Print(astream);
618   return astream;
619 }
620
621 // ----------------------------------------------------------------------------
622 // RemoveAll
623 // ----------------------------------------------------------------------------
624 void TCollection_ExtendedString::RemoveAll(const Standard_ExtCharacter what)
625
626 {
627   if (mylength == 0) return;
628   int c = 0;
629     for (int i=0; i < mylength; i++)
630       if (mystring[i] != what) mystring[c++] = mystring[i];
631   mylength = c;
632   mystring[mylength] =  '\0';
633 }
634
635 // ----------------------------------------------------------------------------
636 // Remove
637 // ----------------------------------------------------------------------------
638 void TCollection_ExtendedString::Remove (const Standard_Integer where,
639                                          const Standard_Integer ahowmany)
640 {
641   if (where+ahowmany <= mylength+1) {
642     int i,j;
643     for (i = where+ahowmany-1, j = where-1; i < mylength; i++, j++)
644       mystring[j] = mystring[i];
645     mylength -= ahowmany;
646     mystring[mylength] =  '\0';
647   }
648   else
649     throw Standard_OutOfRange("TCollection_ExtendedString::Remove: "
650                               "Too many characters to erase or "
651                               "invalid starting value.");
652 }
653
654 // ----------------------------------------------------------------------------
655 // Search
656 // ----------------------------------------------------------------------------
657 Standard_Integer TCollection_ExtendedString::Search
658                                 (const TCollection_ExtendedString& what) const 
659 {
660   Standard_Integer size = what.mylength;
661   Standard_ExtString swhat = what.mystring;  
662   if (size) {
663     int k,j;
664     int i = 0;
665     Standard_Boolean find = Standard_False; 
666     while ( i < mylength-size+1 && !find) {
667       k = i++;
668       j = 0;
669       while (j < size && mystring[k++] == swhat[j++])
670         if (j == size) find = Standard_True;
671     }
672     if (find)  return i;
673   }
674   return -1;
675 }
676
677 // ----------------------------------------------------------------------------
678 // SearchFromEnd
679 // ----------------------------------------------------------------------------
680 Standard_Integer TCollection_ExtendedString::SearchFromEnd
681                                 (const TCollection_ExtendedString& what) const
682 {
683   Standard_Integer size = what.mylength;
684   if (size) {
685     Standard_ExtString swhat = what.mystring;  
686     int k,j;
687     int i = mylength-1;
688     Standard_Boolean find = Standard_False; 
689     while ( i >= size-1 && !find) {
690       k = i--;
691       j = size-1;
692       while (j >= 0 && mystring[k--] == swhat[j--])
693         if (j == -1) find = Standard_True;
694     }
695     if (find)  return i-size+3;
696   }
697   return -1;
698 }
699
700 // ----------------------------------------------------------------------------
701 // SetValue
702 // ----------------------------------------------------------------------------
703 void TCollection_ExtendedString::SetValue(const Standard_Integer      where,
704                                           const Standard_ExtCharacter what)
705 {
706   if (where > 0 && where <= mylength) {
707     mystring[where-1] = what;
708   }
709   else {
710     throw Standard_OutOfRange("TCollection_ExtendedString::SetValue : parameter where");
711   }
712 }
713
714 // ----------------------------------------------------------------------------
715 // SetValue
716 // ----------------------------------------------------------------------------
717 void TCollection_ExtendedString::SetValue
718                                 (const Standard_Integer            where,
719                                  const TCollection_ExtendedString& what)
720 {
721   if (where > 0 && where <= mylength+1) {
722     Standard_Integer size = what.mylength;
723     Standard_ExtString swhat = what.mystring;  
724     size += (where - 1);  
725     if (size >= mylength){
726       if (mystring) {
727         mystring = reallocateExtChars (mystring, size);
728       }
729       else {
730         mystring = allocateExtChars (size);
731       }
732       mylength = size;
733     } 
734     for (int i = where-1; i < size; i++)
735       mystring[i] = swhat[i-(where-1)];
736     mystring[mylength] =  '\0';
737   }
738   else
739     throw Standard_OutOfRange("TCollection_ExtendedString::SetValue : "
740                               "parameter where");
741 }
742
743 // ----------------------------------------------------------------------------
744 // Split
745 // ----------------------------------------------------------------------------
746 TCollection_ExtendedString TCollection_ExtendedString::Split
747                                         (const Standard_Integer where)
748 {
749   if (where >= 0 && where < mylength) {
750     TCollection_ExtendedString res(&mystring[where]);
751     Trunc(where);
752     return res;
753   }
754   throw Standard_OutOfRange("TCollection_ExtendedString::Split index");
755 }
756
757 // ----------------------------------------------------------------------------
758 // Token
759 // ----------------------------------------------------------------------------
760 TCollection_ExtendedString TCollection_ExtendedString::Token
761                                       (const Standard_ExtString separators,
762                                        const Standard_Integer   whichone) const
763 {
764   TCollection_ExtendedString res;
765   if (!separators)
766     throw Standard_NullObject("TCollection_ExtendedString::Token : "
767                               "parameter 'separators'");
768   
769   int                   i,j,k,l;
770   Standard_PExtCharacter  buftmp = allocateExtChars (mylength);
771   Standard_ExtCharacter aSep;
772   
773   Standard_Boolean isSepFound   = Standard_False, otherSepFound;
774   
775   j = 0;
776   
777   for (i = 0; i < whichone && j < mylength; i++) {
778     isSepFound   = Standard_False;
779     k = 0;
780     buftmp[0] = 0;
781     
782     // Avant de commencer il faut virer les saloperies devant
783     //
784     otherSepFound = Standard_True;
785     while (j < mylength && otherSepFound) {
786       l    = 0;
787       otherSepFound = Standard_False;
788       aSep = separators[l];
789       while(aSep != 0) {
790         if (aSep == mystring[j]) {
791           aSep = 0;
792           otherSepFound = Standard_True;
793         }
794         else {
795           aSep = separators[l++];
796         }
797       }
798       if (otherSepFound) j++;
799     }
800     
801     while (!isSepFound && k < mylength && j<mylength ) {
802       l    = 0;
803       aSep = separators[l];
804       
805       while (aSep != 0 && !isSepFound) {
806         if (aSep == mystring[j]) {
807           buftmp[k] = 0;
808           isSepFound = Standard_True;
809         }
810         else {
811           buftmp[k] = mystring[j];
812         }
813         l++;
814         aSep = separators[l];
815       }
816       j++; k++;
817       if(j==mylength) buftmp[k] = 0;
818     }
819   }
820   
821   if (i < whichone) {
822     buftmp[0] = 0;
823     Standard::Free(buftmp);
824   }
825   else {
826     Standard::Free(res.mystring);
827     res.mystring = buftmp;
828     for ( res.mylength=0; buftmp[res.mylength]; ++res.mylength );
829     res.mystring[res.mylength] = '\0';
830   }
831   return res;
832 }
833
834 // ----------------------------------------------------------------------------
835 // ToExtString
836 // ----------------------------------------------------------------------------
837 Standard_ExtString TCollection_ExtendedString::ToExtString() const
838 {
839   if(mystring) return mystring;
840   return NULL_EXTSTRING;
841 }
842
843 // ----------------------------------------------------------------------------
844 // Trunc
845 // ----------------------------------------------------------------------------
846 void TCollection_ExtendedString::Trunc(const Standard_Integer ahowmany)
847 {
848   if (ahowmany < 0 || ahowmany > mylength)
849     throw Standard_OutOfRange("TCollection_ExtendedString::Trunc : "
850                               "parameter 'ahowmany'");
851   mylength = ahowmany;
852   mystring[mylength] =  '\0';
853 }
854
855 // ----------------------------------------------------------------------------
856 // Value
857 // ----------------------------------------------------------------------------
858 Standard_ExtCharacter TCollection_ExtendedString::Value
859                                         (const Standard_Integer where) const
860 {
861  if (where > 0 && where <= mylength) {
862    if(mystring) return mystring[where-1];
863    else         return 0;
864  }
865  throw Standard_OutOfRange("TCollection_ExtendedString::Value : "
866                            "parameter where");
867 }
868
869
870 //----------------------------------------------------------------------------
871 // Convert CString (including multibyte case) to UniCode representation
872 //----------------------------------------------------------------------------
873 Standard_Boolean TCollection_ExtendedString::ConvertToUnicode (const Standard_CString theStringUtf)
874 {
875   NCollection_Utf8Iter anIterRead (theStringUtf);
876   Standard_ExtCharacter* anIterWrite = mystring;
877   if (*anIterRead == 0)
878   {
879     *anIterWrite = '\0';
880     return Standard_True;
881   }
882
883   for (; *anIterRead != 0; ++anIterRead)
884   {
885     if (!anIterRead.IsValid())
886     {
887       return Standard_False;
888     }
889
890     anIterWrite = anIterRead.GetUtf (anIterWrite);
891   }
892   return Standard_True;
893 }
894
895 //----------------------------------------------------------------------------
896 // Returns expected CString length in UTF8 coding.
897 //----------------------------------------------------------------------------
898 Standard_Integer TCollection_ExtendedString::LengthOfCString() const
899 {
900   Standard_Integer aSizeBytes = 0;
901   for (NCollection_Utf16Iter anIter (mystring); *anIter != 0; ++anIter)
902   {
903     aSizeBytes += anIter.AdvanceBytesUtf8();
904   }
905   return aSizeBytes;
906 }
907
908 //----------------------------------------------------------------------------
909 // Converts the internal <mystring> to UTF8 coding and returns length of the 
910 // out CString.
911 //----------------------------------------------------------------------------
912 Standard_Integer TCollection_ExtendedString::ToUTF8CString(Standard_PCharacter& theCString) const
913 {
914   NCollection_Utf16Iter anIterRead (mystring);
915   Standard_Utf8Char* anIterWrite = theCString;
916   if (*anIterRead == 0)
917   {
918     *anIterWrite = '\0';
919     return 0;
920   }
921
922   for (; *anIterRead != 0; ++anIterRead)
923   {
924     anIterWrite = anIterRead.GetUtf (anIterWrite);
925   }
926   *anIterWrite = '\0';
927   return Standard_Integer(anIterWrite - theCString);
928 }