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 : GetChar
18// purpose  :
19// =======================================================================
20template<typename Type>
21Standard_Utf32Char NCollection_UtfString<Type>::GetChar (const Standard_Integer theCharIndex) const
22{
23  //Standard_ASSERT_SKIP (theCharIndex < myLength, "Out of range");
24  NCollection_UtfIterator<Type> anIter (myString);
25  for (; *anIter != 0; ++anIter)
26  {
27    if (anIter.Index() == theCharIndex)
28    {
29      return *anIter;
30    }
31  }
32  return 0;
33}
34
35// =======================================================================
36// function : GetCharBuffer
37// purpose  :
38// =======================================================================
39template<typename Type>
40const Type* NCollection_UtfString<Type>::GetCharBuffer (const Standard_Integer theCharIndex) const
41{
42  //Standard_ASSERT_SKIP(theCharIndex < myLength);
43  NCollection_UtfIterator<Type> anIter (myString);
44  for (; *anIter != 0; ++anIter)
45  {
46    if (anIter.Index() == theCharIndex)
47    {
48      return anIter.BufferHere();
49    }
50  }
51  return NULL;
52}
53
54// =======================================================================
55// function : Clear
56// purpose  :
57// =======================================================================
58template<typename Type> inline
59void NCollection_UtfString<Type>::Clear()
60{
61  strFree (myString);
62  mySize   = 0;
63  myLength = 0;
64  myString = strAlloc (mySize);
65}
66
67// =======================================================================
68// function : NCollection_UtfString
69// purpose  :
70// =======================================================================
71template<typename Type> inline
72NCollection_UtfString<Type>::NCollection_UtfString()
73: myString (strAlloc(0)),
74  mySize   (0),
75  myLength (0)
76{
77  //
78}
79
80// =======================================================================
81// function : NCollection_UtfString
82// purpose  :
83// =======================================================================
84template<typename Type> inline
85NCollection_UtfString<Type>::NCollection_UtfString (const NCollection_UtfString& theCopy)
86: myString (strAlloc (theCopy.mySize)),
87  mySize   (theCopy.mySize),
88  myLength (theCopy.myLength)
89{
90  strCopy ((Standard_Byte* )myString, (const Standard_Byte* )theCopy.myString, mySize);
91}
92
93#ifndef OCCT_NO_RVALUE_REFERENCE
94// =======================================================================
95// function : NCollection_UtfString
96// purpose  :
97// =======================================================================
98template<typename Type> inline
99NCollection_UtfString<Type>::NCollection_UtfString (NCollection_UtfString&& theOther)
100: myString(theOther.myString),
101  mySize  (theOther.mySize),
102  myLength(theOther.myLength)
103{
104  theOther.myString = NULL;
105  theOther.mySize   = 0;
106  theOther.myLength = 0;
107}
108#endif
109
110// =======================================================================
111// function : NCollection_UtfString
112// purpose  :
113// =======================================================================
114template<typename Type> inline
115NCollection_UtfString<Type>::NCollection_UtfString (const char*            theCopyUtf8,
116                                                    const Standard_Integer theLength)
117: myString (NULL),
118  mySize   (0),
119  myLength (0)
120{
121  FromUnicode (theCopyUtf8, theLength);
122}
123
124// =======================================================================
125// function : NCollection_UtfString
126// purpose  :
127// =======================================================================
128template<typename Type> inline
129NCollection_UtfString<Type>::NCollection_UtfString (const Standard_Utf16Char* theCopyUtf16,
130                                                    const Standard_Integer    theLength)
131: myString (NULL),
132  mySize   (0),
133  myLength (0)
134{
135  FromUnicode (theCopyUtf16, theLength);
136}
137
138// =======================================================================
139// function : NCollection_UtfString
140// purpose  :
141// =======================================================================
142template<typename Type> inline
143NCollection_UtfString<Type>::NCollection_UtfString (const Standard_Utf32Char* theCopyUtf32,
144                                                    const Standard_Integer     theLength)
145: myString (NULL),
146  mySize   (0),
147  myLength (0)
148{
149  FromUnicode (theCopyUtf32, theLength);
150}
151
152#if !defined(_MSC_VER) || defined(_NATIVE_WCHAR_T_DEFINED) || (defined(_MSC_VER) && _MSC_VER >= 1900)
153// =======================================================================
154// function : NCollection_UtfString
155// purpose  :
156// =======================================================================
157template<typename Type> inline
158NCollection_UtfString<Type>::NCollection_UtfString (const Standard_WideChar* theCopyUtfWide,
159                                                    const Standard_Integer   theLength)
160: myString (NULL),
161  mySize   (0),
162  myLength (0)
163{
164  FromUnicode (theCopyUtfWide, theLength);
165}
166#endif
167
168// =======================================================================
169// function : ~NCollection_UtfString
170// purpose  :
171// =======================================================================
172template<typename Type> inline
173NCollection_UtfString<Type>::~NCollection_UtfString()
174{
175  strFree (myString);
176}
177
178// =======================================================================
179// function : Assign
180// purpose  :
181// =======================================================================
182template<typename Type> inline
183const NCollection_UtfString<Type>& NCollection_UtfString<Type>::Assign (const NCollection_UtfString<Type>& theOther)
184{
185  if (this == &theOther)
186  {
187    return (*this);
188  }
189
190  strFree (myString);
191  mySize   = theOther.mySize;
192  myLength = theOther.myLength;
193  myString = strAlloc (mySize);
194  strCopy ((Standard_Byte* )myString, (const Standard_Byte* )theOther.myString, mySize);
195  return (*this);
196}
197
198// =======================================================================
199// function : Swap
200// purpose  :
201// =======================================================================
202template<typename Type> inline
203void NCollection_UtfString<Type>::Swap (NCollection_UtfString<Type>& theOther)
204{
205  // Note: we could use std::swap() here, but prefer to not
206  // have dependency on <algorithm> header at that level
207  Type* aString = myString;
208  const Standard_Integer aSize   = mySize;
209  const Standard_Integer aLength = myLength;
210  myString = theOther.myString;
211  mySize   = theOther.mySize;
212  myLength = theOther.myLength;
213  theOther.myString = aString;
214  theOther.mySize   = aSize;
215  theOther.myLength = aLength;
216}
217
218#if !defined(__ANDROID__)
219//! Auxiliary convertion tool.
220class NCollection_UtfStringTool
221{
222public:
223  //! Empty constructor.
224  NCollection_UtfStringTool() : myWideBuffer (NULL) {}
225
226  //! Destructor for temporary resources.
227  Standard_EXPORT ~NCollection_UtfStringTool();
228
229  //! Convert the string from current locale into UNICODE (wide characters) using system APIs.
230  //! Returned pointer will be released by this tool.
231  Standard_EXPORT wchar_t* FromLocale (const char* theString);
232
233  //! Convert the UNICODE (wide characters) string into locale using system APIs.
234  Standard_EXPORT static bool ToLocale (const wchar_t*         theWideString,
235                                        char*                  theBuffer,
236                                        const Standard_Integer theSizeBytes);
237private:
238  wchar_t* myWideBuffer; //!< temporary variable
239};
240#endif
241
242// =======================================================================
243// function : FromLocale
244// purpose  :
245// =======================================================================
246template<typename Type> inline
247void NCollection_UtfString<Type>::FromLocale (const char*            theString,
248                                              const Standard_Integer theLength)
249{
250#if defined(__ANDROID__)
251  // no locales on Android
252  FromUnicode (theString, theLength);
253#else
254  NCollection_UtfStringTool aConvertor;
255  wchar_t* aWideBuffer = aConvertor.FromLocale (theString);
256  if (aWideBuffer == NULL)
257  {
258    Clear();
259    return;
260  }
261  FromUnicode (aWideBuffer, theLength);
262#endif
263}
264
265// =======================================================================
266// function : ToLocale
267// purpose  :
268// =======================================================================
269template<typename Type> inline
270bool NCollection_UtfString<Type>::ToLocale (char*                  theBuffer,
271                                            const Standard_Integer theSizeBytes) const
272{
273#if defined(__ANDROID__)
274  // no locales on Android
275  NCollection_UtfString<Standard_Utf8Char> anUtf8Copy (myString, myLength);
276  const Standard_Integer aSize = anUtf8Copy.Size() + 1;
277  if (theSizeBytes < aSize)
278  {
279    return false;
280  }
281  std::memcpy (theBuffer, anUtf8Copy.ToCString(), (Standard_Size )aSize);
282  return true;
283#else
284  NCollection_UtfString<wchar_t> aWideCopy (myString, myLength);
285  return NCollection_UtfStringTool::ToLocale (aWideCopy.ToCString(), theBuffer, theSizeBytes);
286#endif
287}
288
289// =======================================================================
290// function : operator=
291// purpose  :
292// =======================================================================
293template<typename Type> inline
294const NCollection_UtfString<Type>& NCollection_UtfString<Type>::operator= (const char* theStringUtf8)
295{
296  FromUnicode (theStringUtf8);
297  return (*this);
298}
299
300// =======================================================================
301// function : operator=
302// purpose  :
303// =======================================================================
304template<typename Type> inline
305const NCollection_UtfString<Type>& NCollection_UtfString<Type>::operator= (const Standard_WideChar* theStringUtfWide)
306{
307  FromUnicode (theStringUtfWide);
308  return (*this);
309}
310
311// =======================================================================
312// function : IsEqual
313// purpose  :
314// =======================================================================
315template<typename Type> inline
316bool NCollection_UtfString<Type>::IsEqual (const NCollection_UtfString& theCompare) const
317{
318  return this == &theCompare
319      || strAreEqual (myString, mySize, theCompare.myString, theCompare.mySize);
320}
321
322// =======================================================================
323// function : operator!=
324// purpose  :
325// =======================================================================
326template<typename Type> inline
327bool NCollection_UtfString<Type>::operator!= (const NCollection_UtfString& theCompare) const
328{
329  return (!NCollection_UtfString::operator== (theCompare));
330}
331
332// =======================================================================
333// function : operator+=
334// purpose  :
335// =======================================================================
336template<typename Type> inline
337NCollection_UtfString<Type>& NCollection_UtfString<Type>::operator+= (const NCollection_UtfString<Type>& theAppend)
338{
339  if (theAppend.IsEmpty())
340  {
341    return (*this);
342  }
343
344  // create new string
345  Standard_Integer aSize = mySize + theAppend.mySize;
346  Type* aString = strAlloc (aSize);
347  strCopy ((Standard_Byte* )aString,          (const Standard_Byte* )myString,           mySize);
348  strCopy ((Standard_Byte* )aString + mySize, (const Standard_Byte* )theAppend.myString, theAppend.mySize);
349
350  strFree (myString);
351  mySize   = aSize;
352  myString = aString;
353  myLength += theAppend.myLength;
354  return (*this);
355}
356
357// =======================================================================
358// function : SubString
359// purpose  :
360// =======================================================================
361template<typename Type> inline
362NCollection_UtfString<Type> NCollection_UtfString<Type>::SubString (const Standard_Integer theStart,
363                                                                    const Standard_Integer theEnd) const
364{
365  if (theStart >= theEnd)
366  {
367    return NCollection_UtfString<Type>();
368  }
369  for (NCollection_UtfIterator<Type> anIter(myString); *anIter != 0; ++anIter)
370  {
371    if (anIter.Index() >= theStart)
372    {
373      return NCollection_UtfString<Type> (anIter.BufferHere(), theEnd - theStart);
374    }
375  }
376  return NCollection_UtfString<Type>();
377}
378
379// =======================================================================
380// function : ToUtf8
381// purpose  :
382// =======================================================================
383template<typename Type> inline
384const NCollection_UtfString<Standard_Utf8Char> NCollection_UtfString<Type>::ToUtf8() const
385{
386  NCollection_UtfString<Standard_Utf8Char> aCopy;
387  aCopy.FromUnicode (myString);
388  return aCopy;
389}
390
391// =======================================================================
392// function : ToUtf16
393// purpose  :
394// =======================================================================
395template<typename Type> inline
396const NCollection_UtfString<Standard_Utf16Char> NCollection_UtfString<Type>::ToUtf16() const
397{
398  NCollection_UtfString<Standard_Utf16Char> aCopy;
399  aCopy.FromUnicode (myString);
400  return aCopy;
401}
402
403// =======================================================================
404// function : ToUtf32
405// purpose  :
406// =======================================================================
407template<typename Type> inline
408const NCollection_UtfString<Standard_Utf32Char> NCollection_UtfString<Type>::ToUtf32() const
409{
410  NCollection_UtfString<Standard_Utf32Char> aCopy;
411  aCopy.FromUnicode (myString);
412  return aCopy;
413}
414
415// =======================================================================
416// function : ToUtfWide
417// purpose  :
418// =======================================================================
419template<typename Type> inline
420const NCollection_UtfString<Standard_WideChar> NCollection_UtfString<Type>::ToUtfWide() const
421{
422  NCollection_UtfString<Standard_WideChar> aCopy;
423  aCopy.FromUnicode (myString);
424  return aCopy;
425}
426