1 // Copyright (C) 1999-2005 Open Source Telecom Corporation.
2 // Copyright (C) 2006-2010 David Sugar, Tycho Softworks.
3 //
4 // This program is free software; you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation; either version 2 of the License, or
7 // (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 // GNU General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License
15 // along with this program; if not, write to the Free Software
16 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17 //
18 // As a special exception, you may use this file as part of a free software
19 // library without restriction.  Specifically, if other files instantiate
20 // templates or use macros or inline functions from this file, or you compile
21 // this file and link it with other files to produce an executable, this
22 // file does not by itself cause the resulting executable to be covered by
23 // the GNU General Public License.  This exception does not however
24 // invalidate any other reasons why the executable file might be covered by
25 // the GNU General Public License.
26 //
27 // This exception applies only to the code released under the name GNU
28 // Common C++.  If you copy code from other releases into a copy of GNU
29 // Common C++, as the General Public License permits, the exception does
30 // not apply to the code that you add in this way.  To avoid misleading
31 // anyone as to the status of such modified files, you must delete
32 // this exception notice from them.
33 //
34 // If you write modifications of your own for GNU Common C++, it is your choice
35 // whether to permit this exception to apply to your modifications.
36 // If you do not wish that, delete this exception notice.
37 //
38 
39 #include <cc++/config.h>
40 #include <cc++/string.h>
41 #include <cc++/exception.h>
42 #include <cc++/thread.h>
43 #include <cc++/export.h>
44 #include <cc++/digest.h>
45 
46 #include <cstdio>
47 #include <iomanip>
48 
49 #ifdef  WIN32
50 #include <io.h>
51 #endif
52 
53 #ifdef  CCXX_NAMESPACES
54 namespace ost {
55 using namespace std;
56 #endif
57 
Digest()58 Digest::Digest() :
59 streambuf()
60 #ifdef  HAVE_OLD_IOSTREAM
61 ,ostream()
62 #else
63 ,ostream((streambuf *)this)
64 #endif
65 {
66 #ifdef  HAVE_OLD_IOSTREAM
67     init((streambuf *)this);
68 #endif
69     }
70 
~Digest()71 Digest::~Digest()
72 {
73 }
74 
ChecksumDigest()75 ChecksumDigest::ChecksumDigest() :
76 Digest()
77 {
78     csum = 0;
79 }
80 
overflow(int c)81 int ChecksumDigest::overflow(int c)
82 {
83     csum += c;
84     return c;
85 }
86 
getDigest(unsigned char * buffer)87 unsigned ChecksumDigest::getDigest(unsigned char *buffer)
88 {
89     *buffer = csum;
90     return 1;
91 }
92 
putDigest(const unsigned char * buffer,unsigned len)93 void ChecksumDigest::putDigest(const unsigned char *buffer, unsigned len)
94 {
95     while(len--)
96         csum += *(buffer++);
97 }
98 
strDigest(ostream & os)99 ostream &ChecksumDigest::strDigest(ostream &os)
100 {
101     char buf[3];
102 
103     sprintf(buf, "%02x", csum);
104     os << buf;
105     return os;
106 }
107 
CRC16Digest()108 CRC16Digest::CRC16Digest() : Digest()
109 {
110     crc16 = 0;
111 }
112 
CRC16Digest(const CRC16Digest & crc)113 CRC16Digest::CRC16Digest (const CRC16Digest &crc ) : Digest()
114 {
115     crc16 = crc.crc16;
116 }
117 
operator =(const CRC16Digest & right)118 CRC16Digest& CRC16Digest::operator= ( const CRC16Digest &right )
119 {
120     if ( this == &right ) return *this;
121     crc16 = right.crc16;
122     return *this;
123 }
124 
overflow(int c)125 int CRC16Digest::overflow ( int c )
126 {
127     crc16 = ( unsigned char ) ( crc16 >> 8 ) | ( crc16 << 8 );
128     crc16 ^= ( unsigned char ) ( c );
129     crc16 ^= ( unsigned char ) ( crc16 & 0xff ) >> 4;
130     crc16 ^= ( crc16 << 8 ) << 4;
131     crc16 ^= ( ( crc16 & 0xff ) << 4 ) << 1;
132     return c;
133 }
134 
getDigest(unsigned char * buffer)135 unsigned CRC16Digest::getDigest ( unsigned char *buffer )
136 {
137     memcpy ( buffer, &crc16, sizeof(crc16) );
138     return sizeof(crc16);
139 }
140 
putDigest(const unsigned char * buffer,unsigned len)141 void CRC16Digest::putDigest ( const unsigned char *buffer, unsigned len )
142 {
143     while (len--)
144         overflow (*buffer++);
145 }
146 
strDigest(ostream & os)147 ostream &CRC16Digest::strDigest ( ostream &os )
148 {
149     return os << std::setw(4) << std::setfill('0') << std::hex << (unsigned)crc16 << std::dec;
150 }
151 
152 
CRC32Digest()153 CRC32Digest::CRC32Digest() : Digest()
154 {
155     initDigest();
156     crc32 = 0;
157 }
158 
CRC32Digest(const CRC32Digest & crc)159 CRC32Digest::CRC32Digest(const CRC32Digest &crc) : Digest()
160 {
161     crc32 = crc.crc32;
162     crc_reg = crc.crc_reg;
163     register int32 i;
164     for (i = 0; i < 256; i++) {
165         crc_table[i] = crc.crc_table[i];
166     }
167 }
168 
initDigest(void)169 void CRC32Digest::initDigest(void)
170 {
171     // the generator polynomial used here is the same as Ethernet
172     // x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1
173     const uint32 POLYNOMIAL = 0x04C11DB7;
174 
175     // Initialize the accumulator to all ones
176     crc_reg = 0xFFFFFFFF;
177 
178     // Initialize the lookup table
179     register int32 i,j;
180     register uint32 crc;
181 
182     for (i = 0; i < 256; i++) {
183         crc = ( (uint32) i << 24 );
184         for (j = 0; j < 8; j++) {
185             if (crc & 0x80000000)
186                 crc = (crc << 1) ^ POLYNOMIAL;
187             else
188                 crc <<= 1;
189         }
190         crc_table[i] = crc;
191     }
192 }
193 
194 
overflow(unsigned char octet)195 unsigned char CRC32Digest::overflow(unsigned char octet)
196 {
197     crc_reg = crc_table[((crc_reg >> 24) ^ octet) & 0xFF] ^ (crc_reg << 8);
198     crc32 = ~crc_reg;
199 
200     return octet;
201 }
202 
getDigest(unsigned char * buffer)203 unsigned CRC32Digest::getDigest(unsigned char *buffer)
204 {
205     memcpy(buffer, &crc32, sizeof(crc32));
206     return sizeof(crc32);
207 }
208 
putDigest(const unsigned char * buffer,unsigned len)209 void CRC32Digest::putDigest(const unsigned char *buffer, unsigned len)
210 {
211     while(len--)
212         overflow(*buffer++);
213 }
214 
strDigest(ostream & os)215 ostream& CRC32Digest::strDigest(ostream &os)
216 {
217   return os << std::setw(8) << std::setfill('0') << std::hex << (unsigned)crc32 << std::dec;
218 }
219 
operator =(const CRC32Digest & right)220 CRC32Digest& CRC32Digest::operator= (const CRC32Digest &right)
221 {
222     if ( this == &right ) return *this;
223   crc32   = right.crc32;
224     crc_reg = right.crc_reg;
225 
226     register int32 i;
227     for (i = 0; i < 256; i++) {
228         crc_table[i] = right.crc_table[i];
229     }
230 
231     return *this;
232 }
233 
234 
235 #ifdef  CCXX_NAMESPACES
236 }
237 #endif
238 
239