1 // CrcReg.cpp
2 
3 #include "StdAfx.h"
4 
5 #include "../../C/7zCrc.h"
6 #include "../../C/CpuArch.h"
7 
8 #include "../Common/MyCom.h"
9 
10 #include "../7zip/ICoder.h"
11 #include "../7zip/Common/RegisterCodec.h"
12 
13 EXTERN_C_BEGIN
14 
15 typedef UInt32 (MY_FAST_CALL *CRC_FUNC)(UInt32 v, const void *data, size_t size, const UInt32 *table);
16 
17 extern CRC_FUNC g_CrcUpdate;
18 
19 #ifdef MY_CPU_X86_OR_AMD64
20   UInt32 MY_FAST_CALL CrcUpdateT8(UInt32 v, const void *data, size_t size, const UInt32 *table);
21 #endif
22 
23 #ifndef MY_CPU_BE
24   UInt32 MY_FAST_CALL CrcUpdateT4(UInt32 v, const void *data, size_t size, const UInt32 *table);
25 #endif
26 
27 EXTERN_C_END
28 
29 class CCrcHasher:
30   public IHasher,
31   public ICompressSetCoderProperties,
32   public CMyUnknownImp
33 {
34   UInt32 _crc;
35   CRC_FUNC _updateFunc;
36   bool SetFunctions(UInt32 tSize);
37 public:
CCrcHasher()38   CCrcHasher(): _crc(CRC_INIT_VAL) { SetFunctions(0); }
39 
40   MY_UNKNOWN_IMP1(ICompressSetCoderProperties)
41 
42   STDMETHOD_(void, Init)();
43   STDMETHOD_(void, Update)(const void *data, UInt32 size);
44   STDMETHOD_(void, Final)(Byte *digest);
45   STDMETHOD_(UInt32, GetDigestSize)();
46   STDMETHOD(SetCoderProperties)(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps);
47 };
48 
STDMETHODIMP_(void)49 STDMETHODIMP_(void) CCrcHasher::Init()
50 {
51   _crc = CRC_INIT_VAL;
52 }
53 
STDMETHODIMP_(void)54 STDMETHODIMP_(void) CCrcHasher::Update(const void *data, UInt32 size)
55 {
56   _crc = _updateFunc(_crc, data, size, g_CrcTable);
57 }
58 
STDMETHODIMP_(void)59 STDMETHODIMP_(void) CCrcHasher::Final(Byte *digest)
60 {
61   UInt32 val = CRC_GET_DIGEST(_crc);
62   SetUi32(digest, val);
63 }
64 
STDMETHODIMP_(UInt32)65 STDMETHODIMP_(UInt32) CCrcHasher::GetDigestSize()
66 {
67   return 4;
68 }
69 
SetFunctions(UInt32 tSize)70 bool CCrcHasher::SetFunctions(UInt32 tSize)
71 {
72   _updateFunc = g_CrcUpdate;
73   if (tSize == 4)
74   {
75     #ifndef MY_CPU_BE
76     _updateFunc = CrcUpdateT4;
77     #endif
78   }
79   else if (tSize == 8)
80   {
81     #ifdef MY_CPU_X86_OR_AMD64
82       _updateFunc = CrcUpdateT8;
83     #else
84       return false;
85     #endif
86   }
87   return true;
88 }
89 
SetCoderProperties(const PROPID * propIDs,const PROPVARIANT * coderProps,UInt32 numProps)90 STDMETHODIMP CCrcHasher::SetCoderProperties(const PROPID *propIDs,
91     const PROPVARIANT *coderProps, UInt32 numProps)
92 {
93   for (UInt32 i = 0; i < numProps; i++)
94   {
95     const PROPVARIANT &prop = coderProps[i];
96     if (propIDs[i] == NCoderPropID::kDefaultProp)
97     {
98       if (prop.vt != VT_UI4)
99         return E_INVALIDARG;
100       if (!SetFunctions(prop.ulVal))
101         return E_NOTIMPL;
102     }
103   }
104   return S_OK;
105 }
106 
CreateHasher()107 static IHasher *CreateHasher() { return new CCrcHasher(); }
108 
109 static CHasherInfo g_HasherInfo = { CreateHasher, 0x1, L"CRC32", 4 };
110 
111 REGISTER_HASHER(Crc32)
112