VR-Forces 4.0.4 Class Documentation
include/vrvUtil/DtUnicodeChar.h
Go to the documentation of this file.
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 }

Document ID: Generated on Fri Jun 29 16:33:32 EDT 2012 from SVN revision 116588
Copyright © 2005-2012 VT MÄK Inc. All Rights Reserved (www.mak.com)