123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218 |
- /*
- This software is licensed under the zlib license.
- (C) Copyright 2015 Pedro Gimeno Fortea. All rights reserved.
- This software is provided 'as-is', without any express or implied
- warranty. In no event will the author or authors be held liable for any
- damages arising from the use of this software.
- Permission is granted to anyone to use this software for any purpose,
- including commercial applications, and to alter it and redistribute it
- freely, subject to the following restrictions:
- 1. The origin of this software must not be misrepresented; you must not
- claim that you wrote the original software. If you use this software
- in a product, an acknowledgment in the product documentation would be
- appreciated but is not required.
- 2. Altered source versions must be plainly marked as such, and must not be
- misrepresented as being the original software.
- 3. This notice may not be removed or altered from any source distribution.
- */
- #include <lua.h>
- #include <stdlib.h>
- #include <string.h>
- static int bshiftleft(lua_State *L)
- {
- size_t len;
- unsigned char *src, *dst;
- int rot;
- size_t nbytes;
- if (lua_gettop(L) < 2
- || lua_type(L, 1) != LUA_TSTRING
- || lua_type(L, 2) != LUA_TNUMBER
- )
- return 0;
- src = (unsigned char *)lua_tolstring(L, 1, &len);
- dst = malloc(len);
- if (!dst)
- return 0;
- if (!len)
- {
- lua_pushlstring(L, NULL, 0);
- return 1;
- }
- rot = (int)lua_tonumber(L, 2);
- if (rot == 0)
- {
- memcpy(dst, src, len);
- }
- else if (rot < 0)
- {
- rot = -rot;
- /* Shift right */
- nbytes = (unsigned)rot >> 3;
- rot = rot & 7;
- if (nbytes >= len)
- {
- /* Shifted all the way out */
- memset(dst, 0, len);
- }
- else if (rot)
- {
- /* Bit-granular right shift */
- int i;
- unsigned tmp;
- unsigned char *dst2 = dst + nbytes;
- /* at this point 0 <= nbytes < len, so this can't go negative: */
- len -= nbytes;
- tmp = src[0];
- *dst2++ = tmp >> rot;
- i = 1;
- while (i < len)
- {
- tmp = (tmp << 8) | src[i++];
- *dst2++ = tmp >> rot;
- }
- len += nbytes; /* restore original length */
- /* fill leading chunk with zeros, if it exists */
- memset(dst, 0, nbytes);
- }
- else
- {
- /* Byte-aligned right shift */
- memcpy(dst + nbytes, src, len - nbytes);
- memset(dst, 0, nbytes);
- }
- }
- else
- {
- /* Shift left */
- nbytes = (unsigned)rot >> 3;
- rot = rot & 7;
- if (nbytes >= len)
- {
- /* Shifted all the way out */
- memset(dst, 0, len);
- }
- else if (rot)
- {
- /* Bit-granular left shift */
- int i;
- unsigned tmp;
- unsigned char *dst2 = dst;
- rot = 8-rot;
- tmp = src[i = nbytes];
- while (++i < len)
- {
- tmp = (tmp << 8) | src[i];
- *dst2++ = tmp >> rot;
- }
- *dst2++ = tmp << (8 - rot);
- /* fill trailing chunk with zeros, if it exists */
- memset(dst2, 0, nbytes);
- }
- else
- {
- /* Byte-aligned left shift */
- memcpy(dst, src + nbytes, len - nbytes);
- memset(dst + (len - nbytes), 0, nbytes);
- }
- }
- lua_pushlstring(L, (char *)dst, len);
- free(dst);
- return 1;
- }
- #define BINOP(name, op) \
- static int name(lua_State *L) \
- { \
- unsigned char *src1, *src2, *dst, *dst2, *end; \
- size_t len1, len2; \
- \
- if (lua_gettop(L) < 2 \
- || lua_type(L, 1) != LUA_TSTRING \
- || lua_type(L, 2) != LUA_TSTRING \
- ) \
- return 0; \
- \
- src1 = (unsigned char *)lua_tolstring(L, 1, &len1); \
- src2 = (unsigned char *)lua_tolstring(L, 2, &len2); \
- if (len2 < len1) len1 = len2; \
- dst = dst2 = malloc(len1); \
- if (!dst) \
- return 0; \
- \
- end = src1 + len1; \
- while (src1 != end) \
- { \
- *dst2++ = *src1++ op *src2++; \
- } \
- \
- lua_pushlstring(L, (char *)dst, len1); \
- free(dst); \
- return 1; \
- }
- BINOP(band, &)
- BINOP(bor, |)
- BINOP(bxor, ^)
- static int bnot(lua_State *L)
- {
- unsigned char *src, *dst, *end;
- size_t len;
- if (lua_gettop(L) < 1
- || lua_type(L, 1) != LUA_TSTRING
- )
- return 0;
- src = (unsigned char *)lua_tolstring(L, 1, &len);
- dst = malloc(len);
- if (!dst)
- return 0;
- end = src + len;
- while (src != end)
- {
- *dst++ = ~*src++;
- }
- lua_pushlstring(L, (char *)dst-len, len);
- return 1;
- }
- int luaopen_strbit(lua_State *L)
- {
- lua_newtable(L);
- lua_pushcfunction(L, bshiftleft);
- lua_setfield(L, -2, "bshiftleft");
- lua_pushcfunction(L, band);
- lua_setfield(L, -2, "band");
- lua_pushcfunction(L, bor);
- lua_setfield(L, -2, "bor");
- lua_pushcfunction(L, bxor);
- lua_setfield(L, -2, "bxor");
- lua_pushcfunction(L, bnot);
- lua_setfield(L, -2, "bnot");
- return 1;
- }
|