/*
 * This file was generated automatically by xsubpp version 1.9508 from the
 * contents of EXIF.xs. Do not edit this file, edit EXIF.xs instead.
 *
 *	ANY CHANGES MADE HERE WILL BE LOST!
 *
 */

#line 1 "EXIF.xs"
#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"

#include "exif.h"
#include "jpeg.h"

static char error[256];

struct exiftags *et = NULL;
struct exifprop *ep = NULL;
unsigned short dumplvl = 0;

static int
read_data(char *fname)
{
	static char _file_name[1024] = "";

        int mark, first = 0;
        unsigned int len, rlen;
	unsigned char *exifbuf = NULL;

	FILE *fpn;
	char *mode;

#ifdef WIN32
        mode = "rb";
#else
        mode = "r";
#endif

	if(strcmp(fname, _file_name)){
		fpn = fopen(fname, mode);
		if (fpn) 
			strcpy(_file_name, fname);
		else
			_file_name[0] = '\0';
	} else {
		return 0;
	}

	if (fpn == NULL){
		exifdie((const char *)strerror(errno));
		return 2;
	}

	while (jpegscan(fpn, &mark, &len, !(first++))) {

                if (mark != JPEG_M_APP1) {
                        if (fseek(fpn, len, SEEK_CUR)){
                                exifdie((const char *)strerror(errno));
				free (exifbuf);
				fclose (fpn);
				return 2;
			}
                        continue;
                }
		
                exifbuf = (unsigned char *)malloc(len);
                if (!exifbuf){
                        exifdie((const char *)strerror(errno));
			free (exifbuf);
			fclose (fpn);
			return 2;
		}

                rlen = fread(exifbuf, 1, len, fpn);
                if (rlen != len) {
                        exifwarn("error reading JPEG (length mismatch)");
                        free(exifbuf);
			fclose (fpn);
                        return (1);
                }

                et = exifparse(exifbuf, len);

		if (et && et->props){
			break;
		} else {
	                exifwarn("couldn't find Exif data");
			free (exifbuf);
			fclose (fpn);
        	        return (1);
		}
	}

	free (exifbuf);
	fclose (fpn);
        return (0);
}

static long
get_props(char *field, char *value)
{
	int pas = TRUE;

	if (ep && dumplvl) {

		/* Take care of point-and-shoot values. */

		if (ep->lvl == ED_PAS)
			ep->lvl = pas ? ED_CAM : ED_IMG;

		/* For now, just treat overridden & bad values as verbose. */

		if (ep->lvl == ED_OVR || ep->lvl == ED_BAD)
			ep->lvl = ED_VRB;

		if (ep->lvl == dumplvl) {
			strcpy(field, ep->descr ? ep->descr : ep->name);
			if (!ep->str)
				sprintf(value, "%d", ep->value);
			else
				strcpy(value, ep->str);
		}

		ep = ep->next;
	}

	return (long)ep;
}

static int
close_application()
{
	if (et)
	{
		exiffree(et);
		et = NULL;
	}
}

static int
not_here(char *s)
{
    croak("%s not implemented on this architecture", s);
    return -1;
}

static double
constant(char *name, int len, int arg)
{
    errno = EINVAL;
    return 0;
}

#line 157 "EXIF.c"
XS(XS_Image__EXIF_constant); /* prototype to pass -Wmissing-prototypes */
XS(XS_Image__EXIF_constant)
{
    dXSARGS;
    if (items != 2)
	Perl_croak(aTHX_ "Usage: Image::EXIF::constant(sv, arg)");
    {
#line 153 "EXIF.xs"
	STRLEN		len;
#line 167 "EXIF.c"
	SV *	sv = ST(0);
	char *	s = SvPV(sv, len);
	int	arg = (int)SvIV(ST(1));
	double	RETVAL;
	dXSTARG;
#line 159 "EXIF.xs"
	RETVAL = constant(s,len,arg);
#line 175 "EXIF.c"
	XSprePUSH; PUSHn((double)RETVAL);
    }
    XSRETURN(1);
}

XS(XS_Image__EXIF_c_read_file); /* prototype to pass -Wmissing-prototypes */
XS(XS_Image__EXIF_c_read_file)
{
    dXSARGS;
    if (items != 1)
	Perl_croak(aTHX_ "Usage: Image::EXIF::c_read_file(fname)");
    {
	char *	fname = (char *)SvPV_nolen(ST(0));
	int	RETVAL;
	dXSTARG;
#line 167 "EXIF.xs"
	error[0] = '\0';
	RETVAL = 0;

	RETVAL = read_data(fname);
#line 196 "EXIF.c"
	XSprePUSH; PUSHi((IV)RETVAL);
    }
    XSRETURN(1);
}

XS(XS_Image__EXIF_c_get_camera_info); /* prototype to pass -Wmissing-prototypes */
XS(XS_Image__EXIF_c_get_camera_info)
{
    dXSARGS;
    if (items != 0)
	Perl_croak(aTHX_ "Usage: Image::EXIF::c_get_camera_info()");
    {
	int	RETVAL;
	dXSTARG;
#line 177 "EXIF.xs"
	dumplvl = ED_CAM;
	if (et)
		ep = et->props;
#line 215 "EXIF.c"
    }
    XSRETURN(1);
}

XS(XS_Image__EXIF_c_get_image_info); /* prototype to pass -Wmissing-prototypes */
XS(XS_Image__EXIF_c_get_image_info)
{
    dXSARGS;
    if (items != 0)
	Perl_croak(aTHX_ "Usage: Image::EXIF::c_get_image_info()");
    {
	int	RETVAL;
	dXSTARG;
#line 184 "EXIF.xs"
	dumplvl = ED_IMG;
	if (et)
		ep = et->props;
#line 233 "EXIF.c"
    }
    XSRETURN(1);
}

XS(XS_Image__EXIF_c_get_other_info); /* prototype to pass -Wmissing-prototypes */
XS(XS_Image__EXIF_c_get_other_info)
{
    dXSARGS;
    if (items != 0)
	Perl_croak(aTHX_ "Usage: Image::EXIF::c_get_other_info()");
    {
	int	RETVAL;
	dXSTARG;
#line 191 "EXIF.xs"
	dumplvl = ED_VRB;
	if (et)
		ep = et->props;
#line 251 "EXIF.c"
    }
    XSRETURN(1);
}

XS(XS_Image__EXIF_c_get_unknown_info); /* prototype to pass -Wmissing-prototypes */
XS(XS_Image__EXIF_c_get_unknown_info)
{
    dXSARGS;
    if (items != 0)
	Perl_croak(aTHX_ "Usage: Image::EXIF::c_get_unknown_info()");
    {
	int	RETVAL;
	dXSTARG;
#line 198 "EXIF.xs"
	dumplvl = ED_UNK;
	if (et)
		ep = et->props;
#line 269 "EXIF.c"
    }
    XSRETURN(1);
}

XS(XS_Image__EXIF_c_fetch); /* prototype to pass -Wmissing-prototypes */
XS(XS_Image__EXIF_c_fetch)
{
    dXSARGS;
    if (items != 0)
	Perl_croak(aTHX_ "Usage: Image::EXIF::c_fetch()");
   PERL_UNUSED_VAR(ax); /* -Wall */
    SP -= items;
    {
	int	RETVAL;
	dXSTARG;
#line 205 "EXIF.xs"
	char field[256] = "";
	char value[256] = "";

	int rc = get_props(field, value);
	if (rc){
		EXTEND(sp, 2);
		PUSHs(sv_2mortal(newSVpv((char*)field, 0)));
		PUSHs(sv_2mortal(newSVpv((char*)value, 0)));
	}
#line 295 "EXIF.c"
	PUTBACK;
	return;
    }
}

XS(XS_Image__EXIF_c_errstr); /* prototype to pass -Wmissing-prototypes */
XS(XS_Image__EXIF_c_errstr)
{
    dXSARGS;
    if (items != 0)
	Perl_croak(aTHX_ "Usage: Image::EXIF::c_errstr()");
   PERL_UNUSED_VAR(ax); /* -Wall */
    SP -= items;
    {
	int	RETVAL;
	dXSTARG;
#line 218 "EXIF.xs"
	if (strlen(error)){
		EXTEND(sp, 1);
		PUSHs(sv_2mortal(newSVpv((char*)error, 0)));
	}
#line 317 "EXIF.c"
	PUTBACK;
	return;
    }
}

XS(XS_Image__EXIF_c_close_all); /* prototype to pass -Wmissing-prototypes */
XS(XS_Image__EXIF_c_close_all)
{
    dXSARGS;
    if (items != 0)
	Perl_croak(aTHX_ "Usage: Image::EXIF::c_close_all()");
   PERL_UNUSED_VAR(ax); /* -Wall */
    SP -= items;
    {
	int	RETVAL;
	dXSTARG;
#line 226 "EXIF.xs"
	close_application();
#line 336 "EXIF.c"
	PUTBACK;
	return;
    }
}

#ifdef __cplusplus
extern "C"
#endif
XS(boot_Image__EXIF); /* prototype to pass -Wmissing-prototypes */
XS(boot_Image__EXIF)
{
    dXSARGS;
    char* file = __FILE__;

    XS_VERSION_BOOTCHECK ;

        newXS("Image::EXIF::constant", XS_Image__EXIF_constant, file);
        newXS("Image::EXIF::c_read_file", XS_Image__EXIF_c_read_file, file);
        newXS("Image::EXIF::c_get_camera_info", XS_Image__EXIF_c_get_camera_info, file);
        newXS("Image::EXIF::c_get_image_info", XS_Image__EXIF_c_get_image_info, file);
        newXS("Image::EXIF::c_get_other_info", XS_Image__EXIF_c_get_other_info, file);
        newXS("Image::EXIF::c_get_unknown_info", XS_Image__EXIF_c_get_unknown_info, file);
        newXS("Image::EXIF::c_fetch", XS_Image__EXIF_c_fetch, file);
        newXS("Image::EXIF::c_errstr", XS_Image__EXIF_c_errstr, file);
        newXS("Image::EXIF::c_close_all", XS_Image__EXIF_c_close_all, file);
    XSRETURN_YES;
}

