1 package File
::KDBX
::Iterator
;
2 # PACKAGE: KDBX database iterator
8 use File
::KDBX
::Util
qw(:class :load :search);
10 use Ref
::Util
qw(is_arrayref is_coderef is_scalarref);
13 extends
'Iterator::Simple::Iterator';
15 our $VERSION = '999.999'; # VERSION
19 \
&iterator
= File
::KDBX
::Iterator-
>new(\
&iterator
);
21 Blesses an iterator to augment it with buffering plus some useful utility methods
.
27 my $code = is_coderef
($_[0]) ? shift : sub { undef };
29 my $items = @_ == 1 && is_arrayref
($_[0]) ? $_[0] : \
@_;
30 return $class->SUPER::new
(sub {
32 if (@_ == 1 && is_arrayref
($_[0])) {
41 my $next = shift @$items;
42 return $next if defined $next;
50 $item = $iterator->next;
52 $item = $iterator->();
54 $item = $iterator->next(\
&query
);
55 $item = $iterator->next([\'simple expression
', @fields]);
57 Get the next item or C<undef> if there are no more items. If a query is passed, get the next matching item,
58 discarding any items before the matching item that do not match. Example:
60 my $item = $iterator->next(sub { $_->label =~ /Gym/ });
68 if (is_coderef($code) || overload::Method($code, '&{}')) {
71 elsif (is_scalarref($code)) {
72 return simple_expression_query($$code, @_);
75 return query($code, @_);
81 my $code = shift or return $self->();
83 $code = $self->_create_query($code, @_);
85 while (defined (local $_ = $self->())) {
86 return $_ if $code->($_);
93 $item = $iterator->peek;
95 Peek at the next item. Returns C<undef> if the iterator is empty. This allows you to access the next item
96 without draining it from the iterator. The same item will be returned the next time L</next> is called.
103 my $next = $self->();
104 $self->($next) if defined $next;
110 $iterator->unget(\@items);
111 $iterator->unget(...);
113 $iterator->(\@items);
116 Replace the buffer or unshift one or more items to the current buffer.
123 my $self = shift; # Must shift in a statement before calling.
129 @items = $iterator->each;
131 $iterator->each(sub($item, $num) { ... });
133 Get the rest of the items. There are two forms: Without arguments, C<each> returns a list of the rest of the
134 items. Or pass a coderef to be called once per item, in order. The item is passed as the first argument to the
135 given subroutine and is also available as C<$_>.
141 my $cb = shift or return @{$self->to_array};
144 $cb->($_, $count++) while defined (local $_ = $self->());
150 \&iterator = $iterator->limit($count);
152 Get a new iterator draining from an existing iterator but providing only a limited number of items.
156 sub limit { shift->head(@_) }
160 \&iterator = $iterator->grep(\&query);
161 \&iterator = $iterator->grep([\'simple expression', @fields]);
163 Get a new iterator draining from an existing iterator but providing only items that pass a test
or are matched
172 $code = $self->_create_query($code, @_);
174 ref($self)->new(sub {
175 while (defined (local $_ = $self->())) {
176 return $_ if $code->($_);
184 \
&iterator
= $iterator->map(\
&code
);
186 Get a new iterator draining from an existing iterator but providing modified items
.
194 ref($self)->new(sub {
195 local $_ = $self->();
196 return if !defined $_;
203 \
&iterator
= $iterator->filter(\
&query
);
204 \
&iterator
= $iterator->filter([\'simple expression
', @fields]);
206 See L<Iterator::Simple/"ifilter $iterable, sub{ CODE }">.
213 return $self->SUPER::filter($self->_create_query($code, @_));
220 \&iterator = $iterator->sort_by($field, %options);
221 \&iterator = $iterator->sort_by(\&get_value, %options);
223 Get a new iterator draining from an existing iterator but providing items sorted by an object field. Sorting
224 is done using L<Unicode::Collate> (if available) or C<cmp> to sort alphanumerically. The C<\&get_value>
225 subroutine is called once for each item and should return a string value. Options:
228 * C<ascending> - Order ascending if true, descending otherwise (default: true)
229 * C<case> - If true, take case into account, otherwise ignore case (default: true)
230 * C<collate> - If true, use B<Unicode::Collate> (if available), otherwise use perl built-ins (default: true)
231 * Any B<Unicode::Collate> option is also supported.
233 C<sort_by> and C<order_by> are aliases.
235 B<NOTE:> This method drains the iterator completely but adds items back onto the buffer, so the iterator is
236 still usable afterward. Nevertheless, you mustn't call this on an infinite iterator
or it will run
until
237 available memory
is depleted
.
241 sub sort_by
{ shift-
>order_by(@_) }
242 sub nsort_by
{ shift-
>norder_by(@_) }
249 my $ascending = delete $args{ascending
} // !delete $args{descending
} // 1;
250 my $case = delete $args{case
} // !delete $args{no_case
} // 1;
251 my $collate = (delete $args{collate
} // !delete $args{no_collate
} // 1)
252 && try_load_optional
('Unicode::Collate');
254 if ($collate && !$case) {
256 # use a proper Unicode::Collate level to ignore case
259 $args{upper_before_lower
} //= 1;
262 $value = $case ? sub { $_[0]->$field // '' } : sub { uc($_[0]->$field) // '' } if !is_coderef
($value);
263 my @all = CORE
::map { [$_, $value->($_)] } @{$self->to_array};
266 my $c = Unicode
::Collate-
>new(%args);
268 @all = CORE
::map { $_->[0] } CORE
::sort { $c->cmp($a->[1], $b->[1]) } @all;
270 @all = CORE
::map { $_->[0] } CORE
::sort { $c->cmp($b->[1], $a->[1]) } @all;
274 @all = CORE
::map { $_->[0] } CORE
::sort { $a->[1] cmp $b->[1] } @all;
276 @all = CORE
::map { $_->[0] } CORE
::sort { $b->[1] cmp $a->[1] } @all;
288 \
&iterator
= $iterator->nsort_by($field, %options);
289 \
&iterator
= $iterator->nsort_by(\
&get_value
, %options);
291 Get a new iterator draining from an existing iterator but providing items sorted by an object field
. Sorting
292 is done numerically using C
<< <=> >>. The C
<\
&get_value
> subroutine
is called once
for each item
and should
293 return a numerical value
. Options
:
296 * C<ascending> - Order ascending if true, descending otherwise (default: true)
298 C<nsort_by> and C<norder_by> are aliases.
300 B<NOTE:> This method drains the iterator completely but adds items back onto the buffer, so the iterator is
301 still usable afterward. Nevertheless, you mustn't call this on an infinite iterator or it will run until
302 available memory is depleted.
311 my $ascending = $args{ascending
} // !$args{descending
} // 1;
314 $value = sub { $_[0]->$field // 0 } if !is_coderef
($value);
315 my @all = CORE
::map { [$_, $value->($_)] } @{$self->to_array};
318 @all = CORE
::map { $_->[0] } CORE
::sort { $a->[1] <=> $b->[1] } @all;
320 @all = CORE
::map { $_->[0] } CORE
::sort { $b->[1] <=> $a->[1] } @all;
329 \
@array = $iterator->to_array;
331 Get the rest of the items from an iterator as an arrayref
.
333 B
<NOTE
:> This
method drains the iterator completely
, leaving the iterator empty
. You mustn
't call this on an
334 infinite iterator or it will run until available memory is depleted.
342 push @all, $_ while defined (local $_ = $self->());
350 $size = $iterator->count;
352 Count the rest of the items from an iterator.
354 B<NOTE:> This method drains the iterator completely but adds items back onto the buffer, so the iterator is
355 still usable afterward. Nevertheless, you mustn't call this on an infinite iterator
or it will run
until
356 available memory
is depleted
.
363 my $items = $self->to_array;
365 return scalar @$items;
368 sub count
{ shift-
>size }
370 sub TO_JSON
{ $_[0]->to_array }
375 =for Pod::Coverage TO_JSON
380 ->grep(sub { $_->title =~ /bank/i })
389 A buffered iterator compatible with and expanding upon L<Iterator::Simple>, this provides an easy way to
390 navigate a L<File::KDBX> database.
394 This iterator is buffered, meaning it can drain from an iterator subroutine under the hood, storing items
395 temporarily to be accessed later. This allows features like L</peek> and L</sort> which might be useful in the
396 context of KDBX databases which are normally pretty small so draining an iterator isn't cost-prohibitive.
398 The way this works is that if you call an iterator without arguments, it acts like a normal iterator. If you
399 call it with arguments, however, the arguments are added to the buffer. When called without arguments, the
400 buffer is drained before the iterator function is. Using L</unget> is equivalent to calling the iterator with
401 arguments, and as L</next> is equivalent to calling the iterator without arguments.