<commit_before>/* |===================================|
 * | Bibliothèque de communication i2c |
 * |===================================|
 */
/**
 *    \file i2cCommunication.cpp
 *    \brief Bibliothèque de communication i2c
 *	  \author Nicolas SOBCZAK
 *    \date Octobre 2016
*/

/* ======================================================================================================
 *      Include
 * ======================================================================================================
 */
#include <Wire.h>
#include "Arduino.h"
#include "i2cCommunication.h"

/* ======================================================================================================
 *      Fonctions
 * ======================================================================================================
 */
//_____________________________________________________________________________________________
//_____________________________________________________________________________________________
// LED : ordre 0 ou 1

/**
 * \fn void ledOff(int pin)
 * \brief fonction qui eteint une LED
 * \param int pin de la LED
 */
void ledOff(int pin)
{
  pinMode(pin, OUTPUT);
  digitalWrite(pin, LOW);
}

/**
 * \fn void ledOn(int pin)
 * \brief fonction qui allume une LED
 * \param int pin de la LED
 */
void ledOn(int pin)
{
  pinMode(pin, OUTPUT);
  digitalWrite(pin, HIGH);
}

/**
 * \fn void ledControl(int pin, int order)
 * \brief fonction qui eteint une LED
 * \param int pin de la LED,
 * \param int order =1 pour allumer ou =0 pour eteindre
 */
void ledControl(int pin, int order)
{
  if (order==0)
  {
    ledOff(pin);
  }
  if (order==1)
  {
    ledOn(pin);
  }
}

//_____________________________________________________________________________________________
/**
 * \fn void byteReceived(byte octet)
 * \brief fonction qui affiche l'octet reçu
 * \param byte octet
 */
void byteReceived(byte octet)
{
  Serial.print("ReceivedByte: ");
  Serial.println(octet);   // Afficher la valeur numérique
}

/**
 * \fn void orderNumber(uint8_t order)
 * \brief fonction qui execute l'ordre dont le numéro est entrée en parametre
 * \param uint8_t order = numero de l'ordre a executer
 */
void orderNumber(uint8_t order)
{
  Serial.print("ReceivedOrder: ");
  Serial.println(order);   // Afficher la valeur numérique
  switch (order)
  {
    case 0:
    {
      int pin = 12;
      ledControl(pin, order);              // Allume ou éteint la led
      break;
    }
    case 1:
    {
      int pin = 12;
      ledControl(pin, order);              // Allume ou éteint la led
      break;
    }
    default:
    {
      Serial.println("Ordre non renseigne");
      // if nothing else matches, do the default
      // default is optional
    }
    break;
  }
}

/**
 * \fn void changeData(byte data[])
 * \brief Fonction qui change la variable du tableau correspondace envoyée
 * \param byte data[]
 */
void changeData(byte data[], int correspondance[], int numberOfVariables)
{
  byte value[2];    // tableau pour stocker la variable

  //Changement de l'indice du tableau corerspondance
  int variable = data[0] + 1;
  if (variable == numberOfVariables)
  {
    variable = 0;
  }
  intTo2Bytes(value, correspondance[variable]);

  // Write the value of variables to the array
  data[0] = variable;
  data[1] = value[0];
  data[2] = value[1];
}

//_____________________________________________________________________________________________
// Reception

/**
 * \fn void receiveEvent(int howMany)
 * \brief fonction qui est exécutée lorsque des données sont envoyées par le Maître. Cette fonction est enregistrée comme un événement ("event" en anglais), voir la fonction setup()
 * \param int howMany
 */
void receiveEvent(int howMany)
{
  while(1 < Wire.available()) // Lire tous les octets sauf le dernier => utile si on a écrit qqch devant le numéro de l'ordre mais il vaut mieux ne pas le faire pour éviter les pb
  {
    char c = Wire.read();     // lecture de l'octet/byte comme caractère
    Serial.print(c);          // afficher le caractère
  }
  byte x = Wire.read();        // lecture de l'octet/byte ignoré comme un entier
  orderNumber(x);			  // lecture de l'ordre à executer
}

/**
 * \fn void i2creceive(int adresse)
 * \brief fonction de lecture de données reçues via l'i2c
 * \param int adresse sur laquelle recevoir les donnees
 */
void i2creceive(int adresse)
{
  Wire.begin(adresse);          // Joindre le Bus I2C avec adresse
  Wire.onReceive(receiveEvent); // enregistrer l'événement (lorsqu'une demande arrive)
  Serial.begin(9600);           // Démarrer une communication série
}

//_____________________________________________________________________________________________
// Envoi
/**
 * \fn void i2csend(uint8_t order, int adresse)
 * \brief fonction d'envoi d'1 octet via l'i2c
 * \param uint8_t order numero de l'ordre a envoyer,
 * \param int adresse sur laquelle envoyer les donnees
 */
void i2csend(uint8_t order, int adresse)
{
  Wire.begin(); 					// joindre le bus i2c (adresse est optionnelle pour un maître)
  Wire.beginTransmission(adresse);  // Commencer transmission vers l'esclave  #4
  //Wire.write("order: ");        	// Envoi de 5 octets (5 bytes)
  Wire.write(order);             	// envoi d'un byte/octet (valeur numérique)
  Serial.print("Envoi via i2c de : ");
  Serial.print(order);
  Serial.print(" a l'adresse : ");
  Serial.println(adresse);
  Wire.endTransmission();    		// fin transmission
}

/**
 * \fn void i2csend3bytes(uint8_t byte1, uint8_t byte2, uint8_t byte3, int adresse)
 * \brief fonction d'envoi de 3 octets via l'i2c avec initialisation de l'I2C
 * \param 3 uint8_t byte1, 2 et 3: octets a envoyer,
 * \param int adresse sur laquelle envoyer les donnees
 */
void i2csend3bytes(uint8_t byte1, uint8_t byte2, uint8_t byte3, int adresse)
{
  Wire.begin(); 					// joindre le bus i2c (adresse est optionnelle pour un maître)
  Wire.beginTransmission(adresse);  // Commencer transmission vers l'esclave  #4
  Wire.write(byte1);             	// envoi d'un byte/octet (valeur numérique)
  Wire.write(byte2);
  Wire.write(byte3);
  Serial.print("Envoi via i2c de : ");
  Serial.print(byte1);
  Serial.print(", ");
  Serial.print(byte2);
  Serial.print(" et ");
  Serial.print(byte3);
  Serial.print(" a l'adresse ");
  Serial.println(adresse);
  Wire.endTransmission();    		// fin transmission
}

//_____________________________________________________________________________________________
// Request
/**
 * \fn void i2crequest(int adresse, int nbBytes, int variable)
 * \brief fonction qui demande l'envoi d'une certaine variable à un esclave
 * \param uint8_t order numero de l'ordre a envoyer,
 * \param int adresse sur laquelle envoyer les donnees
 * \param int variable à envoyer
 */
byte* i2crequest(int adresse, int nbBytes, int variable, int numberOfVariables)
{
	byte* dataI2C = new byte[nbBytes];

	do
	{
		// request 3 bytes from slave device on adress adresse
		Wire.requestFrom(adresse, nbBytes);

		while (Wire.available())         //check if data is available
	  	{
		    for(byte i = 0; i < nbBytes; i++)
		    {
		      dataI2C[i] = Wire.read();       // it assigne the data to the array
		    }
	  	}

	  	delay(100);

	} while ((dataI2C[0] != variable) && (dataI2C[0] < numberOfVariables - 1));

	return dataI2C;
}

int *multiplierParDeux(int a, int b){
    int *array= new int[2];
    array[0] = a*2;
    array[1] = b*2;
    return array;
}

//_____________________________________________________________________________________________
// Conversion
/**
 * \fn byte getLowByte(int n)
 * \brief fonction qui convertit un entier en 2 bytes - low ici
 * \param 1 tableau de bytes
 */
byte getLowByte(int n)
{
  byte result;

  result = n%256;
  result = byte(result);

  return result;
}

/**
 * \fn byte getHighByte(int n)
 * \brief fonction qui convertit un entier en 2 bytes - high ici
 * \param 1 tableau de byte
 */
byte getHighByte(int n)
{
  byte result;

  result = n/256;
  result = byte(result);

  return result;
}

/**
 * \fn void intTo2Bytes(byte bytesTab[], int n)
 * \brief fonction qui affiche les 2 bytes d'un nombre entier convertit en binaire
 * \param 1 tableau de byte
 * \param 1 entier : nombre à convertir
 */
void intTo2Bytes(byte bytesTab[], int n)
{
  Serial.println("high byte.low byte : ");

  bytesTab[0] = getHighByte(n);
  bytesTab[1] = getLowByte(n);
  Serial.print(bytesTab[0], HEX);
  Serial.print(".");
  Serial.println(bytesTab[1], HEX);
}

/**
 * \fn int recoverIntFrom2Bytes(byte bytesTab[])
 * \brief fonction qui affiche un entier ayant ete convertit en 2 bytes binaire
 * \param 1 tableau de byte
 * \param 1 entier : nombre à convertir
 */
int recoverIntFrom2Bytes(byte bytesTab[])
{
  int result;

  result = bytesTab[0]*256;
  result += bytesTab[1];

  return result;
}

//_____________________________________________________________________________________________
//_____________________________________________________________________________________________

<commit_msg>Update i2cCommunication.cpp<commit_after>/* |===================================|
 * | Bibliothèque de communication i2c |
 * |===================================|
 */
/**
 *    \file i2cCommunication.cpp
 *    \brief Bibliothèque de communication i2c
 *	  \author Nicolas SOBCZAK
 *    \date Octobre 2016
*/

/* ======================================================================================================
 *      Include
 * ======================================================================================================
 */
#include <Wire.h>
#include "Arduino.h"
#include "i2cCommunication.h"

/* ======================================================================================================
 *      Fonctions
 * ======================================================================================================
 */
//_____________________________________________________________________________________________
//_____________________________________________________________________________________________
// LED : ordre 0 ou 1

/**
 * \fn void ledOff(int pin)
 * \brief fonction qui eteint une LED
 * \param int pin de la LED
 */
void ledOff(int pin)
{
  pinMode(pin, OUTPUT);
  digitalWrite(pin, LOW);
}

/**
 * \fn void ledOn(int pin)
 * \brief fonction qui allume une LED
 * \param int pin de la LED
 */
void ledOn(int pin)
{
  pinMode(pin, OUTPUT);
  digitalWrite(pin, HIGH);
}

/**
 * \fn void ledControl(int pin, int order)
 * \brief fonction qui eteint une LED
 * \param int pin de la LED,
 * \param int order =1 pour allumer ou =0 pour eteindre
 */
void ledControl(int pin, int order)
{
  if (order==0)
  {
    ledOff(pin);
  }
  if (order==1)
  {
    ledOn(pin);
  }
}

//_____________________________________________________________________________________________
/**
 * \fn void byteReceived(byte octet)
 * \brief fonction qui affiche l'octet reçu
 * \param byte octet
 */
void byteReceived(byte octet)
{
  Serial.print("ReceivedByte: ");
  Serial.println(octet);   // Afficher la valeur numérique
}

/**
 * \fn void orderNumber(uint8_t order)
 * \brief fonction qui execute l'ordre dont le numéro est entrée en parametre
 * \param uint8_t order = numero de l'ordre a executer
 */
void orderNumber(uint8_t order)
{
  Serial.print("ReceivedOrder: ");
  Serial.println(order);   // Afficher la valeur numérique
  switch (order)
  {
    case 0:
    {
      int pin = 12;
      ledControl(pin, order);              // Allume ou éteint la led
      break;
    }
    case 1:
    {
      int pin = 12;
      ledControl(pin, order);              // Allume ou éteint la led
      break;
    }
    default:
    {
      Serial.println("Ordre non renseigne");
      // if nothing else matches, do the default
      // default is optional
    }
    break;
  }
}

/**
 * \fn void changeData(byte data[])
 * \brief Fonction qui change la variable du tableau correspondace envoyée
 * \param byte data[]
 */
void changeData(byte data[], int correspondance[], int numberOfVariables)
{
  byte value[2];    // tableau pour stocker la variable

  //Changement de l'indice du tableau corerspondance
  int variable = data[0] + 1;
  if (variable == numberOfVariables)
  {
    variable = 0;
  }
  intTo2Bytes(value, correspondance[variable]);

  // Write the value of variables to the array
  data[0] = variable;
  data[1] = value[0];
  data[2] = value[1];
}

//_____________________________________________________________________________________________
// Reception

/**
 * \fn void receiveEvent(int howMany)
 * \brief fonction qui est exécutée lorsque des données sont envoyées par le Maître. Cette fonction est enregistrée comme un événement ("event" en anglais), voir la fonction setup()
 * \param int howMany
 */
void receiveEvent(int howMany)
{
  while(1 < Wire.available()) // Lire tous les octets sauf le dernier => utile si on a écrit qqch devant le numéro de l'ordre mais il vaut mieux ne pas le faire pour éviter les pb
  {
    char c = Wire.read();     // lecture de l'octet/byte comme caractère
    Serial.print(c);          // afficher le caractère
  }
  byte x = Wire.read();        // lecture de l'octet/byte ignoré comme un entier
  orderNumber(x);			  // lecture de l'ordre à executer
}

/**
 * \fn void i2creceive(int adresse)
 * \brief fonction de lecture de données reçues via l'i2c
 * \param int adresse sur laquelle recevoir les donnees
 */
void i2creceive(int adresse)
{
  Wire.begin(adresse);          // Joindre le Bus I2C avec adresse
  Wire.onReceive(receiveEvent); // enregistrer l'événement (lorsqu'une demande arrive)
  Serial.begin(9600);           // Démarrer une communication série
}

//_____________________________________________________________________________________________
// Envoi
/**
 * \fn void i2csend(uint8_t order, int adresse)
 * \brief fonction d'envoi d'1 octet via l'i2c
 * \param uint8_t order numero de l'ordre a envoyer,
 * \param int adresse sur laquelle envoyer les donnees
 */
void i2csend(uint8_t order, int adresse)
{
  Wire.begin(); 					// joindre le bus i2c (adresse est optionnelle pour un maître)
  Wire.beginTransmission(adresse);  // Commencer transmission vers l'esclave  #4
  //Wire.write("order: ");        	// Envoi de 5 octets (5 bytes)
  Wire.write(order);             	// envoi d'un byte/octet (valeur numérique)
  Serial.print("Envoi via i2c de : ");
  Serial.print(order);
  Serial.print(" a l'adresse : ");
  Serial.println(adresse);
  Wire.endTransmission();    		// fin transmission
}

/**
 * \fn void i2csend3bytes(uint8_t byte1, uint8_t byte2, uint8_t byte3, int adresse)
 * \brief fonction d'envoi de 3 octets via l'i2c avec initialisation de l'I2C
 * \param 3 uint8_t byte1, 2 et 3: octets a envoyer,
 * \param int adresse sur laquelle envoyer les donnees
 */
void i2csend3bytes(uint8_t byte1, uint8_t byte2, uint8_t byte3, int adresse)
{
  Wire.begin(); 					// joindre le bus i2c (adresse est optionnelle pour un maître)
  Wire.beginTransmission(adresse);  // Commencer transmission vers l'esclave  #4
  Wire.write(byte1);             	// envoi d'un byte/octet (valeur numérique)
  Wire.write(byte2);
  Wire.write(byte3);
  Serial.print("Envoi via i2c de : ");
  Serial.print(byte1);
  Serial.print(", ");
  Serial.print(byte2);
  Serial.print(" et ");
  Serial.print(byte3);
  Serial.print(" a l'adresse ");
  Serial.println(adresse);
  Wire.endTransmission();    		// fin transmission
}

//_____________________________________________________________________________________________
// Request
/**
 * \fn void i2crequest(int adresse, int nbBytes, int variable)
 * \brief fonction qui demande l'envoi d'une certaine variable à un esclave
 * \param uint8_t order numero de l'ordre a envoyer,
 * \param int adresse sur laquelle envoyer les donnees
 * \param int variable à envoyer
 */
byte* i2crequest(int adresse, int nbBytes, int variable, int numberOfVariables)
{
	byte* dataI2C = new byte[nbBytes];

	do
	{
		// request 3 bytes from slave device on adress adresse
		Wire.requestFrom(adresse, nbBytes);

		while (Wire.available())         //check if data is available
	  	{
		    for(byte i = 0; i < nbBytes; i++)
		    {
		      dataI2C[i] = Wire.read();       // it assigne the data to the array
		    }
	  	}

	  	delay(100);

	} while ((dataI2C[0] != variable) && (dataI2C[0] < numberOfVariables - 1));

	return dataI2C;
}

//_____________________________________________________________________________________________
// Conversion
/**
 * \fn byte getLowByte(int n)
 * \brief fonction qui convertit un entier en 2 bytes - low ici
 * \param 1 tableau de bytes
 */
byte getLowByte(int n)
{
  byte result;

  result = n%256;
  result = byte(result);

  return result;
}

/**
 * \fn byte getHighByte(int n)
 * \brief fonction qui convertit un entier en 2 bytes - high ici
 * \param 1 tableau de byte
 */
byte getHighByte(int n)
{
  byte result;

  result = n/256;
  result = byte(result);

  return result;
}

/**
 * \fn void intTo2Bytes(byte bytesTab[], int n)
 * \brief fonction qui affiche les 2 bytes d'un nombre entier convertit en binaire
 * \param 1 tableau de byte
 * \param 1 entier : nombre à convertir
 */
void intTo2Bytes(byte bytesTab[], int n)
{
  Serial.println("high byte.low byte : ");

  bytesTab[0] = getHighByte(n);
  bytesTab[1] = getLowByte(n);
  Serial.print(bytesTab[0], HEX);
  Serial.print(".");
  Serial.println(bytesTab[1], HEX);
}

/**
 * \fn int recoverIntFrom2Bytes(byte bytesTab[])
 * \brief fonction qui affiche un entier ayant ete convertit en 2 bytes binaire
 * \param 1 tableau de byte
 * \param 1 entier : nombre à convertir
 */
int recoverIntFrom2Bytes(byte bytesTab[])
{
  int result;

  result = bytesTab[0]*256;
  result += bytesTab[1];

  return result;
}

//_____________________________________________________________________________________________
//_____________________________________________________________________________________________

<|endoftext|>


<commit_before>/**
@file serialization.hpp
@brief Serialization definitions.

@author Timothy Howard
@copyright 2013-2014 Timothy Howard under the MIT license;
see @ref index or the accompanying LICENSE file for full text.
*/

#ifndef HORD_SERIALIZATION_HPP_
#define HORD_SERIALIZATION_HPP_

#include <Hord/config.hpp>

#include <Cacophony/types.hpp>
#include <Cacophony/traits.hpp>
#include <Cacophony/utility.hpp>
#include <Cacophony/ErrorCode.hpp>
#include <Cacophony/Error.hpp>
#include <Cacophony/BinarySerializer.hpp>
#include <Cacophony/support/binary_blob.hpp>
#include <Cacophony/support/sequence.hpp>
#include <Cacophony/support/enum_cfg.hpp>
#include <Cacophony/support/string_cfg.hpp>
#include <Cacophony/support/vector_cfg.hpp>
#include <Cacophony/support/std_string.hpp>
#include <Cacophony/support/std_vector.hpp>

#include <duct/EndianUtils.hpp>
#include <duct/IO/dynamic_streambuf.hpp>

namespace Hord {

// Forward declarations

/**
	@addtogroup serialization
	@{
*/

/**
	Dynamic @c std::stream buffer.
*/
using DynamicStreamBuf
= duct::IO::basic_dynamic_streambuf<
	char,
	std::char_traits<char>,
	HORD_AUX_ALLOCATOR<char>
>;

// Cacophony imports

using Cacophony::const_safe;

/**
	Serializer error code type.
*/
using SerializerErrorCode = Cacophony::ErrorCode;

/**
	Serializer error type.
*/
using SerializerError = Cacophony::Error;

/**
	Data input serializer.
*/
using InputSerializer = Cacophony::BinaryInputSerializer;

/**
	Data output serializer.
*/
using OutputSerializer = Cacophony::BinaryOutputSerializer;

/**
	Serialization function result type.
*/
using ser_result_type = Cacophony::ser_result_type;

/**
	Serialization function tags for Cacophony.

	These should come first in the serialization function parameter
	list.
	@{
*/
using ser_tag_serialize = Cacophony::tag_serialize;
using ser_tag_read = Cacophony::tag_read;
using ser_tag_write = Cacophony::tag_write;
/** @} */

/**
	Get the name of a serializer error.

	@returns C-string containing the name of @a error_code or
	"INVALID" if somehow @a error_code is not actually a
	SerializerErrorCode.
*/
inline char const*
get_ser_error_name(
	SerializerErrorCode const error_code
) noexcept {
	return Cacophony::get_error_name(error_code);
}

/**
	Make input serializer.
*/
inline InputSerializer
make_input_serializer(
	std::istream& stream
) noexcept {
	return InputSerializer{stream, HORD_DATA_ENDIAN};
}

/**
	Make output serializer.
*/
inline OutputSerializer
make_output_serializer(
	std::ostream& stream
) noexcept {
	return OutputSerializer{stream, HORD_DATA_ENDIAN};
}

/** @cond INTERNAL */
#define HORD_SER_ERR_MSG_IO_GENERIC(skind_)			\
	"failed to " skind_ ":"							\
	" serialization error: \n  {%s} %s"

#define HORD_SER_ERR_MSG_IO_PROP(skind_)			\
	"failed to " skind_ " prop %08x -> %s:"			\
	" serialization error: \n  {%s} %s"

#define HORD_THROW_SER_FMT(efmt_, serr_)			\
	HORD_THROW_FMT(									\
		ErrorCode::serialization_io_failed,			\
		efmt_,										\
		get_ser_error_name(serr_.get_code()),		\
		serr_.get_message()							\
	)
//

#define HORD_THROW_SER_PROP(efmt_, serr_, objid_, pkind_)	\
	HORD_THROW_FMT(											\
		Hord::ErrorCode::serialization_io_failed,			\
		efmt_,												\
		objid_,												\
		pkind_,												\
		Hord::get_ser_error_name(serr_.get_code()),			\
		serr_.get_message()									\
	)
//
/** @endcond */ // INTERNAL

/** @} */ // end of doc-group serialization

} // namespace Hord

#endif // HORD_SERIALIZATION_HPP_
<commit_msg>serialization: included duct::IO Cacophony support header.<commit_after>/**
@file serialization.hpp
@brief Serialization definitions.

@author Timothy Howard
@copyright 2013-2014 Timothy Howard under the MIT license;
see @ref index or the accompanying LICENSE file for full text.
*/

#ifndef HORD_SERIALIZATION_HPP_
#define HORD_SERIALIZATION_HPP_

#include <Hord/config.hpp>

#include <Cacophony/types.hpp>
#include <Cacophony/traits.hpp>
#include <Cacophony/utility.hpp>
#include <Cacophony/ErrorCode.hpp>
#include <Cacophony/Error.hpp>
#include <Cacophony/BinarySerializer.hpp>
#include <Cacophony/support/binary_blob.hpp>
#include <Cacophony/support/sequence.hpp>
#include <Cacophony/support/enum_cfg.hpp>
#include <Cacophony/support/string_cfg.hpp>
#include <Cacophony/support/vector_cfg.hpp>
#include <Cacophony/support/std_string.hpp>
#include <Cacophony/support/std_vector.hpp>

#include <duct/EndianUtils.hpp>
#include <duct/IO/dynamic_streambuf.hpp>
#include <duct/IO/cacophony_support.hpp>

namespace Hord {

// Forward declarations

/**
	@addtogroup serialization
	@{
*/

/**
	Dynamic @c std::stream buffer.
*/
using DynamicStreamBuf
= duct::IO::basic_dynamic_streambuf<
	char,
	std::char_traits<char>,
	HORD_AUX_ALLOCATOR<char>
>;

// Cacophony imports

using Cacophony::const_safe;

/**
	Serializer error code type.
*/
using SerializerErrorCode = Cacophony::ErrorCode;

/**
	Serializer error type.
*/
using SerializerError = Cacophony::Error;

/**
	Data input serializer.
*/
using InputSerializer = Cacophony::BinaryInputSerializer;

/**
	Data output serializer.
*/
using OutputSerializer = Cacophony::BinaryOutputSerializer;

/**
	Serialization function result type.
*/
using ser_result_type = Cacophony::ser_result_type;

/**
	Serialization function tags for Cacophony.

	These should come first in the serialization function parameter
	list.
	@{
*/
using ser_tag_serialize = Cacophony::tag_serialize;
using ser_tag_read = Cacophony::tag_read;
using ser_tag_write = Cacophony::tag_write;
/** @} */

/**
	Get the name of a serializer error.

	@returns C-string containing the name of @a error_code or
	"INVALID" if somehow @a error_code is not actually a
	SerializerErrorCode.
*/
inline char const*
get_ser_error_name(
	SerializerErrorCode const error_code
) noexcept {
	return Cacophony::get_error_name(error_code);
}

/**
	Make input serializer.
*/
inline InputSerializer
make_input_serializer(
	std::istream& stream
) noexcept {
	return InputSerializer{stream, HORD_DATA_ENDIAN};
}

/**
	Make output serializer.
*/
inline OutputSerializer
make_output_serializer(
	std::ostream& stream
) noexcept {
	return OutputSerializer{stream, HORD_DATA_ENDIAN};
}

/** @cond INTERNAL */
#define HORD_SER_ERR_MSG_IO_GENERIC(skind_)			\
	"failed to " skind_ ":"							\
	" serialization error: \n  {%s} %s"

#define HORD_SER_ERR_MSG_IO_PROP(skind_)			\
	"failed to " skind_ " prop %08x -> %s:"			\
	" serialization error: \n  {%s} %s"

#define HORD_THROW_SER_FMT(efmt_, serr_)			\
	HORD_THROW_FMT(									\
		ErrorCode::serialization_io_failed,			\
		efmt_,										\
		get_ser_error_name(serr_.get_code()),		\
		serr_.get_message()							\
	)
//

#define HORD_THROW_SER_PROP(efmt_, serr_, objid_, pkind_)	\
	HORD_THROW_FMT(											\
		Hord::ErrorCode::serialization_io_failed,			\
		efmt_,												\
		objid_,												\
		pkind_,												\
		Hord::get_ser_error_name(serr_.get_code()),			\
		serr_.get_message()									\
	)
//
/** @endcond */ // INTERNAL

/** @} */ // end of doc-group serialization

} // namespace Hord

#endif // HORD_SERIALIZATION_HPP_
<|endoftext|>


<commit_before>/* -*- coding: utf-8; mode: c++; tab-width: 3; indent-tabs-mode: nil -*-

Copyright 2010, 2011, 2012, 2013, 2014, 2015
Raffaello D. Di Napoli

This file is part of Abaclade.

Abaclade 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.

Abaclade 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 Abaclade. If not, see
<http://www.gnu.org/licenses/>.
--------------------------------------------------------------------------------------------------*/

#ifndef _ABACLADE_HXX_INTERNAL
   #error "Please #include <abaclade.hxx> instead of this file"
#endif

#if ABC_HOST_API_WIN32
   #include <abaclade/text/parsers/ansi_escape_sequences.hxx>
#endif

////////////////////////////////////////////////////////////////////////////////////////////////////
// abc::io::binary globals

namespace abc {
namespace io {
namespace binary {

namespace detail {

/*! Data collected by open() used to construct a file instance. This is only defined in file.cxx,
after the necessary header files have been included. */
struct file_init_data;

} //namespace detail

// Forward declarations.
class file_base;
class file_reader;
class file_writer;
class pipe_reader;
class pipe_writer;

/*! Creates a unidirectional pipe (FIFO), returning a reader and a writer connected to its ends.

@return
   A pair containing the reader end and the writer end of the pipe.
*/
ABACLADE_SYM std::pair<std::shared_ptr<pipe_reader>, std::shared_ptr<pipe_writer>> pipe(
   bool bAsync = false
);

/*! Returns the binary writer associated to the standard error output file (stderr).

@return
   Standard error file.
*/
ABACLADE_SYM std::shared_ptr<file_writer> stderr();

/*! Returns the binary reader associated to the standard input file (stdin).

@return
   Standard input file.
*/
ABACLADE_SYM std::shared_ptr<file_reader> stdin();

/*! Returns the binary writer associated to the standard output file (stdout).

@return
   Standard output file.
*/
ABACLADE_SYM std::shared_ptr<file_writer> stdout();

/*! Opens a file for binary access.

@param op
   Path to the file.
@param am
   Desired access mode.
@param bAsync
   If true, the returned object will allow for I/O calls that leave the object in a “asynchronous
   operation pending” state.
@param bBypassCache
   If true, the OS will not cache any portion of the file; if false, accesses to the file will be
   backed by the OS file cache subsystem.
@return
   Pointer to a binary I/O object for the file.
*/
std::shared_ptr<file_base> open(
   os::path const & op, access_mode am, bool bAsync = false, bool bBypassCache = false
);

/*! Opens a file for binary reading.

@param op
   Path to the file.
@param bAsync
   If true, the returned object will allow for I/O calls that leave the object in a “asynchronous
   operation pending” state.
@param bBypassCache
   If true, the OS will not cache any portion of the file; if false, accesses to the file will be
   backed by the OS file cache subsystem.
@return
   Pointer to a binary reader for the file.
*/
inline std::shared_ptr<file_reader> open_reader(
   os::path const & op, bool bAsync = false, bool bBypassCache = false
) {
   return std::dynamic_pointer_cast<file_reader>(open(op, access_mode::read, bAsync, bBypassCache));
}

/*! Opens a file for binary writing.

@param op
   Path to the file.
@param bAsync
   If true, the returned object will allow for I/O calls that leave the object in a “asynchronous
   operation pending” state.
@param bBypassCache
   If true, the OS will not cache any portion of the file; if false, accesses to the file will be
   backed by the OS file cache subsystem.
@return
   Pointer to a binary writer for the file.
*/
inline std::shared_ptr<file_writer> open_writer(
   os::path const & op, bool bAsync = false, bool bBypassCache = false
) {
   return std::dynamic_pointer_cast<file_writer>(open(
      op, access_mode::write, bAsync, bBypassCache
   ));
}

} //namespace binary
} //namespace io
} //namespace abc

////////////////////////////////////////////////////////////////////////////////////////////////////
// abc::io::binary::base

namespace abc {
namespace io {
namespace binary {

//! Base interface for binary (non-text) I/O.
class ABACLADE_SYM base : public async {
public:
   //! Destructor. Also needed to make the class polymorphic (have a vtable).
   virtual ~base();
};

} //namespace binary
} //namespace io
} //namespace abc

////////////////////////////////////////////////////////////////////////////////////////////////////
// abc::io::binary::reader

namespace abc {
namespace io {
namespace binary {

//! Interface for binary (non-text) input.
class ABACLADE_SYM reader : public virtual base {
public:
   /*! Reads at most cbMax bytes.

   @param p
      Address of the destination buffer.
   @param cbMax
      Size of the destination buffer, in bytes.
   @return
      Count of bytes read. For non-zero values of cbMax, a return value of 0 indicates that the end
      of the data (EOF) was reached.
   */
   virtual std::size_t read(void * p, std::size_t cbMax) = 0;
};

} //namespace binary
} //namespace io
} //namespace abc

////////////////////////////////////////////////////////////////////////////////////////////////////
// abc::io::binary::writer

namespace abc {
namespace io {
namespace binary {

//! Interface for binary (non-text) output.
class ABACLADE_SYM writer : public virtual base {
public:
   //! Forces writing any data in the write buffer.
   virtual void flush() = 0;

   /*! Writes an array of bytes.

   @param p
      Address of the source buffer.
   @param cb
      Size of the source buffer, in bytes.
   @return
      Count of bytes written.
   */
   virtual std::size_t write(void const * p, std::size_t cb) = 0;
};

} //namespace binary
} //namespace io
} //namespace abc

////////////////////////////////////////////////////////////////////////////////////////////////////
// abc::io::binary::seekable

namespace abc {
namespace io {
namespace binary {

//! Interface for binary I/O classes that allow random access (e.g. seek/tell operations).
class ABACLADE_SYM seekable {
public:
   /*! Changes the current read/write position.

   @param iOffset
      New position, relative to sfWhence.
   @param sfWhence
      Indicates what position iOffset is relative to.
   @return
      Resulting position.
   */
   virtual offset_t seek(offset_t ibOffset, seek_from sfWhence) = 0;

   /*! Returns the current read/write position.

   @return
      Current position.
   */
   virtual offset_t tell() const = 0;
};

} //namespace binary
} //namespace io
} //namespace abc

////////////////////////////////////////////////////////////////////////////////////////////////////
// abc::io::binary::sized

namespace abc {
namespace io {
namespace binary {

//! Interface for binary I/O classes that access data with a known size.
class ABACLADE_SYM sized {
public:
   /*! Returns the size of the data.

   @return
      Data size, in bytes.
   */
   virtual full_size_t size() const = 0;
};

} //namespace binary
} //namespace io
} //namespace abc

////////////////////////////////////////////////////////////////////////////////////////////////////
<commit_msg>Sort functions<commit_after>/* -*- coding: utf-8; mode: c++; tab-width: 3; indent-tabs-mode: nil -*-

Copyright 2010, 2011, 2012, 2013, 2014, 2015
Raffaello D. Di Napoli

This file is part of Abaclade.

Abaclade 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.

Abaclade 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 Abaclade. If not, see
<http://www.gnu.org/licenses/>.
--------------------------------------------------------------------------------------------------*/

#ifndef _ABACLADE_HXX_INTERNAL
   #error "Please #include <abaclade.hxx> instead of this file"
#endif

#if ABC_HOST_API_WIN32
   #include <abaclade/text/parsers/ansi_escape_sequences.hxx>
#endif

////////////////////////////////////////////////////////////////////////////////////////////////////
// abc::io::binary globals

namespace abc {
namespace io {
namespace binary {

namespace detail {

/*! Data collected by open() used to construct a file instance. This is only defined in file.cxx,
after the necessary header files have been included. */
struct file_init_data;

} //namespace detail

// Forward declarations.
class file_base;
class file_reader;
class file_writer;
class pipe_reader;
class pipe_writer;

/*! Opens a file for binary access.

@param op
   Path to the file.
@param am
   Desired access mode.
@param bAsync
   If true, the returned object will allow for I/O calls that leave the object in a “asynchronous
   operation pending” state.
@param bBypassCache
   If true, the OS will not cache any portion of the file; if false, accesses to the file will be
   backed by the OS file cache subsystem.
@return
   Pointer to a binary I/O object for the file.
*/
std::shared_ptr<file_base> open(
   os::path const & op, access_mode am, bool bAsync = false, bool bBypassCache = false
);

/*! Opens a file for binary reading.

@param op
   Path to the file.
@param bAsync
   If true, the returned object will allow for I/O calls that leave the object in a “asynchronous
   operation pending” state.
@param bBypassCache
   If true, the OS will not cache any portion of the file; if false, accesses to the file will be
   backed by the OS file cache subsystem.
@return
   Pointer to a binary reader for the file.
*/
inline std::shared_ptr<file_reader> open_reader(
   os::path const & op, bool bAsync = false, bool bBypassCache = false
) {
   return std::dynamic_pointer_cast<file_reader>(open(op, access_mode::read, bAsync, bBypassCache));
}

/*! Opens a file for binary writing.

@param op
   Path to the file.
@param bAsync
   If true, the returned object will allow for I/O calls that leave the object in a “asynchronous
   operation pending” state.
@param bBypassCache
   If true, the OS will not cache any portion of the file; if false, accesses to the file will be
   backed by the OS file cache subsystem.
@return
   Pointer to a binary writer for the file.
*/
inline std::shared_ptr<file_writer> open_writer(
   os::path const & op, bool bAsync = false, bool bBypassCache = false
) {
   return std::dynamic_pointer_cast<file_writer>(open(
      op, access_mode::write, bAsync, bBypassCache
   ));
}

/*! Creates a unidirectional pipe (FIFO), returning a reader and a writer connected to its ends.

@return
   A pair containing the reader end and the writer end of the pipe.
*/
ABACLADE_SYM std::pair<std::shared_ptr<pipe_reader>, std::shared_ptr<pipe_writer>> pipe(
   bool bAsync = false
);

/*! Returns the binary writer associated to the standard error output file (stderr).

@return
   Standard error file.
*/
ABACLADE_SYM std::shared_ptr<file_writer> stderr();

/*! Returns the binary reader associated to the standard input file (stdin).

@return
   Standard input file.
*/
ABACLADE_SYM std::shared_ptr<file_reader> stdin();

/*! Returns the binary writer associated to the standard output file (stdout).

@return
   Standard output file.
*/
ABACLADE_SYM std::shared_ptr<file_writer> stdout();

} //namespace binary
} //namespace io
} //namespace abc

////////////////////////////////////////////////////////////////////////////////////////////////////
// abc::io::binary::base

namespace abc {
namespace io {
namespace binary {

//! Base interface for binary (non-text) I/O.
class ABACLADE_SYM base : public async {
public:
   //! Destructor. Also needed to make the class polymorphic (have a vtable).
   virtual ~base();
};

} //namespace binary
} //namespace io
} //namespace abc

////////////////////////////////////////////////////////////////////////////////////////////////////
// abc::io::binary::reader

namespace abc {
namespace io {
namespace binary {

//! Interface for binary (non-text) input.
class ABACLADE_SYM reader : public virtual base {
public:
   /*! Reads at most cbMax bytes.

   @param p
      Address of the destination buffer.
   @param cbMax
      Size of the destination buffer, in bytes.
   @return
      Count of bytes read. For non-zero values of cbMax, a return value of 0 indicates that the end
      of the data (EOF) was reached.
   */
   virtual std::size_t read(void * p, std::size_t cbMax) = 0;
};

} //namespace binary
} //namespace io
} //namespace abc

////////////////////////////////////////////////////////////////////////////////////////////////////
// abc::io::binary::writer

namespace abc {
namespace io {
namespace binary {

//! Interface for binary (non-text) output.
class ABACLADE_SYM writer : public virtual base {
public:
   //! Forces writing any data in the write buffer.
   virtual void flush() = 0;

   /*! Writes an array of bytes.

   @param p
      Address of the source buffer.
   @param cb
      Size of the source buffer, in bytes.
   @return
      Count of bytes written.
   */
   virtual std::size_t write(void const * p, std::size_t cb) = 0;
};

} //namespace binary
} //namespace io
} //namespace abc

////////////////////////////////////////////////////////////////////////////////////////////////////
// abc::io::binary::seekable

namespace abc {
namespace io {
namespace binary {

//! Interface for binary I/O classes that allow random access (e.g. seek/tell operations).
class ABACLADE_SYM seekable {
public:
   /*! Changes the current read/write position.

   @param iOffset
      New position, relative to sfWhence.
   @param sfWhence
      Indicates what position iOffset is relative to.
   @return
      Resulting position.
   */
   virtual offset_t seek(offset_t ibOffset, seek_from sfWhence) = 0;

   /*! Returns the current read/write position.

   @return
      Current position.
   */
   virtual offset_t tell() const = 0;
};

} //namespace binary
} //namespace io
} //namespace abc

////////////////////////////////////////////////////////////////////////////////////////////////////
// abc::io::binary::sized

namespace abc {
namespace io {
namespace binary {

//! Interface for binary I/O classes that access data with a known size.
class ABACLADE_SYM sized {
public:
   /*! Returns the size of the data.

   @return
      Data size, in bytes.
   */
   virtual full_size_t size() const = 0;
};

} //namespace binary
} //namespace io
} //namespace abc

////////////////////////////////////////////////////////////////////////////////////////////////////
<|endoftext|>


<commit_before>#pragma once

/**
 * Types and macros to define abstract domains.
 **/

// AG: Something is wrong. Formatting breaks compilation
// clang-format off

#include <crab/config.h>
#include <clam/crab/crab_lang.hh>

#include <crab/domains/array_adaptive.hpp>
#include <crab/domains/flat_boolean_domain.hpp>
#include <crab/domains/region_domain.hpp>
#include <crab/domains/term_equiv.hpp>

namespace clam {
using namespace crab::domains;
using namespace ikos;

/* ====================================================================== */
/* BEGIN MACROS to create the hierarchy of domains. Only for internal use */
/* ====================================================================== */
// The base numerical domain
#define BASE(DOM) base_ ## DOM
// Term functor domain
#define TERM_FUN(DOM) \
  term_domain<term::TDomInfo<number_t, dom_varname_t, DOM>>
// Reduced product of boolean domain with numerical domain
#define BOOL_NUM(DOM) flat_boolean_numerical_domain<DOM>
// Array functor domain where the parameter domain is DOM
#define ARRAY_FUN(DOM) array_adapt_domain<DOM>
// Region functor domain -- the root of the hierarchy of domains.
#define RGN_FUN(DOM) \
  region_domain<region_domain_impl::Params<z_number, varname_t, DOM>>
/* ====================================================================== */
/* END MACROS to create the hierarchy of domains. Only for internal use   */
/* ====================================================================== */

/* ====================================================================== */
/* BEGIN array adaptive domain                                            */
/* ====================================================================== */
class ArrayAdaptParams {
public:
 /* options for array smashing */
  enum { is_smashable = 1 };
  enum { smash_at_nonzero_offset = 1};
  enum { max_smashable_cells = 64};
  /* options for array expansion */
  enum { max_array_size = 64 };
};
template<class Dom>
using array_adapt_domain = array_adaptive_domain<Dom, ArrayAdaptParams>;
/* ====================================================================== */
/* END array adaptive domain                                              */
/* ====================================================================== */

/* ====================================================================== */
/* BEGIN region domain                                                    */
/* ====================================================================== */
using domvar_allocator = crab::var_factory_impl::str_var_alloc_col;
using dom_varname_t = domvar_allocator::varname_t;
/* ====================================================================== */
/* END region domain                                                      */
/* ====================================================================== */
} // end namespace clam
// clang-format on
<commit_msg>refactor(crab): change default parameters of the region domain<commit_after>#pragma once

/**
 * Types and macros to define abstract domains.
 **/

// AG: Something is wrong. Formatting breaks compilation
// clang-format off

#include <crab/config.h>
#include <clam/crab/crab_lang.hh>

#include <crab/domains/array_adaptive.hpp>
#include <crab/domains/flat_boolean_domain.hpp>
#include <crab/domains/region_domain.hpp>
#include <crab/domains/term_equiv.hpp>

namespace clam {
using namespace crab::domains;
using namespace ikos;

/* ====================================================================== */
/* BEGIN MACROS to create the hierarchy of domains. Only for internal use */
/* ====================================================================== */
// The base numerical domain
#define BASE(DOM) base_ ## DOM
// Term functor domain
#define TERM_FUN(DOM) \
  term_domain<term::TDomInfo<number_t, dom_varname_t, DOM>>
// Reduced product of boolean domain with numerical domain
#define BOOL_NUM(DOM) flat_boolean_numerical_domain<DOM>
// Array functor domain where the parameter domain is DOM
#define ARRAY_FUN(DOM) array_adapt_domain<DOM>
// Region functor domain -- the root of the hierarchy of domains.
#define RGN_FUN(DOM) region_domain<RegionParams<DOM>>
/* ====================================================================== */
/* END MACROS to create the hierarchy of domains. Only for internal use   */
/* ====================================================================== */

/* ====================================================================== */
/* BEGIN array adaptive domain                                            */
/* ====================================================================== */
class ArrayAdaptParams {
public:
 /* options for array smashing */
  enum { is_smashable = 1 };
  enum { smash_at_nonzero_offset = 1};
  enum { max_smashable_cells = 64};
  /* options for array expansion */
  enum { max_array_size = 64 };
};
template<class Dom>
using array_adapt_domain = array_adaptive_domain<Dom, ArrayAdaptParams>;
/* ====================================================================== */
/* END array adaptive domain                                              */
/* ====================================================================== */

/* ====================================================================== */
/* BEGIN region domain                                                    */
/* ====================================================================== */
using domvar_allocator = crab::var_factory_impl::str_var_alloc_col;
using dom_varname_t = domvar_allocator::varname_t;
template<class BaseAbsDom>
class RegionParams {
public:
  using number_t = z_number;
  using varname_t = clam::varname_t;
  using varname_allocator_t = crab::var_factory_impl::str_var_alloc_col;
  using base_abstract_domain_t = BaseAbsDom;
  using base_varname_t = typename BaseAbsDom::varname_t;
  /* Enable reasoning about allocation sites*/
  enum { allocation_sites = 1};
  /* Enable reasoning about deallocations */
  enum { deallocation = 1};
  /* This should be always disabled */
  enum { refine_uninitialized_regions = 0};
};
/* ====================================================================== */
/* END region domain                                                      */
/* ====================================================================== */
} // end namespace clam
// clang-format on
<|endoftext|>


<commit_before>#include <get_property_value.h>

boost::python::object PyGetValue::getObject()
{
    return _obj;
}

boost::python::object PyGetValue::GetInteger( const IAAFPropertyValueSP& spPropVal, IAAFTypeDefIntSP& spTypeDef)
{
    AxTypeDefInt axIntDef(spTypeDef);
    AxPropertyValue axValue(spPropVal);
    aafUInt32 size = axIntDef.GetSize();

    if (axIntDef.IsSigned())
    {
        if (sizeof(aafInt8) == size)
            return boost::python::object(GetInt<aafInt8>(axValue));
        else if (sizeof(aafInt16) == size)
            return boost::python::object(GetInt<aafInt16>(axValue));
        else if (sizeof(aafInt32) == size)
            return boost::python::object(GetInt<aafInt32>(axValue));
        else
            return boost::python::object(GetInt<aafInt64>(axValue));
    }
    else
    {
        if (sizeof(aafUInt8) == size)
            return boost::python::object(GetInt<aafUInt8>(axValue));
        else if (sizeof(aafUInt16) == size)
            return boost::python::object(GetInt<aafUInt16>(axValue));
        else if (sizeof(aafUInt32) == size)
            return boost::python::object(GetInt<aafUInt32>(axValue));
        else
            return boost::python::object(GetInt<aafUInt64>(axValue));
    }

}

void PyGetValue::processAny(IAAFPropertyValueSP& spPropVal, IAAFTypeDefSP& spTypeDef)
{
    AxTypeDef axTypeDef(spTypeDef);

    if (isClassType<IAAFTypeDefInt>(axTypeDef))
    {

        IAAFTypeDefIntSP sp(AxQueryInterface<IAAFTypeDef,
                            IAAFTypeDefInt>(axTypeDef));

        this->process(spPropVal, sp);

    }

    else if (isClassType<IAAFTypeDefFixedArray>(axTypeDef))

    {

        IAAFTypeDefFixedArraySP sp(AxQueryInterface<IAAFTypeDef,
                                   IAAFTypeDefFixedArray>(axTypeDef));

        this->process(spPropVal, sp);

    }

    else
    {

        std::wcout << axTypeDef.GetName() << "\n";
        throw std::invalid_argument("Invalid AUID ");

    }

}

void PyGetValue::process( IAAFPropertyValueSP& spPropVal, IAAFTypeDefCharacterSP& spTypeDef)
{
}

void PyGetValue::process( IAAFPropertyValueSP& spPropVal, IAAFTypeDefIndirectSP& spTypeDef )
{
    AxTypeDefIndirect axIndirect( spTypeDef );
    AxTypeDef axActualTypeDef( axIndirect.GetActualType(spPropVal) );
    IAAFPropertyValueSP actualPropertyValueSP = axIndirect.GetActualValue(spPropVal);

    //IAAFTypeDefVariableArraySP spVariableArray;
    if (isClassType<IAAFTypeDefVariableArray>(axActualTypeDef))
    {

        IAAFTypeDefVariableArraySP sp(AxQueryInterface<IAAFTypeDef,
                                      IAAFTypeDefVariableArray>(axActualTypeDef));

        this->process(actualPropertyValueSP,sp);

    }

}

void PyGetValue::process( IAAFPropertyValueSP& spPropVal, IAAFTypeDefIntSP& spTypeDef)
{
    _obj = this->GetInteger(spPropVal,spTypeDef);
}

void PyGetValue::process( IAAFPropertyValueSP& spPropVal, IAAFTypeDefRenameSP& spTypeDef)
{

}

void PyGetValue::process( IAAFPropertyValueSP& spPropVal, IAAFTypeDefEnumSP& spTypeDef)
{

}

void PyGetValue::process( IAAFPropertyValueSP& spPropVal, IAAFTypeDefExtEnumSP& spTypeDef)
{

}

void PyGetValue::process( IAAFPropertyValueSP& spPropVal, IAAFTypeDefFixedArraySP& spTypeDef)
{

    AxTypeDefFixedArray axTDFA(spTypeDef);

    aafUInt32 size = axTDFA.GetCount();

    std::wcout << size << "\n";

}

void PyGetValue::process( IAAFPropertyValueSP& spPropVal, IAAFTypeDefRecordSP& spTypeDef)
{
    AxTypeDefRecord axTDR(spTypeDef);

    aafUInt32 size = axTDR.GetCount();

    boost::python::dict d;

    for (aafUInt32 i = 0; i<size; i++)
    {

        AxString name = axTDR.GetMemberName(i);

        IAAFPropertyValueSP spValue = axTDR.GetValue(spPropVal, i);

        AxPropertyValue axValue(spValue);
        IAAFTypeDefSP spMemTypeDef = axValue.GetType();
        AxTypeDef axDef(spMemTypeDef);

        if (axDef.GetAUID() == kAAFTypeID_DateStruct)
        {
            aafDateStruct_t date = GetDate(axValue);
            d[name] = DateToString(date);
        }
        else if (axDef.GetAUID() == kAAFTypeID_TimeStruct)
        {
            _aafTimeStruct_t time = GetTime( axValue);

            d[name] = TimeToString(time);

        }

        else if (axDef.GetAUID() == kAAFTypeID_TimeStamp)
        {
            _aafTimeStamp_t timeStamp = GetTimeStamp(axValue);
            d[name] = TimeStampToString( timeStamp );
        }

        else
        {

            PyGetValue valueGetter;

            valueGetter.processAny(spValue, spMemTypeDef);

            d[name] = valueGetter.getObject();
            //throw std::invalid_argument("Invalid AUID ");
        }

        //std::wcout << axTDR.GetName() << " " << name << " " <<axDef.GetName() << "\n";

    }
    _obj = d;

}

void PyGetValue::process( IAAFPropertyValueSP& spPropVal, IAAFTypeDefSetSP& spTypeDef)
{
    AxTypeDefSet axDefSet(spTypeDef);

    _obj = boost::python::object(axDefSet.GetElements(spPropVal));

    //boost::python::list elements;
    //AxPropertyValueIter axIter(axDefSet.GetElements(spPropVal));

    /*
    bool notAtEnd =true;
    while (notAtEnd)
    {
        IAAFSmartPointer2<IAAFPropertyValue> nextValue;

        notAtEnd = axIter.NextOne(nextValue);
        if (notAtEnd)
        {

            IAAFPropertyValueSP spValue = nextValue;
            AxPropertyValue axValue(spValue);

            AxTypeDef axValueTypeDef(axValue.GetType());

            if (isClassType<IAAFTypeDefStrongObjRef>(axValueTypeDef))
            {
                IAAFTypeDefStrongObjRefSP sp(AxQueryInterface<IAAFTypeDef,
                                              IAAFTypeDefStrongObjRef>(axValueTypeDef));
                AxTypeDefStrongObjRef axDefRef(sp);

                IAAFObjectSP spObj = axDefRef.GetObject<IAAFObject>(spValue);
                elements.append(spObj);

                //std::wcout << axValueTypeDef.GetName() << "\n";
            }

        }
    }

    _obj = elements;
     */
}

void PyGetValue::process( IAAFPropertyValueSP& spPropVal, IAAFTypeDefStreamSP& spTypeDef)
{

}

void PyGetValue::process( IAAFPropertyValueSP& spPropVal, IAAFTypeDefStringSP& spTypeDef)
{

}

void PyGetValue::process( IAAFPropertyValueSP& spPropVal, IAAFTypeDefStrongObjRefSP& spTypeDef)
{

    AxTypeDefStrongObjRef axDefRef(spTypeDef);

    IAAFObjectSP spObj = axDefRef.GetObject<IAAFObject>(spPropVal);
    _obj = boost::python::object(spObj);
}

void PyGetValue::process( IAAFPropertyValueSP& spPropVal, IAAFTypeDefWeakObjRefSP& spTypeDef)
{

}

void PyGetValue::process( IAAFPropertyValueSP& spPropVal, IAAFTypeDefObjectRefSP& spTypeDef)
{

}

void PyGetValue::process( IAAFPropertyValueSP& spPropVal, IAAFTypeDefOpaqueSP& spTypeDef)
{

}

void PyGetValue::process( IAAFPropertyValueSP& spPropVal, IAAFTypeDefVariableArraySP&  spTypeDef)
{

    AxTypeDefVariableArray axVarArray( spTypeDef );
    AxTypeDef axTypeDefOfArray( axVarArray.GetType() );
    IAAFTypeDefIntSP spTypeDefInt;

    if (isClassType<IAAFTypeDefInt>(axTypeDefOfArray))
    {
        IAAFTypeDefIntSP TypeDefIntSP(AxQueryInterface<IAAFTypeDef,IAAFTypeDefInt>(axTypeDefOfArray));
        AxTypeDefInt axTypeDefInt(TypeDefIntSP);

        aafUInt32 size = axVarArray.GetCount(spPropVal);

        AxPropertyValueIter axIter(axVarArray.GetElements(spPropVal));
        bool notAtEnd = true;

        boost::python::list elements;

        for ( aafUInt32 i = 0; i<size; i++ )

        {

            IAAFSmartPointer2<IAAFPropertyValue> nextValue;
            notAtEnd = axIter.NextOne(nextValue);

            if (notAtEnd)
            {
                AxPropertyValue value(nextValue);
                elements.append(this->GetInteger(nextValue,TypeDefIntSP));

            }

            _obj = elements;
        }

    }

}
<commit_msg>added more GetValues<commit_after>#include <get_property_value.h>

boost::python::object PyGetValue::getObject()
{
    return _obj;
}

boost::python::object PyGetValue::GetInteger( const IAAFPropertyValueSP& spPropVal, IAAFTypeDefIntSP& spTypeDef)
{
    AxTypeDefInt axIntDef(spTypeDef);
    AxPropertyValue axValue(spPropVal);
    aafUInt32 size = axIntDef.GetSize();

    if (axIntDef.IsSigned())
    {
        if (sizeof(aafInt8) == size)
            return boost::python::object(GetInt<aafInt8>(axValue));
        else if (sizeof(aafInt16) == size)
            return boost::python::object(GetInt<aafInt16>(axValue));
        else if (sizeof(aafInt32) == size)
            return boost::python::object(GetInt<aafInt32>(axValue));
        else
            return boost::python::object(GetInt<aafInt64>(axValue));
    }
    else
    {
        if (sizeof(aafUInt8) == size)
            return boost::python::object(GetInt<aafUInt8>(axValue));
        else if (sizeof(aafUInt16) == size)
            return boost::python::object(GetInt<aafUInt16>(axValue));
        else if (sizeof(aafUInt32) == size)
            return boost::python::object(GetInt<aafUInt32>(axValue));
        else
            return boost::python::object(GetInt<aafUInt64>(axValue));
    }

}

void PyGetValue::processAny(IAAFPropertyValueSP& spPropVal, IAAFTypeDefSP& spTypeDef)
{
    AxTypeDef axTypeDef(spTypeDef);
    AxPropertyValue axValue(spPropVal);

    if (axTypeDef.GetAUID() == kAAFTypeID_DateStruct)
    {
        aafDateStruct_t date = GetDate(axValue);
        _obj = boost::python::object( DateToString(date));
    }
    else if (axTypeDef.GetAUID() == kAAFTypeID_TimeStruct)
    {
        _aafTimeStruct_t time = GetTime( axValue);

        _obj = boost::python::object(TimeToString(time));

    }

    else if (axTypeDef.GetAUID() == kAAFTypeID_TimeStamp)
    {
        _aafTimeStamp_t timeStamp = GetTimeStamp(axValue);
        _obj = boost::python::object(TimeStampToString( timeStamp ));
    }

    else if (axTypeDef.GetAUID() == kAAFTypeID_AUID)
    {

        aafUID_t uid = GetUID( axValue);
        _obj = boost::python::object(uid);
    }

    else if (isClassType<IAAFTypeDefInt>(axTypeDef))
    {

        IAAFTypeDefIntSP sp(AxQueryInterface<IAAFTypeDef,
                            IAAFTypeDefInt>(axTypeDef));

        this->process(spPropVal, sp);

    }

    else if (isClassType<IAAFTypeDefFixedArray>(axTypeDef))

    {

        IAAFTypeDefFixedArraySP sp(AxQueryInterface<IAAFTypeDef,
                                   IAAFTypeDefFixedArray>(axTypeDef));

        this->process(spPropVal, sp);

    }

    else
    {

        std::wcout << axTypeDef.GetName() << "\n";
        throw std::invalid_argument("Invalid AUID ");

    }

}

void PyGetValue::process( IAAFPropertyValueSP& spPropVal, IAAFTypeDefCharacterSP& spTypeDef)
{
}

void PyGetValue::process( IAAFPropertyValueSP& spPropVal, IAAFTypeDefIndirectSP& spTypeDef )
{
    AxTypeDefIndirect axIndirect( spTypeDef );
    AxTypeDef axActualTypeDef( axIndirect.GetActualType(spPropVal) );
    IAAFPropertyValueSP actualPropertyValueSP = axIndirect.GetActualValue(spPropVal);

    //IAAFTypeDefVariableArraySP spVariableArray;
    if (isClassType<IAAFTypeDefVariableArray>(axActualTypeDef))
    {

        IAAFTypeDefVariableArraySP sp(AxQueryInterface<IAAFTypeDef,
                                      IAAFTypeDefVariableArray>(axActualTypeDef));

        this->process(actualPropertyValueSP,sp);

    }

}

void PyGetValue::process( IAAFPropertyValueSP& spPropVal, IAAFTypeDefIntSP& spTypeDef)
{
    _obj = this->GetInteger(spPropVal,spTypeDef);
}

void PyGetValue::process( IAAFPropertyValueSP& spPropVal, IAAFTypeDefRenameSP& spTypeDef)
{

}

void PyGetValue::process( IAAFPropertyValueSP& spPropVal, IAAFTypeDefEnumSP& spTypeDef)
{

}

void PyGetValue::process( IAAFPropertyValueSP& spPropVal, IAAFTypeDefExtEnumSP& spTypeDef)
{

}

void PyGetValue::process( IAAFPropertyValueSP& spPropVal, IAAFTypeDefFixedArraySP& spTypeDef)
{

    AxTypeDefFixedArray axTDFA(spTypeDef);

    aafUInt32 size = axTDFA.GetCount();

    std::wcout << size << "\n";

    boost::python::list elements;

    for ( aafUInt32 i = 0; i<size; i++ )
    {

        IAAFPropertyValueSP spElement = axTDFA.GetElementValue(spPropVal, i);

        AxPropertyValue axElement(spElement);

        IAAFTypeDefSP spElementTypeDef = axElement.GetType();

        PyGetValue valueGetter;
        valueGetter.processAny(spElement, spElementTypeDef);

        elements.append(valueGetter.getObject());

    }

    _obj = elements;

}

void PyGetValue::process( IAAFPropertyValueSP& spPropVal, IAAFTypeDefRecordSP& spTypeDef)
{
    AxTypeDefRecord axTDR(spTypeDef);

    aafUInt32 size = axTDR.GetCount();

    boost::python::dict d;

    for (aafUInt32 i = 0; i<size; i++)
    {

        AxString name = axTDR.GetMemberName(i);

        IAAFPropertyValueSP spValue = axTDR.GetValue(spPropVal, i);

        AxPropertyValue axValue(spValue);
        IAAFTypeDefSP spMemTypeDef = axValue.GetType();
        AxTypeDef axDef(spMemTypeDef);

        PyGetValue valueGetter;

        valueGetter.processAny(spValue, spMemTypeDef);

        d[name] = valueGetter.getObject();
        //throw std::invalid_argument("Invalid AUID ");

        //std::wcout << axTDR.GetName() << " " << name << " " <<axDef.GetName() << "\n";

    }
    _obj = d;

}

void PyGetValue::process( IAAFPropertyValueSP& spPropVal, IAAFTypeDefSetSP& spTypeDef)
{
    AxTypeDefSet axDefSet(spTypeDef);

    _obj = boost::python::object(axDefSet.GetElements(spPropVal));

    //boost::python::list elements;
    //AxPropertyValueIter axIter(axDefSet.GetElements(spPropVal));

    /*
    bool notAtEnd =true;
    while (notAtEnd)
    {
        IAAFSmartPointer2<IAAFPropertyValue> nextValue;

        notAtEnd = axIter.NextOne(nextValue);
        if (notAtEnd)
        {

            IAAFPropertyValueSP spValue = nextValue;
            AxPropertyValue axValue(spValue);

            AxTypeDef axValueTypeDef(axValue.GetType());

            if (isClassType<IAAFTypeDefStrongObjRef>(axValueTypeDef))
            {
                IAAFTypeDefStrongObjRefSP sp(AxQueryInterface<IAAFTypeDef,
                                              IAAFTypeDefStrongObjRef>(axValueTypeDef));
                AxTypeDefStrongObjRef axDefRef(sp);

                IAAFObjectSP spObj = axDefRef.GetObject<IAAFObject>(spValue);
                elements.append(spObj);

                //std::wcout << axValueTypeDef.GetName() << "\n";
            }

        }
    }

    _obj = elements;
     */
}

void PyGetValue::process( IAAFPropertyValueSP& spPropVal, IAAFTypeDefStreamSP& spTypeDef)
{

}

void PyGetValue::process( IAAFPropertyValueSP& spPropVal, IAAFTypeDefStringSP& spTypeDef)
{

    AxTypeDefString axTypeDefString(spTypeDef);
    AxString value = axTypeDefString.GetElements( spPropVal );

    _obj = boost::python::object(value);

}

void PyGetValue::process( IAAFPropertyValueSP& spPropVal, IAAFTypeDefStrongObjRefSP& spTypeDef)
{

    AxTypeDefStrongObjRef axDefRef(spTypeDef);

    IAAFObjectSP spObj = axDefRef.GetObject<IAAFObject>(spPropVal);
    _obj = boost::python::object(spObj);
}

void PyGetValue::process( IAAFPropertyValueSP& spPropVal, IAAFTypeDefWeakObjRefSP& spTypeDef)
{

}

void PyGetValue::process( IAAFPropertyValueSP& spPropVal, IAAFTypeDefObjectRefSP& spTypeDef)
{

}

void PyGetValue::process( IAAFPropertyValueSP& spPropVal, IAAFTypeDefOpaqueSP& spTypeDef)
{

}

void PyGetValue::process( IAAFPropertyValueSP& spPropVal, IAAFTypeDefVariableArraySP&  spTypeDef)
{

    AxTypeDefVariableArray axVarArray( spTypeDef );
    AxTypeDef axTypeDefOfArray( axVarArray.GetType() );
    IAAFTypeDefIntSP spTypeDefInt;

    if (isClassType<IAAFTypeDefInt>(axTypeDefOfArray))
    {
        IAAFTypeDefIntSP TypeDefIntSP(AxQueryInterface<IAAFTypeDef,IAAFTypeDefInt>(axTypeDefOfArray));
        AxTypeDefInt axTypeDefInt(TypeDefIntSP);

        aafUInt32 size = axVarArray.GetCount(spPropVal);

        AxPropertyValueIter axIter(axVarArray.GetElements(spPropVal));
        bool notAtEnd = true;

        boost::python::list elements;

        for ( aafUInt32 i = 0; i<size; i++ )

        {

            IAAFSmartPointer2<IAAFPropertyValue> nextValue;
            notAtEnd = axIter.NextOne(nextValue);

            if (notAtEnd)
            {
                AxPropertyValue value(nextValue);
                elements.append(this->GetInteger(nextValue,TypeDefIntSP));

            }

            _obj = elements;
        }

    }

}
<|endoftext|>


<commit_before>/*

Copyright (c) 2009, Arvid Norberg
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * 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.
    * Neither the name of the author 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 OWNER 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.

*/

#ifndef TORRENT_ADDRESS_HPP_INCLUDED
#define TORRENT_ADDRESS_HPP_INCLUDED

#include <boost/version.hpp>

#ifdef __OBJC__
#define Protocol Protocol_
#endif

#if defined TORRENT_WINDOWS || defined TORRENT_CYGWIN
// asio assumes that the windows error codes are defined already
#include <winsock2.h>
#endif

#if BOOST_VERSION < 103500
#include <asio/ip/address.hpp>
#else
#include <boost/asio/ip/address.hpp>
#endif

#ifdef __OBJC__
#undef Protocol
#endif

namespace libtorrent
{

#if BOOST_VERSION < 103500
	typedef ::asio::ip::address address;
	typedef ::asio::ip::address_v4 address_v4;
#if TORRENT_USE_IPV6
	typedef ::asio::ip::address_v6 address_v6;
#endif
#else
	typedef boost::asio::ip::address address;
	typedef boost::asio::ip::address_v4 address_v4;
#if TORRENT_USE_IPV6
	typedef boost::asio::ip::address_v6 address_v6;
#endif
#endif
}

#endif

<commit_msg>include config.hpp<commit_after>/*

Copyright (c) 2009, Arvid Norberg
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * 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.
    * Neither the name of the author 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 OWNER 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.

*/

#ifndef TORRENT_ADDRESS_HPP_INCLUDED
#define TORRENT_ADDRESS_HPP_INCLUDED

#include <boost/version.hpp>
#include "libtorrent/config.hpp"

#ifdef __OBJC__
#define Protocol Protocol_
#endif

#if defined TORRENT_WINDOWS || defined TORRENT_CYGWIN
// asio assumes that the windows error codes are defined already
#include <winsock2.h>
#endif

#if BOOST_VERSION < 103500
#include <asio/ip/address.hpp>
#else
#include <boost/asio/ip/address.hpp>
#endif

#ifdef __OBJC__
#undef Protocol
#endif

namespace libtorrent
{

#if BOOST_VERSION < 103500
	typedef ::asio::ip::address address;
	typedef ::asio::ip::address_v4 address_v4;
#if TORRENT_USE_IPV6
	typedef ::asio::ip::address_v6 address_v6;
#endif
#else
	typedef boost::asio::ip::address address;
	typedef boost::asio::ip::address_v4 address_v4;
#if TORRENT_USE_IPV6
	typedef boost::asio::ip::address_v6 address_v6;
#endif
#endif
}

#endif

<|endoftext|>


<commit_before>/*

Copyright (c) 2003, Arvid Norberg
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * 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.
    * Neither the name of the author 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 OWNER 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.

*/

#ifndef TORRENT_VERSION_HPP_INCLUDED
#define TORRENT_VERSION_HPP_INCLUDED

#define LIBTORRENT_VERSION_MAJOR 0
#define LIBTORRENT_VERSION_MINOR 13

#define LIBTORRENT_VERSION "0.13.0.0"

#endif
<commit_msg>bumped version number<commit_after>/*

Copyright (c) 2003, Arvid Norberg
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * 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.
    * Neither the name of the author 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 OWNER 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.

*/

#ifndef TORRENT_VERSION_HPP_INCLUDED
#define TORRENT_VERSION_HPP_INCLUDED

#define LIBTORRENT_VERSION_MAJOR 0
#define LIBTORRENT_VERSION_MINOR 14

#define LIBTORRENT_VERSION "0.14.0.0"

#endif
<|endoftext|>


<commit_before>/*
 * Portability.hh
 *
 * Copyright 2001, LifeLine Networks BV (www.lifeline.nl). All rights reserved.
 * Copyright 2001, Bastiaan Bakker. All rights reserved.
 *
 * See the COPYING file for the terms of usage and distribution.
 */

#ifndef _LOG4CPP_PORTABILITY_HH
#define _LOG4CPP_PORTABILITY_HH

#if defined (_MSC_VER) || defined(__BORLANDC__)
#    include <log4cpp/config-win32.h>
#else
#if defined(__OPENVMS__)
#    include <log4cpp/config-openvms.h>
#else
#    include <log4cpp/config.h>
#endif
#endif

#include <log4cpp/Export.hh>

#if defined(_MSC_VER)
#    pragma warning( disable : 4786 )
#endif

#endif
<commit_msg>Disable exception specifier warnings (issue #536668)<commit_after>/*
 * Portability.hh
 *
 * Copyright 2001, LifeLine Networks BV (www.lifeline.nl). All rights reserved.
 * Copyright 2001, Bastiaan Bakker. All rights reserved.
 *
 * See the COPYING file for the terms of usage and distribution.
 */

#ifndef _LOG4CPP_PORTABILITY_HH
#define _LOG4CPP_PORTABILITY_HH

#if defined (_MSC_VER) || defined(__BORLANDC__)
#    include <log4cpp/config-win32.h>
#else
#if defined(__OPENVMS__)
#    include <log4cpp/config-openvms.h>
#else
#    include <log4cpp/config.h>
#endif
#endif

#include <log4cpp/Export.hh>

#if defined(_MSC_VER)
#    pragma warning( disable : 4786 )
#    pragma warning( disable : 4290 )
#endif

#endif
<|endoftext|>


<commit_before>/*!
  @file PDBWriter.hpp
  @brief pdb writer.

  write pdb atoms or chains into output stream.

  @author Toru Niina (niina.toru.68u@gmail.com)
  @date 2016-10-18 10:00
  @copyright Toru Niina 2016 on MIT License
*/
#ifndef COFFEE_MILL_PDB_WRITER_HPP
#define COFFEE_MILL_PDB_WRITER_HPP
#include <mill/common/Trajectory.hpp>
#include <mill/common/WriterBase.hpp>
#include <mill/util/logger.hpp>
#include <iomanip>
#include <fstream>
#include <cstdio>

namespace mill
{

class PDBWriter final : public WriterBase
{
  public:
    using base_type                = WriterBase;
    using trajectory_type          = base_type::trajectory_type;
    using snapshot_type            = base_type::snapshot_type;
    using particle_type            = base_type::particle_type;
    using attribute_container_type = base_type::attribute_container_type;

    PDBWriter(const std::string_view fname)
        : current_(0), file_name_(fname), pdb_(file_name_)
    {
        if(!pdb_.good())
        {
            log::fatal("PDBWriter: file open error: ", fname);
        }
    }
    ~PDBWriter() override = default;

    void write_header(const attribute_container_type& header) override
    {
        if(header.count("boundary_width") != 0)
        {
            const auto w = header.at("boundary_width").as_vector();
            // 80 chars + line feed + null
            std::array<char, 82> buffer; buffer.fill('\0');
            std::snprintf(buffer.data(), buffer.size(),
                          "CRYST1%9.3f%9.3f%9.3f%7.2f%7.2f%7.2f%-10s%4d\n",
                          w[0], w[1], w[2], 90.0, 90.0, 90.0, "P 1", 1);
            pdb_ << buffer.data();
        }
        return; // xyz does not have any header info
    }
    void write(const trajectory_type& traj) override
    {
        for(const auto& frame : traj)
        {
            this->write_frame(frame);
        }
        return;
    }
    void write_frame(const snapshot_type& frame) override
    {
        using namespace std::literals::string_literals;
        this->current_ += 1;
        this->pdb_ << "MODEL     "
                   << std::setw(4) << std::right << this->current_ << '\n';

        char chain = '\0';
        std::int64_t serial = 0;
        for(const auto& p : frame)
        {
            serial += 1;
            const auto atom          = p.at("name"    ).try_string().value_or(" C  "s);
            const auto current_chain = p.at("chain_id").try_string().value_or("A"s).front();

            // 80 chars + line feed + null
            std::array<char, 82> buffer; buffer.fill('\0');
            std::snprintf(buffer.data(), buffer.size(),
                "%-6s%5lld %4s%c%3s %c%4lld%c   %8.3f%8.3f%8.3f%6.2f%6.2f          %2s%2s\n",
                p.at("record"  ).try_string() .value_or("ATOM  "s).c_str(),
                static_cast<long long int>(p.at("serial"  ).try_integer().value_or(serial)),
                p.at("name"    ).try_string() .value_or(" C  "s).c_str(),
                p.at("alt_loc" ).try_string() .value_or(" "s).front(),
                p.at("res_name").try_string() .value_or("XXX"s).c_str(),
                p.at("chain_id").try_string() .value_or("A"s).front(),
                static_cast<long long int>(p.at("res_seq" ).try_integer().value_or(serial)),
                p.at("i_code"  ).try_string() .value_or(" "s).front(),
                p.position()[0],
                p.position()[1],
                p.position()[2],
                p.at("occupancy"  ).try_floating().value_or(  0.0),
                p.at("temp_factor").try_floating().value_or(999.9),
                p.at("element"    ).try_string()  .value_or(atom.substr(0, 2)).c_str(),
                p.at("charge"     ).try_string()  .value_or("  "s).c_str());
            pdb_ << buffer.data();

            if(chain != '\0' && chain != current_chain)
            {
                pdb_ << "TER\n";
            }
            chain = current_chain;
        }
        pdb_ << "TER\n";
        pdb_ << "ENDMDL\n";
        return;
    }

    std::size_t      size()      const noexcept override {return current_;}
    std::string_view file_name() const noexcept override {return file_name_;}

  private:

    std::size_t current_;
    std::string file_name_;
    std::ofstream pdb_;

};

} // mill
#endif /* COFFEE_MILL_PDB_WRITER */
<commit_msg>:children_crossing: avoid map::at for informative error message<commit_after>/*!
  @file PDBWriter.hpp
  @brief pdb writer.

  write pdb atoms or chains into output stream.

  @author Toru Niina (niina.toru.68u@gmail.com)
  @date 2016-10-18 10:00
  @copyright Toru Niina 2016 on MIT License
*/
#ifndef COFFEE_MILL_PDB_WRITER_HPP
#define COFFEE_MILL_PDB_WRITER_HPP
#include <mill/common/Trajectory.hpp>
#include <mill/common/WriterBase.hpp>
#include <mill/util/logger.hpp>
#include <iomanip>
#include <fstream>
#include <cstdio>

namespace mill
{

class PDBWriter final : public WriterBase
{
  public:
    using base_type                = WriterBase;
    using trajectory_type          = base_type::trajectory_type;
    using snapshot_type            = base_type::snapshot_type;
    using particle_type            = base_type::particle_type;
    using attribute_container_type = base_type::attribute_container_type;

    PDBWriter(const std::string_view fname)
        : current_(0), file_name_(fname), pdb_(file_name_)
    {
        if(!pdb_.good())
        {
            log::fatal("PDBWriter: file open error: ", fname);
        }
    }
    ~PDBWriter() override = default;

    void write_header(const attribute_container_type& header) override
    {
        if(header.count("boundary_width") != 0)
        {
            const auto w = header.at("boundary_width").as_vector();
            // 80 chars + line feed + null
            std::array<char, 82> buffer; buffer.fill('\0');
            std::snprintf(buffer.data(), buffer.size(),
                          "CRYST1%9.3f%9.3f%9.3f%7.2f%7.2f%7.2f%-10s%4d\n",
                          w[0], w[1], w[2], 90.0, 90.0, 90.0, "P 1", 1);
            pdb_ << buffer.data();
        }
        return; // xyz does not have any header info
    }
    void write(const trajectory_type& traj) override
    {
        for(const auto& frame : traj)
        {
            this->write_frame(frame);
        }
        return;
    }
    void write_frame(const snapshot_type& frame) override
    {
        using namespace std::literals::string_literals;
        this->current_ += 1;
        this->pdb_ << "MODEL     "
                   << std::setw(4) << std::right << this->current_ << '\n';

        char chain = '\0';
        std::int64_t serial = 0;
        for(const auto& p : frame)
        {
            serial += 1;
            const auto atom          = p.at("name"    ).try_string().value_or(" C  "s);
            const auto current_chain = p.at("chain_id").try_string().value_or("A"s).front();

            // 80 chars + line feed + null
            std::array<char, 82> buffer; buffer.fill('\0');
            std::snprintf(buffer.data(), buffer.size(),
                "%-6s%5lld %4s%c%3s %c%4lld%c   %8.3f%8.3f%8.3f%6.2f%6.2f          %2s%2s\n",
                p.try_string("record"  ).value_or("ATOM  "s).c_str(),
                static_cast<long long>(p.try_integer("serial"  ).value_or(serial)),
                p.try_string("name"    ).value_or(" C  "s).c_str(),
                p.try_string("alt_loc" ).value_or(" "s).front(),
                p.try_string("res_name").value_or("XXX"s).c_str(),
                p.try_string("chain_id").value_or("A"s).front(),
                static_cast<long long>(p.try_integer("res_seq" ).value_or(serial)),
                p.try_string("i_code"  ).value_or(" "s).front(),
                p.position()[0],
                p.position()[1],
                p.position()[2],
                p.try_floating("occupancy"  ).value_or(  0.0),
                p.try_floating("temp_factor").value_or(999.9),
                p.try_string  ("element"    ).value_or(atom.substr(0, 2)).c_str(),
                p.try_string  ("charge"     ).value_or("  "s).c_str());
            pdb_ << buffer.data();

            if(chain != '\0' && chain != current_chain)
            {
                pdb_ << "TER\n";
            }
            chain = current_chain;
        }
        pdb_ << "TER\n";
        pdb_ << "ENDMDL\n";
        return;
    }

    std::size_t      size()      const noexcept override {return current_;}
    std::string_view file_name() const noexcept override {return file_name_;}

  private:

    std::size_t current_;
    std::string file_name_;
    std::ofstream pdb_;

};

} // mill
#endif /* COFFEE_MILL_PDB_WRITER */
<|endoftext|>


<commit_before>/**
  * Touhou Community Reliant Automatic Patcher
  * Main DLL
  *
  * ----
  *
  * Binary hack handling.
  */

#include "thcrap.h"
#include <math.h>
#include <locale.h>

/*
 * Grumble, grumble, C is garbage and will only do string→float conversion
 * using the decimal separator from the current locale, and OF COURSE it never
 * occured to anyone, not even Microsoft, to provide a neutral strtod() that
 * always looks for a decimal point, and so we have to dynamically allocate
 * (and free) The Neutral Locale instead. C is garbage.
 */
_locale_t lc_neutral = nullptr;

int hackpoints_error_function_not_found(const char *func_name, int retval)
{
	log_printf("ERROR: function '%s' not found! "
#ifdef _DEBUG
		"(implementation not exported or still missing?)"
#else
		"(outdated or corrupt %s installation, maybe?)"
#endif
		"\n", func_name, PROJECT_NAME_SHORT()
	);
	return retval;
}

int is_valid_hex(char c)
{
	return
		('0' <= c && c <= '9') ||
		('A' <= c && c <= 'F') ||
		('a' <= c && c <= 'f');
}

enum value_type_t {
	VT_NONE = 0,
	VT_BYTE = 1, // sizeof(char)
	VT_FLOAT = 4, // sizeof(float)
	VT_DOUBLE = 8 // sizeof(double)
};

struct value_t {
	value_type_t type = VT_NONE;
	union {
		unsigned char b;
		float f;
		double d;
	};

	size_t size() {
		return (size_t)type;
	}
};

// Returns false only if parsing should be aborted.
bool consume_value(value_t &val, const char** str)
{
	assert(str);

	const char *c = *str;

	// Double / float
	if(*c == '+' || *c == '-') {
		if(!lc_neutral) {
			lc_neutral = _create_locale(LC_NUMERIC, "C");
		}
		char *endptr;

		errno = 0;
		double result = _strtod_l(*str, &endptr, lc_neutral);
		if(errno == ERANGE && (result == HUGE_VAL || result == -HUGE_VAL)) {
			auto val_len = (endptr - *str);
			log_printf(
				"ERROR: Floating point constant \"%.*s\" out of range!\n",
				val_len, str
			);
			return false;
		} else if(endptr == *str) {
			// Not actually a floating-point number, keep going though
			*str += 1;
			return true;
		}
		if(*endptr == 'f') {
			val.type = VT_FLOAT;
			val.f = (float)result;
			endptr++;
		} else {
			val.type = VT_DOUBLE;
			val.d = result;
		}
		if(*endptr != ' ' && *endptr != '\0') {
			val.type = VT_NONE;
			*str += 1;
		} else {
			*str = endptr;
		}
	}
	// Byte
	else if(is_valid_hex(c[0]) && is_valid_hex(c[1])) {
		char conv[3];
		conv[2] = 0;
		memcpy(conv, *str, 2);
		val.type = VT_BYTE;
		val.b = (unsigned char)strtol(conv, nullptr, 16);
		*str += 2;
	}
	// Nothing, keep going
	else {
		*str += 1;
	}
	return true;
}

size_t binhack_calc_size(const char *binhack_str)
{
	size_t size = 0;
	const char *c = binhack_str;
	const char *fs = NULL; // function start
	if(!binhack_str) {
		return 0;
	}
	while(*c) {
		if(*c == '[' || *c == '<') {
			if(fs) {
				log_printf("ERROR: Nested function pointers near %s!\n", c);
				return 0;
			}
			fs = c + 1;
			c++;
		} else if(fs) {
			if((*c == ']' || *c == '>')) {
				size += sizeof(void*);
				fs = nullptr;
			}
			c++;
		} else {
			value_t val;
			if(!consume_value(val, &c)) {
				return 0;
			}
			size += val.size();
		}
	}
	if(fs) {
		log_printf("ERROR: Function name '%s' not terminated...\n", fs);
		size = 0;
	}
	return size;
}

int binhack_render(BYTE *binhack_buf, size_t target_addr, const char *binhack_str)
{
	const char *c = binhack_str;
	const char *fs = NULL; // function start
	size_t written = 0;
	int func_rel = 0; // Relative function pointer flag
	int ret = 0;

	if(!binhack_buf || !binhack_str) {
		return -1;
	}

	while(*c) {
		if(*c == '[' || *c == '<') {
			if(fs) {
				log_printf("ERROR: Nested function pointers near %s!\n", c);
				return 0;
			}
			func_rel = (*c == '[');
			fs = c + 1;
			c++;
		} else if(fs && (*c == ']' || *c == '>')) {
			VLA(char, function, (c - fs) + 1);
			size_t fp = 0;

			strncpy(function, fs, c - fs);
			function[c - fs] = 0;

			fp = (size_t)func_get(function);
			if(fp) {
				if(func_rel) {
					fp -= target_addr + written + sizeof(void*);
				}
				memcpy(binhack_buf, &fp, sizeof(void*));
				binhack_buf += sizeof(void*);
				written += sizeof(void*);
			} else {
				return hackpoints_error_function_not_found(function, 2);
			}
			fs = NULL;
			VLA_FREE(function);
			if(ret) {
				break;
			}
			c++;
		} else if(fs) {
			c++;
		} else {
			value_t val;
			if(!consume_value(val, &c)) {
				return 1;
			}
			const char *copy_ptr = nullptr;
			switch(val.type) {
			case VT_BYTE:   copy_ptr = (const char *)&val.b; break;
			case VT_FLOAT:  copy_ptr = (const char *)&val.f; break;
			case VT_DOUBLE: copy_ptr = (const char *)&val.d; break;
			default:        break; // -Wswitch...
			}
			if(copy_ptr) {
				binhack_buf = (BYTE *)memcpy_advance_dst(
					(char *)binhack_buf, copy_ptr, val.size()
				);
				written += val.size();
			}
		}
	}
	if(fs) {
		log_printf("ERROR: Function name '%s' not terminated...\n", fs);
		ret = 1;
	}
	return ret;
}

size_t hackpoints_count(json_t *hackpoints)
{
	int ret = 0;
	const char *key;
	json_t *obj;
	json_object_foreach(hackpoints, key, obj) {
		json_t *addr = json_object_get(obj, "addr");
		ret += json_flex_array_size(addr);
	}
	return ret;
}

int binhacks_apply(json_t *binhacks, HMODULE hMod)
{
	const char *key;
	json_t *hack;
	size_t binhack_count = hackpoints_count(binhacks);
	size_t c = 0;
	int failed = binhack_count;

	if(!binhack_count) {
		log_printf("No binary hacks to apply.\n");
		return 0;
	}

	log_printf("Applying binary hacks...\n");
	log_printf("------------------------\n");

	json_object_foreach(binhacks, key, hack) {
		auto ignore = json_object_get(hack, "ignore");
		if(json_is_true(ignore)) {
			continue;
		}
		const char *title = json_object_get_string(hack, "title");
		const char *code = json_object_get_string(hack, "code");
		const char *expected = json_object_get_string(hack, "expected");
		// Addresses can be an array, too
		json_t *json_addr = json_object_get(hack, "addr");
		size_t i;
		json_t *addr_val;

		// calculated byte size of the hack
		size_t asm_size = binhack_calc_size(code);
		size_t exp_size = binhack_calc_size(expected);
		if(!asm_size) {
			continue;
		}

		VLA(BYTE, asm_buf, asm_size);
		VLA(BYTE, exp_buf, exp_size);
		json_flex_array_foreach(json_addr, i, addr_val) {
			auto addr = str_address_value(json_string_value(addr_val), hMod, NULL);
			if(!addr) {
				continue;
			}
			log_printf("(%2d/%2d) 0x%p ", ++c, binhack_count, addr);
			if(title) {
				log_printf("%s (%s)... ", title, key);
			} else {
				log_printf("%s...", key);
			}
			if(binhack_render(asm_buf, addr, code)) {
				continue;
			}
			if(exp_size > 0 && exp_size != asm_size) {
				log_printf("different sizes for expected and new code, skipping verification... ");
				exp_size = 0;
			} else if(binhack_render(exp_buf, addr, expected)) {
				exp_size = 0;
			}
			if(PatchRegion((void*)addr, exp_size ? exp_buf : NULL, asm_buf, asm_size)) {
				log_printf("OK\n");
				failed--;
			} else {
				log_printf("expected bytes not matched, skipping...\n");
			}
		}
		VLA_FREE(asm_buf);
		VLA_FREE(exp_buf);
	}
	log_printf("------------------------\n");
	return failed;
}

extern "C" __declspec(dllexport) void binhack_mod_exit()
{
	SAFE_CLEANUP(_free_locale, lc_neutral);
}
<commit_msg>thcrap: Binary hacks: Avoid a potential VLA leak with unknown functions.<commit_after>/**
  * Touhou Community Reliant Automatic Patcher
  * Main DLL
  *
  * ----
  *
  * Binary hack handling.
  */

#include "thcrap.h"
#include <math.h>
#include <locale.h>

/*
 * Grumble, grumble, C is garbage and will only do string→float conversion
 * using the decimal separator from the current locale, and OF COURSE it never
 * occured to anyone, not even Microsoft, to provide a neutral strtod() that
 * always looks for a decimal point, and so we have to dynamically allocate
 * (and free) The Neutral Locale instead. C is garbage.
 */
_locale_t lc_neutral = nullptr;

int hackpoints_error_function_not_found(const char *func_name, int retval)
{
	log_printf("ERROR: function '%s' not found! "
#ifdef _DEBUG
		"(implementation not exported or still missing?)"
#else
		"(outdated or corrupt %s installation, maybe?)"
#endif
		"\n", func_name, PROJECT_NAME_SHORT()
	);
	return retval;
}

int is_valid_hex(char c)
{
	return
		('0' <= c && c <= '9') ||
		('A' <= c && c <= 'F') ||
		('a' <= c && c <= 'f');
}

enum value_type_t {
	VT_NONE = 0,
	VT_BYTE = 1, // sizeof(char)
	VT_FLOAT = 4, // sizeof(float)
	VT_DOUBLE = 8 // sizeof(double)
};

struct value_t {
	value_type_t type = VT_NONE;
	union {
		unsigned char b;
		float f;
		double d;
	};

	size_t size() {
		return (size_t)type;
	}
};

// Returns false only if parsing should be aborted.
bool consume_value(value_t &val, const char** str)
{
	assert(str);

	const char *c = *str;

	// Double / float
	if(*c == '+' || *c == '-') {
		if(!lc_neutral) {
			lc_neutral = _create_locale(LC_NUMERIC, "C");
		}
		char *endptr;

		errno = 0;
		double result = _strtod_l(*str, &endptr, lc_neutral);
		if(errno == ERANGE && (result == HUGE_VAL || result == -HUGE_VAL)) {
			auto val_len = (endptr - *str);
			log_printf(
				"ERROR: Floating point constant \"%.*s\" out of range!\n",
				val_len, str
			);
			return false;
		} else if(endptr == *str) {
			// Not actually a floating-point number, keep going though
			*str += 1;
			return true;
		}
		if(*endptr == 'f') {
			val.type = VT_FLOAT;
			val.f = (float)result;
			endptr++;
		} else {
			val.type = VT_DOUBLE;
			val.d = result;
		}
		if(*endptr != ' ' && *endptr != '\0') {
			val.type = VT_NONE;
			*str += 1;
		} else {
			*str = endptr;
		}
	}
	// Byte
	else if(is_valid_hex(c[0]) && is_valid_hex(c[1])) {
		char conv[3];
		conv[2] = 0;
		memcpy(conv, *str, 2);
		val.type = VT_BYTE;
		val.b = (unsigned char)strtol(conv, nullptr, 16);
		*str += 2;
	}
	// Nothing, keep going
	else {
		*str += 1;
	}
	return true;
}

size_t binhack_calc_size(const char *binhack_str)
{
	size_t size = 0;
	const char *c = binhack_str;
	const char *fs = NULL; // function start
	if(!binhack_str) {
		return 0;
	}
	while(*c) {
		if(*c == '[' || *c == '<') {
			if(fs) {
				log_printf("ERROR: Nested function pointers near %s!\n", c);
				return 0;
			}
			fs = c + 1;
			c++;
		} else if(fs) {
			if((*c == ']' || *c == '>')) {
				size += sizeof(void*);
				fs = nullptr;
			}
			c++;
		} else {
			value_t val;
			if(!consume_value(val, &c)) {
				return 0;
			}
			size += val.size();
		}
	}
	if(fs) {
		log_printf("ERROR: Function name '%s' not terminated...\n", fs);
		size = 0;
	}
	return size;
}

int binhack_render(BYTE *binhack_buf, size_t target_addr, const char *binhack_str)
{
	const char *c = binhack_str;
	const char *fs = NULL; // function start
	size_t written = 0;
	int func_rel = 0; // Relative function pointer flag
	int ret = 0;

	if(!binhack_buf || !binhack_str) {
		return -1;
	}

	while(*c) {
		if(*c == '[' || *c == '<') {
			if(fs) {
				log_printf("ERROR: Nested function pointers near %s!\n", c);
				return 0;
			}
			func_rel = (*c == '[');
			fs = c + 1;
			c++;
		} else if(fs && (*c == ']' || *c == '>')) {
			VLA(char, function, (c - fs) + 1);
			defer({ VLA_FREE(function); });
			size_t fp = 0;

			strncpy(function, fs, c - fs);
			function[c - fs] = 0;

			fp = (size_t)func_get(function);
			if(fp) {
				if(func_rel) {
					fp -= target_addr + written + sizeof(void*);
				}
				memcpy(binhack_buf, &fp, sizeof(void*));
				binhack_buf += sizeof(void*);
				written += sizeof(void*);
			} else {
				return hackpoints_error_function_not_found(function, 2);
			}
			fs = NULL;
			if(ret) {
				break;
			}
			c++;
		} else if(fs) {
			c++;
		} else {
			value_t val;
			if(!consume_value(val, &c)) {
				return 1;
			}
			const char *copy_ptr = nullptr;
			switch(val.type) {
			case VT_BYTE:   copy_ptr = (const char *)&val.b; break;
			case VT_FLOAT:  copy_ptr = (const char *)&val.f; break;
			case VT_DOUBLE: copy_ptr = (const char *)&val.d; break;
			default:        break; // -Wswitch...
			}
			if(copy_ptr) {
				binhack_buf = (BYTE *)memcpy_advance_dst(
					(char *)binhack_buf, copy_ptr, val.size()
				);
				written += val.size();
			}
		}
	}
	if(fs) {
		log_printf("ERROR: Function name '%s' not terminated...\n", fs);
		ret = 1;
	}
	return ret;
}

size_t hackpoints_count(json_t *hackpoints)
{
	int ret = 0;
	const char *key;
	json_t *obj;
	json_object_foreach(hackpoints, key, obj) {
		json_t *addr = json_object_get(obj, "addr");
		ret += json_flex_array_size(addr);
	}
	return ret;
}

int binhacks_apply(json_t *binhacks, HMODULE hMod)
{
	const char *key;
	json_t *hack;
	size_t binhack_count = hackpoints_count(binhacks);
	size_t c = 0;
	int failed = binhack_count;

	if(!binhack_count) {
		log_printf("No binary hacks to apply.\n");
		return 0;
	}

	log_printf("Applying binary hacks...\n");
	log_printf("------------------------\n");

	json_object_foreach(binhacks, key, hack) {
		auto ignore = json_object_get(hack, "ignore");
		if(json_is_true(ignore)) {
			continue;
		}
		const char *title = json_object_get_string(hack, "title");
		const char *code = json_object_get_string(hack, "code");
		const char *expected = json_object_get_string(hack, "expected");
		// Addresses can be an array, too
		json_t *json_addr = json_object_get(hack, "addr");
		size_t i;
		json_t *addr_val;

		// calculated byte size of the hack
		size_t asm_size = binhack_calc_size(code);
		size_t exp_size = binhack_calc_size(expected);
		if(!asm_size) {
			continue;
		}

		VLA(BYTE, asm_buf, asm_size);
		VLA(BYTE, exp_buf, exp_size);
		json_flex_array_foreach(json_addr, i, addr_val) {
			auto addr = str_address_value(json_string_value(addr_val), hMod, NULL);
			if(!addr) {
				continue;
			}
			log_printf("(%2d/%2d) 0x%p ", ++c, binhack_count, addr);
			if(title) {
				log_printf("%s (%s)... ", title, key);
			} else {
				log_printf("%s...", key);
			}
			if(binhack_render(asm_buf, addr, code)) {
				continue;
			}
			if(exp_size > 0 && exp_size != asm_size) {
				log_printf("different sizes for expected and new code, skipping verification... ");
				exp_size = 0;
			} else if(binhack_render(exp_buf, addr, expected)) {
				exp_size = 0;
			}
			if(PatchRegion((void*)addr, exp_size ? exp_buf : NULL, asm_buf, asm_size)) {
				log_printf("OK\n");
				failed--;
			} else {
				log_printf("expected bytes not matched, skipping...\n");
			}
		}
		VLA_FREE(asm_buf);
		VLA_FREE(exp_buf);
	}
	log_printf("------------------------\n");
	return failed;
}

extern "C" __declspec(dllexport) void binhack_mod_exit()
{
	SAFE_CLEANUP(_free_locale, lc_neutral);
}
<|endoftext|>