1/****************************************************************************
2** libebml : parse EBML files, see http://embl.sourceforge.net/
3**
4** <file/class description>
5**
6** Copyright (C) 2002-2005 Steve Lhomme.  All rights reserved.
7**
8** This file is part of libebml.
9**
10** This library is free software; you can redistribute it and/or
11** modify it under the terms of the GNU Lesser General Public
12** License as published by the Free Software Foundation; either
13** version 2.1 of the License, or (at your option) any later version.
14**
15** This library is distributed in the hope that it will be useful,
16** but WITHOUT ANY WARRANTY; without even the implied warranty of
17** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18** Lesser General Public License for more details.
19**
20** You should have received a copy of the GNU Lesser General Public
21** License along with this library; if not, write to the Free Software
22** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
23**
24** See http://www.matroska.org/license/lgpl/ for LGPL licensing information.
25**
26** Contact license@matroska.org if any conditions of this licensing are
27** not clear to you.
28**
29**********************************************************************/
30
31/*!
32	\file
33	\version \$Id: EbmlCrc32.cpp 1155 2005-05-06 11:43:38Z robux4 $
34	\author Steve Lhomme     <robux4 @ users.sf.net>
35	\author Jory Stone       <jcsston @ toughguy.net>
36*/
37#include "ebml/EbmlCrc32.h"
38#include "ebml/EbmlContexts.h"
39#include "ebml/MemIOCallback.h"
40
41START_LIBEBML_NAMESPACE
42
43EbmlId EbmlCrc32_TheId(0xBF, 1);
44const EbmlCallbacks EbmlCrc32::ClassInfos(EbmlCrc32::Create, EbmlCrc32_TheId, "EBMLCrc32\0ratamadabapa", EbmlVoid_Context);
45
46const uint32 EbmlCrc32::m_tab[] = {
47#ifdef WORDS_BIGENDIAN
48	0x00000000L, 0x96300777L, 0x2c610eeeL, 0xba510999L, 0x19c46d07L,
49	0x8ff46a70L, 0x35a563e9L, 0xa395649eL, 0x3288db0eL, 0xa4b8dc79L,
50	0x1ee9d5e0L, 0x88d9d297L, 0x2b4cb609L, 0xbd7cb17eL, 0x072db8e7L,
51	0x911dbf90L, 0x6410b71dL, 0xf220b06aL, 0x4871b9f3L, 0xde41be84L,
52	0x7dd4da1aL, 0xebe4dd6dL, 0x51b5d4f4L, 0xc785d383L, 0x56986c13L,
53	0xc0a86b64L, 0x7af962fdL, 0xecc9658aL, 0x4f5c0114L, 0xd96c0663L,
54	0x633d0ffaL, 0xf50d088dL, 0xc8206e3bL, 0x5e10694cL, 0xe44160d5L,
55	0x727167a2L, 0xd1e4033cL, 0x47d4044bL, 0xfd850dd2L, 0x6bb50aa5L,
56	0xfaa8b535L, 0x6c98b242L, 0xd6c9bbdbL, 0x40f9bcacL, 0xe36cd832L,
57	0x755cdf45L, 0xcf0dd6dcL, 0x593dd1abL, 0xac30d926L, 0x3a00de51L,
58	0x8051d7c8L, 0x1661d0bfL, 0xb5f4b421L, 0x23c4b356L, 0x9995bacfL,
59	0x0fa5bdb8L, 0x9eb80228L, 0x0888055fL, 0xb2d90cc6L, 0x24e90bb1L,
60	0x877c6f2fL, 0x114c6858L, 0xab1d61c1L, 0x3d2d66b6L, 0x9041dc76L,
61	0x0671db01L, 0xbc20d298L, 0x2a10d5efL, 0x8985b171L, 0x1fb5b606L,
62	0xa5e4bf9fL, 0x33d4b8e8L, 0xa2c90778L, 0x34f9000fL, 0x8ea80996L,
63	0x18980ee1L, 0xbb0d6a7fL, 0x2d3d6d08L, 0x976c6491L, 0x015c63e6L,
64	0xf4516b6bL, 0x62616c1cL, 0xd8306585L, 0x4e0062f2L, 0xed95066cL,
65	0x7ba5011bL, 0xc1f40882L, 0x57c40ff5L, 0xc6d9b065L, 0x50e9b712L,
66	0xeab8be8bL, 0x7c88b9fcL, 0xdf1ddd62L, 0x492dda15L, 0xf37cd38cL,
67	0x654cd4fbL, 0x5861b24dL, 0xce51b53aL, 0x7400bca3L, 0xe230bbd4L,
68	0x41a5df4aL, 0xd795d83dL, 0x6dc4d1a4L, 0xfbf4d6d3L, 0x6ae96943L,
69	0xfcd96e34L, 0x468867adL, 0xd0b860daL, 0x732d0444L, 0xe51d0333L,
70	0x5f4c0aaaL, 0xc97c0dddL, 0x3c710550L, 0xaa410227L, 0x10100bbeL,
71	0x86200cc9L, 0x25b56857L, 0xb3856f20L, 0x09d466b9L, 0x9fe461ceL,
72	0x0ef9de5eL, 0x98c9d929L, 0x2298d0b0L, 0xb4a8d7c7L, 0x173db359L,
73	0x810db42eL, 0x3b5cbdb7L, 0xad6cbac0L, 0x2083b8edL, 0xb6b3bf9aL,
74	0x0ce2b603L, 0x9ad2b174L, 0x3947d5eaL, 0xaf77d29dL, 0x1526db04L,
75	0x8316dc73L, 0x120b63e3L, 0x843b6494L, 0x3e6a6d0dL, 0xa85a6a7aL,
76	0x0bcf0ee4L, 0x9dff0993L, 0x27ae000aL, 0xb19e077dL, 0x44930ff0L,
77	0xd2a30887L, 0x68f2011eL, 0xfec20669L, 0x5d5762f7L, 0xcb676580L,
78	0x71366c19L, 0xe7066b6eL, 0x761bd4feL, 0xe02bd389L, 0x5a7ada10L,
79	0xcc4add67L, 0x6fdfb9f9L, 0xf9efbe8eL, 0x43beb717L, 0xd58eb060L,
80	0xe8a3d6d6L, 0x7e93d1a1L, 0xc4c2d838L, 0x52f2df4fL, 0xf167bbd1L,
81	0x6757bca6L, 0xdd06b53fL, 0x4b36b248L, 0xda2b0dd8L, 0x4c1b0aafL,
82	0xf64a0336L, 0x607a0441L, 0xc3ef60dfL, 0x55df67a8L, 0xef8e6e31L,
83	0x79be6946L, 0x8cb361cbL, 0x1a8366bcL, 0xa0d26f25L, 0x36e26852L,
84	0x95770cccL, 0x03470bbbL, 0xb9160222L, 0x2f260555L, 0xbe3bbac5L,
85	0x280bbdb2L, 0x925ab42bL, 0x046ab35cL, 0xa7ffd7c2L, 0x31cfd0b5L,
86	0x8b9ed92cL, 0x1daede5bL, 0xb0c2649bL, 0x26f263ecL, 0x9ca36a75L,
87	0x0a936d02L, 0xa906099cL, 0x3f360eebL, 0x85670772L, 0x13570005L,
88	0x824abf95L, 0x147ab8e2L, 0xae2bb17bL, 0x381bb60cL, 0x9b8ed292L,
89	0x0dbed5e5L, 0xb7efdc7cL, 0x21dfdb0bL, 0xd4d2d386L, 0x42e2d4f1L,
90	0xf8b3dd68L, 0x6e83da1fL, 0xcd16be81L, 0x5b26b9f6L, 0xe177b06fL,
91	0x7747b718L, 0xe65a0888L, 0x706a0fffL, 0xca3b0666L, 0x5c0b0111L,
92	0xff9e658fL, 0x69ae62f8L, 0xd3ff6b61L, 0x45cf6c16L, 0x78e20aa0L,
93	0xeed20dd7L, 0x5483044eL, 0xc2b30339L, 0x612667a7L, 0xf71660d0L,
94	0x4d476949L, 0xdb776e3eL, 0x4a6ad1aeL, 0xdc5ad6d9L, 0x660bdf40L,
95	0xf03bd837L, 0x53aebca9L, 0xc59ebbdeL, 0x7fcfb247L, 0xe9ffb530L,
96	0x1cf2bdbdL, 0x8ac2bacaL, 0x3093b353L, 0xa6a3b424L, 0x0536d0baL,
97	0x9306d7cdL, 0x2957de54L, 0xbf67d923L, 0x2e7a66b3L, 0xb84a61c4L,
98	0x021b685dL, 0x942b6f2aL, 0x37be0bb4L, 0xa18e0cc3L, 0x1bdf055aL,
99	0x8def022dL
100#else
101	0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
102	0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
103	0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
104	0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
105	0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
106	0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
107	0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
108	0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
109	0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
110	0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
111	0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
112	0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
113	0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
114	0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
115	0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
116	0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
117	0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
118	0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
119	0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
120	0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
121	0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
122	0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
123	0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
124	0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
125	0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
126	0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
127	0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
128	0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
129	0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
130	0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
131	0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
132	0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
133	0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
134	0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
135	0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
136	0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
137	0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
138	0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
139	0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
140	0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
141	0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
142	0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
143	0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
144	0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
145	0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
146	0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
147	0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
148	0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
149	0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
150	0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
151	0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
152	0x2d02ef8dL
153#endif
154};
155
156EbmlCrc32::EbmlCrc32()
157{
158	ResetCRC();
159	DefaultSize = DIGESTSIZE;
160	m_crc_final = 0;
161	Size = 4;
162	//This EbmlElement has been set
163//	bValueIsSet = true;
164}
165
166EbmlCrc32::EbmlCrc32(const EbmlCrc32 & ElementToClone)
167:EbmlBinary(ElementToClone)
168{
169	m_crc       = ElementToClone.m_crc;
170	m_crc_final = ElementToClone.m_crc_final;
171}
172
173EbmlElement * EbmlCrc32::Clone() const
174{
175	return new EbmlCrc32(*this);
176}
177
178void EbmlCrc32::AddElementCRC32(EbmlElement &ElementToCRC)
179{
180	// Use a special IOCallback class that Render's to memory instead of to disk
181	MemIOCallback memoryBuffer;
182	ElementToCRC.Render(memoryBuffer, true, true);
183
184	Update(memoryBuffer.GetDataBuffer(), memoryBuffer.GetDataBufferSize());
185//	Finalize();
186};
187
188bool EbmlCrc32::CheckElementCRC32(EbmlElement &ElementToCRC)
189{
190	MemIOCallback memoryBuffer;
191	ElementToCRC.Render(memoryBuffer);
192
193	return CheckCRC(m_crc_final, memoryBuffer.GetDataBuffer(), memoryBuffer.GetDataBufferSize());
194};
195
196uint32 EbmlCrc32::RenderData(IOCallback & output, bool bForceRender, bool bKeepIntact)
197{
198	uint32 Result = DIGESTSIZE;
199
200	if (Result != 0) {
201	    output.writeFully(&m_crc_final, Result);
202	}
203
204	if (Result < DefaultSize) {
205		// pad the rest with 0
206		binary *Pad = new binary[DefaultSize - Result];
207		if (Pad != NULL) {
208			memset(Pad, 0x00, DefaultSize - Result);
209			output.writeFully(Pad, DefaultSize - Result);
210
211			Result = DefaultSize;
212			delete [] Pad;
213		}
214	}
215
216	return Result;
217}
218
219uint64 EbmlCrc32::ReadData(IOCallback & input, ScopeMode ReadFully)
220{
221	if (ReadFully != SCOPE_NO_DATA)
222	{
223		binary *Buffer = new binary[Size];
224		if (Buffer == NULL) {
225			// impossible to read, skip it
226			input.setFilePointer(Size, seek_current);
227		} else {
228			input.readFully(Buffer, Size);
229
230			memcpy((void *)&m_crc_final, Buffer, 4);
231			delete [] Buffer;
232			bValueIsSet = true;
233		}
234	}
235
236	return Size;
237}
238
239bool EbmlCrc32::CheckCRC(uint32 inputCRC, const binary *input, uint32 length)
240{
241	uint32 crc = CRC32_NEGL;
242
243	for(; !IsAligned<uint32>(input) && length > 0; length--)
244		crc = m_tab[CRC32_INDEX(crc) ^ *input++] ^ CRC32_SHIFTED(crc);
245
246	while (length >= 4)
247	{
248		crc ^= *(const uint32 *)input;
249		crc = m_tab[CRC32_INDEX(crc)] ^ CRC32_SHIFTED(crc);
250		crc = m_tab[CRC32_INDEX(crc)] ^ CRC32_SHIFTED(crc);
251		crc = m_tab[CRC32_INDEX(crc)] ^ CRC32_SHIFTED(crc);
252		crc = m_tab[CRC32_INDEX(crc)] ^ CRC32_SHIFTED(crc);
253		length -= 4;
254		input += 4;
255	}
256
257	while (length--)
258		crc = m_tab[CRC32_INDEX(crc) ^ *input++] ^ CRC32_SHIFTED(crc);
259
260	//Now we finalize the CRC32
261	crc ^= CRC32_NEGL;
262
263	if (crc == inputCRC)
264		return true;
265
266	return false;
267};
268
269void EbmlCrc32::FillCRC32(const binary *s, uint32 n)
270{
271	ResetCRC();
272	Update(s, n);
273	Finalize();
274
275	/*uint32 crc = CRC32_NEGL;
276
277	for(; !IsAligned<uint32>(s) && n > 0; n--)
278		crc = m_tab[CRC32_INDEX(crc) ^ *s++] ^ CRC32_SHIFTED(crc);
279
280	while (n >= 4)
281	{
282		crc ^= *(const uint32 *)s;
283		crc = m_tab[CRC32_INDEX(crc)] ^ CRC32_SHIFTED(crc);
284		crc = m_tab[CRC32_INDEX(crc)] ^ CRC32_SHIFTED(crc);
285		crc = m_tab[CRC32_INDEX(crc)] ^ CRC32_SHIFTED(crc);
286		crc = m_tab[CRC32_INDEX(crc)] ^ CRC32_SHIFTED(crc);
287		n -= 4;
288		s += 4;
289	}
290
291	while (n--)
292		crc = m_tab[CRC32_INDEX(crc) ^ *s++] ^ CRC32_SHIFTED(crc);
293
294	m_crc = crc;
295
296	//Now we finalize the CRC32
297	m_crc ^= CRC32_NEGL;
298	//for (unsigned int i = 0; i < 4; i++)
299	//	(&last_crc32)[i] = GetCrcByte(i);*/
300
301}
302
303void EbmlCrc32::Update(const binary *input, uint32 length)
304{
305	uint32 crc = m_crc;
306
307	for(; !IsAligned<uint32>(input) && length > 0; length--)
308		crc = m_tab[CRC32_INDEX(crc) ^ *input++] ^ CRC32_SHIFTED(crc);
309
310	while (length >= 4)
311	{
312		crc ^= *(const uint32 *)input;
313		crc = m_tab[CRC32_INDEX(crc)] ^ CRC32_SHIFTED(crc);
314		crc = m_tab[CRC32_INDEX(crc)] ^ CRC32_SHIFTED(crc);
315		crc = m_tab[CRC32_INDEX(crc)] ^ CRC32_SHIFTED(crc);
316		crc = m_tab[CRC32_INDEX(crc)] ^ CRC32_SHIFTED(crc);
317		length -= 4;
318		input += 4;
319	}
320
321	while (length--)
322		crc = m_tab[CRC32_INDEX(crc) ^ *input++] ^ CRC32_SHIFTED(crc);
323
324	m_crc = crc;
325}
326
327void EbmlCrc32::Finalize()
328{
329	//Finalize the CRC32
330	m_crc ^= CRC32_NEGL;
331	//Copy it over to completed CRC32 memeber
332	m_crc_final = m_crc;
333	//Reset the holding CRC member (m_crc)
334	ResetCRC();
335	//This EbmlElement has been set
336	bValueIsSet = true;
337}
338
339END_LIBEBML_NAMESPACE
340