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 
34 static inline void bitcpy(
35  unsigned char *dst, unsigned char src, unsigned char mask);
36 
37 void
38 bcpybe(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 
127 void
128 bcpyle(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 
217 static inline void
218 bitcpy(unsigned char *dst, unsigned char src, unsigned char mask)
219 {
220  *dst = ((src ^ *dst) & mask) ^ *dst;
221 }
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.
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