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