1442 const void* dict, size_t dictSize) |
1442 const void* dict, size_t dictSize) |
1443 { |
1443 { |
1444 #if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT==1) |
1444 #if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT==1) |
1445 if (ZSTD_isLegacy(src, srcSize)) return ZSTD_decompressLegacy(dst, dstCapacity, src, srcSize, dict, dictSize); |
1445 if (ZSTD_isLegacy(src, srcSize)) return ZSTD_decompressLegacy(dst, dstCapacity, src, srcSize, dict, dictSize); |
1446 #endif |
1446 #endif |
1447 ZSTD_decompressBegin_usingDict(dctx, dict, dictSize); |
1447 CHECK_F(ZSTD_decompressBegin_usingDict(dctx, dict, dictSize)); |
1448 ZSTD_checkContinuity(dctx, dst); |
1448 ZSTD_checkContinuity(dctx, dst); |
1449 return ZSTD_decompressFrame(dctx, dst, dstCapacity, src, srcSize); |
1449 return ZSTD_decompressFrame(dctx, dst, dstCapacity, src, srcSize); |
1450 } |
1450 } |
1451 |
1451 |
1452 |
1452 |
1669 CHECK_E(FSE_buildDTable(dctx->LLTable, litlengthNCount, litlengthMaxValue, litlengthLog), dictionary_corrupted); |
1669 CHECK_E(FSE_buildDTable(dctx->LLTable, litlengthNCount, litlengthMaxValue, litlengthLog), dictionary_corrupted); |
1670 dictPtr += litlengthHeaderSize; |
1670 dictPtr += litlengthHeaderSize; |
1671 } |
1671 } |
1672 |
1672 |
1673 if (dictPtr+12 > dictEnd) return ERROR(dictionary_corrupted); |
1673 if (dictPtr+12 > dictEnd) return ERROR(dictionary_corrupted); |
1674 dctx->rep[0] = MEM_readLE32(dictPtr+0); if (dctx->rep[0] >= dictSize) return ERROR(dictionary_corrupted); |
1674 dctx->rep[0] = MEM_readLE32(dictPtr+0); if (dctx->rep[0] == 0 || dctx->rep[0] >= dictSize) return ERROR(dictionary_corrupted); |
1675 dctx->rep[1] = MEM_readLE32(dictPtr+4); if (dctx->rep[1] >= dictSize) return ERROR(dictionary_corrupted); |
1675 dctx->rep[1] = MEM_readLE32(dictPtr+4); if (dctx->rep[1] == 0 || dctx->rep[1] >= dictSize) return ERROR(dictionary_corrupted); |
1676 dctx->rep[2] = MEM_readLE32(dictPtr+8); if (dctx->rep[2] >= dictSize) return ERROR(dictionary_corrupted); |
1676 dctx->rep[2] = MEM_readLE32(dictPtr+8); if (dctx->rep[2] == 0 || dctx->rep[2] >= dictSize) return ERROR(dictionary_corrupted); |
1677 dictPtr += 12; |
1677 dictPtr += 12; |
1678 |
1678 |
1679 dctx->litEntropy = dctx->fseEntropy = 1; |
1679 dctx->litEntropy = dctx->fseEntropy = 1; |
1680 return dictPtr - (const BYTE*)dict; |
1680 return dictPtr - (const BYTE*)dict; |
1681 } |
1681 } |
1711 |
1711 |
1712 |
1712 |
1713 /* ====== ZSTD_DDict ====== */ |
1713 /* ====== ZSTD_DDict ====== */ |
1714 |
1714 |
1715 struct ZSTD_DDict_s { |
1715 struct ZSTD_DDict_s { |
1716 void* dict; |
1716 void* dictBuffer; |
|
1717 const void* dictContent; |
1717 size_t dictSize; |
1718 size_t dictSize; |
1718 ZSTD_DCtx* refContext; |
1719 ZSTD_DCtx* refContext; |
1719 }; /* typedef'd to ZSTD_DDict within "zstd.h" */ |
1720 }; /* typedef'd to ZSTD_DDict within "zstd.h" */ |
1720 |
1721 |
1721 ZSTD_DDict* ZSTD_createDDict_advanced(const void* dict, size_t dictSize, ZSTD_customMem customMem) |
1722 ZSTD_DDict* ZSTD_createDDict_advanced(const void* dict, size_t dictSize, unsigned byReference, ZSTD_customMem customMem) |
1722 { |
1723 { |
1723 if (!customMem.customAlloc && !customMem.customFree) customMem = defaultCustomMem; |
1724 if (!customMem.customAlloc && !customMem.customFree) customMem = defaultCustomMem; |
1724 if (!customMem.customAlloc || !customMem.customFree) return NULL; |
1725 if (!customMem.customAlloc || !customMem.customFree) return NULL; |
1725 |
1726 |
1726 { ZSTD_DDict* const ddict = (ZSTD_DDict*) ZSTD_malloc(sizeof(ZSTD_DDict), customMem); |
1727 { ZSTD_DDict* const ddict = (ZSTD_DDict*) ZSTD_malloc(sizeof(ZSTD_DDict), customMem); |
1727 void* const dictContent = ZSTD_malloc(dictSize, customMem); |
|
1728 ZSTD_DCtx* const dctx = ZSTD_createDCtx_advanced(customMem); |
1728 ZSTD_DCtx* const dctx = ZSTD_createDCtx_advanced(customMem); |
1729 |
1729 |
1730 if (!dictContent || !ddict || !dctx) { |
1730 if (!ddict || !dctx) { |
1731 ZSTD_free(dictContent, customMem); |
|
1732 ZSTD_free(ddict, customMem); |
1731 ZSTD_free(ddict, customMem); |
1733 ZSTD_free(dctx, customMem); |
1732 ZSTD_free(dctx, customMem); |
1734 return NULL; |
1733 return NULL; |
1735 } |
1734 } |
1736 |
1735 |
1737 if (dictSize) { |
1736 if ((byReference) || (!dict) || (!dictSize)) { |
1738 memcpy(dictContent, dict, dictSize); |
1737 ddict->dictBuffer = NULL; |
1739 } |
1738 ddict->dictContent = dict; |
1740 { size_t const errorCode = ZSTD_decompressBegin_usingDict(dctx, dictContent, dictSize); |
1739 } else { |
|
1740 void* const internalBuffer = ZSTD_malloc(dictSize, customMem); |
|
1741 if (!internalBuffer) { ZSTD_free(dctx, customMem); ZSTD_free(ddict, customMem); return NULL; } |
|
1742 memcpy(internalBuffer, dict, dictSize); |
|
1743 ddict->dictBuffer = internalBuffer; |
|
1744 ddict->dictContent = internalBuffer; |
|
1745 } |
|
1746 { size_t const errorCode = ZSTD_decompressBegin_usingDict(dctx, ddict->dictContent, dictSize); |
1741 if (ZSTD_isError(errorCode)) { |
1747 if (ZSTD_isError(errorCode)) { |
1742 ZSTD_free(dictContent, customMem); |
1748 ZSTD_free(ddict->dictBuffer, customMem); |
1743 ZSTD_free(ddict, customMem); |
1749 ZSTD_free(ddict, customMem); |
1744 ZSTD_free(dctx, customMem); |
1750 ZSTD_free(dctx, customMem); |
1745 return NULL; |
1751 return NULL; |
1746 } } |
1752 } } |
1747 |
1753 |
1748 ddict->dict = dictContent; |
|
1749 ddict->dictSize = dictSize; |
1754 ddict->dictSize = dictSize; |
1750 ddict->refContext = dctx; |
1755 ddict->refContext = dctx; |
1751 return ddict; |
1756 return ddict; |
1752 } |
1757 } |
1753 } |
1758 } |
1756 * Create a digested dictionary, ready to start decompression without startup delay. |
1761 * Create a digested dictionary, ready to start decompression without startup delay. |
1757 * `dict` can be released after `ZSTD_DDict` creation */ |
1762 * `dict` can be released after `ZSTD_DDict` creation */ |
1758 ZSTD_DDict* ZSTD_createDDict(const void* dict, size_t dictSize) |
1763 ZSTD_DDict* ZSTD_createDDict(const void* dict, size_t dictSize) |
1759 { |
1764 { |
1760 ZSTD_customMem const allocator = { NULL, NULL, NULL }; |
1765 ZSTD_customMem const allocator = { NULL, NULL, NULL }; |
1761 return ZSTD_createDDict_advanced(dict, dictSize, allocator); |
1766 return ZSTD_createDDict_advanced(dict, dictSize, 0, allocator); |
1762 } |
1767 } |
|
1768 |
|
1769 |
|
1770 /*! ZSTD_createDDict_byReference() : |
|
1771 * Create a digested dictionary, ready to start decompression operation without startup delay. |
|
1772 * Dictionary content is simply referenced, and therefore stays in dictBuffer. |
|
1773 * It is important that dictBuffer outlives DDict, it must remain read accessible throughout the lifetime of DDict */ |
|
1774 ZSTD_DDict* ZSTD_createDDict_byReference(const void* dictBuffer, size_t dictSize) |
|
1775 { |
|
1776 ZSTD_customMem const allocator = { NULL, NULL, NULL }; |
|
1777 return ZSTD_createDDict_advanced(dictBuffer, dictSize, 1, allocator); |
|
1778 } |
|
1779 |
1763 |
1780 |
1764 size_t ZSTD_freeDDict(ZSTD_DDict* ddict) |
1781 size_t ZSTD_freeDDict(ZSTD_DDict* ddict) |
1765 { |
1782 { |
1766 if (ddict==NULL) return 0; /* support free on NULL */ |
1783 if (ddict==NULL) return 0; /* support free on NULL */ |
1767 { ZSTD_customMem const cMem = ddict->refContext->customMem; |
1784 { ZSTD_customMem const cMem = ddict->refContext->customMem; |
1768 ZSTD_freeDCtx(ddict->refContext); |
1785 ZSTD_freeDCtx(ddict->refContext); |
1769 ZSTD_free(ddict->dict, cMem); |
1786 ZSTD_free(ddict->dictBuffer, cMem); |
1770 ZSTD_free(ddict, cMem); |
1787 ZSTD_free(ddict, cMem); |
1771 return 0; |
1788 return 0; |
1772 } |
1789 } |
1773 } |
1790 } |
1774 |
1791 |
1775 size_t ZSTD_sizeof_DDict(const ZSTD_DDict* ddict) |
1792 size_t ZSTD_sizeof_DDict(const ZSTD_DDict* ddict) |
1776 { |
1793 { |
1777 if (ddict==NULL) return 0; /* support sizeof on NULL */ |
1794 if (ddict==NULL) return 0; /* support sizeof on NULL */ |
1778 return sizeof(*ddict) + sizeof(ddict->refContext) + ddict->dictSize; |
1795 return sizeof(*ddict) + ZSTD_sizeof_DCtx(ddict->refContext) + (ddict->dictBuffer ? ddict->dictSize : 0) ; |
1779 } |
1796 } |
1780 |
1797 |
1781 /*! ZSTD_getDictID_fromDict() : |
1798 /*! ZSTD_getDictID_fromDict() : |
1782 * Provides the dictID stored within dictionary. |
1799 * Provides the dictID stored within dictionary. |
1783 * if @return == 0, the dictionary is not conformant with Zstandard specification. |
1800 * if @return == 0, the dictionary is not conformant with Zstandard specification. |
1794 * If @return == 0, the dictionary is not conformant to Zstandard specification, or empty. |
1811 * If @return == 0, the dictionary is not conformant to Zstandard specification, or empty. |
1795 * Non-conformant dictionaries can still be loaded, but as content-only dictionaries. */ |
1812 * Non-conformant dictionaries can still be loaded, but as content-only dictionaries. */ |
1796 unsigned ZSTD_getDictID_fromDDict(const ZSTD_DDict* ddict) |
1813 unsigned ZSTD_getDictID_fromDDict(const ZSTD_DDict* ddict) |
1797 { |
1814 { |
1798 if (ddict==NULL) return 0; |
1815 if (ddict==NULL) return 0; |
1799 return ZSTD_getDictID_fromDict(ddict->dict, ddict->dictSize); |
1816 return ZSTD_getDictID_fromDict(ddict->dictContent, ddict->dictSize); |
1800 } |
1817 } |
1801 |
1818 |
1802 /*! ZSTD_getDictID_fromFrame() : |
1819 /*! ZSTD_getDictID_fromFrame() : |
1803 * Provides the dictID required to decompressed the frame stored within `src`. |
1820 * Provides the dictID required to decompressed the frame stored within `src`. |
1804 * If @return == 0, the dictID could not be decoded. |
1821 * If @return == 0, the dictID could not be decoded. |
1825 void* dst, size_t dstCapacity, |
1842 void* dst, size_t dstCapacity, |
1826 const void* src, size_t srcSize, |
1843 const void* src, size_t srcSize, |
1827 const ZSTD_DDict* ddict) |
1844 const ZSTD_DDict* ddict) |
1828 { |
1845 { |
1829 #if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT==1) |
1846 #if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT==1) |
1830 if (ZSTD_isLegacy(src, srcSize)) return ZSTD_decompressLegacy(dst, dstCapacity, src, srcSize, ddict->dict, ddict->dictSize); |
1847 if (ZSTD_isLegacy(src, srcSize)) return ZSTD_decompressLegacy(dst, dstCapacity, src, srcSize, ddict->dictContent, ddict->dictSize); |
1831 #endif |
1848 #endif |
1832 ZSTD_refDCtx(dctx, ddict->refContext); |
1849 ZSTD_refDCtx(dctx, ddict->refContext); |
1833 ZSTD_checkContinuity(dctx, dst); |
1850 ZSTD_checkContinuity(dctx, dst); |
1834 return ZSTD_decompressFrame(dctx, dst, dstCapacity, src, srcSize); |
1851 return ZSTD_decompressFrame(dctx, dst, dstCapacity, src, srcSize); |
1835 } |
1852 } |
1917 size_t ZSTD_initDStream_usingDict(ZSTD_DStream* zds, const void* dict, size_t dictSize) |
1934 size_t ZSTD_initDStream_usingDict(ZSTD_DStream* zds, const void* dict, size_t dictSize) |
1918 { |
1935 { |
1919 zds->stage = zdss_loadHeader; |
1936 zds->stage = zdss_loadHeader; |
1920 zds->lhSize = zds->inPos = zds->outStart = zds->outEnd = 0; |
1937 zds->lhSize = zds->inPos = zds->outStart = zds->outEnd = 0; |
1921 ZSTD_freeDDict(zds->ddictLocal); |
1938 ZSTD_freeDDict(zds->ddictLocal); |
1922 if (dict) { |
1939 if (dict && dictSize >= 8) { |
1923 zds->ddictLocal = ZSTD_createDDict(dict, dictSize); |
1940 zds->ddictLocal = ZSTD_createDDict(dict, dictSize); |
1924 if (zds->ddictLocal == NULL) return ERROR(memory_allocation); |
1941 if (zds->ddictLocal == NULL) return ERROR(memory_allocation); |
1925 } else zds->ddictLocal = NULL; |
1942 } else zds->ddictLocal = NULL; |
1926 zds->ddict = zds->ddictLocal; |
1943 zds->ddict = zds->ddictLocal; |
1927 zds->legacyVersion = 0; |
1944 zds->legacyVersion = 0; |
2005 { size_t const hSize = ZSTD_getFrameParams(&zds->fParams, zds->headerBuffer, zds->lhSize); |
2022 { size_t const hSize = ZSTD_getFrameParams(&zds->fParams, zds->headerBuffer, zds->lhSize); |
2006 if (ZSTD_isError(hSize)) |
2023 if (ZSTD_isError(hSize)) |
2007 #if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT>=1) |
2024 #if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT>=1) |
2008 { U32 const legacyVersion = ZSTD_isLegacy(istart, iend-istart); |
2025 { U32 const legacyVersion = ZSTD_isLegacy(istart, iend-istart); |
2009 if (legacyVersion) { |
2026 if (legacyVersion) { |
2010 const void* const dict = zds->ddict ? zds->ddict->dict : NULL; |
2027 const void* const dict = zds->ddict ? zds->ddict->dictContent : NULL; |
2011 size_t const dictSize = zds->ddict ? zds->ddict->dictSize : 0; |
2028 size_t const dictSize = zds->ddict ? zds->ddict->dictSize : 0; |
2012 CHECK_F(ZSTD_initLegacyStream(&zds->legacyContext, zds->previousLegacyVersion, legacyVersion, |
2029 CHECK_F(ZSTD_initLegacyStream(&zds->legacyContext, zds->previousLegacyVersion, legacyVersion, |
2013 dict, dictSize)); |
2030 dict, dictSize)); |
2014 zds->legacyVersion = zds->previousLegacyVersion = legacyVersion; |
2031 zds->legacyVersion = zds->previousLegacyVersion = legacyVersion; |
2015 return ZSTD_decompressLegacyStream(zds->legacyContext, zds->legacyVersion, output, input); |
2032 return ZSTD_decompressLegacyStream(zds->legacyContext, zds->legacyVersion, output, input); |