| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326 |
- using Lua.Standard.Internal;
- namespace Lua.Standard;
- public sealed class BitwiseLibrary
- {
- public static readonly BitwiseLibrary Instance = new();
- public BitwiseLibrary()
- {
- var libraryName = "bit32";
- Functions =
- [
- new(libraryName, "arshift", ArShift),
- new(libraryName, "band", BAnd),
- new(libraryName, "bnot", BNot),
- new(libraryName, "bor", BOr),
- new(libraryName, "btest", BTest),
- new(libraryName, "bxor", BXor),
- new(libraryName, "extract", Extract),
- new(libraryName, "lrotate", LRotate),
- new(libraryName, "lshift", LShift),
- new(libraryName, "replace", Replace),
- new(libraryName, "rrotate", RRotate),
- new(libraryName, "rshift", RShift)
- ];
- }
- public readonly LibraryFunction[] Functions;
- public ValueTask<int> ArShift(LuaFunctionExecutionContext context, CancellationToken cancellationToken)
- {
- var x = context.GetArgument<double>(0);
- var disp = context.GetArgument<double>(1);
- LuaRuntimeException.ThrowBadArgumentIfNumberIsNotInteger(context.Thread, 1, x);
- LuaRuntimeException.ThrowBadArgumentIfNumberIsNotInteger(context.Thread, 2, disp);
- var v = Bit32Helper.ToInt32(x);
- var a = (int)disp;
- if (a < 0)
- {
- v <<= -a;
- }
- else
- {
- v >>= a;
- }
- return new(context.Return((uint)v));
- }
- public ValueTask<int> BAnd(LuaFunctionExecutionContext context, CancellationToken cancellationToken)
- {
- if (context.ArgumentCount == 0)
- {
- context.Return(uint.MaxValue);
- return default;
- }
- var arg0 = context.GetArgument<double>(0);
- LuaRuntimeException.ThrowBadArgumentIfNumberIsNotInteger(context.Thread, 1, arg0);
- var value = Bit32Helper.ToUInt32(arg0);
- for (var i = 1; i < context.ArgumentCount; i++)
- {
- var arg = context.GetArgument<double>(i);
- LuaRuntimeException.ThrowBadArgumentIfNumberIsNotInteger(context.Thread, 1 + i, arg);
- var v = Bit32Helper.ToUInt32(arg);
- value &= v;
- }
- return new(context.Return(value));
- }
- public ValueTask<int> BNot(LuaFunctionExecutionContext context, CancellationToken cancellationToken)
- {
- var arg0 = context.GetArgument<double>(0);
- LuaRuntimeException.ThrowBadArgumentIfNumberIsNotInteger(context.Thread, 1, arg0);
- var value = Bit32Helper.ToUInt32(arg0);
- return new(context.Return(~value));
- }
- public ValueTask<int> BOr(LuaFunctionExecutionContext context, CancellationToken cancellationToken)
- {
- if (context.ArgumentCount == 0)
- {
- return new(context.Return(0));
- }
- var arg0 = context.GetArgument<double>(0);
- LuaRuntimeException.ThrowBadArgumentIfNumberIsNotInteger(context.Thread, 1, arg0);
- var value = Bit32Helper.ToUInt32(arg0);
- for (var i = 1; i < context.ArgumentCount; i++)
- {
- var arg = context.GetArgument<double>(i);
- LuaRuntimeException.ThrowBadArgumentIfNumberIsNotInteger(context.Thread, 1 + i, arg);
- var v = Bit32Helper.ToUInt32(arg);
- value |= v;
- }
- return new(context.Return(value));
- }
- public ValueTask<int> BTest(LuaFunctionExecutionContext context, CancellationToken cancellationToken)
- {
- if (context.ArgumentCount == 0)
- {
- ;
- return new(context.Return(true));
- }
- var arg0 = context.GetArgument<double>(0);
- LuaRuntimeException.ThrowBadArgumentIfNumberIsNotInteger(context.Thread, 1, arg0);
- var value = Bit32Helper.ToUInt32(arg0);
- for (var i = 1; i < context.ArgumentCount; i++)
- {
- var arg = context.GetArgument<double>(i);
- LuaRuntimeException.ThrowBadArgumentIfNumberIsNotInteger(context.Thread, 1 + i, arg);
- var v = Bit32Helper.ToUInt32(arg);
- value &= v;
- }
- return new(context.Return(value != 0));
- }
- public ValueTask<int> BXor(LuaFunctionExecutionContext context, CancellationToken cancellationToken)
- {
- if (context.ArgumentCount == 0)
- {
- return new(context.Return(0));
- }
- var arg0 = context.GetArgument<double>(0);
- LuaRuntimeException.ThrowBadArgumentIfNumberIsNotInteger(context.Thread, 1, arg0);
- var value = Bit32Helper.ToUInt32(arg0);
- for (var i = 1; i < context.ArgumentCount; i++)
- {
- var arg = context.GetArgument<double>(i);
- LuaRuntimeException.ThrowBadArgumentIfNumberIsNotInteger(context.Thread, 1 + i, arg);
- var v = Bit32Helper.ToUInt32(arg);
- value ^= v;
- }
- return new(context.Return(value));
- }
- public ValueTask<int> Extract(LuaFunctionExecutionContext context, CancellationToken cancellationToken)
- {
- var arg0 = context.GetArgument<double>(0);
- var arg1 = context.GetArgument<double>(1);
- var arg2 = context.HasArgument(2)
- ? context.GetArgument<double>(2)
- : 1;
- LuaRuntimeException.ThrowBadArgumentIfNumberIsNotInteger(context.Thread, 1, arg0);
- LuaRuntimeException.ThrowBadArgumentIfNumberIsNotInteger(context.Thread, 2, arg1);
- LuaRuntimeException.ThrowBadArgumentIfNumberIsNotInteger(context.Thread, 3, arg2);
- var n = Bit32Helper.ToUInt32(arg0);
- var field = (int)arg1;
- var width = (int)arg2;
- Bit32Helper.ValidateFieldAndWidth(context.Thread, "extract", 2, field, width);
- if (field == 0 && width == 32)
- {
- return new(context.Return(n));
- }
- else
- {
- var mask = (uint)((1 << width) - 1);
- return new(context.Return((n >> field) & mask));
- }
- }
- public ValueTask<int> LRotate(LuaFunctionExecutionContext context, CancellationToken cancellationToken)
- {
- var x = context.GetArgument<double>(0);
- var disp = context.GetArgument<double>(1);
- LuaRuntimeException.ThrowBadArgumentIfNumberIsNotInteger(context.Thread, 1, x);
- LuaRuntimeException.ThrowBadArgumentIfNumberIsNotInteger(context.Thread, 2, disp);
- var v = Bit32Helper.ToUInt32(x);
- var a = (int)disp % 32;
- if (a < 0)
- {
- v = (v >> -a) | (v << (32 + a));
- }
- else
- {
- v = (v << a) | (v >> (32 - a));
- }
- ;
- return new(context.Return(v));
- }
- public ValueTask<int> LShift(LuaFunctionExecutionContext context, CancellationToken cancellationToken)
- {
- var x = context.GetArgument<double>(0);
- var disp = context.GetArgument<double>(1);
- LuaRuntimeException.ThrowBadArgumentIfNumberIsNotInteger(context.Thread, 1, x);
- LuaRuntimeException.ThrowBadArgumentIfNumberIsNotInteger(context.Thread, 2, disp);
- var v = Bit32Helper.ToUInt32(x);
- var a = (int)disp;
- if (Math.Abs(a) >= 32)
- {
- v = 0;
- }
- else if (a < 0)
- {
- v >>= -a;
- }
- else
- {
- v <<= a;
- }
- return new(context.Return(v));
- }
- public ValueTask<int> Replace(LuaFunctionExecutionContext context, CancellationToken cancellationToken)
- {
- var arg0 = context.GetArgument<double>(0);
- var arg1 = context.GetArgument<double>(1);
- var arg2 = context.GetArgument<double>(2);
- var arg3 = context.HasArgument(3)
- ? context.GetArgument<double>(3)
- : 1;
- LuaRuntimeException.ThrowBadArgumentIfNumberIsNotInteger(context.Thread, 1, arg0);
- LuaRuntimeException.ThrowBadArgumentIfNumberIsNotInteger(context.Thread, 2, arg1);
- LuaRuntimeException.ThrowBadArgumentIfNumberIsNotInteger(context.Thread, 3, arg2);
- LuaRuntimeException.ThrowBadArgumentIfNumberIsNotInteger(context.Thread, 4, arg3);
- var n = Bit32Helper.ToUInt32(arg0);
- var v = Bit32Helper.ToUInt32(arg1);
- var field = (int)arg2;
- var width = (int)arg3;
- Bit32Helper.ValidateFieldAndWidth(context.Thread, "replace", 2, field, width);
- uint mask;
- if (width == 32)
- {
- mask = 0xFFFFFFFF;
- }
- else
- {
- mask = (uint)((1 << width) - 1);
- }
- v = v & mask;
- n = (n & ~(mask << field)) | (v << field);
- return new(context.Return(n));
- }
- public ValueTask<int> RRotate(LuaFunctionExecutionContext context, CancellationToken cancellationToken)
- {
- var x = context.GetArgument<double>(0);
- var disp = context.GetArgument<double>(1);
- LuaRuntimeException.ThrowBadArgumentIfNumberIsNotInteger(context.Thread, 1, x);
- LuaRuntimeException.ThrowBadArgumentIfNumberIsNotInteger(context.Thread, 2, disp);
- var v = Bit32Helper.ToUInt32(x);
- var a = (int)disp % 32;
- if (a < 0)
- {
- v = (v << -a) | (v >> (32 + a));
- }
- else
- {
- v = (v >> a) | (v << (32 - a));
- }
- return new(context.Return(v));
- }
- public ValueTask<int> RShift(LuaFunctionExecutionContext context, CancellationToken cancellationToken)
- {
- var x = context.GetArgument<double>(0);
- var disp = context.GetArgument<double>(1);
- LuaRuntimeException.ThrowBadArgumentIfNumberIsNotInteger(context.Thread, 1, x);
- LuaRuntimeException.ThrowBadArgumentIfNumberIsNotInteger(context.Thread, 2, disp);
- var v = Bit32Helper.ToUInt32(x);
- var a = (int)disp;
- if (Math.Abs(a) >= 32)
- {
- v = 0;
- }
- else if (a < 0)
- {
- v <<= -a;
- }
- else
- {
- v >>= a;
- }
- return new(context.Return(v));
- }
- }
|