=head1 NAME

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

=head1 Sv

=head2 Overview

The Perl C<SV*> is variadic type, which actually can be Hash (HV*), Array(AV*)
etc.

The Sv object I<may> own the underlying Perl <SV*> or I<may not>, i.e. the
held SV* is C<NULL>. That way some methods are NULL-safe, i.e. they can be
invoked when C<SV*> is C<NULL>; the other methods are NULL-unsafe, and inoking
them leads to B<undefined behaviour>, most likely the program will crash.

C<Sv> class tried to follow I<DWIM-principle> whenever it is possible and
zero- or minimal costs. For example:

    SV* arg;
    // arg may be NULL or may be not
    Sv1 sv1(arg)
    Sv2 sv2 = sv1;

If the C<arg> wasn't NULL, then it's refcounter will be increased twice (on
C<sv1> and C<sv2> construction), and decreased twice (on C<sv1> and C<sv2>
destruction). if C<arg> was NULL, then both variables C<sv1> and C<sv2> will
held NULL C<SV*>. The code above is NULL-safe. However, the following
code is NULL-unsafe, i.e. may lead to crashes:

    SV* arg;
    // arg may be NULL or may be not
    Sv1 sv1(arg)
    sv1.payload_attach(&some_payload, &some_marker);

The non-null existance of C<arg> have to checked i.e.

    if (sv1) {
        sv1.payload_attach(&some_payload, &some_marker);
    }

Now this piece of code is safe from crashes at runtime.

=head2 Construction

When the empty constructor is invoked the C<Sv> variable will be empty, i.e.
hold no any perl C<SV*>:

    Sv item;

To let it hold new Perl variable (empty string), it should be constructed
via static method C<create>, i.e.:

    auto item = Sv::create();

It is quite common to just I<wrap> underlying Perl C type, the overloaded
constructor can be invoked

    Sv (SV* sv, bool policy = INCREMENT)
    Sv (AV* sv, bool policy = INCREMENT)
    Sv (HV* sv, bool policy = INCREMENT)
    Sv (CV* sv, bool policy = INCREMENT)
    Sv (GV* sv, bool policy = INCREMENT)

    AV* av = ...;
    Sv my(av);

The ref-couning C<policy> defines, whether the underlying C<SV*> should be
incremented upon Sv object construction; it is C<true> by default. When
the Sv goes out of scope, it's destructor will be invoked and the refcounter
of the underlying C<SV*> will always be C<dec>-remented.

The construtor does never throws, as all valid C<SV*> values are accepted.

The rule of thumb is following: if Sv wrapper is intended to B<share> ownership
with the C<SV*>, it should use C<INCREMENT> policy (this is default, and mostly
used case); if the wrapper should own the variable, then the policy should be
C<NONE>.

There are convenient static methods to create an C<Sv> wrapper without
incrementing the refcounter:

    static Sv noinc (SV* val)
    static Sv noinc (AV* val)
    static Sv noinc (HV* val)
    static Sv noinc (CV* val)
    static Sv noinc (GV* val)

    AV* av = ...;
    auto my = Sv::noinc(av);

The copy and move constructors are provided; the refcounter is not touched:

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

=head2 undef, yes, no

There are a few Sv-constants, which represent common values, e.g. :

    static const Sv undef;
    static const Sv yes;
    static const Sv no;

=head2 assignment operators

    Sv& operator= (SV* val)
    Sv& operator= (AV* val)
    Sv& operator= (HV* val)
    Sv& operator= (CV* val)
    Sv& operator= (GV* val)
    Sv& operator= (const Sv& oth)

The assignment operators are complementaty to the constructors above. As the
possible underlying C<SV*> will be thrown away after assignemnt, it's refcounter
is C<dec>-remented and the ref-counter of the new value is incremented.

    Sv& operator= (Sv&& oth)

Move-assignment operator is implemented simply by swapping underlying C<SV*>
without touching ref-counter.

All assignment operators are NULL-safe

=head2 getters

The get the underlying C<SV*> it is possible either to use related coersion
operator or dereference operator:

    operator SV*   () const
    SV* operator-> () const

Please note, the result might be C<nullptr> if the underlyging C<SV*> was
C<nullptr>.

It is possible to unwrap the underlying C<SV*> either via operator coercion;
it is B<safe and somewhat slower>, as in the case of coercion failure the
C<nullptr> is returned:

    operator AV*   () const
    operator HV*   () const
    operator CV*   () const
    operator GV*   () const

Or it is possible to do zero-cost typecasting, but without any warranty on
type safety or non-nullity:

    template <typename T = SV> one_of_t<T,SV,AV,HV,CV,GV>* get ()

For example:

    AV* av_src = ...;
    Sv sv(av_src);

    AV* av_src = sv;
    if (!av_src) {
        // do something!
    }

    AV* av_src_unsafe = sv.get<AV*>();

To resolve ambiguities in using C<Sv> with Perl macros it the C<void*> coercion
operator is supplied:

    operator void* () const


=head2 bool operator()

    explicit operator bool () const

Returns true if the C<Sv> wraps any Perl C<SV*>. It is convenient to
use in XS-adapters to check whether any value has been supplied in Perl
script, e.g.

    void MyClass::my_method(SV* optional1 = nullptr, Sv opt2 = Sv{}) {
        Sv opt1(optional1);
        if (opt1) { ... }
        // a bit more convenient, right?
        if (opt2) { ... }
    }

Please note, that C<undef> is valid perl C<SV*> and it returns C<true>
for the operator.

=head2 defined()

    bool   defined() const

Null-safe method which returns C<true> the object holds any C<SV*> and
later is defined.

=head2 is_true()

    bool   is_true        () const

Checks whether the object holds Perl value which evaluates to C<true>. This is NULL-safe method.

=head2 type-inspecting methods

    bool   is_scalar      () const
    bool   is_ref         () const
    bool   is_simple      () const
    bool   is_string      () const
    bool   is_like_number () const
    bool   is_array       () const
    bool   is_array_ref   () const
    bool   is_hash        () const
    bool   is_hash_ref    () const
    bool   is_sub         () const
    bool   is_sub_ref     () const
    bool   is_glob        () const
    bool   is_object      () const
    bool   is_object_ref  () const
    bool   is_stash       () const

All the methods above try to guess corresponding C<SV*> type and return
C<true> upon successful guess. All the methods are NULL-safe.

    svtype type           () const

This is NULL-unsafe type extraction from from C<SV*>.

=head2 readonly()

=head2 readonly(bool val)

    bool   readonly       () const
    void readonly (bool val)

This NULL-unsafe methods examine Perl C<SV*> for read-only flag or
set/unset it.


=head2 use_count()

    U32    use_count      () const

Returns refcounter value. If C<SV*> is NULL, then C<0> is returned.


=head2 upgrade (svtype type)

    void upgrade (svtype type)

Tries to upgrade C<SV*> into the specified type. Exception is thrown if the
variable is already marked as readonly or upon attempt to upgrade defined
scalar (non-undef) into more than C<SVt_PVMG>.

This is NULL-unsafe method.


=head2 dump ()

    void dump () const

Dumps the underlyign C<SV*> to C<stderr>.

=head2 reset ()

    void reset ()

Decrements refcounter in the undrerlying C<SV*> and sets it to C<NULL>.

This is NULL-safe method.

=head2 detach()

    SV* detach ()

Releases ownership on the underlying C<SV*> (which might be C<NULL>) and
returns it. The refcounter is not touched.

This is NULL-safe method.

This method is useful when manually returning SV* on perl stack in xs-adapter, e.g.

    void MyClass::method() {
        ...
        Sv mysv = somefunc();
        mXPUSHs(mysv.detach()); // mXPUSHs will make it mortal
        ...
    }
    
note that you *MUST* use perl API macros with mortalizing or you will get a memory leak

=head2 detach_mortal()

    SV* detach_mortal ()

Same as C<detach()> + C<sv_2mortal()>

This is NULL-safe method.

This method is useful when manually returning SV* on perl stack in xs-adapter without using perl mortalizing macros, e.g.

    void MyClass::method() {
        ...
        Sv mysv = somefunc();
        EXTEND(SP, 1);
        ST(0) = mysv.detach_mortal();
        XSRETURN(1);
    }

note that you *MUST NOT* use perl API macros with mortalizing or you will get a C<double free> error.

=head2 operators ==() and !=()

    operator== (const Sv& lh, const Sv& rh)
    operator!= (const Sv& lh, const Sv& rh)
    operator== (const Sv& lh, SV* rh)
    operator!= (const Sv& lh, SV* rh)
    operator== (SV* lh, const Sv& rh)
    operator!= (SV* lh, const Sv& rh)
    operator== (const Sv& lh, AV* rh)
    operator!= (const Sv& lh, AV* rh)
    operator== (AV* lh, const Sv& rh)
    operator!= (AV* lh, const Sv& rh)
    operator== (const Sv& lh, HV* rh)
    operator!= (const Sv& lh, HV* rh)
    operator== (HV* lh, const Sv& rh)
    operator!= (HV* lh, const Sv& rh)
    operator== (const Sv& lh, CV* rh)
    operator!= (const Sv& lh, CV* rh)
    operator== (CV* lh, const Sv& rh)
    operator!= (CV* lh, const Sv& rh)
    operator== (const Sv& lh, GV* rh)
    operator!= (const Sv& lh, GV* rh)
    operator== (GV* lh, const Sv& rh)
    operator!= (GV* lh, const Sv& rh)


This is group of identity checks operators, i.e. determine whether the underlyging
C<SV*> points to the same address as the other argument. As only addresses are
compared, all the operations are NULL-safe.


=head2 magic payload

Perl gives possibility to attach arbitrary data to C<SV*> via magic slots. The
L<XS::Framework> exposes that facility too. To distinguish between different
payloads, it is required to supply the per-type unique marker. L<XS::Framework>
assumes that it is enough to have just I<unique address> to identiy unique
marker. The easiest way to accomplish that is to have:

    static xs::Sv::payload_marker_t my_payload_marker{};

To attach payload the following NULL-unsafe methods can be used:

    MAGIC* payload_attach (void* ptr, Sv obj, const payload_marker_t* marker)
    MAGIC* payload_attach (void* ptr, const payload_marker_t* marker)
    MAGIC* payload_attach (Sv    obj, const payload_marker_t* marker)

The result is perl C<MAGIC*> pointer, which can be safely ignored. To remove
magic payload from <SV*> the C<payload_detach> method can be used:

    int payload_detach (payload_marker_t* marker)

To check payload existance via it's market the C<payload_exists> can be used:

    bool payload_exists (const payload_marker_t* marker)

Finally, to get the payload the C<payload> method should be used:

    Payload payload (const payload_marker_t* marker) const

    struct Payload {
        void* ptr;
        SV*   obj;
    };

In the returned C<Payload> struct you should access the C<ptr> or C<obj>,
depending on what kind of payload was attached. Both C<ptr> and C<obj>
can be used, if both of them were set.

A few words should be told about payload cleanup. If the attached payload
type was C<SV*>, then underlying refcounter will be increased, and once
magic payload goes of of live, the refcounter will be decremented. However,
if arbitrary data was attached as C<void*>, then user-supplied cleanup
function will invoked, once it was attached ot the payload marker. The
usual place to initialize that custom payload function is C<BOOT> XS-adapter
section, for example:

    static xs::Sv::payload_marker_t my_payload_marker{};

    static int my_payload_marker_free(pTHX_ SV*, MAGIC* mg) {
        void* payload = (void*)mg->mg_ptr;
        // place custom clean-up code here.
        return 0;
    }

    BOOT {
        my_payload_marker.svt_free = my_payload_marker_free;
    }

All methods, which work with magic are NULL-unsafe.

=head2 void swap (Sv& lh, Sv& rh)

Swaps underlying SV* between C<lh> and C<rh>

=head1 SEE ALSO

L<XS::Framework>

L<XS::Framework::Manual::SVAPI>

L<XS::Framework::Manual::SVAPI::Sub>

L<XS::Framework::Manual::SVAPI::Array>

L<XS::Framework::Manual::SVAPI::Glob>

L<XS::Framework::Manual::SVAPI::Hash>

L<XS::Framework::Manual::SVAPI::List>

L<XS::Framework::Manual::SVAPI::Object>

L<XS::Framework::Manual::SVAPI::Ref>

L<XS::Framework::Manual::SVAPI::Scalar>

L<XS::Framework::Manual::SVAPI::Simple>

L<XS::Framework::Manual::SVAPI::Stash>

=cut
