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

#line 1 "CairoPath.xs"
/*
 * Copyright (c) 2004-2011 by the cairo perl team (see the file README)
 *
 * Licensed under the LGPL, see LICENSE file for more information.
 *
 * $Id$
 */

#include <cairo-perl.h>
#include <cairo-perl-private.h>

#include "ppport.h"

#define MY_MAGIC_SIG 0xCAFE /* Let's hope this is unique enough */

static MAGIC *
cairo_perl_mg_find (SV *sv, int type)
{
	if (sv) {
		MAGIC *mg;
		for (mg = SvMAGIC (sv); mg; mg = mg->mg_moremagic) {
			if (mg->mg_type == type && mg->mg_private == MY_MAGIC_SIG)
				return mg;
		}
	}
	return NULL;
}

static void *
cairo_perl_mg_get (SV * sv)
{
	MAGIC * mg;
	if (!cairo_perl_sv_is_ref (sv) ||
	    !(mg = cairo_perl_mg_find (SvRV (sv), PERL_MAGIC_ext)))
		return NULL;
	return mg->mg_ptr;
}

/* ------------------------------------------------------------------------- */

static SV *
create_tie (SV * sv, void * object, const char * package)
{
	SV * tie;
	HV * stash;
	MAGIC * mg;

	/* Create a tied reference. */
	tie = newRV_noinc (sv);
	stash = gv_stashpv (package, TRUE);
	sv_bless (tie, stash);
	sv_magic (sv, tie, PERL_MAGIC_tied, Nullch, 0);

	/* Associate the array with the original path via magic. */
	sv_magic (sv, 0, PERL_MAGIC_ext, (const char *) object, 0);

	mg = mg_find (sv, PERL_MAGIC_ext);

	/* Mark the mg as belonging to us. */
	mg->mg_private = MY_MAGIC_SIG;

#if PERL_REVISION <= 5 && PERL_VERSION <= 6
	/* perl 5.6.x doesn't actually set mg_ptr when namlen == 0, so do it
	 * now. */
	mg->mg_ptr = (char *) object;
#endif /* 5.6.x */

	return tie;
}

static SV *
create_tied_av (void * object, const char * package)
{
	return create_tie ((SV *) newAV (), object, package);
}

static SV *
create_tied_hv (void * object, const char * package)
{
	return create_tie ((SV *) newHV (), object, package);
}

/* ------------------------------------------------------------------------- */

#define FETCH_POINT(i)						\
	if ((svp = av_fetch (points, i, 0)) &&			\
	    cairo_perl_sv_is_defined (*svp))			\
	{							\
		point = (AV *) SvRV (*svp);			\
		if ((svp = av_fetch (point, 0, 0)))		\
			data[i+1].point.x = SvNV (*svp);	\
		if ((svp = av_fetch (point, 1, 0)))		\
			data[i+1].point.y = SvNV (*svp);	\
	}

static void
fill_data_from_array (cairo_path_data_t * data, cairo_path_data_type_t type, AV * points)
{
	SV ** svp;
	AV * point;
	switch (type) {
	    case CAIRO_PATH_MOVE_TO:
		data->header.type = CAIRO_PATH_MOVE_TO;
		data->header.length = 2;
		FETCH_POINT (0);
		break;

	    case CAIRO_PATH_LINE_TO:
		data->header.type = CAIRO_PATH_LINE_TO;
		data->header.length = 2;
		FETCH_POINT (0);
		break;

	    case CAIRO_PATH_CURVE_TO:
		data->header.type = CAIRO_PATH_CURVE_TO;
		data->header.length = 4;
		FETCH_POINT (0);
		FETCH_POINT (1);
		FETCH_POINT (2);
		break;

	    case CAIRO_PATH_CLOSE_PATH:
		data->header.type = CAIRO_PATH_CLOSE_PATH;
		data->header.length = 1;
		break;
	}
}

/* This uses cairo_perl_alloc_temp.  So the return value is only valid until
 * the next FREETMPS occurs.  At the moment, the only cairo function that
 * *takes* a cairo_path_t is cairo_append_path, and it acts on the path
 * immediately and does not store it.  So that's fine. */
static cairo_path_t *
path_from_array (SV * sv)
{
	AV *av;
	int i, num_data;
	cairo_path_t *path;
	cairo_path_data_t *data;

	if (!cairo_perl_sv_is_array_ref (sv))
		croak ("a Cairo::Path has to be an array reference");

	av = (AV *) SvRV (sv);

	num_data = 0;
	for (i = 0; i <= av_len (av); i++) {
		SV **svp;
		HV *hv;

		svp = av_fetch (av, i, 0);
		if (!svp || !cairo_perl_sv_is_hash_ref (*svp))
			croak ("a Cairo::Path has to contain hash references");
		hv = (HV *) SvRV (*svp);

		svp = hv_fetch (hv, "type", 4, 0);
		if (!svp || !cairo_perl_sv_is_defined (*svp))
			croak ("hash references inside a Cairo::Path must have a 'type' key");

		switch (cairo_path_data_type_from_sv (*svp)) {
		    case CAIRO_PATH_MOVE_TO:
		    case CAIRO_PATH_LINE_TO:
			num_data += 2;
			break;
		    case CAIRO_PATH_CURVE_TO:
			num_data += 4;
			break;
		    case CAIRO_PATH_CLOSE_PATH:
			num_data += 1;
			break;
		}
	}

	path = cairo_perl_alloc_temp (sizeof (cairo_path_t));
	path->num_data = num_data;
	path->data = cairo_perl_alloc_temp (path->num_data * sizeof (cairo_path_data_t));
	path->status = CAIRO_STATUS_SUCCESS;

	data = path->data;
	for (i = 0; i <= av_len (av); i++) {
		SV **svp;
		HV *hv;
		AV *points;

		svp = av_fetch (av, i, 0);
		hv = (HV *) SvRV (*svp);

		svp = hv_fetch (hv, "points", 6, 0);
		if (!svp || !cairo_perl_sv_is_array_ref (*svp))
			croak ("hash references inside a Cairo::Path must "
			       "contain a 'points' key which contains an array "
			       "reference of points");
		points = (AV *) SvRV (*svp);

		svp = hv_fetch (hv, "type", 4, 0);
		fill_data_from_array (data, cairo_path_data_type_from_sv (*svp), points);
		data += data->header.length;
	}

	return path;
}

SV *
newSVCairoPath (cairo_path_t * path)
{
	return create_tied_av (path, "Cairo::Path");
}

cairo_path_t *
SvCairoPath (SV * sv)
{
	cairo_path_t * path;
	path = cairo_perl_mg_get (sv);
	if (!path) {
		path = path_from_array (sv);
	}
	return path;
}

/* ------------------------------------------------------------------------- */

static SV *
newSVCairoPathData (cairo_path_data_t * data)
{
	return create_tied_hv (data, "Cairo::Path::Data");
}

static cairo_path_data_t *
SvCairoPathData (SV * sv)
{
	return cairo_perl_mg_get (sv);
}

/* ------------------------------------------------------------------------- */

static SV *
newSVCairoPathPoints (cairo_path_data_t * data)
{
	return create_tied_av (data, "Cairo::Path::Points");
}

static cairo_path_data_t *
SvCairoPathPoints (SV * sv)
{
	return cairo_perl_mg_get (sv);
}

/* ------------------------------------------------------------------------- */

static SV *
newSVCairoPathPoint (cairo_path_data_t * data)
{
	return create_tied_av (data, "Cairo::Path::Point");
}

static cairo_path_data_t *
SvCairoPathPoint (SV * sv)
{
	return cairo_perl_mg_get (sv);
}

/* ------------------------------------------------------------------------- */

static IV
n_points (cairo_path_data_t * data)
{
	switch (data->header.type) {
	    case CAIRO_PATH_MOVE_TO:
	    case CAIRO_PATH_LINE_TO:
		return 1;
	    case CAIRO_PATH_CURVE_TO:
		return 3;
	    case CAIRO_PATH_CLOSE_PATH:
		return 0;
	}
	return -1;
}

/* ------------------------------------------------------------------------- */

#line 291 "CairoPath.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 435 "CairoPath.c"

XS_EUPXS(XS_Cairo__Path_DESTROY); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Cairo__Path_DESTROY)
{
    dVAR; dXSARGS;
    if (items != 1)
       croak_xs_usage(cv,  "sv");
    {
#line 285 "CairoPath.xs"
	cairo_path_t *path;
#line 446 "CairoPath.c"
	SV *	sv = ST(0)
;
#line 287 "CairoPath.xs"
	path = SvCairoPath (sv);
	if (path) {
#if PERL_REVISION <= 5 && PERL_VERSION <= 6
		/* Unset mg_ptr to prevent perl 5.6.x from trying to free it again. */
		MAGIC *mg = cairo_perl_mg_find (SvRV (sv), PERL_MAGIC_ext);
		mg->mg_ptr = NULL;
#endif /* 5.6.x */
		cairo_path_destroy (path);
	}
#line 459 "CairoPath.c"
    }
    XSRETURN_EMPTY;
}


XS_EUPXS(XS_Cairo__Path_FETCHSIZE); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Cairo__Path_FETCHSIZE)
{
    dVAR; dXSARGS;
    if (items != 1)
       croak_xs_usage(cv,  "path");
    {
#line 299 "CairoPath.xs"
	int i;
#line 474 "CairoPath.c"
	IV	RETVAL;
	dXSTARG;
	cairo_path_t *	path = SvCairoPath (ST(0))
;
#line 301 "CairoPath.xs"
	RETVAL = 0;
	for (i = 0; i < path->num_data; i += path->data[i].header.length)
		RETVAL++;
#line 483 "CairoPath.c"
	XSprePUSH; PUSHi((IV)RETVAL);
    }
    XSRETURN(1);
}


XS_EUPXS(XS_Cairo__Path_FETCH); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Cairo__Path_FETCH)
{
    dVAR; dXSARGS;
    if (items != 2)
       croak_xs_usage(cv,  "path, index");
    {
#line 309 "CairoPath.xs"
	int i, counter = 0;
#line 499 "CairoPath.c"
	SV *	RETVAL;
	cairo_path_t *	path = SvCairoPath (ST(0))
;
	IV	index = (IV)SvIV(ST(1))
;
#line 311 "CairoPath.xs"
	RETVAL = &PL_sv_undef;
	for (i = 0; i < path->num_data; i += path->data[i].header.length) {
		if (counter++ == index) {
			cairo_path_data_t *data = &path->data[i];
			RETVAL = newSVCairoPathData (data);
			break;
		}
	}
#line 514 "CairoPath.c"
	RETVAL = sv_2mortal(RETVAL);
	ST(0) = RETVAL;
    }
    XSRETURN(1);
}

#if PERL_REVISION <= 5 && PERL_VERSION <= 6
#define XSubPPtmpAAAA 1


XS_EUPXS(XS_Cairo__Path__Data_DESTROY); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Cairo__Path__Data_DESTROY)
{
    dVAR; dXSARGS;
    if (items != 1)
       croak_xs_usage(cv,  "sv");
    {
	SV *	sv = ST(0)
;
#line 330 "CairoPath.xs"
	/* Unset mg_ptr to prevent perl 5.6.x from trying to free it. */
	MAGIC *mg = cairo_perl_mg_find (SvRV (sv), PERL_MAGIC_ext);
	if (mg)
		mg->mg_ptr = NULL;
#line 539 "CairoPath.c"
    }
    XSRETURN_EMPTY;
}

#endif /* 5.6.x */

XS_EUPXS(XS_Cairo__Path__Data_FETCH); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Cairo__Path__Data_FETCH)
{
    dVAR; dXSARGS;
    if (items != 2)
       croak_xs_usage(cv,  "sv, key");
    {
#line 339 "CairoPath.xs"
	cairo_path_data_t * data;
#line 555 "CairoPath.c"
	SV *	RETVAL;
	SV *	sv = ST(0)
;
	const char *	key = (const char *)SvPV_nolen(ST(1))
;
#line 341 "CairoPath.xs"
	data = SvCairoPathData (sv);
	if (strEQ (key, "type")) {
		RETVAL = cairo_path_data_type_to_sv (data->header.type);
	} else if (strEQ (key, "points")) {
		RETVAL = newSVCairoPathPoints (data);
	} else {
		croak ("Unknown key '%s' for Cairo::Path::Data", key);
		RETVAL = NULL;
	}
#line 571 "CairoPath.c"
	RETVAL = sv_2mortal(RETVAL);
	ST(0) = RETVAL;
    }
    XSRETURN(1);
}


XS_EUPXS(XS_Cairo__Path__Data_STORE); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Cairo__Path__Data_STORE)
{
    dVAR; dXSARGS;
    if (items != 3)
       croak_xs_usage(cv,  "sv, key, value");
    {
#line 355 "CairoPath.xs"
	cairo_path_data_t * data;
#line 588 "CairoPath.c"
	SV *	RETVAL;
	SV *	sv = ST(0)
;
	const char *	key = (const char *)SvPV_nolen(ST(1))
;
	SV *	value = ST(2)
;
#line 357 "CairoPath.xs"
	data = SvCairoPathData (sv);
	if (strEQ (key, "points")) {
		RETVAL = newSVCairoPathPoints (data);
		fill_data_from_array (data, data->header.type, (AV *) SvRV (value));
	} else {
		croak ("Unhandled key '%s' for Cairo::Path::Data; "
		       "only changing 'points' is supported", key);
		RETVAL = NULL;
	}
#line 606 "CairoPath.c"
	RETVAL = sv_2mortal(RETVAL);
	ST(0) = RETVAL;
    }
    XSRETURN(1);
}


XS_EUPXS(XS_Cairo__Path__Data_EXISTS); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Cairo__Path__Data_EXISTS)
{
    dVAR; dXSARGS;
    if (items != 2)
       croak_xs_usage(cv,  "sv, key");
    {
	bool	RETVAL;
	const char *	key = (const char *)SvPV_nolen(ST(1))
;
#line 371 "CairoPath.xs"
	if (strEQ (key, "type")) {
		RETVAL = TRUE;
	} else if (strEQ (key, "points")) {
		RETVAL = TRUE;
	} else {
		RETVAL = FALSE;
	}
#line 632 "CairoPath.c"
	ST(0) = boolSV(RETVAL);
    }
    XSRETURN(1);
}


XS_EUPXS(XS_Cairo__Path__Data_FIRSTKEY); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Cairo__Path__Data_FIRSTKEY)
{
    dVAR; dXSARGS;
    if (items != 1)
       croak_xs_usage(cv,  "sv");
    {
	const char *	RETVAL;
	dXSTARG;
#line 383 "CairoPath.xs"
	RETVAL = "type";
#line 650 "CairoPath.c"
	sv_setpv(TARG, RETVAL); XSprePUSH; PUSHTARG;
    }
    XSRETURN(1);
}


XS_EUPXS(XS_Cairo__Path__Data_NEXTKEY); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Cairo__Path__Data_NEXTKEY)
{
    dVAR; dXSARGS;
    if (items != 2)
       croak_xs_usage(cv,  "sv, lastkey");
    {
	const char *	RETVAL;
	dXSTARG;
	const char *	lastkey = (const char *)SvPV_nolen(ST(1))
;
#line 389 "CairoPath.xs"
	if (strEQ (lastkey, "type")) {
		RETVAL = "points";
	} else {
		RETVAL = NULL;
	}
#line 674 "CairoPath.c"
	sv_setpv(TARG, RETVAL); XSprePUSH; PUSHTARG;
    }
    XSRETURN(1);
}

#if PERL_REVISION <= 5 && PERL_VERSION <= 6
#define XSubPPtmpAAAB 1


XS_EUPXS(XS_Cairo__Path__Points_DESTROY); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Cairo__Path__Points_DESTROY)
{
    dVAR; dXSARGS;
    if (items != 1)
       croak_xs_usage(cv,  "sv");
    {
	SV *	sv = ST(0)
;
#line 405 "CairoPath.xs"
	/* Unset mg_ptr to prevent perl 5.6.x from trying to free it. */
	MAGIC *mg = cairo_perl_mg_find (SvRV (sv), PERL_MAGIC_ext);
	if (mg)
		mg->mg_ptr = NULL;
#line 698 "CairoPath.c"
    }
    XSRETURN_EMPTY;
}

#endif /* 5.6.x */

XS_EUPXS(XS_Cairo__Path__Points_FETCHSIZE); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Cairo__Path__Points_FETCHSIZE)
{
    dVAR; dXSARGS;
    if (items != 1)
       croak_xs_usage(cv,  "sv");
    {
#line 414 "CairoPath.xs"
	cairo_path_data_t * data;
#line 714 "CairoPath.c"
	IV	RETVAL;
	dXSTARG;
	SV *	sv = ST(0)
;
#line 416 "CairoPath.xs"
	data = SvCairoPathPoints (sv);
	RETVAL = n_points (data);
#line 722 "CairoPath.c"
	XSprePUSH; PUSHi((IV)RETVAL);
    }
    XSRETURN(1);
}


XS_EUPXS(XS_Cairo__Path__Points_FETCH); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Cairo__Path__Points_FETCH)
{
    dVAR; dXSARGS;
    if (items != 2)
       croak_xs_usage(cv,  "sv, index");
    {
#line 423 "CairoPath.xs"
	cairo_path_data_t * data;
#line 738 "CairoPath.c"
	SV *	RETVAL;
	SV *	sv = ST(0)
;
	IV	index = (IV)SvIV(ST(1))
;
#line 425 "CairoPath.xs"
	data = SvCairoPathPoints (sv);
	if (index >= 0 && index < n_points (data)) {
		RETVAL = newSVCairoPathPoint (&data[index + 1]);
	} else {
		RETVAL = &PL_sv_undef;
	}
#line 751 "CairoPath.c"
	RETVAL = sv_2mortal(RETVAL);
	ST(0) = RETVAL;
    }
    XSRETURN(1);
}


XS_EUPXS(XS_Cairo__Path__Points_STORE); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Cairo__Path__Points_STORE)
{
    dVAR; dXSARGS;
    if (items != 3)
       croak_xs_usage(cv,  "sv, index, value");
    {
#line 436 "CairoPath.xs"
	cairo_path_data_t * data;
#line 768 "CairoPath.c"
	SV *	RETVAL;
	SV *	sv = ST(0)
;
	IV	index = (IV)SvIV(ST(1))
;
	SV *	value = ST(2)
;
#line 438 "CairoPath.xs"
	data = SvCairoPathPoints (sv);
	if (index >= 0 && index < n_points (data)) {
		cairo_path_data_t * point;
		AV * av;
		SV ** svp;
		point = &data[index + 1];
		RETVAL = newSVCairoPathPoint (point);
		av = (AV *) SvRV (value);
		if ((svp = av_fetch (av, 0, 0)))
			point->point.x = SvNV (*svp);
		if ((svp = av_fetch (av, 1, 0)))
			point->point.y = SvNV (*svp);
	} else {
		RETVAL = &PL_sv_undef;
	}
#line 792 "CairoPath.c"
	RETVAL = sv_2mortal(RETVAL);
	ST(0) = RETVAL;
    }
    XSRETURN(1);
}

#if PERL_REVISION <= 5 && PERL_VERSION <= 6
#define XSubPPtmpAAAC 1


XS_EUPXS(XS_Cairo__Path__Point_DESTROY); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Cairo__Path__Point_DESTROY)
{
    dVAR; dXSARGS;
    if (items != 1)
       croak_xs_usage(cv,  "sv");
    {
	SV *	sv = ST(0)
;
#line 464 "CairoPath.xs"
	/* Unset mg_ptr to prevent perl 5.6.x from trying to free it. */
	MAGIC *mg = cairo_perl_mg_find (SvRV (sv), PERL_MAGIC_ext);
	if (mg)
		mg->mg_ptr = NULL;
#line 817 "CairoPath.c"
    }
    XSRETURN_EMPTY;
}

#endif /* 5.6.x */

XS_EUPXS(XS_Cairo__Path__Point_FETCHSIZE); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Cairo__Path__Point_FETCHSIZE)
{
    dVAR; dXSARGS;
    if (items != 1)
       croak_xs_usage(cv,  "sv");
    {
	IV	RETVAL;
	dXSTARG;
#line 473 "CairoPath.xs"
	RETVAL = 2;
#line 835 "CairoPath.c"
	XSprePUSH; PUSHi((IV)RETVAL);
    }
    XSRETURN(1);
}


XS_EUPXS(XS_Cairo__Path__Point_FETCH); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Cairo__Path__Point_FETCH)
{
    dVAR; dXSARGS;
    if (items != 2)
       croak_xs_usage(cv,  "sv, index");
    {
#line 479 "CairoPath.xs"
	cairo_path_data_t * data;
#line 851 "CairoPath.c"
	SV *	RETVAL;
	SV *	sv = ST(0)
;
	IV	index = (IV)SvIV(ST(1))
;
#line 481 "CairoPath.xs"
	data = SvCairoPathPoint (sv);
	switch (index) {
	    case 0:
		RETVAL = newSVnv (data->point.x);
		break;
	    case 1:
		RETVAL = newSVnv (data->point.y);
		break;
	    default:
		RETVAL = &PL_sv_undef;
		break;
	}
#line 870 "CairoPath.c"
	RETVAL = sv_2mortal(RETVAL);
	ST(0) = RETVAL;
    }
    XSRETURN(1);
}


XS_EUPXS(XS_Cairo__Path__Point_STORE); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Cairo__Path__Point_STORE)
{
    dVAR; dXSARGS;
    if (items != 3)
       croak_xs_usage(cv,  "sv, index, value");
    {
#line 498 "CairoPath.xs"
	cairo_path_data_t * data;
#line 887 "CairoPath.c"
	SV *	RETVAL;
	SV *	sv = ST(0)
;
	IV	index = (IV)SvIV(ST(1))
;
	NV	value = (NV)SvNV(ST(2))
;
#line 500 "CairoPath.xs"
	data = SvCairoPathPoint (sv);
	switch (index) {
	    case 0:
		RETVAL = newSVnv (data->point.x = value);
		break;
	    case 1:
		RETVAL = newSVnv (data->point.y = value);
		break;
	    default:
		RETVAL = &PL_sv_undef;
		break;
	}
#line 908 "CairoPath.c"
	RETVAL = sv_2mortal(RETVAL);
	ST(0) = RETVAL;
    }
    XSRETURN(1);
}

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

    PERL_UNUSED_VAR(file);

    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

        newXS_deffile("Cairo::Path::DESTROY", XS_Cairo__Path_DESTROY);
        newXS_deffile("Cairo::Path::FETCHSIZE", XS_Cairo__Path_FETCHSIZE);
        newXS_deffile("Cairo::Path::FETCH", XS_Cairo__Path_FETCH);
#if XSubPPtmpAAAA
        newXS_deffile("Cairo::Path::Data::DESTROY", XS_Cairo__Path__Data_DESTROY);
#endif
        newXS_deffile("Cairo::Path::Data::FETCH", XS_Cairo__Path__Data_FETCH);
        newXS_deffile("Cairo::Path::Data::STORE", XS_Cairo__Path__Data_STORE);
        newXS_deffile("Cairo::Path::Data::EXISTS", XS_Cairo__Path__Data_EXISTS);
        newXS_deffile("Cairo::Path::Data::FIRSTKEY", XS_Cairo__Path__Data_FIRSTKEY);
        newXS_deffile("Cairo::Path::Data::NEXTKEY", XS_Cairo__Path__Data_NEXTKEY);
#if XSubPPtmpAAAB
        newXS_deffile("Cairo::Path::Points::DESTROY", XS_Cairo__Path__Points_DESTROY);
#endif
        newXS_deffile("Cairo::Path::Points::FETCHSIZE", XS_Cairo__Path__Points_FETCHSIZE);
        newXS_deffile("Cairo::Path::Points::FETCH", XS_Cairo__Path__Points_FETCH);
        newXS_deffile("Cairo::Path::Points::STORE", XS_Cairo__Path__Points_STORE);
#if XSubPPtmpAAAC
        newXS_deffile("Cairo::Path::Point::DESTROY", XS_Cairo__Path__Point_DESTROY);
#endif
        newXS_deffile("Cairo::Path::Point::FETCHSIZE", XS_Cairo__Path__Point_FETCHSIZE);
        newXS_deffile("Cairo::Path::Point::FETCH", XS_Cairo__Path__Point_FETCH);
        newXS_deffile("Cairo::Path::Point::STORE", XS_Cairo__Path__Point_STORE);

    /* Initialisation Section */

#if XSubPPtmpAAAA
#endif
#if XSubPPtmpAAAB
#endif
#if XSubPPtmpAAAC
#endif
#line 975 "CairoPath.c"

    /* End of Initialisation Section */

#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
}

