summaryrefslogtreecommitdiffstats
path: root/baseline/source/ammunition/bits.c
diff options
context:
space:
mode:
Diffstat (limited to 'baseline/source/ammunition/bits.c')
-rw-r--r--baseline/source/ammunition/bits.c313
1 files changed, 313 insertions, 0 deletions
diff --git a/baseline/source/ammunition/bits.c b/baseline/source/ammunition/bits.c
new file mode 100644
index 0000000..9169656
--- /dev/null
+++ b/baseline/source/ammunition/bits.c
@@ -0,0 +1,313 @@
1/*
2
3 FILE NAME: bits.c
4
5 TITLE: Package for work with bits
6
7 DESCRIPTION: This file implements functions of the package for work
8 with bit strings. A bit is given by address (start address) of
9 byte from which counting bits starts and its displacement which
10 is any non negative number of bit from the start address. The
11 most significant bit of the start address byte has number 0.
12 The bit string is given by its first bit and its length in
13 bits.
14
15*/
16
17#include "bits.h"
18
19/* This function determines that given bit string contains only zero
20 bits. The function retruns TRUE if all bits of given bit string
21 are zero or `bit_length' <= 0. Value of `bit_displacement' must be
22 non-negative and can be greater than CHAR_BIT. */
23
24int
25ammunition_is_zero_bit_string ( const void *start_byte, int bit_displacement,
26 int bit_length )
27{
28 const unsigned char *current_byte = ( unsigned const char * )start_byte;
29
30 if ( bit_length <= 0 )
31 return 1 /* TRUE */;
32 current_byte += bit_displacement / CHAR_BIT;
33 bit_displacement %= CHAR_BIT;
34 if ( bit_length < CHAR_BIT - bit_displacement )
35 return ( ( ( *current_byte << bit_displacement )
36 & ( UCHAR_MAX << ( CHAR_BIT - bit_length ) ) )
37 & UCHAR_MAX ) == 0;
38 else
39 if ( bit_displacement != 0 ) {
40 if ( ( ( *current_byte << bit_displacement ) & UCHAR_MAX ) != 0 )
41 return 0 /* FALSE */;
42 current_byte += 1;
43 bit_length -= CHAR_BIT - bit_displacement;
44 }
45 _Pragma( "loopbound min 0 max 7" )
46 while ( bit_length >= CHAR_BIT ) {
47 if ( *current_byte != 0 )
48 return 0 /* FALSE */;
49 current_byte++;
50 bit_length -= CHAR_BIT;
51 }
52 if ( bit_length > 0 && ( *current_byte >> ( CHAR_BIT - bit_length ) ) != 0 )
53 return 0 /* FALSE */;
54 return 1 /* TRUE */;
55}
56
57/* This function sets up new value of all bits of given bit string.
58 This function is analog of standard C function `memset'. Value of
59 `bit_displacement' must be non-negative and can be greater than
60 CHAR_BIT. */
61
62void
63ammunition_bit_string_set ( void *start_byte, int bit_displacement, int bit,
64 int bit_length )
65{
66 unsigned char *current_byte = ( unsigned char * )start_byte;
67 unsigned char filling_byte;
68 int mask;
69
70 if ( bit_length <= 0 )
71 return ;
72 bit = bit != 0; /* 1 or 0 */
73 filling_byte = ( bit ? UCHAR_MAX : 0 );
74 current_byte += bit_displacement / CHAR_BIT;
75 bit_displacement %= CHAR_BIT;
76 if ( bit_displacement != 0 ) {
77 mask = UCHAR_MAX << ( CHAR_BIT - bit_displacement );
78 if ( bit_length < CHAR_BIT - bit_displacement )
79 mask |= UCHAR_MAX >> ( bit_displacement + bit_length );
80 *current_byte = ( *current_byte & mask ) | ( filling_byte & ~mask );
81 current_byte += 1;
82 bit_length -= CHAR_BIT - bit_displacement;
83 }
84 _Pragma( "loopbound min 0 max 8" )
85 while ( bit_length >= CHAR_BIT ) {
86 *current_byte = filling_byte;
87 current_byte++;
88 bit_length -= CHAR_BIT;
89 }
90 if ( bit_length > 0 )
91 *current_byte
92 = ( *current_byte & ~( UCHAR_MAX << ( CHAR_BIT - bit_length ) ) )
93 | ( filling_byte & ( UCHAR_MAX << ( CHAR_BIT - bit_length ) ) );
94}
95
96/* This function copys a bit string to another bit string. This
97 function is analog of standard C function `memcpy'. Values of
98 `to_bit_displacement' and `from_bit_displacement' must be
99 non-negative and can be greater than CHAR_BIT. The bit string must
100 be non-overlapped. */
101
102void
103ammunition_bit_string_copy ( void *to, int to_bit_displacement,
104 const void *from, int from_bit_displacement,
105 int bit_length )
106{
107 unsigned char *current_to_byte = ( unsigned char * )to;
108 const unsigned char *current_from_byte = ( unsigned const char * )from;
109 int byte;
110 int mask;
111
112 if ( bit_length <= 0 )
113 return ;
114 current_to_byte += to_bit_displacement / CHAR_BIT;
115 to_bit_displacement %= CHAR_BIT;
116 current_from_byte += from_bit_displacement / CHAR_BIT;
117 from_bit_displacement %= CHAR_BIT;
118 _Pragma( "loopbound min 1 max 8" )
119 while ( 1 ) {
120 byte = ( ( ( *current_from_byte << from_bit_displacement ) & UCHAR_MAX )
121 | ( from_bit_displacement != 0
122 && bit_length > ( CHAR_BIT - from_bit_displacement )
123 ? current_from_byte [1] >> ( CHAR_BIT - from_bit_displacement )
124 : 0 ) );
125 if ( bit_length <= CHAR_BIT )
126 break;
127 /* Shift is correct when to_bit_displacement == 0 because its
128 value is less than word bit size. */
129 *current_to_byte
130 = ( *current_to_byte
131 & ( UCHAR_MAX << ( CHAR_BIT - to_bit_displacement ) ) )
132 | ( byte >> to_bit_displacement );
133 if ( to_bit_displacement != 0 )
134 current_to_byte [1]
135 = ( current_to_byte [1] & ( UCHAR_MAX >> to_bit_displacement ) )
136 | ( byte << ( CHAR_BIT - to_bit_displacement ) );
137 bit_length -= CHAR_BIT;
138 current_from_byte++;
139 current_to_byte++;
140 }
141 /* Shift is correct when to_bit_displacement == 0 because its
142 value is less than word bit size. */
143 mask = ( ( UCHAR_MAX << ( CHAR_BIT - to_bit_displacement ) )
144 | ( UCHAR_MAX >> ( to_bit_displacement + bit_length ) ) );
145 *current_to_byte
146 = ( *current_to_byte & mask ) | ( ( byte >> to_bit_displacement ) & ~mask );
147 bit_length -= CHAR_BIT - to_bit_displacement;
148 if ( bit_length > 0 )
149 current_to_byte [1]
150 = ( current_to_byte [1] & ( UCHAR_MAX >> bit_length ) )
151 | ( ( byte << ( CHAR_BIT - to_bit_displacement ) )
152 & ( UCHAR_MAX << ( CHAR_BIT - bit_length ) ) );
153}
154
155/* This function copys a bit string to another bit string. Copying
156 starts with the last bits of the bit strings. This function is
157 used by function `bit_string_move'. Values of
158 `to_bit_displacement' and `from_bit_displacement' must be
159 non-negative and can be greater than CHAR_BIT. The bit string must
160 be non-overlapped. */
161
162void ammunition_reverse_bit_string_copy ( void *to, int to_bit_displacement,
163 const void *from, int from_bit_displacement,
164 int bit_length )
165{
166 unsigned char *current_to_byte = ( unsigned char * )to;
167 const unsigned char *current_from_byte = ( unsigned const char * )from;
168 int byte;
169 int mask;
170
171 if ( bit_length <= 0 )
172 return ;
173 to_bit_displacement += bit_length - 1;
174 current_to_byte += to_bit_displacement / CHAR_BIT; /* last byte */
175 to_bit_displacement %= CHAR_BIT; /* last bit */
176 from_bit_displacement += bit_length - 1;
177 current_from_byte += from_bit_displacement / CHAR_BIT; /* last byte */
178 from_bit_displacement %= CHAR_BIT; /* last bit */
179 _Pragma( "loopbound min 1 max 8" )
180 while ( 1 ) {
181 /* Shift is correct when to_bit_displacement == 0 because its
182 value is less than word bit size. */
183 byte = ( ( *current_from_byte >> ( CHAR_BIT - 1 - from_bit_displacement ) )
184 | ( ( from_bit_displacement != CHAR_BIT - 1
185 && bit_length > from_bit_displacement + 1
186 ? current_from_byte [ -1 ] << ( from_bit_displacement + 1 )
187 : 0 )
188 & UCHAR_MAX ) );
189 if ( bit_length <= CHAR_BIT )
190 break;
191 /* Shift is correct when to_bit_displacement == 0 because its
192 value is less than word bit size. */
193 *current_to_byte
194 = ( *current_to_byte & ( UCHAR_MAX >> ( to_bit_displacement + 1 ) ) )
195 | ( byte << ( CHAR_BIT - 1 - to_bit_displacement ) );
196 if ( to_bit_displacement != CHAR_BIT - 1 )
197 current_to_byte [-1]
198 = ( current_to_byte [-1]
199 & ( UCHAR_MAX << ( CHAR_BIT - 1 - to_bit_displacement ) ) )
200 | ( byte >> ( to_bit_displacement + 1 ) );
201 bit_length -= CHAR_BIT;
202 current_from_byte--;
203 current_to_byte--;
204 }
205 /* Shift is correct when to_bit_displacement == 0 because its
206 value is less than word bit size. */
207 mask = ( ( UCHAR_MAX >> ( to_bit_displacement + 1 ) ) |
208 ( UCHAR_MAX << ( CHAR_BIT - 1 - to_bit_displacement
209 + bit_length ) ) );
210 *current_to_byte
211 = ( *current_to_byte & mask )
212 | ( ( byte << ( CHAR_BIT - 1 - to_bit_displacement ) ) & ~mask );
213 bit_length -= to_bit_displacement + 1;
214 if ( bit_length > 0 )
215 current_to_byte [-1]
216 = ( current_to_byte [-1] & ( UCHAR_MAX << bit_length ) )
217 | ( byte >> ( to_bit_displacement + 1 )
218 & ( UCHAR_MAX >> ( CHAR_BIT - bit_length ) ) );
219}
220
221/* This function copys a bit string to another bit string with the aid
222 of functions `bit_string_copy' and `reverse_bit_string_copy'. This
223 function is analog of standard C function `memmove'. Values of
224 `to_bit_displacement' and `from_bit_displacement' must be
225 non-negative and can be greater than CHAR_BIT. The bit string can
226 be overlapped. */
227
228void
229ammunition_bit_string_move ( void *to, int to_bit_displacement,
230 const void *from, int from_bit_displacement,
231 int bit_length )
232{
233 unsigned char *current_to_byte = ( unsigned char * )to;
234 const unsigned char *current_from_byte = ( unsigned const char * )from;
235
236 if ( bit_length <= 0 )
237 return ;
238 current_to_byte += to_bit_displacement / CHAR_BIT;
239 to_bit_displacement %= CHAR_BIT;
240 current_from_byte += from_bit_displacement / CHAR_BIT;
241 from_bit_displacement %= CHAR_BIT;
242 if ( current_from_byte > current_to_byte
243 || ( current_from_byte == current_to_byte
244 && from_bit_displacement > to_bit_displacement ) )
245 ammunition_bit_string_copy ( current_to_byte, to_bit_displacement,
246 current_from_byte, from_bit_displacement,
247 bit_length );
248 else
249 ammunition_reverse_bit_string_copy ( current_to_byte, to_bit_displacement,
250 current_from_byte,
251 from_bit_displacement, bit_length );
252}
253
254/* This function compares bit strings. This function is analog of
255 standard C function `memcmp'. The function returns 0 if the bit
256 strings are equal, 1 if the first bit string is greater than the
257 second, -1 if the first bit string is less than the first. Values
258 of `bit_displacement1' and `bit_displacement2' must be non-negative
259 and can be greater than CHAR_BIT. */
260
261int
262ammunition_bit_string_comparison ( const void *str1, int bit_displacement1,
263 const void *str2, int bit_displacement2,
264 int bit_length )
265{
266 const unsigned char *current_byte1 = ( unsigned const char * )str1;
267 const unsigned char *current_byte2 = ( unsigned const char * )str2;
268 int byte1;
269 int byte2;
270 int mask;
271
272 if ( bit_length <= 0 )
273 return 0;
274 current_byte1 += bit_displacement1 / CHAR_BIT;
275 bit_displacement1 %= CHAR_BIT;
276 current_byte2 += bit_displacement2 / CHAR_BIT;
277 bit_displacement2 %= CHAR_BIT;
278 _Pragma( "loopbound min 1 max 284" )
279 while ( 1 ) {
280 byte1 = ( ( ( *current_byte1 << bit_displacement1 ) & UCHAR_MAX )
281 | ( bit_displacement1 != 0
282 /* Shift is correct when to_bit_displacement == 0
283 because its value is less than word bit size. */
284 && bit_length > CHAR_BIT - bit_displacement1
285 ? current_byte1 [1] >> ( CHAR_BIT - bit_displacement1 )
286 : 0 ) );
287 byte2 = ( ( ( *current_byte2 << bit_displacement2 ) & UCHAR_MAX )
288 | ( bit_displacement2 != 0
289 && bit_length > CHAR_BIT - bit_displacement2
290 ? current_byte2 [1] >> ( CHAR_BIT - bit_displacement2 )
291 : 0 ) );
292 if ( bit_length <= CHAR_BIT )
293 break;
294 if ( byte1 > byte2 )
295 return 1;
296 else
297 if ( byte1 < byte2 )
298 return -1;
299 bit_length -= CHAR_BIT;
300 current_byte2++;
301 current_byte1++;
302 }
303 /* Shift is correct when to_bit_displacement == 0 because its value
304 is less than word bit size. */
305 mask = UCHAR_MAX << ( CHAR_BIT - bit_length );
306 if ( ( byte1 & mask ) > ( byte2 & mask ) )
307 return 1;
308 else
309 if ( ( byte1 & mask ) < ( byte2 & mask ) )
310 return -1;
311 else
312 return 0;
313}