1 // © 2016 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html#License
3 /*
4  *******************************************************************************
5  * Copyright (C) 2006-2008, International Business Machines Corporation and    *
6  * others. All Rights Reserved.                                                *
7  *******************************************************************************
8  */
9 package com.ibm.icu.charset;
10 
11 /**
12  * Defines the UConverterSharedData struct, the immutable, shared part of
13  * UConverter.
14  */
15 final class UConverterSharedData {
16     // agljport:todo const void *dataMemory; /* from udata_openChoice() - for cleanup */
17     // agljport:todo void *table; /* Unused. This used to be a UConverterTable - Pointer to conversion data - see mbcs below */
18 
19     // const UConverterStaticData *staticData; /* pointer to the static (non changing) data. */
20     /**
21      * pointer to the static (non changing)
22      * data.
23      */
24     final UConverterStaticData staticData;
25 
26     // const UConverterImpl *impl; /* vtable-style struct of mostly function pointers */
27     // UConverterImpl impl; /* vtable-style struct of mostly function pointers */
28     /** initial values of some members of the mutable part of object */
29 
30     /**
31      * Shared data structures currently come in two flavors:
32      * - readonly for built-in algorithmic converters
33      * - allocated for MBCS, with a pointer to an allocated UConverterTable
34      *   which always has a UConverterMBCSTable
35      *
36      * To eliminate one allocation, I am making the UConverterMBCSTable a member
37      * of the shared data. It is the last member so that static definitions of
38      * UConverterSharedData work as before. The table field above also remains
39      * to avoid updating all static definitions, but is now unused.
40      *
41      */
42     CharsetMBCS.UConverterMBCSTable mbcs;
43 
UConverterSharedData(UConverterStaticData staticData_)44     UConverterSharedData(UConverterStaticData staticData_)
45     {
46         mbcs = new CharsetMBCS.UConverterMBCSTable();
47         staticData = staticData_;
48     }
49 
50     /**
51      * UConverterImpl contains all the data and functions for a converter type.
52      * Its function pointers work much like a C++ vtable. Many converter types
53      * need to define only a subset of the functions; when a function pointer is
54      * NULL, then a default action will be performed.
55      *
56      * Every converter type must implement toUnicode, fromUnicode, and
57      * getNextUChar, otherwise the converter may crash. Every converter type
58      * that has variable-length codepage sequences should also implement
59      * toUnicodeWithOffsets and fromUnicodeWithOffsets for correct offset
60      * handling. All other functions may or may not be implemented - it depends
61      * only on whether the converter type needs them.
62      *
63      * When open() fails, then close() will be called, if present.
64      */
65 /* class UConverterImpl {
66     UConverterType type;
67     UConverterToUnicode toUnicode;
68     protected void doToUnicode(UConverterToUnicodeArgs args, int[] pErrorCode)
69     {
70     }
71 
72      final void toUnicode(UConverterToUnicodeArgs args, int[] pErrorCode)
73     {
74         doToUnicode(args, pErrorCode);
75     }
76 
77     //UConverterFromUnicode fromUnicode;
78     protected void doFromUnicode(UConverterFromUnicodeArgs args, int[] pErrorCode)
79     {
80     }
81 
82      final void fromUnicode(UConverterFromUnicodeArgs args, int[] pErrorCode)
83     {
84         doFromUnicode(args, pErrorCode);
85     }
86 
87     protected int doGetNextUChar(UConverterToUnicodeArgs args, int[] pErrorCode)
88     {
89         return 0;
90     }
91 
92     //UConverterGetNextUChar getNextUChar;
93      final int getNextUChar(UConverterToUnicodeArgs args, int[] pErrorCode)
94     {
95         return doGetNextUChar(args, pErrorCode);
96     }
97 
98     // interface UConverterImplLoadable extends UConverterImpl
99     protected void doLoad(UConverterLoadArgs pArgs, short[] raw, int[] pErrorCode)
100     {
101     }
102 
103     protected void doUnload()
104     {
105     }
106 
107     // interface UConverterImplOpenable extends UConverterImpl
108     protected void doOpen(UConverter cnv, String name, String locale, long options, int[] pErrorCode)
109     {
110     }
111 
112     //UConverterOpen open;
113      final void open(UConverter cnv, String name, String locale, long options, int[] pErrorCode)
114     {
115         doOpen(cnv, name, locale, options, pErrorCode);
116     }
117 
118     protected void doClose(UConverter cnv)
119     {
120     }
121 
122     //UConverterClose close;
123      final void close(UConverter cnv)
124     {
125         doClose(cnv);
126     }
127 
128     protected void doReset(UConverter cnv, int choice)
129     {
130     }
131 
132     //typedef void (*UConverterReset) (UConverter *cnv, UConverterResetChoice choice);
133     //UConverterReset reset;
134      final void reset(UConverter cnv, int choice)
135     {
136         doReset(cnv, choice);
137     }
138 
139     // interface UConverterImplVariableLength extends UConverterImpl
140     protected void doToUnicodeWithOffsets(UConverterToUnicodeArgs args, int[] pErrorCode)
141     {
142     }
143 
144     //UConverterToUnicode toUnicodeWithOffsets;
145      final void toUnicodeWithOffsets(UConverterToUnicodeArgs args, int[] pErrorCode)
146     {
147         doToUnicodeWithOffsets(args, pErrorCode);
148     }
149 
150     protected void doFromUnicodeWithOffsets(UConverterFromUnicodeArgs args, int[] pErrorCode)
151     {
152     }
153 
154     //UConverterFromUnicode fromUnicodeWithOffsets;
155      final void fromUnicodeWithOffsets(UConverterFromUnicodeArgs args, int[] pErrorCode)
156     {
157         doFromUnicodeWithOffsets(args, pErrorCode);
158     }
159 
160     // interface UConverterImplMisc extends UConverterImpl
161     protected void doGetStarters(UConverter converter, boolean starters[], int[] pErrorCode)
162     {
163     }
164 
165     //UConverterGetStarters getStarters;
166      final void getStarters(UConverter converter, boolean starters[], int[] pErrorCode)
167     {
168         doGetStarters(converter, starters, pErrorCode);
169     }
170 
171     protected String doGetName(UConverter cnv)
172     {
173         return "";
174     }
175 
176     //UConverterGetName getName;
177      final String getName(UConverter cnv)
178     {
179         return doGetName(cnv);
180     }
181 
182     protected void doWriteSub(UConverterFromUnicodeArgs pArgs, long offsetIndex, int[] pErrorCode)
183     {
184     }
185 
186     //UConverterWriteSub writeSub;
187      final void writeSub(UConverterFromUnicodeArgs pArgs, long offsetIndex, int[] pErrorCode)
188     {
189         doWriteSub(pArgs, offsetIndex, pErrorCode);
190     }
191 
192     protected UConverter doSafeClone(UConverter cnv, byte[] stackBuffer, int[] pBufferSize, int[] status)
193     {
194         return new UConverter();
195     }
196 
197     //UConverterSafeClone safeClone;
198      final UConverter  safeClone(UConverter cnv, byte[] stackBuffer, int[] pBufferSize, int[] status)
199     {
200         return doSafeClone(cnv, stackBuffer, pBufferSize, status);
201     }
202 
203     protected void doGetUnicodeSet(UConverter cnv, UnicodeSet /*USetAdder* / sa, int /*UConverterUnicodeSet* / which, int[] pErrorCode)
204     {
205     }
206 
207     //UConverterGetUnicodeSet getUnicodeSet;
208     // final void getUnicodeSet(UConverter cnv, UnicodeSet /*USetAdder* / sa, int /*UConverterUnicodeSet* / which, int[] pErrorCode)
209     //{
210     //  doGetUnicodeSet(cnv, sa, which, pErrorCode);
211     //}
212 
213     //}
214 
215     static final String DATA_TYPE = "cnv";
216     private static final int CNV_DATA_BUFFER_SIZE = 25000;
217      static final int sizeofUConverterSharedData = 100;
218 
219     //static UDataMemoryIsAcceptable isCnvAcceptable;
220 
221     /**
222      * Load a non-algorithmic converter.
223      * If pkg==NULL, then this function must be called inside umtx_lock(&cnvCacheMutex).
224 
225     // UConverterSharedData * load(UConverterLoadArgs *pArgs, UErrorCode *err)
226      static final UConverterSharedData load(UConverterLoadArgs pArgs, int[] err)
227     {
228         UConverterSharedData mySharedConverterData = null;
229 
230         if(err == null || ErrorCode.isFailure(err[0])) {
231             return null;
232         }
233 
234         if(pArgs.pkg != null && pArgs.pkg.length() != 0) {
235              application-provided converters are not currently cached
236             return UConverterSharedData.createConverterFromFile(pArgs, err);
237         }
238 
239         //agljport:fix mySharedConverterData = getSharedConverterData(pArgs.name);
240         if (mySharedConverterData == null)
241         {
242             Not cached, we need to stream it in from file
243             mySharedConverterData = UConverterSharedData.createConverterFromFile(pArgs, err);
244             if (ErrorCode.isFailure(err[0]) || (mySharedConverterData == null))
245             {
246                 return null;
247             }
248             else
249             {
250                  share it with other library clients
251                 //agljport:fix shareConverterData(mySharedConverterData);
252             }
253         }
254         else
255         {
256              The data for this converter was already in the cache.
257              Update the reference counter on the shared data: one more client
258             mySharedConverterData.referenceCounter++;
259         }
260 
261         return mySharedConverterData;
262     }
263 
264     Takes an alias name gets an actual converter file name
265      *goes to disk and opens it.
266      *allocates the memory and returns a new UConverter object
267 
268     //static UConverterSharedData *createConverterFromFile(UConverterLoadArgs *pArgs, UErrorCode * err)
269      static final UConverterSharedData createConverterFromFile(UConverterLoadArgs pArgs, int[] err)
270     {
271         UDataMemory data = null;
272         UConverterSharedData sharedData = null;
273 
274         //agljport:todo UTRACE_ENTRY_OC(UTRACE_LOAD);
275 
276         if (err == null || ErrorCode.isFailure(err[0])) {
277             //agljport:todo UTRACE_EXIT_STATUS(*err);
278             return null;
279         }
280 
281         //agljport:todo UTRACE_DATA2(UTRACE_OPEN_CLOSE, "load converter %s from package %s", pArgs->name, pArgs->pkg);
282 
283         //agljport:fix data = udata_openChoice(pArgs.pkgArray, DATA_TYPE.getBytes(), pArgs.name, isCnvAcceptable, null, err);
284         if(ErrorCode.isFailure(err[0]))
285         {
286             //agljport:todo UTRACE_EXIT_STATUS(*err);
287             return null;
288         }
289 
290         sharedData = data_unFlattenClone(pArgs, data, err);
291         if(ErrorCode.isFailure(err[0]))
292         {
293             //agljport:fix udata_close(data);
294             //agljport:todo UTRACE_EXIT_STATUS(*err);
295             return null;
296         }
297 
298 
299          * TODO Store pkg in a field in the shared data so that delta-only converters
300          * can load base converters from the same package.
301          * If the pkg name is longer than the field, then either do not load the converter
302          * in the first place, or just set the pkg field to "".
303 
304 
305         return sharedData;
306     }
307 */
308 
309     /*
310      * returns a converter type from a string
311      */
312     /*   static final UConverterSharedData getAlgorithmicTypeFromName(String realName)
313     {
314         long mid, start, limit;
315         long lastMid;
316         int result;
317         StringBuffer strippedName = new StringBuffer(UConverterConstants.MAX_CONVERTER_NAME_LENGTH);
318 
319         // Lower case and remove ignoreable characters.
320         UConverterAlias.stripForCompare(strippedName, realName);
321 
322         // do a binary search for the alias
323         start = 0;
324         limit = cnvNameType.length;
325         mid = limit;
326         lastMid = -1;
327 
328         for (;;) {
329             mid = (long)((start + limit) / 2);
330             if (lastMid == mid) {   // Have we moved?
331                 break;  // We haven't moved, and it wasn't found.
332             }
333             lastMid = mid;
334             result = strippedName.substring(0).compareTo(cnvNameType[(int)mid].name);
335 
336             if (result < 0) {
337                 limit = mid;
338             } else if (result > 0) {
339                 start = mid;
340             } else {
341                 return converterData[cnvNameType[(int)mid].type];
342             }
343         }
344 
345         return null;
346     }*/
347 
348     /*
349      * Enum for specifying basic types of converters
350      */
351     static final class UConverterType {
352         static final int UNSUPPORTED_CONVERTER = -1;
353         static final int SBCS = 0;
354         static final int DBCS = 1;
355         static final int MBCS = 2;
356         static final int LATIN_1 = 3;
357         static final int UTF8 = 4;
358         static final int UTF16_BigEndian = 5;
359         static final int UTF16_LittleEndian = 6;
360         static final int UTF32_BigEndian = 7;
361         static final int UTF32_LittleEndian = 8;
362         static final int EBCDIC_STATEFUL = 9;
363         static final int ISO_2022 = 10;
364         static final int LMBCS_1 = 11;
365         static final int LMBCS_2 = LMBCS_1 + 1; // 12
366         static final int LMBCS_3 = LMBCS_2 + 1; // 13
367         static final int LMBCS_4 = LMBCS_3 + 1; // 14
368         static final int LMBCS_5 = LMBCS_4 + 1; // 15
369         static final int LMBCS_6 = LMBCS_5 + 1; // 16
370         static final int LMBCS_8 = LMBCS_6 + 1; // 17
371         static final int LMBCS_11 = LMBCS_8 + 1; // 18
372         static final int LMBCS_16 = LMBCS_11 + 1; // 19
373         static final int LMBCS_17 = LMBCS_16 + 1; // 20
374         static final int LMBCS_18 = LMBCS_17 + 1; // 21
375         static final int LMBCS_19 = LMBCS_18 + 1; // 22
376         static final int LMBCS_LAST = LMBCS_19; // 22
377         static final int HZ = LMBCS_LAST + 1; // 23
378         static final int SCSU = HZ + 1; // 24
379         static final int ISCII = SCSU + 1; // 25
380         static final int US_ASCII = ISCII + 1; // 26
381         static final int UTF7 = US_ASCII + 1; // 27
382         static final int BOCU1 = UTF7 + 1; // 28
383         static final int UTF16 = BOCU1 + 1; // 29
384         static final int UTF32 = UTF16 + 1; // 30
385         static final int CESU8 = UTF32 + 1; // 31
386         static final int IMAP_MAILBOX = CESU8 + 1; // 32
387 
388         // Number of converter types for which we have conversion routines.
389         static final int NUMBER_OF_SUPPORTED_CONVERTER_TYPES = IMAP_MAILBOX + 1;
390     }
391 
392     /**
393      * Enum for specifying which platform a converter ID refers to. The use of
394      * platform/CCSID is not recommended. See openCCSID().
395      */
396     static final class UConverterPlatform {
397         static final int UNKNOWN = -1;
398         static final int IBM = 0;
399     }
400 
401     // static UConverterSharedData[] converterData;
402     /*  static class cnvNameTypeClass {
403       String name;
404         int type;
405         cnvNameTypeClass(String name_, int type_) { name = name_; type = type_; }
406     }
407 
408     static cnvNameTypeClass cnvNameType[];*/
409 
410 
411     static final String DATA_TYPE = "cnv";
412     //static final int CNV_DATA_BUFFER_SIZE = 25000;
413     //static final int SIZE_OF_UCONVERTER_SHARED_DATA = 228;
414 
415 }
416