Data-Scan

 view release on metacpan or  search on metacpan

lib/Data/Scan.pm  view on Meta::CPAN

use strict;
use warnings FATAL => 'all';

package Data::Scan;

# ABSTRACT: Stackfree arbitrary data scanner

our $VERSION = '0.009'; # VERSION

our $AUTHORITY = 'cpan:JDDPAUSE'; # AUTHORITY

use Moo;
use Scalar::Util qw/refaddr reftype/;
use Types::Standard qw/ConsumerOf/;


has consumer => (
                 is => 'ro',
                 isa => ConsumerOf['Data::Scan::Role::Consumer'],
                );


my $_open;
my $_close;
my $openaddr = \$_open;
my $closeaddr = \$_close;


#
# Avoid calls to arybase
#
my $ARRAY_START_INDICE = $[;

sub process {
  my ($self) = shift;

  my ($consumer, $previous, $inner) = $self->consumer;
  #
  # Start
  #
  $consumer->dsstart(@_);
  #
  # Loop
  #
  while (@_) {
    #
    # First our private thingies
    #
    while (@_ && ref $_[$ARRAY_START_INDICE]) {
      if    ($openaddr  == refaddr $_[$ARRAY_START_INDICE]) { $consumer->dsopen ((splice @_, $ARRAY_START_INDICE, 2)[-1]) }
      elsif ($closeaddr == refaddr $_[$ARRAY_START_INDICE]) { $consumer->dsclose((splice @_, $ARRAY_START_INDICE, 2)[-1]) }
      else                                                  { last }
    }
    #
    # Consumer's dsread() returns eventual inner content
    #
    unshift(@_,
            $openaddr, $previous,
            @{$inner},
            $closeaddr, $previous
           ) if (@_ && defined($inner = $consumer->dsread($previous = shift)) && (reftype($inner) // '') eq 'ARRAY')
  }
  #
  # End - return value of consumer's dsend() is what we return
  #
  return $consumer->dsend()
}


1;

__END__

=pod

=encoding UTF-8

=head1 NAME

Data::Scan - Stackfree arbitrary data scanner

=head1 VERSION

version 0.009

=head1 SYNOPSIS

    use strict;
    use warnings FATAL => 'all';
    use Data::Scan;
    use Data::Scan::Impl::Printer;  # A Data::Printer implementation example



( run in 2.448 seconds using v1.01-cache-2.11-cpan-5735350b133 )