| ## Public API Reference

- Main Page
- Modules
- Namespaces
- Classes
- Files
- Related Pages

- File List
- File Members

# csutil/csuctransform.h

Go to the documentation of this file.

    00001 /*
    00002     Copyright (C) 2003 by Frank Richter
    00003
    00004     This library is free software; you can redistribute it and/or
    00005     modify it under the terms of the GNU Library General Public
    00006     License as published by the Free Software Foundation; either
    00007     version 2 of the License, or (at your option) any later version.
    00008
    00009     This library is distributed in the hope that it will be useful,
    00010     but WITHOUT ANY WARRANTY; without even the implied warranty of
    00011     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    00012     Library General Public License for more details.
    00013
    00014     You should have received a copy of the GNU Library General Public
    00015     License along with this library; if not, write to the Free
    00016     Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
    00017 */
    00018
    00019 #ifndef __CS_CSUCTRANSFORM_H__
    00020 #define __CS_CSUCTRANSFORM_H__
    00021
    00022 #include "csunicode.h"
    00023
    00035 #define CS_UC_MAX_UTF8_ENCODED          4  /* 6 to encode 32 bit */
    00036
    00040 #define CS_UC_MAX_UTF16_ENCODED         2
    00041
    00045 #define CS_UC_MAX_UTF32_ENCODED         1
    00046 #if (CS_WCHAR_T_SIZE == 1)
    00047 #define CS_UC_MAX_WCHAR_T_ENCODED       CS_UC_MAX_UTF8_ENCODED
    00048 #elif (CS_WCHAR_T_SIZE == 2)
    00049
    00053 #define CS_UC_MAX_WCHAR_T_ENCODED       CS_UC_MAX_UTF16_ENCODED
    00054 #else
    00055 #define CS_UC_MAX_WCHAR_T_ENCODED       CS_UC_MAX_UTF32_ENCODED
    00056 #endif
    00057
    00061 #define CS_UC_MAX_MAPPED                3
    00062
    00066 enum
    00067 {
    00073   csUcMapSimple = (1 << 0)
    00074 };
    00075
    00079 class CS_CRYSTALSPACE_EXPORT csUnicodeTransform
    00080 {
    00081 public:
    00082 #define FAIL(ret)                               \
    00083   {                                             \
    00084     if (isValid) *isValid = false;              \
    00085     ch = CS_UC_CHAR_REPLACER;                   \
    00086     return ret;                                 \
    00087   }
    00088
    00089 #define SUCCEED                                 \
    00090     if (isValid) *isValid = true;               \
    00091     return chUsed;
    00092
    00093 #define GET_NEXT(next)  \
    00094   if ((size_t)chUsed == strlen)                 \
    00095   {                                             \
    00096     FAIL(chUsed);                               \
    00097   }                                             \
    00098   next = *str++;                                \
    00099   if (next == 0)                                \
    00100   {                                             \
    00101     FAIL(chUsed);                               \
    00102   }                                             \
    00103   chUsed++;
    00104
    00123   inline static int UTF8Decode (const utf8_char* str, size_t strlen,
    00124     utf32_char& ch, bool* isValid = 0, bool returnNonChar = false)
    00125   {
    00126     if (str == 0)
    00127     {
    00128       FAIL(0);
    00129     }
    00130     int chUsed = 0;
    00131
    00132     utf8_char curCh;
    00133     GET_NEXT(curCh);
    00134     if ((curCh & 0x80) == 0)
    00135     {
    00136       // easy case
    00137       ch = curCh;
    00138       SUCCEED;
    00139     }
    00140     else
    00141     {
    00142       // Count with how many bytes this char is encoded.
    00143       int n = 0;
    00144       while ((n < 7) && ((curCh & (1 << (7 - n))) != 0)) { n++; }
    00145
    00146       if ((n < 2) || (n > 6))
    00147       {
    00148         // Invalid code: first char of a "sequence" must have
    00149         // at least two and at most six MSBs set
    00150         FAIL(1);
    00151       }
    00152
    00153       ch = (curCh & ((1 << (8 - n)) - 1));
    00154
    00155       for (int i = 1; i < n; i++)
    00156       {
    00157         GET_NEXT(curCh);
    00158         if ((curCh & 0xc0) != 0x80)
    00159         {
    00160           FAIL(chUsed);
    00161         }
    00162         else
    00163         {
    00164           ch <<= 6;
    00165           ch |= (curCh & 0x3f);
    00166         }
    00167       }
    00168
    00169       // Check if in Unicode range.
    00170       if (ch > CS_UC_LAST_CHAR)
    00171       {
    00172         FAIL(chUsed);
    00173       }
    00174
    00175       // Check for "overlong" codes.
    00176       if ((ch < 0x80) && (n > 0))
    00177       {
    00178         FAIL(chUsed);
    00179       }
    00180       else if ((ch < 0x800) && (n > 2))
    00181       {
    00182         FAIL(chUsed);
    00183       }
    00184       else if ((ch < 0x10000) && (n > 3))
    00185       {
    00186         FAIL(chUsed);
    00187       }
    00188       else if ((ch < 0x200000) && (n > 4))
    00189       {
    00190         FAIL(chUsed);
    00191       }
    00192       /*
    00193       else if ((ch < 0x4000000) && (n > 5))
    00194       {
    00195         FAIL(chUsed);
    00196       }
    00197       else if ((ch < 0x80000000) && (n > 6))
    00198       {
    00199         FAIL(chUsed);
    00200       }
    00201       */
    00202
    00203       if (!returnNonChar && (CS_UC_IS_NONCHARACTER(ch)
    00204         || CS_UC_IS_SURROGATE(ch)))
    00205         FAIL(chUsed);
    00206       SUCCEED;
    00207     }
    00208   }
    00209
    00214   inline static int UTF16Decode (const utf16_char* str, size_t strlen,
    00215     utf32_char& ch, bool* isValid = 0, bool returnNonChar = false)
    00216   {
    00217     if (str == 0)
    00218     {
    00219       FAIL(0);
    00220     }
    00221     int chUsed = 0;
    00222
    00223     utf16_char curCh;
    00224     GET_NEXT(curCh);
    00225     // Decode surrogate
    00226     if (CS_UC_IS_SURROGATE (curCh))
    00227     {
    00228       // Invalid code
    00229       if (!CS_UC_IS_HIGH_SURROGATE (curCh))
    00230       {
    00231         FAIL(chUsed);
    00232       }
    00233       ch = 0x10000 + ((curCh & 0x03ff) << 10);
    00234       GET_NEXT(curCh);
    00235       // Invalid code
    00236       if (!CS_UC_IS_LOW_SURROGATE (curCh))
    00237       {
    00238         // Fail with 1 so the char is handled upon the next Decode.
    00239         FAIL(1);
    00240       }
    00241       ch |= (curCh & 0x3ff);
    00242     }
    00243     else
    00244     {
    00245       ch = curCh;
    00246     }
    00247     if (!returnNonChar && (CS_UC_IS_NONCHARACTER(ch)
    00248       || CS_UC_IS_SURROGATE(ch)))
    00249       FAIL(chUsed);
    00250     SUCCEED;
    00251   }
    00252
    00257   inline static int UTF32Decode (const utf32_char* str, size_t strlen,
    00258     utf32_char& ch, bool* isValid = 0, bool returnNonChar = false)
    00259   {
    00260     if (str == 0)
    00261     {
    00262       FAIL(0);
    00263     }
    00264     int chUsed = 0;
    00265
    00266     GET_NEXT(ch);
    00267     if ((!returnNonChar && (CS_UC_IS_NONCHARACTER(ch)
    00268       || CS_UC_IS_SURROGATE(ch))) || (ch > CS_UC_LAST_CHAR))
    00269       FAIL(chUsed);
    00270     SUCCEED;
    00271   }
    00272
    00277   inline static int Decode (const utf8_char* str, size_t strlen,
    00278     utf32_char& ch, bool* isValid = 0, bool returnNonChar = false)
    00279   {
    00280     return UTF8Decode (str, strlen, ch, isValid, returnNonChar);
    00281   }
    00286   inline static int Decode (const utf16_char* str, size_t strlen,
    00287     utf32_char& ch, bool* isValid = 0, bool returnNonChar = false)
    00288   {
    00289     return UTF16Decode (str, strlen, ch, isValid, returnNonChar);
    00290   }
    00295   inline static int Decode (const utf32_char* str, size_t strlen,
    00296     utf32_char& ch, bool* isValid = 0, bool returnNonChar = false)
    00297   {
    00298     return UTF32Decode (str, strlen, ch, isValid, returnNonChar);
    00299   }
    00300
    00302 #undef FAIL
    00303 #undef SUCCEED
    00304 #undef GET_NEXT
    00305
    00308 #define _OUTPUT_CHAR(buf, chr)                          \
    00309   if (bufRemaining > 0)                                 \
    00310   {                                                     \
    00311     if(buf) *buf++ = chr;                               \
    00312     bufRemaining--;                                     \
    00313   }                                                     \
    00314   encodedLen++;
    00315
    00316 #define OUTPUT_CHAR(chr) _OUTPUT_CHAR(buf, chr)
    00317
    00331   inline static int EncodeUTF8 (const utf32_char ch, utf8_char* buf,
    00332     size_t bufsize, bool allowNonchars = false)
    00333   {
    00334     if ((!allowNonchars && ((CS_UC_IS_NONCHARACTER(ch))
    00335       || (CS_UC_IS_SURROGATE(ch)))) || (ch > CS_UC_LAST_CHAR))
    00336       return 0;
    00337     size_t bufRemaining = bufsize;
    00338     int encodedLen = 0;
    00339
    00340     if (ch < 0x80)
    00341     {
    00342       OUTPUT_CHAR ((utf8_char)ch);
    00343     }
    00344     else if (ch < 0x800)
    00345     {
    00346       OUTPUT_CHAR ((utf8_char)(0xc0 | (ch >> 6)));
    00347       OUTPUT_CHAR ((utf8_char)(0x80 | (ch & 0x3f)));
    00348     }
    00349     else if (ch < 0x10000)
    00350     {
    00351       OUTPUT_CHAR ((utf8_char)(0xe0 | (ch >> 12)));
    00352       OUTPUT_CHAR ((utf8_char)(0x80 | ((ch >> 6) & 0x3f)));
    00353       OUTPUT_CHAR ((utf8_char)(0x80 | (ch & 0x3f)));
    00354     }
    00355     else if (ch < 0x200000)
    00356     {
    00357       OUTPUT_CHAR ((utf8_char)(0xf0 | (ch >> 18)));
    00358       OUTPUT_CHAR ((utf8_char)(0x80 | ((ch >> 12) & 0x3f)));
    00359       OUTPUT_CHAR ((utf8_char)(0x80 | ((ch >> 6) & 0x3f)));
    00360       OUTPUT_CHAR ((utf8_char)(0x80 | (ch & 0x3f)));
    00361     }
    00362     /*
    00363     else if (ch < 0x4000000)
    00364     {
    00365       OUTPUT_CHAR ((utf8_char)(0xf8 | (ch >> 24)));
    00366       OUTPUT_CHAR ((utf8_char)(0x80 | ((ch >> 18) & 0x3f)));
    00367       OUTPUT_CHAR ((utf8_char)(0x80 | ((ch >> 12) & 0x3f)));
    00368       OUTPUT_CHAR ((utf8_char)(0x80 | ((ch >> 6) & 0x3f)));
    00369       OUTPUT_CHAR ((utf8_char)(0x80 | (ch & 0x3f)));
    00370     }
    00371     else if (ch < 0x80000000)
    00372     {
    00373       OUTPUT_CHAR ((utf8_char)(0xfc | (ch >> 30)));
    00374       OUTPUT_CHAR ((utf8_char)(0x80 | ((ch >> 24) & 0x3f)));
    00375       OUTPUT_CHAR ((utf8_char)(0x80 | ((ch >> 18) & 0x3f)));
    00376       OUTPUT_CHAR ((utf8_char)(0x80 | ((ch >> 12) & 0x3f)));
    00377       OUTPUT_CHAR ((utf8_char)(0x80 | ((ch >> 6) & 0x3f)));
    00378       OUTPUT_CHAR ((utf8_char)(0x80 | (ch & 0x3f)));
    00379     }
    00380     */
    00381     return encodedLen;
    00382   }
    00383
    00388   inline static int EncodeUTF16 (const utf32_char ch, utf16_char* buf,
    00389     size_t bufsize, bool allowNonchars = false)
    00390   {
    00391     if ((!allowNonchars && ((CS_UC_IS_NONCHARACTER(ch))
    00392       || (CS_UC_IS_SURROGATE(ch)))) || (ch > CS_UC_LAST_CHAR))
    00393       return 0;
    00394     size_t bufRemaining = bufsize;
    00395     int encodedLen = 0;
    00396
    00397     if (ch < 0x10000)
    00398     {
    00399       OUTPUT_CHAR((utf16_char)ch);
    00400     }
    00401     else if (ch < 0x100000)
    00402     {
    00403       utf32_char ch_shifted = ch - 0x10000;
    00404       OUTPUT_CHAR((utf16_char)((ch_shifted >> 10)
    00405         | CS_UC_CHAR_HIGH_SURROGATE_FIRST));
    00406       OUTPUT_CHAR((utf16_char)((ch_shifted & 0x3ff)
    00407         | CS_UC_CHAR_LOW_SURROGATE_FIRST));
    00408     }
    00409     else
    00410       return 0;
    00411
    00412     return encodedLen;
    00413   }
    00414
    00419   inline static int EncodeUTF32 (const utf32_char ch, utf32_char* buf,
    00420     size_t bufsize, bool allowNonchars = false)
    00421   {
    00422     if ((!allowNonchars && ((CS_UC_IS_NONCHARACTER(ch))
    00423       || (CS_UC_IS_SURROGATE(ch)))) || (ch > CS_UC_LAST_CHAR))
    00424       return 0;
    00425     size_t bufRemaining = bufsize;
    00426     int encodedLen = 0;
    00427
    00428     OUTPUT_CHAR(ch);
    00429
    00430     return encodedLen;
    00431   }
    00432
    00437   inline static int Encode (const utf32_char ch, utf8_char* buf,
    00438     size_t bufsize, bool allowNonchars = false)
    00439   {
    00440     return EncodeUTF8 (ch, buf, bufsize, allowNonchars);
    00441   }
    00446   inline static int Encode (const utf32_char ch, utf16_char* buf,
    00447     size_t bufsize, bool allowNonchars = false)
    00448   {
    00449     return EncodeUTF16 (ch, buf, bufsize, allowNonchars);
    00450   }
    00455   inline static int Encode (const utf32_char ch, utf32_char* buf,
    00456     size_t bufsize, bool allowNonchars = false)
    00457   {
    00458     return EncodeUTF32 (ch, buf, bufsize, allowNonchars);
    00459   }
    00461 #undef OUTPUT_CHAR
    00462
    00465 #define OUTPUT_CHAR(chr) _OUTPUT_CHAR(dest, chr)
    00466
    00467 #define UCTF_CONVERTER(funcName, fromType, decoder, toType, encoder)    \
    00468   inline static size_t funcName (toType* dest, size_t destSize,         \
    00469     const fromType* source, size_t srcSize = (size_t)-1)                \
    00470   {                                                                     \
    00471     if ((srcSize == 0) || (source == 0))                                \
    00472       return 0;                                                         \
    00473                                                                         \
    00474     size_t bufRemaining = (destSize > 0) ? destSize - 1 : 0;            \
    00475     size_t encodedLen = 0;                                              \
    00476                                                                         \
    00477     size_t srcChars = srcSize;                                          \
    00478                                                                         \
    00479     if (srcSize == (size_t)-1)                                          \
    00480     {                                                                   \
    00481       srcChars = 0;                                                     \
    00482       const fromType* sptr = source;                                    \
    00483       while (*sptr++ != 0) srcChars++;                                  \
    00484     }                                                                   \
    00485                                                                         \
    00486     while (srcChars > 0)                                                \
    00487     {                                                                   \
    00488       utf32_char ch;                                                    \
    00489       int scnt = decoder (source, srcChars, ch, 0);                     \
    00490       if (scnt == 0) break;                                             \
    00491       int dcnt = encoder (ch, dest, bufRemaining);                      \
    00492       if (dcnt == 0)                                                    \
    00493       {                                                                 \
    00494         dcnt = encoder (CS_UC_CHAR_REPLACER, dest, bufRemaining);       \
    00495       }                                                                 \
    00496                                                                         \
    00497       if ((size_t)dcnt >= bufRemaining)                                 \
    00498       {                                                                 \
    00499         if (dest && (destSize > 0)) dest += bufRemaining;               \
    00500         bufRemaining = 0;                                               \
    00501       }                                                                 \
    00502       else                                                              \
    00503       {                                                                 \
    00504         bufRemaining -= dcnt;                                           \
    00505         if (dest && (destSize > 0)) dest += dcnt;                       \
    00506       }                                                                 \
    00507       encodedLen += dcnt;                                               \
    00508       if ((size_t)scnt >= srcChars) break;                              \
    00509       srcChars -= scnt;                                                 \
    00510       source += scnt;                                                   \
    00511     }                                                                   \
    00512                                                                         \
    00513     if (dest) *dest = 0;                                                \
    00514                                                                         \
    00515     return encodedLen + 1;                                              \
    00516   }
    00517
    00533   UCTF_CONVERTER (UTF8to16, utf8_char, UTF8Decode, utf16_char, EncodeUTF16);
    00538   UCTF_CONVERTER (UTF8to32, utf8_char, UTF8Decode, utf32_char, EncodeUTF32);
    00539
    00544   UCTF_CONVERTER (UTF16to8, utf16_char, UTF16Decode, utf8_char, EncodeUTF8);
    00549   UCTF_CONVERTER (UTF16to32, utf16_char, UTF16Decode, utf32_char, EncodeUTF32);
    00550
    00555   UCTF_CONVERTER (UTF32to8, utf32_char, UTF32Decode, utf8_char, EncodeUTF8);
    00560   UCTF_CONVERTER (UTF32to16, utf32_char, UTF32Decode, utf16_char, EncodeUTF16);
    00563 #undef UCTF_CONVERTER
    00564 #undef OUTPUT_CHAR
    00565 #undef _OUTPUT_CHAR
    00566
    00567 #if (CS_WCHAR_T_SIZE == 1)
    00568   inline static size_t UTF8toWC (wchar_t* dest, size_t destSize,
    00569     const utf8_char* source, size_t srcSize)
    00570   {
    00571     size_t srcChars = srcSize;
    00572     if (srcSize == (size_t)-1)
    00573     {
    00574       srcChars = 0;
    00575       const utf8_char* sptr = source;
    00576       while (*sptr++ != 0) srcChars++;
    00577     }
    00578     if ((dest != 0) && (destSize != 0))
    00579     {
    00580       size_t len = MIN (destSize - 1, srcChars);
    00581       memcpy (dest, source, size * sizeof (wchar_t));
    00582       *(dest + len) = 0;
    00583     }
    00584     return srcChars + 1;
    00585   };
    00586
    00587   inline static size_t UTF16toWC (wchar_t* dest, size_t destSize,
    00588     const utf16_char* source, size_t srcSize)
    00589   {
    00590     return UTF16to8 ((utf8_char*)dest, destSize, source, srcSize);
    00591   };
    00592
    00593   inline static size_t UTF32toWC (wchar_t* dest, size_t destSize,
    00594     const utf32_char* source, size_t srcSize)
    00595   {
    00596     return UTF32to8 ((utf8_char*)dest, destSize, source, srcSize);
    00597   };
    00598
    00599   inline static size_t WCtoUTF8 (utf8_char* dest, size_t destSize,
    00600     const wchar_t* source, size_t srcSize)
    00601   {
    00602     size_t srcChars = srcSize;
    00603     if (srcSize == (size_t)-1)
    00604     {
    00605       srcChars = 0;
    00606       const wchar_t* sptr = source;
    00607       while (*sptr++ != 0) srcChars++;
    00608     }
    00609     if ((dest != 0) && (destSize != 0))
    00610     {
    00611       size_t len = MIN (destSize - 1, srcChars);
    00612       memcpy (dest, source, len * sizeof (wchar_t));
    00613       *(dest + len) = 0;
    00614     }
    00615     return srcChars + 1;
    00616   };
    00617
    00618   inline static size_t WCtoUTF16 (utf16_char* dest, size_t destSize,
    00619     const wchar_t* source, size_t srcSize)
    00620   {
    00621     return UTF8to16 (dest, destSize, source, srcSize);
    00622   };
    00623
    00624   inline static size_t WCtoUTF32 (utf32_char* dest, size_t destSize,
    00625     const wchar_t* source, size_t srcSize)
    00626   {
    00627     return UTF8to32 (dest, destSize, source, srcSize);
    00628   };
    00629
    00630   inline static int Decode (const wchar_t* str, size_t strlen,
    00631     utf32_char& ch, bool* isValid = 0, bool returnNonChar = false)
    00632   {
    00633     return UTF8Decode ((utf8_char*)str, strlen, ch, isValid, returnNonChar);
    00634   }
    00635   inline static int Encode (const utf32_char ch, wchar_t* buf,
    00636     size_t bufsize, bool allowNonchars = false)
    00637   {
    00638     return EncodeUTF8 (ch, (utf8_char*)buf, bufsize, allowNonchars);
    00639   }
    00640 #elif (CS_WCHAR_T_SIZE == 2)
    00641   // Methods below for doxygen documentation are here as the size '2' is
    00642   // default.
    00643
    00650   inline static size_t UTF8toWC (wchar_t* dest, size_t destSize,
    00651     const utf8_char* source, size_t srcSize)
    00652   {
    00653     return UTF8to16 ((utf16_char*)dest, destSize, source, srcSize);
    00654   };
    00655
    00660   inline static size_t UTF16toWC (wchar_t* dest, size_t destSize,
    00661     const utf16_char* source, size_t srcSize)
    00662   {
    00663     size_t srcChars = srcSize;
    00664     if (srcSize == (size_t)-1)
    00665     {
    00666       srcChars = 0;
    00667       const utf16_char* sptr = source;
    00668       while (*sptr++ != 0) srcChars++;
    00669     }
    00670     if ((dest != 0) && (destSize != 0))
    00671     {
    00672       size_t len = MIN (destSize - 1, srcChars);
    00673       memcpy (dest, source, len * sizeof (wchar_t));
    00674       *(dest + len) = 0;
    00675     }
    00676     return srcChars + 1;
    00677   };
    00678
    00683   inline static size_t UTF32toWC (wchar_t* dest, size_t destSize,
    00684     const utf32_char* source, size_t srcSize)
    00685   {
    00686     return UTF32to16 ((utf16_char*)dest, destSize, source, srcSize);
    00687   };
    00688
    00693   inline static size_t WCtoUTF8 (utf8_char* dest, size_t destSize,
    00694     const wchar_t* source, size_t srcSize)
    00695   {
    00696     return UTF16to8 (dest, destSize, (utf16_char*)source, srcSize);
    00697   };
    00698
    00703   inline static size_t WCtoUTF16 (utf16_char* dest, size_t destSize,
    00704     const wchar_t* source, size_t srcSize)
    00705   {
    00706     size_t srcChars = srcSize;
    00707     if (srcSize == (size_t)-1)
    00708     {
    00709       srcChars = 0;
    00710       const wchar_t* sptr = source;
    00711       while (*sptr++ != 0) srcChars++;
    00712     }
    00713     if ((dest != 0) && (destSize != 0))
    00714     {
    00715       size_t len = MIN (destSize - 1, srcChars);
    00716       memcpy (dest, source, len * sizeof (wchar_t));
    00717       *(dest + len) = 0;
    00718     }
    00719     return srcChars + 1;
    00720   };
    00721
    00726   inline static size_t WCtoUTF32 (utf32_char* dest, size_t destSize,
    00727     const wchar_t* source, size_t srcSize)
    00728   {
    00729     return UTF16to32 (dest, destSize, (utf16_char*)source, srcSize);
    00730   };
    00731
    00732   /* Decode()/Encode() overloads for wchar_t.
    00733    * - On VC7+, wchar_t may be an unsigned short or the special type __wchar_t.
    00734    * - On VC6 wchar_t is always an unsigned short. __wchar_t does not exist.
    00735    * Now there may be conflicts with the utf16_char overloads if wchar_t is
    00736    * an unsigned short. On the other hand, we would like to support VC7+'s
    00737    * built-in wchar_t as well.
    00738    * So: on VC7+, provide overloads for __wchar_t, on VC6, don't compile this
    00739    * code at all, on other compilers, provide overloads for wchar_t instead
    00740    * (by re#definining __wchar_t).
    00741    */
    00742 #if !defined(CS_COMPILER_MSVC) || (_MSC_VER > 1300)
    00743 #if !defined(CS_COMPILER_MSVC)
    00744   #define __wchar_t wchar_t
    00745 #endif
    00746
    00750   inline static int Decode (const __wchar_t* str, size_t strlen,
    00751     utf32_char& ch, bool* isValid = 0, bool returnNonChar = false)
    00752   {
    00753     return UTF16Decode ((utf16_char*)str, strlen, ch, isValid, returnNonChar);
    00754   }
    00759   inline static int Encode (const utf32_char ch, __wchar_t* buf,
    00760     size_t bufsize, bool allowNonchars = false)
    00761   {
    00762     return EncodeUTF16 (ch, (utf16_char*)buf, bufsize, allowNonchars);
    00763   }
    00764 #ifdef __wchar_t
    00765   #undef __wchar_t
    00766 #endif
    00767 #endif
    00768
    00769 #elif (CS_WCHAR_T_SIZE == 4)
    00770   inline static size_t UTF8toWC (wchar_t* dest, size_t destSize,
    00771     const utf8_char* source, size_t srcSize)
    00772   {
    00773     return UTF8to32 ((utf32_char*)dest, destSize, source, srcSize);
    00774   };
    00775
    00776   inline static size_t UTF16toWC (wchar_t* dest, size_t destSize,
    00777     const utf16_char* source, size_t srcSize)
    00778   {
    00779     return UTF16to32 ((utf32_char*)dest, destSize, source, srcSize);
    00780   };
    00781
    00782   inline static size_t UTF32toWC (wchar_t* dest, size_t destSize,
    00783     const utf32_char* source,  size_t srcSize)
    00784   {
    00785     size_t srcChars = srcSize;
    00786     if (srcSize == (size_t)-1)
    00787     {
    00788       srcChars = 0;
    00789       const utf32_char* sptr = source;
    00790       while (*sptr++ != 0) srcChars++;
    00791     }
    00792     if ((dest != 0) && (destSize != 0))
    00793     {
    00794       size_t len = MIN (destSize - 1, srcChars);
    00795       memcpy (dest, source, len * sizeof (wchar_t));
    00796       *(dest + len) = 0;
    00797     }
    00798     return srcChars + 1;
    00799   };
    00800
    00801   inline static size_t WCtoUTF8 (utf8_char* dest, size_t destSize,
    00802     const wchar_t* source, size_t srcSize)
    00803   {
    00804     return UTF32to8 (dest, destSize, (utf32_char*)source, srcSize);
    00805   };
    00806
    00807   inline static size_t WCtoUTF16 (utf16_char* dest, size_t destSize,
    00808     const wchar_t* source, size_t srcSize)
    00809   {
    00810     return UTF32to16 (dest, destSize, (utf32_char*)source, srcSize);
    00811   };
    00812
    00813   inline static size_t WCtoUTF32 (utf32_char* dest, size_t destSize,
    00814     const wchar_t* source, size_t srcSize)
    00815   {
    00816     size_t srcChars = srcSize;
    00817     if (srcSize == (size_t)-1)
    00818     {
    00819       srcChars = 0;
    00820       const wchar_t* sptr = source;
    00821       while (*sptr++ != 0) srcChars++;
    00822     }
    00823     if ((dest != 0) && (destSize != 0))
    00824     {
    00825       size_t len = MIN (destSize - 1, srcChars);
    00826       memcpy (dest, source, len * sizeof (wchar_t));
    00827       *(dest + len) = 0;
    00828     }
    00829     return srcChars + 1;
    00830   };
    00831
    00832   inline static int Decode (const wchar_t* str, size_t strlen,
    00833     utf32_char& ch, bool* isValid = 0, bool returnNonChar = false)
    00834   {
    00835     return UTF32Decode ((utf32_char*)str, strlen, ch, isValid, returnNonChar);
    00836   }
    00837   inline static int Encode (const utf32_char ch, wchar_t* buf,
    00838     size_t bufsize, bool allowNonchars = false)
    00839   {
    00840     return EncodeUTF32 (ch, (utf32_char*)buf, bufsize, allowNonchars);
    00841   }
    00842 #else
    00843   #error Odd-sized, unsupported wchar_t!
    00844 #endif
    00845
    00858   inline static int UTF8Skip (const utf8_char* str, size_t maxSkip)
    00859   {
    00860     if (maxSkip < 1) return 0;
    00861
    00862     if ((*str & 0x80) == 0)
    00863     {
    00864       return 1;
    00865     }
    00866     else
    00867     {
    00868       int n = 0;
    00869       while ((n < 7) && ((*str & (1 << (7 - n))) != 0)) { n++; }
    00870
    00871       if ((n < 2) || (n > 6))
    00872       {
    00873         return 1;
    00874       }
    00875
    00876       int skip = 1;
    00877
    00878       for (; skip < n; skip++)
    00879       {
    00880         if (((str[skip] & 0xc0) != 0x80) || ((size_t)skip > maxSkip))
    00881         {
    00882           break;
    00883         }
    00884       }
    00885       return skip;
    00886     }
    00887   }
    00888
    00899   inline static int UTF8Rewind (const utf8_char* str, size_t maxRew)
    00900   {
    00901     if (maxRew < 1) return 0;
    00902
    00903     const utf8_char* pos = str - 1;
    00904
    00905     if ((*pos & 0x80) == 0)
    00906     {
    00907       return 1;
    00908     }
    00909
    00910     // Skip backward to the first byte of the sequence.
    00911     int skip = 1;
    00912     while (((*pos & 0xc0) == 0x80) && ((size_t)skip < maxRew))
    00913     {
    00914       skip++;
    00915       pos--;
    00916     }
    00917
    00918     return skip;
    00919   }
    00920
    00926   inline static int UTF16Skip (const utf16_char* str, size_t maxSkip)
    00927   {
    00928     if (CS_UC_IS_HIGH_SURROGATE (*str))
    00929       return (int)(MIN(maxSkip, 2));
    00930     else
    00931       return (int)(MIN(maxSkip, 1));
    00932   }
    00933
    00939   inline static int UTF16Rewind (const utf16_char* str, size_t maxRew)
    00940   {
    00941     if (maxRew < 1) return 0;
    00942
    00943     const utf16_char* pos = str - 1;
    00944     if (!CS_UC_IS_SURROGATE(*pos))
    00945       return 1;
    00946     else
    00947     {
    00948       if ((maxRew > 1) && (CS_UC_IS_HIGH_SURROGATE(*(pos - 1))))
    00949         return 2;
    00950       else
    00951         return 1;
    00952     }
    00953   }
    00954
    00960   inline static int UTF32Skip (const utf32_char* str, size_t maxSkip)
    00961   {
    00962     (void)str; // silence gcc
    00963     return (int)(MIN(maxSkip, 1));
    00964   }
    00965
    00971   inline static int UTF32Rewind (const utf32_char* str, size_t maxRew)
    00972   {
    00973     (void)str; // silence gcc
    00974     if (maxRew < 1) return 0;
    00975     return 1;
    00976   }
    00991   static size_t MapToUpper (const utf32_char ch, utf32_char* dest,
    00992     size_t destSize, uint flags = 0);
    00997   static size_t MapToLower (const utf32_char ch, utf32_char* dest,
    00998     size_t destSize, uint flags = 0);
    01004   static size_t MapToFold (const utf32_char ch, utf32_char* dest,
    01005     size_t destSize, uint flags = 0);
    01007 };
    01008
    01011 #endif
    01012