]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blame - db/bit.c
xfsprogs: Release v4.17.0
[thirdparty/xfsprogs-dev.git] / db / bit.c
CommitLineData
2bd0ea18 1/*
da23017d
NS
2 * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc.
3 * All Rights Reserved.
dfc130f3 4 *
da23017d
NS
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
2bd0ea18 7 * published by the Free Software Foundation.
dfc130f3 8 *
da23017d
NS
9 * This program is distributed in the hope that it would be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
dfc130f3 13 *
da23017d
NS
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write the Free Software Foundation,
16 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
2bd0ea18
NS
17 */
18
6b803e5a 19#include "libxfs.h"
2bd0ea18
NS
20#include "bit.h"
21
984af2e1
DW
22int
23getbit_l(
2bd0ea18
NS
24 char *ptr,
25 int bit)
26{
27 int mask;
28 int shift;
29
30 ptr += byteize(bit);
31 bit = bitoffs(bit);
32 shift = 7 - bit;
33 mask = 1 << shift;
34 return (*ptr & mask) >> shift;
35}
36
984af2e1
DW
37void
38setbit_l(
2bd0ea18
NS
39 char *ptr,
40 int bit,
41 int val)
42{
43 int mask;
44 int shift;
45
46 ptr += byteize(bit);
47 bit = bitoffs(bit);
48 shift = 7 - bit;
49 mask = (1 << shift);
50 if (val) {
51 *ptr |= mask;
52 } else {
53 mask = ~mask;
54 *ptr &= mask;
55 }
56}
57
14f8b681 58int64_t
2bd0ea18
NS
59getbitval(
60 void *obj,
61 int bitoff,
62 int nbits,
63 int flags)
64{
65 int bit;
66 int i;
67 char *p;
14f8b681 68 int64_t rval;
2bd0ea18
NS
69 int signext;
70 int z1, z2, z3, z4;
dfc130f3
RC
71
72 ASSERT(nbits<=64);
2bd0ea18
NS
73
74 p = (char *)obj + byteize(bitoff);
75 bit = bitoffs(bitoff);
76 signext = (flags & BVSIGNED) != 0;
ee6cd73e 77 z4 = ((intptr_t)p & 0xf) == 0 && bit == 0;
5e656dbb
BN
78 if (nbits == 64 && z4)
79 return be64_to_cpu(*(__be64 *)p);
ee6cd73e 80 z3 = ((intptr_t)p & 0x7) == 0 && bit == 0;
2bd0ea18
NS
81 if (nbits == 32 && z3) {
82 if (signext)
5e656dbb 83 return (__s32)be32_to_cpu(*(__be32 *)p);
2bd0ea18 84 else
5e656dbb 85 return (__u32)be32_to_cpu(*(__be32 *)p);
2bd0ea18 86 }
ee6cd73e 87 z2 = ((intptr_t)p & 0x3) == 0 && bit == 0;
2bd0ea18
NS
88 if (nbits == 16 && z2) {
89 if (signext)
5e656dbb 90 return (__s16)be16_to_cpu(*(__be16 *)p);
2bd0ea18 91 else
5e656dbb 92 return (__u16)be16_to_cpu(*(__be16 *)p);
2bd0ea18 93 }
ee6cd73e 94 z1 = ((intptr_t)p & 0x1) == 0 && bit == 0;
2bd0ea18
NS
95 if (nbits == 8 && z1) {
96 if (signext)
5e656dbb 97 return *(__s8 *)p;
2bd0ea18 98 else
5e656dbb 99 return *(__u8 *)p;
2bd0ea18 100 }
dfc130f3
RC
101
102
2bd0ea18 103 for (i = 0, rval = 0LL; i < nbits; i++) {
984af2e1 104 if (getbit_l(p, bit + i)) {
dfc130f3
RC
105 /* If the last bit is on and we care about sign
106 * bits and we don't have a full 64 bit
107 * container, turn all bits on between the
108 * sign bit and the most sig bit.
109 */
110
111 /* handle endian swap here */
2bd0ea18
NS
112#if __BYTE_ORDER == LITTLE_ENDIAN
113 if (i == 0 && signext && nbits < 64)
a93fcc04 114 rval = (~0ULL) << nbits;
25f9772a 115 rval |= 1ULL << (nbits - i - 1);
2bd0ea18
NS
116#else
117 if ((i == (nbits - 1)) && signext && nbits < 64)
a93fcc04 118 rval |= ((~0ULL) << nbits);
25f9772a 119 rval |= 1ULL << (nbits - i - 1);
2bd0ea18
NS
120#endif
121 }
122 }
123 return rval;
124}
125
dc151328
MT
126/*
127 * The input data can be 8, 16, 32, and 64 sized numeric values
128 * aligned on a byte boundry, or odd sized numbers stored on odd
129 * aligned offset (for example the bmbt fields).
130 *
131 * The input data sent to this routine has been converted to big endian
132 * and has been adjusted in the array so that the first input bit is to
133 * be written in the first bit in the output.
134 *
135 * If the field length and the output buffer are byte aligned, then use
136 * memcpy from the input to the output, but if either entries are not byte
137 * aligned, then loop over the entire bit range reading the input value
138 * and set/clear the matching bit in the output.
139 *
140 * example when ibuf is not multiple of a byte in length:
141 *
142 * ibuf: | BBBBBBBB | bbbxxxxx |
143 * \\\\\\\\--\\\\
144 * obuf+bitoff: | xBBBBBBB | Bbbbxxxx |
145 *
146 */
2bd0ea18
NS
147void
148setbitval(
dc151328
MT
149 void *obuf, /* start of buffer to write into */
150 int bitoff, /* bit offset into the output buffer */
151 int nbits, /* number of bits to write */
152 void *ibuf) /* source bits */
2bd0ea18 153{
dc151328
MT
154 char *in = ibuf;
155 char *out = obuf;
156 int bit;
157
158 if (bitoff % NBBY || nbits % NBBY) {
159 for (bit = 0; bit < nbits; bit++)
984af2e1 160 setbit_l(out, bit + bitoff, getbit_l(in, bit));
dc151328
MT
161 } else
162 memcpy(out + byteize(bitoff), in, byteize(nbits));
2bd0ea18 163}