The London Perl and Raku Workshop takes place on 26th Oct 2024. If your company depends on Perl, please consider sponsoring and/or attending.

NAME

Banal::Utils::Data - Totally banal and trivial utilities for accessing and maniupulating data in various structures.

SYNOPSIS

    use Banal::Utils::Data qw(banal_get_data);
    
    ...

EXPORT

None by default.

EXPORT_OK

SUBROUTINES / FUNCTIONS

banal_get_data(data=>$data, keys=>$keys, ....)

Allows to get a data element within a deep structure composed of possibly complex data types (HASH, ARRAY, ...)

Example: my $name = banal_get_data (data=>$h, keys=>["employee[23]", "department", "name"], ...)

In this example, we are assuming that the initial data ($h) is a HASH that has a key called 'employee' which refers to an ARRAY of hashes, ....

NAMED ARGUMENTS

data -- reference to the structure holding the data tree. Typically a HASH reference.

keys -- An array of keys (or a SCALAR that gives a single key or a path, depending on the semantics) that will be used to navigate down the tree.

For array indexes, just use the usual Perl array access syntax.

You can basically throw anything here (ARRAY reference, SCALAR, etc), and it will probably be interpreted the way you expect it to be (basically flattenned into a list of keys). Even a HASH reference may occur somewhere in there, in which case the last such reference will be taken to be the data-root.

Under normal circumstances, each element in the passed array is taken to be a single individual key (eventually enriched by an array access syntax mentioned above). However, it is possible to force "path semantics" for the interpretation of these, in which case it is possible to use path like notation (similar to that of a POSIX file-system) for each one of the array items that will first be joined together (with a given separator, by default '/') and then resplit on the same separator so that it is possible to mix and match SCALAR and ARRAY path segments.

Please see the 'use_path_semantics' OPTION or the 'path' argument for ways of activating path semantics.

path -- A SCALAR (or a reference to an ARRAY of SCALARS, or any complex structure for that matter) that will be interpreted as an access "path"

You can use 'path' instead of 'keys' to automatically enforce path semantics without having to turn on the 'use_path_semantics' option.

Examples:

        path => "employee[23]/department/name"
        

or an equivalently:

        path => ["employee[23]/department", "name"]
        

or even:

        path => [["employee[23]/department"], "name"]

context -- Similar semantics to 'keys' (or 'path', if path semantics are in force). In practice, it will just be prepended to 'keys' or 'path' (whichever is being used).

It sets a context under which the keys (or path) can be interpreted. In many ways, it is similar to the 'current working directory' in Unix shells.

Note that, it is posible to also throw in a HASH reference in there, in which case the last such reference will be taken to be the data-root. Also note that, the same mechanism is possible thru 'keys' or 'path' as well and the last such HASH reference will win (for setting the data-root).

In fact, even the 'data' argument is handled in this very fashion, being prepended before the 'context'.

Here's the relevant code snippet that tells it all in a concise fashion:

        my $relevant_keys                                               = [];

        # Flatten all context and key segments (which are potentially a mix of path segment strings)
        $keys = flatten_complex_data_to_list_with_options(data=>[$data, $context, $keys], on_HashRef=>'keep');
        
        # If we've got a HASH reference given as a key (or context) segment, that's our root. Otherwise, build the relevant thingy (relative to the root).
        foreach my $key (reverse @$keys) {
                if (reftype($key) eq 'HASH') {
                        $mroot = $key;
                        last;
                }else {
                        unshift @$relevant_keys, $key;
                }
        }
 

In the above snippet, the function call to 'flatten_complex_data_to_list_with_options()' does pretty much what you would expect, flattening an arbitratily complex data structure onto a single flat list. Only the HASH references, if any, are kept untouched. Further below, we find out if there were indeed any, and use the last such reference as our data-root. The key segments occuring earlier than that, if any, will be effectively ignored.

options -- A reference to a HASH, givng a set of options that effect the way stuff is processed, given below on its own heading (OPTIONS)

OPTIONS -- options => {...}

use_path_semantics -- Boolean (0 | 1)

Force the usage of 'path semantics' (or not) as explained above under the descriptions of the arguments 'keys' and 'path'.

path_separator | separator -- the path separator to be used in 'path semantics' mode. Default is forward slash ('/').

remove_extra_separators -- Boolean (0 | 1) that determines whether or not superfulous repeating path separators will be removed. Default is TRUE.

remove_leading_separator -- Boolean (0 | 1) that determines whether or not the leading path separator, if persent, will be removed. Default is FALSE.

Be careful here, as turning this ON will make it impossible to detect absolute path references.

remove_trailing_separator -- Boolean (0 | 1) that determines whether or not the leading path separator, if persent, will be removed. Default is set to the value of 'remove_extra_separators'.

remove_empty_segments -- Boolean (0 | 1) that determines whether or not empty segments, if persent, will be removed. Default is FALSE.

Be careful here, as turning this ON will make it impossible to detect absolute path references, as the first segmebt in an absolute path reference will appear to be an empty segment.

try_avoiding_repeated_segments -- Boolean (0 | 1) that determines whether or not we will try to eliminate repeating segments. Default is FALSE.

lower_case | lc -- Boolean (0 | 1) that determines whether or not we will force lower-case on keys (and anything that serves as a key, such as contexts). Default is FALSE.

trim -- Boolean (0 | 1) that determines whether or not we will trim white space on key segments (and anything that serves as a key segment, such as those coming from contexts). Default is FALSE.

Note that when using 'path semantics', this will also have the effect of trimming white space around path separators.

flatten_complex_data_to_list(@_)

Flattens out a possibly deep structure composed of possibly complex data types (HASH, ARRAY, SCALAR, ...)

Tries very hard to flatten out everything it encounters.

NAMED ARGUMENTS

data -- reference to the structure holding the data tree. Typically a HASH reference.

flatten_complex_data_to_list_with_options(data=>$data, ...)

Flattens out a possibly deep structure composed of possibly complex data types (HASH, ARRAY, SCALAR, ...)

Tries to flatten out items it encounters only as hard as it has been asked for.

NAMED ARGUMENTS

data -- reference to the structure holding the data. Typically an ARRAY reference, but any reference or scalar is accepted.

on_ArrayRef -- Indicates what to do when an ARRAY reference is encountered. Possible values are 'flatten' or 'keep'. default is 'flatten'.

on_HashRef -- Indicates what to do when an HASH reference is encountered. Possible values are 'flatten' or 'keep'. default is 'flatten'.

on_ScalarRef -- Indicates what to do when an SCALAR reference is encountered. Possible values are 'flatten' or 'keep'. default is 'flatten'.

AUTHOR

"aulusoy", <"dev (at) ulusoy.name">

BUGS

Please report any bugs or feature requests to bug-banal-utils at rt.cpan.org, or through the web interface at http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Banal-Utils. I will be notified, and then you'll automatically be notified of progress on your bug as I make changes.

SUPPORT

You can find documentation for this module with the perldoc command.

    perldoc Banal::Utils::Data

You can also look for information at:

ACKNOWLEDGEMENTS

LICENSE AND COPYRIGHT

Copyright 2014 "aulusoy".

This program is free software; you can redistribute it and/or modify it under the terms of the the Artistic License (2.0). You may obtain a copy of the full license at:

http://www.perlfoundation.org/artistic_license_2_0

Any use, modification, and distribution of the Standard or Modified Versions is governed by this Artistic License. By using, modifying or distributing the Package, you accept this license. Do not use, modify, or distribute the Package, if you do not accept this license.

If your Modified Version has been derived from a Modified Version made by someone other than you, you are nevertheless required to ensure that your Modified Version complies with the requirements of this license.

This license does not grant you the right to use any trademark, service mark, tradename, or logo of the Copyright Holder.

This license includes the non-exclusive, worldwide, free-of-charge patent license to make, have made, use, offer to sell, sell, import and otherwise transfer the Package with respect to any patent claims licensable by the Copyright Holder that are necessarily infringed by the Package. If you institute patent litigation (including a cross-claim or counterclaim) against any party alleging that the Package constitutes direct or contributory patent infringement, then this Artistic License to you shall terminate on the date that such litigation is filed.

Disclaimer of Warranty: THE PACKAGE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS "AS IS' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES. THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED TO THE EXTENT PERMITTED BY YOUR LOCAL LAW. UNLESS REQUIRED BY LAW, NO COPYRIGHT HOLDER OR CONTRIBUTOR WILL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING IN ANY WAY OUT OF THE USE OF THE PACKAGE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.