bits.c 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. /* bits.c - bitfield extraction code
  2. *
  3. * This file is Copyright 2010 by the GPSD project
  4. * SPDX-License-Identifier: BSD-2-clause
  5. *
  6. * Bitfield extraction functions. In each, start is a bit index - not
  7. * a byte index - and width is a bit width. The width is bounded above by
  8. * 64 bits.
  9. *
  10. * The sbits() function assumes twos-complement arithmetic. ubits()
  11. * and sbits() assume no padding in integers.
  12. */
  13. #include "../include/gpsd_config.h" // must be before all includes
  14. #include <assert.h>
  15. #include <limits.h>
  16. #include <stdbool.h>
  17. #include <stdint.h>
  18. #include <string.h>
  19. #include "../include/bits.h"
  20. /* extract a (zero-origin) bitfield from a buffer) as an
  21. * unsigned uint64_t
  22. * Note: max width 56!
  23. *
  24. * Parameters: buf -- the buffer
  25. * start -- starting bit of desired bitfield
  26. * width -- width of desired bitfield (0 to 56)
  27. * le -- little endian input (swap bytes)
  28. *
  29. * Returns: bitfield as uint64_t
  30. * zero on errors (56 < width)
  31. */
  32. uint64_t ubits(unsigned char buf[], unsigned int start,
  33. unsigned int width, bool le)
  34. {
  35. uint64_t fld = 0;
  36. unsigned int i;
  37. unsigned end;
  38. assert(width <= sizeof(uint64_t) * CHAR_BIT);
  39. if (0 == width ||
  40. 56 < width) {
  41. return 0;
  42. }
  43. for (i = start / CHAR_BIT;
  44. i < (start + width + CHAR_BIT - 1) / CHAR_BIT; i++) {
  45. fld <<= CHAR_BIT;
  46. fld |= (uint64_t)buf[i];
  47. }
  48. end = (start + width) % CHAR_BIT;
  49. if (0 != end) {
  50. fld >>= (CHAR_BIT - end);
  51. }
  52. fld &= ~(~0ULL << width);
  53. if (le) {
  54. // extraction as a little-endian requested
  55. uint64_t reversed = 0;
  56. for (i = width; i; --i) {
  57. reversed <<= 1;
  58. if (1 == (1 & fld)) {
  59. reversed |= 1;
  60. }
  61. fld >>= 1;
  62. }
  63. fld = reversed;
  64. }
  65. return fld;
  66. }
  67. // extract a bitfield from the buffer as a signed big-endian long
  68. int64_t sbits(signed char buf[], unsigned int start, unsigned int width,
  69. bool le)
  70. {
  71. uint64_t fld = ubits((unsigned char *)buf, start, width, le);
  72. /* ensure width > 0 as the result of
  73. 1ULL << (width - 1)
  74. is undefined for width <= 0 */
  75. assert(width > 0);
  76. if (fld & (1ULL << (width - 1))) {
  77. fld |= (~0ULL << (width - 1));
  78. }
  79. return (int64_t)fld;
  80. }
  81. union int_float {
  82. int32_t i;
  83. float f;
  84. };
  85. union long_double {
  86. int64_t l;
  87. double d;
  88. };
  89. float getlef32(const char *buf, int off)
  90. {
  91. union int_float i_f;
  92. i_f.i = getles32(buf, off);
  93. return i_f.f;
  94. }
  95. double getled64(const char *buf, int off)
  96. {
  97. union long_double l_d;
  98. l_d.l = getles64(buf, off);
  99. return l_d.d;
  100. }
  101. float getbef32(const char *buf, int off)
  102. {
  103. union int_float i_f;
  104. i_f.i = getbes32(buf, off);
  105. return i_f.f;
  106. }
  107. double getbed64(const char *buf, int off)
  108. {
  109. union long_double l_d;
  110. l_d.l = getbes64(buf, off);
  111. return l_d.d;
  112. }
  113. void putbef32(char *buf, int off, float val)
  114. {
  115. union int_float i_f;
  116. i_f.f = val;
  117. putbe32(buf, off, i_f.i);
  118. }
  119. void shiftleft(unsigned char *data, int size, unsigned short left)
  120. {
  121. unsigned char *byte;
  122. if (left >= CHAR_BIT) {
  123. size -= left / CHAR_BIT;
  124. memmove(data, data + left / CHAR_BIT,
  125. (size + CHAR_BIT - 1) / CHAR_BIT);
  126. left %= CHAR_BIT;
  127. }
  128. for (byte = data; size--; ++byte ) {
  129. unsigned char bits;
  130. if (size) {
  131. bits = byte[1] >> (CHAR_BIT - left);
  132. } else {
  133. bits = 0;
  134. }
  135. *byte <<= left;
  136. // Yes, the mask should not be needed, but id avoids a compiler
  137. // bug in gcc-amd64 11.2.1
  138. *byte |= 0x0ff & bits;
  139. }
  140. }
  141. #ifdef __UNUSED__
  142. void putbed64(char *buf, int off, double val)
  143. {
  144. union long_double l_d;
  145. l_d.d = val;
  146. putbe32(buf, (off), (l_d.l) >> 32);
  147. putbe32(buf, (off)+4, (l_d.l));
  148. }
  149. // byte-swap a 16-bit unsigned int
  150. u_int16_t swap_u16(u_int16_t i)
  151. {
  152. u_int8_t c1, c2;
  153. c1 = i & 255;
  154. c2 = (i >> 8) & 255;
  155. return (c1 << 8) + c2;
  156. }
  157. // byte-swap a 32-bit unsigned int
  158. u_int32_t swap_u32(u_int32_t i)
  159. {
  160. u_int8_t c1, c2, c3, c4;
  161. c1 = i & 255;
  162. c2 = (i >> 8) & 255;
  163. c3 = (i >> 16) & 255;
  164. c4 = (i >> 24) & 255;
  165. return ((u_int32_t)c1 << 24) +
  166. ((u_int32_t)c2 << 16) +
  167. ((u_int32_t)c3 << 8) + c4;
  168. }
  169. // byte-swap a 64-bit unsigned int
  170. u_int64_t swap_u64(u_int64_t i)
  171. {
  172. u_int8_t c1, c2, c3, c4, c5, c6, c7, c8;
  173. c1 = i & 255;
  174. c2 = (i >> 8) & 255;
  175. c3 = (i >> 16) & 255;
  176. c4 = (i >> 24) & 255;
  177. c5 = (i >> 32) & 255;
  178. c6 = (i >> 40) & 255;
  179. c7 = (i >> 48) & 255;
  180. c8 = (i >> 56) & 255;
  181. return ((u_int64_t)c1 << 56) +
  182. ((u_int64_t)c2 << 48) +
  183. ((u_int64_t)c3 << 40) +
  184. ((u_int64_t)c4 << 32) +
  185. ((u_int64_t)c5 << 24) +
  186. ((u_int64_t)c6 << 16) +
  187. ((u_int64_t)c7 << 8) +
  188. c8;
  189. }
  190. #endif // __UNUSED__
  191. // vim: set expandtab shiftwidth=4