| Viewing file:  flagcb.c (8.97 KB)      -rw-r--r-- Select action/file-type:
 
  (+) |  (+) |  (+) | Code (+) | Session (+) |  (+) | SDB (+) |  (+) |  (+) |  (+) |  (+) |  (+) | 
 
/*************************************************************************** © 2016 and later: Unicode, Inc. and others.
 * License & terms of use: http://www.unicode.org/copyright.html#License
 **************************************************************************
 **************************************************************************
 * COPYRIGHT:
 * Copyright (c) 1999-2007, International Business Machines Corporation and
 * others. All Rights Reserved.
 **************************************************************************/
 
 #include "unicode/utypes.h"
 #include "unicode/ucnv.h"
 #include "flagcb.h"
 #include <string.h>
 #include <stdlib.h>
 #include <stdio.h>
 
 #define DEBUG_TMI 0  /* set to 1 for Too Much Information (TMI) */
 
 U_CAPI FromUFLAGContext* U_EXPORT2  flagCB_fromU_openContext()
 {
 FromUFLAGContext *ctx;
 
 ctx = (FromUFLAGContext*) malloc(sizeof(FromUFLAGContext));
 
 ctx->subCallback = NULL;
 ctx->subContext  = NULL;
 ctx->flag        = FALSE;
 
 return ctx;
 }
 
 U_CAPI void U_EXPORT2 flagCB_fromU(
 const void *context,
 UConverterFromUnicodeArgs *fromUArgs,
 const UChar* codeUnits,
 int32_t length,
 UChar32 codePoint,
 UConverterCallbackReason reason,
 UErrorCode * err)
 {
 /* First step - based on the reason code, take action */
 
 if(reason == UCNV_UNASSIGNED) { /* whatever set should be trapped here */
 ((FromUFLAGContext*)context)->flag = TRUE;
 }
 
 if(reason == UCNV_CLONE) {
 /* The following is the recommended way to implement UCNV_CLONE
 in a callback. */
 UConverterFromUCallback   saveCallback;
 const void *saveContext;
 FromUFLAGContext *old, *cloned;
 UErrorCode subErr = U_ZERO_ERROR;
 
 #if DEBUG_TMI
 printf("*** FLAGCB: cloning %p ***\n", context);
 #endif
 old = (FromUFLAGContext*)context;
 cloned = flagCB_fromU_openContext();
 
 memcpy(cloned, old, sizeof(FromUFLAGContext));
 
 #if DEBUG_TMI
 printf("%p: my subcb=%p:%p\n", old, old->subCallback,
 old->subContext);
 printf("%p: cloned subcb=%p:%p\n", cloned, cloned->subCallback,
 cloned->subContext);
 #endif
 
 /* We need to get the sub CB to handle cloning,
 * so we have to set up the following, temporarily:
 *
 *   - Set the callback+context to the sub of this (flag) cb
 *   - preserve the current cb+context, it could be anything
 *
 *   Before:
 *      CNV  ->   FLAG ->  subcb -> ...
 *
 *   After:
 *      CNV  ->   subcb -> ...
 *
 *    The chain from 'something' on is saved, and will be restored
 *   at the end of this block.
 *
 */
 
 ucnv_setFromUCallBack(fromUArgs->converter,
 cloned->subCallback,
 cloned->subContext,
 &saveCallback,
 &saveContext,
 &subErr);
 
 if( cloned->subCallback != NULL ) {
 /* Now, call the sub callback if present */
 cloned->subCallback(cloned->subContext, fromUArgs, codeUnits,
 length, codePoint, reason, err);
 }
 
 ucnv_setFromUCallBack(fromUArgs->converter,
 saveCallback,  /* Us */
 cloned,        /* new context */
 &cloned->subCallback,  /* IMPORTANT! Accept any change in CB or context */
 &cloned->subContext,
 &subErr);
 
 if(U_FAILURE(subErr)) {
 *err = subErr;
 }
 }
 
 /* process other reasons here if need be */
 
 /* Always call the subCallback if present */
 if(((FromUFLAGContext*)context)->subCallback != NULL &&
 reason != UCNV_CLONE) {
 ((FromUFLAGContext*)context)->subCallback(  ((FromUFLAGContext*)context)->subContext,
 fromUArgs,
 codeUnits,
 length,
 codePoint,
 reason,
 err);
 }
 
 /* cleanup - free the memory AFTER calling the sub CB */
 if(reason == UCNV_CLOSE) {
 free((void*)context);
 }
 }
 
 /* Debugging callback, just outputs what happens */
 
 /* Test safe clone callback */
 
 static uint32_t    debugCB_nextSerial()
 {
 static uint32_t n = 1;
 
 return (n++);
 }
 
 static void debugCB_print_log(debugCBContext *q, const char *name)
 {
 if(q==NULL) {
 printf("debugCBontext: %s is NULL!!\n", name);
 } else {
 if(q->magic != 0xC0FFEE) {
 fprintf(stderr, "debugCBContext: %p:%d's magic is %x, supposed to be 0xC0FFEE\n",
 q,q->serial, q->magic);
 }
 printf("debugCBContext %p:%d=%s - magic %x\n",
 q, q->serial, name, q->magic);
 }
 }
 
 static debugCBContext *debugCB_clone(debugCBContext *ctx)
 {
 debugCBContext *newCtx;
 newCtx = malloc(sizeof(debugCBContext));
 
 newCtx->serial = debugCB_nextSerial();
 newCtx->magic = 0xC0FFEE;
 
 newCtx->subCallback = ctx->subCallback;
 newCtx->subContext = ctx->subContext;
 
 #if DEBUG_TMI
 printf("debugCB_clone: %p:%d -> new context %p:%d\n", ctx, ctx->serial, newCtx, newCtx->serial);
 #endif
 
 return newCtx;
 }
 
 void debugCB_fromU(const void *context,
 UConverterFromUnicodeArgs *fromUArgs,
 const UChar* codeUnits,
 int32_t length,
 UChar32 codePoint,
 UConverterCallbackReason reason,
 UErrorCode * err)
 {
 debugCBContext *ctx = (debugCBContext*)context;
 /*UConverterFromUCallback junkFrom;*/
 
 #if DEBUG_TMI
 printf("debugCB_fromU: Context %p:%d called, reason %d on cnv %p [err=%s]\n", ctx, ctx->serial, reason, fromUArgs->converter, u_errorName(*err));
 #endif
 
 if(ctx->magic != 0xC0FFEE) {
 fprintf(stderr, "debugCB_fromU: Context %p:%d magic is 0x%x should be 0xC0FFEE.\n", ctx,ctx->serial, ctx->magic);
 return;
 }
 
 if(reason == UCNV_CLONE) {
 /* see comments in above flagCB clone code */
 
 UConverterFromUCallback   saveCallback;
 const void *saveContext;
 debugCBContext *cloned;
 UErrorCode subErr = U_ZERO_ERROR;
 
 /* "recreate" it */
 #if DEBUG_TMI
 printf("debugCB_fromU: cloning..\n");
 #endif
 cloned = debugCB_clone(ctx);
 
 if(cloned == NULL) {
 fprintf(stderr, "debugCB_fromU: internal clone failed on %p\n", ctx);
 *err = U_MEMORY_ALLOCATION_ERROR;
 return;
 }
 
 ucnv_setFromUCallBack(fromUArgs->converter,
 cloned->subCallback,
 cloned->subContext,
 &saveCallback,
 &saveContext,
 &subErr);
 
 if( cloned->subCallback != NULL) {
 #if DEBUG_TMI
 printf("debugCB_fromU:%p calling subCB %p\n", ctx, cloned->subCallback);
 #endif
 /* call subCB if present */
 cloned->subCallback(cloned->subContext, fromUArgs, codeUnits,
 length, codePoint, reason, err);
 } else {
 printf("debugCB_fromU:%p, NOT calling subCB, it's NULL\n", ctx);
 }
 
 /* set back callback */
 ucnv_setFromUCallBack(fromUArgs->converter,
 saveCallback,  /* Us */
 cloned,        /* new context */
 &cloned->subCallback,  /* IMPORTANT! Accept any change in CB or context */
 &cloned->subContext,
 &subErr);
 
 if(U_FAILURE(subErr)) {
 *err = subErr;
 }
 }
 
 /* process other reasons here */
 
 /* always call subcb if present */
 if(ctx->subCallback != NULL && reason != UCNV_CLONE) {
 ctx->subCallback(ctx->subContext,
 fromUArgs,
 codeUnits,
 length,
 codePoint,
 reason,
 err);
 }
 
 if(reason == UCNV_CLOSE) {
 #if DEBUG_TMI
 printf("debugCB_fromU: Context %p:%d closing\n", ctx, ctx->serial);
 #endif
 free(ctx);
 }
 
 #if DEBUG_TMI
 printf("debugCB_fromU: leaving cnv %p, ctx %p: err %s\n", fromUArgs->converter, ctx, u_errorName(*err));
 #endif
 }
 
 debugCBContext *debugCB_openContext()
 {
 debugCBContext *ctx;
 
 ctx = malloc(sizeof(debugCBContext));
 
 if(ctx != NULL) {
 ctx->magic = 0xC0FFEE;
 ctx->serial = debugCB_nextSerial();
 ctx->subCallback = NULL;
 ctx->subContext  = NULL;
 
 #if DEBUG_TMI
 fprintf(stderr, "debugCB:openContext opened[%p] = serial #%d\n", ctx, ctx->serial);
 #endif
 
 }
 
 
 return ctx;
 }
 
 |