]>
Dogcows Code - chaz/p5-File-KDBX/blob - lib/File/KDBX/Iterator.pm
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 = '0.901' ; # VERSION
22 my $code = is_coderef
( $_ [ 0 ]) ? shift : sub { undef };
24 my $items = @_ == 1 && is_arrayref
( $_ [ 0 ]) ? $_ [ 0 ] : \
@_ ;
25 return $class -> SUPER :: new
( sub {
27 if ( @_ == 1 && is_arrayref
( $_ [ 0 ])) {
36 my $next = shift @$items ;
37 return $next if defined $next ;
46 my $code = shift or return $self ->();
48 $code = query_any
( $code , @_ );
50 while ( defined ( local $_ = $self ->())) {
51 return $_ if $code ->( $_ );
61 $self ->( $next ) if defined $next ;
67 my $self = shift ; # Must shift in a statement before calling.
74 my $cb = shift or return @{ $self -> to_array };
76 if ( is_coderef
( $cb )) {
78 $cb ->( $_ , $count++ , @_ ) while defined ( local $_ = $self ->());
80 elsif (! is_ref
( $cb )) {
81 $_ -> $cb ( @_ ) while defined ( local $_ = $self ->());
87 sub where
{ shift-
> grep ( @_ ) }
91 my $code = query_any
( @_ );
94 while ( defined ( local $_ = $self ->())) {
95 return $_ if $code ->( $_ );
106 ref ( $self )-> new ( sub {
107 local $_ = $self ->();
108 return if ! defined $_ ;
119 my $ascending = delete $args { ascending
} // ! delete $args { descending
} // 1 ;
120 my $case = delete $args { case
} // ! delete $args { no_case
} // 1 ;
121 my $collate = ( delete $args { collate
} // ! delete $args { no_collate
} // 1 )
122 && try_load_optional
( 'Unicode::Collate' );
124 if ( $collate && ! $case ) {
126 # use a proper Unicode::Collate level to ignore case
129 $args { upper_before_lower
} // = 1 ;
132 $value = $case ? sub { $_ [ 0 ]-> $field // '' } : sub { uc ( $_ [ 0 ]-> $field ) // '' } if ! is_coderef
( $value );
133 my @all = CORE
:: map { [ $_ , $value ->( $_ )] } @{ $self -> to_array };
136 my $c = Unicode
:: Collate-
> new ( %args );
138 @all = CORE
:: map { $_ ->[ 0 ] } CORE
:: sort { $c -> cmp ( $a ->[ 1 ], $b ->[ 1 ]) } @all ;
140 @all = CORE
:: map { $_ ->[ 0 ] } CORE
:: sort { $c -> cmp ( $b ->[ 1 ], $a ->[ 1 ]) } @all ;
144 @all = CORE
:: map { $_ ->[ 0 ] } CORE
:: sort { $a ->[ 1 ] cmp $b ->[ 1 ] } @all ;
146 @all = CORE
:: map { $_ ->[ 0 ] } CORE
:: sort { $b ->[ 1 ] cmp $a ->[ 1 ] } @all ;
155 sub sort_by
{ shift-
> order_by ( @_ ) }
163 my $ascending = $args { ascending
} // ! $args { descending
} // 1 ;
166 $value = sub { $_ [ 0 ]-> $field // 0 } if ! is_coderef
( $value );
167 my @all = CORE
:: map { [ $_ , $value ->( $_ )] } @{ $self -> to_array };
170 @all = CORE
:: map { $_ ->[ 0 ] } CORE
:: sort { $a ->[ 1 ] <=> $b ->[ 1 ] } @all ;
172 @all = CORE
:: map { $_ ->[ 0 ] } CORE
:: sort { $b ->[ 1 ] <=> $a ->[ 1 ] } @all ;
180 sub nsort_by
{ shift-
> norder_by ( @_ ) }
183 sub limit
{ shift-
> head ( @_ ) }
190 push @all , $_ while defined ( local $_ = $self ->());
198 my $items = $self -> to_array ;
200 return scalar @$items ;
204 sub size
{ shift-
> count }
206 ##############################################################################
208 sub TO_JSON
{ $_ [ 0 ]-> to_array }
220 File::KDBX::Iterator - KDBX database iterator
228 my $kdbx = File::KDBX->load('database.kdbx', 'masterpw');
231 ->where(sub { $_->title =~ /bank/i })
240 A buffered iterator compatible with and expanding upon L<Iterator::Simple>, this provides an easy way to
241 navigate a L<File::KDBX> database. The documentation for B<Iterator::Simple> documents functions and methods
242 supported but this iterator that are not documented here, so consider that additional reading.
246 This iterator is buffered, meaning it can drain from an iterator subroutine under the hood, storing items
247 temporarily to be accessed later. This allows features like L</peek> and L</order_by> which might be useful in
248 the context of KDBX databases which are normally pretty small so draining an iterator completely isn't
249 cost-prohibitive in terms of memory usage.
251 The way this works is that if you call an iterator without arguments, it acts like a normal iterator. If you
252 call it with arguments, however, the arguments are added to the buffer. When called without arguments, the
253 buffer is drained before the iterator function is. Using L</unget> is equivalent to calling the iterator with
254 arguments, and L</next> is equivalent to calling the iterator without arguments.
260 \&iterator = File::KDBX::Iterator->new(\&iterator);
262 Bless an iterator to augment it with buffering plus some useful utility methods.
266 $item = $iterator->next;
268 $item = $iterator->();
270 $item = $iterator->next(\&query);
272 Get the next item or C<undef> if there are no more items. If a query is passed, get the next matching item,
273 discarding any unmatching items before the matching item. Example:
275 my $item = $iterator->next(sub { $_->label =~ /Gym/ });
279 $item = $iterator->peek;
281 Peek at the next item. Returns C<undef> if the iterator is empty. This allows you to access the next item
282 without draining it from the iterator. The same item will be returned the next time L</next> is called.
287 $iterator->unget(\@items);
289 $iterator->(\@items);
291 # Unshift onto buffer:
292 $iterator->unget(@items);
296 Replace the buffer (first form) or unshift one or more items to the current buffer (second form).
302 @items = $iterator->each;
304 $iterator->each(sub($item, $num, @args) { ... }, @args);
306 $iterator->each($method_name, ...);
308 Get or act on the rest of the items. This method has three forms:
314 Without arguments, C<each> returns a list of the rest of the items.
318 Pass a coderef to be called once per item, in order. Arguments to the coderef are the item itself (also available as C<$_>), its index number and then any extra arguments that were passed to C<each> after the coderef.
322 Pass a string that is the name of a method to be called on each object, in order. Any extra arguments passed to C<each> after the method name are passed through to each method call. This form requires each item be an object that C<can> the given method.
326 B<NOTE:> This method drains the iterator completely, leaving it empty. See L</CAVEATS>.
332 \&iterator = $iterator->grep(\&query);
334 Get a new iterator draining from an existing iterator but providing only items that pass a test or are matched
335 by a query. In its basic form this method is very much like perl's built-in grep function, except for
338 There are many examples of the various forms of this method at L<File::KDBX/QUERY>.
342 \&iterator = $iterator->map(\&code);
344 Get a new iterator draining from an existing iterator but providing modified items. In its basic form this
345 method is very much like perl's built-in map function, except for iterators.
349 \&iterator = $iterator->sort_by($field, %options);
350 \&iterator = $iterator->sort_by(\&get_value, %options);
352 Get a new iterator draining from an existing iterator but providing items sorted by an object field. Sorting
353 is done using L<Unicode::Collate> (if available) or C<cmp> to sort alphanumerically. The C<\&get_value>
354 subroutine is called once for each item and should return a string value. Options:
360 C<ascending> - Order ascending if true, descending otherwise (default: true)
364 C<case> - If true, take case into account, otherwise ignore case (default: true)
368 C<collate> - If true, use B<Unicode::Collate> (if available), otherwise use perl built-ins (default: true)
372 Any B<Unicode::Collate> option is also supported.
376 B<NOTE:> This method drains the iterator completely and places the sorted items onto the buffer. See
381 Alias for L</order_by>.
385 \&iterator = $iterator->nsort_by($field, %options);
386 \&iterator = $iterator->nsort_by(\&get_value, %options);
388 Get a new iterator draining from an existing iterator but providing items sorted by an object field. Sorting
389 is done numerically using C<< <=> >>. The C<\&get_value> subroutine or C<$field> accessor is called once for
390 each item and should return a numerical value. Options:
396 C<ascending> - Order ascending if true, descending otherwise (default: true)
400 B<NOTE:> This method drains the iterator completely and places the sorted items onto the buffer. See
405 Alias for L</norder_by>.
409 \&iterator = $iterator->limit($count);
411 Get a new iterator draining from an existing iterator but providing only a limited number of items.
413 C<limit> as an alias for L<< Iterator::Simple/"$iterator->head($count)" >>.
417 \@array = $iterator->to_array;
419 Get the rest of the items from an iterator as an arrayref.
421 B<NOTE:> This method drains the iterator completely, leaving it empty. See L</CAVEATS>.
425 $size = $iterator->count;
427 Count the rest of the items from an iterator.
429 B<NOTE:> This method drains the iterator completely but restores it to its pre-drained state. See L</CAVEATS>.
435 =for Pod::Coverage TO_JSON
439 Some methods attempt to drain the iterator completely before returning. For obvious reasons, this won't work
440 for infinite iterators because your computer doesn't have infinite memory. This isn't a practical issue with
441 B<File::KDBX> lists which are always finite -- unless you do something weird like force a child group to be
442 its own ancestor -- but I'm noting it here as a potential issue if you use this iterator class for other
443 things (which you probably shouldn't do).
447 Please report any bugs or feature requests on the bugtracker website
448 L<https://github.com/chazmcgarvey/File-KDBX/issues>
450 When submitting a bug or request, please include a test-file or a
451 patch to an existing test-file that illustrates the bug or desired
456 Charles McGarvey <ccm@cpan.org>
458 =head1 COPYRIGHT AND LICENSE
460 This software is copyright (c) 2022 by Charles McGarvey.
462 This is free software; you can redistribute it and/or modify it under
463 the same terms as the Perl 5 programming language system itself.
This page took 0.066776 seconds and 4 git commands to generate.