NAME
    Data::CSel::WrapStruct - Wrap data structure into a tree of objects
    suitable for use with Data::CSel

VERSION
    This document describes version 0.008 of Data::CSel::WrapStruct (from
    Perl distribution Data-CSel-WrapStruct), released on 2020-04-15.

SYNOPSIS
     use Data::CSel qw(csel);
     use Data::CSel::WrapStruct qw(wrap_struct unwrap_tree);

     my $data = [
         0,
         1,
         [2, ["two","dua"], {url=>"http://example.com/two.jpg"}, ["even","prime"]],
         3,
         [4, ["four","empat"], {}, ["even"]],
     ];

     my $tree = wrap_struct($data);
     my @nodes = csel(":root > * > *:nth-child(4) > *", $tree);
     my @tags = map { $_->value } @nodes; # -> ("even", "prime", "even")

    Scalars are wrapped using "Data::CSel::WrapStruct::Scalar" class,
    scalarrefs are wrapped using "Data::CSel::WrapStruct::ScalarRef" class,
    arrays are wrapped using "Data::CSel::WrapStruct::Array" class, and
    hashes are wrapped using "Data::CSel::WrapStruct::Hash" class. For
    convenience, when you load "Data::CSel::WrapStruct", it adds
    "Data::CSel::WrapStruct" to @Data::CSel::CLASS_PREFIXES so you don't
    have to specify "{class_prefixes=>["Data::CSel::WrapStruct"]}" "csel()"
    option everytime.

     my @hashes = map {$_->value} csel("Hash", $tree);
     # -> ({url=>"http://example.com/two.jpg"}, {})

    The wrapper objects provide some methods, e.g.:

     my @empty_hashes = map {$_->value} csel("Hash[length=0]", $tree);
     # -> ({})

     my @hashes_that_have_url_key = map {$_->value} csel("Hash[has_key('url')]", $tree);
     # -> ({url=>"http://example.com/two.jpg"})

     my @larger_scalars = [map {$_->value} csel("Scalar[value >= 3]", $tree)]
     # -> (3, 4)

    See "NODE METHODS", "SCALAR NODE METHODS", "SCALARREF NODE METHODS",
    "ARRAY NODE METHODS", "HASH NODE METHODS" for more details on the
    provided methods.

    You can replace the value of nodes using "value":

     my @posint_scalar_nodes = csel("Scalar[value > 0]", $tree);
     for (@posint_scalar_nodes) { $_->value( $_->value * 10 ) }
     use Data::Dump;
     dd unwrap_tree($data);
     # => [
     #     0,
     #     10,
     #     [20, ["two","dua"], {url=>"http://example.com/two.jpg"}, ["even","prime"]],
     #     30,
     #     [40, ["four","empat"], {}, ["even"]],
     # ];

DESCRIPTION
    This module provides "wrap_struct()" which creates a tree of objects
    from a generic data structure. You can then perform node selection using
    Data::CSel's "csel()".

    You can retrieve the original value of data items by calling "value()"
    method on the tree nodes.

NODE METHODS
  parent
  children
  value
    Usage:

     my $val = $node->value; # get node value
     $node->value(1);        # set node value

    Get or set node value.

    Note that when setting node value, the new node value is not
    automatically wrapped for you. If you want to set new node value and
    expect to select it or part of it again with "csel()", you will have to
    wrap the new value first with "wrap_struct".

  remove
    Usage:

     $node->remove;

    Remove node from parent.

SCALAR NODE METHODS
    In addition to methods listed in "NODE METHODS", Scalar nodes also have
    the following methods.

SCALARREF NODE METHODS
    In addition to methods listed in "NODE METHODS", ScalarRef nodes also
    have the following methods.

ARRAY NODE METHODS
    In addition to methods listed in "NODE METHODS", Array nodes also have
    the following methods.

  length
    Get array length. Can be used to select an array based on its length,
    e.g.:

     @nodes = csel('Array[length > 0]');

HASH NODE METHODS
    In addition to methods listed in "NODE METHODS", Hash nodes also have
    the following methods.

  length
    Get the number of keys. Can be used to select a hash based on its number
    of keys, e.g.:

     @nodes = csel('Hash[length > 0]');

  has_key
    Usage:

     my $bool = $node->has_key("foo");

    Check whether hash has a certain key. Can be used to select a hash,
    e.g.:

     @nodes = csel('Hash[has_key("foo")]');

  key
    Usage:

     my $key_val = $node->key("foo");

    Get a hash key's value. Can be used to select a hash based on the value
    of one of its keys, e.g.:

     @nodes = csel('Hash[key("name") = "lisa"]');

FUNCTIONS
    None exported by default, but exportable.

  wrap_struct
    Usage:

     my $tree = wrap_struct($data);

    Wrap a data structure into a tree of objects.

    Currently cannot handle recursive structure.

  unwrap_tree
    Usage:

     my $data = unwrap_tree($wrapped_data);

    Unwrap a tree produced by "wrap_tree" back into unwrapped data
    structure.

FAQ
  Changing the node value doesn't work!
     my $data = [0, 1, 2];
     my @nodes = csel("Scalar[value > 0]", wrap_struct($data));
     for (@nodes) { $_->[0] = "x" }
     use Data::Dump;
     dd $data;

    still prints "[0,1,2]" instead of "[0,'x','x']". Why?

    To set node value, you have to use the "value()" node method with an
    argument:

     ...
     for (@nodes) { $->value("x") }
     ...

    will then print the expected "[0,'x','x']".

  This module is slow!
    If you intend to select a data structure with thousands of nodes or
    more, you're probably better off using other approach, for example
    Data::Walk::More. Data::Walk::More provides containers for the nodes
    you're traversing. For example, the CSel expression
    "Hash[has_keys("foo")] > Array > Scalar[value > 0]" can be written as:

     walk sub {
         my $ref = ref $_;
         return if ref $_; # ... Scalar
         return if $_ <= 0; # ... [value > 0]
         return unless ref $Data::Walk::More::containers[-1] eq 'ARRAY'; # ... Array
         return unless ref $Data::Walk::More::containers[-2] eq 'HASH'; # ... Hash
         return unless exists $Data::Walk::More::containers[-2]{foo}; # ... [has_keys("foo")]
         push @matches, $_;
     }, $data;

HOMEPAGE
    Please visit the project's homepage at
    <https://metacpan.org/release/Data-CSel-WrapStruct>.

SOURCE
    Source repository is at
    <https://github.com/perlancar/perl-Data-CSel-WrapStruct>.

BUGS
    Please report any bugs or feature requests on the bugtracker website
    <https://rt.cpan.org/Public/Dist/Display.html?Name=Data-CSel-WrapStruct>

    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.

SEE ALSO
    Data::CSel

AUTHOR
    perlancar <perlancar@cpan.org>

COPYRIGHT AND LICENSE
    This software is copyright (c) 2020, 2016 by perlancar@cpan.org.

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