"Initial commit to Gerrit"
[profile/ivi/gpsd.git] / bits.h
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  * By defining the GET_ORIGIN and PUT_ORIGIN macros before including
9  * this header, it's possible to change the origin of the indexing.
10  *
11  * Assumptions:
12  *  char is 8 bits, short is 16 bits, int is 32 bits, long long is 64 bits,
13  *  float is 32 bits IEEE754, double is 64 bits IEEE754.
14  *
15  * The use of fixed-length types in the casts enforces these.
16  * Both 32- and 64-bit systems with gcc are OK with this set.
17  *
18  * This file is Copyright (c)2010 by the GPSD project
19  * BSD terms apply: see the file COPYING in the distribution root for details.
20  */
21 #ifndef _GPSD_BITS_H_
22 #define _GPSD_BITS_H_
23
24 #include <stdint.h>
25
26 union int_float {
27     int32_t i;
28     float f;
29 };
30
31 union long_double {
32     int64_t l;
33     double d;
34 };
35
36 #ifndef GET_ORIGIN
37 #define GET_ORIGIN      0
38 #endif
39 #ifndef PUT_ORIGIN
40 #define PUT_ORIGIN      0
41 #endif
42
43 /* these are independent of byte order */
44 #define getsb(buf, off) ((int8_t)buf[(off)-(GET_ORIGIN)])
45 #define getub(buf, off) ((uint8_t)buf[(off)-(GET_ORIGIN)])
46 #define putbyte(buf,off,b) do {buf[(off)-(PUT_ORIGIN)] = (unsigned char)(b);} while (0)
47
48 /* little-endian access */
49 #define getlesw(buf, off)       ((int16_t)(((uint16_t)getub((buf),   (off)+1) << 8) | (uint16_t)getub((buf), (off))))
50 #define getleuw(buf, off)       ((uint16_t)(((uint16_t)getub((buf), (off)+1) << 8) | (uint16_t)getub((buf), (off))))
51 #define getlesl(buf, off)       ((int32_t)(((uint16_t)getleuw((buf),  (off)+2) << 16) | (uint16_t)getleuw((buf), (off))))
52 #define getleul(buf, off)       ((uint32_t)(((uint16_t)getleuw((buf),(off)+2) << 16) | (uint16_t)getleuw((buf), (off))))
53
54 #define putleword(buf, off, w) do {putbyte(buf, (off)+1, (uint)(w) >> 8); putbyte(buf, (off), (w));} while (0)
55 #define putlelong(buf, off, l) do {putleword(buf, (off)+2, (uint)(l) >> 16); putleword(buf, (off), (l));} while (0)
56 #define getlesL(buf, off)       ((int64_t)(((uint64_t)getleul(buf, (off)+4) << 32) | getleul(buf, (off))))
57 #define getleuL(buf, off)       ((uint64_t)(((uint64_t)getleul(buf, (off)+4) << 32) | getleul(buf, (off))))
58
59 #define getlef(buf, off)        (i_f.i = getlesl(buf, off), i_f.f)
60 #define getled(buf, off)        (l_d.l = getlesL(buf, off), l_d.d)
61
62 /* SiRF and most other GPS protocols use big-endian (network byte order) */
63 #define getbesw(buf, off)       ((int16_t)(((uint16_t)getub(buf, (off)) << 8) | (uint16_t)getub(buf, (off)+1)))
64 #define getbeuw(buf, off)       ((uint16_t)(((uint16_t)getub(buf, (off)) << 8) | (uint16_t)getub(buf, (off)+1)))
65 #define getbesl(buf, off)       ((int32_t)(((uint16_t)getbeuw(buf, (off)) << 16) | getbeuw(buf, (off)+2)))
66 #define getbeul(buf, off)       ((uint32_t)(((uint16_t)getbeuw(buf, (off)) << 16) | getbeuw(buf, (off)+2)))
67 #define getbesL(buf, off)       ((int64_t)(((uint64_t)getbeul(buf, (off)) << 32) | getbeul(buf, (off)+4)))
68 #define getbeuL(buf, off)       ((uint64_t)(((uint64_t)getbeul(buf, (off)) << 32) | getbeul(buf, (off)+4)))
69
70 #define putbeword(buf,off,w) do {putbyte(buf, (off) ,(w) >> 8); putbyte(buf, (off)+1, (w));} while (0)
71 #define putbelong(buf,off,l) do {putbeword(buf, (off) ,(l) >> 16); putbeword(buf, (off)+2, (l));} while (0)
72
73 #define getbef(buf, off)        (i_f.i = getbesl(buf, off), i_f.f)
74 #define getbed(buf, off)        (l_d.l = getbesL(buf, off), l_d.d)
75
76
77 /* Zodiac protocol description uses 1-origin indexing by little-endian word */
78 #define getwordz(buf, n)        ( (buf[2*(n)-2])        \
79                 | (buf[2*(n)-1] << 8))
80 #define getlongz(buf, n)        ( (buf[2*(n)-2])        \
81                 | (buf[2*(n)-1] << 8) \
82                 | (buf[2*(n)+0] << 16) \
83                 | (buf[2*(n)+1] << 24))
84 #define getstringz(to, from, s, e)                      \
85     (void)memcpy(to, from+2*(s)-2, 2*((e)-(s)+1))
86
87 /* bitfield extraction */
88 extern unsigned long long ubits(char buf[], unsigned int, unsigned int);
89 extern signed long long sbits(char buf[], unsigned int, unsigned int);
90
91 #endif /* _GPSD_BITS_H_ */