###############################################################################
##
##    Typemap for Memcached::libmemcached objects
##
##    Copyright (c) 2007 Tim Bunce
##    All rights reserved.
##
###############################################################################
## vi:et:sw=4 ts=4

TYPEMAP

# --- simple types ---
memcached_behavior                      T_IV
memcached_return                        T_RETURN

# --- generic simple types ---
# general uint16_t
uint16_t                                T_UV
# XXX need to at least document this as an issue
# Could also check at build time if this perl has 64bit ints and use UV if so
uint64_t                                T_NV

# --- perl api private abstraction typedefs ---
lmc_key                                 T_KEY
lmc_value                               T_VALUE
lmc_data_flags_t                        T_FLAGS

# --- complex types (incl. objects, typedef name encodes class name) ---
# XXX memory management may be reworked to store structure in scalars
Memcached__libmemcached                 T_PTROBJ_RVIV


INPUT
T_RETURN
        $var = ($type)SvIV($arg)

OUTPUT
T_RETURN:init
        RECORD_RETURN_ERR(ptr, $var);
        if (TRACE_MEMCACHED(ptr))
            warn(\"\t<= %s return %d %s\", \"${func_name}\", $var, memcached_strerror(ptr, $var));
T_RETURN
        if (!SvREADONLY($arg)) {
            /* setup return value as a dualvar with int err code and string error message */
            /* XXX could optimize later to reuse read-only char* from memcached_strerror */
            sv_setiv($arg, $var);
            /* XXX need to decide if success is true or false! */
            /* sv_setpv($arg, ($var) ? memcached_strerror(NULL, $var) : "XXX"); */
            sv_setpv($arg, memcached_strerror(ptr, $var));
            SvIOK_on($arg);
        }

INPUT
T_PV
        /* treat undef as null pointer (output does the inverse) */
        $var = (SvOK($arg)) ? ($type)SvPV_nolen($arg) : NULL;

INPUT
T_KEY
        /* treat undef as null pointer */
        $var = (SvOK($arg)) ? ($type)SvPV_nolen($arg) : NULL;

OUTPUT
T_KEY
        /* assumes the existance of a key_length variable holding the length */
        if (!SvREADONLY($arg))
            sv_setpvn((SV*)$arg, $var, key_length);

INPUT
T_VALUE
        /* treat undef as null pointer */
        $var = (SvOK($arg)) ? ($type)SvPV_nolen($arg) : NULL;

OUTPUT
T_VALUE
        /* assumes the existance of a value_length variable holding the length */
        if (!SvREADONLY($arg))
            sv_setpvn((SV*)$arg, $var, value_length);

INPUT
T_FLAGS
        $var = ($type)SvUV($arg)

OUTPUT
T_FLAGS
        if (!SvREADONLY($arg))
            sv_setuv($arg, (UV)$var);


INPUT
T_PTROBJ_RVIV
        if (!SvOK($arg)) {  /* undef         */
            $var = NULL;    /* treat as null */
        }
        else if (sv_derived_from($arg, \"${(my $ntt=$ntype)=~s/__/::/g;\$ntt}\")) {
            if (SvROK($arg) && SvOK(SvRV($arg))) {
                IV tmp = SvIV((SV*)SvRV($arg));
                $var = INT2PTR($type, tmp);
            }
            else { /* already freed */
                $var = NULL;
            }
        }
        else
            croak(\"$var is not of type ${(my $ntt=$ntype)=~s/__/::/g;\$ntt}\");
        if (TRACE_MEMCACHED(ptr))
            warn(\"\t=> %s(%s %s = 0x%p)\", \"${func_name}\", \"${ntype}\", \"${var}\", (void*)$var);

OUTPUT
T_PTROBJ_RVIV:init
        if (TRACE_MEMCACHED(ptr))
            warn(\"\t<= %s(%s %s = %p)\", \"${func_name}\", \"${ntype}\", \"${var}\", (void*)$var);
T_PTROBJ_RVIV
        if (!$var)          /* if null */
            SvOK_off($arg); /* then return as undef instead of reaf to undef */
        else {
            sv_setref_pv($arg, \"${(my $ntt=$ntype)=~s/__/::/g;\$ntt}\", $var);
        }

