diff options
author | mcheshkov <mcheshkov@yandex-team.ru> | 2022-02-10 16:46:15 +0300 |
---|---|---|
committer | Daniil Cherednik <dcherednik@yandex-team.ru> | 2022-02-10 16:46:15 +0300 |
commit | e9d19cec64684c9c1e6b0c98297e5b895cf904fe (patch) | |
tree | 2768b1223e96a8a0610a93d18425d9647c1123c8 /contrib/libs/icu/common/utrace.cpp | |
parent | 60040c91ffe701a84689b2c6310ff845e65cff42 (diff) | |
download | ydb-e9d19cec64684c9c1e6b0c98297e5b895cf904fe.tar.gz |
Restoring authorship annotation for <mcheshkov@yandex-team.ru>. Commit 1 of 2.
Diffstat (limited to 'contrib/libs/icu/common/utrace.cpp')
-rw-r--r-- | contrib/libs/icu/common/utrace.cpp | 1004 |
1 files changed, 502 insertions, 502 deletions
diff --git a/contrib/libs/icu/common/utrace.cpp b/contrib/libs/icu/common/utrace.cpp index c981546594..f642199f25 100644 --- a/contrib/libs/icu/common/utrace.cpp +++ b/contrib/libs/icu/common/utrace.cpp @@ -1,504 +1,504 @@ -// © 2016 and later: Unicode, Inc. and others. -// License & terms of use: http://www.unicode.org/copyright.html -/* -******************************************************************************* -* Copyright (C) 2003-2014, International Business Machines -* Corporation and others. All Rights Reserved. -******************************************************************************* -* file name: utrace.c -* encoding: UTF-8 -* tab size: 8 (not used) -* indentation:4 -*/ - -#include "unicode/utrace.h" -#include "utracimp.h" -#include "cstring.h" -#include "uassert.h" -#include "ucln_cmn.h" - - -static UTraceEntry *pTraceEntryFunc = NULL; -static UTraceExit *pTraceExitFunc = NULL; -static UTraceData *pTraceDataFunc = NULL; -static const void *gTraceContext = NULL; - -/** - * \var utrace_level - * Trace level variable. Negative for "off". - */ -static int32_t -utrace_level = UTRACE_ERROR; - -U_CAPI void U_EXPORT2 -utrace_entry(int32_t fnNumber) { - if (pTraceEntryFunc != NULL) { - (*pTraceEntryFunc)(gTraceContext, fnNumber); - } -} - - -static const char gExitFmt[] = "Returns."; -static const char gExitFmtValue[] = "Returns %d."; -static const char gExitFmtStatus[] = "Returns. Status = %d."; -static const char gExitFmtValueStatus[] = "Returns %d. Status = %d."; -static const char gExitFmtPtrStatus[] = "Returns %d. Status = %p."; - -U_CAPI void U_EXPORT2 -utrace_exit(int32_t fnNumber, int32_t returnType, ...) { - if (pTraceExitFunc != NULL) { - va_list args; - const char *fmt; - - switch (returnType) { - case 0: - fmt = gExitFmt; - break; - case UTRACE_EXITV_I32: - fmt = gExitFmtValue; - break; - case UTRACE_EXITV_STATUS: - fmt = gExitFmtStatus; - break; - case UTRACE_EXITV_I32 | UTRACE_EXITV_STATUS: - fmt = gExitFmtValueStatus; - break; - case UTRACE_EXITV_PTR | UTRACE_EXITV_STATUS: - fmt = gExitFmtPtrStatus; - break; - default: - UPRV_UNREACHABLE; - } - - va_start(args, returnType); - (*pTraceExitFunc)(gTraceContext, fnNumber, fmt, args); - va_end(args); - } -} - - +// © 2016 and later: Unicode, Inc. and others. +// License & terms of use: http://www.unicode.org/copyright.html +/* +******************************************************************************* +* Copyright (C) 2003-2014, International Business Machines +* Corporation and others. All Rights Reserved. +******************************************************************************* +* file name: utrace.c +* encoding: UTF-8 +* tab size: 8 (not used) +* indentation:4 +*/ + +#include "unicode/utrace.h" +#include "utracimp.h" +#include "cstring.h" +#include "uassert.h" +#include "ucln_cmn.h" + + +static UTraceEntry *pTraceEntryFunc = NULL; +static UTraceExit *pTraceExitFunc = NULL; +static UTraceData *pTraceDataFunc = NULL; +static const void *gTraceContext = NULL; + +/** + * \var utrace_level + * Trace level variable. Negative for "off". + */ +static int32_t +utrace_level = UTRACE_ERROR; + +U_CAPI void U_EXPORT2 +utrace_entry(int32_t fnNumber) { + if (pTraceEntryFunc != NULL) { + (*pTraceEntryFunc)(gTraceContext, fnNumber); + } +} + + +static const char gExitFmt[] = "Returns."; +static const char gExitFmtValue[] = "Returns %d."; +static const char gExitFmtStatus[] = "Returns. Status = %d."; +static const char gExitFmtValueStatus[] = "Returns %d. Status = %d."; +static const char gExitFmtPtrStatus[] = "Returns %d. Status = %p."; U_CAPI void U_EXPORT2 -utrace_data(int32_t fnNumber, int32_t level, const char *fmt, ...) { - if (pTraceDataFunc != NULL) { - va_list args; - va_start(args, fmt ); - (*pTraceDataFunc)(gTraceContext, fnNumber, level, fmt, args); - va_end(args); - } -} - - -static void outputChar(char c, char *outBuf, int32_t *outIx, int32_t capacity, int32_t indent) { - int32_t i; - /* Check whether a start of line indenting is needed. Three cases: - * 1. At the start of the first line (output index == 0). - * 2. At the start of subsequent lines (preceeding char in buffer == '\n') - * 3. When preflighting buffer len (buffer capacity is exceeded), when - * a \n is output. Ideally we wouldn't do the indent until the following char - * is received, but that won't work because there's no place to remember that - * the preceding char was \n. Meaning that we may overstimate the - * buffer size needed. No harm done. - */ - if (*outIx==0 || /* case 1. */ - (c!='\n' && c!=0 && *outIx < capacity && outBuf[(*outIx)-1]=='\n') || /* case 2. */ - (c=='\n' && *outIx>=capacity)) /* case 3 */ - { - /* At the start of a line. Indent. */ - for(i=0; i<indent; i++) { - if (*outIx < capacity) { - outBuf[*outIx] = ' '; - } - (*outIx)++; - } - } - - if (*outIx < capacity) { - outBuf[*outIx] = c; - } - if (c != 0) { - /* Nulls only appear as end-of-string terminators. Move them to the output - * buffer, but do not update the length of the buffer, so that any - * following output will overwrite the null. */ - (*outIx)++; - } -} - -static void outputHexBytes(int64_t val, int32_t charsToOutput, - char *outBuf, int32_t *outIx, int32_t capacity) { - static const char gHexChars[] = "0123456789abcdef"; - int32_t shiftCount; - for (shiftCount=(charsToOutput-1)*4; shiftCount >= 0; shiftCount-=4) { - char c = gHexChars[(val >> shiftCount) & 0xf]; - outputChar(c, outBuf, outIx, capacity, 0); - } -} - -/* Output a pointer value in hex. Work with any size of pointer */ -static void outputPtrBytes(void *val, char *outBuf, int32_t *outIx, int32_t capacity) { - uint32_t i; - int32_t incVal = 1; /* +1 for big endian, -1 for little endian */ - char *p = (char *)&val; /* point to current byte to output in the ptr val */ - -#if !U_IS_BIG_ENDIAN - /* Little Endian. Move p to most significant end of the value */ - incVal = -1; - p += sizeof(void *) - 1; -#endif - - /* Loop through the bytes of the ptr as it sits in memory, from - * most significant to least significant end */ - for (i=0; i<sizeof(void *); i++) { - outputHexBytes(*p, 2, outBuf, outIx, capacity); - p += incVal; - } -} - -static void outputString(const char *s, char *outBuf, int32_t *outIx, int32_t capacity, int32_t indent) { - int32_t i = 0; - char c; - if (s==NULL) { - s = "*NULL*"; - } - do { - c = s[i++]; - outputChar(c, outBuf, outIx, capacity, indent); - } while (c != 0); -} - - - -static void outputUString(const UChar *s, int32_t len, - char *outBuf, int32_t *outIx, int32_t capacity, int32_t indent) { - int32_t i = 0; - UChar c; - if (s==NULL) { - outputString(NULL, outBuf, outIx, capacity, indent); - return; - } - - for (i=0; i<len || len==-1; i++) { - c = s[i]; - outputHexBytes(c, 4, outBuf, outIx, capacity); - outputChar(' ', outBuf, outIx, capacity, indent); - if (len == -1 && c==0) { - break; - } - } -} - -U_CAPI int32_t U_EXPORT2 -utrace_vformat(char *outBuf, int32_t capacity, int32_t indent, const char *fmt, va_list args) { - int32_t outIx = 0; - int32_t fmtIx = 0; - char fmtC; - char c; - int32_t intArg; - int64_t longArg = 0; - char *ptrArg; - - /* Loop runs once for each character in the format string. - */ - for (;;) { - fmtC = fmt[fmtIx++]; - if (fmtC != '%') { - /* Literal character, not part of a %sequence. Just copy it to the output. */ - outputChar(fmtC, outBuf, &outIx, capacity, indent); - if (fmtC == 0) { - /* We hit the null that terminates the format string. - * This is the normal (and only) exit from the loop that - * interprets the format - */ - break; - } - continue; - } - - /* We encountered a '%'. Pick up the following format char */ - fmtC = fmt[fmtIx++]; - - switch (fmtC) { - case 'c': - /* single 8 bit char */ - c = (char)va_arg(args, int32_t); - outputChar(c, outBuf, &outIx, capacity, indent); - break; - - case 's': - /* char * string, null terminated. */ - ptrArg = va_arg(args, char *); - outputString((const char *)ptrArg, outBuf, &outIx, capacity, indent); - break; - - case 'S': - /* UChar * string, with length, len==-1 for null terminated. */ - ptrArg = va_arg(args, char *); /* Ptr */ - intArg =(int32_t)va_arg(args, int32_t); /* Length */ - outputUString((const UChar *)ptrArg, intArg, outBuf, &outIx, capacity, indent); - break; - - case 'b': - /* 8 bit int */ - intArg = va_arg(args, int); - outputHexBytes(intArg, 2, outBuf, &outIx, capacity); - break; - - case 'h': - /* 16 bit int */ - intArg = va_arg(args, int); - outputHexBytes(intArg, 4, outBuf, &outIx, capacity); - break; - - case 'd': - /* 32 bit int */ - intArg = va_arg(args, int); - outputHexBytes(intArg, 8, outBuf, &outIx, capacity); - break; - - case 'l': - /* 64 bit long */ - longArg = va_arg(args, int64_t); - outputHexBytes(longArg, 16, outBuf, &outIx, capacity); - break; - - case 'p': - /* Pointers. */ - ptrArg = va_arg(args, char *); - outputPtrBytes(ptrArg, outBuf, &outIx, capacity); - break; - - case 0: - /* Single '%' at end of fmt string. Output as literal '%'. - * Back up index into format string so that the terminating null will be - * re-fetched in the outer loop, causing it to terminate. - */ - outputChar('%', outBuf, &outIx, capacity, indent); - fmtIx--; - break; - - case 'v': - { - /* Vector of values, e.g. %vh */ - char vectorType; - int32_t vectorLen; - const char *i8Ptr; - int16_t *i16Ptr; - int32_t *i32Ptr; - int64_t *i64Ptr; - void **ptrPtr; - int32_t charsToOutput = 0; - int32_t i; - - vectorType = fmt[fmtIx]; /* b, h, d, l, p, etc. */ - if (vectorType != 0) { - fmtIx++; - } - i8Ptr = (const char *)va_arg(args, void*); - i16Ptr = (int16_t *)i8Ptr; - i32Ptr = (int32_t *)i8Ptr; - i64Ptr = (int64_t *)i8Ptr; - ptrPtr = (void **)i8Ptr; - vectorLen =(int32_t)va_arg(args, int32_t); - if (ptrPtr == NULL) { - outputString("*NULL* ", outBuf, &outIx, capacity, indent); - } else { - for (i=0; i<vectorLen || vectorLen==-1; i++) { - switch (vectorType) { - case 'b': - charsToOutput = 2; - longArg = *i8Ptr++; - break; - case 'h': - charsToOutput = 4; - longArg = *i16Ptr++; - break; - case 'd': - charsToOutput = 8; - longArg = *i32Ptr++; - break; - case 'l': - charsToOutput = 16; - longArg = *i64Ptr++; - break; - case 'p': - charsToOutput = 0; - outputPtrBytes(*ptrPtr, outBuf, &outIx, capacity); - longArg = *ptrPtr==NULL? 0: 1; /* test for null terminated array. */ - ptrPtr++; - break; - case 'c': - charsToOutput = 0; - outputChar(*i8Ptr, outBuf, &outIx, capacity, indent); - longArg = *i8Ptr; /* for test for null terminated array. */ - i8Ptr++; - break; - case 's': - charsToOutput = 0; - outputString((const char *)*ptrPtr, outBuf, &outIx, capacity, indent); - outputChar('\n', outBuf, &outIx, capacity, indent); - longArg = *ptrPtr==NULL? 0: 1; /* for test for null term. array. */ - ptrPtr++; - break; - - case 'S': - charsToOutput = 0; - outputUString((const UChar *)*ptrPtr, -1, outBuf, &outIx, capacity, indent); - outputChar('\n', outBuf, &outIx, capacity, indent); - longArg = *ptrPtr==NULL? 0: 1; /* for test for null term. array. */ - ptrPtr++; - break; - - - } - if (charsToOutput > 0) { - outputHexBytes(longArg, charsToOutput, outBuf, &outIx, capacity); - outputChar(' ', outBuf, &outIx, capacity, indent); - } - if (vectorLen == -1 && longArg == 0) { - break; - } - } - } - outputChar('[', outBuf, &outIx, capacity, indent); - outputHexBytes(vectorLen, 8, outBuf, &outIx, capacity); - outputChar(']', outBuf, &outIx, capacity, indent); - } - break; - - - default: - /* %. in format string, where . is some character not in the set - * of recognized format chars. Just output it as if % wasn't there. - * (Covers "%%" outputing a single '%') - */ - outputChar(fmtC, outBuf, &outIx, capacity, indent); - } - } - outputChar(0, outBuf, &outIx, capacity, indent); /* Make sure that output is null terminated */ - return outIx + 1; /* outIx + 1 because outIx does not increment when outputing final null. */ -} - - - - -U_CAPI int32_t U_EXPORT2 -utrace_format(char *outBuf, int32_t capacity, - int32_t indent, const char *fmt, ...) { - int32_t retVal; - va_list args; - va_start(args, fmt ); - retVal = utrace_vformat(outBuf, capacity, indent, fmt, args); - va_end(args); - return retVal; -} - - -U_CAPI void U_EXPORT2 -utrace_setFunctions(const void *context, - UTraceEntry *e, UTraceExit *x, UTraceData *d) { - pTraceEntryFunc = e; - pTraceExitFunc = x; - pTraceDataFunc = d; - gTraceContext = context; -} - - -U_CAPI void U_EXPORT2 -utrace_getFunctions(const void **context, - UTraceEntry **e, UTraceExit **x, UTraceData **d) { - *e = pTraceEntryFunc; - *x = pTraceExitFunc; - *d = pTraceDataFunc; - *context = gTraceContext; -} - -U_CAPI void U_EXPORT2 -utrace_setLevel(int32_t level) { - if (level < UTRACE_OFF) { - level = UTRACE_OFF; - } - if (level > UTRACE_VERBOSE) { - level = UTRACE_VERBOSE; - } - utrace_level = level; -} - -U_CAPI int32_t U_EXPORT2 -utrace_getLevel() { - return utrace_level; -} - - -U_CFUNC UBool -utrace_cleanup() { - pTraceEntryFunc = NULL; - pTraceExitFunc = NULL; - pTraceDataFunc = NULL; - utrace_level = UTRACE_OFF; - gTraceContext = NULL; - return TRUE; -} - - -static const char * const -trFnName[] = { - "u_init", - "u_cleanup", - NULL -}; - - -static const char * const -trConvNames[] = { - "ucnv_open", - "ucnv_openPackage", - "ucnv_openAlgorithmic", - "ucnv_clone", - "ucnv_close", - "ucnv_flushCache", - "ucnv_load", - "ucnv_unload", - NULL -}; - - -static const char * const -trCollNames[] = { - "ucol_open", - "ucol_close", - "ucol_strcoll", - "ucol_getSortKey", - "ucol_getLocale", - "ucol_nextSortKeyPart", - "ucol_strcollIter", - "ucol_openFromShortString", - "ucol_strcollUTF8", - NULL -}; - - -static const char* const -trResDataNames[] = { - "resc", - "bundle-open", - "file-open", - "res-open", - NULL -}; - - -U_CAPI const char * U_EXPORT2 -utrace_functionName(int32_t fnNumber) { - if(UTRACE_FUNCTION_START <= fnNumber && fnNumber < UTRACE_FUNCTION_LIMIT) { - return trFnName[fnNumber]; - } else if(UTRACE_CONVERSION_START <= fnNumber && fnNumber < UTRACE_CONVERSION_LIMIT) { - return trConvNames[fnNumber - UTRACE_CONVERSION_START]; - } else if(UTRACE_COLLATION_START <= fnNumber && fnNumber < UTRACE_COLLATION_LIMIT){ - return trCollNames[fnNumber - UTRACE_COLLATION_START]; - } else if(UTRACE_UDATA_START <= fnNumber && fnNumber < UTRACE_RES_DATA_LIMIT){ - return trResDataNames[fnNumber - UTRACE_UDATA_START]; - } else { - return "[BOGUS Trace Function Number]"; - } -} - +utrace_exit(int32_t fnNumber, int32_t returnType, ...) { + if (pTraceExitFunc != NULL) { + va_list args; + const char *fmt; + + switch (returnType) { + case 0: + fmt = gExitFmt; + break; + case UTRACE_EXITV_I32: + fmt = gExitFmtValue; + break; + case UTRACE_EXITV_STATUS: + fmt = gExitFmtStatus; + break; + case UTRACE_EXITV_I32 | UTRACE_EXITV_STATUS: + fmt = gExitFmtValueStatus; + break; + case UTRACE_EXITV_PTR | UTRACE_EXITV_STATUS: + fmt = gExitFmtPtrStatus; + break; + default: + UPRV_UNREACHABLE; + } + + va_start(args, returnType); + (*pTraceExitFunc)(gTraceContext, fnNumber, fmt, args); + va_end(args); + } +} + + + +U_CAPI void U_EXPORT2 +utrace_data(int32_t fnNumber, int32_t level, const char *fmt, ...) { + if (pTraceDataFunc != NULL) { + va_list args; + va_start(args, fmt ); + (*pTraceDataFunc)(gTraceContext, fnNumber, level, fmt, args); + va_end(args); + } +} + + +static void outputChar(char c, char *outBuf, int32_t *outIx, int32_t capacity, int32_t indent) { + int32_t i; + /* Check whether a start of line indenting is needed. Three cases: + * 1. At the start of the first line (output index == 0). + * 2. At the start of subsequent lines (preceeding char in buffer == '\n') + * 3. When preflighting buffer len (buffer capacity is exceeded), when + * a \n is output. Ideally we wouldn't do the indent until the following char + * is received, but that won't work because there's no place to remember that + * the preceding char was \n. Meaning that we may overstimate the + * buffer size needed. No harm done. + */ + if (*outIx==0 || /* case 1. */ + (c!='\n' && c!=0 && *outIx < capacity && outBuf[(*outIx)-1]=='\n') || /* case 2. */ + (c=='\n' && *outIx>=capacity)) /* case 3 */ + { + /* At the start of a line. Indent. */ + for(i=0; i<indent; i++) { + if (*outIx < capacity) { + outBuf[*outIx] = ' '; + } + (*outIx)++; + } + } + + if (*outIx < capacity) { + outBuf[*outIx] = c; + } + if (c != 0) { + /* Nulls only appear as end-of-string terminators. Move them to the output + * buffer, but do not update the length of the buffer, so that any + * following output will overwrite the null. */ + (*outIx)++; + } +} + +static void outputHexBytes(int64_t val, int32_t charsToOutput, + char *outBuf, int32_t *outIx, int32_t capacity) { + static const char gHexChars[] = "0123456789abcdef"; + int32_t shiftCount; + for (shiftCount=(charsToOutput-1)*4; shiftCount >= 0; shiftCount-=4) { + char c = gHexChars[(val >> shiftCount) & 0xf]; + outputChar(c, outBuf, outIx, capacity, 0); + } +} + +/* Output a pointer value in hex. Work with any size of pointer */ +static void outputPtrBytes(void *val, char *outBuf, int32_t *outIx, int32_t capacity) { + uint32_t i; + int32_t incVal = 1; /* +1 for big endian, -1 for little endian */ + char *p = (char *)&val; /* point to current byte to output in the ptr val */ + +#if !U_IS_BIG_ENDIAN + /* Little Endian. Move p to most significant end of the value */ + incVal = -1; + p += sizeof(void *) - 1; +#endif + + /* Loop through the bytes of the ptr as it sits in memory, from + * most significant to least significant end */ + for (i=0; i<sizeof(void *); i++) { + outputHexBytes(*p, 2, outBuf, outIx, capacity); + p += incVal; + } +} + +static void outputString(const char *s, char *outBuf, int32_t *outIx, int32_t capacity, int32_t indent) { + int32_t i = 0; + char c; + if (s==NULL) { + s = "*NULL*"; + } + do { + c = s[i++]; + outputChar(c, outBuf, outIx, capacity, indent); + } while (c != 0); +} + + + +static void outputUString(const UChar *s, int32_t len, + char *outBuf, int32_t *outIx, int32_t capacity, int32_t indent) { + int32_t i = 0; + UChar c; + if (s==NULL) { + outputString(NULL, outBuf, outIx, capacity, indent); + return; + } + + for (i=0; i<len || len==-1; i++) { + c = s[i]; + outputHexBytes(c, 4, outBuf, outIx, capacity); + outputChar(' ', outBuf, outIx, capacity, indent); + if (len == -1 && c==0) { + break; + } + } +} + +U_CAPI int32_t U_EXPORT2 +utrace_vformat(char *outBuf, int32_t capacity, int32_t indent, const char *fmt, va_list args) { + int32_t outIx = 0; + int32_t fmtIx = 0; + char fmtC; + char c; + int32_t intArg; + int64_t longArg = 0; + char *ptrArg; + + /* Loop runs once for each character in the format string. + */ + for (;;) { + fmtC = fmt[fmtIx++]; + if (fmtC != '%') { + /* Literal character, not part of a %sequence. Just copy it to the output. */ + outputChar(fmtC, outBuf, &outIx, capacity, indent); + if (fmtC == 0) { + /* We hit the null that terminates the format string. + * This is the normal (and only) exit from the loop that + * interprets the format + */ + break; + } + continue; + } + + /* We encountered a '%'. Pick up the following format char */ + fmtC = fmt[fmtIx++]; + + switch (fmtC) { + case 'c': + /* single 8 bit char */ + c = (char)va_arg(args, int32_t); + outputChar(c, outBuf, &outIx, capacity, indent); + break; + + case 's': + /* char * string, null terminated. */ + ptrArg = va_arg(args, char *); + outputString((const char *)ptrArg, outBuf, &outIx, capacity, indent); + break; + + case 'S': + /* UChar * string, with length, len==-1 for null terminated. */ + ptrArg = va_arg(args, char *); /* Ptr */ + intArg =(int32_t)va_arg(args, int32_t); /* Length */ + outputUString((const UChar *)ptrArg, intArg, outBuf, &outIx, capacity, indent); + break; + + case 'b': + /* 8 bit int */ + intArg = va_arg(args, int); + outputHexBytes(intArg, 2, outBuf, &outIx, capacity); + break; + + case 'h': + /* 16 bit int */ + intArg = va_arg(args, int); + outputHexBytes(intArg, 4, outBuf, &outIx, capacity); + break; + + case 'd': + /* 32 bit int */ + intArg = va_arg(args, int); + outputHexBytes(intArg, 8, outBuf, &outIx, capacity); + break; + + case 'l': + /* 64 bit long */ + longArg = va_arg(args, int64_t); + outputHexBytes(longArg, 16, outBuf, &outIx, capacity); + break; + + case 'p': + /* Pointers. */ + ptrArg = va_arg(args, char *); + outputPtrBytes(ptrArg, outBuf, &outIx, capacity); + break; + + case 0: + /* Single '%' at end of fmt string. Output as literal '%'. + * Back up index into format string so that the terminating null will be + * re-fetched in the outer loop, causing it to terminate. + */ + outputChar('%', outBuf, &outIx, capacity, indent); + fmtIx--; + break; + + case 'v': + { + /* Vector of values, e.g. %vh */ + char vectorType; + int32_t vectorLen; + const char *i8Ptr; + int16_t *i16Ptr; + int32_t *i32Ptr; + int64_t *i64Ptr; + void **ptrPtr; + int32_t charsToOutput = 0; + int32_t i; + + vectorType = fmt[fmtIx]; /* b, h, d, l, p, etc. */ + if (vectorType != 0) { + fmtIx++; + } + i8Ptr = (const char *)va_arg(args, void*); + i16Ptr = (int16_t *)i8Ptr; + i32Ptr = (int32_t *)i8Ptr; + i64Ptr = (int64_t *)i8Ptr; + ptrPtr = (void **)i8Ptr; + vectorLen =(int32_t)va_arg(args, int32_t); + if (ptrPtr == NULL) { + outputString("*NULL* ", outBuf, &outIx, capacity, indent); + } else { + for (i=0; i<vectorLen || vectorLen==-1; i++) { + switch (vectorType) { + case 'b': + charsToOutput = 2; + longArg = *i8Ptr++; + break; + case 'h': + charsToOutput = 4; + longArg = *i16Ptr++; + break; + case 'd': + charsToOutput = 8; + longArg = *i32Ptr++; + break; + case 'l': + charsToOutput = 16; + longArg = *i64Ptr++; + break; + case 'p': + charsToOutput = 0; + outputPtrBytes(*ptrPtr, outBuf, &outIx, capacity); + longArg = *ptrPtr==NULL? 0: 1; /* test for null terminated array. */ + ptrPtr++; + break; + case 'c': + charsToOutput = 0; + outputChar(*i8Ptr, outBuf, &outIx, capacity, indent); + longArg = *i8Ptr; /* for test for null terminated array. */ + i8Ptr++; + break; + case 's': + charsToOutput = 0; + outputString((const char *)*ptrPtr, outBuf, &outIx, capacity, indent); + outputChar('\n', outBuf, &outIx, capacity, indent); + longArg = *ptrPtr==NULL? 0: 1; /* for test for null term. array. */ + ptrPtr++; + break; + + case 'S': + charsToOutput = 0; + outputUString((const UChar *)*ptrPtr, -1, outBuf, &outIx, capacity, indent); + outputChar('\n', outBuf, &outIx, capacity, indent); + longArg = *ptrPtr==NULL? 0: 1; /* for test for null term. array. */ + ptrPtr++; + break; + + + } + if (charsToOutput > 0) { + outputHexBytes(longArg, charsToOutput, outBuf, &outIx, capacity); + outputChar(' ', outBuf, &outIx, capacity, indent); + } + if (vectorLen == -1 && longArg == 0) { + break; + } + } + } + outputChar('[', outBuf, &outIx, capacity, indent); + outputHexBytes(vectorLen, 8, outBuf, &outIx, capacity); + outputChar(']', outBuf, &outIx, capacity, indent); + } + break; + + + default: + /* %. in format string, where . is some character not in the set + * of recognized format chars. Just output it as if % wasn't there. + * (Covers "%%" outputing a single '%') + */ + outputChar(fmtC, outBuf, &outIx, capacity, indent); + } + } + outputChar(0, outBuf, &outIx, capacity, indent); /* Make sure that output is null terminated */ + return outIx + 1; /* outIx + 1 because outIx does not increment when outputing final null. */ +} + + + + +U_CAPI int32_t U_EXPORT2 +utrace_format(char *outBuf, int32_t capacity, + int32_t indent, const char *fmt, ...) { + int32_t retVal; + va_list args; + va_start(args, fmt ); + retVal = utrace_vformat(outBuf, capacity, indent, fmt, args); + va_end(args); + return retVal; +} + + +U_CAPI void U_EXPORT2 +utrace_setFunctions(const void *context, + UTraceEntry *e, UTraceExit *x, UTraceData *d) { + pTraceEntryFunc = e; + pTraceExitFunc = x; + pTraceDataFunc = d; + gTraceContext = context; +} + + +U_CAPI void U_EXPORT2 +utrace_getFunctions(const void **context, + UTraceEntry **e, UTraceExit **x, UTraceData **d) { + *e = pTraceEntryFunc; + *x = pTraceExitFunc; + *d = pTraceDataFunc; + *context = gTraceContext; +} + +U_CAPI void U_EXPORT2 +utrace_setLevel(int32_t level) { + if (level < UTRACE_OFF) { + level = UTRACE_OFF; + } + if (level > UTRACE_VERBOSE) { + level = UTRACE_VERBOSE; + } + utrace_level = level; +} + +U_CAPI int32_t U_EXPORT2 +utrace_getLevel() { + return utrace_level; +} + + +U_CFUNC UBool +utrace_cleanup() { + pTraceEntryFunc = NULL; + pTraceExitFunc = NULL; + pTraceDataFunc = NULL; + utrace_level = UTRACE_OFF; + gTraceContext = NULL; + return TRUE; +} + + +static const char * const +trFnName[] = { + "u_init", + "u_cleanup", + NULL +}; + + +static const char * const +trConvNames[] = { + "ucnv_open", + "ucnv_openPackage", + "ucnv_openAlgorithmic", + "ucnv_clone", + "ucnv_close", + "ucnv_flushCache", + "ucnv_load", + "ucnv_unload", + NULL +}; + + +static const char * const +trCollNames[] = { + "ucol_open", + "ucol_close", + "ucol_strcoll", + "ucol_getSortKey", + "ucol_getLocale", + "ucol_nextSortKeyPart", + "ucol_strcollIter", + "ucol_openFromShortString", + "ucol_strcollUTF8", + NULL +}; + + +static const char* const +trResDataNames[] = { + "resc", + "bundle-open", + "file-open", + "res-open", + NULL +}; + + +U_CAPI const char * U_EXPORT2 +utrace_functionName(int32_t fnNumber) { + if(UTRACE_FUNCTION_START <= fnNumber && fnNumber < UTRACE_FUNCTION_LIMIT) { + return trFnName[fnNumber]; + } else if(UTRACE_CONVERSION_START <= fnNumber && fnNumber < UTRACE_CONVERSION_LIMIT) { + return trConvNames[fnNumber - UTRACE_CONVERSION_START]; + } else if(UTRACE_COLLATION_START <= fnNumber && fnNumber < UTRACE_COLLATION_LIMIT){ + return trCollNames[fnNumber - UTRACE_COLLATION_START]; + } else if(UTRACE_UDATA_START <= fnNumber && fnNumber < UTRACE_RES_DATA_LIMIT){ + return trResDataNames[fnNumber - UTRACE_UDATA_START]; + } else { + return "[BOGUS Trace Function Number]"; + } +} + |