libs/core, libs/uci, libs/web: Fixed several inline documentation typos
[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