VR-Link API Documentation for DIS
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
vlUnicodeChar.h
Go to the documentation of this file.
1 /****************************************************************************
2  * Copyright (c) 2014 VT MAK
3  * All rights reserved.
4  ****************************************************************************/
5 
9 
10 #pragma once
11 
12 #include <stdexcept>
13 
17 {
18 public:
19 
20  //A Unicode Code Point, is a unique Unicode Character.
21  typedef unsigned int CodePoint;
22 
23  //A Unicode Surrogate code point, is a 16bit code point, used in UTF-16 encoding.
24  typedef unsigned short Surrogate;
25 
27  typedef unsigned char Octet;
28 
29  // Maximum valid value for a Unicode code point
30  static const CodePoint CodePointMax = 0x0010ffff;
31  static const Surrogate LeadSurrogateMin = 0xd800;
32  static const Surrogate LeadSurrogateMax = 0xdbff;
33  static const Surrogate TrailSurrogateMin = 0xdc00;
34  static const Surrogate TrailSurrogateMax = 0xdfff;
35 
36 public:
37 
38  inline DtUnicodeChar()
39  : myCodePoint( 0 )
40  {
41  }
42 
45  inline explicit DtUnicodeChar( const char c )
46  : myCodePoint( c )
47  {
48  }
49 
53  inline explicit DtUnicodeChar( const wchar_t c )
54  : myCodePoint( c )
55  {
56  }
57 
60  inline explicit DtUnicodeChar( const unsigned short s, const unsigned short c )
62  {
63  if ( ! ( isSurrogate(s) && isSurrogate(c) ) )
64  {
65  throw std::invalid_argument( "UTF-16 characters are not a surrogate pair." );
66  }
67  }
68 
69  inline DtUnicodeChar( const DtUnicodeChar& other )
70  : myCodePoint( other.myCodePoint )
71  {
72  }
73 
74  template <int sizeof_wchar_t>
75  inline static CodePoint widechar( const wchar_t c );
76 
77  inline DtUnicodeChar& operator = ( const DtUnicodeChar& other )
78  {
79  // No need to check for equality.
80  myCodePoint = other.myCodePoint;
81  return *this;
82  }
83 
84  inline bool operator == ( const DtUnicodeChar& other ) const
85  {
86  return myCodePoint == other.myCodePoint;
87  }
88 
89  inline bool operator != ( const DtUnicodeChar& other ) const
90  {
91  return myCodePoint != other.myCodePoint;
92  }
93 
94  static inline bool isCodePointValid( CodePoint codePoint )
95  {
96  return ( codePoint <= CodePointMax && ! isSurrogate((Surrogate)codePoint)
97  && codePoint != 0xfffe && codePoint != 0xffff );
98  }
99 
100  static inline bool isSurrogateSubstringValid( const Surrogate* start,
101  const Surrogate* end, const Surrogate* substringStart,
102  const Surrogate* substringEnd )
103  {
104  // Test to see if beginning in middle of surrogate pair.
105  if ( TrailSurrogateMin == ((*substringStart)&0xfffffc00) && start != substringStart
106  && LeadSurrogateMin == ((*(substringStart - 1))&0xfffffc00) )
107  {
108  return false;
109  }
110 
111  // Test to see if end is middle of pair.
112  if ( (LeadSurrogateMin == ((*(substringEnd - 1 ))&0xfffffc00)) &&
113  substringStart != end && (TrailSurrogateMin == ((*substringEnd)&0xfffffc00)))
114  {
115  return false;
116  }
117 
118  // Not at middle of surrogate pair.
119  return true;
120  }
121 
122  static inline bool isSurrogate( Surrogate cp )
123  {
124  return ( cp >= LeadSurrogateMin && cp <= TrailSurrogateMax );
125  }
126 
128  static inline DtUnicodeChar fromUtf32( unsigned int character )
129  {
130  if ( ! isCodePointValid(character) )
131  {
132  throw std::invalid_argument( "Not a valid UTF 32 code point" );
133  }
134  return DtUnicodeChar( character );
135  }
136 
138  inline unsigned int utf8Length() const
139  {
140  if ( myCodePoint < 0x80 ) // one octet
141  {
142  return 1;
143  }
144  else if ( myCodePoint < 0x800 ) // two octets
145  {
146  return 2;
147  }
148  else if ( myCodePoint < 0x10000 ) // three octets
149  {
150  return 3;
151  }
152  else // four octets
153  {
154  return 4;
155  }
156  }
157 
158  template <int sizeofWChar_t>
159  inline unsigned int wchartLength() const;
160 
161  inline unsigned int wideStringLength() const;
162 
163  inline unsigned int utf16Length() const
164  {
165  return ( (myCodePoint>0xFFFF)? 4 : 2 );
166  }
167 
168  inline unsigned int utf32Length() const
169  {
170  return 4;
171  }
172 
174  {
175  // Get bits 10 - 15 bits from hi, and get bits 0-9 bits from lo.
176  CodePoint X = (hi & 0x3F) << 10 | (lo & 0x3FF);
177  // Get bits 16-21 from hi, and offset.
178  CodePoint U = ((hi >> 6) & (0x1F)) + 1;
179  // Recombine.
180  return (U << 16) | X;
181  }
182 
183  static inline void encodeSurrogatePair( CodePoint cp, Surrogate& hi, Surrogate& lo )
184  {
185  // TAG Top 17-22 bits minus 1,
186  hi = LeadSurrogateMin | ((unsigned short)((cp >> 16) & 0x1F) - 1)
187  // bits 10-16 bits.
188  | (unsigned short)((cp >> 10) & 0x3F);
189  //Has bottom 10 bits + Trail Tag.
190  lo = TrailSurrogateMin | (unsigned short)(cp & 0x3FF);
191  }
192 
193  inline unsigned int utf16CodeUnits() const
194  {
195  return ( (myCodePoint>=0x10000)? 2 : 1 );
196  }
197 
200  inline unsigned int readUtf16( const Surrogate* memory )
201  {
202  if ( isSurrogate(*memory) )
203  {
204  Surrogate hiPair = *memory;
205  Surrogate loPair = *(memory + 1);
206  myCodePoint = decodeSurrogatePair(hiPair,loPair);
207  return 2;
208  }
209  else
210  {
211  myCodePoint = *memory;
212  return 1;
213  }
214  }
215 
216  inline void writeUtf16( Surrogate* memory ) const
217  {
218  if ( myCodePoint >= 0x10000 )
219  {
220  encodeSurrogatePair( myCodePoint, *memory, *(memory+1) );
221  }
222  else
223  {
224  *memory = static_cast<Surrogate>( myCodePoint );
225  }
226  }
227 
228  inline void readUtf32( const unsigned int* memory )
229  {
230  myCodePoint = *memory;
231  }
232 
233  inline void writeUtf32( unsigned int* memory ) const
234  {
235  *memory = myCodePoint;
236  }
237 
239  static inline unsigned int utf8Length( const unsigned char c )
240  {
241  if ( c < 0x80 )
242  {
243  return 1;
244  }
245  else if ( c < 0xE0 )
246  {
247  return 2;
248  }
249  else if ( c < 0xF0 )
250  {
251  return 3;
252  }
253  else if ( c < 0xF8 )
254  {
255  return 4;
256  }
257 
258  throw std::invalid_argument("Not a valid UTF8 string.");
259  }
260 
261  inline unsigned int readUtf8( const unsigned char* memory )
262  {
263  unsigned char c = *memory;
264  if ( c < 0x80 )
265  {
266  myCodePoint = c;
267  return 1;
268  }
269  else if ( c < 0xE0 )
270  {
271  myCodePoint = ((c & 0x1F) << 6) | (*(memory + 1) & 0x3F);
272  return 2;
273  }
274  else if ( c < 0xF0 )
275  {
276  myCodePoint = ((c & 0xF) << 12) | ((*(memory + 1) & 0x3F) << 6)
277  | (*(memory + 2) & 0x3F);
278  return 3;
279  }
280  else if ( c < 0xF8 )
281  {
282  myCodePoint = ((c & 0x7) << 18)
283  | ((*(memory + 1) & 0x3F) << 12)
284  | ((*(memory + 2) & 0x3F) << 6)
285  | (*(memory + 3) & 0x3F);
286  return 4;
287  }
288 
289  throw std::invalid_argument("Not a valid UTF8 string.");
290  }
291 
292  inline void writeUtf8( char* memory ) const
293  {
294  if ( myCodePoint < 0x80 ) // one octet
295  {
296  *memory = (unsigned char)(myCodePoint & 0x7F);
297  }
298  else if ( myCodePoint < 0x800 ) // two octets
299  {
300  *memory = (unsigned char)((myCodePoint >> 6) & 0x1F) | 0xC0;
301  *(memory+1) = (unsigned char)((myCodePoint) & 0x3F) | 0x80;
302 
303  }
304  else if ( myCodePoint < 0x10000 ) // three octets
305  {
306  *memory = (unsigned char)((myCodePoint >> 12) & 0xF ) | 0xE0;
307  *(memory+1) = (unsigned char)((myCodePoint >> 6) & 0x3F) | 0x80;
308  *(memory+2) = (unsigned char)((myCodePoint ) & 0x3F) | 0x80;
309  }
310  else // four octets
311  {
312  *memory = (unsigned char)((myCodePoint >> 18) & 0x7 ) | 0xF0;
313  *(memory+1) = (unsigned char)((myCodePoint >> 12) & 0x3F) | 0x80;
314  *(memory+2) = (unsigned char)((myCodePoint >> 6 ) & 0x3F) | 0x80;
315  *(memory+3) = (unsigned char)((myCodePoint ) & 0x3F) | 0x80;
316  }
317  }
318 
319  template <int sizeofWchart>
320  inline void writeWCharT( wchar_t* memory ) const;
321 
322  inline void writeWChar( wchar_t* memory ) const;
323 
324  inline CodePoint codePoint() const
325  {
326  return myCodePoint;
327  }
328 
329 protected:
330 
331  inline DtUnicodeChar( unsigned int utf32c )
332  : myCodePoint( utf32c )
333  {
334  }
335 
336 private:
337 
339 
340 };
341 
342 
343 template <>
344 inline unsigned int DtUnicodeChar::wchartLength<2>() const
345 {
346  return utf16CodeUnits() << 1;
347 }
348 
349 template <>
350 inline unsigned int DtUnicodeChar::wchartLength<4>() const
351 {
352  return utf32Length();
353 }
354 
355 inline unsigned int DtUnicodeChar::wideStringLength() const
356 {
357  return wchartLength<sizeof(wchar_t)>();
358 }
359 
360 
361 template <int sizeof_wchar_t>
363 {
364  return c;
365 }
366 
367 template <>
368 inline DtUnicodeChar::CodePoint DtUnicodeChar::widechar<2>( const wchar_t c )
369 {
370  if ( isSurrogate(c) )
371  {
372  throw std::invalid_argument( "Invalid UTF-16 character" );
373  }
374  return c;
375 }
376 
377 
378 template <>
379 inline void DtUnicodeChar::writeWCharT<2>( wchar_t* memory ) const
380 {
381  writeUtf16( reinterpret_cast<Surrogate*>(memory) );
382 }
383 
384 template <>
385 inline void DtUnicodeChar::writeWCharT<4>( wchar_t* memory ) const
386 {
387  writeUtf32( reinterpret_cast<unsigned int*>(memory) );
388 }
389 
390 inline void DtUnicodeChar::writeWChar( wchar_t* memory ) const
391 {
392  writeWCharT<sizeof(wchar_t)>( memory );
393 }

Document ID: Generated on Mon Feb 6 18:36:34 EST 2017 from SVN revision 173107
Copyright © 2005-2016 VT MÄK. All Rights Reserved (www.mak.com)