From 889d8c07631e34a71b430d487b39205bf39f0923 Mon Sep 17 00:00:00 2001 From: Sergey Batanov Date: Thu, 12 Oct 2023 00:58:41 +0300 Subject: [PATCH 1/4] =?UTF-8?q?=D0=91=D1=83=D1=84=D0=B5=D1=80=D0=94=D0=B2?= =?UTF-8?q?=D0=BE=D0=B8=D1=87=D0=BD=D1=8B=D1=85=D0=94=D0=B0=D0=BD=D0=BD?= =?UTF-8?q?=D1=8B=D1=85.=D0=A0=D0=B0=D0=B7=D0=B4=D0=B5=D0=BB=D0=B8=D1=82?= =?UTF-8?q?=D1=8C().?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Тест + реализация в лоб для варианта с одним разделителем. --- .../Library/Binary/BinaryDataBuffer.cs | 83 ++++++++++++++++--- tests/binary-objects.os | 26 ++++++ 2 files changed, 98 insertions(+), 11 deletions(-) diff --git a/src/ScriptEngine.HostedScript/Library/Binary/BinaryDataBuffer.cs b/src/ScriptEngine.HostedScript/Library/Binary/BinaryDataBuffer.cs index f11bf92f3..ee332a93c 100644 --- a/src/ScriptEngine.HostedScript/Library/Binary/BinaryDataBuffer.cs +++ b/src/ScriptEngine.HostedScript/Library/Binary/BinaryDataBuffer.cs @@ -521,27 +521,88 @@ public ulong ReadInt64(int position, IValue byteOrder = null) /// - /// Разделить буфер на части по заданному разделителю. - /// - /// НЕ РЕАЛИЗОВАН + /// Разделить буфер на части по заданному разделителю или массиву разделителей (Не реализовано). /// /// - /// - /// - /// По двоичному буферу - /// - /// /// /// Разделитель. /// - /// + /// Массив из буферов двоичных данных /// [ContextMethod("Разделить", "Split")] - public IValue Split(IValue separator) + public ArrayImpl Split(IValue separator) { - throw new NotImplementedException(); + var rawSeparator = separator?.GetRawValue(); + if (rawSeparator is BinaryDataBuffer buffer) + { + if (buffer._buffer.LongLength == 0) + { + throw RuntimeException.InvalidArgumentValue(); + } + return SplitWithOne(buffer); + } + + if (rawSeparator is ArrayImpl) + { + throw new NotImplementedException(); + } + + throw RuntimeException.InvalidArgumentType(); } + private ArrayImpl SplitWithOne(BinaryDataBuffer splitter) + { + var result = new List(); + long start = 0; + long index = Find(_buffer, splitter._buffer, start); + while (index != -1) + { + var length = index - start; + result.Add(new BinaryDataBuffer(Copy(start, length), ByteOrder)); + start = index + splitter._buffer.LongLength; + index = Find(_buffer, splitter._buffer, start); + } + + // хвостовой элемент + result.Add(new BinaryDataBuffer(Copy(start, _buffer.LongLength - start))); + return new ArrayImpl(result); + } + + private byte[] Copy(long start, long length) + { + if (length == 0) return Array.Empty(); + var partition = new byte[length]; + Array.Copy(_buffer, start, partition, 0, length); + return partition; + } + + private static long Find(byte[] buffer, byte[] sub, long start) + { + var maxI = buffer.LongLength - sub.LongLength; + for (var i = start; i < maxI; i++) + { + if (SubsequenceEquals(buffer, i, sub)) + { + return i; + } + } + + return -1; + } + + private static bool SubsequenceEquals(byte[] sequence, long start, byte[] subsequence) + { + for (long j = 0; j < subsequence.LongLength; j++) + { + if (subsequence[j] != sequence[start + j]) + { + return false; + } + } + + return true; + } + /// /// /// Создает копию массива. diff --git a/tests/binary-objects.os b/tests/binary-objects.os index 130fc076a..187825ad9 100644 --- a/tests/binary-objects.os +++ b/tests/binary-objects.os @@ -30,6 +30,8 @@ ВсеТесты.Добавить("ТестДолжен_ПроверитьЧтоМетодОткрытьПотокДляЧтенияВозвращаетПотокТолькоДляЧтения"); ВсеТесты.Добавить("ТестДолжен_ПроверитьЧтоХешированиеРаботаетСПотоком"); ВсеТесты.Добавить("ТестДолжен_ПроверитьЧтоХешированиеРаботаетСДвоичнымиДанными"); + + ВсеТесты.Добавить("ТестДолжен_ПроверитьРазделениеБуфераДвоичныхДанныхОднимБуфером"); Возврат ВсеТесты; @@ -351,3 +353,27 @@ НРег(ПолучитьHexСтрокуИзДвоичныхДанных(Хеширование.ХешСумма))); КонецПроцедуры + +Процедура ТестДолжен_ПроверитьРазделениеБуфераДвоичныхДанныхОднимБуфером() Экспорт + + Подстроки = Новый Массив; + Подстроки.Добавить("Часть1"); + Подстроки.Добавить("Часть2"); + Подстроки.Добавить("Часть3"); + РазделительТекстом = "123"; + + ТестовыйБуфер = ПолучитьБуферДвоичныхДанныхИзСтроки(СтрСоединить(Подстроки, РазделительТекстом)); + Разделитель = ПолучитьБуферДвоичныхДанныхИзСтроки(РазделительТекстом); + + РазделенныеДанные = ТестовыйБуфер.Разделить(Разделитель); + + юТест.ПроверитьРавенство(РазделенныеДанные.Количество(), 3, "два разделителя - три элемента"); + + Для Инд = 0 По Подстроки.ВГраница() Цикл + + СтрокаИзБуфера = ПолучитьСтрокуИзБуфераДвоичныхДанных(РазделенныеДанные[Инд]); + юТест.ПроверитьРавенство(СтрокаИзБуфера, Подстроки[Инд], "сравнение строк после разделения буфера"); + + КонецЦикла; + +КонецПроцедуры From 1e2f647a0bbc5e0db98261ca64e8159398c0bba8 Mon Sep 17 00:00:00 2001 From: Sergey Batanov Date: Fri, 20 Oct 2023 22:27:36 +0300 Subject: [PATCH 2/4] =?UTF-8?q?=D0=A0=D0=B0=D0=B7=D0=B1=D0=B8=D0=B2=D0=BA?= =?UTF-8?q?=D0=B0=20=D0=BF=D0=BE=20=D1=81=D0=BF=D0=B8=D1=81=D0=BA=D1=83=20?= =?UTF-8?q?=D1=80=D0=B0=D0=B7=D0=B4=D0=B5=D0=BB=D0=B8=D1=82=D0=B5=D0=BB?= =?UTF-8?q?=D0=B5=D0=B9.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Library/Binary/BinaryDataBuffer.cs | 94 ++++++++++++------- tests/binary-objects.os | 32 +++++++ 2 files changed, 94 insertions(+), 32 deletions(-) diff --git a/src/ScriptEngine.HostedScript/Library/Binary/BinaryDataBuffer.cs b/src/ScriptEngine.HostedScript/Library/Binary/BinaryDataBuffer.cs index ee332a93c..1684e205e 100644 --- a/src/ScriptEngine.HostedScript/Library/Binary/BinaryDataBuffer.cs +++ b/src/ScriptEngine.HostedScript/Library/Binary/BinaryDataBuffer.cs @@ -97,11 +97,7 @@ public override void SetIndexedValue(IValue index, IValue val) /// /// Булево (Boolean) [ContextProperty("ТолькоЧтение", "ReadOnly")] - public bool ReadOnly - { - get { return _readOnly; } - - } + public bool ReadOnly => _readOnly; /// /// @@ -521,7 +517,7 @@ public ulong ReadInt64(int position, IValue byteOrder = null) /// - /// Разделить буфер на части по заданному разделителю или массиву разделителей (Не реализовано). + /// Разделить буфер на части по заданному разделителю или массиву разделителей. /// /// /// @@ -531,36 +527,60 @@ public ulong ReadInt64(int position, IValue byteOrder = null) /// [ContextMethod("Разделить", "Split")] public ArrayImpl Split(IValue separator) + { + var buffers = ParseParam(separator); + + // Функция поиска требует, чтобы буферы были в порядке убывания размера + buffers.Sort((a, b) => b._buffer.LongLength.CompareTo(a._buffer.LongLength)); + return SplitBuffer(buffers.ToArray()); + } + + private static List ParseParam(IValue separator) { var rawSeparator = separator?.GetRawValue(); - if (rawSeparator is BinaryDataBuffer buffer) + switch (rawSeparator) { - if (buffer._buffer.LongLength == 0) + case BinaryDataBuffer buffer: + return new List { CheckedBuffer(buffer) }; + + case ArrayImpl array: { - throw RuntimeException.InvalidArgumentValue(); + var buffers = new List(); + + foreach (var element in array) + { + buffers.AddRange(ParseParam(element)); + } + + return buffers; } - return SplitWithOne(buffer); + + default: + throw RuntimeException.InvalidArgumentType(); } + } - if (rawSeparator is ArrayImpl) + private static BinaryDataBuffer CheckedBuffer(BinaryDataBuffer buffer) + { + if (buffer.Size == 0) { - throw new NotImplementedException(); + throw RuntimeException.InvalidArgumentValue(); } - throw RuntimeException.InvalidArgumentType(); + return buffer; } - private ArrayImpl SplitWithOne(BinaryDataBuffer splitter) + private ArrayImpl SplitBuffer(BinaryDataBuffer[] splitter) { var result = new List(); long start = 0; - long index = Find(_buffer, splitter._buffer, start); - while (index != -1) + var foundPosition = FindFirst(splitter, start); + while (foundPosition != null) { - var length = index - start; + var length = foundPosition.Item2 - start; result.Add(new BinaryDataBuffer(Copy(start, length), ByteOrder)); - start = index + splitter._buffer.LongLength; - index = Find(_buffer, splitter._buffer, start); + start = foundPosition.Item2 + foundPosition.Item1.Size; + foundPosition = FindFirst(splitter, start); } // хвостовой элемент @@ -568,26 +588,36 @@ private ArrayImpl SplitWithOne(BinaryDataBuffer splitter) return new ArrayImpl(result); } - private byte[] Copy(long start, long length) - { - if (length == 0) return Array.Empty(); - var partition = new byte[length]; - Array.Copy(_buffer, start, partition, 0, length); - return partition; - } - - private static long Find(byte[] buffer, byte[] sub, long start) + /// + /// Ищет ближайшее вхождение любого из буферов. Если на одной позиции находятся два и более буфера, берется бОльший. + /// + /// Массив искомых буферов + /// Начальная позиция поиска + /// Буфер и позиция или null, если нет вхождений + private Tuple FindFirst(BinaryDataBuffer[] buffers, long start) { - var maxI = buffer.LongLength - sub.LongLength; + var maxI = Size - buffers[buffers.Length - 1].Size; for (var i = start; i < maxI; i++) { - if (SubsequenceEquals(buffer, i, sub)) + foreach (var expectedBuffer in buffers) { - return i; + if (SubsequenceEquals(_buffer, i, expectedBuffer._buffer)) + { + var result = new Tuple(expectedBuffer, i); + return result; + } } } - return -1; + return null; + } + + private byte[] Copy(long start, long length) + { + if (length == 0) return Array.Empty(); + var partition = new byte[length]; + Array.Copy(_buffer, start, partition, 0, length); + return partition; } private static bool SubsequenceEquals(byte[] sequence, long start, byte[] subsequence) diff --git a/tests/binary-objects.os b/tests/binary-objects.os index 187825ad9..aa5bc3a01 100644 --- a/tests/binary-objects.os +++ b/tests/binary-objects.os @@ -11,6 +11,7 @@ ВсеТесты = Новый Массив; ВсеТесты.Добавить("ТестДолжен_ПроверитьЧтоСоздаетсяБуферДвоичныхДанных"); + ВсеТесты.Добавить("ТестДолжен_ПроверитьРазделениеБуфераДвоичныхДанныхНесколькимиБуферами"); ВсеТесты.Добавить("ТестДолжен_ПроверитьЧтоМожноЗаписатьБайты"); ВсеТесты.Добавить("ТестДолжен_ПроверитьЧтоМожноПрочитатьБайты"); ВсеТесты.Добавить("ТестДолжен_ПроверитьЧтоМожноЗаписатьПрочитатьЦелое16"); @@ -377,3 +378,34 @@ КонецЦикла; КонецПроцедуры + +Процедура ТестДолжен_ПроверитьРазделениеБуфераДвоичныхДанныхНесколькимиБуферами() Экспорт + + Подстроки = Новый Массив; + Подстроки.Добавить("Часть1"); + Подстроки.Добавить("Часть2"); + Подстроки.Добавить("Часть3"); + Подстроки.Добавить("Часть4"); + Подстроки.Добавить("Часть5"); + + ТестоваяСтрока = "Часть1\R\R\NЧасть2\R\NЧасть3\NЧасть4\RЧасть5"; + + ТестовыйБуфер = ПолучитьБуферДвоичныхДанныхИзСтроки(ТестоваяСтрока); + Разделители = Новый Массив; + Разделители.Добавить(ПолучитьБуферДвоичныхДанныхИзСтроки("\N")); + Разделители.Добавить(ПолучитьБуферДвоичныхДанныхИзСтроки("\R\N")); + Разделители.Добавить(ПолучитьБуферДвоичныхДанныхИзСтроки("\R")); + Разделители.Добавить(ПолучитьБуферДвоичныхДанныхИзСтроки("\R\R\N")); + + РазделенныеДанные = ТестовыйБуфер.Разделить(Разделители); + + юТест.ПроверитьРавенство(РазделенныеДанные.Количество(), 5); + + Для Инд = 0 По РазделенныеДанные.ВГраница() Цикл + + СтрокаИзБуфера = ПолучитьСтрокуИзБуфераДвоичныхДанных(РазделенныеДанные[Инд]); + юТест.ПроверитьРавенство(СтрокаИзБуфера, Подстроки[Инд], "сравнение строк после разделения буфера"); + + КонецЦикла; + +КонецПроцедуры From c247ce12d7986b23509c475cd42daa67adedd94c Mon Sep 17 00:00:00 2001 From: Sergey Batanov Date: Sat, 21 Oct 2023 12:31:36 +0300 Subject: [PATCH 3/4] =?UTF-8?q?=D0=9B=D0=B8=D1=82=D0=B5=D1=80=D0=B0=D0=BB?= =?UTF-8?q?=D1=8B=20=D0=BA=D0=BE=D1=80=D1=82=D0=B5=D0=B6=D0=B5=D0=B9.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Library/Binary/BinaryDataBuffer.cs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/ScriptEngine.HostedScript/Library/Binary/BinaryDataBuffer.cs b/src/ScriptEngine.HostedScript/Library/Binary/BinaryDataBuffer.cs index 1684e205e..a8f7b8289 100644 --- a/src/ScriptEngine.HostedScript/Library/Binary/BinaryDataBuffer.cs +++ b/src/ScriptEngine.HostedScript/Library/Binary/BinaryDataBuffer.cs @@ -575,7 +575,7 @@ private ArrayImpl SplitBuffer(BinaryDataBuffer[] splitter) var result = new List(); long start = 0; var foundPosition = FindFirst(splitter, start); - while (foundPosition != null) + while (foundPosition.pos != -1) { var length = foundPosition.Item2 - start; result.Add(new BinaryDataBuffer(Copy(start, length), ByteOrder)); @@ -594,7 +594,7 @@ private ArrayImpl SplitBuffer(BinaryDataBuffer[] splitter) /// Массив искомых буферов /// Начальная позиция поиска /// Буфер и позиция или null, если нет вхождений - private Tuple FindFirst(BinaryDataBuffer[] buffers, long start) + private (BinaryDataBuffer buffer, long pos) FindFirst(BinaryDataBuffer[] buffers, long start) { var maxI = Size - buffers[buffers.Length - 1].Size; for (var i = start; i < maxI; i++) @@ -603,13 +603,12 @@ private Tuple FindFirst(BinaryDataBuffer[] buffers, long { if (SubsequenceEquals(_buffer, i, expectedBuffer._buffer)) { - var result = new Tuple(expectedBuffer, i); - return result; + return (expectedBuffer, i); } } } - return null; + return (null, -1); } private byte[] Copy(long start, long length) From 9a8ed3df86bb264fa501010a1a2d048368669168 Mon Sep 17 00:00:00 2001 From: Sergey Batanov Date: Sat, 21 Oct 2023 12:33:26 +0300 Subject: [PATCH 4/4] =?UTF-8?q?=D0=9B=D0=B8=D1=82=D0=B5=D1=80=D0=B0=D0=BB?= =?UTF-8?q?=D1=8B=20=D0=BA=D0=BE=D1=80=D1=82=D0=B5=D0=B6=D0=B5=D0=B9.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Library/Binary/BinaryDataBuffer.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ScriptEngine.HostedScript/Library/Binary/BinaryDataBuffer.cs b/src/ScriptEngine.HostedScript/Library/Binary/BinaryDataBuffer.cs index a8f7b8289..ed1374880 100644 --- a/src/ScriptEngine.HostedScript/Library/Binary/BinaryDataBuffer.cs +++ b/src/ScriptEngine.HostedScript/Library/Binary/BinaryDataBuffer.cs @@ -577,9 +577,9 @@ private ArrayImpl SplitBuffer(BinaryDataBuffer[] splitter) var foundPosition = FindFirst(splitter, start); while (foundPosition.pos != -1) { - var length = foundPosition.Item2 - start; + var length = foundPosition.pos - start; result.Add(new BinaryDataBuffer(Copy(start, length), ByteOrder)); - start = foundPosition.Item2 + foundPosition.Item1.Size; + start = foundPosition.pos + foundPosition.buffer.Size; foundPosition = FindFirst(splitter, start); }