source: trunk/src/lua/lbitlib.c @ 2542

Last change on this file since 2542 was 2542, checked in by sam, 10 years ago

lua: compilation fixes for non-quite-POSIX platforms.

File size: 4.2 KB
Line 
1/*
2** $Id: lbitlib.c,v 1.16 2011/06/20 16:35:23 roberto Exp $
3** Standard library for bitwise operations
4** See Copyright Notice in lua.h
5*/
6
7#if defined HAVE_CONFIG_H // LOL BEGIN
8#   include "config.h"
9#endif // LOL END
10
11#define lbitlib_c
12#define LUA_LIB
13
14#include "lua.h"
15
16#include "lauxlib.h"
17#include "lualib.h"
18
19
20/* number of bits to consider in a number */
21#if !defined(LUA_NBITS)
22#define LUA_NBITS       32
23#endif
24
25
26#define ALLONES         (~(((~(lua_Unsigned)0) << (LUA_NBITS - 1)) << 1))
27
28/* macro to trim extra bits */
29#define trim(x)         ((x) & ALLONES)
30
31
32/* builds a number with 'n' ones (1 <= n <= LUA_NBITS) */
33#define mask(n)         (~((ALLONES << 1) << ((n) - 1)))
34
35
36typedef lua_Unsigned b_uint;
37
38
39
40static b_uint andaux (lua_State *L) {
41  int i, n = lua_gettop(L);
42  b_uint r = ~(b_uint)0;
43  for (i = 1; i <= n; i++)
44    r &= luaL_checkunsigned(L, i);
45  return trim(r);
46}
47
48
49static int b_and (lua_State *L) {
50  b_uint r = andaux(L);
51  lua_pushunsigned(L, r);
52  return 1;
53}
54
55
56static int b_test (lua_State *L) {
57  b_uint r = andaux(L);
58  lua_pushboolean(L, r != 0);
59  return 1;
60}
61
62
63static int b_or (lua_State *L) {
64  int i, n = lua_gettop(L);
65  b_uint r = 0;
66  for (i = 1; i <= n; i++)
67    r |= luaL_checkunsigned(L, i);
68  lua_pushunsigned(L, trim(r));
69  return 1;
70}
71
72
73static int b_xor (lua_State *L) {
74  int i, n = lua_gettop(L);
75  b_uint r = 0;
76  for (i = 1; i <= n; i++)
77    r ^= luaL_checkunsigned(L, i);
78  lua_pushunsigned(L, trim(r));
79  return 1;
80}
81
82
83static int b_not (lua_State *L) {
84  b_uint r = ~luaL_checkunsigned(L, 1);
85  lua_pushunsigned(L, trim(r));
86  return 1;
87}
88
89
90static int b_shift (lua_State *L, b_uint r, int i) {
91  if (i < 0) {  /* shift right? */
92    i = -i;
93    r = trim(r);
94    if (i >= LUA_NBITS) r = 0;
95    else r >>= i;
96  }
97  else {  /* shift left */
98    if (i >= LUA_NBITS) r = 0;
99    else r <<= i;
100    r = trim(r);
101  }
102  lua_pushunsigned(L, r);
103  return 1;
104}
105
106
107static int b_lshift (lua_State *L) {
108  return b_shift(L, luaL_checkunsigned(L, 1), luaL_checkint(L, 2));
109}
110
111
112static int b_rshift (lua_State *L) {
113  return b_shift(L, luaL_checkunsigned(L, 1), -luaL_checkint(L, 2));
114}
115
116
117static int b_arshift (lua_State *L) {
118  b_uint r = luaL_checkunsigned(L, 1);
119  int i = luaL_checkint(L, 2);
120  if (i < 0 || !(r & ((b_uint)1 << (LUA_NBITS - 1))))
121    return b_shift(L, r, -i);
122  else {  /* arithmetic shift for 'negative' number */
123    if (i >= LUA_NBITS) r = ALLONES;
124    else
125      r = trim((r >> i) | ~(~(b_uint)0 >> i));  /* add signal bit */
126    lua_pushunsigned(L, r);
127    return 1;
128  }
129}
130
131
132static int b_rot (lua_State *L, int i) {
133  b_uint r = luaL_checkunsigned(L, 1);
134  i &= (LUA_NBITS - 1);  /* i = i % NBITS */
135  r = trim(r);
136  r = (r << i) | (r >> (LUA_NBITS - i));
137  lua_pushunsigned(L, trim(r));
138  return 1;
139}
140
141
142static int b_lrot (lua_State *L) {
143  return b_rot(L, luaL_checkint(L, 2));
144}
145
146
147static int b_rrot (lua_State *L) {
148  return b_rot(L, -luaL_checkint(L, 2));
149}
150
151
152/*
153** get field and width arguments for field-manipulation functions,
154** checking whether they are valid
155*/
156static int fieldargs (lua_State *L, int farg, int *width) {
157  int f = luaL_checkint(L, farg);
158  int w = luaL_optint(L, farg + 1, 1);
159  luaL_argcheck(L, 0 <= f, farg, "field cannot be negative");
160  luaL_argcheck(L, 0 < w, farg + 1, "width must be positive");
161  if (f + w > LUA_NBITS)
162    luaL_error(L, "trying to access non-existent bits");
163  *width = w;
164  return f;
165}
166
167
168static int b_extract (lua_State *L) {
169  int w;
170  b_uint r = luaL_checkunsigned(L, 1);
171  int f = fieldargs(L, 2, &w);
172  r = (r >> f) & mask(w);
173  lua_pushunsigned(L, r);
174  return 1;
175}
176
177
178static int b_replace (lua_State *L) {
179  int w;
180  b_uint r = luaL_checkunsigned(L, 1);
181  b_uint v = luaL_checkunsigned(L, 2);
182  int f = fieldargs(L, 3, &w);
183  int m = mask(w);
184  v &= m;  /* erase bits outside given width */
185  r = (r & ~(m << f)) | (v << f);
186  lua_pushunsigned(L, r);
187  return 1;
188}
189
190
191static const luaL_Reg bitlib[] = {
192  {"arshift", b_arshift},
193  {"band", b_and},
194  {"bnot", b_not},
195  {"bor", b_or},
196  {"bxor", b_xor},
197  {"btest", b_test},
198  {"extract", b_extract},
199  {"lrotate", b_lrot},
200  {"lshift", b_lshift},
201  {"replace", b_replace},
202  {"rrotate", b_rrot},
203  {"rshift", b_rshift},
204  {NULL, NULL}
205};
206
207
208
209LUAMOD_API int luaopen_bit32 (lua_State *L) {
210  luaL_newlib(L, bitlib);
211  return 1;
212}
213
Note: See TracBrowser for help on using the repository browser.