-
Notifications
You must be signed in to change notification settings - Fork 10
Expand file tree
/
Copy pathshell-bitwise
More file actions
236 lines (219 loc) · 5.3 KB
/
shell-bitwise
File metadata and controls
236 lines (219 loc) · 5.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
#!/bin/sh -efu
### This file is covered by the GNU General Public License,
### which should be included with libshell as the file LICENSE.
### All copyright information are listed in the COPYING.
if [ -z "${__included_shell_bits-}" ]; then
__included_shell_bits=1
__shell_prepare_integer()
{
case "$2" in
9223372036854775808|-9223372036854775808|0[xX]8000000000000000|-0[xX]8000000000000000)
set -- "$1" "(0x7fffffffffffffff + 1)"
;;
0[xX][0-9A-Fa-f]*|[1-9]*|-[1-9]*)
;;
-0[xX]*)
return 1
;;
0*|-0*)
set -- "$1" "$(printf '%d' "$2")"
;;
*)
return 1
;;
esac
eval "$1=\"\$2\""
}
### Usage: is_bit_set number bit_pos
###
### Checks whether the bit at position bit_pos is set.
###
### Arguments:
### number - integer value to extract the bit from
### bit_pos - bit position (0 = least significant bit)
###
### Result:
### The return 0 (true) if bit is set, 1 (false) if not.
###
is_bit_set()
{
return $(( !(($1 >> $2) & 1) ))
}
### Usage: get_bit result_var number bit_pos
###
### Extract the value of the specified bit from a number.
###
### Arguments:
### result_var - name of the variable to store the result
### number - integer value to extract the bit from
### bit_pos - bit position (0 = least significant bit)
###
### Result:
### The value of the specified bit (0 or 1) is stored in result_var.
###
get_bit()
{
is_bit_set "$2" "$3" &&
eval "$1=1" ||
eval "$1=0"
}
### Usage: set_bit_value result_var number bit value
###
### Sets the specified bit in a number to a given value (0 or 1).
###
### Arguments:
### result_var - name of the variable to store the result
### number - integer value to modify
### bit - bit position (0 = least significant bit)
### value - desired bit value (0 or 1)
###
### Result:
### The modified number with the updated bit is stored in result_var.
###
set_bit_value()
{
local set_bit_value=''
__set_bit_value() {
local v
__shell_prepare_integer v "$1"
if [ "$3" -eq 0 ]; then
set_bit_value=$(( $v & ~(1 << $2) ))
else
set_bit_value=$(( $v | (1 << $2) ))
fi
}
__set_bit_value "$2" "$3" "$4"
unset -f __set_bit_value
eval "$1=\"\$set_bit_value\""
}
### Usage: set_bit result_var number bit
###
### Sets the specified bit to 1.
###
### Arguments:
### result_var - name of the variable to store the result
### number - integer value to modify
### bit - bit position (0 = least significant bit)
###
### Result:
### The modified number with the bit set to 1 is stored in result_var.
###
set_bit()
{
set_bit_value "$1" "$2" "$3" 1
}
### Usage: clear_bit result_var number bit
###
### Clears (sets to 0) the specified bit.
###
### Arguments:
### result_var - name of the variable to store the result
### number - integer value to modify
### bit - bit position (0 = least significant bit)
###
### Result:
### The modified number with the bit cleared is stored in result_var.
###
clear_bit()
{
set_bit_value "$1" "$2" "$3" 0
}
### Usage: toggle_bit result_var number bit
###
### Toggles (inverts) the specified bit.
###
### Arguments:
### result_var - name of the variable to store the result
### number - integer value to modify
### bit - bit position (0 = least significant bit)
###
### Result:
### The modified number with the bit inverted is stored in result_var.
###
toggle_bit()
{
if is_bit_set "$2" "$3"; then
set_bit_value "$1" "$2" "$3" 0
else
set_bit_value "$1" "$2" "$3" 1
fi
}
### Usage: set_bits result_var number bit1 bit2 ...
###
### Sets multiple bits to 1 in a number.
###
### Arguments:
### result_var - name of the variable to store the result
### number - integer value to modify
### bit1...N - list of bit positions to set
###
### Result:
### The modified number with all specified bits set to 1 is stored in result_var.
###
set_bits()
{
local __res="$1" number="$2"
shift 2
while [ "$#" -gt 0 ]; do
set_bit_value number "$number" "$1" 1
shift
done
eval "$__res=\"\$number\""
}
### Usage: clear_bits result_var number bit1 bit2 ...
###
### Clears (sets to 0) multiple bits in a number.
###
### Arguments:
### result_var - name of the variable to store the result
### number - integer value to modify
### bit1...N - list of bit positions to clear
###
### Result:
### The modified number with all specified bits cleared is stored in result_var.
###
clear_bits()
{
local __res="$1" number="$2"
shift 2
while [ "$#" -gt 0 ]; do
set_bit_value number "$number" "$1" 0
shift
done
eval "$__res=\"\$number\""
}
### Usage: toggle_bits result_var number bit1 bit2 ...
###
### Toggles (inverts) multiple bits in a number.
###
### Arguments:
### result_var - name of the variable to store the result
### number - integer value to modify
### bit1...N - list of bit positions to toggle
###
### Result:
### The modified number with all specified bits inverted is stored in result_var.
###
toggle_bits()
{
printf -v "$__res" '%d' "$number"
local __res="$1" number="$2"
shift 2
while [ "$#" -gt 0 ]; do
toggle_bit number "$number" "$1"
shift
done
eval "$__res=\"\$number\""
}
integer_to_binary()
{
local arg
__shell_prepare_integer arg "$1" ||
return 1
set -- "$arg" "$(( ${2:-8} - 1 ))" ""
while [ $2 -ge 0 ]; do
set -- "$1" "$(( $2 - 1 ))" "$3$(( ($1 >> $2) & 1 ))"
done
printf '%s\n' "$3"
}
fi #__included_shell_bits