0029151: GCC 7.1 warnings "this statement may fall through" [-Wimplicit-fallthrough=]
[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 #if !defined(_MSC_VER) || defined(_NATIVE_WCHAR_T_DEFINED) || (defined(_MSC_VER) && _MSC_VER >= 1900)
183 // =======================================================================
184 // function : NCollection_UtfString
185 // purpose  :
186 // =======================================================================
187 template<typename Type> inline
188 NCollection_UtfString<Type>::NCollection_UtfString (const Standard_WideChar* theCopyUtfWide,
189                                                     const Standard_Integer   theLength)
190 : myString (NULL),
191   mySize   (0),
192   myLength (0)
193 {
194   FromUnicode (theCopyUtfWide, theLength);
195 }
196 #endif
197
198 // =======================================================================
199 // function : ~NCollection_UtfString
200 // purpose  :
201 // =======================================================================
202 template<typename Type> inline
203 NCollection_UtfString<Type>::~NCollection_UtfString()
204 {
205   strFree (myString);
206 }
207
208 // =======================================================================
209 // function : operator=
210 // purpose  :
211 // =======================================================================
212 template<typename Type> inline
213 const NCollection_UtfString<Type>& NCollection_UtfString<Type>::operator= (const NCollection_UtfString<Type>& theOther)
214 {
215   if (this == &theOther)
216   {
217     return (*this);
218   }
219
220   strFree (myString);
221   mySize   = theOther.mySize;
222   myLength = theOther.myLength;
223   myString = strAlloc (mySize);
224   strCopy ((Standard_Byte* )myString, (const Standard_Byte* )theOther.myString, mySize);
225   return (*this);
226 }
227
228 // =======================================================================
229 // function : FromUnicode
230 // purpose  :
231 // =======================================================================
232 template<typename Type> template<typename TypeFrom>
233 void NCollection_UtfString<Type>::FromUnicode (const TypeFrom*        theStringUtf,
234                                                const Standard_Integer theLength)
235 {
236   Type* anOldBuffer = myString; // necessary in case of self-copying
237   NCollection_UtfIterator<TypeFrom> anIterRead (theStringUtf);
238   if (*anIterRead == 0)
239   {
240     // special case
241     Clear();
242     return;
243   }
244
245   switch (sizeof(TypeFrom)) // use switch() rather than if() to shut up msvc compiler
246   {
247     case sizeof(Type):
248     {
249       if (theLength > 0)
250       {
251         // optimized copy
252         for(; *anIterRead != 0 && anIterRead.Index() < theLength; ++anIterRead) {}
253
254         mySize   = Standard_Integer((Standard_Byte* )anIterRead.BufferHere() - (Standard_Byte* )theStringUtf);
255         myLength = anIterRead.Index();
256         myString = strAlloc (mySize);
257         strCopy ((Standard_Byte* )myString, (const Standard_Byte* )theStringUtf, mySize);
258         strFree (anOldBuffer);
259         return;
260       }
261     }
262     default: break;
263   }
264
265   strGetAdvance (theStringUtf, theLength, mySize, myLength);
266   myString = strAlloc (mySize);
267   // reset iterator
268   anIterRead.Init (theStringUtf);
269   Type* anIterWrite = myString;
270   for (; *anIterRead != 0 && anIterRead.Index() < myLength; ++anIterRead)
271   {
272     anIterWrite = anIterRead.GetUtf (anIterWrite);
273   }
274   strFree (anOldBuffer);
275 }
276
277 #if !defined(__ANDROID__)
278 //! Auxiliary convertion tool.
279 class NCollection_UtfStringTool
280 {
281 public:
282   //! Empty constructor.
283   NCollection_UtfStringTool() : myWideBuffer (NULL) {}
284
285   //! Destructor for temporary resources.
286   Standard_EXPORT ~NCollection_UtfStringTool();
287
288   //! Convert the string from current locale into UNICODE (wide characters) using system APIs.
289   //! Returned pointer will be released by this tool.
290   Standard_EXPORT wchar_t* FromLocale (const char* theString);
291
292   //! Convert the UNICODE (wide characters) string into locale using system APIs.
293   Standard_EXPORT static bool ToLocale (const wchar_t*         theWideString,
294                                         char*                  theBuffer,
295                                         const Standard_Integer theSizeBytes);
296 private:
297   wchar_t* myWideBuffer; //!< temporary variable
298 };
299 #endif
300
301 // =======================================================================
302 // function : FromLocale
303 // purpose  :
304 // =======================================================================
305 template<typename Type> inline
306 void NCollection_UtfString<Type>::FromLocale (const char*            theString,
307                                               const Standard_Integer theLength)
308 {
309 #if defined(__ANDROID__)
310   // no locales on Android
311   FromUnicode (theString, theLength);
312 #else
313   NCollection_UtfStringTool aConvertor;
314   wchar_t* aWideBuffer = aConvertor.FromLocale (theString);
315   if (aWideBuffer == NULL)
316   {
317     Clear();
318     return;
319   }
320   FromUnicode (aWideBuffer, theLength);
321 #endif
322 }
323
324 // =======================================================================
325 // function : ToLocale
326 // purpose  :
327 // =======================================================================
328 template<typename Type> inline
329 bool NCollection_UtfString<Type>::ToLocale (char*                  theBuffer,
330                                             const Standard_Integer theSizeBytes) const
331 {
332 #if defined(__ANDROID__)
333   // no locales on Android
334   NCollection_UtfString<Standard_Utf8Char> anUtf8Copy (myString, myLength);
335   const Standard_Integer aSize = anUtf8Copy.Size() + 1;
336   if (theSizeBytes < aSize)
337   {
338     return false;
339   }
340   std::memcpy (theBuffer, anUtf8Copy.ToCString(), (Standard_Size )aSize);
341   return true;
342 #else
343   NCollection_UtfString<wchar_t> aWideCopy (myString, myLength);
344   return NCollection_UtfStringTool::ToLocale (aWideCopy.ToCString(), theBuffer, theSizeBytes);
345 #endif
346 }
347
348 // =======================================================================
349 // function : operator=
350 // purpose  :
351 // =======================================================================
352 template<typename Type> inline
353 const NCollection_UtfString<Type>& NCollection_UtfString<Type>::operator= (const char* theStringUtf8)
354 {
355   FromUnicode (theStringUtf8);
356   return (*this);
357 }
358
359 // =======================================================================
360 // function : operator=
361 // purpose  :
362 // =======================================================================
363 template<typename Type> inline
364 const NCollection_UtfString<Type>& NCollection_UtfString<Type>::operator= (const Standard_WideChar* theStringUtfWide)
365 {
366   FromUnicode (theStringUtfWide);
367   return (*this);
368 }
369
370 // =======================================================================
371 // function : IsEqual
372 // purpose  :
373 // =======================================================================
374 template<typename Type> inline
375 bool NCollection_UtfString<Type>::IsEqual (const NCollection_UtfString& theCompare) const
376 {
377   return this == &theCompare
378       || strAreEqual (myString, mySize, theCompare.myString, theCompare.mySize);
379 }
380
381 // =======================================================================
382 // function : operator!=
383 // purpose  :
384 // =======================================================================
385 template<typename Type> inline
386 bool NCollection_UtfString<Type>::operator!= (const NCollection_UtfString& theCompare) const
387 {
388   return (!NCollection_UtfString::operator== (theCompare));
389 }
390
391 // =======================================================================
392 // function : operator+=
393 // purpose  :
394 // =======================================================================
395 template<typename Type> inline
396 NCollection_UtfString<Type>& NCollection_UtfString<Type>::operator+= (const NCollection_UtfString<Type>& theAppend)
397 {
398   if (theAppend.IsEmpty())
399   {
400     return (*this);
401   }
402
403   // create new string
404   Standard_Integer aSize = mySize + theAppend.mySize;
405   Type* aString = strAlloc (aSize);
406   strCopy ((Standard_Byte* )aString,          (const Standard_Byte* )myString,           mySize);
407   strCopy ((Standard_Byte* )aString + mySize, (const Standard_Byte* )theAppend.myString, theAppend.mySize);
408
409   strFree (myString);
410   mySize   = aSize;
411   myString = aString;
412   myLength += theAppend.myLength;
413   return (*this);
414 }
415
416 // =======================================================================
417 // function : SubString
418 // purpose  :
419 // =======================================================================
420 template<typename Type> inline
421 NCollection_UtfString<Type> NCollection_UtfString<Type>::SubString (const Standard_Integer theStart,
422                                                                     const Standard_Integer theEnd) const
423 {
424   if (theStart >= theEnd)
425   {
426     return NCollection_UtfString<Type>();
427   }
428   for (NCollection_UtfIterator<Type> anIter(myString); *anIter != 0; ++anIter)
429   {
430     if (anIter.Index() >= theStart)
431     {
432       return NCollection_UtfString<Type> (anIter.BufferHere(), theEnd - theStart);
433     }
434   }
435   return NCollection_UtfString<Type>();
436 }
437
438 // =======================================================================
439 // function : ToUtf8
440 // purpose  :
441 // =======================================================================
442 template<typename Type> inline
443 const NCollection_UtfString<Standard_Utf8Char> NCollection_UtfString<Type>::ToUtf8() const
444 {
445   NCollection_UtfString<Standard_Utf8Char> aCopy;
446   aCopy.FromUnicode (myString);
447   return aCopy;
448 }
449
450 // =======================================================================
451 // function : ToUtf16
452 // purpose  :
453 // =======================================================================
454 template<typename Type> inline
455 const NCollection_UtfString<Standard_Utf16Char> NCollection_UtfString<Type>::ToUtf16() const
456 {
457   NCollection_UtfString<Standard_Utf16Char> aCopy;
458   aCopy.FromUnicode (myString);
459   return aCopy;
460 }
461
462 // =======================================================================
463 // function : ToUtf32
464 // purpose  :
465 // =======================================================================
466 template<typename Type> inline
467 const NCollection_UtfString<Standard_Utf32Char> NCollection_UtfString<Type>::ToUtf32() const
468 {
469   NCollection_UtfString<Standard_Utf32Char> aCopy;
470   aCopy.FromUnicode (myString);
471   return aCopy;
472 }
473
474 // =======================================================================
475 // function : ToUtfWide
476 // purpose  :
477 // =======================================================================
478 template<typename Type> inline
479 const NCollection_UtfString<Standard_WideChar> NCollection_UtfString<Type>::ToUtfWide() const
480 {
481   NCollection_UtfString<Standard_WideChar> aCopy;
482   aCopy.FromUnicode (myString);
483   return aCopy;
484 }