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