Home | History | Annotate | Download | only in src
      1 /*
      2 ** $Id: lbitlib.c,v 1.18 2013/03/19 13:19:12 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   r = (r << i) | (r >> (LUA_NBITS - i));
    133   lua_pushunsigned(L, trim(r));
    134   return 1;
    135 }
    136 
    137 
    138 static int b_lrot (lua_State *L) {
    139   return b_rot(L, luaL_checkint(L, 2));
    140 }
    141 
    142 
    143 static int b_rrot (lua_State *L) {
    144   return b_rot(L, -luaL_checkint(L, 2));
    145 }
    146 
    147 
    148 /*
    149 ** get field and width arguments for field-manipulation functions,
    150 ** checking whether they are valid.
    151 ** ('luaL_error' called without 'return' to avoid later warnings about
    152 ** 'width' being used uninitialized.)
    153 */
    154 static int fieldargs (lua_State *L, int farg, int *width) {
    155   int f = luaL_checkint(L, farg);
    156   int w = luaL_optint(L, farg + 1, 1);
    157   luaL_argcheck(L, 0 <= f, farg, "field cannot be negative");
    158   luaL_argcheck(L, 0 < w, farg + 1, "width must be positive");
    159   if (f + w > LUA_NBITS)
    160     luaL_error(L, "trying to access non-existent bits");
    161   *width = w;
    162   return f;
    163 }
    164 
    165 
    166 static int b_extract (lua_State *L) {
    167   int w;
    168   b_uint r = luaL_checkunsigned(L, 1);
    169   int f = fieldargs(L, 2, &w);
    170   r = (r >> f) & mask(w);
    171   lua_pushunsigned(L, r);
    172   return 1;
    173 }
    174 
    175 
    176 static int b_replace (lua_State *L) {
    177   int w;
    178   b_uint r = luaL_checkunsigned(L, 1);
    179   b_uint v = luaL_checkunsigned(L, 2);
    180   int f = fieldargs(L, 3, &w);
    181   int m = mask(w);
    182   v &= m;  /* erase bits outside given width */
    183   r = (r & ~(m << f)) | (v << f);
    184   lua_pushunsigned(L, r);
    185   return 1;
    186 }
    187 
    188 
    189 static const luaL_Reg bitlib[] = {
    190   {"arshift", b_arshift},
    191   {"band", b_and},
    192   {"bnot", b_not},
    193   {"bor", b_or},
    194   {"bxor", b_xor},
    195   {"btest", b_test},
    196   {"extract", b_extract},
    197   {"lrotate", b_lrot},
    198   {"lshift", b_lshift},
    199   {"replace", b_replace},
    200   {"rrotate", b_rrot},
    201   {"rshift", b_rshift},
    202   {NULL, NULL}
    203 };
    204 
    205 
    206 
    207 LUAMOD_API int luaopen_bit32 (lua_State *L) {
    208   luaL_newlib(L, bitlib);
    209   return 1;
    210 }
    211 
    212