| 1 |
/* |
|---|
| 2 |
** Lua BitOp -- a bit operations library for Lua 5.1. |
|---|
| 3 |
** http://bitop.luajit.org/ |
|---|
| 4 |
** |
|---|
| 5 |
** Copyright (C) 2008-2009 Mike Pall. All rights reserved. |
|---|
| 6 |
** |
|---|
| 7 |
** Permission is hereby granted, free of charge, to any person obtaining |
|---|
| 8 |
** a copy of this software and associated documentation files (the |
|---|
| 9 |
** "Software"), to deal in the Software without restriction, including |
|---|
| 10 |
** without limitation the rights to use, copy, modify, merge, publish, |
|---|
| 11 |
** distribute, sublicense, and/or sell copies of the Software, and to |
|---|
| 12 |
** permit persons to whom the Software is furnished to do so, subject to |
|---|
| 13 |
** the following conditions: |
|---|
| 14 |
** |
|---|
| 15 |
** The above copyright notice and this permission notice shall be |
|---|
| 16 |
** included in all copies or substantial portions of the Software. |
|---|
| 17 |
** |
|---|
| 18 |
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
|---|
| 19 |
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
|---|
| 20 |
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. |
|---|
| 21 |
** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY |
|---|
| 22 |
** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, |
|---|
| 23 |
** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE |
|---|
| 24 |
** SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
|---|
| 25 |
** |
|---|
| 26 |
** [ MIT license: http://www.opensource.org/licenses/mit-license.php ] |
|---|
| 27 |
*/ |
|---|
| 28 |
|
|---|
| 29 |
#define LUA_BITOP_VERSION "1.0.1" |
|---|
| 30 |
|
|---|
| 31 |
#define LUA_LIB |
|---|
| 32 |
#define LUA_COMPAT_MODULE |
|---|
| 33 |
#include "lua.h" |
|---|
| 34 |
#include "lauxlib.h" |
|---|
| 35 |
|
|---|
| 36 |
#ifdef _MSC_VER |
|---|
| 37 |
/* MSVC is stuck in the last century and doesn't have C99's stdint.h. */ |
|---|
| 38 |
typedef __int32 int32_t; |
|---|
| 39 |
typedef unsigned __int32 uint32_t; |
|---|
| 40 |
typedef unsigned __int64 uint64_t; |
|---|
| 41 |
#else |
|---|
| 42 |
#include <stdint.h> |
|---|
| 43 |
#endif |
|---|
| 44 |
|
|---|
| 45 |
typedef int32_t SBits; |
|---|
| 46 |
typedef uint32_t UBits; |
|---|
| 47 |
|
|---|
| 48 |
typedef union { |
|---|
| 49 |
lua_Number n; |
|---|
| 50 |
#ifdef LUA_NUMBER_DOUBLE |
|---|
| 51 |
uint64_t b; |
|---|
| 52 |
#else |
|---|
| 53 |
UBits b; |
|---|
| 54 |
#endif |
|---|
| 55 |
} BitNum; |
|---|
| 56 |
|
|---|
| 57 |
/* Convert argument to bit type. */ |
|---|
| 58 |
static UBits barg(lua_State *L, int idx) |
|---|
| 59 |
{ |
|---|
| 60 |
BitNum bn; |
|---|
| 61 |
UBits b; |
|---|
| 62 |
bn.n = lua_tonumber(L, idx); |
|---|
| 63 |
#if defined(LUA_NUMBER_DOUBLE) |
|---|
| 64 |
bn.n += 6755399441055744.0; /* 2^52+2^51 */ |
|---|
| 65 |
#ifdef SWAPPED_DOUBLE |
|---|
| 66 |
b = (UBits)(bn.b >> 32); |
|---|
| 67 |
#else |
|---|
| 68 |
b = (UBits)bn.b; |
|---|
| 69 |
#endif |
|---|
| 70 |
#elif defined(LUA_NUMBER_INT) || defined(LUA_NUMBER_LONG) || \ |
|---|
| 71 |
defined(LUA_NUMBER_LONGLONG) || defined(LUA_NUMBER_LONG_LONG) || \ |
|---|
| 72 |
defined(LUA_NUMBER_LLONG) |
|---|
| 73 |
if (sizeof(UBits) == sizeof(lua_Number)) |
|---|
| 74 |
b = bn.b; |
|---|
| 75 |
else |
|---|
| 76 |
b = (UBits)(SBits)bn.n; |
|---|
| 77 |
#elif defined(LUA_NUMBER_FLOAT) |
|---|
| 78 |
#error "A 'float' lua_Number type is incompatible with this library" |
|---|
| 79 |
#else |
|---|
| 80 |
#error "Unknown number type, check LUA_NUMBER_* in luaconf.h" |
|---|
| 81 |
#endif |
|---|
| 82 |
if (b == 0 && !lua_isnumber(L, idx)) |
|---|
| 83 |
luaL_error(L, "number"); |
|---|
| 84 |
return b; |
|---|
| 85 |
} |
|---|
| 86 |
|
|---|
| 87 |
/* Return bit type. */ |
|---|
| 88 |
#define BRET(b) lua_pushnumber(L, (lua_Number)(SBits)(b)); return 1; |
|---|
| 89 |
|
|---|
| 90 |
static int bit_tobit(lua_State *L) { BRET(barg(L, 1)) } |
|---|
| 91 |
static int bit_bnot(lua_State *L) { BRET(~barg(L, 1)) } |
|---|
| 92 |
|
|---|
| 93 |
#define BIT_OP(func, opr) \ |
|---|
| 94 |
static int func(lua_State *L) { int i; UBits b = barg(L, 1); \ |
|---|
| 95 |
for (i = lua_gettop(L); i > 1; i--) b opr barg(L, i); BRET(b) } |
|---|
| 96 |
BIT_OP(bit_band, &=) |
|---|
| 97 |
BIT_OP(bit_bor, |=) |
|---|
| 98 |
BIT_OP(bit_bxor, ^=) |
|---|
| 99 |
|
|---|
| 100 |
#define bshl(b, n) (b << n) |
|---|
| 101 |
#define bshr(b, n) (b >> n) |
|---|
| 102 |
#define bsar(b, n) ((SBits)b >> n) |
|---|
| 103 |
#define brol(b, n) ((b << n) | (b >> (32-n))) |
|---|
| 104 |
#define bror(b, n) ((b << (32-n)) | (b >> n)) |
|---|
| 105 |
#define BIT_SH(func, fn) \ |
|---|
| 106 |
static int func(lua_State *L) { \ |
|---|
| 107 |
UBits b = barg(L, 1); UBits n = barg(L, 2) & 31; BRET(fn(b, n)) } |
|---|
| 108 |
BIT_SH(bit_lshift, bshl) |
|---|
| 109 |
BIT_SH(bit_rshift, bshr) |
|---|
| 110 |
BIT_SH(bit_arshift, bsar) |
|---|
| 111 |
BIT_SH(bit_rol, brol) |
|---|
| 112 |
BIT_SH(bit_ror, bror) |
|---|
| 113 |
|
|---|
| 114 |
static int bit_bswap(lua_State *L) |
|---|
| 115 |
{ |
|---|
| 116 |
UBits b = barg(L, 1); |
|---|
| 117 |
b = (b >> 24) | ((b >> 8) & 0xff00) | ((b & 0xff00) << 8) | (b << 24); |
|---|
| 118 |
BRET(b) |
|---|
| 119 |
} |
|---|
| 120 |
|
|---|
| 121 |
static int bit_tohex(lua_State *L) |
|---|
| 122 |
{ |
|---|
| 123 |
UBits b = barg(L, 1); |
|---|
| 124 |
SBits n = lua_isnone(L, 2) ? 8 : (SBits)barg(L, 2); |
|---|
| 125 |
const char *hexdigits = "0123456789abcdef"; |
|---|
| 126 |
char buf[8]; |
|---|
| 127 |
int i; |
|---|
| 128 |
if (n < 0) { n = -n; hexdigits = "0123456789ABCDEF"; } |
|---|
| 129 |
if (n > 8) n = 8; |
|---|
| 130 |
for (i = (int)n; --i >= 0; ) { buf[i] = hexdigits[b & 15]; b >>= 4; } |
|---|
| 131 |
lua_pushlstring(L, buf, (size_t)n); |
|---|
| 132 |
return 1; |
|---|
| 133 |
} |
|---|
| 134 |
|
|---|
| 135 |
static const struct luaL_Reg bit_funcs[] = { |
|---|
| 136 |
{ "tobit", bit_tobit }, |
|---|
| 137 |
{ "bnot", bit_bnot }, |
|---|
| 138 |
{ "band", bit_band }, |
|---|
| 139 |
{ "bor", bit_bor }, |
|---|
| 140 |
{ "bxor", bit_bxor }, |
|---|
| 141 |
{ "lshift", bit_lshift }, |
|---|
| 142 |
{ "rshift", bit_rshift }, |
|---|
| 143 |
{ "arshift", bit_arshift }, |
|---|
| 144 |
{ "rol", bit_rol }, |
|---|
| 145 |
{ "ror", bit_ror }, |
|---|
| 146 |
{ "bswap", bit_bswap }, |
|---|
| 147 |
{ "tohex", bit_tohex }, |
|---|
| 148 |
{ NULL, NULL } |
|---|
| 149 |
}; |
|---|
| 150 |
|
|---|
| 151 |
/* Signed right-shifts are implementation-defined per C89/C99. |
|---|
| 152 |
** But the de facto standard are arithmetic right-shifts on two's |
|---|
| 153 |
** complement CPUs. This behaviour is required here, so test for it. |
|---|
| 154 |
*/ |
|---|
| 155 |
#define BAD_SAR (bsar(-8, 2) != (SBits)-2) |
|---|
| 156 |
|
|---|
| 157 |
LUALIB_API int luaopen_bit(lua_State *L) |
|---|
| 158 |
{ |
|---|
| 159 |
UBits b; |
|---|
| 160 |
lua_pushnumber(L, (lua_Number)1437217655L); |
|---|
| 161 |
b = barg(L, -1); |
|---|
| 162 |
if (b != (UBits)1437217655L || BAD_SAR) { /* Perform a simple self-test. */ |
|---|
| 163 |
const char *msg = "compiled with incompatible luaconf.h"; |
|---|
| 164 |
#ifdef LUA_NUMBER_DOUBLE |
|---|
| 165 |
#ifdef _WIN32 |
|---|
| 166 |
if (b == (UBits)1610612736L) |
|---|
| 167 |
msg = "use D3DCREATE_FPU_PRESERVE with DirectX"; |
|---|
| 168 |
#endif |
|---|
| 169 |
if (b == (UBits)1127743488L) |
|---|
| 170 |
msg = "not compiled with SWAPPED_DOUBLE"; |
|---|
| 171 |
#endif |
|---|
| 172 |
if (BAD_SAR) |
|---|
| 173 |
msg = "arithmetic right-shift broken"; |
|---|
| 174 |
luaL_error(L, "bit library self-test failed (%s)", msg); |
|---|
| 175 |
} |
|---|
| 176 |
luaL_openlib(L, "bit", bit_funcs, 0); |
|---|
| 177 |
return 1; |
|---|
| 178 |
} |
|---|
| 179 |
|
|---|