The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

NAME

File::KDBX::Iterator - KDBX database iterator

VERSION

version 0.906

SYNOPSIS

    my $kdbx = File::KDBX->load('database.kdbx', 'masterpw');

    $kdbx->entries
        ->where(sub { $_->title =~ /bank/i })
        ->order_by('title')
        ->limit(5)
        ->each(sub {
            say $_->title;
        });

DESCRIPTION

A buffered iterator compatible with and expanding upon Iterator::Simple, this provides an easy way to navigate a File::KDBX database. The documentation for Iterator::Simple documents functions and methods supported by this iterator that are not documented here, so consider that additional reading.

Buffer

This iterator is buffered, meaning it can drain from an iterator subroutine under the hood, storing items temporarily to be accessed later. This allows features like "peek" and "order_by" which might be useful in the context of KDBX databases which are normally pretty small so draining an iterator completely isn't cost-prohibitive in terms of memory usage.

The way this works is that if you call an iterator without arguments, it acts like a normal iterator. If you call it with arguments, however, the arguments are added to the buffer. When called without arguments, the buffer is drained before the iterator function is. Using "unget" is equivalent to calling the iterator with arguments, and "next" is equivalent to calling the iterator without arguments.

METHODS

new

    \&iterator = File::KDBX::Iterator->new(\&iterator);

Bless an iterator to augment it with buffering plus some useful utility methods.

next

    $item = $iterator->next;
    # OR equivalently
    $item = $iterator->();

    $item = $iterator->next(\&query);

Get the next item or undef if there are no more items. If a query is passed, get the next matching item, discarding any unmatching items before the matching item. Example:

    my $item = $iterator->next(sub { $_->label =~ /Gym/ });

peek

    $item = $iterator->peek;

Peek at the next item. Returns undef if the iterator is empty. This allows you to access the next item without draining it from the iterator. The same item will be returned the next time "next" is called.

unget

    # Replace buffer:
    $iterator->unget(\@items);
    # OR equivalently
    $iterator->(\@items);

    # Unshift onto buffer:
    $iterator->unget(@items);
    # OR equivalently
    $iterator->(@items);

Replace the buffer (first form) or unshift one or more items to the current buffer (second form).

See "Buffer".

each

    @items = $iterator->each;

    $iterator->each(sub($item, $num, @args) { ... }, @args);

    $iterator->each($method_name, ...);

Get or act on the rest of the items. This method has three forms:

  1. Without arguments, each returns a list of the rest of the items.

  2. Pass a coderef to be called once per item, in order. Arguments to the coderef are the item itself (also available as $_), its index number and then any extra arguments that were passed to each after the coderef.

  3. Pass a string that is the name of a method to be called on each object, in order. Any extra arguments passed to each after the method name are passed through to each method call. This form requires each item be an object that can the given method.

NOTE: This method drains the iterator completely, leaving it empty. See "CAVEATS".

grep

where

    \&iterator = $iterator->grep(\&query);
    \&iterator = $iterator->grep(sub($item) { ... });

Get a new iterator draining from an existing iterator but providing only items that pass a test or are matched by a query. In its basic form this method is very much like perl's built-in grep function, except for iterators.

There are many examples of the various forms of this method at "QUERY" in File::KDBX.

map

    \&iterator = $iterator->map(\&code);

Get a new iterator draining from an existing iterator but providing modified items. In its basic form this method is very much like perl's built-in map function, except for iterators.

order_by

    \&iterator = $iterator->sort_by($field, %options);
    \&iterator = $iterator->sort_by(\&get_value, %options);

Get a new iterator draining from an existing iterator but providing items sorted by an object field. Sorting is done using Unicode::Collate (if available) or cmp to sort alphanumerically. The \&get_value subroutine is called once for each item and should return a string value. Options:

  • ascending - Order ascending if true, descending otherwise (default: true)

  • case - If true, take case into account, otherwise ignore case (default: true)

  • collate - If true, use Unicode::Collate (if available), otherwise use perl built-ins (default: true)

  • Any Unicode::Collate option is also supported.

NOTE: This method drains the iterator completely and places the sorted items onto the buffer. See "CAVEATS".

sort_by

Alias for "order_by".

norder_by

    \&iterator = $iterator->nsort_by($field, %options);
    \&iterator = $iterator->nsort_by(\&get_value, %options);

Get a new iterator draining from an existing iterator but providing items sorted by an object field. Sorting is done numerically using <=>. The \&get_value subroutine or $field accessor is called once for each item and should return a numerical value. Options:

  • ascending - Order ascending if true, descending otherwise (default: true)

NOTE: This method drains the iterator completely and places the sorted items onto the buffer. See "CAVEATS".

nsort_by

Alias for "norder_by".

limit

    \&iterator = $iterator->limit($count);

Get a new iterator draining from an existing iterator but providing only a limited number of items.

limit is an alias for "$iterator->head($count)" in Iterator::Simple.

to_array

    \@array = $iterator->to_array;

Get the rest of the items from an iterator as an arrayref.

NOTE: This method drains the iterator completely, leaving it empty. See "CAVEATS".

count

    $size = $iterator->count;

Count the rest of the items from an iterator.

NOTE: This method drains the iterator completely but restores it to its pre-drained state. See "CAVEATS".

size

Alias for "count".

CAVEATS

Some methods attempt to drain the iterator completely before returning. For obvious reasons, this won't work for infinite iterators because your computer doesn't have infinite memory. This isn't a practical issue with File::KDBX lists which are always finite -- unless you do something weird like force a child group to be its own ancestor -- but I'm noting it here as a potential issue if you use this iterator class for other things (which you probably shouldn't do).

KDBX databases are always fully-loaded into memory anyway, so there's not a significant memory cost to draining an iterator completely.

BUGS

Please report any bugs or feature requests on the bugtracker website https://github.com/chazmcgarvey/File-KDBX/issues

When submitting a bug or request, please include a test-file or a patch to an existing test-file that illustrates the bug or desired feature.

AUTHOR

Charles McGarvey <ccm@cpan.org>

COPYRIGHT AND LICENSE

This software is copyright (c) 2022 by Charles McGarvey.

This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.