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

#line 1 "GValue.xs"
/*
 * Copyright (C) 2003-2009 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 35 "GValue.xs"

#include "gperl.h"


/****************************************************************************
 * GValue handling
 *
 * we have code here to handle the fundamental types listed in the API
 * reference, plus the G_TYPE_ENUM and G_TYPE_FLAGS fundamentals.  new
 * fundamentals created by g_type_fundamental_next() are handled by the
 * GPerlValueWrapperClass machinery.
 */

#if 0
  "Skipped embedded POD."
#endif
#line 59 "GValue.xs"
gboolean
gperl_value_from_sv (GValue * value,
		     SV * sv)
{
	GType type;
	if (!gperl_sv_is_defined (sv))
		return TRUE; /* use the GValue type's default */
	type = G_TYPE_FUNDAMENTAL (G_VALUE_TYPE (value));
	/*printf ("TYPE: %d, S: %s\n", type, SvPV_nolen(sv));*/
	switch (type) {
    		case G_TYPE_INTERFACE:
			/* pygtk mentions something about only handling 
			   GInterfaces with a GObject prerequisite.  i'm
			   just blindly treating them as objects until
			   this breaks and i understand what they mean. */
    			g_value_set_object(value, gperl_get_object(sv));
			break;
		case G_TYPE_CHAR:
		{
			gchar *tmp = SvGChar (sv);
#if GLIB_CHECK_VERSION(2, 32, 0)
			g_value_set_schar (value, (gint8)(tmp ? tmp[0] : 0));
#else
			g_value_set_char (value, (gchar)(tmp ? tmp[0] : 0));
#endif
			break;
		}
		case G_TYPE_UCHAR:
		{
			char *tmp = SvPV_nolen (sv);
			g_value_set_uchar (value, (guchar)(tmp ? tmp[0] : 0));
			break;
		}
		case G_TYPE_BOOLEAN:
			/* undef is also false. */
			g_value_set_boolean (value, SvTRUE (sv));
			break;
		case G_TYPE_INT:
			g_value_set_int(value, SvIV(sv));
			break;
		case G_TYPE_UINT:
			g_value_set_uint(value, SvIV(sv));
			break;
		case G_TYPE_LONG:
			g_value_set_long(value, SvIV(sv));
			break;
		case G_TYPE_ULONG:
			g_value_set_ulong(value, SvIV(sv));
			break;
		case G_TYPE_INT64:
			g_value_set_int64(value, SvGInt64(sv));
			break;
		case G_TYPE_UINT64:
			g_value_set_uint64(value, SvGUInt64(sv));
			break;
		case G_TYPE_FLOAT:
			g_value_set_float(value, (gfloat)SvNV(sv));
			break;
		case G_TYPE_DOUBLE:
			g_value_set_double(value, SvNV(sv));
			break;
		case G_TYPE_STRING:
			g_value_set_string(value, SvGChar(sv));
			break;
		case G_TYPE_POINTER:
#if GLIB_CHECK_VERSION(2, 10, 0)
			/* The fundamental type for G_TYPE_GTYPE is
			 * G_TYPE_POINTER, so we have to treat this
			 * specially. */
			if (G_VALUE_TYPE (value) == G_TYPE_GTYPE) {
				g_value_set_gtype (value, gperl_type_from_package (SvGChar (sv)));
				break;
			}
#endif
			g_value_set_pointer (value,
			                     INT2PTR (gpointer, SvIV (sv)));
			break;
		case G_TYPE_BOXED:
			/* SVs need special treatment! */
			if (G_VALUE_HOLDS (value, GPERL_TYPE_SV)) {
				g_value_set_boxed (value,
				                   gperl_sv_is_defined (sv)
				                   ? sv : NULL);
			} else {
				g_value_set_static_boxed (
					value,
					gperl_get_boxed_check (
						sv, G_VALUE_TYPE(value)));
			}
			break;
		case G_TYPE_PARAM:
			g_value_set_param(value, SvGParamSpec (sv));
			break;
		case G_TYPE_OBJECT:
			g_value_set_object(value, gperl_get_object_check (sv, G_VALUE_TYPE(value)));
			break;

		case G_TYPE_ENUM:
			g_value_set_enum(value, gperl_convert_enum(G_VALUE_TYPE(value), sv));
			break;
		case G_TYPE_FLAGS:
			g_value_set_flags(value, gperl_convert_flags(G_VALUE_TYPE(value), sv));
			break;

		default: {
			GPerlValueWrapperClass *wrapper_class;

			wrapper_class = gperl_fundamental_wrapper_class_from_type (type);
			if (wrapper_class && wrapper_class->unwrap) {
				wrapper_class->unwrap (value, sv);
				break;
			}

			croak ("[gperl_value_from_sv] FIXME: unhandled type - %lu (%s fundamental for %s)\n",
			       type, g_type_name (type), G_VALUE_TYPE_NAME (value));
			return FALSE;
		}
	}
	return TRUE;
}


/*
 * =item SV * _gperl_sv_from_value_internal (const GValue * value, gboolean copy_boxed)
 *
 * Coerce whatever is in I<value> into a perl scalar and return it.
 * If I<copy_boxed> is true, boxed values will be copied.  Values of type
 * GPERL_TYPE_SV are always copied (since that is merely a ref).
 *
 * Croaks if the code doesn't know how to perform the conversion.
 *
 * Might end up calling other Perl code.  So if you use this function in XS
 * code for a generic GType, make sure the stack pointer is set up correctly
 * before the call, and restore it after the call.
 *
 * =cut
 */
SV *
_gperl_sv_from_value_internal (const GValue * value,
                               gboolean copy_boxed)
{
	GType type = G_TYPE_FUNDAMENTAL (G_VALUE_TYPE (value));
	switch (type) {
    		case G_TYPE_INTERFACE:
			/* pygtk mentions something about only handling 
			   GInterfaces with a GObject prerequisite.  i'm
			   just blindly treating them as objects until
			   this breaks and i understand what they mean. */
			return gperl_new_object (g_value_get_object (value), FALSE);
		case G_TYPE_CHAR:
#if GLIB_CHECK_VERSION(2, 32, 0)
			return newSViv (g_value_get_schar (value));
#else
			return newSViv (g_value_get_char (value));
#endif

		case G_TYPE_UCHAR:
			return newSVuv (g_value_get_uchar (value));

		case G_TYPE_BOOLEAN:
			return newSViv(g_value_get_boolean(value));

		case G_TYPE_INT:
			return newSViv(g_value_get_int(value));

		case G_TYPE_UINT:
			return newSVuv(g_value_get_uint(value));

		case G_TYPE_LONG:
			return newSViv(g_value_get_long(value));

		case G_TYPE_ULONG:
			return newSVuv(g_value_get_ulong(value));

		case G_TYPE_INT64:
			return newSVGInt64(g_value_get_int64(value));

		case G_TYPE_UINT64:
			return newSVGUInt64(g_value_get_uint64(value));

		case G_TYPE_FLOAT:
			return newSVnv(g_value_get_float(value));

		case G_TYPE_DOUBLE:
			return newSVnv(g_value_get_double(value));

		case G_TYPE_STRING:
			return newSVGChar (g_value_get_string (value));

		case G_TYPE_POINTER:
#if GLIB_CHECK_VERSION(2, 10, 0)
			/* The fundamental type for G_TYPE_GTYPE is
			 * G_TYPE_POINTER, so we have to treat this
			 * specially. */
			if (G_VALUE_TYPE (value) == G_TYPE_GTYPE) {
				GType gtype = g_value_get_gtype (value);
				return newSVGChar (
				  gtype == G_TYPE_NONE
				         ? NULL
				         : gperl_package_from_type (gtype));
			}
#endif
			return newSViv (PTR2IV (g_value_get_pointer (value)));

		case G_TYPE_BOXED:
			/* special case for SVs, which are stored directly
			 * rather than inside blessed wrappers. */
			if (G_VALUE_HOLDS (value, GPERL_TYPE_SV)) {
				SV * sv = g_value_get_boxed (value);
				return sv ? g_value_dup_boxed (value)
				          : &PL_sv_undef;
			}

                        if (copy_boxed)
                                return gperl_new_boxed_copy
                                                (g_value_get_boxed (value),
                                                 G_VALUE_TYPE (value));
                        else
                                return gperl_new_boxed
                                                (g_value_get_boxed (value),
                                                 G_VALUE_TYPE (value),
                                                 FALSE);

		case G_TYPE_PARAM:
			/* can have NULL here fetching object properties of
			 * type G_TYPE_PARAM with no value set yet, or from
			 * ->get_default_value of such a
			 * property. newSVGParamSpec handles NULL by returning
			 * undef. */
			return newSVGParamSpec (g_value_get_param (value));

		case G_TYPE_OBJECT:
			return gperl_new_object (g_value_get_object (value), FALSE);

		case G_TYPE_ENUM:
			return gperl_convert_back_enum (G_VALUE_TYPE (value),
							g_value_get_enum (value));

		case G_TYPE_FLAGS:
			return gperl_convert_back_flags (G_VALUE_TYPE (value),
							 g_value_get_flags (value));

		default: {
			GPerlValueWrapperClass *wrapper_class;

			wrapper_class = gperl_fundamental_wrapper_class_from_type (type);
			if (wrapper_class && wrapper_class->wrap)
				return wrapper_class->wrap (value);

			croak ("[gperl_sv_from_value] FIXME: unhandled type - %lu (%s fundamental for %s)\n",
			       type, g_type_name (type), G_VALUE_TYPE_NAME (value));
		}
	}

	return NULL;
}

#if 0
  "Skipped embedded POD."
#endif
#line 327 "GValue.xs"
SV *
gperl_sv_from_value (const GValue * value)
{
	return _gperl_sv_from_value_internal (value, FALSE);
}

#if 0
  "Skipped embedded POD."
#endif
#line 336 "GValue.xs"

/* apparently this line is required by ExtUtils::ParseXS, but not by xsubpp. */
#line 326 "GValue.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(const CV *const cv, const char *const params);

STATIC void
S_croak_xs_usage(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_nocontext("Usage: %s::%s(%s)", hvname, gvname, params);
        else
	    Perl_croak_nocontext("Usage: %s(%s)", gvname, params);
    } else {
        /* Pants. I don't think that it should be possible to get here. */
	Perl_croak_nocontext("Usage: CODE(0x%" UVxf ")(%s)", PTR2UV(cv), params);
    }
}
#undef  PERL_ARGS_ASSERT_CROAK_XS_USAGE

#define croak_xs_usage        S_croak_xs_usage

#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) */

#if PERL_VERSION_LE(5, 21, 5)
#  define newXS_deffile(a,b) Perl_newXS(aTHX_ a,b,file)
#else
#  define newXS_deffile(a,b) Perl_newXS_deffile(aTHX_ a,b)
#endif

#line 470 "GValue.c"
#ifdef __cplusplus
extern "C"
#endif
XS_EXTERNAL(boot_Glib__Value); /* prototype to pass -Wmissing-prototypes */
XS_EXTERNAL(boot_Glib__Value)
{
#if PERL_VERSION_LE(5, 21, 5)
    dVAR; dXSARGS;
#else
    dVAR; dXSBOOTARGSXSAPIVERCHK;
#endif

    PERL_UNUSED_VAR(cv); /* -W */
    PERL_UNUSED_VAR(items); /* -W */
#if PERL_VERSION_LE(5, 21, 5)
    XS_VERSION_BOOTCHECK;
#  ifdef XS_APIVERSION_BOOTCHECK
    XS_APIVERSION_BOOTCHECK;
#  endif
#endif

#if PERL_VERSION_LE(5, 21, 5)
#  if PERL_VERSION_GE(5, 9, 0)
    if (PL_unitcheckav)
        call_list(PL_scopestack_ix, PL_unitcheckav);
#  endif
    XSRETURN_YES;
#else
    Perl_xs_boot_epilog(aTHX_ ax);
#endif
}

