0022898: IGES import fails in german environment
[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 #ifdef DEB
170         cout <<"UTF8 decoding failure..." <<endl;
171 #endif
172       ;
173     }
174   }
175   else {
176     Standard_NullObject::Raise("TCollection_ExtendedString : "
177                                "parameter 'astring'");
178   }
179 }
180
181 //---------------------------------------------------------------------------
182 // Create an ExtendedString from an ExtString
183 //--------------------------------------------------------------------------
184 TCollection_ExtendedString::TCollection_ExtendedString
185                                         (const Standard_ExtString astring) 
186 {
187
188   if (astring) {
189 #if OptJr
190     EXTSTRINGLEN( astring , mylength ) ;
191 #else
192     EXTSTRLEN(astring,mylength);
193 #endif
194     mystring = Allocate(ROUNDMEM((mylength+1)*2));
195 #if OptJr
196     EXTSTRINGCOPY( mystring , astring , mylength );
197 #else
198     STRCPY(mystring,astring,mylength);
199     mystring[mylength] =  '\0';
200 #endif
201   }
202   else {
203     Standard_NullObject::Raise("TCollection_ExtendedString : null parameter ");
204   }
205 }
206
207 // ----------------------------------------------------------------------------
208 // Create an asciistring from a Standard_Character
209 // ----------------------------------------------------------------------------
210 TCollection_ExtendedString::TCollection_ExtendedString
211                                         (const Standard_Character aChar)
212 {
213   if ( aChar != '\0' ) {
214     mylength    = 1;
215     mystring    = Allocate(2*2);
216     mystring[0] = ToExtCharacter(aChar);
217     mystring[1] =  '\0';
218   }
219   else {
220     //    mystring = 0L;
221     mylength = 0;
222     mystring = Allocate((mylength+1)*2);
223     mystring[mylength] = '\0';
224   }
225 }
226
227 //--------------------------------------------------------------------------
228 // Create a string from a ExtCharacter
229 // ----------------------------------------------------------------------------
230 TCollection_ExtendedString::TCollection_ExtendedString
231                                         (const Standard_ExtCharacter aChar)
232 {
233   mylength    = 1;
234   mystring    = Allocate(2*2);
235   mystring[0] = aChar;
236   mystring[1] =  '\0';
237 }
238
239 // ----------------------------------------------------------------------------
240 // Create an AsciiString from a filler
241 // ----------------------------------------------------------------------------
242 TCollection_ExtendedString::TCollection_ExtendedString
243                                         (const Standard_Integer      length,
244                                          const Standard_ExtCharacter filler )
245 {
246   mystring = Allocate((length+1)*2);
247   mylength = length;
248   for (int i = 0 ; i < length ; i++) mystring[i] = filler;
249   mystring[length] =  '\0';
250 }
251
252 // ----------------------------------------------------------------------------
253 // Create a String from an Integer
254 // ----------------------------------------------------------------------------
255 TCollection_ExtendedString::TCollection_ExtendedString
256                                         (const Standard_Integer aValue)
257 {
258   union {int bid ;
259          char t [13];} CHN ;
260   Sprintf(&CHN.t[0],"%d",aValue);
261 #if OptJr
262   STRINGLEN( CHN.t , mylength ) ;
263 #else
264   STRLEN(CHN.t,mylength);
265 #endif
266   mystring = Allocate((mylength+1)*2);
267   for (int i = 0 ; i < mylength ; i++) mystring[i] = ToExtCharacter(CHN.t[i]);
268   mystring[mylength] =  '\0';
269 }
270
271 // ----------------------------------------------------------------------------
272 // Create a String from a real
273 // ----------------------------------------------------------------------------
274 TCollection_ExtendedString::TCollection_ExtendedString
275                                         (const Standard_Real aValue)
276 {
277   union {int bid ;
278          char t [50];} CHN ;
279   Sprintf(&CHN.t[0],"%g",aValue);
280 #if OptJr
281   STRINGLEN( CHN.t , mylength ) ;
282 #else
283   STRLEN(CHN.t,mylength);
284 #endif
285   mystring = Allocate((mylength+1)*2);
286   for (int i = 0 ; i < mylength ; i++) mystring[i] = ToExtCharacter(CHN.t[i]);
287   mystring[mylength] =  '\0';
288 }
289
290 //-----------------------------------------------------------------------------
291 // create an extendedstring from an extendedstring
292 // ----------------------------------------------------------------------------
293 TCollection_ExtendedString::TCollection_ExtendedString
294                                 (const TCollection_ExtendedString& astring)
295 {
296
297   mylength = astring.mylength;
298   mystring = Allocate(ROUNDMEM((mylength+1)*2));
299   if (astring.mystring)
300 #if OptJr
301     EXTENDEDSTRINGCOPY( mystring , astring.mystring , mylength );
302 #else
303     STRCPY(mystring,astring.mystring,mylength);
304   mystring[mylength] =  '\0';
305 #endif
306 }
307
308 //---------------------------------------------------------------------------
309 //  Create an extendedstring from an AsciiString 
310 //---------------------------------------------------------------------------
311 TCollection_ExtendedString::TCollection_ExtendedString
312                                 (const TCollection_AsciiString& astring) 
313 {
314   mylength = astring.Length();
315   mystring = Allocate((mylength+1)*2);
316 #if OptJr
317   Standard_CString aCString = astring.ToCString() ;
318   for (Standard_Integer i = 0; i <= mylength ; i++)
319     mystring[i] = ToExtCharacter( aCString[i] ); 
320 #else
321   for (Standard_Integer i = 0; i < mylength ; i++)
322     mystring[i] = ToExtCharacter(astring.Value(i+1)); 
323   mystring[mylength] =  '\0';
324 #endif
325 }
326
327 // ----------------------------------------------------------------------------
328 //  AssignCat
329 // ----------------------------------------------------------------------------
330 void TCollection_ExtendedString::AssignCat
331                                 (const TCollection_ExtendedString& other) 
332 {
333   Standard_Integer otherlength = other.mylength; 
334   if (otherlength) {
335     Standard_ExtString sother = other.mystring;
336     Standard_Integer newlength = mylength +otherlength; 
337     if (mystring) {
338         mystring = Reallocate((void*&)mystring,
339                                                              ROUNDMEM((newlength+1)*2));
340 #if OptJr
341 //      if ( ((long ) ( &mystring[ mylength ] ) & 3) == 0 ) {
342       EXTENDEDSTRINGCAT( mystring , mylength , sother , otherlength ) ;
343 //        }
344 //      else
345 //        STRCAT( mystring , mylength , sother , otherlength + 1 ) ;
346 #else
347       STRCAT(mystring,mylength,sother,otherlength);
348 #endif
349     }
350     else {
351       mystring = Allocate(ROUNDMEM((newlength+1)*2));
352 #if OptJr
353       EXTENDEDSTRINGCOPY( mystring , sother , newlength );
354 #else
355       STRCPY(mystring,sother,newlength);
356 #endif
357     }
358     mylength = newlength;
359 #if !OptJr
360     mystring[mylength] =  '\0';
361 #endif
362   }
363 }
364
365 // ----------------------------------------------------------------------------
366 // Cat
367 // ----------------------------------------------------------------------------
368 TCollection_ExtendedString TCollection_ExtendedString::Cat
369                                 (const TCollection_ExtendedString& other) const 
370 {
371   Standard_ExtString sother = other.mystring;
372   const Standard_Integer otherlength = sother ? other.mylength : 0;
373   const Standard_Integer newlength = mylength + otherlength;
374 #ifdef OptJr
375   // ensure rounding allocated memory to 4 bytes
376   TCollection_ExtendedString res (newlength | 0x1, 0);
377   res.mylength = newlength;
378 #else
379   TCollection_ExtendedString res (newlength, 0);
380 #endif
381  
382   if (otherlength) {
383 #if OptJr
384     EXTENDEDSTRINGCOPY( res.mystring , mystring , mylength );
385       //    if ( ((long ) ( &res.mystring[ mylength ] ) & 3) == 0 ) {
386     EXTENDEDSTRINGCAT( res.mystring , mylength , sother , otherlength ) ;
387 //      }
388 //    else
389 //      STRCAT( res.mystring , mylength , sother , otherlength + 1 ) ;
390 #else
391     if (mylength > 0) STRCPY (res.mystring, mystring, mylength);
392     STRCPY (&res.mystring[mylength], sother, otherlength);
393     res.mystring[newlength] =  '\0';
394 #endif
395   }
396   else if (mylength > 0) {
397 //    TCollection_ExtendedString res;
398 //    res.mystring = (Standard_ExtString)Standard::Allocate((mylength+1)*2);
399 #if OptJr
400     EXTENDEDSTRINGCOPY( res.mystring , mystring , mylength );
401 #else
402     STRCPY (res.mystring, mystring,mylength);
403     res.mystring[res.mylength] =  '\0';
404 #endif
405   }
406   return res;
407 }
408
409 // ----------------------------------------------------------------------------
410 // ChangeAll
411 // ----------------------------------------------------------------------------
412 void TCollection_ExtendedString::ChangeAll(const Standard_ExtCharacter aChar,
413                                            const Standard_ExtCharacter NewChar)
414 {
415   for (int i = 0 ; i < mylength; i++)
416     if (mystring[i] == aChar) mystring[i] = NewChar;
417 }
418
419 // ----------------------------------------------------------------------------
420 // Clear
421 // ----------------------------------------------------------------------------
422 void TCollection_ExtendedString::Clear()
423 {
424   if (mystring) Standard::Free((void*&)mystring);
425 //  mystring = 0L;
426   mylength = 0;
427   mystring = Allocate((mylength+1)*2);
428   mystring[mylength] = '\0';
429 }
430
431 // ----------------------------------------------------------------------------
432 // Copy
433 // ----------------------------------------------------------------------------
434 void TCollection_ExtendedString::Copy (const TCollection_ExtendedString& fromwhere)
435 {
436
437   if (fromwhere.mystring) {
438     Standard_Integer newlength = fromwhere.mylength;
439     if (mystring) {
440       mystring = Reallocate((void*&)mystring, ROUNDMEM(( newlength + 1)*2 ));
441     }
442     else {
443       mystring = Allocate(ROUNDMEM((newlength+1)*2));
444     }
445     mylength = newlength;
446 #if OptJr
447     EXTENDEDSTRINGCOPY( mystring , fromwhere.mystring , newlength );
448 #else
449     STRCPY(mystring, fromwhere.mystring,newlength);
450     mystring[mylength] =  '\0';
451 #endif
452   }
453   else {
454     if (mystring) {
455       mylength = 0;
456       mystring[mylength] =  '\0';
457     }
458   }
459 }
460
461 // ----------------------------------------------------------------------------
462 // Destroy
463 // ----------------------------------------------------------------------------
464 void TCollection_ExtendedString::Destroy()
465 {
466   if (mystring) Standard::Free((void*&)mystring);
467   mystring = 0L;
468 }
469
470 //----------------------------------------------------------------------------
471 // Insert a character before 'where'th character
472 // ----------------------------------------------------------------------------
473 void TCollection_ExtendedString::Insert(const Standard_Integer where,
474                                         const Standard_ExtCharacter what)
475 {
476   if (where > mylength + 1 )
477     Standard_OutOfRange::Raise("TCollection_ExtendedString::Insert : "
478                                "Parameter where is too big");
479   if (where < 0)
480     Standard_OutOfRange::Raise("TCollection_ExtendedString::Insert : "
481                                "Parameter where is negative");
482
483   if (mystring) {
484       mystring = Reallocate((void*&)mystring,
485                                                            (mylength+2)*2);
486   }
487   else {
488     mystring = Allocate((mylength+2)*2);
489   }
490   if (where != mylength +1) {
491     for (int i=mylength-1; i >= where-1; i--)
492       mystring[i+1] = mystring[i];
493   }
494   mystring[where-1] = what;
495   mylength++;
496   mystring[mylength] =  '\0';
497 }
498
499 // ----------------------------------------------------------------------------
500 // Insert
501 // ----------------------------------------------------------------------------
502 void TCollection_ExtendedString::Insert(const Standard_Integer            where,
503                                         const TCollection_ExtendedString& what)
504 {
505   Standard_ExtString swhat = what.mystring;
506   if (where <= mylength + 1) {
507     Standard_Integer whatlength = what.mylength;
508     if(whatlength) {
509       Standard_Integer newlength = mylength + whatlength;
510       
511       if (mystring) {
512           mystring = Reallocate(
513                                          (void*&)mystring,(newlength+1)*2);
514       }
515       else {
516         mystring = Allocate((newlength+1)*2);
517       }
518       if (where != mylength +1) {
519         for (int i=mylength-1; i >= where-1; i--)
520           mystring[i+whatlength] = mystring[i];
521       }
522       for (int i=0; i < whatlength; i++)
523         mystring[where-1+i] = swhat[i];
524       
525       mylength = newlength;
526       mystring[mylength] =  '\0';
527     }
528   }
529   else {
530     Standard_OutOfRange::Raise("TCollection_ExtendedString::Insert : "
531                                "Parameter where is too big");
532   }
533 }
534
535 #if OptJr
536 // ----------------------------------------------------------------------------
537 // IsEqual
538 // ----------------------------------------------------------------------------
539 Standard_Boolean TCollection_ExtendedString::IsEqual
540                                 (const Standard_ExtString other) const
541 {
542 // Standard_Integer otherlength ;
543
544 //  EXTSTRINGLEN( other , otherlength )
545 //  if ( mylength != otherlength ) return Standard_False;
546   Standard_Boolean KEqual ;
547   LEXTSTRINGEQUAL( mystring , mylength , other , KEqual ) ;
548   return KEqual ;
549 }
550 #else
551 Standard_Boolean TCollection_ExtendedString::NoIsEqual
552                                 (const Standard_ExtString other) const
553 {return Standard_False ;}
554 #endif
555
556 // ----------------------------------------------------------------------------
557 // IsEqual
558 // ----------------------------------------------------------------------------
559 Standard_Boolean TCollection_ExtendedString::IsEqual
560                                 (const TCollection_ExtendedString& other) const
561 {
562   if (mylength != other.mylength) return Standard_False;
563   Standard_ExtString sother = other.mystring;  
564 #if OptJr
565   Standard_Boolean KEqual ;
566   EXTENDEDSTRINGEQUAL( mystring , sother , mylength , KEqual ) ;
567   return KEqual ;
568 #else
569   for (int i = 0 ; i < mylength ; i++)
570     if (mystring[i] != sother[i]) return Standard_False;
571   return Standard_True;
572 #endif
573 }
574
575 #if OptJr
576 // ----------------------------------------------------------------------------
577 // IsDifferent
578 // ----------------------------------------------------------------------------
579 Standard_Boolean TCollection_ExtendedString::IsDifferent
580                                 (const Standard_ExtString other ) const
581 {
582 // Standard_Integer otherlength ;
583
584 //  EXTSTRINGLEN( other , otherlength )
585 //  if ( mylength != otherlength ) return Standard_True;
586   Standard_Boolean KEqual ;
587   LEXTSTRINGEQUAL( mystring , mylength , other , KEqual ) ;
588   return !KEqual ;
589 }
590 #else
591 Standard_Boolean TCollection_ExtendedString::NoIsDifferent
592                                 (const Standard_ExtString other ) const
593 {return Standard_False ;}
594 #endif
595
596 // ----------------------------------------------------------------------------
597 // IsDifferent
598 // ----------------------------------------------------------------------------
599 Standard_Boolean TCollection_ExtendedString::IsDifferent
600                                 (const TCollection_ExtendedString& other) const
601 {
602   if (mylength != other.mylength) return Standard_True;
603   Standard_ExtString sother = other.mystring;  
604 #if OptJr
605   Standard_Boolean KEqual ;
606   EXTENDEDSTRINGEQUAL( mystring , sother , mylength , KEqual ) ;
607   return !KEqual ;
608 #else
609   for (int i = 0 ; i < mylength ; i++)
610     if (mystring[i] != sother[i]) return Standard_True;
611   return Standard_False;
612 #endif
613 }
614
615 #if OptJr
616 // ----------------------------------------------------------------------------
617 // IsLess
618 // ----------------------------------------------------------------------------
619 Standard_Boolean TCollection_ExtendedString::IsLess
620                                 (const Standard_ExtString other) const
621 {
622 // Standard_Integer otherlength ;
623
624 //  EXTSTRINGLEN( other , otherlength )
625   Standard_Boolean KLess ;
626 //  EXTSTRINGLESS( mystring , mylength , other , otherlength ,
627 //                 INF( mylength , otherlength ) , KLess ) ;
628   LEXTSTRINGLESS( mystring , mylength , other , KLess ) ;
629   return KLess ;
630 }
631 #else
632 Standard_Boolean TCollection_ExtendedString::NoIsLess
633                                 (const Standard_ExtString other) const
634 {return Standard_False ;}
635 #endif
636
637 // ----------------------------------------------------------------------------
638 // IsLess
639 // ----------------------------------------------------------------------------
640 Standard_Boolean TCollection_ExtendedString::IsLess
641                                 (const TCollection_ExtendedString& other) const
642 {
643
644   Standard_Integer otherlength = other.mylength;
645   Standard_ExtString sother = other.mystring;  
646 #if OptJr
647   Standard_Boolean KLess ;
648   EXTENDEDSTRINGLESS( mystring , mylength , sother , otherlength ,
649                       INF( mylength , otherlength ) , KLess ) ;
650   return KLess ;
651 #else
652   Standard_Integer i = 0, j = 0;
653   while ( i < mylength && j < otherlength) {
654     if (mystring[i] < sother[j]) return Standard_True;
655     if (mystring[i] > sother[j]) return Standard_False;
656     i++ ; 
657     j++;
658   }
659   if (i == mylength && j < otherlength) return Standard_True;
660   return Standard_False;
661 #endif
662 }
663
664 #if OptJr
665 // ----------------------------------------------------------------------------
666 // IsGreater
667 // ----------------------------------------------------------------------------
668 Standard_Boolean TCollection_ExtendedString::IsGreater
669                                 (const Standard_ExtString other) const
670 {
671 // Standard_Integer otherlength ;
672
673 //  EXTSTRINGLEN( other , otherlength )
674   Standard_Boolean KGreater ;
675 //  EXTSTRINGGREATER( mystring , mylength , other , otherlength ,
676 //                    INF( mylength , otherlength ) , KGreater ) ;
677   LEXTSTRINGGREATER( mystring , mylength , other , KGreater ) ;
678   return KGreater ;
679 }
680 #else
681 Standard_Boolean TCollection_ExtendedString::NoIsGreater
682                                 (const Standard_ExtString other) const
683 {return Standard_False ;}
684 #endif
685
686 // ----------------------------------------------------------------------------
687 // IsGreater
688 // ----------------------------------------------------------------------------
689 Standard_Boolean TCollection_ExtendedString::IsGreater
690                                 (const TCollection_ExtendedString& other) const
691 {
692   Standard_Integer otherlength = other.mylength;
693   Standard_ExtString sother = other.mystring;  
694 #if OptJr
695   Standard_Boolean KGreater ;
696   EXTENDEDSTRINGGREATER( mystring , mylength , sother , otherlength ,
697                          INF( mylength , otherlength ) , KGreater ) ;
698   return KGreater ;
699 #else
700   Standard_Integer i = 0, j = 0;
701   while (i < mylength && j <= otherlength) {
702     if (mystring[i] < sother[j]) return Standard_False;
703     if (mystring[i] > sother[j]) return Standard_True;
704     i++ ; 
705     j++;
706   }
707   if (j == otherlength && i < mylength) return Standard_True;
708   return Standard_False;
709 #endif
710 }
711
712 // ----------------------------------------------------------------------------
713 // IsAscii
714 // ----------------------------------------------------------------------------
715 Standard_Boolean TCollection_ExtendedString::IsAscii()  const 
716 {
717   for( Standard_Integer i = 0 ; i < mylength ; i++)
718     if (!IsAnAscii(mystring[i])) return Standard_False;
719   return Standard_True;
720 }
721
722 //------------------------------------------------------------------------
723 //  Length
724 // ----------------------------------------------------------------------------
725 Standard_Integer TCollection_ExtendedString::Length()  const
726 {
727   return mylength;
728 }
729
730 // ----------------------------------------------------------------------------
731 // Print
732 // ----------------------------------------------------------------------------
733 void TCollection_ExtendedString::Print(Standard_OStream& astream) const 
734
735   // ASCII symbols (including extended Ascii) are printed as is;
736   // other Unicode characters are encoded as SGML numeric character references
737   for (Standard_Integer i = 0 ; i < mylength ; i++) {
738     Standard_ExtCharacter c = mystring[i];
739     if ( IsAnAscii(c) )
740       astream << ToCharacter(c);
741     else 
742       astream << "&#" << c << ";";
743   }
744 }
745
746
747 // ----------------------------------------------------------------------------
748 Standard_OStream& operator << (Standard_OStream& astream,
749                                const TCollection_ExtendedString& astring)
750 {
751   astring.Print(astream);
752   return astream;
753 }
754
755 // ----------------------------------------------------------------------------
756 // RemoveAll
757 // ----------------------------------------------------------------------------
758 void TCollection_ExtendedString::RemoveAll(const Standard_ExtCharacter what)
759
760 {
761   if (mylength == 0) return;
762   int c = 0;
763     for (int i=0; i < mylength; i++)
764       if (mystring[i] != what) mystring[c++] = mystring[i];
765   mylength = c;
766   mystring[mylength] =  '\0';
767 }
768
769 // ----------------------------------------------------------------------------
770 // Remove
771 // ----------------------------------------------------------------------------
772 void TCollection_ExtendedString::Remove (const Standard_Integer where,
773                                          const Standard_Integer ahowmany)
774 {
775   if (where+ahowmany <= mylength+1) {
776     int i,j;
777     for (i = where+ahowmany-1, j = where-1; i < mylength; i++, j++)
778       mystring[j] = mystring[i];
779     mylength -= ahowmany;
780     mystring[mylength] =  '\0';
781   }
782   else
783     Standard_OutOfRange::Raise("TCollection_ExtendedString::Remove: "
784                                "Too many characters to erase or "
785                                "invalid starting value.");
786 }
787
788 // ----------------------------------------------------------------------------
789 // Search
790 // ----------------------------------------------------------------------------
791 Standard_Integer TCollection_ExtendedString::Search
792                                 (const TCollection_ExtendedString& what) const 
793 {
794   Standard_Integer size = what.mylength;
795   Standard_ExtString swhat = what.mystring;  
796   if (size) {
797     int k,j;
798     int i = 0;
799     Standard_Boolean find = Standard_False; 
800     while ( i < mylength-size+1 && !find) {
801       k = i++;
802       j = 0;
803       while (j < size && mystring[k++] == swhat[j++])
804         if (j == size) find = Standard_True;
805     }
806     if (find)  return i;
807   }
808   return -1;
809 }
810
811 // ----------------------------------------------------------------------------
812 // SearchFromEnd
813 // ----------------------------------------------------------------------------
814 Standard_Integer TCollection_ExtendedString::SearchFromEnd
815                                 (const TCollection_ExtendedString& what) const
816 {
817   Standard_Integer size = what.mylength;
818   if (size) {
819     Standard_ExtString swhat = what.mystring;  
820     int k,j;
821     int i = mylength-1;
822     Standard_Boolean find = Standard_False; 
823     while ( i >= size-1 && !find) {
824       k = i--;
825       j = size-1;
826       while (j >= 0 && mystring[k--] == swhat[j--])
827         if (j == -1) find = Standard_True;
828     }
829     if (find)  return i-size+3;
830   }
831   return -1;
832 }
833
834 // ----------------------------------------------------------------------------
835 // SetValue
836 // ----------------------------------------------------------------------------
837 void TCollection_ExtendedString::SetValue(const Standard_Integer      where,
838                                           const Standard_ExtCharacter what)
839 {
840   if (where > 0 && where <= mylength) {
841     mystring[where-1] = what;
842   }
843   else {
844     Standard_OutOfRange::Raise("TCollection_ExtendedString::SetValue : parameter where");
845   }
846 }
847
848 // ----------------------------------------------------------------------------
849 // SetValue
850 // ----------------------------------------------------------------------------
851 void TCollection_ExtendedString::SetValue
852                                 (const Standard_Integer            where,
853                                  const TCollection_ExtendedString& what)
854 {
855   if (where > 0 && where <= mylength+1) {
856     Standard_Integer size = what.mylength;
857     Standard_ExtString swhat = what.mystring;  
858     size += (where - 1);  
859     if (size >= mylength){
860       if (mystring) {
861         mystring = Reallocate ((void*&)mystring,(size+1)*2);
862       }
863       else {
864         mystring = Allocate((size+1)*2);
865       }
866       mylength = size;
867     } 
868     for (int i = where-1; i < size; i++)
869       mystring[i] = swhat[i-(where-1)];
870     mystring[mylength] =  '\0';
871   }
872   else
873     Standard_OutOfRange::Raise("TCollection_ExtendedString::SetValue : "
874                                "parameter where");
875 }
876
877 // ----------------------------------------------------------------------------
878 // Split
879 // ----------------------------------------------------------------------------
880 TCollection_ExtendedString TCollection_ExtendedString::Split
881                                         (const Standard_Integer where)
882 {
883   if (where >= 0 && where < mylength) {
884     TCollection_ExtendedString res(&mystring[where]);
885     Trunc(where);
886     return res;
887   }
888   Standard_OutOfRange::Raise("TCollection_ExtendedString::Split index");
889   TCollection_ExtendedString res;
890   return res;
891 }
892
893 // ----------------------------------------------------------------------------
894 // Token
895 // ----------------------------------------------------------------------------
896 TCollection_ExtendedString TCollection_ExtendedString::Token
897                                       (const Standard_ExtString separators,
898                                        const Standard_Integer   whichone) const
899 {
900   TCollection_ExtendedString res("");
901   if (!separators)
902     Standard_NullObject::Raise("TCollection_ExtendedString::Token : "
903                                "parameter 'separators'");
904   
905   int                   i,j,k,l;
906   Standard_PExtCharacter  buftmp = Allocate((mylength+1)*2); 
907   Standard_ExtCharacter aSep;
908   
909   Standard_Boolean isSepFound   = Standard_False, otherSepFound;
910   
911   j = 0;
912   
913   for (i = 0; i < whichone && j < mylength; i++) {
914     isSepFound   = Standard_False;
915     k = 0;
916     buftmp[0] = 0;
917     
918     // Avant de commencer il faut virer les saloperies devant
919     //
920     otherSepFound = Standard_True;
921     while (j < mylength && otherSepFound) {
922       l    = 0;
923       otherSepFound = Standard_False;
924       aSep = separators[l];
925       while(aSep != 0) {
926         if (aSep == mystring[j]) {
927           aSep = 0;
928           otherSepFound = Standard_True;
929         }
930         else {
931           aSep = separators[l++];
932         }
933       }
934       if (otherSepFound) j++;
935     }
936     
937     while (!isSepFound && k < mylength && j<mylength ) {
938       l    = 0;
939       aSep = separators[l];
940       
941       while (aSep != 0 && !isSepFound) {
942         if (aSep == mystring[j]) {
943           buftmp[k] = 0;
944           isSepFound = Standard_True;
945         }
946         else {
947           buftmp[k] = mystring[j];
948         }
949         l++;
950         aSep = separators[l];
951       }
952       j++; k++;
953       if(j==mylength) buftmp[k] = 0;
954     }
955   }
956   
957   if (i < whichone) {
958     buftmp[0] = 0;
959     Standard::Free((void*&)buftmp);
960   }
961   else {
962     res.mystring = buftmp;
963 #if OptJr
964     EXTSTRINGLEN( buftmp , res.mylength ) ;
965 #else
966     EXTSTRLEN(buftmp,res.mylength);
967 #endif
968   }
969   return res;
970 }
971
972 // ----------------------------------------------------------------------------
973 // ToExtString
974 // ----------------------------------------------------------------------------
975 const Standard_ExtString TCollection_ExtendedString::ToExtString() const
976 {
977   if(mystring) return mystring;
978   return NULL_EXTSTRING;
979 }
980
981 // ----------------------------------------------------------------------------
982 // Trunc
983 // ----------------------------------------------------------------------------
984 void TCollection_ExtendedString::Trunc(const Standard_Integer ahowmany)
985 {
986   if (ahowmany < 0 || ahowmany > mylength)
987     Standard_OutOfRange::Raise("TCollection_ExtendedString::Trunc : "
988                                "parameter 'ahowmany'");
989   mylength = ahowmany;
990   mystring[mylength] =  '\0';
991 }
992
993 // ----------------------------------------------------------------------------
994 // Value
995 // ----------------------------------------------------------------------------
996 Standard_ExtCharacter TCollection_ExtendedString::Value
997                                         (const Standard_Integer where) const
998 {
999  if (where > 0 && where <= mylength) {
1000    if(mystring) return mystring[where-1];
1001    else         return 0;
1002  }
1003  Standard_OutOfRange::Raise("TCollection_ExtendedString::Value : "
1004                             "parameter where");
1005  return 0;
1006 }
1007
1008
1009 //----------------------------------------------------------------------------
1010 // Convert CString (including multibyte case) to UniCode representation
1011 //----------------------------------------------------------------------------
1012 Standard_Boolean TCollection_ExtendedString::ConvertToUnicode 
1013                                                 (const Standard_CString aStr)
1014 {
1015   Standard_Boolean aRes = Standard_True;
1016   short * p = mystring;
1017   int i = 0;
1018   while (aStr[i] != '\0') { 
1019     if((aStr[i] & 0x80) == 0x00) //1byte => 1 symb - Lat1
1020       {*p++ = ToExtCharacter(aStr[i]); i++;}
1021     else if((aStr[i] & 0xE0) == 0xC0 && 
1022             (aStr[i+1] && 
1023              (aStr[i+1] & 0xC0) == 0x80)) {//2 bytes => 1 symb
1024       *p++ = ConvertToUnicode2B((unsigned char*)&aStr[i]);
1025       i += 2;
1026     } else if((aStr[i] & 0xF0) == 0xE0 && 
1027               ((aStr[i+1] && (aStr[i+1] & 0xC0) == 0x80)) &&
1028               (aStr[i+2] && (aStr[i+2] & 0xC0) == 0x80)) {      
1029       *p++ = ConvertToUnicode3B((unsigned char*)&aStr[i]);
1030       i += 3;
1031     } else { //unsupported case ==> not UTF8
1032       aRes = Standard_False;
1033       break;
1034     }
1035   }
1036   *p = 0x0000;
1037   return aRes;
1038 }
1039 //----------------------------------------------------------------------------
1040 // Returns expected CString length in UTF8 coding.
1041 //----------------------------------------------------------------------------
1042 Standard_Integer TCollection_ExtendedString::LengthOfCString() const
1043 {
1044   Standard_Integer i=0, aLen=0;
1045   while(mystring[i]) {
1046     if((mystring[i] & 0xFF80) == 0) 
1047       aLen++;
1048     else if((mystring[i] & 0xF800) == 0) 
1049       aLen +=2;
1050     else  
1051       aLen += 3;
1052     i++;
1053   }
1054  return aLen;
1055 }
1056
1057 //----------------------------------------------------------------------------
1058 // Converts the internal <mystring> to UTF8 coding and returns length of the 
1059 // out CString.
1060 //----------------------------------------------------------------------------
1061 Standard_Integer TCollection_ExtendedString::ToUTF8CString(Standard_PCharacter& theCString) const
1062 {
1063   Standard_Integer i=0, j=0;
1064   unsigned char a,b,c;
1065   while(mystring[i]) {
1066     if((mystring[i] & 0xFF80) == 0) {
1067       theCString[j++] = (char)mystring[i];
1068     } 
1069     else if((mystring[i] & 0xF800) == 0) {
1070       b = (unsigned char)mystring[i];//yyzzzzzz
1071       c = (unsigned char)mystring[i];//yyzzzzzz
1072       a = (unsigned char)(mystring[i]>>8);//00000yyy
1073       b &= 0x3F;
1074       b |= 0x80;
1075       a <<=2;
1076       a |= 0xC0;//110yyy00;
1077       c >>=6;
1078       c &= 0x03;
1079       a |=c;
1080       theCString[j++] = a;
1081       theCString[j++] = b;
1082     } else {
1083       b = (unsigned char)mystring[i];//yyzzzzzz
1084       c = (unsigned char)mystring[i];//yyzzzzzz
1085       unsigned char d = a = (unsigned char)(mystring[i]>>8);//xxxxyyyy
1086       c &= 0x3F;
1087       c |= 0x80;//10zzzzzz
1088       b >>= 6; //000000yy
1089       d <<= 2;//xxyyyy00;
1090       b |= d;
1091       b = (b & 0x3F) | 0x80;//10yyyyyy
1092       a >>= 4; //0000xxxx
1093       a |= 0xE0;//1110xxxx
1094       theCString[j++] = a;
1095       theCString[j++] = b;
1096       theCString[j++] = c;
1097     }
1098     i++;
1099   }
1100   theCString[j] = 0x00;
1101   return j;
1102 }
1103 //=======================================================================
1104 //function : Allocate
1105 //purpose  : 
1106 //=======================================================================
1107 Standard_PExtCharacter Allocate(const Standard_Size aLength)
1108 {
1109   Standard_PExtCharacter pChar;
1110   //
1111   pChar=(Standard_PExtCharacter)Standard::Allocate(aLength);
1112   //
1113   return pChar;
1114 }
1115 //=======================================================================
1116 //function : Reallocate
1117 //purpose  : 
1118 //=======================================================================
1119 Standard_PExtCharacter Reallocate(Standard_Address aAddr,
1120                                   const Standard_Size aLength)
1121 {
1122   Standard_PExtCharacter pChar;
1123   //
1124   pChar= (Standard_PExtCharacter)Standard::Reallocate(aAddr, aLength);
1125   //
1126   return pChar;
1127 }