File Coverage

xs/XSBind.h
Criterion Covered Total %
statement 2 2 100.0
branch 2 2 100.0
condition n/a
subroutine n/a
pod n/a
total 4 4 100.0


line stmt bran cond sub pod time code
1            
2            
3            

perltidy

4            
 
5             /* Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /* XSBind.h -- Functions to help bind Clownfish to Perl XS api. */ #ifndef H_CFISH_XSBIND #define H_CFISH_XSBIND 1 #include "Clownfish/Obj.h" #include "Clownfish/Blob.h" #include "Clownfish/ByteBuf.h" #include "Clownfish/String.h" #include "Clownfish/Err.h" #include "Clownfish/Hash.h" #include "Clownfish/Num.h" #include "Clownfish/Vector.h" #include "Clownfish/Class.h" /* Avoid conflicts with Clownfish bool type. */ #define HAS_BOOL #define PERL_NO_GET_CONTEXT #include "EXTERN.h" #include "perl.h" #include "XSUB.h" #define NEED_newRV_noinc_GLOBAL #include "ppport.h" #ifdef __cplusplus extern "C" { #endif typedef struct cfish_XSBind_ClassSpec { const char *name; const char *parent_name; uint32_t num_methods; } cfish_XSBind_ClassSpec; typedef struct cfish_XSBind_XSubSpec { const char *alias; XSUBADDR_t xsub; } cfish_XSBind_XSubSpec; typedef struct cfish_XSBind_ParamSpec { const char *label; uint16_t label_len; char required; } cfish_XSBind_ParamSpec; /** Given either a class name or a perl object, manufacture a new Clownfish * object suitable for supplying to a cfish_Foo_init() function. */ CFISH_VISIBLE cfish_Obj* cfish_XSBind_new_blank_obj(pTHX_ SV *either_sv); /** Create a new object to go with the supplied host object. */ CFISH_VISIBLE cfish_Obj* cfish_XSBind_foster_obj(pTHX_ SV *sv, cfish_Class *klass); /** Test whether an SV is defined. Handles "get" magic, unlike SvOK on its * own. */ CFISH_VISIBLE bool cfish_XSBind_sv_defined(pTHX_ SV *sv); /** Test whether an SV is true. Wraps the expensive SvTRUE macro in a * function. */ CFISH_VISIBLE bool cfish_XSBind_sv_true(pTHX_ SV *sv); /** Derive an SV from a Clownfish object. If the Clownfish object is NULL, * the SV will be undef. Doesn't invoke To_Host and always returns a * reference to a Clownfish::Obj. * * The new SV has single refcount for which the caller must take * responsibility. */ CFISH_VISIBLE SV* cfish_XSBind_cfish_obj_to_sv_inc(pTHX_ cfish_Obj *obj); /** XSBind_cfish_obj_to_sv_inc, with a cast. */ #define CFISH_OBJ_TO_SV_INC(_obj) \ cfish_XSBind_cfish_obj_to_sv_inc(aTHX_ (cfish_Obj*)_obj) /** As XSBind_cfish_obj_to_sv_inc above, except decrements the object's * refcount after creating the SV. This is useful when the Clownfish * expression creates a new refcount, e.g. a call to a constructor. */ CFISH_VISIBLE SV* cfish_XSBind_cfish_obj_to_sv_noinc(pTHX_ cfish_Obj *obj); /** XSBind_cfish_obj_to_sv_noinc, with a cast. */ #define CFISH_OBJ_TO_SV_NOINC(_obj) \ cfish_XSBind_cfish_obj_to_sv_noinc(aTHX_ (cfish_Obj*)_obj) /** Null-safe invocation of Obj_To_Host. */ static CFISH_INLINE SV* cfish_XSBind_cfish_to_perl(pTHX_ cfish_Obj *obj) { return obj ? (SV*)CFISH_Obj_To_Host(obj, NULL) : newSV(0); } /** Convert a Perl SV to a Clownfish object of class `klass`. * * - If the SV contains a Clownfish object which passes an "isa" test against * `klass`, return a pointer to it. * - If the SV contains an arrayref and `klass` is VECTOR or OBJ, perform a * deep conversion of the Perl array to a Vector. * - If the SV contains a hashref and `klass` is HASH or OBJ, perform a * deep conversion of the Perl hash to a Hash. * - If `klass` is STRING or OBJ, stringify and return a String. * - If all else fails, throw an exception. * * Returns an non-NULL, "incremented" object that must be decref'd at some * point. */ CFISH_VISIBLE cfish_Obj* cfish_XSBind_perl_to_cfish(pTHX_ SV *sv, cfish_Class *klass); /** As XSBind_perl_to_cfish above, but returns NULL if the SV is undefined * or a reference to an undef. */ CFISH_VISIBLE cfish_Obj* cfish_XSBind_perl_to_cfish_nullable(pTHX_ SV *sv, cfish_Class *klass); /** As XSBind_perl_to_cfish above, but returns an object that can be used for * a while with no need to decref. * * If `klass` is STRING or OBJ, `allocation` must point to stack-allocated * memory that can hold a String. Otherwise, `allocation` should be NULL. */ CFISH_VISIBLE cfish_Obj* cfish_XSBind_perl_to_cfish_noinc(pTHX_ SV *sv, cfish_Class *klass, void *allocation); /** Return the contents of the hash entry's key as UTF-8. */ CFISH_VISIBLE const char* cfish_XSBind_hash_key_to_utf8(pTHX_ HE *entry, STRLEN *size_ptr); /** Perl-specific wrapper for Err#trap. The "routine" must be either a * subroutine reference or the name of a subroutine. */ cfish_Err* cfish_XSBind_trap(SV *routine, SV *context); /** Locate hash-style params passed to an XS subroutine. If a required * parameter is not present, locate_args() will throw an error. * * All possible valid param names must be passed in `specs`; if a * user-supplied param cannot be matched up, locate_args() will throw an * error. * * @param stack The Perl stack. * @param start Where on the Perl stack to start looking for params. For * methods, this would typically be 1; for functions, most likely 0. * @param items The number of arguments passed to the Perl function * (generally, the XS variable `items`). * @params specs An array of XSBind_ParamSpec structs describing the * parameters. * @param locations On success, this output argument will be set to the * location on the stack of each param. Optional arguments that could not * be found have their location set to `items`. * @param The number of parameters in `specs` and elements in `locations`. */ CFISH_VISIBLE void cfish_XSBind_locate_args(pTHX_ SV** stack, int32_t start, int32_t items, const cfish_XSBind_ParamSpec *specs, int32_t *locations, int32_t num_params); /** Convert an argument from the Perl stack to a Clownfish object. Throws * an error if the SV can't be converted. * * @param value The SV from the Perl stack. * @param label The name of the param. * @param klass The class to convert to. * @param allocation Stack allocation for Obj and String. */ CFISH_VISIBLE cfish_Obj* cfish_XSBind_arg_to_cfish(pTHX_ SV *value, const char *label, cfish_Class *klass, void *allocation); /** Like XSBind_arg_to_cfish, but allows undef which is converted to NULL. */ CFISH_VISIBLE cfish_Obj* cfish_XSBind_arg_to_cfish_nullable(pTHX_ SV *value, const char *label, cfish_Class *klass, void *allocation); /** Throw an error because of invalid number of arguments. */ CFISH_VISIBLE void cfish_XSBind_invalid_args_error(pTHX_ CV *cv, const char *param_list); /** Throw an error because of an undefined argument. */ CFISH_VISIBLE void cfish_XSBind_undef_arg_error(pTHX_ const char *label); /** Initialize ISA relations and XSUBs. */ CFISH_VISIBLE void cfish_XSBind_bootstrap(pTHX_ size_t num_classes, const cfish_XSBind_ClassSpec *class_specs, const cfish_XSBind_XSubSpec *xsub_specs, const char *file); #define XSBIND_PARAM(key, required) \ { key, (int16_t)sizeof("" key) - 1, (char)required } /* Define short names for most of the symbols in this file. Note that these * short names are ALWAYS in effect, since they are only used for Perl and we * can be confident they don't conflict with anything. (It's prudent to use * full symbols nevertheless in case someone else defines e.g. a function * named "XSBind_sv_defined".) */ #define XSBind_ClassSpec cfish_XSBind_ClassSpec #define XSBind_XSubSpec cfish_XSBind_XSubSpec #define XSBind_ParamSpec cfish_XSBind_ParamSpec #define XSBind_new_blank_obj cfish_XSBind_new_blank_obj #define XSBind_foster_obj cfish_XSBind_foster_obj #define XSBind_sv_defined cfish_XSBind_sv_defined #define XSBind_sv_true cfish_XSBind_sv_true #define XSBind_cfish_obj_to_sv_inc cfish_XSBind_cfish_obj_to_sv_inc #define XSBind_cfish_obj_to_sv_noinc cfish_XSBind_cfish_obj_to_sv_noinc #define XSBind_cfish_to_perl cfish_XSBind_cfish_to_perl #define XSBind_perl_to_cfish cfish_XSBind_perl_to_cfish #define XSBind_perl_to_cfish_nullable cfish_XSBind_perl_to_cfish_nullable #define XSBind_perl_to_cfish_noinc cfish_XSBind_perl_to_cfish_noinc #define XSBind_hash_key_to_utf8 cfish_XSBind_hash_key_to_utf8 #define XSBind_trap cfish_XSBind_trap #define XSBind_locate_args cfish_XSBind_locate_args #define XSBind_arg_to_cfish cfish_XSBind_arg_to_cfish #define XSBind_arg_to_cfish_nullable cfish_XSBind_arg_to_cfish_nullable #define XSBind_invalid_args_error cfish_XSBind_invalid_args_error #define XSBind_undef_arg_error cfish_XSBind_undef_arg_error #define XSBind_bootstrap cfish_XSBind_bootstrap /* Strip the prefix from some common ClownFish symbols where we know there's * no conflict with Perl. It's a little inconsistent to do this rather than * leave all symbols at full size, but the succinctness is worth it. */ #define THROW CFISH_THROW #define WARN CFISH_WARN #ifdef __cplusplus } #endif #endif // H_CFISH_XSBIND