#ifndef _XH_CONFIG_H_
#define _XH_CONFIG_H_

#include "EXTERN.h"
#include "perl.h"
#define NO_XSLOCKS
#include "XSUB.h"
#define NEED_newRV_noinc
#define NEED_newSVpvn_flags
#define NEED_sv_2pv_flags_GLOBAL
#include "ppport.h"
#include <stdint.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#ifdef WIN32
#include <windows.h>
#include <io.h>
#else
#include <sys/mman.h>
#endif

#if defined(__sparc__) || defined(__sparc)
# define XH_SPARC_ARCH
#endif

#if defined(sun) || defined(__sun)
#  include <sys/isa_defs.h>
#  if defined(_LITTLE_ENDIAN)
#    define XH_LITTLE_ENDIAN
#  else
#    define XH_BIG_ENDIAN
#  endif
#else
#  if defined(SVR4) || defined(__SVR4)
#    include <sys/types.h>
#    include <sys/byteorder.h>
#  elif defined(_AIX) || defined(__TOS_AIX__)
#    include <sys/machine.h>
#  elif defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__DragonFly__) \
          || defined(__APPLE__)
#    if defined(__NetBSD__) || defined(__OpenBSD__)
#      include <sys/types.h>
#    endif
#    include <machine/endian.h>
#  elif defined(__linux__) || defined(__CYGWIN__)
#    include <endian.h>
#  endif
#  ifndef LITTLE_ENDIAN
#    ifdef __LITTLE_ENDIAN
#      define LITTLE_ENDIAN __LITTLE_ENDIAN
#    else
#      define LITTLE_ENDIAN _LITTLE_ENDIAN
#    endif
#  endif
#  ifndef BIG_ENDIAN
#    ifdef __BIG_ENDIAN
#      define BIG_ENDIAN __BIG_ENDIAN
#    else
#      define BIG_ENDIAN _BIG_ENDIAN
#    endif
#  endif
#  ifndef BYTE_ORDER
#    ifdef __BYTE_ORDER
#      define BYTE_ORDER __BYTE_ORDER
#    else
#      define BYTE_ORDER _BYTE_ORDER
#    endif
#  endif
#  if BYTE_ORDER == LITTLE_ENDIAN
#    define XH_LITTLE_ENDIAN
#  else
#    define XH_BIG_ENDIAN
#  endif
#endif

#ifndef MUTABLE_PTR
#if defined(__GNUC__) && !defined(PERL_GCC_BRACE_GROUPS_FORBIDDEN)
#  define MUTABLE_PTR(p) ({ void *_p = (p); _p; })
#else
#  define MUTABLE_PTR(p) ((void *) (p))
#endif
#endif

#ifndef MUTABLE_SV
#define MUTABLE_SV(p)   ((SV *)MUTABLE_PTR(p))
#endif

#ifndef SvRXOK
#define SvRX(sv)   (Perl_get_re_arg(aTHX_ sv))
#define SvRXOK(sv) (Perl_get_re_arg(aTHX_ sv) ? TRUE : FALSE)
static REGEXP *
Perl_get_re_arg(pTHX_ SV *sv) {
    MAGIC *mg;
    if (sv) {
        if (SvMAGICAL(sv))
            mg_get(sv);
        if (SvROK(sv))
            sv = MUTABLE_SV(SvRV(sv));
#if PERL_VERSION < 11
        if (SvTYPE(sv) == SVt_PVMG && (mg = mg_find(sv, PERL_MAGIC_qr)))
            return (REGEXP *) mg->mg_obj;
#else
        if (SvTYPE(sv) == SVt_REGEXP)
            return (REGEXP *) sv;
#endif
    }

    return NULL;
}
#endif

#if PERL_VERSION > 17
# define XH_AMAGIC(sv) HvAMAGIC(SvSTASH(sv))
#else
# if PERL_VERSION > 8
#  define XH_AMAGIC(sv) (SvFLAGS(sv) & SVf_AMAGIC)
# else
#  define XH_AMAGIC(sv) ((SvFLAGS(sv) & SVf_AMAGIC)                     \
     || ((mg = mg_find((SV*) SvSTASH(sv), PERL_MAGIC_overload_table))   \
         && mg->mg_ptr && AMT_AMAGIC((AMT*)mg->mg_ptr)))
# endif
#endif

#if PERL_VERSION > 13
# define XH_AMG_CALL_STRING(sv) AMG_CALLunary(sv, string_amg)
#else
# define XH_AMG_CALL_STRING(sv) AMG_CALLun(sv ,string)
#endif

#if __GNUC__ >= 3
# define expect(expr,value)         __builtin_expect ((expr), (value))
# define XH_INLINE                  static inline
# define XH_UNUSED(v)               x __attribute__((unused))
#else
# define expect(expr,value)         (expr)
# define XH_INLINE                  static
# define XH_UNUSED(v)               v
#endif

#if __STDC_VERSION__ < 199901L
# if __GNUC__ >= 2
#  define XH_FUNCTION __FUNCTION__
# else
#  define XH_FUNCTION "<unknown>"
# endif
#else
# define XH_FUNCTION __func__
#endif

#ifdef _MSC_VER
#define _CRT_SECURE_NO_WARNINGS
#define _CRT_NONSTDC_NO_DEPRECATE
#define strncasecmp _strnicmp
#define strcasecmp _stricmp
#endif

#define expect_false(expr) expect ((expr) != 0, 0)
#define expect_true(expr)  expect ((expr) != 0, 1)

typedef uintptr_t xh_bool_t;
typedef uintptr_t xh_uint_t;
typedef intptr_t  xh_int_t;
typedef u_char    xh_char_t;

#define XH_CHAR_CAST    (xh_char_t *)
#define XH_EMPTY_STRING (XH_CHAR_CAST "")

#if defined(XH_HAVE_ICONV) || defined(XH_HAVE_ICU)
#define XH_HAVE_ENCODER
#endif

#if defined(XH_HAVE_XML2) && defined(XH_HAVE_XML__LIBXML)
#define XH_HAVE_DOM
#endif

#ifdef XH_HAVE_DOM
#include <libxml/parser.h>
#endif

#define XH_HAVE_MMAP

#endif /* _XH_CONFIG_H_ */