VirtualBox

Changeset 28903 in vbox for trunk/src/VBox/Runtime


Ignore:
Timestamp:
Apr 29, 2010 2:58:12 PM (15 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
60847
Message:

IPRT: iconv cache.

Location:
trunk/src/VBox/Runtime
Files:
10 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Runtime/Makefile.kmk

    r28892 r28903  
    187187endif
    188188ifdef VBOX_MAIN_RELEASE_LOG ## @todo (dmik): temporary, until RTThreadSelf/RTThreadAdopt are properly updated
    189  RuntimeR3_DEFS         += RTCRITSECT_STRICT
     189 RuntimeR3_DEFS        += RTCRITSECT_STRICT
    190190endif
    191191ifdef IPRT_WITH_LZJB
    192  RuntimeR3_DEFS         += RTZIP_USE_LZJB
     192 RuntimeR3_DEFS        += RTZIP_USE_LZJB
    193193endif
    194194ifdef IPRT_WITH_LZO
    195  RuntimeR3_DEFS         += RTZIP_USE_LZO
     195 RuntimeR3_DEFS        += RTZIP_USE_LZO
     196endif
     197ifn1of ($(KBUILD_TARGET), win)
     198 RuntimeR3_DEFS        += RT_WITH_ICONV_CACHE
    196199endif
    197200ifdef IPRT_WITH_FUTEX_BASED_SEMS
    198  RuntimeR3_DEFS.linux   += IPRT_WITH_FUTEX_BASED_SEMS
     201 RuntimeR3_DEFS.linux  += IPRT_WITH_FUTEX_BASED_SEMS
    199202endif
    200203RuntimeR3_INCS          = \
  • trunk/src/VBox/Runtime/common/misc/thread.cpp

    r28800 r28903  
    4949#include "internal/sched.h"
    5050#include "internal/process.h"
     51#ifdef RT_WITH_ICONV_CACHE
     52# include "internal/string.h"
     53#endif
    5154
    5255
     
    354357#ifdef IN_RING3
    355358        rtLockValidatorInitPerThread(&pThread->LockValidator);
     359#endif
     360#ifdef RT_WITH_ICONV_CACHE
     361        rtStrIconvCacheInit(pThread);
    356362#endif
    357363        int rc = RTSemEventMultiCreate(&pThread->EventUser);
     
    575581
    576582    rtLockValidatorDeletePerThread(&pThread->LockValidator);
     583#endif
     584#ifdef RT_WITH_ICONV_CACHE
     585    rtStrIconvCacheDestroy(pThread);
    577586#endif
    578587    ASMAtomicXchgU32(&pThread->u32Magic, RTTHREADINT_MAGIC_DEAD);
  • trunk/src/VBox/Runtime/common/string/utf-8-case.cpp

    r28800 r28903  
    109109    }
    110110
    111     /* Hit some bad encoding, continue in case insensitive mode. */
     111    /* Hit some bad encoding, continue in case sensitive mode. */
    112112    return RTStrCmp(psz1, psz2);
    113113}
  • trunk/src/VBox/Runtime/common/string/utf-8.cpp

    r28800 r28903  
    5252 *                          on success (cch = cb again). Optional.
    5353 */
    54 static int rtUtf8Length(const char *psz, size_t cch, size_t *pcuc, size_t *pcchActual)
     54int rtUtf8Length(const char *psz, size_t cch, size_t *pcuc, size_t *pcchActual)
    5555{
    5656    const unsigned char *puch = (const unsigned char *)psz;
     
    316316    }
    317317    return rc;
    318 
    319 
    320     return RTStrUniLenEx(psz, cch, &cCpsIgnored);
    321318}
    322319RT_EXPORT_SYMBOL(RTStrValidateEncodingEx);
  • trunk/src/VBox/Runtime/generic/pathhost-generic.cpp

    r28880 r28903  
    3030*******************************************************************************/
    3131#define LOG_GROUP RTLOGGROUP_PATH
     32#include "internal/iprt.h"
     33#include "internal/path.h"
     34#include "internal/thread.h"
     35
     36#include <iprt/env.h>
    3237#include <iprt/string.h>
    33 #include "internal/iprt.h"
    34 
    35 #include "internal/path.h"
     38#include <iprt/once.h>
     39
     40
     41/*******************************************************************************
     42*   Global Variables                                                           *
     43*******************************************************************************/
     44/** Initialize once object. */
     45static RTONCE       g_OnceInitPathConv = RTONCE_INITIALIZER;
     46/** If set, then we can pass UTF-8 thru directly. */
     47static bool         g_fPassthruUtf8    = false;
     48/** The UTF-8 to FS iconv cache entry. */
     49static RTSTRICONV   g_enmUtf8ToFsIdx   = RTSTRICONV_UTF8_TO_LOCALE;
     50/** The FS to UTF-8 iconv cache entry. */
     51static RTSTRICONV   g_enmFsToUtf8Idx   = RTSTRICONV_LOCALE_TO_UTF8;
     52/** The codeset we're using. */
     53static char         g_szFsCodeset[32];
     54
     55
     56/**
     57 * Do a case insensitive compare where the 2nd string is known and can be case
     58 * folded when writing the code.
     59 *
     60 * @returns see strcmp.
     61 * @param   pszStr1             The string to compare against pszLower and
     62 *                              pszUpper.
     63 * @param   pszUpper            The upper case edition of the 2nd string.
     64 * @param   pszLower            The lower case edition of the 2nd string.
     65 */
     66static int rtPathStrICmp(const char *pszStr1, const char *pszUpper, const char *pszLower)
     67{
     68    Assert(strlen(pszLower) == strlen(pszUpper));
     69    for (;;)
     70    {
     71        char ch1      = *pszStr1++;
     72        char ch2Upper = *pszUpper++;
     73        char ch2Lower = *pszLower++;
     74        if (   ch1 != ch2Upper
     75            && ch1 != ch2Lower)
     76            return ch1 < ch2Upper ? -1 : 1;
     77        if (!ch1)
     78            return 0;
     79    }
     80}
     81
     82/**
     83 * Is the specified codeset something we can treat as UTF-8.
     84 *
     85 * @returns true if we can do UTF-8 passthru, false if not.
     86 * @param   pszCodeset          The codeset in question.
     87 */
     88static bool rtPathConvInitIsUtf8(const char *pszCodeset)
     89{
     90    /* Paranoia. */
     91    if (!pszCodeset)
     92        return false;
     93
     94    /*
     95     * Avoid RTStrICmp at this point.
     96     */
     97    static struct
     98    {
     99        const char *pszUpper;
     100        const char *pszLower;
     101    } const s_aUtf8Compatible[] =
     102    {
     103        /* The default locale. */
     104        { "C"                   , "c"                   },
     105        { "POSIX"               , "posix"               },
     106        /* 7-bit ASCII. */
     107        { "ANSI_X3.4-1968"      , "ansi_x3.4-1968"      },
     108        { "ANSI_X3.4-1986"      , "ansi_x3.4-1986"      },
     109        { "US-ASCII"            , "us-ascii"            },
     110        { "ISO646-US"           , "iso646-us"           },
     111        { "ISO_646.IRV:1991"    , "iso_646.irv:1991"    },
     112        { "ISO-IR-6"            , "iso-ir-6"            },
     113        { "IBM367"              , "ibm367"              },
     114        /* UTF-8 */
     115        { "UTF-8"               , "utf-8"               },
     116        { "UTF8"                , "utf8"                },
     117        { "ISO-10646/UTF-8"     , "iso-10646/utf-8"     },
     118        { "ISO-10646/UTF8"      , "iso-10646/utf8"      }
     119    };
     120
     121    for (size_t i = 0; i < RT_ELEMENTS(s_aUtf8Compatible); i++)
     122        if (!rtPathStrICmp(pszCodeset, s_aUtf8Compatible[i].pszUpper, s_aUtf8Compatible[i].pszLower))
     123            return true;
     124
     125    return false;
     126}
     127
     128
     129/**
     130 * Init once for the path conversion code.
     131 *
     132 * @returns IPRT status code.
     133 * @param   pvUser1             Unused.
     134 * @param   pvUser2             Unused.
     135 */
     136static DECLCALLBACK(int32_t) rtPathConvInitOnce(void *pvUser1, void *pvUser2)
     137{
     138    /*
     139     * Read the environment variable, no mercy on misconfigs here except that
     140     * empty values are quietly ignored.  (We use a temp buffer for stripping.)
     141     */
     142    char *pszEnvValue = NULL;
     143    char  szEnvValue[sizeof(g_szFsCodeset)];
     144    int rc = RTEnvGetEx(RTENV_DEFAULT, RTPATH_CODESET_ENV_VAR, szEnvValue, sizeof(szEnvValue), NULL);
     145    if (rc != VERR_ENV_VAR_NOT_FOUND && RT_FAILURE(rc))
     146        return rc;
     147    if (RT_SUCCESS(rc))
     148        pszEnvValue = RTStrStrip(szEnvValue);
     149
     150    if (pszEnvValue && *pszEnvValue)
     151    {
     152        g_fPassthruUtf8  = rtPathConvInitIsUtf8(pszEnvValue);
     153        g_enmFsToUtf8Idx = RTSTRICONV_FS_TO_UTF8;
     154        g_enmUtf8ToFsIdx = RTSTRICONV_UTF8_TO_FS;
     155        strcpy(g_szFsCodeset, pszEnvValue);
     156    }
     157    else
     158    {
     159        const char *pszCodeset = rtStrGetLocaleCodeset();
     160        size_t      cchCodeset = pszCodeset ? strlen(pszCodeset) : sizeof(g_szFsCodeset);
     161        if (cchCodeset >= sizeof(g_szFsCodeset))
     162            /* This shouldn't happen, but we'll manage. */
     163            g_szFsCodeset[0] = '\0';
     164        else
     165        {
     166            memcpy(g_szFsCodeset, pszCodeset, cchCodeset + 1);
     167            pszCodeset = g_szFsCodeset;
     168        }
     169        g_fPassthruUtf8  = rtPathConvInitIsUtf8(pszCodeset);
     170        g_enmFsToUtf8Idx = RTSTRICONV_LOCALE_TO_UTF8;
     171        g_enmUtf8ToFsIdx = RTSTRICONV_UTF8_TO_LOCALE;
     172    }
     173
     174    NOREF(pvUser1); NOREF(pvUser2);
     175    return VINF_SUCCESS;
     176}
    36177
    37178
    38179int rtPathToNative(char **ppszNativePath, const char *pszPath)
    39180{
    40     return RTStrUtf8ToCurrentCP(ppszNativePath, pszPath);
    41 }
     181    *ppszNativePath = NULL;
     182
     183    int rc = RTOnce(&g_OnceInitPathConv, rtPathConvInitOnce, NULL, NULL);
     184    if (RT_SUCCESS(rc))
     185    {
     186        if (g_fPassthruUtf8 || !*pszPath)
     187            *ppszNativePath = (char *)pszPath;
     188        else
     189            rc = rtStrConvert(pszPath, strlen(pszPath), "UTF-8",
     190                              ppszNativePath, 0, g_szFsCodeset,
     191                              2, g_enmUtf8ToFsIdx);
     192    }
     193    return rc;
     194}
     195
    42196
    43197int rtPathToNativeEx(char **ppszNativePath, const char *pszPath, const char *pszBasePath)
    44198{
     199    /* We don't query the FS for codeset preferences yet, so nothing special to do here. */
    45200    NOREF(pszBasePath);
    46     return RTStrUtf8ToCurrentCP(ppszNativePath, pszPath);
    47 }
     201    return rtPathToNative(ppszNativePath, pszPath);
     202}
     203
    48204
    49205void rtPathFreeNative(char *pszNativePath, const char *pszPath)
    50206{
    51     if (pszNativePath)
     207    if (    pszNativePath != pszPath
     208        &&  pszNativePath)
    52209        RTStrFree(pszNativePath);
    53210}
     
    56213int rtPathFromNative(char **ppszPath, const char *pszNativePath)
    57214{
    58     return RTStrCurrentCPToUtf8(ppszPath, pszNativePath);
     215    *ppszPath = NULL;
     216
     217    int rc = RTOnce(&g_OnceInitPathConv, rtPathConvInitOnce, NULL, NULL);
     218    if (RT_SUCCESS(rc))
     219    {
     220        if (g_fPassthruUtf8 || !*pszNativePath)
     221        {
     222            size_t cCpsIgnored;
     223            size_t cchNativePath;
     224            rc = rtUtf8Length(pszNativePath, RTSTR_MAX, &cCpsIgnored, &cchNativePath);
     225            if (RT_SUCCESS(rc))
     226            {
     227                char *pszPath;
     228                *ppszPath = pszPath = RTStrAlloc(cchNativePath + 1);
     229                if (pszPath)
     230                    memcpy(pszPath, pszNativePath, cchNativePath + 1);
     231                else
     232                    rc = VERR_NO_STR_MEMORY;
     233            }
     234        }
     235        else
     236            rc = rtStrConvert(pszNativePath, strlen(pszNativePath), g_szFsCodeset,
     237                              ppszPath, 0, "UTF-8",
     238                              2, g_enmFsToUtf8Idx);
     239    }
     240    return rc;
    59241}
    60242
     
    62244int rtPathFromNativeEx(char **ppszPath, const char *pszNativePath, const char *pszBasePath)
    63245{
     246    /* We don't query the FS for codeset preferences yet, so nothing special to do here. */
    64247    NOREF(pszBasePath);
    65     return RTStrCurrentCPToUtf8(ppszPath, pszNativePath);
    66 }
    67 
     248    return rtPathFromNative(ppszPath, pszNativePath);
     249}
     250
  • trunk/src/VBox/Runtime/include/internal/path.h

    r28877 r28903  
    3737# define HAVE_DRIVE 1
    3838#endif
     39
     40/** The name of the environment variable that is used to override the default
     41 * codeset used when talking to the file systems.  This is only available on
     42 * Mac OS X and UNIX systems. */
     43#define RTPATH_CODESET_ENV_VAR          "IPRT_PATH_CODESET"
    3944
    4045
  • trunk/src/VBox/Runtime/include/internal/string.h

    r28800 r28903  
    4848#endif
    4949
    50 size_t rtstrFormatRt(PFNRTSTROUTPUT pfnOutput, void *pvArgOutput, const char **ppszFormat, va_list *pArgs, int cchWidth, int cchPrecision, unsigned fFlags, char chArgSize);
    51 size_t rtstrFormatType(PFNRTSTROUTPUT pfnOutput, void *pvArgOutput, const char **ppszFormat, va_list *pArgs, int cchWidth, int cchPrecision, unsigned fFlags, char chArgSize);
     50size_t rtstrFormatRt(PFNRTSTROUTPUT pfnOutput, void *pvArgOutput, const char **ppszFormat, va_list *pArgs,
     51                     int cchWidth, int cchPrecision, unsigned fFlags, char chArgSize);
     52size_t rtstrFormatType(PFNRTSTROUTPUT pfnOutput, void *pvArgOutput, const char **ppszFormat, va_list *pArgs,
     53                       int cchWidth, int cchPrecision, unsigned fFlags, char chArgSize);
     54
     55#ifdef RT_WITH_ICONV_CACHE
     56void rtStrIconvCacheInit(struct RTTHREADINT *pThread);
     57void rtStrIconvCacheDestroy(struct RTTHREADINT *pThread);
     58#endif
     59
     60/**
     61 * Indexes into RTTHREADINT::ahIconvs
     62 */
     63typedef enum RTSTRICONV
     64{
     65    /** UTF-8 to the locale codeset (LC_CTYPE). */
     66    RTSTRICONV_UTF8_TO_LOCALE = 0,
     67    /** The locale codeset (LC_CTYPE) to UTF-8. */
     68    RTSTRICONV_LOCALE_TO_UTF8,
     69    /** UTF-8 to the filesystem codeset - if different from the locale codeset. */
     70    RTSTRICONV_UTF8_TO_FS,
     71    /** The filesystem codeset to UTF-8. */
     72    RTSTRICONV_FS_TO_UTF8,
     73    /** The end of the valid indexes. */
     74    RTSTRICONV_END
     75} RTSTRICONV;
     76
     77int rtStrConvert(const char *pchInput, size_t cchInput, const char *pszInputCS,
     78                 char **ppszOutput, size_t cbOutput, const char *pszOutputCS,
     79                 unsigned cFactor, RTSTRICONV enmCacheIdx);
     80const char *rtStrGetLocaleCodeset(void);
     81int rtUtf8Length(const char *psz, size_t cch, size_t *pcuc, size_t *pcchActual);
    5282
    5383RT_C_DECLS_END
  • trunk/src/VBox/Runtime/include/internal/thread.h

    r28800 r28903  
    3737#include "internal/lockvalidator.h"
    3838#include "internal/magics.h"
     39#ifdef RT_WITH_ICONV_CACHE
     40# include "internal/string.h"
     41#endif
    3942
    4043RT_C_DECLS_BEGIN
    41 
    42 
    4344
    4445
     
    9798    RTLOCKVALPERTHREAD      LockValidator;
    9899#endif /* IN_RING3 */
     100#ifdef RT_WITH_ICONV_CACHE
     101    /** Handle cache for iconv.
     102     * @remarks ASSUMES sizeof(void *) >= sizeof(iconv_t). */
     103    void *ahIconvs[RTSTRICONV_END];
     104#endif
    99105#ifdef IPRT_WITH_GENERIC_TLS
    100106    /** The TLS entries for this thread. */
  • trunk/src/VBox/Runtime/r3/init.cpp

    r28800 r28903  
    234234{
    235235    /*
     236     * Init C runtime locale before we do anything that may end up converting
     237     * paths or we'll end up using the "C" locale for path conversion.
     238     */
     239    setlocale(LC_CTYPE, "");
     240
     241    /*
    236242     * The Process ID.
    237243     */
     
    309315     * The remainder cannot easily be undone, so it has to go last.
    310316     */
    311 
    312     /* Init C runtime locale. */
    313     setlocale(LC_CTYPE, "");
    314317
    315318    /* Fork and exit callbacks. */
  • trunk/src/VBox/Runtime/r3/posix/utf8-posix.cpp

    r28800 r28903  
    3030*******************************************************************************/
    3131#include <iprt/string.h>
     32#include "internal/iprt.h"
     33
    3234#include <iprt/alloc.h>
    3335#include <iprt/assert.h>
     
    4042#include <wctype.h>
    4143
    42 #ifdef RT_OS_SOLARIS
    43 # include <langinfo.h>
     44#include <langinfo.h>
     45
     46#include "internal/alignmentchecks.h"
     47#ifdef RT_WITH_ICONV_CACHE
     48# include "internal/thread.h"
     49# include "internal/string.h"
     50AssertCompile(sizeof(iconv_t) <= sizeof(void *));
    4451#endif
    4552
    46 #include "internal/alignmentchecks.h"
    47 
    48 
    49 /*******************************************************************************
    50 *   Internal Functions                                                         *
    51 *******************************************************************************/
    52 static int rtstrConvert(const void *pvInput, size_t cbInput, const char *pszInputCS, void **ppvOutput, size_t cbOutput, const char *pszOutputCS, unsigned cFactor);
     53
     54/**
     55 * Gets the codeset of the current locale (LC_CTYPE).
     56 *
     57 * @returns Pointer to read-only string with the codeset name.
     58 */
     59const char *rtStrGetLocaleCodeset(void)
     60{
     61    return nl_langinfo(CODESET);
     62}
     63
     64
     65#ifdef RT_WITH_ICONV_CACHE
     66
     67/**
     68 * Initializes the iconv handle cache associated with a thread.
     69 *
     70 * @param   pThread             The thread in question.
     71 */
     72void rtStrIconvCacheInit(PRTTHREADINT pThread)
     73{
     74    for (size_t i = 0; i < RT_ELEMENTS(pThread->ahIconvs); i++)
     75        pThread->ahIconvs[i] = (iconv_t)-1;
     76}
     77
     78/**
     79 * Destroys the iconv handle cache associated with a thread.
     80 *
     81 * @param   pThread             The thread in question.
     82 */
     83void rtStrIconvCacheDestroy(PRTTHREADINT pThread)
     84{
     85    for (size_t i = 0; i < RT_ELEMENTS(pThread->ahIconvs); i++)
     86    {
     87        iconv_t hIconv = pThread->ahIconvs[i];
     88        pThread->ahIconvs[i] = NULL;
     89        if (hIconv != (iconv_t)-1)
     90            iconv_close(hIconv);
     91    }
     92}
    5393
    5494
     
    66106 * @param   pszOutputCS     Codeset of the input string.
    67107 * @param   cFactor         Input vs. output size factor.
    68  */
    69 static int rtstrConvert(const void *pvInput, size_t cbInput, const char *pszInputCS, void **ppvOutput, size_t cbOutput, const char *pszOutputCS, unsigned cFactor)
     108 * @param   phIconv         Pointer to the cache entry.
     109 */
     110static int rtstrConvertCached(const void *pvInput, size_t cbInput, const char *pszInputCS,
     111                              void **ppvOutput, size_t cbOutput, const char *pszOutputCS,
     112                              unsigned cFactor, iconv_t *phIconv)
     113{
     114    /*
     115     * Allocate buffer
     116     */
     117    bool    fUcs2Term;
     118    void   *pvOutput;
     119    size_t  cbOutput2;
     120    if (!cbOutput)
     121    {
     122        cbOutput2 = cbInput * cFactor;
     123        pvOutput = RTMemTmpAlloc(cbOutput2 + sizeof(RTUTF16));
     124        if (!pvOutput)
     125            return VERR_NO_TMP_MEMORY;
     126        fUcs2Term = true;
     127    }
     128    else
     129    {
     130        pvOutput = *ppvOutput;
     131        fUcs2Term = !strcmp(pszOutputCS, "UCS-2")
     132                 || !strcmp(pszOutputCS, "UTF-16")
     133                 || !strcmp(pszOutputCS, "ucs-2")
     134                 || !strcmp(pszOutputCS, "utf-16");
     135        cbOutput2 = cbOutput - (fUcs2Term ? sizeof(RTUTF16) : 1);
     136        if (cbOutput2 > cbOutput)
     137            return VERR_BUFFER_OVERFLOW;
     138    }
     139
     140    /*
     141     * Use a loop here to retry with bigger buffers.
     142     */
     143    for (unsigned cTries = 10; cTries > 0; cTries--)
     144    {
     145        /*
     146         * Create conversion object if necessary.
     147         */
     148        iconv_t hIconv = (iconv_t)*phIconv;
     149        if (hIconv == (iconv_t)-1)
     150        {
     151            IPRT_ALIGNMENT_CHECKS_DISABLE(); /* glibc causes trouble */
     152            *phIconv = hIconv = iconv_open(pszOutputCS, pszInputCS);
     153            IPRT_ALIGNMENT_CHECKS_ENABLE();
     154        }
     155        if (hIconv != (iconv_t)-1)
     156        {
     157            /*
     158             * Do the conversion.
     159             */
     160            size_t      cbInLeft = cbInput;
     161            size_t      cbOutLeft = cbOutput2;
     162            const void *pvInputLeft = pvInput;
     163            void       *pvOutputLeft = pvOutput;
     164#if defined(RT_OS_LINUX) || (defined(RT_OS_DARWIN) && defined(_DARWIN_FEATURE_UNIX_CONFORMANCE)) /* there are different opinions about the constness of the input buffer. */
     165            if (iconv(hIconv, (char **)&pvInputLeft, &cbInLeft, (char **)&pvOutputLeft, &cbOutLeft) != (size_t)-1)
     166#else
     167            if (iconv(hIconv, (const char **)&pvInputLeft, &cbInLeft, (char **)&pvOutputLeft, &cbOutLeft) != (size_t)-1)
     168#endif
     169            {
     170                if (!cbInLeft)
     171                {
     172                    /*
     173                     * We're done, just add the terminator and return.
     174                     * (Two terminators to support UCS-2 output, too.)
     175                     */
     176                    ((char *)pvOutputLeft)[0] = '\0';
     177                    if (fUcs2Term)
     178                        ((char *)pvOutputLeft)[1] = '\0';
     179                    *ppvOutput = pvOutput;
     180                    return VINF_SUCCESS;
     181                }
     182                errno = E2BIG;
     183            }
     184
     185            /*
     186             * If we failed because of output buffer space we'll
     187             * increase the output buffer size and retry.
     188             */
     189            if (errno == E2BIG)
     190            {
     191                if (!cbOutput)
     192                {
     193                    RTMemTmpFree(pvOutput);
     194                    cbOutput2 *= 2;
     195                    pvOutput = RTMemTmpAlloc(cbOutput2 + sizeof(RTUTF16));
     196                    if (!pvOutput)
     197                        return VERR_NO_TMP_MEMORY;
     198                    continue;
     199                }
     200                return VERR_BUFFER_OVERFLOW;
     201            }
     202
     203            /*
     204             * Close the handle on all other errors to make sure we won't carry
     205             * any bad state with us.
     206             */
     207            *phIconv = (iconv_t)-1;
     208            iconv_close(hIconv);
     209        }
     210        break;
     211    }
     212
     213    /* failure */
     214    if (!cbOutput)
     215        RTMemTmpFree(pvOutput);
     216    return VERR_NO_TRANSLATION;
     217}
     218
     219#endif /* RT_WITH_ICONV_CACHE */
     220
     221/**
     222 * Converts a string from one charset to another without using the handle cache.
     223 *
     224 * @returns IPRT status code.
     225 *
     226 * @param   pvInput         Pointer to intput string.
     227 * @param   cbInput         Size (in bytes) of input string. Excludes any terminators.
     228 * @param   pszInputCS      Codeset of the input string.
     229 * @param   ppvOutput       Pointer to pointer to output buffer if cbOutput > 0.
     230 *                          If cbOutput is 0 this is where the pointer to the allocated
     231 *                          buffer is stored.
     232 * @param   cbOutput        Size of the passed in buffer.
     233 * @param   pszOutputCS     Codeset of the input string.
     234 * @param   cFactor         Input vs. output size factor.
     235 */
     236static int rtStrConvertUncached(const void *pvInput, size_t cbInput, const char *pszInputCS,
     237                                void **ppvOutput, size_t cbOutput, const char *pszOutputCS,
     238                                unsigned cFactor)
    70239{
    71240    /*
     
    103272        /* Solaris doesn't grok empty codeset strings, so help it find the current codeset. */
    104273        if (!*pszInputCS)
    105             pszInputCS = nl_langinfo(CODESET);
     274            pszInputCS = rtStrGetLocaleCodeset();
    106275        if (!*pszOutputCS)
    107             pszOutputCS = nl_langinfo(CODESET);
     276            pszOutputCS = rtStrGetLocaleCodeset();
    108277#endif
    109278        IPRT_ALIGNMENT_CHECKS_DISABLE(); /* glibc causes trouble */
     
    171340
    172341/**
     342 * Wrapper that selects rtStrConvertCached or rtStrConvertUncached.
     343 *
     344 * @returns IPRT status code.
     345 *
     346 * @param   pszInput        Pointer to intput string.
     347 * @param   cchInput        Size (in bytes) of input string. Excludes any
     348 *                          terminators.
     349 * @param   pszInputCS      Codeset of the input string.
     350 * @param   ppszOutput      Pointer to pointer to output buffer if cbOutput > 0.
     351 *                          If cbOutput is 0 this is where the pointer to the
     352 *                          allocated buffer is stored.
     353 * @param   cbOutput        Size of the passed in buffer.
     354 * @param   pszOutputCS     Codeset of the input string.
     355 * @param   cFactor         Input vs. output size factor.
     356 * @param   enmCacheIdx     The iconv cache index.
     357 */
     358DECLINLINE(int) rtStrConvertWrapper(const char *pchInput, size_t cchInput, const char *pszInputCS,
     359                                    char **ppszOutput, size_t cbOutput, const char *pszOutputCS,
     360                                    unsigned cFactor, RTSTRICONV enmCacheIdx)
     361{
     362#ifdef RT_WITH_ICONV_CACHE
     363    RTTHREAD hSelf = RTThreadSelf();
     364    if (hSelf != NIL_RTTHREAD)
     365    {
     366        PRTTHREADINT pThread = rtThreadGet(hSelf);
     367        if (   pThread
     368            && (pThread->fIntFlags & (RTTHREADINT_FLAGS_ALIEN | RTTHREADINT_FLAGS_MAIN)) != RTTHREADINT_FLAGS_ALIEN)
     369            return rtstrConvertCached(pchInput, cchInput, pszInputCS,
     370                                      (void **)ppszOutput, cbOutput, pszOutputCS,
     371                                      cFactor, &pThread->ahIconvs[enmCacheIdx]);
     372    }
     373#endif
     374    return rtStrConvertUncached(pchInput, cchInput, pszInputCS,
     375                                (void **)ppszOutput, cbOutput, pszOutputCS,
     376                                cFactor);
     377}
     378
     379
     380/**
     381 * Internal API for use by the path conversion code.
     382 *
     383 * @returns IPRT status code.
     384 *
     385 * @param   pszInput        Pointer to intput string.
     386 * @param   cchInput        Size (in bytes) of input string. Excludes any
     387 *                          terminators.
     388 * @param   pszInputCS      Codeset of the input string.
     389 * @param   ppszOutput      Pointer to pointer to output buffer if cbOutput > 0.
     390 *                          If cbOutput is 0 this is where the pointer to the
     391 *                          allocated buffer is stored.
     392 * @param   cbOutput        Size of the passed in buffer.
     393 * @param   pszOutputCS     Codeset of the input string.
     394 * @param   cFactor         Input vs. output size factor.
     395 * @param   enmCacheIdx     The iconv cache index.
     396 */
     397int rtStrConvert(const char *pchInput, size_t cchInput, const char *pszInputCS,
     398                 char **ppszOutput, size_t cbOutput, const char *pszOutputCS,
     399                 unsigned cFactor, RTSTRICONV enmCacheIdx)
     400{
     401    Assert(enmCacheIdx >= 0 && enmCacheIdx < RTSTRICONV_END);
     402    return rtStrConvertWrapper(pchInput, cchInput, pszInputCS,
     403                               ppszOutput, cbOutput, pszOutputCS,
     404                               cFactor, enmCacheIdx);
     405}
     406
     407
     408/**
    173409 * Allocates tmp buffer, translates pszString from UTF8 to current codepage.
    174410 *
     
    196432        return VERR_NO_TMP_MEMORY;
    197433    }
    198     return rtstrConvert(pszString, cch, "UTF-8", (void **)ppszString, 0, "", 1);
     434    return rtStrConvertWrapper(pszString, cch, "UTF-8", ppszString, 0, "", 1, RTSTRICONV_UTF8_TO_LOCALE);
    199435}
    200436
     
    215451
    216452    /*
    217      * Attempt with UTF-8 length of 2x the native lenght.
     453     * Attempt with UTF-8 length of 2x the native length.
    218454     */
    219455    size_t cch = strlen(pszString);
     
    226462        return VERR_NO_TMP_MEMORY;
    227463    }
    228     return rtstrConvert(pszString, cch, "", (void **)ppszString, 0, "UTF-8", 2);
    229 }
    230 
     464    return rtStrConvertWrapper(pszString, cch, "", ppszString, 0, "UTF-8", 2, RTSTRICONV_LOCALE_TO_UTF8);
     465}
     466
Note: See TracChangeset for help on using the changeset viewer.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette