################################################################################
##
##  Version 3.x, Copyright (C) 2004-2013, Marcus Holland-Moritz.
##  Version 2.x, Copyright (C) 2001, Paul Marquess.
##  Version 1.x, Copyright (C) 1999, Kenneth Albanowski.
##
##  This program is free software; you can redistribute it and/or
##  modify it under the same terms as Perl itself.
##
################################################################################

=provides

/^#\s*define\s+(\w+)/

=implementation

#ifndef IVdf
#  if IVSIZE == LONGSIZE
#    define     IVdf      "ld"
#    define     UVuf      "lu"
#    define     UVof      "lo"
#    define     UVxf      "lx"
#    define     UVXf      "lX"
#  elif IVSIZE == INTSIZE
#    define   IVdf      "d"
#    define   UVuf      "u"
#    define   UVof      "o"
#    define   UVxf      "x"
#    define   UVXf      "X"
#  else
#    error "cannot define IV/UV formats"
#  endif
#endif

#ifndef NVef
#  if defined(USE_LONG_DOUBLE) && defined(HAS_LONG_DOUBLE) && \
      defined(PERL_PRIfldbl) && { VERSION != 5.6.0 }
            /* Not very likely, but let's try anyway. */
#    define NVef          PERL_PRIeldbl
#    define NVff          PERL_PRIfldbl
#    define NVgf          PERL_PRIgldbl
#  else
#    define NVef          "e"
#    define NVff          "f"
#    define NVgf          "g"
#  endif
#endif

=xsubs

void
croak_NVgf(num)
        NV num
        PPCODE:
                Perl_croak(aTHX_ "%.20" NVgf "\n", num);

#if { VERSION >= 5.004 }

SV *
sprintf_iv(iv)
        IV iv
CODE:
        RETVAL = newSVpvf("XX_%" IVdf "_XX", iv);
OUTPUT:
        RETVAL

SV *
sprintf_uv(uv)
        UV uv
CODE:
        RETVAL = newSVpvf("XX_%" UVuf "_XX", uv);
OUTPUT:
        RETVAL

SV *
sprintf_ivmax()
CODE:
        RETVAL = newSVpvf("%" IVdf, IV_MAX);
OUTPUT:
        RETVAL

SV *
sprintf_uvmax()
CODE:
        RETVAL = newSVpvf("%" UVuf, UV_MAX);
OUTPUT:
        RETVAL

#endif

=tests plan => 5

use Config;

if ("$]" < '5.004') {
    for (1..5) {
        skip 'skip: No newSVpvf support', 0;
    }
    exit;
}

my $num = 1.12345678901234567890;

eval { Devel::PPPort::croak_NVgf($num) };
ok($@ =~ /^1.1234567890/);

ok(Devel::PPPort::sprintf_iv(-8), 'XX_-8_XX');
ok(Devel::PPPort::sprintf_uv(15), 'XX_15_XX');

my $ivsize = $Config::Config{ivsize};
my $ivmax = ($ivsize == 4) ? '2147483647' : ($ivsize == 8) ? '9223372036854775807' : 0;
my $uvmax = ($ivsize == 4) ? '4294967295' : ($ivsize == 8) ? '18446744073709551615' : 0;
if ($ivmax == 0) {
    for (1..2) {
        skip 'skip: unknown ivsize', 0;
    }
} else {
    ok(Devel::PPPort::sprintf_ivmax(), $ivmax);
    ok(Devel::PPPort::sprintf_uvmax(), $uvmax);
}
