]> git.cworth.org Git - vogl/blob - src/voglcore/vogl_lzma_codec.cpp
Initial vogl checkin
[vogl] / src / voglcore / vogl_lzma_codec.cpp
1 /**************************************************************************
2  *
3  * Copyright 2013-2014 RAD Game Tools and Valve Software
4  * Copyright 2010-2014 Rich Geldreich and Tenacious Software LLC
5  * All Rights Reserved.
6  *
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:
13  *
14  * The above copyright notice and this permission notice shall be included in
15  * all copies or substantial portions of the Software.
16  *
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
23  * THE SOFTWARE.
24  *
25  **************************************************************************/
26
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"
34
35 namespace vogl
36 {
37     lzma_codec::lzma_codec()
38         : m_pCompress(LzmaCompress),
39           m_pUncompress(LzmaUncompress)
40     {
41         VOGL_ASSUME(cLZMAPropsSize == LZMA_PROPS_SIZE);
42     }
43
44     lzma_codec::~lzma_codec()
45     {
46     }
47
48     bool lzma_codec::pack(const void *p, uint n, vogl::vector<uint8> &buf)
49     {
50         if (n > 1024U * 1024U * 1024U)
51             return false;
52
53         uint max_comp_size = n + math::maximum<uint>(128, n >> 8);
54         buf.resize(sizeof(header) + max_comp_size);
55
56         header *pHDR = reinterpret_cast<header *>(&buf[0]);
57         uint8 *pComp_data = &buf[sizeof(header)];
58
59         utils::zero_object(*pHDR);
60
61         pHDR->m_uncomp_size = n;
62         pHDR->m_adler32 = adler32(p, n);
63
64         if (n)
65         {
66             size_t destLen = 0;
67             size_t outPropsSize = 0;
68             int status = SZ_ERROR_INPUT_EOF;
69
70             for (uint trial = 0; trial < 3; trial++)
71             {
72                 destLen = max_comp_size;
73                 outPropsSize = cLZMAPropsSize;
74
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 */
83 #ifdef WIN32
84                                         (g_number_of_processors > 1) ? 2 : 1
85 #else
86                                         1
87 #endif
88                                         );
89
90                 if (status != SZ_ERROR_OUTPUT_EOF)
91                     break;
92
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)];
97             }
98
99             if (status != SZ_OK)
100             {
101                 buf.clear();
102                 return false;
103             }
104
105             pHDR->m_comp_size = static_cast<uint>(destLen);
106
107             buf.resize(VOGL_SIZEOF_U32(header) + static_cast<uint32>(destLen));
108         }
109
110         pHDR->m_sig = header::cSig;
111         pHDR->m_checksum = static_cast<uint8>(adler32((uint8 *)pHDR + header::cChecksumSkipBytes, sizeof(header) - header::cChecksumSkipBytes));
112
113         return true;
114     }
115
116     bool lzma_codec::unpack(const void *p, uint n, vogl::vector<uint8> &buf)
117     {
118         buf.resize(0);
119
120         if (n < sizeof(header))
121             return false;
122
123         const header &hdr = *static_cast<const header *>(p);
124         if (hdr.m_sig != header::cSig)
125             return false;
126
127         if (static_cast<uint8>(adler32((const uint8 *)&hdr + header::cChecksumSkipBytes, sizeof(hdr) - header::cChecksumSkipBytes)) != hdr.m_checksum)
128             return false;
129
130         if (!hdr.m_uncomp_size)
131             return true;
132
133         if (!hdr.m_comp_size)
134             return false;
135
136         if (hdr.m_uncomp_size > 1024U * 1024U * 1024U)
137             return false;
138
139         if (!buf.try_resize(hdr.m_uncomp_size))
140             return false;
141
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)
145             return false;
146
147         size_t destLen = hdr.m_uncomp_size;
148
149         int status = (*m_pUncompress)(&buf[0], &destLen, pComp_data, &srcLen,
150                                       hdr.m_lzma_props, cLZMAPropsSize);
151
152         if ((status != SZ_OK) || (destLen != hdr.m_uncomp_size))
153         {
154             buf.clear();
155             return false;
156         }
157
158         if (adler32(&buf[0], buf.size()) != hdr.m_adler32)
159         {
160             buf.clear();
161             return false;
162         }
163
164         return true;
165     }
166
167 } // namespace vogl