[Scummvm-git-logs] scummvm master -> 357249fb5af74be77a6eda953d6d729f01a13852
sev-
noreply at scummvm.org
Tue Nov 29 00:05:37 UTC 2022
This automated email contains information about 8 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .
Summary:
b63160a06e COMMON: Remove unused functions in unzip
c60281b3d0 COMMON: Fix crc calculation with reflected messages
ec9bb100e1 COMMON: Switch unzip from zlib to gzio
8f6beba38f COMMON: Make most CRC functions const as they don't modify the object.
f06348708c COMMON: Optimize crcFast and related functions.
35bac4e58c COMMON: Add tests for CRC
05f1a0df51 COMMON: Remove the need for most reflecting when initing reflected table
357249fb5a COMMON: Split slow and fast CRC implementation
Commit: b63160a06ebf8167d73279bbd5a22d0e32115819
https://github.com/scummvm/scummvm/commit/b63160a06ebf8167d73279bbd5a22d0e32115819
Author: Vladimir Serbinenko (phcoder at gmail.com)
Date: 2022-11-29T01:05:31+01:00
Commit Message:
COMMON: Remove unused functions in unzip
Changed paths:
common/unzip.cpp
diff --git a/common/unzip.cpp b/common/unzip.cpp
index 44f7ce73e81..d9b121444b7 100644
--- a/common/unzip.cpp
+++ b/common/unzip.cpp
@@ -157,22 +157,8 @@ typedef struct {
uLong disk_num_start; /* disk number start 2 bytes */
uLong internal_fa; /* internal file attributes 2 bytes */
uLong external_fa; /* external file attributes 4 bytes */
-
- tm_unz tmu_date;
} unz_file_info;
-int unzStringFileNameCompare(const char* fileName1,
- const char* fileName2,
- int iCaseSensitivity);
-/*
- Compare two filename (fileName1,fileName2).
- If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp)
- If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi
- or strcasecmp)
- If iCaseSenisivity = 0, case sensitivity is defaut of your operating system
- (like 1 on Unix, 2 on Windows)
-*/
-
/*
Open a Zip file. path contain the full pathname (by example,
@@ -191,21 +177,6 @@ int unzClose(unzFile file);
these files MUST be closed with unzipCloseCurrentFile before call unzipClose.
return UNZ_OK if there is no problem. */
-int unzGetGlobalInfo(unzFile file,
- unz_global_info *pglobal_info);
-/*
- Write info about the ZipFile in the *pglobal_info structure.
- No preparation of the structure is needed
- return UNZ_OK if there is no problem. */
-
-
-int unzGetGlobalComment(unzFile file, char *szComment, uLong uSizeBuf);
-/*
- Get the global comment string of the ZipFile, in the szComment buffer.
- uSizeBuf is the size of the szComment buffer.
- return the number of byte copied or an error code <0
-*/
-
/***************************************************************************/
/* Unzip package allow you browse the directory of the zipfile */
@@ -285,16 +256,6 @@ int unzReadCurrentFile(unzFile file, voidp buf, unsigned len);
(UNZ_ERRNO for IO error, or zLib error for uncompress error)
*/
-z_off_t unztell(unzFile file);
-/*
- Give the current position in uncompressed data
-*/
-
-int unzeof(unzFile file);
-/*
- return 1 if the end of file was reached, 0 elsewhere
-*/
-
int unzGetLocalExtrafield(unzFile file, voidp buf, unsigned len);
/*
Read extra field from the current file (opened by unzOpenCurrentFile)
@@ -426,32 +387,6 @@ static int unzlocal_getLong(Common::SeekableReadStream *fin, uLong *pX) {
return (fin->err() || fin->eos()) ? UNZ_ERRNO : UNZ_OK;
}
-
-#ifdef CASESENSITIVITYDEFAULT_NO
-#define CASESENSITIVITYDEFAULTVALUE 2
-#else
-#define CASESENSITIVITYDEFAULTVALUE 1
-#endif
-
-/*
- Compare two filename (fileName1,fileName2).
- If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp)
- If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi
- or strcasecmp)
- If iCaseSenisivity = 0, case sensitivity is defaut of your operating system
- (like 1 on Unix, 2 on Windows)
-
-*/
-int unzStringFileNameCompare(const char* fileName1, const char* fileName2, int iCaseSensitivity) {
- if (iCaseSensitivity==0)
- iCaseSensitivity=CASESENSITIVITYDEFAULTVALUE;
-
- if (iCaseSensitivity==1)
- return strcmp(fileName1,fileName2);
-
- return scumm_stricmp(fileName1,fileName2);
-}
-
#define BUFREADCOMMENT (0x400)
/*
@@ -634,44 +569,11 @@ int unzClose(unzFile file) {
return UNZ_PARAMERROR;
s = (unz_s *)file;
- if (s->pfile_in_zip_read != nullptr)
- unzCloseCurrentFile(file);
-
delete s->_stream;
delete s;
return UNZ_OK;
}
-
-/*
- Write info about the ZipFile in the *pglobal_info structure.
- No preparation of the structure is needed
- return UNZ_OK if there is no problem. */
-int unzGetGlobalInfo(unzFile file, unz_global_info *pglobal_info) {
- unz_s *s;
- if (file == nullptr)
- return UNZ_PARAMERROR;
- s = (unz_s *)file;
- *pglobal_info = s->gi;
- return UNZ_OK;
-}
-
-
-/*
- Translate date/time from Dos format to tm_unz (readable more easilty)
-*/
-static void unzlocal_DosDateToTmuDate(uLong ulDosDate, tm_unz* ptm) {
- uLong uDate;
- uDate = (uLong)(ulDosDate>>16);
- ptm->tm_mday = (uInt)(uDate&0x1f);
- ptm->tm_mon = (uInt)((((uDate)&0x1E0)/0x20)-1);
- ptm->tm_year = (uInt)(((uDate&0x0FE00)/0x0200)+1980);
-
- ptm->tm_hour = (uInt) ((ulDosDate &0xF800)/0x800);
- ptm->tm_min = (uInt) ((ulDosDate&0x7E0)/0x20);
- ptm->tm_sec = (uInt) (2*(ulDosDate&0x1f));
-}
-
/*
Get Info about the current file in the zipfile, with internal only info
*/
@@ -731,8 +633,6 @@ static int unzlocal_GetCurrentFileInfoInternal(unzFile file,
if (unzlocal_getLong(s->_stream,&file_info.dosDate) != UNZ_OK)
err=UNZ_ERRNO;
- unzlocal_DosDateToTmuDate(file_info.dosDate,&file_info.tmu_date);
-
if (unzlocal_getLong(s->_stream,&file_info.crc) != UNZ_OK)
err=UNZ_ERRNO;
@@ -1244,98 +1144,6 @@ int unzReadCurrentFile(unzFile file, voidp buf, unsigned len) {
return err;
}
-
-/*
- Give the current position in uncompressed data
-*/
-z_off_t unztell(unzFile file) {
- unz_s* s;
- file_in_zip_read_info_s* pfile_in_zip_read_info;
- if (file==nullptr)
- return UNZ_PARAMERROR;
- s=(unz_s*)file;
- pfile_in_zip_read_info=s->pfile_in_zip_read;
-
- if (pfile_in_zip_read_info==nullptr)
- return UNZ_PARAMERROR;
-
- return (z_off_t)pfile_in_zip_read_info->stream.total_out;
-}
-
-
-/*
- return 1 if the end of file was reached, 0 elsewhere
-*/
-int unzeof(unzFile file) {
- unz_s* s;
- file_in_zip_read_info_s* pfile_in_zip_read_info;
- if (file==nullptr)
- return UNZ_PARAMERROR;
- s=(unz_s*)file;
- pfile_in_zip_read_info=s->pfile_in_zip_read;
-
- if (pfile_in_zip_read_info==nullptr)
- return UNZ_PARAMERROR;
-
- if (pfile_in_zip_read_info->rest_read_uncompressed == 0)
- return 1;
- else
- return 0;
-}
-
-
-
-/*
- Read extra field from the current file (opened by unzOpenCurrentFile)
- This is the local-header version of the extra field (sometimes, there is
- more info in the local-header version than in the central-header)
-
- if buf==NULL, it return the size of the local extra field that can be read
-
- if buf!=NULL, len is the size of the buffer, the extra header is copied in
- buf.
- the return value is the number of bytes copied in buf, or (if <0)
- the error code
-*/
-int unzGetLocalExtrafield(unzFile file, voidp buf, unsigned len) {
- unz_s* s;
- file_in_zip_read_info_s* pfile_in_zip_read_info;
- uInt read_now;
- uLong size_to_read;
-
- if (file==nullptr)
- return UNZ_PARAMERROR;
- s=(unz_s*)file;
- pfile_in_zip_read_info=s->pfile_in_zip_read;
-
- if (pfile_in_zip_read_info==nullptr)
- return UNZ_PARAMERROR;
-
- size_to_read = (pfile_in_zip_read_info->size_local_extrafield -
- pfile_in_zip_read_info->pos_local_extrafield);
-
- if (buf==nullptr)
- return (int)size_to_read;
-
- if (len>size_to_read)
- read_now = (uInt)size_to_read;
- else
- read_now = (uInt)len;
-
- if (read_now==0)
- return 0;
-
- pfile_in_zip_read_info->_stream->seek(pfile_in_zip_read_info->offset_local_extrafield +
- pfile_in_zip_read_info->pos_local_extrafield,SEEK_SET);
- if (pfile_in_zip_read_info->_stream->err())
- return UNZ_ERRNO;
-
- if (pfile_in_zip_read_info->_stream->read(buf,(uInt)size_to_read)!=size_to_read)
- return UNZ_ERRNO;
-
- return (int)read_now;
-}
-
/*
Close the file in zip opened with unzipOpenCurrentFile
Return UNZ_CRCERROR if all the file was read but the CRC is not good
@@ -1378,38 +1186,6 @@ int unzCloseCurrentFile(unzFile file) {
}
-/*
- Get the global comment string of the ZipFile, in the szComment buffer.
- uSizeBuf is the size of the szComment buffer.
- return the number of byte copied or an error code <0
-*/
-int unzGetGlobalComment(unzFile file, char *szComment, uLong uSizeBuf) {
- unz_s* s;
- uLong uReadThis;
- if (file==nullptr)
- return UNZ_PARAMERROR;
- s=(unz_s*)file;
-
- uReadThis = uSizeBuf;
- if (uReadThis>s->gi.size_comment)
- uReadThis = s->gi.size_comment;
-
- s->_stream->seek(s->central_pos+22, SEEK_SET);
- if (s->_stream->err())
- return UNZ_ERRNO;
-
- if (uReadThis>0) {
- *szComment='\0';
- if (s->_stream->read(szComment,(uInt)uReadThis)!=uReadThis)
- return UNZ_ERRNO;
- }
-
- if ((szComment != nullptr) && (uSizeBuf > s->gi.size_comment))
- *(szComment+s->gi.size_comment)='\0';
- return (int)uReadThis;
-}
-
-
namespace Common {
Commit: c60281b3d0c9e7cb06fac482d1417f0a0d38e11d
https://github.com/scummvm/scummvm/commit/c60281b3d0c9e7cb06fac482d1417f0a0d38e11d
Author: Vladimir Serbinenko (phcoder at gmail.com)
Date: 2022-11-29T01:05:31+01:00
Commit Message:
COMMON: Fix crc calculation with reflected messages
Changed paths:
common/crc.h
diff --git a/common/crc.h b/common/crc.h
index 0850f15ea03..47e78bf8860 100644
--- a/common/crc.h
+++ b/common/crc.h
@@ -235,7 +235,7 @@ T CRC<T>::crcFast(byte const message[], int nBytes) {
* Divide the message by the polynomial, a byte at a time.
*/
for (int b = 0; b < nBytes; ++b) {
- byte data = reflectData(message[b] ^ (remainder >> (_width - 8)));
+ byte data = reflectData(message[b]) ^ (remainder >> (_width - 8));
remainder = _crcTable[data] ^ (remainder << 8);
}
Commit: ec9bb100e109635b28c95dc3ac08b2f953257b50
https://github.com/scummvm/scummvm/commit/ec9bb100e109635b28c95dc3ac08b2f953257b50
Author: Vladimir Serbinenko (phcoder at gmail.com)
Date: 2022-11-29T01:05:31+01:00
Commit Message:
COMMON: Switch unzip from zlib to gzio
Tested by loading scummremastered.zip
Changed paths:
common/unzip.cpp
diff --git a/common/unzip.cpp b/common/unzip.cpp
index d9b121444b7..e967d22979c 100644
--- a/common/unzip.cpp
+++ b/common/unzip.cpp
@@ -65,15 +65,8 @@
PkWare has also a specification at :
ftp://ftp.pkware.com/probdesc.zip */
-// Disable symbol overrides so that we can use zlib.h
-#define FORBIDDEN_SYMBOL_ALLOW_ALL
-
#include "common/scummsys.h"
-#ifdef USE_ZLIB
-#include <zlib.h>
-#else // !USE_ZLIB
-
// Even when zlib is not linked in, we can still open ZIP archives and read
// uncompressed files from them. Attempted decompression of compressed files
// will result in an error.
@@ -88,15 +81,10 @@ typedef unsigned long uLong;
typedef long z_off_t;
typedef unsigned char Byte;
typedef Byte Bytef;
-typedef struct {
- Bytef *next_in, *next_out;
- uInt avail_in, avail_out;
- uLong total_out;
-} z_stream;
-
-#endif // !USE_ZLIB
+#include "common/crc.h"
#include "common/fs.h"
+#include "common/gzio.h"
#include "common/unzip.h"
#include "common/memstream.h"
@@ -123,12 +111,12 @@ typedef voidp unzFile;
/* tm_unz contain date/time info */
typedef struct {
- uInt tm_sec; /* seconds after the minute - [0,59] */
- uInt tm_min; /* minutes after the hour - [0,59] */
- uInt tm_hour; /* hours since midnight - [0,23] */
- uInt tm_mday; /* day of the month - [1,31] */
- uInt tm_mon; /* months since January - [0,11] */
- uInt tm_year; /* years - [1980..2044] */
+ uInt tm_sec; /* seconds after the minute - [0,59] */
+ uInt tm_min; /* minutes after the hour - [0,59] */
+ uInt tm_hour; /* hours since midnight - [0,23] */
+ uInt tm_mday; /* day of the month - [1,31] */
+ uInt tm_mon; /* months since January - [0,11] */
+ uInt tm_year; /* years - [1980..2044] */
} tm_unz;
/* unz_global_info structure contain global data about the ZIPfile
@@ -231,7 +219,7 @@ int unzGetCurrentFileInfo(unzFile file,
from it, and close it (you can close it before reading all the file)
*/
-int unzOpenCurrentFile(unzFile file);
+Common::SeekableReadStream *unzOpenCurrentFile(unzFile file, const Common::CRC32& crc);
/*
Open for reading data the current file in the zipfile.
If there is no error, the return value is UNZ_OK.
@@ -302,22 +290,11 @@ typedef struct {
/* file_in_zip_read_info_s contain internal information about a file in zipfile,
when reading and decompress it */
typedef struct {
- char *read_buffer; /* internal buffer for compressed data */
- z_stream stream; /* zLib stream structure for inflate */
-
- uLong pos_in_zipfile; /* position in byte on the zipfile, for fseek*/
- uLong stream_initialized; /* flag set if stream structure is initialized*/
-
uLong offset_local_extrafield;/* offset of the local extra field */
uInt size_local_extrafield;/* size of the local extra field */
uLong pos_local_extrafield; /* position in the local extra field in read*/
- uLong crc32_data; /* crc32 of all data uncompressed */
- uLong crc32_wait; /* crc32 we must obtain after decompress all */
- uLong rest_read_compressed; /* number of byte to be decompressed */
- uLong rest_read_uncompressed;/*number of byte to be obtained after decomp*/
Common::SeekableReadStream *_stream; /* io structore of the zipfile */
- uLong compression_method; /* compression method (0==store) */
uLong byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/
} file_in_zip_read_info_s;
@@ -349,8 +326,7 @@ typedef struct {
unz_file_info cur_file_info; /* public info about the current file in zip*/
unz_file_info_internal cur_file_info_internal; /* private info about it*/
- file_in_zip_read_info_s* pfile_in_zip_read; /* structure about the current
- file if we are decompressing it */
+
ZipHash _hash;
} unz_s;
@@ -531,7 +507,6 @@ unzFile unzOpen(Common::SeekableReadStream *stream) {
us->byte_before_the_zipfile = central_pos -
(us->offset_central_dir+us->size_central_dir);
us->central_pos = central_pos;
- us->pfile_in_zip_read = nullptr;
err = unzGoToFirstFile((unzFile)us);
@@ -931,258 +906,58 @@ static int unzlocal_CheckCurrentFileCoherencyHeader(unz_s* s, uInt* piSizeVar,
Open for reading data the current file in the zipfile.
If there is no error and the file is opened, the return value is UNZ_OK.
*/
-int unzOpenCurrentFile (unzFile file) {
- int err=UNZ_OK;
- int Store;
+Common::SeekableReadStream *unzOpenCurrentFile (unzFile file, const Common::CRC32& crc) {
uInt iSizeVar;
unz_s* s;
- file_in_zip_read_info_s* pfile_in_zip_read_info;
uLong offset_local_extrafield; /* offset of the local extra field */
uInt size_local_extrafield; /* size of the local extra field */
if (file==nullptr)
- return UNZ_PARAMERROR;
+ return nullptr;
s=(unz_s*)file;
if (!s->current_file_ok)
- return UNZ_PARAMERROR;
-
- if (s->pfile_in_zip_read != nullptr)
- unzCloseCurrentFile(file);
+ return nullptr;
if (unzlocal_CheckCurrentFileCoherencyHeader(s,&iSizeVar,
&offset_local_extrafield,&size_local_extrafield)!=UNZ_OK)
- return UNZ_BADZIPFILE;
-
- pfile_in_zip_read_info = (file_in_zip_read_info_s*) malloc(sizeof(file_in_zip_read_info_s));
-
- if (pfile_in_zip_read_info==nullptr)
- return UNZ_INTERNALERROR;
-
- pfile_in_zip_read_info->read_buffer=(char *)malloc(UNZ_BUFSIZE);
- pfile_in_zip_read_info->offset_local_extrafield = offset_local_extrafield;
- pfile_in_zip_read_info->size_local_extrafield = size_local_extrafield;
- pfile_in_zip_read_info->pos_local_extrafield=0;
-
- if (pfile_in_zip_read_info->read_buffer==nullptr)
- {
- free(pfile_in_zip_read_info);
- return UNZ_INTERNALERROR;
- }
-
- pfile_in_zip_read_info->stream_initialized=0;
+ return nullptr;
- if ((s->cur_file_info.compression_method!=0) &&
- (s->cur_file_info.compression_method!=Z_DEFLATED))
- err=UNZ_BADZIPFILE;
- Store = s->cur_file_info.compression_method==0;
-
- pfile_in_zip_read_info->crc32_wait=s->cur_file_info.crc;
- pfile_in_zip_read_info->crc32_data=0;
- pfile_in_zip_read_info->compression_method = s->cur_file_info.compression_method;
- pfile_in_zip_read_info->_stream=s->_stream;
- pfile_in_zip_read_info->byte_before_the_zipfile=s->byte_before_the_zipfile;
-
- pfile_in_zip_read_info->stream.total_out = 0;
-
- if (!Store) {
-#ifdef USE_ZLIB
- pfile_in_zip_read_info->stream.zalloc = (alloc_func)nullptr;
- pfile_in_zip_read_info->stream.zfree = (free_func)nullptr;
- pfile_in_zip_read_info->stream.opaque = (voidpf)nullptr;
-
- err=inflateInit2(&pfile_in_zip_read_info->stream, -MAX_WBITS);
- if (err == Z_OK)
- pfile_in_zip_read_info->stream_initialized = 1;
- /* windowBits is passed < 0 to tell that there is no zlib header.
- * Note that in this case inflate *requires* an extra "dummy" byte
- * after the compressed stream in order to complete decompression and
- * return Z_STREAM_END.
- * In unzip, i don't wait absolutely Z_STREAM_END because I known the
- * size of both compressed and uncompressed data
- */
-#else
- err=UNZ_BADZIPFILE;
-#endif
+ if (s->cur_file_info.compression_method != 0 && s->cur_file_info.compression_method != Z_DEFLATED) {
+ warning("Unknown compression algoritthm %d", (int) s->cur_file_info.compression_method);
+ return nullptr;
}
- pfile_in_zip_read_info->rest_read_compressed = s->cur_file_info.compressed_size;
- pfile_in_zip_read_info->rest_read_uncompressed = s->cur_file_info.uncompressed_size;
-
-
- pfile_in_zip_read_info->pos_in_zipfile =
- s->cur_file_info_internal.offset_curfile + SIZEZIPLOCALHEADER + iSizeVar;
-
- pfile_in_zip_read_info->stream.avail_in = (uInt)0;
-
- s->pfile_in_zip_read = pfile_in_zip_read_info;
- return err;
-}
-
-
-/*
- Read bytes from the current file.
- buf contain buffer where data must be copied
- len the size of buf.
-
- return the number of byte copied if somes bytes are copied
- return 0 if the end of file was reached
- return <0 with error code if there is an error
- (UNZ_ERRNO for IO error, or zLib error for uncompress error)
-*/
-int unzReadCurrentFile(unzFile file, voidp buf, unsigned len) {
- int err=UNZ_OK;
- uInt iRead = 0;
- unz_s* s;
- file_in_zip_read_info_s* pfile_in_zip_read_info;
- if (file==nullptr)
- return UNZ_PARAMERROR;
- s=(unz_s*)file;
- pfile_in_zip_read_info=s->pfile_in_zip_read;
-
- if (pfile_in_zip_read_info==nullptr)
- return UNZ_PARAMERROR;
-
-
- if (pfile_in_zip_read_info->read_buffer == nullptr)
- return UNZ_END_OF_LIST_OF_FILE;
- if (len==0)
- return 0;
-
- pfile_in_zip_read_info->stream.next_out = (Bytef *)buf;
-
- pfile_in_zip_read_info->stream.avail_out = (uInt)len;
-
- if (len>pfile_in_zip_read_info->rest_read_uncompressed)
- pfile_in_zip_read_info->stream.avail_out =
- (uInt)pfile_in_zip_read_info->rest_read_uncompressed;
-
- while (pfile_in_zip_read_info->stream.avail_out>0) {
- if ((pfile_in_zip_read_info->stream.avail_in==0) &&
- (pfile_in_zip_read_info->rest_read_compressed>0)) {
- uInt uReadThis = UNZ_BUFSIZE;
- if (pfile_in_zip_read_info->rest_read_compressed<uReadThis)
- uReadThis = (uInt)pfile_in_zip_read_info->rest_read_compressed;
- if (uReadThis == 0)
- return UNZ_EOF;
- pfile_in_zip_read_info->_stream->seek(pfile_in_zip_read_info->pos_in_zipfile +
- pfile_in_zip_read_info->byte_before_the_zipfile, SEEK_SET);
- if (pfile_in_zip_read_info->_stream->err())
- return UNZ_ERRNO;
- if (pfile_in_zip_read_info->_stream->read(pfile_in_zip_read_info->read_buffer,uReadThis)!=uReadThis)
- return UNZ_ERRNO;
- pfile_in_zip_read_info->pos_in_zipfile += uReadThis;
-
- pfile_in_zip_read_info->rest_read_compressed-=uReadThis;
-
- pfile_in_zip_read_info->stream.next_in = (Bytef *)pfile_in_zip_read_info->read_buffer;
- pfile_in_zip_read_info->stream.avail_in = (uInt)uReadThis;
- }
- if (pfile_in_zip_read_info->compression_method==0) {
- uInt uDoCopy,i;
- if (pfile_in_zip_read_info->stream.avail_out < pfile_in_zip_read_info->stream.avail_in)
- uDoCopy = pfile_in_zip_read_info->stream.avail_out;
- else
- uDoCopy = pfile_in_zip_read_info->stream.avail_in;
-
- for (i=0;i<uDoCopy;i++)
- *(pfile_in_zip_read_info->stream.next_out+i) = *(pfile_in_zip_read_info->stream.next_in+i);
-
-#ifdef USE_ZLIB
- pfile_in_zip_read_info->crc32_data = crc32(pfile_in_zip_read_info->crc32_data,
- pfile_in_zip_read_info->stream.next_out,
- uDoCopy);
-#endif // otherwise leave crc32_data as is and it won't be verified at the end
- pfile_in_zip_read_info->rest_read_uncompressed-=uDoCopy;
- pfile_in_zip_read_info->stream.avail_in -= uDoCopy;
- pfile_in_zip_read_info->stream.avail_out -= uDoCopy;
- pfile_in_zip_read_info->stream.next_out += uDoCopy;
- pfile_in_zip_read_info->stream.next_in += uDoCopy;
- pfile_in_zip_read_info->stream.total_out += uDoCopy;
- iRead += uDoCopy;
- } else {
-#ifdef USE_ZLIB
- uLong uTotalOutBefore,uTotalOutAfter;
- const Bytef *bufBefore;
- uLong uOutThis;
- int flush = Z_SYNC_FLUSH;
-
- uTotalOutBefore = pfile_in_zip_read_info->stream.total_out;
- bufBefore = pfile_in_zip_read_info->stream.next_out;
-
- /*
- if ((pfile_in_zip_read_info->rest_read_uncompressed ==
- pfile_in_zip_read_info->stream.avail_out) &&
- (pfile_in_zip_read_info->rest_read_compressed == 0))
- flush = Z_FINISH;
- */
- err=inflate(&pfile_in_zip_read_info->stream,flush);
-
- uTotalOutAfter = pfile_in_zip_read_info->stream.total_out;
- uOutThis = uTotalOutAfter-uTotalOutBefore;
-
- pfile_in_zip_read_info->crc32_data =
- crc32(pfile_in_zip_read_info->crc32_data,bufBefore, (uInt)(uOutThis));
-
- pfile_in_zip_read_info->rest_read_uncompressed -= uOutThis;
-
- iRead += (uInt)(uTotalOutAfter - uTotalOutBefore);
-
- if (err==Z_STREAM_END)
- return (iRead==0) ? UNZ_EOF : iRead;
- if (err!=Z_OK)
- break;
-#else
- // Cannot decompress the file without zlib.
- err = UNZ_BADZIPFILE;
- break;
-#endif
- }
+ uint32 crc32_wait = s->cur_file_info.crc;
+
+ byte *compressedBuffer = new byte[s->cur_file_info.compressed_size];
+ s->_stream->seek(s->cur_file_info_internal.offset_curfile + SIZEZIPLOCALHEADER + iSizeVar);
+ s->_stream->read(compressedBuffer, s->cur_file_info.compressed_size);
+ byte *uncompressedBuffer = nullptr;
+
+ switch (s->cur_file_info.compression_method) {
+ case 0: // Store
+ uncompressedBuffer = compressedBuffer;
+ break;
+ case Z_DEFLATED:
+ uncompressedBuffer = new byte[s->cur_file_info.uncompressed_size];
+ Common::GzioReadStream::deflateDecompress(uncompressedBuffer, s->cur_file_info.uncompressed_size, compressedBuffer, s->cur_file_info.compressed_size);
+ delete[] compressedBuffer;
+ compressedBuffer = nullptr;
+ break;
+ default:
+ warning("Unknown compression algoritthm %d", (int) s->cur_file_info.compression_method);
+ delete[] compressedBuffer;
+ return nullptr;
}
- if (err==Z_OK)
- return iRead;
- return err;
-}
-
-/*
- Close the file in zip opened with unzipOpenCurrentFile
- Return UNZ_CRCERROR if all the file was read but the CRC is not good
-*/
-int unzCloseCurrentFile(unzFile file) {
- int err=UNZ_OK;
-
- unz_s* s;
- file_in_zip_read_info_s* pfile_in_zip_read_info;
- if (file == nullptr)
- return UNZ_PARAMERROR;
- s = (unz_s*)file;
- pfile_in_zip_read_info = s->pfile_in_zip_read;
-
- if (pfile_in_zip_read_info == nullptr)
- return UNZ_PARAMERROR;
-
-
-#ifdef USE_ZLIB
- // Only verify crc32_data when zlib is linked in, because otherwise crc32() is
- // not defined.
- if (pfile_in_zip_read_info->rest_read_uncompressed == 0) {
- if (pfile_in_zip_read_info->crc32_data != pfile_in_zip_read_info->crc32_wait)
- err=UNZ_CRCERROR;
+ uint32 crc32_data = crc.crcFast(uncompressedBuffer, s->cur_file_info.uncompressed_size);
+ if (crc32_data != crc32_wait) {
+ delete[] uncompressedBuffer;
+ warning("CRC32 mismatch: %08x, %08x", crc32_data, crc32_wait);
+ return nullptr;
}
- if (pfile_in_zip_read_info->stream_initialized)
- inflateEnd(&pfile_in_zip_read_info->stream);
-#endif
-
-
- free(pfile_in_zip_read_info->read_buffer);
- pfile_in_zip_read_info->read_buffer = nullptr;
- pfile_in_zip_read_info->stream_initialized = 0;
- free(pfile_in_zip_read_info);
-
- s->pfile_in_zip_read=nullptr;
-
- return err;
+ return new Common::MemoryReadStream(uncompressedBuffer, s->cur_file_info.uncompressed_size, DisposeAfterUse::YES);
}
@@ -1191,6 +966,7 @@ namespace Common {
class ZipArchive : public Archive {
unzFile _zipFile;
+ Common::CRC32 _crc;
public:
ZipArchive(unzFile zipFile);
@@ -1222,8 +998,9 @@ public:
};
*/
-ZipArchive::ZipArchive(unzFile zipFile) : _zipFile(zipFile) {
+ZipArchive::ZipArchive(unzFile zipFile) : _zipFile(zipFile), _crc() {
assert(_zipFile);
+ _crc.init();
}
ZipArchive::~ZipArchive() {
@@ -1261,32 +1038,7 @@ SeekableReadStream *ZipArchive::createReadStreamForMember(const Path &path) cons
if (unzLocateFile(_zipFile, name.c_str(), 2) != UNZ_OK)
return nullptr;
- unz_file_info fileInfo;
- if (unzOpenCurrentFile(_zipFile) != UNZ_OK)
- return nullptr;
-
- if (unzGetCurrentFileInfo(_zipFile, &fileInfo, nullptr, 0, nullptr, 0, nullptr, 0) != UNZ_OK)
- return nullptr;
-
- byte *buffer = (byte *)malloc(fileInfo.uncompressed_size);
- assert(buffer);
-
- if (unzReadCurrentFile(_zipFile, buffer, fileInfo.uncompressed_size) != (int)fileInfo.uncompressed_size) {
- free(buffer);
- return nullptr;
- }
-
- if (unzCloseCurrentFile(_zipFile) != UNZ_OK) {
- free(buffer);
- return nullptr;
- }
-
- return new MemoryReadStream(buffer, fileInfo.uncompressed_size, DisposeAfterUse::YES);
-
- // FIXME: instead of reading all into a memory stream, we could
- // instead create a new ZipStream class. But then we have to be
- // careful to handle the case where the client code opens multiple
- // files in the archive and tries to use them independently.
+ return unzOpenCurrentFile(_zipFile, _crc);
}
Archive *makeZipArchive(const String &name) {
Commit: 8f6beba38fbb458001be82db51e913aeed11e838
https://github.com/scummvm/scummvm/commit/8f6beba38fbb458001be82db51e913aeed11e838
Author: Vladimir Serbinenko (phcoder at gmail.com)
Date: 2022-11-29T01:05:31+01:00
Commit Message:
COMMON: Make most CRC functions const as they don't modify the object.
Changed paths:
common/crc.h
diff --git a/common/crc.h b/common/crc.h
index 47e78bf8860..117b80cbc62 100644
--- a/common/crc.h
+++ b/common/crc.h
@@ -49,8 +49,8 @@ public:
T processByte(byte byteVal, T remainder);
T finalize(T remainder);
- T crcSlow(byte const message[], int nBytes);
- T crcFast(byte const message[], int nBytes);
+ T crcSlow(byte const message[], int nBytes) const;
+ T crcFast(byte const message[], int nBytes) const;
private:
T _poly;
@@ -65,10 +65,10 @@ private:
bool _inited;
- uint32 reflect(uint32 data, byte nBits);
+ uint32 reflect(uint32 data, byte nBits) const;
- byte reflectData(byte x) { return _reflect ? (byte)reflect(x, 8) : x; }
- T reflectRemainder(T x) { return _reflect ? (T)reflect(x, _width) : x; }
+ byte reflectData(byte x) const { return _reflect ? (byte)reflect(x, 8) : x; }
+ T reflectRemainder(T x) const { return _reflect ? (T)reflect(x, _width) : x; }
};
/*********************************************************************
@@ -84,7 +84,7 @@ private:
*
*********************************************************************/
template<typename T>
-uint32 CRC<T>::reflect(uint32 data, byte nBits) {
+uint32 CRC<T>::reflect(uint32 data, byte nBits) const {
uint32 reflection = 0x00000000;
/*
@@ -117,7 +117,7 @@ uint32 CRC<T>::reflect(uint32 data, byte nBits) {
*
*********************************************************************/
template<typename T>
-T CRC<T>::crcSlow(byte const message[], int nBytes) {
+T CRC<T>::crcSlow(byte const message[], int nBytes) const {
T remainder = _init_remainder;
/*
@@ -225,7 +225,7 @@ T CRC<T>::init() {
*
*********************************************************************/
template<typename T>
-T CRC<T>::crcFast(byte const message[], int nBytes) {
+T CRC<T>::crcFast(byte const message[], int nBytes) const {
T remainder = _init_remainder;
if (!_inited)
Commit: f06348708c94f833c9579aeeec23c0d48e8320e4
https://github.com/scummvm/scummvm/commit/f06348708c94f833c9579aeeec23c0d48e8320e4
Author: Vladimir Serbinenko (phcoder at gmail.com)
Date: 2022-11-29T01:05:31+01:00
Commit Message:
COMMON: Optimize crcFast and related functions.
Currently we reflect every byte when working on reflected CRC's. Instead
follow the standard approach of reversing the table and couple of shifts
which is faster
Changed paths:
common/crc.h
diff --git a/common/crc.h b/common/crc.h
index 117b80cbc62..3454e66fb74 100644
--- a/common/crc.h
+++ b/common/crc.h
@@ -41,34 +41,50 @@
namespace Common {
-template <typename T>
-class CRC {
+template <typename T, bool need_reflect>
+class CRCCommon {
public:
- CRC(T poly, T init_remainder, T final_xor, bool reflect);
+ CRCCommon(T poly, T init_remainder, T final_xor);
T init(void);
- T processByte(byte byteVal, T remainder);
- T finalize(T remainder);
-
+ T finalize(T remainder) const;
T crcSlow(byte const message[], int nBytes) const;
- T crcFast(byte const message[], int nBytes) const;
+ T getInitRemainder() const { return reflectRemainder(_init_remainder); }
-private:
- T _poly;
- T _init_remainder;
- T _final_xor;
- bool _reflect;
+protected:
+ const T _poly;
+ const T _init_remainder;
+ const T _final_xor;
- int _width;
- int _topbit;
+ const int _width;
+ const int _topbit;
T _crcTable[256];
bool _inited;
- uint32 reflect(uint32 data, byte nBits) const;
+ template<typename R>
+ static R reflect(R data);
- byte reflectData(byte x) const { return _reflect ? (byte)reflect(x, 8) : x; }
- T reflectRemainder(T x) const { return _reflect ? (T)reflect(x, _width) : x; }
+ byte reflectData(byte x) const { return need_reflect ? reflect<byte>(x) : x; }
+ T reflectRemainder(T x) const { return need_reflect ? reflect<T>(x) : x; }
+};
+
+template <typename T>
+class CRCNormal : public CRCCommon<T, false> {
+public:
+ CRCNormal(T poly, T init_remainder, T final_xor) : CRCCommon<T, false>(poly, init_remainder, final_xor) {}
+
+ T crcFast(byte const message[], int nBytes) const;
+ T processByte(byte byteVal, T remainder) const;
+};
+
+template <typename T>
+class CRCReflected : public CRCCommon<T, true> {
+public:
+ CRCReflected(T poly, T init_remainder, T final_xor) : CRCCommon<T, true>(poly, init_remainder, final_xor) {}
+
+ T crcFast(byte const message[], int nBytes) const;
+ T processByte(byte byteVal, T remainder) const;
};
/*********************************************************************
@@ -83,19 +99,19 @@ private:
* Returns: The reflection of the original data.
*
*********************************************************************/
-template<typename T>
-uint32 CRC<T>::reflect(uint32 data, byte nBits) const {
- uint32 reflection = 0x00000000;
+template<typename T, bool need_reflect> template<typename R>
+R CRCCommon<T, need_reflect>::reflect(R data) {
+ R reflection = 0;
/*
* Reflect the data about the center bit.
*/
- for (byte bit = 0; bit < nBits; ++bit) {
+ for (byte bit = 0; bit < sizeof(R) * 8; ++bit) {
/*
* If the LSB bit is set, set the reflection of it.
*/
if (data & 0x01) {
- reflection |= (1 << ((nBits - 1) - bit));
+ reflection |= (1 << ((sizeof(R) * 8 - 1) - bit));
}
data = (data >> 1);
@@ -116,8 +132,8 @@ uint32 CRC<T>::reflect(uint32 data, byte nBits) const {
* Returns: The CRC of the message.
*
*********************************************************************/
-template<typename T>
-T CRC<T>::crcSlow(byte const message[], int nBytes) const {
+template<typename T, bool need_reflect>
+T CRCCommon<T, need_reflect>::crcSlow(byte const message[], int nBytes) const {
T remainder = _init_remainder;
/*
@@ -151,11 +167,9 @@ T CRC<T>::crcSlow(byte const message[], int nBytes) const {
}
-template<typename T>
-CRC<T>::CRC(T poly, T init_remainder, T final_xor, bool reflect) :
- _poly(poly), _init_remainder(init_remainder), _final_xor(final_xor), _reflect(reflect) {
- _width = 8 * sizeof(T);
- _topbit = 1 << (_width - 1);
+template<typename T, bool need_reflect>
+CRCCommon<T, need_reflect>::CRCCommon(T poly, T init_remainder, T final_xor) :
+ _poly(poly), _init_remainder(init_remainder), _final_xor(final_xor), _width(8 * sizeof(T)), _topbit(1 << (8 * sizeof(T) - 1)) {
for (int i = 0; i < 256; ++i)
_crcTable[i] = 0;
@@ -176,8 +190,8 @@ CRC<T>::CRC(T poly, T init_remainder, T final_xor, bool reflect) :
* Returns: Initial remainder.
*
*********************************************************************/
-template<typename T>
-T CRC<T>::init() {
+template<typename T, bool need_reflect>
+T CRCCommon<T, need_reflect>::init() {
/*
* Compute the remainder of each possible dividend.
*/
@@ -204,7 +218,7 @@ T CRC<T>::init() {
/*
* Store the result into the table.
*/
- _crcTable[dividend] = remainder;
+ _crcTable[reflectData(dividend)] = reflectRemainder(remainder);
}
_inited = true;
@@ -225,58 +239,95 @@ T CRC<T>::init() {
*
*********************************************************************/
template<typename T>
-T CRC<T>::crcFast(byte const message[], int nBytes) const {
- T remainder = _init_remainder;
+T CRCNormal<T>::crcFast(byte const message[], int nBytes) const {
+ T remainder = this->_init_remainder;
- if (!_inited)
+ if (!this->_inited)
error("CRC::crcFast(): init method must be called first");
/*
* Divide the message by the polynomial, a byte at a time.
*/
for (int b = 0; b < nBytes; ++b) {
- byte data = reflectData(message[b]) ^ (remainder >> (_width - 8));
- remainder = _crcTable[data] ^ (remainder << 8);
+ byte data = message[b] ^ (remainder >> (this->_width - 8));
+ remainder = this->_crcTable[data] ^ (remainder << 8);
}
/*
* The final remainder is the CRC.
*/
- return reflectRemainder(remainder) ^ _final_xor;
+ return remainder ^ this->_final_xor;
+}
+
+/*********************************************************************
+ *
+ * Function: crcFast()
+ *
+ * Description: Compute the CRC of a given message.
+ *
+ * Notes: crcInit() must be called first.
+ *
+ * Returns: The CRC of the message.
+ *
+ *********************************************************************/
+template<typename T>
+T CRCReflected<T>::crcFast(byte const message[], int nBytes) const {
+ T remainder = this->reflectRemainder(this->_init_remainder);
+ if (!this->_inited)
+ error("CRC::crcFast(): init method must be called first");
+
+ /*
+ * Divide the message by the polynomial, a byte at a time.
+ */
+ for (int b = 0; b < nBytes; ++b) {
+ byte data = message[b] ^ remainder;
+ remainder = this->_crcTable[data] ^ (remainder >> 8);
+ }
+
+ /*
+ * The final remainder is the CRC.
+ */
+ return remainder ^ this->_final_xor;
}
template<typename T>
-T CRC<T>::processByte(byte byteVal, T remainder) {
- byte data = reflectData(byteVal) ^ (remainder >> (_width - 8));
+T CRCNormal<T>::processByte(byte byteVal, T remainder) const {
+ byte data = byteVal ^ (remainder >> (this->_width - 8));
- remainder = _crcTable[data] ^ (remainder << 8);
- return remainder;
+ return this->_crcTable[data] ^ (remainder << 8);
}
template<typename T>
-T CRC<T>::finalize(T remainder) {
- return reflectRemainder(remainder) ^ _final_xor;
+T CRCReflected<T>::processByte(byte byteVal, T remainder) const {
+ byte data = byteVal ^ remainder;
+
+ return this->_crcTable[data] ^ (remainder >> 8);
+}
+
+template<typename T, bool need_reflect>
+T CRCCommon<T, need_reflect>::finalize(T remainder) const {
+ return remainder ^ _final_xor;
}
-class CRC_CCITT : public CRC<uint16> {
+class CRC_CCITT : public CRCNormal<uint16> {
public:
- CRC_CCITT() : CRC<uint16>(0x1021, 0xFFFF, 0x0000, false) {}
+ CRC_CCITT() : CRCNormal<uint16>(0x1021, 0xFFFF, 0x0000) {}
};
-class CRC_BINHEX : public CRC<uint16> {
+class CRC_BINHEX : public CRCNormal<uint16> {
public:
- CRC_BINHEX() : CRC<uint16>(0x1021, 0x0000, 0x0000, false) {}
+ CRC_BINHEX() : CRCNormal<uint16>(0x1021, 0x0000, 0x0000) {}
};
-class CRC16 : public CRC<uint16> {
+class CRC16 : public CRCReflected<uint16> {
public:
- CRC16() : CRC<uint16>(0x8005, 0x0000, 0x0000, true) {}
+ CRC16() : CRCReflected<uint16>(0x8005, 0x0000, 0x0000) {}
};
-class CRC32 : public CRC<uint32> {
+class CRC32 : public CRCReflected<uint32> {
public:
- CRC32() : CRC<uint32>(0x04C11DB7, 0xFFFFFFFF, 0xFFFFFFFF, true) {}
+ CRC32() : CRCReflected<uint32>(0x04C11DB7, 0xFFFFFFFF, 0xFFFFFFFF) {}
};
} // End of namespace Common
Commit: 35bac4e58ce407c6189ea524c050d7c022a4b888
https://github.com/scummvm/scummvm/commit/35bac4e58ce407c6189ea524c050d7c022a4b888
Author: Vladimir Serbinenko (phcoder at gmail.com)
Date: 2022-11-29T01:05:31+01:00
Commit Message:
COMMON: Add tests for CRC
Changed paths:
A test/common/crc.h
diff --git a/test/common/crc.h b/test/common/crc.h
new file mode 100644
index 00000000000..d8862e8ad4c
--- /dev/null
+++ b/test/common/crc.h
@@ -0,0 +1,56 @@
+#include <cxxtest/TestSuite.h>
+
+#include "common/crc.h"
+
+namespace {
+const byte *testString = (const byte *)"The quick brown fox jumps over the lazy dog";
+const int testLen = 43;
+}
+
+class CrcTestSuite : public CxxTest::TestSuite
+{
+public:
+ void test_crc32() {
+ Common::CRC32 crc;
+ crc.init();
+ TS_ASSERT_EQUALS(crc.crcFast(testString, testLen), 0x414fa339U);
+ TS_ASSERT_EQUALS(crc.crcSlow(testString, testLen), 0x414fa339U);
+ uint32 running = crc.getInitRemainder();
+ for (const byte *ptr = testString; *ptr; ptr++)
+ running = crc.processByte(*ptr, running);
+ TS_ASSERT_EQUALS(crc.finalize(running), 0x414fa339U);
+ }
+
+ void test_crc16() {
+ Common::CRC16 crc;
+ crc.init();
+ TS_ASSERT_EQUALS(crc.crcFast(testString, testLen), 0xfcdfU);
+ TS_ASSERT_EQUALS(crc.crcSlow(testString, testLen), 0xfcdfU);
+ uint16 running = crc.getInitRemainder();
+ for (const byte *ptr = testString; *ptr; ptr++)
+ running = crc.processByte(*ptr, running);
+ TS_ASSERT_EQUALS(crc.finalize(running), 0xfcdfU);
+ }
+
+ void test_crc_ccitt() {
+ Common::CRC_CCITT crc; // aka ccitt-false
+ crc.init();
+ TS_ASSERT_EQUALS(crc.crcFast(testString, testLen), 0x8fddU);
+ TS_ASSERT_EQUALS(crc.crcSlow(testString, testLen), 0x8fddU);
+ uint16 running = crc.getInitRemainder();
+ for (const byte *ptr = testString; *ptr; ptr++)
+ running = crc.processByte(*ptr, running);
+ TS_ASSERT_EQUALS(crc.finalize(running), 0x8fddU);
+ }
+
+ void test_crc_binhex() {
+ Common::CRC_BINHEX crc; // Aka xmodem
+ crc.init();
+ TS_ASSERT_EQUALS(crc.crcFast(testString, testLen), 0xf0c8U);
+ TS_ASSERT_EQUALS(crc.crcSlow(testString, testLen), 0xf0c8U);
+ uint16 running = crc.getInitRemainder();
+ for (const byte *ptr = testString; *ptr; ptr++)
+ running = crc.processByte(*ptr, running);
+ TS_ASSERT_EQUALS(crc.finalize(running), 0xf0c8U);
+ }
+};
Commit: 05f1a0df510c10f190f51efa6ac951e92c0c60f5
https://github.com/scummvm/scummvm/commit/05f1a0df510c10f190f51efa6ac951e92c0c60f5
Author: Vladimir Serbinenko (phcoder at gmail.com)
Date: 2022-11-29T01:05:31+01:00
Commit Message:
COMMON: Remove the need for most reflecting when initing reflected table
Instead reflect the polynomial and change the shifts. Also removes the
need for explicit init.
This makes our crc more similar to its standard implementation
Changed paths:
common/crc.h
common/macresman.cpp
common/unzip.cpp
engines/mtropolis/boot.cpp
test/common/crc.h
diff --git a/common/crc.h b/common/crc.h
index 3454e66fb74..fa01921635e 100644
--- a/common/crc.h
+++ b/common/crc.h
@@ -45,7 +45,6 @@ template <typename T, bool need_reflect>
class CRCCommon {
public:
CRCCommon(T poly, T init_remainder, T final_xor);
- T init(void);
T finalize(T remainder) const;
T crcSlow(byte const message[], int nBytes) const;
T getInitRemainder() const { return reflectRemainder(_init_remainder); }
@@ -58,10 +57,6 @@ protected:
const int _width;
const int _topbit;
- T _crcTable[256];
-
- bool _inited;
-
template<typename R>
static R reflect(R data);
@@ -72,19 +67,25 @@ protected:
template <typename T>
class CRCNormal : public CRCCommon<T, false> {
public:
- CRCNormal(T poly, T init_remainder, T final_xor) : CRCCommon<T, false>(poly, init_remainder, final_xor) {}
+ CRCNormal(T poly, T init_remainder, T final_xor);
T crcFast(byte const message[], int nBytes) const;
T processByte(byte byteVal, T remainder) const;
+
+private:
+ T _crcTable[256];
};
template <typename T>
class CRCReflected : public CRCCommon<T, true> {
public:
- CRCReflected(T poly, T init_remainder, T final_xor) : CRCCommon<T, true>(poly, init_remainder, final_xor) {}
+ CRCReflected(T poly, T init_remainder, T final_xor);
T crcFast(byte const message[], int nBytes) const;
T processByte(byte byteVal, T remainder) const;
+
+private:
+ T _crcTable[256];
};
/*********************************************************************
@@ -169,29 +170,10 @@ T CRCCommon<T, need_reflect>::crcSlow(byte const message[], int nBytes) const {
template<typename T, bool need_reflect>
CRCCommon<T, need_reflect>::CRCCommon(T poly, T init_remainder, T final_xor) :
- _poly(poly), _init_remainder(init_remainder), _final_xor(final_xor), _width(8 * sizeof(T)), _topbit(1 << (8 * sizeof(T) - 1)) {
-
- for (int i = 0; i < 256; ++i)
- _crcTable[i] = 0;
-
- _inited = false;
-}
+ _poly(poly), _init_remainder(init_remainder), _final_xor(final_xor), _width(8 * sizeof(T)), _topbit(1 << (8 * sizeof(T) - 1)) {}
-/*********************************************************************
- *
- * Function: crcInit()
- *
- * Description: Populate the partial CRC lookup table.
- *
- * Notes: This function must be rerun any time the CRC standard
- * is changed. If desired, it can be run "offline" and
- * the table results stored in an embedded system's ROM.
- *
- * Returns: Initial remainder.
- *
- *********************************************************************/
-template<typename T, bool need_reflect>
-T CRCCommon<T, need_reflect>::init() {
+template <typename T>
+CRCNormal<T>::CRCNormal(T poly, T init_remainder, T final_xor) : CRCCommon<T, false>(poly, init_remainder, final_xor) {
/*
* Compute the remainder of each possible dividend.
*/
@@ -199,7 +181,7 @@ T CRCCommon<T, need_reflect>::init() {
/*
* Start with the dividend followed by zeros.
*/
- T remainder = dividend << (_width - 8);
+ T remainder = dividend << (this->_width - 8);
/*
* Perform modulo-2 division, a bit at a time.
@@ -208,8 +190,8 @@ T CRCCommon<T, need_reflect>::init() {
/*
* Try to divide the current data bit.
*/
- if (remainder & _topbit) {
- remainder = (remainder << 1) ^ _poly;
+ if (remainder & this->_topbit) {
+ remainder = (remainder << 1) ^ this->_poly;
} else {
remainder = (remainder << 1);
}
@@ -218,14 +200,43 @@ T CRCCommon<T, need_reflect>::init() {
/*
* Store the result into the table.
*/
- _crcTable[reflectData(dividend)] = reflectRemainder(remainder);
- }
+ this->_crcTable[dividend] = remainder;
+ }
+}
- _inited = true;
+template <typename T>
+CRCReflected<T>::CRCReflected(T poly, T init_remainder, T final_xor) : CRCCommon<T, true>(poly, init_remainder, final_xor) {
+ T reflected_poly = this->reflectRemainder(poly);
- return _init_remainder;
-}
+ /*
+ * Compute the remainder of each possible dividend.
+ */
+ for (int dividend = 0; dividend < 256; ++dividend) {
+ /*
+ * Start with the dividend followed by zeros.
+ */
+ T remainder = dividend;
+ /*
+ * Perform modulo-2 division, a bit at a time.
+ */
+ for (byte bit = 8; bit > 0; --bit) {
+ /*
+ * Try to divide the current data bit.
+ */
+ if (remainder & 1) {
+ remainder = (remainder >> 1) ^ reflected_poly;
+ } else {
+ remainder = (remainder >> 1);
+ }
+ }
+
+ /*
+ * Store the result into the table.
+ */
+ _crcTable[dividend] = remainder;
+ }
+}
/*********************************************************************
*
@@ -242,9 +253,6 @@ template<typename T>
T CRCNormal<T>::crcFast(byte const message[], int nBytes) const {
T remainder = this->_init_remainder;
- if (!this->_inited)
- error("CRC::crcFast(): init method must be called first");
-
/*
* Divide the message by the polynomial, a byte at a time.
*/
@@ -274,9 +282,6 @@ template<typename T>
T CRCReflected<T>::crcFast(byte const message[], int nBytes) const {
T remainder = this->reflectRemainder(this->_init_remainder);
- if (!this->_inited)
- error("CRC::crcFast(): init method must be called first");
-
/*
* Divide the message by the polynomial, a byte at a time.
*/
diff --git a/common/macresman.cpp b/common/macresman.cpp
index 1eb222464c4..e0f468b2844 100644
--- a/common/macresman.cpp
+++ b/common/macresman.cpp
@@ -556,7 +556,6 @@ bool MacResManager::readAndValidateMacBinaryHeader(SeekableReadStream &stream, b
return false;
CRC_BINHEX crc;
- crc.init();
uint16 checkSum = crc.crcFast(infoHeader, 124);
// Sanity check on the CRC. Some movies could look like MacBinary
diff --git a/common/unzip.cpp b/common/unzip.cpp
index e967d22979c..b53433db834 100644
--- a/common/unzip.cpp
+++ b/common/unzip.cpp
@@ -1000,7 +1000,6 @@ public:
ZipArchive::ZipArchive(unzFile zipFile) : _zipFile(zipFile), _crc() {
assert(_zipFile);
- _crc.init();
}
ZipArchive::~ZipArchive() {
diff --git a/engines/mtropolis/boot.cpp b/engines/mtropolis/boot.cpp
index 1eb9e8291f5..da6dd243479 100644
--- a/engines/mtropolis/boot.cpp
+++ b/engines/mtropolis/boot.cpp
@@ -760,7 +760,6 @@ static bool getMacTypesForMacBinary(const char *fileName, uint32 &outType, uint3
return false;
Common::CRC_BINHEX crc;
- crc.init();
uint16 checkSum = crc.crcFast(mbHeader, 124);
if (checkSum != READ_BE_UINT16(&mbHeader[124]))
diff --git a/test/common/crc.h b/test/common/crc.h
index d8862e8ad4c..0c4ccd9d0ba 100644
--- a/test/common/crc.h
+++ b/test/common/crc.h
@@ -12,7 +12,6 @@ class CrcTestSuite : public CxxTest::TestSuite
public:
void test_crc32() {
Common::CRC32 crc;
- crc.init();
TS_ASSERT_EQUALS(crc.crcFast(testString, testLen), 0x414fa339U);
TS_ASSERT_EQUALS(crc.crcSlow(testString, testLen), 0x414fa339U);
uint32 running = crc.getInitRemainder();
@@ -23,7 +22,6 @@ public:
void test_crc16() {
Common::CRC16 crc;
- crc.init();
TS_ASSERT_EQUALS(crc.crcFast(testString, testLen), 0xfcdfU);
TS_ASSERT_EQUALS(crc.crcSlow(testString, testLen), 0xfcdfU);
uint16 running = crc.getInitRemainder();
@@ -34,7 +32,6 @@ public:
void test_crc_ccitt() {
Common::CRC_CCITT crc; // aka ccitt-false
- crc.init();
TS_ASSERT_EQUALS(crc.crcFast(testString, testLen), 0x8fddU);
TS_ASSERT_EQUALS(crc.crcSlow(testString, testLen), 0x8fddU);
uint16 running = crc.getInitRemainder();
@@ -45,7 +42,6 @@ public:
void test_crc_binhex() {
Common::CRC_BINHEX crc; // Aka xmodem
- crc.init();
TS_ASSERT_EQUALS(crc.crcFast(testString, testLen), 0xf0c8U);
TS_ASSERT_EQUALS(crc.crcSlow(testString, testLen), 0xf0c8U);
uint16 running = crc.getInitRemainder();
Commit: 357249fb5af74be77a6eda953d6d729f01a13852
https://github.com/scummvm/scummvm/commit/357249fb5af74be77a6eda953d6d729f01a13852
Author: Vladimir Serbinenko (phcoder at gmail.com)
Date: 2022-11-29T01:05:31+01:00
Commit Message:
COMMON: Split slow and fast CRC implementation
They have almost nothing in common. And we probably want to kill slow
implementation anyway now that we have tests
Changed paths:
A common/crc_slow.h
common/crc.h
test/common/crc.h
diff --git a/common/crc.h b/common/crc.h
index fa01921635e..9a47fc1df5c 100644
--- a/common/crc.h
+++ b/common/crc.h
@@ -23,7 +23,7 @@
*
* Filename: crc.c
*
- * Description: Slow and fast implementations of the CRC standards.
+ * Description: Fast implementation of the CRC standards.
*
* Notes:
*
@@ -41,139 +41,44 @@
namespace Common {
-template <typename T, bool need_reflect>
-class CRCCommon {
-public:
- CRCCommon(T poly, T init_remainder, T final_xor);
- T finalize(T remainder) const;
- T crcSlow(byte const message[], int nBytes) const;
- T getInitRemainder() const { return reflectRemainder(_init_remainder); }
-
-protected:
- const T _poly;
- const T _init_remainder;
- const T _final_xor;
-
- const int _width;
- const int _topbit;
-
- template<typename R>
- static R reflect(R data);
-
- byte reflectData(byte x) const { return need_reflect ? reflect<byte>(x) : x; }
- T reflectRemainder(T x) const { return need_reflect ? reflect<T>(x) : x; }
-};
-
template <typename T>
-class CRCNormal : public CRCCommon<T, false> {
+class CRCNormal {
public:
CRCNormal(T poly, T init_remainder, T final_xor);
T crcFast(byte const message[], int nBytes) const;
T processByte(byte byteVal, T remainder) const;
+ T getInitRemainder() const { return _init_remainder; }
+ T finalize(T remainder) const { return remainder ^ _final_xor; }
private:
+ const T _init_remainder;
+ const T _final_xor;
+
T _crcTable[256];
};
template <typename T>
-class CRCReflected : public CRCCommon<T, true> {
+class CRCReflected {
public:
CRCReflected(T poly, T init_remainder, T final_xor);
T crcFast(byte const message[], int nBytes) const;
T processByte(byte byteVal, T remainder) const;
+ T getInitRemainder() const { return _reflected_init_remainder; }
+ T finalize(T remainder) const { return remainder ^ _final_xor; }
private:
T _crcTable[256];
+ const T _reflected_init_remainder;
+ const T _final_xor;
};
-/*********************************************************************
- *
- * Function: reflect()
- *
- * Description: Reorder the bits of a binary sequence, by reflecting
- * them about the middle position.
- *
- * Notes: No checking is done that nBits <= 32.
- *
- * Returns: The reflection of the original data.
- *
- *********************************************************************/
-template<typename T, bool need_reflect> template<typename R>
-R CRCCommon<T, need_reflect>::reflect(R data) {
- R reflection = 0;
-
- /*
- * Reflect the data about the center bit.
- */
- for (byte bit = 0; bit < sizeof(R) * 8; ++bit) {
- /*
- * If the LSB bit is set, set the reflection of it.
- */
- if (data & 0x01) {
- reflection |= (1 << ((sizeof(R) * 8 - 1) - bit));
- }
-
- data = (data >> 1);
- }
-
- return reflection;
-}
-
-
-/*********************************************************************
- *
- * Function: crcSlow()
- *
- * Description: Compute the CRC of a given message.
- *
- * Notes:
- *
- * Returns: The CRC of the message.
- *
- *********************************************************************/
-template<typename T, bool need_reflect>
-T CRCCommon<T, need_reflect>::crcSlow(byte const message[], int nBytes) const {
- T remainder = _init_remainder;
-
- /*
- * Perform modulo-2 division, a byte at a time.
- */
- for (int b = 0; b < nBytes; ++b) {
- /*
- * Bring the next byte into the remainder.
- */
- remainder ^= reflectData(message[b]) << (_width - 8);
-
- /*
- * Perform modulo-2 division, a bit at a time.
- */
- for (byte bit = 8; bit > 0; --bit) {
- /*
- * Try to divide the current data bit.
- */
- if (remainder & _topbit) {
- remainder = (remainder << 1) ^ _poly;
- } else {
- remainder = (remainder << 1);
- }
- }
- }
-
- /*
- * The final remainder is the CRC result.
- */
- return reflectRemainder(remainder) ^ _final_xor;
-}
-
-
-template<typename T, bool need_reflect>
-CRCCommon<T, need_reflect>::CRCCommon(T poly, T init_remainder, T final_xor) :
- _poly(poly), _init_remainder(init_remainder), _final_xor(final_xor), _width(8 * sizeof(T)), _topbit(1 << (8 * sizeof(T) - 1)) {}
template <typename T>
-CRCNormal<T>::CRCNormal(T poly, T init_remainder, T final_xor) : CRCCommon<T, false>(poly, init_remainder, final_xor) {
+CRCNormal<T>::CRCNormal(T poly, T init_remainder, T final_xor) : _init_remainder(init_remainder), _final_xor(final_xor) {
+ const T topbit = 1ULL << (8 * sizeof(T) - 1);
+
/*
* Compute the remainder of each possible dividend.
*/
@@ -181,7 +86,7 @@ CRCNormal<T>::CRCNormal(T poly, T init_remainder, T final_xor) : CRCCommon<T, fa
/*
* Start with the dividend followed by zeros.
*/
- T remainder = dividend << (this->_width - 8);
+ T remainder = dividend << (8 * sizeof(T) - 8);
/*
* Perform modulo-2 division, a bit at a time.
@@ -190,8 +95,8 @@ CRCNormal<T>::CRCNormal(T poly, T init_remainder, T final_xor) : CRCCommon<T, fa
/*
* Try to divide the current data bit.
*/
- if (remainder & this->_topbit) {
- remainder = (remainder << 1) ^ this->_poly;
+ if (remainder & topbit) {
+ remainder = (remainder << 1) ^ poly;
} else {
remainder = (remainder << 1);
}
@@ -200,14 +105,12 @@ CRCNormal<T>::CRCNormal(T poly, T init_remainder, T final_xor) : CRCCommon<T, fa
/*
* Store the result into the table.
*/
- this->_crcTable[dividend] = remainder;
+ _crcTable[dividend] = remainder;
}
}
template <typename T>
-CRCReflected<T>::CRCReflected(T poly, T init_remainder, T final_xor) : CRCCommon<T, true>(poly, init_remainder, final_xor) {
- T reflected_poly = this->reflectRemainder(poly);
-
+CRCReflected<T>::CRCReflected(T reflected_poly, T reflected_init_remainder, T final_xor) : _reflected_init_remainder(reflected_init_remainder), _final_xor(final_xor) {
/*
* Compute the remainder of each possible dividend.
*/
@@ -251,20 +154,20 @@ CRCReflected<T>::CRCReflected(T poly, T init_remainder, T final_xor) : CRCCommon
*********************************************************************/
template<typename T>
T CRCNormal<T>::crcFast(byte const message[], int nBytes) const {
- T remainder = this->_init_remainder;
+ T remainder = _init_remainder;
/*
* Divide the message by the polynomial, a byte at a time.
*/
for (int b = 0; b < nBytes; ++b) {
- byte data = message[b] ^ (remainder >> (this->_width - 8));
- remainder = this->_crcTable[data] ^ (remainder << 8);
+ byte data = message[b] ^ (remainder >> (8 * sizeof(T) - 8));
+ remainder = _crcTable[data] ^ (remainder << 8);
}
/*
* The final remainder is the CRC.
*/
- return remainder ^ this->_final_xor;
+ return remainder ^ _final_xor;
}
/*********************************************************************
@@ -280,39 +183,34 @@ T CRCNormal<T>::crcFast(byte const message[], int nBytes) const {
*********************************************************************/
template<typename T>
T CRCReflected<T>::crcFast(byte const message[], int nBytes) const {
- T remainder = this->reflectRemainder(this->_init_remainder);
+ T remainder = _reflected_init_remainder;
/*
* Divide the message by the polynomial, a byte at a time.
*/
for (int b = 0; b < nBytes; ++b) {
byte data = message[b] ^ remainder;
- remainder = this->_crcTable[data] ^ (remainder >> 8);
+ remainder = _crcTable[data] ^ (remainder >> 8);
}
/*
* The final remainder is the CRC.
*/
- return remainder ^ this->_final_xor;
+ return remainder ^ _final_xor;
}
template<typename T>
T CRCNormal<T>::processByte(byte byteVal, T remainder) const {
- byte data = byteVal ^ (remainder >> (this->_width - 8));
+ byte data = byteVal ^ (remainder >> (8 * sizeof(T) - 8));
- return this->_crcTable[data] ^ (remainder << 8);
+ return _crcTable[data] ^ (remainder << 8);
}
template<typename T>
T CRCReflected<T>::processByte(byte byteVal, T remainder) const {
byte data = byteVal ^ remainder;
- return this->_crcTable[data] ^ (remainder >> 8);
-}
-
-template<typename T, bool need_reflect>
-T CRCCommon<T, need_reflect>::finalize(T remainder) const {
- return remainder ^ _final_xor;
+ return _crcTable[data] ^ (remainder >> 8);
}
class CRC_CCITT : public CRCNormal<uint16> {
@@ -327,12 +225,12 @@ public:
class CRC16 : public CRCReflected<uint16> {
public:
- CRC16() : CRCReflected<uint16>(0x8005, 0x0000, 0x0000) {}
+ CRC16() : CRCReflected<uint16>(0xa001, 0x0000, 0x0000) {}
};
class CRC32 : public CRCReflected<uint32> {
public:
- CRC32() : CRCReflected<uint32>(0x04C11DB7, 0xFFFFFFFF, 0xFFFFFFFF) {}
+ CRC32() : CRCReflected<uint32>(0xEDB88320, 0xFFFFFFFF, 0xFFFFFFFF) {}
};
} // End of namespace Common
diff --git a/common/crc_slow.h b/common/crc_slow.h
new file mode 100644
index 00000000000..f06adac9944
--- /dev/null
+++ b/common/crc_slow.h
@@ -0,0 +1,173 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/**********************************************************************
+ *
+ * Filename: crc.c
+ *
+ * Description: Slow implementation of the CRC standards.
+ *
+ * Notes:
+ *
+ *
+ * Copyright (c) 2000 by Michael Barr. This software is placed into
+ * the public domain and may be used for any purpose. However, this
+ * notice must not be changed or removed and no warranty is either
+ * expressed or implied by its publication or distribution.
+ **********************************************************************/
+
+#ifndef COMMON_CRC_SLOW_H
+#define COMMON_CRC_SLOW_H
+
+#include "common/system.h" // For types.
+
+namespace Common {
+
+template <typename T>
+class CRCSlow {
+public:
+ CRCSlow(T poly, T init_remainder, T final_xor, bool need_reflect);
+ T crcSlow(byte const message[], int nBytes) const;
+
+protected:
+ const T _poly;
+ const T _init_remainder;
+ const T _final_xor;
+
+ const int _width;
+ const int _topbit;
+
+ const bool _reflect;
+
+ template<typename R>
+ static R reflect(R data);
+
+ byte reflectData(byte x) const { return _reflect ? reflect<byte>(x) : x; }
+ T reflectRemainder(T x) const { return _reflect ? reflect<T>(x) : x; }
+};
+
+/*********************************************************************
+ *
+ * Function: reflect()
+ *
+ * Description: Reorder the bits of a binary sequence, by reflecting
+ * them about the middle position.
+ *
+ * Notes: No checking is done that nBits <= 32.
+ *
+ * Returns: The reflection of the original data.
+ *
+ *********************************************************************/
+template<typename T> template<typename R>
+R CRCSlow<T>::reflect(R data) {
+ R reflection = 0;
+
+ /*
+ * Reflect the data about the center bit.
+ */
+ for (byte bit = 0; bit < sizeof(R) * 8; ++bit) {
+ /*
+ * If the LSB bit is set, set the reflection of it.
+ */
+ if (data & 0x01) {
+ reflection |= (1 << ((sizeof(R) * 8 - 1) - bit));
+ }
+
+ data = (data >> 1);
+ }
+
+ return reflection;
+}
+
+
+/*********************************************************************
+ *
+ * Function: crcSlow()
+ *
+ * Description: Compute the CRC of a given message.
+ *
+ * Notes:
+ *
+ * Returns: The CRC of the message.
+ *
+ *********************************************************************/
+template<typename T>
+T CRCSlow<T>::crcSlow(byte const message[], int nBytes) const {
+ T remainder = _init_remainder;
+
+ /*
+ * Perform modulo-2 division, a byte at a time.
+ */
+ for (int b = 0; b < nBytes; ++b) {
+ /*
+ * Bring the next byte into the remainder.
+ */
+ remainder ^= reflectData(message[b]) << (_width - 8);
+
+ /*
+ * Perform modulo-2 division, a bit at a time.
+ */
+ for (byte bit = 8; bit > 0; --bit) {
+ /*
+ * Try to divide the current data bit.
+ */
+ if (remainder & _topbit) {
+ remainder = (remainder << 1) ^ _poly;
+ } else {
+ remainder = (remainder << 1);
+ }
+ }
+ }
+
+ /*
+ * The final remainder is the CRC result.
+ */
+ return reflectRemainder(remainder) ^ _final_xor;
+}
+
+
+template<typename T>
+CRCSlow<T>::CRCSlow(T poly, T init_remainder, T final_xor, bool need_reflect) :
+ _poly(poly), _init_remainder(init_remainder), _final_xor(final_xor), _width(8 * sizeof(T)), _topbit(1 << (8 * sizeof(T) - 1)), _reflect(need_reflect) {}
+
+class CRC_CCITT_Slow : public CRCSlow<uint16> {
+public:
+ CRC_CCITT_Slow() : CRCSlow<uint16>(0x1021, 0xFFFF, 0x0000, false) {}
+};
+
+class CRC_BINHEX_Slow : public CRCSlow<uint16> {
+public:
+ CRC_BINHEX_Slow() : CRCSlow<uint16>(0x1021, 0x0000, 0x0000, false) {}
+};
+
+class CRC16_Slow : public CRCSlow<uint16> {
+public:
+ CRC16_Slow() : CRCSlow<uint16>(0x8005, 0x0000, 0x0000, true) {}
+};
+
+class CRC32_Slow : public CRCSlow<uint32> {
+public:
+ CRC32_Slow() : CRCSlow<uint32>(0x04C11DB7, 0xFFFFFFFF, 0xFFFFFFFF, true) {}
+};
+
+} // End of namespace Common
+
+#endif
diff --git a/test/common/crc.h b/test/common/crc.h
index 0c4ccd9d0ba..92bdf76cf4c 100644
--- a/test/common/crc.h
+++ b/test/common/crc.h
@@ -1,6 +1,7 @@
#include <cxxtest/TestSuite.h>
#include "common/crc.h"
+#include "common/crc_slow.h"
namespace {
const byte *testString = (const byte *)"The quick brown fox jumps over the lazy dog";
@@ -13,7 +14,6 @@ public:
void test_crc32() {
Common::CRC32 crc;
TS_ASSERT_EQUALS(crc.crcFast(testString, testLen), 0x414fa339U);
- TS_ASSERT_EQUALS(crc.crcSlow(testString, testLen), 0x414fa339U);
uint32 running = crc.getInitRemainder();
for (const byte *ptr = testString; *ptr; ptr++)
running = crc.processByte(*ptr, running);
@@ -23,7 +23,6 @@ public:
void test_crc16() {
Common::CRC16 crc;
TS_ASSERT_EQUALS(crc.crcFast(testString, testLen), 0xfcdfU);
- TS_ASSERT_EQUALS(crc.crcSlow(testString, testLen), 0xfcdfU);
uint16 running = crc.getInitRemainder();
for (const byte *ptr = testString; *ptr; ptr++)
running = crc.processByte(*ptr, running);
@@ -33,7 +32,6 @@ public:
void test_crc_ccitt() {
Common::CRC_CCITT crc; // aka ccitt-false
TS_ASSERT_EQUALS(crc.crcFast(testString, testLen), 0x8fddU);
- TS_ASSERT_EQUALS(crc.crcSlow(testString, testLen), 0x8fddU);
uint16 running = crc.getInitRemainder();
for (const byte *ptr = testString; *ptr; ptr++)
running = crc.processByte(*ptr, running);
@@ -43,10 +41,29 @@ public:
void test_crc_binhex() {
Common::CRC_BINHEX crc; // Aka xmodem
TS_ASSERT_EQUALS(crc.crcFast(testString, testLen), 0xf0c8U);
- TS_ASSERT_EQUALS(crc.crcSlow(testString, testLen), 0xf0c8U);
uint16 running = crc.getInitRemainder();
for (const byte *ptr = testString; *ptr; ptr++)
running = crc.processByte(*ptr, running);
TS_ASSERT_EQUALS(crc.finalize(running), 0xf0c8U);
}
+
+ void test_crc32_slow() {
+ Common::CRC32_Slow crc;
+ TS_ASSERT_EQUALS(crc.crcSlow(testString, testLen), 0x414fa339U);
+ }
+
+ void test_crc16_slow() {
+ Common::CRC16_Slow crc;
+ TS_ASSERT_EQUALS(crc.crcSlow(testString, testLen), 0xfcdfU);
+ }
+
+ void test_crc_ccitt_slow() {
+ Common::CRC_CCITT_Slow crc; // aka ccitt-false
+ TS_ASSERT_EQUALS(crc.crcSlow(testString, testLen), 0x8fddU);
+ }
+
+ void test_crc_binhex_slow() {
+ Common::CRC_BINHEX_Slow crc; // Aka xmodem
+ TS_ASSERT_EQUALS(crc.crcSlow(testString, testLen), 0xf0c8U);
+ }
};
More information about the Scummvm-git-logs
mailing list