1ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/*
2ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru ********************************************************************
3ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * COPYRIGHT:
459d709d503bab6e2b61931737e662dd293b40578ccornelius * Copyright (c) 1996-2013, International Business Machines Corporation and
5ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * others. All Rights Reserved.
6ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru ********************************************************************
7ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *
8103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius *  uconv_bld.cpp:
9ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *
10ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *  Defines functions that are used in the creation/initialization/deletion
11ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *  of converters and related structures.
12ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *  uses uconv_io.h routines to access disk information
13ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *  is used by ucnv.h to implement public API create/delete/flushCache routines
14ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Modification History:
15ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *
16ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *   Date        Name        Description
17ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *
18ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *   06/20/2000  helena      OS/400 port changes; mostly typecast.
19ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *   06/29/2000  helena      Major rewrite of the callback interface.
20ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*/
21ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
22ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "unicode/utypes.h"
23ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
24ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#if !UCONFIG_NO_CONVERSION
25ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
26ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "unicode/putil.h"
27ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "unicode/udata.h"
28ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "unicode/ucnv.h"
29ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "unicode/uloc.h"
3059d709d503bab6e2b61931737e662dd293b40578ccornelius#include "mutex.h"
31103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#include "putilimp.h"
3259d709d503bab6e2b61931737e662dd293b40578ccornelius#include "uassert.h"
33ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "utracimp.h"
34ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "ucnv_io.h"
35ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "ucnv_bld.h"
36ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "ucnvmbcs.h"
37ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "ucnv_ext.h"
38ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "ucnv_cnv.h"
39ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "ucnv_imp.h"
40ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "uhash.h"
41ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "umutex.h"
42ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "cstring.h"
43ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "cmemory.h"
44ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "ucln_cmn.h"
45ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "ustr_cnv.h"
46ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
47ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
48ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#if 0
49ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include <stdio.h>
50ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruextern void UCNV_DEBUG_LOG(char *what, char *who, void *p, int l);
51ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define UCNV_DEBUG_LOG(x,y,z) UCNV_DEBUG_LOG(x,y,z,__LINE__)
52ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#else
53ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru# define UCNV_DEBUG_LOG(x,y,z)
54ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#endif
55ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
56ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic const UConverterSharedData * const
57ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruconverterData[UCNV_NUMBER_OF_SUPPORTED_CONVERTER_TYPES]={
58ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    NULL, NULL,
59ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
60ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#if UCONFIG_NO_LEGACY_CONVERSION
61ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    NULL,
62ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#else
63ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    &_MBCSData,
64ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#endif
65ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
66ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    &_Latin1Data,
67ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    &_UTF8Data, &_UTF16BEData, &_UTF16LEData, &_UTF32BEData, &_UTF32LEData,
68ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    NULL,
69ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
70ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#if UCONFIG_NO_LEGACY_CONVERSION
71ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    NULL,
72ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    NULL, NULL, NULL, NULL, NULL, NULL,
73ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    NULL, NULL, NULL, NULL, NULL, NULL,
74ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    NULL,
75ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#else
76ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    &_ISO2022Data,
77ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    &_LMBCSData1,&_LMBCSData2, &_LMBCSData3, &_LMBCSData4, &_LMBCSData5, &_LMBCSData6,
78ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    &_LMBCSData8,&_LMBCSData11,&_LMBCSData16,&_LMBCSData17,&_LMBCSData18,&_LMBCSData19,
79ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    &_HZData,
80ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#endif
81ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
82ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    &_SCSUData,
83ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
84ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#if UCONFIG_NO_LEGACY_CONVERSION
85ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    NULL,
86ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#else
87ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    &_ISCIIData,
88ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#endif
89ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
90ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    &_ASCIIData,
91b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    &_UTF7Data, &_Bocu1Data, &_UTF16Data, &_UTF32Data, &_CESU8Data, &_IMAPData,
92103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
93103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#if UCONFIG_NO_LEGACY_CONVERSION
94103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    NULL,
95103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#else
96b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    &_CompoundTextData
97103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#endif
98ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru};
99ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
100ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/* Please keep this in binary sorted order for getAlgorithmicTypeFromName.
101ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru   Also the name should be in lower case and all spaces, dashes and underscores
102ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru   removed
103ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*/
104ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic struct {
105ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  const char *name;
106ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  const UConverterType type;
107ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} const cnvNameType[] = {
108ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  { "bocu1", UCNV_BOCU1 },
109ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  { "cesu8", UCNV_CESU8 },
110ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#if !UCONFIG_NO_LEGACY_CONVERSION
111ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  { "hz",UCNV_HZ },
112ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#endif
113ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  { "imapmailboxname", UCNV_IMAP_MAILBOX },
114ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#if !UCONFIG_NO_LEGACY_CONVERSION
115ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  { "iscii", UCNV_ISCII },
116ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  { "iso2022", UCNV_ISO_2022 },
117ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#endif
118ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  { "iso88591", UCNV_LATIN_1 },
119ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#if !UCONFIG_NO_LEGACY_CONVERSION
120ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  { "lmbcs1", UCNV_LMBCS_1 },
121ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  { "lmbcs11",UCNV_LMBCS_11 },
122ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  { "lmbcs16",UCNV_LMBCS_16 },
123ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  { "lmbcs17",UCNV_LMBCS_17 },
124ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  { "lmbcs18",UCNV_LMBCS_18 },
125ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  { "lmbcs19",UCNV_LMBCS_19 },
126ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  { "lmbcs2", UCNV_LMBCS_2 },
127ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  { "lmbcs3", UCNV_LMBCS_3 },
128ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  { "lmbcs4", UCNV_LMBCS_4 },
129ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  { "lmbcs5", UCNV_LMBCS_5 },
130ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  { "lmbcs6", UCNV_LMBCS_6 },
131ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  { "lmbcs8", UCNV_LMBCS_8 },
132ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#endif
133ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  { "scsu", UCNV_SCSU },
134ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  { "usascii", UCNV_US_ASCII },
135ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  { "utf16", UCNV_UTF16 },
136ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  { "utf16be", UCNV_UTF16_BigEndian },
137ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  { "utf16le", UCNV_UTF16_LittleEndian },
138ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#if U_IS_BIG_ENDIAN
139ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  { "utf16oppositeendian", UCNV_UTF16_LittleEndian },
140ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  { "utf16platformendian", UCNV_UTF16_BigEndian },
141ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#else
142ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  { "utf16oppositeendian", UCNV_UTF16_BigEndian},
143ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  { "utf16platformendian", UCNV_UTF16_LittleEndian },
144ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#endif
145ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  { "utf32", UCNV_UTF32 },
146ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  { "utf32be", UCNV_UTF32_BigEndian },
147ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  { "utf32le", UCNV_UTF32_LittleEndian },
148ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#if U_IS_BIG_ENDIAN
149ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  { "utf32oppositeendian", UCNV_UTF32_LittleEndian },
150ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  { "utf32platformendian", UCNV_UTF32_BigEndian },
151ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#else
152ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  { "utf32oppositeendian", UCNV_UTF32_BigEndian },
153ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  { "utf32platformendian", UCNV_UTF32_LittleEndian },
154ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#endif
155ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  { "utf7", UCNV_UTF7 },
156b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  { "utf8", UCNV_UTF8 },
157b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  { "x11compoundtext", UCNV_COMPOUND_TEXT}
158ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru};
159ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
160ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
161ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/*initializes some global variables */
162ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic UHashtable *SHARED_DATA_HASHTABLE = NULL;
16354dcd9b6a06071f647dac967e9e267abb9410720Craig Corneliusstatic UMutex cnvCacheMutex = U_MUTEX_INITIALIZER;  /* Mutex for synchronizing cnv cache access. */
16454dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius                                                    /*  Note:  the global mutex is used for      */
16554dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius                                                    /*         reference count updates.          */
166ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
167ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic const char **gAvailableConverters = NULL;
168ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic uint16_t gAvailableConverterCount = 0;
16959d709d503bab6e2b61931737e662dd293b40578ccorneliusstatic icu::UInitOnce gAvailableConvertersInitOnce = U_INITONCE_INITIALIZER;
170ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
17185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho#if !U_CHARSET_IS_UTF8
17285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
173ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/* This contains the resolved converter name. So no further alias lookup is needed again. */
174ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic char gDefaultConverterNameBuffer[UCNV_MAX_CONVERTER_NAME_LENGTH + 1]; /* +1 for NULL */
175ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic const char *gDefaultConverterName = NULL;
176ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
177ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/*
178ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruIf the default converter is an algorithmic converter, this is the cached value.
179ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruWe don't cache a full UConverter and clone it because ucnv_clone doesn't have
180ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruless overhead than an algorithmic open. We don't cache non-algorithmic converters
181ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querubecause ucnv_flushCache must be able to unload the default converter and its table.
182ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*/
183ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic const UConverterSharedData *gDefaultAlgorithmicSharedData = NULL;
184ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
185ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/* Does gDefaultConverterName have a converter option and require extra parsing? */
186ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic UBool gDefaultConverterContainsOption;
187ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
18885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho#endif  /* !U_CHARSET_IS_UTF8 */
189ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
190ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic const char DATA_TYPE[] = "cnv";
191ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
19259d709d503bab6e2b61931737e662dd293b40578ccornelius/* ucnv_flushAvailableConverterCache. This is only called from ucnv_cleanup().
19359d709d503bab6e2b61931737e662dd293b40578ccornelius *                       If it is ever to be called from elsewhere, synchronization
19459d709d503bab6e2b61931737e662dd293b40578ccornelius *                       will need to be considered.
19559d709d503bab6e2b61931737e662dd293b40578ccornelius */
19685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Hostatic void
19785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Houcnv_flushAvailableConverterCache() {
19859d709d503bab6e2b61931737e662dd293b40578ccornelius    gAvailableConverterCount = 0;
19985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    if (gAvailableConverters) {
20085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        uprv_free((char **)gAvailableConverters);
20185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        gAvailableConverters = NULL;
20285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    }
20359d709d503bab6e2b61931737e662dd293b40578ccornelius    gAvailableConvertersInitOnce.reset();
20485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho}
20585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
206ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/* ucnv_cleanup - delete all storage held by the converter cache, except any  */
207ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/*                in use by open converters.                                  */
208ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/*                Not thread safe.                                            */
209ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/*                Not supported API.                                          */
210ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic UBool U_CALLCONV ucnv_cleanup(void) {
211ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    ucnv_flushCache();
212ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (SHARED_DATA_HASHTABLE != NULL && uhash_count(SHARED_DATA_HASHTABLE) == 0) {
213ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        uhash_close(SHARED_DATA_HASHTABLE);
214ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        SHARED_DATA_HASHTABLE = NULL;
215ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
216ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
21785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    /* Isn't called from flushCache because other threads may have preexisting references to the table. */
21885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    ucnv_flushAvailableConverterCache();
219ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
22085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho#if !U_CHARSET_IS_UTF8
221ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    gDefaultConverterName = NULL;
222ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    gDefaultConverterNameBuffer[0] = 0;
223ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    gDefaultConverterContainsOption = FALSE;
224ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    gDefaultAlgorithmicSharedData = NULL;
22585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho#endif
226ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
227ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return (SHARED_DATA_HASHTABLE == NULL);
228ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
229ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
230ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic UBool U_CALLCONV
231103e9ffba2cba345d0078eb8b8db33249f81840aCraig CorneliusisCnvAcceptable(void * /*context*/,
232103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius                const char * /*type*/, const char * /*name*/,
23385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                const UDataInfo *pInfo) {
234ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return (UBool)(
235ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        pInfo->size>=20 &&
236ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        pInfo->isBigEndian==U_IS_BIG_ENDIAN &&
237ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        pInfo->charsetFamily==U_CHARSET_FAMILY &&
238ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        pInfo->sizeofUChar==U_SIZEOF_UCHAR &&
239ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        pInfo->dataFormat[0]==0x63 &&   /* dataFormat="cnvt" */
240ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        pInfo->dataFormat[1]==0x6e &&
241ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        pInfo->dataFormat[2]==0x76 &&
242ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        pInfo->dataFormat[3]==0x74 &&
243ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        pInfo->formatVersion[0]==6);  /* Everything will be version 6 */
244ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
245ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
246ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/**
247ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Un flatten shared data from a UDATA..
248ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */
249ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic UConverterSharedData*
250ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruucnv_data_unFlattenClone(UConverterLoadArgs *pArgs, UDataMemory *pData, UErrorCode *status)
251ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
252ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* UDataInfo info; -- necessary only if some converters have different formatVersion */
253ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    const uint8_t *raw = (const uint8_t *)udata_getMemory(pData);
254ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    const UConverterStaticData *source = (const UConverterStaticData *) raw;
255ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UConverterSharedData *data;
256ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UConverterType type = (UConverterType)source->conversionType;
257ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
258ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(U_FAILURE(*status))
259ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return NULL;
260ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
261ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if( (uint16_t)type >= UCNV_NUMBER_OF_SUPPORTED_CONVERTER_TYPES ||
262ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        converterData[type] == NULL ||
263ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        converterData[type]->referenceCounter != 1 ||
264ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        source->structSize != sizeof(UConverterStaticData))
265ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    {
266ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        *status = U_INVALID_TABLE_FORMAT;
267ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return NULL;
268ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
269ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
270ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    data = (UConverterSharedData *)uprv_malloc(sizeof(UConverterSharedData));
271ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(data == NULL) {
272ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        *status = U_MEMORY_ALLOCATION_ERROR;
273ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return NULL;
274ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
275ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
276ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* copy initial values from the static structure for this type */
277ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    uprv_memcpy(data, converterData[type], sizeof(UConverterSharedData));
278ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
279ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#if 0 /* made UConverterMBCSTable part of UConverterSharedData -- markus 20031107 */
280ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /*
281ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     * It would be much more efficient if the table were a direct member, not a pointer.
282ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     * However, that would add to the size of all UConverterSharedData objects
283ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     * even if they do not use this table (especially algorithmic ones).
284ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     * If this changes, then the static templates from converterData[type]
285ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     * need more entries.
286ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     *
287ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     * In principle, it would be cleaner if the load() function below
288ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     * allocated the table.
289ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     */
290ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    data->table = (UConverterTable *)uprv_malloc(sizeof(UConverterTable));
291ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(data->table == NULL) {
292ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        uprv_free(data);
293ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        *status = U_MEMORY_ALLOCATION_ERROR;
294ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return NULL;
295ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
296ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    uprv_memset(data->table, 0, sizeof(UConverterTable));
297ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#endif
298ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
299ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    data->staticData = source;
300ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
301ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    data->sharedDataCached = FALSE;
302ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
303ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* fill in fields from the loaded data */
304ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    data->dataMemory = (void*)pData; /* for future use */
305ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
306ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(data->impl->load != NULL) {
307ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        data->impl->load(data, pArgs, raw + source->structSize, status);
308ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if(U_FAILURE(*status)) {
309ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            uprv_free(data->table);
310ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            uprv_free(data);
311ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            return NULL;
312ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
313ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
314ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return data;
315ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
316ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
317ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/*Takes an alias name gets an actual converter file name
318ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *goes to disk and opens it.
319ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *allocates the memory and returns a new UConverter object
320ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */
321ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic UConverterSharedData *createConverterFromFile(UConverterLoadArgs *pArgs, UErrorCode * err)
322ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
323ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UDataMemory *data;
324ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UConverterSharedData *sharedData;
325ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
326ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UTRACE_ENTRY_OC(UTRACE_UCNV_LOAD);
327ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
328ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (U_FAILURE (*err)) {
329ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        UTRACE_EXIT_STATUS(*err);
330ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return NULL;
331ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
332ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
333ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UTRACE_DATA2(UTRACE_OPEN_CLOSE, "load converter %s from package %s", pArgs->name, pArgs->pkg);
334ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
335ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    data = udata_openChoice(pArgs->pkg, DATA_TYPE, pArgs->name, isCnvAcceptable, NULL, err);
336ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(U_FAILURE(*err))
337ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    {
338ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        UTRACE_EXIT_STATUS(*err);
339ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return NULL;
340ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
341ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
342ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    sharedData = ucnv_data_unFlattenClone(pArgs, data, err);
343ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(U_FAILURE(*err))
344ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    {
345ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        udata_close(data);
346ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        UTRACE_EXIT_STATUS(*err);
347ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return NULL;
348ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
349ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
350ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /*
351ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     * TODO Store pkg in a field in the shared data so that delta-only converters
352ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     * can load base converters from the same package.
353ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     * If the pkg name is longer than the field, then either do not load the converter
354ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     * in the first place, or just set the pkg field to "".
355ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     */
356ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
357ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UTRACE_EXIT_PTR_STATUS(sharedData, *err);
358ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return sharedData;
359ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
360ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
361ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/*returns a converter type from a string
362ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */
363ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic const UConverterSharedData *
364ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QuerugetAlgorithmicTypeFromName(const char *realName)
365ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
366ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    uint32_t mid, start, limit;
367ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    uint32_t lastMid;
368ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int result;
369ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    char strippedName[UCNV_MAX_CONVERTER_NAME_LENGTH];
370ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
371ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* Lower case and remove ignoreable characters. */
372ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    ucnv_io_stripForCompare(strippedName, realName);
373ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
374ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* do a binary search for the alias */
375ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    start = 0;
376ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    limit = sizeof(cnvNameType)/sizeof(cnvNameType[0]);
377ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    mid = limit;
378ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    lastMid = UINT32_MAX;
379ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
380ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    for (;;) {
381ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        mid = (uint32_t)((start + limit) / 2);
382ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (lastMid == mid) {   /* Have we moved? */
383ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            break;  /* We haven't moved, and it wasn't found. */
384ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
385ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        lastMid = mid;
386ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        result = uprv_strcmp(strippedName, cnvNameType[mid].name);
387ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
388ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (result < 0) {
389ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            limit = mid;
390ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        } else if (result > 0) {
391ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            start = mid;
392ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        } else {
393ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            return converterData[cnvNameType[mid].type];
394ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
395ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
396ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
397ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return NULL;
398ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
399ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
400ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/*
401ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru* Based on the number of known converters, this determines how many times larger
402ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru* the shared data hash table should be. When on small platforms, or just a couple
403ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru* of converters are used, this number should be 2. When memory is plentiful, or
404ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru* when ucnv_countAvailable is ever used with a lot of available converters,
405ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru* this should be 4.
406ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru* Larger numbers reduce the number of hash collisions, but use more memory.
407ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*/
408ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define UCNV_CACHE_LOAD_FACTOR 2
409ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
410ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/* Puts the shared data in the static hashtable SHARED_DATA_HASHTABLE */
411ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/*   Will always be called with the cnvCacheMutex alrady being held   */
412ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/*     by the calling function.                                       */
413ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/* Stores the shared data in the SHARED_DATA_HASHTABLE
414ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @param data The shared data
415ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */
416ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic void
417ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruucnv_shareConverterData(UConverterSharedData * data)
418ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
419ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UErrorCode err = U_ZERO_ERROR;
420ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /*Lazy evaluates the Hashtable itself */
421ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /*void *sanity = NULL;*/
422ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
423ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (SHARED_DATA_HASHTABLE == NULL)
424ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    {
425ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        SHARED_DATA_HASHTABLE = uhash_openSize(uhash_hashChars, uhash_compareChars, NULL,
426ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                            ucnv_io_countKnownConverters(&err)*UCNV_CACHE_LOAD_FACTOR,
427ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                            &err);
428ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        ucln_common_registerCleanup(UCLN_COMMON_UCNV, ucnv_cleanup);
429ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
430ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (U_FAILURE(err))
431ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            return;
432ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
433ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
434ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* ### check to see if the element is not already there! */
435ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
436ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /*
437ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    sanity =   ucnv_getSharedConverterData (data->staticData->name);
438ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(sanity != NULL)
439ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    {
440ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UCNV_DEBUG_LOG("put:overwrite!",data->staticData->name,sanity);
441ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
442ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UCNV_DEBUG_LOG("put:chk",data->staticData->name,sanity);
443ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    */
444ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
445ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* Mark it shared */
446ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    data->sharedDataCached = TRUE;
447ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
448ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    uhash_put(SHARED_DATA_HASHTABLE,
449ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            (void*) data->staticData->name, /* Okay to cast away const as long as
450ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            keyDeleter == NULL */
451ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            data,
452ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            &err);
453ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UCNV_DEBUG_LOG("put", data->staticData->name,data);
454ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
455ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
456ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
457ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/*  Look up a converter name in the shared data cache.                    */
458ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/*    cnvCacheMutex must be held by the caller to protect the hash table. */
459ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/* gets the shared data from the SHARED_DATA_HASHTABLE (might return NULL if it isn't there)
460ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @param name The name of the shared data
461ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @return the shared data from the SHARED_DATA_HASHTABLE
462ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */
463ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic UConverterSharedData *
464ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruucnv_getSharedConverterData(const char *name)
465ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
466ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /*special case when no Table has yet been created we return NULL */
467ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (SHARED_DATA_HASHTABLE == NULL)
468ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    {
469ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return NULL;
470ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
471ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    else
472ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    {
473ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        UConverterSharedData *rc;
474ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
475ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        rc = (UConverterSharedData*)uhash_get(SHARED_DATA_HASHTABLE, name);
476ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        UCNV_DEBUG_LOG("get",name,rc);
477ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return rc;
478ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
479ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
480ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
481ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/*frees the string of memory blocks associates with a sharedConverter
482ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *if and only if the referenceCounter == 0
483ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */
484ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/* Deletes (frees) the Shared data it's passed. first it checks the referenceCounter to
485ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * see if anyone is using it, if not it frees all the memory stemming from sharedConverterData and
486ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * returns TRUE,
487ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * otherwise returns FALSE
488ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @param sharedConverterData The shared data
489ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @return if not it frees all the memory stemming from sharedConverterData and
490ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * returns TRUE, otherwise returns FALSE
491ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */
492ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic UBool
493ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruucnv_deleteSharedConverterData(UConverterSharedData * deadSharedData)
494ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
495ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UTRACE_ENTRY_OC(UTRACE_UCNV_UNLOAD);
496ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UTRACE_DATA2(UTRACE_OPEN_CLOSE, "unload converter %s shared data %p", deadSharedData->staticData->name, deadSharedData);
497ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
498ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (deadSharedData->referenceCounter > 0) {
499ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        UTRACE_EXIT_VALUE((int32_t)FALSE);
500ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return FALSE;
501ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
502ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
503ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (deadSharedData->impl->unload != NULL) {
504ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        deadSharedData->impl->unload(deadSharedData);
505ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
506ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
507ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(deadSharedData->dataMemory != NULL)
508ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    {
509ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        UDataMemory *data = (UDataMemory*)deadSharedData->dataMemory;
510ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        udata_close(data);
511ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
512ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
513ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(deadSharedData->table != NULL)
514ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    {
515ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        uprv_free(deadSharedData->table);
516ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
517ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
518ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#if 0
519ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* if the static data is actually owned by the shared data */
520ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* enable if we ever have this situation. */
521ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(deadSharedData->staticDataOwned == TRUE) /* see ucnv_bld.h */
522ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    {
523ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        uprv_free((void*)deadSharedData->staticData);
524ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
525ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#endif
526ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
527ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#if 0
528ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* Zap it ! */
529ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    uprv_memset(deadSharedData->0, sizeof(*deadSharedData));
530ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#endif
531ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
532ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    uprv_free(deadSharedData);
533ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
534ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UTRACE_EXIT_VALUE((int32_t)TRUE);
535ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return TRUE;
536ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
537ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
538ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/**
539ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Load a non-algorithmic converter.
540ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * If pkg==NULL, then this function must be called inside umtx_lock(&cnvCacheMutex).
541ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */
542ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUConverterSharedData *
543ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruucnv_load(UConverterLoadArgs *pArgs, UErrorCode *err) {
544ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UConverterSharedData *mySharedConverterData;
545ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
546ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(err == NULL || U_FAILURE(*err)) {
547ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return NULL;
548ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
549ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
550ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(pArgs->pkg != NULL && *pArgs->pkg != 0) {
551ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* application-provided converters are not currently cached */
552ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return createConverterFromFile(pArgs, err);
553ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
554ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
555ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    mySharedConverterData = ucnv_getSharedConverterData(pArgs->name);
556ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (mySharedConverterData == NULL)
557ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    {
558ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /*Not cached, we need to stream it in from file */
559ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        mySharedConverterData = createConverterFromFile(pArgs, err);
560ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (U_FAILURE (*err) || (mySharedConverterData == NULL))
561ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        {
562ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            return NULL;
563ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
56485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        else if (!pArgs->onlyTestIsLoadable)
565ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        {
566ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            /* share it with other library clients */
567ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            ucnv_shareConverterData(mySharedConverterData);
568ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
569ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
570ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    else
571ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    {
572ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* The data for this converter was already in the cache.            */
573ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* Update the reference counter on the shared data: one more client */
574ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        mySharedConverterData->referenceCounter++;
575ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
576ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
577ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return mySharedConverterData;
578ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
579ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
580ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/**
581ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Unload a non-algorithmic converter.
582ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * It must be sharedData->referenceCounter != ~0
583ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * and this function must be called inside umtx_lock(&cnvCacheMutex).
584ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */
585103e9ffba2cba345d0078eb8b8db33249f81840aCraig CorneliusU_CAPI void
586ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruucnv_unload(UConverterSharedData *sharedData) {
587ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(sharedData != NULL) {
588ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (sharedData->referenceCounter > 0) {
589ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            sharedData->referenceCounter--;
590ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
591ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
592ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if((sharedData->referenceCounter <= 0)&&(sharedData->sharedDataCached == FALSE)) {
593ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            ucnv_deleteSharedConverterData(sharedData);
594ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
595ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
596ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
597ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
598103e9ffba2cba345d0078eb8b8db33249f81840aCraig CorneliusU_CFUNC void
599ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruucnv_unloadSharedDataIfReady(UConverterSharedData *sharedData)
600ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
601ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /*
602ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    Checking whether it's an algorithic converter is okay
603ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    in multithreaded applications because the value never changes.
604ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    Don't check referenceCounter for any other value.
605ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    */
606103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    if(sharedData != NULL && sharedData->referenceCounter != (uint32_t)~0) {
607ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        umtx_lock(&cnvCacheMutex);
608ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        ucnv_unload(sharedData);
609ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        umtx_unlock(&cnvCacheMutex);
610ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
611ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
612ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
613103e9ffba2cba345d0078eb8b8db33249f81840aCraig CorneliusU_CFUNC void
614ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruucnv_incrementRefCount(UConverterSharedData *sharedData)
615ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
61685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    /*
61785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    Checking whether it's an algorithic converter is okay
61885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    in multithreaded applications because the value never changes.
61985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    Don't check referenceCounter for any other value.
62085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    */
621103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    if(sharedData != NULL && sharedData->referenceCounter != (uint32_t)~0) {
622ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        umtx_lock(&cnvCacheMutex);
623ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        sharedData->referenceCounter++;
624ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        umtx_unlock(&cnvCacheMutex);
625ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
626ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
627ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
62885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho/*
62985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho * *pPieces must be initialized.
63085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho * The name without options will be copied to pPieces->cnvName.
63185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho * The locale and options will be copied to pPieces only if present in inName,
63285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho * otherwise the existing values in pPieces remain.
63385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho * *pArgs will be set to the pPieces values.
63485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho */
635ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic void
636ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruparseConverterOptions(const char *inName,
63785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                      UConverterNamePieces *pPieces,
63885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                      UConverterLoadArgs *pArgs,
639ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                      UErrorCode *err)
640ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
64185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    char *cnvName = pPieces->cnvName;
642ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    char c;
643ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t len = 0;
644ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
64585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    pArgs->name=inName;
64685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    pArgs->locale=pPieces->locale;
64785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    pArgs->options=pPieces->options;
64885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
649ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* copy the converter name itself to cnvName */
650ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    while((c=*inName)!=0 && c!=UCNV_OPTION_SEP_CHAR) {
651ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (++len>=UCNV_MAX_CONVERTER_NAME_LENGTH) {
652ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            *err = U_ILLEGAL_ARGUMENT_ERROR;    /* bad name */
65385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            pPieces->cnvName[0]=0;
654ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            return;
655ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
656ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        *cnvName++=c;
657ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        inName++;
658ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
659ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    *cnvName=0;
66085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    pArgs->name=pPieces->cnvName;
661ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
662ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* parse options. No more name copying should occur. */
663ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    while((c=*inName)!=0) {
664ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if(c==UCNV_OPTION_SEP_CHAR) {
665ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            ++inName;
666ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
667ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
668ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* inName is behind an option separator */
669ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if(uprv_strncmp(inName, "locale=", 7)==0) {
670ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            /* do not modify locale itself in case we have multiple locale options */
67185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            char *dest=pPieces->locale;
672ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
673ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            /* copy the locale option value */
674ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            inName+=7;
675ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            len=0;
676ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            while((c=*inName)!=0 && c!=UCNV_OPTION_SEP_CHAR) {
677ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                ++inName;
678ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
679ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                if(++len>=ULOC_FULLNAME_CAPACITY) {
680ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    *err=U_ILLEGAL_ARGUMENT_ERROR;    /* bad name */
68185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                    pPieces->locale[0]=0;
682ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    return;
683ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                }
684ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
685ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                *dest++=c;
686ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
687ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            *dest=0;
688ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        } else if(uprv_strncmp(inName, "version=", 8)==0) {
68985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            /* copy the version option value into bits 3..0 of pPieces->options */
690ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            inName+=8;
691ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            c=*inName;
692ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if(c==0) {
69385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                pArgs->options=(pPieces->options&=~UCNV_OPTION_VERSION);
694ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                return;
695ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            } else if((uint8_t)(c-'0')<10) {
69685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                pArgs->options=pPieces->options=(pPieces->options&~UCNV_OPTION_VERSION)|(uint32_t)(c-'0');
697ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                ++inName;
698ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
699ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        } else if(uprv_strncmp(inName, "swaplfnl", 8)==0) {
700ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            inName+=8;
70185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            pArgs->options=(pPieces->options|=UCNV_OPTION_SWAP_LFNL);
702ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* add processing for new options here with another } else if(uprv_strncmp(inName, "option-name=", XX)==0) { */
703ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        } else {
704ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            /* ignore any other options until we define some */
705ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            while(((c = *inName++) != 0) && (c != UCNV_OPTION_SEP_CHAR)) {
706ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
707ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if(c==0) {
708ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                return;
709ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
710ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
711ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
712ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
713ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
714ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/*Logic determines if the converter is Algorithmic AND/OR cached
715ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *depending on that:
716ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * -we either go to get data from disk and cache it (Data=TRUE, Cached=False)
717ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * -Get it from a Hashtable (Data=X, Cached=TRUE)
718ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * -Call dataConverter initializer (Data=TRUE, Cached=TRUE)
719ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * -Call AlgorithmicConverter initializer (Data=FALSE, Cached=TRUE)
720ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */
721103e9ffba2cba345d0078eb8b8db33249f81840aCraig CorneliusU_CFUNC UConverterSharedData *
72285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Houcnv_loadSharedData(const char *converterName,
72385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                    UConverterNamePieces *pPieces,
72485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                    UConverterLoadArgs *pArgs,
72585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                    UErrorCode * err) {
72685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    UConverterNamePieces stackPieces;
72785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    UConverterLoadArgs stackArgs;
728ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UConverterSharedData *mySharedConverterData = NULL;
729ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UErrorCode internalErrorCode = U_ZERO_ERROR;
730ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UBool mayContainOption = TRUE;
731ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UBool checkForAlgorithmic = TRUE;
732ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
733ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (U_FAILURE (*err)) {
734ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return NULL;
735ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
736ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
73785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    if(pPieces == NULL) {
73885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        if(pArgs != NULL) {
73985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            /*
74085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho             * Bad: We may set pArgs pointers to stackPieces fields
74185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho             * which will be invalid after this function returns.
74285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho             */
74385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            *err = U_INTERNAL_PROGRAM_ERROR;
74485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            return NULL;
74585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
74685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        pPieces = &stackPieces;
747ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
74885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    if(pArgs == NULL) {
74985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        uprv_memset(&stackArgs, 0, sizeof(stackArgs));
75085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        stackArgs.size = (int32_t)sizeof(stackArgs);
75185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        pArgs = &stackArgs;
75285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    }
75385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
75485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    pPieces->cnvName[0] = 0;
75585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    pPieces->locale[0] = 0;
75685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    pPieces->options = 0;
757ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
75885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    pArgs->name = converterName;
75985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    pArgs->locale = pPieces->locale;
76085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    pArgs->options = pPieces->options;
761ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
762ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* In case "name" is NULL we want to open the default converter. */
763ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (converterName == NULL) {
76485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho#if U_CHARSET_IS_UTF8
76585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        pArgs->name = "UTF-8";
76685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        return (UConverterSharedData *)converterData[UCNV_UTF8];
76785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho#else
768ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* Call ucnv_getDefaultName first to query the name from the OS. */
76985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        pArgs->name = ucnv_getDefaultName();
77085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        if (pArgs->name == NULL) {
771ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            *err = U_MISSING_RESOURCE_ERROR;
772ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            return NULL;
773ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
774ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        mySharedConverterData = (UConverterSharedData *)gDefaultAlgorithmicSharedData;
775ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        checkForAlgorithmic = FALSE;
776ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        mayContainOption = gDefaultConverterContainsOption;
777ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* the default converter name is already canonical */
77885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho#endif
779ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
78085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    else if(UCNV_FAST_IS_UTF8(converterName)) {
781ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* fastpath for UTF-8 */
78285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        pArgs->name = "UTF-8";
783ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return (UConverterSharedData *)converterData[UCNV_UTF8];
784ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
785ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    else {
786ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* separate the converter name from the options */
78785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        parseConverterOptions(converterName, pPieces, pArgs, err);
788ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (U_FAILURE(*err)) {
789ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            /* Very bad name used. */
790ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            return NULL;
791ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
792ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
793ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* get the canonical converter name */
79485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        pArgs->name = ucnv_io_getConverterName(pArgs->name, &mayContainOption, &internalErrorCode);
79585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        if (U_FAILURE(internalErrorCode) || pArgs->name == NULL) {
796ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            /*
797ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            * set the input name in case the converter was added
798ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            * without updating the alias table, or when there is no alias table
799ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            */
80085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            pArgs->name = pPieces->cnvName;
8018393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        } else if (internalErrorCode == U_AMBIGUOUS_ALIAS_WARNING) {
8028393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            *err = U_AMBIGUOUS_ALIAS_WARNING;
803ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
804ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
805ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
806ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* separate the converter name from the options */
80785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    if(mayContainOption && pArgs->name != pPieces->cnvName) {
80885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        parseConverterOptions(pArgs->name, pPieces, pArgs, err);
809ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
810ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
811ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* get the shared data for an algorithmic converter, if it is one */
812ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (checkForAlgorithmic) {
81385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        mySharedConverterData = (UConverterSharedData *)getAlgorithmicTypeFromName(pArgs->name);
814ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
815ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (mySharedConverterData == NULL)
816ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    {
817ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* it is a data-based converter, get its shared data.               */
818ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* Hold the cnvCacheMutex through the whole process of checking the */
819ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /*   converter data cache, and adding new entries to the cache      */
820ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /*   to prevent other threads from modifying the cache during the   */
821ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /*   process.                                                       */
82285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        pArgs->nestedLoads=1;
82385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        pArgs->pkg=NULL;
824ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
825ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        umtx_lock(&cnvCacheMutex);
82685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        mySharedConverterData = ucnv_load(pArgs, err);
827ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        umtx_unlock(&cnvCacheMutex);
828ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (U_FAILURE (*err) || (mySharedConverterData == NULL))
829ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        {
830ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            return NULL;
831ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
832ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
833ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
834ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return mySharedConverterData;
835ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
836ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
837103e9ffba2cba345d0078eb8b8db33249f81840aCraig CorneliusU_CAPI UConverter *
838ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruucnv_createConverter(UConverter *myUConverter, const char *converterName, UErrorCode * err)
839ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
84085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    UConverterNamePieces stackPieces;
841103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    UConverterLoadArgs stackArgs=UCNV_LOAD_ARGS_INITIALIZER;
842ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UConverterSharedData *mySharedConverterData;
843ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
844ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UTRACE_ENTRY_OC(UTRACE_UCNV_OPEN);
845ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
846ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(U_SUCCESS(*err)) {
847ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        UTRACE_DATA1(UTRACE_OPEN_CLOSE, "open converter %s", converterName);
848ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
84985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        mySharedConverterData = ucnv_loadSharedData(converterName, &stackPieces, &stackArgs, err);
85085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
85185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        myUConverter = ucnv_createConverterFromSharedData(
85285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            myUConverter, mySharedConverterData,
85385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            &stackArgs,
85485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            err);
855ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
856ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if(U_SUCCESS(*err)) {
85785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            UTRACE_EXIT_PTR_STATUS(myUConverter, *err);
85885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            return myUConverter;
859ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
860ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
861ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
862ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* exit with error */
863ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UTRACE_EXIT_STATUS(*err);
864ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return NULL;
865ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
866ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
86785bf2e2fbc60a9f938064abc8127d61da7d19882Claire HoU_CFUNC UBool
86885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Houcnv_canCreateConverter(const char *converterName, UErrorCode *err) {
86985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    UConverter myUConverter;
87085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    UConverterNamePieces stackPieces;
871103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    UConverterLoadArgs stackArgs=UCNV_LOAD_ARGS_INITIALIZER;
87285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    UConverterSharedData *mySharedConverterData;
87385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
87485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    UTRACE_ENTRY_OC(UTRACE_UCNV_OPEN);
87585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
87685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    if(U_SUCCESS(*err)) {
87785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        UTRACE_DATA1(UTRACE_OPEN_CLOSE, "test if can open converter %s", converterName);
87885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
87985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        stackArgs.onlyTestIsLoadable=TRUE;
88085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        mySharedConverterData = ucnv_loadSharedData(converterName, &stackPieces, &stackArgs, err);
88185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        ucnv_createConverterFromSharedData(
88285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            &myUConverter, mySharedConverterData,
88385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            &stackArgs,
88485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            err);
88585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        ucnv_unloadSharedDataIfReady(mySharedConverterData);
88685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    }
88785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
88885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    UTRACE_EXIT_STATUS(*err);
88985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    return U_SUCCESS(*err);
89085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho}
89185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
892ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUConverter *
893ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruucnv_createAlgorithmicConverter(UConverter *myUConverter,
894ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                                UConverterType type,
895ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                                const char *locale, uint32_t options,
896ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                                UErrorCode *err) {
897ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UConverter *cnv;
898ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    const UConverterSharedData *sharedData;
899103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    UConverterLoadArgs stackArgs=UCNV_LOAD_ARGS_INITIALIZER;
900ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
901ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UTRACE_ENTRY_OC(UTRACE_UCNV_OPEN_ALGORITHMIC);
902ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UTRACE_DATA1(UTRACE_OPEN_CLOSE, "open algorithmic converter type %d", (int32_t)type);
903ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
904ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(type<0 || UCNV_NUMBER_OF_SUPPORTED_CONVERTER_TYPES<=type) {
905ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        *err = U_ILLEGAL_ARGUMENT_ERROR;
906ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        UTRACE_EXIT_STATUS(U_ILLEGAL_ARGUMENT_ERROR);
907ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return NULL;
908ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
909ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
910ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    sharedData = converterData[type];
91185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    /*
91285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    Checking whether it's an algorithic converter is okay
91385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    in multithreaded applications because the value never changes.
91485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    Don't check referenceCounter for any other value.
91585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    */
916103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    if(sharedData == NULL || sharedData->referenceCounter != (uint32_t)~0) {
917ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* not a valid type, or not an algorithmic converter */
918ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        *err = U_ILLEGAL_ARGUMENT_ERROR;
919ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        UTRACE_EXIT_STATUS(U_ILLEGAL_ARGUMENT_ERROR);
920ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return NULL;
921ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
922ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
92385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    stackArgs.name = "";
92485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    stackArgs.options = options;
92585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    stackArgs.locale=locale;
92685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    cnv = ucnv_createConverterFromSharedData(
92785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            myUConverter, (UConverterSharedData *)sharedData,
92885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            &stackArgs, err);
929ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
930ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UTRACE_EXIT_PTR_STATUS(cnv, *err);
931ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return cnv;
932ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
933ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
934103e9ffba2cba345d0078eb8b8db33249f81840aCraig CorneliusU_CFUNC UConverter*
935ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruucnv_createConverterFromPackage(const char *packageName, const char *converterName, UErrorCode * err)
936ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
937ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UConverter *myUConverter;
938ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UConverterSharedData *mySharedConverterData;
93985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    UConverterNamePieces stackPieces;
940103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    UConverterLoadArgs stackArgs=UCNV_LOAD_ARGS_INITIALIZER;
941ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
942ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UTRACE_ENTRY_OC(UTRACE_UCNV_OPEN_PACKAGE);
943ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
944ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(U_FAILURE(*err)) {
945ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        UTRACE_EXIT_STATUS(*err);
946ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return NULL;
947ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
948ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
949ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UTRACE_DATA2(UTRACE_OPEN_CLOSE, "open converter %s from package %s", converterName, packageName);
950ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
951ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* first, get the options out of the converterName string */
95285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    stackPieces.cnvName[0] = 0;
95385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    stackPieces.locale[0] = 0;
95485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    stackPieces.options = 0;
95585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    parseConverterOptions(converterName, &stackPieces, &stackArgs, err);
956ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (U_FAILURE(*err)) {
957ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* Very bad name used. */
958ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        UTRACE_EXIT_STATUS(*err);
959ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return NULL;
960ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
96185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    stackArgs.nestedLoads=1;
96285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    stackArgs.pkg=packageName;
963ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
964ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* open the data, unflatten the shared structure */
96585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    mySharedConverterData = createConverterFromFile(&stackArgs, err);
966ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
967ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (U_FAILURE(*err)) {
968ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        UTRACE_EXIT_STATUS(*err);
969ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return NULL;
970ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
971ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
972ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* create the actual converter */
97385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    myUConverter = ucnv_createConverterFromSharedData(NULL, mySharedConverterData, &stackArgs, err);
974ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
975ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (U_FAILURE(*err)) {
976ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        ucnv_close(myUConverter);
977ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        UTRACE_EXIT_STATUS(*err);
978ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return NULL;
979ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
980ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
981ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UTRACE_EXIT_PTR_STATUS(myUConverter, *err);
982ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return myUConverter;
983ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
984ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
985ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
986103e9ffba2cba345d0078eb8b8db33249f81840aCraig CorneliusU_CFUNC UConverter*
987ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruucnv_createConverterFromSharedData(UConverter *myUConverter,
988ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                                   UConverterSharedData *mySharedConverterData,
98985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                                   UConverterLoadArgs *pArgs,
990ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                                   UErrorCode *err)
991ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
992ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UBool isCopyLocal;
993ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
99485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    if(U_FAILURE(*err)) {
99585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        ucnv_unloadSharedDataIfReady(mySharedConverterData);
99685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        return myUConverter;
99785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    }
998ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(myUConverter == NULL)
999ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    {
1000ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        myUConverter = (UConverter *) uprv_malloc (sizeof (UConverter));
1001ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if(myUConverter == NULL)
1002ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        {
1003ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            *err = U_MEMORY_ALLOCATION_ERROR;
100485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            ucnv_unloadSharedDataIfReady(mySharedConverterData);
1005ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            return NULL;
1006ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1007ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        isCopyLocal = FALSE;
1008ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    } else {
1009ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        isCopyLocal = TRUE;
1010ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1011ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1012ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* initialize the converter */
1013ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    uprv_memset(myUConverter, 0, sizeof(UConverter));
1014ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    myUConverter->isCopyLocal = isCopyLocal;
1015ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /*myUConverter->isExtraLocal = FALSE;*/ /* Set by the memset call */
1016ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    myUConverter->sharedData = mySharedConverterData;
101785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    myUConverter->options = pArgs->options;
101885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    if(!pArgs->onlyTestIsLoadable) {
101985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        myUConverter->preFromUFirstCP = U_SENTINEL;
102085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        myUConverter->fromCharErrorBehaviour = UCNV_TO_U_DEFAULT_CALLBACK;
102185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        myUConverter->fromUCharErrorBehaviour = UCNV_FROM_U_DEFAULT_CALLBACK;
102285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        myUConverter->toUnicodeStatus = mySharedConverterData->toUnicodeStatus;
102385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        myUConverter->maxBytesPerUChar = mySharedConverterData->staticData->maxBytesPerChar;
102485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        myUConverter->subChar1 = mySharedConverterData->staticData->subChar1;
102585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        myUConverter->subCharLen = mySharedConverterData->staticData->subCharLen;
102685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        myUConverter->subChars = (uint8_t *)myUConverter->subUChars;
102785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        uprv_memcpy(myUConverter->subChars, mySharedConverterData->staticData->subChar, myUConverter->subCharLen);
102885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        myUConverter->toUCallbackReason = UCNV_ILLEGAL; /* default reason to invoke (*fromCharErrorBehaviour) */
102985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    }
1030ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1031ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(mySharedConverterData->impl->open != NULL) {
103285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        mySharedConverterData->impl->open(myUConverter, pArgs, err);
103385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        if(U_FAILURE(*err) && !pArgs->onlyTestIsLoadable) {
103485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            /* don't ucnv_close() if onlyTestIsLoadable because not fully initialized */
1035ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            ucnv_close(myUConverter);
1036ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            return NULL;
1037ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1038ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1039ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1040ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return myUConverter;
1041ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
1042ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1043ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/*Frees all shared immutable objects that aren't referred to (reference count = 0)
1044ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */
1045ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruU_CAPI int32_t U_EXPORT2
1046ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruucnv_flushCache ()
1047ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
1048ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UConverterSharedData *mySharedData = NULL;
1049ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t pos;
1050ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t tableDeletedNum = 0;
1051ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    const UHashElement *e;
105227f654740f2a26ad62a5c155af9199af9e69b889claireho    /*UErrorCode status = U_ILLEGAL_ARGUMENT_ERROR;*/
1053ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t i, remaining;
1054ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1055ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UTRACE_ENTRY_OC(UTRACE_UCNV_FLUSH_CACHE);
1056ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1057ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* Close the default converter without creating a new one so that everything will be flushed. */
105827f654740f2a26ad62a5c155af9199af9e69b889claireho    u_flushDefaultConverter();
1059ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1060ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /*if shared data hasn't even been lazy evaluated yet
1061ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    * return 0
1062ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    */
1063ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (SHARED_DATA_HASHTABLE == NULL) {
1064ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        UTRACE_EXIT_VALUE((int32_t)0);
1065ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return 0;
1066ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1067ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1068ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /*creates an enumeration to iterate through every element in the
1069ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    * table
1070ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    *
1071ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    * Synchronization:  holding cnvCacheMutex will prevent any other thread from
1072ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    *                   accessing or modifying the hash table during the iteration.
1073ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    *                   The reference count of an entry may be decremented by
1074ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    *                   ucnv_close while the iteration is in process, but this is
1075ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    *                   benign.  It can't be incremented (in ucnv_createConverter())
1076ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    *                   because the sequence of looking up in the cache + incrementing
1077ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    *                   is protected by cnvCacheMutex.
1078ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    */
1079ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    umtx_lock(&cnvCacheMutex);
1080ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /*
1081ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     * double loop: A delta/extension-only converter has a pointer to its base table's
1082ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     * shared data; the first iteration of the outer loop may see the delta converter
1083ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     * before the base converter, and unloading the delta converter may get the base
1084ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     * converter's reference counter down to 0.
1085ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     */
1086ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    i = 0;
1087ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    do {
1088ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        remaining = 0;
1089ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        pos = -1;
1090ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        while ((e = uhash_nextElement (SHARED_DATA_HASHTABLE, &pos)) != NULL)
1091ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        {
1092ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            mySharedData = (UConverterSharedData *) e->value.pointer;
1093ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            /*deletes only if reference counter == 0 */
1094ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if (mySharedData->referenceCounter == 0)
1095ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            {
1096ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                tableDeletedNum++;
1097ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1098ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                UCNV_DEBUG_LOG("del",mySharedData->staticData->name,mySharedData);
1099ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1100ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                uhash_removeElement(SHARED_DATA_HASHTABLE, e);
1101ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                mySharedData->sharedDataCached = FALSE;
1102ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                ucnv_deleteSharedConverterData (mySharedData);
1103ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            } else {
1104ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                ++remaining;
1105ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
1106ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1107ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    } while(++i == 1 && remaining > 0);
1108ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    umtx_unlock(&cnvCacheMutex);
1109ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1110ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UTRACE_DATA1(UTRACE_INFO, "ucnv_flushCache() exits with %d converters remaining", remaining);
1111ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1112ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UTRACE_EXIT_VALUE(tableDeletedNum);
1113ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return tableDeletedNum;
1114ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
1115ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1116ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/* available converters list --------------------------------------------------- */
1117ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
111859d709d503bab6e2b61931737e662dd293b40578ccorneliusstatic void U_CALLCONV initAvailableConvertersList(UErrorCode &errCode) {
111959d709d503bab6e2b61931737e662dd293b40578ccornelius    U_ASSERT(gAvailableConverterCount == 0);
112059d709d503bab6e2b61931737e662dd293b40578ccornelius    U_ASSERT(gAvailableConverters == NULL);
1121ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
112259d709d503bab6e2b61931737e662dd293b40578ccornelius    ucln_common_registerCleanup(UCLN_COMMON_UCNV, ucnv_cleanup);
112359d709d503bab6e2b61931737e662dd293b40578ccornelius    UEnumeration *allConvEnum = ucnv_openAllNames(&errCode);
112459d709d503bab6e2b61931737e662dd293b40578ccornelius    int32_t allConverterCount = uenum_count(allConvEnum, &errCode);
112559d709d503bab6e2b61931737e662dd293b40578ccornelius    if (U_FAILURE(errCode)) {
112659d709d503bab6e2b61931737e662dd293b40578ccornelius        return;
112759d709d503bab6e2b61931737e662dd293b40578ccornelius    }
1128ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
112959d709d503bab6e2b61931737e662dd293b40578ccornelius    /* We can't have more than "*converterTable" converters to open */
113059d709d503bab6e2b61931737e662dd293b40578ccornelius    gAvailableConverters = (const char **) uprv_malloc(allConverterCount * sizeof(char*));
113159d709d503bab6e2b61931737e662dd293b40578ccornelius    if (!gAvailableConverters) {
113259d709d503bab6e2b61931737e662dd293b40578ccornelius        errCode = U_MEMORY_ALLOCATION_ERROR;
113359d709d503bab6e2b61931737e662dd293b40578ccornelius        return;
113459d709d503bab6e2b61931737e662dd293b40578ccornelius    }
1135ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
113659d709d503bab6e2b61931737e662dd293b40578ccornelius    /* Open the default converter to make sure that it has first dibs in the hash table. */
113759d709d503bab6e2b61931737e662dd293b40578ccornelius    UErrorCode localStatus = U_ZERO_ERROR;
113859d709d503bab6e2b61931737e662dd293b40578ccornelius    UConverter tempConverter;
113959d709d503bab6e2b61931737e662dd293b40578ccornelius    ucnv_close(ucnv_createConverter(&tempConverter, NULL, &localStatus));
1140ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
114159d709d503bab6e2b61931737e662dd293b40578ccornelius    gAvailableConverterCount = 0;
1142ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
114359d709d503bab6e2b61931737e662dd293b40578ccornelius    for (int32_t idx = 0; idx < allConverterCount; idx++) {
114459d709d503bab6e2b61931737e662dd293b40578ccornelius        localStatus = U_ZERO_ERROR;
114559d709d503bab6e2b61931737e662dd293b40578ccornelius        const char *converterName = uenum_next(allConvEnum, NULL, &localStatus);
114659d709d503bab6e2b61931737e662dd293b40578ccornelius        if (ucnv_canCreateConverter(converterName, &localStatus)) {
114759d709d503bab6e2b61931737e662dd293b40578ccornelius            gAvailableConverters[gAvailableConverterCount++] = converterName;
1148ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1149ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
115059d709d503bab6e2b61931737e662dd293b40578ccornelius
115159d709d503bab6e2b61931737e662dd293b40578ccornelius    uenum_close(allConvEnum);
115259d709d503bab6e2b61931737e662dd293b40578ccornelius}
115359d709d503bab6e2b61931737e662dd293b40578ccornelius
115459d709d503bab6e2b61931737e662dd293b40578ccornelius
115559d709d503bab6e2b61931737e662dd293b40578ccorneliusstatic UBool haveAvailableConverterList(UErrorCode *pErrorCode) {
115659d709d503bab6e2b61931737e662dd293b40578ccornelius    umtx_initOnce(gAvailableConvertersInitOnce, &initAvailableConvertersList, *pErrorCode);
115759d709d503bab6e2b61931737e662dd293b40578ccornelius    return U_SUCCESS(*pErrorCode);
1158ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
1159ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1160ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruU_CFUNC uint16_t
1161ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruucnv_bld_countAvailableConverters(UErrorCode *pErrorCode) {
1162ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (haveAvailableConverterList(pErrorCode)) {
1163ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return gAvailableConverterCount;
1164ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1165ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return 0;
1166ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
1167ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1168ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruU_CFUNC const char *
1169ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruucnv_bld_getAvailableConverter(uint16_t n, UErrorCode *pErrorCode) {
1170ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (haveAvailableConverterList(pErrorCode)) {
1171ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (n < gAvailableConverterCount) {
1172ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            return gAvailableConverters[n];
1173ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1174ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        *pErrorCode = U_INDEX_OUTOFBOUNDS_ERROR;
1175ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1176ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return NULL;
1177ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
1178ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1179ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/* default converter name --------------------------------------------------- */
1180ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
118185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho#if !U_CHARSET_IS_UTF8
1182ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/*
1183ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruCopy the canonical converter name.
1184ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruucnv_getDefaultName must be thread safe, which can call this function.
1185ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1186ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruucnv_setDefaultName calls this function and it doesn't have to be
1187ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruthread safe because there is no reliable/safe way to reset the
1188ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruconverter in use in all threads. If you did reset the converter, you
1189ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruwould not be sure that retrieving a default converter for one string
1190ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruwould be the same type of default converter for a successive string.
1191ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruSince the name is a returned via ucnv_getDefaultName without copying,
1192ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruyou shouldn't be modifying or deleting the string from a separate thread.
1193ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*/
1194103e9ffba2cba345d0078eb8b8db33249f81840aCraig Corneliusstatic inline void
1195ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruinternalSetName(const char *name, UErrorCode *status) {
119685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    UConverterNamePieces stackPieces;
1197103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    UConverterLoadArgs stackArgs=UCNV_LOAD_ARGS_INITIALIZER;
1198ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t length=(int32_t)(uprv_strlen(name));
1199ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UBool containsOption = (UBool)(uprv_strchr(name, UCNV_OPTION_SEP_CHAR) != NULL);
1200ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    const UConverterSharedData *algorithmicSharedData;
1201ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
120285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    stackArgs.name = name;
1203ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(containsOption) {
120485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        stackPieces.cnvName[0] = 0;
120585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        stackPieces.locale[0] = 0;
120685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        stackPieces.options = 0;
120785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        parseConverterOptions(name, &stackPieces, &stackArgs, status);
120885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        if(U_FAILURE(*status)) {
120985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            return;
121085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
1211ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
121285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    algorithmicSharedData = getAlgorithmicTypeFromName(stackArgs.name);
1213ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1214ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    umtx_lock(&cnvCacheMutex);
1215ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1216ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    gDefaultAlgorithmicSharedData = algorithmicSharedData;
1217ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    gDefaultConverterContainsOption = containsOption;
1218ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    uprv_memcpy(gDefaultConverterNameBuffer, name, length);
1219ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    gDefaultConverterNameBuffer[length]=0;
122085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
122185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    /* gDefaultConverterName MUST be the last global var set by this function.  */
122285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    /*    It is the variable checked in ucnv_getDefaultName() to see if initialization is required. */
122359d709d503bab6e2b61931737e662dd293b40578ccornelius    //    But there is nothing here preventing that from being reordered, either by the compiler
122459d709d503bab6e2b61931737e662dd293b40578ccornelius    //             or hardware. I'm adding the mutex to ucnv_getDefaultName for now. UMTX_CHECK is not enough.
122559d709d503bab6e2b61931737e662dd293b40578ccornelius    //             -- Andy
1226ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    gDefaultConverterName = gDefaultConverterNameBuffer;
1227ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1228ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    ucln_common_registerCleanup(UCLN_COMMON_UCNV, ucnv_cleanup);
1229ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1230ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    umtx_unlock(&cnvCacheMutex);
1231ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
123285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho#endif
1233ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1234ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/*
1235ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * In order to be really thread-safe, the get function would have to take
1236ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * a buffer parameter and copy the current string inside a mutex block.
1237ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * This implementation only tries to be really thread-safe while
1238ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * setting the name.
1239ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * It assumes that setting a pointer is atomic.
1240ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */
1241ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1242ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruU_CAPI const char*  U_EXPORT2
1243ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruucnv_getDefaultName() {
124485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho#if U_CHARSET_IS_UTF8
124585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    return "UTF-8";
124685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho#else
1247ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* local variable to be thread-safe */
1248ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    const char *name;
1249ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1250ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /*
125159d709d503bab6e2b61931737e662dd293b40578ccornelius    Concurrent calls to ucnv_getDefaultName must be thread safe,
1252ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    but ucnv_setDefaultName is not thread safe.
1253ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    */
125459d709d503bab6e2b61931737e662dd293b40578ccornelius    {
125559d709d503bab6e2b61931737e662dd293b40578ccornelius        icu::Mutex lock(&cnvCacheMutex);
125659d709d503bab6e2b61931737e662dd293b40578ccornelius        name = gDefaultConverterName;
125759d709d503bab6e2b61931737e662dd293b40578ccornelius    }
1258ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(name==NULL) {
1259ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        UErrorCode errorCode = U_ZERO_ERROR;
1260ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        UConverter *cnv = NULL;
1261ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1262ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        name = uprv_getDefaultCodepage();
1263ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1264ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* if the name is there, test it out and get the canonical name with options */
1265ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if(name != NULL) {
1266ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            cnv = ucnv_open(name, &errorCode);
1267ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if(U_SUCCESS(errorCode) && cnv != NULL) {
1268ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                name = ucnv_getName(cnv, &errorCode);
1269ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
1270ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1271ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1272ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if(name == NULL || name[0] == 0
1273ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            || U_FAILURE(errorCode) || cnv == NULL
1274ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            || uprv_strlen(name)>=sizeof(gDefaultConverterNameBuffer))
1275ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        {
1276ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            /* Panic time, let's use a fallback. */
1277ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#if (U_CHARSET_FAMILY == U_ASCII_FAMILY)
1278ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            name = "US-ASCII";
1279ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            /* there is no 'algorithmic' converter for EBCDIC */
1280103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#elif U_PLATFORM == U_PF_OS390
1281ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            name = "ibm-1047_P100-1995" UCNV_SWAP_LFNL_OPTION_STRING;
1282ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#else
1283ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            name = "ibm-37_P100-1995";
1284ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#endif
1285ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1286ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1287ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        internalSetName(name, &errorCode);
1288ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1289ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* The close may make the current name go away. */
1290ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        ucnv_close(cnv);
1291ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1292ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1293ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return name;
129485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho#endif
1295ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
1296ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
129754dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius#if U_CHARSET_IS_UTF8
129854dcd9b6a06071f647dac967e9e267abb9410720Craig CorneliusU_CAPI void U_EXPORT2 ucnv_setDefaultName(const char *) {}
129954dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius#else
1300ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/*
1301ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruThis function is not thread safe, and it can't be thread safe.
1302ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruSee internalSetName or the API reference for details.
1303ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*/
1304ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruU_CAPI void U_EXPORT2
1305ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruucnv_setDefaultName(const char *converterName) {
1306ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(converterName==NULL) {
1307ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* reset to the default codepage */
1308ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        gDefaultConverterName=NULL;
1309ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    } else {
1310ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        UErrorCode errorCode = U_ZERO_ERROR;
1311ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        UConverter *cnv = NULL;
1312ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        const char *name = NULL;
1313ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1314ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* if the name is there, test it out and get the canonical name with options */
1315ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        cnv = ucnv_open(converterName, &errorCode);
1316ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if(U_SUCCESS(errorCode) && cnv != NULL) {
1317ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            name = ucnv_getName(cnv, &errorCode);
1318ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1319ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1320ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if(U_SUCCESS(errorCode) && name!=NULL) {
1321ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            internalSetName(name, &errorCode);
1322ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1323ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* else this converter is bad to use. Don't change it to a bad value. */
1324ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1325ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* The close may make the current name go away. */
1326ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        ucnv_close(cnv);
132727f654740f2a26ad62a5c155af9199af9e69b889claireho
132827f654740f2a26ad62a5c155af9199af9e69b889claireho        /* reset the converter cache */
132927f654740f2a26ad62a5c155af9199af9e69b889claireho        u_flushDefaultConverter();
1330ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1331ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
133254dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius#endif
1333ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1334ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/* data swapping ------------------------------------------------------------ */
1335ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1336ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/* most of this might belong more properly into ucnvmbcs.c, but that is so large */
1337ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1338ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#if !UCONFIG_NO_LEGACY_CONVERSION
1339ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1340ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruU_CAPI int32_t U_EXPORT2
1341ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruucnv_swap(const UDataSwapper *ds,
1342ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru          const void *inData, int32_t length, void *outData,
1343ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru          UErrorCode *pErrorCode) {
1344ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    const UDataInfo *pInfo;
1345ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t headerSize;
1346ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1347ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    const uint8_t *inBytes;
1348ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    uint8_t *outBytes;
1349ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1350ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    uint32_t offset, count, staticDataSize;
1351ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t size;
1352ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1353ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    const UConverterStaticData *inStaticData;
1354ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UConverterStaticData *outStaticData;
1355ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1356ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    const _MBCSHeader *inMBCSHeader;
1357ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    _MBCSHeader *outMBCSHeader;
1358ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    _MBCSHeader mbcsHeader;
1359c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru    uint32_t mbcsHeaderLength;
1360c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru    UBool noFromU=FALSE;
1361c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru
1362ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    uint8_t outputType;
1363ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1364ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t maxFastUChar, mbcsIndexLength;
1365ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1366ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    const int32_t *inExtIndexes;
1367ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t extOffset;
1368ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1369ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* udata_swapDataHeader checks the arguments */
1370ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    headerSize=udata_swapDataHeader(ds, inData, length, outData, pErrorCode);
1371ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) {
1372ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return 0;
1373ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1374ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1375ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* check data format and format version */
1376ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    pInfo=(const UDataInfo *)((const char *)inData+4);
1377ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(!(
1378ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        pInfo->dataFormat[0]==0x63 &&   /* dataFormat="cnvt" */
1379ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        pInfo->dataFormat[1]==0x6e &&
1380ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        pInfo->dataFormat[2]==0x76 &&
1381ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        pInfo->dataFormat[3]==0x74 &&
1382ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        pInfo->formatVersion[0]==6 &&
1383ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        pInfo->formatVersion[1]>=2
1384ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    )) {
1385ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        udata_printError(ds, "ucnv_swap(): data format %02x.%02x.%02x.%02x (format version %02x.%02x) is not recognized as an ICU .cnv conversion table\n",
1386ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                         pInfo->dataFormat[0], pInfo->dataFormat[1],
1387ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                         pInfo->dataFormat[2], pInfo->dataFormat[3],
1388ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                         pInfo->formatVersion[0], pInfo->formatVersion[1]);
1389ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        *pErrorCode=U_UNSUPPORTED_ERROR;
1390ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return 0;
1391ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1392ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1393ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    inBytes=(const uint8_t *)inData+headerSize;
1394ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    outBytes=(uint8_t *)outData+headerSize;
1395ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1396ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* read the initial UConverterStaticData structure after the UDataInfo header */
1397ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    inStaticData=(const UConverterStaticData *)inBytes;
1398ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    outStaticData=(UConverterStaticData *)outBytes;
1399ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1400ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(length<0) {
1401ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        staticDataSize=ds->readUInt32(inStaticData->structSize);
1402ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    } else {
1403ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        length-=headerSize;
1404103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        if( length<(int32_t)sizeof(UConverterStaticData) ||
1405ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            (uint32_t)length<(staticDataSize=ds->readUInt32(inStaticData->structSize))
1406ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        ) {
1407ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            udata_printError(ds, "ucnv_swap(): too few bytes (%d after header) for an ICU .cnv conversion table\n",
1408ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                             length);
1409ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            *pErrorCode=U_INDEX_OUTOFBOUNDS_ERROR;
1410ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            return 0;
1411ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1412ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1413ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1414ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(length>=0) {
1415ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* swap the static data */
1416ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if(inStaticData!=outStaticData) {
1417ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            uprv_memcpy(outStaticData, inStaticData, staticDataSize);
1418ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1419ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1420ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        ds->swapArray32(ds, &inStaticData->structSize, 4,
1421ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                           &outStaticData->structSize, pErrorCode);
1422ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        ds->swapArray32(ds, &inStaticData->codepage, 4,
1423ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                           &outStaticData->codepage, pErrorCode);
1424ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1425ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        ds->swapInvChars(ds, inStaticData->name, (int32_t)uprv_strlen(inStaticData->name),
1426ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                            outStaticData->name, pErrorCode);
1427ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if(U_FAILURE(*pErrorCode)) {
1428ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            udata_printError(ds, "ucnv_swap(): error swapping converter name\n");
1429ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            return 0;
1430ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1431ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1432ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1433ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    inBytes+=staticDataSize;
1434ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    outBytes+=staticDataSize;
1435ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(length>=0) {
1436ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        length-=(int32_t)staticDataSize;
1437ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1438ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1439ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* check for supported conversionType values */
1440ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(inStaticData->conversionType==UCNV_MBCS) {
1441ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* swap MBCS data */
1442ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        inMBCSHeader=(const _MBCSHeader *)inBytes;
1443ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        outMBCSHeader=(_MBCSHeader *)outBytes;
1444ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1445103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        if(0<=length && length<(int32_t)sizeof(_MBCSHeader)) {
1446ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            udata_printError(ds, "ucnv_swap(): too few bytes (%d after headers) for an ICU MBCS .cnv conversion table\n",
1447ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                                length);
1448ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            *pErrorCode=U_INDEX_OUTOFBOUNDS_ERROR;
1449ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            return 0;
1450ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1451c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru        if(inMBCSHeader->version[0]==4 && inMBCSHeader->version[1]>=1) {
1452c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru            mbcsHeaderLength=MBCS_HEADER_V4_LENGTH;
1453c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru        } else if(inMBCSHeader->version[0]==5 && inMBCSHeader->version[1]>=3 &&
1454c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru                  ((mbcsHeader.options=ds->readUInt32(inMBCSHeader->options))&
1455c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru                   MBCS_OPT_UNKNOWN_INCOMPATIBLE_MASK)==0
1456c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru        ) {
1457c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru            mbcsHeaderLength=mbcsHeader.options&MBCS_OPT_LENGTH_MASK;
1458c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru            noFromU=(UBool)((mbcsHeader.options&MBCS_OPT_NO_FROM_U)!=0);
1459c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru        } else {
1460ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            udata_printError(ds, "ucnv_swap(): unsupported _MBCSHeader.version %d.%d\n",
1461ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                             inMBCSHeader->version[0], inMBCSHeader->version[1]);
1462ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            *pErrorCode=U_UNSUPPORTED_ERROR;
1463ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            return 0;
1464ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1465ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1466ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        uprv_memcpy(mbcsHeader.version, inMBCSHeader->version, 4);
1467ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        mbcsHeader.countStates=         ds->readUInt32(inMBCSHeader->countStates);
1468ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        mbcsHeader.countToUFallbacks=   ds->readUInt32(inMBCSHeader->countToUFallbacks);
1469ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        mbcsHeader.offsetToUCodeUnits=  ds->readUInt32(inMBCSHeader->offsetToUCodeUnits);
1470ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        mbcsHeader.offsetFromUTable=    ds->readUInt32(inMBCSHeader->offsetFromUTable);
1471ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        mbcsHeader.offsetFromUBytes=    ds->readUInt32(inMBCSHeader->offsetFromUBytes);
1472ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        mbcsHeader.flags=               ds->readUInt32(inMBCSHeader->flags);
1473ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        mbcsHeader.fromUBytesLength=    ds->readUInt32(inMBCSHeader->fromUBytesLength);
1474c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru        /* mbcsHeader.options have been read above */
1475ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1476ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        extOffset=(int32_t)(mbcsHeader.flags>>8);
1477ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        outputType=(uint8_t)mbcsHeader.flags;
1478c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru        if(noFromU && outputType==MBCS_OUTPUT_1) {
1479c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru            udata_printError(ds, "ucnv_swap(): unsupported combination of makeconv --small with SBCS\n");
1480c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru            *pErrorCode=U_UNSUPPORTED_ERROR;
1481c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru            return 0;
1482c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru        }
1483ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1484ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* make sure that the output type is known */
1485ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        switch(outputType) {
1486ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        case MBCS_OUTPUT_1:
1487ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        case MBCS_OUTPUT_2:
1488ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        case MBCS_OUTPUT_3:
1489ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        case MBCS_OUTPUT_4:
1490ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        case MBCS_OUTPUT_3_EUC:
1491ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        case MBCS_OUTPUT_4_EUC:
1492ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        case MBCS_OUTPUT_2_SISO:
1493ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        case MBCS_OUTPUT_EXT_ONLY:
1494ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            /* OK */
1495ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            break;
1496ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        default:
1497ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            udata_printError(ds, "ucnv_swap(): unsupported MBCS output type 0x%x\n",
1498ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                             outputType);
1499ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            *pErrorCode=U_UNSUPPORTED_ERROR;
1500ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            return 0;
1501ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1502ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1503ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* calculate the length of the MBCS data */
1504ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1505ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /*
1506ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru         * utf8Friendly MBCS files (mbcsHeader.version 4.3)
1507ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru         * contain an additional mbcsIndex table:
1508ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru         *   uint16_t[(maxFastUChar+1)>>6];
1509ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru         * where maxFastUChar=((mbcsHeader.version[2]<<8)|0xff).
1510ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru         */
1511ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        maxFastUChar=0;
1512ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        mbcsIndexLength=0;
1513ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if( outputType!=MBCS_OUTPUT_EXT_ONLY && outputType!=MBCS_OUTPUT_1 &&
1514ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            mbcsHeader.version[1]>=3 && (maxFastUChar=mbcsHeader.version[2])!=0
1515ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        ) {
1516ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            maxFastUChar=(maxFastUChar<<8)|0xff;
1517ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            mbcsIndexLength=((maxFastUChar+1)>>6)*2;  /* number of bytes */
1518ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1519ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1520ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if(extOffset==0) {
1521c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru            size=(int32_t)(mbcsHeader.offsetFromUBytes+mbcsIndexLength);
1522c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru            if(!noFromU) {
1523c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru                size+=(int32_t)mbcsHeader.fromUBytesLength;
1524c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru            }
1525ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1526ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            /* avoid compiler warnings - not otherwise necessary, and the value does not matter */
1527ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            inExtIndexes=NULL;
1528ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        } else {
1529ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            /* there is extension data after the base data, see ucnv_ext.h */
1530ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if(length>=0 && length<(extOffset+UCNV_EXT_INDEXES_MIN_LENGTH*4)) {
1531ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                udata_printError(ds, "ucnv_swap(): too few bytes (%d after headers) for an ICU MBCS .cnv conversion table with extension data\n",
1532ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                                 length);
1533ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                *pErrorCode=U_INDEX_OUTOFBOUNDS_ERROR;
1534ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                return 0;
1535ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
1536ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1537ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            inExtIndexes=(const int32_t *)(inBytes+extOffset);
1538ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            size=extOffset+udata_readInt32(ds, inExtIndexes[UCNV_EXT_SIZE]);
1539ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1540ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1541ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if(length>=0) {
1542ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if(length<size) {
1543ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                udata_printError(ds, "ucnv_swap(): too few bytes (%d after headers) for an ICU MBCS .cnv conversion table\n",
1544ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                                 length);
1545ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                *pErrorCode=U_INDEX_OUTOFBOUNDS_ERROR;
1546ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                return 0;
1547ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
1548ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1549ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            /* copy the data for inaccessible bytes */
1550ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if(inBytes!=outBytes) {
1551ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                uprv_memcpy(outBytes, inBytes, size);
1552ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
1553ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1554c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru            /* swap the MBCSHeader, except for the version field */
1555c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru            count=mbcsHeaderLength*4;
1556c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru            ds->swapArray32(ds, &inMBCSHeader->countStates, count-4,
1557ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                               &outMBCSHeader->countStates, pErrorCode);
1558ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1559ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if(outputType==MBCS_OUTPUT_EXT_ONLY) {
1560ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                /*
1561ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                 * extension-only file,
1562ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                 * contains a base name instead of normal base table data
1563ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                 */
1564ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1565ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                /* swap the base name, between the header and the extension data */
1566c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru                const char *inBaseName=(const char *)inBytes+count;
1567c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru                char *outBaseName=(char *)outBytes+count;
1568c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru                ds->swapInvChars(ds, inBaseName, (int32_t)uprv_strlen(inBaseName),
1569c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru                                    outBaseName, pErrorCode);
1570ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            } else {
1571ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                /* normal file with base table data */
1572ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1573ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                /* swap the state table, 1kB per state */
1574c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru                offset=count;
1575c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru                count=mbcsHeader.countStates*1024;
1576c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru                ds->swapArray32(ds, inBytes+offset, (int32_t)count,
1577c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru                                   outBytes+offset, pErrorCode);
1578ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1579ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                /* swap the toUFallbacks[] */
1580c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru                offset+=count;
1581c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru                count=mbcsHeader.countToUFallbacks*8;
1582c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru                ds->swapArray32(ds, inBytes+offset, (int32_t)count,
1583ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                                   outBytes+offset, pErrorCode);
1584ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1585ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                /* swap the unicodeCodeUnits[] */
1586ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                offset=mbcsHeader.offsetToUCodeUnits;
1587ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                count=mbcsHeader.offsetFromUTable-offset;
1588ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                ds->swapArray16(ds, inBytes+offset, (int32_t)count,
1589ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                                   outBytes+offset, pErrorCode);
1590ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1591ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                /* offset to the stage 1 table, independent of the outputType */
1592ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                offset=mbcsHeader.offsetFromUTable;
1593ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1594ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                if(outputType==MBCS_OUTPUT_1) {
1595ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    /* SBCS: swap the fromU tables, all 16 bits wide */
1596ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    count=(mbcsHeader.offsetFromUBytes-offset)+mbcsHeader.fromUBytesLength;
1597ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    ds->swapArray16(ds, inBytes+offset, (int32_t)count,
1598ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                                       outBytes+offset, pErrorCode);
1599ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                } else {
1600ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    /* otherwise: swap the stage tables separately */
1601ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1602ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    /* stage 1 table: uint16_t[0x440 or 0x40] */
1603ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    if(inStaticData->unicodeMask&UCNV_HAS_SUPPLEMENTARY) {
1604ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        count=0x440*2; /* for all of Unicode */
1605ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    } else {
1606ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        count=0x40*2; /* only BMP */
1607ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    }
1608ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    ds->swapArray16(ds, inBytes+offset, (int32_t)count,
1609ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                                       outBytes+offset, pErrorCode);
1610ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1611ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    /* stage 2 table: uint32_t[] */
1612ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    offset+=count;
1613ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    count=mbcsHeader.offsetFromUBytes-offset;
1614ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    ds->swapArray32(ds, inBytes+offset, (int32_t)count,
1615ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                                       outBytes+offset, pErrorCode);
1616ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1617ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    /* stage 3/result bytes: sometimes uint16_t[] or uint32_t[] */
1618ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    offset=mbcsHeader.offsetFromUBytes;
1619c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru                    count= noFromU ? 0 : mbcsHeader.fromUBytesLength;
1620ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    switch(outputType) {
1621ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    case MBCS_OUTPUT_2:
1622ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    case MBCS_OUTPUT_3_EUC:
1623ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    case MBCS_OUTPUT_2_SISO:
1624ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        ds->swapArray16(ds, inBytes+offset, (int32_t)count,
1625ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                                           outBytes+offset, pErrorCode);
1626ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        break;
1627ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    case MBCS_OUTPUT_4:
1628ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        ds->swapArray32(ds, inBytes+offset, (int32_t)count,
1629ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                                           outBytes+offset, pErrorCode);
1630ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        break;
1631ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    default:
1632ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        /* just uint8_t[], nothing to swap */
1633ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        break;
1634ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    }
1635ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1636ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    if(mbcsIndexLength!=0) {
1637ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        offset+=count;
1638ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        count=mbcsIndexLength;
1639ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        ds->swapArray16(ds, inBytes+offset, (int32_t)count,
1640ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                                           outBytes+offset, pErrorCode);
1641ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    }
1642ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                }
1643ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
1644ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1645ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if(extOffset!=0) {
1646ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                /* swap the extension data */
1647ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                inBytes+=extOffset;
1648ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                outBytes+=extOffset;
1649ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1650ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                /* swap toUTable[] */
1651ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                offset=udata_readInt32(ds, inExtIndexes[UCNV_EXT_TO_U_INDEX]);
1652ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                length=udata_readInt32(ds, inExtIndexes[UCNV_EXT_TO_U_LENGTH]);
1653ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                ds->swapArray32(ds, inBytes+offset, length*4, outBytes+offset, pErrorCode);
1654ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1655ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                /* swap toUUChars[] */
1656ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                offset=udata_readInt32(ds, inExtIndexes[UCNV_EXT_TO_U_UCHARS_INDEX]);
1657ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                length=udata_readInt32(ds, inExtIndexes[UCNV_EXT_TO_U_UCHARS_LENGTH]);
1658ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                ds->swapArray16(ds, inBytes+offset, length*2, outBytes+offset, pErrorCode);
1659ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1660ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                /* swap fromUTableUChars[] */
1661ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                offset=udata_readInt32(ds, inExtIndexes[UCNV_EXT_FROM_U_UCHARS_INDEX]);
1662ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                length=udata_readInt32(ds, inExtIndexes[UCNV_EXT_FROM_U_LENGTH]);
1663ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                ds->swapArray16(ds, inBytes+offset, length*2, outBytes+offset, pErrorCode);
1664ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1665ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                /* swap fromUTableValues[] */
1666ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                offset=udata_readInt32(ds, inExtIndexes[UCNV_EXT_FROM_U_VALUES_INDEX]);
1667ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                /* same length as for fromUTableUChars[] */
1668ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                ds->swapArray32(ds, inBytes+offset, length*4, outBytes+offset, pErrorCode);
1669ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1670ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                /* no need to swap fromUBytes[] */
1671ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1672ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                /* swap fromUStage12[] */
1673ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                offset=udata_readInt32(ds, inExtIndexes[UCNV_EXT_FROM_U_STAGE_12_INDEX]);
1674ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                length=udata_readInt32(ds, inExtIndexes[UCNV_EXT_FROM_U_STAGE_12_LENGTH]);
1675ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                ds->swapArray16(ds, inBytes+offset, length*2, outBytes+offset, pErrorCode);
1676ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1677ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                /* swap fromUStage3[] */
1678ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                offset=udata_readInt32(ds, inExtIndexes[UCNV_EXT_FROM_U_STAGE_3_INDEX]);
1679ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                length=udata_readInt32(ds, inExtIndexes[UCNV_EXT_FROM_U_STAGE_3_LENGTH]);
1680ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                ds->swapArray16(ds, inBytes+offset, length*2, outBytes+offset, pErrorCode);
1681ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1682ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                /* swap fromUStage3b[] */
1683ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                offset=udata_readInt32(ds, inExtIndexes[UCNV_EXT_FROM_U_STAGE_3B_INDEX]);
1684ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                length=udata_readInt32(ds, inExtIndexes[UCNV_EXT_FROM_U_STAGE_3B_LENGTH]);
1685ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                ds->swapArray32(ds, inBytes+offset, length*4, outBytes+offset, pErrorCode);
1686ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1687ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                /* swap indexes[] */
1688ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                length=udata_readInt32(ds, inExtIndexes[UCNV_EXT_INDEXES_LENGTH]);
1689ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                ds->swapArray32(ds, inBytes, length*4, outBytes, pErrorCode);
1690ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
1691ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1692ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    } else {
1693ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        udata_printError(ds, "ucnv_swap(): unknown conversionType=%d!=UCNV_MBCS\n",
1694ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                         inStaticData->conversionType);
1695ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        *pErrorCode=U_UNSUPPORTED_ERROR;
1696ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return 0;
1697ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1698ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1699ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return headerSize+(int32_t)staticDataSize+size;
1700ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
1701ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1702ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#endif /* #if !UCONFIG_NO_LEGACY_CONVERSION */
1703ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1704ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#endif
1705