/src/e2fsprogs/lib/ext2fs/bitops.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * bitops.c --- Bitmap frobbing code. See bitops.h for the inlined |
3 | | * routines. |
4 | | * |
5 | | * Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o. |
6 | | * |
7 | | * %Begin-Header% |
8 | | * This file may be redistributed under the terms of the GNU Library |
9 | | * General Public License, version 2. |
10 | | * %End-Header% |
11 | | */ |
12 | | |
13 | | #include "config.h" |
14 | | #include <stdio.h> |
15 | | #if HAVE_SYS_TYPES_H |
16 | | #include <sys/types.h> |
17 | | #endif |
18 | | |
19 | | #include "ext2_fs.h" |
20 | | #include "ext2fs.h" |
21 | | |
22 | | /* |
23 | | * C language bitmap functions written by Theodore Ts'o, 9/26/92. |
24 | | * Modified by Pete A. Zaitcev 7/14/95 to be portable to big endian |
25 | | * systems, as well as non-32 bit systems. |
26 | | */ |
27 | | |
28 | | int ext2fs_set_bit(unsigned int nr,void * addr) |
29 | 129k | { |
30 | 129k | int mask, retval; |
31 | 129k | unsigned char *ADDR = (unsigned char *) addr; |
32 | | |
33 | 129k | ADDR += nr >> 3; |
34 | 129k | mask = 1 << (nr & 0x07); |
35 | 129k | retval = mask & *ADDR; |
36 | 129k | *ADDR |= mask; |
37 | 129k | return retval; |
38 | 129k | } |
39 | | |
40 | | int ext2fs_clear_bit(unsigned int nr, void * addr) |
41 | 0 | { |
42 | 0 | int mask, retval; |
43 | 0 | unsigned char *ADDR = (unsigned char *) addr; |
44 | |
|
45 | 0 | ADDR += nr >> 3; |
46 | 0 | mask = 1 << (nr & 0x07); |
47 | 0 | retval = mask & *ADDR; |
48 | 0 | *ADDR &= ~mask; |
49 | 0 | return retval; |
50 | 0 | } |
51 | | |
52 | | int ext2fs_test_bit(unsigned int nr, const void * addr) |
53 | 0 | { |
54 | 0 | int mask; |
55 | 0 | const unsigned char *ADDR = (const unsigned char *) addr; |
56 | |
|
57 | 0 | ADDR += nr >> 3; |
58 | 0 | mask = 1 << (nr & 0x07); |
59 | 0 | return (mask & *ADDR); |
60 | 0 | } |
61 | | |
62 | | void ext2fs_warn_bitmap(errcode_t errcode, unsigned long arg, |
63 | | const char *description) |
64 | 190k | { |
65 | 190k | #ifndef OMIT_COM_ERR |
66 | 190k | if (description) |
67 | 190k | com_err(0, errcode, "#%lu for %s", arg, description); |
68 | 0 | else |
69 | 0 | com_err(0, errcode, "#%lu", arg); |
70 | 190k | #endif |
71 | 190k | } |
72 | | |
73 | | /* Bitmap functions that take a 64-bit offset */ |
74 | | |
75 | | int ext2fs_set_bit64(__u64 nr, void * addr) |
76 | 0 | { |
77 | 0 | int mask, retval; |
78 | 0 | unsigned char *ADDR = (unsigned char *) addr; |
79 | |
|
80 | 0 | ADDR += nr >> 3; |
81 | 0 | mask = 1 << (nr & 0x07); |
82 | 0 | retval = mask & *ADDR; |
83 | 0 | *ADDR |= mask; |
84 | 0 | return retval; |
85 | 0 | } |
86 | | |
87 | | int ext2fs_clear_bit64(__u64 nr, void * addr) |
88 | 0 | { |
89 | 0 | int mask, retval; |
90 | 0 | unsigned char *ADDR = (unsigned char *) addr; |
91 | |
|
92 | 0 | ADDR += nr >> 3; |
93 | 0 | mask = 1 << (nr & 0x07); |
94 | 0 | retval = mask & *ADDR; |
95 | 0 | *ADDR &= ~mask; |
96 | 0 | return retval; |
97 | 0 | } |
98 | | |
99 | | int ext2fs_test_bit64(__u64 nr, const void * addr) |
100 | 0 | { |
101 | 0 | int mask; |
102 | 0 | const unsigned char *ADDR = (const unsigned char *) addr; |
103 | |
|
104 | 0 | ADDR += nr >> 3; |
105 | 0 | mask = 1 << (nr & 0x07); |
106 | 0 | return (mask & *ADDR); |
107 | 0 | } |
108 | | |
109 | | static unsigned int popcount8(unsigned int w) |
110 | 0 | { |
111 | 0 | unsigned int res = w - ((w >> 1) & 0x55); |
112 | 0 | res = (res & 0x33) + ((res >> 2) & 0x33); |
113 | 0 | return (res + (res >> 4)) & 0x0F; |
114 | 0 | } |
115 | | |
116 | | static unsigned int popcount32(unsigned int w) |
117 | 0 | { |
118 | 0 | unsigned int res = w - ((w >> 1) & 0x55555555); |
119 | 0 | res = (res & 0x33333333) + ((res >> 2) & 0x33333333); |
120 | 0 | res = (res + (res >> 4)) & 0x0F0F0F0F; |
121 | 0 | res = res + (res >> 8); |
122 | 0 | return (res + (res >> 16)) & 0x000000FF; |
123 | 0 | } |
124 | | |
125 | | unsigned int ext2fs_bitcount(const void *addr, unsigned int nbytes) |
126 | 0 | { |
127 | 0 | const unsigned char *cp = addr; |
128 | 0 | const __u32 *p; |
129 | 0 | unsigned int res = 0; |
130 | |
|
131 | 0 | while (((((uintptr_t) cp) & 3) != 0) && (nbytes > 0)) { |
132 | 0 | res += popcount8(*cp++); |
133 | 0 | nbytes--; |
134 | 0 | } |
135 | 0 | p = (const __u32 *) cp; |
136 | |
|
137 | 0 | while (nbytes > 4) { |
138 | 0 | res += popcount32(*p++); |
139 | 0 | nbytes -= 4; |
140 | 0 | } |
141 | 0 | cp = (const unsigned char *) p; |
142 | |
|
143 | 0 | while (nbytes > 0) { |
144 | 0 | res += popcount8(*cp++); |
145 | 0 | nbytes--; |
146 | 0 | } |
147 | 0 | return res; |
148 | 0 | } |