]>
Dogcows Code - chaz/p5-File-KDBX/blob - lib/File/KDBX/IO.pm
1 package File
::KDBX
::IO
;
2 # ABSTRACT: Base IO class for KDBX-related streams
7 use Devel
::GlobalDestruction
;
8 use File
::KDBX
::Util
qw(:empty :bool);
9 use List
::Util
qw(sum0);
10 use Ref
::Util
qw(is_blessed_ref is_ref is_scalarref);
11 use Symbol
qw(gensym);
14 use parent
'IO::Handle';
16 our $VERSION = '999.999'; # VERSION
18 sub _croak
{ require Carp
; goto &Carp
::croak
}
22 _buffer_in
=> sub { [] },
23 _buffer_out
=> sub { [] },
28 while (my ($attr, $default) = each %ATTRS) {
29 no strict
'refs'; ## no critic (ProhibitNoStrict)
32 *$self->{$attr} = shift if @_;
33 *$self->{$attr} //= (ref $default eq 'CODE') ? $default->($self) : $default;
38 my $class = shift || (caller)[0];
39 my $self = bless gensym
, ref($class) || $class;
40 tie
*$self, $self if 5.005 <= $];
45 return if in_global_destruction
;
46 local ($., $@, $!, $^E, $?);
53 my $fh = $self->_fh // return TRUE
;
60 return FALSE
if @{$self->_buffer_in};
61 my $fh = $self->_fh // return TRUE
;
62 local *$self->{_error
} = *$self->{_error
};
63 my $char = $self->getc || return TRUE
;
66 sub read { shift-
>sysread(@_) }
70 return FALSE
if !$self->write($buf, length($buf));
74 sub printf { shift-
>print(sprintf(@_)) }
75 sub say { shift-
>print(@_, "\n") }
76 sub getc { my $c; (shift-
>read($c, 1) // 0) == 1 ? $c : undef }
79 my ($out, $len, $offset) = @_;
80 $out = \
$_[0] if !is_scalarref
($out);
83 $self->_mode('r') if !$self->_mode;
85 my $fh = $self->_fh or return 0;
86 return 0 if defined $len && $len == 0;
88 my $append = $self->_append_output;
94 if (length($$out) < $offset) {
95 $$out .= "\0" x
($offset - length($$out));
98 substr($$out, $offset) = '';
102 elsif (!defined $$out) {
108 my $buffer = $self->_buffer_in;
109 my $buffer_len = $self->_buffer_in_length;
111 if (!$len && !$offset) {
113 my $blen = length($buffer->[0]);
115 $$out .= shift @$buffer;
118 $$out = shift @$buffer;
123 my $fill = $self->_FILL($fh) or return 0;
130 return length($fill);
134 while ($buffer_len < $len) {
135 my $fill = $self->_FILL($fh);
137 $self->_buffer_in_add($fill);
138 $buffer_len += length($fill);
142 while ($read_len < $len && @$buffer) {
143 my $wanted = $len - $read_len;
144 my $read = shift @$buffer;
145 if ($wanted < length($read)) {
146 $$out .= substr($read, 0, $wanted, '');
147 unshift @$buffer, $read;
148 $read_len += $wanted;
152 $read_len += length($read);
159 my ($self, $buf, $len, $offset) = @_;
160 $len //= length($buf);
163 $self->_mode('w') if !$self->_mode;
165 return $self->_WRITE(substr($buf, $offset, $len), $self->_fh);
170 my $fh = $self->_fh // return FALSE
;
171 return $fh->autoflush(@_);
176 my $fh = $self->_fh // return FALSE
;
182 if (!defined $/) { # SLURP
183 local *$self->{_append_output
} = 1;
185 1 while 0 < $self->read($data);
188 elsif (is_scalarref
($/) && ${$/} =~ /^\d+$/ && 0 < ${$/}) {
190 goto &_not_implemented
;
192 elsif (length $/ == 0) {
194 goto &_not_implemented
;
198 goto &_not_implemented
;
203 wantarray or _croak
'Must call getlines in list context';
205 while (defined (my $line = $self->getline)) {
211 my ($self, $ord) = @_;
212 unshift @{$self->_buffer_in}, chr($ord);
216 my ($self, $buf, $len, $offset) = @_;
217 return $self->syswrite($buf, $len, $offset) == $len;
221 return !!$self->_error;
225 my $fh = $self->_fh // return -1;
226 $self->_error(undef);
231 my $fh = $self->_fh // return undef;
236 my $fh = $self->_fh // return undef;
242 my $orig = $self->autoflush;
243 my $r = $self->print(@_);
244 $self->autoflush($orig);
249 my $fh = $self->_fh // return TRUE
;
250 return $fh->blocking(@_);
253 sub format_write
{ goto &_not_implemented
}
254 sub new_from_fd
{ goto &_not_implemented
}
255 sub fcntl { goto &_not_implemented
}
256 sub fileno { goto &_not_implemented
}
257 sub ioctl { goto &_not_implemented
}
258 sub stat { goto &_not_implemented
}
259 sub truncate { goto &_not_implemented
}
260 sub format_page_number
{ goto &_not_implemented
}
261 sub format_lines_per_page
{ goto &_not_implemented
}
262 sub format_lines_left
{ goto &_not_implemented
}
263 sub format_name
{ goto &_not_implemented
}
264 sub format_top_name
{ goto &_not_implemented
}
265 sub input_line_number
{ goto &_not_implemented
}
266 sub fdopen
{ goto &_not_implemented
}
267 sub untaint
{ goto &_not_implemented
}
269 ##############################################################################
271 sub _buffer_in_add
{ push @{shift-
>_buffer_in}, @_ }
272 sub _buffer_in_length
{ sum0
map { length($_) } @{shift-
>_buffer_in} }
274 sub _buffer_out_add
{ push @{shift-
>_buffer_out}, @_ }
275 sub _buffer_out_length
{ sum0
map { length($_) } @{shift-
>_buffer_out} }
277 sub _not_implemented
{ _croak
'Operation not supported' }
279 ##############################################################################
282 return $_[0] if is_blessed_ref
($_[0]);
291 goto &getlines
if wantarray;
301 # *READLINE = \&getline;
311 *BINMODE
= \
&binmode;
314 sub _FILL
{ die 'Not implemented' }
316 ##############################################################################
318 if ($ENV{DEBUG_IO
}) {
319 my %debug = (level
=> 0);
341 format_lines_per_page
362 no strict
'refs'; ## no critic (ProhibitNoStrict)
363 no warnings
'redefine';
364 my $orig = *$method{CODE
};
366 local $debug{level
} = $debug{level
} + 2;
367 my $indented_method = (' ' x
$debug{level
}) . $method;
369 print STDERR
sprintf('%-20s -> %s (%s)', $indented_method, $self,
370 join(', ', map { defined $_ ? substr($_, 0, 16) : 'undef' } @_)), "\n";
371 my $r = $orig->($self, @_) // 'undef';
372 print STDERR
sprintf('%-20s <- %s [%s]', $indented_method, $self, $r), "\n";
390 format_lines_per_page
411 This is a L<IO::Handle> subclass which provides self-tying and buffering. It currently provides an interface
412 for subclasses that is similar to L<PerlIO::via>, but this is subject to change. Don't depend on this outside
413 of the L<File::KDBX> distribution. Currently-available subclasses:
416 * L<File::KDBX::IO::Crypt>
417 * L<File::KDBX::IO::HashBlock>
418 * L<File::KDBX::IO::HmacBlock>
This page took 0.053378 seconds and 4 git commands to generate.