![]() |
VR-Forces 4.0.4 Class Documentation
|
00001 /****************************************************************************** 00002 ** Copyright (c) 2010 MAK Technologies, Inc. 00003 ** All rights reserved. 00004 ******************************************************************************/ 00005 /********************************************************************* 00006 ** $RCSfile: DtUnicodeChar.h,v $ $Revision: $ $State: $ 00007 *********************************************************************/ 00008 00011 00012 #pragma once 00013 00014 #include <stdexcept> 00015 00016 namespace makVrv 00017 { 00019 class DtUnicodeChar 00020 { 00021 public: 00022 00023 //A Unicode Code Point, is a unique Unicode Character. 00024 typedef unsigned int CodePoint; 00025 00026 //A Unicode Surrogate code point, is a 16bit code point, used in UTF-16 encoding. 00027 typedef unsigned short Surrogate; 00028 00030 typedef unsigned char Octet; 00031 00032 inline DtUnicodeChar() 00033 : myCodePoint(0) 00034 { 00035 } 00036 00039 inline explicit DtUnicodeChar(const char c) 00040 : myCodePoint(c) 00041 { 00042 } 00043 00044 00048 inline explicit DtUnicodeChar(const wchar_t c) 00049 : myCodePoint(c) 00050 { 00051 } 00052 00055 inline explicit DtUnicodeChar(const unsigned short s,const unsigned short c) 00056 : myCodePoint( decodeSurrogatePair(s,c) ) 00057 { 00058 if(!(isSurrogate(s) && isSurrogate(c))) 00059 { 00060 throw std::invalid_argument("UTF-16 characters are not a surrogate pair."); 00061 } 00062 } 00063 00064 inline DtUnicodeChar(const DtUnicodeChar& other) 00065 : myCodePoint(other.myCodePoint) 00066 { 00067 } 00068 00069 template <int sizeof_wchar_t> 00070 inline static CodePoint widechar(const wchar_t c); 00071 00072 inline DtUnicodeChar& operator=(const DtUnicodeChar& other) 00073 { 00074 //No need to check for equality. 00075 myCodePoint = other.myCodePoint; 00076 return *this; 00077 } 00078 00079 inline bool operator==(const DtUnicodeChar& other) const 00080 { 00081 return myCodePoint == other.myCodePoint; 00082 } 00083 00084 inline bool operator!=(const DtUnicodeChar& other) const 00085 { 00086 return myCodePoint != other.myCodePoint; 00087 } 00088 00089 // Maximum valid value for a Unicode code point 00090 static const CodePoint CodePointMax = 0x0010ffff; 00091 static const Surrogate LeadSurrogateMin = 0xd800; 00092 static const Surrogate LeadSurrogateMax = 0xdbff; 00093 static const Surrogate TrailSurrogateMin = 0xdc00; 00094 static const Surrogate TrailSurrogateMax = 0xdfff; 00095 00096 static inline bool isCodePointValid(CodePoint codePoint) 00097 { 00098 return (codePoint <= CodePointMax && !isSurrogate((Surrogate)codePoint) && 00099 codePoint != 0xfffe && codePoint != 0xffff); 00100 } 00101 00102 static inline bool isSurrogateSubstringValid(const Surrogate* start, 00103 const Surrogate* end, const Surrogate* substringStart, 00104 const Surrogate* substringEnd) 00105 { 00106 // Test to see if beginning in middle of surrogate pair. 00107 if(TrailSurrogateMin == ((*substringStart)&0xfffffc00) && 00108 start != substringStart && 00109 LeadSurrogateMin == ((*(substringStart - 1))&0xfffffc00)) 00110 { 00111 00112 return false; 00113 } 00114 00115 //Test to see if end is middle of pair. 00116 if((LeadSurrogateMin == ((*(substringEnd - 1 ))&0xfffffc00)) && 00117 substringStart != end && 00118 (TrailSurrogateMin == ((*substringEnd)&0xfffffc00))) 00119 { 00120 return false; 00121 } 00122 00123 //Not at middle of surrogate pair. 00124 return true; 00125 } 00126 00127 00128 static inline bool isSurrogate(Surrogate cp) 00129 { 00130 return (cp >= LeadSurrogateMin && cp <= TrailSurrogateMax); 00131 } 00132 00134 static inline DtUnicodeChar fromUtf32(unsigned int character) 00135 { 00136 if(!isCodePointValid(character)) throw std::invalid_argument("Not a valid UTF 32 code point"); 00137 return DtUnicodeChar(character); 00138 } 00139 00141 inline unsigned int utf8Length() const 00142 { 00143 if (myCodePoint < 0x80) // one octet 00144 { 00145 return 1; 00146 } 00147 else if (myCodePoint < 0x800) // two octets 00148 { 00149 return 2; 00150 } 00151 else if (myCodePoint < 0x10000) // three octets 00152 { 00153 return 3; 00154 } 00155 else // four octets 00156 { 00157 return 4; 00158 } 00159 } 00160 00161 template <int sizeofWChar_t> 00162 inline unsigned int wchartLength() const; 00163 00164 inline unsigned int wideStringLength() const; 00165 00166 inline unsigned int utf16Length() const 00167 { 00168 if(myCodePoint > 0xFFFF) return 4; else return 2; 00169 } 00170 00171 inline unsigned int utf32Length() const 00172 { 00173 return 4; 00174 } 00175 00176 static inline CodePoint decodeSurrogatePair(Surrogate hi,Surrogate lo) 00177 { 00178 //Get bits 10 - 15 bits from hi, and get bits 0-9 bits from lo 00179 CodePoint X = (hi & 0x3F) << 10 | (lo & 0x3FF); 00180 //Get bits 16-21 from hi, and offset. 00181 CodePoint U = ((hi >> 6) & (0x1F)) + 1; 00182 //Recombine. 00183 return (U << 16) | X; 00184 } 00185 00186 static inline void encodeSurrogatePair(CodePoint cp, Surrogate& hi,Surrogate& lo) 00187 { 00188 // TAG Top 17-22 bits minus 1, 00189 hi = LeadSurrogateMin | ((unsigned short)((cp >> 16) & 0x1F) - 1) 00190 // bits 10-16 bits. 00191 | (unsigned short)((cp >> 10) & 0x3F); 00192 //Has bottom 10 bits + Trail Tag. 00193 lo = TrailSurrogateMin | (unsigned short)(cp & 0x3FF); 00194 } 00195 00196 inline unsigned int utf16CodeUnits() const 00197 { 00198 if(myCodePoint >= 0x10000) 00199 { 00200 return 2; 00201 } 00202 else 00203 { 00204 return 1; 00205 } 00206 } 00207 00210 inline unsigned int readUtf16(const Surrogate* memory) 00211 { 00212 if(isSurrogate(*memory)) 00213 { 00214 Surrogate hiPair = *memory; 00215 Surrogate loPair = *(memory + 1); 00216 myCodePoint = decodeSurrogatePair(hiPair,loPair); 00217 return 2; 00218 } 00219 else 00220 { 00221 myCodePoint = *memory; 00222 return 1; 00223 } 00224 } 00225 00226 inline void writeUtf16(Surrogate* memory) const 00227 { 00228 if(myCodePoint >= 0x10000) 00229 { 00230 encodeSurrogatePair(myCodePoint,*memory,*(memory + 1)); 00231 } 00232 else 00233 { 00234 *memory = static_cast<Surrogate>(myCodePoint); 00235 } 00236 } 00237 00238 inline void readUtf32(const unsigned int* memory) 00239 { 00240 myCodePoint = *memory; 00241 } 00242 00243 inline void writeUtf32(unsigned int* memory) const 00244 { 00245 *memory = myCodePoint; 00246 } 00247 00249 static inline unsigned int utf8Length(const unsigned char c) 00250 { 00251 if(c < 0x80) 00252 { 00253 return 1; 00254 } 00255 else if(c < 0xE0) 00256 { 00257 return 2; 00258 } 00259 else if(c < 0xF0) 00260 { 00261 return 3; 00262 } 00263 else if(c < 0xF8) 00264 { 00265 return 4; 00266 } 00267 else 00268 { 00269 throw std::invalid_argument("Not a valid UTF8 string."); 00270 } 00271 } 00272 00273 inline unsigned int readUtf8(const unsigned char* memory) 00274 { 00275 unsigned char c = *memory; 00276 if(c < 0x80) 00277 { 00278 myCodePoint = c; 00279 return 1; 00280 } 00281 else if(c < 0xE0) 00282 { 00283 myCodePoint = ((c & 0x1F) << 6) | 00284 (*(memory + 1) & 0x3F); 00285 return 2; 00286 } 00287 else if(c < 0xF0) 00288 { 00289 myCodePoint = ((c & 0xF) << 12) | 00290 ((*(memory + 1) & 0x3F) << 6) | 00291 (*(memory + 2) & 0x3F); 00292 return 3; 00293 } 00294 else if(c < 0xF8) 00295 { 00296 myCodePoint = ((c & 0x7) << 18) | 00297 ((*(memory + 1) & 0x3F) << 12) | 00298 ((*(memory + 2) & 0x3F) << 6) | 00299 (*(memory + 3) & 0x3F); 00300 return 4; 00301 } 00302 else 00303 { 00304 throw std::invalid_argument("Not a valid UTF8 string."); 00305 } 00306 } 00307 00308 inline void writeUtf8(char* memory) const 00309 { 00310 if (myCodePoint < 0x80) // one octet 00311 { 00312 *memory = (unsigned char)(myCodePoint & 0x7F); 00313 } 00314 else if (myCodePoint < 0x800) // two octets 00315 { 00316 *memory = (unsigned char)((myCodePoint >> 6) & 0x1F) | 0xC0; 00317 *(memory+1) = (unsigned char)((myCodePoint ) & 0x3F) | 0x80; 00318 00319 } 00320 else if (myCodePoint < 0x10000) // three octets 00321 { 00322 *memory = (unsigned char)((myCodePoint >> 12) & 0xF ) | 0xE0; 00323 *(memory+1) = (unsigned char)((myCodePoint >> 6) & 0x3F) | 0x80; 00324 *(memory+2) = (unsigned char)((myCodePoint ) & 0x3F) | 0x80; 00325 } 00326 else // four octets 00327 { 00328 *memory = (unsigned char)((myCodePoint >> 18) & 0x7 ) | 0xF0; 00329 *(memory+1) = (unsigned char)((myCodePoint >> 12) & 0x3F) | 0x80; 00330 *(memory+2) = (unsigned char)((myCodePoint >> 6 ) & 0x3F) | 0x80; 00331 *(memory+3) = (unsigned char)((myCodePoint ) & 0x3F) | 0x80; 00332 } 00333 } 00334 00335 template <int sizeofWchart> 00336 inline void writeWCharT(wchar_t* memory) const; 00337 00338 00339 inline void writeWChar(wchar_t* memory) const; 00340 00341 inline CodePoint codePoint() const 00342 { 00343 return myCodePoint; 00344 } 00345 00346 protected: 00347 00348 inline DtUnicodeChar(unsigned int utf32c) 00349 : myCodePoint(utf32c) 00350 { 00351 } 00352 00353 private: 00354 CodePoint myCodePoint; 00355 }; 00356 00357 template <> 00358 inline unsigned int DtUnicodeChar::wchartLength<2>() const 00359 { 00360 return utf16CodeUnits() << 1; 00361 } 00362 00363 template <> 00364 inline unsigned int DtUnicodeChar::wchartLength<4>() const 00365 { 00366 return utf32Length(); 00367 } 00368 00369 00370 00371 template <int sizeof_wchar_t> 00372 inline DtUnicodeChar::CodePoint DtUnicodeChar::widechar(const wchar_t c) 00373 { 00374 return c; 00375 } 00376 00377 template <> 00378 inline DtUnicodeChar::CodePoint DtUnicodeChar::widechar<2>(const wchar_t c) 00379 { 00380 if(isSurrogate(c)) 00381 { 00382 throw std::invalid_argument("Invalid UTF-16 character"); 00383 } 00384 return c; 00385 } 00386 00387 template <> 00388 inline void DtUnicodeChar::writeWCharT<2>(wchar_t* memory) const 00389 { 00390 writeUtf16(reinterpret_cast<Surrogate*>(memory)); 00391 } 00392 00393 template <> 00394 inline void DtUnicodeChar::writeWCharT<4>(wchar_t* memory) const 00395 { 00396 writeUtf32(reinterpret_cast<unsigned int*>(memory)); 00397 } 00398 00399 inline unsigned int DtUnicodeChar::wideStringLength() const 00400 { 00401 return wchartLength<sizeof(wchar_t)>(); 00402 } 00403 00404 inline void DtUnicodeChar::writeWChar(wchar_t* memory) const 00405 { 00406 writeWCharT<sizeof(wchar_t)>(memory); 00407 } 00408 }