Coverage Report

Created: 2025-10-10 06:04

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/gpsd/gpsd-3.26.2~dev/libgps/bits.c
Line
Count
Source
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
15
#include <assert.h>
16
#include <limits.h>
17
#include <stdbool.h>
18
#include <stdint.h>
19
#include <string.h>
20
21
#include "../include/bits.h"
22
23
/* extract a (zero-origin) bitfield from a buffer) as an
24
 * unsigned uint64_t
25
 * Note: max width 56!
26
 *
27
 * Parameters: buf -- the buffer
28
 *             start -- starting bit of desired bitfield
29
 *             width -- width of desired bitfield (0 to 56)
30
 *             le -- little endian input (swap bytes)
31
 *
32
 * Returns: bitfield as uint64_t
33
 *          zero on errors (56 < width)
34
 */
35
uint64_t ubits(const unsigned char buf[], unsigned int start,
36
               unsigned int width, bool le)
37
0
{
38
0
    uint64_t fld = 0;
39
0
    unsigned int i;
40
0
    unsigned end;
41
42
0
    assert(width <= sizeof(uint64_t) * CHAR_BIT);
43
0
    if (0 == width ||
44
0
        56 < width) {
45
0
        return 0;
46
0
    }
47
0
    for (i = start / CHAR_BIT;
48
0
         i < (start + width + CHAR_BIT - 1) / CHAR_BIT; i++) {
49
0
        fld <<= CHAR_BIT;
50
0
        fld |= (uint64_t)buf[i];
51
0
    }
52
53
0
    end = (start + width) % CHAR_BIT;
54
0
    if (0 != end) {
55
0
        fld >>= (CHAR_BIT - end);
56
0
    }
57
58
0
    fld &= ~(~0ULL << width);
59
60
0
    if (le) {
61
        // extraction as a little-endian requested
62
0
        uint64_t reversed = 0;
63
64
0
        for (i = width; i; --i) {
65
0
            reversed <<= 1;
66
0
            if (1 == (1 & fld)) {
67
0
                reversed |= 1;
68
0
            }
69
0
            fld >>= 1;
70
0
        }
71
0
        fld = reversed;
72
0
    }
73
74
0
    return fld;
75
0
}
76
77
// extract a bitfield from the buffer as a signed big-endian long
78
int64_t sbits(const unsigned char buf[], unsigned int start, unsigned int width,
79
              bool le)
80
0
{
81
0
    uint64_t fld = ubits(buf, start, width, le);
82
83
    /* ensure width > 0 as the result of
84
       1ULL << (width - 1)
85
       is undefined for width <= 0 */
86
0
    assert(width > 0);
87
88
0
    if (fld & (1ULL << (width - 1))) {
89
0
        fld |= (~0ULL << (width - 1));
90
0
    }
91
0
    return (int64_t)fld;
92
0
}
93
94
union int_float {
95
    int32_t i;
96
    float f;
97
};
98
99
union long_double {
100
    int64_t l;
101
    double d;
102
};
103
104
float getlef32(const char *buf, int off)
105
0
{
106
0
    union int_float i_f;
107
108
0
    i_f.i = getles32(buf, off);
109
0
    return i_f.f;
110
0
}
111
112
double getled64(const char *buf, int off)
113
0
{
114
0
    union long_double l_d;
115
116
0
    l_d.l = getles64(buf, off);
117
0
    return l_d.d;
118
0
}
119
120
float getbef32(const char *buf, int off)
121
0
{
122
0
    union int_float i_f;
123
124
0
    i_f.i = getbes32(buf, off);
125
0
    return i_f.f;
126
0
}
127
128
double getbed64(const char *buf, int off)
129
0
{
130
0
    union long_double l_d;
131
132
0
    l_d.l = getbes64(buf, off);
133
0
    return l_d.d;
134
0
}
135
136
void putbef32(char *buf, int off, float val)
137
0
{
138
0
    union int_float i_f;
139
140
0
    i_f.f = val;
141
0
    putbe32(buf, off, i_f.i);
142
0
}
143
144
145
void shiftleft(unsigned char *data, int size, unsigned short left)
146
0
{
147
0
    unsigned char *byte;
148
149
0
    if (CHAR_BIT <= left) {
150
0
        size -= left / CHAR_BIT;
151
0
        memmove(data, data + left / CHAR_BIT,
152
0
                (size + CHAR_BIT - 1) / CHAR_BIT);
153
0
        left %= CHAR_BIT;
154
0
    }
155
156
0
    for (byte = data; size--; ++byte ) {
157
0
        unsigned char bits;
158
159
0
        if (size) {
160
0
            bits = byte[1] >> (CHAR_BIT - left);
161
0
        } else {
162
0
            bits = 0;
163
0
        }
164
0
        *byte <<= left;
165
        // Yes, the mask should not be needed, but id avoids a compiler
166
        // bug in gcc-amd64 11.2.1
167
0
        *byte |= 0x0ff & bits;
168
0
    }
169
0
}
170
171
#ifdef __UNUSED__
172
void putbed64(char *buf, int off, double val)
173
{
174
    union long_double l_d;
175
176
    l_d.d = val;
177
    putbe32(buf, (off), (l_d.l) >> 32);
178
    putbe32(buf, (off)+4, (l_d.l));
179
}
180
181
// byte-swap a 16-bit unsigned int
182
u_int16_t swap_u16(u_int16_t i)
183
{
184
    u_int8_t c1, c2;
185
186
    c1 = i & 255;
187
    c2 = (i >> 8) & 255;
188
189
    return (c1 << 8) + c2;
190
}
191
192
// byte-swap a 32-bit unsigned int
193
u_int32_t swap_u32(u_int32_t i)
194
{
195
    u_int8_t c1, c2, c3, c4;
196
197
    c1 = i & 255;
198
    c2 = (i >> 8) & 255;
199
    c3 = (i >> 16) & 255;
200
    c4 = (i >> 24) & 255;
201
202
    return ((u_int32_t)c1 << 24) +
203
            ((u_int32_t)c2 << 16) +
204
            ((u_int32_t)c3 << 8) + c4;
205
}
206
207
// byte-swap a 64-bit unsigned int
208
u_int64_t swap_u64(u_int64_t i)
209
{
210
    u_int8_t c1, c2, c3, c4, c5, c6, c7, c8;
211
212
    c1 = i & 255;
213
    c2 = (i >> 8) & 255;
214
    c3 = (i >> 16) & 255;
215
    c4 = (i >> 24) & 255;
216
    c5 = (i >> 32) & 255;
217
    c6 = (i >> 40) & 255;
218
    c7 = (i >> 48) & 255;
219
    c8 = (i >> 56) & 255;
220
221
    return ((u_int64_t)c1 << 56) +
222
            ((u_int64_t)c2 << 48) +
223
            ((u_int64_t)c3 << 40) +
224
            ((u_int64_t)c4 << 32) +
225
            ((u_int64_t)c5 << 24) +
226
            ((u_int64_t)c6 << 16) +
227
            ((u_int64_t)c7 << 8) +
228
            c8;
229
}
230
#endif  // __UNUSED__
231
// vim: set expandtab shiftwidth=4