bits.h 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566
  1. /*
  2. * bits.h - extract binary data from message buffer
  3. *
  4. * These macros extract bytes, words, longwords, floats, doubles, or
  5. * bitfields of arbitrary length and size from a message that contains
  6. * these items in either MSB-first or LSB-first byte order.
  7. *
  8. * We enforce data sizes of integral types in the casts on these.
  9. * Both 32- and 64-bit systems with gcc are OK with this set.
  10. *
  11. * This file is Copyright 2010 by the GPSD project
  12. * SPDX-License-Identifier: BSD-2-clause
  13. */
  14. #ifndef _GPSD_BITS_H_
  15. #define _GPSD_BITS_H_
  16. #include <stdint.h>
  17. #include <limits.h>
  18. /* number of bytes requited to contain a bit array of specified length */
  19. #define BITS_TO_BYTES(bitlen) (((bitlen) + CHAR_BIT - 1) / CHAR_BIT)
  20. /* these are independent of byte order */
  21. #define getsb(buf, off) ((int8_t)buf[off])
  22. #define getub(buf, off) ((uint8_t)buf[off])
  23. #define putbyte(buf,off,b) do {buf[off] = (unsigned char)(b);} while (0)
  24. /* little-endian access */
  25. #define getles16(buf, off) ((int16_t)(((uint16_t)getub((buf), (off)+1) << 8) | (uint16_t)getub((buf), (off))))
  26. #define getleu16(buf, off) ((uint16_t)(((uint16_t)getub((buf), (off)+1) << 8) | (uint16_t)getub((buf), (off))))
  27. #define getles32(buf, off) ((int32_t)(((uint16_t)getleu16((buf), (off)+2) << 16) | (uint16_t)getleu16((buf), (off))))
  28. #define getleu32(buf, off) ((uint32_t)(((uint16_t)getleu16((buf),(off)+2) << 16) | (uint16_t)getleu16((buf), (off))))
  29. #define getles64(buf, off) ((int64_t)(((uint64_t)getleu32(buf, (off)+4) << 32) | getleu32(buf, (off))))
  30. #define getleu64(buf, off) ((uint64_t)(((uint64_t)getleu32(buf, (off)+4) << 32) | getleu32(buf, (off))))
  31. extern float getlef32(const char *, int);
  32. extern double getled64(const char *, int);
  33. #define putle16(buf, off, w) do {putbyte(buf, (off)+1, (unsigned int)(w) >> 8); putbyte(buf, (off), (w));} while (0)
  34. #define putle32(buf, off, l) do {putle16(buf, (off)+2, (unsigned int)(l) >> 16); putle16(buf, (off), (l));} while (0)
  35. /* big-endian access */
  36. #define getbes16(buf, off) ((int16_t)(((uint16_t)getub(buf, (off)) << 8) | (uint16_t)getub(buf, (off)+1)))
  37. #define getbeu16(buf, off) ((uint16_t)(((uint16_t)getub(buf, (off)) << 8) | (uint16_t)getub(buf, (off)+1)))
  38. #define getbeu24(buf, off) ((uint32_t)(((uint16_t)getbeu16(buf, (off)) << 8) | getub(buf, (off)+2)))
  39. #define getbes32(buf, off) ((int32_t)(((uint16_t)getbeu16(buf, (off)) << 16) | getbeu16(buf, (off)+2)))
  40. #define getbeu32(buf, off) ((uint32_t)(((uint16_t)getbeu16(buf, (off)) << 16) | getbeu16(buf, (off)+2)))
  41. #define getbes64(buf, off) ((int64_t)(((uint64_t)getbeu32(buf, (off)) << 32) | getbeu32(buf, (off)+4)))
  42. #define getbeu64(buf, off) ((uint64_t)(((uint64_t)getbeu32(buf, (off)) << 32) | getbeu32(buf, (off)+4)))
  43. extern float getbef32(const char *, int);
  44. extern double getbed64(const char *, int);
  45. #define putbe16(buf,off,w) do {putbyte(buf, (off), (w) >> 8); putbyte(buf, (off)+1, (w));} while (0)
  46. #define putbe32(buf,off,l) do {putbe16(buf, (off), (l) >> 16); putbe16(buf, (off)+2, (l));} while (0)
  47. extern void putbef32(char *, int, float);
  48. extern void putbed64(char *, int, double);
  49. extern void shiftleft(unsigned char *, int, unsigned short);
  50. /* bitfield extraction */
  51. extern uint64_t ubits(unsigned char buf[], unsigned int, unsigned int, bool);
  52. extern int64_t sbits(signed char buf[], unsigned int, unsigned int, bool);
  53. #endif /* _GPSD_BITS_H_ */
  54. // vim: set expandtab shiftwidth=4