LCOV - app.info - xpcom/io/nsNativeCharsetUtils.cpp

LCOV - code coverage report
| Current view: | directory - xpcom/io - nsNativeCharsetUtils.cpp (source / functions) |  | Found | Hit | Coverage |
| Test: | app.info | Lines: | 174 | 138 | 79.3 %
| Date: | 2012-04-21 | Functions: | 20 | 18 | 90.0 %

           1                 : /* ***** BEGIN LICENSE BLOCK *****
           2                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
           3                 :  *
           4                 :  * The contents of this file are subject to the Mozilla Public License Version
           5                 :  * 1.1 (the "License"); you may not use this file except in compliance with
           6                 :  * the License. You may obtain a copy of the License at
           7                 :  * http://www.mozilla.org/MPL/
           8                 :  *
           9                 :  * Software distributed under the License is distributed on an "AS IS" basis,
          10                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
          11                 :  * for the specific language governing rights and limitations under the
          12                 :  * License.
          13                 :  *
          14                 :  * The Original Code is Mozilla.
          15                 :  *
          16                 :  * The Initial Developer of the Original Code is
          17                 :  * Netscape Communications Corporation.
          18                 :  * Portions created by the Initial Developer are Copyright (C) 2002
          19                 :  * the Initial Developer. All Rights Reserved.
          20                 :  *
          21                 :  * Contributor(s):
          22                 :  *   Darin Fisher <darin@netscape.com>
          23                 :  *   Brian Stell <bstell@ix.netcom.com>
          24                 :  *   Frank Tang <ftang@netscape.com>
          25                 :  *   Brendan Eich <brendan@mozilla.org>
          26                 :  *   Sergei Dolgov <sergei_d@fi.fi.tartu.ee>
          27                 :  *   Jungshik Shin <jshin@i18nl10n.com>
          28                 :  *
          29                 :  * Alternatively, the contents of this file may be used under the terms of
          30                 :  * either the GNU General Public License Version 2 or later (the "GPL"), or
          31                 :  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
          32                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
          33                 :  * of those above. If you wish to allow use of your version of this file only
          34                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
          35                 :  * use your version of this file under the terms of the MPL, indicate your
          36                 :  * decision by deleting the provisions above and replace them with the notice
          37                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
          38                 :  * the provisions above, a recipient may use your version of this file under
          39                 :  * the terms of any one of the MPL, the GPL or the LGPL.
          40                 :  *
          41                 :  * ***** END LICENSE BLOCK ***** */
          42                 :
          43                 : #include "xpcom-private.h"
          44                 :
          45                 : //-----------------------------------------------------------------------------
          46                 : // XP_MACOSX or ANDROID
          47                 : //-----------------------------------------------------------------------------
          48                 : #if defined(XP_MACOSX) || defined(ANDROID)
          49                 :
          50                 : #include "nsAString.h"
          51                 : #include "nsReadableUtils.h"
          52                 : #include "nsString.h"
          53                 :
          54                 : nsresult
          55                 : NS_CopyNativeToUnicode(const nsACString &input, nsAString  &output)
          56                 : {
          57                 :     CopyUTF8toUTF16(input, output);
          58                 :     return NS_OK;
          59                 : }
          60                 :
          61                 : nsresult
          62                 : NS_CopyUnicodeToNative(const nsAString  &input, nsACString &output)
          63                 : {
          64                 :     CopyUTF16toUTF8(input, output);
          65                 :     return NS_OK;
          66                 : }
          67                 :
          68                 : void
          69                 : NS_StartupNativeCharsetUtils()
          70                 : {
          71                 : }
          72                 :
          73                 : void
          74                 : NS_ShutdownNativeCharsetUtils()
          75                 : {
          76                 : }
          77                 :
          78                 :
          79                 : //-----------------------------------------------------------------------------
          80                 : // XP_UNIX
          81                 : //-----------------------------------------------------------------------------
          82                 : #elif defined(XP_UNIX)
          83                 :
          84                 : #include <stdlib.h>   // mbtowc, wctomb
          85                 : #include <locale.h>   // setlocale
          86                 : #include "mozilla/Mutex.h"
          87                 : #include "nscore.h"
          88                 : #include "nsAString.h"
          89                 : #include "nsReadableUtils.h"
          90                 :
          91                 : using namespace mozilla;
          92                 :
          93                 : //
          94                 : // choose a conversion library.  we used to use mbrtowc/wcrtomb under Linux,
          95                 : // but that doesn't work for non-BMP characters whether we use '-fshort-wchar'
          96                 : // or not (see bug 206811 and
          97                 : // news://news.mozilla.org:119/bajml3$fvr1@ripley.netscape.com). we now use
          98                 : // iconv for all platforms where nltypes.h and nllanginfo.h are present
          99                 : // along with iconv.
         100                 : //
         101                 : #if defined(HAVE_ICONV) && defined(HAVE_NL_TYPES_H) && defined(HAVE_LANGINFO_CODESET)
         102                 : #define USE_ICONV 1
         103                 : #else
         104                 : #define USE_STDCONV 1
         105                 : #endif
         106                 :
         107                 : static void
         108               0 : isolatin1_to_utf16(const char **input, PRUint32 *inputLeft, PRUnichar **output, PRUint32 *outputLeft)
         109                 : {
         110               0 :     while (*inputLeft && *outputLeft) {
         111               0 :         **output = (unsigned char) **input;
         112               0 :         (*input)++;
         113               0 :         (*inputLeft)--;
         114               0 :         (*output)++;
         115               0 :         (*outputLeft)--;
         116                 :     }
         117               0 : }
         118                 :
         119                 : static void
         120               0 : utf16_to_isolatin1(const PRUnichar **input, PRUint32 *inputLeft, char **output, PRUint32 *outputLeft)
         121                 : {
         122               0 :     while (*inputLeft && *outputLeft) {
         123               0 :         **output = (unsigned char) **input;
         124               0 :         (*input)++;
         125               0 :         (*inputLeft)--;
         126               0 :         (*output)++;
         127               0 :         (*outputLeft)--;
         128                 :     }
         129               0 : }
         130                 :
         131                 : //-----------------------------------------------------------------------------
         132                 : // conversion using iconv
         133                 : //-----------------------------------------------------------------------------
         134                 : #if defined(USE_ICONV)
         135                 : #include <nl_types.h> // CODESET
         136                 : #include <langinfo.h> // nl_langinfo
         137                 : #include <iconv.h>    // iconv_open, iconv, iconv_close
         138                 : #include <errno.h>
         139                 : #include "plstr.h"
         140                 :
         141                 : #if defined(HAVE_ICONV_WITH_CONST_INPUT)
         142                 : #define ICONV_INPUT(x) (x)
         143                 : #else
         144                 : #define ICONV_INPUT(x) ((char **)x)
         145                 : #endif
         146                 :
         147                 : // solaris definitely needs this, but we'll enable it by default
         148                 : // just in case... but we know for sure that iconv(3) in glibc
         149                 : // doesn't need this.
         150                 : #if !defined(__GLIBC__)
         151                 : #define ENABLE_UTF8_FALLBACK_SUPPORT
         152                 : #endif
         153                 :
         154                 : #define INVALID_ICONV_T ((iconv_t) -1)
         155                 :
         156                 : static inline size_t
         157         1332325 : xp_iconv(iconv_t converter,
         158                 :          const char **input,
         159                 :          size_t      *inputLeft,
         160                 :          char       **output,
         161                 :          size_t      *outputLeft)
         162                 : {
         163         1332325 :     size_t res, outputAvail = outputLeft ? *outputLeft : 0;
         164         1332325 :     res = iconv(converter, ICONV_INPUT(input), inputLeft, output, outputLeft);
         165         1332325 :     if (res == (size_t) -1) {
         166                 :         // on some platforms (e.g., linux) iconv will fail with
         167                 :         // E2BIG if it cannot convert _all_ of its input.  it'll
         168                 :         // still adjust all of the in/out params correctly, so we
         169                 :         // can ignore this error.  the assumption is that we will
         170                 :         // be called again to complete the conversion.
         171               0 :         if ((errno == E2BIG) && (*outputLeft < outputAvail))
         172               0 :             res = 0;
         173                 :     }
         174         1332325 :     return res;
         175                 : }
         176                 :
         177                 : static inline void
         178          888094 : xp_iconv_reset(iconv_t converter)
         179                 : {
         180                 :     // NOTE: the man pages on Solaris claim that you can pass NULL
         181                 :     // for all parameter to reset the converter, but beware the
         182                 :     // evil Solaris crash if you go down this route >:-)
         183                 :
         184          888094 :     const char *zero_char_in_ptr  = NULL;
         185          888094 :     char       *zero_char_out_ptr = NULL;
         186          888094 :     size_t      zero_size_in      = 0,
         187          888094 :                 zero_size_out     = 0;
         188                 :
         189                 :     xp_iconv(converter, &zero_char_in_ptr,
         190                 :                         &zero_size_in,
         191                 :                         &zero_char_out_ptr,
         192          888094 :                         &zero_size_out);
         193          888094 : }
         194                 :
         195                 : static inline iconv_t
         196            2730 : xp_iconv_open(const char **to_list, const char **from_list)
         197                 : {
         198                 :     iconv_t res;
         199                 :     const char **from_name;
         200                 :     const char **to_name;
         201                 :
         202                 :     // try all possible combinations to locate a converter.
         203            2730 :     to_name = to_list;
         204            5460 :     while (*to_name) {
         205            2730 :         if (**to_name) {
         206            2730 :             from_name = from_list;
         207            5460 :             while (*from_name) {
         208            2730 :                 if (**from_name) {
         209            2730 :                     res = iconv_open(*to_name, *from_name);
         210            2730 :                     if (res != INVALID_ICONV_T)
         211            2730 :                         return res;
         212                 :                 }
         213               0 :                 from_name++;
         214                 :             }
         215                 :         }
         216               0 :         to_name++;
         217                 :     }
         218                 :
         219               0 :     return INVALID_ICONV_T;
         220                 : }
         221                 :
         222                 : /*
         223                 :  * PRUnichar[] is NOT a UCS-2 array BUT a UTF-16 string. Therefore, we
         224                 :  * have to use UTF-16 with iconv(3) on platforms where it's supported.
         225                 :  * However, the way UTF-16 and UCS-2 are interpreted varies across platforms
         226                 :  * and implementations of iconv(3). On Tru64, it also depends on the environment
         227                 :  * variable. To avoid the trouble arising from byte-swapping
         228                 :  * (bug 208809), we have to try UTF-16LE/BE and UCS-2LE/BE before falling
         229                 :  * back to UTF-16 and UCS-2 and variants. We assume that UTF-16 and UCS-2
         230                 :  * on systems without UTF-16LE/BE and UCS-2LE/BE have the native endianness,
         231                 :  * which isn't the case of glibc 2.1.x, for which we use 'UNICODELITTLE'
         232                 :  * and 'UNICODEBIG'. It's also not true of Tru64 V4 when the environment
         233                 :  * variable ICONV_BYTEORDER is set to 'big-endian', about which not much
         234                 :  * can be done other than adding a note in the release notes. (bug 206811)
         235                 :  */
         236                 : static const char *UTF_16_NAMES[] = {
         237                 : #if defined(IS_LITTLE_ENDIAN)
         238                 :     "UTF-16LE",
         239                 : #if defined(__GLIBC__)
         240                 :     "UNICODELITTLE",
         241                 : #endif
         242                 :     "UCS-2LE",
         243                 : #else
         244                 :     "UTF-16BE",
         245                 : #if defined(__GLIBC__)
         246                 :     "UNICODEBIG",
         247                 : #endif
         248                 :     "UCS-2BE",
         249                 : #endif
         250                 :     "UTF-16",
         251                 :     "UCS-2",
         252                 :     "UCS2",
         253                 :     "UCS_2",
         254                 :     "ucs-2",
         255                 :     "ucs2",
         256                 :     "ucs_2",
         257                 :     NULL
         258                 : };
         259                 :
         260                 : #if defined(ENABLE_UTF8_FALLBACK_SUPPORT)
         261                 : static const char *UTF_8_NAMES[] = {
         262                 :     "UTF-8",
         263                 :     "UTF8",
         264                 :     "UTF_8",
         265                 :     "utf-8",
         266                 :     "utf8",
         267                 :     "utf_8",
         268                 :     NULL
         269                 : };
         270                 : #endif
         271                 :
         272                 : static const char *ISO_8859_1_NAMES[] = {
         273                 :     "ISO-8859-1",
         274                 : #if !defined(__GLIBC__)
         275                 :     "ISO8859-1",
         276                 :     "ISO88591",
         277                 :     "ISO_8859_1",
         278                 :     "ISO8859_1",
         279                 :     "iso-8859-1",
         280                 :     "iso8859-1",
         281                 :     "iso88591",
         282                 :     "iso_8859_1",
         283                 :     "iso8859_1",
         284                 : #endif
         285                 :     NULL
         286                 : };
         287                 :
         288                 : class nsNativeCharsetConverter
         289                 : {
         290                 : public:
         291                 :     nsNativeCharsetConverter();
         292                 :    ~nsNativeCharsetConverter();
         293                 :
         294                 :     nsresult NativeToUnicode(const char      **input , PRUint32 *inputLeft,
         295                 :                              PRUnichar       **output, PRUint32 *outputLeft);
         296                 :     nsresult UnicodeToNative(const PRUnichar **input , PRUint32 *inputLeft,
         297                 :                              char            **output, PRUint32 *outputLeft);
         298                 :
         299                 :     static void GlobalInit();
         300                 :     static void GlobalShutdown();
         301                 :     static bool IsNativeUTF8();
         302                 :
         303                 : private:
         304                 :     static iconv_t gNativeToUnicode;
         305                 :     static iconv_t gUnicodeToNative;
         306                 : #if defined(ENABLE_UTF8_FALLBACK_SUPPORT)
         307                 :     static iconv_t gNativeToUTF8;
         308                 :     static iconv_t gUTF8ToNative;
         309                 :     static iconv_t gUnicodeToUTF8;
         310                 :     static iconv_t gUTF8ToUnicode;
         311                 : #endif
         312                 :     static Mutex  *gLock;
         313                 :     static bool    gInitialized;
         314                 :     static bool    gIsNativeUTF8;
         315                 :
         316                 :     static void LazyInit();
         317                 :
         318          444047 :     static void Lock()   { if (gLock) gLock->Lock();   }
         319          444047 :     static void Unlock() { if (gLock) gLock->Unlock(); }
         320                 : };
         321                 :
         322                 : iconv_t nsNativeCharsetConverter::gNativeToUnicode = INVALID_ICONV_T;
         323                 : iconv_t nsNativeCharsetConverter::gUnicodeToNative = INVALID_ICONV_T;
         324                 : #if defined(ENABLE_UTF8_FALLBACK_SUPPORT)
         325                 : iconv_t nsNativeCharsetConverter::gNativeToUTF8    = INVALID_ICONV_T;
         326                 : iconv_t nsNativeCharsetConverter::gUTF8ToNative    = INVALID_ICONV_T;
         327                 : iconv_t nsNativeCharsetConverter::gUnicodeToUTF8   = INVALID_ICONV_T;
         328                 : iconv_t nsNativeCharsetConverter::gUTF8ToUnicode   = INVALID_ICONV_T;
         329                 : #endif
         330                 : Mutex  *nsNativeCharsetConverter::gLock            = nsnull;
         331                 : bool    nsNativeCharsetConverter::gInitialized     = false;
         332                 : bool    nsNativeCharsetConverter::gIsNativeUTF8    = false;
         333                 :
         334                 : void
         335            1365 : nsNativeCharsetConverter::LazyInit()
         336                 : {
         337            1365 :     const char  *blank_list[] = { "", NULL };
         338            1365 :     const char **native_charset_list = blank_list;
         339            1365 :     const char  *native_charset = nl_langinfo(CODESET);
         340            1365 :     if (native_charset == nsnull) {
         341               0 :         NS_ERROR("native charset is unknown");
         342                 :         // fallback to ISO-8859-1
         343               0 :         native_charset_list = ISO_8859_1_NAMES;
         344                 :     }
         345                 :     else
         346            1365 :         native_charset_list[0] = native_charset;
         347                 :
         348                 :     // Most, if not all, Unixen supporting UTF-8 and nl_langinfo(CODESET)
         349                 :     // return 'UTF-8' (or 'utf-8')
         350            1365 :     if (!PL_strcasecmp(native_charset, "UTF-8"))
         351            1365 :         gIsNativeUTF8 = true;
         352                 :
         353            1365 :     gNativeToUnicode = xp_iconv_open(UTF_16_NAMES, native_charset_list);
         354            1365 :     gUnicodeToNative = xp_iconv_open(native_charset_list, UTF_16_NAMES);
         355                 :
         356                 : #if defined(ENABLE_UTF8_FALLBACK_SUPPORT)
         357                 :     if (gNativeToUnicode == INVALID_ICONV_T) {
         358                 :         gNativeToUTF8 = xp_iconv_open(UTF_8_NAMES, native_charset_list);
         359                 :         gUTF8ToUnicode = xp_iconv_open(UTF_16_NAMES, UTF_8_NAMES);
         360                 :         NS_ASSERTION(gNativeToUTF8 != INVALID_ICONV_T, "no native to utf-8 converter");
         361                 :         NS_ASSERTION(gUTF8ToUnicode != INVALID_ICONV_T, "no utf-8 to utf-16 converter");
         362                 :     }
         363                 :     if (gUnicodeToNative == INVALID_ICONV_T) {
         364                 :         gUnicodeToUTF8 = xp_iconv_open(UTF_8_NAMES, UTF_16_NAMES);
         365                 :         gUTF8ToNative = xp_iconv_open(native_charset_list, UTF_8_NAMES);
         366                 :         NS_ASSERTION(gUnicodeToUTF8 != INVALID_ICONV_T, "no utf-16 to utf-8 converter");
         367                 :         NS_ASSERTION(gUTF8ToNative != INVALID_ICONV_T, "no utf-8 to native converter");
         368                 :     }
         369                 : #else
         370            1365 :     NS_ASSERTION(gNativeToUnicode != INVALID_ICONV_T, "no native to utf-16 converter");
         371            1365 :     NS_ASSERTION(gUnicodeToNative != INVALID_ICONV_T, "no utf-16 to native converter");
         372                 : #endif
         373                 :
         374                 :     /*
         375                 :      * On Solaris 8 (and newer?), the iconv modules converting to UCS-2
         376                 :      * prepend a byte order mark unicode character (BOM, u+FEFF) during
         377                 :      * the first use of the iconv converter. The same is the case of
         378                 :      * glibc 2.2.9x and Tru64 V5 (see bug 208809) when 'UTF-16' is used.
         379                 :      * However, we use 'UTF-16LE/BE' in both cases, instead so that we
         380                 :      * should be safe. But just in case...
         381                 :      *
         382                 :      * This dummy conversion gets rid of the BOMs and fixes bug 153562.
         383                 :      */
         384            1365 :     char dummy_input[1] = { ' ' };
         385                 :     char dummy_output[4];
         386                 :
         387            1365 :     if (gNativeToUnicode != INVALID_ICONV_T) {
         388            1365 :         const char *input = dummy_input;
         389            1365 :         size_t input_left = sizeof(dummy_input);
         390            1365 :         char *output = dummy_output;
         391            1365 :         size_t output_left = sizeof(dummy_output);
         392                 :
         393            1365 :         xp_iconv(gNativeToUnicode, &input, &input_left, &output, &output_left);
         394                 :     }
         395                 : #if defined(ENABLE_UTF8_FALLBACK_SUPPORT)
         396                 :     if (gUTF8ToUnicode != INVALID_ICONV_T) {
         397                 :         const char *input = dummy_input;
         398                 :         size_t input_left = sizeof(dummy_input);
         399                 :         char *output = dummy_output;
         400                 :         size_t output_left = sizeof(dummy_output);
         401                 :
         402                 :         xp_iconv(gUTF8ToUnicode, &input, &input_left, &output, &output_left);
         403                 :     }
         404                 : #endif
         405                 :
         406            1365 :     gInitialized = true;
         407            1365 : }
         408                 :
         409                 : void
         410            1365 : nsNativeCharsetConverter::GlobalInit()
         411                 : {
         412            1365 :     gLock = new Mutex("nsNativeCharsetConverter.gLock");
         413            1365 : }
         414                 :
         415                 : void
         416            1365 : nsNativeCharsetConverter::GlobalShutdown()
         417                 : {
         418            1365 :     if (gLock) {
         419            1365 :         delete gLock;
         420            1365 :         gLock = nsnull;
         421                 :     }
         422                 :
         423            1365 :     if (gNativeToUnicode != INVALID_ICONV_T) {
         424            1365 :         iconv_close(gNativeToUnicode);
         425            1365 :         gNativeToUnicode = INVALID_ICONV_T;
         426                 :     }
         427                 :
         428            1365 :     if (gUnicodeToNative != INVALID_ICONV_T) {
         429            1365 :         iconv_close(gUnicodeToNative);
         430            1365 :         gUnicodeToNative = INVALID_ICONV_T;
         431                 :     }
         432                 :
         433                 : #if defined(ENABLE_UTF8_FALLBACK_SUPPORT)
         434                 :     if (gNativeToUTF8 != INVALID_ICONV_T) {
         435                 :         iconv_close(gNativeToUTF8);
         436                 :         gNativeToUTF8 = INVALID_ICONV_T;
         437                 :     }
         438                 :     if (gUTF8ToNative != INVALID_ICONV_T) {
         439                 :         iconv_close(gUTF8ToNative);
         440                 :         gUTF8ToNative = INVALID_ICONV_T;
         441                 :     }
         442                 :     if (gUnicodeToUTF8 != INVALID_ICONV_T) {
         443                 :         iconv_close(gUnicodeToUTF8);
         444                 :         gUnicodeToUTF8 = INVALID_ICONV_T;
         445                 :     }
         446                 :     if (gUTF8ToUnicode != INVALID_ICONV_T) {
         447                 :         iconv_close(gUTF8ToUnicode);
         448                 :         gUTF8ToUnicode = INVALID_ICONV_T;
         449                 :     }
         450                 : #endif
         451                 :
         452            1365 :     gInitialized = false;
         453            1365 : }
         454                 :
         455          444047 : nsNativeCharsetConverter::nsNativeCharsetConverter()
         456                 : {
         457          444047 :     Lock();
         458          444047 :     if (!gInitialized)
         459            1365 :         LazyInit();
         460          444047 : }
         461                 :
         462          444047 : nsNativeCharsetConverter::~nsNativeCharsetConverter()
         463                 : {
         464                 :     // reset converters for next time
         465          444047 :     if (gNativeToUnicode != INVALID_ICONV_T)
         466          444047 :         xp_iconv_reset(gNativeToUnicode);
         467          444047 :     if (gUnicodeToNative != INVALID_ICONV_T)
         468          444047 :         xp_iconv_reset(gUnicodeToNative);
         469                 : #if defined(ENABLE_UTF8_FALLBACK_SUPPORT)
         470                 :     if (gNativeToUTF8 != INVALID_ICONV_T)
         471                 :         xp_iconv_reset(gNativeToUTF8);
         472                 :     if (gUTF8ToNative != INVALID_ICONV_T)
         473                 :         xp_iconv_reset(gUTF8ToNative);
         474                 :     if (gUnicodeToUTF8 != INVALID_ICONV_T)
         475                 :         xp_iconv_reset(gUnicodeToUTF8);
         476                 :     if (gUTF8ToUnicode != INVALID_ICONV_T)
         477                 :         xp_iconv_reset(gUTF8ToUnicode);
         478                 : #endif
         479          444047 :     Unlock();
         480          444047 : }
         481                 :
         482                 : nsresult
         483          215382 : nsNativeCharsetConverter::NativeToUnicode(const char **input,
         484                 :                                           PRUint32    *inputLeft,
         485                 :                                           PRUnichar  **output,
         486                 :                                           PRUint32    *outputLeft)
         487                 : {
         488          215382 :     size_t res = 0;
         489          215382 :     size_t inLeft = (size_t) *inputLeft;
         490          215382 :     size_t outLeft = (size_t) *outputLeft * 2;
         491                 :
         492          215382 :     if (gNativeToUnicode != INVALID_ICONV_T) {
         493                 :
         494          215382 :         res = xp_iconv(gNativeToUnicode, input, &inLeft, (char **) output, &outLeft);
         495                 :
         496          215382 :         *inputLeft = inLeft;
         497          215382 :         *outputLeft = outLeft / 2;
         498          215382 :         if (res != (size_t) -1)
         499          215382 :             return NS_OK;
         500                 :
         501               0 :         NS_WARNING("conversion from native to utf-16 failed");
         502                 :
         503                 :         // reset converter
         504               0 :         xp_iconv_reset(gNativeToUnicode);
         505                 :     }
         506                 : #if defined(ENABLE_UTF8_FALLBACK_SUPPORT)
         507                 :     else if ((gNativeToUTF8 != INVALID_ICONV_T) &&
         508                 :              (gUTF8ToUnicode != INVALID_ICONV_T)) {
         509                 :         // convert first to UTF8, then from UTF8 to UCS2
         510                 :         const char *in = *input;
         511                 :
         512                 :         char ubuf[1024];
         513                 :
         514                 :         // we assume we're always called with enough space in |output|,
         515                 :         // so convert many chars at a time...
         516                 :         while (inLeft) {
         517                 :             char *p = ubuf;
         518                 :             size_t n = sizeof(ubuf);
         519                 :             res = xp_iconv(gNativeToUTF8, &in, &inLeft, &p, &n);
         520                 :             if (res == (size_t) -1) {
         521                 :                 NS_ERROR("conversion from native to utf-8 failed");
         522                 :                 break;
         523                 :             }
         524                 :             NS_ASSERTION(outLeft > 0, "bad assumption");
         525                 :             p = ubuf;
         526                 :             n = sizeof(ubuf) - n;
         527                 :             res = xp_iconv(gUTF8ToUnicode, (const char **) &p, &n, (char **) output, &outLeft);
         528                 :             if (res == (size_t) -1) {
         529                 :                 NS_ERROR("conversion from utf-8 to utf-16 failed");
         530                 :                 break;
         531                 :             }
         532                 :         }
         533                 :
         534                 :         (*input) += (*inputLeft - inLeft);
         535                 :         *inputLeft = inLeft;
         536                 :         *outputLeft = outLeft / 2;
         537                 :
         538                 :         if (res != (size_t) -1)
         539                 :             return NS_OK;
         540                 :
         541                 :         // reset converters
         542                 :         xp_iconv_reset(gNativeToUTF8);
         543                 :         xp_iconv_reset(gUTF8ToUnicode);
         544                 :     }
         545                 : #endif
         546                 :
         547                 :     // fallback: zero-pad and hope for the best
         548                 :     // XXX This is lame and we have to do better.
         549               0 :     isolatin1_to_utf16(input, inputLeft, output, outputLeft);
         550                 :
         551               0 :     return NS_OK;
         552                 : }
         553                 :
         554                 : nsresult
         555          227484 : nsNativeCharsetConverter::UnicodeToNative(const PRUnichar **input,
         556                 :                                           PRUint32         *inputLeft,
         557                 :                                           char            **output,
         558                 :                                           PRUint32         *outputLeft)
         559                 : {
         560          227484 :     size_t res = 0;
         561          227484 :     size_t inLeft = (size_t) *inputLeft * 2;
         562          227484 :     size_t outLeft = (size_t) *outputLeft;
         563                 :
         564          227484 :     if (gUnicodeToNative != INVALID_ICONV_T) {
         565          227484 :         res = xp_iconv(gUnicodeToNative, (const char **) input, &inLeft, output, &outLeft);
         566                 :
         567          227484 :         if (res != (size_t) -1) {
         568          227484 :             *inputLeft = inLeft / 2;
         569          227484 :             *outputLeft = outLeft;
         570          227484 :             return NS_OK;
         571                 :         }
         572                 :
         573               0 :         NS_ERROR("iconv failed");
         574                 :
         575                 :         // reset converter
         576               0 :         xp_iconv_reset(gUnicodeToNative);
         577                 :     }
         578                 : #if defined(ENABLE_UTF8_FALLBACK_SUPPORT)
         579                 :     else if ((gUnicodeToUTF8 != INVALID_ICONV_T) &&
         580                 :              (gUTF8ToNative != INVALID_ICONV_T)) {
         581                 :         const char *in = (const char *) *input;
         582                 :
         583                 :         char ubuf[6]; // max utf-8 char length (really only needs to be 4 bytes)
         584                 :
         585                 :         // convert one uchar at a time...
         586                 :         while (inLeft && outLeft) {
         587                 :             char *p = ubuf;
         588                 :             size_t n = sizeof(ubuf), one_uchar = sizeof(PRUnichar);
         589                 :             res = xp_iconv(gUnicodeToUTF8, &in, &one_uchar, &p, &n);
         590                 :             if (res == (size_t) -1) {
         591                 :                 NS_ERROR("conversion from utf-16 to utf-8 failed");
         592                 :                 break;
         593                 :             }
         594                 :             p = ubuf;
         595                 :             n = sizeof(ubuf) - n;
         596                 :             res = xp_iconv(gUTF8ToNative, (const char **) &p, &n, output, &outLeft);
         597                 :             if (res == (size_t) -1) {
         598                 :                 if (errno == E2BIG) {
         599                 :                     // not enough room for last uchar... back up and return.
         600                 :                     in -= sizeof(PRUnichar);
         601                 :                     res = 0;
         602                 :                 }
         603                 :                 else
         604                 :                     NS_ERROR("conversion from utf-8 to native failed");
         605                 :                 break;
         606                 :             }
         607                 :             inLeft -= sizeof(PRUnichar);
         608                 :         }
         609                 :
         610                 :         if (res != (size_t) -1) {
         611                 :             (*input) += (*inputLeft - inLeft/2);
         612                 :             *inputLeft = inLeft/2;
         613                 :             *outputLeft = outLeft;
         614                 :             return NS_OK;
         615                 :         }
         616                 :
         617                 :         // reset converters
         618                 :         xp_iconv_reset(gUnicodeToUTF8);
         619                 :         xp_iconv_reset(gUTF8ToNative);
         620                 :     }
         621                 : #endif
         622                 :
         623                 :     // fallback: truncate and hope for the best
         624               0 :     utf16_to_isolatin1(input, inputLeft, output, outputLeft);
         625                 :
         626               0 :     return NS_OK;
         627                 : }
         628                 :
         629                 : bool
         630           62059 : nsNativeCharsetConverter::IsNativeUTF8()
         631                 : {
         632           62059 :     if (!gInitialized) {
         633               0 :         Lock();
         634               0 :         if (!gInitialized)
         635               0 :            LazyInit();
         636               0 :         Unlock();
         637                 :     }
         638           62059 :     return gIsNativeUTF8;
         639                 : }
         640                 :
         641                 : #endif // USE_ICONV
         642                 :
         643                 : //-----------------------------------------------------------------------------
         644                 : // conversion using mb[r]towc/wc[r]tomb
         645                 : //-----------------------------------------------------------------------------
         646                 : #if defined(USE_STDCONV)
         647                 : #if defined(HAVE_WCRTOMB) || defined(HAVE_MBRTOWC)
         648                 : #include <wchar.h>    // mbrtowc, wcrtomb
         649                 : #endif
         650                 :
         651                 : class nsNativeCharsetConverter
         652                 : {
         653                 : public:
         654                 :     nsNativeCharsetConverter();
         655                 :
         656                 :     nsresult NativeToUnicode(const char      **input , PRUint32 *inputLeft,
         657                 :                              PRUnichar       **output, PRUint32 *outputLeft);
         658                 :     nsresult UnicodeToNative(const PRUnichar **input , PRUint32 *inputLeft,
         659                 :                              char            **output, PRUint32 *outputLeft);
         660                 :
         661                 :     static void GlobalInit();
         662                 :     static void GlobalShutdown() { }
         663                 :     static bool IsNativeUTF8();
         664                 :
         665                 : private:
         666                 :     static bool gWCharIsUnicode;
         667                 :
         668                 : #if defined(HAVE_WCRTOMB) || defined(HAVE_MBRTOWC)
         669                 :     mbstate_t ps;
         670                 : #endif
         671                 : };
         672                 :
         673                 : bool nsNativeCharsetConverter::gWCharIsUnicode = false;
         674                 :
         675                 : nsNativeCharsetConverter::nsNativeCharsetConverter()
         676                 : {
         677                 : #if defined(HAVE_WCRTOMB) || defined(HAVE_MBRTOWC)
         678                 :     memset(&ps, 0, sizeof(ps));
         679                 : #endif
         680                 : }
         681                 :
         682                 : void
         683                 : nsNativeCharsetConverter::GlobalInit()
         684                 : {
         685                 :     // verify that wchar_t for the current locale is actually unicode.
         686                 :     // if it is not, then we should avoid calling mbtowc/wctomb and
         687                 :     // just fallback on zero-pad/truncation conversion.
         688                 :     //
         689                 :     // this test cannot be done at build time because the encoding of
         690                 :     // wchar_t may depend on the runtime locale.  sad, but true!!
         691                 :     //
         692                 :     // so, if wchar_t is unicode then converting an ASCII character
         693                 :     // to wchar_t should not change its numeric value.  we'll just
         694                 :     // check what happens with the ASCII 'a' character.
         695                 :     //
         696                 :     // this test is not perfect... obviously, it could yield false
         697                 :     // positives, but then at least ASCII text would be converted
         698                 :     // properly (or maybe just the 'a' character) -- oh well :(
         699                 :
         700                 :     char a = 'a';
         701                 :     unsigned int w = 0;
         702                 :
         703                 :     int res = mbtowc((wchar_t *) &w, &a, 1);
         704                 :
         705                 :     gWCharIsUnicode = (res != -1 && w == 'a');
         706                 :
         707                 : #ifdef DEBUG
         708                 :     if (!gWCharIsUnicode)
         709                 :         NS_WARNING("wchar_t is not unicode (unicode conversion will be lossy)");
         710                 : #endif
         711                 : }
         712                 :
         713                 : nsresult
         714                 : nsNativeCharsetConverter::NativeToUnicode(const char **input,
         715                 :                                           PRUint32    *inputLeft,
         716                 :                                           PRUnichar  **output,
         717                 :                                           PRUint32    *outputLeft)
         718                 : {
         719                 :     if (gWCharIsUnicode) {
         720                 :         int incr;
         721                 :
         722                 :         // cannot use wchar_t here since it may have been redefined (e.g.,
         723                 :         // via -fshort-wchar).  hopefully, sizeof(tmp) is sufficient XP.
         724                 :         unsigned int tmp = 0;
         725                 :         while (*inputLeft && *outputLeft) {
         726                 : #ifdef HAVE_MBRTOWC
         727                 :             incr = (int) mbrtowc((wchar_t *) &tmp, *input, *inputLeft, &ps);
         728                 : #else
         729                 :             // XXX is this thread-safe?
         730                 :             incr = (int) mbtowc((wchar_t *) &tmp, *input, *inputLeft);
         731                 : #endif
         732                 :             if (incr < 0) {
         733                 :                 NS_WARNING("mbtowc failed: possible charset mismatch");
         734                 :                 // zero-pad and hope for the best
         735                 :                 tmp = (unsigned char) **input;
         736                 :                 incr = 1;
         737                 :             }
         738                 :             **output = (PRUnichar) tmp;
         739                 :             (*input) += incr;
         740                 :             (*inputLeft) -= incr;
         741                 :             (*output)++;
         742                 :             (*outputLeft)--;
         743                 :         }
         744                 :     }
         745                 :     else {
         746                 :         // wchar_t isn't unicode, so the best we can do is treat the
         747                 :         // input as if it is isolatin1 :(
         748                 :         isolatin1_to_utf16(input, inputLeft, output, outputLeft);
         749                 :     }
         750                 :
         751                 :     return NS_OK;
         752                 : }
         753                 :
         754                 : nsresult
         755                 : nsNativeCharsetConverter::UnicodeToNative(const PRUnichar **input,
         756                 :                                           PRUint32         *inputLeft,
         757                 :                                           char            **output,
         758                 :                                           PRUint32         *outputLeft)
         759                 : {
         760                 :     if (gWCharIsUnicode) {
         761                 :         int incr;
         762                 :
         763                 :         while (*inputLeft && *outputLeft >= MB_CUR_MAX) {
         764                 : #ifdef HAVE_WCRTOMB
         765                 :             incr = (int) wcrtomb(*output, (wchar_t) **input, &ps);
         766                 : #else
         767                 :             // XXX is this thread-safe?
         768                 :             incr = (int) wctomb(*output, (wchar_t) **input);
         769                 : #endif
         770                 :             if (incr < 0) {
         771                 :                 NS_WARNING("mbtowc failed: possible charset mismatch");
         772                 :                 **output = (unsigned char) **input; // truncate
         773                 :                 incr = 1;
         774                 :             }
         775                 :             // most likely we're dead anyways if this assertion should fire
         776                 :             NS_ASSERTION(PRUint32(incr) <= *outputLeft, "wrote beyond end of string");
         777                 :             (*output) += incr;
         778                 :             (*outputLeft) -= incr;
         779                 :             (*input)++;
         780                 :             (*inputLeft)--;
         781                 :         }
         782                 :     }
         783                 :     else {
         784                 :         // wchar_t isn't unicode, so the best we can do is treat the
         785                 :         // input as if it is isolatin1 :(
         786                 :         utf16_to_isolatin1(input, inputLeft, output, outputLeft);
         787                 :     }
         788                 :
         789                 :     return NS_OK;
         790                 : }
         791                 :
         792                 : // XXX : for now, return false
         793                 : bool
         794                 : nsNativeCharsetConverter::IsNativeUTF8()
         795                 : {
         796                 :     return false;
         797                 : }
         798                 :
         799                 : #endif // USE_STDCONV
         800                 :
         801                 : //-----------------------------------------------------------------------------
         802                 : // API implementation
         803                 : //-----------------------------------------------------------------------------
         804                 :
         805                 : nsresult
         806          215382 : NS_CopyNativeToUnicode(const nsACString &input, nsAString &output)
         807                 : {
         808          215382 :     output.Truncate();
         809                 :
         810          215382 :     PRUint32 inputLen = input.Length();
         811                 :
         812          215382 :     nsACString::const_iterator iter;
         813          215382 :     input.BeginReading(iter);
         814                 :
         815                 :     //
         816                 :     // OPTIMIZATION: preallocate space for largest possible result; convert
         817                 :     // directly into the result buffer to avoid intermediate buffer copy.
         818                 :     //
         819                 :     // this will generally result in a larger allocation, but that seems
         820                 :     // better than an extra buffer copy.
         821                 :     //
         822          215382 :     if (!EnsureStringLength(output, inputLen))
         823               0 :         return NS_ERROR_OUT_OF_MEMORY;
         824          215382 :     nsAString::iterator out_iter;
         825          215382 :     output.BeginWriting(out_iter);
         826                 :
         827          215382 :     PRUnichar *result = out_iter.get();
         828          215382 :     PRUint32 resultLeft = inputLen;
         829                 :
         830          215382 :     const char *buf = iter.get();
         831          215382 :     PRUint32 bufLeft = inputLen;
         832                 :
         833          430764 :     nsNativeCharsetConverter conv;
         834          215382 :     nsresult rv = conv.NativeToUnicode(&buf, &bufLeft, &result, &resultLeft);
         835          215382 :     if (NS_SUCCEEDED(rv)) {
         836          215382 :         NS_ASSERTION(bufLeft == 0, "did not consume entire input buffer");
         837          215382 :         output.SetLength(inputLen - resultLeft);
         838                 :     }
         839          215382 :     return rv;
         840                 : }
         841                 :
         842                 : nsresult
         843          228665 : NS_CopyUnicodeToNative(const nsAString &input, nsACString &output)
         844                 : {
         845          228665 :     output.Truncate();
         846                 :
         847          228665 :     nsAString::const_iterator iter, end;
         848          228665 :     input.BeginReading(iter);
         849          228665 :     input.EndReading(end);
         850                 :
         851                 :     // cannot easily avoid intermediate buffer copy.
         852                 :     char temp[4096];
         853                 :
         854          457330 :     nsNativeCharsetConverter conv;
         855                 :
         856          228665 :     const PRUnichar *buf = iter.get();
         857          228665 :     PRUint32 bufLeft = Distance(iter, end);
         858          684814 :     while (bufLeft) {
         859          227484 :         char *p = temp;
         860          227484 :         PRUint32 tempLeft = sizeof(temp);
         861                 :
         862          227484 :         nsresult rv = conv.UnicodeToNative(&buf, &bufLeft, &p, &tempLeft);
         863          227484 :         if (NS_FAILED(rv)) return rv;
         864                 :
         865          227484 :         if (tempLeft < sizeof(temp))
         866          227484 :             output.Append(temp, sizeof(temp) - tempLeft);
         867                 :     }
         868          228665 :     return NS_OK;
         869                 : }
         870                 :
         871                 : bool
         872           62059 : NS_IsNativeUTF8()
         873                 : {
         874           62059 :     return nsNativeCharsetConverter::IsNativeUTF8();
         875                 : }
         876                 :
         877                 : void
         878            1365 : NS_StartupNativeCharsetUtils()
         879                 : {
         880                 :     //
         881                 :     // need to initialize the locale or else charset conversion will fail.
         882                 :     // better not delay this in case some other component alters the locale
         883                 :     // settings.
         884                 :     //
         885                 :     // XXX we assume that we are called early enough that we should
         886                 :     // always be the first to care about the locale's charset.
         887                 :     //
         888            1365 :     setlocale(LC_CTYPE, "");
         889                 :
         890            1365 :     nsNativeCharsetConverter::GlobalInit();
         891            1365 : }
         892                 :
         893                 : void
         894            1365 : NS_ShutdownNativeCharsetUtils()
         895                 : {
         896            1365 :     nsNativeCharsetConverter::GlobalShutdown();
         897            1365 : }
         898                 :
         899                 : //-----------------------------------------------------------------------------
         900                 : // XP_WIN
         901                 : //-----------------------------------------------------------------------------
         902                 : #elif defined(XP_WIN)
         903                 :
         904                 : #include <windows.h>
         905                 : #include "nsAString.h"
         906                 : #include "nsReadableUtils.h"
         907                 :
         908                 : nsresult
         909                 : NS_CopyNativeToUnicode(const nsACString &input, nsAString &output)
         910                 : {
         911                 :     PRUint32 inputLen = input.Length();
         912                 :
         913                 :     nsACString::const_iterator iter;
         914                 :     input.BeginReading(iter);
         915                 :
         916                 :     const char *buf = iter.get();
         917                 :
         918                 :     // determine length of result
         919                 :     PRUint32 resultLen = 0;
         920                 :     int n = ::MultiByteToWideChar(CP_ACP, 0, buf, inputLen, NULL, 0);
         921                 :     if (n > 0)
         922                 :         resultLen += n;
         923                 :
         924                 :     // allocate sufficient space
         925                 :     if (!EnsureStringLength(output, resultLen))
         926                 :         return NS_ERROR_OUT_OF_MEMORY;
         927                 :     if (resultLen > 0) {
         928                 :         nsAString::iterator out_iter;
         929                 :         output.BeginWriting(out_iter);
         930                 :
         931                 :         PRUnichar *result = out_iter.get();
         932                 :
         933                 :         ::MultiByteToWideChar(CP_ACP, 0, buf, inputLen, result, resultLen);
         934                 :     }
         935                 :     return NS_OK;
         936                 : }
         937                 :
         938                 : nsresult
         939                 : NS_CopyUnicodeToNative(const nsAString  &input, nsACString &output)
         940                 : {
         941                 :     PRUint32 inputLen = input.Length();
         942                 :
         943                 :     nsAString::const_iterator iter;
         944                 :     input.BeginReading(iter);
         945                 :
         946                 :     const PRUnichar *buf = iter.get();
         947                 :
         948                 :     // determine length of result
         949                 :     PRUint32 resultLen = 0;
         950                 :
         951                 :     int n = ::WideCharToMultiByte(CP_ACP, 0, buf, inputLen, NULL, 0, NULL, NULL);
         952                 :     if (n > 0)
         953                 :         resultLen += n;
         954                 :
         955                 :     // allocate sufficient space
         956                 :     if (!EnsureStringLength(output, resultLen))
         957                 :         return NS_ERROR_OUT_OF_MEMORY;
         958                 :     if (resultLen > 0) {
         959                 :         nsACString::iterator out_iter;
         960                 :         output.BeginWriting(out_iter);
         961                 :
         962                 :         // default "defaultChar" is '?', which is an illegal character on windows
         963                 :         // file system.  That will cause file uncreatable. Change it to '_'
         964                 :         const char defaultChar = '_';
         965                 :
         966                 :         char *result = out_iter.get();
         967                 :
         968                 :         ::WideCharToMultiByte(CP_ACP, 0, buf, inputLen, result, resultLen,
         969                 :                               &defaultChar, NULL);
         970                 :     }
         971                 :     return NS_OK;
         972                 : }
         973                 :
         974                 : // moved from widget/windows/nsToolkit.cpp
         975                 : PRInt32
         976                 : NS_ConvertAtoW(const char *aStrInA, int aBufferSize, PRUnichar *aStrOutW)
         977                 : {
         978                 :     return MultiByteToWideChar(CP_ACP, 0, aStrInA, -1, aStrOutW, aBufferSize);
         979                 : }
         980                 :
         981                 : PRInt32
         982                 : NS_ConvertWtoA(const PRUnichar *aStrInW, int aBufferSizeOut,
         983                 :                char *aStrOutA, const char *aDefault)
         984                 : {
         985                 :     if ((!aStrInW) || (!aStrOutA) || (aBufferSizeOut <= 0))
         986                 :         return 0;
         987                 :
         988                 :     int numCharsConverted = WideCharToMultiByte(CP_ACP, 0, aStrInW, -1,
         989                 :                                                 aStrOutA, aBufferSizeOut,
         990                 :                                                 aDefault, NULL);
         991                 :
         992                 :     if (!numCharsConverted) {
         993                 :         if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
         994                 :             // Overflow, add missing null termination but return 0
         995                 :             aStrOutA[aBufferSizeOut-1] = '\0';
         996                 :         }
         997                 :         else {
         998                 :             // Other error, clear string and return 0
         999                 :             aStrOutA[0] = '\0';
        1000                 :         }
        1001                 :     }
        1002                 :     else if (numCharsConverted < aBufferSizeOut) {
        1003                 :         // Add 2nd null (really necessary?)
        1004                 :         aStrOutA[numCharsConverted] = '\0';
        1005                 :     }
        1006                 :
        1007                 :     return numCharsConverted;
        1008                 : }
        1009                 :
        1010                 : //-----------------------------------------------------------------------------
        1011                 : // XP_OS2
        1012                 : //-----------------------------------------------------------------------------
        1013                 : #elif defined(XP_OS2)
        1014                 :
        1015                 : #define INCL_DOS
        1016                 : #include <os2.h>
        1017                 : #include <uconv.h>
        1018                 : #include "nsAString.h"
        1019                 : #include "nsReadableUtils.h"
        1020                 : #include <ulserrno.h>
        1021                 : #include "nsNativeCharsetUtils.h"
        1022                 :
        1023                 : static UconvObject UnicodeConverter = NULL;
        1024                 :
        1025                 : nsresult
        1026                 : NS_CopyNativeToUnicode(const nsACString &input, nsAString  &output)
        1027                 : {
        1028                 :     PRUint32 inputLen = input.Length();
        1029                 :
        1030                 :     nsACString::const_iterator iter;
        1031                 :     input.BeginReading(iter);
        1032                 :     const char *inputStr = iter.get();
        1033                 :
        1034                 :     // determine length of result
        1035                 :     PRUint32 resultLen = inputLen;
        1036                 :     if (!EnsureStringLength(output, resultLen))
        1037                 :         return NS_ERROR_OUT_OF_MEMORY;
        1038                 :
        1039                 :     nsAString::iterator out_iter;
        1040                 :     output.BeginWriting(out_iter);
        1041                 :     UniChar *result = (UniChar*)out_iter.get();
        1042                 :
        1043                 :     size_t cSubs = 0;
        1044                 :     size_t resultLeft = resultLen;
        1045                 :
        1046                 :     if (!UnicodeConverter)
        1047                 :       NS_StartupNativeCharsetUtils();
        1048                 :
        1049                 :     int unirc = ::UniUconvToUcs(UnicodeConverter, (void**)&inputStr, &inputLen,
        1050                 :                                 &result, &resultLeft, &cSubs);
        1051                 :
        1052                 :     NS_ASSERTION(unirc != UCONV_E2BIG, "Path too big");
        1053                 :
        1054                 :     if (unirc != ULS_SUCCESS) {
        1055                 :         output.Truncate();
        1056                 :         return NS_ERROR_FAILURE;
        1057                 :     }
        1058                 :
        1059                 :     // Need to update string length to reflect how many bytes were actually
        1060                 :     // written.
        1061                 :     output.Truncate(resultLen - resultLeft);
        1062                 :     return NS_OK;
        1063                 : }
        1064                 :
        1065                 : nsresult
        1066                 : NS_CopyUnicodeToNative(const nsAString &input, nsACString &output)
        1067                 : {
        1068                 :     size_t inputLen = input.Length();
        1069                 :
        1070                 :     nsAString::const_iterator iter;
        1071                 :     input.BeginReading(iter);
        1072                 :     UniChar* inputStr = (UniChar*) const_cast<PRUnichar*>(iter.get());
        1073                 :
        1074                 :     // maximum length of unicode string of length x converted to native
        1075                 :     // codepage is x*2
        1076                 :     size_t resultLen = inputLen * 2;
        1077                 :     if (!EnsureStringLength(output, resultLen))
        1078                 :         return NS_ERROR_OUT_OF_MEMORY;
        1079                 :
        1080                 :     nsACString::iterator out_iter;
        1081                 :     output.BeginWriting(out_iter);
        1082                 :     char *result = out_iter.get();
        1083                 :
        1084                 :     size_t cSubs = 0;
        1085                 :     size_t resultLeft = resultLen;
        1086                 :
        1087                 :     if (!UnicodeConverter)
        1088                 :       NS_StartupNativeCharsetUtils();
        1089                 :
        1090                 :     int unirc = ::UniUconvFromUcs(UnicodeConverter, &inputStr, &inputLen,
        1091                 :                                   (void**)&result, &resultLeft, &cSubs);
        1092                 :
        1093                 :     NS_ASSERTION(unirc != UCONV_E2BIG, "Path too big");
        1094                 :
        1095                 :     if (unirc != ULS_SUCCESS) {
        1096                 :         output.Truncate();
        1097                 :         return NS_ERROR_FAILURE;
        1098                 :     }
        1099                 :
        1100                 :     // Need to update string length to reflect how many bytes were actually
        1101                 :     // written.
        1102                 :     output.Truncate(resultLen - resultLeft);
        1103                 :     return NS_OK;
        1104                 : }
        1105                 :
        1106                 : void
        1107                 : NS_StartupNativeCharsetUtils()
        1108                 : {
        1109                 :     ULONG ulLength;
        1110                 :     ULONG ulCodePage;
        1111                 :     DosQueryCp(sizeof(ULONG), &ulCodePage, &ulLength);
        1112                 :
        1113                 :     UniChar codepage[20];
        1114                 :     int unirc = ::UniMapCpToUcsCp(ulCodePage, codepage, 20);
        1115                 :     if (unirc == ULS_SUCCESS) {
        1116                 :         unirc = ::UniCreateUconvObject(codepage, &UnicodeConverter);
        1117                 :         if (unirc == ULS_SUCCESS) {
        1118                 :             uconv_attribute_t attr;
        1119                 :             ::UniQueryUconvObject(UnicodeConverter, &attr, sizeof(uconv_attribute_t),
        1120                 :                                   NULL, NULL, NULL);
        1121                 :             attr.options = UCONV_OPTION_SUBSTITUTE_BOTH;
        1122                 :             attr.subchar_len=1;
        1123                 :             attr.subchar[0]='_';
        1124                 :             ::UniSetUconvObject(UnicodeConverter, &attr);
        1125                 :         }
        1126                 :     }
        1127                 : }
        1128                 :
        1129                 : void
        1130                 : NS_ShutdownNativeCharsetUtils()
        1131                 : {
        1132                 :     ::UniFreeUconvObject(UnicodeConverter);
        1133                 : }
        1134                 :
        1135                 : #else
        1136                 :
        1137                 : #include "nsReadableUtils.h"
        1138                 :
        1139                 : nsresult
        1140                 : NS_CopyNativeToUnicode(const nsACString &input, nsAString  &output)
        1141                 : {
        1142                 :     CopyASCIItoUTF16(input, output);
        1143                 :     return NS_OK;
        1144                 : }
        1145                 :
        1146                 : nsresult
        1147                 : NS_CopyUnicodeToNative(const nsAString  &input, nsACString &output)
        1148                 : {
        1149                 :     LossyCopyUTF16toASCII(input, output);
        1150                 :     return NS_OK;
        1151                 : }
        1152                 :
        1153                 : void
        1154                 : NS_StartupNativeCharsetUtils()
        1155                 : {
        1156                 : }
        1157                 :
        1158                 : void
        1159                 : NS_ShutdownNativeCharsetUtils()
        1160                 : {
        1161                 : }
        1162                 :
        1163                 : #endif

Generated by: LCOV version 1.7