1 /**************************************************************************
2 * © 2016 and later: Unicode, Inc. and others.
3 * License & terms of use: http://www.unicode.org/copyright.html#License
4 **************************************************************************
5 **************************************************************************
7 * Copyright (c) 1999-2007, International Business Machines Corporation and
8 * others. All Rights Reserved.
9 **************************************************************************/
11 #include "unicode/utypes.h"
12 #include "unicode/ucnv.h"
18 #define DEBUG_TMI 0 /* set to 1 for Too Much Information (TMI) */
20 U_CAPI FromUFLAGContext
* U_EXPORT2
flagCB_fromU_openContext()
22 FromUFLAGContext
*ctx
;
24 ctx
= (FromUFLAGContext
*) malloc(sizeof(FromUFLAGContext
));
26 ctx
->subCallback
= NULL
;
27 ctx
->subContext
= NULL
;
33 U_CAPI
void U_EXPORT2
flagCB_fromU(
35 UConverterFromUnicodeArgs
*fromUArgs
,
36 const UChar
* codeUnits
,
39 UConverterCallbackReason reason
,
42 /* First step - based on the reason code, take action */
44 if(reason
== UCNV_UNASSIGNED
) { /* whatever set should be trapped here */
45 ((FromUFLAGContext
*)context
)->flag
= TRUE
;
48 if(reason
== UCNV_CLONE
) {
49 /* The following is the recommended way to implement UCNV_CLONE
51 UConverterFromUCallback saveCallback
;
52 const void *saveContext
;
53 FromUFLAGContext
*old
, *cloned
;
54 UErrorCode subErr
= U_ZERO_ERROR
;
57 printf("*** FLAGCB: cloning %p ***\n", context
);
59 old
= (FromUFLAGContext
*)context
;
60 cloned
= flagCB_fromU_openContext();
62 memcpy(cloned
, old
, sizeof(FromUFLAGContext
));
65 printf("%p: my subcb=%p:%p\n", old
, old
->subCallback
,
67 printf("%p: cloned subcb=%p:%p\n", cloned
, cloned
->subCallback
,
71 /* We need to get the sub CB to handle cloning,
72 * so we have to set up the following, temporarily:
74 * - Set the callback+context to the sub of this (flag) cb
75 * - preserve the current cb+context, it could be anything
78 * CNV -> FLAG -> subcb -> ...
83 * The chain from 'something' on is saved, and will be restored
84 * at the end of this block.
88 ucnv_setFromUCallBack(fromUArgs
->converter
,
95 if( cloned
->subCallback
!= NULL
) {
96 /* Now, call the sub callback if present */
97 cloned
->subCallback(cloned
->subContext
, fromUArgs
, codeUnits
,
98 length
, codePoint
, reason
, err
);
101 ucnv_setFromUCallBack(fromUArgs
->converter
,
102 saveCallback
, /* Us */
103 cloned
, /* new context */
104 &cloned
->subCallback
, /* IMPORTANT! Accept any change in CB or context */
108 if(U_FAILURE(subErr
)) {
113 /* process other reasons here if need be */
115 /* Always call the subCallback if present */
116 if(((FromUFLAGContext
*)context
)->subCallback
!= NULL
&&
117 reason
!= UCNV_CLONE
) {
118 ((FromUFLAGContext
*)context
)->subCallback( ((FromUFLAGContext
*)context
)->subContext
,
127 /* cleanup - free the memory AFTER calling the sub CB */
128 if(reason
== UCNV_CLOSE
) {
129 free((void*)context
);
133 /* Debugging callback, just outputs what happens */
135 /* Test safe clone callback */
137 static uint32_t debugCB_nextSerial()
139 static uint32_t n
= 1;
144 static void debugCB_print_log(debugCBContext
*q
, const char *name
)
147 printf("debugCBontext: %s is NULL!!\n", name
);
149 if(q
->magic
!= 0xC0FFEE) {
150 fprintf(stderr
, "debugCBContext: %p:%d's magic is %x, supposed to be 0xC0FFEE\n",
151 q
,q
->serial
, q
->magic
);
153 printf("debugCBContext %p:%d=%s - magic %x\n",
154 q
, q
->serial
, name
, q
->magic
);
158 static debugCBContext
*debugCB_clone(debugCBContext
*ctx
)
160 debugCBContext
*newCtx
;
161 newCtx
= malloc(sizeof(debugCBContext
));
163 newCtx
->serial
= debugCB_nextSerial();
164 newCtx
->magic
= 0xC0FFEE;
166 newCtx
->subCallback
= ctx
->subCallback
;
167 newCtx
->subContext
= ctx
->subContext
;
170 printf("debugCB_clone: %p:%d -> new context %p:%d\n", ctx
, ctx
->serial
, newCtx
, newCtx
->serial
);
176 void debugCB_fromU(const void *context
,
177 UConverterFromUnicodeArgs
*fromUArgs
,
178 const UChar
* codeUnits
,
181 UConverterCallbackReason reason
,
184 debugCBContext
*ctx
= (debugCBContext
*)context
;
185 /*UConverterFromUCallback junkFrom;*/
188 printf("debugCB_fromU: Context %p:%d called, reason %d on cnv %p [err=%s]\n", ctx
, ctx
->serial
, reason
, fromUArgs
->converter
, u_errorName(*err
));
191 if(ctx
->magic
!= 0xC0FFEE) {
192 fprintf(stderr
, "debugCB_fromU: Context %p:%d magic is 0x%x should be 0xC0FFEE.\n", ctx
,ctx
->serial
, ctx
->magic
);
196 if(reason
== UCNV_CLONE
) {
197 /* see comments in above flagCB clone code */
199 UConverterFromUCallback saveCallback
;
200 const void *saveContext
;
201 debugCBContext
*cloned
;
202 UErrorCode subErr
= U_ZERO_ERROR
;
206 printf("debugCB_fromU: cloning..\n");
208 cloned
= debugCB_clone(ctx
);
211 fprintf(stderr
, "debugCB_fromU: internal clone failed on %p\n", ctx
);
212 *err
= U_MEMORY_ALLOCATION_ERROR
;
216 ucnv_setFromUCallBack(fromUArgs
->converter
,
223 if( cloned
->subCallback
!= NULL
) {
225 printf("debugCB_fromU:%p calling subCB %p\n", ctx
, cloned
->subCallback
);
227 /* call subCB if present */
228 cloned
->subCallback(cloned
->subContext
, fromUArgs
, codeUnits
,
229 length
, codePoint
, reason
, err
);
231 printf("debugCB_fromU:%p, NOT calling subCB, it's NULL\n", ctx
);
234 /* set back callback */
235 ucnv_setFromUCallBack(fromUArgs
->converter
,
236 saveCallback
, /* Us */
237 cloned
, /* new context */
238 &cloned
->subCallback
, /* IMPORTANT! Accept any change in CB or context */
242 if(U_FAILURE(subErr
)) {
247 /* process other reasons here */
249 /* always call subcb if present */
250 if(ctx
->subCallback
!= NULL
&& reason
!= UCNV_CLONE
) {
251 ctx
->subCallback(ctx
->subContext
,
260 if(reason
== UCNV_CLOSE
) {
262 printf("debugCB_fromU: Context %p:%d closing\n", ctx
, ctx
->serial
);
268 printf("debugCB_fromU: leaving cnv %p, ctx %p: err %s\n", fromUArgs
->converter
, ctx
, u_errorName(*err
));
272 debugCBContext
*debugCB_openContext()
276 ctx
= malloc(sizeof(debugCBContext
));
279 ctx
->magic
= 0xC0FFEE;
280 ctx
->serial
= debugCB_nextSerial();
281 ctx
->subCallback
= NULL
;
282 ctx
->subContext
= NULL
;
285 fprintf(stderr
, "debugCB:openContext opened[%p] = serial #%d\n", ctx
, ctx
->serial
);