2 *******************************************************************************
\r
3 * Copyright (C) 2006-2008, International Business Machines Corporation and *
\r
4 * others. All Rights Reserved. *
\r
5 *******************************************************************************
\r
7 package com.ibm.icu.charset;
\r
10 * Defines the UConverterSharedData struct, the immutable, shared part of
\r
13 final class UConverterSharedData {
\r
14 // uint32_t structSize; /* Size of this structure */
\r
15 // int structSize; /* Size of this structure */
\r
17 * used to count number of clients, 0xffffffff for static SharedData
\r
19 int referenceCounter;
\r
21 // agljport:todo const void *dataMemory; /* from udata_openChoice() - for cleanup */
\r
22 // agljport:todo void *table; /* Unused. This used to be a UConverterTable - Pointer to conversion data - see mbcs below */
\r
24 // const UConverterStaticData *staticData; /* pointer to the static (non changing) data. */
\r
26 * pointer to the static (non changing)
\r
29 UConverterStaticData staticData;
\r
31 // UBool sharedDataCached; /* TRUE: shared data is in cache, don't destroy
\r
32 // on close() if 0 ref. FALSE: shared data isn't in the cache, do attempt to
\r
33 // clean it up if the ref is 0 */
\r
36 * TRUE: shared data is in cache, don't destroy
\r
37 * on close() if 0 ref. FALSE: shared data isn't
\r
38 * in the cache, do attempt to clean it up if
\r
41 boolean sharedDataCached;
\r
44 * UBool staticDataOwned; TRUE if static data owned by shared data & should
\r
45 * be freed with it, NEVER true for udata() loaded statics. This ignored
\r
46 * variable was removed to make space for sharedDataCached.
\r
49 // const UConverterImpl *impl; /* vtable-style struct of mostly function pointers */
\r
50 // UConverterImpl impl; /* vtable-style struct of mostly function pointers */
\r
51 /** initial values of some members of the mutable part of object */
\r
52 long toUnicodeStatus;
\r
55 * Shared data structures currently come in two flavors:
\r
56 * - readonly for built-in algorithmic converters
\r
57 * - allocated for MBCS, with a pointer to an allocated UConverterTable
\r
58 * which always has a UConverterMBCSTable
\r
60 * To eliminate one allocation, I am making the UConverterMBCSTable a member
\r
61 * of the shared data. It is the last member so that static definitions of
\r
62 * UConverterSharedData work as before. The table field above also remains
\r
63 * to avoid updating all static definitions, but is now unused.
\r
66 CharsetMBCS.UConverterMBCSTable mbcs;
\r
68 UConverterSharedData() {
\r
69 mbcs = new CharsetMBCS.UConverterMBCSTable();
\r
72 UConverterSharedData(int referenceCounter_, UConverterStaticData staticData_, boolean sharedDataCached_, long toUnicodeStatus_)
\r
75 referenceCounter = referenceCounter_;
\r
76 staticData = staticData_;
\r
77 sharedDataCached = sharedDataCached_;
\r
79 toUnicodeStatus = toUnicodeStatus_;
\r
83 * UConverterImpl contains all the data and functions for a converter type.
\r
84 * Its function pointers work much like a C++ vtable. Many converter types
\r
85 * need to define only a subset of the functions; when a function pointer is
\r
86 * NULL, then a default action will be performed.
\r
88 * Every converter type must implement toUnicode, fromUnicode, and
\r
89 * getNextUChar, otherwise the converter may crash. Every converter type
\r
90 * that has variable-length codepage sequences should also implement
\r
91 * toUnicodeWithOffsets and fromUnicodeWithOffsets for correct offset
\r
92 * handling. All other functions may or may not be implemented - it depends
\r
93 * only on whether the converter type needs them.
\r
95 * When open() fails, then close() will be called, if present.
\r
97 /* class UConverterImpl {
\r
98 UConverterType type;
\r
99 UConverterToUnicode toUnicode;
\r
100 protected void doToUnicode(UConverterToUnicodeArgs args, int[] pErrorCode)
\r
104 final void toUnicode(UConverterToUnicodeArgs args, int[] pErrorCode)
\r
106 doToUnicode(args, pErrorCode);
\r
109 //UConverterFromUnicode fromUnicode;
\r
110 protected void doFromUnicode(UConverterFromUnicodeArgs args, int[] pErrorCode)
\r
114 final void fromUnicode(UConverterFromUnicodeArgs args, int[] pErrorCode)
\r
116 doFromUnicode(args, pErrorCode);
\r
119 protected int doGetNextUChar(UConverterToUnicodeArgs args, int[] pErrorCode)
\r
124 //UConverterGetNextUChar getNextUChar;
\r
125 final int getNextUChar(UConverterToUnicodeArgs args, int[] pErrorCode)
\r
127 return doGetNextUChar(args, pErrorCode);
\r
130 // interface UConverterImplLoadable extends UConverterImpl
\r
131 protected void doLoad(UConverterLoadArgs pArgs, short[] raw, int[] pErrorCode)
\r
135 protected void doUnload()
\r
139 // interface UConverterImplOpenable extends UConverterImpl
\r
140 protected void doOpen(UConverter cnv, String name, String locale, long options, int[] pErrorCode)
\r
144 //UConverterOpen open;
\r
145 final void open(UConverter cnv, String name, String locale, long options, int[] pErrorCode)
\r
147 doOpen(cnv, name, locale, options, pErrorCode);
\r
150 protected void doClose(UConverter cnv)
\r
154 //UConverterClose close;
\r
155 final void close(UConverter cnv)
\r
160 protected void doReset(UConverter cnv, int choice)
\r
164 //typedef void (*UConverterReset) (UConverter *cnv, UConverterResetChoice choice);
\r
165 //UConverterReset reset;
\r
166 final void reset(UConverter cnv, int choice)
\r
168 doReset(cnv, choice);
\r
171 // interface UConverterImplVariableLength extends UConverterImpl
\r
172 protected void doToUnicodeWithOffsets(UConverterToUnicodeArgs args, int[] pErrorCode)
\r
176 //UConverterToUnicode toUnicodeWithOffsets;
\r
177 final void toUnicodeWithOffsets(UConverterToUnicodeArgs args, int[] pErrorCode)
\r
179 doToUnicodeWithOffsets(args, pErrorCode);
\r
182 protected void doFromUnicodeWithOffsets(UConverterFromUnicodeArgs args, int[] pErrorCode)
\r
186 //UConverterFromUnicode fromUnicodeWithOffsets;
\r
187 final void fromUnicodeWithOffsets(UConverterFromUnicodeArgs args, int[] pErrorCode)
\r
189 doFromUnicodeWithOffsets(args, pErrorCode);
\r
192 // interface UConverterImplMisc extends UConverterImpl
\r
193 protected void doGetStarters(UConverter converter, boolean starters[], int[] pErrorCode)
\r
197 //UConverterGetStarters getStarters;
\r
198 final void getStarters(UConverter converter, boolean starters[], int[] pErrorCode)
\r
200 doGetStarters(converter, starters, pErrorCode);
\r
203 protected String doGetName(UConverter cnv)
\r
208 //UConverterGetName getName;
\r
209 final String getName(UConverter cnv)
\r
211 return doGetName(cnv);
\r
214 protected void doWriteSub(UConverterFromUnicodeArgs pArgs, long offsetIndex, int[] pErrorCode)
\r
218 //UConverterWriteSub writeSub;
\r
219 final void writeSub(UConverterFromUnicodeArgs pArgs, long offsetIndex, int[] pErrorCode)
\r
221 doWriteSub(pArgs, offsetIndex, pErrorCode);
\r
224 protected UConverter doSafeClone(UConverter cnv, byte[] stackBuffer, int[] pBufferSize, int[] status)
\r
226 return new UConverter();
\r
229 //UConverterSafeClone safeClone;
\r
230 final UConverter safeClone(UConverter cnv, byte[] stackBuffer, int[] pBufferSize, int[] status)
\r
232 return doSafeClone(cnv, stackBuffer, pBufferSize, status);
\r
235 protected void doGetUnicodeSet(UConverter cnv, UnicodeSet /*USetAdder* / sa, int /*UConverterUnicodeSet* / which, int[] pErrorCode)
\r
239 //UConverterGetUnicodeSet getUnicodeSet;
\r
240 // final void getUnicodeSet(UConverter cnv, UnicodeSet /*USetAdder* / sa, int /*UConverterUnicodeSet* / which, int[] pErrorCode)
\r
242 // doGetUnicodeSet(cnv, sa, which, pErrorCode);
\r
247 static final String DATA_TYPE = "cnv";
\r
248 private static final int CNV_DATA_BUFFER_SIZE = 25000;
\r
249 static final int sizeofUConverterSharedData = 100;
\r
251 //static UDataMemoryIsAcceptable isCnvAcceptable;
\r
254 * Load a non-algorithmic converter.
\r
255 * If pkg==NULL, then this function must be called inside umtx_lock(&cnvCacheMutex).
\r
257 // UConverterSharedData * load(UConverterLoadArgs *pArgs, UErrorCode *err)
\r
258 static final UConverterSharedData load(UConverterLoadArgs pArgs, int[] err)
\r
260 UConverterSharedData mySharedConverterData = null;
\r
262 if(err == null || ErrorCode.isFailure(err[0])) {
\r
266 if(pArgs.pkg != null && pArgs.pkg.length() != 0) {
\r
267 application-provided converters are not currently cached
\r
268 return UConverterSharedData.createConverterFromFile(pArgs, err);
\r
271 //agljport:fix mySharedConverterData = getSharedConverterData(pArgs.name);
\r
272 if (mySharedConverterData == null)
\r
274 Not cached, we need to stream it in from file
\r
275 mySharedConverterData = UConverterSharedData.createConverterFromFile(pArgs, err);
\r
276 if (ErrorCode.isFailure(err[0]) || (mySharedConverterData == null))
\r
282 share it with other library clients
\r
283 //agljport:fix shareConverterData(mySharedConverterData);
\r
288 The data for this converter was already in the cache.
\r
289 Update the reference counter on the shared data: one more client
\r
290 mySharedConverterData.referenceCounter++;
\r
293 return mySharedConverterData;
\r
296 Takes an alias name gets an actual converter file name
\r
297 *goes to disk and opens it.
\r
298 *allocates the memory and returns a new UConverter object
\r
300 //static UConverterSharedData *createConverterFromFile(UConverterLoadArgs *pArgs, UErrorCode * err)
\r
301 static final UConverterSharedData createConverterFromFile(UConverterLoadArgs pArgs, int[] err)
\r
303 UDataMemory data = null;
\r
304 UConverterSharedData sharedData = null;
\r
306 //agljport:todo UTRACE_ENTRY_OC(UTRACE_LOAD);
\r
308 if (err == null || ErrorCode.isFailure(err[0])) {
\r
309 //agljport:todo UTRACE_EXIT_STATUS(*err);
\r
313 //agljport:todo UTRACE_DATA2(UTRACE_OPEN_CLOSE, "load converter %s from package %s", pArgs->name, pArgs->pkg);
\r
315 //agljport:fix data = udata_openChoice(pArgs.pkgArray, DATA_TYPE.getBytes(), pArgs.name, isCnvAcceptable, null, err);
\r
316 if(ErrorCode.isFailure(err[0]))
\r
318 //agljport:todo UTRACE_EXIT_STATUS(*err);
\r
322 sharedData = data_unFlattenClone(pArgs, data, err);
\r
323 if(ErrorCode.isFailure(err[0]))
\r
325 //agljport:fix udata_close(data);
\r
326 //agljport:todo UTRACE_EXIT_STATUS(*err);
\r
331 * TODO Store pkg in a field in the shared data so that delta-only converters
\r
332 * can load base converters from the same package.
\r
333 * If the pkg name is longer than the field, then either do not load the converter
\r
334 * in the first place, or just set the pkg field to "".
\r
340 UConverterDataReader dataReader = null;
\r
343 * returns a converter type from a string
\r
345 /* static final UConverterSharedData getAlgorithmicTypeFromName(String realName)
\r
347 long mid, start, limit;
\r
350 StringBuffer strippedName = new StringBuffer(UConverterConstants.MAX_CONVERTER_NAME_LENGTH);
\r
352 // Lower case and remove ignoreable characters.
\r
353 UConverterAlias.stripForCompare(strippedName, realName);
\r
355 // do a binary search for the alias
\r
357 limit = cnvNameType.length;
\r
362 mid = (long)((start + limit) / 2);
\r
363 if (lastMid == mid) { // Have we moved?
\r
364 break; // We haven't moved, and it wasn't found.
\r
367 result = strippedName.substring(0).compareTo(cnvNameType[(int)mid].name);
\r
371 } else if (result > 0) {
\r
374 return converterData[cnvNameType[(int)mid].type];
\r
382 * Enum for specifying basic types of converters
\r
384 static final class UConverterType {
\r
385 static final int UNSUPPORTED_CONVERTER = -1;
\r
386 static final int SBCS = 0;
\r
387 static final int DBCS = 1;
\r
388 static final int MBCS = 2;
\r
389 static final int LATIN_1 = 3;
\r
390 static final int UTF8 = 4;
\r
391 static final int UTF16_BigEndian = 5;
\r
392 static final int UTF16_LittleEndian = 6;
\r
393 static final int UTF32_BigEndian = 7;
\r
394 static final int UTF32_LittleEndian = 8;
\r
395 static final int EBCDIC_STATEFUL = 9;
\r
396 static final int ISO_2022 = 10;
\r
397 static final int LMBCS_1 = 11;
\r
398 static final int LMBCS_2 = LMBCS_1 + 1; // 12
\r
399 static final int LMBCS_3 = LMBCS_2 + 1; // 13
\r
400 static final int LMBCS_4 = LMBCS_3 + 1; // 14
\r
401 static final int LMBCS_5 = LMBCS_4 + 1; // 15
\r
402 static final int LMBCS_6 = LMBCS_5 + 1; // 16
\r
403 static final int LMBCS_8 = LMBCS_6 + 1; // 17
\r
404 static final int LMBCS_11 = LMBCS_8 + 1; // 18
\r
405 static final int LMBCS_16 = LMBCS_11 + 1; // 19
\r
406 static final int LMBCS_17 = LMBCS_16 + 1; // 20
\r
407 static final int LMBCS_18 = LMBCS_17 + 1; // 21
\r
408 static final int LMBCS_19 = LMBCS_18 + 1; // 22
\r
409 static final int LMBCS_LAST = LMBCS_19; // 22
\r
410 static final int HZ = LMBCS_LAST + 1; // 23
\r
411 static final int SCSU = HZ + 1; // 24
\r
412 static final int ISCII = SCSU + 1; // 25
\r
413 static final int US_ASCII = ISCII + 1; // 26
\r
414 static final int UTF7 = US_ASCII + 1; // 27
\r
415 static final int BOCU1 = UTF7 + 1; // 28
\r
416 static final int UTF16 = BOCU1 + 1; // 29
\r
417 static final int UTF32 = UTF16 + 1; // 30
\r
418 static final int CESU8 = UTF32 + 1; // 31
\r
419 static final int IMAP_MAILBOX = CESU8 + 1; // 32
\r
421 // Number of converter types for which we have conversion routines.
\r
422 static final int NUMBER_OF_SUPPORTED_CONVERTER_TYPES = IMAP_MAILBOX + 1;
\r
426 * Enum for specifying which platform a converter ID refers to. The use of
\r
427 * platform/CCSID is not recommended. See openCCSID().
\r
429 static final class UConverterPlatform {
\r
430 static final int UNKNOWN = -1;
\r
431 static final int IBM = 0;
\r
434 // static UConverterSharedData[] converterData;
\r
435 /* static class cnvNameTypeClass {
\r
438 cnvNameTypeClass(String name_, int type_) { name = name_; type = type_; }
\r
441 static cnvNameTypeClass cnvNameType[];*/
\r
444 static final String DATA_TYPE = "cnv";
\r
445 //static final int CNV_DATA_BUFFER_SIZE = 25000;
\r
446 //static final int SIZE_OF_UCONVERTER_SHARED_DATA = 228;
\r