Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  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. #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. */
  152. static int fieldargs (lua_State *L, int farg, int *width) {
  153.   int f = luaL_checkint(L, farg);
  154.   int w = luaL_optint(L, farg + 1, 1);
  155.   luaL_argcheck(L, 0 <= f, farg, "field cannot be negative");
  156.   luaL_argcheck(L, 0 < w, farg + 1, "width must be positive");
  157.   if (f + w > LUA_NBITS)
  158.     luaL_error(L, "trying to access non-existent bits");
  159.   *width = w;
  160.   return f;
  161. }
  162.  
  163.  
  164. static int b_extract (lua_State *L) {
  165.   int w;
  166.   b_uint r = luaL_checkunsigned(L, 1);
  167.   int f = fieldargs(L, 2, &w);
  168.   r = (r >> f) & mask(w);
  169.   lua_pushunsigned(L, r);
  170.   return 1;
  171. }
  172.  
  173.  
  174. static int b_replace (lua_State *L) {
  175.   int w;
  176.   b_uint r = luaL_checkunsigned(L, 1);
  177.   b_uint v = luaL_checkunsigned(L, 2);
  178.   int f = fieldargs(L, 3, &w);
  179.   int m = mask(w);
  180.   v &= m;  /* erase bits outside given width */
  181.   r = (r & ~(m << f)) | (v << f);
  182.   lua_pushunsigned(L, r);
  183.   return 1;
  184. }
  185.  
  186.  
  187. static const luaL_Reg bitlib[] = {
  188.   {"arshift", b_arshift},
  189.   {"band", b_and},
  190.   {"bnot", b_not},
  191.   {"bor", b_or},
  192.   {"bxor", b_xor},
  193.   {"btest", b_test},
  194.   {"extract", b_extract},
  195.   {"lrotate", b_lrot},
  196.   {"lshift", b_lshift},
  197.   {"replace", b_replace},
  198.   {"rrotate", b_rrot},
  199.   {"rshift", b_rshift},
  200.   {NULL, NULL}
  201. };
  202.  
  203.  
  204.  
  205. LUAMOD_API int luaopen_bit32 (lua_State *L) {
  206.   luaL_newlib(L, bitlib);
  207.   return 1;
  208. }
  209.  
  210.