Changeset 96550 in vbox for trunk/include/iprt
- Timestamp:
- Aug 30, 2022 1:04:57 AM (2 years ago)
- Location:
- trunk/include/iprt
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/iprt/bldprog-strtab-template.cpp.h
r96407 r96550 85 85 86 86 #ifdef BLDPROG_STRTAB_WITH_COMPRESSION 87 # include < algorithm>87 # include <iprt/asm.h> 88 88 # include <map> 89 89 # include <iprt/sanitized/string> 90 # include <vector> 91 92 typedef std::map<std::string, size_t> BLDPROGWORDFREQMAP; 93 typedef BLDPROGWORDFREQMAP::value_type BLDPROGWORDFREQPAIR; 90 91 # define BLDPROG_STRTAB_WITH_WORD_SEP_ALTERNATIVE 92 typedef struct BLDPROGWORDFREQSTATS 93 { 94 uint32_t cWithoutSep; /**< Number of occurances without a separator. */ 95 # ifdef BLDPROG_STRTAB_WITH_WORD_SEP_ALTERNATIVE 96 uint32_t cWithSep; /**< Number of occurance with a separator. */ 97 char chSep; /**< The separator. First come basis. */ 98 # endif 99 } BLDPROGWORDFREQSTATS; 100 101 typedef std::map<std::string, BLDPROGWORDFREQSTATS> BLDPROGWORDFREQMAP; 94 102 95 103 #endif … … 148 156 149 157 #ifdef BLDPROG_STRTAB_WITH_COMPRESSION 150 /** The 127 words we've picked to be indexed by reference.*/151 BLDPROGSTRING aCompDict[ 127];152 /** The frequency of the 127dictionary entries. */153 size_t auCompDictFreq[ 127];158 /** The 256 words we've picked to be indexed by reference. */ 159 BLDPROGSTRING aCompDict[256]; 160 /** The frequency of the 256 dictionary entries. */ 161 size_t auCompDictFreq[256]; 154 162 /** Incoming strings pending compression. */ 155 163 PBLDPROGSTRING *papPendingStrings; … … 161 169 * @todo rewrite in plain C. */ 162 170 BLDPROGWORDFREQMAP Frequencies; 171 /** Map of characters used by input strings. */ 172 uint64_t bmUsedChars[256/64]; 163 173 #endif 164 174 … … 200 210 pThis->cPendingStrings = 0; 201 211 pThis->cMaxPendingStrings = cMaxStrings; 212 memset(pThis->bmUsedChars, 0, sizeof(pThis->bmUsedChars)); 213 ASMBitSet(pThis->bmUsedChars, 0); /* Some parts of the code still thinks zero is a terminator, so don't use it for now. */ 214 # ifndef BLDPROG_STRTAB_PURE_ASCII 215 ASMBitSet(pThis->bmUsedChars, 0xff); /* Reserve escape byte for codepoints above 127. */ 216 # endif 202 217 #endif 203 218 … … 300 315 static void bldProgStrTab_compressorAnalyzeString(PBLDPROGSTRTAB pThis, PBLDPROGSTRING pStr) 301 316 { 317 /* 318 * Mark all the string characters as used. 319 */ 302 320 const char *psz = pStr->pszString; 321 char ch; 322 while ((ch = *psz++) != '\0') 323 ASMBitSet(pThis->bmUsedChars, (uint8_t)ch); 303 324 304 325 /* 305 326 * For now we just consider words. 306 327 */ 307 char ch;328 psz = pStr->pszString; 308 329 while ((ch = *psz) != '\0') 309 330 { … … 314 335 BLDPROGWORDFREQMAP::iterator it = pThis->Frequencies.find(strWord); 315 336 if (it != pThis->Frequencies.end()) 316 it->second += cchWord - 1; 337 { 338 # ifdef BLDPROG_STRTAB_WITH_WORD_SEP_ALTERNATIVE 339 char const chSep = psz[cchWord]; 340 if (chSep != '\0' && (it->second.chSep == chSep || it->second.chSep == '\0')) 341 { 342 it->second.chSep = chSep; 343 it->second.cWithSep++; 344 } 345 else 346 # endif 347 it->second.cWithoutSep++; 348 } 317 349 else 318 pThis->Frequencies[strWord] = 0; 319 320 /** @todo could gain hits by including the space after the word, but that 321 * has the same accounting problems as the two words scenario below. */ 350 { 351 # ifdef BLDPROG_STRTAB_WITH_WORD_SEP_ALTERNATIVE 352 char const chSep = psz[cchWord]; 353 if (chSep != '\0') 354 { 355 BLDPROGWORDFREQSTATS NewWord = { 0, 0, chSep }; 356 pThis->Frequencies[strWord] = NewWord; 357 } 358 else 359 # endif 360 { 361 static BLDPROGWORDFREQSTATS s_NewWord = { 0 }; 362 pThis->Frequencies[strWord] = s_NewWord; 363 } 364 } 322 365 323 366 # if 0 /** @todo need better accounting for overlapping alternatives before this can be enabled. */ … … 525 568 526 569 /* Check for g_aWord matches. */ 527 size_t cchMax = pszSrcEnd - pszSrc; 528 for (unsigned i = 0; i < RT_ELEMENTS(pThis->aCompDict); i++) 529 { 530 size_t cchLen = pThis->aCompDict[i].cchString; 531 if ( cchLen >= cchWord 532 && cchLen <= cchMax 533 && memcmp(pThis->aCompDict[i].pszString, pszSrc, cchLen) == 0) 534 { 535 *pszDst++ = (unsigned char)(0x80 | i); 536 pszSrc += cchLen; 537 cchWord = 0; 538 break; 539 } 540 } 541 542 if (cchWord) 570 if (cchWord > 1) 571 { 572 size_t cchMax = pszSrcEnd - pszSrc; 573 for (unsigned i = 0; i < RT_ELEMENTS(pThis->aCompDict); i++) 574 { 575 size_t cchLen = pThis->aCompDict[i].cchString; 576 if ( cchLen >= cchWord 577 && cchLen <= cchMax 578 && memcmp(pThis->aCompDict[i].pszString, pszSrc, cchLen) == 0) 579 { 580 *pszDst++ = (unsigned char)i; 581 pszSrc += cchLen; 582 cchWord = 0; 583 break; 584 } 585 } 586 } 587 588 if (cchWord > 0) 543 589 { 544 590 /* Copy the current word. */ … … 574 620 575 621 /** 576 * For sorting the frequency fidning in descending order. 577 * 578 * Comparison operators are put outside to make older gcc versions (like 4.1.1 579 * on lnx64-rel) happy. 580 */ 581 class WordFreqSortEntry 622 * Entry in SortedDictionary. 623 * 624 * Uses variable length string member, so not class and allocated via malloc. 625 */ 626 struct SortedDictionaryEntry 627 { 628 size_t m_cchGain; 629 size_t m_cchString; 630 char m_szString[RT_FLEXIBLE_ARRAY]; 631 632 /** Allocates and initializes a new entry. */ 633 static SortedDictionaryEntry *allocate(const char *a_pch, size_t a_cch, size_t a_cchGain, char a_chSep) 634 { 635 size_t cbString = a_cch + !!a_chSep + 1; 636 SortedDictionaryEntry *pNew = (SortedDictionaryEntry *)malloc(RT_UOFFSETOF(SortedDictionaryEntry, m_szString) + cbString); 637 if (pNew) 638 { 639 pNew->m_cchGain = a_cchGain; 640 memcpy(pNew->m_szString, a_pch, a_cch); 641 if (a_chSep) 642 pNew->m_szString[a_cch++] = a_chSep; 643 pNew->m_szString[a_cch] = '\0'; 644 pNew->m_cchString = a_cch; 645 } 646 return pNew; 647 } 648 649 650 /** Compares this dictionary entry with an incoming one. 651 * @retval -1 if this entry is of less worth than the new one. 652 * @retval 0 if this entry is of equal worth to the new one. 653 * @retval +1 if this entry is of more worth than the new one. 654 */ 655 int compare(size_t a_cchGain, size_t a_cchString) 656 { 657 /* Higher gain is preferred of course: */ 658 if (m_cchGain < a_cchGain) 659 return -1; 660 if (m_cchGain > a_cchGain) 661 return 1; 662 663 /* Gain is the same. Prefer the shorter string, as it will result in a shorter string table: */ 664 if (m_cchString > a_cchString) 665 return -1; 666 if (m_cchString < a_cchString) 667 return 1; 668 return 0; 669 } 670 }; 671 672 673 /** 674 * Insertion sort dictionary that keeps the 256 best words. 675 * 676 * Used by bldProgStrTab_compressorDoStringCompression to pick the dictionary 677 * words. 678 */ 679 class SortedDictionary 582 680 { 583 681 public: 584 BLDPROGWORDFREQPAIR const *m_pPair; 585 586 public: 587 WordFreqSortEntry(BLDPROGWORDFREQPAIR const *pPair) : m_pPair(pPair) {} 682 size_t m_cEntries; 683 SortedDictionaryEntry *m_apEntries[256]; 684 685 SortedDictionary() 686 : m_cEntries(0) 687 { 688 for (size_t i = 0; i < RT_ELEMENTS(m_apEntries); i++) 689 m_apEntries[i] = NULL; 690 } 691 692 ~SortedDictionary() 693 { 694 while (m_cEntries > 0) 695 { 696 free(m_apEntries[--m_cEntries]); 697 m_apEntries[m_cEntries] = NULL; 698 } 699 } 700 701 702 /** 703 * Inserts a new entry, if it's worth it. 704 * @returns true on succes, false if out of memory. 705 */ 706 bool insert(const char *a_pchString, size_t a_cchStringBase, size_t a_cchGain, char a_chSep = 0) 707 { 708 size_t const cchString = a_cchStringBase + (a_chSep + 1); 709 710 /* 711 * Drop the insert if the symbol table is full and the insert is less worth the last entry: 712 */ 713 if ( m_cEntries >= RT_ELEMENTS(m_apEntries) 714 && m_apEntries[RT_ELEMENTS(m_apEntries) - 1]->compare(a_cchGain, cchString) >= 0) 715 return true; 716 717 /* 718 * Create a new entry to insert. 719 */ 720 SortedDictionaryEntry *pNewEntry = SortedDictionaryEntry::allocate(a_pchString, a_cchStringBase, a_cchGain, a_chSep); 721 if (!pNewEntry) 722 return false; 723 724 /* 725 * Find the insert point. 726 */ 727 if (m_cEntries == 0) 728 { 729 m_apEntries[0] = pNewEntry; 730 m_cEntries = 1; 731 } 732 else 733 { 734 /* If table is full, drop the last entry before we start (already made 735 sure the incoming entry is preferable to the one were dropping): */ 736 if (m_cEntries >= RT_ELEMENTS(m_apEntries)) 737 { 738 free(m_apEntries[RT_ELEMENTS(m_apEntries) - 1]); 739 m_apEntries[RT_ELEMENTS(m_apEntries) - 1] = NULL; 740 m_cEntries = RT_ELEMENTS(m_apEntries) - 1; 741 } 742 743 /* Find where to insert the new entry: */ 744 /** @todo use binary search. */ 745 size_t i = m_cEntries; 746 while (i > 0 && m_apEntries[i - 1]->compare(a_cchGain, cchString) < 0) 747 i--; 748 749 /* Shift entries to make room and insert the new entry. */ 750 if (i < m_cEntries) 751 memmove(&m_apEntries[i + 1], &m_apEntries[i], (m_cEntries - i) * sizeof(m_apEntries[0])); 752 m_apEntries[i] = pNewEntry; 753 m_cEntries++; 754 } 755 return true; 756 } 588 757 }; 589 590 bool operator == (WordFreqSortEntry const &rLeft, WordFreqSortEntry const &rRight)591 {592 return rLeft.m_pPair->second == rRight.m_pPair->second;593 }594 595 bool operator < (WordFreqSortEntry const &rLeft, WordFreqSortEntry const &rRight)596 {597 return rLeft.m_pPair->second > rRight.m_pPair->second;598 }599 758 600 759 … … 608 767 { 609 768 /* 610 * Sort the frequency analyzis result and pick the top 127 ones. 611 */ 612 std::vector<WordFreqSortEntry> SortMap; 769 * Sort the frequency analyzis result and pick the top entries for any 770 * available dictionary slots. 771 */ 772 SortedDictionary SortedDict; 613 773 for (BLDPROGWORDFREQMAP::iterator it = pThis->Frequencies.begin(); it != pThis->Frequencies.end(); ++it) 614 774 { 615 BLDPROGWORDFREQPAIR const &rPair = *it; 616 SortMap.push_back(WordFreqSortEntry(&rPair)); 617 } 618 619 sort(SortMap.begin(), SortMap.end()); 620 621 size_t cb = 0; 622 size_t i = 0; 623 for (std::vector<WordFreqSortEntry>::iterator it = SortMap.begin(); 624 it != SortMap.end() && i < RT_ELEMENTS(pThis->aCompDict); 625 ++it, i++) 626 { 627 pThis->auCompDictFreq[i] = it->m_pPair->second; 628 pThis->aCompDict[i].cchString = it->m_pPair->first.length(); 775 bool fInsert; 776 size_t const cchString = it->first.length(); 777 # ifndef BLDPROG_STRTAB_WITH_WORD_SEP_ALTERNATIVE 778 size_t const cchGainWithout = it->second.cWithoutSep * cchString; 779 # else 780 size_t const cchGainWithout = (it->second.cWithoutSep + it->second.cWithSep) * cchString; 781 size_t const cchGainWith = it->second.cWithSep * (cchString + 1); 782 if (cchGainWith > cchGainWithout) 783 fInsert = SortedDict.insert(it->first.c_str(), cchString, cchGainWith, it->second.chSep); 784 else 785 # endif 786 fInsert = SortedDict.insert(it->first.c_str(), cchString, cchGainWithout); 787 if (!fInsert) 788 return false; 789 } 790 791 size_t cb = 0; 792 size_t cWords = 0; 793 size_t iDict = 0; 794 for (size_t i = 0; i < RT_ELEMENTS(pThis->aCompDict); i++) 795 { 796 char szTmp[2] = { (char)i, '\0' }; 797 const char *psz = szTmp; 798 if ( ASMBitTest(pThis->bmUsedChars, (int32_t)i) 799 || iDict >= SortedDict.m_cEntries) 800 { 801 /* character entry */ 802 pThis->auCompDictFreq[i] = 0; 803 pThis->aCompDict[i].cchString = 1; 804 } 805 else 806 { 807 /* word entry */ 808 cb += SortedDict.m_apEntries[iDict]->m_cchGain; 809 pThis->auCompDictFreq[i] = SortedDict.m_apEntries[iDict]->m_cchGain; 810 pThis->aCompDict[i].cchString = SortedDict.m_apEntries[iDict]->m_cchString; 811 psz = SortedDict.m_apEntries[iDict]->m_szString; 812 cWords++; 813 iDict++; 814 } 629 815 pThis->aCompDict[i].pszString = (char *)malloc(pThis->aCompDict[i].cchString + 1); 630 816 if (pThis->aCompDict[i].pszString) 631 memcpy(pThis->aCompDict[i].pszString, it->m_pPair->first.c_str(), pThis->aCompDict[i].cchString + 1);817 memcpy(pThis->aCompDict[i].pszString, psz, pThis->aCompDict[i].cchString + 1); 632 818 else 633 819 return false; 634 cb += it->m_pPair->second;635 820 } 636 821 637 822 if (fVerbose) 638 printf("debug: Estimated string compression saving: %u bytes\n", (unsigned)cb); 823 printf("debug: Estimated string compression saving: %u bytes\n" 824 "debug: %u words, %u characters\n" 825 , (unsigned)cb, (unsigned)cWords, (unsigned)(RT_ELEMENTS(pThis->aCompDict) - cWords)); 639 826 640 827 /* … … 647 834 size_t cchNewMax = 0; 648 835 size_t cchNewMin = BLDPROG_STRTAB_MAX_STRLEN; 649 i= pThis->cPendingStrings;836 size_t i = pThis->cPendingStrings; 650 837 while (i-- > 0) 651 838 { … … 760 947 */ 761 948 for (unsigned i = 0; i < RT_ELEMENTS(pThis->aCompDict); i++) 762 bldProgStrTab_AddStringToHashTab(pThis, &pThis->aCompDict[i]); 949 if (pThis->aCompDict[i].cchString > 1) 950 bldProgStrTab_AddStringToHashTab(pThis, &pThis->aCompDict[i]); 951 # ifdef RT_STRICT 952 else if (pThis->aCompDict[i].cchString != 1) 953 abort(); 954 # endif 763 955 #endif 764 956 if (fVerbose) … … 799 991 for (size_t i = 0; i < pThis->cSortedStrings; i++) 800 992 { 801 PBLDPROGSTRING pCur= pThis->papSortedStrings[i];993 PBLDPROGSTRING pCur = pThis->papSortedStrings[i]; 802 994 const char * const pszCur = pCur->pszString; 803 995 size_t const cchCur = pCur->cchString; … … 914 1106 while ((uch = *psz++) != '\0') 915 1107 { 1108 #ifdef BLDPROG_STRTAB_WITH_COMPRESSION 1109 if (pThis->aCompDict[uch].cchString == 1) 1110 #else 916 1111 if (!(uch & 0x80)) 1112 #endif 917 1113 { 918 1114 if (uch != '\'' && uch != '\\') … … 925 1121 } 926 1122 #ifdef BLDPROG_STRTAB_WITH_COMPRESSION 927 else if (uch != 0xff) 928 fputs(pThis->aCompDict[uch & 0x7f].pszString, pOut); 929 else 930 { 931 # ifdef BLDPROG_STRTAB_PURE_ASCII 932 abort(); 933 # else 1123 # ifndef BLDPROG_STRTAB_PURE_ASCII 1124 else if (uch == 0xff) 1125 { 934 1126 RTUNICP uc = RTStrGetCp((const char *)psz); 935 1127 psz += RTStrCpSize(uc); 936 1128 fprintf(pOut, "\\u%04x", uc); 937 # endif 938 } 1129 } 1130 # else 1131 else 1132 fputs(pThis->aCompDict[uch].pszString, pOut); 1133 # endif 939 1134 #else 940 1135 else … … 968 1163 # ifdef BLDPROG_STRTAB_WITH_COMPRESSION 969 1164 for (unsigned i = 0; i < RT_ELEMENTS(pThis->aCompDict); i++) 970 BldProgStrTab_CheckStrTabString(pThis, &pThis->aCompDict[i]); 1165 { 1166 if (ASMBitTest(pThis->bmUsedChars, (int32_t)i) 1167 ? pThis->aCompDict[i].cchString != 1 : pThis->aCompDict[i].cchString < 1) 1168 abort(); 1169 if (pThis->aCompDict[i].cchString > 1) 1170 BldProgStrTab_CheckStrTabString(pThis, &pThis->aCompDict[i]); 1171 } 971 1172 # endif 972 1173 #endif … … 983 1184 for (unsigned i = 0x7f; i < 0x100; i++) 984 1185 abCharCat[i] = 2; 1186 #ifdef BLDPROG_STRTAB_WITH_COMPRESSION 1187 for (unsigned i = 0; i < 0x100; i++) 1188 if (!ASMBitTest(pThis->bmUsedChars, (int32_t)i)) /* Encode table references using '\xYY'. */ 1189 abCharCat[i] = 2; 1190 #endif 985 1191 986 1192 /* … … 1001 1207 if (offEnd > off) 1002 1208 { 1003 /* Comment with a uncompressed and more readable version of the string. */1209 /* Comment with an uncompressed and more readable version of the string. */ 1004 1210 if (off == pCur->offStrTab) 1005 1211 fprintf(pOut, "/* 0x%05x = \"", off); … … 1046 1252 pszBaseName, (unsigned)RT_ELEMENTS(pThis->aCompDict)); 1047 1253 for (unsigned i = 0; i < RT_ELEMENTS(pThis->aCompDict); i++) 1048 fprintf(pOut, " { %#08x, %#04x }, // %6lu - %s\n", 1049 pThis->aCompDict[i].offStrTab, (unsigned)pThis->aCompDict[i].cchString, 1050 (unsigned long)pThis->auCompDictFreq[i], pThis->aCompDict[i].pszString); 1254 if (pThis->aCompDict[i].cchString > 1) 1255 fprintf(pOut, " /*[%3u]=*/ { %#08x, %#04x }, // %6lu - %s\n", i, 1256 pThis->aCompDict[i].offStrTab, (unsigned)pThis->aCompDict[i].cchString, 1257 (unsigned long)pThis->auCompDictFreq[i], pThis->aCompDict[i].pszString); 1258 # ifndef BLDPROG_STRTAB_PURE_ASCII 1259 else if (i == 0xff) 1260 fprintf(pOut, " /*[%3u]=*/ { 0x000000, 0x00 }, // UTF-8 escape\n", i); 1261 # endif 1262 else if (i == 0) 1263 fprintf(pOut, " /*[%3u]=*/ { 0x000000, 0x00 }, // unused, because zero terminator\n", i); 1264 else if (i < 0x20) 1265 fprintf(pOut, " /*[%3u]=*/ { 0x000000, 0x00 }, // %02x\n", i, i); 1266 else 1267 fprintf(pOut, " /*[%3u]=*/ { 0x000000, 0x00 }, // '%c'\n", i, (char)i); 1051 1268 fprintf(pOut, "};\n\n"); 1052 1269 #endif … … 1068 1285 " /*.paCompDict = */ &g_aCompDict%s[0]\n" 1069 1286 "};\n" 1070 , (unsigned)RT_ELEMENTS(pThis->aCompDict), pszBaseName); 1287 # ifndef BLDPROG_STRTAB_PURE_ASCII /* 255 or 256 entries is how the decoder knows */ 1288 , (unsigned)RT_ELEMENTS(pThis->aCompDict) - 1, 1289 # else 1290 , (unsigned)RT_ELEMENTS(pThis->aCompDict), 1291 # endif 1292 pszBaseName); 1071 1293 #else 1072 1294 fprintf(pOut, -
trunk/include/iprt/bldprog-strtab.h
r96407 r96550 64 64 const char *pchStrTab; 65 65 uint32_t cchStrTab; 66 uint 8_tcCompDict;66 uint32_t cCompDict; 67 67 PCRTBLDPROGSTRREF paCompDict; 68 68 } RTBLDPROGSTRTAB; … … 101 101 if (pStrTab->cCompDict) 102 102 { 103 Assert(pStrTab->cCompDict == 256 || pStrTab->cCompDict == 255); 104 103 105 /* 104 * Could becompressed, decompress it.106 * Is compressed, decompress it. 105 107 */ 106 108 char * const pchDstStart = pszDst; … … 109 111 { 110 112 unsigned char uch = *(unsigned char *)pchSrc++; 111 if (!(uch & 0x80)) 112 { 113 /* 114 * Plain text. 115 */ 116 AssertReturn(cbDst > 1, RTBldProgStrTabQueryStringFail(VERR_BUFFER_OVERFLOW, pchDstStart, pszDst, cbDst)); 117 cbDst -= 1; 118 *pszDst++ = (char)uch; 119 Assert(uch != 0); 120 } 121 else if (uch != 0xff) 122 { 123 /* 124 * Dictionary reference. (No UTF-8 unescaping necessary here.) 125 */ 126 PCRTBLDPROGSTRREF pWord = &pStrTab->paCompDict[uch & 0x7f]; 113 if (uch != 0xff || pStrTab->cCompDict > 0xff) 114 { 115 /* 116 * Look it up in the dictionary, either a single 7-bit character or a word. 117 * Either way, no UTF-8 unescaping necessary. 118 */ 119 PCRTBLDPROGSTRREF pWord = &pStrTab->paCompDict[uch]; 127 120 size_t const cchWord = pWord->cch; 128 AssertReturn((size_t)pWord->off + cchWord <= pStrTab->cchStrTab, 129 RTBldProgStrTabQueryStringFail(VERR_INVALID_PARAMETER, pchDstStart, pszDst, cbDst)); 130 AssertReturn(cbDst > cchWord, 131 RTBldProgStrTabQueryStringFail(VERR_BUFFER_OVERFLOW, pchDstStart, pszDst, cbDst)); 132 memcpy(pszDst, &pStrTab->pchStrTab[pWord->off], cchWord); 133 pszDst += cchWord; 134 cbDst -= cchWord; 121 if (cchWord <= 1) 122 { 123 Assert(uch != 0); 124 Assert(uch <= 127); 125 AssertReturn(cbDst > 1, RTBldProgStrTabQueryStringFail(VERR_BUFFER_OVERFLOW, pchDstStart, pszDst, cbDst)); 126 cbDst -= 1; 127 *pszDst++ = (char)uch; 128 } 129 else 130 { 131 Assert(cchWord > 1); 132 AssertReturn((size_t)pWord->off + cchWord <= pStrTab->cchStrTab, 133 RTBldProgStrTabQueryStringFail(VERR_INVALID_PARAMETER, pchDstStart, pszDst, cbDst)); 134 AssertReturn(cbDst > cchWord, 135 RTBldProgStrTabQueryStringFail(VERR_BUFFER_OVERFLOW, pchDstStart, pszDst, cbDst)); 136 memcpy(pszDst, &pStrTab->pchStrTab[pWord->off], cchWord); 137 pszDst += cchWord; 138 cbDst -= cchWord; 139 } 135 140 } 136 141 else … … 195 200 if (pStrTab->cCompDict) 196 201 { 202 Assert(pStrTab->cCompDict == 256 || pStrTab->cCompDict == 255); 203 197 204 /* 198 205 * Could be compressed, decompress it. … … 203 210 { 204 211 unsigned char uch = *(unsigned char *)pchSrc++; 205 if (!(uch & 0x80)) 206 { 207 /* 208 * Plain text. 209 */ 210 Assert(uch != 0); 211 cchRet += pfnOutput(pvArgOutput, (const char *)&uch, 1); 212 } 213 else if (uch != 0xff) 214 { 215 /* 216 * Dictionary reference. (No UTF-8 unescaping necessary here.) 217 */ 218 PCRTBLDPROGSTRREF pWord = &pStrTab->paCompDict[uch & 0x7f]; 212 if (uch != 0xff || pStrTab->cCompDict > 0xff) 213 { 214 /* 215 * Look it up in the dictionary, either a single 7-bit character or a word. 216 * Either way, no UTF-8 unescaping necessary. 217 */ 218 PCRTBLDPROGSTRREF pWord = &pStrTab->paCompDict[uch]; 219 219 size_t const cchWord = pWord->cch; 220 AssertReturn((size_t)pWord->off + cchWord <= pStrTab->cchStrTab, cchRet); 221 222 cchRet += pfnOutput(pvArgOutput, &pStrTab->pchStrTab[pWord->off], cchWord); 220 if (cchWord <= 1) 221 { 222 Assert(uch != 0); 223 Assert(uch <= 127); 224 cchRet += pfnOutput(pvArgOutput, (const char *)&uch, 1); 225 } 226 else 227 { 228 Assert(cchWord > 1); 229 AssertReturn((size_t)pWord->off + cchWord <= pStrTab->cchStrTab, cchRet); 230 231 cchRet += pfnOutput(pvArgOutput, &pStrTab->pchStrTab[pWord->off], cchWord); 232 } 223 233 } 224 234 else
Note:
See TracChangeset
for help on using the changeset viewer.