1 package File
::KDBX
::Iterator
;
2 # ABSTRACT: KDBX database iterator
8 use File
::KDBX
::Util
qw(:class :load :search);
11 use Ref
::Util
qw(is_arrayref is_coderef is_ref is_scalarref);
14 BEGIN { mark_as_loaded
('Iterator::Simple::Iterator') }
15 extends
'Iterator::Simple::Iterator';
17 our $VERSION = '999.999'; # VERSION
21 \
&iterator
= File
::KDBX
::Iterator-
>new(\
&iterator
);
23 Bless an iterator to augment it with buffering plus some useful utility methods
.
29 my $code = is_coderef
($_[0]) ? shift : sub { undef };
31 my $items = @_ == 1 && is_arrayref
($_[0]) ? $_[0] : \
@_;
32 return $class->SUPER::new
(sub {
34 if (@_ == 1 && is_arrayref
($_[0])) {
43 my $next = shift @$items;
44 return $next if defined $next;
52 $item = $iterator->next;
54 $item = $iterator->();
56 $item = $iterator->next(\
&query
);
58 Get the
next item
or C
<undef> if there are
no more items
. If a query
is passed
, get the
next matching item
,
59 discarding any unmatching items before the matching item
. Example
:
61 my $item = $iterator->next(sub { $_->label =~ /Gym/ });
67 my $code = shift or return $self->();
69 $code = query_any
($code, @_);
71 while (defined (local $_ = $self->())) {
72 return $_ if $code->($_);
79 $item = $iterator->peek;
81 Peek at the
next item
. Returns C
<undef> if the iterator
is empty
. This allows you to access the
next item
82 without draining it from the iterator
. The same item will be returned the
next time L
</next> is called
.
90 $self->($next) if defined $next;
97 $iterator->unget(\
@items);
101 # Unshift onto buffer:
102 $iterator->unget(@items);
106 Replace the buffer
(first form
) or unshift one
or more items to the current buffer
(second form
).
113 my $self = shift; # Must shift in a statement before calling.
119 @items = $iterator->each;
121 $iterator->each(sub($item, $num, @args) { ... }, @args);
123 $iterator->each($method_name, ...);
125 Get
or act on the rest of the items
. This
method has three forms
:
128 1. Without arguments, C<each> returns a list of the rest of the items.
129 2. Pass a coderef to be called once per item, in order. Arguments to the coderef are the item itself (also
130 available as C<$_>), its index number and then any extra arguments that were passed to C<each> after the
132 3. Pass a string that is the name of a method to be called on each object, in order. Any extra arguments
133 passed to C<each> after the method name are passed through to each method call. This form requires each
134 item be an object that C<can> the given method.
136 B<NOTE:> This method drains the iterator completely, leaving it empty. See L</CAVEATS>.
142 my $cb = shift or return @{$self->to_array};
144 if (is_coderef
($cb)) {
146 $cb->($_, $count++, @_) while defined (local $_ = $self->());
148 elsif (!is_ref
($cb)) {
149 $_->$cb(@_) while defined (local $_ = $self->());
158 \
&iterator
= $iterator->grep(\
&query
);
159 \
&iterator
= $iterator->grep(sub($item) { ... });
161 Get a new iterator draining from an existing iterator but providing only items that pass a test
or are matched
162 by a query
. In its basic form this
method is very much like perl
's built-in grep function, except for
165 There are many examples of the various forms of this method at L<File::KDBX/QUERY>.
169 sub where { shift->grep(@_) }
173 my $code = query_any(@_);
175 ref($self)->new(sub {
176 while (defined (local $_ = $self->())) {
177 return $_ if $code->($_);
185 \&iterator = $iterator->map(\&code);
187 Get a new iterator draining from an existing iterator but providing modified items. In its basic form this
188 method is very much like perl's built-in
map function
, except
for iterators
.
196 ref($self)->new(sub {
197 local $_ = $self->();
198 return if !defined $_;
205 \
&iterator
= $iterator->sort_by($field, %options);
206 \
&iterator
= $iterator->sort_by(\
&get_value
, %options);
208 Get a new iterator draining from an existing iterator but providing items sorted by an object field
. Sorting
209 is done using L
<Unicode
::Collate
> (if available
) or C
<cmp> to
sort alphanumerically
. The C
<\
&get_value
>
210 subroutine
is called once
for each item
and should
return a string value
. Options
:
213 * C<ascending> - Order ascending if true, descending otherwise (default: true)
214 * C<case> - If true, take case into account, otherwise ignore case (default: true)
215 * C<collate> - If true, use B<Unicode::Collate> (if available), otherwise use perl built-ins (default: true)
216 * Any B<Unicode::Collate> option is also supported.
218 B<NOTE:> This method drains the iterator completely and places the sorted items onto the buffer. See
228 my $ascending = delete $args{ascending
} // !delete $args{descending
} // 1;
229 my $case = delete $args{case
} // !delete $args{no_case
} // 1;
230 my $collate = (delete $args{collate
} // !delete $args{no_collate
} // 1)
231 && try_load_optional
('Unicode::Collate');
233 if ($collate && !$case) {
235 # use a proper Unicode::Collate level to ignore case
238 $args{upper_before_lower
} //= 1;
241 $value = $case ? sub { $_[0]->$field // '' } : sub { uc($_[0]->$field) // '' } if !is_coderef
($value);
242 my @all = CORE
::map { [$_, $value->($_)] } @{$self->to_array};
245 my $c = Unicode
::Collate-
>new(%args);
247 @all = CORE
::map { $_->[0] } CORE
::sort { $c->cmp($a->[1], $b->[1]) } @all;
249 @all = CORE
::map { $_->[0] } CORE
::sort { $c->cmp($b->[1], $a->[1]) } @all;
253 @all = CORE
::map { $_->[0] } CORE
::sort { $a->[1] cmp $b->[1] } @all;
255 @all = CORE
::map { $_->[0] } CORE
::sort { $b->[1] cmp $a->[1] } @all;
265 Alias
for L
</order_by
>.
269 sub sort_by
{ shift-
>order_by(@_) }
273 \
&iterator
= $iterator->nsort_by($field, %options);
274 \
&iterator
= $iterator->nsort_by(\
&get_value
, %options);
276 Get a new iterator draining from an existing iterator but providing items sorted by an object field
. Sorting
277 is done numerically using C
<< <=> >>. The C
<\
&get_value
> subroutine
or C
<$field> accessor
is called once
for
278 each item
and should
return a numerical value
. Options
:
281 * C<ascending> - Order ascending if true, descending otherwise (default: true)
283 B<NOTE:> This method drains the iterator completely and places the sorted items onto the buffer. See
293 my $ascending = $args{ascending
} // !$args{descending
} // 1;
296 $value = sub { $_[0]->$field // 0 } if !is_coderef
($value);
297 my @all = CORE
::map { [$_, $value->($_)] } @{$self->to_array};
300 @all = CORE
::map { $_->[0] } CORE
::sort { $a->[1] <=> $b->[1] } @all;
302 @all = CORE
::map { $_->[0] } CORE
::sort { $b->[1] <=> $a->[1] } @all;
311 Alias
for L
</norder_by
>.
315 sub nsort_by
{ shift-
>norder_by(@_) }
319 \
&iterator
= $iterator->limit($count);
321 Get a new iterator draining from an existing iterator but providing only a limited number of items
.
323 C
<limit
> is an alias
for L
<< Iterator
::Simple
/"$iterator->head($count)" >>.
327 sub limit
{ shift-
>head(@_) }
331 \
@array = $iterator->to_array;
333 Get the rest of the items from an iterator as an arrayref
.
335 B
<NOTE
:> This
method drains the iterator completely
, leaving it empty
. See L
</CAVEATS
>.
343 push @all, $_ while defined (local $_ = $self->());
349 $size = $iterator->count;
351 Count the rest of the items from an iterator
.
353 B
<NOTE
:> This
method drains the iterator completely but restores it to its pre-drained
state. See L
</CAVEATS
>.
360 my $items = $self->to_array;
362 return scalar @$items;
371 sub size
{ shift-
>count }
373 ##############################################################################
375 sub TO_JSON
{ $_[0]->to_array }
380 =for Pod::Coverage TO_JSON
384 my $kdbx = File::KDBX->load('database.kdbx', 'masterpw');
387 ->where(sub { $_->title =~ /bank/i })
396 A buffered iterator compatible with and expanding upon L<Iterator::Simple>, this provides an easy way to
397 navigate a L<File::KDBX> database. The documentation for B<Iterator::Simple> documents functions and methods
398 supported by this iterator that are not documented here, so consider that additional reading.
402 This iterator is buffered, meaning it can drain from an iterator subroutine under the hood, storing items
403 temporarily to be accessed later. This allows features like L</peek> and L</order_by> which might be useful in
404 the context of KDBX databases which are normally pretty small so draining an iterator completely isn't
405 cost-prohibitive in terms of memory usage.
407 The way this works is that if you call an iterator without arguments, it acts like a normal iterator. If you
408 call it with arguments, however, the arguments are added to the buffer. When called without arguments, the
409 buffer is drained before the iterator function is. Using L</unget> is equivalent to calling the iterator with
410 arguments, and L</next> is equivalent to calling the iterator without arguments.
414 Some methods attempt to drain the iterator completely before returning. For obvious reasons, this won't work
415 for infinite iterators because your computer doesn't have infinite memory. This isn't a practical issue with
416 B<File::KDBX> lists which are always finite -- unless you do something weird like force a child group to be
417 its own ancestor -- but I'm noting it here as a potential issue if you use this iterator class for other
418 things (which you probably shouldn't do).
420 KDBX databases are always fully-loaded into memory anyway, so there's not a significant memory cost to
421 draining an iterator completely.