62235535d7789fa536e4a40115bab651e870541f
[occt.git] / src / TCollection / TCollection_ExtendedString.cxx
1 // Copyright (c) 1993-1999 Matra Datavision
2 // Copyright (c) 1999-2012 OPEN CASCADE SAS
3 //
4 // The content of this file is subject to the Open CASCADE Technology Public
5 // License Version 6.5 (the "License"). You may not use the content of this file
6 // except in compliance with the License. Please obtain a copy of the License
7 // at http://www.opencascade.org and read it completely before using this file.
8 //
9 // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
10 // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
11 //
12 // The Original Code and all software distributed under the License is
13 // distributed on an "AS IS" basis, without warranty of any kind, and the
14 // Initial Developer hereby disclaims all such warranties, including without
15 // limitation, any warranties of merchantability, fitness for a particular
16 // purpose or non-infringement. Please see the License for the specific terms
17 // and conditions governing the rights and limitations under the License.
18
19
20 #define OptJr 1
21
22 // OCC6794: if OptJr is ON, we need to ensure that memory allocations are done by 4 bytes words,
23 // in order to avoid writing into unallocated memory at the string end when it is copied
24 // by CSTRINGCOPY or ASCIISTRINGCOPY macros
25 // (though, due to OCC memory manager roundings of allocated memory, the problem appears
26 //  only when MMGT_OPT is 0 and string size is greater than MMGT_THRESHOLD)
27 #ifdef OptJr
28 #define ROUNDMEM(len) (((len)+3)&~0x3)
29 #else
30 #define ROUNDMEM(len) (len)
31 #endif
32 //#if defined(WNT) || defined(LIN)
33 #include <stdio.h>
34 //#endif
35
36 #include <TCollection_ExtendedString.ixx>
37 #include <Standard.hxx>
38 #include <Standard_ExtString.hxx>
39 #include <Standard_NullObject.hxx>
40 #include <Standard_OutOfRange.hxx>
41 #include <Standard_ctype.hxx>
42 #include <Standard_String.hxx>
43 #include <TCollection_AsciiString.hxx>
44
45 static
46   Standard_PExtCharacter Allocate(const Standard_Size aLength);
47
48 static
49   Standard_PExtCharacter Reallocate(Standard_Address aAddr,
50                                     const Standard_Size aLength);
51
52 Standard_EXPORT short NULL_EXTSTRING[1] = {0};
53
54 //============================== input value have len = 2 bytes ====
55 inline Standard_ExtCharacter ConvertToUnicode2B (unsigned char *p)
56 {
57   // *p, *(p+1)
58   union {
59     struct {
60       unsigned char  h;
61       unsigned char  l;
62     } hl;
63     Standard_ExtCharacter chr;
64   } EL;
65
66   unsigned char l = *(p+1);
67   l |= 0xC0;
68   unsigned char h = *p;
69   h <<= 6;
70   h |= 0x3F;
71   l &= h;// l is defined
72   h = *p;
73   h >>= 2;
74   h &= 0x07;
75   EL.hl.l = l;
76   EL.hl.h = h;
77   return EL.chr;
78 }
79
80 //============================== input value have len = 3 bytes ====
81 inline Standard_ExtCharacter ConvertToUnicode3B (unsigned char *p)
82 {
83   // *p, *(p+1), *(p+2) =>0 , 1, 2
84   union {
85     struct {
86       unsigned char  h;
87       unsigned char  l;
88     } hl;
89     Standard_ExtCharacter chr;
90   } EL;
91
92
93   unsigned char h = *(p+1);//h = 10yyyyyy
94   unsigned char l = *(p+2);//h = 10zzzzzz
95
96   l |= 0xC0;
97   h <<= 6;   //yy------
98   h |= 0x3F; //yy111111
99   l &= h;   //  yyzzzzzz - l is defined 
100   EL.hl.l = l; 
101  
102   unsigned char a = *p;// a = 1110xxxx
103   a <<= 4;//xxxx----
104   a |= 0x0F;//a = xxxx1111
105   h = *(p+1);
106   h >>= 2;//----yyyy
107   h |= 0xF0; //1111yyyy
108   a &= h; // a = xxxxyyyy
109   EL.hl.h = a; //h is defined
110   return EL.chr;
111 }
112 //============================== returns number of symbols in UTF8 string ====
113 inline Standard_Integer  nbSymbols(const Standard_CString aStr) {
114   Standard_Integer aLen = 0;// length in symbols
115   int i = 0;
116   while (aStr[i] != '\0') {  
117     if((aStr[i] & 0x80) == 0x00) //1byte => 1 symb - Lat1
118       {aLen++; i++;}
119     else if((aStr[i] & 0xE0) == 0xC0 && 
120             (aStr[i+1] && 
121              (aStr[i+1] & 0xC0) == 0x80)) {//2 bytes => 1 symb
122       aLen++;
123       i += 2;
124     } else if((aStr[i] & 0xF0) == 0xE0 && 
125               ((aStr[i+1] && (aStr[i+1] & 0xC0) == 0x80)) &&
126               (aStr[i+2] && (aStr[i+2] & 0xC0) == 0x80)) {
127       aLen++;
128       i += 3;
129     } else 
130       i++; 
131   }
132   return aLen;
133 }
134
135 //-----------------------------------------------------------------------------
136 // Create an empty ExtendedString
137 // ----------------------------------------------------------------------------
138 TCollection_ExtendedString::TCollection_ExtendedString()
139 {
140 //  mystring = 0L;
141   mylength = 0;
142   mystring = Allocate((mylength+1)*2);
143   mystring[mylength] = '\0';
144 }
145
146 //----------------------------------------------------------------------------
147 // Create an ExtendedString from a Standard_CString
148 //----------------------------------------------------------------------------
149 TCollection_ExtendedString::TCollection_ExtendedString
150                                           (const Standard_CString astring, 
151                                            const Standard_Boolean isMultiByte) 
152 {
153   if (astring) {
154     if(!isMultiByte) {
155 #if OptJr
156       STRINGLEN( astring , mylength ) ;
157 #else
158       STRLEN(astring,mylength);
159 #endif
160       mystring = Allocate((mylength+1)*2);
161       for (int i = 0 ; i < mylength ; i++)
162         mystring[i] = ToExtCharacter(astring[i]); 
163       mystring[mylength] =  '\0';
164     }
165     else {
166       mylength = nbSymbols(astring);
167       mystring = Allocate(ROUNDMEM((mylength+1)*2));
168       if(!ConvertToUnicode (astring))
169       {
170 #ifdef DEB
171         cout <<"UTF8 decoding failure..." <<endl;
172 #endif
173       }
174     }
175   }
176   else {
177     Standard_NullObject::Raise("TCollection_ExtendedString : "
178                                "parameter 'astring'");
179   }
180 }
181
182 //---------------------------------------------------------------------------
183 // Create an ExtendedString from an ExtString
184 //--------------------------------------------------------------------------
185 TCollection_ExtendedString::TCollection_ExtendedString
186                                         (const Standard_ExtString astring) 
187 {
188
189   if (astring) {
190 #if OptJr
191     EXTSTRINGLEN( astring , mylength ) ;
192 #else
193     EXTSTRLEN(astring,mylength);
194 #endif
195     mystring = Allocate(ROUNDMEM((mylength+1)*2));
196 #if OptJr
197     EXTSTRINGCOPY( mystring , astring , mylength );
198 #else
199     STRCPY(mystring,astring,mylength);
200     mystring[mylength] =  '\0';
201 #endif
202   }
203   else {
204     Standard_NullObject::Raise("TCollection_ExtendedString : null parameter ");
205   }
206 }
207
208 // ----------------------------------------------------------------------------
209 // Create an asciistring from a Standard_Character
210 // ----------------------------------------------------------------------------
211 TCollection_ExtendedString::TCollection_ExtendedString
212                                         (const Standard_Character aChar)
213 {
214   if ( aChar != '\0' ) {
215     mylength    = 1;
216     mystring    = Allocate(2*2);
217     mystring[0] = ToExtCharacter(aChar);
218     mystring[1] =  '\0';
219   }
220   else {
221     //    mystring = 0L;
222     mylength = 0;
223     mystring = Allocate((mylength+1)*2);
224     mystring[mylength] = '\0';
225   }
226 }
227
228 //--------------------------------------------------------------------------
229 // Create a string from a ExtCharacter
230 // ----------------------------------------------------------------------------
231 TCollection_ExtendedString::TCollection_ExtendedString
232                                         (const Standard_ExtCharacter aChar)
233 {
234   mylength    = 1;
235   mystring    = Allocate(2*2);
236   mystring[0] = aChar;
237   mystring[1] =  '\0';
238 }
239
240 // ----------------------------------------------------------------------------
241 // Create an AsciiString from a filler
242 // ----------------------------------------------------------------------------
243 TCollection_ExtendedString::TCollection_ExtendedString
244                                         (const Standard_Integer      length,
245                                          const Standard_ExtCharacter filler )
246 {
247   mystring = Allocate((length+1)*2);
248   mylength = length;
249   for (int i = 0 ; i < length ; i++) mystring[i] = filler;
250   mystring[length] =  '\0';
251 }
252
253 // ----------------------------------------------------------------------------
254 // Create a String from an Integer
255 // ----------------------------------------------------------------------------
256 TCollection_ExtendedString::TCollection_ExtendedString
257                                         (const Standard_Integer aValue)
258 {
259   union {int bid ;
260          char t [13];} CHN ;
261   Sprintf(&CHN.t[0],"%d",aValue);
262 #if OptJr
263   STRINGLEN( CHN.t , mylength ) ;
264 #else
265   STRLEN(CHN.t,mylength);
266 #endif
267   mystring = Allocate((mylength+1)*2);
268   for (int i = 0 ; i < mylength ; i++) mystring[i] = ToExtCharacter(CHN.t[i]);
269   mystring[mylength] =  '\0';
270 }
271
272 // ----------------------------------------------------------------------------
273 // Create a String from a real
274 // ----------------------------------------------------------------------------
275 TCollection_ExtendedString::TCollection_ExtendedString
276                                         (const Standard_Real aValue)
277 {
278   union {int bid ;
279          char t [50];} CHN ;
280   Sprintf(&CHN.t[0],"%g",aValue);
281 #if OptJr
282   STRINGLEN( CHN.t , mylength ) ;
283 #else
284   STRLEN(CHN.t,mylength);
285 #endif
286   mystring = Allocate((mylength+1)*2);
287   for (int i = 0 ; i < mylength ; i++) mystring[i] = ToExtCharacter(CHN.t[i]);
288   mystring[mylength] =  '\0';
289 }
290
291 //-----------------------------------------------------------------------------
292 // create an extendedstring from an extendedstring
293 // ----------------------------------------------------------------------------
294 TCollection_ExtendedString::TCollection_ExtendedString
295                                 (const TCollection_ExtendedString& astring)
296 {
297
298   mylength = astring.mylength;
299   mystring = Allocate(ROUNDMEM((mylength+1)*2));
300   if (astring.mystring)
301 #if OptJr
302     EXTENDEDSTRINGCOPY( mystring , astring.mystring , mylength );
303 #else
304     STRCPY(mystring,astring.mystring,mylength);
305   mystring[mylength] =  '\0';
306 #endif
307 }
308
309 //---------------------------------------------------------------------------
310 //  Create an extendedstring from an AsciiString 
311 //---------------------------------------------------------------------------
312 TCollection_ExtendedString::TCollection_ExtendedString
313                                 (const TCollection_AsciiString& astring) 
314 {
315   mylength = astring.Length();
316   mystring = Allocate((mylength+1)*2);
317 #if OptJr
318   Standard_CString aCString = astring.ToCString() ;
319   for (Standard_Integer i = 0; i <= mylength ; i++)
320     mystring[i] = ToExtCharacter( aCString[i] ); 
321 #else
322   for (Standard_Integer i = 0; i < mylength ; i++)
323     mystring[i] = ToExtCharacter(astring.Value(i+1)); 
324   mystring[mylength] =  '\0';
325 #endif
326 }
327
328 // ----------------------------------------------------------------------------
329 //  AssignCat
330 // ----------------------------------------------------------------------------
331 void TCollection_ExtendedString::AssignCat
332                                 (const TCollection_ExtendedString& other) 
333 {
334   Standard_Integer otherlength = other.mylength; 
335   if (otherlength) {
336     Standard_ExtString sother = other.mystring;
337     Standard_Integer newlength = mylength +otherlength; 
338     if (mystring) {
339         mystring = Reallocate((void*&)mystring,
340                                                              ROUNDMEM((newlength+1)*2));
341 #if OptJr
342 //      if ( ((long ) ( &mystring[ mylength ] ) & 3) == 0 ) {
343       EXTENDEDSTRINGCAT( mystring , mylength , sother , otherlength ) ;
344 //        }
345 //      else
346 //        STRCAT( mystring , mylength , sother , otherlength + 1 ) ;
347 #else
348       STRCAT(mystring,mylength,sother,otherlength);
349 #endif
350     }
351     else {
352       mystring = Allocate(ROUNDMEM((newlength+1)*2));
353 #if OptJr
354       EXTENDEDSTRINGCOPY( mystring , sother , newlength );
355 #else
356       STRCPY(mystring,sother,newlength);
357 #endif
358     }
359     mylength = newlength;
360 #if !OptJr
361     mystring[mylength] =  '\0';
362 #endif
363   }
364 }
365
366 // ----------------------------------------------------------------------------
367 // Cat
368 // ----------------------------------------------------------------------------
369 TCollection_ExtendedString TCollection_ExtendedString::Cat
370                                 (const TCollection_ExtendedString& other) const 
371 {
372   Standard_ExtString sother = other.mystring;
373   const Standard_Integer otherlength = sother ? other.mylength : 0;
374   const Standard_Integer newlength = mylength + otherlength;
375 #ifdef OptJr
376   // ensure rounding allocated memory to 4 bytes
377   TCollection_ExtendedString res (newlength | 0x1, 0);
378   res.mylength = newlength;
379 #else
380   TCollection_ExtendedString res (newlength, 0);
381 #endif
382  
383   if (otherlength) {
384 #if OptJr
385     EXTENDEDSTRINGCOPY( res.mystring , mystring , mylength );
386       //    if ( ((long ) ( &res.mystring[ mylength ] ) & 3) == 0 ) {
387     EXTENDEDSTRINGCAT( res.mystring , mylength , sother , otherlength ) ;
388 //      }
389 //    else
390 //      STRCAT( res.mystring , mylength , sother , otherlength + 1 ) ;
391 #else
392     if (mylength > 0) STRCPY (res.mystring, mystring, mylength);
393     STRCPY (&res.mystring[mylength], sother, otherlength);
394     res.mystring[newlength] =  '\0';
395 #endif
396   }
397   else if (mylength > 0) {
398 //    TCollection_ExtendedString res;
399 //    res.mystring = (Standard_ExtString)Standard::Allocate((mylength+1)*2);
400 #if OptJr
401     EXTENDEDSTRINGCOPY( res.mystring , mystring , mylength );
402 #else
403     STRCPY (res.mystring, mystring,mylength);
404     res.mystring[res.mylength] =  '\0';
405 #endif
406   }
407   return res;
408 }
409
410 // ----------------------------------------------------------------------------
411 // ChangeAll
412 // ----------------------------------------------------------------------------
413 void TCollection_ExtendedString::ChangeAll(const Standard_ExtCharacter aChar,
414                                            const Standard_ExtCharacter NewChar)
415 {
416   for (int i = 0 ; i < mylength; i++)
417     if (mystring[i] == aChar) mystring[i] = NewChar;
418 }
419
420 // ----------------------------------------------------------------------------
421 // Clear
422 // ----------------------------------------------------------------------------
423 void TCollection_ExtendedString::Clear()
424 {
425   if (mystring) Standard::Free((void*&)mystring);
426 //  mystring = 0L;
427   mylength = 0;
428   mystring = Allocate((mylength+1)*2);
429   mystring[mylength] = '\0';
430 }
431
432 // ----------------------------------------------------------------------------
433 // Copy
434 // ----------------------------------------------------------------------------
435 void TCollection_ExtendedString::Copy (const TCollection_ExtendedString& fromwhere)
436 {
437
438   if (fromwhere.mystring) {
439     Standard_Integer newlength = fromwhere.mylength;
440     if (mystring) {
441       mystring = Reallocate((void*&)mystring, ROUNDMEM(( newlength + 1)*2 ));
442     }
443     else {
444       mystring = Allocate(ROUNDMEM((newlength+1)*2));
445     }
446     mylength = newlength;
447 #if OptJr
448     EXTENDEDSTRINGCOPY( mystring , fromwhere.mystring , newlength );
449 #else
450     STRCPY(mystring, fromwhere.mystring,newlength);
451     mystring[mylength] =  '\0';
452 #endif
453   }
454   else {
455     if (mystring) {
456       mylength = 0;
457       mystring[mylength] =  '\0';
458     }
459   }
460 }
461
462 // ----------------------------------------------------------------------------
463 // Destroy
464 // ----------------------------------------------------------------------------
465 void TCollection_ExtendedString::Destroy()
466 {
467   if (mystring) Standard::Free((void*&)mystring);
468   mystring = 0L;
469 }
470
471 //----------------------------------------------------------------------------
472 // Insert a character before 'where'th character
473 // ----------------------------------------------------------------------------
474 void TCollection_ExtendedString::Insert(const Standard_Integer where,
475                                         const Standard_ExtCharacter what)
476 {
477   if (where > mylength + 1 )
478     Standard_OutOfRange::Raise("TCollection_ExtendedString::Insert : "
479                                "Parameter where is too big");
480   if (where < 0)
481     Standard_OutOfRange::Raise("TCollection_ExtendedString::Insert : "
482                                "Parameter where is negative");
483
484   if (mystring) {
485       mystring = Reallocate((void*&)mystring,
486                                                            (mylength+2)*2);
487   }
488   else {
489     mystring = Allocate((mylength+2)*2);
490   }
491   if (where != mylength +1) {
492     for (int i=mylength-1; i >= where-1; i--)
493       mystring[i+1] = mystring[i];
494   }
495   mystring[where-1] = what;
496   mylength++;
497   mystring[mylength] =  '\0';
498 }
499
500 // ----------------------------------------------------------------------------
501 // Insert
502 // ----------------------------------------------------------------------------
503 void TCollection_ExtendedString::Insert(const Standard_Integer            where,
504                                         const TCollection_ExtendedString& what)
505 {
506   Standard_ExtString swhat = what.mystring;
507   if (where <= mylength + 1) {
508     Standard_Integer whatlength = what.mylength;
509     if(whatlength) {
510       Standard_Integer newlength = mylength + whatlength;
511       
512       if (mystring) {
513           mystring = Reallocate(
514                                          (void*&)mystring,(newlength+1)*2);
515       }
516       else {
517         mystring = Allocate((newlength+1)*2);
518       }
519       if (where != mylength +1) {
520         for (int i=mylength-1; i >= where-1; i--)
521           mystring[i+whatlength] = mystring[i];
522       }
523       for (int i=0; i < whatlength; i++)
524         mystring[where-1+i] = swhat[i];
525       
526       mylength = newlength;
527       mystring[mylength] =  '\0';
528     }
529   }
530   else {
531     Standard_OutOfRange::Raise("TCollection_ExtendedString::Insert : "
532                                "Parameter where is too big");
533   }
534 }
535
536 #if OptJr
537 // ----------------------------------------------------------------------------
538 // IsEqual
539 // ----------------------------------------------------------------------------
540 Standard_Boolean TCollection_ExtendedString::IsEqual
541                                 (const Standard_ExtString other) const
542 {
543 // Standard_Integer otherlength ;
544
545 //  EXTSTRINGLEN( other , otherlength )
546 //  if ( mylength != otherlength ) return Standard_False;
547   Standard_Boolean KEqual ;
548   LEXTSTRINGEQUAL( mystring , mylength , other , KEqual ) ;
549   return KEqual ;
550 }
551 #else
552 Standard_Boolean TCollection_ExtendedString::NoIsEqual
553                                 (const Standard_ExtString other) const
554 {return Standard_False ;}
555 #endif
556
557 // ----------------------------------------------------------------------------
558 // IsEqual
559 // ----------------------------------------------------------------------------
560 Standard_Boolean TCollection_ExtendedString::IsEqual
561                                 (const TCollection_ExtendedString& other) const
562 {
563   if (mylength != other.mylength) return Standard_False;
564   Standard_ExtString sother = other.mystring;  
565 #if OptJr
566   Standard_Boolean KEqual ;
567   EXTENDEDSTRINGEQUAL( mystring , sother , mylength , KEqual ) ;
568   return KEqual ;
569 #else
570   for (int i = 0 ; i < mylength ; i++)
571     if (mystring[i] != sother[i]) return Standard_False;
572   return Standard_True;
573 #endif
574 }
575
576 #if OptJr
577 // ----------------------------------------------------------------------------
578 // IsDifferent
579 // ----------------------------------------------------------------------------
580 Standard_Boolean TCollection_ExtendedString::IsDifferent
581                                 (const Standard_ExtString other ) const
582 {
583 // Standard_Integer otherlength ;
584
585 //  EXTSTRINGLEN( other , otherlength )
586 //  if ( mylength != otherlength ) return Standard_True;
587   Standard_Boolean KEqual ;
588   LEXTSTRINGEQUAL( mystring , mylength , other , KEqual ) ;
589   return !KEqual ;
590 }
591 #else
592 Standard_Boolean TCollection_ExtendedString::NoIsDifferent
593                                 (const Standard_ExtString other ) const
594 {return Standard_False ;}
595 #endif
596
597 // ----------------------------------------------------------------------------
598 // IsDifferent
599 // ----------------------------------------------------------------------------
600 Standard_Boolean TCollection_ExtendedString::IsDifferent
601                                 (const TCollection_ExtendedString& other) const
602 {
603   if (mylength != other.mylength) return Standard_True;
604   Standard_ExtString sother = other.mystring;  
605 #if OptJr
606   Standard_Boolean KEqual ;
607   EXTENDEDSTRINGEQUAL( mystring , sother , mylength , KEqual ) ;
608   return !KEqual ;
609 #else
610   for (int i = 0 ; i < mylength ; i++)
611     if (mystring[i] != sother[i]) return Standard_True;
612   return Standard_False;
613 #endif
614 }
615
616 #if OptJr
617 // ----------------------------------------------------------------------------
618 // IsLess
619 // ----------------------------------------------------------------------------
620 Standard_Boolean TCollection_ExtendedString::IsLess
621                                 (const Standard_ExtString other) const
622 {
623 // Standard_Integer otherlength ;
624
625 //  EXTSTRINGLEN( other , otherlength )
626   Standard_Boolean KLess ;
627 //  EXTSTRINGLESS( mystring , mylength , other , otherlength ,
628 //                 INF( mylength , otherlength ) , KLess ) ;
629   LEXTSTRINGLESS( mystring , mylength , other , KLess ) ;
630   return KLess ;
631 }
632 #else
633 Standard_Boolean TCollection_ExtendedString::NoIsLess
634                                 (const Standard_ExtString other) const
635 {return Standard_False ;}
636 #endif
637
638 // ----------------------------------------------------------------------------
639 // IsLess
640 // ----------------------------------------------------------------------------
641 Standard_Boolean TCollection_ExtendedString::IsLess
642                                 (const TCollection_ExtendedString& other) const
643 {
644
645   Standard_Integer otherlength = other.mylength;
646   Standard_ExtString sother = other.mystring;  
647 #if OptJr
648   Standard_Boolean KLess ;
649   EXTENDEDSTRINGLESS( mystring , mylength , sother , otherlength ,
650                       INF( mylength , otherlength ) , KLess ) ;
651   return KLess ;
652 #else
653   Standard_Integer i = 0, j = 0;
654   while ( i < mylength && j < otherlength) {
655     if (mystring[i] < sother[j]) return Standard_True;
656     if (mystring[i] > sother[j]) return Standard_False;
657     i++ ; 
658     j++;
659   }
660   if (i == mylength && j < otherlength) return Standard_True;
661   return Standard_False;
662 #endif
663 }
664
665 #if OptJr
666 // ----------------------------------------------------------------------------
667 // IsGreater
668 // ----------------------------------------------------------------------------
669 Standard_Boolean TCollection_ExtendedString::IsGreater
670                                 (const Standard_ExtString other) const
671 {
672 // Standard_Integer otherlength ;
673
674 //  EXTSTRINGLEN( other , otherlength )
675   Standard_Boolean KGreater ;
676 //  EXTSTRINGGREATER( mystring , mylength , other , otherlength ,
677 //                    INF( mylength , otherlength ) , KGreater ) ;
678   LEXTSTRINGGREATER( mystring , mylength , other , KGreater ) ;
679   return KGreater ;
680 }
681 #else
682 Standard_Boolean TCollection_ExtendedString::NoIsGreater
683                                 (const Standard_ExtString other) const
684 {return Standard_False ;}
685 #endif
686
687 // ----------------------------------------------------------------------------
688 // IsGreater
689 // ----------------------------------------------------------------------------
690 Standard_Boolean TCollection_ExtendedString::IsGreater
691                                 (const TCollection_ExtendedString& other) const
692 {
693   Standard_Integer otherlength = other.mylength;
694   Standard_ExtString sother = other.mystring;  
695 #if OptJr
696   Standard_Boolean KGreater ;
697   EXTENDEDSTRINGGREATER( mystring , mylength , sother , otherlength ,
698                          INF( mylength , otherlength ) , KGreater ) ;
699   return KGreater ;
700 #else
701   Standard_Integer i = 0, j = 0;
702   while (i < mylength && j <= otherlength) {
703     if (mystring[i] < sother[j]) return Standard_False;
704     if (mystring[i] > sother[j]) return Standard_True;
705     i++ ; 
706     j++;
707   }
708   if (j == otherlength && i < mylength) return Standard_True;
709   return Standard_False;
710 #endif
711 }
712
713 // ----------------------------------------------------------------------------
714 // IsAscii
715 // ----------------------------------------------------------------------------
716 Standard_Boolean TCollection_ExtendedString::IsAscii()  const 
717 {
718   for( Standard_Integer i = 0 ; i < mylength ; i++)
719     if (!IsAnAscii(mystring[i])) return Standard_False;
720   return Standard_True;
721 }
722
723 //------------------------------------------------------------------------
724 //  Length
725 // ----------------------------------------------------------------------------
726 Standard_Integer TCollection_ExtendedString::Length()  const
727 {
728   return mylength;
729 }
730
731 // ----------------------------------------------------------------------------
732 // Print
733 // ----------------------------------------------------------------------------
734 void TCollection_ExtendedString::Print(Standard_OStream& astream) const 
735
736   // ASCII symbols (including extended Ascii) are printed as is;
737   // other Unicode characters are encoded as SGML numeric character references
738   for (Standard_Integer i = 0 ; i < mylength ; i++) {
739     Standard_ExtCharacter c = mystring[i];
740     if ( IsAnAscii(c) )
741       astream << ToCharacter(c);
742     else 
743       astream << "&#" << c << ";";
744   }
745 }
746
747
748 // ----------------------------------------------------------------------------
749 Standard_OStream& operator << (Standard_OStream& astream,
750                                const TCollection_ExtendedString& astring)
751 {
752   astring.Print(astream);
753   return astream;
754 }
755
756 // ----------------------------------------------------------------------------
757 // RemoveAll
758 // ----------------------------------------------------------------------------
759 void TCollection_ExtendedString::RemoveAll(const Standard_ExtCharacter what)
760
761 {
762   if (mylength == 0) return;
763   int c = 0;
764     for (int i=0; i < mylength; i++)
765       if (mystring[i] != what) mystring[c++] = mystring[i];
766   mylength = c;
767   mystring[mylength] =  '\0';
768 }
769
770 // ----------------------------------------------------------------------------
771 // Remove
772 // ----------------------------------------------------------------------------
773 void TCollection_ExtendedString::Remove (const Standard_Integer where,
774                                          const Standard_Integer ahowmany)
775 {
776   if (where+ahowmany <= mylength+1) {
777     int i,j;
778     for (i = where+ahowmany-1, j = where-1; i < mylength; i++, j++)
779       mystring[j] = mystring[i];
780     mylength -= ahowmany;
781     mystring[mylength] =  '\0';
782   }
783   else
784     Standard_OutOfRange::Raise("TCollection_ExtendedString::Remove: "
785                                "Too many characters to erase or "
786                                "invalid starting value.");
787 }
788
789 // ----------------------------------------------------------------------------
790 // Search
791 // ----------------------------------------------------------------------------
792 Standard_Integer TCollection_ExtendedString::Search
793                                 (const TCollection_ExtendedString& what) const 
794 {
795   Standard_Integer size = what.mylength;
796   Standard_ExtString swhat = what.mystring;  
797   if (size) {
798     int k,j;
799     int i = 0;
800     Standard_Boolean find = Standard_False; 
801     while ( i < mylength-size+1 && !find) {
802       k = i++;
803       j = 0;
804       while (j < size && mystring[k++] == swhat[j++])
805         if (j == size) find = Standard_True;
806     }
807     if (find)  return i;
808   }
809   return -1;
810 }
811
812 // ----------------------------------------------------------------------------
813 // SearchFromEnd
814 // ----------------------------------------------------------------------------
815 Standard_Integer TCollection_ExtendedString::SearchFromEnd
816                                 (const TCollection_ExtendedString& what) const
817 {
818   Standard_Integer size = what.mylength;
819   if (size) {
820     Standard_ExtString swhat = what.mystring;  
821     int k,j;
822     int i = mylength-1;
823     Standard_Boolean find = Standard_False; 
824     while ( i >= size-1 && !find) {
825       k = i--;
826       j = size-1;
827       while (j >= 0 && mystring[k--] == swhat[j--])
828         if (j == -1) find = Standard_True;
829     }
830     if (find)  return i-size+3;
831   }
832   return -1;
833 }
834
835 // ----------------------------------------------------------------------------
836 // SetValue
837 // ----------------------------------------------------------------------------
838 void TCollection_ExtendedString::SetValue(const Standard_Integer      where,
839                                           const Standard_ExtCharacter what)
840 {
841   if (where > 0 && where <= mylength) {
842     mystring[where-1] = what;
843   }
844   else {
845     Standard_OutOfRange::Raise("TCollection_ExtendedString::SetValue : parameter where");
846   }
847 }
848
849 // ----------------------------------------------------------------------------
850 // SetValue
851 // ----------------------------------------------------------------------------
852 void TCollection_ExtendedString::SetValue
853                                 (const Standard_Integer            where,
854                                  const TCollection_ExtendedString& what)
855 {
856   if (where > 0 && where <= mylength+1) {
857     Standard_Integer size = what.mylength;
858     Standard_ExtString swhat = what.mystring;  
859     size += (where - 1);  
860     if (size >= mylength){
861       if (mystring) {
862         mystring = Reallocate ((void*&)mystring,(size+1)*2);
863       }
864       else {
865         mystring = Allocate((size+1)*2);
866       }
867       mylength = size;
868     } 
869     for (int i = where-1; i < size; i++)
870       mystring[i] = swhat[i-(where-1)];
871     mystring[mylength] =  '\0';
872   }
873   else
874     Standard_OutOfRange::Raise("TCollection_ExtendedString::SetValue : "
875                                "parameter where");
876 }
877
878 // ----------------------------------------------------------------------------
879 // Split
880 // ----------------------------------------------------------------------------
881 TCollection_ExtendedString TCollection_ExtendedString::Split
882                                         (const Standard_Integer where)
883 {
884   if (where >= 0 && where < mylength) {
885     TCollection_ExtendedString res(&mystring[where]);
886     Trunc(where);
887     return res;
888   }
889   Standard_OutOfRange::Raise("TCollection_ExtendedString::Split index");
890   TCollection_ExtendedString res;
891   return res;
892 }
893
894 // ----------------------------------------------------------------------------
895 // Token
896 // ----------------------------------------------------------------------------
897 TCollection_ExtendedString TCollection_ExtendedString::Token
898                                       (const Standard_ExtString separators,
899                                        const Standard_Integer   whichone) const
900 {
901   TCollection_ExtendedString res("");
902   if (!separators)
903     Standard_NullObject::Raise("TCollection_ExtendedString::Token : "
904                                "parameter 'separators'");
905   
906   int                   i,j,k,l;
907   Standard_PExtCharacter  buftmp = Allocate((mylength+1)*2); 
908   Standard_ExtCharacter aSep;
909   
910   Standard_Boolean isSepFound   = Standard_False, otherSepFound;
911   
912   j = 0;
913   
914   for (i = 0; i < whichone && j < mylength; i++) {
915     isSepFound   = Standard_False;
916     k = 0;
917     buftmp[0] = 0;
918     
919     // Avant de commencer il faut virer les saloperies devant
920     //
921     otherSepFound = Standard_True;
922     while (j < mylength && otherSepFound) {
923       l    = 0;
924       otherSepFound = Standard_False;
925       aSep = separators[l];
926       while(aSep != 0) {
927         if (aSep == mystring[j]) {
928           aSep = 0;
929           otherSepFound = Standard_True;
930         }
931         else {
932           aSep = separators[l++];
933         }
934       }
935       if (otherSepFound) j++;
936     }
937     
938     while (!isSepFound && k < mylength && j<mylength ) {
939       l    = 0;
940       aSep = separators[l];
941       
942       while (aSep != 0 && !isSepFound) {
943         if (aSep == mystring[j]) {
944           buftmp[k] = 0;
945           isSepFound = Standard_True;
946         }
947         else {
948           buftmp[k] = mystring[j];
949         }
950         l++;
951         aSep = separators[l];
952       }
953       j++; k++;
954       if(j==mylength) buftmp[k] = 0;
955     }
956   }
957   
958   if (i < whichone) {
959     buftmp[0] = 0;
960     Standard::Free((void*&)buftmp);
961   }
962   else {
963     res.mystring = buftmp;
964 #if OptJr
965     EXTSTRINGLEN( buftmp , res.mylength ) ;
966 #else
967     EXTSTRLEN(buftmp,res.mylength);
968 #endif
969   }
970   return res;
971 }
972
973 // ----------------------------------------------------------------------------
974 // ToExtString
975 // ----------------------------------------------------------------------------
976 const Standard_ExtString TCollection_ExtendedString::ToExtString() const
977 {
978   if(mystring) return mystring;
979   return NULL_EXTSTRING;
980 }
981
982 // ----------------------------------------------------------------------------
983 // Trunc
984 // ----------------------------------------------------------------------------
985 void TCollection_ExtendedString::Trunc(const Standard_Integer ahowmany)
986 {
987   if (ahowmany < 0 || ahowmany > mylength)
988     Standard_OutOfRange::Raise("TCollection_ExtendedString::Trunc : "
989                                "parameter 'ahowmany'");
990   mylength = ahowmany;
991   mystring[mylength] =  '\0';
992 }
993
994 // ----------------------------------------------------------------------------
995 // Value
996 // ----------------------------------------------------------------------------
997 Standard_ExtCharacter TCollection_ExtendedString::Value
998                                         (const Standard_Integer where) const
999 {
1000  if (where > 0 && where <= mylength) {
1001    if(mystring) return mystring[where-1];
1002    else         return 0;
1003  }
1004  Standard_OutOfRange::Raise("TCollection_ExtendedString::Value : "
1005                             "parameter where");
1006  return 0;
1007 }
1008
1009
1010 //----------------------------------------------------------------------------
1011 // Convert CString (including multibyte case) to UniCode representation
1012 //----------------------------------------------------------------------------
1013 Standard_Boolean TCollection_ExtendedString::ConvertToUnicode 
1014                                                 (const Standard_CString aStr)
1015 {
1016   Standard_Boolean aRes = Standard_True;
1017   short * p = mystring;
1018   int i = 0;
1019   while (aStr[i] != '\0') { 
1020     if((aStr[i] & 0x80) == 0x00) //1byte => 1 symb - Lat1
1021       {*p++ = ToExtCharacter(aStr[i]); i++;}
1022     else if((aStr[i] & 0xE0) == 0xC0 && 
1023             (aStr[i+1] && 
1024              (aStr[i+1] & 0xC0) == 0x80)) {//2 bytes => 1 symb
1025       *p++ = ConvertToUnicode2B((unsigned char*)&aStr[i]);
1026       i += 2;
1027     } else if((aStr[i] & 0xF0) == 0xE0 && 
1028               ((aStr[i+1] && (aStr[i+1] & 0xC0) == 0x80)) &&
1029               (aStr[i+2] && (aStr[i+2] & 0xC0) == 0x80)) {      
1030       *p++ = ConvertToUnicode3B((unsigned char*)&aStr[i]);
1031       i += 3;
1032     } else { //unsupported case ==> not UTF8
1033       aRes = Standard_False;
1034       break;
1035     }
1036   }
1037   *p = 0x0000;
1038   return aRes;
1039 }
1040 //----------------------------------------------------------------------------
1041 // Returns expected CString length in UTF8 coding.
1042 //----------------------------------------------------------------------------
1043 Standard_Integer TCollection_ExtendedString::LengthOfCString() const
1044 {
1045   Standard_Integer i=0, aLen=0;
1046   while(mystring[i]) {
1047     if((mystring[i] & 0xFF80) == 0) 
1048       aLen++;
1049     else if((mystring[i] & 0xF800) == 0) 
1050       aLen +=2;
1051     else  
1052       aLen += 3;
1053     i++;
1054   }
1055  return aLen;
1056 }
1057
1058 //----------------------------------------------------------------------------
1059 // Converts the internal <mystring> to UTF8 coding and returns length of the 
1060 // out CString.
1061 //----------------------------------------------------------------------------
1062 Standard_Integer TCollection_ExtendedString::ToUTF8CString(Standard_PCharacter& theCString) const
1063 {
1064   Standard_Integer i=0, j=0;
1065   unsigned char a,b,c;
1066   while(mystring[i]) {
1067     if((mystring[i] & 0xFF80) == 0) {
1068       theCString[j++] = (char)mystring[i];
1069     } 
1070     else if((mystring[i] & 0xF800) == 0) {
1071       b = (unsigned char)mystring[i];//yyzzzzzz
1072       c = (unsigned char)mystring[i];//yyzzzzzz
1073       a = (unsigned char)(mystring[i]>>8);//00000yyy
1074       b &= 0x3F;
1075       b |= 0x80;
1076       a <<=2;
1077       a |= 0xC0;//110yyy00;
1078       c >>=6;
1079       c &= 0x03;
1080       a |=c;
1081       theCString[j++] = a;
1082       theCString[j++] = b;
1083     } else {
1084       b = (unsigned char)mystring[i];//yyzzzzzz
1085       c = (unsigned char)mystring[i];//yyzzzzzz
1086       unsigned char d = a = (unsigned char)(mystring[i]>>8);//xxxxyyyy
1087       c &= 0x3F;
1088       c |= 0x80;//10zzzzzz
1089       b >>= 6; //000000yy
1090       d <<= 2;//xxyyyy00;
1091       b |= d;
1092       b = (b & 0x3F) | 0x80;//10yyyyyy
1093       a >>= 4; //0000xxxx
1094       a |= 0xE0;//1110xxxx
1095       theCString[j++] = a;
1096       theCString[j++] = b;
1097       theCString[j++] = c;
1098     }
1099     i++;
1100   }
1101   theCString[j] = 0x00;
1102   return j;
1103 }
1104 //=======================================================================
1105 //function : Allocate
1106 //purpose  : 
1107 //=======================================================================
1108 Standard_PExtCharacter Allocate(const Standard_Size aLength)
1109 {
1110   Standard_PExtCharacter pChar;
1111   //
1112   pChar=(Standard_PExtCharacter)Standard::Allocate(aLength);
1113   //
1114   return pChar;
1115 }
1116 //=======================================================================
1117 //function : Reallocate
1118 //purpose  : 
1119 //=======================================================================
1120 Standard_PExtCharacter Reallocate(Standard_Address aAddr,
1121                                   const Standard_Size aLength)
1122 {
1123   Standard_PExtCharacter pChar;
1124   //
1125   pChar= (Standard_PExtCharacter)Standard::Reallocate(aAddr, aLength);
1126   //
1127   return pChar;
1128 }