<commit_before>/**************************************************************************
 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
 *                                                                        *
 * Author: The ALICE Off-line Project.                                    *
 * Contributors are mentioned in the code where appropriate.              *
 *                                                                        *
 * Permission to use, copy, modify and distribute this software and its   *
 * documentation strictly for non-commercial purposes is hereby granted   *
 * without fee, provided that the above copyright notice appears in all   *
 * copies and that both the copyright notice and this permission notice   *
 * appear in the supporting documentation. The authors make no claims     *
 * about the suitability of this software for any purpose. It is          *
 * provided "as is" without express or implied warranty.                  *
 **************************************************************************/

// $Id$

#include "AliMUONDigitCalibrator.h"

#include "AliLog.h"
#include "AliMUONCalibrationData.h"
#include "AliMUONLogger.h"
#include "AliMUONPadStatusMaker.h"
#include "AliMUONPadStatusMapMaker.h"
#include "AliMUONRecoParam.h"
#include "AliMUONVCalibParam.h"
#include "AliMUONVDigit.h"
#include "AliMUONVDigitStore.h"
#include "AliMUONVStore.h"
#include "AliMpBusPatch.h"
#include "AliMpConstants.h"
#include "AliMpCDB.h"
#include "AliMpDDLStore.h"
#include "AliMpDEIterator.h"
#include "AliMpDetElement.h"
#include "AliMpManuStore.h"

//-----------------------------------------------------------------------------
/// \class AliMUONDigitCalibrator
/// Class used to calibrate digits (either real or simulated ones).
///
/// The calibration consists of subtracting the pedestal
/// and multiplying by a gain, so that
/// Signal = (ADC-pedestal)*gain
///
/// Please note also that for the moment, if a digit lies on a dead channel
/// we remove this digit from the list of digits.
/// FIXME: this has to be revisited. By using the AliMUONDigit::fFlags we
/// should in principle flag a digit as bad w/o removing it, but this
/// then requires some changes in the cluster finder to deal with this extra
/// information correctly (e.g. to set a quality for the cluster if it contains
/// bad digits).
///
/// \author Laurent Aphecetche
//-----------------------------------------------------------------------------

/// \cond CLASSIMP
ClassImp(AliMUONDigitCalibrator)
/// \endcond

const Int_t AliMUONDigitCalibrator::fgkNoGain(0);
const Int_t AliMUONDigitCalibrator::fgkGainConstantCapa(1);
const Int_t AliMUONDigitCalibrator::fgkGain(2);
const Int_t AliMUONDigitCalibrator::fgkInjectionGain(3);

//_____________________________________________________________________________
AliMUONDigitCalibrator::AliMUONDigitCalibrator(const AliMUONCalibrationData& calib,
                                               const AliMUONRecoParam* recoParams,
                                               const char* calibMode)
: TObject(),
fLogger(new AliMUONLogger(20000)),
fStatusMaker(0x0),
fStatusMapMaker(0x0),
fPedestals(0x0),
fGains(0x0),
fApplyGains(0),
fCapacitances(0x0),
fNumberOfBadPads(0),
fNumberOfPads(0),
fChargeSigmaCut(0),
fMask(0)
{
  /// ctor

  Ctor(calibMode,calib,recoParams);
}

//_____________________________________________________________________________
AliMUONDigitCalibrator::AliMUONDigitCalibrator(const AliMUONCalibrationData& calib,
                                               const char* calibMode)
: TObject(),
fLogger(new AliMUONLogger(20000)),
fStatusMaker(0x0),
fStatusMapMaker(0x0),
fPedestals(0x0),
fGains(0x0),
fApplyGains(0),
fCapacitances(0x0),
fNumberOfBadPads(0),
fNumberOfPads(0),
fChargeSigmaCut(0),
fMask(0)
{
  /// ctor

  Ctor(calibMode,calib,0x0);
}

//_____________________________________________________________________________
void
AliMUONDigitCalibrator::Ctor(const char* calibMode,
                             const AliMUONCalibrationData& calib,
                             const AliMUONRecoParam* recoParams)
{
  /// designated ctor

  TString cMode(calibMode);
  cMode.ToUpper();

  if ( cMode == "NOGAIN" )
  {
    fApplyGains = fgkNoGain;
    AliInfo("Will NOT apply gain correction");
  }
  else if ( cMode == "GAINCONSTANTCAPA" )
  {
    fApplyGains = fgkGainConstantCapa;
    AliInfo("Will apply gain correction, but with constant capacitance");
  }
  else if ( cMode == "GAIN" )
  {
    fApplyGains = fgkGain;
    AliInfo("Will apply gain correction, with measured capacitances");
  }
  else if ( cMode == "INJECTIONGAIN")
	{
		fApplyGains = fgkInjectionGain;
    AliInfo("Will apply injection gain correction, with EMELEC factory gains");
	}
  else
  {
    AliError(Form("Invalid calib mode = %s. Will use NOGAIN instead",calibMode));
    fApplyGains = fgkNoGain;
  }

  // Load mapping manu store
  if ( ! AliMpCDB::LoadManuStore() ) {
    AliFatal("Could not access manu store from OCDB !");
  }

  fStatusMaker = new AliMUONPadStatusMaker(calib);

  // Set default values, as loose as reasonable

  fChargeSigmaCut = 3.0;

	fMask = 0x8080; // reject pads where ped *or* hv are missing

	if ( recoParams )
	{
    // if we have reco params, we use limits and cuts from there :

    fStatusMaker->SetLimits(*recoParams);

    fMask = recoParams->PadGoodnessMask();
		//WARNING : getting this mask wrong is a very effective way of getting
		//no digits at all out of this class ;-)

    fChargeSigmaCut = recoParams->ChargeSigmaCut();
	}

  Bool_t deferredInitialization = kTRUE;

  fStatusMapMaker = new AliMUONPadStatusMapMaker(*fStatusMaker,fMask,deferredInitialization);

  fPedestals = calib.Pedestals();

  fGains = calib.Gains(); // we get gains whatever the calibMode is, in order
  // to get the saturation value...

  if ( fApplyGains == fgkGain || fApplyGains == fgkInjectionGain )
  {
    fCapacitances = calib.Capacitances();
  }
}

//_____________________________________________________________________________
AliMUONDigitCalibrator::~AliMUONDigitCalibrator()
{
  /// dtor.

  if ( fNumberOfPads > 0 )
  {
    if ( fStatusMaker )
    {
      fStatusMaker->Report(fMask);
    }

    AliInfo("Summary of messages:");

    fLogger->Print();

    AliInfo(Form("We have seen %g pads, and rejected %g (%7.2f %%)",
                 fNumberOfPads,fNumberOfBadPads,
                 ( fNumberOfPads > 0 ) ? fNumberOfBadPads*100.0/fNumberOfPads : 0 ));
	}

  delete fStatusMaker;
  delete fStatusMapMaker;
  delete fLogger;
}

//_____________________________________________________________________________
void
AliMUONDigitCalibrator::Calibrate(AliMUONVDigitStore& digitStore)
{
  /// Calibrate the digits contained in digitStore
  TIter next(digitStore.CreateTrackerIterator());
  AliMUONVDigit* digit;

  fStatusMapMaker->RefreshRejectProbabilities(); // this will do something only for simulations
  // (and only for those simulations where the reject list contain probabilities which are
  // different from zero or one)

  AliDebug(1,Form("# of digits = %d",digitStore.GetSize()));

  while ( ( digit = static_cast<AliMUONVDigit*>(next() ) ) )
  {
    if ( digit->IsCalibrated() )
    {
      fLogger->Log("ERROR : trying to calibrate a digit twice");
      return;
    }

    digit->Calibrated(kTRUE);

    Float_t charge(0.0);
    Int_t statusMap;
    Bool_t isSaturated(kFALSE);

    ++fNumberOfPads;

    Bool_t ok = IsValidDigit(digit->DetElemId(),digit->ManuId(),digit->ManuChannel(),&statusMap);

    digit->SetStatusMap(statusMap);

    if (ok)
    {
      charge = CalibrateDigit(digit->DetElemId(),digit->ManuId(),digit->ManuChannel(),
                              digit->ADC(),fChargeSigmaCut,&isSaturated);
    }
    else
    {
      ++fNumberOfBadPads;
    }

    digit->SetCharge(charge);
    digit->Saturated(isSaturated);
  }
}

//_____________________________________________________________________________
Float_t
AliMUONDigitCalibrator::CalibrateDigit(Int_t detElemId, Int_t manuId, Int_t manuChannel,
                                       Float_t adc, Float_t nsigmas,
                                       Bool_t* isSaturated) const

{
  /// Calibrate one digit
  /// Return the digit charge, in fC

  AliMUONVCalibParam* pedestal = static_cast<AliMUONVCalibParam*>
  (fPedestals->FindObject(detElemId,manuId));

  if (!pedestal)
  {
    // no pedestal -> no charge
    fLogger->Log(Form("Got a null pedestal object for DE,manu=%d,%d",detElemId,manuId));
    return 0.0;
  }

  AliMUONVCalibParam* gain = static_cast<AliMUONVCalibParam*>
  (fGains->FindObject(detElemId,manuId));

  if (!gain)
  {
    if ( fApplyGains != fgkNoGain )
    {
      // no gain -> no charge
      fLogger->Log(Form("Got a null gain object for DE,manu=%d,%d",
                        detElemId,manuId));
      return 0.0;
    }
  }

  Float_t padc = adc-pedestal->ValueAsFloat(manuChannel,0);

	// Gain (mV/fC) = 1/(a0*capa) with a0~1.25 and capa~0.2
  Float_t charge(0);
  Float_t capa(0.2); // capa = 0.2 and a0 = 1.25
	Float_t a0(1.25);  // is equivalent to gain = 4 mV/fC
	Float_t a1(0);
	Float_t adc2mv(0.61); // 1 ADC channel = 0.61 mV
	Float_t injGain(4); // By default the gain is set to 4 mV/fC
  //
  // Note that the ChargeMax (for one pad) is roughly 4096 * 0.61 mV/channel / 4 mV/fC = 625 fC

  if ( fApplyGains == fgkGain || fApplyGains == fgkInjectionGain )
  {
    Int_t serialNumber
    = AliMpManuStore::Instance()->GetManuSerial(detElemId, manuId);

    AliMUONVCalibParam* param = static_cast<AliMUONVCalibParam*>(fCapacitances->FindObject(serialNumber));

    if ( param )
    {
      capa = param->ValueAsFloat(manuChannel,0);
			injGain = param->ValueAsFloat(manuChannel,1);
      if ( injGain < 0 )
      {
        fLogger->Log(Form("injGain is %e < 0 for serialNumber=%d",injGain,serialNumber));
        return 0.0;
      }
    }
    else
    {
      // If capa not found in the OCDB we exit
	    fLogger->Log(Form("No capa (injGain) found for serialNumber=%d",serialNumber));
			return 0.0;
    }
  }

  if ( padc > nsigmas*pedestal->ValueAsFloat(manuChannel,1) )
  {
    if ( fApplyGains == fgkGain || fApplyGains == fgkGainConstantCapa )
    {
      a0 = gain->ValueAsFloat(manuChannel,0);
      a1 = gain->ValueAsFloat(manuChannel,1);
      Int_t thres = gain->ValueAsInt(manuChannel,2);
      if ( padc < thres )
      {
        charge = a0*padc;
      }
      else
      {
        charge = a0*thres + a0*(padc-thres) + a1*(padc-thres)*(padc-thres);
      }
			charge *= capa*adc2mv;
    }
    else if ( fApplyGains == fgkInjectionGain )
    {

      charge = padc*adc2mv/injGain;
    }
		else
		{
			charge = a0*padc*capa*adc2mv;
		}
  }

  if ( isSaturated )
  {
    Int_t saturation(3000);

    if ( gain && ( fApplyGains != fgkNoGain ) )
    {
      saturation = gain->ValueAsInt(manuChannel,4);
    }

    if ( padc >= saturation )
    {
      *isSaturated = kTRUE;
    }
    else
    {
      *isSaturated = kFALSE;
    }
  }

  return charge;
}

//_____________________________________________________________________________
Bool_t
AliMUONDigitCalibrator::IsValidDigit(Int_t detElemId, Int_t manuId, Int_t manuChannel,
                                     Int_t* statusMap) const

{
  /// Check if a given pad is ok or not.

  // First a protection against bad input parameters
  AliMpDetElement* de = AliMpDDLStore::Instance()->GetDetElement(detElemId);
  if (!de) return kFALSE; // not existing DE
  if (!de->IsExistingChannel(manuId,manuChannel))
  {
    // non-existing (might happen when we get parity errors in read-out
    // that spoils the manuId
    return kFALSE;
  }
  if (!de->IsConnectedChannel(manuId,manuChannel))
  {
    // existing (in read-out), but not connected channel
    return kFALSE;
  }

  // ok, now we have a valid channel number, so let's see if that pad
  // behaves or not ;-)

  Int_t sm = fStatusMapMaker->StatusMap(detElemId,manuId,manuChannel);

  if (statusMap) *statusMap = sm;

  if ( ( sm & AliMUONPadStatusMapMaker::SelfDeadMask() ) != 0 )
  {
    // pad itself is bad (not testing its neighbours at this stage)
    return kFALSE;
  }

  return kTRUE;
}

//_____________________________________________________________________________
Int_t
AliMUONDigitCalibrator::PadStatus(Int_t detElemId, Int_t manuId, Int_t manuChannel) const
{
  /// Return the status of the given pad
  return fStatusMaker->PadStatus(detElemId,manuId,manuChannel);
}

//_____________________________________________________________________________
Int_t
AliMUONDigitCalibrator::StatusMap(Int_t detElemId, Int_t manuId, Int_t manuChannel) const
{
  /// Return the status map of the given pad
  return fStatusMapMaker->StatusMap(detElemId,manuId,manuChannel);

}

<commit_msg>Adding paranoiac protection to be 200% sure to get physical charges<commit_after>/**************************************************************************
 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
 *                                                                        *
 * Author: The ALICE Off-line Project.                                    *
 * Contributors are mentioned in the code where appropriate.              *
 *                                                                        *
 * Permission to use, copy, modify and distribute this software and its   *
 * documentation strictly for non-commercial purposes is hereby granted   *
 * without fee, provided that the above copyright notice appears in all   *
 * copies and that both the copyright notice and this permission notice   *
 * appear in the supporting documentation. The authors make no claims     *
 * about the suitability of this software for any purpose. It is          *
 * provided "as is" without express or implied warranty.                  *
 **************************************************************************/

// $Id$

#include "AliMUONDigitCalibrator.h"

#include "AliLog.h"
#include "AliMUONCalibrationData.h"
#include "AliMUONLogger.h"
#include "AliMUONPadStatusMaker.h"
#include "AliMUONPadStatusMapMaker.h"
#include "AliMUONRecoParam.h"
#include "AliMUONVCalibParam.h"
#include "AliMUONVDigit.h"
#include "AliMUONVDigitStore.h"
#include "AliMUONVStore.h"
#include "AliMpBusPatch.h"
#include "AliMpConstants.h"
#include "AliMpCDB.h"
#include "AliMpDDLStore.h"
#include "AliMpDEIterator.h"
#include "AliMpDetElement.h"
#include "AliMpManuStore.h"

//-----------------------------------------------------------------------------
/// \class AliMUONDigitCalibrator
/// Class used to calibrate digits (either real or simulated ones).
///
/// The calibration consists of subtracting the pedestal
/// and multiplying by a gain, so that
/// Signal = (ADC-pedestal)*gain
///
/// Please note also that for the moment, if a digit lies on a dead channel
/// we remove this digit from the list of digits.
/// FIXME: this has to be revisited. By using the AliMUONDigit::fFlags we
/// should in principle flag a digit as bad w/o removing it, but this
/// then requires some changes in the cluster finder to deal with this extra
/// information correctly (e.g. to set a quality for the cluster if it contains
/// bad digits).
///
/// \author Laurent Aphecetche
//-----------------------------------------------------------------------------

/// \cond CLASSIMP
ClassImp(AliMUONDigitCalibrator)
/// \endcond

const Int_t AliMUONDigitCalibrator::fgkNoGain(0);
const Int_t AliMUONDigitCalibrator::fgkGainConstantCapa(1);
const Int_t AliMUONDigitCalibrator::fgkGain(2);
const Int_t AliMUONDigitCalibrator::fgkInjectionGain(3);

//_____________________________________________________________________________
AliMUONDigitCalibrator::AliMUONDigitCalibrator(const AliMUONCalibrationData& calib,
                                               const AliMUONRecoParam* recoParams,
                                               const char* calibMode)
: TObject(),
fLogger(new AliMUONLogger(20000)),
fStatusMaker(0x0),
fStatusMapMaker(0x0),
fPedestals(0x0),
fGains(0x0),
fApplyGains(0),
fCapacitances(0x0),
fNumberOfBadPads(0),
fNumberOfPads(0),
fChargeSigmaCut(0),
fMask(0)
{
  /// ctor

  Ctor(calibMode,calib,recoParams);
}

//_____________________________________________________________________________
AliMUONDigitCalibrator::AliMUONDigitCalibrator(const AliMUONCalibrationData& calib,
                                               const char* calibMode)
: TObject(),
fLogger(new AliMUONLogger(20000)),
fStatusMaker(0x0),
fStatusMapMaker(0x0),
fPedestals(0x0),
fGains(0x0),
fApplyGains(0),
fCapacitances(0x0),
fNumberOfBadPads(0),
fNumberOfPads(0),
fChargeSigmaCut(0),
fMask(0)
{
  /// ctor

  Ctor(calibMode,calib,0x0);
}

//_____________________________________________________________________________
void
AliMUONDigitCalibrator::Ctor(const char* calibMode,
                             const AliMUONCalibrationData& calib,
                             const AliMUONRecoParam* recoParams)
{
  /// designated ctor

  TString cMode(calibMode);
  cMode.ToUpper();

  if ( cMode == "NOGAIN" )
  {
    fApplyGains = fgkNoGain;
    AliInfo("Will NOT apply gain correction");
  }
  else if ( cMode == "GAINCONSTANTCAPA" )
  {
    fApplyGains = fgkGainConstantCapa;
    AliInfo("Will apply gain correction, but with constant capacitance");
  }
  else if ( cMode == "GAIN" )
  {
    fApplyGains = fgkGain;
    AliInfo("Will apply gain correction, with measured capacitances");
  }
  else if ( cMode == "INJECTIONGAIN")
	{
		fApplyGains = fgkInjectionGain;
    AliInfo("Will apply injection gain correction, with EMELEC factory gains");
	}
  else
  {
    AliError(Form("Invalid calib mode = %s. Will use NOGAIN instead",calibMode));
    fApplyGains = fgkNoGain;
  }

  // Load mapping manu store
  if ( ! AliMpCDB::LoadManuStore() ) {
    AliFatal("Could not access manu store from OCDB !");
  }

  fStatusMaker = new AliMUONPadStatusMaker(calib);

  // Set default values, as loose as reasonable

  fChargeSigmaCut = 3.0;

	fMask = 0x8080; // reject pads where ped *or* hv are missing

	if ( recoParams )
	{
    // if we have reco params, we use limits and cuts from there :

    fStatusMaker->SetLimits(*recoParams);

    fMask = recoParams->PadGoodnessMask();
		//WARNING : getting this mask wrong is a very effective way of getting
		//no digits at all out of this class ;-)

    fChargeSigmaCut = recoParams->ChargeSigmaCut();
	}

  Bool_t deferredInitialization = kTRUE;

  fStatusMapMaker = new AliMUONPadStatusMapMaker(*fStatusMaker,fMask,deferredInitialization);

  fPedestals = calib.Pedestals();

  fGains = calib.Gains(); // we get gains whatever the calibMode is, in order
  // to get the saturation value...

  if ( fApplyGains == fgkGain || fApplyGains == fgkInjectionGain )
  {
    fCapacitances = calib.Capacitances();
  }
}

//_____________________________________________________________________________
AliMUONDigitCalibrator::~AliMUONDigitCalibrator()
{
  /// dtor.

  if ( fNumberOfPads > 0 )
  {
    if ( fStatusMaker )
    {
      fStatusMaker->Report(fMask);
    }

    AliInfo("Summary of messages:");

    fLogger->Print();

    AliInfo(Form("We have seen %g pads, and rejected %g (%7.2f %%)",
                 fNumberOfPads,fNumberOfBadPads,
                 ( fNumberOfPads > 0 ) ? fNumberOfBadPads*100.0/fNumberOfPads : 0 ));
	}

  delete fStatusMaker;
  delete fStatusMapMaker;
  delete fLogger;
}

//_____________________________________________________________________________
void
AliMUONDigitCalibrator::Calibrate(AliMUONVDigitStore& digitStore)
{
  /// Calibrate the digits contained in digitStore
  TIter next(digitStore.CreateTrackerIterator());
  AliMUONVDigit* digit;

  fStatusMapMaker->RefreshRejectProbabilities(); // this will do something only for simulations
  // (and only for those simulations where the reject list contain probabilities which are
  // different from zero or one)

  AliDebug(1,Form("# of digits = %d",digitStore.GetSize()));

  while ( ( digit = static_cast<AliMUONVDigit*>(next() ) ) )
  {
    if ( digit->IsCalibrated() )
    {
      fLogger->Log("ERROR : trying to calibrate a digit twice");
      return;
    }

    digit->Calibrated(kTRUE);

    Float_t charge(0.0);
    Int_t statusMap;
    Bool_t isSaturated(kFALSE);

    ++fNumberOfPads;

    Bool_t ok = IsValidDigit(digit->DetElemId(),digit->ManuId(),digit->ManuChannel(),&statusMap);

    digit->SetStatusMap(statusMap);

    if (ok)
    {
      charge = CalibrateDigit(digit->DetElemId(),digit->ManuId(),digit->ManuChannel(),
                              digit->ADC(),fChargeSigmaCut,&isSaturated);
    }
    else
    {
      ++fNumberOfBadPads;
    }

    digit->SetCharge(charge);
    digit->Saturated(isSaturated);
  }
}

//_____________________________________________________________________________
Float_t
AliMUONDigitCalibrator::CalibrateDigit(Int_t detElemId, Int_t manuId, Int_t manuChannel,
                                       Float_t adc, Float_t nsigmas,
                                       Bool_t* isSaturated) const

{
  /// Calibrate one digit
  /// Return the digit charge, in fC

  AliMUONVCalibParam* pedestal = static_cast<AliMUONVCalibParam*>
  (fPedestals->FindObject(detElemId,manuId));

  if (!pedestal)
  {
    // no pedestal -> no charge
    fLogger->Log(Form("Got a null pedestal object for DE,manu=%d,%d",detElemId,manuId));
    return 0.0;
  }

  AliMUONVCalibParam* gain = static_cast<AliMUONVCalibParam*>
  (fGains->FindObject(detElemId,manuId));

  if (!gain)
  {
    if ( fApplyGains != fgkNoGain )
    {
      // no gain -> no charge
      fLogger->Log(Form("Got a null gain object for DE,manu=%d,%d",
                        detElemId,manuId));
      return 0.0;
    }
  }

  Float_t padc = adc-pedestal->ValueAsFloat(manuChannel,0);

	// Gain (mV/fC) = 1/(a0*capa) with a0~1.25 and capa~0.2
  Float_t charge(0);
  Float_t capa(0.2); // capa = 0.2 and a0 = 1.25
	Float_t a0(1.25);  // is equivalent to gain = 4 mV/fC
	Float_t a1(0);
	Float_t adc2mv(0.61); // 1 ADC channel = 0.61 mV
	Float_t injGain(4); // By default the gain is set to 4 mV/fC
  //
  // Note that the ChargeMax (for one pad) is roughly 4096 * 0.61 mV/channel / 4 mV/fC = 625 fC

  if ( fApplyGains == fgkGain || fApplyGains == fgkInjectionGain )
  {
    Int_t serialNumber
    = AliMpManuStore::Instance()->GetManuSerial(detElemId, manuId);

    AliMUONVCalibParam* param = static_cast<AliMUONVCalibParam*>(fCapacitances->FindObject(serialNumber));

    if ( param )
    {
      capa = param->ValueAsFloat(manuChannel,0);
			injGain = param->ValueAsFloat(manuChannel,1);
      if ( injGain < 0 )
      {
        fLogger->Log(Form("injGain is %e < 0 for serialNumber=%d",injGain,serialNumber));
        return 0.0;
      }
    }
    else
    {
      // If capa not found in the OCDB we exit
	    fLogger->Log(Form("No capa (injGain) found for serialNumber=%d",serialNumber));
			return 0.0;
    }
  }

  if ( padc > nsigmas*pedestal->ValueAsFloat(manuChannel,1) )
  {
    if ( fApplyGains == fgkGain || fApplyGains == fgkGainConstantCapa )
    {
      a0 = gain->ValueAsFloat(manuChannel,0);
      a1 = gain->ValueAsFloat(manuChannel,1);
      Int_t thres = gain->ValueAsInt(manuChannel,2);
      if ( padc < thres )
      {
        charge = a0*padc;
      }
      else
      {
        charge = a0*thres + a0*(padc-thres) + a1*(padc-thres)*(padc-thres);
      }
			charge *= capa*adc2mv;
    }
    else if ( fApplyGains == fgkInjectionGain )
    {

      charge = padc*adc2mv/injGain;
    }
		else
		{
			charge = a0*padc*capa*adc2mv;
		}
  }

  if ( isSaturated )
  {
    Int_t saturation(3000);

    if ( gain && ( fApplyGains != fgkNoGain ) )
    {
      saturation = gain->ValueAsInt(manuChannel,4);
    }

    if ( padc >= saturation )
    {
      *isSaturated = kTRUE;
    }
    else
    {
      *isSaturated = kFALSE;
    }
  }

  return ( charge > 0.0 ? charge : 0.0 );
}

//_____________________________________________________________________________
Bool_t
AliMUONDigitCalibrator::IsValidDigit(Int_t detElemId, Int_t manuId, Int_t manuChannel,
                                     Int_t* statusMap) const

{
  /// Check if a given pad is ok or not.

  // First a protection against bad input parameters
  AliMpDetElement* de = AliMpDDLStore::Instance()->GetDetElement(detElemId);
  if (!de) return kFALSE; // not existing DE
  if (!de->IsExistingChannel(manuId,manuChannel))
  {
    // non-existing (might happen when we get parity errors in read-out
    // that spoils the manuId
    return kFALSE;
  }
  if (!de->IsConnectedChannel(manuId,manuChannel))
  {
    // existing (in read-out), but not connected channel
    return kFALSE;
  }

  // ok, now we have a valid channel number, so let's see if that pad
  // behaves or not ;-)

  Int_t sm = fStatusMapMaker->StatusMap(detElemId,manuId,manuChannel);

  if (statusMap) *statusMap = sm;

  if ( ( sm & AliMUONPadStatusMapMaker::SelfDeadMask() ) != 0 )
  {
    // pad itself is bad (not testing its neighbours at this stage)
    return kFALSE;
  }

  return kTRUE;
}

//_____________________________________________________________________________
Int_t
AliMUONDigitCalibrator::PadStatus(Int_t detElemId, Int_t manuId, Int_t manuChannel) const
{
  /// Return the status of the given pad
  return fStatusMaker->PadStatus(detElemId,manuId,manuChannel);
}

//_____________________________________________________________________________
Int_t
AliMUONDigitCalibrator::StatusMap(Int_t detElemId, Int_t manuId, Int_t manuChannel) const
{
  /// Return the status map of the given pad
  return fStatusMapMaker->StatusMap(detElemId,manuId,manuChannel);

}

<|endoftext|>


<commit_before>/* Copyright 2012-present Facebook, Inc.
 * Licensed under the Apache License, Version 2.0 */

#include "watchman.h"

static void full_crawl(
    unlocked_watchman_root* unlocked,
    watchman_pending_collection& pending) {
  struct timeval start;
  struct write_locked_watchman_root lock;

  w_perf_t sample("full-crawl");
  if (cfg_get_bool(unlocked->root, "iothrottle", false)) {
    w_ioprio_set_low();
  }
  w_root_lock(unlocked, "io_thread: bump ticks", &lock);
  // Ensure that we observe these files with a new, distinct clock,
  // otherwise a fresh subscription established immediately after a watch
  // can get stuck with an empty view until another change is observed
  lock.root->inner.ticks++;
  gettimeofday(&start, NULL);
  w_pending_coll_add(
      &lock.root->ioThread.pending, lock.root->root_path, start, 0);
  // There is the potential for a subtle race condition here.  The boolean
  // parameter indicates whether we want to merge in the set of
  // notifications pending from the watcher or not.  Since we now coalesce
  // overlaps we must consume our outstanding set before we merge in any
  // new kernel notification information or we risk missing out on
  // observing changes that happen during the initial crawl.  This
  // translates to a two level loop; the outer loop sweeps in data from
  // inotify, then the inner loop processes it and any dirs that we pick up
  // from recursive processing.
  while (w_root_process_pending(&lock, &pending, true)) {
    while (w_root_process_pending(&lock, &pending, false)) {
      ;
    }
  }
  lock.root->inner.done_initial = true;
  sample.add_root_meta(lock.root);
  w_root_unlock(&lock, unlocked);

  if (cfg_get_bool(unlocked->root, "iothrottle", false)) {
    w_ioprio_set_normal();
  }

  sample.finish();
  sample.force_log();
  sample.log();

  w_log(
      W_LOG_ERR,
      "%scrawl complete\n",
      unlocked->root->recrawlInfo.rlock()->recrawlCount ? "re" : "");
}

static void io_thread(struct unlocked_watchman_root *unlocked)
{
  int timeoutms, biggest_timeout;
  struct watchman_pending_collection pending;
  struct write_locked_watchman_root lock;

  timeoutms = unlocked->root->trigger_settle;

  // Upper bound on sleep delay.  These options are measured in seconds.
  biggest_timeout = unlocked->root->gc_interval;
  if (biggest_timeout == 0 ||
      (unlocked->root->idle_reap_age != 0 &&
       unlocked->root->idle_reap_age < biggest_timeout)) {
    biggest_timeout = unlocked->root->idle_reap_age;
  }
  if (biggest_timeout == 0) {
    biggest_timeout = 86400;
  }
  // And convert to milliseconds
  biggest_timeout *= 1000;

  while (!unlocked->root->inner.cancelled) {
    bool pinged;

    if (!unlocked->root->inner.done_initial) {
      /* first order of business is to find all the files under our root */
      full_crawl(unlocked, pending);

      timeoutms = unlocked->root->trigger_settle;
    }

    // Wait for the notify thread to give us pending items, or for
    // the settle period to expire
    w_log(W_LOG_DBG, "poll_events timeout=%dms\n", timeoutms);
    pinged = w_pending_coll_lock_and_wait(
        &unlocked->root->ioThread.pending, timeoutms);
    w_log(W_LOG_DBG, " ... wake up (pinged=%s)\n", pinged ? "true" : "false");
    w_pending_coll_append(&pending, &unlocked->root->ioThread.pending);
    w_pending_coll_unlock(&unlocked->root->ioThread.pending);

    if (!pinged && w_pending_coll_size(&pending) == 0) {
      process_pending_symlink_targets(unlocked);

      // No new pending items were given to us, so consider that
      // we may now be settled.

      w_root_lock(unlocked, "io_thread: settle out", &lock);
      if (!lock.root->inner.done_initial) {
        // we need to recrawl, stop what we're doing here
        w_root_unlock(&lock, unlocked);
        continue;
      }

      process_subscriptions(&lock);
      process_triggers(&lock);
      if (consider_reap(&lock)) {
        w_root_unlock(&lock, unlocked);
        w_root_stop_watch(unlocked);
        break;
      }
      consider_age_out(&lock);
      w_root_unlock(&lock, unlocked);

      timeoutms = MIN(biggest_timeout, timeoutms * 2);
      continue;
    }

    // Otherwise we have pending items to stat and crawl

    // We are now, by definition, unsettled, so reduce sleep timeout
    // to the settle duration ready for the next loop through
    timeoutms = unlocked->root->trigger_settle;

    w_root_lock(unlocked, "io_thread: process notifications", &lock);
    if (!lock.root->inner.done_initial) {
      // we need to recrawl.  Discard these notifications
      w_pending_coll_drain(&pending);
      w_root_unlock(&lock, unlocked);
      continue;
    }

    lock.root->inner.ticks++;
    // If we're not settled, we need an opportunity to age out
    // dead file nodes.  This happens in the test harness.
    consider_age_out(&lock);

    while (w_root_process_pending(&lock, &pending, false)) {
      ;
    }

    w_root_unlock(&lock, unlocked);
  }
}

void w_root_process_path(
    struct write_locked_watchman_root* lock,
    struct watchman_pending_collection* coll,
    const w_string& full_path,
    struct timeval now,
    int flags,
    struct watchman_dir_ent* pre_stat) {
  /* From a particular query's point of view, there are four sorts of cookies we
   * can observe:
   * 1. Cookies that this query has created. This marks the end of this query's
   *    sync_to_now, so we hide it from the results.
   * 2. Cookies that another query on the same watch by the same process has
   *    created. This marks the end of that other query's sync_to_now, so from
   *    the point of view of this query we turn a blind eye to it.
   * 3. Cookies created by another process on the same watch. We're independent
   *    of other processes, so we report these.
   * 4. Cookies created by a nested watch by the same or a different process.
   *    We're independent of other watches, so we report these.
   *
   * The below condition is true for cases 1 and 2 and false for 3 and 4.
   */
  if (w_string_startswith(full_path, lock->root->query_cookie_prefix)) {
    bool consider_cookie =
        (lock->root->inner.watcher->flags & WATCHER_HAS_PER_FILE_NOTIFICATIONS)
        ? ((flags & W_PENDING_VIA_NOTIFY) || !lock->root->inner.done_initial)
        : true;

    if (!consider_cookie) {
      // Never allow cookie files to show up in the tree
      return;
    }

    {
      auto map = lock->root->query_cookies.rlock();
      auto cookie_iter = map->find(full_path);
      w_log(
          W_LOG_DBG,
          "cookie for %s? %s\n",
          full_path.c_str(),
          cookie_iter != map->end() ? "yes" : "no");

      if (cookie_iter != map->end()) {
        auto cookie = cookie_iter->second;
        cookie->seen = true;
        cookie->cond.notify_one();
      }
    };

    // Never allow cookie files to show up in the tree
    return;
  }

  if (w_string_equal(full_path, lock->root->root_path)
      || (flags & W_PENDING_CRAWL_ONLY) == W_PENDING_CRAWL_ONLY) {
    crawler(lock, coll, full_path, now,
        (flags & W_PENDING_RECURSIVE) == W_PENDING_RECURSIVE);
  } else {
    stat_path(lock, coll, full_path, now, flags, pre_stat);
  }
}

bool w_root_process_pending(struct write_locked_watchman_root *lock,
    struct watchman_pending_collection *coll,
    bool pull_from_root)
{
  struct watchman_pending_fs *p, *pending;

  if (pull_from_root) {
    // You MUST own root->pending lock for this
    w_pending_coll_append(coll, &lock->root->ioThread.pending);
  }

  if (!coll->pending) {
    return false;
  }

  w_log(
      W_LOG_DBG,
      "processing %d events in %s\n",
      w_pending_coll_size(coll),
      lock->root->root_path.c_str());

  // Steal the contents
  pending = coll->pending;
  coll->pending = NULL;
  w_pending_coll_drain(coll);

  while (pending) {
    p = pending;
    pending = p->next;

    if (!lock->root->inner.cancelled) {
      w_root_process_path(lock, coll, p->path, p->now, p->flags, NULL);
    }

    w_pending_fs_free(p);
  }

  return true;
}

void *run_io_thread(void *arg)
{
  struct unlocked_watchman_root unlocked = {(w_root_t*)arg};

  w_set_thread_name("io %s", unlocked.root->root_path.c_str());
  io_thread(&unlocked);
  w_log(W_LOG_DBG, "out of loop\n");

  w_root_delref(&unlocked);
  return 0;
}

/* vim:ts=2:sw=2:et:
 */
<commit_msg>factor out settle actions as its own function<commit_after>/* Copyright 2012-present Facebook, Inc.
 * Licensed under the Apache License, Version 2.0 */

#include "watchman.h"

static void full_crawl(
    unlocked_watchman_root* unlocked,
    watchman_pending_collection& pending) {
  struct timeval start;
  struct write_locked_watchman_root lock;

  w_perf_t sample("full-crawl");
  if (cfg_get_bool(unlocked->root, "iothrottle", false)) {
    w_ioprio_set_low();
  }
  w_root_lock(unlocked, "io_thread: bump ticks", &lock);
  // Ensure that we observe these files with a new, distinct clock,
  // otherwise a fresh subscription established immediately after a watch
  // can get stuck with an empty view until another change is observed
  lock.root->inner.ticks++;
  gettimeofday(&start, NULL);
  w_pending_coll_add(
      &lock.root->ioThread.pending, lock.root->root_path, start, 0);
  // There is the potential for a subtle race condition here.  The boolean
  // parameter indicates whether we want to merge in the set of
  // notifications pending from the watcher or not.  Since we now coalesce
  // overlaps we must consume our outstanding set before we merge in any
  // new kernel notification information or we risk missing out on
  // observing changes that happen during the initial crawl.  This
  // translates to a two level loop; the outer loop sweeps in data from
  // inotify, then the inner loop processes it and any dirs that we pick up
  // from recursive processing.
  while (w_root_process_pending(&lock, &pending, true)) {
    while (w_root_process_pending(&lock, &pending, false)) {
      ;
    }
  }
  lock.root->inner.done_initial = true;
  sample.add_root_meta(lock.root);
  w_root_unlock(&lock, unlocked);

  if (cfg_get_bool(unlocked->root, "iothrottle", false)) {
    w_ioprio_set_normal();
  }

  sample.finish();
  sample.force_log();
  sample.log();

  w_log(
      W_LOG_ERR,
      "%scrawl complete\n",
      unlocked->root->recrawlInfo.rlock()->recrawlCount ? "re" : "");
}

// Performs settle-time actions.
// Returns true if the root was reaped and the io thread should terminate.
static bool do_settle_things(struct unlocked_watchman_root* unlocked) {
  struct write_locked_watchman_root lock;

  // No new pending items were given to us, so consider that
  // we may now be settled.

  process_pending_symlink_targets(unlocked);

  w_root_lock(unlocked, "io_thread: settle out", &lock);
  if (!lock.root->inner.done_initial) {
    // we need to recrawl, stop what we're doing here
    w_root_unlock(&lock, unlocked);
    return false;
  }

  process_subscriptions(&lock);
  process_triggers(&lock);
  if (consider_reap(&lock)) {
    w_root_unlock(&lock, unlocked);
    w_root_stop_watch(unlocked);
    return true;
  }

  consider_age_out(&lock);
  w_root_unlock(&lock, unlocked);
  return false;
}

static void io_thread(struct unlocked_watchman_root *unlocked)
{
  int timeoutms, biggest_timeout;
  struct watchman_pending_collection pending;
  struct write_locked_watchman_root lock;

  timeoutms = unlocked->root->trigger_settle;

  // Upper bound on sleep delay.  These options are measured in seconds.
  biggest_timeout = unlocked->root->gc_interval;
  if (biggest_timeout == 0 ||
      (unlocked->root->idle_reap_age != 0 &&
       unlocked->root->idle_reap_age < biggest_timeout)) {
    biggest_timeout = unlocked->root->idle_reap_age;
  }
  if (biggest_timeout == 0) {
    biggest_timeout = 86400;
  }
  // And convert to milliseconds
  biggest_timeout *= 1000;

  while (!unlocked->root->inner.cancelled) {
    bool pinged;

    if (!unlocked->root->inner.done_initial) {
      /* first order of business is to find all the files under our root */
      full_crawl(unlocked, pending);

      timeoutms = unlocked->root->trigger_settle;
    }

    // Wait for the notify thread to give us pending items, or for
    // the settle period to expire
    w_log(W_LOG_DBG, "poll_events timeout=%dms\n", timeoutms);
    pinged = w_pending_coll_lock_and_wait(
        &unlocked->root->ioThread.pending, timeoutms);
    w_log(W_LOG_DBG, " ... wake up (pinged=%s)\n", pinged ? "true" : "false");
    w_pending_coll_append(&pending, &unlocked->root->ioThread.pending);
    w_pending_coll_unlock(&unlocked->root->ioThread.pending);

    if (!pinged && w_pending_coll_size(&pending) == 0) {
      if (do_settle_things(unlocked)) {
        break;
      }
      timeoutms = MIN(biggest_timeout, timeoutms * 2);
      continue;
    }

    // Otherwise we have pending items to stat and crawl

    // We are now, by definition, unsettled, so reduce sleep timeout
    // to the settle duration ready for the next loop through
    timeoutms = unlocked->root->trigger_settle;

    w_root_lock(unlocked, "io_thread: process notifications", &lock);
    if (!lock.root->inner.done_initial) {
      // we need to recrawl.  Discard these notifications
      w_pending_coll_drain(&pending);
      w_root_unlock(&lock, unlocked);
      continue;
    }

    lock.root->inner.ticks++;
    // If we're not settled, we need an opportunity to age out
    // dead file nodes.  This happens in the test harness.
    consider_age_out(&lock);

    while (w_root_process_pending(&lock, &pending, false)) {
      ;
    }

    w_root_unlock(&lock, unlocked);
  }
}

void w_root_process_path(
    struct write_locked_watchman_root* lock,
    struct watchman_pending_collection* coll,
    const w_string& full_path,
    struct timeval now,
    int flags,
    struct watchman_dir_ent* pre_stat) {
  /* From a particular query's point of view, there are four sorts of cookies we
   * can observe:
   * 1. Cookies that this query has created. This marks the end of this query's
   *    sync_to_now, so we hide it from the results.
   * 2. Cookies that another query on the same watch by the same process has
   *    created. This marks the end of that other query's sync_to_now, so from
   *    the point of view of this query we turn a blind eye to it.
   * 3. Cookies created by another process on the same watch. We're independent
   *    of other processes, so we report these.
   * 4. Cookies created by a nested watch by the same or a different process.
   *    We're independent of other watches, so we report these.
   *
   * The below condition is true for cases 1 and 2 and false for 3 and 4.
   */
  if (w_string_startswith(full_path, lock->root->query_cookie_prefix)) {
    bool consider_cookie =
        (lock->root->inner.watcher->flags & WATCHER_HAS_PER_FILE_NOTIFICATIONS)
        ? ((flags & W_PENDING_VIA_NOTIFY) || !lock->root->inner.done_initial)
        : true;

    if (!consider_cookie) {
      // Never allow cookie files to show up in the tree
      return;
    }

    {
      auto map = lock->root->query_cookies.rlock();
      auto cookie_iter = map->find(full_path);
      w_log(
          W_LOG_DBG,
          "cookie for %s? %s\n",
          full_path.c_str(),
          cookie_iter != map->end() ? "yes" : "no");

      if (cookie_iter != map->end()) {
        auto cookie = cookie_iter->second;
        cookie->seen = true;
        cookie->cond.notify_one();
      }
    };

    // Never allow cookie files to show up in the tree
    return;
  }

  if (w_string_equal(full_path, lock->root->root_path)
      || (flags & W_PENDING_CRAWL_ONLY) == W_PENDING_CRAWL_ONLY) {
    crawler(lock, coll, full_path, now,
        (flags & W_PENDING_RECURSIVE) == W_PENDING_RECURSIVE);
  } else {
    stat_path(lock, coll, full_path, now, flags, pre_stat);
  }
}

bool w_root_process_pending(struct write_locked_watchman_root *lock,
    struct watchman_pending_collection *coll,
    bool pull_from_root)
{
  struct watchman_pending_fs *p, *pending;

  if (pull_from_root) {
    // You MUST own root->pending lock for this
    w_pending_coll_append(coll, &lock->root->ioThread.pending);
  }

  if (!coll->pending) {
    return false;
  }

  w_log(
      W_LOG_DBG,
      "processing %d events in %s\n",
      w_pending_coll_size(coll),
      lock->root->root_path.c_str());

  // Steal the contents
  pending = coll->pending;
  coll->pending = NULL;
  w_pending_coll_drain(coll);

  while (pending) {
    p = pending;
    pending = p->next;

    if (!lock->root->inner.cancelled) {
      w_root_process_path(lock, coll, p->path, p->now, p->flags, NULL);
    }

    w_pending_fs_free(p);
  }

  return true;
}

void *run_io_thread(void *arg)
{
  struct unlocked_watchman_root unlocked = {(w_root_t*)arg};

  w_set_thread_name("io %s", unlocked.root->root_path.c_str());
  io_thread(&unlocked);
  w_log(W_LOG_DBG, "out of loop\n");

  w_root_delref(&unlocked);
  return 0;
}

/* vim:ts=2:sw=2:et:
 */
<|endoftext|>


<commit_before>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you under the Apache
 *   License, Version 2.0 (the "License"); you may not use this file
 *   except in compliance with the License. You may obtain a copy of
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
 */

#include <algorithm>
#include <cmath>

#include <limits.h>
#include <rtl/ustring.hxx>
#include <tools/debug.hxx>
#include <tools/fract.hxx>
#include <tools/lineend.hxx>
#include <tools/stream.hxx>

template<typename T>
static boost::rational<T> rational_FromDouble(double dVal);

template<typename T>
static void rational_ReduceInaccurate(boost::rational<T>& rRational, unsigned nSignificantBits);

// Initialized by setting nNum as nominator and nDen as denominator
// Negative values in the denominator are invalid and cause the
// inversion of both nominator and denominator signs
// in order to return the correct value.
Fraction::Fraction( long nNum, long nDen )
{
    if ( nDen == 0 ) {
        valid = false;
        SAL_WARN( "tools.fraction", "'Fraction(" + std::to_string(nNum) + ",0)' invalid fraction created" );
        return;
    }
    value.assign( nNum, nDen);
    valid = true;
}

Fraction::Fraction( double dVal )
{
    try {
        value = rational_FromDouble<sal_Int64>( dVal );
        if ( HasOverflowValue() )
            throw boost::bad_rational();
        valid = true;
    } catch(const boost::bad_rational& unused) {
        valid = false;
        SAL_WARN( "tools.fraction", "'Fraction(" + std::to_string(dVal) + ")' invalid fraction created" );
    }
}

bool Fraction::HasOverflowValue()
{
    return value.numerator() < std::numeric_limits<long>::min() ||
        value.numerator() > std::numeric_limits<long>::max() ||
        value.denominator() < std::numeric_limits<long>::min() ||
        value.denominator() > std::numeric_limits<long>::max();
}

Fraction::operator double() const
{
    if ( !valid ) {
        SAL_WARN( "tools.fraction", "'double()' on invalid fraction" );
        return 0.0;
    }

    return boost::rational_cast<double>(value);
}

// This methods first validates both values.
// If one of the arguments is invalid, the whole operation is invalid.
// After computation detect if result overflows a long value
// which cause the operation to be marked as invalid
Fraction& Fraction::operator += ( const Fraction& rVal )
{
    if ( !rVal.valid )
        valid = false;
    if ( !valid ) {
        SAL_WARN( "tools.fraction", "'operator +=' with invalid fraction" );
        return *this;
    }

    value += rVal.value;

    if ( HasOverflowValue() ) {
        valid = false;
        SAL_WARN( "tools.fraction", "'operator +=' detected overflow" );
    }

    return *this;
}

Fraction& Fraction::operator -= ( const Fraction& rVal )
{
    if ( !rVal.valid )
        valid = false;
    if ( !valid ) {
        SAL_WARN( "tools.fraction", "'operator -=' with invalid fraction" );
        return *this;
    }

    value -= rVal.value;

    if ( HasOverflowValue() ) {
        valid = false;
        SAL_WARN( "tools.fraction", "'operator -=' detected overflow" );
    }

    return *this;
}

Fraction& Fraction::operator *= ( const Fraction& rVal )
{
    if ( !rVal.valid )
        valid = false;
    if ( !valid ) {
        SAL_WARN( "tools.fraction", "'operator *=' with invalid fraction" );
        return *this;
    }

    value *= rVal.value;

    if ( HasOverflowValue() ) {
        valid = false;
        SAL_WARN( "tools.fraction", "'operator *=' detected overflow" );
    }

    return *this;
}

Fraction& Fraction::operator /= ( const Fraction& rVal )
{
    if ( !rVal.valid )
        valid = false;
    if ( !valid ) {
        SAL_WARN( "tools.fraction", "'operator /=' with invalid fraction" );
        return *this;
    }

    value /= rVal.value;

    if ( HasOverflowValue() ) {
        valid = false;
        SAL_WARN( "tools.fraction", "'operator /=' detected overflow" );
    }

    return *this;
}

/** Inaccurate cancellation for a fraction.

    Clip both nominator and denominator to said number of bits. If
    either of those already have equal or less number of bits used,
    this method does nothing.

    @param nSignificantBits denotes, how many significant binary
    digits to maintain, in both nominator and denominator.

    @example ReduceInaccurate(8) has an error <1% [1/2^(8-1)] - the
    largest error occurs with the following pair of values:

    binary    1000000011111111111111111111111b/1000000000000000000000000000000b
    =         1082130431/1073741824
    = approx. 1.007812499

    A ReduceInaccurate(8) yields 1/1.
*/
void Fraction::ReduceInaccurate( unsigned nSignificantBits )
{
    if ( !valid ) {
        SAL_WARN( "tools.fraction", "'ReduceInaccurate' on invalid fraction" );
        return;
    }
    if ( !value.numerator() )
        return;

    rational_ReduceInaccurate(value, nSignificantBits);
}

bool operator == ( const Fraction& rVal1, const Fraction& rVal2 )
{
    if ( !rVal1.valid || !rVal2.valid ) {
        SAL_WARN( "tools.fraction", "'operator ==' with an invalid fraction" );
        return false;
    }

    return rVal1.value == rVal2.value;
}

bool operator < ( const Fraction& rVal1, const Fraction& rVal2 )
{
    if ( !rVal1.valid || !rVal2.valid ) {
        SAL_WARN( "tools.fraction", "'operator <' with an invalid fraction" );
        return false;
    }

    return rVal1.value < rVal2.value;
}

bool operator > ( const Fraction& rVal1, const Fraction& rVal2 )
{
    if ( !rVal1.valid || !rVal2.valid ) {
        SAL_WARN( "tools.fraction", "'operator >' with an invalid fraction" );
        return false;
    }

    return rVal1.value > rVal2.value;
}

SvStream& ReadFraction( SvStream& rIStream, Fraction& rFract )
{
    sal_Int32 num(0), den(0);
    rIStream.ReadInt32( num );
    rIStream.ReadInt32( den );
    if ( den <= 0 ) {
        SAL_WARN( "tools.fraction", "'ReadFraction()' read an invalid fraction" );
        rFract.valid = false;
    } else {
        rFract.value.assign( num, den );
        rFract.valid = true;
    }
    return rIStream;
}

SvStream& WriteFraction( SvStream& rOStream, const Fraction& rFract )
{
    if ( !rFract.valid ) {
        SAL_WARN( "tools.fraction", "'WriteFraction()' write an invalid fraction" );
        rOStream.WriteInt32( 0 );
        rOStream.WriteInt32( -1 );
    } else {
        rOStream.WriteInt32( rFract.value.numerator() );
        rOStream.WriteInt32( rFract.value.denominator() );
    }
    return rOStream;
}

// If dVal > LONG_MAX or dVal < LONG_MIN, the rational throws a boost::bad_rational.
// Otherwise, dVal and denominator are multiplied by 10, until one of them
// is larger than (LONG_MAX / 10).
//
// NOTE: here we use 'long' due that only values in long range are valid.
template<typename T>
static boost::rational<T> rational_FromDouble(double dVal)
{
    if ( dVal > std::numeric_limits<long>::max() ||
            dVal < std::numeric_limits<long>::min() )
        throw boost::bad_rational();

    const long nMAX = std::numeric_limits<long>::max() / 10;
    long nDen = 1;
    while ( std::abs( dVal ) < nMAX && nDen < nMAX ) {
        dVal *= 10;
        nDen *= 10;
    }
    return boost::rational<T>( long(dVal), nDen );
}

// Similar to clz_table that can be googled
const char nbits_table[32] =
{
    32,  1, 23,  2, 29, 24, 14,  3,
    30, 27, 25, 18, 20, 15, 10,  4,
    31, 22, 28, 13, 26, 17, 19,  9,
    21, 12, 16,  8, 11,  7,  6,  5
};

static int impl_NumberOfBits( unsigned long nNum )
{
    // http://en.wikipedia.org/wiki/De_Bruijn_sequence
    // background paper: Using de Bruijn Sequences to Index a 1 in a
    // Computer Word (1998) Charles E. Leiserson,
    // Harald Prokop, Keith H. Randall
    // (e.g. http://citeseer.ist.psu.edu/leiserson98using.html)
    const sal_uInt32 nDeBruijn = 0x7DCD629;

    if ( nNum == 0 )
        return 0;

    // Get it to form like 0000001111111111b
    nNum |= ( nNum >>  1 );
    nNum |= ( nNum >>  2 );
    nNum |= ( nNum >>  4 );
    nNum |= ( nNum >>  8 );
    nNum |= ( nNum >> 16 );

    sal_uInt32 nNumber;
    int nBonus = 0;

#if SAL_TYPES_SIZEOFLONG == 4
    nNumber = nNum;
#elif SAL_TYPES_SIZEOFLONG == 8
    nNum |= ( nNum >> 32 );

    if ( nNum & 0x80000000 )
    {
        nNumber = sal_uInt32( nNum >> 32 );
        nBonus = 32;

        if ( nNumber == 0 )
            return 32;
    }
    else
        nNumber = sal_uInt32( nNum & 0xFFFFFFFF );
#else
#error "Unknown size of long!"
#endif

    // De facto shift left of nDeBruijn using multiplication (nNumber
    // is all ones from topmost bit, thus nDeBruijn + (nDeBruijn *
    // nNumber) => nDeBruijn * (nNumber+1) clears all those bits to
    // zero, sets the next bit to one, and thus effectively shift-left
    // nDeBruijn by lg2(nNumber+1). This generates a distinct 5bit
    // sequence in the msb for each distinct position of the last
    // leading 0 bit - that's the property of a de Bruijn number.
    nNumber = nDeBruijn + ( nDeBruijn * nNumber );

    // 5-bit window indexes the result
    return ( nbits_table[nNumber >> 27] ) + nBonus;
}

/** Inaccurate cancellation for a fraction.

    Clip both nominator and denominator to said number of bits. If
    either of those already have equal or less number of bits used,
    this method does nothing.

    @param nSignificantBits denotes, how many significant binary
    digits to maintain, in both nominator and denominator.

    @example ReduceInaccurate(8) has an error <1% [1/2^(8-1)] - the
    largest error occurs with the following pair of values:

    binary    1000000011111111111111111111111b/1000000000000000000000000000000b
    =         1082130431/1073741824
    = approx. 1.007812499

    A ReduceInaccurate(8) yields 1/1.
*/
template<typename T>
static void rational_ReduceInaccurate(boost::rational<T>& rRational, unsigned nSignificantBits)
{
    if ( !rRational )
        return;

    // http://www.boost.org/doc/libs/release/libs/rational/rational.html#Internal%20representation
    const bool bNeg = ( rRational.numerator() < 0 );
    T nMul = bNeg? -rRational.numerator(): rRational.numerator();
    T nDiv = rRational.denominator();

    DBG_ASSERT(nSignificantBits<65, "More than 64 bit of significance is overkill!");

    // How much bits can we lose?
    const int nMulBitsToLose = std::max( ( impl_NumberOfBits( nMul ) - int( nSignificantBits ) ), 0 );
    const int nDivBitsToLose = std::max( ( impl_NumberOfBits( nDiv ) - int( nSignificantBits ) ), 0 );

    const int nToLose = std::min( nMulBitsToLose, nDivBitsToLose );

    // Remove the bits
    nMul >>= nToLose;
    nDiv >>= nToLose;

    if ( !nMul || !nDiv ) {
        // Return without reduction
        OSL_FAIL( "Oops, we reduced too much..." );
        return;
    }

    rRational.assign( bNeg? -T( nMul ): T( nMul ), nDiv );
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<commit_msg>fix build on android-arm tinderbox<commit_after>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you under the Apache
 *   License, Version 2.0 (the "License"); you may not use this file
 *   except in compliance with the License. You may obtain a copy of
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
 */

#include <algorithm>
#include <cmath>

#include <limits.h>
#include <rtl/ustring.hxx>
#include <tools/debug.hxx>
#include <tools/fract.hxx>
#include <tools/lineend.hxx>
#include <tools/stream.hxx>

template<typename T>
static boost::rational<T> rational_FromDouble(double dVal);

template<typename T>
static void rational_ReduceInaccurate(boost::rational<T>& rRational, unsigned nSignificantBits);

// Initialized by setting nNum as nominator and nDen as denominator
// Negative values in the denominator are invalid and cause the
// inversion of both nominator and denominator signs
// in order to return the correct value.
Fraction::Fraction( long nNum, long nDen )
{
    if ( nDen == 0 ) {
        valid = false;
        SAL_WARN( "tools.fraction", "'Fraction(" << nNum << ",0)' invalid fraction created" );
        return;
    }
    value.assign( nNum, nDen);
    valid = true;
}

Fraction::Fraction( double dVal )
{
    try {
        value = rational_FromDouble<sal_Int64>( dVal );
        if ( HasOverflowValue() )
            throw boost::bad_rational();
        valid = true;
    } catch(const boost::bad_rational& unused) {
        valid = false;
        SAL_WARN( "tools.fraction", "'Fraction(" << dVal << ")' invalid fraction created" );
    }
}

bool Fraction::HasOverflowValue()
{
    return value.numerator() < std::numeric_limits<long>::min() ||
        value.numerator() > std::numeric_limits<long>::max() ||
        value.denominator() < std::numeric_limits<long>::min() ||
        value.denominator() > std::numeric_limits<long>::max();
}

Fraction::operator double() const
{
    if ( !valid ) {
        SAL_WARN( "tools.fraction", "'double()' on invalid fraction" );
        return 0.0;
    }

    return boost::rational_cast<double>(value);
}

// This methods first validates both values.
// If one of the arguments is invalid, the whole operation is invalid.
// After computation detect if result overflows a long value
// which cause the operation to be marked as invalid
Fraction& Fraction::operator += ( const Fraction& rVal )
{
    if ( !rVal.valid )
        valid = false;
    if ( !valid ) {
        SAL_WARN( "tools.fraction", "'operator +=' with invalid fraction" );
        return *this;
    }

    value += rVal.value;

    if ( HasOverflowValue() ) {
        valid = false;
        SAL_WARN( "tools.fraction", "'operator +=' detected overflow" );
    }

    return *this;
}

Fraction& Fraction::operator -= ( const Fraction& rVal )
{
    if ( !rVal.valid )
        valid = false;
    if ( !valid ) {
        SAL_WARN( "tools.fraction", "'operator -=' with invalid fraction" );
        return *this;
    }

    value -= rVal.value;

    if ( HasOverflowValue() ) {
        valid = false;
        SAL_WARN( "tools.fraction", "'operator -=' detected overflow" );
    }

    return *this;
}

Fraction& Fraction::operator *= ( const Fraction& rVal )
{
    if ( !rVal.valid )
        valid = false;
    if ( !valid ) {
        SAL_WARN( "tools.fraction", "'operator *=' with invalid fraction" );
        return *this;
    }

    value *= rVal.value;

    if ( HasOverflowValue() ) {
        valid = false;
        SAL_WARN( "tools.fraction", "'operator *=' detected overflow" );
    }

    return *this;
}

Fraction& Fraction::operator /= ( const Fraction& rVal )
{
    if ( !rVal.valid )
        valid = false;
    if ( !valid ) {
        SAL_WARN( "tools.fraction", "'operator /=' with invalid fraction" );
        return *this;
    }

    value /= rVal.value;

    if ( HasOverflowValue() ) {
        valid = false;
        SAL_WARN( "tools.fraction", "'operator /=' detected overflow" );
    }

    return *this;
}

/** Inaccurate cancellation for a fraction.

    Clip both nominator and denominator to said number of bits. If
    either of those already have equal or less number of bits used,
    this method does nothing.

    @param nSignificantBits denotes, how many significant binary
    digits to maintain, in both nominator and denominator.

    @example ReduceInaccurate(8) has an error <1% [1/2^(8-1)] - the
    largest error occurs with the following pair of values:

    binary    1000000011111111111111111111111b/1000000000000000000000000000000b
    =         1082130431/1073741824
    = approx. 1.007812499

    A ReduceInaccurate(8) yields 1/1.
*/
void Fraction::ReduceInaccurate( unsigned nSignificantBits )
{
    if ( !valid ) {
        SAL_WARN( "tools.fraction", "'ReduceInaccurate' on invalid fraction" );
        return;
    }
    if ( !value.numerator() )
        return;

    rational_ReduceInaccurate(value, nSignificantBits);
}

bool operator == ( const Fraction& rVal1, const Fraction& rVal2 )
{
    if ( !rVal1.valid || !rVal2.valid ) {
        SAL_WARN( "tools.fraction", "'operator ==' with an invalid fraction" );
        return false;
    }

    return rVal1.value == rVal2.value;
}

bool operator < ( const Fraction& rVal1, const Fraction& rVal2 )
{
    if ( !rVal1.valid || !rVal2.valid ) {
        SAL_WARN( "tools.fraction", "'operator <' with an invalid fraction" );
        return false;
    }

    return rVal1.value < rVal2.value;
}

bool operator > ( const Fraction& rVal1, const Fraction& rVal2 )
{
    if ( !rVal1.valid || !rVal2.valid ) {
        SAL_WARN( "tools.fraction", "'operator >' with an invalid fraction" );
        return false;
    }

    return rVal1.value > rVal2.value;
}

SvStream& ReadFraction( SvStream& rIStream, Fraction& rFract )
{
    sal_Int32 num(0), den(0);
    rIStream.ReadInt32( num );
    rIStream.ReadInt32( den );
    if ( den <= 0 ) {
        SAL_WARN( "tools.fraction", "'ReadFraction()' read an invalid fraction" );
        rFract.valid = false;
    } else {
        rFract.value.assign( num, den );
        rFract.valid = true;
    }
    return rIStream;
}

SvStream& WriteFraction( SvStream& rOStream, const Fraction& rFract )
{
    if ( !rFract.valid ) {
        SAL_WARN( "tools.fraction", "'WriteFraction()' write an invalid fraction" );
        rOStream.WriteInt32( 0 );
        rOStream.WriteInt32( -1 );
    } else {
        rOStream.WriteInt32( rFract.value.numerator() );
        rOStream.WriteInt32( rFract.value.denominator() );
    }
    return rOStream;
}

// If dVal > LONG_MAX or dVal < LONG_MIN, the rational throws a boost::bad_rational.
// Otherwise, dVal and denominator are multiplied by 10, until one of them
// is larger than (LONG_MAX / 10).
//
// NOTE: here we use 'long' due that only values in long range are valid.
template<typename T>
static boost::rational<T> rational_FromDouble(double dVal)
{
    if ( dVal > std::numeric_limits<long>::max() ||
            dVal < std::numeric_limits<long>::min() )
        throw boost::bad_rational();

    const long nMAX = std::numeric_limits<long>::max() / 10;
    long nDen = 1;
    while ( std::abs( dVal ) < nMAX && nDen < nMAX ) {
        dVal *= 10;
        nDen *= 10;
    }
    return boost::rational<T>( long(dVal), nDen );
}

// Similar to clz_table that can be googled
const char nbits_table[32] =
{
    32,  1, 23,  2, 29, 24, 14,  3,
    30, 27, 25, 18, 20, 15, 10,  4,
    31, 22, 28, 13, 26, 17, 19,  9,
    21, 12, 16,  8, 11,  7,  6,  5
};

static int impl_NumberOfBits( unsigned long nNum )
{
    // http://en.wikipedia.org/wiki/De_Bruijn_sequence
    // background paper: Using de Bruijn Sequences to Index a 1 in a
    // Computer Word (1998) Charles E. Leiserson,
    // Harald Prokop, Keith H. Randall
    // (e.g. http://citeseer.ist.psu.edu/leiserson98using.html)
    const sal_uInt32 nDeBruijn = 0x7DCD629;

    if ( nNum == 0 )
        return 0;

    // Get it to form like 0000001111111111b
    nNum |= ( nNum >>  1 );
    nNum |= ( nNum >>  2 );
    nNum |= ( nNum >>  4 );
    nNum |= ( nNum >>  8 );
    nNum |= ( nNum >> 16 );

    sal_uInt32 nNumber;
    int nBonus = 0;

#if SAL_TYPES_SIZEOFLONG == 4
    nNumber = nNum;
#elif SAL_TYPES_SIZEOFLONG == 8
    nNum |= ( nNum >> 32 );

    if ( nNum & 0x80000000 )
    {
        nNumber = sal_uInt32( nNum >> 32 );
        nBonus = 32;

        if ( nNumber == 0 )
            return 32;
    }
    else
        nNumber = sal_uInt32( nNum & 0xFFFFFFFF );
#else
#error "Unknown size of long!"
#endif

    // De facto shift left of nDeBruijn using multiplication (nNumber
    // is all ones from topmost bit, thus nDeBruijn + (nDeBruijn *
    // nNumber) => nDeBruijn * (nNumber+1) clears all those bits to
    // zero, sets the next bit to one, and thus effectively shift-left
    // nDeBruijn by lg2(nNumber+1). This generates a distinct 5bit
    // sequence in the msb for each distinct position of the last
    // leading 0 bit - that's the property of a de Bruijn number.
    nNumber = nDeBruijn + ( nDeBruijn * nNumber );

    // 5-bit window indexes the result
    return ( nbits_table[nNumber >> 27] ) + nBonus;
}

/** Inaccurate cancellation for a fraction.

    Clip both nominator and denominator to said number of bits. If
    either of those already have equal or less number of bits used,
    this method does nothing.

    @param nSignificantBits denotes, how many significant binary
    digits to maintain, in both nominator and denominator.

    @example ReduceInaccurate(8) has an error <1% [1/2^(8-1)] - the
    largest error occurs with the following pair of values:

    binary    1000000011111111111111111111111b/1000000000000000000000000000000b
    =         1082130431/1073741824
    = approx. 1.007812499

    A ReduceInaccurate(8) yields 1/1.
*/
template<typename T>
static void rational_ReduceInaccurate(boost::rational<T>& rRational, unsigned nSignificantBits)
{
    if ( !rRational )
        return;

    // http://www.boost.org/doc/libs/release/libs/rational/rational.html#Internal%20representation
    const bool bNeg = ( rRational.numerator() < 0 );
    T nMul = bNeg? -rRational.numerator(): rRational.numerator();
    T nDiv = rRational.denominator();

    DBG_ASSERT(nSignificantBits<65, "More than 64 bit of significance is overkill!");

    // How much bits can we lose?
    const int nMulBitsToLose = std::max( ( impl_NumberOfBits( nMul ) - int( nSignificantBits ) ), 0 );
    const int nDivBitsToLose = std::max( ( impl_NumberOfBits( nDiv ) - int( nSignificantBits ) ), 0 );

    const int nToLose = std::min( nMulBitsToLose, nDivBitsToLose );

    // Remove the bits
    nMul >>= nToLose;
    nDiv >>= nToLose;

    if ( !nMul || !nDiv ) {
        // Return without reduction
        OSL_FAIL( "Oops, we reduced too much..." );
        return;
    }

    rRational.assign( bNeg? -T( nMul ): T( nMul ), nDiv );
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<|endoftext|>


<commit_before>#include <QtTest/QtTest>
#include <QFile>
#include <QDir>
#include <QTextStream>
#include <iostream>
#include <THtmlParser>
#include "otmparser.h"
#include "otamaconverter.h"
#include "erbconverter.h"
#include "erbparser.h"

//static QString configPath;
extern int defaultTrimMode;

class TestTfpconverter: public QObject, public ErbConverter
{
    Q_OBJECT
public:
    TestTfpconverter() : ErbConverter(QDir("."), QDir()) { }
private slots:
    void initTestCase();
    void parse_data();
    void parse();
    void otamaconvert_data();
    void otamaconvert();
    void erbparse_data();
    void erbparse();
};

void TestTfpconverter::initTestCase()
{
    defaultTrimMode = 1;
//     configPath = QFileInfo(QCoreApplication::applicationFilePath()).absoluteDir().absolutePath() + QDir::separator() + ".." + QDir::separator() + ".." + QDir::separator() + "config" +  QDir::separator() + "treefrog.ini";
}

void TestTfpconverter::parse_data()
{
    QTest::addColumn<QString>("fileName");

    QTest::newRow("1") << "data1.phtm";
    QTest::newRow("2") << "data2.phtm";
    QTest::newRow("3") << "data3.phtm";
    QTest::newRow("4") << "data4.phtm";
    QTest::newRow("5") << "data5.phtm";
    QTest::newRow("6") << "data6.phtm";
    QTest::newRow("7") << "data7.phtm";
    QTest::newRow("8") << "data8.phtm";
}

void TestTfpconverter::parse()
{
    QFETCH(QString, fileName);

    QFile file(fileName);
    QVERIFY(file.open(QIODevice::ReadOnly | QIODevice::Text));
    QTextStream ts(&file);
    ts.setCodec("UTF-8");
    QString html = ts.readAll();

    THtmlParser parser;
    parser.parse(html);
    QString result = parser.toString();

    QFile res("result.phtm");
    res.open(QIODevice::WriteOnly | QIODevice::Truncate);
    QTextStream rests(&res);
    rests.setCodec("UTF-8");
    rests << result;
    res.close();

    QCOMPARE(html, result);
}

// void TestTfpconverter::olgparser_data()
// {
//     QTest::addColumn<QString>("fileName");
//     QTest::addColumn<QString>("label");
//     QTest::addColumn<int>("count");

//     QTest::newRow("1") << "logic1.olg" << "#hoge" << 2;
// }

// void TestTfpconverter::olgparser()
// {
//     QFETCH(QString, fileName);
//     QFETCH(QString, label);
//     QFETCH(int, count);

//     QFile file(fileName);
//     QVERIFY(file.open(QIODevice::ReadOnly | QIODevice::Text));
//     QTextStream ts(&file);
//     ts.setCodec("UTF-8");
//     QString olg = ts.readAll();

//     OlgParser parser("%%");
//     parser.parse(olg);
//     QStringList vals = parser.value(label);
//     qDebug() << vals.join(":");
//     QCOMPARE(vals.count(), count);
// }

void TestTfpconverter::otamaconvert_data()
{
    QTest::addColumn<QString>("htmlFileName");
    QTest::addColumn<QString>("olgFileName");
    QTest::addColumn<QString>("resultFileName");

    QTest::newRow("1") << "index1.html" << "logic1.olg" << "res1.html";
    QTest::newRow("2") << "index2.html" << "logic1.olg" << "res2.html";
    QTest::newRow("3") << "index3.html" << "logic1.olg" << "res3.html";
    QTest::newRow("4") << "index4.html" << "logic1.olg" << "res4.html";
    QTest::newRow("5") << "index5.html" << "logic1.olg" << "res5.html";
}

void TestTfpconverter::otamaconvert()
{
    QFETCH(QString, htmlFileName);
    QFETCH(QString, olgFileName);
    QFETCH(QString, resultFileName);

    QFile htmlFile(htmlFileName);
    QVERIFY(htmlFile.open(QIODevice::ReadOnly | QIODevice::Text));
    QTextStream tshtml(&htmlFile);
    tshtml.setCodec("UTF-8");

    QFile olgFile(olgFileName);
    QVERIFY(olgFile.open(QIODevice::ReadOnly | QIODevice::Text));
    QTextStream tsolg(&olgFile);
    tsolg.setCodec("UTF-8");

    QFile resultFile(resultFileName);
    QVERIFY(resultFile.open(QIODevice::ReadOnly | QIODevice::Text));
    QTextStream tsres(&resultFile);
    tsres.setCodec("UTF-8");

    QString result = OtamaConverter::convertToErb(tshtml.readAll(), tsolg.readAll());
    QString expect = tsres.readAll();
    QCOMPARE(result, expect);
}

void TestTfpconverter::erbparse_data()
{
    QTest::addColumn<QString>("erb");
    QTest::addColumn<QString>("expe");

    QTest::newRow("1") << "Hello ... \n"
                       << "  responsebody += tr(\"Hello ... \\n\");\n";
    QTest::newRow("2") << "Hello <%# this is comment!! %>"
                       << "  responsebody += tr(\"Hello \");\n  /* this is comment!! */\n  responsebody += tr(\"\");\n";
    QTest::newRow("3") << "Hello <%# this is comment!! %>   \n"
                       << "  responsebody += tr(\"Hello \");\n  /* this is comment!! */\n  responsebody += tr(\"\");\n";

    QTest::newRow("4") << "Hello <%# this is \"comment!!\" %>"
                       << "  responsebody += tr(\"Hello \");\n  /* this is \"comment!!\" */\n  responsebody += tr(\"\");\n";
    QTest::newRow("5") << "Hello <%# this is \"comment!!\" %>  \r\n"
                       << "  responsebody += tr(\"Hello \");\n  /* this is \"comment!!\" */\n  responsebody += tr(\"\");\n";

    QTest::newRow("6") << "Hello <% int i; %>"
                       << "  responsebody += tr(\"Hello \");\n  int i;\n  responsebody += tr(\"\");\n";
    QTest::newRow("7") << "Hello <% QString s(\"%>\"); %>"
                       << "  responsebody += tr(\"Hello \");\n  QString s(\"%>\");\n  responsebody += tr(\"\");\n";
    QTest::newRow("8") << "Hello <%== vvv %>"
                       << "  responsebody += tr(\"Hello \");\n  responsebody += QVariant(vvv).toString();\n  responsebody += tr(\"\");\n";
    QTest::newRow("9") << "Hello <%= vvv %> \n"
                       << "  responsebody += tr(\"Hello \");\n  responsebody += THttpUtility::htmlEscape(vvv);\n  responsebody += tr(\" \\n\");\n";
    QTest::newRow("10") << "Hello <%= vvv; -%> \n"
                        << "  responsebody += tr(\"Hello \");\n  responsebody += THttpUtility::htmlEscape(vvv);\n  responsebody += tr(\"\");\n";
    QTest::newRow("11") << "Hello <% int i; -%> \r\n "
                        << "  responsebody += tr(\"Hello \");\n  int i;\n  responsebody += tr(\" \");\n";
    QTest::newRow("12") << "Hello <% int i; %> \r\n"
                        << "  responsebody += tr(\"Hello \");\n  int i;\n  responsebody += tr(\"\");\n";
    QTest::newRow("13") << "Hello ... \r\n"
                        << "  responsebody += tr(\"Hello ... \\r\\n\");\n";

    /** echo export object **/
    QTest::newRow("14") << "Hello <%=$ hoge -%> \r\n "
                        << "  responsebody += tr(\"Hello \");\n  tehex(hoge);\n  responsebody += tr(\" \");\n";
    QTest::newRow("15") << "Hello <%==$ hoge %> \r\n "
                        << "  responsebody += tr(\"Hello \");\n  techoex(hoge);\n  responsebody += tr(\" \\r\\n \");\n";

    /** Echo a default value on ERB **/
    QTest::newRow("16") << "<%# comment. %|% 33 %>"
                        << "  responsebody += tr(\"\");\n  /* comment. */\n  responsebody += tr(\"\");\n";
    QTest::newRow("17") << "<%= number %|% 33 %>"
                        << "  responsebody += tr(\"\");\n  { QString ___s = QVariant(number).toString(); responsebody += (___s.isEmpty()) ? THttpUtility::htmlEscape(33) : THttpUtility::htmlEscape(___s); }\n  responsebody += tr(\"\");\n";
    QTest::newRow("18") << "<%== number %|% 33 %>"
                        << "  responsebody += tr(\"\");\n  { QString ___s = QVariant(number).toString(); responsebody += (___s.isEmpty()) ? QVariant(33).toString() : ___s; }\n  responsebody += tr(\"\");\n";
    QTest::newRow("19") << "<%=$number %|% 33 %>"
                        << "  responsebody += tr(\"\");\n  tehex2(number, (33));\n  responsebody += tr(\"\");\n";
    // Irregular pattern
    QTest::newRow("20") << "<%==$number %|% 33 -%>\t\n"
                        << "  responsebody += tr(\"\");\n  techoex2(number, (33));\n  responsebody += tr(\"\");\n";
    QTest::newRow("21") << "<%== \"  %|%\" %|% \"%|%\" -%> \t \n"
                        << "  responsebody += tr(\"\");\n  { QString ___s = QVariant(\"  %|%\").toString(); responsebody += (___s.isEmpty()) ? QVariant(\"%|%\").toString() : ___s; }\n  responsebody += tr(\"\");\n";
}

void TestTfpconverter::erbparse()
{
    QFETCH(QString, erb);
    QFETCH(QString, expe);

    ErbParser parser(ErbParser::NormalTrim);
    parser.parse(erb);
    QString result = parser.sourceCode();
    QCOMPARE(result, expe);
}

QTEST_MAIN(TestTfpconverter)
#include "tmaketest.moc"
<commit_msg>test case wad updated<commit_after>#include <QtTest/QtTest>
#include <QFile>
#include <QDir>
#include <QTextStream>
#include <iostream>
#include <THtmlParser>
#include "otmparser.h"
#include "otamaconverter.h"
#include "erbconverter.h"
#include "erbparser.h"

//static QString configPath;
extern int defaultTrimMode;

class TestTfpconverter: public QObject, public ErbConverter
{
    Q_OBJECT
public:
    TestTfpconverter() : ErbConverter(QDir("."), QDir()) { }
private slots:
    void initTestCase();
    void parse_data();
    void parse();
    void otamaconvert_data();
    void otamaconvert();
    void erbparse_data();
    void erbparse();
};

void TestTfpconverter::initTestCase()
{
    defaultTrimMode = 1;
//     configPath = QFileInfo(QCoreApplication::applicationFilePath()).absoluteDir().absolutePath() + QDir::separator() + ".." + QDir::separator() + ".." + QDir::separator() + "config" +  QDir::separator() + "treefrog.ini";
}

void TestTfpconverter::parse_data()
{
    QTest::addColumn<QString>("fileName");

    QTest::newRow("1") << "data1.phtm";
    QTest::newRow("2") << "data2.phtm";
    QTest::newRow("3") << "data3.phtm";
    QTest::newRow("4") << "data4.phtm";
    QTest::newRow("5") << "data5.phtm";
    QTest::newRow("6") << "data6.phtm";
    QTest::newRow("6-1") << "data6-1.phtm";
    QTest::newRow("7") << "data7.phtm";
    QTest::newRow("8") << "data8.phtm";
}

void TestTfpconverter::parse()
{
    QFETCH(QString, fileName);

    QFile file(fileName);
    QVERIFY(file.open(QIODevice::ReadOnly | QIODevice::Text));
    QTextStream ts(&file);
    ts.setCodec("UTF-8");
    QString html = ts.readAll();

    THtmlParser parser;
    parser.parse(html);
    QString result = parser.toString();

    QFile res("result.phtm");
    res.open(QIODevice::WriteOnly | QIODevice::Truncate);
    QTextStream rests(&res);
    rests.setCodec("UTF-8");
    rests << result;
    res.close();

    QCOMPARE(html, result);
}

// void TestTfpconverter::olgparser_data()
// {
//     QTest::addColumn<QString>("fileName");
//     QTest::addColumn<QString>("label");
//     QTest::addColumn<int>("count");

//     QTest::newRow("1") << "logic1.olg" << "#hoge" << 2;
// }

// void TestTfpconverter::olgparser()
// {
//     QFETCH(QString, fileName);
//     QFETCH(QString, label);
//     QFETCH(int, count);

//     QFile file(fileName);
//     QVERIFY(file.open(QIODevice::ReadOnly | QIODevice::Text));
//     QTextStream ts(&file);
//     ts.setCodec("UTF-8");
//     QString olg = ts.readAll();

//     OlgParser parser("%%");
//     parser.parse(olg);
//     QStringList vals = parser.value(label);
//     qDebug() << vals.join(":");
//     QCOMPARE(vals.count(), count);
// }

void TestTfpconverter::otamaconvert_data()
{
    QTest::addColumn<QString>("htmlFileName");
    QTest::addColumn<QString>("olgFileName");
    QTest::addColumn<QString>("resultFileName");

    QTest::newRow("1") << "index1.html" << "logic1.olg" << "res1.html";
    QTest::newRow("2") << "index2.html" << "logic1.olg" << "res2.html";
    QTest::newRow("3") << "index3.html" << "logic1.olg" << "res3.html";
    QTest::newRow("4") << "index4.html" << "logic1.olg" << "res4.html";
    QTest::newRow("5") << "index5.html" << "logic1.olg" << "res5.html";
}

void TestTfpconverter::otamaconvert()
{
    QFETCH(QString, htmlFileName);
    QFETCH(QString, olgFileName);
    QFETCH(QString, resultFileName);

    QFile htmlFile(htmlFileName);
    QVERIFY(htmlFile.open(QIODevice::ReadOnly | QIODevice::Text));
    QTextStream tshtml(&htmlFile);
    tshtml.setCodec("UTF-8");

    QFile olgFile(olgFileName);
    QVERIFY(olgFile.open(QIODevice::ReadOnly | QIODevice::Text));
    QTextStream tsolg(&olgFile);
    tsolg.setCodec("UTF-8");

    QFile resultFile(resultFileName);
    QVERIFY(resultFile.open(QIODevice::ReadOnly | QIODevice::Text));
    QTextStream tsres(&resultFile);
    tsres.setCodec("UTF-8");

    QString result = OtamaConverter::convertToErb(tshtml.readAll(), tsolg.readAll());
    QString expect = tsres.readAll();
    QCOMPARE(result, expect);
}

void TestTfpconverter::erbparse_data()
{
    QTest::addColumn<QString>("erb");
    QTest::addColumn<QString>("expe");

    QTest::newRow("1") << "Hello ... \n"
                       << "  responsebody += tr(\"Hello ... \\n\");\n";
    QTest::newRow("2") << "Hello <%# this is comment!! %>"
                       << "  responsebody += tr(\"Hello \");\n  /* this is comment!! */\n  responsebody += tr(\"\");\n";
    QTest::newRow("3") << "Hello <%# this is comment!! %>   \n"
                       << "  responsebody += tr(\"Hello \");\n  /* this is comment!! */\n  responsebody += tr(\"\");\n";

    QTest::newRow("4") << "Hello <%# this is \"comment!!\" %>"
                       << "  responsebody += tr(\"Hello \");\n  /* this is \"comment!!\" */\n  responsebody += tr(\"\");\n";
    QTest::newRow("5") << "Hello <%# this is \"comment!!\" %>  \r\n"
                       << "  responsebody += tr(\"Hello \");\n  /* this is \"comment!!\" */\n  responsebody += tr(\"\");\n";

    QTest::newRow("6") << "Hello <% int i; %>"
                       << "  responsebody += tr(\"Hello \");\n  int i;\n  responsebody += tr(\"\");\n";
    QTest::newRow("7") << "Hello <% QString s(\"%>\"); %>"
                       << "  responsebody += tr(\"Hello \");\n  QString s(\"%>\");\n  responsebody += tr(\"\");\n";
    QTest::newRow("8") << "Hello <%== vvv %>"
                       << "  responsebody += tr(\"Hello \");\n  responsebody += QVariant(vvv).toString();\n  responsebody += tr(\"\");\n";
    QTest::newRow("9") << "Hello <%= vvv %> \n"
                       << "  responsebody += tr(\"Hello \");\n  responsebody += THttpUtility::htmlEscape(vvv);\n  responsebody += tr(\" \\n\");\n";
    QTest::newRow("10") << "Hello <%= vvv; -%> \n"
                        << "  responsebody += tr(\"Hello \");\n  responsebody += THttpUtility::htmlEscape(vvv);\n  responsebody += tr(\"\");\n";
    QTest::newRow("11") << "Hello <% int i; -%> \r\n "
                        << "  responsebody += tr(\"Hello \");\n  int i;\n  responsebody += tr(\" \");\n";
    QTest::newRow("12") << "Hello <% int i; %> \r\n"
                        << "  responsebody += tr(\"Hello \");\n  int i;\n  responsebody += tr(\"\");\n";
    QTest::newRow("13") << "Hello ... \r\n"
                        << "  responsebody += tr(\"Hello ... \\r\\n\");\n";

    /** echo export object **/
    QTest::newRow("14") << "Hello <%=$ hoge -%> \r\n "
                        << "  responsebody += tr(\"Hello \");\n  tehex(hoge);\n  responsebody += tr(\" \");\n";
    QTest::newRow("15") << "Hello <%==$ hoge %> \r\n "
                        << "  responsebody += tr(\"Hello \");\n  techoex(hoge);\n  responsebody += tr(\" \\r\\n \");\n";

    /** Echo a default value on ERB **/
    QTest::newRow("16") << "<%# comment. %|% 33 %>"
                        << "  responsebody += tr(\"\");\n  /* comment. */\n  responsebody += tr(\"\");\n";
    QTest::newRow("17") << "<%= number %|% 33 %>"
                        << "  responsebody += tr(\"\");\n  { QString ___s = QVariant(number).toString(); responsebody += (___s.isEmpty()) ? THttpUtility::htmlEscape(33) : THttpUtility::htmlEscape(___s); }\n  responsebody += tr(\"\");\n";
    QTest::newRow("18") << "<%== number %|% 33 %>"
                        << "  responsebody += tr(\"\");\n  { QString ___s = QVariant(number).toString(); responsebody += (___s.isEmpty()) ? QVariant(33).toString() : ___s; }\n  responsebody += tr(\"\");\n";
    QTest::newRow("19") << "<%=$number %|% 33 %>"
                        << "  responsebody += tr(\"\");\n  tehex2(number, (33));\n  responsebody += tr(\"\");\n";
    // Irregular pattern
    QTest::newRow("20") << "<%==$number %|% 33 -%>\t\n"
                        << "  responsebody += tr(\"\");\n  techoex2(number, (33));\n  responsebody += tr(\"\");\n";
    QTest::newRow("21") << "<%== \"  %|%\" %|% \"%|%\" -%> \t \n"
                        << "  responsebody += tr(\"\");\n  { QString ___s = QVariant(\"  %|%\").toString(); responsebody += (___s.isEmpty()) ? QVariant(\"%|%\").toString() : ___s; }\n  responsebody += tr(\"\");\n";
}

void TestTfpconverter::erbparse()
{
    QFETCH(QString, erb);
    QFETCH(QString, expe);

    ErbParser parser(ErbParser::NormalTrim);
    parser.parse(erb);
    QString result = parser.sourceCode();
    QCOMPARE(result, expe);
}

QTEST_MAIN(TestTfpconverter)
#include "tmaketest.moc"
<|endoftext|>


<commit_before>#include "zmtp_socket.h"
#include "util.h"

zmtp_socket_state_t parse_greeting (zmtp_socket_state_t old_state, uint8_t *buffer, int length) {
  assert (buffer);

  zmtp_socket_state_t new_state = old_state;

  if (new_state == SIG_WAIT) {
    Serial.printf("buffer: %x, length: %d\n", buffer, length);

    if (length < 10 || buffer[0] != 0xFF || buffer[9] != 0x7F) {
      return _ERROR;
    }

    new_state = SIG_ACK;
    buffer += 10;
    length -= 10;
  }

  if (length == 0) {
    return new_state;
  }

  if (new_state == SIG_ACK) {
    Serial.printf("buffer: %x, length: %d\n", buffer, length);

    if (length < 2 || buffer[0] != 0x03 || buffer[1] != 0x00) {
      return _ERROR;
    }

    new_state = VER_ACK;
    buffer += 2;
    length -= 2;
  }

  if (length == 0) {
    return new_state;
  }

  if (new_state == VER_ACK) {
    Serial.printf("buffer: %x, length: %d\n", buffer, length);

    if (length < 52 || memcmp (buffer, "NULL", 4)) {
      return _ERROR;
    }

    new_state = GRT_ACK;
  }

  return new_state;
}

zmtp_socket_state_t parse_handshake (uint8_t *buffer, int length) {
  assert (buffer);

  if (length <= 2 || buffer[0] != 0x04) {
    return _ERROR;
  }

  uint8_t command_size = buffer[1];

  if (command_size > length || command_size < 6) {
    return _ERROR;
  }

  if (buffer[2] != 0x05 || !memcpy (buffer + 3, "READY", 5)) {
    return _ERROR;
  }

  return READY;
}

ZMTPSocket::ZMTPSocket (zmtp_socket_type_t type) {
  this->type = type;
  this->state = INIT;
  this->identity = NULL;
  this->identity_size = 0;
}

ZMTPSocket::~ZMTPSocket () {
  delete this->identity;
}

void ZMTPSocket::setIdentity (uint8_t *data, size_t size) {
  assert (data);
  assert (size < 256);

  if (this->identity) {
    delete this->identity;
  }

  this->identity = new uint8_t[size];
  memcpy (this->identity, data, size);
  identity_size = size;
}

bool ZMTPSocket::ready () {
  return this->state == READY;
}

bool ZMTPSocket::connect (uint8_t *addr, uint16_t port) {
  assert (this->state == INIT);
  assert (addr);

  bool success = this->socket.connect (IPAddress (addr), port);

  if (success) {
    Serial.println ("Connected.");

    assert (this->type == DEALER);
    uint8_t greeting[64];
    memset (greeting, 0, 64);

    // signature
    greeting[0] = 0xFF;
    greeting[9] = 0x7F;

    // version
    greeting[10] = 0x03;
    greeting[11] = 0x00;

    // mechanism
    memcpy (greeting + 12, "NULL", 4);

    // as-server
    greeting[32] = 0x00;

    zmtp_debug_dump (greeting, 64);

    this->socket.write (greeting, 64);
    this->socket.flush ();

    this->state = SIG_WAIT;
  } else {
    Serial.println ("Failed to connect.");

    this->state = _ERROR;
  }

  this->print ();

  return success;
}

void ZMTPSocket::update () {
  if (this->socket.available ()) {
    uint8_t buffer[256];
    int bytes_read = this->socket.read (buffer, 256);
    Serial.printf ("Bytes read: %d\n", bytes_read);

    Serial.print ("Bytes: ");
    zmtp_debug_dump (buffer, bytes_read);

    switch (this->state) {
      case SIG_WAIT:
      case SIG_ACK:
      case VER_ACK:
      case GRT_ACK:
        this->state = parse_greeting (this->state, buffer, bytes_read);

        this->print ();

        if (this->state == GRT_ACK) {
          Serial.println ("Received ZMTP greeting.");
          this->sendHandshake ();
          this->state = READY_WAIT;
        }
        break;

      case READY_WAIT:
        this->state = parse_handshake (buffer, bytes_read);
        if (this->state == READY) {
          Serial.println ("Received ZMTP handshake.");
        }
        break;

      case READY:
        Serial.println ("Message frame.");
        break;

      case INIT:
      case _ERROR:
      default:
        break;
    }
  }
}

void ZMTPSocket::send (zmtp_frame_t *frame) {
  assert (this->state == READY);
  assert (frame);

  this->socket.write (zmtp_frame_bytes (frame), zmtp_frame_size (frame));
  this->socket.flush ();
}

void ZMTPSocket::print () {
  zmtp_debug_dump (this->type);
  zmtp_debug_dump (this->state);
}

void ZMTPSocket::sendHandshake () {
  uint8_t handshake[60];

  // command-size
  handshake[0] = 0x04;
  handshake[1] = 58;

  // ready
  handshake[2] = 0x05;
  memcpy (handshake + 3, "READY", 5);

  // metadata
  handshake[8] = 11;
  memcpy (handshake + 9, "Socket-Type", 11);
  memset (handshake + 20, 0, 4);
  handshake[23] = 6;
  memcpy (handshake + 24, "DEALER", 6);

  handshake[30] = 8;
  memcpy (handshake + 31, "Identity", 8);
  memset (handshake + 39, 0, 4);
  handshake[42] = this->identity_size + 1;
  handshake[43] = 1;
  memcpy (handshake + 44, this->identity, this->identity_size);

  zmtp_debug_dump (handshake, 60);

  this->socket.write (handshake, 60);
  this->socket.flush ();
}
<commit_msg>Flush all available data on update.<commit_after>#include "zmtp_socket.h"
#include "util.h"

zmtp_socket_state_t parse_greeting (zmtp_socket_state_t old_state, uint8_t *buffer, int length) {
  assert (buffer);

  zmtp_socket_state_t new_state = old_state;

  if (new_state == SIG_WAIT) {
    Serial.printf("buffer: %x, length: %d\n", buffer, length);

    if (length < 10 || buffer[0] != 0xFF || buffer[9] != 0x7F) {
      return _ERROR;
    }

    new_state = SIG_ACK;
    buffer += 10;
    length -= 10;
  }

  if (length == 0) {
    return new_state;
  }

  if (new_state == SIG_ACK) {
    Serial.printf("buffer: %x, length: %d\n", buffer, length);

    if (length < 2 || buffer[0] != 0x03 || buffer[1] != 0x00) {
      return _ERROR;
    }

    new_state = VER_ACK;
    buffer += 2;
    length -= 2;
  }

  if (length == 0) {
    return new_state;
  }

  if (new_state == VER_ACK) {
    Serial.printf("buffer: %x, length: %d\n", buffer, length);

    if (length < 52 || memcmp (buffer, "NULL", 4)) {
      return _ERROR;
    }

    new_state = GRT_ACK;
  }

  return new_state;
}

zmtp_socket_state_t parse_handshake (uint8_t *buffer, int length) {
  assert (buffer);

  if (length <= 2 || buffer[0] != 0x04) {
    return _ERROR;
  }

  uint8_t command_size = buffer[1];

  if (command_size > length || command_size < 6) {
    return _ERROR;
  }

  if (buffer[2] != 0x05 || !memcpy (buffer + 3, "READY", 5)) {
    return _ERROR;
  }

  return READY;
}

ZMTPSocket::ZMTPSocket (zmtp_socket_type_t type) {
  this->type = type;
  this->state = INIT;
  this->identity = NULL;
  this->identity_size = 0;
}

ZMTPSocket::~ZMTPSocket () {
  delete this->identity;
}

void ZMTPSocket::setIdentity (uint8_t *data, size_t size) {
  assert (data);
  assert (size < 256);

  if (this->identity) {
    delete this->identity;
  }

  this->identity = new uint8_t[size];
  memcpy (this->identity, data, size);
  identity_size = size;
}

bool ZMTPSocket::ready () {
  return this->state == READY;
}

bool ZMTPSocket::connect (uint8_t *addr, uint16_t port) {
  assert (this->state == INIT);
  assert (addr);

  bool success = this->socket.connect (IPAddress (addr), port);

  if (success) {
    Serial.println ("Connected.");

    assert (this->type == DEALER);
    uint8_t greeting[64];
    memset (greeting, 0, 64);

    // signature
    greeting[0] = 0xFF;
    greeting[9] = 0x7F;

    // version
    greeting[10] = 0x03;
    greeting[11] = 0x00;

    // mechanism
    memcpy (greeting + 12, "NULL", 4);

    // as-server
    greeting[32] = 0x00;

    zmtp_debug_dump (greeting, 64);

    this->socket.write (greeting, 64);
    this->socket.flush ();

    this->state = SIG_WAIT;
  } else {
    Serial.println ("Failed to connect.");

    this->state = _ERROR;
  }

  this->print ();

  return success;
}

void ZMTPSocket::update () {
  while (this->socket.available ()) {
    uint8_t buffer[256];
    int bytes_read = this->socket.read (buffer, 256);
    Serial.printf ("Bytes read: %d\n", bytes_read);

    Serial.print ("Bytes: ");
    zmtp_debug_dump (buffer, bytes_read);

    switch (this->state) {
      case SIG_WAIT:
      case SIG_ACK:
      case VER_ACK:
      case GRT_ACK:
        this->state = parse_greeting (this->state, buffer, bytes_read);

        this->print ();

        if (this->state == GRT_ACK) {
          Serial.println ("Received ZMTP greeting.");
          this->sendHandshake ();
          this->state = READY_WAIT;
        }
        break;

      case READY_WAIT:
        this->state = parse_handshake (buffer, bytes_read);
        if (this->state == READY) {
          Serial.println ("Received ZMTP handshake.");
        }
        break;

      case READY:
        Serial.println ("Message frame.");
        break;

      case INIT:
      case _ERROR:
      default:
        break;
    }
  }
}

void ZMTPSocket::send (zmtp_frame_t *frame) {
  assert (this->state == READY);
  assert (frame);

  this->socket.write (zmtp_frame_bytes (frame), zmtp_frame_size (frame));
  this->socket.flush ();
}

void ZMTPSocket::print () {
  zmtp_debug_dump (this->type);
  zmtp_debug_dump (this->state);
}

void ZMTPSocket::sendHandshake () {
  uint8_t handshake[60];

  // command-size
  handshake[0] = 0x04;
  handshake[1] = 58;

  // ready
  handshake[2] = 0x05;
  memcpy (handshake + 3, "READY", 5);

  // metadata
  handshake[8] = 11;
  memcpy (handshake + 9, "Socket-Type", 11);
  memset (handshake + 20, 0, 4);
  handshake[23] = 6;
  memcpy (handshake + 24, "DEALER", 6);

  handshake[30] = 8;
  memcpy (handshake + 31, "Identity", 8);
  memset (handshake + 39, 0, 4);
  handshake[42] = this->identity_size + 1;
  handshake[43] = 1;
  memcpy (handshake + 44, this->identity, this->identity_size);

  zmtp_debug_dump (handshake, 60);

  this->socket.write (handshake, 60);
  this->socket.flush ();
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2014 Samsung Electronics Co., Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

#include <dali/dali.h>
#include <iostream>

using namespace Dali;

// This example shows how to create and display Hello World! using a simple TextActor
//
class HelloWorldController : public ConnectionTracker
{
public:

  HelloWorldController( Application& application )
  : mApplication( application )
  {
    std::cout << "HelloWorldController::HelloWorldController" << std::endl;

    // Connect to the Application's Init signal
    mApplication.InitSignal().Connect( this, &HelloWorldController::Create );
  }

  ~HelloWorldController()
  {
    // Nothing to do here;
  }

  // The Init signal is received once (only) during the Application lifetime
  void Create( Application& application )
  {
    // TODO
  }

  bool OnTouch( Actor actor, const TouchEvent& touch )
  {
    // quit the application
    mApplication.Quit();
    return true;
  }

private:
  Application&  mApplication;
};

void RunTest( Application& application )
{
  HelloWorldController test( application );

  application.MainLoop();
}

// Entry point for Linux & Tizen applications
//
int main( int argc, char **argv )
{
  Application application = Application::New( &argc, &argv );

  RunTest( application );

  return 0;
}
<commit_msg>Fixed the Hello World example<commit_after>/*
 * Copyright (c) 2014 Samsung Electronics Co., Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

#include <dali-toolkit/dali-toolkit.h>

using namespace Dali;
using Dali::Toolkit::TextLabel;

// This example shows how to create and display Hello World! using a simple TextActor
//
class HelloWorldController : public ConnectionTracker
{
public:

  HelloWorldController( Application& application )
  : mApplication( application )
  {
    // Connect to the Application's Init signal
    mApplication.InitSignal().Connect( this, &HelloWorldController::Create );
  }

  ~HelloWorldController()
  {
    // Nothing to do here;
  }

  // The Init signal is received once (only) during the Application lifetime
  void Create( Application& application )
  {
    // Get a handle to the stage
    Stage stage = Stage::GetCurrent();

    TextLabel textLabel = TextLabel::New();
    textLabel.SetAnchorPoint( AnchorPoint::TOP_LEFT );
    textLabel.SetProperty( TextLabel::Property::TEXT, "Hello World" );
    stage.Add( textLabel );

    // Respond to a click anywhere on the stage
    stage.GetRootLayer().TouchedSignal().Connect( this, &HelloWorldController::OnTouch );
  }

  bool OnTouch( Actor actor, const TouchEvent& touch )
  {
    // quit the application
    mApplication.Quit();
    return true;
  }

private:
  Application&  mApplication;
};

void RunTest( Application& application )
{
  HelloWorldController test( application );

  application.MainLoop();
}

// Entry point for Linux & Tizen applications
//
int main( int argc, char **argv )
{
  Application application = Application::New( &argc, &argv );

  RunTest( application );

  return 0;
}
<|endoftext|>


<commit_before>#include "FortWrap.h"
#include <iostream>
using namespace std;

int main(void)
{
  float fa=1.0, fb=2.0;
  double da=1.0, db=2.0;

  if (FortFuncs::add_floats(fa,fb) != fa+fb)
    return 1;

  if (FortFuncs::add_doubles(da,db) != da+db)
    return 2;

  return 3;
}
<commit_msg>Removing a debug piece of code that was left in.<commit_after>#include "FortWrap.h"
#include <iostream>
using namespace std;

int main(void)
{
  float fa=1.0, fb=2.0;
  double da=1.0, db=2.0;

  if (FortFuncs::add_floats(fa,fb) != fa+fb)
    return 1;

  if (FortFuncs::add_doubles(da,db) != da+db)
    return 2;

  return 0;
}
<|endoftext|>