]>
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.905' ; # 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 by 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);
333 \&iterator = $iterator->grep(sub($item) { ... });
335 Get a new iterator draining from an existing iterator but providing only items that pass a test or are matched
336 by a query. In its basic form this method is very much like perl's built-in grep function, except for
339 There are many examples of the various forms of this method at L<File::KDBX/QUERY>.
343 \&iterator = $iterator->map(\&code);
345 Get a new iterator draining from an existing iterator but providing modified items. In its basic form this
346 method is very much like perl's built-in map function, except for iterators.
350 \&iterator = $iterator->sort_by($field, %options);
351 \&iterator = $iterator->sort_by(\&get_value, %options);
353 Get a new iterator draining from an existing iterator but providing items sorted by an object field. Sorting
354 is done using L<Unicode::Collate> (if available) or C<cmp> to sort alphanumerically. The C<\&get_value>
355 subroutine is called once for each item and should return a string value. Options:
361 C<ascending> - Order ascending if true, descending otherwise (default: true)
365 C<case> - If true, take case into account, otherwise ignore case (default: true)
369 C<collate> - If true, use B<Unicode::Collate> (if available), otherwise use perl built-ins (default: true)
373 Any B<Unicode::Collate> option is also supported.
377 B<NOTE:> This method drains the iterator completely and places the sorted items onto the buffer. See
382 Alias for L</order_by>.
386 \&iterator = $iterator->nsort_by($field, %options);
387 \&iterator = $iterator->nsort_by(\&get_value, %options);
389 Get a new iterator draining from an existing iterator but providing items sorted by an object field. Sorting
390 is done numerically using C<< <=> >>. The C<\&get_value> subroutine or C<$field> accessor is called once for
391 each item and should return a numerical value. Options:
397 C<ascending> - Order ascending if true, descending otherwise (default: true)
401 B<NOTE:> This method drains the iterator completely and places the sorted items onto the buffer. See
406 Alias for L</norder_by>.
410 \&iterator = $iterator->limit($count);
412 Get a new iterator draining from an existing iterator but providing only a limited number of items.
414 C<limit> is an alias for L<< Iterator::Simple/"$iterator->head($count)" >>.
418 \@array = $iterator->to_array;
420 Get the rest of the items from an iterator as an arrayref.
422 B<NOTE:> This method drains the iterator completely, leaving it empty. See L</CAVEATS>.
426 $size = $iterator->count;
428 Count the rest of the items from an iterator.
430 B<NOTE:> This method drains the iterator completely but restores it to its pre-drained state. See L</CAVEATS>.
436 =for Pod::Coverage TO_JSON
440 Some methods attempt to drain the iterator completely before returning. For obvious reasons, this won't work
441 for infinite iterators because your computer doesn't have infinite memory. This isn't a practical issue with
442 B<File::KDBX> lists which are always finite -- unless you do something weird like force a child group to be
443 its own ancestor -- but I'm noting it here as a potential issue if you use this iterator class for other
444 things (which you probably shouldn't do).
446 KDBX databases are always fully-loaded into memory anyway, so there's not a significant memory cost to
447 draining an iterator completely.
451 Please report any bugs or feature requests on the bugtracker website
452 L<https://github.com/chazmcgarvey/File-KDBX/issues>
454 When submitting a bug or request, please include a test-file or a
455 patch to an existing test-file that illustrates the bug or desired
460 Charles McGarvey <ccm@cpan.org>
462 =head1 COPYRIGHT AND LICENSE
464 This software is copyright (c) 2022 by Charles McGarvey.
466 This is free software; you can redistribute it and/or modify it under
467 the same terms as the Perl 5 programming language system itself.
This page took 0.063832 seconds and 4 git commands to generate.