]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blob - db/bit.c
xfs_scrub: adapt phase5 to deferred descriptions
[thirdparty/xfsprogs-dev.git] / db / bit.c
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
10 int
11 getbit_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
25 void
26 setbit_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
46 int64_t
47 getbitval(
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 int z1, z2, z3, z4;
59
60 ASSERT(nbits<=64);
61
62 p = (char *)obj + byteize(bitoff);
63 bit = bitoffs(bitoff);
64 signext = (flags & BVSIGNED) != 0;
65 z4 = ((intptr_t)p & 0xf) == 0 && bit == 0;
66 if (nbits == 64 && z4)
67 return be64_to_cpu(*(__be64 *)p);
68 z3 = ((intptr_t)p & 0x7) == 0 && bit == 0;
69 if (nbits == 32 && z3) {
70 if (signext)
71 return (__s32)be32_to_cpu(*(__be32 *)p);
72 else
73 return (__u32)be32_to_cpu(*(__be32 *)p);
74 }
75 z2 = ((intptr_t)p & 0x3) == 0 && bit == 0;
76 if (nbits == 16 && z2) {
77 if (signext)
78 return (__s16)be16_to_cpu(*(__be16 *)p);
79 else
80 return (__u16)be16_to_cpu(*(__be16 *)p);
81 }
82 z1 = ((intptr_t)p & 0x1) == 0 && bit == 0;
83 if (nbits == 8 && z1) {
84 if (signext)
85 return *(__s8 *)p;
86 else
87 return *(__u8 *)p;
88 }
89
90
91 for (i = 0, rval = 0LL; i < nbits; i++) {
92 if (getbit_l(p, bit + i)) {
93 /* If the last bit is on and we care about sign
94 * bits and we don't have a full 64 bit
95 * container, turn all bits on between the
96 * sign bit and the most sig bit.
97 */
98
99 /* handle endian swap here */
100 #if __BYTE_ORDER == LITTLE_ENDIAN
101 if (i == 0 && signext && nbits < 64)
102 rval = (~0ULL) << nbits;
103 rval |= 1ULL << (nbits - i - 1);
104 #else
105 if ((i == (nbits - 1)) && signext && nbits < 64)
106 rval |= ((~0ULL) << nbits);
107 rval |= 1ULL << (nbits - i - 1);
108 #endif
109 }
110 }
111 return rval;
112 }
113
114 /*
115 * The input data can be 8, 16, 32, and 64 sized numeric values
116 * aligned on a byte boundry, or odd sized numbers stored on odd
117 * aligned offset (for example the bmbt fields).
118 *
119 * The input data sent to this routine has been converted to big endian
120 * and has been adjusted in the array so that the first input bit is to
121 * be written in the first bit in the output.
122 *
123 * If the field length and the output buffer are byte aligned, then use
124 * memcpy from the input to the output, but if either entries are not byte
125 * aligned, then loop over the entire bit range reading the input value
126 * and set/clear the matching bit in the output.
127 *
128 * example when ibuf is not multiple of a byte in length:
129 *
130 * ibuf: | BBBBBBBB | bbbxxxxx |
131 * \\\\\\\\--\\\\
132 * obuf+bitoff: | xBBBBBBB | Bbbbxxxx |
133 *
134 */
135 void
136 setbitval(
137 void *obuf, /* start of buffer to write into */
138 int bitoff, /* bit offset into the output buffer */
139 int nbits, /* number of bits to write */
140 void *ibuf) /* source bits */
141 {
142 char *in = ibuf;
143 char *out = obuf;
144 int bit;
145
146 if (bitoff % NBBY || nbits % NBBY) {
147 for (bit = 0; bit < nbits; bit++)
148 setbit_l(out, bit + bitoff, getbit_l(in, bit));
149 } else
150 memcpy(out + byteize(bitoff), in, byteize(nbits));
151 }