Skip to content

Commit

Permalink
Merge pull request EvilBeaver#538 from dmpas/feature/issue-477-bit-fu…
Browse files Browse the repository at this point in the history
…nctions

Битовые функции
  • Loading branch information
EvilBeaver authored Oct 1, 2017
2 parents fea9b8c + 90d115c commit d0f7b00
Show file tree
Hide file tree
Showing 5 changed files with 326 additions and 4 deletions.
1 change: 0 additions & 1 deletion src/ScriptEngine.HostedScript/HostedScriptEngine.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@ public HostedScriptEngine()

_env.InjectObject(_globalCtx, false);
_engine.Environment = _env;

}

public void InitExternalLibraries(string systemLibrary, IEnumerable<string> searchDirs)
Expand Down
160 changes: 160 additions & 0 deletions src/ScriptEngine.HostedScript/Library/GlobalBitFunctions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
/*----------------------------------------------------------
This Source Code Form is subject to the terms of the
Mozilla Public License, v.2.0. If a copy of the MPL
was not distributed with this file, You can obtain one
at http://mozilla.org/MPL/2.0/.
----------------------------------------------------------*/

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using ScriptEngine.Machine;
using ScriptEngine.Machine.Contexts;

namespace ScriptEngine.HostedScript.Library
{
/// <summary>
/// Глобальный контекст. Побитовые операции с целыми числами.
/// </summary>
[GlobalContext(Category="Побитовые операции с целыми числами")]
public sealed class GlobalBitFunctions : GlobalContextBase<GlobalBitFunctions>
{

/// <summary>
/// Выполняет побитовое И для заданных чисел.
/// </summary>
/// <param name="number1">Число 1</param>
/// <param name="number2">Число 2</param>
/// <returns>Число. Результат побитового И</returns>
[ContextMethod("ПобитовоеИ")]
public uint BitwiseAnd(uint number1, uint number2)
{
return number1 & number2;
}

/// <summary>
/// Выполняет побитовое Или для заданных чисел.
/// </summary>
/// <param name="number1">Число 1</param>
/// <param name="number2">Число 2</param>
/// <returns>Число. Результат побитового Или</returns>
[ContextMethod("ПобитовоеИли")]
public uint BitwiseOr(uint number1, uint number2)
{
return number1 | number2;
}

/// <summary>
/// Инвертирует биты числе.
/// </summary>
/// <param name="number1"></param>
/// <returns>Число</returns>
[ContextMethod("ПобитовоеНе")]
public uint BitwiseNot(uint number1)
{
return ~number1;
}

/// <summary>
/// Выполняет преобразование, эквивалентное <code>ПобитовоеИ(Число1, ПобитовоеНе(Число2))</code>
/// </summary>
/// <param name="number1">Число 1</param>
/// <param name="number2">Число 2</param>
/// <returns>Число. Результат преобразования</returns>
[ContextMethod("ПобитовоеИНе")]
public uint BitwiseAndNot(uint number1, uint number2)
{
return number1 & ~number2;
}

/// <summary>
/// Выполняет побитовое Исключительное Или для заданных чисел.
/// </summary>
/// <param name="number1">Число 1</param>
/// <param name="number2">Число 2</param>
/// <returns>Число. Результат побитового Исключительного Или</returns>
[ContextMethod("ПобитовоеИсключительноеИли")]
public uint BitwiseXor(uint number1, uint number2)
{
return number1 ^ number2;
}

/// <summary>
/// Получает значение заданного бита.
/// </summary>
/// <param name="value">Число</param>
/// <param name="bitNumber">Номер бита</param>
/// <returns>Булево. Истина - бит установлен в 1, Ложь - бит установлен в 0</returns>
[ContextMethod("ПроверитьБит")]
public bool CheckBit(uint value, int bitNumber)
{
return (value & (1 << bitNumber)) != 0;
}

/// <summary>
/// Устанавливает нужный бит числа в указанное значение
/// </summary>
/// <param name="value">Число</param>
/// <param name="bitNumber">Номер бита</param>
/// <param name="bitValue">Значение бита</param>
/// <returns>Число. Число с установленным в нужное значение битом</returns>
[ContextMethod("УстановитьБит")]
public uint SetBit(uint value, int bitNumber, int bitValue)
{
return bitValue == 0
? (value & ~(uint)(1 << bitNumber))
: (value | (uint)(1 << bitNumber));
}

/// <summary>
/// Проверяет соответствие числа битовой маске.
/// </summary>
/// <param name="value">Число</param>
/// <param name="mask">Маска</param>
/// <returns>Булево. Истина, когда в числе установлены в 1 все биты маски.
/// Ложь - в остальных случаях</returns>
[ContextMethod("ПроверитьПоБитовойМаске")]
public bool CheckByBitMask(uint value, uint mask)
{
return (value & mask) == mask;
}

/// <summary>
/// Выполняет побитовый сдвиг числа влево на заданное смещение
/// </summary>
/// <param name="value">Число</param>
/// <param name="offset">Смещение</param>
/// <returns></returns>
[ContextMethod("ПобитовыйСдвигВлево")]
public uint BitwiseShiftLeft(uint value, int offset)
{
if (offset < 0 || offset > 31)
{
throw RuntimeException.InvalidArgumentValue(offset);
}
return value << offset;
}

/// <summary>
/// Выполняет побитовый сдвиг числа вправо на заданное смещение
/// </summary>
/// <param name="value">Число</param>
/// <param name="offset">Смещение</param>
/// <returns></returns>
[ContextMethod("ПобитовыйСдвигВправо")]
public uint BitwiseShiftRight(uint value, int offset)
{
if (offset < 0 || offset > 31)
{
throw RuntimeException.InvalidArgumentValue(offset);
}
return value >> offset;
}

public static IAttachableContext CreateInstance()
{
return new GlobalBitFunctions();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@
<Compile Include="Library\FixedArrayImpl.cs" />
<Compile Include="Library\FixedMapImpl.cs" />
<Compile Include="Library\FixedStructureImpl.cs" />
<Compile Include="Library\GlobalBitFunctions.cs" />
<Compile Include="Library\Hash\CombinedStream.cs" />
<Compile Include="Library\Hash\Crc32.cs" />
<Compile Include="Library\Hash\HashFunctionEnum.cs" />
Expand Down Expand Up @@ -264,4 +265,4 @@ cp -f "$(TargetDir)Newtonsoft.Json.dll" "$(SolutionDir)StandaloneRunner"</PostBu
<Target Name="AfterBuild">
</Target>
-->
</Project>
</Project>
12 changes: 10 additions & 2 deletions src/ScriptEngine/Machine/Contexts/ContextValuesMarshaller.cs
Original file line number Diff line number Diff line change
Expand Up @@ -55,14 +55,22 @@ public static object ConvertParam(IValue value, Type type)
{
valueObj = value.AsString();
}
else if (type == typeof(int) || type == typeof(uint) || type == typeof(short) || type == typeof(ushort) || type == typeof(byte) || type == typeof(sbyte))
else if (type == typeof(int) || type == typeof(short) || type == typeof(sbyte))
{
valueObj = (int)value.AsNumber();
}
else if (type == typeof(long) || type == typeof(ulong))
else if (type == typeof(uint) || type == typeof(ushort) || type == typeof(byte))
{
valueObj = (uint)value.AsNumber();
}
else if (type == typeof(long))
{
valueObj = (long)value.AsNumber();
}
else if (type == typeof(ulong))
{
valueObj = (ulong)value.AsNumber();
}
else if (type == typeof(double) || type == typeof(decimal))
{
valueObj = value.AsNumber();
Expand Down
154 changes: 154 additions & 0 deletions tests/bitwise.os
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
Перем юТест;

////////////////////////////////////////////////////////////////////
// Программный интерфейс

Функция ПолучитьСписокТестов(ЮнитТестирование) Экспорт

юТест = ЮнитТестирование;

ВсеТесты = Новый Массив;

ВсеТесты.Добавить("ТестДолжен_ПроверитьПобитовоеИ");
ВсеТесты.Добавить("ТестДолжен_ПроверитьПобитовоеИНе");
ВсеТесты.Добавить("ТестДолжен_ПроверитьПобитовоеИли");
ВсеТесты.Добавить("ТестДолжен_ПроверитьПобитовоеИсключительнонИли");
ВсеТесты.Добавить("ТестДолжен_ПроверитьПобитовыеСдвиги");
ВсеТесты.Добавить("ТестДолжен_ПроверитьУстановкуБитов");

Возврат ВсеТесты;

КонецФункции

Процедура ТестДолжен_ПроверитьПобитовоеИ() Экспорт

СамоеБольшоеЧисло = 4294967295;

юТест.ПроверитьРавенство(ПобитовоеИ(4294967295, 0), 0);
юТест.ПроверитьРавенство(ПобитовоеИ(0, 4294967295), 0);
юТест.ПроверитьРавенство(ПобитовоеИ(1, 4294967295), 1);
юТест.ПроверитьРавенство(ПобитовоеИ(2, 4294967295), 2);
юТест.ПроверитьРавенство(ПобитовоеИ(7, 5), 5);

КонецПроцедуры

Процедура ТестДолжен_ПроверитьПобитовоеИНе() Экспорт

СамоеБольшоеЧисло = 4294967295;

юТест.ПроверитьРавенство(ПобитовоеИНе(4294967295, 0), 4294967295);
юТест.ПроверитьРавенство(ПобитовоеИНе(0, 4294967295), 0);
юТест.ПроверитьРавенство(ПобитовоеИНе(1, 4294967295), 0);
юТест.ПроверитьРавенство(ПобитовоеИНе(2, 4294967295), 0);
юТест.ПроверитьРавенство(ПобитовоеИНе(7, 5), 2);

КонецПроцедуры

Процедура ТестДолжен_ПроверитьПобитовоеИли() Экспорт

СамоеБольшоеЧисло = 4294967295;

юТест.ПроверитьРавенство(ПобитовоеИли(4294967295, 0), 4294967295);
юТест.ПроверитьРавенство(ПобитовоеИли(0, 4294967295), 4294967295);
юТест.ПроверитьРавенство(ПобитовоеИли(1, 4294967295), 4294967295);
юТест.ПроверитьРавенство(ПобитовоеИли(2, 4294967295), 4294967295);
юТест.ПроверитьРавенство(ПобитовоеИли(7, 1), 7);
юТест.ПроверитьРавенство(ПобитовоеИли(17, 7), 23);

КонецПроцедуры

Функция СдвигВлевоВызвалИсключение(Знач Число, Знач Смещение)

Попытка

Число = ПобитовыйСдвигВлево(Число, Смещение);

Исключение

Возврат Истина;

КонецПопытки;

Возврат Ложь;

КонецФункции

Функция СдвигВправоВызвалИсключение(Знач Число, Знач Смещение)

Попытка

Число = ПобитовыйСдвигВлево(Число, Смещение);

Исключение

Возврат Истина;

КонецПопытки;

Возврат Ложь;

КонецФункции


Процедура ТестДолжен_ПроверитьПобитовыеСдвиги() Экспорт

юТест.ПроверитьРавенство(ПобитовыйСдвигВлево(1, 0), 1);
юТест.ПроверитьРавенство(ПобитовыйСдвигВлево(1, 1), 2);
юТест.ПроверитьРавенство(ПобитовыйСдвигВлево(1, 2), 4);
юТест.ПроверитьРавенство(ПобитовыйСдвигВлево(1, 3), 8);

юТест.ПроверитьИстину(СдвигВлевоВызвалИсключение(1, 32));
юТест.ПроверитьИстину(СдвигВлевоВызвалИсключение(1, 33));
юТест.ПроверитьИстину(СдвигВлевоВызвалИсключение(1, -1));
юТест.ПроверитьИстину(СдвигВлевоВызвалИсключение(1, -2));


юТест.ПроверитьРавенство(ПобитовыйСдвигВправо(1, 0), 1);
юТест.ПроверитьРавенство(ПобитовыйСдвигВправо(2, 1), 1);
юТест.ПроверитьРавенство(ПобитовыйСдвигВправо(3, 2), 0);
юТест.ПроверитьРавенство(ПобитовыйСдвигВправо(8, 3), 1);

юТест.ПроверитьИстину(СдвигВправоВызвалИсключение(1, 32));
юТест.ПроверитьИстину(СдвигВправоВызвалИсключение(1, 33));
юТест.ПроверитьИстину(СдвигВправоВызвалИсключение(1, -1));
юТест.ПроверитьИстину(СдвигВправоВызвалИсключение(1, -2));

КонецПроцедуры

Процедура ТестДолжен_ПроверитьПобитовоеИсключительнонИли() Экспорт

юТест.ПроверитьРавенство(ПобитовоеИсключительноеИли(4294967295, 0), 4294967295);
юТест.ПроверитьРавенство(ПобитовоеИсключительноеИли(7, 1), 6);
юТест.ПроверитьРавенство(ПобитовоеИсключительноеИли(17, 7), 22);

КонецПроцедуры

Процедура ТестДолжен_ПроверитьУстановкуБитов() Экспорт

Число = 0;
Число = УстановитьБит(Число, 0, 1);
Число = УстановитьБит(Число, 1, 1);
Число = УстановитьБит(Число, 2, 1);
Число = УстановитьБит(Число, 3, 1);

юТест.ПроверитьРавенство(Число, 15);

Число = УстановитьБит(Число, 0, 0);
юТест.ПроверитьРавенство(Число, 14);

Число = 48;
юТест.ПроверитьРавенство(ПроверитьБит(Число, 1), Ложь);
юТест.ПроверитьРавенство(ПроверитьБит(Число, 2), Ложь);
юТест.ПроверитьРавенство(ПроверитьБит(Число, 3), Ложь);
юТест.ПроверитьРавенство(ПроверитьБит(Число, 4), Истина);
юТест.ПроверитьРавенство(ПроверитьБит(Число, 5), Истина);
юТест.ПроверитьРавенство(ПроверитьБит(Число, 6), Ложь);

юТест.ПроверитьИстину(ПроверитьПоБитовойМаске(127, 48));
юТест.ПроверитьИстину(ПроверитьПоБитовойМаске(52, 48));
юТест.ПроверитьИстину(ПроверитьПоБитовойМаске(56, 48));

юТест.ПроверитьЛожь(ПроверитьПоБитовойМаске(33, 48));
юТест.ПроверитьЛожь(ПроверитьПоБитовойМаске(47, 48));

КонецПроцедуры

0 comments on commit d0f7b00

Please sign in to comment.