GCC Code Coverage Report


Directory: src/gate/
File: src/gate/encode/crchash.c
Date: 2025-12-12 23:40:09
Exec Total Coverage
Lines: 66 66 100.0%
Functions: 8 8 100.0%
Branches: 29 33 87.9%

Line Branch Exec Source
1 /* GATE PROJECT LICENSE:
2 +----------------------------------------------------------------------------+
3 | Copyright(c) 2018-2025, Stefan Meislinger <sm@opengate.at> |
4 | All rights reserved. |
5 | |
6 | Redistribution and use in source and binary forms, with or without |
7 | modification, are permitted provided that the following conditions are met:|
8 | |
9 | 1. Redistributions of source code must retain the above copyright notice, |
10 | this list of conditions and the following disclaimer. |
11 | 2. Redistributions in binary form must reproduce the above copyright |
12 | notice, this list of conditions and the following disclaimer in the |
13 | documentation and/or other materials provided with the distribution. |
14 | |
15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"|
16 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
17 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
18 | ARE DISCLAIMED.IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE |
19 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
20 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
21 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
22 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
23 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
24 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF |
25 | THE POSSIBILITY OF SUCH DAMAGE. |
26 +----------------------------------------------------------------------------+
27 */
28
29 #include "gate/encode/crchash.h"
30 #include "gate/memalloc.h"
31 #include "gate/debugging.h"
32
33 /* https://de.wikipedia.org/wiki/Zyklische_Redundanzpr%C3%BCfung */
34
35 13 void gate_crc32_init(gate_crc32_t* crc32hash)
36 {
37 13 crc32hash->value = 0;
38 13 }
39
40 #define CRC32POLY 0x04C11DB7
41
42 11 void gate_crc32_update(gate_crc32_t* crc32hash, void const* databuffer, unsigned databufferlength)
43 {
44 11 unsigned char const* ptr_data = (unsigned char const*)databuffer;
45
46
2/4
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 11 times.
11 GATE_DEBUG_ASSERT((databufferlength == 0) || (databuffer != NULL));
47
48
2/2
✓ Branch 0 taken 800 times.
✓ Branch 1 taken 11 times.
811 while (databufferlength-- > 0)
49 {
50 800 unsigned char chr = *ptr_data;
51 unsigned n;
52
2/2
✓ Branch 0 taken 6400 times.
✓ Branch 1 taken 800 times.
7200 for (n = 0; n != 8; ++n)
53 {
54
2/2
✓ Branch 0 taken 3210 times.
✓ Branch 1 taken 3190 times.
6400 if (((crc32hash->value >> 31u) & 1u) != ((chr >> n) & 1u))
55 {
56 3210 crc32hash->value = (crc32hash->value << 1) ^ CRC32POLY;
57 }
58 else
59 {
60 3190 crc32hash->value = (crc32hash->value << 1);
61 }
62 }
63 800 ++ptr_data;
64 }
65 11 }
66 11 void gate_crc32_finish(gate_crc32_t* crc32hash, gate_crc32_result_t* resulthashbuffer)
67 {
68 11 resulthashbuffer->hash[0] = (unsigned char)((crc32hash->value >> 24) & 0x0ff);
69 11 resulthashbuffer->hash[1] = (unsigned char)((crc32hash->value >> 16) & 0x0ff);
70 11 resulthashbuffer->hash[2] = (unsigned char)((crc32hash->value >> 8) & 0x0ff);
71 11 resulthashbuffer->hash[3] = (unsigned char)((crc32hash->value) & 0x0ff);
72 11 }
73
74
75
76
77 #define GATE_CRC16_MODE_NORMAL 1
78 #define GATE_CRC16_MODE_NORMAL_SWAP 2
79 #define GATE_CRC16_MODE_REVERSE 3
80 #define GATE_CRC16_MODE_REVERSE_SWAP 4
81
82 gate_crc16_t gate_crc16hash_arc = { 0x0000, 0xa001, GATE_CRC16_MODE_REVERSE };
83 gate_crc16_t gate_crc16hash_modbus = { 0xffff, 0xa001, GATE_CRC16_MODE_REVERSE };
84 gate_crc16_t gate_crc16hash_kermit = { 0x0000, 0x8408, GATE_CRC16_MODE_REVERSE_SWAP };
85 gate_crc16_t gate_crc16hash_xmodem = { 0x0000, 0x1021, GATE_CRC16_MODE_NORMAL };
86 gate_crc16_t gate_crc16hash_ccitt = { 0xffff, 0x1021, GATE_CRC16_MODE_NORMAL };
87
88 28 void gate_crc16_init(gate_crc16_t* crc16hash, unsigned crc16type)
89 {
90
5/5
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 4 times.
✓ Branch 4 taken 12 times.
28 switch (crc16type)
91 {
92 4 case GATE_CRC16_TYPE_ARC: *crc16hash = gate_crc16hash_arc; break;
93 4 case GATE_CRC16_TYPE_KERMIT: *crc16hash = gate_crc16hash_kermit; break;
94 4 case GATE_CRC16_TYPE_CCITT_FALSE: *crc16hash = gate_crc16hash_ccitt; break;
95 4 case GATE_CRC16_TYPE_XMODEM: *crc16hash = gate_crc16hash_xmodem; break;
96 12 default:
97 12 case GATE_CRC16_TYPE_MODBUS: *crc16hash = gate_crc16hash_modbus; break;
98 }
99 28 }
100
101 /* http://www.nongnu.org/avr-libc/user-manual/group__util__crc.html#gaca726c22a1900f9bad52594c8846115f
102 uses a regular polynomial representation
103 */
104 8 static void gate_crc16_add_data_normal(unsigned short* crcvalue, unsigned short mask, char const* buffer, unsigned int bufferlen)
105 {
106 unsigned ndx;
107
2/2
✓ Branch 0 taken 480 times.
✓ Branch 1 taken 8 times.
488 while (bufferlen--)
108 {
109 480 unsigned char data = (unsigned char)(*(buffer++));
110 480 *crcvalue ^= ((unsigned short)data) << 8;
111
2/2
✓ Branch 0 taken 3840 times.
✓ Branch 1 taken 480 times.
4320 for (ndx = 0; ndx != 8; ++ndx)
112 {
113
2/2
✓ Branch 0 taken 1944 times.
✓ Branch 1 taken 1896 times.
3840 if (*crcvalue & 0x8000)
114 {
115 1944 *crcvalue = (*crcvalue << 1) ^ mask;
116 }
117 else
118 {
119 1896 *crcvalue <<= 1;
120 }
121 }
122 }
123 8 }
124
125 /* http://de.wikipedia.org/wiki/Zyklische_Redundanzpr%C3%BCfung
126 uses a reversed polynomial representation
127 */
128 19 static void gate_crc16_add_data_reverse(unsigned short* crcvalue, unsigned short mask, char const* buffer, unsigned int bufferlen)
129 {
130 unsigned int len;
131 unsigned int ndx;
132
2/2
✓ Branch 0 taken 1280 times.
✓ Branch 1 taken 19 times.
1299 for (len = bufferlen; len > 0; --len, ++buffer)
133 {
134 1280 *crcvalue = *crcvalue ^ (unsigned short)(unsigned char)(*buffer);
135
2/2
✓ Branch 0 taken 10240 times.
✓ Branch 1 taken 1280 times.
11520 for (ndx = 0; ndx != 8; ++ndx)
136 {
137
2/2
✓ Branch 0 taken 5151 times.
✓ Branch 1 taken 5089 times.
10240 if ((*crcvalue & 1) != 0)
138 {
139 5151 *crcvalue = (*crcvalue >> 1) ^ mask;
140 }
141 else
142 {
143 5089 *crcvalue >>= 1;
144 }
145 }
146 }
147 19 }
148
149
150
151 27 void gate_crc16_update(gate_crc16_t* crc16hash, void const* databuffer, unsigned databufferlength)
152 {
153
2/3
✓ Branch 0 taken 19 times.
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
27 switch (crc16hash->mode)
154 {
155 19 case GATE_CRC16_MODE_REVERSE:
156 case GATE_CRC16_MODE_REVERSE_SWAP:
157 19 gate_crc16_add_data_reverse(&crc16hash->value, crc16hash->mask, databuffer, databufferlength);
158 19 break;
159 8 case GATE_CRC16_MODE_NORMAL:
160 case GATE_CRC16_MODE_NORMAL_SWAP:
161 8 gate_crc16_add_data_normal(&crc16hash->value, crc16hash->mask, databuffer, databufferlength);
162 8 break;
163 }
164 27 }
165 22 void gate_crc16_finish(gate_crc16_t* crc16hash, gate_crc16_result_t* resulthashbuffer)
166 {
167
2/3
✓ Branch 0 taken 19 times.
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
22 switch (crc16hash->mode)
168 {
169 19 case GATE_CRC16_MODE_REVERSE:
170 case GATE_CRC16_MODE_NORMAL:
171 19 resulthashbuffer->hash[0] = (unsigned char)((crc16hash->value & 0xff00) >> 8);
172 19 resulthashbuffer->hash[1] = (unsigned char)(crc16hash->value & 0x00ff);
173 19 break;
174
175 3 case GATE_CRC16_MODE_NORMAL_SWAP:
176 case GATE_CRC16_MODE_REVERSE_SWAP:
177 3 resulthashbuffer->hash[0] = (unsigned char)(crc16hash->value & 0x00ff);
178 3 resulthashbuffer->hash[1] = (unsigned char)((crc16hash->value & 0xff00) >> 8);
179 3 break;
180 }
181
182
183 22 }
184