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