#############################################################################
## Name:        TiehHandler.pm
## Purpose:     Pod::HtmlEasy::TiehHandler (some sub based in IO::Scalar)
## Author:      Graciliano M. P.
## Modified by:
## Created:     11/01/2004
## RCS-ID:      
## Copyright:   (c) 2004 Graciliano M. P.
## Licence:     This program is free software; you can redistribute it and/or
##              modify it under the same terms as Perl itself
#############################################################################

package Pod::HtmlEasy::TiehHandler ;

use strict ;
use warnings;

use vars qw($VERSION @ISA) ;
$VERSION = '0.01' ;

sub TIEHANDLE {
  my $class = shift ;
  my $scalar = shift ;
  return bless({SCALAR => $scalar} , $class) ;
}

sub PRINT {
  my $this = shift ;
  ${ $this->{SCALAR} } .= join("", (@_[0..$#_]) ) ;
  return 1 ;
}

sub PRINTF { &PRINT($_[0],sprintf($_[1],@_[2..$#_])) ;}

sub READ      { shift->read(@_) }
sub READLINE  { wantarray ? shift->getlines(@_) : shift->getline(@_) }

sub GETC      {
  my $this = shift;
  return undef if $this->EOF ;
  substr( ${ $this->{SCALAR} } , $this->{POS}++ , 1) ;
}

sub SEEK {
  my $this = shift ;
  my ($pos, $whence) = @_ ;

  my $eofpos = length( ${ $this->{SCALAR} } ) ;

  if    ($whence == 0) { $this->{POS} = $pos }             ### SEEK_SET
  elsif ($whence == 1) { $this->{POS} += $pos }            ### SEEK_CUR
  elsif ($whence == 2) { $this->{POS} = $eofpos + $pos}    ### SEEK_END

  if ($this->{POS} < 0)       { $this->{POS} = 0 }
  if ($this->{POS} > $eofpos) { $this->{POS} = $eofpos }
  
  1 ;
}

sub TELL { $_[0]->{POS} ;}

sub EOF {
  my $this = shift ;
  ( $this->{POS} >= length( ${ $this->{SCALAR} } ) )
}

sub WRITE {}

sub FILENO {}

sub CLOSE {}
sub UNTIE {}
sub DESTROY {}

##
## From IO::Scalar:
##

sub getline {
  my $this = shift;
  return undef if $this->EOF ;

  my $sr = $this->{SCALAR} ;
  my $i  = $this->{POS} ;

  ### Case 1: $/ is undef: slurp all...
  if (!defined($/)) {
    $this->{POS} = length $$sr ;
    return substr($$sr, $i) ;
  }

  ### Case 2: $/ is "\n": zoom zoom zoom...
  elsif ($/ eq "\012") {
    ### Seek ahead for "\n"... yes, this really is faster than regexps.
    my $len = length($$sr);
    for (; $i < $len; ++$i) {
      last if ord (substr ($$sr, $i, 1)) == 10;
    }

    ### Extract the line:
    my $line;
    if ($i < $len) {                ### We found a "\n":
      $line = substr ($$sr, $this->{POS}, $i - $this->{POS} + 1);
      $this->{POS} = $i+1;            ### Remember where we finished up.
    }
    else {                          ### No "\n"; slurp the remainder:
      $line = substr ($$sr, $this->{POS}, $i - $this->{POS});
      $this->{POS} = $len;
    }
    return $line;
  }

  ### Case 3: $/ is ref to int. Do fixed-size records.
  ###        (Thanks to Dominique Quatravaux.)
  elsif (ref($/)) {
    my $len = length($$sr);
    my $i = ${$/} + 0;
    my $line = substr ($$sr, $this->{POS}, $i);
    $this->{POS} += $i;
    $this->{POS} = $len if ($this->{POS} > $len);
    return $line;
  }

  ### Case 4: $/ is either "" (paragraphs) or something weird...
  ###         This is Graham's general-purpose stuff, which might be
  ###         a tad slower than Case 2 for typical data, because
  ###         of the regexps.
  else {
    pos($$sr) = $i;

	### If in paragraph mode, skip leading lines (and update i!):
    length($/) or (($$sr =~ m/\G\n*/g) and ($i = pos($$sr))) ;

    ### If we see the separator in the buffer ahead...
    if ( length($/) ? $$sr =~ m,\Q$/\E,g          ###   (ordinary sep) TBD: precomp!
                    : $$sr =~ m,\n\n,g            ###   (a paragraph)
       ) {
           $this->{POS} = pos $$sr;
           return substr($$sr, $i, $this->{POS}-$i);
    }
    ### Else if no separator remains, just slurp the rest:
    else {
      $this->{POS} = length $$sr;
      return substr($$sr, $i);
    }
  }
}

sub getlines {
  my $this = shift ;
  my ($line, @lines) ;
  push @lines, $line while (defined($line = $this->getline)) ;
  @lines ;
}

#######
# END #
#######

1;


