//==================================================================================================
// S t a n d a r d                                                                        Interface
// C o n v e r s i o n
//                                                                                By Bruno Bachelet
//==================================================================================================
// Copyright (c) 1999-2016
// Bruno Bachelet - bruno@nawouak.net - http://www.nawouak.net
//
// This file is part of the B++ Library. 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 (http://www.gnu.org).

/*DESCRIPTION*/
/* This module provides facilities to guaranty the portability of the conversion between the
   standard types commonly used. */

// File Name //-------------------------------------------------------------------------------------
#line __LINE__ "standard/conversion.hpp"

// Guardian //--------------------------------------------------------------------------------------
#ifndef guStandardConversion
#define guStandardConversion

// Headers //---------------------------------------------------------------------------------------
#include <bpp/standard/error.hpp> /*INCLUDE*/

namespace bpp {

// Importation/Exportation //-----------------------------------------------------------------------
#ifdef STANDARD_DLL
 #define dll_export DLL_EXPORT
#else
 #define dll_export DLL_IMPORT
#endif

// Namespaces //------------------------------------------------------------------------------------
#define public_area  standardConversion
#define private_area standardConversion_private

namespace public_area  { /*NAMESPACE*/ using namespace standardError; }
namespace private_area { using namespace public_area; }

extern_module_name;

// Initialization //--------------------------------------------------------------------------------
#define iniStandardConversion
has_initializer;

// Macrocommands //---------------------------------------------------------------------------------

// Types & Classes //-------------------------------------------------------------------------------
namespace public_area  {}
namespace private_area {}

// Functions Interface //---------------------------------------------------------------------------
namespace public_area {
 inline tyBoolean boolean(tyByte);
 inline tyBoolean boolean(tyCardinal);
 inline tyBoolean boolean(tyCharacter);
 inline tyBoolean boolean(tyInteger);
 inline tyBoolean boolean(tyReal);

 inline tyByte byte(tyBoolean);
 inline tyByte byte(tyCardinal);
 inline tyByte byte(tyCharacter);
 inline tyByte byte(tyInteger);
 inline tyByte byte(tyReal);

 inline tyCardinal cardinal(tyBoolean);
 inline tyCardinal cardinal(tyByte);
 inline tyCardinal cardinal(tyCharacter);
 inline tyCardinal cardinal(tyInteger);
 inline tyCardinal cardinal(tyReal);

 inline tyCharacter character(tyBoolean);
 inline tyCharacter character(tyByte);
 inline tyCharacter character(tyCardinal);
 inline tyCharacter character(tyInteger);
 inline tyCharacter character(tyReal);

 inline tyInteger integer(tyBoolean);
 inline tyInteger integer(tyByte);
 inline tyInteger integer(tyCardinal);
 inline tyInteger integer(tyCharacter);
 inline tyInteger integer(tyReal);

 inline tyReal real(tyBoolean);
 inline tyReal real(tyByte);
 inline tyReal real(tyCardinal);
 inline tyReal real(tyCharacter);
 inline tyReal real(tyInteger);
}

namespace private_area { testing_mode ( function void test(void); ) }

// Errors //----------------------------------------------------------------------------------------
namespace public_area {
 /*ERROR*/ extern_error erByteConversion; /* The conversion into a byte is impossible. */
 /*ERROR*/ extern_error erCardinalConversion; /* The conversion into a cardinal is impossible. */
 /*ERROR*/ extern_error erIntegerConversion; /* The conversion into an integer is impossible. */
}

// Constants & Variables //-------------------------------------------------------------------------
/*CONSTANT*/ /* The sign of the modulo operator applied to a negative number. */
extern_static_constant(public,tyInteger,goNegativeModulo,negativeModulo);
/*CONSTANT*/
/* Is 0 if the default truncating of a negative real is a floor truncating.
   Is -1 if it is a ceiling truncating. */
extern_static_constant(public,tyInteger,goNegativeTruncating,negativeTruncating);

// Functions Inline //------------------------------------------------------------------------------
namespace public_area {
 //----------------------------------------------------------------------------------Byte To Boolean
 /*FUNCTION*/ /* Converts a byte into a boolean. */
 inline tyBoolean boolean(tyByte agByte) { return (agByte!=0); }
 //------------------------------------------------------------------------------Cardinal To Boolean
 /*FUNCTION*/ /* Converts a cardinal into a boolean. */
 inline tyBoolean boolean(tyCardinal agCardinal) { return (agCardinal!=0); }
 //-----------------------------------------------------------------------------Character To Boolean
 /*FUNCTION*/ /* Converts a character into a boolean. */
 inline tyBoolean boolean(tyCharacter agCharacter)
 { return (agCharacter=='y' or agCharacter=='Y'); }
 //-------------------------------------------------------------------------------Integer To Boolean
 /*FUNCTION*/ /* Converts an integer into a boolean. */
 inline tyBoolean boolean(tyInteger agInteger) { return (agInteger!=0); }
 //----------------------------------------------------------------------------------Real To Boolean
 /*FUNCTION*/ /* Converts a real into a boolean. */
 inline tyBoolean boolean(tyReal agReal) { return (agReal!=0); }

 //----------------------------------------------------------------------------------Boolean To Byte
 /*FUNCTION*/ /* Converts a boolean into a byte. */
 inline tyByte byte(tyBoolean agBoolean) { if (agBoolean) return (1); return (0); }
 //---------------------------------------------------------------------------------Cardinal To Byte
 /*FUNCTION*/ /* Converts a cardinal into a byte. */
 inline tyByte byte(tyCardinal agCardinal) {
  if (agCardinal>tyCardinal(byteMax())) send_inline_error(erByteConversion,"byte");
  return (tyByte(agCardinal));
 }
 //--------------------------------------------------------------------------------Character To Byte
 /*FUNCTION*/ /* Converts a character into a byte. */
 inline tyByte byte(tyCharacter agCharacter) { return (tyByte(agCharacter)); }
 //----------------------------------------------------------------------------------Integer To Byte
 /*FUNCTION*/ /* Converts an integer into a byte. */
 inline tyByte byte(tyInteger agInteger) {
  if (agInteger<0 or agInteger>byteMax()) send_inline_error(erByteConversion,"byte");
  return (tyByte(agInteger));
 }
 //-------------------------------------------------------------------------------------Real To Byte
 /*FUNCTION*/ /* Converts a real into a byte. */
 inline tyByte byte(tyReal agReal) {
  if (agReal<0 or (agReal-1.0)>=byteMax()) send_inline_error(erByteConversion,"byte");
  return (tyByte(agReal));
 }

 //------------------------------------------------------------------------------Boolean To Cardinal
 /*FUNCTION*/ /* Converts a boolean into a cardinal. */
 inline tyCardinal cardinal(tyBoolean agBoolean) { if (agBoolean) return (1); return (0); }
 //---------------------------------------------------------------------------------Byte To Cardinal
 /*FUNCTION*/ /* Converts a byte into a cardinal. */
 inline tyCardinal cardinal(tyByte agByte) { return (tyCardinal(agByte)); }
 //----------------------------------------------------------------------------Character To Cardinal
 /*FUNCTION*/ /* Converts a character into a cardinal. */
 inline tyCardinal cardinal(tyCharacter agCharacter) { return (cardinal(byte(agCharacter))); }
 //------------------------------------------------------------------------------Integer To Cardinal
 /*FUNCTION*/ /* Converts an integer into a cardinal. */
 inline tyCardinal cardinal(tyInteger agInteger) {
  if (cardinalSize()<integerSize() and agInteger>tyInteger(cardinalMax()))
   send_inline_error(erCardinalConversion,"cardinal");

  if (agInteger<0) send_inline_error(erCardinalConversion,"cardinal");
  return (tyCardinal(agInteger));
 }
 //---------------------------------------------------------------------------------Real To Cardinal
 /*FUNCTION*/ /* Converts a real into a cardinal. */
 inline tyCardinal cardinal(tyReal agReal) {
  if (agReal<0 or (agReal-1.0)>=cardinalMax()) send_inline_error(erCardinalConversion,"cardinal");
  return (tyCardinal(agReal));
 }

 //-----------------------------------------------------------------------------Boolean To Character
 /*FUNCTION*/ /* Converts a boolean into a character. */
 inline tyCharacter character(tyBoolean agBoolean) { if (agBoolean) return ('Y'); return ('N'); }
 //--------------------------------------------------------------------------------Byte To Character
 /*FUNCTION*/ /* Converts a byte into a character. */
 inline tyCharacter character(tyByte agByte) { return (tyCharacter(agByte)); }
 //----------------------------------------------------------------------------Cardinal To Character
 /*FUNCTION*/ /* Converts a cardinal into a character. */
 inline tyCharacter character(tyCardinal agCardinal) { return (character(byte(agCardinal))); }
 //-----------------------------------------------------------------------------Integer To Character
 /*FUNCTION*/ /* Converts an integer into a character. */
 inline tyCharacter character(tyInteger agInteger) { return (character(byte(agInteger))); }
 //--------------------------------------------------------------------------------Real To Character
 /*FUNCTION*/ /* Converts a real into a character. */
 inline tyCharacter character(tyReal agReal) { return (character(byte(agReal))); }

 //-------------------------------------------------------------------------------Boolean To Integer
 /*FUNCTION*/ /* Converts a real into an integer. */
 inline tyInteger integer(tyBoolean agBoolean) { if (agBoolean) return (1); return (0); }
 //----------------------------------------------------------------------------------Byte To Integer
 /*FUNCTION*/ /* Converts a byte into an integer. */
 inline tyInteger integer(tyByte agByte) { return (tyInteger(agByte)); }
 //------------------------------------------------------------------------------Cardinal To Integer
 /*FUNCTION*/ /* Converts a cardinal into an integer. */
 inline tyInteger integer(tyCardinal agCardinal) {
  if (cardinalSize()>=integerSize() and agCardinal>tyCardinal(integerMax()))
   send_inline_error(erIntegerConversion,"integer");

  return (tyInteger(agCardinal));
 }
 //-----------------------------------------------------------------------------Character To Integer
 /*FUNCTION*/ /* Converts a character into an integer. */
 inline tyInteger integer(tyCharacter agCharacter) { return (integer(byte(agCharacter))); }
 //----------------------------------------------------------------------------------Real To Integer
 /*FUNCTION*/ /* Converts a real into an integer. */
 inline tyInteger integer(tyReal agReal) {
  if (agReal<integerMin() or (agReal-1.0)>=integerMax())
   send_inline_error(erIntegerConversion,"integer");

  if (agReal>=0) return (tyInteger(agReal));
  if (tyInteger(agReal)>agReal) return (tyInteger(agReal)-1l);
  return (tyInteger(agReal));
 }

 //----------------------------------------------------------------------------------Boolean To Real
 /*FUNCTION*/ /* Converts a boolean into a real. */
 inline tyReal real(tyBoolean agBoolean) { if (agBoolean) return (1); return (0); }
 //-------------------------------------------------------------------------------------Byte To Real
 /*FUNCTION*/ /* Converts a byte into a real. */
 inline tyReal real(tyByte agByte) { return (tyReal(agByte)); }
 //---------------------------------------------------------------------------------Cardinal To Real
 /*FUNCTION*/ /* Converts a cardinal into a real. */
 inline tyReal real(tyCardinal agCardinal) { return (tyReal(agCardinal)); }
 //--------------------------------------------------------------------------------Character To Real
 /*FUNCTION*/ /* Converts a character into a real. */
 inline tyReal real(tyCharacter agCharacter) { return (tyReal(byte(agCharacter))); }
 //----------------------------------------------------------------------------------Integer To Real
 /*FUNCTION*/ /* Converts an integer into a real. */
 inline tyReal real(tyInteger agInteger) { return (tyReal(agInteger)); }
}

namespace private_area {}

// X X X  Inline //---------------------------------------------------------------------------------
namespace {}

// End //-------------------------------------------------------------------------------------------
}
#undef dll_export
#undef public_area
#undef private_area
#endif
 
//==================================================================================================
// S t a n d a r d                                                                   Implementation
// C o n v e r s i o n
//                                                                                By Bruno Bachelet
//==================================================================================================
// Copyright (c) 1999-2016
// Bruno Bachelet - bruno@nawouak.net - http://www.nawouak.net
//
// This file is part of the B++ Library. 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 (http://www.gnu.org).

// File Name //-------------------------------------------------------------------------------------
#line __LINE__ "standard/conversion.cpp"

// DLL Belonging //---------------------------------------------------------------------------------
#define STANDARD_DLL

// Headers //---------------------------------------------------------------------------------------
#include <bpp/standard/conversion.hpp> /*INTERFACE*/

namespace bpp {

// Namespaces //------------------------------------------------------------------------------------
#define public_area  standardConversion
#define private_area standardConversion_private
#define dll_export   DLL_EXPORT

namespace public_area  {}
namespace private_area {}

static_module_name("Standard/Conversion");

// Initialization //--------------------------------------------------------------------------------
#undef iniStandardConversion
static_constant(private_area::clInitializer,goInitializer);

// Errors //----------------------------------------------------------------------------------------
namespace public_area {
 static_error erByteConversion;
 static_error erCardinalConversion;
 static_error erIntegerConversion;
}

// Constants & Variables //-------------------------------------------------------------------------
static_constant(tyInteger,goNegativeModulo);
static_constant(tyInteger,goNegativeTruncating);

// Static Members //--------------------------------------------------------------------------------
namespace public_area  {}
namespace private_area {}

// Functions Implementation //----------------------------------------------------------------------
namespace public_area  {}
namespace private_area {}

// I n i t i a l i z e r  Implementation //---------------------------------------------------------
namespace private_area {
 //--------------------------------------------------------------------------------------------Start
 property void clInitializer::start(void) {
  if (atCounter++ == 0) {
   try {
    #include <bpp/modules.hpp> /*NEED*/
    registerStop(this);
    environment::informInitialization(goModuleName);

    erByteConversion.create("The conversion into a byte is impossible.");
    erCardinalConversion.create("The conversion into a cardinal is impossible.");
    erIntegerConversion.create("The conversion into an integer is impossible.");

    goNegativeModulo     = -1l%2l;
    goNegativeTruncating = -1l-tyInteger(tyReal(-0.5));
   }

   initializer_catch;
  }
 }
 //---------------------------------------------------------------------------------------------Stop
 property void clInitializer::stop(void) { environment::informTermination(goModuleName); }
}

// End //-------------------------------------------------------------------------------------------
}