bits.c 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  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 "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 "bits.h"
  20. /* extract a (zero-origin) bitfield from the buffer as an
  21. * unsigned big-endian uint64_t */
  22. uint64_t ubits(unsigned char buf[], unsigned int start,
  23. unsigned int width, bool le)
  24. {
  25. uint64_t fld = 0;
  26. unsigned int i;
  27. unsigned end;
  28. assert(width <= sizeof(uint64_t) * CHAR_BIT);
  29. for (i = start / CHAR_BIT;
  30. i < (start + width + CHAR_BIT - 1) / CHAR_BIT; i++) {
  31. fld <<= CHAR_BIT;
  32. fld |= (unsigned char)buf[i];
  33. }
  34. end = (start + width) % CHAR_BIT;
  35. if (end != 0) {
  36. fld >>= (CHAR_BIT - end);
  37. }
  38. fld &= ~(~0ULL << width);
  39. /* was extraction as a little-endian requested? */
  40. if (le)
  41. {
  42. uint64_t reversed = 0;
  43. for (i = width; i; --i)
  44. {
  45. reversed <<= 1;
  46. if (fld & 1)
  47. reversed |= 1;
  48. fld >>= 1;
  49. }
  50. fld = reversed;
  51. }
  52. return fld;
  53. }
  54. /* extract a bitfield from the buffer as a signed big-endian long */
  55. int64_t sbits(signed char buf[], unsigned int start, unsigned int width,
  56. bool le)
  57. {
  58. uint64_t fld = ubits((unsigned char *)buf, start, width, le);
  59. /* ensure width > 0 as the result of
  60. 1ULL << (width - 1)
  61. is undefined for width <= 0 */
  62. assert(width > 0);
  63. if (fld & (1ULL << (width - 1))) {
  64. fld |= (~0ULL << (width - 1));
  65. }
  66. return (int64_t)fld;
  67. }
  68. union int_float {
  69. int32_t i;
  70. float f;
  71. };
  72. union long_double {
  73. int64_t l;
  74. double d;
  75. };
  76. float getlef32(const char *buf, int off)
  77. {
  78. union int_float i_f;
  79. i_f.i = getles32(buf, off);
  80. return i_f.f;
  81. }
  82. double getled64(const char *buf, int off)
  83. {
  84. union long_double l_d;
  85. l_d.l = getles64(buf, off);
  86. return l_d.d;
  87. }
  88. float getbef32(const char *buf, int off)
  89. {
  90. union int_float i_f;
  91. i_f.i = getbes32(buf, off);
  92. return i_f.f;
  93. }
  94. double getbed64(const char *buf, int off)
  95. {
  96. union long_double l_d;
  97. l_d.l = getbes64(buf, off);
  98. return l_d.d;
  99. }
  100. void putbef32(char *buf, int off, float val)
  101. {
  102. union int_float i_f;
  103. i_f.f = val;
  104. putbe32(buf, off, i_f.i);
  105. }
  106. void shiftleft(unsigned char *data, int size, unsigned short left)
  107. {
  108. unsigned char *byte;
  109. if (left >= CHAR_BIT) {
  110. size -= left/CHAR_BIT;
  111. memmove(data, data + left/CHAR_BIT, (size + CHAR_BIT - 1)/CHAR_BIT);
  112. left %= CHAR_BIT;
  113. }
  114. for (byte = data; size--; ++byte )
  115. {
  116. unsigned char bits;
  117. if (size)
  118. bits = byte[1] >> (CHAR_BIT - left);
  119. else
  120. bits = 0;
  121. *byte <<= left;
  122. *byte |= bits;
  123. }
  124. }
  125. #ifdef __UNUSED__
  126. void putbed64(char *buf, int off, double val)
  127. {
  128. union long_double l_d;
  129. l_d.d = val;
  130. putbe32(buf, (off), (l_d.l) >> 32);
  131. putbe32(buf, (off)+4, (l_d.l));
  132. }
  133. u_int16_t swap_u16(u_int16_t i)
  134. /* byte-swap a 16-bit unsigned int */
  135. {
  136. u_int8_t c1, c2;
  137. c1 = i & 255;
  138. c2 = (i >> 8) & 255;
  139. return (c1 << 8) + c2;
  140. }
  141. /* byte-swap a 32-bit unsigned int */
  142. u_int32_t swap_u32(u_int32_t i)
  143. {
  144. u_int8_t c1, c2, c3, c4;
  145. c1 = i & 255;
  146. c2 = (i >> 8) & 255;
  147. c3 = (i >> 16) & 255;
  148. c4 = (i >> 24) & 255;
  149. return ((u_int32_t)c1 << 24) +
  150. ((u_int32_t)c2 << 16) +
  151. ((u_int32_t)c3 << 8) + c4;
  152. }
  153. u_int64_t swap_u64(u_int64_t i)
  154. /* byte-swap a 64-bit unsigned int */
  155. {
  156. u_int8_t c1, c2, c3, c4, c5, c6, c7, c8;
  157. c1 = i & 255;
  158. c2 = (i >> 8) & 255;
  159. c3 = (i >> 16) & 255;
  160. c4 = (i >> 24) & 255;
  161. c5 = (i >> 32) & 255;
  162. c6 = (i >> 40) & 255;
  163. c7 = (i >> 48) & 255;
  164. c8 = (i >> 56) & 255;
  165. return ((u_int64_t)c1 << 56) +
  166. ((u_int64_t)c2 << 48) +
  167. ((u_int64_t)c3 << 40) +
  168. ((u_int64_t)c4 << 32) +
  169. ((u_int64_t)c5 << 24) +
  170. ((u_int64_t)c6 << 16) +
  171. ((u_int64_t)c7 << 8) +
  172. c8;
  173. }
  174. #endif /* __UNUSED__ */
  175. // vim: set expandtab shiftwidth=4