1 package File
::KDBX
::Iterator
;
2 # PACKAGE: KDBX database iterator
8 use File
::KDBX
::Util
qw(:class :load :search);
11 use Ref
::Util
qw(is_arrayref is_coderef 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 Blesses 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
);
57 $item = $iterator->next([\'simple expression
', @fields]);
59 Get the next item or C<undef> if there are no more items. If a query is passed, get the next matching item,
60 discarding any items before the matching item that do not match. Example:
62 my $item = $iterator->next(sub { $_->label =~ /Gym/ });
70 if (is_coderef($code) || overload::Method($code, '&{}')) {
73 elsif (is_scalarref($code)) {
74 return simple_expression_query($$code, @_);
77 return query($code, @_);
83 my $code = shift or return $self->();
85 $code = $self->_create_query($code, @_);
87 while (defined (local $_ = $self->())) {
88 return $_ if $code->($_);
95 $item = $iterator->peek;
97 Peek at the next item. Returns C<undef> if the iterator is empty. This allows you to access the next item
98 without draining it from the iterator. The same item will be returned the next time L</next> is called.
105 my $next = $self->();
106 $self->($next) if defined $next;
112 $iterator->unget(\@items);
113 $iterator->unget(...);
115 $iterator->(\@items);
118 Replace the buffer or unshift one or more items to the current buffer.
125 my $self = shift; # Must shift in a statement before calling.
131 @items = $iterator->each;
133 $iterator->each(sub($item, $num) { ... });
135 Get the rest of the items. There are two forms: Without arguments, C<each> returns a list of the rest of the
136 items. Or pass a coderef to be called once per item, in order. The item is passed as the first argument to the
137 given subroutine and is also available as C<$_>.
143 my $cb = shift or return @{$self->to_array};
146 $cb->($_, $count++) while defined (local $_ = $self->());
152 \&iterator = $iterator->limit($count);
154 Get a new iterator draining from an existing iterator but providing only a limited number of items.
158 sub limit { shift->head(@_) }
162 \&iterator = $iterator->grep(\&query);
163 \&iterator = $iterator->grep([\'simple expression', @fields]);
165 Get a new iterator draining from an existing iterator but providing only items that pass a test
or are matched
174 $code = $self->_create_query($code, @_);
176 ref($self)->new(sub {
177 while (defined (local $_ = $self->())) {
178 return $_ if $code->($_);
186 \
&iterator
= $iterator->map(\
&code
);
188 Get a new iterator draining from an existing iterator but providing modified items
.
196 ref($self)->new(sub {
197 local $_ = $self->();
198 return if !defined $_;
205 \
&iterator
= $iterator->filter(\
&query
);
206 \
&iterator
= $iterator->filter([\'simple expression
', @fields]);
208 See L<Iterator::Simple/"ifilter $iterable, sub{ CODE }">.
215 return $self->SUPER::filter($self->_create_query($code, @_));
222 \&iterator = $iterator->sort_by($field, %options);
223 \&iterator = $iterator->sort_by(\&get_value, %options);
225 Get a new iterator draining from an existing iterator but providing items sorted by an object field. Sorting
226 is done using L<Unicode::Collate> (if available) or C<cmp> to sort alphanumerically. The C<\&get_value>
227 subroutine is called once for each item and should return a string value. Options:
230 * C<ascending> - Order ascending if true, descending otherwise (default: true)
231 * C<case> - If true, take case into account, otherwise ignore case (default: true)
232 * C<collate> - If true, use B<Unicode::Collate> (if available), otherwise use perl built-ins (default: true)
233 * Any B<Unicode::Collate> option is also supported.
235 C<sort_by> and C<order_by> are aliases.
237 B<NOTE:> This method drains the iterator completely but adds items back onto the buffer, so the iterator is
238 still usable afterward. Nevertheless, you mustn't call this on an infinite iterator
or it will run
until
239 available memory
is depleted
.
243 sub sort_by
{ shift-
>order_by(@_) }
244 sub nsort_by
{ shift-
>norder_by(@_) }
251 my $ascending = delete $args{ascending
} // !delete $args{descending
} // 1;
252 my $case = delete $args{case
} // !delete $args{no_case
} // 1;
253 my $collate = (delete $args{collate
} // !delete $args{no_collate
} // 1)
254 && try_load_optional
('Unicode::Collate');
256 if ($collate && !$case) {
258 # use a proper Unicode::Collate level to ignore case
261 $args{upper_before_lower
} //= 1;
264 $value = $case ? sub { $_[0]->$field // '' } : sub { uc($_[0]->$field) // '' } if !is_coderef
($value);
265 my @all = CORE
::map { [$_, $value->($_)] } @{$self->to_array};
268 my $c = Unicode
::Collate-
>new(%args);
270 @all = CORE
::map { $_->[0] } CORE
::sort { $c->cmp($a->[1], $b->[1]) } @all;
272 @all = CORE
::map { $_->[0] } CORE
::sort { $c->cmp($b->[1], $a->[1]) } @all;
276 @all = CORE
::map { $_->[0] } CORE
::sort { $a->[1] cmp $b->[1] } @all;
278 @all = CORE
::map { $_->[0] } CORE
::sort { $b->[1] cmp $a->[1] } @all;
290 \
&iterator
= $iterator->nsort_by($field, %options);
291 \
&iterator
= $iterator->nsort_by(\
&get_value
, %options);
293 Get a new iterator draining from an existing iterator but providing items sorted by an object field
. Sorting
294 is done numerically using C
<< <=> >>. The C
<\
&get_value
> subroutine
is called once
for each item
and should
295 return a numerical value
. Options
:
298 * C<ascending> - Order ascending if true, descending otherwise (default: true)
300 C<nsort_by> and C<norder_by> are aliases.
302 B<NOTE:> This method drains the iterator completely but adds items back onto the buffer, so the iterator is
303 still usable afterward. Nevertheless, you mustn't call this on an infinite iterator or it will run until
304 available memory is depleted.
313 my $ascending = $args{ascending
} // !$args{descending
} // 1;
316 $value = sub { $_[0]->$field // 0 } if !is_coderef
($value);
317 my @all = CORE
::map { [$_, $value->($_)] } @{$self->to_array};
320 @all = CORE
::map { $_->[0] } CORE
::sort { $a->[1] <=> $b->[1] } @all;
322 @all = CORE
::map { $_->[0] } CORE
::sort { $b->[1] <=> $a->[1] } @all;
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 the iterator empty
. You mustn
't call this on an
336 infinite iterator or it will run until available memory is depleted.
344 push @all, $_ while defined (local $_ = $self->());
352 $size = $iterator->count;
354 Count the rest of the items from an iterator.
356 B<NOTE:> This method drains the iterator completely but adds items back onto the buffer, so the iterator is
357 still usable afterward. Nevertheless, you mustn't call this on an infinite iterator
or it will run
until
358 available memory
is depleted
.
365 my $items = $self->to_array;
367 return scalar @$items;
370 sub count
{ shift-
>size }
372 sub TO_JSON
{ $_[0]->to_array }
377 =for Pod::Coverage TO_JSON
382 ->grep(sub { $_->title =~ /bank/i })
391 A buffered iterator compatible with and expanding upon L<Iterator::Simple>, this provides an easy way to
392 navigate a L<File::KDBX> database.
396 This iterator is buffered, meaning it can drain from an iterator subroutine under the hood, storing items
397 temporarily to be accessed later. This allows features like L</peek> and L</sort> which might be useful in the
398 context of KDBX databases which are normally pretty small so draining an iterator isn't cost-prohibitive.
400 The way this works is that if you call an iterator without arguments, it acts like a normal iterator. If you
401 call it with arguments, however, the arguments are added to the buffer. When called without arguments, the
402 buffer is drained before the iterator function is. Using L</unget> is equivalent to calling the iterator with
403 arguments, and as L</next> is equivalent to calling the iterator without arguments.