Lely core libraries 1.9.2
endian.c
Go to the documentation of this file.
1
24// Disable macro definitions of htobe*() and htole*(). This ensures our
25// implementation of these functions is exported.
26#define __NO_STRING_INLINES
27
28#include "util.h"
29#define LELY_UTIL_ENDIAN_INLINE extern inline
30#include <lely/util/endian.h>
31
32#include <assert.h>
33
34static inline void bitcpy(
35 unsigned char *dst, unsigned char src, unsigned char mask);
36
37void
38bcpybe(void *dst, int dstbit, const void *src, int srcbit, size_t n)
39{
40 if (!n)
41 return;
42
43 assert(dst);
44 assert(src);
45
46 unsigned char *dp = dst;
47 dp += dstbit / CHAR_BIT;
48 dstbit %= CHAR_BIT;
49 if (dstbit < 0) {
50 dp--;
51 dstbit += CHAR_BIT;
52 }
53
54 const unsigned char *sp = src;
55 sp += srcbit / CHAR_BIT;
56 srcbit %= CHAR_BIT;
57 if (srcbit < 0) {
58 sp--;
59 srcbit += CHAR_BIT;
60 }
61
62 unsigned char first = UCHAR_MAX >> dstbit;
63 unsigned char last = ~(UCHAR_MAX >> ((dstbit + n) % CHAR_BIT));
64
65 int shift = dstbit - srcbit;
66 if (shift) {
67 int right = shift & (CHAR_BIT - 1);
68 int left = -shift & (CHAR_BIT - 1);
69
70 if (dstbit + n <= CHAR_BIT) {
71 if (last)
72 first &= last;
73 if (shift > 0) {
74 bitcpy(dp, *sp >> right, first);
75 } else if (srcbit + n <= CHAR_BIT) {
76 bitcpy(dp, *sp << left, first);
77 } else {
78 bitcpy(dp, *sp << left | sp[1] >> right, first);
79 }
80 } else {
81 unsigned char b = *sp++;
82 if (shift > 0) {
83 bitcpy(dp, b >> right, first);
84 } else {
85 bitcpy(dp, b << left | *sp >> right, first);
86 b = *sp++;
87 }
88 dp++;
89 n -= CHAR_BIT - dstbit;
90
91 int m = n % CHAR_BIT;
92 n /= CHAR_BIT;
93 while (n--) {
94 *dp++ = b << left | *sp >> right;
95 b = *sp++;
96 }
97
98 if (last) {
99 if (m <= right)
100 bitcpy(dp, b << left, last);
101 else
102 bitcpy(dp, b << left | *sp >> right,
103 last);
104 }
105 }
106 } else {
107 if (dstbit + n <= CHAR_BIT) {
108 if (last)
109 first &= last;
110 bitcpy(dp, *sp, first);
111 } else {
112 if (first) {
113 bitcpy(dp++, *sp++, first);
114 n -= CHAR_BIT - dstbit;
115 }
116
117 n /= CHAR_BIT;
118 while (n--)
119 *dp++ = *sp++;
120
121 if (last)
122 bitcpy(dp, *sp, last);
123 }
124 }
125}
126
127void
128bcpyle(void *dst, int dstbit, const void *src, int srcbit, size_t n)
129{
130 if (!n)
131 return;
132
133 assert(dst);
134 assert(src);
135
136 unsigned char *dp = dst;
137 dp += dstbit / CHAR_BIT;
138 dstbit %= CHAR_BIT;
139 if (dstbit < 0) {
140 dp--;
141 dstbit += CHAR_BIT;
142 }
143
144 const unsigned char *sp = src;
145 sp += srcbit / CHAR_BIT;
146 srcbit %= CHAR_BIT;
147 if (srcbit < 0) {
148 sp--;
149 srcbit += CHAR_BIT;
150 }
151
152 unsigned char first = UCHAR_MAX << dstbit;
153 unsigned char last = ~(UCHAR_MAX << ((dstbit + n) % CHAR_BIT));
154
155 int shift = dstbit - srcbit;
156 if (shift) {
157 int right = -shift & (CHAR_BIT - 1);
158 int left = shift & (CHAR_BIT - 1);
159
160 if (dstbit + n <= CHAR_BIT) {
161 if (last)
162 first &= last;
163 if (shift > 0) {
164 bitcpy(dp, *sp << left, first);
165 } else if (srcbit + n <= CHAR_BIT) {
166 bitcpy(dp, *sp >> right, first);
167 } else {
168 bitcpy(dp, *sp >> right | sp[1] << left, first);
169 }
170 } else {
171 unsigned char b = *sp++;
172 if (shift > 0) {
173 bitcpy(dp, b << left, first);
174 } else {
175 bitcpy(dp, b >> right | *sp << left, first);
176 b = *sp++;
177 }
178 dp++;
179 n -= CHAR_BIT - dstbit;
180
181 int m = n % CHAR_BIT;
182 n /= CHAR_BIT;
183 while (n--) {
184 *dp++ = b >> right | *sp << left;
185 b = *sp++;
186 }
187
188 if (last) {
189 if (m <= right)
190 bitcpy(dp, b >> right, last);
191 else
192 bitcpy(dp, b >> right | *sp << left,
193 last);
194 }
195 }
196 } else {
197 if (dstbit + n <= CHAR_BIT) {
198 if (last)
199 first &= last;
200 bitcpy(dp, *sp, first);
201 } else {
202 if (first) {
203 bitcpy(dp++, *sp++, first);
204 n -= CHAR_BIT - dstbit;
205 }
206
207 n /= CHAR_BIT;
208 while (n--)
209 *dp++ = *sp++;
210
211 if (last)
212 bitcpy(dp, *sp, last);
213 }
214 }
215}
216
217static inline void
218bitcpy(unsigned char *dst, unsigned char src, unsigned char mask)
219{
220 *dst = ((src ^ *dst) & mask) ^ *dst;
221}
void bcpybe(void *dst, int dstbit, const void *src, int srcbit, size_t n)
Copies n bits from a source to a destination buffer.
Definition: endian.c:38
void bcpyle(void *dst, int dstbit, const void *src, int srcbit, size_t n)
Copies n bits from a source to a destination buffer.
Definition: endian.c:128
This header file is part of the utilities library; it contains the byte order (endianness) function d...
This is the internal header file of the utilities library.