1 /**************************************************************************
3 * Copyright 2013-2014 RAD Game Tools and Valve Software
4 * Copyright 2010-2014 Rich Geldreich and Tenacious Software LLC
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 **************************************************************************/
27 // File: vogl_lzma_codec.cpp
28 #include "vogl_core.h"
29 #include "vogl_lzma_codec.h"
30 #include "vogl_strutils.h"
31 #include "vogl_checksum.h"
32 #include "lzma_LzmaLib.h"
33 #include "vogl_threading.h"
37 lzma_codec::lzma_codec()
38 : m_pCompress(LzmaCompress),
39 m_pUncompress(LzmaUncompress)
41 VOGL_ASSUME(cLZMAPropsSize == LZMA_PROPS_SIZE);
44 lzma_codec::~lzma_codec()
48 bool lzma_codec::pack(const void *p, uint n, vogl::vector<uint8> &buf)
50 if (n > 1024U * 1024U * 1024U)
53 uint max_comp_size = n + math::maximum<uint>(128, n >> 8);
54 buf.resize(sizeof(header) + max_comp_size);
56 header *pHDR = reinterpret_cast<header *>(&buf[0]);
57 uint8 *pComp_data = &buf[sizeof(header)];
59 utils::zero_object(*pHDR);
61 pHDR->m_uncomp_size = n;
62 pHDR->m_adler32 = adler32(p, n);
67 size_t outPropsSize = 0;
68 int status = SZ_ERROR_INPUT_EOF;
70 for (uint trial = 0; trial < 3; trial++)
72 destLen = max_comp_size;
73 outPropsSize = cLZMAPropsSize;
75 status = (*m_pCompress)(pComp_data, &destLen, reinterpret_cast<const unsigned char *>(p), n,
76 pHDR->m_lzma_props, &outPropsSize,
77 -1, /* 0 <= level <= 9, default = 5 */
78 0, /* default = (1 << 24) */
79 -1, /* 0 <= lc <= 8, default = 3 */
80 -1, /* 0 <= lp <= 4, default = 0 */
81 -1, /* 0 <= pb <= 4, default = 2 */
82 -1, /* 5 <= fb <= 273, default = 32 */
84 (g_number_of_processors > 1) ? 2 : 1
90 if (status != SZ_ERROR_OUTPUT_EOF)
93 max_comp_size += ((n + 1) / 2);
94 buf.resize(sizeof(header) + max_comp_size);
95 pHDR = reinterpret_cast<header *>(&buf[0]);
96 pComp_data = &buf[sizeof(header)];
105 pHDR->m_comp_size = static_cast<uint>(destLen);
107 buf.resize(VOGL_SIZEOF_U32(header) + static_cast<uint32>(destLen));
110 pHDR->m_sig = header::cSig;
111 pHDR->m_checksum = static_cast<uint8>(adler32((uint8 *)pHDR + header::cChecksumSkipBytes, sizeof(header) - header::cChecksumSkipBytes));
116 bool lzma_codec::unpack(const void *p, uint n, vogl::vector<uint8> &buf)
120 if (n < sizeof(header))
123 const header &hdr = *static_cast<const header *>(p);
124 if (hdr.m_sig != header::cSig)
127 if (static_cast<uint8>(adler32((const uint8 *)&hdr + header::cChecksumSkipBytes, sizeof(hdr) - header::cChecksumSkipBytes)) != hdr.m_checksum)
130 if (!hdr.m_uncomp_size)
133 if (!hdr.m_comp_size)
136 if (hdr.m_uncomp_size > 1024U * 1024U * 1024U)
139 if (!buf.try_resize(hdr.m_uncomp_size))
142 const uint8 *pComp_data = static_cast<const uint8 *>(p) + sizeof(header);
143 size_t srcLen = n - sizeof(header);
144 if (srcLen < hdr.m_comp_size)
147 size_t destLen = hdr.m_uncomp_size;
149 int status = (*m_pUncompress)(&buf[0], &destLen, pComp_data, &srcLen,
150 hdr.m_lzma_props, cLZMAPropsSize);
152 if ((status != SZ_OK) || (destLen != hdr.m_uncomp_size))
158 if (adler32(&buf[0], buf.size()) != hdr.m_adler32)