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