| 489 | { |
| 490 | |
| 491 | DescPrinter::DescPrinter(thread_db* tdbb, const dsc* desc, FB_SIZE_T mLen, USHORT charSetId) |
| 492 | : maxLen(mLen) |
| 493 | { |
| 494 | const char* const NULL_KEY_STRING = "NULL"; |
| 495 | |
| 496 | if (!desc) |
| 497 | { |
| 498 | value = NULL_KEY_STRING; |
| 499 | return; |
| 500 | } |
| 501 | |
| 502 | fb_assert(!desc->isBlob()); |
| 503 | |
| 504 | const bool isBinary = (desc->isText() && desc->getCharSet() == CS_BINARY); |
| 505 | value = MOV_make_string2(tdbb, desc, isBinary ? CS_BINARY : charSetId); |
| 506 | |
| 507 | const char* const str = value.c_str(); |
| 508 | |
| 509 | if (desc->isText() || desc->isDateTime()) |
| 510 | { |
| 511 | if (desc->dsc_dtype == dtype_text) |
| 512 | { |
| 513 | const char* const pad = (desc->getCharSet() == CS_BINARY) ? "\0" : " "; |
| 514 | value.rtrim(pad); |
| 515 | } |
| 516 | |
| 517 | if (isBinary) |
| 518 | { |
| 519 | string hex; |
| 520 | |
| 521 | FB_SIZE_T len = value.length(); |
| 522 | const bool cut = (len > (maxLen - 3) / 2); // 3 is a length of enclosing symbols: x' and ' |
| 523 | if (cut) |
| 524 | len = (maxLen - 5) / 2; // 5 is a length of enclosing symbols: x' and ... |
| 525 | |
| 526 | char* s = hex.getBuffer(2 * len); // each raw byte represented by 2 chars in string |
| 527 | |
| 528 | for (FB_SIZE_T i = 0; i < len; i++) |
| 529 | { |
| 530 | sprintf(s, "%02X", (int)(unsigned char) str[i]); |
| 531 | s += 2; |
| 532 | } |
| 533 | value = "x'" + hex + (cut ? "..." : "'"); |
| 534 | } |
| 535 | else |
| 536 | value = "'" + value + "'"; |
| 537 | } |
| 538 | |
| 539 | if (value.length() > maxLen) |
| 540 | { |
| 541 | fb_assert(desc->isText()); |
| 542 | |
| 543 | value.resize(maxLen); |
| 544 | |
| 545 | const CharSet* const cs = INTL_charset_lookup(tdbb, charSetId); |
| 546 | |
| 547 | while (value.hasData() && !cs->wellFormed(value.length(), (const UCHAR*) value.c_str())) |
| 548 | value.resize(value.length() - 1); |
nothing calls this directly
no test coverage detected