@@ -97,11 +97,7 @@ public override void SetIndexedValue(IValue index, IValue val)
97
97
/// </summary>
98
98
/// <value>Булево (Boolean)</value>
99
99
[ ContextProperty ( "ТолькоЧтение" , "ReadOnly" ) ]
100
- public bool ReadOnly
101
- {
102
- get { return _readOnly ; }
103
-
104
- }
100
+ public bool ReadOnly => _readOnly ;
105
101
106
102
/// <summary>
107
103
///
@@ -521,27 +517,121 @@ public ulong ReadInt64(int position, IValue byteOrder = null)
521
517
522
518
523
519
/// <summary>
524
- /// Разделить буфер на части по заданному разделителю.
525
- ///
526
- /// НЕ РЕАЛИЗОВАН
520
+ /// Разделить буфер на части по заданному разделителю или массиву разделителей.
527
521
/// </summary>
528
522
///
529
- /// <remarks>
530
- ///
531
- /// По двоичному буферу
532
- /// </remarks>
533
- ///
534
523
/// <param name="separator">
535
524
/// Разделитель. </param>
536
525
///
537
- /// <returns name="Array"/ >
526
+ /// <returns name="Array">Массив из буферов двоичных данных</returns >
538
527
///
539
528
[ ContextMethod ( "Разделить" , "Split" ) ]
540
- public IValue Split ( IValue separator )
529
+ public ArrayImpl Split ( IValue separator )
541
530
{
542
- throw new NotImplementedException ( ) ;
531
+ var buffers = ParseParam ( separator ) ;
532
+
533
+ // Функция поиска требует, чтобы буферы были в порядке убывания размера
534
+ buffers . Sort ( ( a , b ) => b . _buffer . LongLength . CompareTo ( a . _buffer . LongLength ) ) ;
535
+ return SplitBuffer ( buffers . ToArray ( ) ) ;
536
+ }
537
+
538
+ private static List < BinaryDataBuffer > ParseParam ( IValue separator )
539
+ {
540
+ var rawSeparator = separator ? . GetRawValue ( ) ;
541
+ switch ( rawSeparator )
542
+ {
543
+ case BinaryDataBuffer buffer :
544
+ return new List < BinaryDataBuffer > { CheckedBuffer ( buffer ) } ;
545
+
546
+ case ArrayImpl array :
547
+ {
548
+ var buffers = new List < BinaryDataBuffer > ( ) ;
549
+
550
+ foreach ( var element in array )
551
+ {
552
+ buffers . AddRange ( ParseParam ( element ) ) ;
553
+ }
554
+
555
+ return buffers ;
556
+ }
557
+
558
+ default :
559
+ throw RuntimeException . InvalidArgumentType ( ) ;
560
+ }
561
+ }
562
+
563
+ private static BinaryDataBuffer CheckedBuffer ( BinaryDataBuffer buffer )
564
+ {
565
+ if ( buffer . Size == 0 )
566
+ {
567
+ throw RuntimeException . InvalidArgumentValue ( ) ;
568
+ }
569
+
570
+ return buffer ;
571
+ }
572
+
573
+ private ArrayImpl SplitBuffer ( BinaryDataBuffer [ ] splitter )
574
+ {
575
+ var result = new List < BinaryDataBuffer > ( ) ;
576
+ long start = 0 ;
577
+ var foundPosition = FindFirst ( splitter , start ) ;
578
+ while ( foundPosition . pos != - 1 )
579
+ {
580
+ var length = foundPosition . pos - start ;
581
+ result . Add ( new BinaryDataBuffer ( Copy ( start , length ) , ByteOrder ) ) ;
582
+ start = foundPosition . pos + foundPosition . buffer . Size ;
583
+ foundPosition = FindFirst ( splitter , start ) ;
584
+ }
585
+
586
+ // хвостовой элемент
587
+ result . Add ( new BinaryDataBuffer ( Copy ( start , _buffer . LongLength - start ) ) ) ;
588
+ return new ArrayImpl ( result ) ;
589
+ }
590
+
591
+ /// <summary>
592
+ /// Ищет ближайшее вхождение любого из буферов. Если на одной позиции находятся два и более буфера, берется бОльший.
593
+ /// </summary>
594
+ /// <param name="buffers">Массив искомых буферов</param>
595
+ /// <param name="start">Начальная позиция поиска</param>
596
+ /// <returns>Буфер и позиция или null, если нет вхождений</returns>
597
+ private ( BinaryDataBuffer buffer , long pos ) FindFirst ( BinaryDataBuffer [ ] buffers , long start )
598
+ {
599
+ var maxI = Size - buffers [ buffers . Length - 1 ] . Size ;
600
+ for ( var i = start ; i < maxI ; i ++ )
601
+ {
602
+ foreach ( var expectedBuffer in buffers )
603
+ {
604
+ if ( SubsequenceEquals ( _buffer , i , expectedBuffer . _buffer ) )
605
+ {
606
+ return ( expectedBuffer , i ) ;
607
+ }
608
+ }
609
+ }
610
+
611
+ return ( null , - 1 ) ;
612
+ }
613
+
614
+ private byte [ ] Copy ( long start , long length )
615
+ {
616
+ if ( length == 0 ) return Array . Empty < byte > ( ) ;
617
+ var partition = new byte [ length ] ;
618
+ Array . Copy ( _buffer , start , partition , 0 , length ) ;
619
+ return partition ;
543
620
}
544
621
622
+ private static bool SubsequenceEquals ( byte [ ] sequence , long start , byte [ ] subsequence )
623
+ {
624
+ for ( long j = 0 ; j < subsequence . LongLength ; j ++ )
625
+ {
626
+ if ( subsequence [ j ] != sequence [ start + j ] )
627
+ {
628
+ return false ;
629
+ }
630
+ }
631
+
632
+ return true ;
633
+ }
634
+
545
635
/// <summary>
546
636
///
547
637
/// Создает копию массива.
0 commit comments