Skip to content

Commit

Permalink
Add bit32 library
Browse files Browse the repository at this point in the history
  • Loading branch information
siffiejoe committed Jul 8, 2020
1 parent 931652a commit 7e2b0b5
Show file tree
Hide file tree
Showing 4 changed files with 298 additions and 0 deletions.
233 changes: 233 additions & 0 deletions lbitlib.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,233 @@
/*
** $Id: lbitlib.c,v 1.30.1.1 2017/04/19 17:20:42 roberto Exp $
** Standard library for bitwise operations
** See Copyright Notice in lua.h
*/

#define lbitlib_c
#define LUA_LIB

#include "lprefix.h"


#include "lua.h"

#include "lauxlib.h"
#include "lualib.h"


#if defined(LUA_COMPAT_BITLIB) /* { */


#define pushunsigned(L,n) lua_pushinteger(L, (lua_Integer)(n))
#define checkunsigned(L,i) ((lua_Unsigned)luaL_checkinteger(L,i))


/* number of bits to consider in a number */
#if !defined(LUA_NBITS)
#define LUA_NBITS 32
#endif


/*
** a lua_Unsigned with its first LUA_NBITS bits equal to 1. (Shift must
** be made in two parts to avoid problems when LUA_NBITS is equal to the
** number of bits in a lua_Unsigned.)
*/
#define ALLONES (~(((~(lua_Unsigned)0) << (LUA_NBITS - 1)) << 1))


/* macro to trim extra bits */
#define trim(x) ((x) & ALLONES)


/* builds a number with 'n' ones (1 <= n <= LUA_NBITS) */
#define mask(n) (~((ALLONES << 1) << ((n) - 1)))



static lua_Unsigned andaux (lua_State *L) {
int i, n = lua_gettop(L);
lua_Unsigned r = ~(lua_Unsigned)0;
for (i = 1; i <= n; i++)
r &= checkunsigned(L, i);
return trim(r);
}


static int b_and (lua_State *L) {
lua_Unsigned r = andaux(L);
pushunsigned(L, r);
return 1;
}


static int b_test (lua_State *L) {
lua_Unsigned r = andaux(L);
lua_pushboolean(L, r != 0);
return 1;
}


static int b_or (lua_State *L) {
int i, n = lua_gettop(L);
lua_Unsigned r = 0;
for (i = 1; i <= n; i++)
r |= checkunsigned(L, i);
pushunsigned(L, trim(r));
return 1;
}


static int b_xor (lua_State *L) {
int i, n = lua_gettop(L);
lua_Unsigned r = 0;
for (i = 1; i <= n; i++)
r ^= checkunsigned(L, i);
pushunsigned(L, trim(r));
return 1;
}


static int b_not (lua_State *L) {
lua_Unsigned r = ~checkunsigned(L, 1);
pushunsigned(L, trim(r));
return 1;
}


static int b_shift (lua_State *L, lua_Unsigned r, lua_Integer i) {
if (i < 0) { /* shift right? */
i = -i;
r = trim(r);
if (i >= LUA_NBITS) r = 0;
else r >>= i;
}
else { /* shift left */
if (i >= LUA_NBITS) r = 0;
else r <<= i;
r = trim(r);
}
pushunsigned(L, r);
return 1;
}


static int b_lshift (lua_State *L) {
return b_shift(L, checkunsigned(L, 1), luaL_checkinteger(L, 2));
}


static int b_rshift (lua_State *L) {
return b_shift(L, checkunsigned(L, 1), -luaL_checkinteger(L, 2));
}


static int b_arshift (lua_State *L) {
lua_Unsigned r = checkunsigned(L, 1);
lua_Integer i = luaL_checkinteger(L, 2);
if (i < 0 || !(r & ((lua_Unsigned)1 << (LUA_NBITS - 1))))
return b_shift(L, r, -i);
else { /* arithmetic shift for 'negative' number */
if (i >= LUA_NBITS) r = ALLONES;
else
r = trim((r >> i) | ~(trim(~(lua_Unsigned)0) >> i)); /* add signal bit */
pushunsigned(L, r);
return 1;
}
}


static int b_rot (lua_State *L, lua_Integer d) {
lua_Unsigned r = checkunsigned(L, 1);
int i = d & (LUA_NBITS - 1); /* i = d % NBITS */
r = trim(r);
if (i != 0) /* avoid undefined shift of LUA_NBITS when i == 0 */
r = (r << i) | (r >> (LUA_NBITS - i));
pushunsigned(L, trim(r));
return 1;
}


static int b_lrot (lua_State *L) {
return b_rot(L, luaL_checkinteger(L, 2));
}


static int b_rrot (lua_State *L) {
return b_rot(L, -luaL_checkinteger(L, 2));
}


/*
** get field and width arguments for field-manipulation functions,
** checking whether they are valid.
** ('luaL_error' called without 'return' to avoid later warnings about
** 'width' being used uninitialized.)
*/
static int fieldargs (lua_State *L, int farg, int *width) {
lua_Integer f = luaL_checkinteger(L, farg);
lua_Integer w = luaL_optinteger(L, farg + 1, 1);
luaL_argcheck(L, 0 <= f, farg, "field cannot be negative");
luaL_argcheck(L, 0 < w, farg + 1, "width must be positive");
if (f + w > LUA_NBITS)
luaL_error(L, "trying to access non-existent bits");
*width = (int)w;
return (int)f;
}


static int b_extract (lua_State *L) {
int w;
lua_Unsigned r = trim(checkunsigned(L, 1));
int f = fieldargs(L, 2, &w);
r = (r >> f) & mask(w);
pushunsigned(L, r);
return 1;
}


static int b_replace (lua_State *L) {
int w;
lua_Unsigned r = trim(checkunsigned(L, 1));
lua_Unsigned v = trim(checkunsigned(L, 2));
int f = fieldargs(L, 3, &w);
lua_Unsigned m = mask(w);
r = (r & ~(m << f)) | ((v & m) << f);
pushunsigned(L, r);
return 1;
}


static const luaL_Reg bitlib[] = {
{"arshift", b_arshift},
{"band", b_and},
{"bnot", b_not},
{"bor", b_or},
{"bxor", b_xor},
{"btest", b_test},
{"extract", b_extract},
{"lrotate", b_lrot},
{"lshift", b_lshift},
{"replace", b_replace},
{"rrotate", b_rrot},
{"rshift", b_rshift},
{NULL, NULL}
};



LUAMOD_API int luaopen_bit32 (lua_State *L) {
luaL_newlib(L, bitlib);
return 1;
}


#else /* }{ */


LUAMOD_API int luaopen_bit32 (lua_State *L) {
return luaL_error(L, "library 'bit32' has been deprecated");
}

#endif /* } */
28 changes: 28 additions & 0 deletions rockspecs/bit32-5.3.5-1.rockspec
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package = "bit32"
version = "5.3.5-1"
source = {
url = "git://github.com/keplerproject/lua-compat-5.3/archive/v0.9.zip",
dir = "lua-compat-5.3-0.9",
}
description = {
summary = "Lua 5.2 bit manipulation library",
detailed = [[
bit32 is the native Lua 5.2 bit manipulation library, in the version
from Lua 5.3; it is compatible with Lua 5.1, 5.2 and 5.3.
]],
homepage = "http://www.lua.org/manual/5.2/manual.html#6.7",
license = "MIT"
}
dependencies = {
"lua >= 5.1, < 5.5"
}
build = {
type = "builtin",
modules = {
bit32 = {
sources = { "lbitlib.c" },
defines = { "LUA_COMPAT_BITLIB" },
incdirs = { "c-api" },
}
}
}
28 changes: 28 additions & 0 deletions rockspecs/bit32-scm-1.rockspec
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package = "bit32"
version = "scm-1"
source = {
url = "https://github.com/keplerproject/lua-compat-5.3/archive/master.zip",
branch = "lua-compat-5.3-master",
}
description = {
summary = "Lua 5.2 bit manipulation library",
detailed = [[
bit32 is the native Lua 5.2 bit manipulation library, in the version
from Lua 5.3; it is compatible with Lua 5.1, 5.2 and 5.3.
]],
homepage = "http://www.lua.org/manual/5.2/manual.html#6.7",
license = "MIT"
}
dependencies = {
"lua >= 5.1, < 5.5"
}
build = {
type = "builtin",
modules = {
bit32 = {
sources = { "lbitlib.c" },
defines = { "LUA_COMPAT_BITLIB" },
incdirs = { "c-api" },
}
}
}
9 changes: 9 additions & 0 deletions tests/test-bit32.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#!/usr/bin/env lua

local bit32 = require("bit32")


assert(bit32.bnot(0) == 2^32-1)
assert(bit32.band(1, 3, 5) == 1)
assert(bit32.bor(1, 3, 5) == 7)

0 comments on commit 7e2b0b5

Please sign in to comment.