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