1 /********************************************************************
3 * Copyright (c) 1999-2002, International Business Machines Corporation and
4 * others. All Rights Reserved.
5 ********************************************************************/
7 #include "unicode/utypes.h"
8 #include "unicode/ucnv.h"
14 #define DEBUG_TMI 0 /* set to 1 for Too Much Information (TMI) */
16 U_CAPI FromUFLAGContext
* U_EXPORT2
flagCB_fromU_openContext()
18 FromUFLAGContext
*ctx
;
20 ctx
= (FromUFLAGContext
*) malloc(sizeof(FromUFLAGContext
));
22 ctx
->subCallback
= NULL
;
23 ctx
->subContext
= NULL
;
29 U_CAPI
void U_EXPORT2
flagCB_fromU(
31 UConverterFromUnicodeArgs
*fromUArgs
,
32 const UChar
* codeUnits
,
35 UConverterCallbackReason reason
,
38 /* First step - based on the reason code, take action */
40 if(reason
== UCNV_UNASSIGNED
) { /* whatever set should be trapped here */
41 ((FromUFLAGContext
*)context
)->flag
= TRUE
;
44 if(reason
== UCNV_CLONE
) {
45 /* The following is the recommended way to implement UCNV_CLONE
47 UConverterFromUCallback saveCallback
;
49 FromUFLAGContext
*old
, *cloned
;
50 UErrorCode subErr
= U_ZERO_ERROR
;
53 printf("*** FLAGCB: cloning %p ***\n", context
);
55 old
= (FromUFLAGContext
*)context
;
56 cloned
= flagCB_fromU_openContext();
58 memcpy(cloned
, old
, sizeof(FromUFLAGContext
));
61 printf("%p: my subcb=%p:%p\n", old
, old
->subCallback
,
63 printf("%p: cloned subcb=%p:%p\n", cloned
, cloned
->subCallback
,
67 /* We need to get the sub CB to handle cloning,
68 * so we have to set up the following, temporarily:
70 * - Set the callback+context to the sub of this (flag) cb
71 * - preserve the current cb+context, it could be anything
74 * CNV -> FLAG -> subcb -> ...
79 * The chain from 'something' on is saved, and will be restored
80 * at the end of this block.
84 ucnv_setFromUCallBack(fromUArgs
->converter
,
91 if( cloned
->subCallback
!= NULL
) {
92 /* Now, call the sub callback if present */
93 cloned
->subCallback(cloned
->subContext
, fromUArgs
, codeUnits
,
94 length
, codePoint
, reason
, err
);
97 ucnv_setFromUCallBack(fromUArgs
->converter
,
98 saveCallback
, /* Us */
99 cloned
, /* new context */
100 &cloned
->subCallback
, /* IMPORTANT! Accept any change in CB or context */
104 if(U_FAILURE(subErr
)) {
109 /* process other reasons here if need be */
111 /* Always call the subCallback if present */
112 if(((FromUFLAGContext
*)context
)->subCallback
!= NULL
&&
113 reason
!= UCNV_CLONE
) {
114 ((FromUFLAGContext
*)context
)->subCallback( ((FromUFLAGContext
*)context
)->subContext
,
123 /* cleanup - free the memory AFTER calling the sub CB */
124 if(reason
== UCNV_CLOSE
) {
125 free((void*)context
);
129 /* Debugging callback, just outputs what happens */
131 /* Test safe clone callback */
133 static uint32_t debugCB_nextSerial()
135 static uint32_t n
= 1;
140 static void debugCB_print_log(debugCBContext
*q
, const char *name
)
143 printf("debugCBontext: %s is NULL!!\n", name
);
145 if(q
->magic
!= 0xC0FFEE) {
146 fprintf(stderr
, "debugCBContext: %p:%d's magic is %x, supposed to be 0xC0FFEE\n",
147 q
,q
->serial
, q
->magic
);
149 printf("debugCBContext %p:%d=%s - magic %x\n",
150 q
, q
->serial
, name
, q
->magic
);
154 static debugCBContext
*debugCB_clone(debugCBContext
*ctx
)
156 debugCBContext
*newCtx
;
157 newCtx
= malloc(sizeof(debugCBContext
));
159 newCtx
->serial
= debugCB_nextSerial();
160 newCtx
->magic
= 0xC0FFEE;
162 newCtx
->subCallback
= ctx
->subCallback
;
163 newCtx
->subContext
= ctx
->subContext
;
166 printf("debugCB_clone: %p:%d -> new context %p:%d\n", ctx
, ctx
->serial
, newCtx
, newCtx
->serial
);
172 void debugCB_fromU(const void *context
,
173 UConverterFromUnicodeArgs
*fromUArgs
,
174 const UChar
* codeUnits
,
177 UConverterCallbackReason reason
,
180 debugCBContext
*ctx
= (debugCBContext
*)context
;
181 /*UConverterFromUCallback junkFrom;*/
184 printf("debugCB_fromU: Context %p:%d called, reason %d on cnv %p [err=%s]\n", ctx
, ctx
->serial
, reason
, fromUArgs
->converter
, u_errorName(*err
));
187 if(ctx
->magic
!= 0xC0FFEE) {
188 fprintf(stderr
, "debugCB_fromU: Context %p:%d magic is 0x%x should be 0xC0FFEE.\n", ctx
,ctx
->serial
, ctx
->magic
);
192 if(reason
== UCNV_CLONE
) {
193 /* see comments in above flagCB clone code */
195 UConverterFromUCallback saveCallback
;
197 debugCBContext
*cloned
;
198 UErrorCode subErr
= U_ZERO_ERROR
;
202 printf("debugCB_fromU: cloning..\n");
204 cloned
= debugCB_clone(ctx
);
207 fprintf(stderr
, "debugCB_fromU: internal clone failed on %p\n", ctx
);
208 *err
= U_MEMORY_ALLOCATION_ERROR
;
212 ucnv_setFromUCallBack(fromUArgs
->converter
,
219 if( cloned
->subCallback
!= NULL
) {
221 printf("debugCB_fromU:%p calling subCB %p\n", ctx
, cloned
->subCallback
);
223 /* call subCB if present */
224 cloned
->subCallback(cloned
->subContext
, fromUArgs
, codeUnits
,
225 length
, codePoint
, reason
, err
);
227 printf("debugCB_fromU:%p, NOT calling subCB, it's NULL\n", ctx
);
230 /* set back callback */
231 ucnv_setFromUCallBack(fromUArgs
->converter
,
232 saveCallback
, /* Us */
233 cloned
, /* new context */
234 &cloned
->subCallback
, /* IMPORTANT! Accept any change in CB or context */
238 if(U_FAILURE(subErr
)) {
243 /* process other reasons here */
245 /* always call subcb if present */
246 if(ctx
->subCallback
!= NULL
&& reason
!= UCNV_CLONE
) {
247 ctx
->subCallback(ctx
->subContext
,
256 if(reason
== UCNV_CLOSE
) {
258 printf("debugCB_fromU: Context %p:%d closing\n", ctx
, ctx
->serial
);
264 printf("debugCB_fromU: leaving cnv %p, ctx %p: err %s\n", fromUArgs
->converter
, ctx
, u_errorName(*err
));
268 debugCBContext
*debugCB_openContext()
272 ctx
= malloc(sizeof(debugCBContext
));
275 ctx
->magic
= 0xC0FFEE;
276 ctx
->serial
= debugCB_nextSerial();
277 ctx
->subCallback
= NULL
;
278 ctx
->subContext
= NULL
;
281 fprintf(stderr
, "debugCB:openContext opened[%p] = serial #%d\n", ctx
, ctx
->serial
);