NAME

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

Stash

Overview

The Stash class extension of Hash class, which provides convenient access to perl symbol table as well as symbol resolution via call, call_SUPER and call_next methods.

Stash may be empty, i.e. contain NULL SV*.

Construction

    static Stash root ()

Returns Perl's default stash.

    Stash (std::nullptr_t = nullptr)

Creates an empty stash.

    static Stash from_name (SV* fqn, I32 flags = 0)
    Stash (const std::string_view& package, I32 flags = 0)

Looks up for the specified fully-qualified package name and returns, may be empty, Stash object for the result. The flags are additional parameters for lookup, e.g. GV_ADD will create new symbol table. See gv_stashpvn in perlapi.

    Stash (SV* sv, bool policy = INCREMENT)
    Stash (HV* sv, bool policy = INCREMENT)

Upgrades hash HV*, which already refers to symbol table, or reference to it (SV*) into <Stash> object. If the supplied agrument is invalid, the exception will be thrown. It is possible that the first agrument be NULL or undef, in that case empty stash will be crated.

Copy and move-constructore are also available:

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

It it possible to create Hash object from CallProxy invocation:

    Stash (const CallProxy& p)

however, please note, that the CallProxy will be called in scalar context. It is expected, that the scall will hash/refernce to hash of existing symbol table.

assignment operators

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

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

    void set (HV* val)

The set method directly assigns the value to the underlying SV* in the form of HV*, bypassing all checks. Use the method with caution.

element access

    Glob fetch (const std::string_view& key)
    Glob at (const std::string_view& key)
    Glob operator[] (const std::string_view& key)
    op_proxy operator[] (const std::string_view& key)

The first three methods return Glob type via the key string. fetch provides safe access to the elements, i.e. in case of absence of a key empty Glob will be returned. The at method will throw error of the specified key is not found in the current symbol table. The operator[] fetch is the alias for fetch method.

The non-const operator[] allows in-place fast modification of underlying element, i.e.

    Stash stash = Stash("my::package", GV_ADD);
    stash["PI"] = Simple(3.14);

All the methods above are NULL-safe; the assingment of empty stash leads to thrown exception.

    void store (const std::string_view& key, SV* v)
    void store (const std::string_view& key, AV* v)
    void store (const std::string_view& key, HV* v)
    void store (const std::string_view& key, CV* v)
    void store (const std::string_view& key, GV* v)
    void store (const std::string_view& key, const Sv&     v)
    void store (const std::string_view& key, const Scalar& v)
    void store (const std::string_view& key, const Array&  v)
    void store (const std::string_view& key, const Hash&   v)
    void store (const std::string_view& key, const Sub&    v)
    void store (const std::string_view& key, const Glob&   v)
    void store (const std::string_view& key, const CallProxy& p)

The NULL-safe store method allows to inject the new value into the stash. The exception will be thrown if the stash object is empty.

The following methods provide convenient access Stash symbol values, when the type is known:

    Scalar scalar (const std::string_view& name) const
    Array  array  (const std::string_view& name) const
    Hash   hash   (const std::string_view& name) const
    Sub    sub    (const std::string_view& name) const

    void scalar (const std::string_view& name, const Scalar& v)
    void array  (const std::string_view& name, const Array&  v)
    void hash   (const std::string_view& name, const Hash&   v)
    void sub    (const std::string_view& name, const Sub&    v)

The read-access is NULL-safe; the write-access (i.e assignment) on empty Stash throws exception. Usage example:

    Stash stash = Stash("my::package");
    auto pi = stash.scalar("pi");
    stash.scalar("e", Simple(2.71));    // will throw if "my::package" is not known to Perl

method access

    Sub method (const Sv& name) const
    Sub method (const std::string_view& name) const

    Sub method_strict (const Sv& name) const
    Sub method_strict (const std::string_view& name) const

    Sub super_method        (const Sub& current) const
    Sub super_method_strict (const Sub& current) const

    Sub next_method        (const Sub& current) const
    Sub next_method_strict (const Sub& current) const

The method resolving can be performed either via std::string_view or Sv name. If a method name cannot be found, the empty Sub is returned. To avoid that the method_strict should be invoked; if the method name cannot be found, then exception will be thrown.

The super_method takes the existing Sub and tries to find the corresponding method in the parent package of the current Stash. It uses the resolution order specified in the class (i.e. use mro 'c3'). The next_method tries to find the next method using method resolution order, see mro. The _strict version throw exception if nothing is found.

This are null-unsafe methods.

Usage example:

    Stash stash = Stash("my::derived");
    Sub m_child = stash.method("method");
    Sub m_parent = stash.super_method(m_child);
    m_parent.call();

method call

    CallProxy call (const Sv& name)                                                const
    CallProxy call (const std::string_view& name)                                  const
    CallProxy call (const Sv& name,               const Scalar& arg)               const
    CallProxy call (const std::string_view& name, const Scalar& arg)               const
    CallProxy call (const Sv& name,               SV*const* args, size_t items)    const
    CallProxy call (const std::string_view& name, SV*const* args, size_t items)    const
    CallProxy call (const Sv& name,               std::initializer_list<Scalar> l) const
    CallProxy call (const std::string_view& name, std::initializer_list<Scalar> l) const

    CallProxy call_SUPER (const Sub& current)                                  const
    CallProxy call_SUPER (const Sub& current, const Scalar& arg)               const
    CallProxy call_SUPER (const Sub& current, SV*const* args, size_t items)    const
    CallProxy call_SUPER (const Sub& current, std::initializer_list<Scalar> l) const

    CallProxy call_next (const Sub& current)                                  const
    CallProxy call_next (const Sub& current, const Scalar& arg)               const
    CallProxy call_next (const Sub& current, SV*const* args, size_t items)    const
    CallProxy call_next (const Sub& current, std::initializer_list<Scalar> l) const

    CallProxy call_next_maybe (const Sub& current)                                  const
    CallProxy call_next_maybe (const Sub& current, const Scalar& arg)               const
    CallProxy call_next_maybe (const Sub& current, SV*const* args, size_t items)    const
    CallProxy call_next_maybe (const Sub& current, std::initializer_list<Scalar> l) const

    CallProxy call_super (const Sub& current)                                  const
    CallProxy call_super (const Sub& current, const Scalar& arg)               const
    CallProxy call_super (const Sub& current, SV*const* args, size_t items)    const
    CallProxy call_super (const Sub& current, std::initializer_list<Scalar> l) const

    CallProxy call_super_maybe (const Sub& current)                                  const
    CallProxy call_super_maybe (const Sub& current, const Scalar& arg)               const
    CallProxy call_super_maybe (const Sub& current, SV*const* args, size_t items)    const
    CallProxy call_super_maybe (const Sub& current, std::initializer_list<Scalar> l) const

It is possible to invoke arbitrary method with arbitrary arguments if method name is known in a Stash; if method is not found, then an exception will be thrown. The call_SUPER / call_super / call_next will lookup for corresponding method in the parent or next class in the hierachy (see mro).

The diffence between call_SUPER / call_super is how the parent method is looked-up: either via classical DFS MRO resolution or via class-defined resolution (i.e. use mro 'c3' for using C3-resolution).

The same methods with _maybe prefix do exist: if the corresponding metthod is not found, then empty result will be returned, i.e. no exception will be thrown. (Actually we discourage using of them, as this is leads do pefromance penalities without any actual job to be done. Why you use XS::Framework at all, then?).

The CallProxy object is returned to peform actuall method call.

This are null-unsafe methods.

package name

    std::string_view name           () const
    HEK*             name_hek       () const
    const Simple&    name_sv        () const

To know the name of the package, to which the current Stash object points, the name, name_sv and name_hek methods can be used. For example:

    Stash stash = Stash("my::package");
    auto name = stash.name();   // returns "my::package"

If it is planned to let the package name be used in Perl in future, then prefer to use name_sv method.

    std::string_view effective_name () const

It is possible to have effective_name of the current stash, if the stash was aliased. See HvENAME in perlapi.

This are null-unsafe methods.

path()

    panda::string    path           () const

Returns the file path for the current stash, i.e.

    Stash s("A::B::C", GV_ADD);
    s.path();  // returns A/B/C.pm

mark_as_loaded()

    void mark_as_loaded (const Stash& source)            const
    void mark_as_loaded (const std::string_view& source) const

Let the perl knows, where the current Stash comes from, i.e. inserts into the perl INC variable the source for the current Stash. This is useful, when writing multiple XS-bases packages in a single module. XS::Framework ships with a few useful macros, so, it is usually used in the BOOT section of the package like the following:

    Stash(__PACKAGE__, GV_ADD).mark_as_loaded(__MODULE__);

The typical sympthom to use mark_as_loaded is the following error:

    Can't locate MyModule/MyClass.pm in @INC

inherit()

    void inherit        (const Stash& parent)
    void inherit        (const std::string_view& parent)

Links the current symbol table as the descendant class for parent Stash. In other words, it the following construct:

    Stash child("MyPackage::Child"); // or, better Stash(__PACKAGE__, GV_ADD)
    child.mark_as_loaded(__MODULE__);
    Stash base("MyPackage::Base");
    child.inherit(base);

is equivalent to perl code:

    package MyPackage::Child;
    use parent qw/MyPackage::Base/;

If the parent package is defined as string_view, it will be automatically added to Perl via GV_ADD.

The inherit is NULL-safe method; the exception will be thrown if it is invoked on empty Stash.

isa()

    bool isa (const std::string_view& parent, U32 hash = 0, int flags = 0) const
    bool isa (HEK* hek)            const
    bool isa (const Stash& parent) const

The isa method returns true if the current Stash exactly matches parent Stash or if the current Stash is child class for the parent Stash. The similar code in Perl is

    child_CLASS->isa(parent_CLASS);

Under the hood the method uses hv_common function (see perlapi).

bless()

    Object bless () const;

This method creates new Object, which is blessed into to the current package (Stash).

    Object bless (const Sv& what) const;

This bless method version works somewhat similiar to the following Perl construction

    my $class = ...;
    my $obj = ...;
    return bless $obj => $class;

i.e. if what is already an object, it is blessed into the Stash, otherwise new RV* created from the what argument, and the blessed object returned.

add_const_sub()

    void add_const_sub (const std::string_view& name, const Sv& val);
    

Creates subroutine name that returns constant val eligible for compile-time inlining (like newCONSTSUB). val is retained and made readonly.

val can be either any Scalar or <Array>. In latter case, const sub will return list containing array's values.

SEE ALSO

XS::Framework

XS::Framework::Manual::SVAPI

XS::Framework::Manual::SVAPI::Sv

XS::Framework::Manual::SVAPI::Hash