<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$ */

///////////////////////////////////////////////////////////////////////////////
//                                                                           //
//  TRD raw data conversion class                                            //
//                                                                           //
///////////////////////////////////////////////////////////////////////////////

#include <Riostream.h>

#include "AliTRDrawData.h"
#include "AliTRDdigitsManager.h"
#include "AliTRDgeometry.h"
#include "AliTRDdataArrayI.h"
#include "AliTRDRawStream.h"
#include "AliRawDataHeader.h"
#include "AliRawReader.h"
#include "AliTRDCommonParam.h"
#include "AliTRDcalibDB.h"
#include "AliDAQ.h"

ClassImp(AliTRDrawData)

//_____________________________________________________________________________
AliTRDrawData::AliTRDrawData():TObject()
{
  //
  // Default constructor
  //

  fDebug         = 0;

}

//_____________________________________________________________________________
AliTRDrawData::AliTRDrawData(const AliTRDrawData &r):TObject()
{
  //
  // AliTRDrawData copy constructor
  //

  ((AliTRDrawData &) r).Copy(*this);

}

//_____________________________________________________________________________
AliTRDrawData::~AliTRDrawData()
{
  //
  // Destructor
  //

}

//_____________________________________________________________________________
AliTRDrawData &AliTRDrawData::operator=(const AliTRDrawData &r)
{
  //
  // Assignment operator
  //

  if (this != &r) ((AliTRDrawData &) r).Copy(*this);
  return *this;

}

//_____________________________________________________________________________
void AliTRDrawData::Copy(TObject &r) const
{
  //
  // Copy function
  //

  ((AliTRDrawData &) r).fDebug         = fDebug;

}

//_____________________________________________________________________________
Bool_t AliTRDrawData::Digits2Raw(TTree *digitsTree)
{
  //
  // Convert the digits to raw data byte stream. The output is written
  // into the the binary files TRD_<DDL number>.ddl.
  //
  // The pseudo raw data format is currently defined like this:
  //
  //          DDL data header
  //
  //          Subevent (= single chamber) header (8 bytes)
  //                  FLAG
  //                  Detector number (2 bytes)
  //                  Number of data bytes (2 bytes)
  //                  Number of pads with data (2 bytes)
  //                  1 empty byte
  //
  //          Data bank
  //

  const Int_t kNumberOfDDLs         = AliDAQ::NumberOfDdls("TRD");
  const Int_t kSubeventHeaderLength = 8;
  const Int_t kSubeventDummyFlag    = 0xBB;
  Int_t       headerSubevent[3];

  ofstream      *outputFile[kNumberOfDDLs];
  UInt_t         bHPosition[kNumberOfDDLs];
  Int_t          ntotalbyte[kNumberOfDDLs];
  Int_t          nbyte = 0;
  Int_t          npads = 0;
  unsigned char *bytePtr;
  unsigned char *headerPtr;

  AliTRDdigitsManager* digitsManager = new AliTRDdigitsManager();
  digitsManager->SetDebug(fDebug);

  // Read in the digit arrays
  if (!digitsManager->ReadDigits(digitsTree)) {
    delete digitsManager;
    return kFALSE;
  }

  AliTRDgeometry   *geo = new AliTRDgeometry();
  AliTRDdataArrayI *digits;

  AliTRDCommonParam* commonParam = AliTRDCommonParam::Instance();
  if (!commonParam)
  {
    printf("<AliTRDrawData::Digits2Raw> ");
    printf("Could not get common params\n");
    return 0;
  }

  AliTRDcalibDB* calibration = AliTRDcalibDB::Instance();
  if (!calibration)
  {
    printf("<AliTRDdigitizer::Digits2Raw> ");
    printf("Could not get calibration object\n");
    return kFALSE;
  }

  // the event header
  AliRawDataHeader header;

  // Open the output files
  for (Int_t iDDL = 0; iDDL < kNumberOfDDLs; iDDL++) {
    char name[20];
    strcpy(name,AliDAQ::DdlFileName("TRD",iDDL));
#ifndef __DECCXX
    outputFile[iDDL] = new ofstream(name, ios::binary);
#else
    outputFile[iDDL] = new ofstream(name);
#endif

    // Write a dummy data header
    bHPosition[iDDL] = outputFile[iDDL]->tellp();
    outputFile[iDDL]->write((char*)(&header),sizeof(header));
    ntotalbyte[iDDL] = 0;
  }

  // Loop through all detectors
  for (Int_t det = 0; det < AliTRDgeometry::Ndet(); det++) {

    Int_t cham      = geo->GetChamber(det);
    Int_t plan      = geo->GetPlane(det);
    Int_t sect      = geo->GetSector(det);
    Int_t rowMax    = commonParam->GetRowMax(plan,cham,sect);
    Int_t colMax    = commonParam->GetColMax(plan);
    Int_t timeTotal = calibration->GetNumberOfTimeBins();
    Int_t bufferMax = rowMax*colMax*timeTotal;
    Int_t *buffer   = new Int_t[bufferMax];

    npads   = 0;
    nbyte   = 0;
    bytePtr = (unsigned char *) buffer;

    Int_t iDDL = sect;

    // Get the digits array
    digits = digitsManager->GetDigits(det);
    digits->Expand();

    // Loop through the detector pixel
    for (Int_t col = 0; col < colMax; col++) {
      for (Int_t row = 0; row < rowMax; row++) {

	// Check whether data exists for this pad
        Bool_t dataflag = kFALSE;
        for (Int_t time = 0; time < timeTotal; time++) {
          Int_t data = digits->GetDataUnchecked(row,col,time);
          if (data) {
            dataflag = kTRUE;
            break;
	  }
	}

        if (dataflag) {

          npads++;

	  // The pad row number
          *bytePtr++ = row + 1;
	  // The pad column number
          *bytePtr++ = col + 1;
          nbyte += 2;

          Int_t nzero = 0;
          for (Int_t time = 0; time < timeTotal; time++) {

            Int_t data = digits->GetDataUnchecked(row,col,time);

            if (!data) {
              nzero++;
              if ((nzero ==       256) ||
                  (time  == timeTotal-1)) {
                *bytePtr++ = 0;
                *bytePtr++ = nzero-1;
                nbyte += 2;
                nzero  = 0;
      	      }
	    }
            else {
              if (nzero) {
                *bytePtr++ = 0;
                *bytePtr++ = nzero-1;
                nbyte += 2;
                nzero  = 0;
	      }
              // High byte (MSB always set)
              *bytePtr++ = ((data >> 8) | 128);
              // Low byte
              *bytePtr++ = (data & 0xff);
              nbyte += 2;
	    }

	  }

	}

      }

    }

    // Fill the end of the buffer with zeros
    while (nbyte % 4) {
      *bytePtr++ = 0;
      nbyte++;
    }

    if (fDebug > 1) {
      Info("Digits2Raw","det = %d, nbyte = %d (%d)",det,nbyte,bufferMax);
    }

    // Write the subevent header
    bytePtr    = (unsigned char *) headerSubevent;
    headerPtr  = bytePtr;
    *bytePtr++ = kSubeventDummyFlag;
    *bytePtr++ = (det   & 0xff);
    *bytePtr++ = (det   >> 8);
    *bytePtr++ = (nbyte & 0xff);
    *bytePtr++ = (nbyte >> 8);
    *bytePtr++ = (nbyte >> 16);
    *bytePtr++ = (npads & 0xff);
    *bytePtr++ = (npads >> 8);
    outputFile[iDDL]->write((char*)headerPtr,kSubeventHeaderLength);

    // Write the buffer to the file
    bytePtr = (unsigned char *) buffer;
    outputFile[iDDL]->write((char*)bytePtr,nbyte);

    ntotalbyte[iDDL] += nbyte + kSubeventHeaderLength;

    delete buffer;

  }

  if (fDebug) {
    for (Int_t iDDL = 0; iDDL < kNumberOfDDLs; iDDL++) {
      Info("Digits2Raw","Total size: DDL %d = %d",iDDL,ntotalbyte[iDDL]);
    }
  }

  // Update the data headers and close the output files
  for (Int_t iDDL = 0; iDDL < kNumberOfDDLs; iDDL++) {
    header.fSize = UInt_t(outputFile[iDDL]->tellp()) - bHPosition[iDDL];
    header.SetAttribute(0);  // valid data
    outputFile[iDDL]->seekp(bHPosition[iDDL]);
    outputFile[iDDL]->write((char*)(&header),sizeof(header));

    outputFile[iDDL]->close();
    delete outputFile[iDDL];
  }

  delete geo;
  delete digitsManager;

  return kTRUE;

}

//_____________________________________________________________________________
AliTRDdigitsManager* AliTRDrawData::Raw2Digits(AliRawReader* rawReader)
{
  //
  // Read the raw data digits and put them into the returned digits manager
  //

  AliTRDdataArrayI *digits    = 0;
  AliTRDdataArrayI *track0    = 0;
  AliTRDdataArrayI *track1    = 0;
  AliTRDdataArrayI *track2    = 0;

  AliTRDgeometry *geo = new AliTRDgeometry();

  AliTRDCommonParam* commonParam = AliTRDCommonParam::Instance();
  if (!commonParam)
  {
    printf("<AliTRDrawData::Raw2Digits> ");
    printf("Could not get common params\n");
    return 0;
  }

  AliTRDcalibDB* calibration = AliTRDcalibDB::Instance();
  if (!calibration)
  {
    printf("<AliTRDdigitizer::Raw2Digits> ");
    printf("Could not get calibration object\n");
    return 0;
  }

  // Create the digits manager
  AliTRDdigitsManager* digitsManager = new AliTRDdigitsManager();
  digitsManager->SetDebug(fDebug);
  digitsManager->CreateArrays();

  AliTRDRawStream input(rawReader);

  // Loop through the digits
  while (input.Next()) {

    Int_t det    = input.GetDetector();
    Int_t npads  = input.GetNPads();

    if (input.IsNewDetector()) {

      if (digits) digits->Compress(1,0);
      if (track0) track0->Compress(1,0);
      if (track1) track1->Compress(1,0);
      if (track2) track2->Compress(1,0);

      if (fDebug > 2) {
	Info("Raw2Digits","Subevent header:");
	Info("Raw2Digits","\tdet   = %d",det);
	Info("Raw2Digits","\tnpads = %d",npads);
      }

      // Create the data buffer
      Int_t cham      = geo->GetChamber(det);
      Int_t plan      = geo->GetPlane(det);
      Int_t sect      = geo->GetSector(det);
      Int_t rowMax    = commonParam->GetRowMax(plan,cham,sect);
      Int_t colMax    = commonParam->GetColMax(plan);
      Int_t timeTotal = calibration->GetNumberOfTimeBins();

      // Add a container for the digits of this detector
      digits = digitsManager->GetDigits(det);
      track0 = digitsManager->GetDictionary(det,0);
      track1 = digitsManager->GetDictionary(det,1);
      track2 = digitsManager->GetDictionary(det,2);
      // Allocate memory space for the digits buffer
      if (digits->GetNtime() == 0) {
        digits->Allocate(rowMax,colMax,timeTotal);
        track0->Allocate(rowMax,colMax,timeTotal);
        track1->Allocate(rowMax,colMax,timeTotal);
        track2->Allocate(rowMax,colMax,timeTotal);
      }

    }

    digits->SetDataUnchecked(input.GetRow(),input.GetColumn(),
			     input.GetTime(),input.GetSignal());
    track0->SetDataUnchecked(input.GetRow(),input.GetColumn(),
                             input.GetTime(),               -1);
    track1->SetDataUnchecked(input.GetRow(),input.GetColumn(),
                             input.GetTime(),               -1);
    track2->SetDataUnchecked(input.GetRow(),input.GetColumn(),
                             input.GetTime(),               -1);
  }

  if (digits) digits->Compress(1,0);
  if (track0) track0->Compress(1,0);
  if (track1) track1->Compress(1,0);
  if (track2) track2->Compress(1,0);

  delete geo;

  return digitsManager;

}
<commit_msg>Compiler warning fixed.<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$ */

///////////////////////////////////////////////////////////////////////////////
//                                                                           //
//  TRD raw data conversion class                                            //
//                                                                           //
///////////////////////////////////////////////////////////////////////////////

#include <Riostream.h>

#include "AliTRDrawData.h"
#include "AliTRDdigitsManager.h"
#include "AliTRDgeometry.h"
#include "AliTRDdataArrayI.h"
#include "AliTRDRawStream.h"
#include "AliRawDataHeader.h"
#include "AliRawReader.h"
#include "AliTRDCommonParam.h"
#include "AliTRDcalibDB.h"
#include "AliDAQ.h"

ClassImp(AliTRDrawData)

//_____________________________________________________________________________
AliTRDrawData::AliTRDrawData():TObject()
{
  //
  // Default constructor
  //

  fDebug         = 0;

}

//_____________________________________________________________________________
AliTRDrawData::AliTRDrawData(const AliTRDrawData &r):TObject()
{
  //
  // AliTRDrawData copy constructor
  //

  ((AliTRDrawData &) r).Copy(*this);

}

//_____________________________________________________________________________
AliTRDrawData::~AliTRDrawData()
{
  //
  // Destructor
  //

}

//_____________________________________________________________________________
AliTRDrawData &AliTRDrawData::operator=(const AliTRDrawData &r)
{
  //
  // Assignment operator
  //

  if (this != &r) ((AliTRDrawData &) r).Copy(*this);
  return *this;

}

//_____________________________________________________________________________
void AliTRDrawData::Copy(TObject &r) const
{
  //
  // Copy function
  //

  ((AliTRDrawData &) r).fDebug         = fDebug;

}

//_____________________________________________________________________________
Bool_t AliTRDrawData::Digits2Raw(TTree *digitsTree)
{
  //
  // Convert the digits to raw data byte stream. The output is written
  // into the the binary files TRD_<DDL number>.ddl.
  //
  // The pseudo raw data format is currently defined like this:
  //
  //          DDL data header
  //
  //          Subevent (= single chamber) header (8 bytes)
  //                  FLAG
  //                  Detector number (2 bytes)
  //                  Number of data bytes (2 bytes)
  //                  Number of pads with data (2 bytes)
  //                  1 empty byte
  //
  //          Data bank
  //

  const Int_t kNumberOfDDLs         = AliDAQ::NumberOfDdls("TRD");
  const Int_t kSubeventHeaderLength = 8;
  const Int_t kSubeventDummyFlag    = 0xBB;
  Int_t       headerSubevent[3];

  ofstream     **outputFile = new ofstream* [kNumberOfDDLs];
  UInt_t        *bHPosition = new UInt_t    [kNumberOfDDLs];
  Int_t         *ntotalbyte = new Int_t     [kNumberOfDDLs];
  Int_t          nbyte = 0;
  Int_t          npads = 0;
  unsigned char *bytePtr;
  unsigned char *headerPtr;

  AliTRDdigitsManager* digitsManager = new AliTRDdigitsManager();
  digitsManager->SetDebug(fDebug);

  // Read in the digit arrays
  if (!digitsManager->ReadDigits(digitsTree)) {
    delete digitsManager;
    return kFALSE;
  }

  AliTRDgeometry   *geo = new AliTRDgeometry();
  AliTRDdataArrayI *digits;

  AliTRDCommonParam* commonParam = AliTRDCommonParam::Instance();
  if (!commonParam)
  {
    printf("<AliTRDrawData::Digits2Raw> ");
    printf("Could not get common params\n");
    return 0;
  }

  AliTRDcalibDB* calibration = AliTRDcalibDB::Instance();
  if (!calibration)
  {
    printf("<AliTRDdigitizer::Digits2Raw> ");
    printf("Could not get calibration object\n");
    return kFALSE;
  }

  // the event header
  AliRawDataHeader header;

  // Open the output files
  for (Int_t iDDL = 0; iDDL < kNumberOfDDLs; iDDL++) {
    char name[20];
    strcpy(name,AliDAQ::DdlFileName("TRD",iDDL));
#ifndef __DECCXX
    outputFile[iDDL] = new ofstream(name, ios::binary);
#else
    outputFile[iDDL] = new ofstream(name);
#endif

    // Write a dummy data header
    bHPosition[iDDL] = outputFile[iDDL]->tellp();
    outputFile[iDDL]->write((char*)(&header),sizeof(header));
    ntotalbyte[iDDL] = 0;
  }

  // Loop through all detectors
  for (Int_t det = 0; det < AliTRDgeometry::Ndet(); det++) {

    Int_t cham      = geo->GetChamber(det);
    Int_t plan      = geo->GetPlane(det);
    Int_t sect      = geo->GetSector(det);
    Int_t rowMax    = commonParam->GetRowMax(plan,cham,sect);
    Int_t colMax    = commonParam->GetColMax(plan);
    Int_t timeTotal = calibration->GetNumberOfTimeBins();
    Int_t bufferMax = rowMax*colMax*timeTotal;
    Int_t *buffer   = new Int_t[bufferMax];

    npads   = 0;
    nbyte   = 0;
    bytePtr = (unsigned char *) buffer;

    Int_t iDDL = sect;

    // Get the digits array
    digits = digitsManager->GetDigits(det);
    digits->Expand();

    // Loop through the detector pixel
    for (Int_t col = 0; col < colMax; col++) {
      for (Int_t row = 0; row < rowMax; row++) {

	// Check whether data exists for this pad
        Bool_t dataflag = kFALSE;
        for (Int_t time = 0; time < timeTotal; time++) {
          Int_t data = digits->GetDataUnchecked(row,col,time);
          if (data) {
            dataflag = kTRUE;
            break;
	  }
	}

        if (dataflag) {

          npads++;

	  // The pad row number
          *bytePtr++ = row + 1;
	  // The pad column number
          *bytePtr++ = col + 1;
          nbyte += 2;

          Int_t nzero = 0;
          for (Int_t time = 0; time < timeTotal; time++) {

            Int_t data = digits->GetDataUnchecked(row,col,time);

            if (!data) {
              nzero++;
              if ((nzero ==       256) ||
                  (time  == timeTotal-1)) {
                *bytePtr++ = 0;
                *bytePtr++ = nzero-1;
                nbyte += 2;
                nzero  = 0;
      	      }
	    }
            else {
              if (nzero) {
                *bytePtr++ = 0;
                *bytePtr++ = nzero-1;
                nbyte += 2;
                nzero  = 0;
	      }
              // High byte (MSB always set)
              *bytePtr++ = ((data >> 8) | 128);
              // Low byte
              *bytePtr++ = (data & 0xff);
              nbyte += 2;
	    }

	  }

	}

      }

    }

    // Fill the end of the buffer with zeros
    while (nbyte % 4) {
      *bytePtr++ = 0;
      nbyte++;
    }

    if (fDebug > 1) {
      Info("Digits2Raw","det = %d, nbyte = %d (%d)",det,nbyte,bufferMax);
    }

    // Write the subevent header
    bytePtr    = (unsigned char *) headerSubevent;
    headerPtr  = bytePtr;
    *bytePtr++ = kSubeventDummyFlag;
    *bytePtr++ = (det   & 0xff);
    *bytePtr++ = (det   >> 8);
    *bytePtr++ = (nbyte & 0xff);
    *bytePtr++ = (nbyte >> 8);
    *bytePtr++ = (nbyte >> 16);
    *bytePtr++ = (npads & 0xff);
    *bytePtr++ = (npads >> 8);
    outputFile[iDDL]->write((char*)headerPtr,kSubeventHeaderLength);

    // Write the buffer to the file
    bytePtr = (unsigned char *) buffer;
    outputFile[iDDL]->write((char*)bytePtr,nbyte);

    ntotalbyte[iDDL] += nbyte + kSubeventHeaderLength;

    delete buffer;

  }

  if (fDebug) {
    for (Int_t iDDL = 0; iDDL < kNumberOfDDLs; iDDL++) {
      Info("Digits2Raw","Total size: DDL %d = %d",iDDL,ntotalbyte[iDDL]);
    }
  }

  // Update the data headers and close the output files
  for (Int_t iDDL = 0; iDDL < kNumberOfDDLs; iDDL++) {
    header.fSize = UInt_t(outputFile[iDDL]->tellp()) - bHPosition[iDDL];
    header.SetAttribute(0);  // valid data
    outputFile[iDDL]->seekp(bHPosition[iDDL]);
    outputFile[iDDL]->write((char*)(&header),sizeof(header));

    outputFile[iDDL]->close();
    delete outputFile[iDDL];
  }

  delete geo;
  delete digitsManager;

  delete [] outputFile;
  delete [] bHPosition;
  delete [] ntotalbyte;

  return kTRUE;

}

//_____________________________________________________________________________
AliTRDdigitsManager* AliTRDrawData::Raw2Digits(AliRawReader* rawReader)
{
  //
  // Read the raw data digits and put them into the returned digits manager
  //

  AliTRDdataArrayI *digits    = 0;
  AliTRDdataArrayI *track0    = 0;
  AliTRDdataArrayI *track1    = 0;
  AliTRDdataArrayI *track2    = 0;

  AliTRDgeometry *geo = new AliTRDgeometry();

  AliTRDCommonParam* commonParam = AliTRDCommonParam::Instance();
  if (!commonParam)
  {
    printf("<AliTRDrawData::Raw2Digits> ");
    printf("Could not get common params\n");
    return 0;
  }

  AliTRDcalibDB* calibration = AliTRDcalibDB::Instance();
  if (!calibration)
  {
    printf("<AliTRDdigitizer::Raw2Digits> ");
    printf("Could not get calibration object\n");
    return 0;
  }

  // Create the digits manager
  AliTRDdigitsManager* digitsManager = new AliTRDdigitsManager();
  digitsManager->SetDebug(fDebug);
  digitsManager->CreateArrays();

  AliTRDRawStream input(rawReader);

  // Loop through the digits
  while (input.Next()) {

    Int_t det    = input.GetDetector();
    Int_t npads  = input.GetNPads();

    if (input.IsNewDetector()) {

      if (digits) digits->Compress(1,0);
      if (track0) track0->Compress(1,0);
      if (track1) track1->Compress(1,0);
      if (track2) track2->Compress(1,0);

      if (fDebug > 2) {
	Info("Raw2Digits","Subevent header:");
	Info("Raw2Digits","\tdet   = %d",det);
	Info("Raw2Digits","\tnpads = %d",npads);
      }

      // Create the data buffer
      Int_t cham      = geo->GetChamber(det);
      Int_t plan      = geo->GetPlane(det);
      Int_t sect      = geo->GetSector(det);
      Int_t rowMax    = commonParam->GetRowMax(plan,cham,sect);
      Int_t colMax    = commonParam->GetColMax(plan);
      Int_t timeTotal = calibration->GetNumberOfTimeBins();

      // Add a container for the digits of this detector
      digits = digitsManager->GetDigits(det);
      track0 = digitsManager->GetDictionary(det,0);
      track1 = digitsManager->GetDictionary(det,1);
      track2 = digitsManager->GetDictionary(det,2);
      // Allocate memory space for the digits buffer
      if (digits->GetNtime() == 0) {
        digits->Allocate(rowMax,colMax,timeTotal);
        track0->Allocate(rowMax,colMax,timeTotal);
        track1->Allocate(rowMax,colMax,timeTotal);
        track2->Allocate(rowMax,colMax,timeTotal);
      }

    }

    digits->SetDataUnchecked(input.GetRow(),input.GetColumn(),
			     input.GetTime(),input.GetSignal());
    track0->SetDataUnchecked(input.GetRow(),input.GetColumn(),
                             input.GetTime(),               -1);
    track1->SetDataUnchecked(input.GetRow(),input.GetColumn(),
                             input.GetTime(),               -1);
    track2->SetDataUnchecked(input.GetRow(),input.GetColumn(),
                             input.GetTime(),               -1);
  }

  if (digits) digits->Compress(1,0);
  if (track0) track0->Compress(1,0);
  if (track1) track1->Compress(1,0);
  if (track2) track2->Compress(1,0);

  delete geo;

  return digitsManager;

}
<|endoftext|>


<commit_before>/* TableStyle: Stores (and writes) table-based information that is
 * needed at the head of an OO document.
 *
 * Copyright (C) 2002-2004 William Lachance (william.lachance@sympatico.ca)
 * Copyright (C) 2004 Net Integration Technologies, Inc. (http://www.net-itech.com)
 * Copyright (C) 2004 Fridrich Strba (fridrich.strba@bluewin.ch)
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
 *
 * For further information visit http://libwpd.sourceforge.net
 *
 */

/* "This product is not manufactured, approved, or supported by
 * Corel Corporation or Corel Corporation Limited."
 */
#include <math.h>
#include "FilterInternal.hxx"
#include "TableStyle.hxx"
#include "DocumentElement.hxx"

#ifdef _MSC_VER
#include <minmax.h>
#endif

TableCellStyle::TableCellStyle(const WPXPropertyList &xPropList, const char *psName) :
    Style(psName),
        mPropList(xPropList)
{
}

void TableCellStyle::write(DocumentHandler &xHandler) const
{
    TagOpenElement styleOpen("style:style");
    styleOpen.addAttribute("style:name", getName());
    styleOpen.addAttribute("style:family", "table-cell");
    styleOpen.write(xHandler);

        // WLACH_REFACTORING: Only temporary.. a much better solution is to
        // generalize this sort of thing into the "Style" superclass
        WPXPropertyList stylePropList;
        WPXPropertyList::Iter i(mPropList);
        for (i.rewind(); i.next();)
        {
                if (strlen(i.key()) > 2 && strncmp(i.key(), "fo", 2) == 0)
                        stylePropList.insert(i.key(), i()->clone());
        }
        stylePropList.insert("fo:padding", "0.0382inch");
        xHandler.startElement("style:properties", stylePropList);
    xHandler.endElement("style:properties");

    xHandler.endElement("style:style");
}

TableRowStyle::TableRowStyle(const WPXPropertyList &propList, const char *psName) :
    Style(psName),
        mPropList(propList)
{
}

void TableRowStyle::write(DocumentHandler &xHandler) const
{
    TagOpenElement styleOpen("style:style");
    styleOpen.addAttribute("style:name", getName());
    styleOpen.addAttribute("style:family", "table-row");
    styleOpen.write(xHandler);

        TagOpenElement stylePropertiesOpen("style:properties");
        if (mPropList["style:min-row-height"])
                stylePropertiesOpen.addAttribute("style:min-row-height", mPropList["style:min-row-height"]->getStr());
        else if (mPropList["style:row-height"])
                stylePropertiesOpen.addAttribute("style:row-height", mPropList["style:row-height"]->getStr());
        stylePropertiesOpen.write(xHandler);
        xHandler.endElement("style:properties");

    xHandler.endElement("style:style");
}

TableStyle::TableStyle(const WPXPropertyList &xPropList, const WPXPropertyListVector &columns, const char *psName) :
    Style(psName),
        mPropList(xPropList),
        mColumns(columns)
{
}

TableStyle::~TableStyle()
{
    typedef std::vector<TableCellStyle *>::iterator TCSVIter;
    for (TCSVIter iterTableCellStyles = mTableCellStyles.begin() ; iterTableCellStyles != mTableCellStyles.end(); iterTableCellStyles++)
        delete(*iterTableCellStyles);

}

void TableStyle::write(DocumentHandler &xHandler) const
{
    TagOpenElement styleOpen("style:style");
    styleOpen.addAttribute("style:name", getName());
    styleOpen.addAttribute("style:family", "table");
    if (getMasterPageName())
        styleOpen.addAttribute("style:master-page-name", getMasterPageName()->cstr());
    styleOpen.write(xHandler);

    TagOpenElement stylePropertiesOpen("style:properties");
        if (mPropList["table:align"])
                stylePropertiesOpen.addAttribute("table:align", mPropList["table:align"]->getStr());
    if (mPropList["fo:margin-left"])
        stylePropertiesOpen.addAttribute("fo:margin-left", mPropList["fo:margin-left"]->getStr());
    if (mPropList["fo:margin-right"])
        stylePropertiesOpen.addAttribute("fo:margin-right", mPropList["fo:margin-right"]->getStr());
    if (mPropList["style:width"])
        stylePropertiesOpen.addAttribute("style:width", mPropList["style:width"]->getStr());
    if (mPropList["fo:break-before"])
        stylePropertiesOpen.addAttribute("fo:break-before", mPropList["fo:break-before"]->getStr());
    stylePropertiesOpen.write(xHandler);

    xHandler.endElement("style:properties");

    xHandler.endElement("style:style");

    int i=1;
        WPXPropertyListVector::Iter j(mColumns);
    for (j.rewind(); j.next();)
    {
        TagOpenElement styleOpen("style:style");
        WPXString sColumnName;
        sColumnName.sprintf("%s.Column%i", getName().cstr(), i);
        styleOpen.addAttribute("style:name", sColumnName);
        styleOpen.addAttribute("style:family", "table-column");
        styleOpen.write(xHandler);

                xHandler.startElement("style:properties", j());
        xHandler.endElement("style:properties");

        xHandler.endElement("style:style");

        i++;
    }

    typedef std::vector<TableRowStyle *>::const_iterator TRSVIter;
    for (TRSVIter iterTableRow = mTableRowStyles.begin() ; iterTableRow != mTableRowStyles.end(); iterTableRow++)
        (*iterTableRow)->write(xHandler);

    typedef std::vector<TableCellStyle *>::const_iterator TCSVIter;
    for (TCSVIter iterTableCell = mTableCellStyles.begin() ; iterTableCell != mTableCellStyles.end(); iterTableCell++)
        (*iterTableCell)->write(xHandler);
}
<commit_msg>INTEGRATION: CWS fs08 (1.3.20); FILE MERGED 2006/12/19 10:09:06 fridrich_strba 1.3.20.1: removing memory leaks and warnings with GNU/Linux gcc 3.4.5<commit_after>/* TableStyle: Stores (and writes) table-based information that is
 * needed at the head of an OO document.
 *
 * Copyright (C) 2002-2004 William Lachance (william.lachance@sympatico.ca)
 * Copyright (C) 2004 Net Integration Technologies, Inc. (http://www.net-itech.com)
 * Copyright (C) 2004 Fridrich Strba (fridrich.strba@bluewin.ch)
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
 *
 * For further information visit http://libwpd.sourceforge.net
 *
 */

/* "This product is not manufactured, approved, or supported by
 * Corel Corporation or Corel Corporation Limited."
 */
#include <math.h>
#include "FilterInternal.hxx"
#include "TableStyle.hxx"
#include "DocumentElement.hxx"

#ifdef _MSC_VER
#include <minmax.h>
#endif

TableCellStyle::TableCellStyle(const WPXPropertyList &xPropList, const char *psName) :
    Style(psName),
        mPropList(xPropList)
{
}

void TableCellStyle::write(DocumentHandler *pHandler) const
{
    TagOpenElement styleOpen("style:style");
    styleOpen.addAttribute("style:name", getName());
    styleOpen.addAttribute("style:family", "table-cell");
    styleOpen.write(pHandler);

        // WLACH_REFACTORING: Only temporary.. a much better solution is to
        // generalize this sort of thing into the "Style" superclass
        WPXPropertyList stylePropList;
        WPXPropertyList::Iter i(mPropList);
        for (i.rewind(); i.next();)
        {
                if (strlen(i.key()) > 2 && strncmp(i.key(), "fo", 2) == 0)
                        stylePropList.insert(i.key(), i()->clone());
        }
        stylePropList.insert("fo:padding", "0.0382inch");
        pHandler->startElement("style:properties", stylePropList);
    pHandler->endElement("style:properties");

    pHandler->endElement("style:style");
}

TableRowStyle::TableRowStyle(const WPXPropertyList &propList, const char *psName) :
    Style(psName),
        mPropList(propList)
{
}

void TableRowStyle::write(DocumentHandler *pHandler) const
{
    TagOpenElement styleOpen("style:style");
    styleOpen.addAttribute("style:name", getName());
    styleOpen.addAttribute("style:family", "table-row");
    styleOpen.write(pHandler);

        TagOpenElement stylePropertiesOpen("style:properties");
        if (mPropList["style:min-row-height"])
                stylePropertiesOpen.addAttribute("style:min-row-height", mPropList["style:min-row-height"]->getStr());
        else if (mPropList["style:row-height"])
                stylePropertiesOpen.addAttribute("style:row-height", mPropList["style:row-height"]->getStr());
        stylePropertiesOpen.write(pHandler);
        pHandler->endElement("style:properties");

    pHandler->endElement("style:style");
}

TableStyle::TableStyle(const WPXPropertyList &xPropList, const WPXPropertyListVector &columns, const char *psName) :
    Style(psName),
        mPropList(xPropList),
        mColumns(columns)
{
}

TableStyle::~TableStyle()
{
    typedef std::vector<TableCellStyle *>::iterator TCSVIter;
    typedef std::vector<TableRowStyle *>::iterator TRSVIter;
    for (TCSVIter iterTableCellStyles = mTableCellStyles.begin() ; iterTableCellStyles != mTableCellStyles.end(); iterTableCellStyles++)
        delete(*iterTableCellStyles);
    for (TRSVIter iterTableRowStyles = mTableRowStyles.begin() ; iterTableRowStyles != mTableRowStyles.end(); iterTableRowStyles++)
        delete(*iterTableRowStyles);

}

void TableStyle::write(DocumentHandler *pHandler) const
{
    TagOpenElement styleOpen("style:style");
    styleOpen.addAttribute("style:name", getName());
    styleOpen.addAttribute("style:family", "table");
    if (getMasterPageName())
        styleOpen.addAttribute("style:master-page-name", getMasterPageName()->cstr());
    styleOpen.write(pHandler);

    TagOpenElement stylePropertiesOpen("style:properties");
        if (mPropList["table:align"])
                stylePropertiesOpen.addAttribute("table:align", mPropList["table:align"]->getStr());
    if (mPropList["fo:margin-left"])
        stylePropertiesOpen.addAttribute("fo:margin-left", mPropList["fo:margin-left"]->getStr());
    if (mPropList["fo:margin-right"])
        stylePropertiesOpen.addAttribute("fo:margin-right", mPropList["fo:margin-right"]->getStr());
    if (mPropList["style:width"])
        stylePropertiesOpen.addAttribute("style:width", mPropList["style:width"]->getStr());
    if (mPropList["fo:break-before"])
        stylePropertiesOpen.addAttribute("fo:break-before", mPropList["fo:break-before"]->getStr());
    stylePropertiesOpen.write(pHandler);

    pHandler->endElement("style:properties");

    pHandler->endElement("style:style");

    int i=1;
        WPXPropertyListVector::Iter j(mColumns);
    for (j.rewind(); j.next();)
    {
        TagOpenElement styleNestedOpen("style:style");
        WPXString sColumnName;
        sColumnName.sprintf("%s.Column%i", getName().cstr(), i);
        styleNestedOpen.addAttribute("style:name", sColumnName);
        styleNestedOpen.addAttribute("style:family", "table-column");
        styleNestedOpen.write(pHandler);

                pHandler->startElement("style:properties", j());
        pHandler->endElement("style:properties");

        pHandler->endElement("style:style");

        i++;
    }

    typedef std::vector<TableRowStyle *>::const_iterator TRSVIter;
    for (TRSVIter iterTableRow = mTableRowStyles.begin() ; iterTableRow != mTableRowStyles.end(); iterTableRow++)
        (*iterTableRow)->write(pHandler);

    typedef std::vector<TableCellStyle *>::const_iterator TCSVIter;
    for (TCSVIter iterTableCell = mTableCellStyles.begin() ; iterTableCell != mTableCellStyles.end(); iterTableCell++)
        (*iterTableCell)->write(pHandler);
}
<|endoftext|>


<commit_before>#include <QFileInfo>
#include <QDir>
#include "identity.h"
#include "kernel.h"
#include "mastercatalog.h"
#include "abstractfactory.h"
#include "connectorinterface.h"
#include "ilwisobjectconnector.h"
#include "catalogexplorer.h"
#include "connectorfactory.h"
#include "ilwiscontext.h"
#include "catalogexplorer.h"
#include "catalogconnector.h"
#include "foldercatalogexplorer.h"

using namespace Ilwis;

CatalogExplorer *FolderCatalogExplorer::create(const Resource &resource, bool load, const IOOptions &options) {
    if ( resource.ilwisType() == itCATALOG ){
        QDir localDir = resource.url().toLocalFile();
        if ( localDir.path() != "." && localDir.exists()){
            return new FolderCatalogExplorer(resource, load, options);
        }
    }
    return nullptr;

}

FolderCatalogExplorer::FolderCatalogExplorer(const Resource &resource, bool , const IOOptions &options) : CatalogExplorer(resource,options){
}

std::vector<QUrl> FolderCatalogExplorer::sources(const QStringList &filters, int options ) const
{
    return FolderCatalogExplorer::loadFolders(source(), filters, options);
}

std::vector<QUrl> FolderCatalogExplorer::loadFolders(const Resource& source, const QStringList& namefilter, int options)
{
    QStringList fileList;

     QUrl location = source.url();
     if ( location.toString() == "file://") { // root will only contain drives (folders)
         QFileInfoList drives = QDir::drives();
         QStringList dirs;
         foreach(const auto& drive , drives) {
             QDir dir(drive.canonicalFilePath());
              dirs.append(dir.entryList(QDir::Dirs | QDir::NoDotAndDotDot));
         }
         fileList.append(dirs);
     } else {
         QString p = location.toLocalFile();
         QDir folder(p);
         p = folder.absolutePath();
         folder.setFilter(QDir::Dirs | QDir::NoDotAndDotDot);
         if (!folder.exists()) {
             return  std::vector<QUrl>();
         }
         QString slash = location.toString().endsWith("/") ? "" : "/";
//         fileList = folder.entryList();

//         for(QString& file : fileList) {
//             file = source.url().toString() + slash + file;
//         }
         folder.setFilter(QDir::Files);
         QStringList files = folder.entryList(namefilter);
         for(QString file : files) {
             QString fullfile = source.url().toString() + slash +  file;
             fileList.push_back(fullfile);
         }

     }
     std::vector<QUrl> files(fileList.size());
     auto iter = files.begin();
     for(const QString& filename : fileList) {
         (*iter) = filename;
         ++iter;
     }
     return files;
}

QFileInfo FolderCatalogExplorer::toLocalFile(const QUrl& datasource) const
{
    return QFileInfo(datasource.toLocalFile());
}

QString FolderCatalogExplorer::provider() const
{
    return "ilwis";
}

std::vector<Resource> FolderCatalogExplorer::loadItems(const IOOptions&)
{
    return std::vector<Resource>();
}

bool FolderCatalogExplorer::canUse(const Resource &resource) const
{
    if ( resource.ilwisType() == itCATALOG ){
        QDir localDir = resource.url().toLocalFile();
        if ( localDir.exists()){
            return true;
        }
    }
    return false;
}

<commit_msg>folders are allowed in the explorer as valid objects<commit_after>#include <QFileInfo>
#include <QDir>
#include "identity.h"
#include "kernel.h"
#include "mastercatalog.h"
#include "abstractfactory.h"
#include "connectorinterface.h"
#include "ilwisobjectconnector.h"
#include "catalogexplorer.h"
#include "connectorfactory.h"
#include "ilwiscontext.h"
#include "catalogexplorer.h"
#include "catalogconnector.h"
#include "foldercatalogexplorer.h"

using namespace Ilwis;

CatalogExplorer *FolderCatalogExplorer::create(const Resource &resource, bool load, const IOOptions &options) {
    if ( resource.ilwisType() == itCATALOG ){
        QDir localDir = resource.url().toLocalFile();
        if ( localDir.path() != "." && localDir.exists()){
            return new FolderCatalogExplorer(resource, load, options);
        }
    }
    return nullptr;

}

FolderCatalogExplorer::FolderCatalogExplorer(const Resource &resource, bool , const IOOptions &options) : CatalogExplorer(resource,options){
}

std::vector<QUrl> FolderCatalogExplorer::sources(const QStringList &filters, int options ) const
{
    return FolderCatalogExplorer::loadFolders(source(), filters, options);
}

std::vector<QUrl> FolderCatalogExplorer::loadFolders(const Resource& source, const QStringList& namefilter, int options)
{
    QStringList fileList;

     QUrl location = source.url();
     if ( location.toString() == "file://") { // root will only contain drives (folders)
         QFileInfoList drives = QDir::drives();
         QStringList dirs;
         foreach(const auto& drive , drives) {
             QDir dir(drive.canonicalFilePath());
              dirs.append(dir.entryList(QDir::Dirs | QDir::NoDotAndDotDot));
         }
         fileList.append(dirs);
     } else {
         QString p = location.toLocalFile();
         QDir folder(p);
         p = folder.absolutePath();
         folder.setFilter(QDir::Dirs | QDir::NoDotAndDotDot);
         QStringList dirlist = folder.entryList();
         if (!folder.exists()) {
             return  std::vector<QUrl>();
         }
         QString slash = location.toString().endsWith("/") ? "" : "/";
//         fileList = folder.entryList();

//         for(QString& file : fileList) {
//             file = source.url().toString() + slash + file;
//         }
         folder.setFilter(QDir::Files | QDir::Dirs);

         QStringList files = folder.entryList(namefilter);
         files.append(dirlist);
         for(QString file : files) {
             QString fullfile = source.url().toString() + slash +  file;
             fileList.push_back(fullfile);
         }

     }
     std::vector<QUrl> files(fileList.size());
     auto iter = files.begin();
     for(const QString& filename : fileList) {
         (*iter) = filename;
         ++iter;
     }
     return files;
}

QFileInfo FolderCatalogExplorer::toLocalFile(const QUrl& datasource) const
{
    return QFileInfo(datasource.toLocalFile());
}

QString FolderCatalogExplorer::provider() const
{
    return "ilwis";
}

std::vector<Resource> FolderCatalogExplorer::loadItems(const IOOptions&)
{
    return std::vector<Resource>();
}

bool FolderCatalogExplorer::canUse(const Resource &resource) const
{
    if ( resource.ilwisType() == itCATALOG ){
        QDir localDir = resource.url().toLocalFile();
        if ( localDir.exists()){
            return true;
        }
    }
    return false;
}

<|endoftext|>


<commit_before>#include <cassert>
#include <cstdint>
#include <unordered_set>

// with these settings it works up to size 16
typedef uint32_t pos_t;         // increase the size of this for larger boards
constexpr pos_t CELL_WIDTH = 2; // number of bits per cell

constexpr pos_t CELL_MAX = (1 << CELL_WIDTH) - 1;          // max value of a cell
constexpr pos_t MAX_SIZE = sizeof(pos_t) * 8 / CELL_WIDTH; // max board size

struct Cell {
    pos_t value;
    Cell(pos_t value) : value(value) {}

    Cell flip() const {
        if (value == 1)
            return Cell(2);
        if (value == 2)
            return Cell(1);
        assert(false);
    }
    bool is_stone() const { return value == 1 || value == 2; }
    bool operator==(Cell o) const { return value == o.value; }
    operator bool() const { return value; }
    friend std::ostream &operator<<(std::ostream &os, const Cell cell) {
        os << ".BW"[cell.value];
        return os;
    }
};
const Cell EMPTY = Cell(0);
const Cell BLACK = Cell(1);
const Cell WHITE = Cell(2);

struct Move {
    Cell color;
    pos_t position; // meaningless if is_pass is true
    bool is_pass;
    Move(Cell color, pos_t position, bool is_pass = false)
        : color(color), position(position), is_pass(is_pass) {}
    static Move pass(Cell color) { return Move(color, 0, true); }
};

struct Score {
    pos_t black, white;
    Score() : black(0), white(0) {}
    Score(pos_t black, pos_t white) : black(black), white(white) {}

    bool operator==(Score o) const { return o.black == black && o.white == white; }
};

// a group represents a sequence of stones with the same cell value
struct Group {
    Cell cell;
    pos_t position, size;
    Group(Cell cell, pos_t position, pos_t size)
        : cell(cell), position(position), size(size) {}
};

struct Board {
    const pos_t size;
    pos_t board;
    Board(pos_t size) : size(size), board(0) {}

    inline Cell get(pos_t pos) const {
        assert(pos < size);
        return Cell(board >> pos * CELL_WIDTH & CELL_MAX);
    }
    inline void set(pos_t pos, Cell cell) {
        assert(pos < size);
        assert(cell.value <= CELL_MAX);
        board ^= (board & CELL_MAX << pos * CELL_WIDTH) ^ cell.value << pos * CELL_WIDTH;
    }
    Score score() const {
        Score sc;
        Board left_smear(size), right_smear(size);
        Cell last_left = EMPTY, last_right = EMPTY;
        for (pos_t i = 0; i < size; i++) {
            if (Cell next = get(i))
                last_right = next;
            right_smear.set(i, last_right);
            if (Cell next = get(size - i - 1))
                last_left = next;
            left_smear.set(size - i - 1, last_left);
        }
        for (pos_t i = 0; i < size; i++) {
            Cell left = left_smear.get(i), right = right_smear.get(i);
            if ((left == BLACK && (left == right || right == EMPTY)) ||
                (right == BLACK && left == EMPTY))
                sc.black++;
            if ((left == WHITE && (left == right || right == EMPTY)) ||
                (right == WHITE && left == EMPTY))
                sc.white++;
        }
        return sc;
    }
    // returns a bitset of empty positions on the board.
    pos_t empty_set() const {
        pos_t res = 0;
        for (pos_t i = size; i--;)
            res <<= 1, res |= get(i) == EMPTY;
        return res;
    }
    // retuns a vector of all groups on the board, ordered.
    std::vector<Group> groups() const {
        std::vector<Group> groups{Group(get(0), 0, 1)};
        for (pos_t i = 1; i < size; i++) {
            if (get(i) == groups.back().cell)
                groups.back().size++;
            else
                groups.push_back(Group(get(i), i, 1));
        }
        return groups;
    }
    // remove all stones in a group
    void clear_group(Group group) {
        for (pos_t i = 0; i < group.size; i++)
            set(i + group.position, EMPTY);
    }
    // clear any groups captured by a recent play at the given position
    void clear_captured(pos_t position) {
        // this can probably be optimized
        assert(get(position).is_stone());
        auto g = groups();
        for (size_t i = 0; i < g.size(); i++) {
            if (g[i].cell.is_stone() &&
                (position == g[i].position - 1 || position == g[i].position + g[i].size)) {
                // left boundary
                if (i == 0 && i + 1 < g.size() && g[i + 1].cell.is_stone())
                    clear_group(g[i]);
                // right boundary
                else if (i > 0 && i + 1 == g.size() && g[i - 1].cell.is_stone())
                    clear_group(g[i]);
                // middle
                else if (i > 0 && i + 1 < g.size() && g[i - 1].cell.is_stone() &&
                         g[i + 1].cell.is_stone() && g[i - 1].cell == g[i + 1].cell)
                    clear_group(g[i]);
            }
        }
    }
    bool operator==(Board o) const { return o.board == board; }
    friend std::ostream &operator<<(std::ostream &os, Board board) {
        for (pos_t i = 0; i < board.size; i++)
            os << board.get(i);
        return os;
    }
};

struct BoardHasher {
    size_t operator()(Board b) const { return b.board; }
};

struct History {
    std::unordered_set<Board, BoardHasher> states;

    void add(Board s) { states.insert(s); }
    // returns true if the given board has previously been added
    bool check(Board s) const { return states.find(s) != states.end(); }
};

struct State {
    Board board;
    History history;
    enum GameState { NORMAL, PASS, GAME_OVER } game_state = NORMAL;
    State(pos_t size) : board(size) {}

    bool terminal() const { return game_state == GAME_OVER; }
    void play(Move move) {
        assert(game_state != GAME_OVER);
        if (move.is_pass) {
            if (game_state == NORMAL)
                game_state = PASS;
            else if (game_state == PASS)
                game_state = GAME_OVER;
        } else {
            assert(legal_moves(move.color) & 1 << move.position);
            assert(board.get(move.position) == EMPTY);
            board.set(move.position, move.color);
            board.clear_captured(move.position);
            assert(!history.check(board));
            history.add(board);
            game_state = NORMAL;
        }
    }
    // retuns a bitset of all legal moves for a given color
    pos_t legal_moves(Cell color) const {
        assert(color.is_stone());
        pos_t legal = board.empty_set();
        auto illegal = [&](pos_t i) { legal &= ~(1 << i); };

        // check history
        for (pos_t i = 0; i < board.size; i++) {
            Board b = board;
            b.set(i, color);
            b.clear_captured(i);
            if (history.check(b))
                illegal(i);
        }

        // check liberties
        auto groups = board.groups();
        for (size_t i = 0; i < groups.size(); i++) {
            const Group g = groups[i];
            if (g.cell == EMPTY && g.size == 1) {
                // left suicide
                if (i == 0 && i < groups.size() - 2 && groups[i + 1].cell == color.flip())
                    illegal(g.position);
                // right suicide
                else if (i == groups.size() - 1 && i > 1 && groups[i - 1].cell == color.flip())
                    illegal(g.position);
                // middle suicide
                else if (i > 0 && i < groups.size() - 1 && groups[i - 1].cell == color.flip() &&
                         groups[i + 1].cell == color.flip())
                    illegal(g.position);
            }
        }
        return legal;
    }

    // append legal moves of a specific type and color to a vector.
    // TODO
    void atari_moves(Cell color, std::vector<Move> &moves) const {}
    void cell_2_conjecture(Cell color, std::vector<Move> &moves) const {}
    void safe_moves(Cell color, std::vector<Move> &moves) const {}
    void other_moves(Cell color, std::vector<Move> &moves) const {}
    void moves(Cell color, std::vector<Move> &moves) const {
        moves.push_back(Move::pass(color));
        atari_moves(color, moves);
        cell_2_conjecture(color, moves);
        safe_moves(color, moves);
        other_moves(color, moves);
    }
};
<commit_msg>Rename group -> chain to be consistent with the literature<commit_after>#include <cassert>
#include <cstdint>
#include <unordered_set>

// with these settings it works up to size 16
typedef uint32_t pos_t;         // increase the size of this for larger boards
constexpr pos_t CELL_WIDTH = 2; // number of bits per cell

constexpr pos_t CELL_MAX = (1 << CELL_WIDTH) - 1;          // max value of a cell
constexpr pos_t MAX_SIZE = sizeof(pos_t) * 8 / CELL_WIDTH; // max board size

struct Cell {
    pos_t value;
    Cell(pos_t value) : value(value) {}

    Cell flip() const {
        if (value == 1)
            return Cell(2);
        if (value == 2)
            return Cell(1);
        assert(false);
    }
    bool is_stone() const { return value == 1 || value == 2; }
    bool operator==(Cell o) const { return value == o.value; }
    operator bool() const { return value; }
    friend std::ostream &operator<<(std::ostream &os, const Cell cell) {
        os << ".BW"[cell.value];
        return os;
    }
};
const Cell EMPTY = Cell(0);
const Cell BLACK = Cell(1);
const Cell WHITE = Cell(2);

struct Move {
    Cell color;
    pos_t position; // meaningless if is_pass is true
    bool is_pass;
    Move(Cell color, pos_t position, bool is_pass = false)
        : color(color), position(position), is_pass(is_pass) {}
    static Move pass(Cell color) { return Move(color, 0, true); }
};

struct Score {
    pos_t black, white;
    Score() : black(0), white(0) {}
    Score(pos_t black, pos_t white) : black(black), white(white) {}

    bool operator==(Score o) const { return o.black == black && o.white == white; }
};

// a chain represents a sequence of stones with the same cell value
struct Chain {
    Cell cell;
    pos_t position, size;
    Chain(Cell cell, pos_t position, pos_t size) : cell(cell), position(position), size(size) {}
};

struct Board {
    const pos_t size;
    pos_t board;
    Board(pos_t size) : size(size), board(0) {}

    inline Cell get(pos_t pos) const {
        assert(pos < size);
        return Cell(board >> pos * CELL_WIDTH & CELL_MAX);
    }
    inline void set(pos_t pos, Cell cell) {
        assert(pos < size);
        assert(cell.value <= CELL_MAX);
        board ^= (board & CELL_MAX << pos * CELL_WIDTH) ^ cell.value << pos * CELL_WIDTH;
    }
    Score score() const {
        Score sc;
        Board left_smear(size), right_smear(size);
        Cell last_left = EMPTY, last_right = EMPTY;
        for (pos_t i = 0; i < size; i++) {
            if (Cell next = get(i))
                last_right = next;
            right_smear.set(i, last_right);
            if (Cell next = get(size - i - 1))
                last_left = next;
            left_smear.set(size - i - 1, last_left);
        }
        for (pos_t i = 0; i < size; i++) {
            Cell left = left_smear.get(i), right = right_smear.get(i);
            if ((left == BLACK && (left == right || right == EMPTY)) ||
                (right == BLACK && left == EMPTY))
                sc.black++;
            if ((left == WHITE && (left == right || right == EMPTY)) ||
                (right == WHITE && left == EMPTY))
                sc.white++;
        }
        return sc;
    }
    // returns a bitset of empty positions on the board.
    pos_t empty_set() const {
        pos_t res = 0;
        for (pos_t i = size; i--;)
            res <<= 1, res |= get(i) == EMPTY;
        return res;
    }
    // retuns a vector of all chains on the board, ordered.
    std::vector<Chain> chains() const {
        std::vector<Chain> chains{Chain(get(0), 0, 1)};
        for (pos_t i = 1; i < size; i++) {
            if (get(i) == chains.back().cell)
                chains.back().size++;
            else
                chains.push_back(Chain(get(i), i, 1));
        }
        return chains;
    }
    // remove all stones in a chain
    void clear_chain(Chain chain) {
        for (pos_t i = 0; i < chain.size; i++)
            set(i + chain.position, EMPTY);
    }
    // clear any chains captured by a recent play at the given position
    void clear_captured(pos_t position) {
        // this can probably be optimized
        assert(get(position).is_stone());
        auto ch = chains();
        for (size_t i = 0; i < ch.size(); i++) {
            if (ch[i].cell.is_stone() &&
                (position == ch[i].position - 1 || position == ch[i].position + ch[i].size)) {
                // left boundary
                if (i == 0 && i + 1 < ch.size() && ch[i + 1].cell.is_stone())
                    clear_chain(ch[i]);
                // right boundary
                else if (i > 0 && i + 1 == ch.size() && ch[i - 1].cell.is_stone())
                    clear_chain(ch[i]);
                // middle
                else if (i > 0 && i + 1 < ch.size() && ch[i - 1].cell.is_stone() &&
                         ch[i + 1].cell.is_stone() && ch[i - 1].cell == ch[i + 1].cell)
                    clear_chain(ch[i]);
            }
        }
    }
    bool operator==(Board o) const { return o.board == board; }
    friend std::ostream &operator<<(std::ostream &os, Board board) {
        for (pos_t i = 0; i < board.size; i++)
            os << board.get(i);
        return os;
    }
};

struct BoardHasher {
    size_t operator()(Board b) const { return b.board; }
};

struct History {
    std::unordered_set<Board, BoardHasher> states;

    void add(Board s) { states.insert(s); }
    // returns true if the given board has previously been added
    bool check(Board s) const { return states.find(s) != states.end(); }
};

struct State {
    Board board;
    History history;
    enum GameState { NORMAL, PASS, GAME_OVER } game_state = NORMAL;
    State(pos_t size) : board(size) {}

    bool terminal() const { return game_state == GAME_OVER; }
    void play(Move move) {
        assert(game_state != GAME_OVER);
        if (move.is_pass) {
            if (game_state == NORMAL)
                game_state = PASS;
            else if (game_state == PASS)
                game_state = GAME_OVER;
        } else {
            assert(legal_moves(move.color) & 1 << move.position);
            assert(board.get(move.position) == EMPTY);
            board.set(move.position, move.color);
            board.clear_captured(move.position);
            assert(!history.check(board));
            history.add(board);
            game_state = NORMAL;
        }
    }
    // retuns a bitset of all legal moves for a given color
    pos_t legal_moves(Cell color) const {
        assert(color.is_stone());
        pos_t legal = board.empty_set();
        auto illegal = [&](pos_t i) { legal &= ~(1 << i); };

        // check history
        for (pos_t i = 0; i < board.size; i++) {
            Board b = board;
            b.set(i, color);
            b.clear_captured(i);
            if (history.check(b))
                illegal(i);
        }

        // check liberties
        auto ch = board.chains();
        for (size_t i = 0; i < ch.size(); i++) {
            if (ch[i].cell == EMPTY && ch[i].size == 1) {
                // left suicide
                if (i == 0 && i < ch.size() - 2 && ch[i + 1].cell == color.flip())
                    illegal(ch[i].position);
                // right suicide
                else if (i == ch.size() - 1 && i > 1 && ch[i - 1].cell == color.flip())
                    illegal(ch[i].position);
                // middle suicide
                else if (i > 0 && i < ch.size() - 1 && ch[i - 1].cell == color.flip() &&
                         ch[i + 1].cell == color.flip())
                    illegal(ch[i].position);
            }
        }
        return legal;
    }

    // append legal moves of a specific type and color to a vector.
    // TODO
    void atari_moves(Cell color, std::vector<Move> &moves) const {}
    void cell_2_conjecture(Cell color, std::vector<Move> &moves) const {}
    void safe_moves(Cell color, std::vector<Move> &moves) const {}
    void other_moves(Cell color, std::vector<Move> &moves) const {}
    void moves(Cell color, std::vector<Move> &moves) const {
        moves.push_back(Move::pass(color));
        atari_moves(color, moves);
        cell_2_conjecture(color, moves);
        safe_moves(color, moves);
        other_moves(color, moves);
    }
};
<|endoftext|>


<commit_before>/*

Copyright (c) 2013, Project OSRM, Dennis Luxen, others
All rights reserved.

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

Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

*/

#include <cstdio>

#include "../DataStructures/SharedMemoryFactory.h"
#include "../Server/DataStructures/SharedDataType.h"
#include "../Util/GitDescription.h"
#include "../Util/simple_logger.hpp"

void delete_region(const SharedDataType region)
{
    if (SharedMemory::RegionExists(region) && !SharedMemory::Remove(region))
    {
        const std::string name = [&]
        {
            switch (region)
            {
            case CURRENT_REGIONS:
                return "CURRENT_REGIONS";
            case LAYOUT_1:
                return "LAYOUT_1";
            case DATA_1:
                return "DATA_1";
            case LAYOUT_2:
                return "LAYOUT_2";
            case DATA_2:
                return "DATA_2";
            case LAYOUT_NONE:
                return "LAYOUT_NONE";
            default: // DATA_NONE:
                return "DATA_NONE";
            }
        }();

        SimpleLogger().Write(logWARNING) << "could not delete shared memory region " << name;
    }
}

// find all existing shmem regions and remove them.
void springclean()
{
    SimpleLogger().Write() << "spring-cleaning all shared memory regions";
    delete_region(DATA_1);
    delete_region(LAYOUT_1);
    delete_region(DATA_2);
    delete_region(LAYOUT_2);
    delete_region(CURRENT_REGIONS);
}

int main()
{
    LogPolicy::GetInstance().Unmute();
    try
    {
        SimpleLogger().Write() << "starting up engines, " << g_GIT_DESCRIPTION << ", "
                               << "compiled at " << __DATE__ << ", " __TIME__ << "\n\n";
        SimpleLogger().Write() << "Releasing all locks";
        SimpleLogger().Write() << "ATTENTION! BE CAREFUL!";
        SimpleLogger().Write() << "----------------------";
        SimpleLogger().Write() << "This tool may put osrm-routed into an undefined state!";
        SimpleLogger().Write() << "By typing 'Y' you acknowledge that you know what your are doing.";
        SimpleLogger().Write() << "\n\nDo you want to purge all shared memory allocated by osrm-datastore? [type 'Y' to confirm]";

        const auto c = getchar();
        if (c != 'Y')
        {
            SimpleLogger().Write() << "aborted.";
            return 0;
        }
        springclean();
    }
    catch (const std::exception &e)
    {
        SimpleLogger().Write(logWARNING) << "[excpetion] " << e.what();
    }
    return 0;
}
<commit_msg>rename variable, break long lines<commit_after>/*

Copyright (c) 2013, Project OSRM, Dennis Luxen, others
All rights reserved.

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

Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

*/

#include <cstdio>

#include "../DataStructures/SharedMemoryFactory.h"
#include "../Server/DataStructures/SharedDataType.h"
#include "../Util/GitDescription.h"
#include "../Util/simple_logger.hpp"

void delete_region(const SharedDataType region)
{
    if (SharedMemory::RegionExists(region) && !SharedMemory::Remove(region))
    {
        const std::string name = [&]
        {
            switch (region)
            {
            case CURRENT_REGIONS:
                return "CURRENT_REGIONS";
            case LAYOUT_1:
                return "LAYOUT_1";
            case DATA_1:
                return "DATA_1";
            case LAYOUT_2:
                return "LAYOUT_2";
            case DATA_2:
                return "DATA_2";
            case LAYOUT_NONE:
                return "LAYOUT_NONE";
            default: // DATA_NONE:
                return "DATA_NONE";
            }
        }();

        SimpleLogger().Write(logWARNING) << "could not delete shared memory region " << name;
    }
}

// find all existing shmem regions and remove them.
void springclean()
{
    SimpleLogger().Write() << "spring-cleaning all shared memory regions";
    delete_region(DATA_1);
    delete_region(LAYOUT_1);
    delete_region(DATA_2);
    delete_region(LAYOUT_2);
    delete_region(CURRENT_REGIONS);
}

int main()
{
    LogPolicy::GetInstance().Unmute();
    try
    {
        SimpleLogger().Write() << "starting up engines, " << g_GIT_DESCRIPTION << ", "
                               << "compiled at " << __DATE__ << ", " __TIME__ << "\n\n";
        SimpleLogger().Write() << "Releasing all locks";
        SimpleLogger().Write() << "ATTENTION! BE CAREFUL!";
        SimpleLogger().Write() << "----------------------";
        SimpleLogger().Write() << "This tool may put osrm-routed into an undefined state!";
        SimpleLogger().Write() << "Type 'Y' to acknowledge that you know what your are doing.";
        SimpleLogger().Write() << "\n\nDo you want to purge all shared memory allocated " <<
                                  "by osrm-datastore? [type 'Y' to confirm]";

        const auto letter = getchar();
        if (letter != 'Y')
        {
            SimpleLogger().Write() << "aborted.";
            return 0;
        }
        springclean();
    }
    catch (const std::exception &e)
    {
        SimpleLogger().Write(logWARNING) << "[excpetion] " << e.what();
    }
    return 0;
}
<|endoftext|>


<commit_before>/*=========================================================================

 Program:   ORFEO Toolbox
 Language:  C++
 Date:      $Date$
 Version:   $Revision$

 Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
 See OTBCopyright.txt for details.

 This software is distributed WITHOUT ANY WARRANTY; without even
 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
 PURPOSE.  See the above copyright notices for more information.

 =========================================================================*/
#include "otbWrapperApplication.h"
#include "otbWrapperApplicationFactory.h"

#include "otbStreamingWarpImageFilter.h"
#include "itkLinearInterpolateImageFunction.h"
#include "otbBCOInterpolateImageFunction.h"
#include "itkNearestNeighborInterpolateImageFunction.h"
#include "otbBandMathImageFilter.h"
#include "otbConcatenateVectorImageFilter.h"
#include "otbMultiToMonoChannelExtractROI.h"
#include "otbImageToVectorImageCastFilter.h"
#include "itkVectorCastImageFilter.h"

namespace otb
{
enum
{
  Interpolator_Linear,
  Interpolator_NNeighbor,
  Interpolator_BCO
};

namespace Wrapper
{

class GridBasedImageResampling : public Application
{
public:
  /** Standard class typedefs. */
  typedef GridBasedImageResampling      Self;
  typedef Application                   Superclass;
  typedef itk::SmartPointer<Self>       Pointer;
  typedef itk::SmartPointer<const Self> ConstPointer;

  typedef itk::Vector<double,2>         DeformationType;
  typedef otb::Image<DeformationType>   DeformationFieldType;

  typedef itk::VectorCastImageFilter
  <FloatVectorImageType,
   DeformationFieldType>                DeformationFieldCastFilterType;

  typedef otb::StreamingWarpImageFilter
  <FloatVectorImageType,
   FloatVectorImageType,
   DeformationFieldType>                WarpFilterType;
  typedef otb::MultiToMonoChannelExtractROI
  <FloatVectorImageType::InternalPixelType,
   FloatVectorImageType::InternalPixelType>
                                        ExtractFilterType;

  typedef otb::BandMathImageFilter
  <ExtractFilterType::OutputImageType>  BandMathFilterType;

  typedef otb::ImageToVectorImageCastFilter
  <ExtractFilterType::OutputImageType,
   FloatVectorImageType>                VectorCastFilterType;

  typedef otb::ConcatenateVectorImageFilter
  <FloatVectorImageType,
   FloatVectorImageType,
   FloatVectorImageType>                ConcatenateFilterType;

  /** Standard macro */
  itkNewMacro(Self);

  itkTypeMacro(GridBasedImageResampling, otb::Application);

private:

  GridBasedImageResampling()
  {
    // Instanciate warp filter
    m_WarpImageFilter = WarpFilterType::New();
    m_BandMathX = BandMathFilterType::New();
    m_BandMathY = BandMathFilterType::New();
    m_ExtractX = ExtractFilterType::New();
    m_ExtractY = ExtractFilterType::New();
    m_VectorCastX = VectorCastFilterType::New();
    m_VectorCastY = VectorCastFilterType::New();
    m_Concatenate = ConcatenateFilterType::New();
    m_DeformationFieldCaster = DeformationFieldCastFilterType::New();
  }

 void DoInit()
  {
    SetName("GridBasedImageResampling");
    SetDescription("Resamples an image according to a resampling grid");

    SetDocName("Grid Based Image Resampling");
    SetDocLongDescription("This application allows to perform image resampling from an input resampling grid.");
    SetDocLimitations("None");
    SetDocAuthors("OTB-Team");

    AddDocTag(Tags::Geometry);

    SetDocSeeAlso("otbStereorecificationGridGeneration");

    AddParameter(ParameterType_Group,"io","Input and output data");
    SetParameterDescription("io","This group of parameters allows to set the input and output images.");
    AddParameter(ParameterType_InputImage,"io.in","Input image");
    SetParameterDescription("io.in","The input image to resample");
    AddParameter(ParameterType_OutputImage, "io.out", "Output Image");
    SetParameterDescription("io.out","The resampled output image");

    AddParameter(ParameterType_Group,"grid","Resampling grid parameters");
    AddParameter(ParameterType_InputImage,"grid.in","Input resampling grid");
    SetParameterDescription("grid.in","The resampling grid");
    AddParameter(ParameterType_Choice,   "grid.type", "Grid Type");
    SetParameterDescription("grid.type","Allows to choose between two grid types");
    AddChoice("grid.type.def","Deformation  grid: G(x_out,y_out) = (x_in-x_out, y_in-y_out)");
    SetParameterDescription("grid.type.def","A deformation grid contains at each grid position the offset to apply to this position in order to get to the corresponding point in the input image to resample");
    AddChoice("grid.type.loc","Localisation grid: G(x_out,y_out) = (x_in, y_in)");
    SetParameterDescription("grid.type.loc","A localisation grid contains at each grid position the corresponding position in the input image to resample");

    AddParameter(ParameterType_Group, "out", "Output Image parameters");
    SetParameterDescription("out","Parameters of the output image");

    AddParameter(ParameterType_Float, "out.ulx", "Upper Left X");
    SetParameterDescription("out.ulx","X Coordinate of the upper-left pixel of the output resampled image");
    SetDefaultParameterFloat("out.ulx",0);
    AddParameter(ParameterType_Float, "out.uly", "Upper Left Y");
    SetParameterDescription("out.uly","Y Coordinate of the upper-left pixel of the output resampled image");
    SetDefaultParameterFloat("out.uly",0);

    AddParameter(ParameterType_Int, "out.sizex", "Size X");
    SetParameterDescription("out.sizex","Size of the output resampled image along X (in pixels)");
    AddParameter(ParameterType_Int, "out.sizey", "Size Y");
    SetParameterDescription("out.sizey","Size of the output resampled image along Y (in pixels)");
    AddParameter(ParameterType_Float, "out.spacingx", "Pixel Size X");
    SetParameterDescription("out.spacingx","Size of each pixel along X axis");
    SetDefaultParameterFloat("out.spacingx",1.);
    AddParameter(ParameterType_Float, "out.spacingy", "Pixel Size Y");
    SetParameterDescription("out.spacingy","Size of each pixel along Y axis");
    SetDefaultParameterFloat("out.spacingy",1.);

    // Interpolators
    AddParameter(ParameterType_Choice,   "interpolator", "Interpolation");
    SetParameterDescription("interpolator","This group of parameters allows to define how the input image will be interpolated during resampling.");
    AddChoice("interpolator.nn",     "Nearest Neighbor interpolation");
    SetParameterDescription("interpolator.nn","Nearest neighbor interpolation leads to poor image quality, but it is very fast.");
    AddChoice("interpolator.linear", "Linear interpolation");
    SetParameterDescription("interpolator.linear","Linear interpolation leads to average image quality but is quite fast");
    AddChoice("interpolator.bco",    "Bicubic interpolation");
    AddParameter(ParameterType_Radius, "interpolator.bco.radius", "Radius for bicubic interpolation");
    SetParameterDescription("interpolator.bco.radius","This parameter allows to control the size of the bicubic interpolation filter. If the target pixel size is higher than the input pixel size, increasing this parameter will reduce aliasing artefacts.");
    SetDefaultParameterInt("interpolator.bco.radius", 2);
    SetParameterString("interpolator","bco");

    AddRAMParameter();

    // Doc example
    SetDocExampleParameterValue("io.in","ROI_IKO_PAN_LesHalles_sub.tif");
    SetDocExampleParameterValue("io.out","ROI_IKO_PAN_LesHalles_sub_resampled.tif uint8");
    SetDocExampleParameterValue("grid.in","ROI_IKO_PAN_LesHalles_sub_deformation_field.tif");
    SetDocExampleParameterValue("out.sizex","256");
    SetDocExampleParameterValue("out.sizey","256");
    SetDocExampleParameterValue("grid.type","def");
  }

 void DoUpdateParameters()
  {
    // Nothing to do here
  }

void DoExecute()
    {
      // Get the input image
      FloatVectorImageType* inImage = GetParameterImage("io.in");

      // Get the resampling grid
      FloatVectorImageType * inGrid = GetParameterImage("grid.in");

      if(inGrid->GetNumberOfComponentsPerPixel() != 2)
        {
        itkExceptionMacro(<<"Number of components of the grid is not 2, this is probably not an image of 2D resampling grid.");
        }

      // In case of localisation grid, we must internally convert to
      // deformation grid, which is the only type handled by StreamingWarpImageFilter
      if(GetParameterInt("grid.type") == 0)
        {
        GetLogger()->Info("Grid intepreted as a location grid.");
        m_ExtractX->SetInput(inGrid);
        m_ExtractX->SetChannel(1);
        m_BandMathX->SetNthInput(0,m_ExtractX->GetOutput(),"locX");
        m_BandMathX->SetExpression("locX-idxPhyX");
        m_ExtractY->SetInput(inGrid);
        m_ExtractY->SetChannel(1);
        m_BandMathY->SetNthInput(0,m_ExtractY->GetOutput(),"locY");
        m_BandMathY->SetExpression("locY-idxPhyY");
        m_VectorCastX->SetInput(m_BandMathX->GetOutput());
        m_Concatenate->SetInput1(m_VectorCastX->GetOutput());
        m_VectorCastY->SetInput(m_BandMathY->GetOutput());
        m_Concatenate->SetInput2(m_VectorCastY->GetOutput());
        m_DeformationFieldCaster->SetInput(m_Concatenate->GetOutput());
        }
      else
        {
        GetLogger()->Info("Grid intepreted as a deformation grid.");
        m_DeformationFieldCaster->SetInput(inGrid);
        }

      m_DeformationFieldCaster->GetOutput()->UpdateOutputInformation();

      m_WarpImageFilter->SetDeformationField(m_DeformationFieldCaster->GetOutput());

      // Set inputs
      m_WarpImageFilter->SetInput(inImage);

    // Get Interpolator
    switch ( GetParameterInt("interpolator") )
      {
      case Interpolator_Linear:
      {
      typedef itk::LinearInterpolateImageFunction<FloatVectorImageType,
        double>          LinearInterpolationType;
      LinearInterpolationType::Pointer interpolator = LinearInterpolationType::New();
      m_WarpImageFilter->SetInterpolator(interpolator);
      }
      break;
      case Interpolator_NNeighbor:
      {
      typedef itk::NearestNeighborInterpolateImageFunction<FloatVectorImageType,
        double> NearestNeighborInterpolationType;
      NearestNeighborInterpolationType::Pointer interpolator = NearestNeighborInterpolationType::New();
      m_WarpImageFilter->SetInterpolator(interpolator);
      }
      break;
      case Interpolator_BCO:
      {
      typedef otb::BCOInterpolateImageFunction<FloatVectorImageType> BCOInterpolationType;
      BCOInterpolationType::Pointer interpolator = BCOInterpolationType::New();
      interpolator->SetRadius(GetParameterInt("interpolator.bco.radius"));
      m_WarpImageFilter->SetInterpolator(interpolator);
      }
      break;
      }

    // Set Output information
    WarpFilterType::SizeType size;
    size[0] = GetParameterInt("out.sizex");
    size[1] = GetParameterInt("out.sizey");
    m_WarpImageFilter->SetOutputSize(size);

    WarpFilterType::SpacingType spacing;
    spacing[0] = GetParameterFloat("out.spacingx");
    spacing[1] = GetParameterFloat("out.spacingy");
    m_WarpImageFilter->SetOutputSpacing(spacing);

    WarpFilterType::PointType ul;
    ul[0] = GetParameterFloat("out.ulx");
    ul[1] = GetParameterFloat("out.uly");
    m_WarpImageFilter->SetOutputOrigin(ul);

    // Output Image
    SetParameterOutputImage("io.out", m_WarpImageFilter->GetOutput());

    }

  WarpFilterType::Pointer        m_WarpImageFilter;
  ExtractFilterType::Pointer     m_ExtractX;
  ExtractFilterType::Pointer     m_ExtractY;
  BandMathFilterType::Pointer    m_BandMathX;
  BandMathFilterType::Pointer    m_BandMathY;
  VectorCastFilterType::Pointer  m_VectorCastX;
  VectorCastFilterType::Pointer  m_VectorCastY;
  ConcatenateFilterType::Pointer m_Concatenate;
  DeformationFieldCastFilterType::Pointer m_DeformationFieldCaster;
};
} // End namespace Wrapper
} // End namepsace otb

OTB_APPLICATION_EXPORT(otb::Wrapper::GridBasedImageResampling)
<commit_msg>BUG: Fixing a bug in choice order and adding an option to set the default pixel value<commit_after>/*=========================================================================

 Program:   ORFEO Toolbox
 Language:  C++
 Date:      $Date$
 Version:   $Revision$

 Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
 See OTBCopyright.txt for details.

 This software is distributed WITHOUT ANY WARRANTY; without even
 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
 PURPOSE.  See the above copyright notices for more information.

 =========================================================================*/
#include "otbWrapperApplication.h"
#include "otbWrapperApplicationFactory.h"

#include "otbStreamingWarpImageFilter.h"
#include "itkLinearInterpolateImageFunction.h"
#include "otbBCOInterpolateImageFunction.h"
#include "itkNearestNeighborInterpolateImageFunction.h"
#include "otbBandMathImageFilter.h"
#include "otbConcatenateVectorImageFilter.h"
#include "otbMultiToMonoChannelExtractROI.h"
#include "otbImageToVectorImageCastFilter.h"
#include "itkVectorCastImageFilter.h"

namespace otb
{
enum
{
  Interpolator_Linear,
  Interpolator_NNeighbor,
  Interpolator_BCO
};

namespace Wrapper
{

class GridBasedImageResampling : public Application
{
public:
  /** Standard class typedefs. */
  typedef GridBasedImageResampling      Self;
  typedef Application                   Superclass;
  typedef itk::SmartPointer<Self>       Pointer;
  typedef itk::SmartPointer<const Self> ConstPointer;

  typedef itk::Vector<double,2>         DeformationType;
  typedef otb::Image<DeformationType>   DeformationFieldType;

  typedef itk::VectorCastImageFilter
  <FloatVectorImageType,
   DeformationFieldType>                DeformationFieldCastFilterType;

  typedef otb::StreamingWarpImageFilter
  <FloatVectorImageType,
   FloatVectorImageType,
   DeformationFieldType>                WarpFilterType;
  typedef otb::MultiToMonoChannelExtractROI
  <FloatVectorImageType::InternalPixelType,
   FloatVectorImageType::InternalPixelType>
                                        ExtractFilterType;

  typedef otb::BandMathImageFilter
  <ExtractFilterType::OutputImageType>  BandMathFilterType;

  typedef otb::ImageToVectorImageCastFilter
  <ExtractFilterType::OutputImageType,
   FloatVectorImageType>                VectorCastFilterType;

  typedef otb::ConcatenateVectorImageFilter
  <FloatVectorImageType,
   FloatVectorImageType,
   FloatVectorImageType>                ConcatenateFilterType;

  /** Standard macro */
  itkNewMacro(Self);

  itkTypeMacro(GridBasedImageResampling, otb::Application);

private:

  GridBasedImageResampling()
  {
    // Instanciate warp filter
    m_WarpImageFilter = WarpFilterType::New();
    m_BandMathX = BandMathFilterType::New();
    m_BandMathY = BandMathFilterType::New();
    m_ExtractX = ExtractFilterType::New();
    m_ExtractY = ExtractFilterType::New();
    m_VectorCastX = VectorCastFilterType::New();
    m_VectorCastY = VectorCastFilterType::New();
    m_Concatenate = ConcatenateFilterType::New();
    m_DeformationFieldCaster = DeformationFieldCastFilterType::New();
  }

 void DoInit()
  {
    SetName("GridBasedImageResampling");
    SetDescription("Resamples an image according to a resampling grid");

    SetDocName("Grid Based Image Resampling");
    SetDocLongDescription("This application allows to perform image resampling from an input resampling grid.");
    SetDocLimitations("None");
    SetDocAuthors("OTB-Team");

    AddDocTag(Tags::Geometry);

    SetDocSeeAlso("otbStereorecificationGridGeneration");

    AddParameter(ParameterType_Group,"io","Input and output data");
    SetParameterDescription("io","This group of parameters allows to set the input and output images.");
    AddParameter(ParameterType_InputImage,"io.in","Input image");
    SetParameterDescription("io.in","The input image to resample");
    AddParameter(ParameterType_OutputImage, "io.out", "Output Image");
    SetParameterDescription("io.out","The resampled output image");

    AddParameter(ParameterType_Group,"grid","Resampling grid parameters");
    AddParameter(ParameterType_InputImage,"grid.in","Input resampling grid");
    SetParameterDescription("grid.in","The resampling grid");
    AddParameter(ParameterType_Choice,   "grid.type", "Grid Type");
    SetParameterDescription("grid.type","Allows to choose between two grid types");
    AddChoice("grid.type.def","Deformation  grid: G(x_out,y_out) = (x_in-x_out, y_in-y_out)");
    SetParameterDescription("grid.type.def","A deformation grid contains at each grid position the offset to apply to this position in order to get to the corresponding point in the input image to resample");
    AddChoice("grid.type.loc","Localisation grid: G(x_out,y_out) = (x_in, y_in)");
    SetParameterDescription("grid.type.loc","A localisation grid contains at each grid position the corresponding position in the input image to resample");

    AddParameter(ParameterType_Group, "out", "Output Image parameters");
    SetParameterDescription("out","Parameters of the output image");

    AddParameter(ParameterType_Float, "out.ulx", "Upper Left X");
    SetParameterDescription("out.ulx","X Coordinate of the upper-left pixel of the output resampled image");
    SetDefaultParameterFloat("out.ulx",0);
    AddParameter(ParameterType_Float, "out.uly", "Upper Left Y");
    SetParameterDescription("out.uly","Y Coordinate of the upper-left pixel of the output resampled image");
    SetDefaultParameterFloat("out.uly",0);

    AddParameter(ParameterType_Int, "out.sizex", "Size X");
    SetParameterDescription("out.sizex","Size of the output resampled image along X (in pixels)");
    AddParameter(ParameterType_Int, "out.sizey", "Size Y");
    SetParameterDescription("out.sizey","Size of the output resampled image along Y (in pixels)");
    AddParameter(ParameterType_Float, "out.spacingx", "Pixel Size X");
    SetParameterDescription("out.spacingx","Size of each pixel along X axis");
    SetDefaultParameterFloat("out.spacingx",1.);
    AddParameter(ParameterType_Float, "out.spacingy", "Pixel Size Y");
    SetParameterDescription("out.spacingy","Size of each pixel along Y axis");
    SetDefaultParameterFloat("out.spacingy",1.);

    AddParameter(ParameterType_Float,"out.default","Default value");
    SetParameterDescription("out.default","The default value to give to pixel that falls outside of the input image.");
    SetDefaultParameterFloat("out.default",0);

    // Interpolators
    AddParameter(ParameterType_Choice,   "interpolator", "Interpolation");
    SetParameterDescription("interpolator","This group of parameters allows to define how the input image will be interpolated during resampling.");
    AddChoice("interpolator.nn",     "Nearest Neighbor interpolation");
    SetParameterDescription("interpolator.nn","Nearest neighbor interpolation leads to poor image quality, but it is very fast.");
    AddChoice("interpolator.linear", "Linear interpolation");
    SetParameterDescription("interpolator.linear","Linear interpolation leads to average image quality but is quite fast");
    AddChoice("interpolator.bco",    "Bicubic interpolation");
    AddParameter(ParameterType_Radius, "interpolator.bco.radius", "Radius for bicubic interpolation");
    SetParameterDescription("interpolator.bco.radius","This parameter allows to control the size of the bicubic interpolation filter. If the target pixel size is higher than the input pixel size, increasing this parameter will reduce aliasing artefacts.");
    SetDefaultParameterInt("interpolator.bco.radius", 2);
    SetParameterString("interpolator","bco");

    AddRAMParameter();

    // Doc example
    SetDocExampleParameterValue("io.in","ROI_IKO_PAN_LesHalles_sub.tif");
    SetDocExampleParameterValue("io.out","ROI_IKO_PAN_LesHalles_sub_resampled.tif uint8");
    SetDocExampleParameterValue("grid.in","ROI_IKO_PAN_LesHalles_sub_deformation_field.tif");
    SetDocExampleParameterValue("out.sizex","256");
    SetDocExampleParameterValue("out.sizey","256");
    SetDocExampleParameterValue("grid.type","def");
  }

 void DoUpdateParameters()
  {
    // Nothing to do here
  }

void DoExecute()
    {
      // Get the input image
      FloatVectorImageType* inImage = GetParameterImage("io.in");

      // Get the resampling grid
      FloatVectorImageType * inGrid = GetParameterImage("grid.in");

      if(inGrid->GetNumberOfComponentsPerPixel() != 2)
        {
        itkExceptionMacro(<<"Number of components of the grid is not 2, this is probably not an image of 2D resampling grid.");
        }

      // In case of localisation grid, we must internally convert to
      // deformation grid, which is the only type handled by StreamingWarpImageFilter
      if(GetParameterInt("grid.type") == 1)
        {
        GetLogger()->Info("Grid intepreted as a location grid.");
        m_ExtractX->SetInput(inGrid);
        m_ExtractX->SetChannel(1);
        m_BandMathX->SetNthInput(0,m_ExtractX->GetOutput(),"locX");
        m_BandMathX->SetExpression("locX-idxPhyX");
        m_ExtractY->SetInput(inGrid);
        m_ExtractY->SetChannel(1);
        m_BandMathY->SetNthInput(0,m_ExtractY->GetOutput(),"locY");
        m_BandMathY->SetExpression("locY-idxPhyY");
        m_VectorCastX->SetInput(m_BandMathX->GetOutput());
        m_Concatenate->SetInput1(m_VectorCastX->GetOutput());
        m_VectorCastY->SetInput(m_BandMathY->GetOutput());
        m_Concatenate->SetInput2(m_VectorCastY->GetOutput());
        m_DeformationFieldCaster->SetInput(m_Concatenate->GetOutput());
        }
      else
        {
        GetLogger()->Info("Grid intepreted as a deformation grid.");
        m_DeformationFieldCaster->SetInput(inGrid);
        }

      m_DeformationFieldCaster->GetOutput()->UpdateOutputInformation();

      m_WarpImageFilter->SetDeformationField(m_DeformationFieldCaster->GetOutput());

      // Set inputs
      m_WarpImageFilter->SetInput(inImage);

    // Get Interpolator
    switch ( GetParameterInt("interpolator") )
      {
      case Interpolator_Linear:
      {
      typedef itk::LinearInterpolateImageFunction<FloatVectorImageType,
        double>          LinearInterpolationType;
      LinearInterpolationType::Pointer interpolator = LinearInterpolationType::New();
      m_WarpImageFilter->SetInterpolator(interpolator);
      }
      break;
      case Interpolator_NNeighbor:
      {
      typedef itk::NearestNeighborInterpolateImageFunction<FloatVectorImageType,
        double> NearestNeighborInterpolationType;
      NearestNeighborInterpolationType::Pointer interpolator = NearestNeighborInterpolationType::New();
      m_WarpImageFilter->SetInterpolator(interpolator);
      }
      break;
      case Interpolator_BCO:
      {
      typedef otb::BCOInterpolateImageFunction<FloatVectorImageType> BCOInterpolationType;
      BCOInterpolationType::Pointer interpolator = BCOInterpolationType::New();
      interpolator->SetRadius(GetParameterInt("interpolator.bco.radius"));
      m_WarpImageFilter->SetInterpolator(interpolator);
      }
      break;
      }

    // Set Output information
    WarpFilterType::SizeType size;
    size[0] = GetParameterInt("out.sizex");
    size[1] = GetParameterInt("out.sizey");
    m_WarpImageFilter->SetOutputSize(size);

    WarpFilterType::SpacingType spacing;
    spacing[0] = GetParameterFloat("out.spacingx");
    spacing[1] = GetParameterFloat("out.spacingy");
    m_WarpImageFilter->SetOutputSpacing(spacing);

    WarpFilterType::PointType ul;
    ul[0] = GetParameterFloat("out.ulx");
    ul[1] = GetParameterFloat("out.uly");
    m_WarpImageFilter->SetOutputOrigin(ul);

    // Build the default pixel
    FloatVectorImageType::PixelType defaultValue;
    defaultValue.SetSize(inImage->GetNumberOfComponentsPerPixel());
    defaultValue.Fill(GetParameterFloat("out.default"));

    m_WarpImageFilter->SetEdgePaddingValue(defaultValue);

    // Output Image
    SetParameterOutputImage("io.out", m_WarpImageFilter->GetOutput());

    }

  WarpFilterType::Pointer        m_WarpImageFilter;
  ExtractFilterType::Pointer     m_ExtractX;
  ExtractFilterType::Pointer     m_ExtractY;
  BandMathFilterType::Pointer    m_BandMathX;
  BandMathFilterType::Pointer    m_BandMathY;
  VectorCastFilterType::Pointer  m_VectorCastX;
  VectorCastFilterType::Pointer  m_VectorCastY;
  ConcatenateFilterType::Pointer m_Concatenate;
  DeformationFieldCastFilterType::Pointer m_DeformationFieldCaster;
};
} // End namespace Wrapper
} // End namepsace otb

OTB_APPLICATION_EXPORT(otb::Wrapper::GridBasedImageResampling)
<|endoftext|>


<commit_before>#include <stdexcept>

namespace qi
{
  template <typename T>
  AutoService<T>::AutoService(const std::string& name, Session& session)
    : qi::Trackable<AutoService<T> > (this)
    , _session(session)
    , _name(name)
  {
    Future<qi::AnyObject> fut = session.service(name);
    fut.connect(&AutoService::onServiceModified, this, fut);

    _session.serviceRegistered.connect(&AutoService::onServiceAdded, this, _2);
    _session.serviceUnregistered.connect(&AutoService::onServiceRemoved, this, _2);
  }

  template <typename T>
  AutoService<T>::~AutoService()
  {
    this->destroy();
  }

  template <typename T>
  void AutoService<T>::onServiceRemoved(const std::string& name)
  {
    if (name == _name)
    {
      {
        boost::mutex::scoped_lock scoped_lock(_mutex);
        _object = qi::Object<T>();
        _promise.reset();
      }
      serviceRemoved();
    }
  }

  template <typename T>
  void AutoService<T>::onServiceModified(const qi::Future<qi::AnyObject>& future)
  {
    if (!future.hasError())
    {
      {
        boost::mutex::scoped_lock scoped_lock(_mutex);
        _object = qi::Object<T>(future.value());
        if (!_promise.future().isFinished())
          _promise.setValue(0);
      }
      serviceAdded();
    }
    else
    { // A Service has been added, but it has been impossible to get it; so we delete it.
      {
        boost::mutex::scoped_lock scoped_lock(_mutex);
        _object = qi::Object<T>();
        _promise.reset();
      }
      serviceRemoved();
    }
  }

  template <typename T>
  void AutoService<T>::onServiceAdded(const std::string& name)
  {
    if (name == _name)
    {
      qi::Future<qi::AnyObject> future = _session.service(name);
      future.connect(&AutoService::onServiceModified, this, future);
    }
  }

  /**
   * The compiler will recursively call operator-> on each returned object until he get a pointer
   * We return an qi::details::Keeper<T> to keep T* alive during the call
   * (Object<T> will be temporary stored on stack while the call is pending)
   */
  template <typename T>
  qi::detail::Keeper<T> AutoService<T>::operator->()
  {
    boost::mutex::scoped_lock scoped_lock(_mutex);
    qi::detail::Keeper<T> keeper = qi::detail::Keeper<T>(_object);
    if (keeper._obj)
      return keeper;
    throw std::runtime_error("Service " + _name + " unavailable");
  }

  template <typename T>
  qi::detail::Keeper<T> AutoService<T>::operator->() const
  {
    boost::mutex::scoped_lock scoped_lock(_mutex);
    qi::detail::Keeper<T> keeper = qi::detail::Keeper<T>(_object);
    if (keeper._obj)
      return keeper;
    throw std::runtime_error("Service " + _name + " unavailable");
  }

  template <typename T>
  T* AutoService<T>::get() const
  {
    boost::mutex::scoped_lock scoped_lock(_mutex);
    if (_object)
      return &(*_object);
    throw std::runtime_error("Service " + _name + " unavailable");
  }

  template <typename T>
  T* AutoService<T>::get()
  {
    boost::mutex::scoped_lock scoped_lock(_mutex);
    if (_object)
      return &(*_object);
    throw std::runtime_error("Service " + _name + " unavailable");
  }

  template <typename T>
  T& AutoService<T>::operator*()
  {
    return *get();
  }

  template <typename T>
  qi::FutureSync<void> AutoService<T>::waitForReady()
  {
    return _promise.future();
  }

  template <typename T>
  qi::AnyObject AutoService<T>::asAnyObject()
  {
    return _object.asAnyObject();
  }

  /**
   * Warning: AutoService<AnyObject> is invalid.
   *
   * Prefere use AnyAutoService instead.
   */
  template <>
  class AutoService<qi::AnyObject>
  {
  private:
    virtual void forbiden() = 0;
  };

  namespace detail
  {
    template <typename T>
    class Keeper
    {
    public:
      Keeper(qi::Object<T>& obj)
        : _obj(obj)
      {
      }

      T* operator->()
      {
        return &(*_obj);
      }

      qi::Object<T> _obj;
    };
  }
}
<commit_msg>AutoService::asAnyObject(): Throw if unavailable<commit_after>#include <stdexcept>

namespace qi
{
  template <typename T>
  AutoService<T>::AutoService(const std::string& name, Session& session)
    : qi::Trackable<AutoService<T> > (this)
    , _session(session)
    , _name(name)
  {
    Future<qi::AnyObject> fut = session.service(name);
    fut.connect(&AutoService::onServiceModified, this, fut);

    _session.serviceRegistered.connect(&AutoService::onServiceAdded, this, _2);
    _session.serviceUnregistered.connect(&AutoService::onServiceRemoved, this, _2);
  }

  template <typename T>
  AutoService<T>::~AutoService()
  {
    this->destroy();
  }

  template <typename T>
  void AutoService<T>::onServiceRemoved(const std::string& name)
  {
    if (name == _name)
    {
      {
        boost::mutex::scoped_lock scoped_lock(_mutex);
        _object = qi::Object<T>();
        _promise.reset();
      }
      serviceRemoved();
    }
  }

  template <typename T>
  void AutoService<T>::onServiceModified(const qi::Future<qi::AnyObject>& future)
  {
    if (!future.hasError())
    {
      {
        boost::mutex::scoped_lock scoped_lock(_mutex);
        _object = qi::Object<T>(future.value());
        if (!_promise.future().isFinished())
          _promise.setValue(0);
      }
      serviceAdded();
    }
    else
    { // A Service has been added, but it has been impossible to get it; so we delete it.
      {
        boost::mutex::scoped_lock scoped_lock(_mutex);
        _object = qi::Object<T>();
        _promise.reset();
      }
      serviceRemoved();
    }
  }

  template <typename T>
  void AutoService<T>::onServiceAdded(const std::string& name)
  {
    if (name == _name)
    {
      qi::Future<qi::AnyObject> future = _session.service(name);
      future.connect(&AutoService::onServiceModified, this, future);
    }
  }

  /**
   * The compiler will recursively call operator-> on each returned object until he get a pointer
   * We return an qi::details::Keeper<T> to keep T* alive during the call
   * (Object<T> will be temporary stored on stack while the call is pending)
   */
  template <typename T>
  qi::detail::Keeper<T> AutoService<T>::operator->()
  {
    boost::mutex::scoped_lock scoped_lock(_mutex);
    qi::detail::Keeper<T> keeper = qi::detail::Keeper<T>(_object);
    if (keeper._obj)
      return keeper;
    else
      throw std::runtime_error("Service " + _name + " unavailable");
  }

  template <typename T>
  qi::detail::Keeper<T> AutoService<T>::operator->() const
  {
    boost::mutex::scoped_lock scoped_lock(_mutex);
    qi::detail::Keeper<T> keeper = qi::detail::Keeper<T>(_object);
    if (keeper._obj)
      return keeper;
    else
      throw std::runtime_error("Service " + _name + " unavailable");
  }

  template <typename T>
  T* AutoService<T>::get() const
  {
    boost::mutex::scoped_lock scoped_lock(_mutex);
    if (_object)
      return &(*_object);
    else
      throw std::runtime_error("Service " + _name + " unavailable");
  }

  template <typename T>
  T* AutoService<T>::get()
  {
    boost::mutex::scoped_lock scoped_lock(_mutex);
    if (_object)
      return &(*_object);
    else
      throw std::runtime_error("Service " + _name + " unavailable");
  }

  template <typename T>
  T& AutoService<T>::operator*()
  {
    return *get();
  }

  template <typename T>
  qi::FutureSync<void> AutoService<T>::waitForReady()
  {
    return _promise.future();
  }

  template <typename T>
  qi::AnyObject AutoService<T>::asAnyObject()
  {
    boost::mutex::scoped_lock scoped_lock(_mutex);
    if (_object)
      return _object.asAnyObject();
    else
      throw std::runtime_error("Service " + _name + " unavailable");
  }

  /**
   * Warning: AutoService<AnyObject> is invalid.
   *
   * Prefere use AnyAutoService instead.
   */
  template <>
  class AutoService<qi::AnyObject>
  {
  private:
    virtual void forbiden() = 0;
  };

  namespace detail
  {
    template <typename T>
    class Keeper
    {
    public:
      Keeper(qi::Object<T>& obj)
        : _obj(obj)
      {
      }

      T* operator->()
      {
        return &(*_obj);
      }

      qi::Object<T> _obj;
    };
  }
}
<|endoftext|>