]> git.saurik.com Git - apple/icu.git/blame - icuSources/samples/ucnv/flagcb.c
ICU-62141.0.1.tar.gz
[apple/icu.git] / icuSources / samples / ucnv / flagcb.c
CommitLineData
f3c0d7a5
A
1/**************************************************************************
2 * © 2016 and later: Unicode, Inc. and others.
3 * License & terms of use: http://www.unicode.org/copyright.html#License
4 **************************************************************************
5 **************************************************************************
b75a7d8f 6 * COPYRIGHT:
46f4442e 7 * Copyright (c) 1999-2007, International Business Machines Corporation and
b75a7d8f 8 * others. All Rights Reserved.
f3c0d7a5 9 **************************************************************************/
b75a7d8f
A
10
11#include "unicode/utypes.h"
12#include "unicode/ucnv.h"
13#include "flagcb.h"
14#include <string.h>
15#include <stdlib.h>
16#include <stdio.h>
17
18#define DEBUG_TMI 0 /* set to 1 for Too Much Information (TMI) */
19
20U_CAPI FromUFLAGContext* U_EXPORT2 flagCB_fromU_openContext()
21{
22 FromUFLAGContext *ctx;
23
24 ctx = (FromUFLAGContext*) malloc(sizeof(FromUFLAGContext));
25
26 ctx->subCallback = NULL;
27 ctx->subContext = NULL;
28 ctx->flag = FALSE;
29
30 return ctx;
31}
32
33U_CAPI void U_EXPORT2 flagCB_fromU(
34 const void *context,
35 UConverterFromUnicodeArgs *fromUArgs,
36 const UChar* codeUnits,
37 int32_t length,
38 UChar32 codePoint,
39 UConverterCallbackReason reason,
40 UErrorCode * err)
41{
42 /* First step - based on the reason code, take action */
43
44 if(reason == UCNV_UNASSIGNED) { /* whatever set should be trapped here */
45 ((FromUFLAGContext*)context)->flag = TRUE;
46 }
47
48 if(reason == UCNV_CLONE) {
49 /* The following is the recommended way to implement UCNV_CLONE
50 in a callback. */
51 UConverterFromUCallback saveCallback;
46f4442e 52 const void *saveContext;
b75a7d8f
A
53 FromUFLAGContext *old, *cloned;
54 UErrorCode subErr = U_ZERO_ERROR;
55
56#if DEBUG_TMI
57 printf("*** FLAGCB: cloning %p ***\n", context);
58#endif
59 old = (FromUFLAGContext*)context;
60 cloned = flagCB_fromU_openContext();
61
62 memcpy(cloned, old, sizeof(FromUFLAGContext));
63
64#if DEBUG_TMI
65 printf("%p: my subcb=%p:%p\n", old, old->subCallback,
66 old->subContext);
67 printf("%p: cloned subcb=%p:%p\n", cloned, cloned->subCallback,
68 cloned->subContext);
69#endif
70
71 /* We need to get the sub CB to handle cloning,
72 * so we have to set up the following, temporarily:
73 *
74 * - Set the callback+context to the sub of this (flag) cb
75 * - preserve the current cb+context, it could be anything
76 *
77 * Before:
78 * CNV -> FLAG -> subcb -> ...
79 *
80 * After:
81 * CNV -> subcb -> ...
82 *
83 * The chain from 'something' on is saved, and will be restored
84 * at the end of this block.
85 *
86 */
87
88 ucnv_setFromUCallBack(fromUArgs->converter,
89 cloned->subCallback,
90 cloned->subContext,
91 &saveCallback,
92 &saveContext,
93 &subErr);
94
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);
99 }
100
101 ucnv_setFromUCallBack(fromUArgs->converter,
102 saveCallback, /* Us */
103 cloned, /* new context */
104 &cloned->subCallback, /* IMPORTANT! Accept any change in CB or context */
105 &cloned->subContext,
106 &subErr);
107
108 if(U_FAILURE(subErr)) {
109 *err = subErr;
110 }
111 }
112
113 /* process other reasons here if need be */
114
115 /* Always call the subCallback if present */
116 if(((FromUFLAGContext*)context)->subCallback != NULL &&
117 reason != UCNV_CLONE) {
118 ((FromUFLAGContext*)context)->subCallback( ((FromUFLAGContext*)context)->subContext,
119 fromUArgs,
120 codeUnits,
121 length,
122 codePoint,
123 reason,
124 err);
125 }
126
127 /* cleanup - free the memory AFTER calling the sub CB */
128 if(reason == UCNV_CLOSE) {
129 free((void*)context);
130 }
131}
132
133/* Debugging callback, just outputs what happens */
134
135/* Test safe clone callback */
136
137static uint32_t debugCB_nextSerial()
138{
139 static uint32_t n = 1;
140
141 return (n++);
142}
143
144static void debugCB_print_log(debugCBContext *q, const char *name)
145{
146 if(q==NULL) {
147 printf("debugCBontext: %s is NULL!!\n", name);
148 } else {
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);
152 }
153 printf("debugCBContext %p:%d=%s - magic %x\n",
154 q, q->serial, name, q->magic);
155 }
156}
157
158static debugCBContext *debugCB_clone(debugCBContext *ctx)
159{
160 debugCBContext *newCtx;
161 newCtx = malloc(sizeof(debugCBContext));
162
163 newCtx->serial = debugCB_nextSerial();
164 newCtx->magic = 0xC0FFEE;
165
166 newCtx->subCallback = ctx->subCallback;
167 newCtx->subContext = ctx->subContext;
168
169#if DEBUG_TMI
170 printf("debugCB_clone: %p:%d -> new context %p:%d\n", ctx, ctx->serial, newCtx, newCtx->serial);
171#endif
172
173 return newCtx;
174}
175
176void debugCB_fromU(const void *context,
177 UConverterFromUnicodeArgs *fromUArgs,
178 const UChar* codeUnits,
179 int32_t length,
180 UChar32 codePoint,
181 UConverterCallbackReason reason,
182 UErrorCode * err)
183{
184 debugCBContext *ctx = (debugCBContext*)context;
185 /*UConverterFromUCallback junkFrom;*/
186
187#if DEBUG_TMI
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));
189#endif
190
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);
193 return;
194 }
195
196 if(reason == UCNV_CLONE) {
197 /* see comments in above flagCB clone code */
198
199 UConverterFromUCallback saveCallback;
46f4442e 200 const void *saveContext;
b75a7d8f
A
201 debugCBContext *cloned;
202 UErrorCode subErr = U_ZERO_ERROR;
203
204 /* "recreate" it */
205#if DEBUG_TMI
206 printf("debugCB_fromU: cloning..\n");
207#endif
208 cloned = debugCB_clone(ctx);
209
210 if(cloned == NULL) {
211 fprintf(stderr, "debugCB_fromU: internal clone failed on %p\n", ctx);
212 *err = U_MEMORY_ALLOCATION_ERROR;
213 return;
214 }
215
216 ucnv_setFromUCallBack(fromUArgs->converter,
217 cloned->subCallback,
218 cloned->subContext,
219 &saveCallback,
220 &saveContext,
221 &subErr);
222
223 if( cloned->subCallback != NULL) {
224#if DEBUG_TMI
225 printf("debugCB_fromU:%p calling subCB %p\n", ctx, cloned->subCallback);
226#endif
227 /* call subCB if present */
228 cloned->subCallback(cloned->subContext, fromUArgs, codeUnits,
229 length, codePoint, reason, err);
230 } else {
231 printf("debugCB_fromU:%p, NOT calling subCB, it's NULL\n", ctx);
232 }
233
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 */
239 &cloned->subContext,
240 &subErr);
241
242 if(U_FAILURE(subErr)) {
243 *err = subErr;
244 }
245 }
246
247 /* process other reasons here */
248
249 /* always call subcb if present */
250 if(ctx->subCallback != NULL && reason != UCNV_CLONE) {
251 ctx->subCallback(ctx->subContext,
252 fromUArgs,
253 codeUnits,
254 length,
255 codePoint,
256 reason,
257 err);
258 }
259
260 if(reason == UCNV_CLOSE) {
261#if DEBUG_TMI
262 printf("debugCB_fromU: Context %p:%d closing\n", ctx, ctx->serial);
263#endif
264 free(ctx);
265 }
266
267#if DEBUG_TMI
268 printf("debugCB_fromU: leaving cnv %p, ctx %p: err %s\n", fromUArgs->converter, ctx, u_errorName(*err));
269#endif
270}
271
272debugCBContext *debugCB_openContext()
273{
274 debugCBContext *ctx;
275
276 ctx = malloc(sizeof(debugCBContext));
277
278 if(ctx != NULL) {
279 ctx->magic = 0xC0FFEE;
280 ctx->serial = debugCB_nextSerial();
281 ctx->subCallback = NULL;
282 ctx->subContext = NULL;
283
284#if DEBUG_TMI
285 fprintf(stderr, "debugCB:openContext opened[%p] = serial #%d\n", ctx, ctx->serial);
286#endif
287
288 }
289
290
291 return ctx;
292}