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
);
160 Get a new iterator draining from an existing iterator but providing only items that pass a test
or are matched
161 by a query
. In its basic form this
method is very much like perl
's built-in grep function, except for
164 There are many examples of the various forms of this method at L<File::KDBX/QUERY>.
168 sub where { shift->grep(@_) }
172 my $code = query_any(@_);
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. In its basic form this
187 method is very much like perl's built-in
map function
, except
for iterators
.
195 ref($self)->new(sub {
196 local $_ = $self->();
197 return if !defined $_;
204 \
&iterator
= $iterator->sort_by($field, %options);
205 \
&iterator
= $iterator->sort_by(\
&get_value
, %options);
207 Get a new iterator draining from an existing iterator but providing items sorted by an object field
. Sorting
208 is done using L
<Unicode
::Collate
> (if available
) or C
<cmp> to
sort alphanumerically
. The C
<\
&get_value
>
209 subroutine
is called once
for each item
and should
return a string value
. Options
:
212 * C<ascending> - Order ascending if true, descending otherwise (default: true)
213 * C<case> - If true, take case into account, otherwise ignore case (default: true)
214 * C<collate> - If true, use B<Unicode::Collate> (if available), otherwise use perl built-ins (default: true)
215 * Any B<Unicode::Collate> option is also supported.
217 B<NOTE:> This method drains the iterator completely and places the sorted items onto the buffer. See
227 my $ascending = delete $args{ascending
} // !delete $args{descending
} // 1;
228 my $case = delete $args{case
} // !delete $args{no_case
} // 1;
229 my $collate = (delete $args{collate
} // !delete $args{no_collate
} // 1)
230 && try_load_optional
('Unicode::Collate');
232 if ($collate && !$case) {
234 # use a proper Unicode::Collate level to ignore case
237 $args{upper_before_lower
} //= 1;
240 $value = $case ? sub { $_[0]->$field // '' } : sub { uc($_[0]->$field) // '' } if !is_coderef
($value);
241 my @all = CORE
::map { [$_, $value->($_)] } @{$self->to_array};
244 my $c = Unicode
::Collate-
>new(%args);
246 @all = CORE
::map { $_->[0] } CORE
::sort { $c->cmp($a->[1], $b->[1]) } @all;
248 @all = CORE
::map { $_->[0] } CORE
::sort { $c->cmp($b->[1], $a->[1]) } @all;
252 @all = CORE
::map { $_->[0] } CORE
::sort { $a->[1] cmp $b->[1] } @all;
254 @all = CORE
::map { $_->[0] } CORE
::sort { $b->[1] cmp $a->[1] } @all;
264 Alias
for L
</order_by
>.
268 sub sort_by
{ shift-
>order_by(@_) }
272 \
&iterator
= $iterator->nsort_by($field, %options);
273 \
&iterator
= $iterator->nsort_by(\
&get_value
, %options);
275 Get a new iterator draining from an existing iterator but providing items sorted by an object field
. Sorting
276 is done numerically using C
<< <=> >>. The C
<\
&get_value
> subroutine
or C
<$field> accessor
is called once
for
277 each item
and should
return a numerical value
. Options
:
280 * C<ascending> - Order ascending if true, descending otherwise (default: true)
282 B<NOTE:> This method drains the iterator completely and places the sorted items onto the buffer. See
292 my $ascending = $args{ascending
} // !$args{descending
} // 1;
295 $value = sub { $_[0]->$field // 0 } if !is_coderef
($value);
296 my @all = CORE
::map { [$_, $value->($_)] } @{$self->to_array};
299 @all = CORE
::map { $_->[0] } CORE
::sort { $a->[1] <=> $b->[1] } @all;
301 @all = CORE
::map { $_->[0] } CORE
::sort { $b->[1] <=> $a->[1] } @all;
310 Alias
for L
</norder_by
>.
314 sub nsort_by
{ shift-
>norder_by(@_) }
318 \
&iterator
= $iterator->limit($count);
320 Get a new iterator draining from an existing iterator but providing only a limited number of items
.
322 C
<limit
> as an alias
for L
<< Iterator
::Simple
/"$iterator->head($count)" >>.
326 sub limit
{ shift-
>head(@_) }
330 \
@array = $iterator->to_array;
332 Get the rest of the items from an iterator as an arrayref
.
334 B
<NOTE
:> This
method drains the iterator completely
, leaving it empty
. See L
</CAVEATS
>.
342 push @all, $_ while defined (local $_ = $self->());
348 $size = $iterator->count;
350 Count the rest of the items from an iterator
.
352 B
<NOTE
:> This
method drains the iterator completely but restores it to its pre-drained
state. See L
</CAVEATS
>.
359 my $items = $self->to_array;
361 return scalar @$items;
370 sub size
{ shift-
>count }
372 ##############################################################################
374 sub TO_JSON
{ $_[0]->to_array }
379 =for Pod::Coverage TO_JSON
383 my $kdbx = File::KDBX->load('database.kdbx', 'masterpw');
386 ->where(sub { $_->title =~ /bank/i })
395 A buffered iterator compatible with and expanding upon L<Iterator::Simple>, this provides an easy way to
396 navigate a L<File::KDBX> database. The documentation for B<Iterator::Simple> documents functions and methods
397 supported but this iterator that are not documented here, so consider that additional reading.
401 This iterator is buffered, meaning it can drain from an iterator subroutine under the hood, storing items
402 temporarily to be accessed later. This allows features like L</peek> and L</order_by> which might be useful in
403 the context of KDBX databases which are normally pretty small so draining an iterator completely isn't
404 cost-prohibitive in terms of memory usage.
406 The way this works is that if you call an iterator without arguments, it acts like a normal iterator. If you
407 call it with arguments, however, the arguments are added to the buffer. When called without arguments, the
408 buffer is drained before the iterator function is. Using L</unget> is equivalent to calling the iterator with
409 arguments, and L</next> is equivalent to calling the iterator without arguments.
413 Some methods attempt to drain the iterator completely before returning. For obvious reasons, this won't work
414 for infinite iterators because your computer doesn't have infinite memory. This isn't a practical issue with
415 B<File::KDBX> lists which are always finite -- unless you do something weird like force a child group to be
416 its own ancestor -- but I'm noting it here as a potential issue if you use this iterator class for other
417 things (which you probably shouldn't do).