GCC Code Coverage Report


Directory: src/gate/
File: src/gate/encode/crchash.c
Date: 2025-09-14 13:10:38
Exec Total Coverage
Lines: 65 65 100.0%
Functions: 8 8 100.0%
Branches: 27 29 93.1%

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
32 /* https://de.wikipedia.org/wiki/Zyklische_Redundanzpr%C3%BCfung */
33
34 5 void gate_crc32_init(gate_crc32_t* crc32hash)
35 {
36 5 crc32hash->value = 0;
37 5 }
38
39 #define CRC32POLY 0x04C11DB7
40
41 4 void gate_crc32_update(gate_crc32_t* crc32hash, void const* databuffer, unsigned databufferlength)
42 {
43 4 unsigned char const* ptr_data = (unsigned char const*)databuffer;
44 unsigned char chr;
45 unsigned n;
46
47
2/2
✓ Branch 0 taken 240 times.
✓ Branch 1 taken 4 times.
244 while (databufferlength-- > 0)
48 {
49 240 chr = *ptr_data;
50
2/2
✓ Branch 0 taken 1920 times.
✓ Branch 1 taken 240 times.
2160 for (n = 0; n != 8; ++n)
51 {
52
2/2
✓ Branch 0 taken 963 times.
✓ Branch 1 taken 957 times.
1920 if (((crc32hash->value >> 31u) & 1u) != ((chr >> n) & 1u))
53 {
54 963 crc32hash->value = (crc32hash->value << 1) ^ CRC32POLY;
55 }
56 else
57 {
58 957 crc32hash->value = (crc32hash->value << 1);
59 }
60 }
61 240 ++ptr_data;
62 }
63 4 }
64 4 void gate_crc32_finish(gate_crc32_t* crc32hash, gate_crc32_result_t* resulthashbuffer)
65 {
66 4 resulthashbuffer->hash[0] = (unsigned char)((crc32hash->value >> 24) & 0x0ff);
67 4 resulthashbuffer->hash[1] = (unsigned char)((crc32hash->value >> 16) & 0x0ff);
68 4 resulthashbuffer->hash[2] = (unsigned char)((crc32hash->value >> 8) & 0x0ff);
69 4 resulthashbuffer->hash[3] = (unsigned char)((crc32hash->value) & 0x0ff);
70 4 }
71
72
73
74
75 #define GATE_CRC16_MODE_NORMAL 1
76 #define GATE_CRC16_MODE_NORMAL_SWAP 2
77 #define GATE_CRC16_MODE_REVERSE 3
78 #define GATE_CRC16_MODE_REVERSE_SWAP 4
79
80 gate_crc16_t gate_crc16hash_arc = { 0x0000, 0xa001, GATE_CRC16_MODE_REVERSE };
81 gate_crc16_t gate_crc16hash_modbus = { 0xffff, 0xa001, GATE_CRC16_MODE_REVERSE };
82 gate_crc16_t gate_crc16hash_kermit = { 0x0000, 0x8408, GATE_CRC16_MODE_REVERSE_SWAP };
83 gate_crc16_t gate_crc16hash_xmodem = { 0x0000, 0x1021, GATE_CRC16_MODE_NORMAL };
84 gate_crc16_t gate_crc16hash_ccitt = { 0xffff, 0x1021, GATE_CRC16_MODE_NORMAL };
85
86 23 void gate_crc16_init(gate_crc16_t* crc16hash, unsigned crc16type)
87 {
88
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 7 times.
23 switch (crc16type)
89 {
90 4 case GATE_CRC16_TYPE_ARC: *crc16hash = gate_crc16hash_arc; break;
91 4 case GATE_CRC16_TYPE_KERMIT: *crc16hash = gate_crc16hash_kermit; break;
92 4 case GATE_CRC16_TYPE_CCITT_FALSE: *crc16hash = gate_crc16hash_ccitt; break;
93 4 case GATE_CRC16_TYPE_XMODEM: *crc16hash = gate_crc16hash_xmodem; break;
94 7 default:
95 7 case GATE_CRC16_TYPE_MODBUS: *crc16hash = gate_crc16hash_modbus; break;
96 }
97 23 }
98
99 /* http://www.nongnu.org/avr-libc/user-manual/group__util__crc.html#gaca726c22a1900f9bad52594c8846115f
100 uses a regular polynomial representation
101 */
102 8 static void gate_crc16_add_data_normal(unsigned short* crcvalue, unsigned short mask, char const* buffer, unsigned int bufferlen)
103 {
104 unsigned ndx;
105
2/2
✓ Branch 0 taken 480 times.
✓ Branch 1 taken 8 times.
488 while (bufferlen--)
106 {
107 480 unsigned char data = (unsigned char)(*(buffer++));
108 480 *crcvalue ^= ((unsigned short)data) << 8;
109
2/2
✓ Branch 0 taken 3840 times.
✓ Branch 1 taken 480 times.
4320 for (ndx = 0; ndx != 8; ++ndx)
110 {
111
2/2
✓ Branch 0 taken 1944 times.
✓ Branch 1 taken 1896 times.
3840 if (*crcvalue & 0x8000)
112 {
113 1944 *crcvalue = (*crcvalue << 1) ^ mask;
114 }
115 else
116 {
117 1896 *crcvalue <<= 1;
118 }
119 }
120 }
121 8 }
122
123 /* http://de.wikipedia.org/wiki/Zyklische_Redundanzpr%C3%BCfung
124 uses a reversed polynomial representation
125 */
126 15 static void gate_crc16_add_data_reverse(unsigned short* crcvalue, unsigned short mask, char const* buffer, unsigned int bufferlen)
127 {
128 unsigned int len;
129 unsigned int ndx;
130
2/2
✓ Branch 0 taken 960 times.
✓ Branch 1 taken 15 times.
975 for (len = bufferlen; len > 0; --len, ++buffer)
131 {
132 960 *crcvalue = *crcvalue ^ (unsigned short)(unsigned char)(*buffer);
133
2/2
✓ Branch 0 taken 7680 times.
✓ Branch 1 taken 960 times.
8640 for (ndx = 0; ndx != 8; ++ndx)
134 {
135
2/2
✓ Branch 0 taken 3831 times.
✓ Branch 1 taken 3849 times.
7680 if ((*crcvalue & 1) != 0)
136 {
137 3831 *crcvalue = (*crcvalue >> 1) ^ mask;
138 }
139 else
140 {
141 3849 *crcvalue >>= 1;
142 }
143 }
144 }
145 15 }
146
147
148
149 23 void gate_crc16_update(gate_crc16_t* crc16hash, void const* databuffer, unsigned databufferlength)
150 {
151
2/3
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
23 switch (crc16hash->mode)
152 {
153 15 case GATE_CRC16_MODE_REVERSE:
154 case GATE_CRC16_MODE_REVERSE_SWAP:
155 15 gate_crc16_add_data_reverse(&crc16hash->value, crc16hash->mask, databuffer, databufferlength);
156 15 break;
157 8 case GATE_CRC16_MODE_NORMAL:
158 case GATE_CRC16_MODE_NORMAL_SWAP:
159 8 gate_crc16_add_data_normal(&crc16hash->value, crc16hash->mask, databuffer, databufferlength);
160 8 break;
161 }
162 23 }
163 18 void gate_crc16_finish(gate_crc16_t* crc16hash, gate_crc16_result_t* resulthashbuffer)
164 {
165
2/3
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
18 switch (crc16hash->mode)
166 {
167 15 case GATE_CRC16_MODE_REVERSE:
168 case GATE_CRC16_MODE_NORMAL:
169 15 resulthashbuffer->hash[0] = (unsigned char)((crc16hash->value & 0xff00) >> 8);
170 15 resulthashbuffer->hash[1] = (unsigned char)(crc16hash->value & 0x00ff);
171 15 break;
172
173 3 case GATE_CRC16_MODE_NORMAL_SWAP:
174 case GATE_CRC16_MODE_REVERSE_SWAP:
175 3 resulthashbuffer->hash[0] = (unsigned char)(crc16hash->value & 0x00ff);
176 3 resulthashbuffer->hash[1] = (unsigned char)((crc16hash->value & 0xff00) >> 8);
177 3 break;
178 }
179
180
181 18 }
182