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