<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$
// Category: management

//-----------------------------------------------------------------------------
// Class AliMpManuStore
// --------------------
// The container class for manu serial numbersd
// Authors: Ivana Hrivnacova, IPN Orsay
//          Christian Finck, SUBATECH Nantes
//-----------------------------------------------------------------------------

#include "AliMpManuStore.h"

#include "AliMpDEStore.h"
#include "AliMpDEManager.h"
#include "AliMpDetElement.h"
#include "AliMpConstants.h"
#include "AliMpDataStreams.h"
#include "AliMpFiles.h"
#include "AliMpHelper.h"
#include "AliMpConstants.h"
#include "AliMpEncodePair.h"

#include "AliLog.h"

#include <Riostream.h>
#include <TClass.h>
#include <TSystem.h>
#include <TObjString.h>
#include <TObjArray.h>
#include <TMap.h>

#include <fstream>
#include <cstdlib>

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

AliMpManuStore* AliMpManuStore::fgInstance = 0;
Bool_t          AliMpManuStore::fgWarnIfDoublon = kFALSE;

//
// static methods
//

//______________________________________________________________________________
AliMpManuStore* AliMpManuStore::Instance(Bool_t warn)
{
    /// Create the DDL store if it does not yet exist
    /// and return its instance

    if ( ! fgInstance && warn  ) {
        AliWarningClass("Manu Store has not been loaded");
    }

    return fgInstance;
}

//______________________________________________________________________________
AliMpManuStore* AliMpManuStore::ReadData(const AliMpDataStreams& dataStreams,
                                         Bool_t warn)
{
    /// Load the DDL store from ASCII data files
    /// and return its instance

    if ( fgInstance ) {
        if ( warn )
            AliWarningClass("DDL Store has been already loaded");
        return fgInstance;
    }

    if ( dataStreams.GetReadFromFiles() )
      AliInfoClass("Reading Manu Store from ASCII files.");

    fgInstance = new AliMpManuStore(dataStreams);
    return fgInstance;
}

//
// ctors, dtor
//

//______________________________________________________________________________
AliMpManuStore::AliMpManuStore(const AliMpDataStreams& dataStreams)
: TObject(),
  fkDataStreams(dataStreams),
  fManuToSerialNbs(),
  fSerialNbToManus(),
  fNofManusInDE(),
  fNofManus(0)
{
/// Standard constructor

  AliDebug(1,"");

  // Check if DE store is loaded
  if ( ! AliMpDEStore::Instance(false) ) {
     AliErrorStream()
       << "Mapping segmentation has not be loaded. Cannont load Manu store"
       << endl;
     return;
  }

  ReadManuSerial();
}

//______________________________________________________________________________
AliMpManuStore::AliMpManuStore(TRootIOCtor* ioCtor)
: TObject(),
  fkDataStreams(ioCtor),
  fManuToSerialNbs(),
  fSerialNbToManus(),
  fNofManusInDE(),
  fNofManus(0)
{
/// Constructor for IO

  AliDebug(1,"");
}

//______________________________________________________________________________
AliMpManuStore::~AliMpManuStore()
{
/// Destructor

  AliDebug(1,"");
}

//
// private methods
//

//______________________________________________________________________________
Bool_t AliMpManuStore::ReadData(const AliMpDetElement* de, Int_t& nofManus)
{
/// Read manu serial numbers for the given detection element

  Int_t deId = de->GetId();
  TString deName = de->GetDEName();
  AliMp::StationType stationType
    =  AliMpDEManager::GetStationType(de->GetId());
  AliMq::Station12Type station12Type
    =  AliMpDEManager::GetStation12Type(de->GetId());

  // Nothing to be done for trigger
  if ( stationType == AliMp::kStationTrigger ) {
    nofManus = 0;
    return kTRUE;
  }

  static Int_t manuMask = AliMpConstants::ManuMask(AliMp::kNonBendingPlane);

  istream& in
    = fkDataStreams.
        CreateDataStream(
          AliMpFiles::ManuToSerialPath(deName, stationType, station12Type));

  char line[80];

  nofManus = 0;
  while ( in.getline(line,80) ) {

    if ( line[0] == '#' ) continue;

    TString tmp(AliMpHelper::Normalize(line));

    TObjArray* stringList = tmp.Tokenize(TString(" "));

    Int_t manuId     = atoi( ((TObjString*)stringList->At(0))->GetName());
    Int_t manuSerial = atoi( ((TObjString*)stringList->At(2))->GetName());

    TString sPlane = ((TObjString*)stringList->At(1))->GetString();

    // filling manuId <> manuSerial
    if (!sPlane.CompareTo(PlaneTypeName(AliMp::kBendingPlane)))
	AddManu(deId, manuId, manuSerial);
    else
	AddManu(deId, manuId + manuMask, manuSerial);

    ++nofManus;

    delete stringList;
  }

  return kTRUE;
}

//______________________________________________________________________________
Bool_t  AliMpManuStore::ReadManuSerial()
{
/// Read data files for all detection elements.
/// Return true if reading was successful.

  Bool_t isOk = kTRUE;

  // Loop over DE
  AliMpDEIterator it;
  for ( it.First(); ! it.IsDone(); it.Next() ) {

    AliMpDetElement* detElement = it.CurrentDE();

    Int_t nofManus;
    Bool_t result = ReadData(detElement, nofManus);
    fNofManusInDE.Add(detElement->GetId(), nofManus);
    fNofManus += nofManus;

    AliDebugStream(2)
      << "Adding " << nofManus << " manus for de "
      << detElement->GetId() << endl;

    isOk = isOk && result;
  }

  return isOk;
}

//______________________________________________________________________________
void  AliMpManuStore::ReplaceManu(Int_t detElemId, Int_t manuId, Int_t serialNb)
{
/// Replace manu in the map.
/// As TExMap has no replcae function, we have to rebuild map once again.
/// Not yet in use, declared private.

  Long_t index = AliMp::Pair(detElemId, manuId);

  TExMap newManuToSerialNbs;
  // Loop over map
  TExMapIter it(&fManuToSerialNbs);

#if ROOT_SVN_REVISION >= 29598
  Long64_t key;
  Long64_t value;
#else
  Long_t key;
  Long_t value;
#endif
  while ( ( it.Next(key, value) ) ) {

    if ( key != index )
      newManuToSerialNbs.Add(key, value);
    else
      newManuToSerialNbs.Add(index, Long_t(serialNb));
  }

  TExMap newSerialNbToManus;
  // Loop over map
  TExMapIter it2(&fSerialNbToManus);
  while ( ( it2.Next(key, value) ) ) {

    if ( value != index )
      newSerialNbToManus.Add(key, value);
    else
      newSerialNbToManus.Add(Long_t(serialNb), index);
  }

  // And now replace the maps
  fManuToSerialNbs = newManuToSerialNbs;
  fSerialNbToManus = newManuToSerialNbs;
}

//______________________________________________________________________________
Bool_t  AliMpManuStore::WriteData(const TString& outDir)
{
/// Write data files for all detection elements.
/// Return true if reading was successful.
/// Not yet in use, declared private.

  TString curDir = gSystem->pwd();

  // Create top directory
  //
  if ( gSystem->OpenDirectory(outDir.Data()) ) {
    AliErrorStream()
      << "Directory " << outDir.Data() << " already exists" << endl;
    return kFALSE;
  }
  else {
    AliDebugStream(2) << "Making directory " <<  outDir.Data() << endl;
    gSystem->mkdir(outDir.Data());
  }

  // Loop over DE
  AliMpDEIterator it;
  for ( it.First(); ! it.IsDone(); it.Next() ) {

    AliMpDetElement* detElement = it.CurrentDE();
    Int_t detElemId = detElement->GetId();
    TString deName = detElement->GetDEName();
    AliMp::StationType stationType
      =  AliMpDEManager::GetStationType(detElemId);
    AliMq::Station12Type station12Type
      =  AliMpDEManager::GetStation12Type(detElemId);

    if ( stationType == AliMp::kStationTrigger ) continue;

    // Create directory if it does not yet exist
    //
    TString dirPath = outDir + AliMpFiles::StationDataDir(stationType, station12Type);
    if ( ! gSystem->OpenDirectory(dirPath.Data()) ) {
      AliDebugStream(2) << "Making directory " <<  dirPath.Data() << endl;
      gSystem->mkdir(dirPath.Data());
    }

    // Compose output file path
    //
    string dataPath = AliMpFiles::ManuToSerialPath(deName, stationType, station12Type).Data();
    string top = AliMpFiles::GetTop().Data();
    if ( dataPath.find(top) != string::npos ) dataPath.erase(0, top.size()+1);
    dataPath.erase(0,dataPath.find('/')+1);
    TString dataPath1 = dataPath;
    TString filePath = outDir + "/" + dataPath1;

    // Open file
    //
    ofstream out(filePath.Data());
    if ( ! out.good() ) {
      AliErrorStream()
        << "Cannot open output file  " << filePath.Data() << endl;
      return kFALSE;
    }

    // Loop over map
    TExMapIter it2(&fManuToSerialNbs);
#if ROOT_SVN_REVISION >= 29598
    Long64_t key;
    Long64_t value;
#else
    Long_t key;
    Long_t value;
#endif
    while ( ( it2.Next(key, value) ) ) {
      Int_t pairFirst = AliMp::PairFirst(key);

      if ( pairFirst != detElemId ) continue;

      Int_t manuId = AliMp::PairSecond(key);

      AliDebugStream(3)
        << "Go to write " << key << " "
        << pairFirst << " " << manuId << " " << value << endl;

      static Int_t manuMask = AliMpConstants::ManuMask(AliMp::kNonBendingPlane);

      TString planeName = PlaneTypeName(AliMp::kBendingPlane);
      if ( manuId> manuMask ) {
        planeName = PlaneTypeName(AliMp::kNonBendingPlane);
        manuId -= manuMask;
      }
      out << manuId << " " << planeName.Data() <<  " " << value << endl;

      AliDebugStream(3)
        << manuId << " " << planeName.Data() <<  " " << value << endl;
    }
    out.close();
  }
  gSystem->cd(curDir);
  return kTRUE;
}

//
// public methods
//

//______________________________________________________________________________
Int_t  AliMpManuStore::NofManus() const
{
/// Return total number of manus in the store

  return fNofManus;
}

//______________________________________________________________________________
Int_t  AliMpManuStore::NofManus(Int_t detElemId) const
{
/// Return number of manus in given detection element

   if ( ! AliMpDEManager::IsValidDetElemId(detElemId, kTRUE) ) return 0;

   return fNofManusInDE.GetValue(detElemId);
}

//______________________________________________________________________________
Bool_t  AliMpManuStore::AddManu(Int_t detElemId, Int_t manuId, Int_t serialNb)
{
/// Add manu to the map

  Long_t index = AliMp::Pair(detElemId, manuId);

  AliDebugStream(2)
    << "Adding (" << detElemId << "," <<  manuId
    << ") as index=" << index << " and serialNb=" << serialNb << endl;

  fManuToSerialNbs.Add(index, Long_t(serialNb));

  Long_t value = fSerialNbToManus.GetValue(Long_t(serialNb));
  if ( value ) {
    if ( fgWarnIfDoublon ) {
      AliWarningStream()
        << "Serial number " << serialNb
        << " already present for (detElemId, manuId) = " ;
        AliMp::PairPut(AliWarningStream(), (MpPair_t) value) << endl;
     }
     return kFALSE;
  }
  else {
    fSerialNbToManus.Add(Long_t(serialNb), index);
    return kTRUE;
  }
}

//______________________________________________________________________________
Int_t AliMpManuStore::GetManuSerial(Int_t detElemId, Int_t manuId) const
{
/// Return manu serial number for given detElemId and manuId

  Long_t index = AliMp::Pair(detElemId, manuId);
  // cout << index << " " << fManuToSerialNbs.GetValue(index) << endl;

  return fManuToSerialNbs.GetValue(index);
}

//______________________________________________________________________________
MpPair_t  AliMpManuStore::GetDetElemIdManu(Int_t manuSerial) const
{
/// Return detElemId and manuId for given manu serial number
/// as encoded pair

  return fSerialNbToManus.GetValue(Long_t(manuSerial));
}

<commit_msg>Fixing memory leak in AliMpManuStore::ReadData (bug report #66668)<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$
// Category: management

//-----------------------------------------------------------------------------
// Class AliMpManuStore
// --------------------
// The container class for manu serial numbersd
// Authors: Ivana Hrivnacova, IPN Orsay
//          Christian Finck, SUBATECH Nantes
//-----------------------------------------------------------------------------

#include "AliMpManuStore.h"

#include "AliMpDEStore.h"
#include "AliMpDEManager.h"
#include "AliMpDetElement.h"
#include "AliMpConstants.h"
#include "AliMpDataStreams.h"
#include "AliMpFiles.h"
#include "AliMpHelper.h"
#include "AliMpConstants.h"
#include "AliMpEncodePair.h"

#include "AliLog.h"

#include <Riostream.h>
#include <TClass.h>
#include <TSystem.h>
#include <TObjString.h>
#include <TObjArray.h>
#include <TMap.h>

#include <fstream>
#include <cstdlib>

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

AliMpManuStore* AliMpManuStore::fgInstance = 0;
Bool_t          AliMpManuStore::fgWarnIfDoublon = kFALSE;

//
// static methods
//

//______________________________________________________________________________
AliMpManuStore* AliMpManuStore::Instance(Bool_t warn)
{
    /// Create the DDL store if it does not yet exist
    /// and return its instance

    if ( ! fgInstance && warn  ) {
        AliWarningClass("Manu Store has not been loaded");
    }

    return fgInstance;
}

//______________________________________________________________________________
AliMpManuStore* AliMpManuStore::ReadData(const AliMpDataStreams& dataStreams,
                                         Bool_t warn)
{
    /// Load the DDL store from ASCII data files
    /// and return its instance

    if ( fgInstance ) {
        if ( warn )
            AliWarningClass("DDL Store has been already loaded");
        return fgInstance;
    }

    if ( dataStreams.GetReadFromFiles() )
      AliInfoClass("Reading Manu Store from ASCII files.");

    fgInstance = new AliMpManuStore(dataStreams);
    return fgInstance;
}

//
// ctors, dtor
//

//______________________________________________________________________________
AliMpManuStore::AliMpManuStore(const AliMpDataStreams& dataStreams)
: TObject(),
  fkDataStreams(dataStreams),
  fManuToSerialNbs(),
  fSerialNbToManus(),
  fNofManusInDE(),
  fNofManus(0)
{
/// Standard constructor

  AliDebug(1,"");

  // Check if DE store is loaded
  if ( ! AliMpDEStore::Instance(false) ) {
     AliErrorStream()
       << "Mapping segmentation has not be loaded. Cannont load Manu store"
       << endl;
     return;
  }

  ReadManuSerial();
}

//______________________________________________________________________________
AliMpManuStore::AliMpManuStore(TRootIOCtor* ioCtor)
: TObject(),
  fkDataStreams(ioCtor),
  fManuToSerialNbs(),
  fSerialNbToManus(),
  fNofManusInDE(),
  fNofManus(0)
{
/// Constructor for IO

  AliDebug(1,"");
}

//______________________________________________________________________________
AliMpManuStore::~AliMpManuStore()
{
/// Destructor

  AliDebug(1,"");
}

//
// private methods
//

//______________________________________________________________________________
Bool_t AliMpManuStore::ReadData(const AliMpDetElement* de, Int_t& nofManus)
{
/// Read manu serial numbers for the given detection element

  Int_t deId = de->GetId();
  TString deName = de->GetDEName();
  AliMp::StationType stationType
    =  AliMpDEManager::GetStationType(de->GetId());
  AliMq::Station12Type station12Type
    =  AliMpDEManager::GetStation12Type(de->GetId());

  // Nothing to be done for trigger
  if ( stationType == AliMp::kStationTrigger ) {
    nofManus = 0;
    return kTRUE;
  }

  static Int_t manuMask = AliMpConstants::ManuMask(AliMp::kNonBendingPlane);

  istream& in
    = fkDataStreams.
        CreateDataStream(
          AliMpFiles::ManuToSerialPath(deName, stationType, station12Type));

  char line[80];

  nofManus = 0;
  while ( in.getline(line,80) ) {

    if ( line[0] == '#' ) continue;

    TString tmp(AliMpHelper::Normalize(line));

    TObjArray* stringList = tmp.Tokenize(TString(" "));

    Int_t manuId     = atoi( ((TObjString*)stringList->At(0))->GetName());
    Int_t manuSerial = atoi( ((TObjString*)stringList->At(2))->GetName());

    TString sPlane = ((TObjString*)stringList->At(1))->GetString();

    // filling manuId <> manuSerial
    if (!sPlane.CompareTo(PlaneTypeName(AliMp::kBendingPlane)))
	AddManu(deId, manuId, manuSerial);
    else
	AddManu(deId, manuId + manuMask, manuSerial);

    ++nofManus;

    delete stringList;
  }

  delete ∈

  return kTRUE;
}

//______________________________________________________________________________
Bool_t  AliMpManuStore::ReadManuSerial()
{
/// Read data files for all detection elements.
/// Return true if reading was successful.

  Bool_t isOk = kTRUE;

  // Loop over DE
  AliMpDEIterator it;
  for ( it.First(); ! it.IsDone(); it.Next() ) {

    AliMpDetElement* detElement = it.CurrentDE();

    Int_t nofManus;
    Bool_t result = ReadData(detElement, nofManus);
    fNofManusInDE.Add(detElement->GetId(), nofManus);
    fNofManus += nofManus;

    AliDebugStream(2)
      << "Adding " << nofManus << " manus for de "
      << detElement->GetId() << endl;

    isOk = isOk && result;
  }

  return isOk;
}

//______________________________________________________________________________
void  AliMpManuStore::ReplaceManu(Int_t detElemId, Int_t manuId, Int_t serialNb)
{
/// Replace manu in the map.
/// As TExMap has no replcae function, we have to rebuild map once again.
/// Not yet in use, declared private.

  Long_t index = AliMp::Pair(detElemId, manuId);

  TExMap newManuToSerialNbs;
  // Loop over map
  TExMapIter it(&fManuToSerialNbs);

#if ROOT_SVN_REVISION >= 29598
  Long64_t key;
  Long64_t value;
#else
  Long_t key;
  Long_t value;
#endif
  while ( ( it.Next(key, value) ) ) {

    if ( key != index )
      newManuToSerialNbs.Add(key, value);
    else
      newManuToSerialNbs.Add(index, Long_t(serialNb));
  }

  TExMap newSerialNbToManus;
  // Loop over map
  TExMapIter it2(&fSerialNbToManus);
  while ( ( it2.Next(key, value) ) ) {

    if ( value != index )
      newSerialNbToManus.Add(key, value);
    else
      newSerialNbToManus.Add(Long_t(serialNb), index);
  }

  // And now replace the maps
  fManuToSerialNbs = newManuToSerialNbs;
  fSerialNbToManus = newManuToSerialNbs;
}

//______________________________________________________________________________
Bool_t  AliMpManuStore::WriteData(const TString& outDir)
{
/// Write data files for all detection elements.
/// Return true if reading was successful.
/// Not yet in use, declared private.

  TString curDir = gSystem->pwd();

  // Create top directory
  //
  if ( gSystem->OpenDirectory(outDir.Data()) ) {
    AliErrorStream()
      << "Directory " << outDir.Data() << " already exists" << endl;
    return kFALSE;
  }
  else {
    AliDebugStream(2) << "Making directory " <<  outDir.Data() << endl;
    gSystem->mkdir(outDir.Data());
  }

  // Loop over DE
  AliMpDEIterator it;
  for ( it.First(); ! it.IsDone(); it.Next() ) {

    AliMpDetElement* detElement = it.CurrentDE();
    Int_t detElemId = detElement->GetId();
    TString deName = detElement->GetDEName();
    AliMp::StationType stationType
      =  AliMpDEManager::GetStationType(detElemId);
    AliMq::Station12Type station12Type
      =  AliMpDEManager::GetStation12Type(detElemId);

    if ( stationType == AliMp::kStationTrigger ) continue;

    // Create directory if it does not yet exist
    //
    TString dirPath = outDir + AliMpFiles::StationDataDir(stationType, station12Type);
    if ( ! gSystem->OpenDirectory(dirPath.Data()) ) {
      AliDebugStream(2) << "Making directory " <<  dirPath.Data() << endl;
      gSystem->mkdir(dirPath.Data());
    }

    // Compose output file path
    //
    string dataPath = AliMpFiles::ManuToSerialPath(deName, stationType, station12Type).Data();
    string top = AliMpFiles::GetTop().Data();
    if ( dataPath.find(top) != string::npos ) dataPath.erase(0, top.size()+1);
    dataPath.erase(0,dataPath.find('/')+1);
    TString dataPath1 = dataPath;
    TString filePath = outDir + "/" + dataPath1;

    // Open file
    //
    ofstream out(filePath.Data());
    if ( ! out.good() ) {
      AliErrorStream()
        << "Cannot open output file  " << filePath.Data() << endl;
      return kFALSE;
    }

    // Loop over map
    TExMapIter it2(&fManuToSerialNbs);
#if ROOT_SVN_REVISION >= 29598
    Long64_t key;
    Long64_t value;
#else
    Long_t key;
    Long_t value;
#endif
    while ( ( it2.Next(key, value) ) ) {
      Int_t pairFirst = AliMp::PairFirst(key);

      if ( pairFirst != detElemId ) continue;

      Int_t manuId = AliMp::PairSecond(key);

      AliDebugStream(3)
        << "Go to write " << key << " "
        << pairFirst << " " << manuId << " " << value << endl;

      static Int_t manuMask = AliMpConstants::ManuMask(AliMp::kNonBendingPlane);

      TString planeName = PlaneTypeName(AliMp::kBendingPlane);
      if ( manuId> manuMask ) {
        planeName = PlaneTypeName(AliMp::kNonBendingPlane);
        manuId -= manuMask;
      }
      out << manuId << " " << planeName.Data() <<  " " << value << endl;

      AliDebugStream(3)
        << manuId << " " << planeName.Data() <<  " " << value << endl;
    }
    out.close();
  }
  gSystem->cd(curDir);
  return kTRUE;
}

//
// public methods
//

//______________________________________________________________________________
Int_t  AliMpManuStore::NofManus() const
{
/// Return total number of manus in the store

  return fNofManus;
}

//______________________________________________________________________________
Int_t  AliMpManuStore::NofManus(Int_t detElemId) const
{
/// Return number of manus in given detection element

   if ( ! AliMpDEManager::IsValidDetElemId(detElemId, kTRUE) ) return 0;

   return fNofManusInDE.GetValue(detElemId);
}

//______________________________________________________________________________
Bool_t  AliMpManuStore::AddManu(Int_t detElemId, Int_t manuId, Int_t serialNb)
{
/// Add manu to the map

  Long_t index = AliMp::Pair(detElemId, manuId);

  AliDebugStream(2)
    << "Adding (" << detElemId << "," <<  manuId
    << ") as index=" << index << " and serialNb=" << serialNb << endl;

  fManuToSerialNbs.Add(index, Long_t(serialNb));

  Long_t value = fSerialNbToManus.GetValue(Long_t(serialNb));
  if ( value ) {
    if ( fgWarnIfDoublon ) {
      AliWarningStream()
        << "Serial number " << serialNb
        << " already present for (detElemId, manuId) = " ;
        AliMp::PairPut(AliWarningStream(), (MpPair_t) value) << endl;
     }
     return kFALSE;
  }
  else {
    fSerialNbToManus.Add(Long_t(serialNb), index);
    return kTRUE;
  }
}

//______________________________________________________________________________
Int_t AliMpManuStore::GetManuSerial(Int_t detElemId, Int_t manuId) const
{
/// Return manu serial number for given detElemId and manuId

  Long_t index = AliMp::Pair(detElemId, manuId);
  // cout << index << " " << fManuToSerialNbs.GetValue(index) << endl;

  return fManuToSerialNbs.GetValue(index);
}

//______________________________________________________________________________
MpPair_t  AliMpManuStore::GetDetElemIdManu(Int_t manuSerial) const
{
/// Return detElemId and manuId for given manu serial number
/// as encoded pair

  return fSerialNbToManus.GetValue(Long_t(manuSerial));
}

<|endoftext|>


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

#include "uridineminimizationbenchmark.h"

#include <chemkit/molecule.h>
#include <chemkit/forcefield.h>
#include <chemkit/moleculefile.h>

const std::string dataPath = "../../data/";

void UridineMinimizationBenchmark::benchmark()
{
    boost::shared_ptr<chemkit::Molecule> molecule = chemkit::MoleculeFile::quickRead(dataPath + "uridine.mol2");
    QVERIFY(molecule != 0);

    chemkit::ForceField *forceField = chemkit::ForceField::create("uff");
    QVERIFY(forceField != 0);

    forceField->setMolecule(molecule.get());
    bool ok = forceField->setup();
    QVERIFY(ok);

    QBENCHMARK {
        for(;;){
            // converge when rmsg = 0.1
            bool converged = forceField->minimizationStep(0.1);

            if(converged){
                break;
            }
        }
    }

    delete forceField;
}

QTEST_APPLESS_MAIN(UridineMinimizationBenchmark)
<commit_msg>Use MoleculeGeometryOptimizer in UridineMinimizationBenchmark<commit_after>/******************************************************************************
**
** Copyright (C) 2009-2011 Kyle Lutz <kyle.r.lutz@gmail.com>
** All rights reserved.
**
** This file is a part of the chemkit project. For more information
** see <http://www.chemkit.org>.
**
** Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions
** are met:
**
**   * Redistributions of source code must retain the above copyright
**     notice, this list of conditions and the following disclaimer.
**   * Redistributions in binary form must reproduce the above copyright
**     notice, this list of conditions and the following disclaimer in the
**     documentation and/or other materials provided with the distribution.
**   * Neither the name of the chemkit project nor the names of its
**     contributors may be used to endorse or promote products derived
**     from this software without specific prior written permission.
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**
******************************************************************************/

#include "uridineminimizationbenchmark.h"

#include <chemkit/molecule.h>
#include <chemkit/moleculefile.h>
#include <chemkit/moleculegeometryoptimizer.h>

const std::string dataPath = "../../data/";

void UridineMinimizationBenchmark::benchmark()
{
    boost::shared_ptr<chemkit::Molecule> molecule = chemkit::MoleculeFile::quickRead(dataPath + "uridine.mol2");
    QVERIFY(molecule != 0);

    chemkit::MoleculeGeometryOptimizer optimizer;
    optimizer.setForceField("uff");
    optimizer.setMolecule(molecule.get());

    bool ok = optimizer.setup();
    QVERIFY(ok);

    QBENCHMARK {
        for(;;){
            // converge when rmsg = 0.1
            bool converged = optimizer.step();

            if(converged){
                break;
            }
        }
    }
}

QTEST_APPLESS_MAIN(UridineMinimizationBenchmark)
<|endoftext|>


<commit_before>/***************************************************************************
 *   Copyright (C) 2008 by Daniel Schwen   *
 *   daniel@schwen.de   *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 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 General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include <stdio.h>
#include <stdlib.h>
#include <queue>
#include <iostream>
#include <fstream>
#include <sstream>

#include "simconf.h"
#include "element.h"
#include "material.h"
#include "sample_wire.h"
#include "sample_burried_wire.h"
#include "ion.h"
#include "trim.h"
#include "invert.h"
#include <r250.h>

#include "functions.h"

using namespace std;

int main(int argc, char *argv[])
{
  char fname[200];
  if( argc != 6 )
  {
    cerr << "syntax: " << argv[0] << " basename angle[deg] diameter(nm) burried[0,1] numbermultiplier" << endl;
    return 1;
  }

  double theta = atof(argv[2]) * M_PI/180.0; // 0 = parallel to wire
  double diameter  = 10.0*atof(argv[3]);
  double length  = 11000.0; // 1.1 mu
  bool burried = ( atoi(argv[4]) != 0 );
  double mult = atof(argv[5]);

  // ion series
  const int nstep = 5;
  double ion_dose[nstep] = { 3.0e13, 2.2e13, 1.5e13, 1.2e13, 2.5e13 }; // in ions/cm^2
  int ion_count[nstep];
  ionBase* ion_prototype[nstep];
  ion_prototype[0] = new ionBase(  5, 11.0 , 320.0e3 ); // Z,m,E
  ion_prototype[1] = new ionBase(  5, 11.0 , 220.0e3 ); // Z,m,E
  ion_prototype[2] = new ionBase(  5, 11.0 , 160.0e3 ); // Z,m,E
  ion_prototype[3] = new ionBase(  5, 11.0 , 120.0e3 ); // Z,m,E
  ion_prototype[4] = new ionBase( 15, 31.0 , 250.0e3 ); // Z,m,E

  // seed randomnumber generator from system entropy pool
  FILE *urand = fopen( "/dev/random", "r" );
  int seed;
  fread( &seed, sizeof(int), 1, urand );
  fclose( urand );
  r250_init( seed<0 ? -seed : seed ); // random generator goes haywire with neg. seed

  // initialize global parameter structure and read data tables from file
  simconf = new simconfType;

  // initialize sample structure
  sampleWire *sample;
  if( burried )
    sample = new sampleBurriedWire( diameter, diameter, length );
  else
  {
    sample = new sampleWire( diameter, diameter, length );
    sample->bc[2] = sampleWire::CUT;
  }

  // calculate actual ion numbers
  for( int s = 0; s < nstep; ++s )
  {
    double A; // irradiated area in Ang^2
    if( burried )
      A =( 2.0*length + sample->w[0] ) * ( 2.0*length + sample->w[1] );
    else
      A = cos(theta) * M_PI * 0.25 * sample->w[0] * sample->w[1] + //   slanted top face
          sin(theta) * length * sample->w[0];                      // + projected side

    // 1cm^2 = 1e16 Ang**2, 1Ang^2 = 1e-16cm^2
    ion_count[s] = ion_dose[s] * A * 1.0e-16 * mult;
    cerr << "Ion " << s << ' ' << ion_count[s] << endl;
  }

  // initialize trim engine for the sample
/*  const int z1 = 31;
  const int z2 = 33;
  trimVacMap *trim = new trimVacMap( sample, z1, z2 ); // GaAs*/
  //trimBase *trim = new trimBase( sample );
  trimBase *trim = new trimPrimaries( sample );

  materialBase *material;
  elementBase *element;

  // Si
  material = new materialBase( 2.329 ); // rho
  element = new elementBase;
  element->z = 14; // Si
  element->m = 28.0;
  element->t = 1.0;
  material->element.push_back( element );
  material->prepare(); // all materials added
  sample->material.push_back( material ); // add material to sample

  // SiO2 (material[1] for the cover layer in SampleBurriedWire)
  material = new materialBase( 2.634 ); // rho
  element = new elementBase;
  element->z = 14; // Si
  element->m = 28.0;
  element->t = 1.0;
  material->element.push_back( element );
  element = new elementBase;
  element->z = 8; // O
  element->m = 16.0;
  element->t = 2.0;
  material->element.push_back( element );
  material->prepare(); // all materials added
  sample->material.push_back( material ); // add material to sample

  // create a FIFO for recoils
  queue<ionBase*> recoils;

  double norm;
  double jmp = 2.7; // diffusion jump distance
  int jumps;
  double dif[3];

  //snprintf( fname, 199, "%s.Erec", argv[1] );
  //FILE *erec = fopen( fname, "wt" );

  //snprintf( fname, 199, "%s.dist", argv[1] );
  //FILE *rdist = fopen( fname, "wt" );

  ionBase *pka;

  // map concentration along length
  int *lbins[2];
  int lx = 100; // 100 bins
  int dl = length/double(lx);
  lbins[1] = new int[lx]; // P z=15
  for( int i = 0; i < 2; ++i )
  {
    lbins[i] = new int[lx]; // 0=B (z=5), 1=P (z=15)
    for( int l = 0; l < lx; ++l )
      lbins[i][l] = 0;
  }

  // xyz data
  int xyz_lines = 0;
  stringstream xyz_data;

  for( int s = 0; s < nstep; ++s )
  {
    for( int n = 0; n < ion_count[s]; ++n )
    {
      if( n % 10000 == 0 )
        cerr << "pka #" << n+1 << endl;

      // generate new PKA from prototype ion
      pka = new ionBase( ion_prototype[s] );
      pka->gen = 0; // generation (0 = PKA)
      pka->tag = -1;
      pka->md = 0;

      pka->dir[0] = 0.0;
      pka->dir[1] = sin( theta );
      pka->dir[2] = cos( theta );

      v_norm( pka->dir );

      if( burried )
      {
        // cannot anticipate the straggling in the burrial layer, thus have to shoot onto a big surface
        // TODO: take theta into account!
        pka->pos[0] = dr250() * ( 2.0*length + sample->w[0] ) - ( length + 0.5 * sample->w[0] ) ;
        pka->pos[1] = dr250() * ( 2.0*length + sample->w[1] ) - ( length + 0.5 * sample->w[1] ) ;
        pka->pos[2] = -250.0; // overcoat thickness
      }
      else
      {
        if( theta == 0.0 )
        {
          // 0 degrees => start on top of wire!
          pka->pos[2] = 0.0;
          do
          {
            pka->pos[0] = dr250() * sample->w[0];
            pka->pos[1] = dr250() * sample->w[1];
          } while( sample->lookupMaterial(pka->pos ) == 0 );
        }
        else
        {
          // start on side _or_ top!
          double vpos[3], t;
          do
          {
            do
            {
              vpos[0] = dr250() * sample->w[0];
              vpos[1] = 0.0;
              vpos[2] = ( dr250() * ( length + diameter/tan(theta) ) ) - diameter/tan(theta);

              t = ( 1.0 - sqrt( 1.0 - sqr( 2*vpos[0]/diameter - 1.0 ) ) ) * diameter/(2.0*pka->dir[1]);

              // if we start beyond wire length (that would be inside the substrate) then retry
            } while( t*pka->dir[2] + vpos[2] >= length );

            // if first intersection with cylinder is at z<0 then check if we hit the top face instead
            if( t*pka->dir[2] + vpos[2] < 0.0 )
              t = -vpos[2]/pka->dir[2];

            // start PKA at calculated intersection point
            for( int i = 0; i < 3; i++ )
                pka->pos[i] = t*pka->dir[i] + vpos[i];

          } while( sample->lookupMaterial(pka->pos ) == 0 );
        }
      }
      //cout << "START " << pka->pos[0] << ' ' << pka->pos[1] << ' ' << pka->pos[2] << ' ' << endl;
      //continue;

      pka->set_ef();
      recoils.push( pka );

      while( !recoils.empty() )
      {
        pka = recoils.front();
        recoils.pop();
        sample->averages( pka );

        // do ion analysis/processing BEFORE the cascade here

        if( pka->z1 == ion_prototype[s]->z1  )
        {
          //printf(  "p1 %f\t%f\t%f\n", pka->pos[0], pka->pos[1], pka->pos[2] );
        }

        // follow this ion's trajectory and store recoils
        trim->trim( pka, recoils );

        // do ion analysis/processing AFTER the cascade here

        // ion is in the wire
        if(  sample->lookupMaterial( pka->pos ) == sample->material[0] )
        {
          xyz_data << simconf->scoef[pka->z1-1].sym << ' '
                   << pka->pos[0]/100.0 << ' ' << pka->pos[1]/100.0 << ' ' << pka->pos[2]/100.0 << endl;
          xyz_lines++;

          int l = pka->pos[2] / dl;
          if( l >=0 && l < lx ) lbins[ pka->z1 == 5 ? 0 : 1 ][l]++;
        }

        // done with this recoil
        delete pka;
      }
    }
  }

  // write xyz file
  stringstream xyz_name;
  xyz_name << argv[1] << ".xyz";
  ofstream xyz( xyz_name.str().c_str() );
  xyz << xyz_lines << endl << endl << xyz_data.str();
  xyz.close();

  // write lbins file (atoms per nm wire length)
  stringstream ldat_name;
  ldat_name << argv[1] << ".ldat";
  ofstream ldat( ldat_name.str().c_str() );
  for( int l = 0; l < lx; ++l )
    ldat << l*dl << ' ' << lbins[0][l]/(mult*0.1*dl) << ' ' << lbins[1][l]/(mult*0.1*dl) << endl;
  ldat.close();

  delete[] lbins[0];
  delete[] lbins[1];

  return EXIT_SUCCESS;
}
<commit_msg>output concentration per nm^3<commit_after>/***************************************************************************
 *   Copyright (C) 2008 by Daniel Schwen   *
 *   daniel@schwen.de   *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 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 General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include <stdio.h>
#include <stdlib.h>
#include <queue>
#include <iostream>
#include <fstream>
#include <sstream>

#include "simconf.h"
#include "element.h"
#include "material.h"
#include "sample_wire.h"
#include "sample_burried_wire.h"
#include "ion.h"
#include "trim.h"
#include "invert.h"
#include <r250.h>

#include "functions.h"

using namespace std;

int main(int argc, char *argv[])
{
  char fname[200];
  if( argc != 6 )
  {
    cerr << "syntax: " << argv[0] << " basename angle[deg] diameter(nm) burried[0,1] numbermultiplier" << endl;
    return 1;
  }

  double theta = atof(argv[2]) * M_PI/180.0; // 0 = parallel to wire
  double diameter  = 10.0*atof(argv[3]);
  double length  = 11000.0; // 1.1 mu
  bool burried = ( atoi(argv[4]) != 0 );
  double mult = atof(argv[5]);

  // ion series
  const int nstep = 5;
  double ion_dose[nstep] = { 3.0e13, 2.2e13, 1.5e13, 1.2e13, 2.5e13 }; // in ions/cm^2
  int ion_count[nstep];
  ionBase* ion_prototype[nstep];
  ion_prototype[0] = new ionBase(  5, 11.0 , 320.0e3 ); // Z,m,E
  ion_prototype[1] = new ionBase(  5, 11.0 , 220.0e3 ); // Z,m,E
  ion_prototype[2] = new ionBase(  5, 11.0 , 160.0e3 ); // Z,m,E
  ion_prototype[3] = new ionBase(  5, 11.0 , 120.0e3 ); // Z,m,E
  ion_prototype[4] = new ionBase( 15, 31.0 , 250.0e3 ); // Z,m,E

  // seed randomnumber generator from system entropy pool
  FILE *urand = fopen( "/dev/random", "r" );
  int seed;
  fread( &seed, sizeof(int), 1, urand );
  fclose( urand );
  r250_init( seed<0 ? -seed : seed ); // random generator goes haywire with neg. seed

  // initialize global parameter structure and read data tables from file
  simconf = new simconfType;

  // initialize sample structure
  sampleWire *sample;
  if( burried )
    sample = new sampleBurriedWire( diameter, diameter, length );
  else
  {
    sample = new sampleWire( diameter, diameter, length );
    sample->bc[2] = sampleWire::CUT;
  }

  // calculate actual ion numbers
  for( int s = 0; s < nstep; ++s )
  {
    double A; // irradiated area in Ang^2
    if( burried )
      A =( 2.0*length + sample->w[0] ) * ( 2.0*length + sample->w[1] );
    else
      A = cos(theta) * M_PI * 0.25 * sample->w[0] * sample->w[1] + //   slanted top face
          sin(theta) * length * sample->w[0];                      // + projected side

    // 1cm^2 = 1e16 Ang**2, 1Ang^2 = 1e-16cm^2
    ion_count[s] = ion_dose[s] * A * 1.0e-16 * mult;
    cerr << "Ion " << s << ' ' << ion_count[s] << endl;
  }

  // initialize trim engine for the sample
/*  const int z1 = 31;
  const int z2 = 33;
  trimVacMap *trim = new trimVacMap( sample, z1, z2 ); // GaAs*/
  //trimBase *trim = new trimBase( sample );
  trimBase *trim = new trimPrimaries( sample );

  materialBase *material;
  elementBase *element;

  // Si
  material = new materialBase( 2.329 ); // rho
  element = new elementBase;
  element->z = 14; // Si
  element->m = 28.0;
  element->t = 1.0;
  material->element.push_back( element );
  material->prepare(); // all materials added
  sample->material.push_back( material ); // add material to sample

  // SiO2 (material[1] for the cover layer in SampleBurriedWire)
  material = new materialBase( 2.634 ); // rho
  element = new elementBase;
  element->z = 14; // Si
  element->m = 28.0;
  element->t = 1.0;
  material->element.push_back( element );
  element = new elementBase;
  element->z = 8; // O
  element->m = 16.0;
  element->t = 2.0;
  material->element.push_back( element );
  material->prepare(); // all materials added
  sample->material.push_back( material ); // add material to sample

  // create a FIFO for recoils
  queue<ionBase*> recoils;

  double norm;
  double jmp = 2.7; // diffusion jump distance
  int jumps;
  double dif[3];

  //snprintf( fname, 199, "%s.Erec", argv[1] );
  //FILE *erec = fopen( fname, "wt" );

  //snprintf( fname, 199, "%s.dist", argv[1] );
  //FILE *rdist = fopen( fname, "wt" );

  ionBase *pka;

  // map concentration along length
  int *lbins[2];
  int lx = 100; // 100 bins
  int dl = length/double(lx);
  lbins[1] = new int[lx]; // P z=15
  for( int i = 0; i < 2; ++i )
  {
    lbins[i] = new int[lx]; // 0=B (z=5), 1=P (z=15)
    for( int l = 0; l < lx; ++l )
      lbins[i][l] = 0;
  }

  // xyz data
  int xyz_lines = 0;
  stringstream xyz_data;

  for( int s = 0; s < nstep; ++s )
  {
    for( int n = 0; n < ion_count[s]; ++n )
    {
      if( n % 10000 == 0 )
        cerr << "pka #" << n+1 << endl;

      // generate new PKA from prototype ion
      pka = new ionBase( ion_prototype[s] );
      pka->gen = 0; // generation (0 = PKA)
      pka->tag = -1;
      pka->md = 0;

      pka->dir[0] = 0.0;
      pka->dir[1] = sin( theta );
      pka->dir[2] = cos( theta );

      v_norm( pka->dir );

      if( burried )
      {
        // cannot anticipate the straggling in the burrial layer, thus have to shoot onto a big surface
        // TODO: take theta into account!
        pka->pos[0] = dr250() * ( 2.0*length + sample->w[0] ) - ( length + 0.5 * sample->w[0] ) ;
        pka->pos[1] = dr250() * ( 2.0*length + sample->w[1] ) - ( length + 0.5 * sample->w[1] ) ;
        pka->pos[2] = -250.0; // overcoat thickness
      }
      else
      {
        if( theta == 0.0 )
        {
          // 0 degrees => start on top of wire!
          pka->pos[2] = 0.0;
          do
          {
            pka->pos[0] = dr250() * sample->w[0];
            pka->pos[1] = dr250() * sample->w[1];
          } while( sample->lookupMaterial(pka->pos ) == 0 );
        }
        else
        {
          // start on side _or_ top!
          double vpos[3], t;
          do
          {
            do
            {
              vpos[0] = dr250() * sample->w[0];
              vpos[1] = 0.0;
              vpos[2] = ( dr250() * ( length + diameter/tan(theta) ) ) - diameter/tan(theta);

              t = ( 1.0 - sqrt( 1.0 - sqr( 2*vpos[0]/diameter - 1.0 ) ) ) * diameter/(2.0*pka->dir[1]);

              // if we start beyond wire length (that would be inside the substrate) then retry
            } while( t*pka->dir[2] + vpos[2] >= length );

            // if first intersection with cylinder is at z<0 then check if we hit the top face instead
            if( t*pka->dir[2] + vpos[2] < 0.0 )
              t = -vpos[2]/pka->dir[2];

            // start PKA at calculated intersection point
            for( int i = 0; i < 3; i++ )
                pka->pos[i] = t*pka->dir[i] + vpos[i];

          } while( sample->lookupMaterial(pka->pos ) == 0 );
        }
      }
      //cout << "START " << pka->pos[0] << ' ' << pka->pos[1] << ' ' << pka->pos[2] << ' ' << endl;
      //continue;

      pka->set_ef();
      recoils.push( pka );

      while( !recoils.empty() )
      {
        pka = recoils.front();
        recoils.pop();
        sample->averages( pka );

        // do ion analysis/processing BEFORE the cascade here

        if( pka->z1 == ion_prototype[s]->z1  )
        {
          //printf(  "p1 %f\t%f\t%f\n", pka->pos[0], pka->pos[1], pka->pos[2] );
        }

        // follow this ion's trajectory and store recoils
        trim->trim( pka, recoils );

        // do ion analysis/processing AFTER the cascade here

        // ion is in the wire
        if(  sample->lookupMaterial( pka->pos ) == sample->material[0] )
        {
          xyz_data << simconf->scoef[pka->z1-1].sym << ' '
                   << pka->pos[0]/100.0 << ' ' << pka->pos[1]/100.0 << ' ' << pka->pos[2]/100.0 << endl;
          xyz_lines++;

          int l = pka->pos[2] / dl;
          if( l >=0 && l < lx ) lbins[ pka->z1 == 5 ? 0 : 1 ][l]++;
        }

        // done with this recoil
        delete pka;
      }
    }
  }

  // write xyz file
  stringstream xyz_name;
  xyz_name << argv[1] << ".xyz";
  ofstream xyz( xyz_name.str().c_str() );
  xyz << xyz_lines << endl << endl << xyz_data.str();
  xyz.close();

  // write lbins file (atoms per nm^3)
  stringstream ldat_name;
  ldat_name << argv[1] << ".ldat";
  ofstream ldat( ldat_name.str().c_str() );
  double dv = 1e-3 * dl * M_PI * 0.25 *sample->w[0] * sample->w[1]; // volume per bin in nm^3
  for( int l = 0; l < lx; ++l )
    ldat << l*dl << ' ' << lbins[0][l]/(mult*dv) << ' ' << lbins[1][l]/(mult*dv) << endl;
  ldat.close();

  delete[] lbins[0];
  delete[] lbins[1];

  return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>/***************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact:  Qt Software Information (qt-info@nokia.com)
**
**
** Non-Open Source Usage
**
** Licensees may use this file in accordance with the Qt Beta Version
** License Agreement, Agreement version 2.2 provided with the Software or,
** alternatively, in accordance with the terms contained in a written
** agreement between you and Nokia.
**
** GNU General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU General
** Public License versions 2.0 or 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the packaging
** of this file.  Please review the following information to ensure GNU
** General Public Licensing requirements will be met:
**
** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
** http://www.gnu.org/copyleft/gpl.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt GPL Exception
** version 1.3, included in the file GPL_EXCEPTION.txt in this package.
**
***************************************************************************/

#include "LookupContext.h"
#include "ResolveExpression.h"
#include "Overview.h"

#include <CoreTypes.h>
#include <Symbols.h>
#include <Literals.h>
#include <Names.h>
#include <Scope.h>
#include <Control.h>

#include <QtDebug>

using namespace CPlusPlus;

bool LookupContext::isNameCompatibleWithIdentifier(Name *name, Identifier *id)
{
    if (! name) {
        return false;
    } else if (NameId *nameId = name->asNameId()) {
        Identifier *identifier = nameId->identifier();
        return identifier->isEqualTo(id);
    } else if (DestructorNameId *nameId = name->asDestructorNameId()) {
        Identifier *identifier = nameId->identifier();
        return identifier->isEqualTo(id);
    } else if (TemplateNameId *templNameId = name->asTemplateNameId()) {
        Identifier *identifier = templNameId->identifier();
        return identifier->isEqualTo(id);
    }

    return false;
}

/////////////////////////////////////////////////////////////////////
// LookupContext
/////////////////////////////////////////////////////////////////////
LookupContext::LookupContext(Control *control)
    : _control(control),
      _symbol(0)
{ }

LookupContext::LookupContext(Symbol *symbol,
                             Document::Ptr expressionDocument,
                             Document::Ptr thisDocument,
                             const Snapshot &documents)
    : _symbol(symbol),
      _expressionDocument(expressionDocument),
      _thisDocument(thisDocument),
      _documents(documents)
{
    _control = _expressionDocument->control();
    _visibleScopes = buildVisibleScopes();
}

LookupContext::LookupContext(Symbol *symbol,
                             const LookupContext &context)
    : _control(context._control),
      _symbol(symbol),
      _expressionDocument(context._expressionDocument),
      _documents(context._documents)
{
    const QString fn = QString::fromUtf8(symbol->fileName(), symbol->fileNameLength());
    _thisDocument = _documents.value(fn);
    _visibleScopes = buildVisibleScopes();
}

LookupContext::LookupContext(Symbol *symbol,
              Document::Ptr thisDocument,
              const LookupContext &context)
    : _control(context._control),
      _symbol(symbol),
      _expressionDocument(context._expressionDocument),
      _thisDocument(thisDocument),
      _documents(context._documents)
{
    _visibleScopes = buildVisibleScopes();
}

bool LookupContext::isValid() const
{ return _control != 0; }

LookupContext::operator bool() const
{ return _control != 0; }

Control *LookupContext::control() const
{ return _control; }

Symbol *LookupContext::symbol() const
{ return _symbol; }

Document::Ptr LookupContext::expressionDocument() const
{ return _expressionDocument; }

Document::Ptr LookupContext::thisDocument() const
{ return _thisDocument; }

Document::Ptr LookupContext::document(const QString &fileName) const
{ return _documents.value(fileName); }

Identifier *LookupContext::identifier(Name *name) const
{
    if (NameId *nameId = name->asNameId())
        return nameId->identifier();
    else if (TemplateNameId *templId = name->asTemplateNameId())
        return templId->identifier();
    else if (DestructorNameId *dtorId = name->asDestructorNameId())
        return dtorId->identifier();
    else if (QualifiedNameId *q = name->asQualifiedNameId())
        return identifier(q->unqualifiedNameId());
    return 0;
}

bool LookupContext::maybeValidSymbol(Symbol *symbol,
                                     ResolveMode mode,
                                     const QList<Symbol *> &candidates)
{
    if (((mode & ResolveNamespace) && symbol->isNamespace()) ||
        ((mode & ResolveClass)     && symbol->isClass())     ||
         (mode & ResolveSymbol)) {
        return ! candidates.contains(symbol);
    }

    return false;
}

QList<Symbol *> LookupContext::resolve(Name *name, const QList<Scope *> &visibleScopes,
                                       ResolveMode mode) const
{
    if (QualifiedNameId *q = name->asQualifiedNameId()) {
        QList<Symbol *> candidates;
        QList<Scope *> scopes = visibleScopes;
        for (unsigned i = 0; i < q->nameCount(); ++i) {
            Name *name = q->nameAt(i);

            if (i + 1 == q->nameCount())
                candidates = resolve(name, scopes, mode);
            else
                candidates = resolveClassOrNamespace(name, scopes);

            if (candidates.isEmpty() || i + 1 == q->nameCount())
                break;

            scopes.clear();
            foreach (Symbol *candidate, candidates) {
                if (ScopedSymbol *scoped = candidate->asScopedSymbol()) {
                    expand(scoped->members(), visibleScopes, &scopes);
                }
            }
        }

        Identifier *id = identifier(name);
        foreach (Scope *scope, visibleScopes) {
            Symbol *symbol = scope->lookat(id);
            for (; symbol; symbol = symbol->next()) {
                if (! symbol->name())
                    continue;
                else if (! maybeValidSymbol(symbol, mode, candidates))
                    continue;
                QualifiedNameId *qq = symbol->name()->asQualifiedNameId();
                if (! qq)
                    continue;
                if (q->nameCount() > qq->nameCount())
                    continue;

                for (int i = q->nameCount() - 1; i != -1; --i) {
                    Name *a = q->nameAt(i);
                    Name *b = qq->nameAt(i);

                    if (! a->isEqualTo(b))
                        break;
                    else if (i == 0)
                        candidates.append(symbol);
                }
            }
        }

        return candidates;
    }

    QList<Symbol *> candidates;
    if (Identifier *id = identifier(name)) {
        for (int scopeIndex = 0; scopeIndex < visibleScopes.size(); ++scopeIndex) {
            Scope *scope = visibleScopes.at(scopeIndex);
            for (Symbol *symbol = scope->lookat(id); symbol; symbol = symbol->next()) {
                if (! symbol->name()) {
                    continue;
                } else if (! maybeValidSymbol(symbol, mode, candidates)) {
                    continue;
                } else if (QualifiedNameId *q = symbol->name()->asQualifiedNameId()) {
                    if (! q->unqualifiedNameId()->isEqualTo(name))
                        continue;

                    if (q->nameCount() > 1) {
                        Name *classOrNamespaceName =
                                control()->qualifiedNameId(q->names(),
                                                           q->nameCount() - 1);

                        const QList<Symbol *> resolvedClassOrNamespace =
                                resolveClassOrNamespace(classOrNamespaceName, visibleScopes);

                        bool good = false;
                        foreach (Symbol *classOrNamespace, resolvedClassOrNamespace) {
                            ScopedSymbol *scoped = classOrNamespace->asScopedSymbol();
                            if (visibleScopes.contains(scoped->members())) {
                                good = true;
                                break;
                            }
                        }

                        if (! good)
                            continue;
                    }
                } else if (! isNameCompatibleWithIdentifier(symbol->name(), id)) {
                    continue;
                } else if (symbol->name()->isDestructorNameId() != name->isDestructorNameId()) {
                    continue;
                }

                candidates.append(symbol);
            }
        }
    } else if (OperatorNameId *opId = name->asOperatorNameId()) {
        for (int scopeIndex = 0; scopeIndex < visibleScopes.size(); ++scopeIndex) {
            Scope *scope = visibleScopes.at(scopeIndex);
            for (Symbol *symbol = scope->lookat(opId->kind()); symbol; symbol = symbol->next()) {
                if (! opId->isEqualTo(symbol->name()))
                    continue;
                else if (! candidates.contains(symbol))
                    candidates.append(symbol);
            }
        }
    }

    return candidates;
}

QList<Scope *> LookupContext::buildVisibleScopes()
{
    QList<Scope *> scopes;

    if (_symbol) {
        for (Scope *scope = _symbol->scope(); scope; scope = scope->enclosingScope()) {
            scopes.append(scope);
        }
    }

    QSet<QString> processed;
    processed.insert(_thisDocument->fileName());

    QList<QString> todo = _thisDocument->includedFiles();
    while (! todo.isEmpty()) {
        QString fn = todo.last();
        todo.removeLast();

        if (processed.contains(fn))
            continue;

        processed.insert(fn);
        if (Document::Ptr doc = document(fn)) {
            scopes.append(doc->globalNamespace()->members());
            todo += doc->includedFiles();
        }
    }

    while (true) {
        QList<Scope *> expandedScopes;
        expand(scopes, &expandedScopes);

        if (expandedScopes.size() == scopes.size())
            return expandedScopes;

        scopes = expandedScopes;
    }

    return scopes;
}

QList<Scope *> LookupContext::visibleScopes(const QPair<FullySpecifiedType, Symbol *> &result) const
{
    Symbol *symbol = result.second;
    QList<Scope *> scopes;
    for (Scope *scope = symbol->scope(); scope; scope = scope->enclosingScope())
        scopes.append(scope);
    scopes += visibleScopes();
    scopes = expand(scopes);
    return scopes;
}

QList<Scope *> LookupContext::expand(const QList<Scope *> &scopes) const
{
    QList<Scope *> expanded;
    expand(scopes, &expanded);
    return expanded;
}

void LookupContext::expand(const QList<Scope *> &scopes, QList<Scope *> *expandedScopes) const
{
    for (int i = 0; i < scopes.size(); ++i) {
        expand(scopes.at(i), scopes, expandedScopes);
    }
}

void LookupContext::expandNamespace(Scope *scope,
                                    const QList<Scope *> &visibleScopes,
                                    QList<Scope *> *expandedScopes) const
{
    Namespace *ns = scope->owner()->asNamespace();
    if (! ns)
        return;

    if (Name *nsName = ns->name()) {
        const QList<Symbol *> namespaceList = resolveNamespace(nsName, visibleScopes);
        foreach (Symbol *otherNs, namespaceList) {
            if (otherNs == ns)
                continue;
            expand(otherNs->asNamespace()->members(), visibleScopes, expandedScopes);
        }
    }

    for (unsigned i = 0; i < scope->symbolCount(); ++i) { // ### make me fast
        Symbol *symbol = scope->symbolAt(i);
        if (Namespace *ns = symbol->asNamespace()) {
            if (! ns->name()) {
                expand(ns->members(), visibleScopes, expandedScopes);
            }
        } else if (UsingNamespaceDirective *u = symbol->asUsingNamespaceDirective()) {
            const QList<Symbol *> candidates = resolveNamespace(u->name(), visibleScopes);
            for (int j = 0; j < candidates.size(); ++j) {
                expand(candidates.at(j)->asNamespace()->members(),
                       visibleScopes, expandedScopes);
            }
        } else if (Enum *e = symbol->asEnum()) {
            expand(e->members(), visibleScopes, expandedScopes);
        }
    }
}

void LookupContext::expandClass(Scope *scope,
                                const QList<Scope *> &visibleScopes,
                                QList<Scope *> *expandedScopes) const
{
    Class *klass = scope->owner()->asClass();
    if (! klass)
        return;

    for (unsigned i = 0; i < scope->symbolCount(); ++i) {
        Symbol *symbol = scope->symbolAt(i);
        if (Class *nestedClass = symbol->asClass()) {
            if (! nestedClass->name()) {
                expand(nestedClass->members(), visibleScopes, expandedScopes);
            }
        } else if (Enum *e = symbol->asEnum()) {
            expand(e->members(), visibleScopes, expandedScopes);
        }
    }

    if (klass->baseClassCount()) {
        QList<Scope *> classVisibleScopes = visibleScopes;
        for (Scope *scope = klass->scope(); scope; scope = scope->enclosingScope()) {
            if (scope->isNamespaceScope()) {
                Namespace *enclosingNamespace = scope->owner()->asNamespace();
                if (enclosingNamespace->name()) {
                    const QList<Symbol *> nsList = resolveNamespace(enclosingNamespace->name(),
                                                                    visibleScopes);
                    foreach (Symbol *ns, nsList) {
                        expand(ns->asNamespace()->members(), classVisibleScopes,
                               &classVisibleScopes);
                    }
                }
            }
        }

        for (unsigned i = 0; i < klass->baseClassCount(); ++i) {
            BaseClass *baseClass = klass->baseClassAt(i);
            Name *baseClassName = baseClass->name();
            const QList<Symbol *> baseClassCandidates = resolveClass(baseClassName,
                                                                     classVisibleScopes);
            if (baseClassCandidates.isEmpty()) {
                Overview overview;
                qDebug() << "unresolved base class:" << overview.prettyName(baseClassName);
            }

            for (int j = 0; j < baseClassCandidates.size(); ++j) {
                if (Class *baseClassSymbol = baseClassCandidates.at(j)->asClass())
                    expand(baseClassSymbol->members(), visibleScopes, expandedScopes);
            }
        }
    }
}

void LookupContext::expandBlock(Scope *scope,
                                const QList<Scope *> &visibleScopes,
                                QList<Scope *> *expandedScopes) const
{
    for (unsigned i = 0; i < scope->symbolCount(); ++i) {
        Symbol *symbol = scope->symbolAt(i);
        if (UsingNamespaceDirective *u = symbol->asUsingNamespaceDirective()) {
            const QList<Symbol *> candidates = resolveNamespace(u->name(),
                                                                visibleScopes);
            for (int j = 0; j < candidates.size(); ++j) {
                expand(candidates.at(j)->asNamespace()->members(),
                       visibleScopes, expandedScopes);
            }
        }

    }
}

void LookupContext::expandFunction(Scope *scope,
                                   const QList<Scope *> &visibleScopes,
                                   QList<Scope *> *expandedScopes) const
{
    Function *function = scope->owner()->asFunction();
    if (! expandedScopes->contains(function->arguments()))
        expandedScopes->append(function->arguments());
    if (QualifiedNameId *q = function->name()->asQualifiedNameId()) {
        Name *nestedNameSpec = 0;
        if (q->nameCount() == 1 && q->isGlobal())
            nestedNameSpec = q->nameAt(0);
        else
            nestedNameSpec = control()->qualifiedNameId(q->names(), q->nameCount() - 1,
                                                        q->isGlobal());
        const QList<Symbol *> candidates = resolveClassOrNamespace(nestedNameSpec, visibleScopes);
        for (int j = 0; j < candidates.size(); ++j) {
            expand(candidates.at(j)->asScopedSymbol()->members(),
                   visibleScopes, expandedScopes);
        }
    }
}

void LookupContext::expand(Scope *scope,
                           const QList<Scope *> &visibleScopes,
                           QList<Scope *> *expandedScopes) const
{
    if (expandedScopes->contains(scope))
        return;

    expandedScopes->append(scope);

    if (scope->isNamespaceScope()) {
        expandNamespace(scope, visibleScopes, expandedScopes);
    } else if (scope->isClassScope()) {
        expandClass(scope, visibleScopes, expandedScopes);
    } else if (scope->isBlockScope()) {
        expandBlock(scope, visibleScopes, expandedScopes);
    } else if (scope->isFunctionScope()) {
        expandFunction(scope, visibleScopes, expandedScopes);
    } else if (scope->isPrototypeScope()) {
        //qDebug() << "prototype scope" << overview.prettyName(scope->owner()->name());
    }
}
<commit_msg>Fixed crash in lookup context due to null-name<commit_after>/***************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact:  Qt Software Information (qt-info@nokia.com)
**
**
** Non-Open Source Usage
**
** Licensees may use this file in accordance with the Qt Beta Version
** License Agreement, Agreement version 2.2 provided with the Software or,
** alternatively, in accordance with the terms contained in a written
** agreement between you and Nokia.
**
** GNU General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU General
** Public License versions 2.0 or 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the packaging
** of this file.  Please review the following information to ensure GNU
** General Public Licensing requirements will be met:
**
** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
** http://www.gnu.org/copyleft/gpl.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt GPL Exception
** version 1.3, included in the file GPL_EXCEPTION.txt in this package.
**
***************************************************************************/

#include "LookupContext.h"
#include "ResolveExpression.h"
#include "Overview.h"

#include <CoreTypes.h>
#include <Symbols.h>
#include <Literals.h>
#include <Names.h>
#include <Scope.h>
#include <Control.h>

#include <QtDebug>

using namespace CPlusPlus;

bool LookupContext::isNameCompatibleWithIdentifier(Name *name, Identifier *id)
{
    if (! name) {
        return false;
    } else if (NameId *nameId = name->asNameId()) {
        Identifier *identifier = nameId->identifier();
        return identifier->isEqualTo(id);
    } else if (DestructorNameId *nameId = name->asDestructorNameId()) {
        Identifier *identifier = nameId->identifier();
        return identifier->isEqualTo(id);
    } else if (TemplateNameId *templNameId = name->asTemplateNameId()) {
        Identifier *identifier = templNameId->identifier();
        return identifier->isEqualTo(id);
    }

    return false;
}

/////////////////////////////////////////////////////////////////////
// LookupContext
/////////////////////////////////////////////////////////////////////
LookupContext::LookupContext(Control *control)
    : _control(control),
      _symbol(0)
{ }

LookupContext::LookupContext(Symbol *symbol,
                             Document::Ptr expressionDocument,
                             Document::Ptr thisDocument,
                             const Snapshot &documents)
    : _symbol(symbol),
      _expressionDocument(expressionDocument),
      _thisDocument(thisDocument),
      _documents(documents)
{
    _control = _expressionDocument->control();
    _visibleScopes = buildVisibleScopes();
}

LookupContext::LookupContext(Symbol *symbol,
                             const LookupContext &context)
    : _control(context._control),
      _symbol(symbol),
      _expressionDocument(context._expressionDocument),
      _documents(context._documents)
{
    const QString fn = QString::fromUtf8(symbol->fileName(), symbol->fileNameLength());
    _thisDocument = _documents.value(fn);
    _visibleScopes = buildVisibleScopes();
}

LookupContext::LookupContext(Symbol *symbol,
              Document::Ptr thisDocument,
              const LookupContext &context)
    : _control(context._control),
      _symbol(symbol),
      _expressionDocument(context._expressionDocument),
      _thisDocument(thisDocument),
      _documents(context._documents)
{
    _visibleScopes = buildVisibleScopes();
}

bool LookupContext::isValid() const
{ return _control != 0; }

LookupContext::operator bool() const
{ return _control != 0; }

Control *LookupContext::control() const
{ return _control; }

Symbol *LookupContext::symbol() const
{ return _symbol; }

Document::Ptr LookupContext::expressionDocument() const
{ return _expressionDocument; }

Document::Ptr LookupContext::thisDocument() const
{ return _thisDocument; }

Document::Ptr LookupContext::document(const QString &fileName) const
{ return _documents.value(fileName); }

Identifier *LookupContext::identifier(Name *name) const
{
    if (NameId *nameId = name->asNameId())
        return nameId->identifier();
    else if (TemplateNameId *templId = name->asTemplateNameId())
        return templId->identifier();
    else if (DestructorNameId *dtorId = name->asDestructorNameId())
        return dtorId->identifier();
    else if (QualifiedNameId *q = name->asQualifiedNameId())
        return identifier(q->unqualifiedNameId());
    return 0;
}

bool LookupContext::maybeValidSymbol(Symbol *symbol,
                                     ResolveMode mode,
                                     const QList<Symbol *> &candidates)
{
    if (((mode & ResolveNamespace) && symbol->isNamespace()) ||
        ((mode & ResolveClass)     && symbol->isClass())     ||
         (mode & ResolveSymbol)) {
        return ! candidates.contains(symbol);
    }

    return false;
}

QList<Symbol *> LookupContext::resolve(Name *name, const QList<Scope *> &visibleScopes,
                                       ResolveMode mode) const
{
    QList<Symbol *> candidates;

    if (!name)
        return candidates;

    if (QualifiedNameId *q = name->asQualifiedNameId()) {
        QList<Scope *> scopes = visibleScopes;
        for (unsigned i = 0; i < q->nameCount(); ++i) {
            Name *name = q->nameAt(i);

            if (i + 1 == q->nameCount())
                candidates = resolve(name, scopes, mode);
            else
                candidates = resolveClassOrNamespace(name, scopes);

            if (candidates.isEmpty() || i + 1 == q->nameCount())
                break;

            scopes.clear();
            foreach (Symbol *candidate, candidates) {
                if (ScopedSymbol *scoped = candidate->asScopedSymbol()) {
                    expand(scoped->members(), visibleScopes, &scopes);
                }
            }
        }

        Identifier *id = identifier(name);
        foreach (Scope *scope, visibleScopes) {
            Symbol *symbol = scope->lookat(id);
            for (; symbol; symbol = symbol->next()) {
                if (! symbol->name())
                    continue;
                else if (! maybeValidSymbol(symbol, mode, candidates))
                    continue;
                QualifiedNameId *qq = symbol->name()->asQualifiedNameId();
                if (! qq)
                    continue;
                if (q->nameCount() > qq->nameCount())
                    continue;

                for (int i = q->nameCount() - 1; i != -1; --i) {
                    Name *a = q->nameAt(i);
                    Name *b = qq->nameAt(i);

                    if (! a->isEqualTo(b))
                        break;
                    else if (i == 0)
                        candidates.append(symbol);
                }
            }
        }

        return candidates;
    }

    if (Identifier *id = identifier(name)) {
        for (int scopeIndex = 0; scopeIndex < visibleScopes.size(); ++scopeIndex) {
            Scope *scope = visibleScopes.at(scopeIndex);
            for (Symbol *symbol = scope->lookat(id); symbol; symbol = symbol->next()) {
                if (! symbol->name()) {
                    continue;
                } else if (! maybeValidSymbol(symbol, mode, candidates)) {
                    continue;
                } else if (QualifiedNameId *q = symbol->name()->asQualifiedNameId()) {
                    if (! q->unqualifiedNameId()->isEqualTo(name))
                        continue;

                    if (q->nameCount() > 1) {
                        Name *classOrNamespaceName =
                                control()->qualifiedNameId(q->names(),
                                                           q->nameCount() - 1);

                        const QList<Symbol *> resolvedClassOrNamespace =
                                resolveClassOrNamespace(classOrNamespaceName, visibleScopes);

                        bool good = false;
                        foreach (Symbol *classOrNamespace, resolvedClassOrNamespace) {
                            ScopedSymbol *scoped = classOrNamespace->asScopedSymbol();
                            if (visibleScopes.contains(scoped->members())) {
                                good = true;
                                break;
                            }
                        }

                        if (! good)
                            continue;
                    }
                } else if (! isNameCompatibleWithIdentifier(symbol->name(), id)) {
                    continue;
                } else if (symbol->name()->isDestructorNameId() != name->isDestructorNameId()) {
                    continue;
                }

                candidates.append(symbol);
            }
        }
    } else if (OperatorNameId *opId = name->asOperatorNameId()) {
        for (int scopeIndex = 0; scopeIndex < visibleScopes.size(); ++scopeIndex) {
            Scope *scope = visibleScopes.at(scopeIndex);
            for (Symbol *symbol = scope->lookat(opId->kind()); symbol; symbol = symbol->next()) {
                if (! opId->isEqualTo(symbol->name()))
                    continue;
                else if (! candidates.contains(symbol))
                    candidates.append(symbol);
            }
        }
    }

    return candidates;
}

QList<Scope *> LookupContext::buildVisibleScopes()
{
    QList<Scope *> scopes;

    if (_symbol) {
        for (Scope *scope = _symbol->scope(); scope; scope = scope->enclosingScope()) {
            scopes.append(scope);
        }
    }

    QSet<QString> processed;
    processed.insert(_thisDocument->fileName());

    QList<QString> todo = _thisDocument->includedFiles();
    while (! todo.isEmpty()) {
        QString fn = todo.last();
        todo.removeLast();

        if (processed.contains(fn))
            continue;

        processed.insert(fn);
        if (Document::Ptr doc = document(fn)) {
            scopes.append(doc->globalNamespace()->members());
            todo += doc->includedFiles();
        }
    }

    while (true) {
        QList<Scope *> expandedScopes;
        expand(scopes, &expandedScopes);

        if (expandedScopes.size() == scopes.size())
            return expandedScopes;

        scopes = expandedScopes;
    }

    return scopes;
}

QList<Scope *> LookupContext::visibleScopes(const QPair<FullySpecifiedType, Symbol *> &result) const
{
    Symbol *symbol = result.second;
    QList<Scope *> scopes;
    for (Scope *scope = symbol->scope(); scope; scope = scope->enclosingScope())
        scopes.append(scope);
    scopes += visibleScopes();
    scopes = expand(scopes);
    return scopes;
}

QList<Scope *> LookupContext::expand(const QList<Scope *> &scopes) const
{
    QList<Scope *> expanded;
    expand(scopes, &expanded);
    return expanded;
}

void LookupContext::expand(const QList<Scope *> &scopes, QList<Scope *> *expandedScopes) const
{
    for (int i = 0; i < scopes.size(); ++i) {
        expand(scopes.at(i), scopes, expandedScopes);
    }
}

void LookupContext::expandNamespace(Scope *scope,
                                    const QList<Scope *> &visibleScopes,
                                    QList<Scope *> *expandedScopes) const
{
    Namespace *ns = scope->owner()->asNamespace();
    if (! ns)
        return;

    if (Name *nsName = ns->name()) {
        const QList<Symbol *> namespaceList = resolveNamespace(nsName, visibleScopes);
        foreach (Symbol *otherNs, namespaceList) {
            if (otherNs == ns)
                continue;
            expand(otherNs->asNamespace()->members(), visibleScopes, expandedScopes);
        }
    }

    for (unsigned i = 0; i < scope->symbolCount(); ++i) { // ### make me fast
        Symbol *symbol = scope->symbolAt(i);
        if (Namespace *ns = symbol->asNamespace()) {
            if (! ns->name()) {
                expand(ns->members(), visibleScopes, expandedScopes);
            }
        } else if (UsingNamespaceDirective *u = symbol->asUsingNamespaceDirective()) {
            const QList<Symbol *> candidates = resolveNamespace(u->name(), visibleScopes);
            for (int j = 0; j < candidates.size(); ++j) {
                expand(candidates.at(j)->asNamespace()->members(),
                       visibleScopes, expandedScopes);
            }
        } else if (Enum *e = symbol->asEnum()) {
            expand(e->members(), visibleScopes, expandedScopes);
        }
    }
}

void LookupContext::expandClass(Scope *scope,
                                const QList<Scope *> &visibleScopes,
                                QList<Scope *> *expandedScopes) const
{
    Class *klass = scope->owner()->asClass();
    if (! klass)
        return;

    for (unsigned i = 0; i < scope->symbolCount(); ++i) {
        Symbol *symbol = scope->symbolAt(i);
        if (Class *nestedClass = symbol->asClass()) {
            if (! nestedClass->name()) {
                expand(nestedClass->members(), visibleScopes, expandedScopes);
            }
        } else if (Enum *e = symbol->asEnum()) {
            expand(e->members(), visibleScopes, expandedScopes);
        }
    }

    if (klass->baseClassCount()) {
        QList<Scope *> classVisibleScopes = visibleScopes;
        for (Scope *scope = klass->scope(); scope; scope = scope->enclosingScope()) {
            if (scope->isNamespaceScope()) {
                Namespace *enclosingNamespace = scope->owner()->asNamespace();
                if (enclosingNamespace->name()) {
                    const QList<Symbol *> nsList = resolveNamespace(enclosingNamespace->name(),
                                                                    visibleScopes);
                    foreach (Symbol *ns, nsList) {
                        expand(ns->asNamespace()->members(), classVisibleScopes,
                               &classVisibleScopes);
                    }
                }
            }
        }

        for (unsigned i = 0; i < klass->baseClassCount(); ++i) {
            BaseClass *baseClass = klass->baseClassAt(i);
            Name *baseClassName = baseClass->name();
            const QList<Symbol *> baseClassCandidates = resolveClass(baseClassName,
                                                                     classVisibleScopes);
            if (baseClassCandidates.isEmpty()) {
                Overview overview;
                qDebug() << "unresolved base class:" << overview.prettyName(baseClassName);
            }

            for (int j = 0; j < baseClassCandidates.size(); ++j) {
                if (Class *baseClassSymbol = baseClassCandidates.at(j)->asClass())
                    expand(baseClassSymbol->members(), visibleScopes, expandedScopes);
            }
        }
    }
}

void LookupContext::expandBlock(Scope *scope,
                                const QList<Scope *> &visibleScopes,
                                QList<Scope *> *expandedScopes) const
{
    for (unsigned i = 0; i < scope->symbolCount(); ++i) {
        Symbol *symbol = scope->symbolAt(i);
        if (UsingNamespaceDirective *u = symbol->asUsingNamespaceDirective()) {
            const QList<Symbol *> candidates = resolveNamespace(u->name(),
                                                                visibleScopes);
            for (int j = 0; j < candidates.size(); ++j) {
                expand(candidates.at(j)->asNamespace()->members(),
                       visibleScopes, expandedScopes);
            }
        }

    }
}

void LookupContext::expandFunction(Scope *scope,
                                   const QList<Scope *> &visibleScopes,
                                   QList<Scope *> *expandedScopes) const
{
    Function *function = scope->owner()->asFunction();
    if (! expandedScopes->contains(function->arguments()))
        expandedScopes->append(function->arguments());
    if (QualifiedNameId *q = function->name()->asQualifiedNameId()) {
        Name *nestedNameSpec = 0;
        if (q->nameCount() == 1 && q->isGlobal())
            nestedNameSpec = q->nameAt(0);
        else
            nestedNameSpec = control()->qualifiedNameId(q->names(), q->nameCount() - 1,
                                                        q->isGlobal());
        const QList<Symbol *> candidates = resolveClassOrNamespace(nestedNameSpec, visibleScopes);
        for (int j = 0; j < candidates.size(); ++j) {
            expand(candidates.at(j)->asScopedSymbol()->members(),
                   visibleScopes, expandedScopes);
        }
    }
}

void LookupContext::expand(Scope *scope,
                           const QList<Scope *> &visibleScopes,
                           QList<Scope *> *expandedScopes) const
{
    if (expandedScopes->contains(scope))
        return;

    expandedScopes->append(scope);

    if (scope->isNamespaceScope()) {
        expandNamespace(scope, visibleScopes, expandedScopes);
    } else if (scope->isClassScope()) {
        expandClass(scope, visibleScopes, expandedScopes);
    } else if (scope->isBlockScope()) {
        expandBlock(scope, visibleScopes, expandedScopes);
    } else if (scope->isFunctionScope()) {
        expandFunction(scope, visibleScopes, expandedScopes);
    } else if (scope->isPrototypeScope()) {
        //qDebug() << "prototype scope" << overview.prettyName(scope->owner()->name());
    }
}
<|endoftext|>


<commit_before>#include <okui/applications/Native.h>
#include <okui/applications/SDL.h>
#include <okui/StateMachine.h>

class Application : public okui::applications::Native<okui::applications::SDL> {
public:
    virtual std::string name() const override { return "StateMachine Example"; }
    virtual std::string organization() const override { return "BitTorrent Inc."; }
};

struct State {
    double x, y, opacity;
    constexpr auto members() { return std::tie(x, y, opacity); }
};

class View : public okui::View, public okui::StateMachine<State> {
public:
    View() : okui::StateMachine<State>("Above") {
        addUpdateHook("StateMachine", [&]{ drive(); });
        setTransition("Above", "Normal", 200ms, okui::interpolation::Quadratic::EaseOut);
        setTransition("Normal", "Left", 200ms, okui::interpolation::Quadratic::EaseIn);
    }

private:
    virtual void update(stdts::string_view id, State& state, bool& isAnimated) override {
        state.opacity = id == "Normal" ? 1.0 : 0.0;
        state.x = id == "Left" ? -100.0 : 300.0;
        state.y = id == "Above" ? -100.0 : 300.0;
    }

    virtual void apply(const State& state) override {
        setOpacity(state.opacity);
        setBounds(state.x, state.y, 100.0, 100.0);
    }
};

int main() {
    Application application;

    okui::Window window{&application};
    window.open();

    View view;
    view.setBackgroundColor(okui::Color::kBlue);
    window.contentView()->addSubview(&view);

    view.asyncAfter(2s, [&] { view.setState("Normal"); });
    view.asyncAfter(4s, [&] { view.setState("Left"); });

    application.run();
    return 0;
}
<commit_msg>add final specifier to quiet analysis<commit_after>#include <okui/applications/Native.h>
#include <okui/applications/SDL.h>
#include <okui/StateMachine.h>

class Application : public okui::applications::Native<okui::applications::SDL> {
public:
    virtual std::string name() const override { return "StateMachine Example"; }
    virtual std::string organization() const override { return "BitTorrent Inc."; }
};

struct State {
    double x, y, opacity;
    constexpr auto members() { return std::tie(x, y, opacity); }
};

class View final : public okui::View, public okui::StateMachine<State> {
public:
    View() : okui::StateMachine<State>("Above") {
        addUpdateHook("StateMachine", [&]{ drive(); });
        setTransition("Above", "Normal", 200ms, okui::interpolation::Quadratic::EaseOut);
        setTransition("Normal", "Left", 200ms, okui::interpolation::Quadratic::EaseIn);
    }

private:
    virtual void update(stdts::string_view id, State& state, bool& isAnimated) override {
        state.opacity = id == "Normal" ? 1.0 : 0.0;
        state.x = id == "Left" ? -100.0 : 300.0;
        state.y = id == "Above" ? -100.0 : 300.0;
    }

    virtual void apply(const State& state) override {
        setOpacity(state.opacity);
        setBounds(state.x, state.y, 100.0, 100.0);
    }
};

int main() {
    Application application;

    okui::Window window{&application};
    window.open();

    View view;
    view.setBackgroundColor(okui::Color::kBlue);
    window.contentView()->addSubview(&view);

    view.asyncAfter(2s, [&] { view.setState("Normal"); });
    view.asyncAfter(4s, [&] { view.setState("Left"); });

    application.run();
    return 0;
}
<|endoftext|>


<commit_before>/*
    Generic Console Output Support
    Copyright (C) 1998-2001 by Jorrit Tyberghein
    Copyright (c) 2004-2005 by Frank Richter

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public
    License as published by the Free Software Foundation; either
    version 2 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Library General Public License for more details.

    You should have received a copy of the GNU Library General Public
    License along with this library; if not, write to the Free
    Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#include <stdarg.h>
#include <stdio.h>
#include "cssysdef.h"
#include "csutil/ansiparse.h"
#include "csutil/csstring.h"
#include "csutil/csuctransform.h"
#include "csutil/sysfunc.h"

// Replacement for printf(); exact same prototype/functionality as printf()
int csPrintf (char const* str, ...)
{
  va_list args;
  va_start (args, str);
  int const rc = csPrintfV (str, args);
  va_end (args);
  return rc;
}

static int cs_fputsn (FILE* file, const char* str, size_t len)
{
  size_t wstrSize = len + 1;
  CS_ALLOC_STACK_ARRAY(wchar_t, wstr, wstrSize);

  csUnicodeTransform::UTF8toWC (wstr, wstrSize, (utf8_char*)str, len);

  int n = 0;
  const wchar_t* wcsPtr = wstr;
#if defined(CS_HAVE_FPUTWS) && defined(CS_HAVE_FWIDE) \
  && defined(CS_HAVE_WCSRTOMBS)
  if (fwide (file, 0) > 0)
  {
    return fputws (wstr, file);
  }
  else
  {
    mbstate_t mbs;
    memset (&mbs, 0, sizeof (mbs));
    char mbstr[64];
    size_t mbslen;
    while (wcsPtr != 0)
    {
      memset (mbstr, 0, sizeof (mbstr));
      mbslen = wcsrtombs (mbstr, &wcsPtr, sizeof (mbstr) - 1, &mbs);
      if (mbslen == (size_t)-1)
      {
	if (errno == EILSEQ)
	{
	  // Catch char that couldn't be encoded, print ? instead
	  if (fputs (mbstr, file) == EOF) return EOF;
	  if (fputc ('?', file) == EOF) return EOF;
	  if (CS_UC_IS_HIGH_SURROGATE (*wcsPtr))
	  {
	    wcsPtr++;
	    if (CS_UC_IS_LOW_SURROGATE (*wcsPtr))
	      wcsPtr++;
	  }
	  else
	    wcsPtr++;
	  continue;
	}
	break;
      }
      if (fputs (mbstr, file) == EOF) return EOF;
    }
    if (wcsPtr == 0) return (int)len;
  }
#endif
  // Use a cheap Wide-to-ASCII conversion.
  const wchar_t* ch = wcsPtr;

  while (len-- > 0)
  {
    if (*ch < 0x80)
    {
      if (fputc ((char)*ch, file) == EOF) return EOF;
      n++;
    }
    else
    {
      if (fputc ('?', file) == EOF) return EOF;
      n++;
    }

    ch++;
  }

  return n;
}

static int csFPutStr (FILE* file, const char* str)
{
  bool isTTY = isatty (fileno (file));

  int ret = 0;
  size_t ansiCommandLen;
  csAnsiParser::CommandClass cmdClass;
  size_t textLen;
  // Check for ANSI codes
  while (csAnsiParser::ParseAnsi (str, ansiCommandLen, cmdClass, textLen))
  {
    int rc;
    if (isTTY && (cmdClass == csAnsiParser::classFormat))
    {
      // Only let formatting codes through
      rc = cs_fputsn (file, str, ansiCommandLen);
      if (rc == EOF)
	return EOF;
      ret += rc;
    }

    if (textLen > 0)
    {
      rc = cs_fputsn (file, str + ansiCommandLen, textLen);
      if (rc == EOF)
	return EOF;
      ret += rc;
    }

    str += ansiCommandLen + textLen;
  }
  return ret;
}

// Replacement for vprintf()
int csPrintfV(char const* str, va_list args)
{
  csString temp;
  temp.FormatV (str, args);

  return csFPutStr (stdout, temp);
}

int csFPrintf (FILE* file, const char* str, ...)
{
  va_list args;
  va_start (args, str);
  int const rc = csFPrintfV (file, str, args);
  va_end (args);
  return rc;
}

int csFPrintfV (FILE* file, const char* str, va_list args)
{
  csString temp;
  temp.FormatV (str, args);

  return csFPutStr (file, temp);
}

int csPrintfErrV (const char* str, va_list arg)
{
  int rc = csFPrintfV (stderr, str, arg);
  fflush (stderr);
  return rc;
}

int csPrintfErr (const char* str, ...)
{
  va_list args;
  va_start (args, str);
  int const rc = csFPrintfV (stderr, str, args);
  va_end (args);
  return rc;
}

<commit_msg>res made some tweaks to the lighter2 TUI to better work on Linux. res fixed the lighter2 tui and Win32 ANSI support for the fact that   cursor positions are 1-based, not 0-based.<commit_after>/*
    Generic Console Output Support
    Copyright (C) 1998-2001 by Jorrit Tyberghein
    Copyright (c) 2004-2005 by Frank Richter

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public
    License as published by the Free Software Foundation; either
    version 2 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Library General Public License for more details.

    You should have received a copy of the GNU Library General Public
    License along with this library; if not, write to the Free
    Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#include <stdarg.h>
#include <stdio.h>
#include "cssysdef.h"
#include "csutil/ansiparse.h"
#include "csutil/csstring.h"
#include "csutil/csuctransform.h"
#include "csutil/sysfunc.h"

// Replacement for printf(); exact same prototype/functionality as printf()
int csPrintf (char const* str, ...)
{
  va_list args;
  va_start (args, str);
  int const rc = csPrintfV (str, args);
  va_end (args);
  return rc;
}

static int cs_fputsn (FILE* file, const char* str, size_t len)
{
  size_t wstrSize = len + 1;
  CS_ALLOC_STACK_ARRAY(wchar_t, wstr, wstrSize);

  csUnicodeTransform::UTF8toWC (wstr, wstrSize, (utf8_char*)str, len);

  int n = 0;
  const wchar_t* wcsPtr = wstr;
#if defined(CS_HAVE_FPUTWS) && defined(CS_HAVE_FWIDE) \
  && defined(CS_HAVE_WCSRTOMBS)
  if (fwide (file, 0) > 0)
  {
    return fputws (wstr, file);
  }
  else
  {
    mbstate_t mbs;
    memset (&mbs, 0, sizeof (mbs));
    char mbstr[64];
    size_t mbslen;
    while (wcsPtr != 0)
    {
      memset (mbstr, 0, sizeof (mbstr));
      mbslen = wcsrtombs (mbstr, &wcsPtr, sizeof (mbstr) - 1, &mbs);
      if (mbslen == (size_t)-1)
      {
	if (errno == EILSEQ)
	{
	  // Catch char that couldn't be encoded, print ? instead
	  if (fputs (mbstr, file) == EOF) return EOF;
	  if (fputc ('?', file) == EOF) return EOF;
	  if (CS_UC_IS_HIGH_SURROGATE (*wcsPtr))
	  {
	    wcsPtr++;
	    if (CS_UC_IS_LOW_SURROGATE (*wcsPtr))
	      wcsPtr++;
	  }
	  else
	    wcsPtr++;
	  continue;
	}
	break;
      }
      if (fputs (mbstr, file) == EOF) return EOF;
    }
    if (wcsPtr == 0) return (int)len;
  }
#endif
  // Use a cheap Wide-to-ASCII conversion.
  const wchar_t* ch = wcsPtr;

  while (len-- > 0)
  {
    if (*ch < 0x80)
    {
      if (fputc ((char)*ch, file) == EOF) return EOF;
      n++;
    }
    else
    {
      if (fputc ('?', file) == EOF) return EOF;
      n++;
    }

    ch++;
  }

  return n;
}

static int csFPutStr (FILE* file, const char* str)
{
  bool isTTY = isatty (fileno (file));

  int ret = 0;
  size_t ansiCommandLen;
  csAnsiParser::CommandClass cmdClass;
  size_t textLen;
  // Check for ANSI codes
  while (csAnsiParser::ParseAnsi (str, ansiCommandLen, cmdClass, textLen))
  {
    int rc;
    if (isTTY && (cmdClass != csAnsiParser::classNone)
      && (cmdClass != csAnsiParser::classUnknown))
    {
      // Only let known codes through
      rc = cs_fputsn (file, str, ansiCommandLen);
      if (rc == EOF)
	return EOF;
      ret += rc;
    }

    if (textLen > 0)
    {
      rc = cs_fputsn (file, str + ansiCommandLen, textLen);
      if (rc == EOF)
	return EOF;
      ret += rc;
    }

    str += ansiCommandLen + textLen;
  }
  return ret;
}

// Replacement for vprintf()
int csPrintfV(char const* str, va_list args)
{
  csString temp;
  temp.FormatV (str, args);

  return csFPutStr (stdout, temp);
}

int csFPrintf (FILE* file, const char* str, ...)
{
  va_list args;
  va_start (args, str);
  int const rc = csFPrintfV (file, str, args);
  va_end (args);
  return rc;
}

int csFPrintfV (FILE* file, const char* str, va_list args)
{
  csString temp;
  temp.FormatV (str, args);

  return csFPutStr (file, temp);
}

int csPrintfErrV (const char* str, va_list arg)
{
  int rc = csFPrintfV (stderr, str, arg);
  fflush (stderr);
  return rc;
}

int csPrintfErr (const char* str, ...)
{
  va_list args;
  va_start (args, str);
  int const rc = csFPrintfV (stderr, str, args);
  va_end (args);
  return rc;
}

<|endoftext|>