]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blame_incremental - db/bit.c
xfsprogs: Release v6.15.0
[thirdparty/xfsprogs-dev.git] / db / bit.c
... / ...
CommitLineData
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc.
4 * All Rights Reserved.
5 */
6
7#include "libxfs.h"
8#include "bit.h"
9
10int
11getbit_l(
12 char *ptr,
13 int bit)
14{
15 int mask;
16 int shift;
17
18 ptr += byteize(bit);
19 bit = bitoffs(bit);
20 shift = 7 - bit;
21 mask = 1 << shift;
22 return (*ptr & mask) >> shift;
23}
24
25void
26setbit_l(
27 char *ptr,
28 int bit,
29 int val)
30{
31 int mask;
32 int shift;
33
34 ptr += byteize(bit);
35 bit = bitoffs(bit);
36 shift = 7 - bit;
37 mask = (1 << shift);
38 if (val) {
39 *ptr |= mask;
40 } else {
41 mask = ~mask;
42 *ptr &= mask;
43 }
44}
45
46int64_t
47getbitval(
48 void *obj,
49 int bitoff,
50 int nbits,
51 int flags)
52{
53 int bit;
54 int i;
55 char *p;
56 int64_t rval;
57 int signext;
58
59 ASSERT(nbits<=64);
60
61 p = (char *)obj + byteize(bitoff);
62 bit = bitoffs(bitoff);
63 signext = (flags & BVSIGNED) != 0;
64
65 if (bit != 0)
66 goto scrape_bits;
67
68 switch (nbits) {
69 case 64:
70 return get_unaligned_be64(p);
71 case 32:
72 if (signext)
73 return (__s32)get_unaligned_be32(p);
74 return (__u32)get_unaligned_be32(p);
75 case 16:
76 if (signext)
77 return (__s16)get_unaligned_be16(p);
78 return (__u16)get_unaligned_be16(p);
79 case 8:
80 if (signext)
81 return *(__s8 *)p;
82 return *(__u8 *)p;
83 }
84
85scrape_bits:
86 for (i = 0, rval = 0LL; i < nbits; i++) {
87 if (getbit_l(p, bit + i)) {
88 /* If the last bit is on and we care about sign
89 * bits and we don't have a full 64 bit
90 * container, turn all bits on between the
91 * sign bit and the most sig bit.
92 */
93
94 /* handle endian swap here */
95#if __BYTE_ORDER == LITTLE_ENDIAN
96 if (i == 0 && signext && nbits < 64)
97 rval = (~0ULL) << nbits;
98 rval |= 1ULL << (nbits - i - 1);
99#else
100 if ((i == (nbits - 1)) && signext && nbits < 64)
101 rval |= ((~0ULL) << nbits);
102 rval |= 1ULL << (nbits - i - 1);
103#endif
104 }
105 }
106 return rval;
107}
108
109/*
110 * The input data can be 8, 16, 32, and 64 sized numeric values
111 * aligned on a byte boundry, or odd sized numbers stored on odd
112 * aligned offset (for example the bmbt fields).
113 *
114 * The input data sent to this routine has been converted to big endian
115 * and has been adjusted in the array so that the first input bit is to
116 * be written in the first bit in the output.
117 *
118 * If the field length and the output buffer are byte aligned, then use
119 * memcpy from the input to the output, but if either entries are not byte
120 * aligned, then loop over the entire bit range reading the input value
121 * and set/clear the matching bit in the output.
122 *
123 * example when ibuf is not multiple of a byte in length:
124 *
125 * ibuf: | BBBBBBBB | bbbxxxxx |
126 * \\\\\\\\--\\\\
127 * obuf+bitoff: | xBBBBBBB | Bbbbxxxx |
128 *
129 */
130void
131setbitval(
132 void *obuf, /* start of buffer to write into */
133 int bitoff, /* bit offset into the output buffer */
134 int nbits, /* number of bits to write */
135 void *ibuf) /* source bits */
136{
137 char *in = ibuf;
138 char *out = obuf;
139 int bit;
140
141 if (bitoff % NBBY || nbits % NBBY) {
142 for (bit = 0; bit < nbits; bit++)
143 setbit_l(out, bit + bitoff, getbit_l(in, bit));
144 } else
145 memcpy(out + byteize(bitoff), in, byteize(nbits));
146}