=head1 NAME

XS::Framework::Manual::SVAPI::Hash - XS::Framework Hash C++ class reference

=head1 Hash

=head2 Overview

The C<Hash> class is the wrapper around Perls C<HV*> type, which is a variant
of C<SV*>. As with C<Sv>, it might hold an underlying Perl hash C<HV*> or might

=head2 Construction

    static Hash noinc  (SV* val)
    static Hash noinc  (HV* val)

    Hash (std::nullptr_t = nullptr)
    Hash (SV* sv, bool policy = INCREMENT)
    Hash (HV* sv, bool policy = INCREMENT)

The new C<Hash> is created, and it either takes ownership on the underlying
C<SV*>/C<HV*> with corresponding refcounting policy, or just empty wrapper
is created, which holds no value. On invalid C<SV*>, e.g. pointer to Arrray,
an exception will be thrown. The valid C<SV*> should be either C<HV*> or
reference to C<HV*> or C<undef>.

Please, note, that empty C<Hash> means that it holds no value (aka NULL),
it is not the same, when it holds underlying empty HV* with zero items.

    static Hash create()
    static Hash create (size_t cap)

It is possible to create new C<Hash> with empty underlying C<HV*>, optionally
reserving space for C<cap> items (SV*).

It is possible to create Hash object in-place via itializer list, which should
contain name (C<string>) / value (C<Scalar>) pairs, i.e.:

    static Hash create (std::initializer_list<std::tuple<panda::string_view, Scalar>> l)
    Hash (std::initializer_list<std::tuple<panda::string_view, Scalar>>)

For example,

    auto h = Hash::create({
        {"key-int", Simple(1)},
        {"key-string", Simple("val2")},

The copy and move constructors are also available:

    Hash (const Hash& oth)
    Hash (Hash&&      oth)
    Hash (const Sv&   oth)
    Hash (Sv&&        oth)

=head2 assignment operators

    Hash& operator= (SV* val)
    Hash& operator= (HV* val)
    Hash& operator= (const Hash& oth)
    Hash& operator= (Hash&& oth)
    Hash& operator= (const Sv& oth)
    Hash& operator= (Sv&& oth)

The assignment operators are complementaty to the constructors above. They
inherit behaviour from C<Sv>, including NULL-safety. The previously held
C<SV*> will be C<dec>-remented.

The last operator performs proxy call in B<scalar> context, the same as in
appropriate constructor above.

    void set (SV* val)

The C<set> method directly assigns the value to the underlying C<SV*>,
I<bypassing all checks>. Use the method with caution.

=head2 getters

There are zero-cost NULL-safe getters:

    operator HV* () const
    HV* operator-> () const
    template <typename T = SV> one_of_t<T,SV,HV>* get ()

For example,

    Hash hash = ...;
    HV* hv = hash.get<HV>();

=head2 element access

    Scalar fetch (const panda::string_view& key) const
    Scalar at (const panda::string_view& key) const
    Scalar operator[] (const panda::string_view& key) const
    KeyProxy operator[] (const panda::string_view& key)

The first three methods return C<Scalar> type. C<fetch> provides bounary-safe
access to the elements, if the index is out of bounds, then empty C<Scalar>
is returned and underlying C<HV*> is kept untouched. The C<at> method also
checks key existance, and if it is not found, then an exception will
be thrown (similar to C<std::map::at()>). The C<operator[]> is an alias
for C<fetch>. The non-const acccessor is needed to allow
in-place fast modification and lazy creation of underlying element, i.e.

    Hash hash = ...;
    hash["key"] = Simple(10);

C<fetch>, C<at> and C<operator[] const> are NULL-safe; while mofifying
C<operator[]> is NULL-unsafe.

    void store (const panda::string_view& key, const Scalar& val, U32 hash = 0)
    void store (const panda::string_view& key, std::nullptr_t,    U32 hash = 0)
    void store (const panda::string_view& key, SV* v,             U32 hash = 0)
    void store (const panda::string_view& key, const Sv& v,       U32 hash = 0)

The C<store> method is used store item in the hash. If underlyging Perl
array HV* is NULL, then C<store> will throw exception.
The C<hash> parameter is the precomputed hash value; if it is
zero then Perl will compute it.

To check element existance, the NULL-safe C<exist> method (or it's alias
C<contains>) can be used:

    bool exists   (const panda::string_view& key) const
    bool contains (const panda::string_view& key) const

To delete arbitrary element by key the NULL-unsafe C<erase> method can be
used (the previous value, if existed, is returned; empty C<Scalar> is
returned otherwise).

    Scalar erase (const panda::string_view& key)

=head2 clear()

    void clear ()

Frees all items in the underlying C<HV*> array. This is NULL-safe method.

=head2 undef()

    void undef()

Frees all items in the underlying C<HV*> hash; the hash container C<HV*>
itself remains alive. This is NULL-safe method.

=head2 push_on_stack()

    U32 push_on_stack (SV** sp) const

This method copies all hash items into perl stack C<SV**>.

It returns the count of copied items. The method takes care of all needed
mechanis, e.g. C<sv_2mortal> and increasing refcounter of the items.

This is NULL-unsafe method.

=head2 size()

    size_t  size      () const

Returns size of underlying hash, i.e. number of used keys. If it is NULL,
then C<0> is returned. In other words, this method is NULL-safe.

=head2 capacity()

    size_t  capacity  () const

Returns capacity of underlying hash. If it is NULL, then C<0> is returned. In
other words, this method is NULL-safe.

=head2 reserve()

    void reserve (size_t newsz)

Increases the capacity of the container. This is NULL-unsafe method.

=head2 itearators

C<Hash> provides iterator and const-iterator random-access accessors for it's content:

    const_iterator cbegin () const
    const_iterator cend   () const
    const_iterator begin  () const
    const_iterator end    () const
    iterator       begin  ()
    iterator       end    ()

This methods are NULL-safe. As usually, when underlying array is modified, the
used iterators become invalid, and should not used any longer.

Usage example:

    Hash hash = ...;
    for (auto it = hash.begin(); it != hash.end(); ++it) {
        panda::string_view key = it->key();
        Scalar value = it->value();
        U32 key_hash = it->hash();

=head1 SEE ALSO