0024911: Avoid using virtual functions in NCollection classes
[occt.git] / src / NCollection / NCollection_UtfString.lxx
1 // Created on: 2013-01-28
2 // Created by: Kirill GAVRILOV
3 // Copyright (c) 2013-2014 OPEN CASCADE SAS
4 //
5 // This file is part of Open CASCADE Technology software library.
6 //
7 // This library is free software; you can redistribute it and/or modify it under
8 // the terms of the GNU Lesser General Public License version 2.1 as published
9 // by the Free Software Foundation, with special exception defined in the file
10 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11 // distribution for complete text of the license and disclaimer of any warranty.
12 //
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
15
16 // =======================================================================
17 // function : strGetAdvance
18 // purpose  : Compute advance for specified string.
19 // =======================================================================
20 template<typename TypeTo> template<typename TypeFrom> inline
21 void NCollection_UtfString<TypeTo>::strGetAdvance (const TypeFrom*        theStringUtf,
22                                                    const Standard_Integer theLengthMax,
23                                                    Standard_Integer&      theSizeBytes,
24                                                    Standard_Integer&      theLength)
25 {
26   theSizeBytes = 0;
27   theLength    = 0;
28   NCollection_UtfIterator<TypeFrom> anIter (theStringUtf);
29   const Standard_Integer aLengthMax = (theLengthMax > 0) ? theLengthMax : IntegerLast();
30   switch (sizeof(TypeTo))
31   {
32     case sizeof(Standard_Utf8Char):
33     {
34       for (; *anIter != 0 && anIter.Index() < aLengthMax; ++anIter)
35       {
36         theSizeBytes += anIter.AdvanceBytesUtf8();
37       }
38       theLength = anIter.Index();
39       return;
40     }
41     case sizeof(Standard_Utf16Char):
42     {
43       for (; *anIter != 0 && anIter.Index() < aLengthMax; ++anIter)
44       {
45         theSizeBytes += anIter.AdvanceBytesUtf16();
46       }
47       theLength = anIter.Index();
48       return;
49     }
50     case sizeof(Standard_Utf32Char):
51     {
52       for (; *anIter != 0 && anIter.Index() < aLengthMax; ++anIter)
53       {
54         theSizeBytes += anIter.AdvanceBytesUtf32();
55       }
56       theLength = anIter.Index();
57       return;
58     }
59     default: return;
60   }
61 }
62
63 // =======================================================================
64 // function : GetChar
65 // purpose  :
66 // =======================================================================
67 template<typename Type>
68 Standard_Utf32Char NCollection_UtfString<Type>::GetChar (const Standard_Integer theCharIndex) const
69 {
70   //Standard_ASSERT_SKIP (theCharIndex < myLength, "Out of range");
71   NCollection_UtfIterator<Type> anIter (myString);
72   for (; *anIter != 0; ++anIter)
73   {
74     if (anIter.Index() == theCharIndex)
75     {
76       return *anIter;
77     }
78   }
79   return 0;
80 }
81
82 // =======================================================================
83 // function : GetCharBuffer
84 // purpose  :
85 // =======================================================================
86 template<typename Type>
87 const Type* NCollection_UtfString<Type>::GetCharBuffer (const Standard_Integer theCharIndex) const
88 {
89   //Standard_ASSERT_SKIP(theCharIndex < myLength);
90   NCollection_UtfIterator<Type> anIter (myString);
91   for (; *anIter != 0; ++anIter)
92   {
93     if (anIter.Index() == theCharIndex)
94     {
95       return anIter.BufferHere();
96     }
97   }
98   return NULL;
99 }
100
101 // =======================================================================
102 // function : Clear
103 // purpose  :
104 // =======================================================================
105 template<typename Type> inline
106 void NCollection_UtfString<Type>::Clear()
107 {
108   strFree (myString);
109   mySize   = 0;
110   myLength = 0;
111   myString = strAlloc (mySize);
112 }
113
114 // =======================================================================
115 // function : NCollection_UtfString
116 // purpose  :
117 // =======================================================================
118 template<typename Type> inline
119 NCollection_UtfString<Type>::NCollection_UtfString()
120 : myString (strAlloc(0)),
121   mySize   (0),
122   myLength (0)
123 {
124   //
125 }
126
127 // =======================================================================
128 // function : NCollection_UtfString
129 // purpose  :
130 // =======================================================================
131 template<typename Type> inline
132 NCollection_UtfString<Type>::NCollection_UtfString (const NCollection_UtfString& theCopy)
133 : myString (strAlloc (theCopy.mySize)),
134   mySize   (theCopy.mySize),
135   myLength (theCopy.myLength)
136 {
137   strCopy ((Standard_Byte* )myString, (const Standard_Byte* )theCopy.myString, mySize);
138 }
139
140 // =======================================================================
141 // function : NCollection_UtfString
142 // purpose  :
143 // =======================================================================
144 template<typename Type> inline
145 NCollection_UtfString<Type>::NCollection_UtfString (const char*            theCopyUtf8,
146                                                     const Standard_Integer theLength)
147 : myString (NULL),
148   mySize   (0),
149   myLength (0)
150 {
151   FromUnicode (theCopyUtf8, theLength);
152 }
153
154 // =======================================================================
155 // function : NCollection_UtfString
156 // purpose  :
157 // =======================================================================
158 template<typename Type> inline
159 NCollection_UtfString<Type>::NCollection_UtfString (const Standard_Utf16Char* theCopyUtf16,
160                                                     const Standard_Integer    theLength)
161 : myString (NULL),
162   mySize   (0),
163   myLength (0)
164 {
165   FromUnicode (theCopyUtf16, theLength);
166 }
167
168 // =======================================================================
169 // function : NCollection_UtfString
170 // purpose  :
171 // =======================================================================
172 template<typename Type> inline
173 NCollection_UtfString<Type>::NCollection_UtfString (const Standard_Utf32Char* theCopyUtf32,
174                                                     const Standard_Integer     theLength)
175 : myString (NULL),
176   mySize   (0),
177   myLength (0)
178 {
179   FromUnicode (theCopyUtf32, theLength);
180 }
181
182 // =======================================================================
183 // function : NCollection_UtfString
184 // purpose  :
185 // =======================================================================
186 template<typename Type> inline
187 NCollection_UtfString<Type>::NCollection_UtfString (const Standard_WideChar* theCopyUtfWide,
188                                                     const Standard_Integer   theLength)
189 : myString (NULL),
190   mySize   (0),
191   myLength (0)
192 {
193   FromUnicode (theCopyUtfWide, theLength);
194 }
195
196 // =======================================================================
197 // function : ~NCollection_UtfString
198 // purpose  :
199 // =======================================================================
200 template<typename Type> inline
201 NCollection_UtfString<Type>::~NCollection_UtfString()
202 {
203   strFree (myString);
204 }
205
206 // =======================================================================
207 // function : operator=
208 // purpose  :
209 // =======================================================================
210 template<typename Type> inline
211 const NCollection_UtfString<Type>& NCollection_UtfString<Type>::operator= (const NCollection_UtfString<Type>& theOther)
212 {
213   if (this == &theOther)
214   {
215     return (*this);
216   }
217
218   strFree (myString);
219   mySize   = theOther.mySize;
220   myLength = theOther.myLength;
221   myString = strAlloc (mySize);
222   strCopy ((Standard_Byte* )myString, (const Standard_Byte* )theOther.myString, mySize);
223   return (*this);
224 }
225
226 // =======================================================================
227 // function : FromUnicode
228 // purpose  :
229 // =======================================================================
230 template<typename Type> template<typename TypeFrom>
231 void NCollection_UtfString<Type>::FromUnicode (const TypeFrom*        theStringUtf,
232                                                const Standard_Integer theLength)
233 {
234   Type* anOldBuffer = myString; // necessary in case of self-copying
235   NCollection_UtfIterator<TypeFrom> anIterRead (theStringUtf);
236   if (*anIterRead == 0)
237   {
238     // special case
239     Clear();
240     return;
241   }
242
243   switch (sizeof(TypeFrom)) // use switch() rather than if() to shut up msvc compiler
244   {
245     case sizeof(Type):
246     {
247       if (theLength > 0)
248       {
249         // optimized copy
250         for(; *anIterRead != 0 && anIterRead.Index() < theLength; ++anIterRead) {}
251
252         mySize   = Standard_Integer((Standard_Byte* )anIterRead.BufferHere() - (Standard_Byte* )theStringUtf);
253         myLength = anIterRead.Index();
254         myString = strAlloc (mySize);
255         strCopy ((Standard_Byte* )myString, (const Standard_Byte* )theStringUtf, mySize);
256         strFree (anOldBuffer);
257         return;
258       }
259     }
260     default: break;
261   }
262
263   strGetAdvance (theStringUtf, theLength, mySize, myLength);
264   myString = strAlloc (mySize);
265   // reset iterator
266   anIterRead.Init (theStringUtf);
267   Type* anIterWrite = myString;
268   for (; *anIterRead != 0 && anIterRead.Index() < myLength; ++anIterRead)
269   {
270     anIterWrite = anIterRead.GetUtf (anIterWrite);
271   }
272   strFree (anOldBuffer);
273 }
274
275 // =======================================================================
276 // function : FromLocale
277 // purpose  :
278 // =======================================================================
279 template<typename Type> inline
280 void NCollection_UtfString<Type>::FromLocale (const char*            theString,
281                                               const Standard_Integer theLength)
282 {
283 #if(defined(_WIN32) || defined(__WIN32__))
284   // use WinAPI
285   int aWideSize = MultiByteToWideChar (CP_ACP, MB_PRECOMPOSED, theString, -1, NULL, 0);
286   if (aWideSize <= 0)
287   {
288     Clear();
289     return;
290   }
291   wchar_t* aWideBuffer = new wchar_t[aWideSize + 1];
292   MultiByteToWideChar (CP_ACP, MB_PRECOMPOSED, theString, -1, aWideBuffer, aWideSize);
293   aWideBuffer[aWideSize] = L'\0';
294   FromUnicode (aWideBuffer, theLength);
295   delete[] aWideBuffer;
296 #else
297   // this is size in bytes but should probably be enough to store string in wide chars
298   // notice that these functions are sensitive to locale set by application!
299   int aMbLen = mblen (theString, MB_CUR_MAX);
300   if (aMbLen <= 0)
301   {
302     Clear();
303     return;
304   }
305   wchar_t* aWideBuffer = new wchar_t[aMbLen + 1];
306   mbstowcs (aWideBuffer, theString, aMbLen);
307   aWideBuffer[aMbLen] = L'\0';
308   FromUnicode (aWideBuffer, theLength);
309   delete[] aWideBuffer;
310 #endif
311 }
312
313 // =======================================================================
314 // function : ToLocale
315 // purpose  :
316 // =======================================================================
317 template<typename Type> inline
318 bool NCollection_UtfString<Type>::ToLocale (char*                  theBuffer,
319                                             const Standard_Integer theSizeBytes) const
320 {
321   NCollection_UtfString<wchar_t> aWideCopy (myString, myLength);
322 #if(defined(_WIN32) || defined(__WIN32__))
323   int aMbBytes = WideCharToMultiByte (CP_ACP, 0, aWideCopy.ToCString(), -1, theBuffer, theSizeBytes, NULL, NULL);
324 #else
325   std::size_t aMbBytes = std::wcstombs (theBuffer, aWideCopy.ToCString(), theSizeBytes);
326 #endif
327   if (aMbBytes <= 0)
328   {
329     *theBuffer = '\0';
330     return false;
331   }
332   return true;
333 }
334
335 // =======================================================================
336 // function : operator=
337 // purpose  :
338 // =======================================================================
339 template<typename Type> inline
340 const NCollection_UtfString<Type>& NCollection_UtfString<Type>::operator= (const char* theStringUtf8)
341 {
342   FromUnicode (theStringUtf8);
343   return (*this);
344 }
345
346 // =======================================================================
347 // function : operator=
348 // purpose  :
349 // =======================================================================
350 template<typename Type> inline
351 const NCollection_UtfString<Type>& NCollection_UtfString<Type>::operator= (const Standard_WideChar* theStringUtfWide)
352 {
353   FromUnicode (theStringUtfWide);
354   return (*this);
355 }
356
357 // =======================================================================
358 // function : IsEqual
359 // purpose  :
360 // =======================================================================
361 template<typename Type> inline
362 bool NCollection_UtfString<Type>::IsEqual (const NCollection_UtfString& theCompare) const
363 {
364   return this == &theCompare
365       || strAreEqual (myString, mySize, theCompare.myString, theCompare.mySize);
366 }
367
368 // =======================================================================
369 // function : operator!=
370 // purpose  :
371 // =======================================================================
372 template<typename Type> inline
373 bool NCollection_UtfString<Type>::operator!= (const NCollection_UtfString& theCompare) const
374 {
375   return (!NCollection_UtfString::operator== (theCompare));
376 }
377
378 // =======================================================================
379 // function : operator+=
380 // purpose  :
381 // =======================================================================
382 template<typename Type> inline
383 NCollection_UtfString<Type>& NCollection_UtfString<Type>::operator+= (const NCollection_UtfString<Type>& theAppend)
384 {
385   if (theAppend.IsEmpty())
386   {
387     return (*this);
388   }
389
390   // create new string
391   Standard_Integer aSize = mySize + theAppend.mySize;
392   Type* aString = strAlloc (aSize);
393   strCopy ((Standard_Byte* )aString,          (const Standard_Byte* )myString,           mySize);
394   strCopy ((Standard_Byte* )aString + mySize, (const Standard_Byte* )theAppend.myString, theAppend.mySize);
395
396   strFree (myString);
397   mySize   = aSize;
398   myString = aString;
399   myLength += theAppend.myLength;
400   return (*this);
401 }
402
403 // =======================================================================
404 // function : SubString
405 // purpose  :
406 // =======================================================================
407 template<typename Type> inline
408 NCollection_UtfString<Type> NCollection_UtfString<Type>::SubString (const Standard_Integer theStart,
409                                                                     const Standard_Integer theEnd) const
410 {
411   if (theStart >= theEnd)
412   {
413     return NCollection_UtfString<Type>();
414   }
415   for (NCollection_UtfIterator<Type> anIter(myString); *anIter != 0; ++anIter)
416   {
417     if (anIter.Index() >= theStart)
418     {
419       return NCollection_UtfString<Type> (anIter.BufferHere(), theEnd - theStart);
420     }
421   }
422   return NCollection_UtfString<Type>();
423 }
424
425 // =======================================================================
426 // function : ToUtf8
427 // purpose  :
428 // =======================================================================
429 template<typename Type> inline
430 const NCollection_UtfString<Standard_Utf8Char> NCollection_UtfString<Type>::ToUtf8() const
431 {
432   NCollection_UtfString<Standard_Utf8Char> aCopy;
433   aCopy.FromUnicode (myString);
434   return aCopy;
435 }
436
437 // =======================================================================
438 // function : ToUtf16
439 // purpose  :
440 // =======================================================================
441 template<typename Type> inline
442 const NCollection_UtfString<Standard_Utf16Char> NCollection_UtfString<Type>::ToUtf16() const
443 {
444   NCollection_UtfString<Standard_Utf16Char> aCopy;
445   aCopy.FromUnicode (myString);
446   return aCopy;
447 }
448
449 // =======================================================================
450 // function : ToUtf32
451 // purpose  :
452 // =======================================================================
453 template<typename Type> inline
454 const NCollection_UtfString<Standard_Utf32Char> NCollection_UtfString<Type>::ToUtf32() const
455 {
456   NCollection_UtfString<Standard_Utf32Char> aCopy;
457   aCopy.FromUnicode (myString);
458   return aCopy;
459 }
460
461 // =======================================================================
462 // function : ToUtfWide
463 // purpose  :
464 // =======================================================================
465 template<typename Type> inline
466 const NCollection_UtfString<Standard_WideChar> NCollection_UtfString<Type>::ToUtfWide() const
467 {
468   NCollection_UtfString<Standard_WideChar> aCopy;
469   aCopy.FromUnicode (myString);
470   return aCopy;
471 }