20cd1d53e4884de8ebcaafa297ae851142817cbe
[project/luci.git] / libs / core / luasrc / bits.lua
1 --[[
2 /*
3 * Copyright (c) 2007 Tim Kelly/Dialectronics
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining
6 * a copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sublicense, and/or sell copies of the Software, and to permit
10 * persons to whom the Software is furnished to do so, subject to the
11 * following conditions:
12 *
13 * The above copyright notice and this permission notice shall be
14 * included in all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
20 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT
21 * OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
22 * THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 */
24
25 Modifications and documentation for LuCI made by
26 Steven Barth <steven@midlink.org> and
27 Jo-Philipp Wich <xm@leipzig.freifunk.net>
28
29 --]]
30
31 --- LuCI number conversion and bit manipulation functions.
32 module("luci.bits", package.seeall);
33
34 local hex2bin = {
35 ["0"] = "0000",
36 ["1"] = "0001",
37 ["2"] = "0010",
38 ["3"] = "0011",
39 ["4"] = "0100",
40 ["5"] = "0101",
41 ["6"] = "0110",
42 ["7"] = "0111",
43 ["8"] = "1000",
44 ["9"] = "1001",
45 ["a"] = "1010",
46 ["b"] = "1011",
47 ["c"] = "1100",
48 ["d"] = "1101",
49 ["e"] = "1110",
50 ["f"] = "1111"
51 }
52
53 local bin2hex = {
54 ["0000"] = "0",
55 ["0001"] = "1",
56 ["0010"] = "2",
57 ["0011"] = "3",
58 ["0100"] = "4",
59 ["0101"] = "5",
60 ["0110"] = "6",
61 ["0111"] = "7",
62 ["1000"] = "8",
63 ["1001"] = "9",
64 ["1010"] = "A",
65 ["1011"] = "B",
66 ["1100"] = "C",
67 ["1101"] = "D",
68 ["1110"] = "E",
69 ["1111"] = "F"
70 }
71
72 --- Convert hexadecimal to binary number.
73 -- This function is big endian and can take up to 32 bits.
74 -- @param s String containing hex value
75 -- @return String containing binary value
76 function Hex2Bin(s)
77
78 local ret = ""
79 local i = 0
80
81
82 for i in string.gfind(s, ".") do
83 i = string.lower(i)
84
85 ret = ret..hex2bin[i]
86
87 end
88
89 return ret
90 end
91
92 --- Convert binary to hexadecimal number.
93 -- This function is big endian and can take up to 32 bits.
94 -- @param s String containing binary value
95 -- @return String containing hex value
96 function Bin2Hex(s)
97
98 local l = 0
99 local h = ""
100 local b = ""
101 local rem
102
103 l = string.len(s)
104 rem = l % 4
105 l = l-1
106 h = ""
107
108 -- need to prepend zeros to eliminate mod 4
109 if (rem > 0) then
110 s = string.rep("0", 4 - rem)..s
111 end
112
113 for i = 1, l, 4 do
114 b = string.sub(s, i, i+3)
115 h = h..bin2hex[b]
116 end
117
118 return h
119
120 end
121
122 --- Convert binary to decimal number.
123 -- This function is big endian and can take up to 32 bits.
124 -- @param s String containing binary value
125 -- @return String containing decimal value
126 function Bin2Dec(s)
127
128 local num = 0
129 local ex = string.len(s) - 1
130 local l = 0
131
132 l = ex + 1
133 for i = 1, l do
134 b = string.sub(s, i, i)
135 if b == "1" then
136 num = num + 2^ex
137 end
138 ex = ex - 1
139 end
140
141 return string.format("%u", num)
142
143 end
144
145 --- Convert decimal to binary number.
146 -- This function is big endian and can take up to 32 bits.
147 -- @param s String or number containing decimal value
148 -- @param num Pad binary number to num bits
149 -- @return String containing binary value
150 function Dec2Bin(s, num)
151
152 local n
153
154 if (num == nil) then
155 n = 0
156 else
157 n = num
158 end
159
160 s = string.format("%x", s)
161
162 s = Hex2Bin(s)
163
164 while string.len(s) < n do
165 s = "0"..s
166 end
167
168 return s
169
170 end
171
172 --- Convert hexadecimal to decimal number.
173 -- This function is big endian and can take up to 32 bits.
174 -- @param s String containing hex value
175 -- @return String containing decimal value
176 function Hex2Dec(s)
177
178 local s = Hex2Bin(s)
179
180 return Bin2Dec(s)
181
182 end
183
184 --- Convert decimal to hexadecimal number.
185 -- This function is big endian and can take up to 32 bits.
186 -- @param s String containing decimal value
187 -- @return String containing hex value
188 function Dec2Hex(s)
189
190 s = string.format("%x", s)
191
192 return s
193
194 end
195
196
197 --- Apply bitmask to value using bitwise And.
198 -- This function is big endian and will extend the values to 32 bits.
199 -- @param v String containing hex value to be masked
200 -- @param m String containing hex value of mask
201 -- @return String containing hex value of masked value
202 function BMAnd(v, m)
203
204 local bv = Hex2Bin(v)
205 local bm = Hex2Bin(m)
206
207 local i = 0
208 local s = ""
209
210 while (string.len(bv) < 32) do
211 bv = "0000"..bv
212 end
213
214 while (string.len(bm) < 32) do
215 bm = "0000"..bm
216 end
217
218
219 for i = 1, 32 do
220 cv = string.sub(bv, i, i)
221 cm = string.sub(bm, i, i)
222 if cv == cm then
223 if cv == "1" then
224 s = s.."1"
225 else
226 s = s.."0"
227 end
228 else
229 s = s.."0"
230
231 end
232 end
233
234 return Bin2Hex(s)
235
236 end
237
238 --- Apply bitmask to value using bitwise Nand.
239 -- This function is big endian and will extend the values to 32 bits.
240 -- @param v String containing hex value to be masked
241 -- @param m String containing hex value of mask
242 -- @return String containing hex value of masked value
243 function BMNAnd(v, m)
244
245 local bv = Hex2Bin(v)
246 local bm = Hex2Bin(m)
247
248 local i = 0
249 local s = ""
250
251 while (string.len(bv) < 32) do
252 bv = "0000"..bv
253 end
254
255 while (string.len(bm) < 32) do
256 bm = "0000"..bm
257 end
258
259
260 for i = 1, 32 do
261 cv = string.sub(bv, i, i)
262 cm = string.sub(bm, i, i)
263 if cv == cm then
264 if cv == "1" then
265 s = s.."0"
266 else
267 s = s.."1"
268 end
269 else
270 s = s.."1"
271
272 end
273 end
274
275 return Bin2Hex(s)
276
277 end
278
279 --- Apply bitmask to value using bitwise Or.
280 -- This function is big endian and will extend the values to 32 bits.
281 -- @param v String containing hex value to be masked
282 -- @param m String containing hex value of mask
283 -- @return String containing hex value of masked value
284 function BMOr(v, m)
285
286 local bv = Hex2Bin(v)
287 local bm = Hex2Bin(m)
288
289 local i = 0
290 local s = ""
291
292 while (string.len(bv) < 32) do
293 bv = "0000"..bv
294 end
295
296 while (string.len(bm) < 32) do
297 bm = "0000"..bm
298 end
299
300
301 for i = 1, 32 do
302 cv = string.sub(bv, i, i)
303 cm = string.sub(bm, i, i)
304 if cv == "1" then
305 s = s.."1"
306 elseif cm == "1" then
307 s = s.."1"
308 else
309 s = s.."0"
310 end
311 end
312
313 return Bin2Hex(s)
314
315 end
316
317 --- Apply bitmask to value using bitwise Xor.
318 -- This function is big endian and will extend the values to 32 bits.
319 -- @param v String containing hex value to be masked
320 -- @param m String containing hex value of mask
321 -- @return String containing hex value of masked value
322 function BMXOr(v, m)
323
324 local bv = Hex2Bin(v)
325 local bm = Hex2Bin(m)
326
327 local i = 0
328 local s = ""
329
330 while (string.len(bv) < 32) do
331 bv = "0000"..bv
332 end
333
334 while (string.len(bm) < 32) do
335 bm = "0000"..bm
336 end
337
338
339 for i = 1, 32 do
340 cv = string.sub(bv, i, i)
341 cm = string.sub(bm, i, i)
342 if cv == "1" then
343 if cm == "0" then
344 s = s.."1"
345 else
346 s = s.."0"
347 end
348 elseif cm == "1" then
349 if cv == "0" then
350 s = s.."1"
351 else
352 s = s.."0"
353 end
354 else
355 -- cv and cm == "0"
356 s = s.."0"
357 end
358 end
359
360 return Bin2Hex(s)
361
362 end
363
364 --- Apply bitmask to value using bitwise Not.
365 -- This function is big endian and will extend the values to 32 bits.
366 -- @param v String containing hex value to be masked
367 -- @param m String containing hex value of mask
368 -- @return String containing hex value of masked value
369 function BMNot(v, m)
370
371 local bv = Hex2Bin(v)
372 local bm = Hex2Bin(m)
373
374 local i = 0
375 local s = ""
376
377 while (string.len(bv) < 32) do
378 bv = "0000"..bv
379 end
380
381 while (string.len(bm) < 32) do
382 bm = "0000"..bm
383 end
384
385
386 for i = 1, 32 do
387 cv = string.sub(bv, i, i)
388 cm = string.sub(bm, i, i)
389 if cm == "1" then
390 if cv == "1" then
391 -- turn off
392 s = s.."0"
393 else
394 -- turn on
395 s = s.."1"
396 end
397 else
398 -- leave untouched
399 s = s..cv
400
401 end
402 end
403
404 return Bin2Hex(s)
405
406 end
407
408
409 --- Perform righthand bit shifting on value.
410 -- This function pads the shifted value with zeroes and will extend to 32 bits.
411 -- @param v String containing hex value to be shifted
412 -- @param nb Number of bits to shift right
413 -- @return String containing hex value of shifted value
414 function BShRight(v, nb)
415
416 local s = Hex2Bin(v)
417
418 while (string.len(s) < 32) do
419 s = "0000"..s
420 end
421
422 s = string.sub(s, 1, 32 - nb)
423
424 while (string.len(s) < 32) do
425 s = "0"..s
426 end
427
428 return Bin2Hex(s)
429
430 end
431
432 --- Perform lefthand bit shifting on value.
433 -- This function pads the shifted value with zeroes and extend to 32 bits.
434 -- @param v String containing hex value to be shifted
435 -- @param nb Number of bits to shift left
436 -- @return String containing hex value of shifted value
437 function BShLeft(v, nb)
438
439 local s = Hex2Bin(v)
440
441 while (string.len(s) < 32) do
442 s = "0000"..s
443 end
444
445 s = string.sub(s, nb + 1, 32)
446
447 while (string.len(s) < 32) do
448 s = s.."0"
449 end
450
451 return Bin2Hex(s)
452
453 end