Jungshik Shin | 87232d8 | 2017-05-13 21:10:13 -0700 | [diff] [blame] | 1 | // © 2016 and later: Unicode, Inc. and others. |
Jungshik Shin | 5feb9ad | 2016-10-21 12:52:48 -0700 | [diff] [blame] | 2 | // License & terms of use: http://www.unicode.org/copyright.html |
jshin@chromium.org | 6f31ac3 | 2014-03-26 22:15:14 +0000 | [diff] [blame] | 3 | /* |
| 4 | ******************************************************************************* |
Jungshik Shin (jungshik at google) | 0f8746a | 2015-01-08 15:46:45 -0800 | [diff] [blame] | 5 | * Copyright (C) 2003-2014, International Business Machines |
jshin@chromium.org | 6f31ac3 | 2014-03-26 22:15:14 +0000 | [diff] [blame] | 6 | * Corporation and others. All Rights Reserved. |
| 7 | ******************************************************************************* |
| 8 | * file name: utrace.c |
Jungshik Shin | 87232d8 | 2017-05-13 21:10:13 -0700 | [diff] [blame] | 9 | * encoding: UTF-8 |
jshin@chromium.org | 6f31ac3 | 2014-03-26 22:15:14 +0000 | [diff] [blame] | 10 | * tab size: 8 (not used) |
| 11 | * indentation:4 |
| 12 | */ |
| 13 | |
jshin@chromium.org | 6f31ac3 | 2014-03-26 22:15:14 +0000 | [diff] [blame] | 14 | #include "unicode/utrace.h" |
| 15 | #include "utracimp.h" |
| 16 | #include "cstring.h" |
| 17 | #include "uassert.h" |
| 18 | #include "ucln_cmn.h" |
| 19 | |
| 20 | |
| 21 | static UTraceEntry *pTraceEntryFunc = NULL; |
| 22 | static UTraceExit *pTraceExitFunc = NULL; |
| 23 | static UTraceData *pTraceDataFunc = NULL; |
| 24 | static const void *gTraceContext = NULL; |
| 25 | |
Jungshik Shin | 87232d8 | 2017-05-13 21:10:13 -0700 | [diff] [blame] | 26 | /** |
| 27 | * \var utrace_level |
| 28 | * Trace level variable. Negative for "off". |
| 29 | */ |
| 30 | static int32_t |
jshin@chromium.org | 6f31ac3 | 2014-03-26 22:15:14 +0000 | [diff] [blame] | 31 | utrace_level = UTRACE_ERROR; |
| 32 | |
| 33 | U_CAPI void U_EXPORT2 |
| 34 | utrace_entry(int32_t fnNumber) { |
| 35 | if (pTraceEntryFunc != NULL) { |
| 36 | (*pTraceEntryFunc)(gTraceContext, fnNumber); |
| 37 | } |
| 38 | } |
| 39 | |
| 40 | |
| 41 | static const char gExitFmt[] = "Returns."; |
| 42 | static const char gExitFmtValue[] = "Returns %d."; |
| 43 | static const char gExitFmtStatus[] = "Returns. Status = %d."; |
| 44 | static const char gExitFmtValueStatus[] = "Returns %d. Status = %d."; |
| 45 | static const char gExitFmtPtrStatus[] = "Returns %d. Status = %p."; |
| 46 | |
| 47 | U_CAPI void U_EXPORT2 |
| 48 | utrace_exit(int32_t fnNumber, int32_t returnType, ...) { |
| 49 | if (pTraceExitFunc != NULL) { |
| 50 | va_list args; |
| 51 | const char *fmt; |
| 52 | |
| 53 | switch (returnType) { |
| 54 | case 0: |
| 55 | fmt = gExitFmt; |
| 56 | break; |
| 57 | case UTRACE_EXITV_I32: |
| 58 | fmt = gExitFmtValue; |
| 59 | break; |
| 60 | case UTRACE_EXITV_STATUS: |
| 61 | fmt = gExitFmtStatus; |
| 62 | break; |
| 63 | case UTRACE_EXITV_I32 | UTRACE_EXITV_STATUS: |
| 64 | fmt = gExitFmtValueStatus; |
| 65 | break; |
| 66 | case UTRACE_EXITV_PTR | UTRACE_EXITV_STATUS: |
| 67 | fmt = gExitFmtPtrStatus; |
| 68 | break; |
| 69 | default: |
Frank Tang | 3e05d9d | 2021-11-08 14:04:04 -0800 | [diff] [blame] | 70 | UPRV_UNREACHABLE_EXIT; |
jshin@chromium.org | 6f31ac3 | 2014-03-26 22:15:14 +0000 | [diff] [blame] | 71 | } |
| 72 | |
| 73 | va_start(args, returnType); |
| 74 | (*pTraceExitFunc)(gTraceContext, fnNumber, fmt, args); |
| 75 | va_end(args); |
| 76 | } |
| 77 | } |
| 78 | |
| 79 | |
| 80 | |
| 81 | U_CAPI void U_EXPORT2 |
| 82 | utrace_data(int32_t fnNumber, int32_t level, const char *fmt, ...) { |
| 83 | if (pTraceDataFunc != NULL) { |
| 84 | va_list args; |
| 85 | va_start(args, fmt ); |
| 86 | (*pTraceDataFunc)(gTraceContext, fnNumber, level, fmt, args); |
| 87 | va_end(args); |
| 88 | } |
| 89 | } |
| 90 | |
| 91 | |
| 92 | static void outputChar(char c, char *outBuf, int32_t *outIx, int32_t capacity, int32_t indent) { |
| 93 | int32_t i; |
| 94 | /* Check whether a start of line indenting is needed. Three cases: |
| 95 | * 1. At the start of the first line (output index == 0). |
Frank Tang | 3e05d9d | 2021-11-08 14:04:04 -0800 | [diff] [blame] | 96 | * 2. At the start of subsequent lines (preceding char in buffer == '\n') |
jshin@chromium.org | 6f31ac3 | 2014-03-26 22:15:14 +0000 | [diff] [blame] | 97 | * 3. When preflighting buffer len (buffer capacity is exceeded), when |
| 98 | * a \n is output. Ideally we wouldn't do the indent until the following char |
| 99 | * is received, but that won't work because there's no place to remember that |
| 100 | * the preceding char was \n. Meaning that we may overstimate the |
| 101 | * buffer size needed. No harm done. |
| 102 | */ |
| 103 | if (*outIx==0 || /* case 1. */ |
| 104 | (c!='\n' && c!=0 && *outIx < capacity && outBuf[(*outIx)-1]=='\n') || /* case 2. */ |
| 105 | (c=='\n' && *outIx>=capacity)) /* case 3 */ |
| 106 | { |
| 107 | /* At the start of a line. Indent. */ |
| 108 | for(i=0; i<indent; i++) { |
| 109 | if (*outIx < capacity) { |
| 110 | outBuf[*outIx] = ' '; |
| 111 | } |
| 112 | (*outIx)++; |
| 113 | } |
| 114 | } |
| 115 | |
| 116 | if (*outIx < capacity) { |
| 117 | outBuf[*outIx] = c; |
| 118 | } |
| 119 | if (c != 0) { |
| 120 | /* Nulls only appear as end-of-string terminators. Move them to the output |
| 121 | * buffer, but do not update the length of the buffer, so that any |
| 122 | * following output will overwrite the null. */ |
| 123 | (*outIx)++; |
| 124 | } |
| 125 | } |
| 126 | |
| 127 | static void outputHexBytes(int64_t val, int32_t charsToOutput, |
| 128 | char *outBuf, int32_t *outIx, int32_t capacity) { |
| 129 | static const char gHexChars[] = "0123456789abcdef"; |
| 130 | int32_t shiftCount; |
| 131 | for (shiftCount=(charsToOutput-1)*4; shiftCount >= 0; shiftCount-=4) { |
| 132 | char c = gHexChars[(val >> shiftCount) & 0xf]; |
| 133 | outputChar(c, outBuf, outIx, capacity, 0); |
| 134 | } |
| 135 | } |
| 136 | |
| 137 | /* Output a pointer value in hex. Work with any size of pointer */ |
| 138 | static void outputPtrBytes(void *val, char *outBuf, int32_t *outIx, int32_t capacity) { |
Jungshik Shin | 87232d8 | 2017-05-13 21:10:13 -0700 | [diff] [blame] | 139 | uint32_t i; |
jshin@chromium.org | 6f31ac3 | 2014-03-26 22:15:14 +0000 | [diff] [blame] | 140 | int32_t incVal = 1; /* +1 for big endian, -1 for little endian */ |
| 141 | char *p = (char *)&val; /* point to current byte to output in the ptr val */ |
| 142 | |
| 143 | #if !U_IS_BIG_ENDIAN |
| 144 | /* Little Endian. Move p to most significant end of the value */ |
| 145 | incVal = -1; |
| 146 | p += sizeof(void *) - 1; |
| 147 | #endif |
| 148 | |
| 149 | /* Loop through the bytes of the ptr as it sits in memory, from |
| 150 | * most significant to least significant end */ |
| 151 | for (i=0; i<sizeof(void *); i++) { |
| 152 | outputHexBytes(*p, 2, outBuf, outIx, capacity); |
| 153 | p += incVal; |
| 154 | } |
| 155 | } |
| 156 | |
| 157 | static void outputString(const char *s, char *outBuf, int32_t *outIx, int32_t capacity, int32_t indent) { |
| 158 | int32_t i = 0; |
| 159 | char c; |
| 160 | if (s==NULL) { |
| 161 | s = "*NULL*"; |
| 162 | } |
| 163 | do { |
| 164 | c = s[i++]; |
| 165 | outputChar(c, outBuf, outIx, capacity, indent); |
| 166 | } while (c != 0); |
| 167 | } |
| 168 | |
| 169 | |
| 170 | |
| 171 | static void outputUString(const UChar *s, int32_t len, |
| 172 | char *outBuf, int32_t *outIx, int32_t capacity, int32_t indent) { |
| 173 | int32_t i = 0; |
| 174 | UChar c; |
| 175 | if (s==NULL) { |
| 176 | outputString(NULL, outBuf, outIx, capacity, indent); |
| 177 | return; |
| 178 | } |
| 179 | |
| 180 | for (i=0; i<len || len==-1; i++) { |
| 181 | c = s[i]; |
| 182 | outputHexBytes(c, 4, outBuf, outIx, capacity); |
| 183 | outputChar(' ', outBuf, outIx, capacity, indent); |
| 184 | if (len == -1 && c==0) { |
| 185 | break; |
| 186 | } |
| 187 | } |
| 188 | } |
| 189 | |
| 190 | U_CAPI int32_t U_EXPORT2 |
| 191 | utrace_vformat(char *outBuf, int32_t capacity, int32_t indent, const char *fmt, va_list args) { |
| 192 | int32_t outIx = 0; |
| 193 | int32_t fmtIx = 0; |
| 194 | char fmtC; |
| 195 | char c; |
| 196 | int32_t intArg; |
| 197 | int64_t longArg = 0; |
| 198 | char *ptrArg; |
| 199 | |
| 200 | /* Loop runs once for each character in the format string. |
| 201 | */ |
| 202 | for (;;) { |
| 203 | fmtC = fmt[fmtIx++]; |
| 204 | if (fmtC != '%') { |
| 205 | /* Literal character, not part of a %sequence. Just copy it to the output. */ |
| 206 | outputChar(fmtC, outBuf, &outIx, capacity, indent); |
| 207 | if (fmtC == 0) { |
| 208 | /* We hit the null that terminates the format string. |
| 209 | * This is the normal (and only) exit from the loop that |
| 210 | * interprets the format |
| 211 | */ |
| 212 | break; |
| 213 | } |
| 214 | continue; |
| 215 | } |
| 216 | |
| 217 | /* We encountered a '%'. Pick up the following format char */ |
| 218 | fmtC = fmt[fmtIx++]; |
| 219 | |
| 220 | switch (fmtC) { |
| 221 | case 'c': |
| 222 | /* single 8 bit char */ |
| 223 | c = (char)va_arg(args, int32_t); |
| 224 | outputChar(c, outBuf, &outIx, capacity, indent); |
| 225 | break; |
| 226 | |
| 227 | case 's': |
| 228 | /* char * string, null terminated. */ |
| 229 | ptrArg = va_arg(args, char *); |
| 230 | outputString((const char *)ptrArg, outBuf, &outIx, capacity, indent); |
| 231 | break; |
| 232 | |
| 233 | case 'S': |
| 234 | /* UChar * string, with length, len==-1 for null terminated. */ |
Jungshik Shin | 87232d8 | 2017-05-13 21:10:13 -0700 | [diff] [blame] | 235 | ptrArg = va_arg(args, char *); /* Ptr */ |
jshin@chromium.org | 6f31ac3 | 2014-03-26 22:15:14 +0000 | [diff] [blame] | 236 | intArg =(int32_t)va_arg(args, int32_t); /* Length */ |
| 237 | outputUString((const UChar *)ptrArg, intArg, outBuf, &outIx, capacity, indent); |
| 238 | break; |
| 239 | |
| 240 | case 'b': |
| 241 | /* 8 bit int */ |
| 242 | intArg = va_arg(args, int); |
| 243 | outputHexBytes(intArg, 2, outBuf, &outIx, capacity); |
| 244 | break; |
| 245 | |
| 246 | case 'h': |
| 247 | /* 16 bit int */ |
| 248 | intArg = va_arg(args, int); |
| 249 | outputHexBytes(intArg, 4, outBuf, &outIx, capacity); |
| 250 | break; |
| 251 | |
| 252 | case 'd': |
| 253 | /* 32 bit int */ |
| 254 | intArg = va_arg(args, int); |
| 255 | outputHexBytes(intArg, 8, outBuf, &outIx, capacity); |
| 256 | break; |
| 257 | |
| 258 | case 'l': |
| 259 | /* 64 bit long */ |
| 260 | longArg = va_arg(args, int64_t); |
| 261 | outputHexBytes(longArg, 16, outBuf, &outIx, capacity); |
| 262 | break; |
| 263 | |
| 264 | case 'p': |
| 265 | /* Pointers. */ |
Jungshik Shin | 87232d8 | 2017-05-13 21:10:13 -0700 | [diff] [blame] | 266 | ptrArg = va_arg(args, char *); |
jshin@chromium.org | 6f31ac3 | 2014-03-26 22:15:14 +0000 | [diff] [blame] | 267 | outputPtrBytes(ptrArg, outBuf, &outIx, capacity); |
| 268 | break; |
| 269 | |
| 270 | case 0: |
| 271 | /* Single '%' at end of fmt string. Output as literal '%'. |
| 272 | * Back up index into format string so that the terminating null will be |
| 273 | * re-fetched in the outer loop, causing it to terminate. |
| 274 | */ |
| 275 | outputChar('%', outBuf, &outIx, capacity, indent); |
| 276 | fmtIx--; |
| 277 | break; |
| 278 | |
| 279 | case 'v': |
| 280 | { |
| 281 | /* Vector of values, e.g. %vh */ |
| 282 | char vectorType; |
| 283 | int32_t vectorLen; |
| 284 | const char *i8Ptr; |
| 285 | int16_t *i16Ptr; |
| 286 | int32_t *i32Ptr; |
| 287 | int64_t *i64Ptr; |
| 288 | void **ptrPtr; |
| 289 | int32_t charsToOutput = 0; |
| 290 | int32_t i; |
| 291 | |
| 292 | vectorType = fmt[fmtIx]; /* b, h, d, l, p, etc. */ |
| 293 | if (vectorType != 0) { |
| 294 | fmtIx++; |
| 295 | } |
| 296 | i8Ptr = (const char *)va_arg(args, void*); |
| 297 | i16Ptr = (int16_t *)i8Ptr; |
| 298 | i32Ptr = (int32_t *)i8Ptr; |
| 299 | i64Ptr = (int64_t *)i8Ptr; |
| 300 | ptrPtr = (void **)i8Ptr; |
| 301 | vectorLen =(int32_t)va_arg(args, int32_t); |
| 302 | if (ptrPtr == NULL) { |
| 303 | outputString("*NULL* ", outBuf, &outIx, capacity, indent); |
| 304 | } else { |
| 305 | for (i=0; i<vectorLen || vectorLen==-1; i++) { |
| 306 | switch (vectorType) { |
| 307 | case 'b': |
| 308 | charsToOutput = 2; |
| 309 | longArg = *i8Ptr++; |
| 310 | break; |
| 311 | case 'h': |
| 312 | charsToOutput = 4; |
| 313 | longArg = *i16Ptr++; |
| 314 | break; |
| 315 | case 'd': |
| 316 | charsToOutput = 8; |
| 317 | longArg = *i32Ptr++; |
| 318 | break; |
| 319 | case 'l': |
| 320 | charsToOutput = 16; |
| 321 | longArg = *i64Ptr++; |
| 322 | break; |
| 323 | case 'p': |
| 324 | charsToOutput = 0; |
| 325 | outputPtrBytes(*ptrPtr, outBuf, &outIx, capacity); |
| 326 | longArg = *ptrPtr==NULL? 0: 1; /* test for null terminated array. */ |
| 327 | ptrPtr++; |
| 328 | break; |
| 329 | case 'c': |
| 330 | charsToOutput = 0; |
| 331 | outputChar(*i8Ptr, outBuf, &outIx, capacity, indent); |
| 332 | longArg = *i8Ptr; /* for test for null terminated array. */ |
| 333 | i8Ptr++; |
| 334 | break; |
| 335 | case 's': |
| 336 | charsToOutput = 0; |
Jungshik Shin | 87232d8 | 2017-05-13 21:10:13 -0700 | [diff] [blame] | 337 | outputString((const char *)*ptrPtr, outBuf, &outIx, capacity, indent); |
jshin@chromium.org | 6f31ac3 | 2014-03-26 22:15:14 +0000 | [diff] [blame] | 338 | outputChar('\n', outBuf, &outIx, capacity, indent); |
| 339 | longArg = *ptrPtr==NULL? 0: 1; /* for test for null term. array. */ |
| 340 | ptrPtr++; |
| 341 | break; |
| 342 | |
| 343 | case 'S': |
| 344 | charsToOutput = 0; |
| 345 | outputUString((const UChar *)*ptrPtr, -1, outBuf, &outIx, capacity, indent); |
| 346 | outputChar('\n', outBuf, &outIx, capacity, indent); |
| 347 | longArg = *ptrPtr==NULL? 0: 1; /* for test for null term. array. */ |
| 348 | ptrPtr++; |
| 349 | break; |
| 350 | |
| 351 | |
| 352 | } |
| 353 | if (charsToOutput > 0) { |
| 354 | outputHexBytes(longArg, charsToOutput, outBuf, &outIx, capacity); |
| 355 | outputChar(' ', outBuf, &outIx, capacity, indent); |
| 356 | } |
| 357 | if (vectorLen == -1 && longArg == 0) { |
| 358 | break; |
| 359 | } |
| 360 | } |
| 361 | } |
| 362 | outputChar('[', outBuf, &outIx, capacity, indent); |
| 363 | outputHexBytes(vectorLen, 8, outBuf, &outIx, capacity); |
| 364 | outputChar(']', outBuf, &outIx, capacity, indent); |
| 365 | } |
| 366 | break; |
| 367 | |
| 368 | |
| 369 | default: |
| 370 | /* %. in format string, where . is some character not in the set |
| 371 | * of recognized format chars. Just output it as if % wasn't there. |
Frank Tang | 3e05d9d | 2021-11-08 14:04:04 -0800 | [diff] [blame] | 372 | * (Covers "%%" outputting a single '%') |
jshin@chromium.org | 6f31ac3 | 2014-03-26 22:15:14 +0000 | [diff] [blame] | 373 | */ |
| 374 | outputChar(fmtC, outBuf, &outIx, capacity, indent); |
| 375 | } |
| 376 | } |
Frank Tang | 3e05d9d | 2021-11-08 14:04:04 -0800 | [diff] [blame] | 377 | outputChar(0, outBuf, &outIx, capacity, indent); /* Make sure that output is null terminated */ |
| 378 | return outIx + 1; /* outIx + 1 because outIx does not increment when outputting final null. */ |
jshin@chromium.org | 6f31ac3 | 2014-03-26 22:15:14 +0000 | [diff] [blame] | 379 | } |
| 380 | |
| 381 | |
| 382 | |
| 383 | |
| 384 | U_CAPI int32_t U_EXPORT2 |
| 385 | utrace_format(char *outBuf, int32_t capacity, |
| 386 | int32_t indent, const char *fmt, ...) { |
| 387 | int32_t retVal; |
| 388 | va_list args; |
| 389 | va_start(args, fmt ); |
| 390 | retVal = utrace_vformat(outBuf, capacity, indent, fmt, args); |
| 391 | va_end(args); |
| 392 | return retVal; |
| 393 | } |
| 394 | |
| 395 | |
| 396 | U_CAPI void U_EXPORT2 |
| 397 | utrace_setFunctions(const void *context, |
| 398 | UTraceEntry *e, UTraceExit *x, UTraceData *d) { |
| 399 | pTraceEntryFunc = e; |
| 400 | pTraceExitFunc = x; |
| 401 | pTraceDataFunc = d; |
| 402 | gTraceContext = context; |
| 403 | } |
| 404 | |
| 405 | |
| 406 | U_CAPI void U_EXPORT2 |
| 407 | utrace_getFunctions(const void **context, |
| 408 | UTraceEntry **e, UTraceExit **x, UTraceData **d) { |
| 409 | *e = pTraceEntryFunc; |
| 410 | *x = pTraceExitFunc; |
| 411 | *d = pTraceDataFunc; |
| 412 | *context = gTraceContext; |
| 413 | } |
| 414 | |
| 415 | U_CAPI void U_EXPORT2 |
| 416 | utrace_setLevel(int32_t level) { |
| 417 | if (level < UTRACE_OFF) { |
| 418 | level = UTRACE_OFF; |
| 419 | } |
| 420 | if (level > UTRACE_VERBOSE) { |
| 421 | level = UTRACE_VERBOSE; |
| 422 | } |
| 423 | utrace_level = level; |
| 424 | } |
| 425 | |
| 426 | U_CAPI int32_t U_EXPORT2 |
| 427 | utrace_getLevel() { |
| 428 | return utrace_level; |
| 429 | } |
| 430 | |
| 431 | |
| 432 | U_CFUNC UBool |
| 433 | utrace_cleanup() { |
| 434 | pTraceEntryFunc = NULL; |
| 435 | pTraceExitFunc = NULL; |
| 436 | pTraceDataFunc = NULL; |
| 437 | utrace_level = UTRACE_OFF; |
| 438 | gTraceContext = NULL; |
Frank Tang | 1f164ee | 2022-11-08 12:31:27 -0800 | [diff] [blame^] | 439 | return true; |
jshin@chromium.org | 6f31ac3 | 2014-03-26 22:15:14 +0000 | [diff] [blame] | 440 | } |
| 441 | |
| 442 | |
| 443 | static const char * const |
| 444 | trFnName[] = { |
| 445 | "u_init", |
| 446 | "u_cleanup", |
| 447 | NULL |
| 448 | }; |
| 449 | |
| 450 | |
| 451 | static const char * const |
| 452 | trConvNames[] = { |
| 453 | "ucnv_open", |
| 454 | "ucnv_openPackage", |
| 455 | "ucnv_openAlgorithmic", |
| 456 | "ucnv_clone", |
| 457 | "ucnv_close", |
| 458 | "ucnv_flushCache", |
| 459 | "ucnv_load", |
| 460 | "ucnv_unload", |
| 461 | NULL |
| 462 | }; |
| 463 | |
| 464 | |
| 465 | static const char * const |
| 466 | trCollNames[] = { |
| 467 | "ucol_open", |
| 468 | "ucol_close", |
| 469 | "ucol_strcoll", |
| 470 | "ucol_getSortKey", |
| 471 | "ucol_getLocale", |
| 472 | "ucol_nextSortKeyPart", |
| 473 | "ucol_strcollIter", |
Jungshik Shin (jungshik at google) | 0f8746a | 2015-01-08 15:46:45 -0800 | [diff] [blame] | 474 | "ucol_openFromShortString", |
| 475 | "ucol_strcollUTF8", |
jshin@chromium.org | 6f31ac3 | 2014-03-26 22:15:14 +0000 | [diff] [blame] | 476 | NULL |
| 477 | }; |
| 478 | |
Frank Tang | 952ccb9 | 2019-08-22 12:09:17 -0700 | [diff] [blame] | 479 | |
| 480 | static const char* const |
| 481 | trResDataNames[] = { |
Frank Tang | b869661 | 2019-10-25 14:58:21 -0700 | [diff] [blame] | 482 | "resc", |
| 483 | "bundle-open", |
| 484 | "file-open", |
| 485 | "res-open", |
Frank Tang | 952ccb9 | 2019-08-22 12:09:17 -0700 | [diff] [blame] | 486 | NULL |
| 487 | }; |
| 488 | |
jshin@chromium.org | 6f31ac3 | 2014-03-26 22:15:14 +0000 | [diff] [blame] | 489 | |
| 490 | U_CAPI const char * U_EXPORT2 |
| 491 | utrace_functionName(int32_t fnNumber) { |
| 492 | if(UTRACE_FUNCTION_START <= fnNumber && fnNumber < UTRACE_FUNCTION_LIMIT) { |
| 493 | return trFnName[fnNumber]; |
| 494 | } else if(UTRACE_CONVERSION_START <= fnNumber && fnNumber < UTRACE_CONVERSION_LIMIT) { |
| 495 | return trConvNames[fnNumber - UTRACE_CONVERSION_START]; |
| 496 | } else if(UTRACE_COLLATION_START <= fnNumber && fnNumber < UTRACE_COLLATION_LIMIT){ |
| 497 | return trCollNames[fnNumber - UTRACE_COLLATION_START]; |
Frank Tang | b869661 | 2019-10-25 14:58:21 -0700 | [diff] [blame] | 498 | } else if(UTRACE_UDATA_START <= fnNumber && fnNumber < UTRACE_RES_DATA_LIMIT){ |
| 499 | return trResDataNames[fnNumber - UTRACE_UDATA_START]; |
jshin@chromium.org | 6f31ac3 | 2014-03-26 22:15:14 +0000 | [diff] [blame] | 500 | } else { |
| 501 | return "[BOGUS Trace Function Number]"; |
| 502 | } |
| 503 | } |
| 504 | |