<commit_before>//===--- VirtualNearMissCheck.cpp - clang-tidy-----------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "VirtualNearMissCheck.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/CXXInheritance.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/Lex/Lexer.h"

using namespace clang::ast_matchers;

namespace clang {
namespace tidy {
namespace misc {

AST_MATCHER(CXXMethodDecl, isStatic) { return Node.isStatic(); }

AST_MATCHER(CXXMethodDecl, isOverloadedOperator) {
  return Node.isOverloadedOperator();
}

/// Finds out if the given method overrides some method.
static bool isOverrideMethod(const CXXMethodDecl *MD) {
  return MD->size_overridden_methods() > 0 || MD->hasAttr<OverrideAttr>();
}

/// Checks whether the return types are covariant, according to
/// C++[class.virtual]p7.
///
/// Similar with clang::Sema::CheckOverridingFunctionReturnType.
/// \returns true if the return types of BaseMD and DerivedMD are covariant.
static bool checkOverridingFunctionReturnType(const ASTContext *Context,
                                              const CXXMethodDecl *BaseMD,
                                              const CXXMethodDecl *DerivedMD) {
  QualType BaseReturnTy = BaseMD->getType()
                              ->getAs<FunctionType>()
                              ->getReturnType()
                              .getCanonicalType();
  QualType DerivedReturnTy = DerivedMD->getType()
                                 ->getAs<FunctionType>()
                                 ->getReturnType()
                                 .getCanonicalType();

  if (DerivedReturnTy->isDependentType() || BaseReturnTy->isDependentType())
    return false;

  // Check if return types are identical.
  if (Context->hasSameType(DerivedReturnTy, BaseReturnTy))
    return true;

  /// Check if the return types are covariant.

  // Both types must be pointers or references to classes.
  if (!(BaseReturnTy->isPointerType() && DerivedReturnTy->isPointerType()) &&
      !(BaseReturnTy->isReferenceType() && DerivedReturnTy->isReferenceType()))
    return false;

  /// BTy is the class type in return type of BaseMD. For example,
  ///    B* Base::md()
  /// While BRD is the declaration of B.
  QualType DTy = DerivedReturnTy->getPointeeType().getCanonicalType();
  QualType BTy = BaseReturnTy->getPointeeType().getCanonicalType();

  const CXXRecordDecl *DRD = DTy->getAsCXXRecordDecl();
  const CXXRecordDecl *BRD = BTy->getAsCXXRecordDecl();
  if (DRD == nullptr || BRD == nullptr)
    return false;

  if (!DRD->hasDefinition() || !BRD->hasDefinition())
    return false;

  if (DRD == BRD)
    return true;

  if (!Context->hasSameUnqualifiedType(DTy, BTy)) {
    // Begin checking whether the conversion from D to B is valid.
    CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
                       /*DetectVirtual=*/false);

    // Check whether D is derived from B, and fill in a CXXBasePaths object.
    if (!DRD->isDerivedFrom(BRD, Paths))
      return false;

    // Check ambiguity.
    if (Paths.isAmbiguous(Context->getCanonicalType(BTy).getUnqualifiedType()))
      return false;

    // Check accessibility.
    // FIXME: We currently only support checking if B is accessible base class
    // of D, or D is the same class which DerivedMD is in.
    bool IsItself =
        DRD->getCanonicalDecl() == DerivedMD->getParent()->getCanonicalDecl();
    bool HasPublicAccess = false;
    for (const auto &Path : Paths) {
      if (Path.Access == AS_public)
        HasPublicAccess = true;
    }
    if (!HasPublicAccess && !IsItself)
      return false;
    // End checking conversion from D to B.
  }

  // Both pointers or references should have the same cv-qualification.
  if (DerivedReturnTy.getLocalCVRQualifiers() !=
      BaseReturnTy.getLocalCVRQualifiers())
    return false;

  // The class type D should have the same cv-qualification as or less
  // cv-qualification than the class type B.
  if (DTy.isMoreQualifiedThan(BTy))
    return false;

  return true;
}

/// \returns decayed type for arrays and functions.
static QualType getDecayedType(QualType Type) {
  if (const auto *Decayed = Type->getAs<DecayedType>())
    return Decayed->getDecayedType();
  return Type;
}

/// \returns true if the param types are the same.
static bool checkParamTypes(const CXXMethodDecl *BaseMD,
                            const CXXMethodDecl *DerivedMD) {
  unsigned NumParamA = BaseMD->getNumParams();
  unsigned NumParamB = DerivedMD->getNumParams();
  if (NumParamA != NumParamB)
    return false;

  for (unsigned I = 0; I < NumParamA; I++) {
    if (getDecayedType(BaseMD->getParamDecl(I)->getType().getCanonicalType()) !=
        getDecayedType(
            DerivedMD->getParamDecl(I)->getType().getCanonicalType()))
      return false;
  }
  return true;
}

/// \returns true if derived method can override base method except for the
/// name.
static bool checkOverrideWithoutName(const ASTContext *Context,
                                     const CXXMethodDecl *BaseMD,
                                     const CXXMethodDecl *DerivedMD) {
  if (BaseMD->isStatic() != DerivedMD->isStatic())
    return false;

  if (BaseMD->getType() == DerivedMD->getType())
    return true;

  // Now the function types are not identical. Then check if the return types
  // are covariant and if the param types are the same.
  if (!checkOverridingFunctionReturnType(Context, BaseMD, DerivedMD))
    return false;
  return checkParamTypes(BaseMD, DerivedMD);
}

/// Check whether BaseMD overrides DerivedMD.
///
/// Prerequisite: the class which BaseMD is in should be a base class of that
/// DerivedMD is in.
static bool checkOverrideByDerivedMethod(const CXXMethodDecl *BaseMD,
                                         const CXXMethodDecl *DerivedMD) {
  for (CXXMethodDecl::method_iterator I = DerivedMD->begin_overridden_methods(),
                                      E = DerivedMD->end_overridden_methods();
       I != E; ++I) {
    const CXXMethodDecl *OverriddenMD = *I;
    if (BaseMD->getCanonicalDecl() == OverriddenMD->getCanonicalDecl())
      return true;
  }

  return false;
}

bool VirtualNearMissCheck::isPossibleToBeOverridden(
    const CXXMethodDecl *BaseMD) {
  auto Iter = PossibleMap.find(BaseMD);
  if (Iter != PossibleMap.end())
    return Iter->second;

  bool IsPossible = !BaseMD->isImplicit() && !isa<CXXConstructorDecl>(BaseMD) &&
                    !isa<CXXDestructorDecl>(BaseMD) && BaseMD->isVirtual() &&
                    !BaseMD->isOverloadedOperator() &&
                    !isa<CXXConversionDecl>(BaseMD);
  PossibleMap[BaseMD] = IsPossible;
  return IsPossible;
}

bool VirtualNearMissCheck::isOverriddenByDerivedClass(
    const CXXMethodDecl *BaseMD, const CXXRecordDecl *DerivedRD) {
  auto Key = std::make_pair(BaseMD, DerivedRD);
  auto Iter = OverriddenMap.find(Key);
  if (Iter != OverriddenMap.end())
    return Iter->second;

  bool IsOverridden = false;
  for (const CXXMethodDecl *DerivedMD : DerivedRD->methods()) {
    if (!isOverrideMethod(DerivedMD))
      continue;

    if (checkOverrideByDerivedMethod(BaseMD, DerivedMD)) {
      IsOverridden = true;
      break;
    }
  }
  OverriddenMap[Key] = IsOverridden;
  return IsOverridden;
}

void VirtualNearMissCheck::registerMatchers(MatchFinder *Finder) {
  if (!getLangOpts().CPlusPlus)
    return;

  Finder->addMatcher(
      cxxMethodDecl(
          unless(anyOf(isOverride(), isImplicit(), cxxConstructorDecl(),
                       cxxDestructorDecl(), cxxConversionDecl(), isStatic(),
                       isOverloadedOperator())))
          .bind("method"),
      this);
}

void VirtualNearMissCheck::check(const MatchFinder::MatchResult &Result) {
  const auto *DerivedMD = Result.Nodes.getNodeAs<CXXMethodDecl>("method");
  assert(DerivedMD);

  const ASTContext *Context = Result.Context;

  const auto *DerivedRD = DerivedMD->getParent()->getDefinition();
  assert(DerivedRD);

  for (const auto &BaseSpec : DerivedRD->bases()) {
    if (const auto *BaseRD = BaseSpec.getType()->getAsCXXRecordDecl()) {
      for (const auto *BaseMD : BaseRD->methods()) {
        if (!isPossibleToBeOverridden(BaseMD))
          continue;

        if (isOverriddenByDerivedClass(BaseMD, DerivedRD))
          continue;

        unsigned EditDistance =
            BaseMD->getName().edit_distance(DerivedMD->getName());
        if (EditDistance > 0 && EditDistance <= EditDistanceThreshold) {
          if (checkOverrideWithoutName(Context, BaseMD, DerivedMD)) {
            // A "virtual near miss" is found.
            auto Range = CharSourceRange::getTokenRange(
                SourceRange(DerivedMD->getLocation()));

            bool ApplyFix = !BaseMD->isTemplateInstantiation() &&
                            !DerivedMD->isTemplateInstantiation();
            auto Diag =
                diag(DerivedMD->getLocStart(),
                     "method '%0' has a similar name and the same signature as "
                     "virtual method '%1'; did you mean to override it?")
                << DerivedMD->getQualifiedNameAsString()
                << BaseMD->getQualifiedNameAsString();
            if (ApplyFix)
              Diag << FixItHint::CreateReplacement(Range, BaseMD->getName());
          }
        }
      }
    }
  }
}

} // namespace misc
} // namespace tidy
} // namespace clang
<commit_msg>[clang-tidy] Don't compute the edit distance if it's over the threshold.<commit_after>//===--- VirtualNearMissCheck.cpp - clang-tidy-----------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "VirtualNearMissCheck.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/CXXInheritance.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/Lex/Lexer.h"

using namespace clang::ast_matchers;

namespace clang {
namespace tidy {
namespace misc {

AST_MATCHER(CXXMethodDecl, isStatic) { return Node.isStatic(); }

AST_MATCHER(CXXMethodDecl, isOverloadedOperator) {
  return Node.isOverloadedOperator();
}

/// Finds out if the given method overrides some method.
static bool isOverrideMethod(const CXXMethodDecl *MD) {
  return MD->size_overridden_methods() > 0 || MD->hasAttr<OverrideAttr>();
}

/// Checks whether the return types are covariant, according to
/// C++[class.virtual]p7.
///
/// Similar with clang::Sema::CheckOverridingFunctionReturnType.
/// \returns true if the return types of BaseMD and DerivedMD are covariant.
static bool checkOverridingFunctionReturnType(const ASTContext *Context,
                                              const CXXMethodDecl *BaseMD,
                                              const CXXMethodDecl *DerivedMD) {
  QualType BaseReturnTy = BaseMD->getType()
                              ->getAs<FunctionType>()
                              ->getReturnType()
                              .getCanonicalType();
  QualType DerivedReturnTy = DerivedMD->getType()
                                 ->getAs<FunctionType>()
                                 ->getReturnType()
                                 .getCanonicalType();

  if (DerivedReturnTy->isDependentType() || BaseReturnTy->isDependentType())
    return false;

  // Check if return types are identical.
  if (Context->hasSameType(DerivedReturnTy, BaseReturnTy))
    return true;

  /// Check if the return types are covariant.

  // Both types must be pointers or references to classes.
  if (!(BaseReturnTy->isPointerType() && DerivedReturnTy->isPointerType()) &&
      !(BaseReturnTy->isReferenceType() && DerivedReturnTy->isReferenceType()))
    return false;

  /// BTy is the class type in return type of BaseMD. For example,
  ///    B* Base::md()
  /// While BRD is the declaration of B.
  QualType DTy = DerivedReturnTy->getPointeeType().getCanonicalType();
  QualType BTy = BaseReturnTy->getPointeeType().getCanonicalType();

  const CXXRecordDecl *DRD = DTy->getAsCXXRecordDecl();
  const CXXRecordDecl *BRD = BTy->getAsCXXRecordDecl();
  if (DRD == nullptr || BRD == nullptr)
    return false;

  if (!DRD->hasDefinition() || !BRD->hasDefinition())
    return false;

  if (DRD == BRD)
    return true;

  if (!Context->hasSameUnqualifiedType(DTy, BTy)) {
    // Begin checking whether the conversion from D to B is valid.
    CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
                       /*DetectVirtual=*/false);

    // Check whether D is derived from B, and fill in a CXXBasePaths object.
    if (!DRD->isDerivedFrom(BRD, Paths))
      return false;

    // Check ambiguity.
    if (Paths.isAmbiguous(Context->getCanonicalType(BTy).getUnqualifiedType()))
      return false;

    // Check accessibility.
    // FIXME: We currently only support checking if B is accessible base class
    // of D, or D is the same class which DerivedMD is in.
    bool IsItself =
        DRD->getCanonicalDecl() == DerivedMD->getParent()->getCanonicalDecl();
    bool HasPublicAccess = false;
    for (const auto &Path : Paths) {
      if (Path.Access == AS_public)
        HasPublicAccess = true;
    }
    if (!HasPublicAccess && !IsItself)
      return false;
    // End checking conversion from D to B.
  }

  // Both pointers or references should have the same cv-qualification.
  if (DerivedReturnTy.getLocalCVRQualifiers() !=
      BaseReturnTy.getLocalCVRQualifiers())
    return false;

  // The class type D should have the same cv-qualification as or less
  // cv-qualification than the class type B.
  if (DTy.isMoreQualifiedThan(BTy))
    return false;

  return true;
}

/// \returns decayed type for arrays and functions.
static QualType getDecayedType(QualType Type) {
  if (const auto *Decayed = Type->getAs<DecayedType>())
    return Decayed->getDecayedType();
  return Type;
}

/// \returns true if the param types are the same.
static bool checkParamTypes(const CXXMethodDecl *BaseMD,
                            const CXXMethodDecl *DerivedMD) {
  unsigned NumParamA = BaseMD->getNumParams();
  unsigned NumParamB = DerivedMD->getNumParams();
  if (NumParamA != NumParamB)
    return false;

  for (unsigned I = 0; I < NumParamA; I++) {
    if (getDecayedType(BaseMD->getParamDecl(I)->getType().getCanonicalType()) !=
        getDecayedType(
            DerivedMD->getParamDecl(I)->getType().getCanonicalType()))
      return false;
  }
  return true;
}

/// \returns true if derived method can override base method except for the
/// name.
static bool checkOverrideWithoutName(const ASTContext *Context,
                                     const CXXMethodDecl *BaseMD,
                                     const CXXMethodDecl *DerivedMD) {
  if (BaseMD->isStatic() != DerivedMD->isStatic())
    return false;

  if (BaseMD->getType() == DerivedMD->getType())
    return true;

  // Now the function types are not identical. Then check if the return types
  // are covariant and if the param types are the same.
  if (!checkOverridingFunctionReturnType(Context, BaseMD, DerivedMD))
    return false;
  return checkParamTypes(BaseMD, DerivedMD);
}

/// Check whether BaseMD overrides DerivedMD.
///
/// Prerequisite: the class which BaseMD is in should be a base class of that
/// DerivedMD is in.
static bool checkOverrideByDerivedMethod(const CXXMethodDecl *BaseMD,
                                         const CXXMethodDecl *DerivedMD) {
  for (CXXMethodDecl::method_iterator I = DerivedMD->begin_overridden_methods(),
                                      E = DerivedMD->end_overridden_methods();
       I != E; ++I) {
    const CXXMethodDecl *OverriddenMD = *I;
    if (BaseMD->getCanonicalDecl() == OverriddenMD->getCanonicalDecl())
      return true;
  }

  return false;
}

bool VirtualNearMissCheck::isPossibleToBeOverridden(
    const CXXMethodDecl *BaseMD) {
  auto Iter = PossibleMap.find(BaseMD);
  if (Iter != PossibleMap.end())
    return Iter->second;

  bool IsPossible = !BaseMD->isImplicit() && !isa<CXXConstructorDecl>(BaseMD) &&
                    !isa<CXXDestructorDecl>(BaseMD) && BaseMD->isVirtual() &&
                    !BaseMD->isOverloadedOperator() &&
                    !isa<CXXConversionDecl>(BaseMD);
  PossibleMap[BaseMD] = IsPossible;
  return IsPossible;
}

bool VirtualNearMissCheck::isOverriddenByDerivedClass(
    const CXXMethodDecl *BaseMD, const CXXRecordDecl *DerivedRD) {
  auto Key = std::make_pair(BaseMD, DerivedRD);
  auto Iter = OverriddenMap.find(Key);
  if (Iter != OverriddenMap.end())
    return Iter->second;

  bool IsOverridden = false;
  for (const CXXMethodDecl *DerivedMD : DerivedRD->methods()) {
    if (!isOverrideMethod(DerivedMD))
      continue;

    if (checkOverrideByDerivedMethod(BaseMD, DerivedMD)) {
      IsOverridden = true;
      break;
    }
  }
  OverriddenMap[Key] = IsOverridden;
  return IsOverridden;
}

void VirtualNearMissCheck::registerMatchers(MatchFinder *Finder) {
  if (!getLangOpts().CPlusPlus)
    return;

  Finder->addMatcher(
      cxxMethodDecl(
          unless(anyOf(isOverride(), isImplicit(), cxxConstructorDecl(),
                       cxxDestructorDecl(), cxxConversionDecl(), isStatic(),
                       isOverloadedOperator())))
          .bind("method"),
      this);
}

void VirtualNearMissCheck::check(const MatchFinder::MatchResult &Result) {
  const auto *DerivedMD = Result.Nodes.getNodeAs<CXXMethodDecl>("method");
  assert(DerivedMD);

  const ASTContext *Context = Result.Context;

  const auto *DerivedRD = DerivedMD->getParent()->getDefinition();
  assert(DerivedRD);

  for (const auto &BaseSpec : DerivedRD->bases()) {
    if (const auto *BaseRD = BaseSpec.getType()->getAsCXXRecordDecl()) {
      for (const auto *BaseMD : BaseRD->methods()) {
        if (!isPossibleToBeOverridden(BaseMD))
          continue;

        if (isOverriddenByDerivedClass(BaseMD, DerivedRD))
          continue;

        unsigned EditDistance = BaseMD->getName().edit_distance(
            DerivedMD->getName(), EditDistanceThreshold);
        if (EditDistance > 0 && EditDistance <= EditDistanceThreshold) {
          if (checkOverrideWithoutName(Context, BaseMD, DerivedMD)) {
            // A "virtual near miss" is found.
            auto Range = CharSourceRange::getTokenRange(
                SourceRange(DerivedMD->getLocation()));

            bool ApplyFix = !BaseMD->isTemplateInstantiation() &&
                            !DerivedMD->isTemplateInstantiation();
            auto Diag =
                diag(DerivedMD->getLocStart(),
                     "method '%0' has a similar name and the same signature as "
                     "virtual method '%1'; did you mean to override it?")
                << DerivedMD->getQualifiedNameAsString()
                << BaseMD->getQualifiedNameAsString();
            if (ApplyFix)
              Diag << FixItHint::CreateReplacement(Range, BaseMD->getName());
          }
        }
      }
    }
  }
}

} // namespace misc
} // namespace tidy
} // namespace clang
<|endoftext|>


<commit_before><commit_msg>A number of error catches have been introduced.  If the user specifies input that is not sensible (or possible), the program will exit.<commit_after><|endoftext|>


<commit_before><commit_msg>vg filter option fixes<commit_after><|endoftext|>


<commit_before><commit_msg>removed isdust<commit_after><|endoftext|>


<commit_before><commit_msg>Accidentally uncommented old code<commit_after><|endoftext|>


<commit_before>#include <allegro5/allegro.h>
#include <cstdio>
#include <vector>

#include "renderer.h"
#include "global_constants.h"
#include "entity.h"

Renderer::Renderer() : spriteloader()
{
    // Create a display
    display = al_create_display(WINDOW_WIDTH, WINDOW_HEIGHT);
    if(!display)
    {
        // FIXME: Make the error argument mean anything?
        fprintf(stderr, "Fatal Error: Could not create display\n");
        throw -1;
    }

    background = al_create_bitmap(WINDOW_WIDTH, WINDOW_HEIGHT);
    midground = al_create_bitmap(WINDOW_WIDTH, WINDOW_HEIGHT);
    foreground = al_create_bitmap(WINDOW_WIDTH, WINDOW_HEIGHT);
}

Renderer::~Renderer()
{
    // Cleanup
    al_destroy_display(display);
}

void Renderer::render(Gamestate *currentstate, PlayerPtr myself)
{
    // Set camera
    Character *c = static_cast<Character*>(currentstate->get(currentstate->get(myself)->character));
    if (c != 0)
    {
        cam_x = c->x - WINDOW_WIDTH/2.0;
        cam_y = c->y - WINDOW_HEIGHT/2.0;
    }

    al_set_target_bitmap(background);
    al_clear_to_color(al_map_rgba(0, 0, 0, 0));
    al_set_target_bitmap(midground);
    al_clear_to_color(al_map_rgba(0, 0, 0, 0));
    al_set_target_bitmap(foreground);
    al_clear_to_color(al_map_rgba(0, 0, 0, 0));

    // Go through all objects and let them render themselves on the layers
    for (auto& e : currentstate->entitylist)
    {
        e.second->render(this);
    }

    // Set render target to be the display
    al_set_target_backbuffer(display);

    // Draw the map background first
    currentstate->currentmap->render(cam_x, cam_y);

    // Then draw each layer
    al_draw_bitmap(background, 0, 0, 0);
    al_draw_bitmap(midground, 0, 0, 0);
    al_draw_bitmap(foreground, 0, 0, 0);

    al_flip_display();
}
<commit_msg>Fixed out of map rendering glitches.<commit_after>#include <allegro5/allegro.h>
#include <cstdio>
#include <vector>

#include "renderer.h"
#include "global_constants.h"
#include "entity.h"

Renderer::Renderer() : spriteloader()
{
    // Create a display
    display = al_create_display(WINDOW_WIDTH, WINDOW_HEIGHT);
    if(!display)
    {
        // FIXME: Make the error argument mean anything?
        fprintf(stderr, "Fatal Error: Could not create display\n");
        throw -1;
    }

    background = al_create_bitmap(WINDOW_WIDTH, WINDOW_HEIGHT);
    midground = al_create_bitmap(WINDOW_WIDTH, WINDOW_HEIGHT);
    foreground = al_create_bitmap(WINDOW_WIDTH, WINDOW_HEIGHT);
}

Renderer::~Renderer()
{
    // Cleanup
    al_destroy_display(display);
}

void Renderer::render(Gamestate *currentstate, PlayerPtr myself)
{
    // Set camera
    Character *c = static_cast<Character*>(currentstate->get(currentstate->get(myself)->character));
    if (c != 0)
    {
        cam_x = c->x - WINDOW_WIDTH/2.0;
        cam_y = c->y - WINDOW_HEIGHT/2.0;
    }

    al_set_target_bitmap(background);
    al_clear_to_color(al_map_rgba(0, 0, 0, 0));
    al_set_target_bitmap(midground);
    al_clear_to_color(al_map_rgba(0, 0, 0, 0));
    al_set_target_bitmap(foreground);
    al_clear_to_color(al_map_rgba(0, 0, 0, 0));

    // Go through all objects and let them render themselves on the layers
    for (auto& e : currentstate->entitylist)
    {
        e.second->render(this);
    }

    // Set render target to be the display
    al_set_target_backbuffer(display);

    // Clear black
    al_clear_to_color(al_map_rgba(0, 0, 0, 1));

    // Draw the map background first
    currentstate->currentmap->render(cam_x, cam_y);

    // Then draw each layer
    al_draw_bitmap(background, 0, 0, 0);
    al_draw_bitmap(midground, 0, 0, 0);
    al_draw_bitmap(foreground, 0, 0, 0);

    al_flip_display();
}
<|endoftext|>


<commit_before>#include "RapidExternalEvtGen.h"

#include <cstdlib>
#include <fstream>
#include <queue>

#include "TRandom.h"
#include "TSystem.h"

#ifdef RAPID_EVTGEN
#include "EvtGen/EvtGen.hh"
#include "EvtGenBase/EvtRandomEngine.hh"
#include "EvtGenBase/EvtAbsRadCorr.hh"
#include "EvtGenBase/EvtDecayBase.hh"
#include "EvtGenBase/EvtParticle.hh"
#include "EvtGenBase/EvtParticleFactory.hh"
#include "EvtGenBase/EvtPatches.hh"
#include "EvtGenBase/EvtPDL.hh"
#include "EvtGenBase/EvtMTRandomEngine.hh"

#include "EvtGenExternal/EvtExternalGenList.hh"
#endif

bool RapidExternalEvtGen::decay(std::vector<RapidParticle*>& parts) {
#ifdef RAPID_EVTGEN
	EvtParticle* theParent(0);

	if(parts.size() < 1) {
		std::cout << "WARNING in RapidExternalEvtGen::decay : There are no particles to decay." << std::endl;
		return false;
	}
	EvtId theId = EvtPDL::evtIdFromLundKC(parts[0]->id());

	// Parent particle 4-momentum
	TLorentzVector pIn = parts[0]->getP();
	EvtVector4R pInit(pIn.E(),pIn.Px(),pIn.Py(),pIn.Pz());

	theParent = EvtParticleFactory::particleFactory(theId, pInit);
	if (theParent->getSpinStates() == 3) {theParent->setVectorSpinDensity();}

	// Generate the event
	evtGen_->generateDecay(theParent);

	// Store particles to read in the order RapidSim stores them
	std::queue<EvtParticle*> evtParts;
	// Also store the number of children expected for each of these particles so we can remove PHOTOS photons
	std::queue<int> nExpectedChildren;
	evtParts.push(theParent);
	nExpectedChildren.push(parts[0]->nDaughters());

	EvtVector4R x4Evt;
	EvtVector4R p4Evt;
	TLorentzVector p4TLV;

	int iPart=1; // The momentum and origin vertex of the first particle are already set

	while(!evtParts.empty()) {
		EvtParticle* theParticle = evtParts.front();

		// B0 and Bs may mix in EvtGen - RapidSim ignores this step and only records the second state
		while(theParticle->getNDaug()==1) {
			theParticle = theParticle->getDaug(0);
		}

		int nChildren = nExpectedChildren.front();

		// Loop over the daughter tracks
		for (int iChild = 0; iChild < nChildren; ++iChild) {
			EvtParticle* child = theParticle->getDaug(iChild);

			if (child != 0) {
				p4Evt = child->getP4Lab();
				x4Evt = child->get4Pos();
				p4TLV.SetPxPyPzE(p4Evt.get(1),p4Evt.get(2),p4Evt.get(3),p4Evt.get(0));
				if(parts.size() < iPart+1u) {
					std::cout << "WARNING in RapidExternalEvtGen::decay : EvtGen has produced too many particles." << std::endl;
					return false;
				}
				parts[iPart]->setP(p4TLV);
				parts[iPart]->getOriginVertex()->setXYZ(1e3*x4Evt.get(1),1e3*x4Evt.get(2),1e3*x4Evt.get(3));
				evtParts.push(child);
				nExpectedChildren.push(parts[iPart]->nDaughters());
				++iPart;
			}
		}

		delete theParticle;
		evtParts.pop();
		nExpectedChildren.pop();
	}

	return true;
#else
	if(!suppressWarning_) {
		std::cout << "WARNING in RapidExternalEvtGen::decay : EvtGen extension not compiled. Will not use EvtGen to decay " << parts[0]->name() << "." << std::endl;
		suppressWarning_=true;
	}

	return false;
#endif
}

bool RapidExternalEvtGen::setup() {
#ifdef RAPID_EVTGEN
	std::cout << "INFO in RapidExternalEvtGen::setup : Setting decay for external EvtGen generator." << std::endl;
	if(!evtGen_) setupGenerator();
	evtGen_->readUDecay(decFileName_.Data());
	return true;
#else
	std::cout << "WARNING in RapidExternalEvtGen::setup : EvtGen extension not compiled." << std::endl;
	return false;
#endif
}

bool RapidExternalEvtGen::setupGenerator() {
#ifdef RAPID_EVTGEN
	std::cout << "INFO in RapidExternalEvtGen::setupGenerator : Setting up external EvtGen generator." << std::endl;
	EvtRandomEngine* randomEngine = 0;
	EvtAbsRadCorr* radCorrEngine = 0;
	std::list<EvtDecayBase*> extraModels;

	// Define the random number generator
	uint seed = gRandom->GetSeed();
	randomEngine = new EvtMTRandomEngine(seed);

	bool useEvtGenRandom(false);
	EvtExternalGenList genList(true, "", "gamma", useEvtGenRandom);
	radCorrEngine = genList.getPhotosModel();
	extraModels = genList.getListOfModels();

	TString evtPDLPath;
	evtPDLPath += getenv("EVTGEN_ROOT");
	evtPDLPath += "/evt.pdl";

	bool foundDec=false;

	TString decPath;
	decPath += getenv("RAPIDSIM_CONFIG");
	if(decPath!="") {
		decPath += "/config/evtgen/DECAY.DEC";
		if(!gSystem->AccessPathName(decPath)) foundDec=true;
	}

	// We want to initialise EvtGen before we define our DEC file so we can use EvtPDL
	// To do this pass an empty DEC file as the main decay file and pass our file later as a user file
	if(!foundDec) {
		decPath += getenv("RAPIDSIM_ROOT");
		decPath += "/config/evtgen/DECAY.DEC";
	}

	evtGen_ = new EvtGen(decPath.Data(), evtPDLPath.Data(), randomEngine,
			radCorrEngine, &extraModels);

	return true;
#else
	std::cout << "WARNING in RapidExternalEvtGen::setup : EvtGen extension not compiled." << std::endl;
	return false;
#endif
}

void RapidExternalEvtGen::writeDecFile(TString fname, std::vector<RapidParticle*>& parts, bool usePhotos) {
#ifdef RAPID_EVTGEN
	if(!evtGen_) setupGenerator();

	decFileName_ = fname+".DEC";
	std::cout << "INFO in RapidExternalEvtGen::writeDecFile : Writing EvtGen DEC file : " << decFileName_ << std::endl;

	std::ofstream fout;
	fout.open(decFileName_, std::ofstream::out);

	if(usePhotos) {
		fout << "yesPhotos\n" << std::endl;
	} else {
		fout << "noPhotos\n" << std::endl;
	}

	// Loop over all particles and write out Decay rule for each
	for(unsigned int iPart=0; iPart<parts.size(); ++iPart) {
		unsigned int nChildren = parts[iPart]->nDaughters();
		if(nChildren>0) {
			int id = parts[iPart]->id();
			fout << "Decay " << getEvtGenName(id) << "\n1.00\t";
			if ( !(parts[iPart]->evtGenDecayModel()).Contains("TAUOLA") ) {
				for(unsigned int iChild=0; iChild<nChildren; ++iChild) {
					fout << getEvtGenName(parts[iPart]->daughter(iChild)->id()) << "\t";
				}
			}
			fout << parts[iPart]->evtGenDecayModel() << ";" << std::endl;
			fout <<"Enddecay" << std::endl;

			// Workaround to deal with mixing of B0 and Bs
			if(TMath::Abs(id)==531||TMath::Abs(id)==511) fout <<"CDecay " << getEvtGenConjName(id) << std::endl << std::endl;
		}
	}
	fout <<"End\n" << std::endl;
	fout.close();
#else
	std::cout << "WARNING in RapidExternalEvtGen::writeDecFile : EvtGen extension not compiled. Cannot write DEC file "
		  << fname << " for " << parts.size() << "particles with usePhotos=" << usePhotos << "." << std::endl;
#endif
}

TString RapidExternalEvtGen::getEvtGenName(int id) {
#ifdef RAPID_EVTGEN
	EvtId evtId = EvtPDL::evtIdFromLundKC(id);
	TString name = EvtPDL::name(evtId);
	return name;
#else
	std::cout << "WARNING in RapidExternalEvtGen::getEvtGenName : EvtGen extension not compiled. Cannot lookup name for particle ID " << id << "." << std::endl;
	return "";
#endif
}

TString RapidExternalEvtGen::getEvtGenConjName(int id) {
#ifdef RAPID_EVTGEN
	EvtId evtId = EvtPDL::evtIdFromLundKC(id);
	EvtId evtConjId = EvtPDL::chargeConj(evtId);
	TString name = EvtPDL::name(evtConjId);
	return name;
#else
	std::cout << "WARNING in RapidExternalEvtGen::getEvtGenConjName : EvtGen extension not compiled. Cannot lookup conjugate name for particle ID " << id << "." << std::endl;
	return "";
#endif
}
<commit_msg>Fix memory leak when using EvtGen with PHOTOS<commit_after>#include "RapidExternalEvtGen.h"

#include <cstdlib>
#include <fstream>
#include <queue>

#include "TRandom.h"
#include "TSystem.h"

#ifdef RAPID_EVTGEN
#include "EvtGen/EvtGen.hh"
#include "EvtGenBase/EvtRandomEngine.hh"
#include "EvtGenBase/EvtAbsRadCorr.hh"
#include "EvtGenBase/EvtDecayBase.hh"
#include "EvtGenBase/EvtParticle.hh"
#include "EvtGenBase/EvtParticleFactory.hh"
#include "EvtGenBase/EvtPatches.hh"
#include "EvtGenBase/EvtPDL.hh"
#include "EvtGenBase/EvtMTRandomEngine.hh"

#include "EvtGenExternal/EvtExternalGenList.hh"
#endif

bool RapidExternalEvtGen::decay(std::vector<RapidParticle*>& parts) {
#ifdef RAPID_EVTGEN
	EvtParticle* theParent(0);

	if(parts.size() < 1) {
		std::cout << "WARNING in RapidExternalEvtGen::decay : There are no particles to decay." << std::endl;
		return false;
	}
	EvtId theId = EvtPDL::evtIdFromLundKC(parts[0]->id());

	// Parent particle 4-momentum
	TLorentzVector pIn = parts[0]->getP();
	EvtVector4R pInit(pIn.E(),pIn.Px(),pIn.Py(),pIn.Pz());

	theParent = EvtParticleFactory::particleFactory(theId, pInit);
	if (theParent->getSpinStates() == 3) {theParent->setVectorSpinDensity();}

	// Generate the event
	evtGen_->generateDecay(theParent);

	// Store particles to read in the order RapidSim stores them
	std::queue<EvtParticle*> evtParts;
	// Also store the number of children expected for each of these particles so we can remove PHOTOS photons
	std::queue<int> nExpectedChildren;
	evtParts.push(theParent);
	nExpectedChildren.push(parts[0]->nDaughters());

	EvtVector4R x4Evt;
	EvtVector4R p4Evt;
	TLorentzVector p4TLV;

	int iPart=1; // The momentum and origin vertex of the first particle are already set

	while(!evtParts.empty()) {
		EvtParticle* theParticle = evtParts.front();

		// B0 and Bs may mix in EvtGen - RapidSim ignores this step and only records the second state
		while(theParticle->getNDaug()==1) {
			theParticle = theParticle->getDaug(0);
		}

		uint nChildren = nExpectedChildren.front();

		// Loop over the daughter tracks
		for (uint iChild = 0; iChild < nChildren; ++iChild) {
			EvtParticle* child = theParticle->getDaug(iChild);

			if (child != 0) {
				p4Evt = child->getP4Lab();
				x4Evt = child->get4Pos();
				p4TLV.SetPxPyPzE(p4Evt.get(1),p4Evt.get(2),p4Evt.get(3),p4Evt.get(0));
				if(parts.size() < iPart+1u) {
					std::cout << "WARNING in RapidExternalEvtGen::decay : EvtGen has produced too many particles." << std::endl;
					return false;
				}
				parts[iPart]->setP(p4TLV);
				parts[iPart]->getOriginVertex()->setXYZ(1e3*x4Evt.get(1),1e3*x4Evt.get(2),1e3*x4Evt.get(3));
				evtParts.push(child);
				nExpectedChildren.push(parts[iPart]->nDaughters());
				++iPart;
			}
		}

		// Clean up any PHOTOS photons
		for (uint iChild = nChildren; iChild < theParticle->getNDaug(); ++iChild) {
			delete theParticle->getDaug(iChild);
		}
		delete theParticle;
		evtParts.pop();
		nExpectedChildren.pop();
	}

	return true;
#else
	if(!suppressWarning_) {
		std::cout << "WARNING in RapidExternalEvtGen::decay : EvtGen extension not compiled. Will not use EvtGen to decay " << parts[0]->name() << "." << std::endl;
		suppressWarning_=true;
	}

	return false;
#endif
}

bool RapidExternalEvtGen::setup() {
#ifdef RAPID_EVTGEN
	std::cout << "INFO in RapidExternalEvtGen::setup : Setting decay for external EvtGen generator." << std::endl;
	if(!evtGen_) setupGenerator();
	evtGen_->readUDecay(decFileName_.Data());
	return true;
#else
	std::cout << "WARNING in RapidExternalEvtGen::setup : EvtGen extension not compiled." << std::endl;
	return false;
#endif
}

bool RapidExternalEvtGen::setupGenerator() {
#ifdef RAPID_EVTGEN
	std::cout << "INFO in RapidExternalEvtGen::setupGenerator : Setting up external EvtGen generator." << std::endl;
	EvtRandomEngine* randomEngine = 0;
	EvtAbsRadCorr* radCorrEngine = 0;
	std::list<EvtDecayBase*> extraModels;

	// Define the random number generator
	uint seed = gRandom->GetSeed();
	randomEngine = new EvtMTRandomEngine(seed);

	bool useEvtGenRandom(false);
	EvtExternalGenList genList(true, "", "gamma", useEvtGenRandom);
	radCorrEngine = genList.getPhotosModel();
	extraModels = genList.getListOfModels();

	TString evtPDLPath;
	evtPDLPath += getenv("EVTGEN_ROOT");
	evtPDLPath += "/evt.pdl";

	bool foundDec=false;

	TString decPath;
	decPath += getenv("RAPIDSIM_CONFIG");
	if(decPath!="") {
		decPath += "/config/evtgen/DECAY.DEC";
		if(!gSystem->AccessPathName(decPath)) foundDec=true;
	}

	// We want to initialise EvtGen before we define our DEC file so we can use EvtPDL
	// To do this pass an empty DEC file as the main decay file and pass our file later as a user file
	if(!foundDec) {
		decPath += getenv("RAPIDSIM_ROOT");
		decPath += "/config/evtgen/DECAY.DEC";
	}

	evtGen_ = new EvtGen(decPath.Data(), evtPDLPath.Data(), randomEngine,
			radCorrEngine, &extraModels);

	return true;
#else
	std::cout << "WARNING in RapidExternalEvtGen::setup : EvtGen extension not compiled." << std::endl;
	return false;
#endif
}

void RapidExternalEvtGen::writeDecFile(TString fname, std::vector<RapidParticle*>& parts, bool usePhotos) {
#ifdef RAPID_EVTGEN
	if(!evtGen_) setupGenerator();

	decFileName_ = fname+".DEC";
	std::cout << "INFO in RapidExternalEvtGen::writeDecFile : Writing EvtGen DEC file : " << decFileName_ << std::endl;

	std::ofstream fout;
	fout.open(decFileName_, std::ofstream::out);

	if(usePhotos) {
		fout << "yesPhotos\n" << std::endl;
	} else {
		fout << "noPhotos\n" << std::endl;
	}

	// Loop over all particles and write out Decay rule for each
	for(unsigned int iPart=0; iPart<parts.size(); ++iPart) {
		unsigned int nChildren = parts[iPart]->nDaughters();
		if(nChildren>0) {
			int id = parts[iPart]->id();
			fout << "Decay " << getEvtGenName(id) << "\n1.00\t";
			if ( !(parts[iPart]->evtGenDecayModel()).Contains("TAUOLA") ) {
				for(unsigned int iChild=0; iChild<nChildren; ++iChild) {
					fout << getEvtGenName(parts[iPart]->daughter(iChild)->id()) << "\t";
				}
			}
			fout << parts[iPart]->evtGenDecayModel() << ";" << std::endl;
			fout <<"Enddecay" << std::endl;

			// Workaround to deal with mixing of B0 and Bs
			if(TMath::Abs(id)==531||TMath::Abs(id)==511) fout <<"CDecay " << getEvtGenConjName(id) << std::endl << std::endl;
		}
	}
	fout <<"End\n" << std::endl;
	fout.close();
#else
	std::cout << "WARNING in RapidExternalEvtGen::writeDecFile : EvtGen extension not compiled. Cannot write DEC file "
		  << fname << " for " << parts.size() << "particles with usePhotos=" << usePhotos << "." << std::endl;
#endif
}

TString RapidExternalEvtGen::getEvtGenName(int id) {
#ifdef RAPID_EVTGEN
	EvtId evtId = EvtPDL::evtIdFromLundKC(id);
	TString name = EvtPDL::name(evtId);
	return name;
#else
	std::cout << "WARNING in RapidExternalEvtGen::getEvtGenName : EvtGen extension not compiled. Cannot lookup name for particle ID " << id << "." << std::endl;
	return "";
#endif
}

TString RapidExternalEvtGen::getEvtGenConjName(int id) {
#ifdef RAPID_EVTGEN
	EvtId evtId = EvtPDL::evtIdFromLundKC(id);
	EvtId evtConjId = EvtPDL::chargeConj(evtId);
	TString name = EvtPDL::name(evtConjId);
	return name;
#else
	std::cout << "WARNING in RapidExternalEvtGen::getEvtGenConjName : EvtGen extension not compiled. Cannot lookup conjugate name for particle ID " << id << "." << std::endl;
	return "";
#endif
}
<|endoftext|>


<commit_before>/*

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

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

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in
      the documentation and/or other materials provided with the distribution.
    * Neither the name of the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

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

*/

#include "libtorrent/resolver.hpp"
#include <boost/bind.hpp>
#include "libtorrent/debug.hpp"

namespace libtorrent
{
// #error the first places to use this resolver is the http_connection/http_tracker_connection and udp_tracker_connection. make sure to prefer cache on shutdown

	resolver::resolver(io_service& ios)
		: m_ios(ios)
		, m_resolver(ios)
		, m_max_size(700)
		, m_timeout(1200)
	{}

	void resolver::on_lookup(error_code const& ec, tcp::resolver::iterator i
		, resolver_interface::callback_t h, std::string hostname)
	{
#if defined TORRENT_ASIO_DEBUGGING
		complete_async("resolver::on_lookup");
#endif
		if (ec)
		{
			std::vector<address> empty;
			h(ec, empty);
			return;
		}

		dns_cache_entry& ce = m_cache[hostname];
		time_t now = time(NULL);
		ce.last_seen = now;
		ce.addresses.clear();
		while (i != tcp::resolver::iterator())
		{
			ce.addresses.push_back(i->endpoint().address());
			++i;
		}

		h(ec, ce.addresses);

		// if m_cache grows too big, weed out the
		// oldest entries
		if (m_cache.size() > m_max_size)
		{
			cache_t::iterator oldest = m_cache.begin();
			for (cache_t::iterator i = m_cache.begin();
				i != m_cache.end(); ++i)
			{
				cache_t::iterator e = i;
				++i;
				if (i->second.last_seen < oldest->second.last_seen)
					oldest = i;
			}

			// remove the oldest entry
			m_cache.erase(oldest);
		}
	}

	void resolver::async_resolve(std::string const& host, int flags
		, resolver_interface::callback_t const& h)
	{
		cache_t::iterator i = m_cache.find(host);
		if (i != m_cache.end())
		{
			// keep cache entries valid for m_timeout seconds
			if ((flags & resolver_interface::prefer_cache)
				|| i->second.last_seen + m_timeout >= time(NULL))
			{
				error_code ec;
				m_ios.post(boost::bind(h, ec, i->second.addresses));
				return;
			}
		}

		// the port is ignored
		tcp::resolver::query q(host, "80");

#if defined TORRENT_ASIO_DEBUGGING
		add_outstanding_async("resolver::on_lookup");
#endif
		m_resolver.async_resolve(q, boost::bind(&resolver::on_lookup, this, _1, _2
			, h, host));
	}
}

<commit_msg>fix todo comment<commit_after>/*

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

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

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in
      the documentation and/or other materials provided with the distribution.
    * Neither the name of the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

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

*/

#include "libtorrent/resolver.hpp"
#include <boost/bind.hpp>
#include "libtorrent/debug.hpp"

namespace libtorrent
{
// TODO: 3 the first places to use this resolver is the
// http_connection/http_tracker_connection and udp_tracker_connection.
// make sure to prefer cache on shutdown
	resolver::resolver(io_service& ios)
		: m_ios(ios)
		, m_resolver(ios)
		, m_max_size(700)
		, m_timeout(1200)
	{}

	void resolver::on_lookup(error_code const& ec, tcp::resolver::iterator i
		, resolver_interface::callback_t h, std::string hostname)
	{
#if defined TORRENT_ASIO_DEBUGGING
		complete_async("resolver::on_lookup");
#endif
		if (ec)
		{
			std::vector<address> empty;
			h(ec, empty);
			return;
		}

		dns_cache_entry& ce = m_cache[hostname];
		time_t now = time(NULL);
		ce.last_seen = now;
		ce.addresses.clear();
		while (i != tcp::resolver::iterator())
		{
			ce.addresses.push_back(i->endpoint().address());
			++i;
		}

		h(ec, ce.addresses);

		// if m_cache grows too big, weed out the
		// oldest entries
		if (m_cache.size() > m_max_size)
		{
			cache_t::iterator oldest = m_cache.begin();
			for (cache_t::iterator i = m_cache.begin();
				i != m_cache.end(); ++i)
			{
				cache_t::iterator e = i;
				++i;
				if (i->second.last_seen < oldest->second.last_seen)
					oldest = i;
			}

			// remove the oldest entry
			m_cache.erase(oldest);
		}
	}

	void resolver::async_resolve(std::string const& host, int flags
		, resolver_interface::callback_t const& h)
	{
		cache_t::iterator i = m_cache.find(host);
		if (i != m_cache.end())
		{
			// keep cache entries valid for m_timeout seconds
			if ((flags & resolver_interface::prefer_cache)
				|| i->second.last_seen + m_timeout >= time(NULL))
			{
				error_code ec;
				m_ios.post(boost::bind(h, ec, i->second.addresses));
				return;
			}
		}

		// the port is ignored
		tcp::resolver::query q(host, "80");

#if defined TORRENT_ASIO_DEBUGGING
		add_outstanding_async("resolver::on_lookup");
#endif
		m_resolver.async_resolve(q, boost::bind(&resolver::on_lookup, this, _1, _2
			, h, host));
	}
}

<|endoftext|>


<commit_before>#include "zipper.h"
#include "defs.h"
#include "tools.h"

#include <fstream>
#include <stdexcept>

namespace zipper {

	struct Zipper::Impl
	{
		Zipper& m_outer;
		zipFile m_zf;
		ourmemory_t m_zipmem;
		zlib_filefunc_def m_filefunc;

		Impl(Zipper& outer) : m_outer(outer), m_zipmem(), m_filefunc()
		{
			m_zf = NULL;
			//m_filefunc = { 0 };
		}

		bool initFile(const std::string& filename)
		{
			#ifdef USEWIN32IOAPI
				zlib_filefunc64_def ffunc = { 0 };
			#endif

			int mode = 0;
			int flags = Zipper::Append;

			/* open the zip file for output */
			if (checkFileExists(filename))
				mode = (flags & Zipper::Overwrite) ? APPEND_STATUS_CREATE : APPEND_STATUS_ADDINZIP;
			else
				mode = APPEND_STATUS_CREATE;

			#ifdef USEWIN32IOAPI
				fill_win32_filefunc64A(&ffunc);
				m_zf = zipOpen2_64(filename.c_str(), mode, NULL, &ffunc);
			#else
				m_zf = zipOpen64(filename.c_str(), mode);
			#endif

			return NULL != m_zf;
		}

		bool initWithStream(std::iostream& stream)
		{
			m_zipmem.grow = 1;

			stream.seekg(0, std::ios::end);
			size_t size = (size_t)stream.tellg();
			stream.seekg(0);

			if (size > 0)
			{
				m_zipmem.base = new char[(size_t)size];
				stream.read(m_zipmem.base, size);
			}

			fill_memory_filefunc(&m_filefunc, &m_zipmem);

			return initMemory(size > 0 ? APPEND_STATUS_CREATE : APPEND_STATUS_ADDINZIP, m_filefunc);
		}

		bool initWithVector(std::vector<unsigned char>& buffer)
		{
			m_zipmem.grow = 1;

			if (!buffer.empty())
			{
				m_zipmem.base = new char[buffer.size()];
				memcpy(m_zipmem.base, (char*)buffer.data(), buffer.size());
				m_zipmem.size = (uLong)buffer.size();
			}

			fill_memory_filefunc(&m_filefunc, &m_zipmem);

			return initMemory(buffer.empty() ? APPEND_STATUS_CREATE : APPEND_STATUS_ADDINZIP, m_filefunc);
		}

		bool initMemory(int mode, zlib_filefunc_def& filefunc)
		{
			m_zf = zipOpen3("__notused__", mode, 0, 0, &filefunc);
			return m_zf != NULL;
		}

		bool add(std::istream& input_stream, const std::string& nameInZip, const std::string& password, int flags)
		{
			if (!m_zf) return false;

			int compressLevel = 0;
			int zip64 = 0;
			int size_buf = WRITEBUFFERSIZE;
			int err = ZIP_OK;
			unsigned long crcFile = 0;

			zip_fileinfo zi = { 0 };
			size_t size_read;

			std::vector<char> buff;
			buff.resize(size_buf);

			if (nameInZip.empty())
				return false;

			if (flags & Zipper::Faster) compressLevel = 1;
			if (flags & Zipper::Better) compressLevel = 9;

			zip64 = (int)isLargeFile(input_stream);
			if (password.empty())
				err = zipOpenNewFileInZip64(m_zf,
					nameInZip.c_str(),
					&zi,
					NULL,
					0,
					NULL,
					0,
					NULL /* comment*/,
					(compressLevel != 0) ? Z_DEFLATED : 0,
					compressLevel,
					zip64);
			else
			{
				getFileCrc(input_stream, buff, crcFile);
				err = zipOpenNewFileInZip3_64(m_zf,
					nameInZip.c_str(),
					&zi,
					NULL,
					0,
					NULL,
					0,
					NULL /* comment*/,
					(compressLevel != 0) ? Z_DEFLATED : 0,
					compressLevel,
					0,
					/* -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, */
					-MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY,
					password.c_str(),
					crcFile,
					zip64);
			}

			if (ZIP_OK == err)
			{
				do {
					err = ZIP_OK;
					input_stream.read(buff.data(), buff.size());
					size_read = (size_t)input_stream.gcount();
					if (size_read < buff.size() && !input_stream.eof() && !input_stream.good())
						err = ZIP_ERRNO;

					if (size_read > 0)
						err = zipWriteInFileInZip(this->m_zf, buff.data(), (unsigned int)size_read);

				} while ((err == ZIP_OK) && (size_read>0));
			}
			else
				throw EXCEPTION_CLASS(("Error adding '" + nameInZip + "' to zip").c_str());

			if (ZIP_OK == err)
				err = zipCloseFileInZip(this->m_zf);

			return ZIP_OK == err;
		}

		void close()
		{
			if (m_zf)
				zipClose(m_zf, NULL);

			if (m_zipmem.base && m_zipmem.limit > 0)
			{
				if (m_outer.m_usingMemoryVector)
				{
					m_outer.m_vecbuffer.resize(m_zipmem.limit);
					m_outer.m_vecbuffer.assign(m_zipmem.base, m_zipmem.base + m_zipmem.limit);
				}

				else if (m_outer.m_usingStream)
					m_outer.m_obuffer.write(m_zipmem.base, m_zipmem.limit);
			}

			free(m_zipmem.base);
		}
	};

	///////////////////////////////////////////////////////////////////////////////
	///////////////////////////////////////////////////////////////////////////////

	Zipper::Zipper(const std::string& zipname)
		: m_obuffer(*(new std::stringstream())) //not used but using local variable throws exception
		, m_vecbuffer(*(new std::vector<unsigned char>())) //not used but using local variable throws exception
		, m_usingMemoryVector(false)
		, m_usingStream(false)
		, m_zipname(zipname)
		, m_impl(new Impl(*this))
	{
		if (!m_impl->initFile(zipname))
			throw EXCEPTION_CLASS("Error creating zip in file!");

		m_open = true;
	}

	Zipper::Zipper(const std::string& zipname, const std::string& password)
		: m_obuffer(*(new std::stringstream())) //not used but using local variable throws exception
		, m_vecbuffer(*(new std::vector<unsigned char>())) //not used but using local variable throws exception
		, m_usingMemoryVector(false)
		, m_usingStream(false)
		, m_zipname(zipname)
		, m_password(password)
		, m_impl(new Impl(*this))
	{
		if (!m_impl->initFile(zipname))
			throw EXCEPTION_CLASS("Error creating zip in file!");

		m_open = true;
	}

	Zipper::Zipper(std::iostream& buffer)
		: m_vecbuffer(*(new std::vector<unsigned char>())) //not used but using local variable throws exception
		, m_obuffer(buffer)
		, m_usingMemoryVector(false)
		, m_usingStream(true)
		, m_impl(new Impl(*this))
	{
		if (!m_impl->initWithStream(m_obuffer))
			throw EXCEPTION_CLASS("Error creating zip in memory!");

		m_open = true;
	}

	Zipper::Zipper(std::vector<unsigned char>& buffer)
		: m_vecbuffer(buffer)
		, m_obuffer(*(new std::stringstream())) //not used but using local variable throws exception
		, m_usingMemoryVector(true)
		, m_usingStream(false)
		, m_impl(new Impl(*this))
	{
		if (!m_impl->initWithVector(m_vecbuffer))
			throw EXCEPTION_CLASS("Error creating zip in memory!");

		m_open = true;
	}

	Zipper::~Zipper(void)
	{
		close();
	}

	bool Zipper::add(std::istream& source, const std::string& nameInZip, zipFlags flags)
	{
		return m_impl->add(source, nameInZip, "", flags);
	}

	bool Zipper::add(const std::string& fileOrFolderPath, zipFlags flags)
	{
		if (isDirectory(fileOrFolderPath))
		{
			std::string folderName = fileNameFromPath(fileOrFolderPath);
			std::vector<std::string> files = filesFromDirectory(fileOrFolderPath);
			std::vector<std::string>::iterator it = files.begin();
			for (; it != files.end(); ++it)
			{
				std::ifstream input(it->c_str(), std::ios::binary);
				std::string nameInZip = it->substr(it->find(folderName), it->size());
				add(input, nameInZip, flags);
				input.close();
			}
		}
		else
		{
			std::ifstream input(fileOrFolderPath.c_str(), std::ios::binary);
			add(input, fileNameFromPath(fileOrFolderPath), flags);
			input.close();
		}

		return true;
	}

	void Zipper::open()
	{
		if (!m_open)
		{
			if (m_usingMemoryVector)
			{
				if (!m_impl->initWithVector(m_vecbuffer))
					throw EXCEPTION_CLASS("Error opening zip memory!");
			}
			else if (m_usingStream)
			{
				if (!m_impl->initWithStream(m_obuffer))
					throw EXCEPTION_CLASS("Error opening zip memory!");
			}
			else
			{
				if (!m_impl->initFile(m_zipname))
					throw EXCEPTION_CLASS("Error opening zip file!");
			}

			m_open = true;
		}
	}

	void Zipper::close()
	{
		if (m_open)
		{
			m_impl->close();
			m_open = false;
		}
	}
}
<commit_msg>if there is aaa/bbb/ccc/aaa/ path, the code will have problem<commit_after>#include "zipper.h"
#include "defs.h"
#include "tools.h"

#include <fstream>
#include <stdexcept>

namespace zipper {

	struct Zipper::Impl
	{
		Zipper& m_outer;
		zipFile m_zf;
		ourmemory_t m_zipmem;
		zlib_filefunc_def m_filefunc;

		Impl(Zipper& outer) : m_outer(outer), m_zipmem(), m_filefunc()
		{
			m_zf = NULL;
			//m_filefunc = { 0 };
		}

		bool initFile(const std::string& filename)
		{
			#ifdef USEWIN32IOAPI
				zlib_filefunc64_def ffunc = { 0 };
			#endif

			int mode = 0;
			int flags = Zipper::Append;

			/* open the zip file for output */
			if (checkFileExists(filename))
				mode = (flags & Zipper::Overwrite) ? APPEND_STATUS_CREATE : APPEND_STATUS_ADDINZIP;
			else
				mode = APPEND_STATUS_CREATE;

			#ifdef USEWIN32IOAPI
				fill_win32_filefunc64A(&ffunc);
				m_zf = zipOpen2_64(filename.c_str(), mode, NULL, &ffunc);
			#else
				m_zf = zipOpen64(filename.c_str(), mode);
			#endif

			return NULL != m_zf;
		}

		bool initWithStream(std::iostream& stream)
		{
			m_zipmem.grow = 1;

			stream.seekg(0, std::ios::end);
			size_t size = (size_t)stream.tellg();
			stream.seekg(0);

			if (size > 0)
			{
				m_zipmem.base = new char[(size_t)size];
				stream.read(m_zipmem.base, size);
			}

			fill_memory_filefunc(&m_filefunc, &m_zipmem);

			return initMemory(size > 0 ? APPEND_STATUS_CREATE : APPEND_STATUS_ADDINZIP, m_filefunc);
		}

		bool initWithVector(std::vector<unsigned char>& buffer)
		{
			m_zipmem.grow = 1;

			if (!buffer.empty())
			{
				m_zipmem.base = new char[buffer.size()];
				memcpy(m_zipmem.base, (char*)buffer.data(), buffer.size());
				m_zipmem.size = (uLong)buffer.size();
			}

			fill_memory_filefunc(&m_filefunc, &m_zipmem);

			return initMemory(buffer.empty() ? APPEND_STATUS_CREATE : APPEND_STATUS_ADDINZIP, m_filefunc);
		}

		bool initMemory(int mode, zlib_filefunc_def& filefunc)
		{
			m_zf = zipOpen3("__notused__", mode, 0, 0, &filefunc);
			return m_zf != NULL;
		}

		bool add(std::istream& input_stream, const std::string& nameInZip, const std::string& password, int flags)
		{
			if (!m_zf) return false;

			int compressLevel = 0;
			int zip64 = 0;
			int size_buf = WRITEBUFFERSIZE;
			int err = ZIP_OK;
			unsigned long crcFile = 0;

			zip_fileinfo zi = { 0 };
			size_t size_read;

			std::vector<char> buff;
			buff.resize(size_buf);

			if (nameInZip.empty())
				return false;

			if (flags & Zipper::Faster) compressLevel = 1;
			if (flags & Zipper::Better) compressLevel = 9;

			zip64 = (int)isLargeFile(input_stream);
			if (password.empty())
				err = zipOpenNewFileInZip64(m_zf,
					nameInZip.c_str(),
					&zi,
					NULL,
					0,
					NULL,
					0,
					NULL /* comment*/,
					(compressLevel != 0) ? Z_DEFLATED : 0,
					compressLevel,
					zip64);
			else
			{
				getFileCrc(input_stream, buff, crcFile);
				err = zipOpenNewFileInZip3_64(m_zf,
					nameInZip.c_str(),
					&zi,
					NULL,
					0,
					NULL,
					0,
					NULL /* comment*/,
					(compressLevel != 0) ? Z_DEFLATED : 0,
					compressLevel,
					0,
					/* -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, */
					-MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY,
					password.c_str(),
					crcFile,
					zip64);
			}

			if (ZIP_OK == err)
			{
				do {
					err = ZIP_OK;
					input_stream.read(buff.data(), buff.size());
					size_read = (size_t)input_stream.gcount();
					if (size_read < buff.size() && !input_stream.eof() && !input_stream.good())
						err = ZIP_ERRNO;

					if (size_read > 0)
						err = zipWriteInFileInZip(this->m_zf, buff.data(), (unsigned int)size_read);

				} while ((err == ZIP_OK) && (size_read>0));
			}
			else
				throw EXCEPTION_CLASS(("Error adding '" + nameInZip + "' to zip").c_str());

			if (ZIP_OK == err)
				err = zipCloseFileInZip(this->m_zf);

			return ZIP_OK == err;
		}

		void close()
		{
			if (m_zf)
				zipClose(m_zf, NULL);

			if (m_zipmem.base && m_zipmem.limit > 0)
			{
				if (m_outer.m_usingMemoryVector)
				{
					m_outer.m_vecbuffer.resize(m_zipmem.limit);
					m_outer.m_vecbuffer.assign(m_zipmem.base, m_zipmem.base + m_zipmem.limit);
				}

				else if (m_outer.m_usingStream)
					m_outer.m_obuffer.write(m_zipmem.base, m_zipmem.limit);
			}

			free(m_zipmem.base);
		}
	};

	///////////////////////////////////////////////////////////////////////////////
	///////////////////////////////////////////////////////////////////////////////

	Zipper::Zipper(const std::string& zipname)
		: m_obuffer(*(new std::stringstream())) //not used but using local variable throws exception
		, m_vecbuffer(*(new std::vector<unsigned char>())) //not used but using local variable throws exception
		, m_usingMemoryVector(false)
		, m_usingStream(false)
		, m_zipname(zipname)
		, m_impl(new Impl(*this))
	{
		if (!m_impl->initFile(zipname))
			throw EXCEPTION_CLASS("Error creating zip in file!");

		m_open = true;
	}

	Zipper::Zipper(const std::string& zipname, const std::string& password)
		: m_obuffer(*(new std::stringstream())) //not used but using local variable throws exception
		, m_vecbuffer(*(new std::vector<unsigned char>())) //not used but using local variable throws exception
		, m_usingMemoryVector(false)
		, m_usingStream(false)
		, m_zipname(zipname)
		, m_password(password)
		, m_impl(new Impl(*this))
	{
		if (!m_impl->initFile(zipname))
			throw EXCEPTION_CLASS("Error creating zip in file!");

		m_open = true;
	}

	Zipper::Zipper(std::iostream& buffer)
		: m_vecbuffer(*(new std::vector<unsigned char>())) //not used but using local variable throws exception
		, m_obuffer(buffer)
		, m_usingMemoryVector(false)
		, m_usingStream(true)
		, m_impl(new Impl(*this))
	{
		if (!m_impl->initWithStream(m_obuffer))
			throw EXCEPTION_CLASS("Error creating zip in memory!");

		m_open = true;
	}

	Zipper::Zipper(std::vector<unsigned char>& buffer)
		: m_vecbuffer(buffer)
		, m_obuffer(*(new std::stringstream())) //not used but using local variable throws exception
		, m_usingMemoryVector(true)
		, m_usingStream(false)
		, m_impl(new Impl(*this))
	{
		if (!m_impl->initWithVector(m_vecbuffer))
			throw EXCEPTION_CLASS("Error creating zip in memory!");

		m_open = true;
	}

	Zipper::~Zipper(void)
	{
		close();
	}

	bool Zipper::add(std::istream& source, const std::string& nameInZip, zipFlags flags)
	{
		return m_impl->add(source, nameInZip, "", flags);
	}

	bool Zipper::add(const std::string& fileOrFolderPath, zipFlags flags)
	{
		if (isDirectory(fileOrFolderPath))
		{
			std::string folderName = fileNameFromPath(fileOrFolderPath);
			std::vector<std::string> files = filesFromDirectory(fileOrFolderPath);
			std::vector<std::string>::iterator it = files.begin();
			for (; it != files.end(); ++it)
			{
				std::ifstream input(it->c_str(), std::ios::binary);
				std::string nameInZip = it->substr(it->rfind(folderName), it->size());
				add(input, nameInZip, flags);
				input.close();
			}
		}
		else
		{
			std::ifstream input(fileOrFolderPath.c_str(), std::ios::binary);
			add(input, fileNameFromPath(fileOrFolderPath), flags);
			input.close();
		}

		return true;
	}

	void Zipper::open()
	{
		if (!m_open)
		{
			if (m_usingMemoryVector)
			{
				if (!m_impl->initWithVector(m_vecbuffer))
					throw EXCEPTION_CLASS("Error opening zip memory!");
			}
			else if (m_usingStream)
			{
				if (!m_impl->initWithStream(m_obuffer))
					throw EXCEPTION_CLASS("Error opening zip memory!");
			}
			else
			{
				if (!m_impl->initFile(m_zipname))
					throw EXCEPTION_CLASS("Error opening zip file!");
			}

			m_open = true;
		}
	}

	void Zipper::close()
	{
		if (m_open)
		{
			m_impl->close();
			m_open = false;
		}
	}
}
<|endoftext|>


<commit_before>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
/* libodfgen
 * Version: MPL 2.0 / LGPLv2.1+
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * Major Contributor(s):
 * Copyright (C) 2002-2003 William Lachance (wrlach@gmail.com)
 *
 * For minor contributions see the git repository.
 *
 * Alternatively, the contents of this file may be used under the terms
 * of the GNU Lesser General Public License Version 2.1 or later
 * (LGPLv2.1+), in which case the provisions of the LGPLv2.1+ are
 * applicable instead of those above.
 *
 * For further information visit http://libwpd.sourceforge.net
 */

/* "This product is not manufactured, approved, or supported by
 * Corel Corporation or Corel Corporation Limited."
 */
#include "FilterInternal.hxx"
#include "PageSpan.hxx"
#include "DocumentElement.hxx"

PageSpan::PageSpan(const librevenge::RVNGPropertyList &xPropList) :
	mxPropList(xPropList),
	mpHeaderContent(0),
	mpFooterContent(0),
	mpHeaderLeftContent(0),
	mpFooterLeftContent(0),
	mpHeaderFirstContent(0),
	mpFooterFirstContent(0),
	mpHeaderLastContent(0),
	mpFooterLastContent(0)
{
}

namespace
{
typedef std::vector<DocumentElement *>::iterator DEVIter;
}

PageSpan::~PageSpan()
{
	if (mpHeaderContent)
	{
		for (DEVIter iterHeaderContent = mpHeaderContent->begin();
		        iterHeaderContent != mpHeaderContent->end();
		        ++iterHeaderContent)
			delete(*iterHeaderContent);
		delete mpHeaderContent;
	}

	if (mpHeaderLeftContent)
	{
		for (DEVIter iterHeaderLeftContent = mpHeaderLeftContent->begin();
		        iterHeaderLeftContent != mpHeaderLeftContent->end();
		        ++iterHeaderLeftContent)
			delete(*iterHeaderLeftContent);
		delete mpHeaderLeftContent;
	}

	if (mpHeaderFirstContent)
	{
		for (DEVIter iterHeaderFirstContent = mpHeaderFirstContent->begin();
		        iterHeaderFirstContent != mpHeaderFirstContent->end();
		        ++iterHeaderFirstContent)
			delete(*iterHeaderFirstContent);
		delete mpHeaderFirstContent;
	}

	if (mpHeaderLastContent)
	{
		for (DEVIter iterHeaderLastContent = mpHeaderLastContent->begin();
		        iterHeaderLastContent != mpHeaderLastContent->end();
		        ++iterHeaderLastContent)
			delete(*iterHeaderLastContent);
		delete mpHeaderLastContent;
	}

	if (mpFooterContent)
	{
		for (DEVIter iterFooterContent = mpFooterContent->begin();
		        iterFooterContent != mpFooterContent->end();
		        ++iterFooterContent)
			delete(*iterFooterContent);
		delete mpFooterContent;
	}

	if (mpFooterLeftContent)
	{
		for (DEVIter iterFooterLeftContent = mpFooterLeftContent->begin();
		        iterFooterLeftContent != mpFooterLeftContent->end();
		        ++iterFooterLeftContent)
			delete(*iterFooterLeftContent);
		delete mpFooterLeftContent;
	}

	if (mpFooterFirstContent)
	{
		for (DEVIter iterFooterFirstContent = mpFooterFirstContent->begin();
		        iterFooterFirstContent != mpFooterFirstContent->end();
		        ++iterFooterFirstContent)
			delete(*iterFooterFirstContent);
		delete mpFooterFirstContent;
	}

	if (mpFooterLastContent)
	{
		for (DEVIter iterFooterLastContent = mpFooterLastContent->begin();
		        iterFooterLastContent != mpFooterLastContent->end();
		        ++iterFooterLastContent)
			delete(*iterFooterLastContent);
		delete mpFooterLastContent;
	}
}

int PageSpan::getSpan() const
{
	if (mxPropList["librevenge:num-pages"])
		return mxPropList["librevenge:num-pages"]->getInt();

	return 0; // should never happen
}

void PageSpan::setHeaderContent(std::vector<DocumentElement *> *pHeaderContent)
{
	if (mpHeaderContent)
	{
		for (DEVIter iterHeaderContent = mpHeaderContent->begin();
		        iterHeaderContent != mpHeaderContent->end();
		        ++iterHeaderContent)
			delete(*iterHeaderContent);
		delete mpHeaderContent;
	}

	mpHeaderContent = pHeaderContent;
}

void PageSpan::setFooterContent(std::vector<DocumentElement *> *pFooterContent)
{
	if (mpFooterContent)
	{
		for (DEVIter iterFooterContent = mpFooterContent->begin();
		        iterFooterContent != mpFooterContent->end();
		        ++iterFooterContent)
			delete(*iterFooterContent);
		delete mpFooterContent;
	}

	mpFooterContent = pFooterContent;
}

void PageSpan::setHeaderLeftContent(std::vector<DocumentElement *> *pHeaderContent)
{
	if (mpHeaderLeftContent)
	{
		for (DEVIter iterHeaderLeftContent = mpHeaderLeftContent->begin();
		        iterHeaderLeftContent != mpHeaderLeftContent->end();
		        ++iterHeaderLeftContent)
			delete(*iterHeaderLeftContent);
		delete mpHeaderLeftContent;
	}

	mpHeaderLeftContent = pHeaderContent;
}

void PageSpan::setFooterLeftContent(std::vector<DocumentElement *> *pFooterContent)
{
	if (mpFooterLeftContent)
	{
		for (DEVIter iterFooterLeftContent = mpFooterLeftContent->begin();
		        iterFooterLeftContent != mpFooterLeftContent->end();
		        ++iterFooterLeftContent)
			delete(*iterFooterLeftContent);
		delete mpFooterLeftContent;
	}

	mpFooterLeftContent = pFooterContent;
}

void PageSpan::setHeaderFirstContent(std::vector<DocumentElement *> *pHeaderContent)
{
	if (mpHeaderFirstContent)
	{
		for (DEVIter iterHeaderFirstContent = mpHeaderFirstContent->begin();
		        iterHeaderFirstContent != mpHeaderFirstContent->end();
		        ++iterHeaderFirstContent)
			delete(*iterHeaderFirstContent);
		delete mpHeaderFirstContent;
	}

	mpHeaderFirstContent = pHeaderContent;
}

void PageSpan::setFooterFirstContent(std::vector<DocumentElement *> *pFooterContent)
{
	if (mpFooterFirstContent)
	{
		for (DEVIter iterFooterFirstContent = mpFooterFirstContent->begin();
		        iterFooterFirstContent != mpFooterFirstContent->end();
		        ++iterFooterFirstContent)
			delete(*iterFooterFirstContent);
		delete mpFooterFirstContent;
	}

	mpFooterFirstContent = pFooterContent;
}

void PageSpan::setHeaderLastContent(std::vector<DocumentElement *> *pHeaderContent)
{
	if (mpHeaderLastContent)
	{
		for (DEVIter iterHeaderLastContent = mpHeaderLastContent->begin();
		        iterHeaderLastContent != mpHeaderLastContent->end();
		        ++iterHeaderLastContent)
			delete(*iterHeaderLastContent);
		delete mpHeaderLastContent;
	}

	mpHeaderLastContent = pHeaderContent;
}

void PageSpan::setFooterLastContent(std::vector<DocumentElement *> *pFooterContent)
{
	if (mpFooterLastContent)
	{
		for (DEVIter iterFooterLastContent = mpFooterLastContent->begin();
		        iterFooterLastContent != mpFooterLastContent->end();
		        ++iterFooterLastContent)
			delete(*iterFooterLastContent);
		delete mpFooterLastContent;
	}

	mpFooterLastContent = pFooterContent;
}

void PageSpan::writePageLayout(const int iNum, OdfDocumentHandler *pHandler) const
{
	librevenge::RVNGPropertyList propList;

	librevenge::RVNGString sPageLayoutName;
	sPageLayoutName.sprintf("PM%i", iNum+2);
	propList.insert("style:name", sPageLayoutName);
	pHandler->startElement("style:page-layout", propList);

	librevenge::RVNGPropertyList tempPropList = mxPropList;
	if (!tempPropList["style:writing-mode"])
		tempPropList.insert("style:writing-mode", librevenge::RVNGString("lr-tb"));
	if (!tempPropList["style:footnote-max-height"])
		tempPropList.insert("style:footnote-max-height", librevenge::RVNGString("0in"));
	pHandler->startElement("style:page-layout-properties", tempPropList);

	librevenge::RVNGPropertyList footnoteSepPropList;
	footnoteSepPropList.insert("style:width", librevenge::RVNGString("0.0071in"));
	footnoteSepPropList.insert("style:distance-before-sep", librevenge::RVNGString("0.0398in"));
	footnoteSepPropList.insert("style:distance-after-sep", librevenge::RVNGString("0.0398in"));
	footnoteSepPropList.insert("style:adjustment", librevenge::RVNGString("left"));
	footnoteSepPropList.insert("style:rel-width", librevenge::RVNGString("25%"));
	footnoteSepPropList.insert("style:color", librevenge::RVNGString("#000000"));
	pHandler->startElement("style:footnote-sep", footnoteSepPropList);

	pHandler->endElement("style:footnote-sep");
	pHandler->endElement("style:page-layout-properties");
	pHandler->endElement("style:page-layout");
}

void PageSpan::writeMasterPages(const int iStartingNum, const int iPageLayoutNum, const bool bLastPageSpan,
                                OdfDocumentHandler *pHandler) const
{
	int iSpan = 0;
	(bLastPageSpan) ? iSpan = 1 : iSpan = getSpan();

	for (int i=iStartingNum; i<(iStartingNum+iSpan); ++i)
	{
		TagOpenElement masterPageOpen("style:master-page");
		librevenge::RVNGString sMasterPageName, sMasterPageDisplayName;
		sMasterPageName.sprintf("Page_Style_%i", i);
		sMasterPageDisplayName.sprintf("Page Style %i", i);
		librevenge::RVNGString sPageLayoutName;
		librevenge::RVNGPropertyList propList;
		sPageLayoutName.sprintf("PM%i", iPageLayoutNum+2);
		propList.insert("style:name", sMasterPageName);
		propList.insert("style:display-name", sMasterPageDisplayName);
		propList.insert("style:page-layout-name", sPageLayoutName);
		if (!bLastPageSpan)
		{
			librevenge::RVNGString sNextMasterPageName;
			sNextMasterPageName.sprintf("Page_Style_%i", (i+1));
			propList.insert("style:next-style-name", sNextMasterPageName);
		}
		pHandler->startElement("style:master-page", propList);

		if (mpHeaderContent)
		{
			_writeHeaderFooter("style:header", *mpHeaderContent, pHandler);
			pHandler->endElement("style:header");
		}
		else if (mpHeaderLeftContent || mpHeaderFirstContent || mpHeaderLastContent)
		{
			TagOpenElement("style:header").write(pHandler);
			pHandler->endElement("style:header");
		}
		if (mpHeaderLeftContent)
		{
			_writeHeaderFooter("style:header-left", *mpHeaderLeftContent, pHandler);
			pHandler->endElement("style:header-left");
		}
		if (mpHeaderFirstContent)
		{
			_writeHeaderFooter("style:header-first", *mpHeaderFirstContent, pHandler);
			pHandler->endElement("style:header-first");
		}
		if (mpHeaderLastContent)
		{
			_writeHeaderFooter("style:header-last", *mpHeaderLastContent, pHandler);
			pHandler->endElement("style:header-last");
		}

		if (mpFooterContent)
		{
			_writeHeaderFooter("style:footer", *mpFooterContent, pHandler);
			pHandler->endElement("style:footer");
		}
		else if (mpFooterLeftContent || mpFooterFirstContent || mpFooterLastContent)
		{
			TagOpenElement("style:footer").write(pHandler);
			pHandler->endElement("style:footer");
		}
		if (mpFooterLeftContent)
		{
			_writeHeaderFooter("style:footer-left", *mpFooterLeftContent, pHandler);
			pHandler->endElement("style:footer-left");
		}
		if (mpFooterFirstContent)
		{
			_writeHeaderFooter("style:footer-first", *mpFooterFirstContent, pHandler);
			pHandler->endElement("style:footer-first");
		}
		if (mpFooterLastContent)
		{
			_writeHeaderFooter("style:footer-last", *mpFooterLastContent, pHandler);
			pHandler->endElement("style:footer-last");
		}

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

void PageSpan::_writeHeaderFooter(const char *headerFooterTagName,
                                  const std::vector<DocumentElement *> &headerFooterContent,
                                  OdfDocumentHandler *pHandler) const
{
	TagOpenElement headerFooterOpen(headerFooterTagName);
	headerFooterOpen.write(pHandler);
	for (std::vector<DocumentElement *>::const_iterator iter = headerFooterContent.begin();
	        iter != headerFooterContent.end();
	        ++iter)
	{
		(*iter)->write(pHandler);
	}
}

/* vim:set shiftwidth=4 softtabstop=4 noexpandtab: */
<commit_msg>LO does not support yet the header/footer occurrence "last", so don't bother<commit_after>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
/* libodfgen
 * Version: MPL 2.0 / LGPLv2.1+
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * Major Contributor(s):
 * Copyright (C) 2002-2003 William Lachance (wrlach@gmail.com)
 *
 * For minor contributions see the git repository.
 *
 * Alternatively, the contents of this file may be used under the terms
 * of the GNU Lesser General Public License Version 2.1 or later
 * (LGPLv2.1+), in which case the provisions of the LGPLv2.1+ are
 * applicable instead of those above.
 *
 * For further information visit http://libwpd.sourceforge.net
 */

/* "This product is not manufactured, approved, or supported by
 * Corel Corporation or Corel Corporation Limited."
 */
#include "FilterInternal.hxx"
#include "PageSpan.hxx"
#include "DocumentElement.hxx"

PageSpan::PageSpan(const librevenge::RVNGPropertyList &xPropList) :
	mxPropList(xPropList),
	mpHeaderContent(0),
	mpFooterContent(0),
	mpHeaderLeftContent(0),
	mpFooterLeftContent(0),
	mpHeaderFirstContent(0),
	mpFooterFirstContent(0),
	mpHeaderLastContent(0),
	mpFooterLastContent(0)
{
}

namespace
{
typedef std::vector<DocumentElement *>::iterator DEVIter;
}

PageSpan::~PageSpan()
{
	if (mpHeaderContent)
	{
		for (DEVIter iterHeaderContent = mpHeaderContent->begin();
		        iterHeaderContent != mpHeaderContent->end();
		        ++iterHeaderContent)
			delete(*iterHeaderContent);
		delete mpHeaderContent;
	}

	if (mpHeaderLeftContent)
	{
		for (DEVIter iterHeaderLeftContent = mpHeaderLeftContent->begin();
		        iterHeaderLeftContent != mpHeaderLeftContent->end();
		        ++iterHeaderLeftContent)
			delete(*iterHeaderLeftContent);
		delete mpHeaderLeftContent;
	}

	if (mpHeaderFirstContent)
	{
		for (DEVIter iterHeaderFirstContent = mpHeaderFirstContent->begin();
		        iterHeaderFirstContent != mpHeaderFirstContent->end();
		        ++iterHeaderFirstContent)
			delete(*iterHeaderFirstContent);
		delete mpHeaderFirstContent;
	}

	if (mpHeaderLastContent)
	{
		for (DEVIter iterHeaderLastContent = mpHeaderLastContent->begin();
		        iterHeaderLastContent != mpHeaderLastContent->end();
		        ++iterHeaderLastContent)
			delete(*iterHeaderLastContent);
		delete mpHeaderLastContent;
	}

	if (mpFooterContent)
	{
		for (DEVIter iterFooterContent = mpFooterContent->begin();
		        iterFooterContent != mpFooterContent->end();
		        ++iterFooterContent)
			delete(*iterFooterContent);
		delete mpFooterContent;
	}

	if (mpFooterLeftContent)
	{
		for (DEVIter iterFooterLeftContent = mpFooterLeftContent->begin();
		        iterFooterLeftContent != mpFooterLeftContent->end();
		        ++iterFooterLeftContent)
			delete(*iterFooterLeftContent);
		delete mpFooterLeftContent;
	}

	if (mpFooterFirstContent)
	{
		for (DEVIter iterFooterFirstContent = mpFooterFirstContent->begin();
		        iterFooterFirstContent != mpFooterFirstContent->end();
		        ++iterFooterFirstContent)
			delete(*iterFooterFirstContent);
		delete mpFooterFirstContent;
	}

	if (mpFooterLastContent)
	{
		for (DEVIter iterFooterLastContent = mpFooterLastContent->begin();
		        iterFooterLastContent != mpFooterLastContent->end();
		        ++iterFooterLastContent)
			delete(*iterFooterLastContent);
		delete mpFooterLastContent;
	}
}

int PageSpan::getSpan() const
{
	if (mxPropList["librevenge:num-pages"])
		return mxPropList["librevenge:num-pages"]->getInt();

	return 0; // should never happen
}

void PageSpan::setHeaderContent(std::vector<DocumentElement *> *pHeaderContent)
{
	if (mpHeaderContent)
	{
		for (DEVIter iterHeaderContent = mpHeaderContent->begin();
		        iterHeaderContent != mpHeaderContent->end();
		        ++iterHeaderContent)
			delete(*iterHeaderContent);
		delete mpHeaderContent;
	}

	mpHeaderContent = pHeaderContent;
}

void PageSpan::setFooterContent(std::vector<DocumentElement *> *pFooterContent)
{
	if (mpFooterContent)
	{
		for (DEVIter iterFooterContent = mpFooterContent->begin();
		        iterFooterContent != mpFooterContent->end();
		        ++iterFooterContent)
			delete(*iterFooterContent);
		delete mpFooterContent;
	}

	mpFooterContent = pFooterContent;
}

void PageSpan::setHeaderLeftContent(std::vector<DocumentElement *> *pHeaderContent)
{
	if (mpHeaderLeftContent)
	{
		for (DEVIter iterHeaderLeftContent = mpHeaderLeftContent->begin();
		        iterHeaderLeftContent != mpHeaderLeftContent->end();
		        ++iterHeaderLeftContent)
			delete(*iterHeaderLeftContent);
		delete mpHeaderLeftContent;
	}

	mpHeaderLeftContent = pHeaderContent;
}

void PageSpan::setFooterLeftContent(std::vector<DocumentElement *> *pFooterContent)
{
	if (mpFooterLeftContent)
	{
		for (DEVIter iterFooterLeftContent = mpFooterLeftContent->begin();
		        iterFooterLeftContent != mpFooterLeftContent->end();
		        ++iterFooterLeftContent)
			delete(*iterFooterLeftContent);
		delete mpFooterLeftContent;
	}

	mpFooterLeftContent = pFooterContent;
}

void PageSpan::setHeaderFirstContent(std::vector<DocumentElement *> *pHeaderContent)
{
	if (mpHeaderFirstContent)
	{
		for (DEVIter iterHeaderFirstContent = mpHeaderFirstContent->begin();
		        iterHeaderFirstContent != mpHeaderFirstContent->end();
		        ++iterHeaderFirstContent)
			delete(*iterHeaderFirstContent);
		delete mpHeaderFirstContent;
	}

	mpHeaderFirstContent = pHeaderContent;
}

void PageSpan::setFooterFirstContent(std::vector<DocumentElement *> *pFooterContent)
{
	if (mpFooterFirstContent)
	{
		for (DEVIter iterFooterFirstContent = mpFooterFirstContent->begin();
		        iterFooterFirstContent != mpFooterFirstContent->end();
		        ++iterFooterFirstContent)
			delete(*iterFooterFirstContent);
		delete mpFooterFirstContent;
	}

	mpFooterFirstContent = pFooterContent;
}

void PageSpan::setHeaderLastContent(std::vector<DocumentElement *> *pHeaderContent)
{
	if (mpHeaderLastContent)
	{
		for (DEVIter iterHeaderLastContent = mpHeaderLastContent->begin();
		        iterHeaderLastContent != mpHeaderLastContent->end();
		        ++iterHeaderLastContent)
			delete(*iterHeaderLastContent);
		delete mpHeaderLastContent;
	}

	mpHeaderLastContent = pHeaderContent;
}

void PageSpan::setFooterLastContent(std::vector<DocumentElement *> *pFooterContent)
{
	if (mpFooterLastContent)
	{
		for (DEVIter iterFooterLastContent = mpFooterLastContent->begin();
		        iterFooterLastContent != mpFooterLastContent->end();
		        ++iterFooterLastContent)
			delete(*iterFooterLastContent);
		delete mpFooterLastContent;
	}

	mpFooterLastContent = pFooterContent;
}

void PageSpan::writePageLayout(const int iNum, OdfDocumentHandler *pHandler) const
{
	librevenge::RVNGPropertyList propList;

	librevenge::RVNGString sPageLayoutName;
	sPageLayoutName.sprintf("PM%i", iNum+2);
	propList.insert("style:name", sPageLayoutName);
	pHandler->startElement("style:page-layout", propList);

	librevenge::RVNGPropertyList tempPropList = mxPropList;
	if (!tempPropList["style:writing-mode"])
		tempPropList.insert("style:writing-mode", librevenge::RVNGString("lr-tb"));
	if (!tempPropList["style:footnote-max-height"])
		tempPropList.insert("style:footnote-max-height", librevenge::RVNGString("0in"));
	pHandler->startElement("style:page-layout-properties", tempPropList);

	librevenge::RVNGPropertyList footnoteSepPropList;
	footnoteSepPropList.insert("style:width", librevenge::RVNGString("0.0071in"));
	footnoteSepPropList.insert("style:distance-before-sep", librevenge::RVNGString("0.0398in"));
	footnoteSepPropList.insert("style:distance-after-sep", librevenge::RVNGString("0.0398in"));
	footnoteSepPropList.insert("style:adjustment", librevenge::RVNGString("left"));
	footnoteSepPropList.insert("style:rel-width", librevenge::RVNGString("25%"));
	footnoteSepPropList.insert("style:color", librevenge::RVNGString("#000000"));
	pHandler->startElement("style:footnote-sep", footnoteSepPropList);

	pHandler->endElement("style:footnote-sep");
	pHandler->endElement("style:page-layout-properties");
	pHandler->endElement("style:page-layout");
}

void PageSpan::writeMasterPages(const int iStartingNum, const int iPageLayoutNum, const bool bLastPageSpan,
                                OdfDocumentHandler *pHandler) const
{
	int iSpan = 0;
	(bLastPageSpan) ? iSpan = 1 : iSpan = getSpan();

	for (int i=iStartingNum; i<(iStartingNum+iSpan); ++i)
	{
		TagOpenElement masterPageOpen("style:master-page");
		librevenge::RVNGString sMasterPageName, sMasterPageDisplayName;
		sMasterPageName.sprintf("Page_Style_%i", i);
		sMasterPageDisplayName.sprintf("Page Style %i", i);
		librevenge::RVNGString sPageLayoutName;
		librevenge::RVNGPropertyList propList;
		sPageLayoutName.sprintf("PM%i", iPageLayoutNum+2);
		propList.insert("style:name", sMasterPageName);
		propList.insert("style:display-name", sMasterPageDisplayName);
		propList.insert("style:page-layout-name", sPageLayoutName);
		if (!bLastPageSpan)
		{
			librevenge::RVNGString sNextMasterPageName;
			sNextMasterPageName.sprintf("Page_Style_%i", (i+1));
			propList.insert("style:next-style-name", sNextMasterPageName);
		}
		pHandler->startElement("style:master-page", propList);

		if (mpHeaderContent)
		{
			_writeHeaderFooter("style:header", *mpHeaderContent, pHandler);
			pHandler->endElement("style:header");
		}
		else if (mpHeaderLeftContent || mpHeaderFirstContent /* || mpHeaderLastContent */)
		{
			TagOpenElement("style:header").write(pHandler);
			pHandler->endElement("style:header");
		}
		if (mpHeaderLeftContent)
		{
			_writeHeaderFooter("style:header-left", *mpHeaderLeftContent, pHandler);
			pHandler->endElement("style:header-left");
		}
		if (mpHeaderFirstContent)
		{
			_writeHeaderFooter("style:header-first", *mpHeaderFirstContent, pHandler);
			pHandler->endElement("style:header-first");
		}
		/*
		if (mpHeaderLastContent)
		{
			_writeHeaderFooter("style:header-last", *mpHeaderLastContent, pHandler);
			pHandler->endElement("style:header-last");
		}
		*/

		if (mpFooterContent)
		{
			_writeHeaderFooter("style:footer", *mpFooterContent, pHandler);
			pHandler->endElement("style:footer");
		}
		else if (mpFooterLeftContent || mpFooterFirstContent /* || mpFooterLastContent */)
		{
			TagOpenElement("style:footer").write(pHandler);
			pHandler->endElement("style:footer");
		}
		if (mpFooterLeftContent)
		{
			_writeHeaderFooter("style:footer-left", *mpFooterLeftContent, pHandler);
			pHandler->endElement("style:footer-left");
		}
		if (mpFooterFirstContent)
		{
			_writeHeaderFooter("style:footer-first", *mpFooterFirstContent, pHandler);
			pHandler->endElement("style:footer-first");
		}
		/*
		if (mpFooterLastContent)
		{
			_writeHeaderFooter("style:footer-last", *mpFooterLastContent, pHandler);
			pHandler->endElement("style:footer-last");
		}
		*/

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

void PageSpan::_writeHeaderFooter(const char *headerFooterTagName,
                                  const std::vector<DocumentElement *> &headerFooterContent,
                                  OdfDocumentHandler *pHandler) const
{
	TagOpenElement headerFooterOpen(headerFooterTagName);
	headerFooterOpen.write(pHandler);
	for (std::vector<DocumentElement *>::const_iterator iter = headerFooterContent.begin();
	        iter != headerFooterContent.end();
	        ++iter)
	{
		(*iter)->write(pHandler);
	}
}

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


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

#include <ReadData.hpp>

namespace AstroData {

RingBufferError::RingBufferError(const std::string & message) : message(message) {}

RingBufferError::~RingBufferError() noexcept {}

const char * RingBufferError::what() const noexcept {
    return message.c_str();
}

void readZappedChannels(Observation & observation, const std::string & inputFilename, std::vector<unsigned int> & zappedChannels) {
  unsigned int nrChannels = 0;
  std::ifstream input;

  input.open(inputFilename);
  if ( !input ) {
    throw FileError("ERROR: impossible to open zapped channels file \"" + inputFilename + "\"");
  }
  while ( !input.eof() ) {
    unsigned int channel = observation.getNrChannels();

    input >> channel;
    if ( channel < observation.getNrChannels() ) {
      zappedChannels[channel] = 1;
      nrChannels++;
    }
  }
  input.close();
  observation.setNrZappedChannels(nrChannels);
}

void readIntegrationSteps(const Observation & observation, const std::string  & inputFilename, std::set<unsigned int> & integrationSteps) {
  std::ifstream input;

  input.open(inputFilename);
  if ( !input ) {
    throw FileError("ERROR: impossible to open integration steps file \"" + inputFilename + "\"");
  }
  while ( !input.eof() ) {
    unsigned int step = observation.getNrSamplesPerBatch();

    input >> step;
    if ( step < observation.getNrSamplesPerBatch() ) {
      integrationSteps.insert(step);
    }
  }
  input.close();
}

#ifdef HAVE_PSRDADA
void readPSRDADAHeader(Observation & observation, dada_hdu_t & ringBuffer) {
  // Staging variables for the header elements
  unsigned int uintValue = 0;
  float floatValue[2] = {0.0f, 0.0f};
  // Header string
  uint64_t headerBytes = 0;
  char * header = 0;

  header = ipcbuf_get_next_read(ringBuffer.header_block, &headerBytes);
  if ( (header == 0) || (headerBytes == 0 ) ) {
    throw RingBufferError("ERROR: impossible to read the PSRDADA header");
  }
  ascii_header_get(header, "SAMPLES_PER_BATCH", "%d", &uintValue);
  observation.setNrSamplesPerBatch(uintValue);
  ascii_header_get(header, "NCHAN", "%d", &uintValue);
  ascii_header_get(header, "MIN_FREQUENCY", "%f", &floatValue[0]);
  ascii_header_get(header, "CHANNEL_BANDWIDTH", "%f", &floatValue[1]);
  observation.setFrequencyRange(1, uintValue, floatValue[0], floatValue[1]);
  ascii_header_get(header, "TSAMP", "%f", &floatValue[0]);
  observation.setSamplingTime(floatValue[0]);
  if ( ipcbuf_mark_cleared(ringBuffer.header_block) < 0 ) {
    throw RingBufferError("ERROR: impossible to mark the PSRDADA header as cleared");
  }
}
#endif // HAVE_PSRDADA

} // AstroData

<commit_msg>Fixing a bug in which the number of subbands was not set when reading input from PSRDADA.<commit_after>// Copyright 2017 Netherlands Institute for Radio Astronomy (ASTRON)
// Copyright 2017 Netherlands eScience Center
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <ReadData.hpp>

namespace AstroData {

RingBufferError::RingBufferError(const std::string & message) : message(message) {}

RingBufferError::~RingBufferError() noexcept {}

const char * RingBufferError::what() const noexcept {
    return message.c_str();
}

void readZappedChannels(Observation & observation, const std::string & inputFilename, std::vector<unsigned int> & zappedChannels) {
  unsigned int nrChannels = 0;
  std::ifstream input;

  input.open(inputFilename);
  if ( !input ) {
    throw FileError("ERROR: impossible to open zapped channels file \"" + inputFilename + "\"");
  }
  while ( !input.eof() ) {
    unsigned int channel = observation.getNrChannels();

    input >> channel;
    if ( channel < observation.getNrChannels() ) {
      zappedChannels[channel] = 1;
      nrChannels++;
    }
  }
  input.close();
  observation.setNrZappedChannels(nrChannels);
}

void readIntegrationSteps(const Observation & observation, const std::string  & inputFilename, std::set<unsigned int> & integrationSteps) {
  std::ifstream input;

  input.open(inputFilename);
  if ( !input ) {
    throw FileError("ERROR: impossible to open integration steps file \"" + inputFilename + "\"");
  }
  while ( !input.eof() ) {
    unsigned int step = observation.getNrSamplesPerBatch();

    input >> step;
    if ( step < observation.getNrSamplesPerBatch() ) {
      integrationSteps.insert(step);
    }
  }
  input.close();
}

#ifdef HAVE_PSRDADA
void readPSRDADAHeader(Observation & observation, dada_hdu_t & ringBuffer) {
  // Staging variables for the header elements
  unsigned int uintValue = 0;
  float floatValue[2] = {0.0f, 0.0f};
  // Header string
  uint64_t headerBytes = 0;
  char * header = 0;

  header = ipcbuf_get_next_read(ringBuffer.header_block, &headerBytes);
  if ( (header == 0) || (headerBytes == 0 ) ) {
    throw RingBufferError("ERROR: impossible to read the PSRDADA header");
  }
  ascii_header_get(header, "SAMPLES_PER_BATCH", "%d", &uintValue);
  observation.setNrSamplesPerBatch(uintValue);
  ascii_header_get(header, "NCHAN", "%d", &uintValue);
  ascii_header_get(header, "MIN_FREQUENCY", "%f", &floatValue[0]);
  ascii_header_get(header, "CHANNEL_BANDWIDTH", "%f", &floatValue[1]);
  observation.setFrequencyRange(observation.getNrSubbands(), uintValue, floatValue[0], floatValue[1]);
  ascii_header_get(header, "TSAMP", "%f", &floatValue[0]);
  observation.setSamplingTime(floatValue[0]);
  if ( ipcbuf_mark_cleared(ringBuffer.header_block) < 0 ) {
    throw RingBufferError("ERROR: impossible to mark the PSRDADA header as cleared");
  }
}
#endif // HAVE_PSRDADA

} // AstroData

<|endoftext|>


<commit_before>#include "Settings.h"

#include <QSettings>

#include "Autostart.h"
#include "Hearthstone.h"

#include "Updater.h"
extern Updater *gUpdater;

DEFINE_SINGLETON_SCOPE( Settings );

#define KEY_ACCOUNT_USERNAME "username"
#define KEY_ACCOUNT_PASSWORD "password"
#define KEY_WEBSERVICE_URL "webserviceUrl"
#define KEY_UPLOAD_METADATA_ENABLED "uploadMetadataEnabled"
#define KEY_HEARTHSTONE_DIRECTORY_PATH "hearthstoneDirectoryPath"
#define KEY_OVERLAY_ENABLED "overlayEnabled"

Settings::Settings() {
}

Settings::~Settings() {
}

QString Settings::AccountUsername() const {
  return QSettings().value( KEY_ACCOUNT_USERNAME ).toString();
}

QString Settings::AccountPassword() const {
  return QSettings().value( KEY_ACCOUNT_PASSWORD ).toString();
}

bool Settings::HasAccount() const {
  return !AccountUsername().isEmpty() && !AccountPassword().isEmpty();
}

void Settings::SetAccount( const QString& username, const QString& password ) {
  QSettings s;
  s.setValue( KEY_ACCOUNT_USERNAME, username );
  s.setValue( KEY_ACCOUNT_PASSWORD, password );

  emit AccountChanged( username, password );
}

QString Settings::WebserviceURL() const {
  return QSettings().value( KEY_WEBSERVICE_URL ).toString();
}

void Settings::SetWebserviceURL( const QString& webserviceUrl ) {
  QSettings s;
  s.setValue( KEY_WEBSERVICE_URL, webserviceUrl );

  emit WebserviceURLChanged( webserviceUrl );
}

bool Settings::Autostart() const {
  return ::Autostart().Active();
}

void Settings::SetAutostart( bool enabled ) {
  ::Autostart().SetActive( enabled );

  emit AutostartChanged( enabled );
}

bool Settings::AutoUpdateCheck() const {
  bool enabled = gUpdater && gUpdater->AutomaticallyChecksForUpdates();
  return enabled;
}

void Settings::SetAutoUpdateCheck( bool enabled ) {
  if( gUpdater ) {
    gUpdater->SetAutomaticallyChecksForUpdates( enabled );
  }

  emit AutoUpdateCheckChanged( enabled );
}

void Settings::CheckForUpdates() {
  if( gUpdater ) {
    gUpdater->CheckForUpdatesNow();
  }
}

bool Settings::UploadMetadataEnabled() const {
  return QSettings().value( KEY_UPLOAD_METADATA_ENABLED, false ).toBool();
}

void Settings::SetUploadMetadataEnabled( bool enabled ) {
  QSettings().setValue( KEY_UPLOAD_METADATA_ENABLED, enabled );

  emit UploadMetadataEnabledChanged( enabled );
}

bool Settings::OverlayEnabled() const {
  return QSettings().value( KEY_OVERLAY_ENABLED, true ).toBool();
}

void Settings::SetOverlayEnabled( bool enabled ) {
  QSettings().setValue( KEY_OVERLAY_ENABLED, enabled );
  emit OverlayEnabledChanged( enabled );
}

QString Settings::HearthstoneDirectoryPath() const {
  QString path = QSettings().value( KEY_HEARTHSTONE_DIRECTORY_PATH ).toString();
  if( path.isEmpty() ) {
    path = Hearthstone::Instance()->DetectHearthstonePath();
  }
  return path;
}

void Settings::SetHearthstoneDirectoryPath( const QString& path ) {
  QSettings s;
  s.setValue( KEY_HEARTHSTONE_DIRECTORY_PATH, path );

  emit HearthstoneDirectoryPathChanged( path );
}
<commit_msg>Only enable overlay by default for new users<commit_after>#include "Settings.h"

#include <QSettings>

#include "Autostart.h"
#include "Hearthstone.h"

#include "Updater.h"
extern Updater *gUpdater;

DEFINE_SINGLETON_SCOPE( Settings );

#define KEY_ACCOUNT_USERNAME "username"
#define KEY_ACCOUNT_PASSWORD "password"
#define KEY_WEBSERVICE_URL "webserviceUrl"
#define KEY_UPLOAD_METADATA_ENABLED "uploadMetadataEnabled"
#define KEY_HEARTHSTONE_DIRECTORY_PATH "hearthstoneDirectoryPath"
#define KEY_OVERLAY_ENABLED "overlayEnabled"

Settings::Settings() {
}

Settings::~Settings() {
}

QString Settings::AccountUsername() const {
  return QSettings().value( KEY_ACCOUNT_USERNAME ).toString();
}

QString Settings::AccountPassword() const {
  return QSettings().value( KEY_ACCOUNT_PASSWORD ).toString();
}

bool Settings::HasAccount() const {
  return !AccountUsername().isEmpty() && !AccountPassword().isEmpty();
}

void Settings::SetAccount( const QString& username, const QString& password ) {
  QSettings s;
  s.setValue( KEY_ACCOUNT_USERNAME, username );
  s.setValue( KEY_ACCOUNT_PASSWORD, password );

  emit AccountChanged( username, password );
}

QString Settings::WebserviceURL() const {
  return QSettings().value( KEY_WEBSERVICE_URL ).toString();
}

void Settings::SetWebserviceURL( const QString& webserviceUrl ) {
  QSettings s;
  s.setValue( KEY_WEBSERVICE_URL, webserviceUrl );

  emit WebserviceURLChanged( webserviceUrl );
}

bool Settings::Autostart() const {
  return ::Autostart().Active();
}

void Settings::SetAutostart( bool enabled ) {
  ::Autostart().SetActive( enabled );

  emit AutostartChanged( enabled );
}

bool Settings::AutoUpdateCheck() const {
  bool enabled = gUpdater && gUpdater->AutomaticallyChecksForUpdates();
  return enabled;
}

void Settings::SetAutoUpdateCheck( bool enabled ) {
  if( gUpdater ) {
    gUpdater->SetAutomaticallyChecksForUpdates( enabled );
  }

  emit AutoUpdateCheckChanged( enabled );
}

void Settings::CheckForUpdates() {
  if( gUpdater ) {
    gUpdater->CheckForUpdatesNow();
  }
}

bool Settings::UploadMetadataEnabled() const {
  return QSettings().value( KEY_UPLOAD_METADATA_ENABLED, false ).toBool();
}

void Settings::SetUploadMetadataEnabled( bool enabled ) {
  QSettings().setValue( KEY_UPLOAD_METADATA_ENABLED, enabled );

  emit UploadMetadataEnabledChanged( enabled );
}

bool Settings::OverlayEnabled() const {
  // Enable overlay by default for new users, but not for existing ones
  bool defaultOverlayEnabled = HasAccount() ? false : true;
  return QSettings().value( KEY_OVERLAY_ENABLED, defaultOverlayEnabled ).toBool();
}

void Settings::SetOverlayEnabled( bool enabled ) {
  QSettings().setValue( KEY_OVERLAY_ENABLED, enabled );
  emit OverlayEnabledChanged( enabled );
}

QString Settings::HearthstoneDirectoryPath() const {
  QString path = QSettings().value( KEY_HEARTHSTONE_DIRECTORY_PATH ).toString();
  if( path.isEmpty() ) {
    path = Hearthstone::Instance()->DetectHearthstonePath();
  }
  return path;
}

void Settings::SetHearthstoneDirectoryPath( const QString& path ) {
  QSettings s;
  s.setValue( KEY_HEARTHSTONE_DIRECTORY_PATH, path );

  emit HearthstoneDirectoryPathChanged( path );
}
<|endoftext|>