1ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/*
2ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru ********************************************************************
3ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * COPYRIGHT:
427f654740f2a26ad62a5c155af9199af9e69b889claireho * Copyright (c) 1996-2010, International Business Machines Corporation and
5ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * others. All Rights Reserved.
6ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru ********************************************************************
7ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *
8ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *  uconv_bld.c:
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"
30ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "utracimp.h"
31ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "ucnv_io.h"
32ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "ucnv_bld.h"
33ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "ucnvmbcs.h"
34ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "ucnv_ext.h"
35ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "ucnv_cnv.h"
36ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "ucnv_imp.h"
37ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "uhash.h"
38ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "umutex.h"
39ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "cstring.h"
40ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "cmemory.h"
41ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "ucln_cmn.h"
42ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "ustr_cnv.h"
43ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
44ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
45ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
46ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#if 0
47ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include <stdio.h>
48ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruextern void UCNV_DEBUG_LOG(char *what, char *who, void *p, int l);
49ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define UCNV_DEBUG_LOG(x,y,z) UCNV_DEBUG_LOG(x,y,z,__LINE__)
50ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#else
51ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru# define UCNV_DEBUG_LOG(x,y,z)
52ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#endif
53ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
54ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic const UConverterSharedData * const
55ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruconverterData[UCNV_NUMBER_OF_SUPPORTED_CONVERTER_TYPES]={
56ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    NULL, NULL,
57ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
58ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#if UCONFIG_NO_LEGACY_CONVERSION
59ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    NULL,
60ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#else
61ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    &_MBCSData,
62ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#endif
63ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
64ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    &_Latin1Data,
65ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    &_UTF8Data, &_UTF16BEData, &_UTF16LEData, &_UTF32BEData, &_UTF32LEData,
66ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    NULL,
67ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
68ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#if UCONFIG_NO_LEGACY_CONVERSION
69ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    NULL,
70ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    NULL, NULL, NULL, NULL, NULL, NULL,
71ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    NULL, NULL, NULL, NULL, NULL, NULL,
72ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    NULL,
73ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#else
74ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    &_ISO2022Data,
75ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    &_LMBCSData1,&_LMBCSData2, &_LMBCSData3, &_LMBCSData4, &_LMBCSData5, &_LMBCSData6,
76ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    &_LMBCSData8,&_LMBCSData11,&_LMBCSData16,&_LMBCSData17,&_LMBCSData18,&_LMBCSData19,
77ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    &_HZData,
78ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#endif
79ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
80ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    &_SCSUData,
81ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
82ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#if UCONFIG_NO_LEGACY_CONVERSION
83ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    NULL,
84ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#else
85ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    &_ISCIIData,
86ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#endif
87ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
88ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    &_ASCIIData,
89ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    &_UTF7Data, &_Bocu1Data, &_UTF16Data, &_UTF32Data, &_CESU8Data, &_IMAPData
90ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru};
91ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
92ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/* Please keep this in binary sorted order for getAlgorithmicTypeFromName.
93ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru   Also the name should be in lower case and all spaces, dashes and underscores
94ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru   removed
95ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*/
96ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic struct {
97ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  const char *name;
98ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  const UConverterType type;
99ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} const cnvNameType[] = {
100ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  { "bocu1", UCNV_BOCU1 },
101ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  { "cesu8", UCNV_CESU8 },
102ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#if !UCONFIG_NO_LEGACY_CONVERSION
103ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  { "hz",UCNV_HZ },
104ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#endif
105ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  { "imapmailboxname", UCNV_IMAP_MAILBOX },
106ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#if !UCONFIG_NO_LEGACY_CONVERSION
107ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  { "iscii", UCNV_ISCII },
108ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  { "iso2022", UCNV_ISO_2022 },
109ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#endif
110ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  { "iso88591", UCNV_LATIN_1 },
111ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#if !UCONFIG_NO_LEGACY_CONVERSION
112ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  { "lmbcs1", UCNV_LMBCS_1 },
113ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  { "lmbcs11",UCNV_LMBCS_11 },
114ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  { "lmbcs16",UCNV_LMBCS_16 },
115ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  { "lmbcs17",UCNV_LMBCS_17 },
116ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  { "lmbcs18",UCNV_LMBCS_18 },
117ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  { "lmbcs19",UCNV_LMBCS_19 },
118ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  { "lmbcs2", UCNV_LMBCS_2 },
119ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  { "lmbcs3", UCNV_LMBCS_3 },
120ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  { "lmbcs4", UCNV_LMBCS_4 },
121ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  { "lmbcs5", UCNV_LMBCS_5 },
122ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  { "lmbcs6", UCNV_LMBCS_6 },
123ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  { "lmbcs8", UCNV_LMBCS_8 },
124ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#endif
125ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  { "scsu", UCNV_SCSU },
126ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  { "usascii", UCNV_US_ASCII },
127ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  { "utf16", UCNV_UTF16 },
128ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  { "utf16be", UCNV_UTF16_BigEndian },
129ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  { "utf16le", UCNV_UTF16_LittleEndian },
130ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#if U_IS_BIG_ENDIAN
131ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  { "utf16oppositeendian", UCNV_UTF16_LittleEndian },
132ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  { "utf16platformendian", UCNV_UTF16_BigEndian },
133ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#else
134ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  { "utf16oppositeendian", UCNV_UTF16_BigEndian},
135ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  { "utf16platformendian", UCNV_UTF16_LittleEndian },
136ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#endif
137ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  { "utf32", UCNV_UTF32 },
138ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  { "utf32be", UCNV_UTF32_BigEndian },
139ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  { "utf32le", UCNV_UTF32_LittleEndian },
140ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#if U_IS_BIG_ENDIAN
141ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  { "utf32oppositeendian", UCNV_UTF32_LittleEndian },
142ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  { "utf32platformendian", UCNV_UTF32_BigEndian },
143ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#else
144ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  { "utf32oppositeendian", UCNV_UTF32_BigEndian },
145ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  { "utf32platformendian", UCNV_UTF32_LittleEndian },
146ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#endif
147ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  { "utf7", UCNV_UTF7 },
148ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  { "utf8", UCNV_UTF8 }
149ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru};
150ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
151ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
152ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/*initializes some global variables */
153ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic UHashtable *SHARED_DATA_HASHTABLE = NULL;
154ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic UMTX        cnvCacheMutex = NULL;  /* Mutex for synchronizing cnv cache access. */
155ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                                          /*  Note:  the global mutex is used for      */
156ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                                          /*         reference count updates.          */
157ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
158ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic const char **gAvailableConverters = NULL;
159ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic uint16_t gAvailableConverterCount = 0;
160ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
16185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho#if !U_CHARSET_IS_UTF8
16285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
163ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/* This contains the resolved converter name. So no further alias lookup is needed again. */
164ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic char gDefaultConverterNameBuffer[UCNV_MAX_CONVERTER_NAME_LENGTH + 1]; /* +1 for NULL */
165ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic const char *gDefaultConverterName = NULL;
166ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
167ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/*
168ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruIf the default converter is an algorithmic converter, this is the cached value.
169ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruWe don't cache a full UConverter and clone it because ucnv_clone doesn't have
170ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruless overhead than an algorithmic open. We don't cache non-algorithmic converters
171ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querubecause ucnv_flushCache must be able to unload the default converter and its table.
172ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*/
173ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic const UConverterSharedData *gDefaultAlgorithmicSharedData = NULL;
174ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
175ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/* Does gDefaultConverterName have a converter option and require extra parsing? */
176ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic UBool gDefaultConverterContainsOption;
177ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
17885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho#endif  /* !U_CHARSET_IS_UTF8 */
179ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
180ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic const char DATA_TYPE[] = "cnv";
181ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
18285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Hostatic void
18385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Houcnv_flushAvailableConverterCache() {
18485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    if (gAvailableConverters) {
18585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        umtx_lock(&cnvCacheMutex);
18685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        gAvailableConverterCount = 0;
18785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        uprv_free((char **)gAvailableConverters);
18885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        gAvailableConverters = NULL;
18985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        umtx_unlock(&cnvCacheMutex);
19085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    }
19185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho}
19285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
193ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/* ucnv_cleanup - delete all storage held by the converter cache, except any  */
194ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/*                in use by open converters.                                  */
195ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/*                Not thread safe.                                            */
196ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/*                Not supported API.                                          */
197ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic UBool U_CALLCONV ucnv_cleanup(void) {
198ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    ucnv_flushCache();
199ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (SHARED_DATA_HASHTABLE != NULL && uhash_count(SHARED_DATA_HASHTABLE) == 0) {
200ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        uhash_close(SHARED_DATA_HASHTABLE);
201ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        SHARED_DATA_HASHTABLE = NULL;
202ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
203ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
20485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    /* Isn't called from flushCache because other threads may have preexisting references to the table. */
20585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    ucnv_flushAvailableConverterCache();
206ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
20785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho#if !U_CHARSET_IS_UTF8
208ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    gDefaultConverterName = NULL;
209ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    gDefaultConverterNameBuffer[0] = 0;
210ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    gDefaultConverterContainsOption = FALSE;
211ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    gDefaultAlgorithmicSharedData = NULL;
21285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho#endif
213ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
214ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    umtx_destroy(&cnvCacheMutex);    /* Don't worry about destroying the mutex even  */
215ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                                     /*  if the hash table still exists.  The mutex  */
216ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                                     /*  will lazily re-init  itself if needed.      */
217ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return (SHARED_DATA_HASHTABLE == NULL);
218ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
219ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
220ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic UBool U_CALLCONV
221ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruisCnvAcceptable(void *context,
22285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                const char *type, const char *name,
22385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                const UDataInfo *pInfo) {
224ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return (UBool)(
225ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        pInfo->size>=20 &&
226ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        pInfo->isBigEndian==U_IS_BIG_ENDIAN &&
227ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        pInfo->charsetFamily==U_CHARSET_FAMILY &&
228ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        pInfo->sizeofUChar==U_SIZEOF_UCHAR &&
229ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        pInfo->dataFormat[0]==0x63 &&   /* dataFormat="cnvt" */
230ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        pInfo->dataFormat[1]==0x6e &&
231ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        pInfo->dataFormat[2]==0x76 &&
232ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        pInfo->dataFormat[3]==0x74 &&
233ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        pInfo->formatVersion[0]==6);  /* Everything will be version 6 */
234ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
235ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
236ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/**
237ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Un flatten shared data from a UDATA..
238ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */
239ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic UConverterSharedData*
240ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruucnv_data_unFlattenClone(UConverterLoadArgs *pArgs, UDataMemory *pData, UErrorCode *status)
241ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
242ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* UDataInfo info; -- necessary only if some converters have different formatVersion */
243ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    const uint8_t *raw = (const uint8_t *)udata_getMemory(pData);
244ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    const UConverterStaticData *source = (const UConverterStaticData *) raw;
245ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UConverterSharedData *data;
246ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UConverterType type = (UConverterType)source->conversionType;
247ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
248ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(U_FAILURE(*status))
249ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return NULL;
250ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
251ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if( (uint16_t)type >= UCNV_NUMBER_OF_SUPPORTED_CONVERTER_TYPES ||
252ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        converterData[type] == NULL ||
253ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        converterData[type]->referenceCounter != 1 ||
254ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        source->structSize != sizeof(UConverterStaticData))
255ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    {
256ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        *status = U_INVALID_TABLE_FORMAT;
257ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return NULL;
258ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
259ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
260ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    data = (UConverterSharedData *)uprv_malloc(sizeof(UConverterSharedData));
261ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(data == NULL) {
262ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        *status = U_MEMORY_ALLOCATION_ERROR;
263ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return NULL;
264ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
265ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
266ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* copy initial values from the static structure for this type */
267ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    uprv_memcpy(data, converterData[type], sizeof(UConverterSharedData));
268ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
269ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#if 0 /* made UConverterMBCSTable part of UConverterSharedData -- markus 20031107 */
270ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /*
271ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     * It would be much more efficient if the table were a direct member, not a pointer.
272ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     * However, that would add to the size of all UConverterSharedData objects
273ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     * even if they do not use this table (especially algorithmic ones).
274ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     * If this changes, then the static templates from converterData[type]
275ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     * need more entries.
276ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     *
277ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     * In principle, it would be cleaner if the load() function below
278ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     * allocated the table.
279ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     */
280ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    data->table = (UConverterTable *)uprv_malloc(sizeof(UConverterTable));
281ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(data->table == NULL) {
282ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        uprv_free(data);
283ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        *status = U_MEMORY_ALLOCATION_ERROR;
284ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return NULL;
285ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
286ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    uprv_memset(data->table, 0, sizeof(UConverterTable));
287ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#endif
288ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
289ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    data->staticData = source;
290ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
291ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    data->sharedDataCached = FALSE;
292ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
293ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* fill in fields from the loaded data */
294ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    data->dataMemory = (void*)pData; /* for future use */
295ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
296ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(data->impl->load != NULL) {
297ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        data->impl->load(data, pArgs, raw + source->structSize, status);
298ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if(U_FAILURE(*status)) {
299ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            uprv_free(data->table);
300ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            uprv_free(data);
301ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            return NULL;
302ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
303ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
304ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return data;
305ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
306ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
307ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/*Takes an alias name gets an actual converter file name
308ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *goes to disk and opens it.
309ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *allocates the memory and returns a new UConverter object
310ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */
311ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic UConverterSharedData *createConverterFromFile(UConverterLoadArgs *pArgs, UErrorCode * err)
312ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
313ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UDataMemory *data;
314ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UConverterSharedData *sharedData;
315ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
316ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UTRACE_ENTRY_OC(UTRACE_UCNV_LOAD);
317ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
318ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (U_FAILURE (*err)) {
319ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        UTRACE_EXIT_STATUS(*err);
320ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return NULL;
321ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
322ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
323ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UTRACE_DATA2(UTRACE_OPEN_CLOSE, "load converter %s from package %s", pArgs->name, pArgs->pkg);
324ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
325ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    data = udata_openChoice(pArgs->pkg, DATA_TYPE, pArgs->name, isCnvAcceptable, NULL, err);
326ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(U_FAILURE(*err))
327ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    {
328ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        UTRACE_EXIT_STATUS(*err);
329ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return NULL;
330ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
331ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
332ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    sharedData = ucnv_data_unFlattenClone(pArgs, data, err);
333ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(U_FAILURE(*err))
334ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    {
335ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        udata_close(data);
336ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        UTRACE_EXIT_STATUS(*err);
337ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return NULL;
338ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
339ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
340ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /*
341ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     * TODO Store pkg in a field in the shared data so that delta-only converters
342ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     * can load base converters from the same package.
343ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     * If the pkg name is longer than the field, then either do not load the converter
344ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     * in the first place, or just set the pkg field to "".
345ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     */
346ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
347ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UTRACE_EXIT_PTR_STATUS(sharedData, *err);
348ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return sharedData;
349ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
350ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
351ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/*returns a converter type from a string
352ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */
353ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic const UConverterSharedData *
354ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QuerugetAlgorithmicTypeFromName(const char *realName)
355ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
356ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    uint32_t mid, start, limit;
357ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    uint32_t lastMid;
358ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int result;
359ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    char strippedName[UCNV_MAX_CONVERTER_NAME_LENGTH];
360ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
361ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* Lower case and remove ignoreable characters. */
362ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    ucnv_io_stripForCompare(strippedName, realName);
363ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
364ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* do a binary search for the alias */
365ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    start = 0;
366ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    limit = sizeof(cnvNameType)/sizeof(cnvNameType[0]);
367ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    mid = limit;
368ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    lastMid = UINT32_MAX;
369ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
370ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    for (;;) {
371ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        mid = (uint32_t)((start + limit) / 2);
372ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (lastMid == mid) {   /* Have we moved? */
373ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            break;  /* We haven't moved, and it wasn't found. */
374ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
375ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        lastMid = mid;
376ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        result = uprv_strcmp(strippedName, cnvNameType[mid].name);
377ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
378ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (result < 0) {
379ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            limit = mid;
380ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        } else if (result > 0) {
381ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            start = mid;
382ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        } else {
383ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            return converterData[cnvNameType[mid].type];
384ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
385ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
386ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
387ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return NULL;
388ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
389ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
390ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/*
391ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru* Based on the number of known converters, this determines how many times larger
392ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru* the shared data hash table should be. When on small platforms, or just a couple
393ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru* of converters are used, this number should be 2. When memory is plentiful, or
394ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru* when ucnv_countAvailable is ever used with a lot of available converters,
395ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru* this should be 4.
396ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru* Larger numbers reduce the number of hash collisions, but use more memory.
397ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*/
398ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define UCNV_CACHE_LOAD_FACTOR 2
399ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
400ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/* Puts the shared data in the static hashtable SHARED_DATA_HASHTABLE */
401ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/*   Will always be called with the cnvCacheMutex alrady being held   */
402ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/*     by the calling function.                                       */
403ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/* Stores the shared data in the SHARED_DATA_HASHTABLE
404ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @param data The shared data
405ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */
406ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic void
407ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruucnv_shareConverterData(UConverterSharedData * data)
408ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
409ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UErrorCode err = U_ZERO_ERROR;
410ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /*Lazy evaluates the Hashtable itself */
411ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /*void *sanity = NULL;*/
412ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
413ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (SHARED_DATA_HASHTABLE == NULL)
414ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    {
415ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        SHARED_DATA_HASHTABLE = uhash_openSize(uhash_hashChars, uhash_compareChars, NULL,
416ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                            ucnv_io_countKnownConverters(&err)*UCNV_CACHE_LOAD_FACTOR,
417ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                            &err);
418ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        ucln_common_registerCleanup(UCLN_COMMON_UCNV, ucnv_cleanup);
419ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
420ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (U_FAILURE(err))
421ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            return;
422ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
423ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
424ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* ### check to see if the element is not already there! */
425ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
426ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /*
427ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    sanity =   ucnv_getSharedConverterData (data->staticData->name);
428ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(sanity != NULL)
429ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    {
430ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UCNV_DEBUG_LOG("put:overwrite!",data->staticData->name,sanity);
431ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
432ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UCNV_DEBUG_LOG("put:chk",data->staticData->name,sanity);
433ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    */
434ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
435ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* Mark it shared */
436ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    data->sharedDataCached = TRUE;
437ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
438ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    uhash_put(SHARED_DATA_HASHTABLE,
439ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            (void*) data->staticData->name, /* Okay to cast away const as long as
440ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            keyDeleter == NULL */
441ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            data,
442ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            &err);
443ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UCNV_DEBUG_LOG("put", data->staticData->name,data);
444ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
445ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
446ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
447ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/*  Look up a converter name in the shared data cache.                    */
448ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/*    cnvCacheMutex must be held by the caller to protect the hash table. */
449ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/* gets the shared data from the SHARED_DATA_HASHTABLE (might return NULL if it isn't there)
450ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @param name The name of the shared data
451ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @return the shared data from the SHARED_DATA_HASHTABLE
452ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */
453ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic UConverterSharedData *
454ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruucnv_getSharedConverterData(const char *name)
455ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
456ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /*special case when no Table has yet been created we return NULL */
457ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (SHARED_DATA_HASHTABLE == NULL)
458ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    {
459ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return NULL;
460ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
461ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    else
462ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    {
463ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        UConverterSharedData *rc;
464ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
465ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        rc = (UConverterSharedData*)uhash_get(SHARED_DATA_HASHTABLE, name);
466ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        UCNV_DEBUG_LOG("get",name,rc);
467ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return rc;
468ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
469ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
470ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
471ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/*frees the string of memory blocks associates with a sharedConverter
472ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *if and only if the referenceCounter == 0
473ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */
474ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/* Deletes (frees) the Shared data it's passed. first it checks the referenceCounter to
475ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * see if anyone is using it, if not it frees all the memory stemming from sharedConverterData and
476ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * returns TRUE,
477ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * otherwise returns FALSE
478ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @param sharedConverterData The shared data
479ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @return if not it frees all the memory stemming from sharedConverterData and
480ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * returns TRUE, otherwise returns FALSE
481ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */
482ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic UBool
483ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruucnv_deleteSharedConverterData(UConverterSharedData * deadSharedData)
484ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
485ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UTRACE_ENTRY_OC(UTRACE_UCNV_UNLOAD);
486ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UTRACE_DATA2(UTRACE_OPEN_CLOSE, "unload converter %s shared data %p", deadSharedData->staticData->name, deadSharedData);
487ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
488ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (deadSharedData->referenceCounter > 0) {
489ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        UTRACE_EXIT_VALUE((int32_t)FALSE);
490ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return FALSE;
491ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
492ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
493ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (deadSharedData->impl->unload != NULL) {
494ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        deadSharedData->impl->unload(deadSharedData);
495ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
496ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
497ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(deadSharedData->dataMemory != NULL)
498ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    {
499ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        UDataMemory *data = (UDataMemory*)deadSharedData->dataMemory;
500ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        udata_close(data);
501ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
502ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
503ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(deadSharedData->table != NULL)
504ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    {
505ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        uprv_free(deadSharedData->table);
506ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
507ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
508ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#if 0
509ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* if the static data is actually owned by the shared data */
510ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* enable if we ever have this situation. */
511ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(deadSharedData->staticDataOwned == TRUE) /* see ucnv_bld.h */
512ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    {
513ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        uprv_free((void*)deadSharedData->staticData);
514ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
515ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#endif
516ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
517ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#if 0
518ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* Zap it ! */
519ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    uprv_memset(deadSharedData->0, sizeof(*deadSharedData));
520ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#endif
521ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
522ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    uprv_free(deadSharedData);
523ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
524ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UTRACE_EXIT_VALUE((int32_t)TRUE);
525ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return TRUE;
526ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
527ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
528ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/**
529ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Load a non-algorithmic converter.
530ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * If pkg==NULL, then this function must be called inside umtx_lock(&cnvCacheMutex).
531ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */
532ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUConverterSharedData *
533ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruucnv_load(UConverterLoadArgs *pArgs, UErrorCode *err) {
534ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UConverterSharedData *mySharedConverterData;
535ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
536ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(err == NULL || U_FAILURE(*err)) {
537ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return NULL;
538ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
539ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
540ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(pArgs->pkg != NULL && *pArgs->pkg != 0) {
541ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* application-provided converters are not currently cached */
542ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return createConverterFromFile(pArgs, err);
543ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
544ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
545ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    mySharedConverterData = ucnv_getSharedConverterData(pArgs->name);
546ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (mySharedConverterData == NULL)
547ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    {
548ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /*Not cached, we need to stream it in from file */
549ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        mySharedConverterData = createConverterFromFile(pArgs, err);
550ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (U_FAILURE (*err) || (mySharedConverterData == NULL))
551ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        {
552ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            return NULL;
553ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
55485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        else if (!pArgs->onlyTestIsLoadable)
555ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        {
556ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            /* share it with other library clients */
557ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            ucnv_shareConverterData(mySharedConverterData);
558ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
559ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
560ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    else
561ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    {
562ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* The data for this converter was already in the cache.            */
563ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* Update the reference counter on the shared data: one more client */
564ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        mySharedConverterData->referenceCounter++;
565ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
566ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
567ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return mySharedConverterData;
568ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
569ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
570ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/**
571ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Unload a non-algorithmic converter.
572ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * It must be sharedData->referenceCounter != ~0
573ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * and this function must be called inside umtx_lock(&cnvCacheMutex).
574ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */
575ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid
576ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruucnv_unload(UConverterSharedData *sharedData) {
577ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(sharedData != NULL) {
578ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (sharedData->referenceCounter > 0) {
579ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            sharedData->referenceCounter--;
580ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
581ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
582ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if((sharedData->referenceCounter <= 0)&&(sharedData->sharedDataCached == FALSE)) {
583ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            ucnv_deleteSharedConverterData(sharedData);
584ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
585ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
586ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
587ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
588ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid
589ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruucnv_unloadSharedDataIfReady(UConverterSharedData *sharedData)
590ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
591ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /*
592ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    Checking whether it's an algorithic converter is okay
593ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    in multithreaded applications because the value never changes.
594ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    Don't check referenceCounter for any other value.
595ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    */
596ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(sharedData != NULL && sharedData->referenceCounter != ~0) {
597ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        umtx_lock(&cnvCacheMutex);
598ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        ucnv_unload(sharedData);
599ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        umtx_unlock(&cnvCacheMutex);
600ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
601ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
602ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
603ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid
604ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruucnv_incrementRefCount(UConverterSharedData *sharedData)
605ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
60685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    /*
60785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    Checking whether it's an algorithic converter is okay
60885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    in multithreaded applications because the value never changes.
60985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    Don't check referenceCounter for any other value.
61085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    */
611ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(sharedData != NULL && sharedData->referenceCounter != ~0) {
612ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        umtx_lock(&cnvCacheMutex);
613ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        sharedData->referenceCounter++;
614ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        umtx_unlock(&cnvCacheMutex);
615ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
616ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
617ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
61885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho/*
61985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho * *pPieces must be initialized.
62085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho * The name without options will be copied to pPieces->cnvName.
62185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho * The locale and options will be copied to pPieces only if present in inName,
62285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho * otherwise the existing values in pPieces remain.
62385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho * *pArgs will be set to the pPieces values.
62485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho */
625ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic void
626ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruparseConverterOptions(const char *inName,
62785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                      UConverterNamePieces *pPieces,
62885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                      UConverterLoadArgs *pArgs,
629ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                      UErrorCode *err)
630ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
63185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    char *cnvName = pPieces->cnvName;
632ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    char c;
633ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t len = 0;
634ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
63585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    pArgs->name=inName;
63685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    pArgs->locale=pPieces->locale;
63785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    pArgs->options=pPieces->options;
63885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
639ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* copy the converter name itself to cnvName */
640ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    while((c=*inName)!=0 && c!=UCNV_OPTION_SEP_CHAR) {
641ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (++len>=UCNV_MAX_CONVERTER_NAME_LENGTH) {
642ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            *err = U_ILLEGAL_ARGUMENT_ERROR;    /* bad name */
64385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            pPieces->cnvName[0]=0;
644ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            return;
645ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
646ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        *cnvName++=c;
647ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        inName++;
648ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
649ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    *cnvName=0;
65085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    pArgs->name=pPieces->cnvName;
651ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
652ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* parse options. No more name copying should occur. */
653ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    while((c=*inName)!=0) {
654ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if(c==UCNV_OPTION_SEP_CHAR) {
655ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            ++inName;
656ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
657ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
658ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* inName is behind an option separator */
659ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if(uprv_strncmp(inName, "locale=", 7)==0) {
660ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            /* do not modify locale itself in case we have multiple locale options */
66185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            char *dest=pPieces->locale;
662ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
663ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            /* copy the locale option value */
664ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            inName+=7;
665ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            len=0;
666ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            while((c=*inName)!=0 && c!=UCNV_OPTION_SEP_CHAR) {
667ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                ++inName;
668ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
669ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                if(++len>=ULOC_FULLNAME_CAPACITY) {
670ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    *err=U_ILLEGAL_ARGUMENT_ERROR;    /* bad name */
67185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                    pPieces->locale[0]=0;
672ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    return;
673ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                }
674ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
675ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                *dest++=c;
676ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
677ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            *dest=0;
678ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        } else if(uprv_strncmp(inName, "version=", 8)==0) {
67985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            /* copy the version option value into bits 3..0 of pPieces->options */
680ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            inName+=8;
681ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            c=*inName;
682ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if(c==0) {
68385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                pArgs->options=(pPieces->options&=~UCNV_OPTION_VERSION);
684ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                return;
685ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            } else if((uint8_t)(c-'0')<10) {
68685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                pArgs->options=pPieces->options=(pPieces->options&~UCNV_OPTION_VERSION)|(uint32_t)(c-'0');
687ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                ++inName;
688ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
689ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        } else if(uprv_strncmp(inName, "swaplfnl", 8)==0) {
690ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            inName+=8;
69185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            pArgs->options=(pPieces->options|=UCNV_OPTION_SWAP_LFNL);
692ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* add processing for new options here with another } else if(uprv_strncmp(inName, "option-name=", XX)==0) { */
693ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        } else {
694ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            /* ignore any other options until we define some */
695ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            while(((c = *inName++) != 0) && (c != UCNV_OPTION_SEP_CHAR)) {
696ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
697ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if(c==0) {
698ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                return;
699ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
700ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
701ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
702ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
703ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
704ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/*Logic determines if the converter is Algorithmic AND/OR cached
705ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *depending on that:
706ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * -we either go to get data from disk and cache it (Data=TRUE, Cached=False)
707ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * -Get it from a Hashtable (Data=X, Cached=TRUE)
708ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * -Call dataConverter initializer (Data=TRUE, Cached=TRUE)
709ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * -Call AlgorithmicConverter initializer (Data=FALSE, Cached=TRUE)
710ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */
711ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUConverterSharedData *
71285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Houcnv_loadSharedData(const char *converterName,
71385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                    UConverterNamePieces *pPieces,
71485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                    UConverterLoadArgs *pArgs,
71585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                    UErrorCode * err) {
71685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    UConverterNamePieces stackPieces;
71785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    UConverterLoadArgs stackArgs;
718ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UConverterSharedData *mySharedConverterData = NULL;
719ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UErrorCode internalErrorCode = U_ZERO_ERROR;
720ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UBool mayContainOption = TRUE;
721ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UBool checkForAlgorithmic = TRUE;
722ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
723ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (U_FAILURE (*err)) {
724ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return NULL;
725ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
726ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
72785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    if(pPieces == NULL) {
72885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        if(pArgs != NULL) {
72985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            /*
73085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho             * Bad: We may set pArgs pointers to stackPieces fields
73185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho             * which will be invalid after this function returns.
73285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho             */
73385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            *err = U_INTERNAL_PROGRAM_ERROR;
73485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            return NULL;
73585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
73685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        pPieces = &stackPieces;
737ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
73885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    if(pArgs == NULL) {
73985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        uprv_memset(&stackArgs, 0, sizeof(stackArgs));
74085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        stackArgs.size = (int32_t)sizeof(stackArgs);
74185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        pArgs = &stackArgs;
74285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    }
74385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
74485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    pPieces->cnvName[0] = 0;
74585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    pPieces->locale[0] = 0;
74685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    pPieces->options = 0;
747ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
74885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    pArgs->name = converterName;
74985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    pArgs->locale = pPieces->locale;
75085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    pArgs->options = pPieces->options;
751ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
752ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* In case "name" is NULL we want to open the default converter. */
753ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (converterName == NULL) {
75485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho#if U_CHARSET_IS_UTF8
75585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        pArgs->name = "UTF-8";
75685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        return (UConverterSharedData *)converterData[UCNV_UTF8];
75785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho#else
758ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* Call ucnv_getDefaultName first to query the name from the OS. */
75985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        pArgs->name = ucnv_getDefaultName();
76085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        if (pArgs->name == NULL) {
761ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            *err = U_MISSING_RESOURCE_ERROR;
762ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            return NULL;
763ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
764ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        mySharedConverterData = (UConverterSharedData *)gDefaultAlgorithmicSharedData;
765ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        checkForAlgorithmic = FALSE;
766ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        mayContainOption = gDefaultConverterContainsOption;
767ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* the default converter name is already canonical */
76885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho#endif
769ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
77085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    else if(UCNV_FAST_IS_UTF8(converterName)) {
771ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* fastpath for UTF-8 */
77285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        pArgs->name = "UTF-8";
773ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return (UConverterSharedData *)converterData[UCNV_UTF8];
774ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
775ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    else {
776ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* separate the converter name from the options */
77785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        parseConverterOptions(converterName, pPieces, pArgs, err);
778ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (U_FAILURE(*err)) {
779ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            /* Very bad name used. */
780ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            return NULL;
781ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
782ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
783ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* get the canonical converter name */
78485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        pArgs->name = ucnv_io_getConverterName(pArgs->name, &mayContainOption, &internalErrorCode);
78585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        if (U_FAILURE(internalErrorCode) || pArgs->name == NULL) {
786ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            /*
787ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            * set the input name in case the converter was added
788ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            * without updating the alias table, or when there is no alias table
789ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            */
79085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            pArgs->name = pPieces->cnvName;
791ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
792ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
793ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
794ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* separate the converter name from the options */
79585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    if(mayContainOption && pArgs->name != pPieces->cnvName) {
79685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        parseConverterOptions(pArgs->name, pPieces, pArgs, err);
797ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
798ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
799ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* get the shared data for an algorithmic converter, if it is one */
800ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (checkForAlgorithmic) {
80185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        mySharedConverterData = (UConverterSharedData *)getAlgorithmicTypeFromName(pArgs->name);
802ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
803ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (mySharedConverterData == NULL)
804ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    {
805ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* it is a data-based converter, get its shared data.               */
806ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* Hold the cnvCacheMutex through the whole process of checking the */
807ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /*   converter data cache, and adding new entries to the cache      */
808ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /*   to prevent other threads from modifying the cache during the   */
809ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /*   process.                                                       */
81085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        pArgs->nestedLoads=1;
81185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        pArgs->pkg=NULL;
812ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
813ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        umtx_lock(&cnvCacheMutex);
81485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        mySharedConverterData = ucnv_load(pArgs, err);
815ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        umtx_unlock(&cnvCacheMutex);
816ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (U_FAILURE (*err) || (mySharedConverterData == NULL))
817ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        {
818ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            return NULL;
819ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
820ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
821ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
822ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return mySharedConverterData;
823ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
824ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
825ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUConverter *
826ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruucnv_createConverter(UConverter *myUConverter, const char *converterName, UErrorCode * err)
827ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
82885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    UConverterNamePieces stackPieces;
82985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    UConverterLoadArgs stackArgs={ (int32_t)sizeof(UConverterLoadArgs) };
830ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UConverterSharedData *mySharedConverterData;
831ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
832ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UTRACE_ENTRY_OC(UTRACE_UCNV_OPEN);
833ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
834ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(U_SUCCESS(*err)) {
835ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        UTRACE_DATA1(UTRACE_OPEN_CLOSE, "open converter %s", converterName);
836ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
83785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        mySharedConverterData = ucnv_loadSharedData(converterName, &stackPieces, &stackArgs, err);
83885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
83985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        myUConverter = ucnv_createConverterFromSharedData(
84085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            myUConverter, mySharedConverterData,
84185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            &stackArgs,
84285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            err);
843ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
844ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if(U_SUCCESS(*err)) {
84585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            UTRACE_EXIT_PTR_STATUS(myUConverter, *err);
84685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            return myUConverter;
847ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
848ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
849ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
850ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* exit with error */
851ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UTRACE_EXIT_STATUS(*err);
852ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return NULL;
853ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
854ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
85585bf2e2fbc60a9f938064abc8127d61da7d19882Claire HoU_CFUNC UBool
85685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Houcnv_canCreateConverter(const char *converterName, UErrorCode *err) {
85785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    UConverter myUConverter;
85885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    UConverterNamePieces stackPieces;
85985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    UConverterLoadArgs stackArgs={ (int32_t)sizeof(UConverterLoadArgs) };
86085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    UConverterSharedData *mySharedConverterData;
86185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
86285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    UTRACE_ENTRY_OC(UTRACE_UCNV_OPEN);
86385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
86485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    if(U_SUCCESS(*err)) {
86585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        UTRACE_DATA1(UTRACE_OPEN_CLOSE, "test if can open converter %s", converterName);
86685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
86785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        stackArgs.onlyTestIsLoadable=TRUE;
86885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        mySharedConverterData = ucnv_loadSharedData(converterName, &stackPieces, &stackArgs, err);
86985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        ucnv_createConverterFromSharedData(
87085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            &myUConverter, mySharedConverterData,
87185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            &stackArgs,
87285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            err);
87385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        ucnv_unloadSharedDataIfReady(mySharedConverterData);
87485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    }
87585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
87685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    UTRACE_EXIT_STATUS(*err);
87785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    return U_SUCCESS(*err);
87885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho}
87985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
880ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUConverter *
881ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruucnv_createAlgorithmicConverter(UConverter *myUConverter,
882ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                                UConverterType type,
883ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                                const char *locale, uint32_t options,
884ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                                UErrorCode *err) {
885ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UConverter *cnv;
886ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    const UConverterSharedData *sharedData;
88785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    UConverterLoadArgs stackArgs={ (int32_t)sizeof(UConverterLoadArgs) };
888ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
889ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UTRACE_ENTRY_OC(UTRACE_UCNV_OPEN_ALGORITHMIC);
890ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UTRACE_DATA1(UTRACE_OPEN_CLOSE, "open algorithmic converter type %d", (int32_t)type);
891ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
892ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(type<0 || UCNV_NUMBER_OF_SUPPORTED_CONVERTER_TYPES<=type) {
893ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        *err = U_ILLEGAL_ARGUMENT_ERROR;
894ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        UTRACE_EXIT_STATUS(U_ILLEGAL_ARGUMENT_ERROR);
895ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return NULL;
896ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
897ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
898ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    sharedData = converterData[type];
89985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    /*
90085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    Checking whether it's an algorithic converter is okay
90185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    in multithreaded applications because the value never changes.
90285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    Don't check referenceCounter for any other value.
90385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    */
90485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    if(sharedData == NULL || sharedData->referenceCounter != ~0) {
905ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* not a valid type, or not an algorithmic converter */
906ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        *err = U_ILLEGAL_ARGUMENT_ERROR;
907ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        UTRACE_EXIT_STATUS(U_ILLEGAL_ARGUMENT_ERROR);
908ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return NULL;
909ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
910ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
91185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    stackArgs.name = "";
91285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    stackArgs.options = options;
91385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    stackArgs.locale=locale;
91485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    cnv = ucnv_createConverterFromSharedData(
91585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            myUConverter, (UConverterSharedData *)sharedData,
91685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            &stackArgs, err);
917ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
918ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UTRACE_EXIT_PTR_STATUS(cnv, *err);
919ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return cnv;
920ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
921ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
922ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUConverter*
923ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruucnv_createConverterFromPackage(const char *packageName, const char *converterName, UErrorCode * err)
924ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
925ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UConverter *myUConverter;
926ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UConverterSharedData *mySharedConverterData;
92785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    UConverterNamePieces stackPieces;
92885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    UConverterLoadArgs stackArgs={ (int32_t)sizeof(UConverterLoadArgs) };
929ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
930ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UTRACE_ENTRY_OC(UTRACE_UCNV_OPEN_PACKAGE);
931ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
932ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(U_FAILURE(*err)) {
933ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        UTRACE_EXIT_STATUS(*err);
934ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return NULL;
935ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
936ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
937ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UTRACE_DATA2(UTRACE_OPEN_CLOSE, "open converter %s from package %s", converterName, packageName);
938ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
939ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* first, get the options out of the converterName string */
94085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    stackPieces.cnvName[0] = 0;
94185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    stackPieces.locale[0] = 0;
94285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    stackPieces.options = 0;
94385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    parseConverterOptions(converterName, &stackPieces, &stackArgs, err);
944ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (U_FAILURE(*err)) {
945ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* Very bad name used. */
946ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        UTRACE_EXIT_STATUS(*err);
947ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return NULL;
948ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
94985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    stackArgs.nestedLoads=1;
95085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    stackArgs.pkg=packageName;
951ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
952ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* open the data, unflatten the shared structure */
95385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    mySharedConverterData = createConverterFromFile(&stackArgs, err);
954ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
955ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (U_FAILURE(*err)) {
956ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        UTRACE_EXIT_STATUS(*err);
957ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return NULL;
958ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
959ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
960ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* create the actual converter */
96185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    myUConverter = ucnv_createConverterFromSharedData(NULL, mySharedConverterData, &stackArgs, err);
962ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
963ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (U_FAILURE(*err)) {
964ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        ucnv_close(myUConverter);
965ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        UTRACE_EXIT_STATUS(*err);
966ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return NULL;
967ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
968ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
969ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UTRACE_EXIT_PTR_STATUS(myUConverter, *err);
970ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return myUConverter;
971ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
972ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
973ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
974ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUConverter*
975ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruucnv_createConverterFromSharedData(UConverter *myUConverter,
976ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                                   UConverterSharedData *mySharedConverterData,
97785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                                   UConverterLoadArgs *pArgs,
978ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                                   UErrorCode *err)
979ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
980ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UBool isCopyLocal;
981ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
98285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    if(U_FAILURE(*err)) {
98385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        ucnv_unloadSharedDataIfReady(mySharedConverterData);
98485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        return myUConverter;
98585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    }
986ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(myUConverter == NULL)
987ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    {
988ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        myUConverter = (UConverter *) uprv_malloc (sizeof (UConverter));
989ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if(myUConverter == NULL)
990ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        {
991ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            *err = U_MEMORY_ALLOCATION_ERROR;
99285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            ucnv_unloadSharedDataIfReady(mySharedConverterData);
993ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            return NULL;
994ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
995ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        isCopyLocal = FALSE;
996ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    } else {
997ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        isCopyLocal = TRUE;
998ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
999ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1000ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* initialize the converter */
1001ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    uprv_memset(myUConverter, 0, sizeof(UConverter));
1002ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    myUConverter->isCopyLocal = isCopyLocal;
1003ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /*myUConverter->isExtraLocal = FALSE;*/ /* Set by the memset call */
1004ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    myUConverter->sharedData = mySharedConverterData;
100585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    myUConverter->options = pArgs->options;
100685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    if(!pArgs->onlyTestIsLoadable) {
100785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        myUConverter->preFromUFirstCP = U_SENTINEL;
100885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        myUConverter->fromCharErrorBehaviour = UCNV_TO_U_DEFAULT_CALLBACK;
100985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        myUConverter->fromUCharErrorBehaviour = UCNV_FROM_U_DEFAULT_CALLBACK;
101085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        myUConverter->toUnicodeStatus = mySharedConverterData->toUnicodeStatus;
101185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        myUConverter->maxBytesPerUChar = mySharedConverterData->staticData->maxBytesPerChar;
101285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        myUConverter->subChar1 = mySharedConverterData->staticData->subChar1;
101385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        myUConverter->subCharLen = mySharedConverterData->staticData->subCharLen;
101485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        myUConverter->subChars = (uint8_t *)myUConverter->subUChars;
101585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        uprv_memcpy(myUConverter->subChars, mySharedConverterData->staticData->subChar, myUConverter->subCharLen);
101685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        myUConverter->toUCallbackReason = UCNV_ILLEGAL; /* default reason to invoke (*fromCharErrorBehaviour) */
101785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    }
1018ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1019ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(mySharedConverterData->impl->open != NULL) {
102085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        mySharedConverterData->impl->open(myUConverter, pArgs, err);
102185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        if(U_FAILURE(*err) && !pArgs->onlyTestIsLoadable) {
102285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            /* don't ucnv_close() if onlyTestIsLoadable because not fully initialized */
1023ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            ucnv_close(myUConverter);
1024ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            return NULL;
1025ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1026ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1027ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1028ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return myUConverter;
1029ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
1030ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1031ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/*Frees all shared immutable objects that aren't referred to (reference count = 0)
1032ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */
1033ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruU_CAPI int32_t U_EXPORT2
1034ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruucnv_flushCache ()
1035ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
1036ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UConverterSharedData *mySharedData = NULL;
1037ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t pos;
1038ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t tableDeletedNum = 0;
1039ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    const UHashElement *e;
104027f654740f2a26ad62a5c155af9199af9e69b889claireho    /*UErrorCode status = U_ILLEGAL_ARGUMENT_ERROR;*/
1041ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t i, remaining;
1042ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1043ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UTRACE_ENTRY_OC(UTRACE_UCNV_FLUSH_CACHE);
1044ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1045ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* Close the default converter without creating a new one so that everything will be flushed. */
104627f654740f2a26ad62a5c155af9199af9e69b889claireho    u_flushDefaultConverter();
1047ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1048ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /*if shared data hasn't even been lazy evaluated yet
1049ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    * return 0
1050ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    */
1051ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (SHARED_DATA_HASHTABLE == NULL) {
1052ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        UTRACE_EXIT_VALUE((int32_t)0);
1053ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return 0;
1054ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1055ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1056ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /*creates an enumeration to iterate through every element in the
1057ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    * table
1058ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    *
1059ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    * Synchronization:  holding cnvCacheMutex will prevent any other thread from
1060ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    *                   accessing or modifying the hash table during the iteration.
1061ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    *                   The reference count of an entry may be decremented by
1062ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    *                   ucnv_close while the iteration is in process, but this is
1063ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    *                   benign.  It can't be incremented (in ucnv_createConverter())
1064ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    *                   because the sequence of looking up in the cache + incrementing
1065ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    *                   is protected by cnvCacheMutex.
1066ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    */
1067ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    umtx_lock(&cnvCacheMutex);
1068ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /*
1069ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     * double loop: A delta/extension-only converter has a pointer to its base table's
1070ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     * shared data; the first iteration of the outer loop may see the delta converter
1071ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     * before the base converter, and unloading the delta converter may get the base
1072ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     * converter's reference counter down to 0.
1073ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     */
1074ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    i = 0;
1075ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    do {
1076ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        remaining = 0;
1077ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        pos = -1;
1078ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        while ((e = uhash_nextElement (SHARED_DATA_HASHTABLE, &pos)) != NULL)
1079ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        {
1080ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            mySharedData = (UConverterSharedData *) e->value.pointer;
1081ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            /*deletes only if reference counter == 0 */
1082ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if (mySharedData->referenceCounter == 0)
1083ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            {
1084ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                tableDeletedNum++;
1085ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1086ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                UCNV_DEBUG_LOG("del",mySharedData->staticData->name,mySharedData);
1087ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1088ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                uhash_removeElement(SHARED_DATA_HASHTABLE, e);
1089ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                mySharedData->sharedDataCached = FALSE;
1090ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                ucnv_deleteSharedConverterData (mySharedData);
1091ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            } else {
1092ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                ++remaining;
1093ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
1094ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1095ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    } while(++i == 1 && remaining > 0);
1096ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    umtx_unlock(&cnvCacheMutex);
1097ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1098ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UTRACE_DATA1(UTRACE_INFO, "ucnv_flushCache() exits with %d converters remaining", remaining);
1099ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1100ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UTRACE_EXIT_VALUE(tableDeletedNum);
1101ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return tableDeletedNum;
1102ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
1103ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1104ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/* available converters list --------------------------------------------------- */
1105ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1106ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic UBool haveAvailableConverterList(UErrorCode *pErrorCode) {
1107ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int needInit;
1108ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UMTX_CHECK(&cnvCacheMutex, (gAvailableConverters == NULL), needInit);
1109ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (needInit) {
1110ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        UConverter tempConverter;
1111ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        UEnumeration *allConvEnum = NULL;
1112ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        uint16_t idx;
1113ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        uint16_t localConverterCount;
1114ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        uint16_t allConverterCount;
1115ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        UErrorCode localStatus;
1116ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        const char *converterName;
1117ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        const char **localConverterList;
1118ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1119ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        allConvEnum = ucnv_openAllNames(pErrorCode);
1120ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        allConverterCount = uenum_count(allConvEnum, pErrorCode);
1121ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (U_FAILURE(*pErrorCode)) {
1122ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            return FALSE;
1123ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1124ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1125ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* We can't have more than "*converterTable" converters to open */
1126ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        localConverterList = (const char **) uprv_malloc(allConverterCount * sizeof(char*));
1127ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (!localConverterList) {
1128ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            *pErrorCode = U_MEMORY_ALLOCATION_ERROR;
1129ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            return FALSE;
1130ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1131ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1132ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* Open the default converter to make sure that it has first dibs in the hash table. */
1133ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        localStatus = U_ZERO_ERROR;
1134ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        ucnv_close(ucnv_createConverter(&tempConverter, NULL, &localStatus));
1135ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1136ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        localConverterCount = 0;
1137ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1138ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        for (idx = 0; idx < allConverterCount; idx++) {
1139ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            localStatus = U_ZERO_ERROR;
1140ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            converterName = uenum_next(allConvEnum, NULL, &localStatus);
114185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            if (ucnv_canCreateConverter(converterName, &localStatus)) {
1142ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                localConverterList[localConverterCount++] = converterName;
1143ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
1144ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1145ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        uenum_close(allConvEnum);
1146ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1147ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        umtx_lock(&cnvCacheMutex);
1148ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (gAvailableConverters == NULL) {
1149ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            gAvailableConverterCount = localConverterCount;
115085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            gAvailableConverters = localConverterList;
1151ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            ucln_common_registerCleanup(UCLN_COMMON_UCNV, ucnv_cleanup);
1152ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1153ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        else {
1154ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            uprv_free((char **)localConverterList);
1155ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1156ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        umtx_unlock(&cnvCacheMutex);
1157ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1158ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return TRUE;
1159ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
1160ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1161ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruU_CFUNC uint16_t
1162ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruucnv_bld_countAvailableConverters(UErrorCode *pErrorCode) {
1163ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (haveAvailableConverterList(pErrorCode)) {
1164ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return gAvailableConverterCount;
1165ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1166ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return 0;
1167ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
1168ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1169ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruU_CFUNC const char *
1170ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruucnv_bld_getAvailableConverter(uint16_t n, UErrorCode *pErrorCode) {
1171ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (haveAvailableConverterList(pErrorCode)) {
1172ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (n < gAvailableConverterCount) {
1173ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            return gAvailableConverters[n];
1174ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1175ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        *pErrorCode = U_INDEX_OUTOFBOUNDS_ERROR;
1176ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1177ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return NULL;
1178ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
1179ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1180ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/* default converter name --------------------------------------------------- */
1181ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
118285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho#if !U_CHARSET_IS_UTF8
1183ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/*
1184ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruCopy the canonical converter name.
1185ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruucnv_getDefaultName must be thread safe, which can call this function.
1186ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1187ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruucnv_setDefaultName calls this function and it doesn't have to be
1188ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruthread safe because there is no reliable/safe way to reset the
1189ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruconverter in use in all threads. If you did reset the converter, you
1190ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruwould not be sure that retrieving a default converter for one string
1191ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruwould be the same type of default converter for a successive string.
1192ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruSince the name is a returned via ucnv_getDefaultName without copying,
1193ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruyou shouldn't be modifying or deleting the string from a separate thread.
1194ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*/
1195ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic U_INLINE void
1196ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruinternalSetName(const char *name, UErrorCode *status) {
119785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    UConverterNamePieces stackPieces;
119885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    UConverterLoadArgs stackArgs={ (int32_t)sizeof(UConverterLoadArgs) };
1199ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t length=(int32_t)(uprv_strlen(name));
1200ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UBool containsOption = (UBool)(uprv_strchr(name, UCNV_OPTION_SEP_CHAR) != NULL);
1201ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    const UConverterSharedData *algorithmicSharedData;
1202ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
120385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    stackArgs.name = name;
1204ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(containsOption) {
120585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        stackPieces.cnvName[0] = 0;
120685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        stackPieces.locale[0] = 0;
120785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        stackPieces.options = 0;
120885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        parseConverterOptions(name, &stackPieces, &stackArgs, status);
120985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        if(U_FAILURE(*status)) {
121085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            return;
121185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
1212ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
121385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    algorithmicSharedData = getAlgorithmicTypeFromName(stackArgs.name);
1214ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1215ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    umtx_lock(&cnvCacheMutex);
1216ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1217ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    gDefaultAlgorithmicSharedData = algorithmicSharedData;
1218ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    gDefaultConverterContainsOption = containsOption;
1219ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    uprv_memcpy(gDefaultConverterNameBuffer, name, length);
1220ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    gDefaultConverterNameBuffer[length]=0;
122185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
122285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    /* gDefaultConverterName MUST be the last global var set by this function.  */
122385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    /*    It is the variable checked in ucnv_getDefaultName() to see if initialization is required. */
1224ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    gDefaultConverterName = gDefaultConverterNameBuffer;
1225ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1226ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    ucln_common_registerCleanup(UCLN_COMMON_UCNV, ucnv_cleanup);
1227ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1228ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    umtx_unlock(&cnvCacheMutex);
1229ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
123085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho#endif
1231ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1232ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/*
1233ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * In order to be really thread-safe, the get function would have to take
1234ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * a buffer parameter and copy the current string inside a mutex block.
1235ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * This implementation only tries to be really thread-safe while
1236ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * setting the name.
1237ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * It assumes that setting a pointer is atomic.
1238ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */
1239ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1240ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruU_CAPI const char*  U_EXPORT2
1241ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruucnv_getDefaultName() {
124285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho#if U_CHARSET_IS_UTF8
124385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    return "UTF-8";
124485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho#else
1245ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* local variable to be thread-safe */
1246ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    const char *name;
1247ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1248ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /*
1249ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    Multiple calls to ucnv_getDefaultName must be thread safe,
1250ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    but ucnv_setDefaultName is not thread safe.
1251ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    */
1252ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UMTX_CHECK(&cnvCacheMutex, gDefaultConverterName, name);
1253ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(name==NULL) {
1254ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        UErrorCode errorCode = U_ZERO_ERROR;
1255ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        UConverter *cnv = NULL;
1256ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1257ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        name = uprv_getDefaultCodepage();
1258ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1259ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* if the name is there, test it out and get the canonical name with options */
1260ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if(name != NULL) {
1261ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            cnv = ucnv_open(name, &errorCode);
1262ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if(U_SUCCESS(errorCode) && cnv != NULL) {
1263ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                name = ucnv_getName(cnv, &errorCode);
1264ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
1265ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1266ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1267ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if(name == NULL || name[0] == 0
1268ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            || U_FAILURE(errorCode) || cnv == NULL
1269ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            || uprv_strlen(name)>=sizeof(gDefaultConverterNameBuffer))
1270ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        {
1271ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            /* Panic time, let's use a fallback. */
1272ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#if (U_CHARSET_FAMILY == U_ASCII_FAMILY)
1273ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            name = "US-ASCII";
1274ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            /* there is no 'algorithmic' converter for EBCDIC */
1275ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#elif defined(OS390)
1276ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            name = "ibm-1047_P100-1995" UCNV_SWAP_LFNL_OPTION_STRING;
1277ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#else
1278ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            name = "ibm-37_P100-1995";
1279ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#endif
1280ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1281ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1282ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        internalSetName(name, &errorCode);
1283ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1284ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* The close may make the current name go away. */
1285ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        ucnv_close(cnv);
1286ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1287ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1288ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return name;
128985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho#endif
1290ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
1291ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1292ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/*
1293ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruThis function is not thread safe, and it can't be thread safe.
1294ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruSee internalSetName or the API reference for details.
1295ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*/
1296ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruU_CAPI void U_EXPORT2
1297ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruucnv_setDefaultName(const char *converterName) {
129885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho#if !U_CHARSET_IS_UTF8
1299ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(converterName==NULL) {
1300ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* reset to the default codepage */
1301ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        gDefaultConverterName=NULL;
1302ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    } else {
1303ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        UErrorCode errorCode = U_ZERO_ERROR;
1304ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        UConverter *cnv = NULL;
1305ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        const char *name = NULL;
1306ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1307ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* if the name is there, test it out and get the canonical name with options */
1308ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        cnv = ucnv_open(converterName, &errorCode);
1309ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if(U_SUCCESS(errorCode) && cnv != NULL) {
1310ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            name = ucnv_getName(cnv, &errorCode);
1311ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1312ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1313ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if(U_SUCCESS(errorCode) && name!=NULL) {
1314ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            internalSetName(name, &errorCode);
1315ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1316ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* else this converter is bad to use. Don't change it to a bad value. */
1317ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1318ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* The close may make the current name go away. */
1319ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        ucnv_close(cnv);
132027f654740f2a26ad62a5c155af9199af9e69b889claireho
132127f654740f2a26ad62a5c155af9199af9e69b889claireho        /* reset the converter cache */
132227f654740f2a26ad62a5c155af9199af9e69b889claireho        u_flushDefaultConverter();
1323ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
132485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho#endif
1325ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
1326ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1327ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/* data swapping ------------------------------------------------------------ */
1328ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1329ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/* most of this might belong more properly into ucnvmbcs.c, but that is so large */
1330ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1331ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#if !UCONFIG_NO_LEGACY_CONVERSION
1332ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1333ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruU_CAPI int32_t U_EXPORT2
1334ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruucnv_swap(const UDataSwapper *ds,
1335ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru          const void *inData, int32_t length, void *outData,
1336ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru          UErrorCode *pErrorCode) {
1337ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    const UDataInfo *pInfo;
1338ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t headerSize;
1339ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1340ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    const uint8_t *inBytes;
1341ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    uint8_t *outBytes;
1342ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1343ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    uint32_t offset, count, staticDataSize;
1344ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t size;
1345ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1346ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    const UConverterStaticData *inStaticData;
1347ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UConverterStaticData *outStaticData;
1348ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1349ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    const _MBCSHeader *inMBCSHeader;
1350ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    _MBCSHeader *outMBCSHeader;
1351ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    _MBCSHeader mbcsHeader;
1352c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru    uint32_t mbcsHeaderLength;
1353c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru    UBool noFromU=FALSE;
1354c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru
1355ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    uint8_t outputType;
1356ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1357ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t maxFastUChar, mbcsIndexLength;
1358ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1359ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    const int32_t *inExtIndexes;
1360ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t extOffset;
1361ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1362ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* udata_swapDataHeader checks the arguments */
1363ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    headerSize=udata_swapDataHeader(ds, inData, length, outData, pErrorCode);
1364ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) {
1365ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return 0;
1366ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1367ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1368ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* check data format and format version */
1369ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    pInfo=(const UDataInfo *)((const char *)inData+4);
1370ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(!(
1371ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        pInfo->dataFormat[0]==0x63 &&   /* dataFormat="cnvt" */
1372ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        pInfo->dataFormat[1]==0x6e &&
1373ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        pInfo->dataFormat[2]==0x76 &&
1374ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        pInfo->dataFormat[3]==0x74 &&
1375ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        pInfo->formatVersion[0]==6 &&
1376ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        pInfo->formatVersion[1]>=2
1377ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    )) {
1378ac04d0bbe12b3ef54518635711412f178cb4d16Jean-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",
1379ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                         pInfo->dataFormat[0], pInfo->dataFormat[1],
1380ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                         pInfo->dataFormat[2], pInfo->dataFormat[3],
1381ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                         pInfo->formatVersion[0], pInfo->formatVersion[1]);
1382ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        *pErrorCode=U_UNSUPPORTED_ERROR;
1383ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return 0;
1384ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1385ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1386ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    inBytes=(const uint8_t *)inData+headerSize;
1387ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    outBytes=(uint8_t *)outData+headerSize;
1388ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1389ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* read the initial UConverterStaticData structure after the UDataInfo header */
1390ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    inStaticData=(const UConverterStaticData *)inBytes;
1391ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    outStaticData=(UConverterStaticData *)outBytes;
1392ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1393ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(length<0) {
1394ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        staticDataSize=ds->readUInt32(inStaticData->structSize);
1395ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    } else {
1396ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        length-=headerSize;
1397ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if( length<sizeof(UConverterStaticData) ||
1398ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            (uint32_t)length<(staticDataSize=ds->readUInt32(inStaticData->structSize))
1399ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        ) {
1400ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            udata_printError(ds, "ucnv_swap(): too few bytes (%d after header) for an ICU .cnv conversion table\n",
1401ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                             length);
1402ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            *pErrorCode=U_INDEX_OUTOFBOUNDS_ERROR;
1403ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            return 0;
1404ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1405ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1406ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1407ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(length>=0) {
1408ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* swap the static data */
1409ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if(inStaticData!=outStaticData) {
1410ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            uprv_memcpy(outStaticData, inStaticData, staticDataSize);
1411ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1412ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1413ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        ds->swapArray32(ds, &inStaticData->structSize, 4,
1414ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                           &outStaticData->structSize, pErrorCode);
1415ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        ds->swapArray32(ds, &inStaticData->codepage, 4,
1416ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                           &outStaticData->codepage, pErrorCode);
1417ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1418ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        ds->swapInvChars(ds, inStaticData->name, (int32_t)uprv_strlen(inStaticData->name),
1419ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                            outStaticData->name, pErrorCode);
1420ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if(U_FAILURE(*pErrorCode)) {
1421ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            udata_printError(ds, "ucnv_swap(): error swapping converter name\n");
1422ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            return 0;
1423ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1424ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1425ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1426ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    inBytes+=staticDataSize;
1427ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    outBytes+=staticDataSize;
1428ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(length>=0) {
1429ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        length-=(int32_t)staticDataSize;
1430ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1431ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1432ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* check for supported conversionType values */
1433ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(inStaticData->conversionType==UCNV_MBCS) {
1434ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* swap MBCS data */
1435ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        inMBCSHeader=(const _MBCSHeader *)inBytes;
1436ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        outMBCSHeader=(_MBCSHeader *)outBytes;
1437ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1438ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if(0<=length && length<sizeof(_MBCSHeader)) {
1439ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            udata_printError(ds, "ucnv_swap(): too few bytes (%d after headers) for an ICU MBCS .cnv conversion table\n",
1440ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                                length);
1441ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            *pErrorCode=U_INDEX_OUTOFBOUNDS_ERROR;
1442ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            return 0;
1443ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1444c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru        if(inMBCSHeader->version[0]==4 && inMBCSHeader->version[1]>=1) {
1445c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru            mbcsHeaderLength=MBCS_HEADER_V4_LENGTH;
1446c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru        } else if(inMBCSHeader->version[0]==5 && inMBCSHeader->version[1]>=3 &&
1447c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru                  ((mbcsHeader.options=ds->readUInt32(inMBCSHeader->options))&
1448c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru                   MBCS_OPT_UNKNOWN_INCOMPATIBLE_MASK)==0
1449c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru        ) {
1450c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru            mbcsHeaderLength=mbcsHeader.options&MBCS_OPT_LENGTH_MASK;
1451c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru            noFromU=(UBool)((mbcsHeader.options&MBCS_OPT_NO_FROM_U)!=0);
1452c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru        } else {
1453ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            udata_printError(ds, "ucnv_swap(): unsupported _MBCSHeader.version %d.%d\n",
1454ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                             inMBCSHeader->version[0], inMBCSHeader->version[1]);
1455ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            *pErrorCode=U_UNSUPPORTED_ERROR;
1456ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            return 0;
1457ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1458ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1459ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        uprv_memcpy(mbcsHeader.version, inMBCSHeader->version, 4);
1460ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        mbcsHeader.countStates=         ds->readUInt32(inMBCSHeader->countStates);
1461ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        mbcsHeader.countToUFallbacks=   ds->readUInt32(inMBCSHeader->countToUFallbacks);
1462ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        mbcsHeader.offsetToUCodeUnits=  ds->readUInt32(inMBCSHeader->offsetToUCodeUnits);
1463ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        mbcsHeader.offsetFromUTable=    ds->readUInt32(inMBCSHeader->offsetFromUTable);
1464ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        mbcsHeader.offsetFromUBytes=    ds->readUInt32(inMBCSHeader->offsetFromUBytes);
1465ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        mbcsHeader.flags=               ds->readUInt32(inMBCSHeader->flags);
1466ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        mbcsHeader.fromUBytesLength=    ds->readUInt32(inMBCSHeader->fromUBytesLength);
1467c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru        /* mbcsHeader.options have been read above */
1468ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1469ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        extOffset=(int32_t)(mbcsHeader.flags>>8);
1470ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        outputType=(uint8_t)mbcsHeader.flags;
1471c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru        if(noFromU && outputType==MBCS_OUTPUT_1) {
1472c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru            udata_printError(ds, "ucnv_swap(): unsupported combination of makeconv --small with SBCS\n");
1473c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru            *pErrorCode=U_UNSUPPORTED_ERROR;
1474c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru            return 0;
1475c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru        }
1476ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1477ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* make sure that the output type is known */
1478ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        switch(outputType) {
1479ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        case MBCS_OUTPUT_1:
1480ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        case MBCS_OUTPUT_2:
1481ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        case MBCS_OUTPUT_3:
1482ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        case MBCS_OUTPUT_4:
1483ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        case MBCS_OUTPUT_3_EUC:
1484ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        case MBCS_OUTPUT_4_EUC:
1485ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        case MBCS_OUTPUT_2_SISO:
1486ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        case MBCS_OUTPUT_EXT_ONLY:
1487ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            /* OK */
1488ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            break;
1489ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        default:
1490ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            udata_printError(ds, "ucnv_swap(): unsupported MBCS output type 0x%x\n",
1491ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                             outputType);
1492ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            *pErrorCode=U_UNSUPPORTED_ERROR;
1493ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            return 0;
1494ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1495ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1496ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* calculate the length of the MBCS data */
1497ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1498ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /*
1499ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru         * utf8Friendly MBCS files (mbcsHeader.version 4.3)
1500ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru         * contain an additional mbcsIndex table:
1501ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru         *   uint16_t[(maxFastUChar+1)>>6];
1502ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru         * where maxFastUChar=((mbcsHeader.version[2]<<8)|0xff).
1503ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru         */
1504ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        maxFastUChar=0;
1505ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        mbcsIndexLength=0;
1506ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if( outputType!=MBCS_OUTPUT_EXT_ONLY && outputType!=MBCS_OUTPUT_1 &&
1507ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            mbcsHeader.version[1]>=3 && (maxFastUChar=mbcsHeader.version[2])!=0
1508ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        ) {
1509ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            maxFastUChar=(maxFastUChar<<8)|0xff;
1510ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            mbcsIndexLength=((maxFastUChar+1)>>6)*2;  /* number of bytes */
1511ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1512ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1513ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if(extOffset==0) {
1514c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru            size=(int32_t)(mbcsHeader.offsetFromUBytes+mbcsIndexLength);
1515c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru            if(!noFromU) {
1516c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru                size+=(int32_t)mbcsHeader.fromUBytesLength;
1517c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru            }
1518ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1519ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            /* avoid compiler warnings - not otherwise necessary, and the value does not matter */
1520ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            inExtIndexes=NULL;
1521ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        } else {
1522ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            /* there is extension data after the base data, see ucnv_ext.h */
1523ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if(length>=0 && length<(extOffset+UCNV_EXT_INDEXES_MIN_LENGTH*4)) {
1524ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                udata_printError(ds, "ucnv_swap(): too few bytes (%d after headers) for an ICU MBCS .cnv conversion table with extension data\n",
1525ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                                 length);
1526ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                *pErrorCode=U_INDEX_OUTOFBOUNDS_ERROR;
1527ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                return 0;
1528ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
1529ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1530ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            inExtIndexes=(const int32_t *)(inBytes+extOffset);
1531ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            size=extOffset+udata_readInt32(ds, inExtIndexes[UCNV_EXT_SIZE]);
1532ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1533ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1534ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if(length>=0) {
1535ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if(length<size) {
1536ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                udata_printError(ds, "ucnv_swap(): too few bytes (%d after headers) for an ICU MBCS .cnv conversion table\n",
1537ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                                 length);
1538ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                *pErrorCode=U_INDEX_OUTOFBOUNDS_ERROR;
1539ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                return 0;
1540ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
1541ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1542ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            /* copy the data for inaccessible bytes */
1543ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if(inBytes!=outBytes) {
1544ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                uprv_memcpy(outBytes, inBytes, size);
1545ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
1546ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1547c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru            /* swap the MBCSHeader, except for the version field */
1548c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru            count=mbcsHeaderLength*4;
1549c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru            ds->swapArray32(ds, &inMBCSHeader->countStates, count-4,
1550ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                               &outMBCSHeader->countStates, pErrorCode);
1551ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1552ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if(outputType==MBCS_OUTPUT_EXT_ONLY) {
1553ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                /*
1554ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                 * extension-only file,
1555ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                 * contains a base name instead of normal base table data
1556ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                 */
1557ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1558ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                /* swap the base name, between the header and the extension data */
1559c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru                const char *inBaseName=(const char *)inBytes+count;
1560c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru                char *outBaseName=(char *)outBytes+count;
1561c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru                ds->swapInvChars(ds, inBaseName, (int32_t)uprv_strlen(inBaseName),
1562c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru                                    outBaseName, pErrorCode);
1563ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            } else {
1564ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                /* normal file with base table data */
1565ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1566ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                /* swap the state table, 1kB per state */
1567c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru                offset=count;
1568c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru                count=mbcsHeader.countStates*1024;
1569c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru                ds->swapArray32(ds, inBytes+offset, (int32_t)count,
1570c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru                                   outBytes+offset, pErrorCode);
1571ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1572ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                /* swap the toUFallbacks[] */
1573c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru                offset+=count;
1574c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru                count=mbcsHeader.countToUFallbacks*8;
1575c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru                ds->swapArray32(ds, inBytes+offset, (int32_t)count,
1576ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                                   outBytes+offset, pErrorCode);
1577ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1578ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                /* swap the unicodeCodeUnits[] */
1579ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                offset=mbcsHeader.offsetToUCodeUnits;
1580ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                count=mbcsHeader.offsetFromUTable-offset;
1581ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                ds->swapArray16(ds, inBytes+offset, (int32_t)count,
1582ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                                   outBytes+offset, pErrorCode);
1583ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1584ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                /* offset to the stage 1 table, independent of the outputType */
1585ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                offset=mbcsHeader.offsetFromUTable;
1586ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1587ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                if(outputType==MBCS_OUTPUT_1) {
1588ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    /* SBCS: swap the fromU tables, all 16 bits wide */
1589ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    count=(mbcsHeader.offsetFromUBytes-offset)+mbcsHeader.fromUBytesLength;
1590ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    ds->swapArray16(ds, inBytes+offset, (int32_t)count,
1591ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                                       outBytes+offset, pErrorCode);
1592ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                } else {
1593ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    /* otherwise: swap the stage tables separately */
1594ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1595ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    /* stage 1 table: uint16_t[0x440 or 0x40] */
1596ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    if(inStaticData->unicodeMask&UCNV_HAS_SUPPLEMENTARY) {
1597ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        count=0x440*2; /* for all of Unicode */
1598ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    } else {
1599ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        count=0x40*2; /* only BMP */
1600ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    }
1601ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    ds->swapArray16(ds, inBytes+offset, (int32_t)count,
1602ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                                       outBytes+offset, pErrorCode);
1603ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1604ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    /* stage 2 table: uint32_t[] */
1605ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    offset+=count;
1606ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    count=mbcsHeader.offsetFromUBytes-offset;
1607ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    ds->swapArray32(ds, inBytes+offset, (int32_t)count,
1608ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                                       outBytes+offset, pErrorCode);
1609ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1610ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    /* stage 3/result bytes: sometimes uint16_t[] or uint32_t[] */
1611ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    offset=mbcsHeader.offsetFromUBytes;
1612c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru                    count= noFromU ? 0 : mbcsHeader.fromUBytesLength;
1613ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    switch(outputType) {
1614ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    case MBCS_OUTPUT_2:
1615ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    case MBCS_OUTPUT_3_EUC:
1616ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    case MBCS_OUTPUT_2_SISO:
1617ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        ds->swapArray16(ds, inBytes+offset, (int32_t)count,
1618ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                                           outBytes+offset, pErrorCode);
1619ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        break;
1620ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    case MBCS_OUTPUT_4:
1621ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        ds->swapArray32(ds, inBytes+offset, (int32_t)count,
1622ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                                           outBytes+offset, pErrorCode);
1623ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        break;
1624ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    default:
1625ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        /* just uint8_t[], nothing to swap */
1626ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        break;
1627ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    }
1628ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1629ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    if(mbcsIndexLength!=0) {
1630ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        offset+=count;
1631ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        count=mbcsIndexLength;
1632ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        ds->swapArray16(ds, inBytes+offset, (int32_t)count,
1633ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                                           outBytes+offset, pErrorCode);
1634ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    }
1635ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                }
1636ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
1637ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1638ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if(extOffset!=0) {
1639ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                /* swap the extension data */
1640ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                inBytes+=extOffset;
1641ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                outBytes+=extOffset;
1642ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1643ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                /* swap toUTable[] */
1644ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                offset=udata_readInt32(ds, inExtIndexes[UCNV_EXT_TO_U_INDEX]);
1645ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                length=udata_readInt32(ds, inExtIndexes[UCNV_EXT_TO_U_LENGTH]);
1646ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                ds->swapArray32(ds, inBytes+offset, length*4, outBytes+offset, pErrorCode);
1647ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1648ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                /* swap toUUChars[] */
1649ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                offset=udata_readInt32(ds, inExtIndexes[UCNV_EXT_TO_U_UCHARS_INDEX]);
1650ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                length=udata_readInt32(ds, inExtIndexes[UCNV_EXT_TO_U_UCHARS_LENGTH]);
1651ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                ds->swapArray16(ds, inBytes+offset, length*2, outBytes+offset, pErrorCode);
1652ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1653ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                /* swap fromUTableUChars[] */
1654ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                offset=udata_readInt32(ds, inExtIndexes[UCNV_EXT_FROM_U_UCHARS_INDEX]);
1655ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                length=udata_readInt32(ds, inExtIndexes[UCNV_EXT_FROM_U_LENGTH]);
1656ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                ds->swapArray16(ds, inBytes+offset, length*2, outBytes+offset, pErrorCode);
1657ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1658ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                /* swap fromUTableValues[] */
1659ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                offset=udata_readInt32(ds, inExtIndexes[UCNV_EXT_FROM_U_VALUES_INDEX]);
1660ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                /* same length as for fromUTableUChars[] */
1661ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                ds->swapArray32(ds, inBytes+offset, length*4, outBytes+offset, pErrorCode);
1662ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1663ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                /* no need to swap fromUBytes[] */
1664ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1665ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                /* swap fromUStage12[] */
1666ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                offset=udata_readInt32(ds, inExtIndexes[UCNV_EXT_FROM_U_STAGE_12_INDEX]);
1667ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                length=udata_readInt32(ds, inExtIndexes[UCNV_EXT_FROM_U_STAGE_12_LENGTH]);
1668ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                ds->swapArray16(ds, inBytes+offset, length*2, outBytes+offset, pErrorCode);
1669ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1670ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                /* swap fromUStage3[] */
1671ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                offset=udata_readInt32(ds, inExtIndexes[UCNV_EXT_FROM_U_STAGE_3_INDEX]);
1672ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                length=udata_readInt32(ds, inExtIndexes[UCNV_EXT_FROM_U_STAGE_3_LENGTH]);
1673ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                ds->swapArray16(ds, inBytes+offset, length*2, outBytes+offset, pErrorCode);
1674ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1675ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                /* swap fromUStage3b[] */
1676ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                offset=udata_readInt32(ds, inExtIndexes[UCNV_EXT_FROM_U_STAGE_3B_INDEX]);
1677ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                length=udata_readInt32(ds, inExtIndexes[UCNV_EXT_FROM_U_STAGE_3B_LENGTH]);
1678ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                ds->swapArray32(ds, inBytes+offset, length*4, outBytes+offset, pErrorCode);
1679ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1680ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                /* swap indexes[] */
1681ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                length=udata_readInt32(ds, inExtIndexes[UCNV_EXT_INDEXES_LENGTH]);
1682ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                ds->swapArray32(ds, inBytes, length*4, outBytes, pErrorCode);
1683ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
1684ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1685ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    } else {
1686ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        udata_printError(ds, "ucnv_swap(): unknown conversionType=%d!=UCNV_MBCS\n",
1687ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                         inStaticData->conversionType);
1688ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        *pErrorCode=U_UNSUPPORTED_ERROR;
1689ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return 0;
1690ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1691ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1692ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return headerSize+(int32_t)staticDataSize+size;
1693ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
1694ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1695ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#endif /* #if !UCONFIG_NO_LEGACY_CONVERSION */
1696ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1697ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#endif
1698