/*
 * This file was generated automatically by ExtUtils::ParseXS version 3.22 from the
 * contents of GBoxed.xs. Do not edit this file, edit GBoxed.xs instead.
 *
 *    ANY CHANGES MADE HERE WILL BE LOST!
 *
 */

#line 1 "GBoxed.xs"
/*
 * Copyright (C) 2003-2005, 2009-2013 by the gtk2-perl team (see the file
 * AUTHORS for the full list)
 *
 * This library is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Library General Public License as published by
 * the Free Software Foundation; either version 2.1 of the License, or (at your
 * option) any later version.
 *
 * This library is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
 * License for more details.
 *
 * You should have received a copy of the GNU Library General Public License
 * along with this library; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * $Id$
 */

#if 0
  "Skipped embedded POD."
#endif
#line 77 "GBoxed.xs"
/* there's still one list open! */

#include "gperl.h"

/* #define NOISY */

/*
!PRIVATE!

BoxedInfo

similar to ClassInfo in GObject.xs, BoxedInfo stores information about a
boxed type's mapping from C to perl.  we keep two hashes of these structures,
one indexed by GType, the other by perl package name, for quick and easy
lookup.

the fundamental job of this mapping is to tell us what perl package 
corresponds to a particular GType.

the next most important thing is the wrapper_class --- this tells the bindings
what set of functions to use to convert this boxed type in and out of perl.
a default implementation is supplied; see the BoxedWrapper and default_*
stuff.

 */

static GHashTable * info_by_gtype = NULL;
static GHashTable * info_by_package = NULL;

/* and thread-safety for the above: */
G_LOCK_DEFINE_STATIC (info_by_gtype);
G_LOCK_DEFINE_STATIC (info_by_package);

typedef struct _BoxedInfo BoxedInfo;
typedef struct _BoxedWrapper BoxedWrapper;

struct _BoxedInfo {
	GType                    gtype;
	char                   * package;
	GPerlBoxedWrapperClass * wrapper_class;
};


static BoxedInfo *
boxed_info_new (GType gtype,
		const char * package,
		GPerlBoxedWrapperClass * wrapper_class)
{
	BoxedInfo * boxed_info;
	boxed_info = g_new0 (BoxedInfo, 1);
	boxed_info->gtype = gtype;
	boxed_info->package = package ? g_strdup (package) : NULL;
	boxed_info->wrapper_class = wrapper_class;
	return boxed_info;
}

static BoxedInfo *
boxed_info_copy (BoxedInfo * boxed_info)
{
	BoxedInfo * new_boxed_info;
	new_boxed_info = g_new0 (BoxedInfo, 1);
	memcpy (new_boxed_info, boxed_info, sizeof (BoxedInfo));
	new_boxed_info->package = g_strdup (boxed_info->package);
	return new_boxed_info;
}

static void
boxed_info_destroy (BoxedInfo * boxed_info)
{
	if (boxed_info) {
		boxed_info->gtype = 0;
		if (boxed_info->package)
			g_free (boxed_info->package);
		boxed_info->package = NULL;
		boxed_info->wrapper_class = NULL;
		g_free (boxed_info);
	}
}

#if 0
  "Skipped embedded POD."
#endif
#line 177 "GBoxed.xs"
void
gperl_register_boxed (GType gtype,
                      const char * package,
                      GPerlBoxedWrapperClass * wrapper_class)
{
	BoxedInfo * boxed_info;

	G_LOCK (info_by_gtype);
	G_LOCK (info_by_package);

	if (!info_by_gtype) {
		info_by_gtype = g_hash_table_new_full (g_direct_hash,
						       g_direct_equal,
						       NULL, 
						       (GDestroyNotify)
							 boxed_info_destroy);
		info_by_package = g_hash_table_new_full (g_str_hash,
						         g_str_equal,
						         NULL, 
						         NULL);
	}
	boxed_info = boxed_info_new (gtype, package, wrapper_class);

	/* We need to insert into info_by_package first because there might
	 * otherwise be trouble if we overwrite an entry: inserting into
	 * info_by_gtype frees the boxed_info of the overwritten entry, so that
	 * boxed_info->package is no longer valid at this point.
	 *
	 * Note also it's g_hash_table_replace() for info_by_package,
	 * because the old key string in the old boxed_info will be freed
	 * when info_by_gtype updates the value there.
	 */
	g_hash_table_replace (info_by_package, boxed_info->package, boxed_info);
	g_hash_table_insert (info_by_gtype, (gpointer) gtype, boxed_info);

	/* GBoxed types are plain structures, so it would be really
	 * surprising to find a boxed type that actually inherits another
	 * boxed type.  we'll do that at the perl level, for example with
	 * GdkEvent, but at the C level it's not safe.  such things should
	 * be objects.
	 *  so, we don't have to worry about the complicated semantics of
	 * type registration like gperl_register_object, and life is simple
	 * and beautiful.
	 */
	if (package && gtype != G_TYPE_BOXED)
		gperl_set_isa (package, "Glib::Boxed");
#ifdef NOISY
	warn ("gperl_register_boxed (%d(%s), %s, %p)\n",
	      gtype, g_type_name (gtype), package, wrapper_class);
#endif

	G_UNLOCK (info_by_gtype);
	G_UNLOCK (info_by_package);
}

#if 0
  "Skipped embedded POD."
#endif
#line 245 "GBoxed.xs"

void
gperl_register_boxed_alias (GType gtype,
			    const char * package)
{
	BoxedInfo * boxed_info;

	G_LOCK (info_by_gtype);
	boxed_info = (BoxedInfo *)
		g_hash_table_lookup (info_by_gtype, (gpointer) gtype);
	G_UNLOCK (info_by_gtype);

	if (!boxed_info) {
		croak ("cannot register alias %s for the unregistered type %s",
		       package, g_type_name (gtype));
	}

	G_LOCK (info_by_package);
	/* associate package with the same boxed_info.  boxed_info is still
	   owned by info_by_gtype.  info_by_package doesn't have a
	   free-function installed, so that's ok. */
	g_hash_table_insert (info_by_package, (char *) package, boxed_info);
	G_UNLOCK (info_by_package);
}

#if 0
  "Skipped embedded POD."
#endif
#line 281 "GBoxed.xs"

void
gperl_register_boxed_synonym (GType registered_gtype,
                              GType synonym_gtype)
{
	BoxedInfo * registered_boxed_info, * synonym_boxed_info;

	G_LOCK (info_by_gtype);

	registered_boxed_info = (BoxedInfo *)
		g_hash_table_lookup (info_by_gtype, (gpointer) registered_gtype);

	if (!registered_boxed_info) {
		croak ("cannot make %s synonymous to the unregistered type %s",
		       g_type_name (synonym_gtype),
		       g_type_name (registered_gtype));
	}

	synonym_boxed_info = boxed_info_copy (registered_boxed_info);
	g_hash_table_insert (info_by_gtype, (gpointer) synonym_gtype,
	                     synonym_boxed_info);

	G_UNLOCK (info_by_gtype);
}

#if 0
  "Skipped embedded POD."
#endif
#line 312 "GBoxed.xs"
GType
gperl_boxed_type_from_package (const char * package)
{
	BoxedInfo * boxed_info;

	G_LOCK (info_by_package);

	boxed_info = (BoxedInfo*)
		g_hash_table_lookup (info_by_package, package);

	G_UNLOCK (info_by_package);

	if (!boxed_info)
		return 0;
	return boxed_info->gtype;
}

#if 0
  "Skipped embedded POD."
#endif
#line 335 "GBoxed.xs"
const char *
gperl_boxed_package_from_type (GType type)
{
	BoxedInfo * boxed_info;

	G_LOCK (info_by_gtype);

	boxed_info = (BoxedInfo*)
		g_hash_table_lookup (info_by_gtype, (gpointer) type);

	G_UNLOCK (info_by_gtype);

	if (!boxed_info)
		return NULL;
	return boxed_info->package;
}

/************************************************************/

/*
BoxedWrapper

In order to make life simple, we supply a default GPerlBoxedWrapperClass,
which wraps boxed type objects into an opaque data structure.

GBoxed types don't know what their own type is, nor do they give you a way
to store metadata.  thus, we actually wrap a BoxedWrapper struct into 
the perl wrapper, and store the boxed object and some metadata in the
BoxedWrapper.
*/

/* inspired by pygtk */
struct _BoxedWrapper {
	gpointer boxed;
	GType gtype;
	gboolean free_on_destroy;
};

static BoxedWrapper *
boxed_wrapper_new (gpointer boxed,
                   GType gtype,
                   gboolean free_on_destroy)
{
	BoxedWrapper * boxed_wrapper;
	boxed_wrapper = g_new (BoxedWrapper, 1);
	boxed_wrapper->boxed = boxed;
	boxed_wrapper->gtype = gtype;
	boxed_wrapper->free_on_destroy = free_on_destroy;
	return boxed_wrapper;
}

static void
boxed_wrapper_destroy (BoxedWrapper * boxed_wrapper)
{
	if (boxed_wrapper) {
		if (boxed_wrapper->free_on_destroy)
			g_boxed_free (boxed_wrapper->gtype, boxed_wrapper->boxed);
		g_free (boxed_wrapper);
	} else {
		warn ("boxed_wrapper_destroy called on NULL pointer");
	}
}

static SV *
default_boxed_wrap (GType        gtype,
		    const char * package,
		    gpointer     boxed,
		    gboolean     own)
{
	SV * sv;
	BoxedWrapper * boxed_wrapper;

	boxed_wrapper = boxed_wrapper_new (boxed, gtype, own);

	sv = newSV (0);
	sv_setref_pv (sv, package, boxed_wrapper);

#ifdef NOISY
	warn ("default_boxed_wrap 0x%p for %s 0x%p",
	      boxed_wrapper, package, boxed);
#endif
	return sv;
}

static gpointer
default_boxed_unwrap (GType        gtype,
		      const char * package,
		      SV         * sv)
{
	BoxedWrapper * boxed_wrapper;

	PERL_UNUSED_VAR (gtype);

	if (!gperl_sv_is_ref (sv))
		croak ("expected a blessed reference");

	if (!sv_derived_from (sv, package))
		croak ("%s is not of type %s",
		       gperl_format_variable_for_output (sv),
		       package);

	boxed_wrapper = INT2PTR (BoxedWrapper*, SvIV (SvRV (sv)));
	if (!boxed_wrapper)
		croak ("internal nastiness: boxed wrapper contains NULL pointer");
	return boxed_wrapper->boxed;

}

static void
default_boxed_destroy (SV * sv)
{
#ifdef NOISY
	{
	BoxedWrapper * wrapper = (BoxedWrapper*) SvIV (SvRV (sv));
	warn ("default_boxed_destroy wrapper 0x%p --- %s 0x%p\n", wrapper,
	      g_type_name (wrapper ? wrapper->gtype : 0),
	      wrapper ? wrapper->boxed : NULL);
	}
#endif
	boxed_wrapper_destroy (INT2PTR (BoxedWrapper*, SvIV (SvRV (sv))));
}


static GPerlBoxedWrapperClass _default_wrapper_class = {
	default_boxed_wrap,
	default_boxed_unwrap,
	default_boxed_destroy
};

#if 0
  "Skipped embedded POD."
#endif
#line 472 "GBoxed.xs"
GPerlBoxedWrapperClass *
gperl_default_boxed_wrapper_class (void)
{
	return &_default_wrapper_class;
}

/***************************************************************************/


#if 0
  "Skipped embedded POD."
#endif
#line 496 "GBoxed.xs"
SV *
gperl_new_boxed (gpointer boxed,
		 GType gtype,
		 gboolean own)
{
	BoxedInfo * boxed_info;
	GPerlBoxedWrapFunc wrap;

	if (!boxed)
	{
#ifdef NOISY
		warn ("NULL pointer made it into gperl_new_boxed");
#endif
		return &PL_sv_undef;
	}

	G_LOCK (info_by_gtype);

	boxed_info = (BoxedInfo*)
		g_hash_table_lookup (info_by_gtype, (gpointer) gtype);

	G_UNLOCK (info_by_gtype);

	if (!boxed_info)
		croak ("GType %s (%d) is not registered with gperl",
		       g_type_name (gtype), gtype);

	wrap = boxed_info->wrapper_class
	     ? boxed_info->wrapper_class->wrap
	     : _default_wrapper_class.wrap;
	
	if (!wrap)
		croak ("no function to wrap boxed objects of type %s / %s",
		       g_type_name (gtype), boxed_info->package);

	return (*wrap) (gtype, boxed_info->package, boxed, own);
}


#if 0
  "Skipped embedded POD."
#endif
#line 541 "GBoxed.xs"
SV *
gperl_new_boxed_copy (gpointer boxed,
                      GType gtype)
{
	return boxed
		? gperl_new_boxed (g_boxed_copy (gtype, boxed), gtype, TRUE)
		: &PL_sv_undef;
}


#if 0
  "Skipped embedded POD."
#endif
#line 557 "GBoxed.xs"
gpointer
gperl_get_boxed_check (SV * sv, GType gtype)
{
	BoxedInfo * boxed_info;
	GPerlBoxedUnwrapFunc unwrap;

	if (!gperl_sv_is_defined (sv))
		croak ("variable not allowed to be undef where %s is wanted",
		       g_type_name (gtype));

	G_LOCK (info_by_gtype);
	boxed_info = g_hash_table_lookup (info_by_gtype, (gpointer) gtype);
	G_UNLOCK (info_by_gtype);

	if (!boxed_info)
		croak ("internal problem: GType %s (%d) has not been registered with GPerl",
			g_type_name (gtype), gtype);

	unwrap = boxed_info->wrapper_class
	       ? boxed_info->wrapper_class->unwrap
	       : _default_wrapper_class.unwrap;

	if (!unwrap)
		croak ("no function to unwrap boxed objects of type %s / %s",
		       g_type_name (gtype), boxed_info->package);

	return (*unwrap) (gtype, boxed_info->package, sv);
}

#if 0
  "Skipped embedded POD."
#endif
#line 589 "GBoxed.xs"



static BoxedInfo *
lookup_known_package_recursive (const char * package)
{
	BoxedInfo * boxed_info =
		g_hash_table_lookup (info_by_package, package);

	if (!boxed_info) {
		int i;
		char * isa_name = form ("%s::ISA", package);
		AV * isa = get_av (isa_name, FALSE);
		if (!isa)
			return NULL;
		for (i = 0 ; i <= av_len (isa); i++) {
			SV ** sv = av_fetch (isa, i, FALSE);
			char * p = sv ? SvPV_nolen (*sv) : NULL;
			if (p) {
				boxed_info =
					lookup_known_package_recursive (p);
				if (boxed_info)
					break;
			}
		}
	}

	return boxed_info;
}


#if GLIB_CHECK_VERSION (2, 4, 0)


static SV*
strv_wrap (GType        gtype,
	   const char * package,
	   gpointer     boxed,
	   gboolean     own)
{
	AV * av;
	int i;
	gchar ** strv;
	PERL_UNUSED_VAR (gtype);
	PERL_UNUSED_VAR (package);

	if (!boxed)
		return &PL_sv_undef;

	strv = (gchar**) boxed;

	av = newAV ();

	for (i = 0 ; strv[i] != NULL ; i++)
		av_push (av, newSVGChar (strv[i]));

	if (own)
		g_strfreev (strv);

	return newRV_noinc ((SV*)av);
}

static gpointer
strv_unwrap (GType        gtype,
	     const char * package,
	     SV         * sv)
{
	gchar ** strv = NULL;
	PERL_UNUSED_VAR (gtype);
	PERL_UNUSED_VAR (package);

	/* pass undef */
	if (!gperl_sv_is_defined (sv))
		return NULL;

	if (gperl_sv_is_ref (sv)) {
		AV * av;
		int n;

		/* only allow a reference to an array */
		if (!gperl_sv_is_array_ref (sv))
			croak ("expecting a reference to an array of strings for Glib::Strv");
		av = (AV*) SvRV (sv);
		n = av_len (av) + 1;
		if (n > 0) {
			int i;
			strv = gperl_alloc_temp ((n + 1) * sizeof (gchar *));
			for (i = 0 ; i < n ; i++)
				strv[i] = SvGChar (*av_fetch (av, i, FALSE));
			strv[n] = NULL;
		}
		
	} else {
		/* stringify anything else, assuming it's a one-element list */
		strv = gperl_alloc_temp (2 * sizeof (gchar*));
		strv[0] = SvGChar (sv);
		strv[1] = NULL;
	}

	return strv;
}

static GPerlBoxedWrapperClass strv_wrapper_class = {
	strv_wrap,
	strv_unwrap,
	NULL
};

#endif


static SV*
gstring_wrap (GType        gtype,
	      const char * package,
	      gpointer     boxed,
	      gboolean     own)
{
	SV * sv;
	GString *gstr;
	PERL_UNUSED_VAR (gtype);
	PERL_UNUSED_VAR (package);

	if (!boxed)
		return &PL_sv_undef;

	gstr = (GString*) boxed;

	sv = newSVpv (gstr->str, gstr->len);

	if (own)
		g_string_free (gstr, TRUE);

	return sv;
}

static gpointer
gstring_unwrap (GType        gtype,
	        const char * package,
	        SV         * sv)
{
	GString *gstr = NULL;
	PERL_UNUSED_VAR (gtype);
	PERL_UNUSED_VAR (package);

	/* pass undef */
	if (!gperl_sv_is_defined (sv))
		return NULL;

	gstr = gperl_alloc_temp (sizeof (GString));
	gstr->str = SvPV (sv, gstr->len);
	gstr->allocated_len = gstr->len;

	return gstr;
}

static GPerlBoxedWrapperClass gstring_wrapper_class = {
	gstring_wrap,
	gstring_unwrap,
	NULL
};


#if GLIB_CHECK_VERSION (2, 26, 0)

static SV*
gerror_wrap (GType        gtype,
	     const char * package,
	     gpointer     boxed,
	     gboolean     own)
{
	SV *sv;
	GError *error;
	PERL_UNUSED_VAR (gtype);
	PERL_UNUSED_VAR (package);

	if (!boxed)
		return &PL_sv_undef;

	error = (GError*) boxed;

	sv = gperl_sv_from_gerror (error);

	if (own)
		g_error_free (error);

	return sv;
}

static gpointer
gerror_unwrap (GType        gtype,
	       const char * package,
	       SV         * sv)
{
	GError *error = NULL;
	PERL_UNUSED_VAR (gtype);
	PERL_UNUSED_VAR (package);

	gperl_gerror_from_sv (sv, &error);

	return error;
}

static GPerlBoxedWrapperClass gerror_wrapper_class = {
	gerror_wrap,
	gerror_unwrap,
	NULL
};

#endif



#line 705 "GBoxed.c"
#ifndef PERL_UNUSED_VAR
#  define PERL_UNUSED_VAR(var) if (0) var = var
#endif

#ifndef dVAR
#  define dVAR		dNOOP
#endif


/* This stuff is not part of the API! You have been warned. */
#ifndef PERL_VERSION_DECIMAL
#  define PERL_VERSION_DECIMAL(r,v,s) (r*1000000 + v*1000 + s)
#endif
#ifndef PERL_DECIMAL_VERSION
#  define PERL_DECIMAL_VERSION \
	  PERL_VERSION_DECIMAL(PERL_REVISION,PERL_VERSION,PERL_SUBVERSION)
#endif
#ifndef PERL_VERSION_GE
#  define PERL_VERSION_GE(r,v,s) \
	  (PERL_DECIMAL_VERSION >= PERL_VERSION_DECIMAL(r,v,s))
#endif
#ifndef PERL_VERSION_LE
#  define PERL_VERSION_LE(r,v,s) \
	  (PERL_DECIMAL_VERSION <= PERL_VERSION_DECIMAL(r,v,s))
#endif

/* XS_INTERNAL is the explicit static-linkage variant of the default
 * XS macro.
 *
 * XS_EXTERNAL is the same as XS_INTERNAL except it does not include
 * "STATIC", ie. it exports XSUB symbols. You probably don't want that
 * for anything but the BOOT XSUB.
 *
 * See XSUB.h in core!
 */


/* TODO: This might be compatible further back than 5.10.0. */
#if PERL_VERSION_GE(5, 10, 0) && PERL_VERSION_LE(5, 15, 1)
#  undef XS_EXTERNAL
#  undef XS_INTERNAL
#  if defined(__CYGWIN__) && defined(USE_DYNAMIC_LOADING)
#    define XS_EXTERNAL(name) __declspec(dllexport) XSPROTO(name)
#    define XS_INTERNAL(name) STATIC XSPROTO(name)
#  endif
#  if defined(__SYMBIAN32__)
#    define XS_EXTERNAL(name) EXPORT_C XSPROTO(name)
#    define XS_INTERNAL(name) EXPORT_C STATIC XSPROTO(name)
#  endif
#  ifndef XS_EXTERNAL
#    if defined(HASATTRIBUTE_UNUSED) && !defined(__cplusplus)
#      define XS_EXTERNAL(name) void name(pTHX_ CV* cv __attribute__unused__)
#      define XS_INTERNAL(name) STATIC void name(pTHX_ CV* cv __attribute__unused__)
#    else
#      ifdef __cplusplus
#        define XS_EXTERNAL(name) extern "C" XSPROTO(name)
#        define XS_INTERNAL(name) static XSPROTO(name)
#      else
#        define XS_EXTERNAL(name) XSPROTO(name)
#        define XS_INTERNAL(name) STATIC XSPROTO(name)
#      endif
#    endif
#  endif
#endif

/* perl >= 5.10.0 && perl <= 5.15.1 */


/* The XS_EXTERNAL macro is used for functions that must not be static
 * like the boot XSUB of a module. If perl didn't have an XS_EXTERNAL
 * macro defined, the best we can do is assume XS is the same.
 * Dito for XS_INTERNAL.
 */
#ifndef XS_EXTERNAL
#  define XS_EXTERNAL(name) XS(name)
#endif
#ifndef XS_INTERNAL
#  define XS_INTERNAL(name) XS(name)
#endif

/* Now, finally, after all this mess, we want an ExtUtils::ParseXS
 * internal macro that we're free to redefine for varying linkage due
 * to the EXPORT_XSUB_SYMBOLS XS keyword. This is internal, use
 * XS_EXTERNAL(name) or XS_INTERNAL(name) in your code if you need to!
 */

#undef XS_EUPXS
#if defined(PERL_EUPXS_ALWAYS_EXPORT)
#  define XS_EUPXS(name) XS_EXTERNAL(name)
#else
   /* default to internal */
#  define XS_EUPXS(name) XS_INTERNAL(name)
#endif

#ifndef PERL_ARGS_ASSERT_CROAK_XS_USAGE
#define PERL_ARGS_ASSERT_CROAK_XS_USAGE assert(cv); assert(params)

/* prototype to pass -Wmissing-prototypes */
STATIC void
S_croak_xs_usage(pTHX_ const CV *const cv, const char *const params);

STATIC void
S_croak_xs_usage(pTHX_ const CV *const cv, const char *const params)
{
    const GV *const gv = CvGV(cv);

    PERL_ARGS_ASSERT_CROAK_XS_USAGE;

    if (gv) {
        const char *const gvname = GvNAME(gv);
        const HV *const stash = GvSTASH(gv);
        const char *const hvname = stash ? HvNAME(stash) : NULL;

        if (hvname)
            Perl_croak(aTHX_ "Usage: %s::%s(%s)", hvname, gvname, params);
        else
            Perl_croak(aTHX_ "Usage: %s(%s)", gvname, params);
    } else {
        /* Pants. I don't think that it should be possible to get here. */
        Perl_croak(aTHX_ "Usage: CODE(0x%"UVxf")(%s)", PTR2UV(cv), params);
    }
}
#undef  PERL_ARGS_ASSERT_CROAK_XS_USAGE

#ifdef PERL_IMPLICIT_CONTEXT
#define croak_xs_usage(a,b)    S_croak_xs_usage(aTHX_ a,b)
#else
#define croak_xs_usage        S_croak_xs_usage
#endif

#endif

/* NOTE: the prototype of newXSproto() is different in versions of perls,
 * so we define a portable version of newXSproto()
 */
#ifdef newXS_flags
#define newXSproto_portable(name, c_impl, file, proto) newXS_flags(name, c_impl, file, proto, 0)
#else
#define newXSproto_portable(name, c_impl, file, proto) (PL_Sv=(SV*)newXS(name, c_impl, file), sv_setpv(PL_Sv, proto), (CV*)PL_Sv)
#endif /* !defined(newXS_flags) */

#line 847 "GBoxed.c"

XS_EUPXS(XS_Glib__Boxed_copy); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Glib__Boxed_copy)
{
    dVAR; dXSARGS;
    if (items != 1)
       croak_xs_usage(cv,  "sv");
    {
#line 837 "GBoxed.xs"
	BoxedInfo * boxed_info;
	GPerlBoxedWrapperClass * class;
	gpointer boxed;
	const char * package;
#line 861 "GBoxed.c"
	SV *	RETVAL;
	SV *	sv = ST(0)
;
#line 842 "GBoxed.xs"
	/* the sticky part is that we have to decipher from the SV what gtype
	 * we actually have; but the SV may have been blessed into some
	 * other type.  however, if we got here, then Glib::Boxed is in the
	 * @ISA somewhere, so we should be able to walk the inheritance
	 * tree until we find a valid GType. */
	package = sv_reftype (SvRV (sv), TRUE);
	G_LOCK (info_by_package);
	boxed_info = lookup_known_package_recursive (package);
	G_UNLOCK (info_by_package);

	if (!boxed_info)
		croak ("can't find boxed class registration info for %s\n",
		       package);

	class = boxed_info->wrapper_class
	      ? boxed_info->wrapper_class
	      : &_default_wrapper_class;

	if (!class->wrap)
		croak ("no function to wrap boxed objects of type %s / %s",
		       g_type_name (boxed_info->gtype), boxed_info->package);
	if (!class->unwrap)
		croak ("no function to unwrap boxed objects of type %s / %s",
		       g_type_name (boxed_info->gtype), boxed_info->package);

	boxed = class->unwrap (boxed_info->gtype, boxed_info->package, sv);

	/* No PUTBACK/SPAGAIN needed here. */
	RETVAL = class->wrap (boxed_info->gtype, boxed_info->package, 
	                      g_boxed_copy (boxed_info->gtype, boxed), TRUE);
#line 896 "GBoxed.c"
	ST(0) = RETVAL;
	sv_2mortal(ST(0));
    }
    XSRETURN(1);
}


XS_EUPXS(XS_Glib__Boxed_DESTROY); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Glib__Boxed_DESTROY)
{
    dVAR; dXSARGS;
    if (items != 1)
       croak_xs_usage(cv,  "sv");
    {
	SV *	sv = ST(0)
;
#line 879 "GBoxed.xs"
	BoxedInfo * boxed_info;
	const char * class;
	GPerlBoxedDestroyFunc destroy;
#line 917 "GBoxed.c"
#line 883 "GBoxed.xs"
	if (!gperl_sv_is_ref (sv) || !SvRV (sv))
		croak ("DESTROY called on a bad value");

	/* we need to find the wrapper class associated with whatever type
	 * the wrapper is blessed into. */
	class = sv_reftype (SvRV (sv), TRUE);
	G_LOCK (info_by_package);
	boxed_info = g_hash_table_lookup (info_by_package, class);
	G_UNLOCK (info_by_package);
#ifdef NOISY
	warn ("Glib::Boxed::DESTROY (%s) for %s -> %s", 
	      SvPV_nolen (sv),
	      class,
	      boxed_info ? g_type_name (boxed_info->gtype) : NULL);
#endif
	destroy = boxed_info
	        ? (boxed_info->wrapper_class
		      ? boxed_info->wrapper_class->destroy
		      : _default_wrapper_class.destroy)
		: NULL;
	if (destroy)
		(*destroy) (sv);
#line 941 "GBoxed.c"
    }
    XSRETURN_EMPTY;
}

#ifdef __cplusplus
extern "C"
#endif
XS_EXTERNAL(boot_Glib__Boxed); /* prototype to pass -Wmissing-prototypes */
XS_EXTERNAL(boot_Glib__Boxed)
{
    dVAR; dXSARGS;
#if (PERL_REVISION == 5 && PERL_VERSION < 9)
    char* file = __FILE__;
#else
    const char* file = __FILE__;
#endif

    PERL_UNUSED_VAR(cv); /* -W */
    PERL_UNUSED_VAR(items); /* -W */
#ifdef XS_APIVERSION_BOOTCHECK
    XS_APIVERSION_BOOTCHECK;
#endif
    XS_VERSION_BOOTCHECK;

        newXS("Glib::Boxed::copy", XS_Glib__Boxed_copy, file);
        newXS("Glib::Boxed::DESTROY", XS_Glib__Boxed_DESTROY, file);

    /* Initialisation Section */

#line 804 "GBoxed.xs"
	gperl_register_boxed (G_TYPE_BOXED, "Glib::Boxed", NULL);
	gperl_register_boxed (G_TYPE_STRING, "Glib::String", NULL);
	gperl_set_isa ("Glib::String", "Glib::Boxed");
	gperl_register_boxed (G_TYPE_GSTRING, "Glib::GString", &gstring_wrapper_class);
#if GLIB_CHECK_VERSION (2, 4, 0)
	gperl_register_boxed (G_TYPE_STRV, "Glib::Strv", &strv_wrapper_class);
#endif
#if GLIB_CHECK_VERSION (2, 26, 0)
	gperl_register_boxed (G_TYPE_ERROR, "Glib::Error", &gerror_wrapper_class);
#endif

#line 983 "GBoxed.c"

    /* End of Initialisation Section */

#if (PERL_REVISION == 5 && PERL_VERSION >= 9)
  if (PL_unitcheckav)
       call_list(PL_scopestack_ix, PL_unitcheckav);
#endif
    XSRETURN_YES;
}

