Crypt::IDA::SlidingWindow - Abstract Sliding Window class
use Crypt::IDA::SlidingWindow my $sw = Crypt::IDA::SlidingWindow->new( mode => 'split', rows => 4, window => 16384 ); # accessors (can also use $sw->{variable} form) my $read_head = $sw->read_head; my $window = $sw->window; #... # Testing what can advance my ($read_ok, $process_ok, $write_ok, @bundle_ok) = $sw->can_advance; my $read_ok = $sw->can_fill; my $read_ok = $sw->can_fill_substream($row); my $process_ok = $sw->process_ok; my $write_ok = $sw->can_empty; my $write_ok = $sw->can_empty_substream($row); # advance pointers after ... $sw->advance_read($cols); # filling input stream $sw->advance_read_substream($row,$cols); # filling input substream $sw->advance_process($cols); # processing $sw->advance_write($cols); # emptying output stream $sw->advance_write_substream($row,$cols);# emptying output substream
This class is not meant to be called directly. Its functionality can be accessed via method calls in Crypt::IDA::Algorithm. It's also possible that it may change in future:
Crypt::IDA::Algorithm
the underlying object may change from {} to [] for more efficiency
likewise, I might replace it with an XS library
the callback feature might change or disappear (moved to Crypt::IDA::Algorithm)
This class implements a Sliding Window algorithm to support cleaner IDA split/combine code. It manages access to the input and output matrix buffers to prevent them from overflowing.
The abstraction assumes that:
all pointers refer to matrix columns rather than bytes
input and output matrices have the same number of columns
pointers are linear (always increasing), rather than circular
we're doing IDA-like split/combine operations with one matrix handling a "bundle" of substreams:
When splitting, single stream on input, bundle of substreams on output
When combining, bundle of substreams on input, single stream on output
The class manages three types of pointer:
a 'read' ('fill') pointer tracking input into the input matrix
a 'processed' pointer tracking transformation of input into output
a 'write' ('empty') pointer tracking data being removed from the output matrix
These should be self-explanatory.
Internally, all the pointers are linear, but it's possible to convert them to circular pointers within the input or output matrices. Simply:
calculate pointer % window_size
pointer % window_size
multiply that value by the size in bytes of a matrix column
This class also provides a convenience method destraddle that takes a pointer and a number of columns to increase it by and checks whether that range would cross the end of the matrix boundary. It returns:
destraddle
the same columns parameter, if the range is contiguous within the matrix
two columns values representing contiguous ranges at the end and start of the matrix, respectively, otherwise
For example:
# Read a row of bytes from a matrix, handling wrap-around my ($first,$second) = $sw->destraddle($tail,$cols); my $rel_col = $tail % $sw->{window}; $str = $mat->getvals($row,$rel_col,$first ,$order); $str.= $mat->getvals($row,0, $second,$order) if defined($second);
This class maintains an extra set of head and tail pointers for each substream, in addition to the main head/tail pointer. It's assumed that substreams can advance at different rates from each other.
The code for advance_read_substream and advance_write_substream checks whether advancing that substream can advance the parent read/writer, and does so automatically. Callers can check the return value of the method calls, with 1 indicating that the parent pointer advanced.
advance_read_substream
advance_write_substream
When the parent pointer advances, it indicates either:
when combining, all input substreams got some input, so more processing can be done (providing there is output space)
when splitting, all output substreams flushed some share data, so more processing can be done (providing there's more input data).
In the current version of the code, it's also possible to pass a callback to receive notification whenever a bundle of substreams makes progress in this way:
# when splitting, get callback when all output substreams advance $sw->cb_write_bundle(sub {...}); # when splitting, get callback when all input substreams advance $sw->cb_read_bundle(sub {...}
This might change in future.
Declan Malone, <idablack@sourceforge.net>
Copyright (C) 2019 Declan Malone
This package is free software; you can redistribute it and/or modify it under the terms of version 2 (or, at your discretion, any later version) of the "GNU General Public License" ("GPL").
Please refer to the file "GNU_GPL.txt" in this distribution for details.
This package is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
To install Crypt::IDA, copy and paste the appropriate command in to your terminal.
cpanm
cpanm Crypt::IDA
CPAN shell
perl -MCPAN -e shell install Crypt::IDA
For more information on module installation, please visit the detailed CPAN module installation guide.