<commit_before>//
//	Copyright  (c)  1997    Industrial   Light   and   Magic.
//	All   rights   reserved.    Used   under   authorization.
//	This material contains the confidential  and  proprietary
//	information   of   Industrial   Light   and   Magic   and
//	may not be copied in whole or in part without the express
//	written   permission   of  Industrial Light  and   Magic.
//	This  copyright  notice  does  not   imply   publication.
//

//------------------------------------------------------------------------
//
//	Functions to control floating point exceptions.
//
//------------------------------------------------------------------------

#include <IexMathFpu.h>
#include <IlmBaseConfig.h>

#if 0
    #include <iostream>
    #define debug(x) (std::cout << x << std::flush)
#else
    #define debug(x)
#endif

#ifdef HAVE_UCONTEXT_H

#include <ucontext.h>
#include <signal.h>
#include <iostream>
#include <stdint.h>

namespace Iex
{

namespace FpuControl
{

//-------------------------------------------------------------------
//
//    Modern x86 processors and all AMD64 processors have two
//    sets of floating-point control/status registers: cw and sw
//    for legacy x87 stack-based arithmetic, and mxcsr for
//    SIMD arithmetic.  When setting exception masks or checking
//    for exceptions, we must set/check all relevant registers,
//    since applications may contain code that uses either FP
//    model.
//
//    These functions handle both FP models for x86 and AMD64.
//
//-------------------------------------------------------------------

//-------------------------------------------------------------------
//
//    Restore the control register state from a signal handler
//    user context, optionally clearing the exception bits
//    in the restored control register, if applicable.
//
//-------------------------------------------------------------------

void restoreControlRegs (const ucontext_t & ucon,
			 bool clearExceptions = false);

//------------------------------------------------------------
//
//    Set exception mask bits in the control register state.
//    A value of 1 means the exception is masked, a value of
//    0 means the exception is enabled.
//
//    setExceptionMask returns the previous mask value.  If
//    the 'exceptions' pointer is non-null, it returns in
//    this argument the FPU exception bits.
//
//------------------------------------------------------------

const int INVALID_EXC   = (1<<0);
const int DENORMAL_EXC  = (1<<1);
const int DIVZERO_EXC   = (1<<2);
const int OVERFLOW_EXC  = (1<<3);
const int UNDERFLOW_EXC = (1<<4);
const int INEXACT_EXC   = (1<<5);
const int ALL_EXC       = INVALID_EXC  | DENORMAL_EXC  | DIVZERO_EXC |
                          OVERFLOW_EXC | UNDERFLOW_EXC | INEXACT_EXC;

int setExceptionMask (int mask, int * exceptions = 0);
int getExceptionMask ();

//---------------------------------------------
//
//    Get/clear the exception bits in the FPU.
//
//---------------------------------------------

int  getExceptions ();
void clearExceptions ();

//------------------------------------------------------------------
//
//    Everything below here is implementation.  Do not use these
//    constants or functions in your applications or libraries.
//    This is not the code you're looking for.  Move along.
//
//    Optimization notes -- on a Pentium 4, at least, it appears
//    to be faster to get the mxcsr first and then the cw; and to
//    set the cw first and then the mxcsr.  Also, it seems to
//    be faster to clear the sw exception bits after setting
//    cw and mxcsr.
//
//------------------------------------------------------------------

static inline uint16_t
getSw ()
{
    uint16_t sw;
    asm volatile ("fnstsw %0" : "=m" (sw) : );
    return sw;
}

static inline void
setCw (uint16_t cw)
{
    asm volatile ("fldcw %0" : : "m" (cw) );
}

static inline uint16_t
getCw ()
{
    uint16_t cw;
    asm volatile ("fnstcw %0" : "=m" (cw) : );
    return cw;
}

static inline void
setMxcsr (uint32_t mxcsr, bool clearExceptions)
{
    mxcsr &= clearExceptions ? 0xffffffc0 : 0xffffffff;
    asm volatile ("ldmxcsr %0" : : "m" (mxcsr) );
}

static inline uint32_t
getMxcsr ()
{
    uint32_t mxcsr;
    asm volatile ("stmxcsr %0" : "=m" (mxcsr) : );
    return mxcsr;
}

static inline int
calcMask (uint16_t cw, uint32_t mxcsr)
{
    //
    // Hopefully, if the user has been using FpuControl functions,
    // the masks are the same, but just in case they're not, we
    // AND them together to report the proper subset of the masks.
    //

    return (cw & ALL_EXC) & ((mxcsr >> 7) & ALL_EXC);
}

inline int
setExceptionMask (int mask, int * exceptions)
{
    uint16_t cw = getCw ();
    uint32_t mxcsr = getMxcsr ();

    if (exceptions)
	*exceptions = (mxcsr & ALL_EXC) | (getSw () & ALL_EXC);

    int oldmask = calcMask (cw, mxcsr);

    //
    // The exception constants are chosen very carefully so that
    // we can do a simple mask and shift operation to insert
    // them into the control words.  The mask operation is for
    // safety, in case the user accidentally set some other
    // bits in the exception mask.
    //

    mask &= ALL_EXC;
    cw = (cw & ~ALL_EXC) | mask;
    mxcsr = (mxcsr & ~(ALL_EXC << 7)) | (mask << 7);

    setCw (cw);
    setMxcsr (mxcsr, false);

    return oldmask;
}

inline int
getExceptionMask ()
{
    uint32_t mxcsr = getMxcsr ();
    uint16_t cw = getCw ();
    return calcMask (cw, mxcsr);
}

inline int
getExceptions ()
{
    return (getMxcsr () | getSw ()) & ALL_EXC;
}

void
clearExceptions ()
{
    uint32_t mxcsr = getMxcsr () & 0xffffffc0;
    asm volatile ("ldmxcsr %0\n"
		  "fnclex"
		  : : "m" (mxcsr) );
}

// If the fpe was taken while doing a float-to-int cast using the x87,
// the rounding mode and possibly the precision will be wrong.  So instead
// of restoring to the state as of the fault, we force the rounding mode
// to be 'nearest' and the precision to be double extended.
//
// rounding mode is in bits 10-11, value 00 == round to nearest
// precision is in bits 8-9, value 11 == double extended (80-bit)
//
const uint16_t cwRestoreMask = ~((3 << 10) | (3 << 8));
const uint16_t cwRestoreVal = (0 << 10) | (3 << 8);

inline void
restoreControlRegs (const ucontext_t & ucon, bool clearExceptions)
{
    setCw ((ucon.uc_mcontext.fpregs->cwd & cwRestoreMask) | cwRestoreVal);
    setMxcsr (ucon.uc_mcontext.fpregs->mxcsr, clearExceptions);
}

#if 0

//
// Ugly, the mxcsr isn't defined in GNU libc ucontext_t, but
// it's passed to the signal handler by the kernel.  Use
// the kernel's version of the ucontext to get it, see
// <asm/sigcontext.h>
//

#include <asm/sigcontext.h>

inline void
restoreControlRegs (const ucontext_t & ucon, bool clearExceptions)
{
    setCw ((ucon.uc_mcontext.fpregs->cw & cwRestoreMask) | cwRestoreVal);

    _fpstate * kfp = reinterpret_cast<_fpstate *> (ucon.uc_mcontext.fpregs);
    setMxcsr (kfp->magic == 0 ? kfp->mxcsr : 0, clearExceptions);
}

#endif

} // namespace FpuControl

namespace {

volatile FpExceptionHandler fpeHandler = 0;

extern "C" void
catchSigFpe (int sig, siginfo_t *info, ucontext_t *ucon)
{
    debug ("catchSigFpe (sig = "<< sig << ", ...)\n");

    FpuControl::restoreControlRegs (*ucon, true);

    if (fpeHandler == 0)
	return;

    if (info->si_code == SI_USER)
    {
	fpeHandler (0, "Floating-point exception, caused by "
		       "a signal sent from another process.");
	return;
    }

    if (sig == SIGFPE)
    {
	switch (info->si_code)
	{
	  //
	  // IEEE 754 floating point exceptions:
	  //

	  case FPE_FLTDIV:
	    fpeHandler (IEEE_DIVZERO, "Floating-point division by zero.");
	    return;

	  case FPE_FLTOVF:
	    fpeHandler (IEEE_OVERFLOW, "Floating-point overflow.");
	    return;

	  case FPE_FLTUND:
	    fpeHandler (IEEE_UNDERFLOW, "Floating-point underflow.");
	    return;

	  case FPE_FLTRES:
	    fpeHandler (IEEE_INEXACT, "Inexact floating-point result.");
	    return;

	  case FPE_FLTINV:
	    fpeHandler (IEEE_INVALID, "Invalid floating-point operation.");
	    return;

	  //
	  // Other arithmetic exceptions which can also
	  // be trapped by the operating system:
	  //

	  case FPE_INTDIV:
	    fpeHandler (0, "Integer division by zero.");
	    break;

	  case FPE_INTOVF:
	    fpeHandler (0, "Integer overflow.");
	    break;

	  case FPE_FLTSUB:
	    fpeHandler (0, "Subscript out of range.");
	    break;
	}
    }

    fpeHandler (0, "Floating-point exception.");
}

} // namespace

void
setFpExceptions (int when)
{
    int mask = FpuControl::ALL_EXC;

    if (when & IEEE_OVERFLOW)
	mask &= ~FpuControl::OVERFLOW_EXC;
    if (when & IEEE_UNDERFLOW)
	mask &= ~FpuControl::UNDERFLOW_EXC;
    if (when & IEEE_DIVZERO)
	mask &= ~FpuControl::DIVZERO_EXC;
    if (when & IEEE_INEXACT)
	mask &= ~FpuControl::INEXACT_EXC;
    if (when & IEEE_INVALID)
	mask &= ~FpuControl::INVALID_EXC;

    //
    // The Linux kernel apparently sometimes passes
    // incorrect si_info to signal handlers unless
    // the exception flags are cleared.
    //
    // XXX is this still true on 2.4+ kernels?
    //

    FpuControl::setExceptionMask (mask);
    FpuControl::clearExceptions ();
}

int
fpExceptions ()
{
    int mask = FpuControl::getExceptionMask ();

    int when = 0;

    if (!(mask & FpuControl::OVERFLOW_EXC))
	when |= IEEE_OVERFLOW;
    if (!(mask & FpuControl::UNDERFLOW_EXC))
	when |= IEEE_UNDERFLOW;
    if (!(mask & FpuControl::DIVZERO_EXC))
	when |= IEEE_DIVZERO;
    if (!(mask & FpuControl::INEXACT_EXC))
	when |= IEEE_INEXACT;
    if (!(mask & FpuControl::INVALID_EXC))
	when |= IEEE_INVALID;

    return when;
}

void
handleExceptionsSetInRegisters()
{
    if (fpeHandler == 0)
	return;

    int mask = FpuControl::getExceptionMask ();

    int exc = FpuControl::getExceptions();

    if (!(mask & FpuControl::DIVZERO_EXC) && (exc & FpuControl::DIVZERO_EXC))
    {
        fpeHandler(IEEE_DIVZERO, "Floating-point division by zero.");
        return;
    }

    if (!(mask & FpuControl::OVERFLOW_EXC) && (exc & FpuControl::OVERFLOW_EXC))
    {
        fpeHandler(IEEE_OVERFLOW, "Floating-point overflow.");
        return;
    }

    if (!(mask & FpuControl::UNDERFLOW_EXC) && (exc & FpuControl::UNDERFLOW_EXC))
    {
        fpeHandler(IEEE_UNDERFLOW, "Floating-point underflow.");
        return;
    }

    if (!(mask & FpuControl::INEXACT_EXC) && (exc & FpuControl::INEXACT_EXC))
    {
        fpeHandler(IEEE_INEXACT, "Inexact floating-point result.");
        return;
    }

    if (!(mask & FpuControl::INVALID_EXC) && (exc & FpuControl::INVALID_EXC))
    {
        fpeHandler(IEEE_INVALID, "Invalid floating-point operation.");
        return;
    }
}

void
setFpExceptionHandler (FpExceptionHandler handler)
{
    if (fpeHandler == 0)
    {
	struct sigaction action;
	sigemptyset (&action.sa_mask);
	action.sa_flags = SA_SIGINFO | SA_NOMASK;
	action.sa_sigaction = (void (*) (int, siginfo_t *, void *)) catchSigFpe;
	action.sa_restorer = 0;

	sigaction (SIGFPE, &action, 0);
    }

    fpeHandler = handler;
}

} // namespace Iex

#else

#include <signal.h>
#include <assert.h>

namespace Iex
{

    namespace {
	volatile FpExceptionHandler fpeHandler = 0;
	void fpExc_(int x)
	{
	    if (fpeHandler != 0)
	    {
		fpeHandler(x, "");
	    }
	    else
	    {
		assert(0 != "Floating point exception");
	    }
	}
    }

void
setFpExceptions( int )
{
}

void
setFpExceptionHandler (FpExceptionHandler handler)
{
    // improve floating point exception handling nanoscopically above "nothing at all"
    fpeHandler = handler;
    signal(SIGFPE, fpExc_);
}

int
fpExceptions()
{
    return 0;
}

void
handleExceptionsSetInRegisters()
{
    // No implementation on this platform
}

} // namespace Iex

#endif
<commit_msg>Fix build with gcc-4.7<commit_after>//
//	Copyright  (c)  1997    Industrial   Light   and   Magic.
//	All   rights   reserved.    Used   under   authorization.
//	This material contains the confidential  and  proprietary
//	information   of   Industrial   Light   and   Magic   and
//	may not be copied in whole or in part without the express
//	written   permission   of  Industrial Light  and   Magic.
//	This  copyright  notice  does  not   imply   publication.
//

//------------------------------------------------------------------------
//
//	Functions to control floating point exceptions.
//
//------------------------------------------------------------------------

#include <stdint.h>

#include <IexMathFpu.h>
#include <IlmBaseConfig.h>

#if 0
    #include <iostream>
    #define debug(x) (std::cout << x << std::flush)
#else
    #define debug(x)
#endif

#ifdef HAVE_UCONTEXT_H

#include <ucontext.h>
#include <signal.h>
#include <iostream>
#include <stdint.h>

namespace Iex
{

namespace FpuControl
{

//-------------------------------------------------------------------
//
//    Modern x86 processors and all AMD64 processors have two
//    sets of floating-point control/status registers: cw and sw
//    for legacy x87 stack-based arithmetic, and mxcsr for
//    SIMD arithmetic.  When setting exception masks or checking
//    for exceptions, we must set/check all relevant registers,
//    since applications may contain code that uses either FP
//    model.
//
//    These functions handle both FP models for x86 and AMD64.
//
//-------------------------------------------------------------------

//-------------------------------------------------------------------
//
//    Restore the control register state from a signal handler
//    user context, optionally clearing the exception bits
//    in the restored control register, if applicable.
//
//-------------------------------------------------------------------

void restoreControlRegs (const ucontext_t & ucon,
			 bool clearExceptions = false);

//------------------------------------------------------------
//
//    Set exception mask bits in the control register state.
//    A value of 1 means the exception is masked, a value of
//    0 means the exception is enabled.
//
//    setExceptionMask returns the previous mask value.  If
//    the 'exceptions' pointer is non-null, it returns in
//    this argument the FPU exception bits.
//
//------------------------------------------------------------

const int INVALID_EXC   = (1<<0);
const int DENORMAL_EXC  = (1<<1);
const int DIVZERO_EXC   = (1<<2);
const int OVERFLOW_EXC  = (1<<3);
const int UNDERFLOW_EXC = (1<<4);
const int INEXACT_EXC   = (1<<5);
const int ALL_EXC       = INVALID_EXC  | DENORMAL_EXC  | DIVZERO_EXC |
                          OVERFLOW_EXC | UNDERFLOW_EXC | INEXACT_EXC;

int setExceptionMask (int mask, int * exceptions = 0);
int getExceptionMask ();

//---------------------------------------------
//
//    Get/clear the exception bits in the FPU.
//
//---------------------------------------------

int  getExceptions ();
void clearExceptions ();

//------------------------------------------------------------------
//
//    Everything below here is implementation.  Do not use these
//    constants or functions in your applications or libraries.
//    This is not the code you're looking for.  Move along.
//
//    Optimization notes -- on a Pentium 4, at least, it appears
//    to be faster to get the mxcsr first and then the cw; and to
//    set the cw first and then the mxcsr.  Also, it seems to
//    be faster to clear the sw exception bits after setting
//    cw and mxcsr.
//
//------------------------------------------------------------------

static inline uint16_t
getSw ()
{
    uint16_t sw;
    asm volatile ("fnstsw %0" : "=m" (sw) : );
    return sw;
}

static inline void
setCw (uint16_t cw)
{
    asm volatile ("fldcw %0" : : "m" (cw) );
}

static inline uint16_t
getCw ()
{
    uint16_t cw;
    asm volatile ("fnstcw %0" : "=m" (cw) : );
    return cw;
}

static inline void
setMxcsr (uint32_t mxcsr, bool clearExceptions)
{
    mxcsr &= clearExceptions ? 0xffffffc0 : 0xffffffff;
    asm volatile ("ldmxcsr %0" : : "m" (mxcsr) );
}

static inline uint32_t
getMxcsr ()
{
    uint32_t mxcsr;
    asm volatile ("stmxcsr %0" : "=m" (mxcsr) : );
    return mxcsr;
}

static inline int
calcMask (uint16_t cw, uint32_t mxcsr)
{
    //
    // Hopefully, if the user has been using FpuControl functions,
    // the masks are the same, but just in case they're not, we
    // AND them together to report the proper subset of the masks.
    //

    return (cw & ALL_EXC) & ((mxcsr >> 7) & ALL_EXC);
}

inline int
setExceptionMask (int mask, int * exceptions)
{
    uint16_t cw = getCw ();
    uint32_t mxcsr = getMxcsr ();

    if (exceptions)
	*exceptions = (mxcsr & ALL_EXC) | (getSw () & ALL_EXC);

    int oldmask = calcMask (cw, mxcsr);

    //
    // The exception constants are chosen very carefully so that
    // we can do a simple mask and shift operation to insert
    // them into the control words.  The mask operation is for
    // safety, in case the user accidentally set some other
    // bits in the exception mask.
    //

    mask &= ALL_EXC;
    cw = (cw & ~ALL_EXC) | mask;
    mxcsr = (mxcsr & ~(ALL_EXC << 7)) | (mask << 7);

    setCw (cw);
    setMxcsr (mxcsr, false);

    return oldmask;
}

inline int
getExceptionMask ()
{
    uint32_t mxcsr = getMxcsr ();
    uint16_t cw = getCw ();
    return calcMask (cw, mxcsr);
}

inline int
getExceptions ()
{
    return (getMxcsr () | getSw ()) & ALL_EXC;
}

void
clearExceptions ()
{
    uint32_t mxcsr = getMxcsr () & 0xffffffc0;
    asm volatile ("ldmxcsr %0\n"
		  "fnclex"
		  : : "m" (mxcsr) );
}

// If the fpe was taken while doing a float-to-int cast using the x87,
// the rounding mode and possibly the precision will be wrong.  So instead
// of restoring to the state as of the fault, we force the rounding mode
// to be 'nearest' and the precision to be double extended.
//
// rounding mode is in bits 10-11, value 00 == round to nearest
// precision is in bits 8-9, value 11 == double extended (80-bit)
//
const uint16_t cwRestoreMask = ~((3 << 10) | (3 << 8));
const uint16_t cwRestoreVal = (0 << 10) | (3 << 8);

inline void
restoreControlRegs (const ucontext_t & ucon, bool clearExceptions)
{
    setCw ((ucon.uc_mcontext.fpregs->cwd & cwRestoreMask) | cwRestoreVal);
    setMxcsr (ucon.uc_mcontext.fpregs->mxcsr, clearExceptions);
}

#if 0

//
// Ugly, the mxcsr isn't defined in GNU libc ucontext_t, but
// it's passed to the signal handler by the kernel.  Use
// the kernel's version of the ucontext to get it, see
// <asm/sigcontext.h>
//

#include <asm/sigcontext.h>

inline void
restoreControlRegs (const ucontext_t & ucon, bool clearExceptions)
{
    setCw ((ucon.uc_mcontext.fpregs->cw & cwRestoreMask) | cwRestoreVal);

    _fpstate * kfp = reinterpret_cast<_fpstate *> (ucon.uc_mcontext.fpregs);
    setMxcsr (kfp->magic == 0 ? kfp->mxcsr : 0, clearExceptions);
}

#endif

} // namespace FpuControl

namespace {

volatile FpExceptionHandler fpeHandler = 0;

extern "C" void
catchSigFpe (int sig, siginfo_t *info, ucontext_t *ucon)
{
    debug ("catchSigFpe (sig = "<< sig << ", ...)\n");

    FpuControl::restoreControlRegs (*ucon, true);

    if (fpeHandler == 0)
	return;

    if (info->si_code == SI_USER)
    {
	fpeHandler (0, "Floating-point exception, caused by "
		       "a signal sent from another process.");
	return;
    }

    if (sig == SIGFPE)
    {
	switch (info->si_code)
	{
	  //
	  // IEEE 754 floating point exceptions:
	  //

	  case FPE_FLTDIV:
	    fpeHandler (IEEE_DIVZERO, "Floating-point division by zero.");
	    return;

	  case FPE_FLTOVF:
	    fpeHandler (IEEE_OVERFLOW, "Floating-point overflow.");
	    return;

	  case FPE_FLTUND:
	    fpeHandler (IEEE_UNDERFLOW, "Floating-point underflow.");
	    return;

	  case FPE_FLTRES:
	    fpeHandler (IEEE_INEXACT, "Inexact floating-point result.");
	    return;

	  case FPE_FLTINV:
	    fpeHandler (IEEE_INVALID, "Invalid floating-point operation.");
	    return;

	  //
	  // Other arithmetic exceptions which can also
	  // be trapped by the operating system:
	  //

	  case FPE_INTDIV:
	    fpeHandler (0, "Integer division by zero.");
	    break;

	  case FPE_INTOVF:
	    fpeHandler (0, "Integer overflow.");
	    break;

	  case FPE_FLTSUB:
	    fpeHandler (0, "Subscript out of range.");
	    break;
	}
    }

    fpeHandler (0, "Floating-point exception.");
}

} // namespace

void
setFpExceptions (int when)
{
    int mask = FpuControl::ALL_EXC;

    if (when & IEEE_OVERFLOW)
	mask &= ~FpuControl::OVERFLOW_EXC;
    if (when & IEEE_UNDERFLOW)
	mask &= ~FpuControl::UNDERFLOW_EXC;
    if (when & IEEE_DIVZERO)
	mask &= ~FpuControl::DIVZERO_EXC;
    if (when & IEEE_INEXACT)
	mask &= ~FpuControl::INEXACT_EXC;
    if (when & IEEE_INVALID)
	mask &= ~FpuControl::INVALID_EXC;

    //
    // The Linux kernel apparently sometimes passes
    // incorrect si_info to signal handlers unless
    // the exception flags are cleared.
    //
    // XXX is this still true on 2.4+ kernels?
    //

    FpuControl::setExceptionMask (mask);
    FpuControl::clearExceptions ();
}

int
fpExceptions ()
{
    int mask = FpuControl::getExceptionMask ();

    int when = 0;

    if (!(mask & FpuControl::OVERFLOW_EXC))
	when |= IEEE_OVERFLOW;
    if (!(mask & FpuControl::UNDERFLOW_EXC))
	when |= IEEE_UNDERFLOW;
    if (!(mask & FpuControl::DIVZERO_EXC))
	when |= IEEE_DIVZERO;
    if (!(mask & FpuControl::INEXACT_EXC))
	when |= IEEE_INEXACT;
    if (!(mask & FpuControl::INVALID_EXC))
	when |= IEEE_INVALID;

    return when;
}

void
handleExceptionsSetInRegisters()
{
    if (fpeHandler == 0)
	return;

    int mask = FpuControl::getExceptionMask ();

    int exc = FpuControl::getExceptions();

    if (!(mask & FpuControl::DIVZERO_EXC) && (exc & FpuControl::DIVZERO_EXC))
    {
        fpeHandler(IEEE_DIVZERO, "Floating-point division by zero.");
        return;
    }

    if (!(mask & FpuControl::OVERFLOW_EXC) && (exc & FpuControl::OVERFLOW_EXC))
    {
        fpeHandler(IEEE_OVERFLOW, "Floating-point overflow.");
        return;
    }

    if (!(mask & FpuControl::UNDERFLOW_EXC) && (exc & FpuControl::UNDERFLOW_EXC))
    {
        fpeHandler(IEEE_UNDERFLOW, "Floating-point underflow.");
        return;
    }

    if (!(mask & FpuControl::INEXACT_EXC) && (exc & FpuControl::INEXACT_EXC))
    {
        fpeHandler(IEEE_INEXACT, "Inexact floating-point result.");
        return;
    }

    if (!(mask & FpuControl::INVALID_EXC) && (exc & FpuControl::INVALID_EXC))
    {
        fpeHandler(IEEE_INVALID, "Invalid floating-point operation.");
        return;
    }
}

void
setFpExceptionHandler (FpExceptionHandler handler)
{
    if (fpeHandler == 0)
    {
	struct sigaction action;
	sigemptyset (&action.sa_mask);
	action.sa_flags = SA_SIGINFO | SA_NOMASK;
	action.sa_sigaction = (void (*) (int, siginfo_t *, void *)) catchSigFpe;
	action.sa_restorer = 0;

	sigaction (SIGFPE, &action, 0);
    }

    fpeHandler = handler;
}

} // namespace Iex

#else

#include <signal.h>
#include <assert.h>

namespace Iex
{

    namespace {
	volatile FpExceptionHandler fpeHandler = 0;
	void fpExc_(int x)
	{
	    if (fpeHandler != 0)
	    {
		fpeHandler(x, "");
	    }
	    else
	    {
		assert(0 != "Floating point exception");
	    }
	}
    }

void
setFpExceptions( int )
{
}

void
setFpExceptionHandler (FpExceptionHandler handler)
{
    // improve floating point exception handling nanoscopically above "nothing at all"
    fpeHandler = handler;
    signal(SIGFPE, fpExc_);
}

int
fpExceptions()
{
    return 0;
}

void
handleExceptionsSetInRegisters()
{
    // No implementation on this platform
}

} // namespace Iex

#endif
<|endoftext|>


<commit_before>// Copyright (C) 2012 Jrme Leclercq
// This file is part of the "Nazara Engine - Core module"
// For conditions of distribution and use, see copyright notice in Config.hpp

#include <Nazara/Core/Win32/HardwareInfoImpl.hpp>
#include <Nazara/Core/Error.hpp>
#include <windows.h>

#ifdef NAZARA_COMPILER_MSVC
#include <intrin.h>
#endif

#include <Nazara/Core/Debug.hpp>

void NzHardwareInfoImpl::Cpuid(nzUInt32 code, nzUInt32 result[4])
{
	#if defined(NAZARA_COMPILER_MSVC)
	__cpuid(reinterpret_cast<int*>(result), static_cast<int>(code));
	#elif defined(NAZARA_COMPILER_CLANG) || defined(NAZARA_COMPILER_GCC) || defined(NAZARA_COMPILER_INTEL)
	// Source: http://stackoverflow.com/questions/1666093/cpuid-implementations-in-c
	asm volatile
	("cpuid"
	 :"=a" (result[0]), "=b" (result[1]), "=c" (result[2]), "=d" (result[3])
     :"a" (code), "c" (0));
	#else
	NazaraInternalError("Cpuid has been called although it is not supported");
	#endif
}

unsigned int NzHardwareInfoImpl::GetProcessorCount()
{
	// Plus simple (et plus portable) que de passer par le CPUID
	SYSTEM_INFO infos;
	GetSystemInfo(&infos);

	return infos.dwNumberOfProcessors;
}

bool NzHardwareInfoImpl::IsCpuidSupported()
{
	#if defined(NAZARA_COMPILER_MSVC)
	int supported;
	__asm
	{
		pushfd
		pop	eax
		mov	ecx,	eax
		xor	eax,	0x200000
		push	eax
		popfd
		pushfd
		pop	eax
		xor	eax,	ecx
		mov	supported,	eax
		push	ecx
		popfd
	};

	return supported != 0;
	#elif defined(NAZARA_COMPILER_CLANG) || defined(NAZARA_COMPILER_GCC) || defined(NAZARA_COMPILER_INTEL)
	int supported;
	asm volatile
	("	pushfl\n"
	 "  pop	%%eax\n"
	 "	mov	%%eax,	%%ecx\n"
	 "	xor	$0x200000,	%%eax\n"
	 "	push	%%eax\n"
	 "	popfl\n"
	 "	pushfl\n"
	 "	pop	%%eax\n"
	 "	xor	%%ecx,	%%eax\n"
	 "	mov	%%eax,	%0\n"
	 "	push	%%ecx\n"
	 "	popfl\n"
	 : "=m" (supported)
	 : :"eax", "ecx", "memory");

	return supported != 0;
	#else
	return false;
	#endif
}
<commit_msg>Made inline-assembly more readable<commit_after>// Copyright (C) 2012 Jrme Leclercq
// This file is part of the "Nazara Engine - Core module"
// For conditions of distribution and use, see copyright notice in Config.hpp

#include <Nazara/Core/Win32/HardwareInfoImpl.hpp>
#include <Nazara/Core/Error.hpp>
#include <windows.h>

#ifdef NAZARA_COMPILER_MSVC
#include <intrin.h>
#endif

#include <Nazara/Core/Debug.hpp>

void NzHardwareInfoImpl::Cpuid(nzUInt32 code, nzUInt32 result[4])
{
	#if defined(NAZARA_COMPILER_MSVC)
	__cpuid(reinterpret_cast<int*>(result), static_cast<int>(code)); // Visual propose une fonction intrinsque pour le cpuid
	#elif defined(NAZARA_COMPILER_CLANG) || defined(NAZARA_COMPILER_GCC) || defined(NAZARA_COMPILER_INTEL)
	// Source: http://stackoverflow.com/questions/1666093/cpuid-implementations-in-c
	asm volatile ("cpuid" // Besoin d'tre volatile ?
				  : "=a" (result[0]), "=b" (result[1]), "=c" (result[2]), "=d" (result[3]) // output
                  : "a" (code), "c" (0));                                                  // input
	#else
	NazaraInternalError("Cpuid has been called although it is not supported");
	#endif
}

unsigned int NzHardwareInfoImpl::GetProcessorCount()
{
	// Plus simple (et plus portable) que de passer par le CPUID
	SYSTEM_INFO infos;
	GetSystemInfo(&infos);

	return infos.dwNumberOfProcessors;
}

bool NzHardwareInfoImpl::IsCpuidSupported()
{
	#if defined(NAZARA_COMPILER_MSVC)
	int supported;
	__asm
	{
		pushfd
		pop  eax
		mov  ecx, eax
		xor  eax, 0x200000
		push eax
		popfd
		pushfd
		pop  eax
		xor  eax, ecx
		mov  supported, eax
		push ecx
		popfd
	};

	return supported != 0;
	#elif defined(NAZARA_COMPILER_CLANG) || defined(NAZARA_COMPILER_GCC) || defined(NAZARA_COMPILER_INTEL)
	int supported;
	asm volatile ("	pushfl\n"
	              "	pop %%eax\n"
	              "	mov %%eax, %%ecx\n"
	              "	xor $0x200000, %%eax\n"
	              "	push %%eax\n"
	              "	popfl\n"
	              "	pushfl\n"
	              "	pop %%eax\n"
	              "	xor %%ecx, %%eax\n"
	              "	mov %%eax, %0\n"
	              "	push %%ecx\n"
	              "	popfl"
	              : "=m" (supported)         // output
	              :                          // input
	              : "eax", "ecx", "memory"); // clobbered register

	return supported != 0;
	#else
	return false;
	#endif
}
<|endoftext|>


<commit_before>/*************************************************************************
*    UrBackup - Client/Server backup system
*    Copyright (C) 2011  Martin Raiber
*
*    This program is free software: you can redistribute it and/or modify
*    it under the terms of the GNU General Public License as published by
*    the Free Software Foundation, either version 3 of the License, or
*    (at your option) any later version.
*
*    This program 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 General Public License for more details.
*
*    You should have received a copy of the GNU General Public License
*    along with this program.  If not, see <http://www.gnu.org/licenses/>.
**************************************************************************/

#include "vld.h"

#include "AcceptThread.h"
#include "Server.h"
#include "stringtools.h"
#include "SelectThread.h"
#include "Client.h"
#include <memory.h>
#ifndef _WIN32
#include <errno.h>
#endif

extern bool run;

OutputCallback::OutputCallback(SOCKET fd_)
{
	  fd=fd_;
}

OutputCallback::~OutputCallback()
{
    closesocket(fd);
}

void OutputCallback::operator() (const void* buf, size_t count)
{
	for(int rc=0;rc<=static_cast<int>(count);)
	{
		rc = send(fd, (const char*)buf+rc, static_cast<int>(count)-rc, MSG_NOSIGNAL);
		if (rc < 0)
		{
			int ec;
	#ifdef _WIN32
			ec=GetLastError();
	#else
			ec=errno;
	#endif
			Server->Log("Send failed in OutputCallback ec="+nconvert(ec), LL_INFO);
			throw std::runtime_error("Send failed in OutputCallback");
		}
	}
}

CAcceptThread::CAcceptThread( unsigned int nWorkerThreadsPerMaster, unsigned short int uPort ) : error(false)
{
	WorkerThreadsPerMaster=nWorkerThreadsPerMaster;

	Server->Log("Creating SOCKET...",LL_INFO);
	s=socket(AF_INET,SOCK_STREAM,0);
	if(s<1)
	{
		Server->Log("Creating SOCKET failed",LL_ERROR);
		error=true;
		return;
	}
	Server->Log("done.",LL_INFO);

	int optval=1;
	int rc=setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char*)&optval, sizeof(int));
	if(rc==SOCKET_ERROR)
	{
		Server->Log("Failed setting SO_REUSEADDR for port "+nconvert(uPort),LL_ERROR);
		error=true;
		return;
	}

	sockaddr_in addr;

	memset(&addr, 0, sizeof(sockaddr_in));
	addr.sin_family=AF_INET;
	addr.sin_port=htons(uPort);
	addr.sin_addr.s_addr=INADDR_ANY;

	rc=bind(s,(sockaddr*)&addr,sizeof(addr));
	if(rc==SOCKET_ERROR)
	{
		Server->Log("Failed binding SOCKET to Port "+nconvert(uPort),LL_ERROR);
		error=true;
		return;
	}

	listen(s, 10000);

	Server->Log("Server started up sucessfully!",LL_INFO);
}

CAcceptThread::~CAcceptThread()
{
	closesocket(s);
	Server->Log("Deleting SelectThreads..");
	for(size_t i=0;i<SelectThreads.size();++i)
	{
		delete SelectThreads[i];
	}
}

#ifndef _WIN32
void printLinError(void)
{
	switch(errno)
	{
		case EWOULDBLOCK: Server->Log("Reason: EWOULDBLOCK", LL_ERROR); break;
		case EBADF: Server->Log("Reason: EBADF", LL_ERROR); break;
		case ECONNABORTED: Server->Log("Reason: ECONNABORTED", LL_ERROR); break;
		case EINTR: Server->Log("Reason: EINTR", LL_ERROR); break;
		case EINVAL: Server->Log("Reason: EINVAL", LL_ERROR); break;
		case EMFILE: Server->Log("Reason: EMFILE", LL_ERROR); break;
		case ENFILE: Server->Log("Reason: ENFILE", LL_ERROR); break;
		case ENOTSOCK: Server->Log("Reason: ENOTSOCK", LL_ERROR); break;
		case EFAULT: Server->Log("Reason: EFAULT", LL_ERROR); break;
		case ENOBUFS: Server->Log("Reason: ENOBUFS", LL_ERROR); break;
		case ENOMEM: Server->Log("Reason: ENOMEM", LL_ERROR); break;
		case EPROTO: Server->Log("Reason: EPROTO", LL_ERROR); break;
		case EPERM: Server->Log("Reason: EPERM", LL_ERROR); break;
	}
}
#endif

void CAcceptThread::operator()(bool single)
{
	do
	{
		socklen_t addrsize=sizeof(sockaddr_in);

#ifdef _WIN32
		fd_set fdset;
		FD_ZERO(&fdset);
		FD_SET(s, &fdset);

		timeval lon;
		lon.tv_sec=1;
		lon.tv_usec=0;

		_i32 rc=select((int)s+1, &fdset, 0, 0, &lon);

		if( rc<0 )
			return;

		if( FD_ISSET(s,&fdset) )
		{
#else
		pollfd conn[1];
		conn[0].fd=s;
		conn[0].events=POLLIN;
		conn[0].revents=0;
		int rc = poll(conn, 1, 1000);
		if(rc<0)
			return;

		if(rc>0)
		{
#endif
			sockaddr_in naddr;
			SOCKET ns=accept(s, (sockaddr*)&naddr, &addrsize);
			if(ns!=SOCKET_ERROR)
			{
				//Server->Log("New Connection incomming", LL_INFO);

				OutputCallback *output=new OutputCallback(ns);
				FCGIProtocolDriver *driver=new FCGIProtocolDriver(*output );

				CClient *client=new CClient();
				client->set(ns, output, driver);

				AddToSelectThread(client);
			}
			else
			{
				Server->Log("Accepting client failed", LL_ERROR);
#ifndef _WIN32
				printLinError();
#endif
				Server->wait(1000);
			}
		}
	}while(single==false);
}

void CAcceptThread::AddToSelectThread(CClient *client)
{
	for(size_t i=0;i<SelectThreads.size();++i)
	{
		if( SelectThreads[i]->FreeClients()>0 )
		{
			SelectThreads[i]->AddClient( client );
			return;
		}
	}

	CSelectThread *nt=new CSelectThread(WorkerThreadsPerMaster);
	nt->AddClient( client );

	SelectThreads.push_back( nt );

	Server->createThread(nt);
}

bool CAcceptThread::has_error(void)
{
	return error;
}
<commit_msg>Send all data if send syscall only sends a subset<commit_after>/*************************************************************************
*    UrBackup - Client/Server backup system
*    Copyright (C) 2011  Martin Raiber
*
*    This program is free software: you can redistribute it and/or modify
*    it under the terms of the GNU General Public License as published by
*    the Free Software Foundation, either version 3 of the License, or
*    (at your option) any later version.
*
*    This program 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 General Public License for more details.
*
*    You should have received a copy of the GNU General Public License
*    along with this program.  If not, see <http://www.gnu.org/licenses/>.
**************************************************************************/

#include "vld.h"

#include "AcceptThread.h"
#include "Server.h"
#include "stringtools.h"
#include "SelectThread.h"
#include "Client.h"
#include <memory.h>
#ifndef _WIN32
#include <errno.h>
#endif

extern bool run;

OutputCallback::OutputCallback(SOCKET fd_)
{
	  fd=fd_;
}

OutputCallback::~OutputCallback()
{
    closesocket(fd);
}

void OutputCallback::operator() (const void* buf, size_t count)
{
	size_t sent=0;
	do
	{
		int rc = send(fd, (const char*)buf+sent, static_cast<int>(count-sent), MSG_NOSIGNAL);
		if (rc < 0)
		{
			int ec;
	#ifdef _WIN32
			ec=GetLastError();
	#else
			ec=errno;
	#endif
			Server->Log("Send failed in OutputCallback ec="+nconvert(ec), LL_INFO);
			throw std::runtime_error("Send failed in OutputCallback");
		}
		else
		{
			sent+=rc;
		}
	}
	while(sent<count);
}

CAcceptThread::CAcceptThread( unsigned int nWorkerThreadsPerMaster, unsigned short int uPort ) : error(false)
{
	WorkerThreadsPerMaster=nWorkerThreadsPerMaster;

	Server->Log("Creating SOCKET...",LL_INFO);
	s=socket(AF_INET,SOCK_STREAM,0);
	if(s<1)
	{
		Server->Log("Creating SOCKET failed",LL_ERROR);
		error=true;
		return;
	}
	Server->Log("done.",LL_INFO);

	int optval=1;
	int rc=setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char*)&optval, sizeof(int));
	if(rc==SOCKET_ERROR)
	{
		Server->Log("Failed setting SO_REUSEADDR for port "+nconvert(uPort),LL_ERROR);
		error=true;
		return;
	}

	sockaddr_in addr;

	memset(&addr, 0, sizeof(sockaddr_in));
	addr.sin_family=AF_INET;
	addr.sin_port=htons(uPort);
	addr.sin_addr.s_addr=INADDR_ANY;

	rc=bind(s,(sockaddr*)&addr,sizeof(addr));
	if(rc==SOCKET_ERROR)
	{
		Server->Log("Failed binding SOCKET to Port "+nconvert(uPort),LL_ERROR);
		error=true;
		return;
	}

	listen(s, 10000);

	Server->Log("Server started up sucessfully!",LL_INFO);
}

CAcceptThread::~CAcceptThread()
{
	closesocket(s);
	Server->Log("Deleting SelectThreads..");
	for(size_t i=0;i<SelectThreads.size();++i)
	{
		delete SelectThreads[i];
	}
}

#ifndef _WIN32
void printLinError(void)
{
	switch(errno)
	{
		case EWOULDBLOCK: Server->Log("Reason: EWOULDBLOCK", LL_ERROR); break;
		case EBADF: Server->Log("Reason: EBADF", LL_ERROR); break;
		case ECONNABORTED: Server->Log("Reason: ECONNABORTED", LL_ERROR); break;
		case EINTR: Server->Log("Reason: EINTR", LL_ERROR); break;
		case EINVAL: Server->Log("Reason: EINVAL", LL_ERROR); break;
		case EMFILE: Server->Log("Reason: EMFILE", LL_ERROR); break;
		case ENFILE: Server->Log("Reason: ENFILE", LL_ERROR); break;
		case ENOTSOCK: Server->Log("Reason: ENOTSOCK", LL_ERROR); break;
		case EFAULT: Server->Log("Reason: EFAULT", LL_ERROR); break;
		case ENOBUFS: Server->Log("Reason: ENOBUFS", LL_ERROR); break;
		case ENOMEM: Server->Log("Reason: ENOMEM", LL_ERROR); break;
		case EPROTO: Server->Log("Reason: EPROTO", LL_ERROR); break;
		case EPERM: Server->Log("Reason: EPERM", LL_ERROR); break;
	}
}
#endif

void CAcceptThread::operator()(bool single)
{
	do
	{
		socklen_t addrsize=sizeof(sockaddr_in);

#ifdef _WIN32
		fd_set fdset;
		FD_ZERO(&fdset);
		FD_SET(s, &fdset);

		timeval lon;
		lon.tv_sec=1;
		lon.tv_usec=0;

		_i32 rc=select((int)s+1, &fdset, 0, 0, &lon);

		if( rc<0 )
			return;

		if( FD_ISSET(s,&fdset) )
		{
#else
		pollfd conn[1];
		conn[0].fd=s;
		conn[0].events=POLLIN;
		conn[0].revents=0;
		int rc = poll(conn, 1, 1000);
		if(rc<0)
			return;

		if(rc>0)
		{
#endif
			sockaddr_in naddr;
			SOCKET ns=accept(s, (sockaddr*)&naddr, &addrsize);
			if(ns!=SOCKET_ERROR)
			{
				//Server->Log("New Connection incomming", LL_INFO);

				OutputCallback *output=new OutputCallback(ns);
				FCGIProtocolDriver *driver=new FCGIProtocolDriver(*output );

				CClient *client=new CClient();
				client->set(ns, output, driver);

				AddToSelectThread(client);
			}
			else
			{
				Server->Log("Accepting client failed", LL_ERROR);
#ifndef _WIN32
				printLinError();
#endif
				Server->wait(1000);
			}
		}
	}while(single==false);
}

void CAcceptThread::AddToSelectThread(CClient *client)
{
	for(size_t i=0;i<SelectThreads.size();++i)
	{
		if( SelectThreads[i]->FreeClients()>0 )
		{
			SelectThreads[i]->AddClient( client );
			return;
		}
	}

	CSelectThread *nt=new CSelectThread(WorkerThreadsPerMaster);
	nt->AddClient( client );

	SelectThreads.push_back( nt );

	Server->createThread(nt);
}

bool CAcceptThread::has_error(void)
{
	return error;
}
<|endoftext|>


<commit_before>#include <sstream>
#include <string>
#include <string_view>

#include "../test.h"
#include "simdjson.cpp"
#include "simdjson.h"

using namespace simdjson;

static void GenStat(Stat &stat, const dom::element &v) {
  switch (v.type()) {
    case dom::element_type::ARRAY:
      for (dom::element child : dom::array(v)) {
        stat.elementCount++;
        GenStat(stat, child);
      }
      stat.arrayCount++;
      break;
    case dom::element_type::OBJECT:
      for (dom::key_value_pair kv : dom::object(v)) {
        GenStat(stat, dom::element(kv.value));
        stat.memberCount++;
        stat.stringCount++;
      }
      stat.objectCount++;
      break;
    case dom::element_type::INT64:
    case dom::element_type::UINT64:
    case dom::element_type::DOUBLE:
      stat.numberCount++;
      break;
    case dom::element_type::STRING: {
      stat.stringCount++;
      std::string_view sv = v.get<std::string_view>();
      stat.stringLength += sv.size();
    } break;
    case dom::element_type::BOOL:
      if (v.get<bool>()) {
        stat.trueCount++;
      } else {
        stat.falseCount++;
      }
      break;
    case dom::element_type::NULL_VALUE:
      ++stat.nullCount;
      break;
  }
}

class SimdJsonParseResult : public ParseResultBase {
 public:
  dom::element root{};
  std::unique_ptr<dom::parser> parser = std::make_unique<dom::parser>();
};

class SimdStringResult : public StringResultBase {
 public:
  std::stringstream ss;
  const char *c_str() const override { return ss.str().c_str(); }
};
class SimdTest : public TestBase {
 public:
#if TEST_INFO
  const char *GetName() const override { return "simdjson"; }
  const char *GetFilename() const override { return __FILE__; }
#endif

#if TEST_PARSE
  ParseResultBase *Parse(const char *j, size_t length) const override {
    auto pr = std::make_unique<SimdJsonParseResult>();

    std::string_view s(j, length);
    simdjson::error_code error;
    pr->parser->parse(s).tie(pr->root, error);
    if (error) {
      return nullptr;
    }
    return pr.release();
  }
#endif

#if TEST_STRINGIFY
  StringResultBase *Stringify(
      const ParseResultBase *parseResult) const override {
    auto sr = std::make_unique<SimdStringResult>();

    auto pr = static_cast<const SimdJsonParseResult *>(parseResult);
    sr->ss << pr->root;
    return sr.release();
  }
#endif

#if TEST_PRETTIFY
  // Currently unsupported, simdjson v0.3
  StringResultBase *Prettify(
      const ParseResultBase *parseResult) const override {
    (void)parseResult;
    return nullptr;
  }
#endif

#if TEST_STATISTICS
  bool Statistics(const ParseResultBase *parseResult,
                  Stat *stat) const override {
    auto pr = static_cast<const SimdJsonParseResult *>(parseResult);
    memset(stat, 0, sizeof(Stat));
    GenStat(*stat, pr->root);
    return true;
  }
#endif

#if TEST_CONFORMANCE
  bool ParseDouble(const char *j, double *d) const override {
    simdjson::error_code error;
    simdjson::dom::parser parser;
    parser.parse(j, std::strlen(j)).at(0).get<double>().tie(*d, error);
    if (error) {
      return false;
    }
    return true;
  }

  bool ParseString(const char *j, std::string &s) const override {
    simdjson::error_code error;
    std::string_view answer;
    parser.parse(j,strlen(j))
        .at(0)
        .get<std::string_view>()
        .tie(answer, error);
    if (error) {
      return false;
    }
    s.assign(answer.data(), answer.size());
    return true;
  }
#endif
};

REGISTER_TEST(SimdTest);

<commit_msg>Slightly more correct.<commit_after>#include <sstream>
#include <string>
#include <string_view>

#include "../test.h"
#include "simdjson.cpp"
#include "simdjson.h"

using namespace simdjson;

static void GenStat(Stat &stat, const dom::element v) {
  switch (v.type()) {
    case dom::element_type::ARRAY:
      for (dom::element child : dom::array(v)) {
        stat.elementCount++;
        GenStat(stat, child);
      }
      stat.arrayCount++;
      break;
    case dom::element_type::OBJECT:
      for (dom::key_value_pair kv : dom::object(v)) {
        GenStat(stat, kv.value);
        stat.stringLength += kv.key.size();
        stat.memberCount++;
        stat.stringCount++;
      }
      stat.objectCount++;
      break;
    case dom::element_type::INT64:
    case dom::element_type::UINT64:
    case dom::element_type::DOUBLE:
      stat.numberCount++;
      break;
    case dom::element_type::STRING: {
      stat.stringCount++;
      std::string_view sv = v.get<std::string_view>();
      stat.stringLength += sv.size();
    } break;
    case dom::element_type::BOOL:
      if (v.get<bool>()) {
        stat.trueCount++;
      } else {
        stat.falseCount++;
      }
      break;
    case dom::element_type::NULL_VALUE:
      ++stat.nullCount;
      break;
  }
}

class SimdJsonParseResult : public ParseResultBase {
 public:
  dom::element root{};
  std::unique_ptr<dom::parser> parser = std::make_unique<dom::parser>();
};

class SimdStringResult : public StringResultBase {
 public:
  std::stringstream ss;
  const char *c_str() const override { return ss.str().c_str(); }
};
class SimdTest : public TestBase {
 public:
#if TEST_INFO
  const char *GetName() const override { return "simdjson"; }
  const char *GetFilename() const override { return __FILE__; }
#endif

#if TEST_PARSE
  ParseResultBase *Parse(const char *j, size_t length) const override {
    auto pr = std::make_unique<SimdJsonParseResult>();

    std::string_view s(j, length);
    simdjson::error_code error;
    pr->parser->parse(s).tie(pr->root, error);
    if (error) {
      return nullptr;
    }
    return pr.release();
  }
#endif

#if TEST_STRINGIFY
  StringResultBase *Stringify(
      const ParseResultBase *parseResult) const override {
    auto sr = std::make_unique<SimdStringResult>();

    auto pr = static_cast<const SimdJsonParseResult *>(parseResult);
    sr->ss << pr->root;
    return sr.release();
  }
#endif

#if TEST_PRETTIFY
  // Currently unsupported, simdjson v0.3
  StringResultBase *Prettify(
      const ParseResultBase *parseResult) const override {
    (void)parseResult;
    return nullptr;
  }
#endif

#if TEST_STATISTICS
  bool Statistics(const ParseResultBase *parseResult,
                  Stat *stat) const override {
    auto pr = static_cast<const SimdJsonParseResult *>(parseResult);
    memset(stat, 0, sizeof(Stat));
    GenStat(*stat, pr->root);
    return true;
  }
#endif

#if TEST_CONFORMANCE
  bool ParseDouble(const char *j, double *d) const override {
    simdjson::error_code error;
    simdjson::dom::parser parser;
    parser.parse(j, std::strlen(j)).at(0).get<double>().tie(*d, error);
    if (error) {
      return false;
    }
    return true;
  }

  bool ParseString(const char *j, std::string &s) const override {
    simdjson::error_code error;
    std::string_view answer;
    parser.parse(j,strlen(j))
        .at(0)
        .get<std::string_view>()
        .tie(answer, error);
    if (error) {
      return false;
    }
    s.assign(answer.data(), answer.size());
    return true;
  }
#endif
};

REGISTER_TEST(SimdTest);

<|endoftext|>


<commit_before>#include <iostream>
#include <string>
#include <fstream>
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/graphviz.hpp>

using namespace std;
using namespace boost;

enum vertex_kmb_color_t { vertex_kmb_color };
enum edge_penwidth_t { edge_penwidth };

namespace boost
{
    BOOST_INSTALL_PROPERTY(vertex, kmb_color);
    BOOST_INSTALL_PROPERTY(edge, penwidth);
}

// BGL types
typedef boost::property < boost::vertex_name_t , unsigned,
        boost::property < boost::vertex_color_t, float ,
        boost::property < vertex_kmb_color_t, string > > > vertex_p;
typedef boost::property < boost::edge_weight_t , unsigned,
        boost::property < edge_penwidth_t , unsigned > > edge_p;
typedef boost::adjacency_list <boost::listS, boost::vecS, boost::undirectedS, vertex_p, edge_p, boost::no_property > graph_t;

typedef boost::graph_traits<graph_t>::vertex_descriptor Vertex;
typedef boost::graph_traits<graph_t>::edge_descriptor Edge;

// Global Variables
string InputFileName, OutputFileName;
float MulticastFraction = 0.0;

int main(int argc, char* argv[])
{
    if(argc != 4)
    {
        cerr << "Usage: " << argv[0] << " <Multicast Fraction> <Input.dot> <Output.dot>\n";
        return 1;
    }

    try
    {
        MulticastFraction = stof(string(argv[1]));
        if(MulticastFraction < 0 || MulticastFraction > 1)
            throw invalid_argument("Fraction should be > 0 and < 1.");
    }
    catch(std::exception &err)
    {
        cerr << err.what() << endl;
        cerr << "Invalid fraction argument\n";
        return 1;
    }

    InputFileName.assign(argv[2]);
    OutputFileName.assign(argv[3]);

    ifstream InputFile(InputFileName.c_str(), ios::in);
    ofstream OutputFile(OutputFileName.c_str(), ios::out);

    assert(OutputFile.is_open() && InputFile.is_open() && "Error opening files");

    graph_t Network(0);
    boost::dynamic_properties dp;
    auto name = boost::get(boost::vertex_name, Network);
    dp.property("node_id", name);
    auto kmb_color = boost::get(vertex_kmb_color, Network);
    dp.property("fillcolor", kmb_color);
    auto weight = boost::get(boost::edge_weight, Network);
    dp.property("weight", weight);
    auto penwidth = boost::get(edge_penwidth, Network);
    dp.property("penwidth", penwidth);

    try
    {
        read_graphviz(InputFile, Network, dp, "node_id");
    }
    catch(std::exception &err)
    {
        cerr << err.what() << endl;
        cerr << "read_graphviz failed for " << InputFileName << "\n";
        return 1;
    }

    // Initialize all dynamic properties

    BGL_FORALL_VERTICES(v, Network, graph_t)
    {
        kmb_color[v] = "white";
    }

    BGL_FORALL_EDGES(e, Network, graph_t)
    {
        penwidth[e] = 1;
        weight[e] = 1;
    }

    try
    {
        write_graphviz_dp(OutputFile, Network, dp);
    }
    catch(std::exception &err)
    {
        cerr << err.what() << endl;
        cerr << "write_graphviz failed for " << OutputFileName << "\n";
        return 1;
    }

    return 0;
}
<commit_msg>Step1 - not tested<commit_after>#include <iostream>
#include <string>
#include <fstream>
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/graphviz.hpp>
#include <boost/graph/dijkstra_shortest_paths.hpp>
#include <set>
#include <vector>
#include <random>

using namespace std;
using namespace boost;

enum vertex_kmb_color_t { vertex_kmb_color };
enum edge_penwidth_t { edge_penwidth };

namespace boost
{
    BOOST_INSTALL_PROPERTY(vertex, kmb_color);
    BOOST_INSTALL_PROPERTY(edge, penwidth);
}

// BGL types
typedef boost::property < boost::vertex_name_t , unsigned,
        boost::property < boost::vertex_color_t, float ,
        boost::property < vertex_kmb_color_t, string > > > vertex_p;
typedef boost::property < boost::edge_weight_t , double,
        boost::property < edge_penwidth_t , unsigned > > edge_p;
typedef boost::adjacency_list <boost::listS, boost::vecS, boost::undirectedS, vertex_p, edge_p, boost::no_property > graph_t;

typedef boost::graph_traits<graph_t>::vertex_descriptor Vertex;
typedef boost::graph_traits<graph_t>::edge_descriptor Edge;

// Global Variables
string InputFileName, OutputFileName;
float MulticastFraction = 0.0;
unsigned NumVertices = 0;
set<Vertex> MulticastVertices;

int main(int argc, char* argv[])
{
    if(argc != 4)
    {
        cerr << "Usage: " << argv[0] << " <Multicast Fraction> <Input.dot> <Output.dot>\n";
        return 1;
    }

    try
    {
        MulticastFraction = stof(string(argv[1]));
        if(MulticastFraction < 0 || MulticastFraction > 1)
            throw invalid_argument("Fraction should be > 0 and < 1.");
    }
    catch(std::exception &err)
    {
        cerr << err.what() << endl;
        cerr << "Invalid fraction argument\n";
        return 1;
    }

    InputFileName.assign(argv[2]);
    OutputFileName.assign(argv[3]);

    ifstream InputFile(InputFileName.c_str(), ios::in);
    ofstream OutputFile(OutputFileName.c_str(), ios::out);

    assert(OutputFile.is_open() && InputFile.is_open() && "Error opening files");

    graph_t Network(0);
    boost::dynamic_properties dp;
    auto name = boost::get(boost::vertex_name, Network);
    dp.property("node_id", name);
    auto kmb_color = boost::get(vertex_kmb_color, Network);
    dp.property("fillcolor", kmb_color);
    auto weight = boost::get(boost::edge_weight, Network);
    dp.property("weight", weight);
    auto penwidth = boost::get(edge_penwidth, Network);
    dp.property("penwidth", penwidth);

    try
    {
        read_graphviz(InputFile, Network, dp, "node_id");
    }
    catch(std::exception &err)
    {
        cerr << err.what() << endl;
        cerr << "read_graphviz failed for " << InputFileName << "\n";
        return 1;
    }

    // Initialize all dynamic properties

    BGL_FORALL_VERTICES(v, Network, graph_t)
    {
        kmb_color[v] = "white";
    }

    BGL_FORALL_EDGES(e, Network, graph_t)
    {
        penwidth[e] = 1;
        weight[e] = 1;
    }

    // TODO: Add timing code

    NumVertices = boost::num_vertices(Network);
    unsigned NumMulticast = (unsigned)MulticastFraction * NumVertices;

    // Assume that vertices are numbered 0 -- N-1 (generated by BRITE)
    // Randomly select multicast nodes using uniform distribution

    random_device RandomDevice;
    mt19937 Generator(RandomDevice());
    uniform_int_distribution<> Dist(0, NumMulticast);

    do
    {
        MulticastVertices.insert((Vertex)Dist(Generator));
    } while( MulticastVertices.size() < NumMulticast);

    graph_t G1(0);

    // Step 1 -- Construct undirected distance graph G1, G and S.

    for(auto V = MulticastVertices.begin(), E = MulticastVertices.end(); V != E; V++)
    {
        Vertex Vx = *V;
        // Get the shortest path between Vx,All
        vector<Vertex> P(NumVertices);
        vector<unsigned> D(NumVertices);
        dijkstra_shortest_paths(Network, Vx,
                                predecessor_map(boost::make_iterator_property_map(P.begin(), get(boost::vertex_index, Network))).
                                distance_map(boost::make_iterator_property_map(D.begin(), get(boost::vertex_index, Network))));
        for(auto W = std::next(V); W != E; W++)
        {
            Vertex Wx = *W;
            boost::add_vertex(Vx, G1);
            boost::add_vertex(Wx, G1);
            boost::add_edge(Vx, Wx, edge_p(D[Wx],1), G1);
        }
    }

    try
    {
        write_graphviz_dp(OutputFile, Network, dp);
    }
    catch(std::exception &err)
    {
        cerr << err.what() << endl;
        cerr << "write_graphviz failed for " << OutputFileName << "\n";
        return 1;
    }

    return 0;
}
<|endoftext|>


<commit_before>#include "rt_feedback.h"

void rt_feedback(ap32_data fet_packet_spk_id[dim],
                 hls::stream<ap32_data> &spk_id_out)
{
#pragma HLS INTERFACE ap_fifo port=fet_packet_spk_id
#pragma HLS INTERFACE axis port=spk_id_out

    int time;
    int id; // first two items in the packet

    time = 0;
    id   = -1;

	read_packet_in:
	for (int i=0; i<dim; i++) {
#pragma HLS PIPELINE
		if(i==0)
			time = fet_packet_spk_id[i].range(31,0);
		if(i==6)
			id   = fet_packet_spk_id[i].range(31,0);
	}

    feedback_rule_out: // 1ms stimulation per targeted spike
    if (id == 888) {
        for (int j=0; j<pulse_width; j++)
            spk_id_out.write(id);
    }
}
<commit_msg>working version of rt_feedback module<commit_after>#include "rt_feedback.h"

void rt_feedback(ap32_data fet_packet_spk_id[dim],
                 hls::stream<ap32_data> &spk_id_out)
{
#pragma HLS INTERFACE ap_fifo port=fet_packet_spk_id
#pragma HLS INTERFACE axis port=spk_id_out

    int time;
    int fet;
    int id; // first two items in the packet

    time = 0;
    id   = -1;

	read_packet_in:
	for (int i=0; i<dim; i++) {
    	if(i==0)
    		time = fet_packet_spk_id[i].range(31,0);
        if(i>0 && i<dim-1)
            fet  = fet_packet_spk_id[i].range(31,0);
    	if(i==dim-1)
    		id   = fet_packet_spk_id[i].range(31,0);
	}

    feedback_rule_out: // 1ms stimulation per targeted spike
    if (id == 101) {
        for (int j=0; j<pulse_width; j++)
            spk_id_out.write(id);
    }
}
<|endoftext|>


<commit_before>/*
    Copyright (C) 2001 by Jorrit Tyberghein

    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 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#include "picview.h"

/** Event codes for the control bar's widgets. */
enum PICVIEW_EVENTS { PVE_FIRST, PVE_PREV, PVE_NEXT, PVE_QUIT, PVE_SCALE };

/** Callback for picture viewer events. */
struct onPicViewEvent : public iAws2ScriptEvent
{
private:
	/** Holds the instance of the picture viewer that we're responding to. */
	PicView *picview;

public:
	onPicViewEvent(PicView *_pv):picview(_pv) {}
	virtual ~onPicViewEvent() {};

	virtual void operator() (iAws2ScriptObject *info)
	{
		switch(info->GetIntArg(0))
		{
			case PVE_FIRST:
				picview->LoadNextImage (true, 1);
			break;

			case PVE_PREV:
				picview->LoadNextImage (false, -1);
			break;

			case PVE_NEXT:
				picview->LoadNextImage (false, 1);
			break;

			case PVE_QUIT:
				picview->Quit();
			break;

			case PVE_SCALE:
				picview->FlipScale();
				picview->LoadNextImage (false, 0);
			break;
		}
	}

};

//---------------------------------------------------------------------------

CS_IMPLEMENT_APPLICATION

//---------------------------------------------------------------------------

PicView::PicView ()
{
  SetApplicationName ("CrystalSpace.PicView");
  pic = 0;
  scale = false;
}

PicView::~PicView ()
{
}

void PicView::ProcessFrame ()
{
  iGraphics2D* g2d = g3d->GetDriver2D ();

  if (!g3d->BeginDraw (CSDRAW_2DGRAPHICS)) return;

  g2d->Clear(0);

  if (pic)
  {
    if (scale)
      pic->DrawScaled(g3d, 0, 0, g2d->GetWidth (), g2d->GetHeight ());
    else
      pic->Draw(g3d, 0, 0);
  }

  aws->Redraw ();
}

void PicView::FinishFrame ()
{
  g3d->FinishDraw ();
  g3d->Print (0);
}

bool PicView::OnKeyboard(iEvent& ev)
{
  csKeyEventType eventtype = csKeyEventHelper::GetEventType(&ev);
  if (eventtype == csKeyEventTypeDown)
  {
    utf32_char code = csKeyEventHelper::GetCookedCode(&ev);
    if (code == CSKEY_ESC || code == 'q')
    {
      picview_events->Exec("picView.Quit()");
    }
    else if (code == 'f')
    {
      picview_events->Exec("picView.First()");
    }
    else if (code == 'p')
    {
      picview_events->Exec("picView.Prev()");
    }
    else if (code == 'n')
    {
      picview_events->Exec("picView.Next()");
    }
    else if (code == 's')
    {
      picview_events->Exec("picView.Scale()");
    }
  }
  return false;
}

bool PicView::HandleEvent (iEvent &ev)
{
  csBaseEventHandler::HandleEvent(ev);
  if (aws) return aws->HandleEvent (ev);
  return false;
}

bool PicView::OnInitialize(int /*argc*/, char* /*argv*/ [])
{
  SetupConfigManager(GetObjectRegistry(), "/config/picview.cfg");

  if (!csInitializer::RequestPlugins(GetObjectRegistry(),
    CS_REQUEST_VFS,
    CS_REQUEST_OPENGL3D,
    CS_REQUEST_ENGINE,
    CS_REQUEST_FONTSERVER,
    CS_REQUEST_IMAGELOADER,
    CS_REQUEST_REPORTER,
    CS_REQUEST_REPORTERLISTENER,
    CS_REQUEST_PLUGIN("crystalspace.window.alternatemanager2", iAws2),
    CS_REQUEST_END))
    return ReportError("Failed to initialize plugins!");

  csBaseEventHandler::Initialize(GetObjectRegistry());

  if (!RegisterQueue(GetObjectRegistry(), csevAllEvents(GetObjectRegistry())))
    return ReportError("Failed to set up event handler!");

  return true;
}

void PicView::OnExit()
{
}

bool PicView::Application()
{
  if (!OpenApplication(GetObjectRegistry()))
    return ReportError("Error opening system!");

  g3d = CS_QUERY_REGISTRY(GetObjectRegistry(), iGraphics3D);
  if (!g3d) return ReportError("Failed to locate 3D renderer!");

  engine = CS_QUERY_REGISTRY(GetObjectRegistry(), iEngine);
  if (!engine) return ReportError("Failed to locate 3D engine!");

  kbd = CS_QUERY_REGISTRY(GetObjectRegistry(), iKeyboardDriver);
  if (!kbd) return ReportError("Failed to locate Keyboard Driver!");

  vfs = CS_QUERY_REGISTRY(GetObjectRegistry(), iVFS);
  if (!vfs) return ReportError("Failed to locate Virtual FileSystem!");

  imgloader = CS_QUERY_REGISTRY(GetObjectRegistry(), iImageIO);
  if (!imgloader) return ReportError("Failed to locate Image Loader!");

  aws = CS_QUERY_REGISTRY(GetObjectRegistry(), iAws2);
  if (!aws) return ReportError("Failed to locate Alternative Windowing System 2!");

  vfs->ChDir ("/tmp");
  files = vfs->FindFiles ("/this/*");
  cur_idx = 0;

  CreateGui();

  x = g3d->GetDriver2D ()->GetWidth ();
  y = g3d->GetDriver2D ()->GetHeight ();

  Run();

  return true;
}

void PicView::CreateGui ()
{
  aws->SetDrawTarget(g3d->GetDriver2D (), g3d);

  picview_events = aws->CreateScriptObject("picView", new onPicViewEvent(this));

  picview_events->SetProp("cmdFirst", PVE_FIRST);
  picview_events->SetProp("cmdPrev", PVE_PREV);
  picview_events->SetProp("cmdNext", PVE_NEXT);
  picview_events->SetProp("cmdQuit", PVE_QUIT);
  picview_events->SetProp("cmdScale", PVE_SCALE);

  // Load the normal skin.
  if (aws->Load ("/varia/picview.skin.js")==false)
    ReportError("Couldn't load skin definition file: '/varia/picview.skin.js'!");

  // Load the no files we recognize tooltip.
  if (files->IsEmpty())
  {
	  if (aws->Load ("/varia/picview.nopics.js")==false)
    	ReportError("Couldn't load skin definition file: '/varia/picview.nopics.js'!");
  }
  // Otherwise, queue up the first picture.
  else
  {
	 picview_events->Exec("picView.First()");
  }
}

void PicView::LoadNextImage (bool rewind, int step)
{
  if (rewind) cur_idx = files->Length ();
  size_t startIdx = cur_idx;
  csRef<iImage> ifile;
  iTextureManager* txtmgr = g3d->GetTextureManager();

  do
  {
    if ((step < 0) && ((size_t)-step > cur_idx))
      cur_idx = files->Length ()-1;
    else
      cur_idx += step;
    if ((size_t)cur_idx >= files->Length ()) cur_idx = 0;

    csRef<iDataBuffer> buf (vfs->ReadFile (files->Get (cur_idx), false));
    if (!buf) continue;

    ifile = imgloader->Load (buf, txtmgr->GetTextureFormat ());
  }
  while (!ifile.IsValid() && (cur_idx != startIdx));
  if (!ifile)
  {
	  picview_events->Exec("nmp.Show()");
	  return;
  }

  delete pic;
  txt = txtmgr->RegisterTexture (ifile, CS_TEXTURE_2D);
  pic = new csSimplePixmap (txt);
}

//---------------------------------------------------------------------------

// void PicView::ButtonFirst (unsigned long, intptr_t app, iAwsSource* /*source*/)
// {
//   PicView* picview = (PicView*)app;
//   picview->LoadNextImage (1, -1);
// }

// void PicView::ButtonPrev (unsigned long, intptr_t app, iAwsSource* /*source*/)
// {
//   PicView* picview = (PicView*)app;
//   picview->LoadNextImage (0, -1);
// }

// void PicView::ButtonNext (unsigned long, intptr_t app, iAwsSource* /*source*/)
// {
//   PicView* picview = (PicView*)app;
//   picview->LoadNextImage (0, 1);
// }

// void PicView::ButtonQuit (unsigned long, intptr_t /*app*/, iAwsSource* /*source*/)
// {
//   csRef<iEventQueue> q = CS_QUERY_REGISTRY(GetObjectRegistry(), iEventQueue);
//   if (q.IsValid()) q->GetEventOutlet()->Broadcast(csevQuit(GetObjectRegistry()));
// }

// void PicView::ButtonScale (unsigned long, intptr_t app, iAwsSource* /*source*/)
// {
//   PicView* picview = (PicView*)app;
//   picview->scale ^= true;
// }

/*-------------------------------------------------------------------------*
 * Main function
 *-------------------------------------------------------------------------*/
int main (int argc, char* argv[])
{
  return csApplicationRunner<PicView>::Run (argc, argv);
}
<commit_msg>Fixed an infinite loop bug in picview.<commit_after>/*
    Copyright (C) 2001 by Jorrit Tyberghein

    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 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#include "picview.h"

/** Event codes for the control bar's widgets. */
enum PICVIEW_EVENTS { PVE_FIRST, PVE_PREV, PVE_NEXT, PVE_QUIT, PVE_SCALE };

/** Callback for picture viewer events. */
struct onPicViewEvent : public iAws2ScriptEvent
{
private:
	/** Holds the instance of the picture viewer that we're responding to. */
	PicView *picview;

public:
	onPicViewEvent(PicView *_pv):picview(_pv) {}
	virtual ~onPicViewEvent() {};

	virtual void operator() (iAws2ScriptObject *info)
	{
		switch(info->GetIntArg(0))
		{
			case PVE_FIRST:
				picview->LoadNextImage (true, 1);
			break;

			case PVE_PREV:
				picview->LoadNextImage (false, -1);
			break;

			case PVE_NEXT:
				picview->LoadNextImage (false, 1);
			break;

			case PVE_QUIT:
				picview->Quit();
			break;

			case PVE_SCALE:
				picview->FlipScale();
				picview->LoadNextImage (false, 0);
			break;
		}
	}

};

//---------------------------------------------------------------------------

CS_IMPLEMENT_APPLICATION

//---------------------------------------------------------------------------

PicView::PicView ()
{
  SetApplicationName ("CrystalSpace.PicView");
  pic = 0;
  scale = false;
  cur_idx=0;
}

PicView::~PicView ()
{
}

void PicView::ProcessFrame ()
{
  iGraphics2D* g2d = g3d->GetDriver2D ();

  if (!g3d->BeginDraw (CSDRAW_2DGRAPHICS)) return;

  g2d->Clear(0);

  if (pic)
  {
    if (scale)
      pic->DrawScaled(g3d, 0, 0, g2d->GetWidth (), g2d->GetHeight ());
    else
      pic->Draw(g3d, 0, 0);
  }

  aws->Redraw ();
}

void PicView::FinishFrame ()
{
  g3d->FinishDraw ();
  g3d->Print (0);
}

bool PicView::OnKeyboard(iEvent& ev)
{
  csKeyEventType eventtype = csKeyEventHelper::GetEventType(&ev);
  if (eventtype == csKeyEventTypeDown)
  {
    utf32_char code = csKeyEventHelper::GetCookedCode(&ev);
    if (code == CSKEY_ESC || code == 'q')
    {
      picview_events->Exec("picView.Quit()");
    }
    else if (code == 'f')
    {
      picview_events->Exec("picView.First()");
    }
    else if (code == 'p')
    {
      picview_events->Exec("picView.Prev()");
    }
    else if (code == 'n')
    {
      picview_events->Exec("picView.Next()");
    }
    else if (code == 's')
    {
      picview_events->Exec("picView.Scale()");
    }
  }
  return false;
}

bool PicView::HandleEvent (iEvent &ev)
{
  csBaseEventHandler::HandleEvent(ev);
  if (aws) return aws->HandleEvent (ev);
  return false;
}

bool PicView::OnInitialize(int /*argc*/, char* /*argv*/ [])
{
  SetupConfigManager(GetObjectRegistry(), "/config/picview.cfg");

  if (!csInitializer::RequestPlugins(GetObjectRegistry(),
    CS_REQUEST_VFS,
    CS_REQUEST_OPENGL3D,
    CS_REQUEST_ENGINE,
    CS_REQUEST_FONTSERVER,
    CS_REQUEST_IMAGELOADER,
    CS_REQUEST_REPORTER,
    CS_REQUEST_REPORTERLISTENER,
    CS_REQUEST_PLUGIN("crystalspace.window.alternatemanager2", iAws2),
    CS_REQUEST_END))
    return ReportError("Failed to initialize plugins!");

  csBaseEventHandler::Initialize(GetObjectRegistry());

  if (!RegisterQueue(GetObjectRegistry(), csevAllEvents(GetObjectRegistry())))
    return ReportError("Failed to set up event handler!");

  return true;
}

void PicView::OnExit()
{
}

bool PicView::Application()
{
  if (!OpenApplication(GetObjectRegistry()))
    return ReportError("Error opening system!");

  g3d = CS_QUERY_REGISTRY(GetObjectRegistry(), iGraphics3D);
  if (!g3d) return ReportError("Failed to locate 3D renderer!");

  engine = CS_QUERY_REGISTRY(GetObjectRegistry(), iEngine);
  if (!engine) return ReportError("Failed to locate 3D engine!");

  kbd = CS_QUERY_REGISTRY(GetObjectRegistry(), iKeyboardDriver);
  if (!kbd) return ReportError("Failed to locate Keyboard Driver!");

  vfs = CS_QUERY_REGISTRY(GetObjectRegistry(), iVFS);
  if (!vfs) return ReportError("Failed to locate Virtual FileSystem!");

  imgloader = CS_QUERY_REGISTRY(GetObjectRegistry(), iImageIO);
  if (!imgloader) return ReportError("Failed to locate Image Loader!");

  aws = CS_QUERY_REGISTRY(GetObjectRegistry(), iAws2);
  if (!aws) return ReportError("Failed to locate Alternative Windowing System 2!");

  vfs->ChDir ("/tmp");
  files = vfs->FindFiles ("/this/*");
  cur_idx = 0;

  CreateGui();

  x = g3d->GetDriver2D ()->GetWidth ();
  y = g3d->GetDriver2D ()->GetHeight ();

  Run();

  return true;
}

void PicView::CreateGui ()
{
  aws->SetDrawTarget(g3d->GetDriver2D (), g3d);

  picview_events = aws->CreateScriptObject("picView", new onPicViewEvent(this));

  picview_events->SetProp("cmdFirst", PVE_FIRST);
  picview_events->SetProp("cmdPrev", PVE_PREV);
  picview_events->SetProp("cmdNext", PVE_NEXT);
  picview_events->SetProp("cmdQuit", PVE_QUIT);
  picview_events->SetProp("cmdScale", PVE_SCALE);

  // Load the normal skin.
  if (aws->Load ("/varia/picview.skin.js")==false)
    ReportError("Couldn't load skin definition file: '/varia/picview.skin.js'!");

  // Load the no files we recognize tooltip.
  if (files->IsEmpty())
  {
	  if (aws->Load ("/varia/picview.nopics.js")==false)
    	ReportError("Couldn't load skin definition file: '/varia/picview.nopics.js'!");
  }
  // Otherwise, queue up the first picture.
  else
  {
	 picview_events->Exec("picView.First()");
  }
}

void PicView::LoadNextImage (bool rewind, int step)
{
  if (rewind) cur_idx = 0; //files->Length ();
  size_t startIdx = cur_idx;
  csRef<iImage> ifile;
  iTextureManager* txtmgr = g3d->GetTextureManager();

  do
  {
    if ((step < 0) && ((size_t)-step > cur_idx))
      cur_idx = files->Length ()-1;
    else
      cur_idx += step;

    if ((size_t)cur_idx >= files->Length ()) cur_idx = 0;

    csRef<iDataBuffer> buf (vfs->ReadFile (files->Get (cur_idx), false));
    if (!buf) continue;

    ifile = imgloader->Load (buf, txtmgr->GetTextureFormat ());
  }  while (!ifile.IsValid() && (cur_idx != startIdx));

  if (!ifile)
  {
	  picview_events->Exec("nmp.Show()");
	  return;
  }

  delete pic;
  txt = txtmgr->RegisterTexture (ifile, CS_TEXTURE_2D);
  pic = new csSimplePixmap (txt);
}

//---------------------------------------------------------------------------

// void PicView::ButtonFirst (unsigned long, intptr_t app, iAwsSource* /*source*/)
// {
//   PicView* picview = (PicView*)app;
//   picview->LoadNextImage (1, -1);
// }

// void PicView::ButtonPrev (unsigned long, intptr_t app, iAwsSource* /*source*/)
// {
//   PicView* picview = (PicView*)app;
//   picview->LoadNextImage (0, -1);
// }

// void PicView::ButtonNext (unsigned long, intptr_t app, iAwsSource* /*source*/)
// {
//   PicView* picview = (PicView*)app;
//   picview->LoadNextImage (0, 1);
// }

// void PicView::ButtonQuit (unsigned long, intptr_t /*app*/, iAwsSource* /*source*/)
// {
//   csRef<iEventQueue> q = CS_QUERY_REGISTRY(GetObjectRegistry(), iEventQueue);
//   if (q.IsValid()) q->GetEventOutlet()->Broadcast(csevQuit(GetObjectRegistry()));
// }

// void PicView::ButtonScale (unsigned long, intptr_t app, iAwsSource* /*source*/)
// {
//   PicView* picview = (PicView*)app;
//   picview->scale ^= true;
// }

/*-------------------------------------------------------------------------*
 * Main function
 *-------------------------------------------------------------------------*/
int main (int argc, char* argv[])
{
  return csApplicationRunner<PicView>::Run (argc, argv);
}
<|endoftext|>


<commit_before>// socket.cpp
//
// --------------------------------------------------------------------------
// This file is part of the "sockpp" C++ socket library.
//
// Copyright (c) 2014-2017 Frank Pagliughi
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// 1. Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its
// contributors may be used to endorse or promote products derived from this
// software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// --------------------------------------------------------------------------

#include "sockpp/socket.h"
#include "sockpp/exception.h"
#include <algorithm>
#include <cstring>

// Used to explicitly ignore the returned value of a function call.
#define ignore_result(x) if (x) {}

using namespace std::chrono;

namespace sockpp {

/////////////////////////////////////////////////////////////////////////////
// Some platform-specific functions

#if !defined(_WIN32)
timeval to_timeval(const microseconds& dur)
{
	const seconds sec = duration_cast<seconds>(dur);

	timeval tv;
    tv.tv_sec  = sec.count();
    tv.tv_usec = duration_cast<microseconds>(dur - sec).count();
	return tv;
}
#endif

/////////////////////////////////////////////////////////////////////////////
//								socket
/////////////////////////////////////////////////////////////////////////////

int socket::get_last_error()
{
	#if defined(_WIN32)
		return ::WSAGetLastError();
	#else
		int err = errno;
		return err;
	#endif
}

// --------------------------------------------------------------------------

bool socket::close(socket_t h)
{
	return check_ret_bool(
		#if defined(_WIN32)
			::closesocket(h);
		#else
			::close(h)
		#endif
	);
}

// --------------------------------------------------------------------------

void socket::initialize()
{
	#if defined(_WIN32)
		WSADATA wsadata;
		::WSAStartup(MAKEWORD(2, 0), &wsadata);
	#else
		// Don't signal on socket write errors.
		::signal(SIGPIPE, SIG_IGN);
	#endif
}

// --------------------------------------------------------------------------

void socket::destroy()
{
	#if defined(_WIN32)
		::WSACleanup();
	#endif
}

// --------------------------------------------------------------------------

socket socket::create(int domain, int type, int protocol /*=0*/)
{
	socket sock(::socket(domain, type, protocol));
	if (!sock)
		sock.clear(get_last_error());
	return sock;
}

// --------------------------------------------------------------------------

socket socket::clone() const
{
	socket_t h = INVALID_SOCKET;
	#if defined(_WIN32)
		WSAPROTOCOL_INFO protInfo;
		if (::WSADuplicateSocket(handle_, ::GetCurrentProcessId(), &protInfo) == 0)
			h = ::WSASocket(AF_INET, SOCK_STREAM, 0, &protInfo, 0, WSA_FLAG_OVERLAPPED);
		// TODO: Set lastErr_ on failure
	#else
		h = ::dup(handle_);
	#endif

	return socket(h);
}

// --------------------------------------------------------------------------

std::tuple<socket, socket> socket::pair(int domain, int type, int protocol /*=0*/)
{
	socket sock0, sock1;

    #if !defined(_WIN32)
		int sv[2];
        int ret = ::socketpair(domain, type, protocol, sv);

        if (ret == 0) {
		    sock0.reset(sv[0]);
		    sock1.reset(sv[1]);
		}
		else {
		    int err = get_last_error();
		    sock0.clear(err);
		    sock1.clear(err);
		}
    #endif

    // TODO: Should we set an "unsupported" error on Windows?

	return std::make_tuple<socket, socket>(std::move(sock0), std::move(sock1));
}

// --------------------------------------------------------------------------

void socket::reset(socket_t h /*=INVALID_SOCKET*/)
{
	socket_t oh = handle_;
	handle_ = h;
	if (oh != INVALID_SOCKET)
		close(oh);
	clear();
}

// --------------------------------------------------------------------------
// Binds the socket to the specified address.

bool socket::bind(const sock_address& addr)
{
	return check_ret_bool(::bind(handle_, addr.sockaddr_ptr(), addr.size()));
}

// --------------------------------------------------------------------------
// Gets the local address to which the socket is bound.

sock_address_any socket::address() const
{
    auto addrStore = sockaddr_storage{};
	socklen_t len = sizeof(sockaddr_storage);

	if (!check_ret_bool(::getsockname(handle_,
				reinterpret_cast<sockaddr*>(&addrStore), &len)))
		return sock_address_any{};

    return sock_address_any(addrStore, len);
}

// --------------------------------------------------------------------------
// Gets the address of the remote peer, if this socket is connected.

sock_address_any socket::peer_address() const
{
    auto addrStore = sockaddr_storage{};
	socklen_t len = sizeof(sockaddr_storage);

	if (!check_ret_bool(::getpeername(handle_,
				reinterpret_cast<sockaddr*>(&addrStore), &len)))
		return sock_address_any{};

    return sock_address_any(addrStore, len);
}

// --------------------------------------------------------------------------

bool socket::get_option(int level, int optname, void* optval, socklen_t* optlen) const
{
	#if defined(_WIN32)
		int len = static_cast<int>(*optlen);
		return check_ret_bool(::getsockopt(handle_, level, optname,
										   static_cast<char*>(optval), &len));
		*optlen = static_cast<socklen_t>(len);
	#else
		return check_ret_bool(::getsockopt(handle_, level, optname, optval, optlen));
	#endif
}

// --------------------------------------------------------------------------

bool socket::set_option(int level, int optname, const void* optval, socklen_t optlen)
{
	#if defined(_WIN32)
		return check_ret_bool(::setsockopt(handle_, level, optname,
										   static_cast<const char*>(optval),
										   static_cast<int>(optlen)));
	#else
		return check_ret_bool(::setsockopt(handle_, level, optname, optval, optlen));
	#endif
}

// --------------------------------------------------------------------------
// Gets a description of the last error encountered.

std::string socket::error_str(int err)
{
	return sys_error::error_str(err);
}

// --------------------------------------------------------------------------
// Shuts down all or part of the connection.

bool socket::shutdown(int how /*=SHUT_RDWR*/)
{
	return check_ret_bool(::shutdown(handle_, how));
}

// --------------------------------------------------------------------------
// Closes the socket

bool socket::close()
{
	if (handle_ == INVALID_SOCKET)
		return true;

	socket_t h = release();
	return close(h);
}

/////////////////////////////////////////////////////////////////////////////
// End namespace sockpp
}

<commit_msg>socket::close() preserves last_error()<commit_after>// socket.cpp
//
// --------------------------------------------------------------------------
// This file is part of the "sockpp" C++ socket library.
//
// Copyright (c) 2014-2017 Frank Pagliughi
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// 1. Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its
// contributors may be used to endorse or promote products derived from this
// software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// --------------------------------------------------------------------------

#include "sockpp/socket.h"
#include "sockpp/exception.h"
#include <algorithm>
#include <cstring>

// Used to explicitly ignore the returned value of a function call.
#define ignore_result(x) if (x) {}

using namespace std::chrono;

namespace sockpp {

/////////////////////////////////////////////////////////////////////////////
// Some platform-specific functions

#if !defined(_WIN32)
timeval to_timeval(const microseconds& dur)
{
	const seconds sec = duration_cast<seconds>(dur);

	timeval tv;
    tv.tv_sec  = sec.count();
    tv.tv_usec = duration_cast<microseconds>(dur - sec).count();
	return tv;
}
#endif

/////////////////////////////////////////////////////////////////////////////
//								socket
/////////////////////////////////////////////////////////////////////////////

int socket::get_last_error()
{
	#if defined(_WIN32)
		return ::WSAGetLastError();
	#else
		int err = errno;
		return err;
	#endif
}

// --------------------------------------------------------------------------

bool socket::close(socket_t h)
{
    #if defined(_WIN32)
        return ::closesocket(h) >= 0;
    #else
        return ::close(h) >= 0;
    #endif
}

// --------------------------------------------------------------------------

void socket::initialize()
{
	#if defined(_WIN32)
		WSADATA wsadata;
		::WSAStartup(MAKEWORD(2, 0), &wsadata);
	#else
		// Don't signal on socket write errors.
		::signal(SIGPIPE, SIG_IGN);
	#endif
}

// --------------------------------------------------------------------------

void socket::destroy()
{
	#if defined(_WIN32)
		::WSACleanup();
	#endif
}

// --------------------------------------------------------------------------

socket socket::create(int domain, int type, int protocol /*=0*/)
{
	socket sock(::socket(domain, type, protocol));
	if (!sock)
		sock.clear(get_last_error());
	return sock;
}

// --------------------------------------------------------------------------

socket socket::clone() const
{
	socket_t h = INVALID_SOCKET;
	#if defined(_WIN32)
		WSAPROTOCOL_INFO protInfo;
		if (::WSADuplicateSocket(handle_, ::GetCurrentProcessId(), &protInfo) == 0)
			h = ::WSASocket(AF_INET, SOCK_STREAM, 0, &protInfo, 0, WSA_FLAG_OVERLAPPED);
		// TODO: Set lastErr_ on failure
	#else
		h = ::dup(handle_);
	#endif

	return socket(h);
}

// --------------------------------------------------------------------------

std::tuple<socket, socket> socket::pair(int domain, int type, int protocol /*=0*/)
{
	socket sock0, sock1;

    #if !defined(_WIN32)
		int sv[2];
        int ret = ::socketpair(domain, type, protocol, sv);

        if (ret == 0) {
		    sock0.reset(sv[0]);
		    sock1.reset(sv[1]);
		}
		else {
		    int err = get_last_error();
		    sock0.clear(err);
		    sock1.clear(err);
		}
    #endif

    // TODO: Should we set an "unsupported" error on Windows?

	return std::make_tuple<socket, socket>(std::move(sock0), std::move(sock1));
}

// --------------------------------------------------------------------------

void socket::reset(socket_t h /*=INVALID_SOCKET*/)
{
	socket_t oh = handle_;
	handle_ = h;
	if (oh != INVALID_SOCKET)
		close(oh);
	clear();
}

// --------------------------------------------------------------------------
// Binds the socket to the specified address.

bool socket::bind(const sock_address& addr)
{
	return check_ret_bool(::bind(handle_, addr.sockaddr_ptr(), addr.size()));
}

// --------------------------------------------------------------------------
// Gets the local address to which the socket is bound.

sock_address_any socket::address() const
{
    auto addrStore = sockaddr_storage{};
	socklen_t len = sizeof(sockaddr_storage);

	if (!check_ret_bool(::getsockname(handle_,
				reinterpret_cast<sockaddr*>(&addrStore), &len)))
		return sock_address_any{};

    return sock_address_any(addrStore, len);
}

// --------------------------------------------------------------------------
// Gets the address of the remote peer, if this socket is connected.

sock_address_any socket::peer_address() const
{
    auto addrStore = sockaddr_storage{};
	socklen_t len = sizeof(sockaddr_storage);

	if (!check_ret_bool(::getpeername(handle_,
				reinterpret_cast<sockaddr*>(&addrStore), &len)))
		return sock_address_any{};

    return sock_address_any(addrStore, len);
}

// --------------------------------------------------------------------------

bool socket::get_option(int level, int optname, void* optval, socklen_t* optlen) const
{
	#if defined(_WIN32)
		int len = static_cast<int>(*optlen);
		return check_ret_bool(::getsockopt(handle_, level, optname,
										   static_cast<char*>(optval), &len));
		*optlen = static_cast<socklen_t>(len);
	#else
		return check_ret_bool(::getsockopt(handle_, level, optname, optval, optlen));
	#endif
}

// --------------------------------------------------------------------------

bool socket::set_option(int level, int optname, const void* optval, socklen_t optlen)
{
	#if defined(_WIN32)
		return check_ret_bool(::setsockopt(handle_, level, optname,
										   static_cast<const char*>(optval),
										   static_cast<int>(optlen)));
	#else
		return check_ret_bool(::setsockopt(handle_, level, optname, optval, optlen));
	#endif
}

// --------------------------------------------------------------------------
// Gets a description of the last error encountered.

std::string socket::error_str(int err)
{
	return sys_error::error_str(err);
}

// --------------------------------------------------------------------------
// Shuts down all or part of the connection.

bool socket::shutdown(int how /*=SHUT_RDWR*/)
{
	return check_ret_bool(::shutdown(handle_, how));
}

// --------------------------------------------------------------------------
// Closes the socket and updates lastErr_

bool socket::close()
{
	if (handle_ == INVALID_SOCKET)
		return true;

	socket_t h = release();
    if (close(h))
        return true;

    if (lastErr_ == 0)          // Preserve any pre-existing error
        set_last_error();
    return false;
}

/////////////////////////////////////////////////////////////////////////////
// End namespace sockpp
}

<|endoftext|>