<commit_before>//===--- swift_indent_main.cpp - Swift code formatting tool ---------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
//  Extracts a Symbol Graph from a .swiftmodule file.
//
//===----------------------------------------------------------------------===//

#include "swift/AST/DiagnosticsFrontend.h"
#include "swift/Basic/LLVM.h"
#include "swift/Basic/LLVMInitialize.h"
#include "swift/Basic/Version.h"
#include "swift/Frontend/Frontend.h"
#include "swift/Frontend/PrintingDiagnosticConsumer.h"
#include "swift/Option/Options.h"
#include "swift/SymbolGraphGen/SymbolGraphGen.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/raw_ostream.h"

using namespace swift;
using namespace options;

int swift_symbolgraph_extract_main(ArrayRef<const char *> Args,
                                   const char *Argv0, void *MainAddr) {
  INITIALIZE_LLVM();

  CompilerInvocation Invocation;
  CompilerInstance CI;
  PrintingDiagnosticConsumer DiagPrinter;
  auto &Diags = CI.getDiags();
  Diags.addConsumer(DiagPrinter);

  std::unique_ptr<llvm::opt::OptTable> Table = createSwiftOptTable();
  unsigned MissingIndex;
  unsigned MissingCount;
  llvm::opt::InputArgList ParsedArgs = Table->ParseArgs(
      Args, MissingIndex, MissingCount, SwiftSymbolGraphExtractOption);
  if (MissingCount) {
    Diags.diagnose(SourceLoc(), diag::error_missing_arg_value,
                   ParsedArgs.getArgString(MissingIndex), MissingCount);
    return EXIT_FAILURE;
  }

  if (ParsedArgs.hasArg(OPT_UNKNOWN)) {
    for (const auto *A : ParsedArgs.filtered(OPT_UNKNOWN)) {
      Diags.diagnose(SourceLoc(), diag::error_unknown_arg,
                     A->getAsString(ParsedArgs));
    }
    return EXIT_FAILURE;
  }

  auto MainExecutablePath = llvm::sys::fs::getMainExecutable(Argv0, MainAddr);

  if (ParsedArgs.getLastArg(OPT_help) || Args.empty()) {
    std::string ExecutableName =
        llvm::sys::path::stem(MainExecutablePath).str();
    Table->printHelp(llvm::outs(), ExecutableName.c_str(),
                     "Swift Symbol Graph Extractor",
                     SwiftSymbolGraphExtractOption, 0,
                     /*ShowAllAliases*/ false);
    return EXIT_FAILURE;
  }

  std::string ModuleName;
  if (auto *A = ParsedArgs.getLastArg(OPT_module_name)) {
    ModuleName = A->getValue();
  } else {
    Diags.diagnose(SourceLoc(), diag::error_option_required, "-module-name");
    return EXIT_FAILURE;
  }

  llvm::Triple Target;
  if (auto *A = ParsedArgs.getLastArg(OPT_target)) {
    Target = llvm::Triple(A->getValue());
  } else {
    Diags.diagnose(SourceLoc(), diag::error_option_required, "-target");
    return EXIT_FAILURE;
  }

  std::string OutputDir;
  if (auto *A = ParsedArgs.getLastArg(OPT_output_dir)) {
    OutputDir = A->getValue();
  } else {
    Diags.diagnose(SourceLoc(), diag::error_option_required, "-output-dir");
    return EXIT_FAILURE;
  }

  if (!llvm::sys::fs::is_directory(OutputDir)) {
    Diags.diagnose(SourceLoc(), diag::error_nonexistent_output_dir, OutputDir);
    return EXIT_FAILURE;
  }

  Invocation.setMainExecutablePath(MainExecutablePath);
  Invocation.setModuleName("swift_symbolgraph_extract");

  if (auto *A = ParsedArgs.getLastArg(OPT_resource_dir)) {
    Invocation.setRuntimeResourcePath(A->getValue());
  }

  std::string SDK = "";
  if (auto *A = ParsedArgs.getLastArg(OPT_sdk)) {
    SDK = A->getValue();
  }
  Invocation.setSDKPath(SDK);

  Invocation.setTargetTriple(Target);

  for (const auto *A : ParsedArgs.filtered(OPT_Xcc)) {
    Invocation.getClangImporterOptions().ExtraArgs.push_back(A->getValue());
  }

  std::vector<SearchPathOptions::FrameworkSearchPath> FrameworkSearchPaths;
  for (const auto *A : ParsedArgs.filtered(OPT_F)) {
    FrameworkSearchPaths.push_back({A->getValue(), /*isSystem*/ false});
  }
  for (const auto *A : ParsedArgs.filtered(OPT_Fsystem)) {
    FrameworkSearchPaths.push_back({A->getValue(), /*isSystem*/ true});
  }
  Invocation.setFrameworkSearchPaths(FrameworkSearchPaths);
  Invocation.getSearchPathOptions().LibrarySearchPaths =
      ParsedArgs.getAllArgValues(OPT_L);
  Invocation.setImportSearchPaths(ParsedArgs.getAllArgValues(OPT_I));

  Invocation.getLangOptions().EnableObjCInterop = Target.isOSDarwin();
  Invocation.getLangOptions().DebuggerSupport = true;

  Invocation.getFrontendOptions().EnableLibraryEvolution = true;

  std::string ModuleCachePath = "";
  if (auto *A = ParsedArgs.getLastArg(OPT_module_cache_path)) {
    ModuleCachePath = A->getValue();
  }
  Invocation.setClangModuleCachePath(ModuleCachePath);
  Invocation.getClangImporterOptions().ModuleCachePath = ModuleCachePath;
  Invocation.setDefaultPrebuiltCacheIfNecessary();

  if (auto *A = ParsedArgs.getLastArg(OPT_swift_version)) {
    using version::Version;
    auto SwiftVersion = A->getValue();
    bool isValid = false;
    if (auto Version =
            Version::parseVersionString(SwiftVersion, SourceLoc(), nullptr)) {
      if (auto Effective = Version.getValue().getEffectiveLanguageVersion()) {
        Invocation.getLangOptions().EffectiveLanguageVersion = *Effective;
        isValid = true;
      }
    }
    if (!isValid) {
      Diags.diagnose(SourceLoc(), diag::error_invalid_arg_value,
                     "-swift-version", SwiftVersion);
      return EXIT_FAILURE;
    }
  }

  symbolgraphgen::SymbolGraphOptions Options{
      OutputDir,
      Target,
      ParsedArgs.hasArg(OPT_pretty_print),
      AccessLevel::Public,
      !ParsedArgs.hasArg(OPT_skip_synthesized_members),
      ParsedArgs.hasArg(OPT_v),
      ParsedArgs.hasArg(OPT_skip_inherited_docs),
      ParsedArgs.hasArg(OPT_include_spi_symbols),
      /*IncludeClangDocs=*/false,
  };

  if (auto *A = ParsedArgs.getLastArg(OPT_minimum_access_level)) {
    Options.MinimumAccessLevel =
        llvm::StringSwitch<AccessLevel>(A->getValue())
            .Case("open", AccessLevel::Open)
            .Case("public", AccessLevel::Public)
            .Case("internal", AccessLevel::Internal)
            .Case("fileprivate", AccessLevel::FilePrivate)
            .Case("private", AccessLevel::Private)
            .Default(AccessLevel::Public);
  }

  std::string InstanceSetupError;
  if (CI.setup(Invocation, InstanceSetupError)) {
    llvm::outs() << InstanceSetupError << '\n';
    return EXIT_FAILURE;
  }

  auto M = CI.getASTContext().getModuleByName(ModuleName);
  if (!M) {
    llvm::errs()
      << "Couldn't load module '" << ModuleName << '\''
      << " in the current SDK and search paths.\n";

    SmallVector<Identifier, 32> VisibleModuleNames;
    CI.getASTContext().getVisibleTopLevelModuleNames(VisibleModuleNames);

    if (VisibleModuleNames.empty()) {
      llvm::errs() << "Could not find any modules.\n";
    } else {
      std::sort(VisibleModuleNames.begin(), VisibleModuleNames.end(),
                [](const Identifier &A, const Identifier &B) -> bool {
        return A.str() < B.str();
      });
      llvm::errs() << "Current visible modules:\n";
      for (const auto &ModuleName : VisibleModuleNames) {
        llvm::errs() << ModuleName.str() << "\n";
      }
    }
    return EXIT_FAILURE;
  }

  if (M->failedToLoad()) {
    llvm::errs() << "Error: Failed to load the module '" << ModuleName
                 << "'. Are you missing build dependencies or "
                    "include/framework directories?\n"
                 << "See the previous error messages for details. Aborting.\n";

    return EXIT_FAILURE;
  }

  const auto &MainFile = M->getMainFile(FileUnitKind::SerializedAST);

  if (Options.PrintMessages)
    llvm::errs() << "Emitting symbol graph for module file: " << MainFile.getModuleDefiningPath() << '\n';

  int Success = symbolgraphgen::emitSymbolGraphForModule(M, Options);

  // Look for cross-import overlays that the given module imports.

  // Clear out the diagnostic printer before looking for cross-import overlay modules,
  // since some SDK modules can cause errors in the getModuleByName() call. The call
  // itself will properly return nullptr after this failure, so for our purposes we
  // don't need to print these errors.
  CI.removeDiagnosticConsumer(&DiagPrinter);

  SmallVector<ModuleDecl *, 8> Overlays;
  M->findDeclaredCrossImportOverlaysTransitive(Overlays);
  for (const auto *OM : Overlays) {
    auto CIM = CI.getASTContext().getModuleByName(OM->getNameStr());
    if (CIM) {
      const auto &CIMainFile = CIM->getMainFile(FileUnitKind::SerializedAST);

      if (Options.PrintMessages)
        llvm::errs() << "Emitting symbol graph for cross-import overlay module file: "
          << CIMainFile.getModuleDefiningPath() << '\n';

      Success |= symbolgraphgen::emitSymbolGraphForModule(CIM, Options);
    }
  }

  return Success;
}
<commit_msg>allow swift-symbolgraph-extract to be called on non-swift modules (#42399)<commit_after>//===--- swift_indent_main.cpp - Swift code formatting tool ---------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
//  Extracts a Symbol Graph from a .swiftmodule file.
//
//===----------------------------------------------------------------------===//

#include "swift/AST/DiagnosticsFrontend.h"
#include "swift/Basic/LLVM.h"
#include "swift/Basic/LLVMInitialize.h"
#include "swift/Basic/Version.h"
#include "swift/Frontend/Frontend.h"
#include "swift/Frontend/PrintingDiagnosticConsumer.h"
#include "swift/Option/Options.h"
#include "swift/SymbolGraphGen/SymbolGraphGen.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/raw_ostream.h"

using namespace swift;
using namespace options;

int swift_symbolgraph_extract_main(ArrayRef<const char *> Args,
                                   const char *Argv0, void *MainAddr) {
  INITIALIZE_LLVM();

  CompilerInvocation Invocation;
  CompilerInstance CI;
  PrintingDiagnosticConsumer DiagPrinter;
  auto &Diags = CI.getDiags();
  Diags.addConsumer(DiagPrinter);

  std::unique_ptr<llvm::opt::OptTable> Table = createSwiftOptTable();
  unsigned MissingIndex;
  unsigned MissingCount;
  llvm::opt::InputArgList ParsedArgs = Table->ParseArgs(
      Args, MissingIndex, MissingCount, SwiftSymbolGraphExtractOption);
  if (MissingCount) {
    Diags.diagnose(SourceLoc(), diag::error_missing_arg_value,
                   ParsedArgs.getArgString(MissingIndex), MissingCount);
    return EXIT_FAILURE;
  }

  if (ParsedArgs.hasArg(OPT_UNKNOWN)) {
    for (const auto *A : ParsedArgs.filtered(OPT_UNKNOWN)) {
      Diags.diagnose(SourceLoc(), diag::error_unknown_arg,
                     A->getAsString(ParsedArgs));
    }
    return EXIT_FAILURE;
  }

  auto MainExecutablePath = llvm::sys::fs::getMainExecutable(Argv0, MainAddr);

  if (ParsedArgs.getLastArg(OPT_help) || Args.empty()) {
    std::string ExecutableName =
        llvm::sys::path::stem(MainExecutablePath).str();
    Table->printHelp(llvm::outs(), ExecutableName.c_str(),
                     "Swift Symbol Graph Extractor",
                     SwiftSymbolGraphExtractOption, 0,
                     /*ShowAllAliases*/ false);
    return EXIT_FAILURE;
  }

  std::string ModuleName;
  if (auto *A = ParsedArgs.getLastArg(OPT_module_name)) {
    ModuleName = A->getValue();
  } else {
    Diags.diagnose(SourceLoc(), diag::error_option_required, "-module-name");
    return EXIT_FAILURE;
  }

  llvm::Triple Target;
  if (auto *A = ParsedArgs.getLastArg(OPT_target)) {
    Target = llvm::Triple(A->getValue());
  } else {
    Diags.diagnose(SourceLoc(), diag::error_option_required, "-target");
    return EXIT_FAILURE;
  }

  std::string OutputDir;
  if (auto *A = ParsedArgs.getLastArg(OPT_output_dir)) {
    OutputDir = A->getValue();
  } else {
    Diags.diagnose(SourceLoc(), diag::error_option_required, "-output-dir");
    return EXIT_FAILURE;
  }

  if (!llvm::sys::fs::is_directory(OutputDir)) {
    Diags.diagnose(SourceLoc(), diag::error_nonexistent_output_dir, OutputDir);
    return EXIT_FAILURE;
  }

  Invocation.setMainExecutablePath(MainExecutablePath);
  Invocation.setModuleName("swift_symbolgraph_extract");

  if (auto *A = ParsedArgs.getLastArg(OPT_resource_dir)) {
    Invocation.setRuntimeResourcePath(A->getValue());
  }

  std::string SDK = "";
  if (auto *A = ParsedArgs.getLastArg(OPT_sdk)) {
    SDK = A->getValue();
  }
  Invocation.setSDKPath(SDK);

  Invocation.setTargetTriple(Target);

  for (const auto *A : ParsedArgs.filtered(OPT_Xcc)) {
    Invocation.getClangImporterOptions().ExtraArgs.push_back(A->getValue());
  }

  std::vector<SearchPathOptions::FrameworkSearchPath> FrameworkSearchPaths;
  for (const auto *A : ParsedArgs.filtered(OPT_F)) {
    FrameworkSearchPaths.push_back({A->getValue(), /*isSystem*/ false});
  }
  for (const auto *A : ParsedArgs.filtered(OPT_Fsystem)) {
    FrameworkSearchPaths.push_back({A->getValue(), /*isSystem*/ true});
  }
  Invocation.setFrameworkSearchPaths(FrameworkSearchPaths);
  Invocation.getSearchPathOptions().LibrarySearchPaths =
      ParsedArgs.getAllArgValues(OPT_L);
  Invocation.setImportSearchPaths(ParsedArgs.getAllArgValues(OPT_I));

  Invocation.getLangOptions().EnableObjCInterop = Target.isOSDarwin();
  Invocation.getLangOptions().DebuggerSupport = true;

  Invocation.getFrontendOptions().EnableLibraryEvolution = true;

  std::string ModuleCachePath = "";
  if (auto *A = ParsedArgs.getLastArg(OPT_module_cache_path)) {
    ModuleCachePath = A->getValue();
  }
  Invocation.setClangModuleCachePath(ModuleCachePath);
  Invocation.getClangImporterOptions().ModuleCachePath = ModuleCachePath;
  Invocation.setDefaultPrebuiltCacheIfNecessary();

  if (auto *A = ParsedArgs.getLastArg(OPT_swift_version)) {
    using version::Version;
    auto SwiftVersion = A->getValue();
    bool isValid = false;
    if (auto Version =
            Version::parseVersionString(SwiftVersion, SourceLoc(), nullptr)) {
      if (auto Effective = Version.getValue().getEffectiveLanguageVersion()) {
        Invocation.getLangOptions().EffectiveLanguageVersion = *Effective;
        isValid = true;
      }
    }
    if (!isValid) {
      Diags.diagnose(SourceLoc(), diag::error_invalid_arg_value,
                     "-swift-version", SwiftVersion);
      return EXIT_FAILURE;
    }
  }

  symbolgraphgen::SymbolGraphOptions Options{
      OutputDir,
      Target,
      ParsedArgs.hasArg(OPT_pretty_print),
      AccessLevel::Public,
      !ParsedArgs.hasArg(OPT_skip_synthesized_members),
      ParsedArgs.hasArg(OPT_v),
      ParsedArgs.hasArg(OPT_skip_inherited_docs),
      ParsedArgs.hasArg(OPT_include_spi_symbols),
      /*IncludeClangDocs=*/false,
  };

  if (auto *A = ParsedArgs.getLastArg(OPT_minimum_access_level)) {
    Options.MinimumAccessLevel =
        llvm::StringSwitch<AccessLevel>(A->getValue())
            .Case("open", AccessLevel::Open)
            .Case("public", AccessLevel::Public)
            .Case("internal", AccessLevel::Internal)
            .Case("fileprivate", AccessLevel::FilePrivate)
            .Case("private", AccessLevel::Private)
            .Default(AccessLevel::Public);
  }

  std::string InstanceSetupError;
  if (CI.setup(Invocation, InstanceSetupError)) {
    llvm::outs() << InstanceSetupError << '\n';
    return EXIT_FAILURE;
  }

  auto M = CI.getASTContext().getModuleByName(ModuleName);
  if (!M) {
    llvm::errs()
      << "Couldn't load module '" << ModuleName << '\''
      << " in the current SDK and search paths.\n";

    SmallVector<Identifier, 32> VisibleModuleNames;
    CI.getASTContext().getVisibleTopLevelModuleNames(VisibleModuleNames);

    if (VisibleModuleNames.empty()) {
      llvm::errs() << "Could not find any modules.\n";
    } else {
      std::sort(VisibleModuleNames.begin(), VisibleModuleNames.end(),
                [](const Identifier &A, const Identifier &B) -> bool {
        return A.str() < B.str();
      });
      llvm::errs() << "Current visible modules:\n";
      for (const auto &ModuleName : VisibleModuleNames) {
        llvm::errs() << ModuleName.str() << "\n";
      }
    }
    return EXIT_FAILURE;
  }

  if (M->failedToLoad()) {
    llvm::errs() << "Error: Failed to load the module '" << ModuleName
                 << "'. Are you missing build dependencies or "
                    "include/framework directories?\n"
                 << "See the previous error messages for details. Aborting.\n";

    return EXIT_FAILURE;
  }

  FileUnitKind expectedKind = FileUnitKind::SerializedAST;
  if (M->isNonSwiftModule())
    expectedKind = FileUnitKind::ClangModule;
  const auto &MainFile = M->getMainFile(expectedKind);

  if (Options.PrintMessages)
    llvm::errs() << "Emitting symbol graph for module file: " << MainFile.getModuleDefiningPath() << '\n';

  int Success = symbolgraphgen::emitSymbolGraphForModule(M, Options);

  // Look for cross-import overlays that the given module imports.

  // Clear out the diagnostic printer before looking for cross-import overlay modules,
  // since some SDK modules can cause errors in the getModuleByName() call. The call
  // itself will properly return nullptr after this failure, so for our purposes we
  // don't need to print these errors.
  CI.removeDiagnosticConsumer(&DiagPrinter);

  SmallVector<ModuleDecl *, 8> Overlays;
  M->findDeclaredCrossImportOverlaysTransitive(Overlays);
  for (const auto *OM : Overlays) {
    auto CIM = CI.getASTContext().getModuleByName(OM->getNameStr());
    if (CIM) {
      const auto &CIMainFile = CIM->getMainFile(FileUnitKind::SerializedAST);

      if (Options.PrintMessages)
        llvm::errs() << "Emitting symbol graph for cross-import overlay module file: "
          << CIMainFile.getModuleDefiningPath() << '\n';

      Success |= symbolgraphgen::emitSymbolGraphForModule(CIM, Options);
    }
  }

  return Success;
}
<|endoftext|>


<commit_before>/***************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (directui@nokia.com)
**
** This file is part of libmeegotouch.
**
** If you have questions regarding the use of this file, please contact
** Nokia at directui@nokia.com.
**
** This library is free software; you can redistribute it and/or
** modify it under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation
** and appearing in the file LICENSE.LGPL included in the packaging
** of this file.
**
****************************************************************************/

#include "mbuttonview.h"
#include "mbuttonview_p.h"

#include <QPainter>
#include <QGraphicsSceneMouseEvent>
#include <QFontMetricsF>
#include <QPixmap>
#include <QIcon>

#include "mbutton.h"
#include "mfeedback.h"
#include "mtheme.h"
#include "mscalableimage.h"
#include "mviewcreator.h"
#include "mscenemanager.h"
#include "mlabel.h"
#include "mdebug.h"
#include "mtimestamp.h"

// Distance in pixels from the widget bounding box inside which a release is still accepted
#define RELEASE_MISS_DELTA 30

MButtonViewPrivate::MButtonViewPrivate()
    : icon(0), toggledIcon(0), label(NULL), iconFromQIcon(false), toggledIconFromQIcon(false)
{
}

void MButtonViewPrivate::freeIcons()
{
    if (iconFromQIcon && icon) {
        delete icon;
    } else {
        MTheme::releasePixmap(icon);
    }

    if (toggledIconFromQIcon && toggledIcon) {
        delete toggledIcon;
    } else {
        MTheme::releasePixmap(toggledIcon);
    }

    icon = 0;
    toggledIcon = 0;
}

MButtonViewPrivate::~MButtonViewPrivate()
{
    freeIcons();
}

// As the condition of text color and background change for button
bool MButtonViewPrivate::toggleState() const
{
    Q_Q(const MButtonView);
    if (q->model()->checkable()) {
        bool state = (!q->model()->checked() && q->model()->down())
                     || (q->model()->checked() && !q->model()->down());
        return state;
    } else
        return q->model()->down();
}

void MButtonViewPrivate::refreshStyleMode()
{
    Q_Q(MButtonView);

    if (q->model()->down())
        q->style().setModePressed();
    else if (q->model()->checked())
        q->style().setModeSelected();
    else
        q->style().setModeDefault();

    label->setAlignment(q->style()->horizontalTextAlign() | q->style()->verticalTextAlign());
    label->setFont(q->style()->font());
    label->setColor(q->style()->textColor());

    //update the icons only if the iconSize in the style has changed
    QSize size = q->style()->iconSize();
    if (icon && icon->size() != size) {
        if (iconFromQIcon)
            loadIcon(q->model()->icon(), size);
        else
            loadIcon(q->model()->iconID(), size);
    }
    if (toggledIcon && toggledIcon->size() != size) {
        if (toggledIconFromQIcon)
            loadIcon(q->model()->icon(), size);
        else
            loadIcon(q->model()->toggledIconID(), size, QIcon::Selected);
    }

    calcIconTextRects();
}

void MButtonViewPrivate::calcIconTextRects()
{
    Q_Q(const MButtonView);

    //total horizontal and vertical text margins
    int hTextMargin = q->style()->textMarginLeft() + q->style()->textMarginRight();
    int vTextMargin = q->style()->textMarginTop() + q->style()->textMarginBottom();

    //total horizontal and vertical padding
    int hPadding = q->style()->paddingLeft() + q->style()->paddingRight();
    int vPadding = q->style()->paddingTop() + q->style()->paddingBottom();

    //area for the content (icon and text)
    QRect contentRect(q->style()->paddingLeft(), q->style()->paddingTop(),
                      q->size().width() - hPadding,
                      q->size().height() - vPadding);

    //text rect when there is no icon
    QRect textRect = QRect(contentRect.left() + q->style()->textMarginLeft(),
                           contentRect.top() + q->style()->textMarginTop(),
                           contentRect.width() - hTextMargin,
                           contentRect.height() - vTextMargin);

    //icon visible and valid?
    if (q->model()->iconVisible() && (icon || toggledIcon)) {

        int iconWidth = q->style()->iconSize().width();
        int iconHeight = q->style()->iconSize().height();

        //text visible and valid?
        if (q->model()->textVisible() && !q->model()->text().isEmpty()) {

            switch (q->style()->iconAlign()) {
                //icon on left and text on right
            case Qt::AlignLeft: {
                iconRect = QRectF(contentRect.left(), contentRect.center().y() - (iconHeight / 2), iconWidth, iconHeight);
                textRect.setX(iconRect.right() + q->style()->textMarginLeft());
                textRect.setWidth(contentRect.width() - iconWidth - hTextMargin);
                break;
            }

            //icon on right and text on left
            case Qt::AlignRight: {
                iconRect = QRectF(contentRect.right() - iconWidth, contentRect.center().y() - (iconHeight / 2), iconWidth, iconHeight);
                textRect.setWidth(contentRect.width() - iconWidth - hTextMargin);
                break;
            }

            //icon on bottom and text on top
            case Qt::AlignBottom: {
                iconRect = QRectF(contentRect.center().x() - (iconWidth / 2), contentRect.bottom() - iconHeight, iconWidth, iconHeight);
                textRect.setHeight(contentRect.height() - iconHeight - vTextMargin);
                break;
            }

            //icon on top and text on bottom
            default: {
                iconRect = QRectF(contentRect.center().x() - (iconWidth / 2), contentRect.top(), iconWidth, iconHeight);
                textRect.setY(iconRect.bottom() + q->style()->textMarginTop());
                textRect.setHeight(contentRect.height() - iconHeight - vTextMargin);
                break;
            }
            }
        }
        // no text
        else {
            //icon on center
            iconRect = QRectF(contentRect.center().x() - (iconWidth / 2), contentRect.center().y() - (iconHeight / 2), iconWidth, iconHeight);
        }
    }

    //adjust label with button margins
    label->setGeometry(textRect.translated(q->marginLeft(), q->marginTop()));
}

void MButtonViewPrivate::loadIcon(const QIcon &newQIcon, const QSize &newIconSize)
{
    freeIcons();

    icon = new QPixmap(newQIcon.pixmap(newIconSize));
    iconFromQIcon = true;

    toggledIcon = new QPixmap(newQIcon.pixmap(newIconSize, QIcon::Selected));
    if (toggledIcon && !toggledIcon->isNull()) {
        toggledIconFromQIcon = true;
    }
}

void MButtonViewPrivate::loadIcon(const QString &newIconId, const QSize &newIconSize, QIcon::Mode mode)
{
    const QPixmap **tmp;
    bool *fromQIcon;

    if (mode == QIcon::Selected)
    {
        fromQIcon = &toggledIconFromQIcon;
        tmp = &toggledIcon;
    }
    else
    {
        fromQIcon = &iconFromQIcon;
        tmp = &icon;
    }

    if (*tmp)
    {
        if (*fromQIcon)
            delete *tmp;
        else
            MTheme::releasePixmap(*tmp);
    }

    *fromQIcon = false;
    *tmp = 0;

    if (!newIconId.isEmpty())
        *tmp = MTheme::pixmap(newIconId, newIconSize);
}

MButtonView::MButtonView(MButton *controller) :
    MWidgetView(* new MButtonViewPrivate, controller)
{
    Q_D(MButtonView);
    d->label = new MLabel(controller);
    d->label->setParentItem(controller);
    d->label->setTextElide(true);
    d->label->setObjectName("ButtonLabel");
}

MButtonView::MButtonView(MButtonViewPrivate &dd, MButton *controller) :
    MWidgetView(dd, controller)
{
    Q_D(MButtonView);
    d->label = new MLabel(controller);
    d->label->setParentItem(controller);
    d->label->setTextElide(true);
    d->label->setObjectName("ButtonLabel");
}

MButtonView::~MButtonView()
{
    Q_D(MButtonView);
    if (d->label) {
        delete d->label;
        d->label = 0;
    }
}

void MButtonView::resizeEvent(QGraphicsSceneResizeEvent *event)
{
    Q_D(MButtonView);

    MWidgetView::resizeEvent(event);

    d->calcIconTextRects();
}

void MButtonView::drawContents(QPainter *painter, const QStyleOptionGraphicsItem *option) const
{
    Q_UNUSED(option);

    Q_D(const MButtonView);
    mTimestamp("MButtonView", QString("start text=%1").arg(model()->text()));
    drawIcon(painter, d->iconRect);
    mTimestamp("MButtonView", QString("end text=%1").arg(model()->text()));
}

void MButtonView::drawIcon(QPainter *painter, const QRectF &iconRect) const
{
    if (model()->iconVisible()) {
        Q_D(const MButtonView);

        bool toggleState = d->toggleState();

        const QPixmap *pixmap = NULL;
        if (toggleState && d->toggledIcon)
            pixmap = d->toggledIcon;
        else
            pixmap = d->icon;

        if (pixmap)
            painter->drawPixmap(iconRect, *pixmap, QRectF(pixmap->rect()));
    }
}

/*MLabel* MButtonView::label()
{
    Q_D(const MButtonView);
    return d->label;
}*/

void MButtonView::applyStyle()
{
    Q_D(MButtonView);

    MWidgetView::applyStyle();

    d->refreshStyleMode();

    update();
}

void MButtonView::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
    Q_UNUSED(event);

    if (model()->down()) {
        return;
    }
    model()->setDown(true);

    style()->pressFeedback().play();
}

void MButtonView::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{
    Q_D(MButtonView);

    QPointF touch = event->scenePos();
    QRectF rect = d->controller->sceneBoundingRect();
    rect.adjust(-RELEASE_MISS_DELTA, -RELEASE_MISS_DELTA,
                RELEASE_MISS_DELTA, RELEASE_MISS_DELTA);

    if (rect.contains(touch)) {
        if (!model()->down()) {
            model()->setDown(true);
            style()->pressFeedback().play();
        }
    } else {
        if (model()->down()) {
            model()->setDown(false);
            style()->cancelFeedback().play();
        }
    }

}

void MButtonView::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
{
    Q_D(MButtonView);

    if (!model()->down()) {
        return;
    }
    model()->setDown(false);

    style()->releaseFeedback().play();

    QPointF touch = event->scenePos();
    QRectF rect = d->controller->sceneBoundingRect();
    rect.adjust(-RELEASE_MISS_DELTA, -RELEASE_MISS_DELTA,
                RELEASE_MISS_DELTA, RELEASE_MISS_DELTA);
    if (rect.contains(touch))
        model()->click();
}

void MButtonView::cancelEvent(MCancelEvent *event)
{
    Q_UNUSED(event);

    if (!model()->down()) {
        return;
    }

    style()->cancelFeedback().play();

    model()->setDown(false);
}

void MButtonView::updateData(const QList<const char *>& modifications)
{
    Q_D(MButtonView);

    MWidgetView::updateData(modifications);
    const char *member;
    foreach(member, modifications) {
        if (member == MButtonModel::Text) {
            d->label->setText(model()->text());
            d->calcIconTextRects();
        } else if (member == MButtonModel::TextVisible) {
            d->label->setVisible(model()->textVisible());
            d->calcIconTextRects();
        } else if (member == MButtonModel::IconID) {
            d->loadIcon(model()->iconID(), style()->iconSize());
            d->calcIconTextRects();
        } else if (member == MButtonModel::ToggledIconID) {
            d->loadIcon(model()->toggledIconID(), style()->iconSize(), QIcon::Selected);
            d->calcIconTextRects();
        } else if (member == MButtonModel::Icon) {
            d->loadIcon(model()->icon(), style()->iconSize());
            d->calcIconTextRects();
        } else if (member == MButtonModel::IconVisible) {
            d->calcIconTextRects();
        } else if (member == MButtonModel::Down || member == MButtonModel::Checked ||
                   member == MButtonModel::Checkable) {
            d->refreshStyleMode();
        }
    }
    update();
}

void MButtonView::setupModel()
{
    Q_D(MButtonView);

    MWidgetView::setupModel();
    QList<const char *> members;
    if (model()->icon().isNull())
        members << MButtonModel::IconID;
    else
        members << MButtonModel::Icon;
    if (!model()->toggledIconID().isEmpty())
        members << MButtonModel::ToggledIconID;

    updateData(members);

    d->label->setText(model()->text());
    d->label->setVisible(model()->textVisible());

    update();
}

QSizeF MButtonView::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
{
    Q_D(const MButtonView);

    if (which == Qt::MinimumSize || which == Qt::MaximumSize)
        return MWidgetView::sizeHint(which, constraint);

    if (style()->preferredSize().isValid())
        return style()->preferredSize();

    QSizeF iconSize(0, 0);
    if (model()->iconVisible() && d->icon)
        iconSize = d->icon->size();

    QSizeF textSize(0, 0);
    if (model()->textVisible() && !model()->text().isEmpty()) {
        QFontMetricsF fm(style()->font());
        textSize = fm.size(0, model()->text());
        textSize += QSizeF(style()->textMarginLeft() + style()->textMarginRight(), style()->textMarginTop() + style()->textMarginBottom());
    }

    qreal width = 0, height = 0;
    if (style()->iconAlign() == Qt::AlignTop || style()->iconAlign() == Qt::AlignBottom) {
        width  = qMax(iconSize.width(), textSize.width());
        height = iconSize.height() + textSize.height();
    } else {
        width  = iconSize.width() + textSize.width();
        height = qMax(iconSize.height(), textSize.height());
    }

    return QSizeF(width + style()->paddingLeft() + style()->paddingRight(), height + style()->paddingTop() + style()->paddingBottom());
}

M_REGISTER_VIEW_NEW(MButtonView, MButton)
<commit_msg>Changes: MButtonView - Using QRectF instead of QRect<commit_after>/***************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (directui@nokia.com)
**
** This file is part of libmeegotouch.
**
** If you have questions regarding the use of this file, please contact
** Nokia at directui@nokia.com.
**
** This library is free software; you can redistribute it and/or
** modify it under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation
** and appearing in the file LICENSE.LGPL included in the packaging
** of this file.
**
****************************************************************************/

#include "mbuttonview.h"
#include "mbuttonview_p.h"

#include <QPainter>
#include <QGraphicsSceneMouseEvent>
#include <QFontMetricsF>
#include <QPixmap>
#include <QIcon>

#include "mbutton.h"
#include "mfeedback.h"
#include "mtheme.h"
#include "mscalableimage.h"
#include "mviewcreator.h"
#include "mscenemanager.h"
#include "mlabel.h"
#include "mdebug.h"
#include "mtimestamp.h"

// Distance in pixels from the widget bounding box inside which a release is still accepted
#define RELEASE_MISS_DELTA 30

MButtonViewPrivate::MButtonViewPrivate()
    : icon(0), toggledIcon(0), label(NULL), iconFromQIcon(false), toggledIconFromQIcon(false)
{
}

void MButtonViewPrivate::freeIcons()
{
    if (iconFromQIcon && icon) {
        delete icon;
    } else {
        MTheme::releasePixmap(icon);
    }

    if (toggledIconFromQIcon && toggledIcon) {
        delete toggledIcon;
    } else {
        MTheme::releasePixmap(toggledIcon);
    }

    icon = 0;
    toggledIcon = 0;
}

MButtonViewPrivate::~MButtonViewPrivate()
{
    freeIcons();
}

// As the condition of text color and background change for button
bool MButtonViewPrivate::toggleState() const
{
    Q_Q(const MButtonView);
    if (q->model()->checkable()) {
        bool state = (!q->model()->checked() && q->model()->down())
                     || (q->model()->checked() && !q->model()->down());
        return state;
    } else
        return q->model()->down();
}

void MButtonViewPrivate::refreshStyleMode()
{
    Q_Q(MButtonView);

    if (q->model()->down())
        q->style().setModePressed();
    else if (q->model()->checked())
        q->style().setModeSelected();
    else
        q->style().setModeDefault();

    label->setAlignment(q->style()->horizontalTextAlign() | q->style()->verticalTextAlign());
    label->setFont(q->style()->font());
    label->setColor(q->style()->textColor());

    //update the icons only if the iconSize in the style has changed
    QSize size = q->style()->iconSize();
    if (icon && icon->size() != size) {
        if (iconFromQIcon)
            loadIcon(q->model()->icon(), size);
        else
            loadIcon(q->model()->iconID(), size);
    }
    if (toggledIcon && toggledIcon->size() != size) {
        if (toggledIconFromQIcon)
            loadIcon(q->model()->icon(), size);
        else
            loadIcon(q->model()->toggledIconID(), size, QIcon::Selected);
    }

    calcIconTextRects();
}

void MButtonViewPrivate::calcIconTextRects()
{
    Q_Q(const MButtonView);

    //total horizontal and vertical text margins
    int hTextMargin = q->style()->textMarginLeft() + q->style()->textMarginRight();
    int vTextMargin = q->style()->textMarginTop() + q->style()->textMarginBottom();

    //total horizontal and vertical padding
    int hPadding = q->style()->paddingLeft() + q->style()->paddingRight();
    int vPadding = q->style()->paddingTop() + q->style()->paddingBottom();

    //area for the content (icon and text)
    QRectF contentRect(q->style()->paddingLeft(), q->style()->paddingTop(),
                      q->size().width() - hPadding,
                      q->size().height() - vPadding);

    //text rect when there is no icon
    QRectF textRect(contentRect.left() + q->style()->textMarginLeft(),
                    contentRect.top() + q->style()->textMarginTop(),
                    contentRect.width() - hTextMargin,
                    contentRect.height() - vTextMargin);

    //icon visible and valid?
    if (q->model()->iconVisible() && (icon || toggledIcon)) {

        int iconWidth = q->style()->iconSize().width();
        int iconHeight = q->style()->iconSize().height();

        //text visible and valid?
        if (q->model()->textVisible() && !q->model()->text().isEmpty()) {

            switch (q->style()->iconAlign()) {
                //icon on left and text on right
            case Qt::AlignLeft: {
                iconRect = QRectF(contentRect.left(), contentRect.center().y() - (iconHeight / 2), iconWidth, iconHeight);
                textRect.setX(iconRect.right() + q->style()->textMarginLeft());
                textRect.setWidth(contentRect.width() - iconWidth - hTextMargin);
                break;
            }

            //icon on right and text on left
            case Qt::AlignRight: {
                iconRect = QRectF(contentRect.right() - iconWidth, contentRect.center().y() - (iconHeight / 2), iconWidth, iconHeight);
                textRect.setWidth(contentRect.width() - iconWidth - hTextMargin);
                break;
            }

            //icon on bottom and text on top
            case Qt::AlignBottom: {
                iconRect = QRectF(contentRect.center().x() - (iconWidth / 2), contentRect.bottom() - iconHeight, iconWidth, iconHeight);
                textRect.setHeight(contentRect.height() - iconHeight - vTextMargin);
                break;
            }

            //icon on top and text on bottom
            default: {
                iconRect = QRectF(contentRect.center().x() - (iconWidth / 2), contentRect.top(), iconWidth, iconHeight);
                textRect.setY(iconRect.bottom() + q->style()->textMarginTop());
                textRect.setHeight(contentRect.height() - iconHeight - vTextMargin);
                break;
            }
            }
        }
        // no text
        else {
            //icon on center
            iconRect = QRectF(contentRect.center().x() - (iconWidth / 2), contentRect.center().y() - (iconHeight / 2), iconWidth, iconHeight);
        }
    }

    //adjust label with button margins
    label->setGeometry(textRect.translated(q->marginLeft(), q->marginTop()));
}

void MButtonViewPrivate::loadIcon(const QIcon &newQIcon, const QSize &newIconSize)
{
    freeIcons();

    icon = new QPixmap(newQIcon.pixmap(newIconSize));
    iconFromQIcon = true;

    toggledIcon = new QPixmap(newQIcon.pixmap(newIconSize, QIcon::Selected));
    if (toggledIcon && !toggledIcon->isNull()) {
        toggledIconFromQIcon = true;
    }
}

void MButtonViewPrivate::loadIcon(const QString &newIconId, const QSize &newIconSize, QIcon::Mode mode)
{
    const QPixmap **tmp;
    bool *fromQIcon;

    if (mode == QIcon::Selected)
    {
        fromQIcon = &toggledIconFromQIcon;
        tmp = &toggledIcon;
    }
    else
    {
        fromQIcon = &iconFromQIcon;
        tmp = &icon;
    }

    if (*tmp)
    {
        if (*fromQIcon)
            delete *tmp;
        else
            MTheme::releasePixmap(*tmp);
    }

    *fromQIcon = false;
    *tmp = 0;

    if (!newIconId.isEmpty())
        *tmp = MTheme::pixmap(newIconId, newIconSize);
}

MButtonView::MButtonView(MButton *controller) :
    MWidgetView(* new MButtonViewPrivate, controller)
{
    Q_D(MButtonView);
    d->label = new MLabel(controller);
    d->label->setParentItem(controller);
    d->label->setTextElide(true);
    d->label->setObjectName("ButtonLabel");
}

MButtonView::MButtonView(MButtonViewPrivate &dd, MButton *controller) :
    MWidgetView(dd, controller)
{
    Q_D(MButtonView);
    d->label = new MLabel(controller);
    d->label->setParentItem(controller);
    d->label->setTextElide(true);
    d->label->setObjectName("ButtonLabel");
}

MButtonView::~MButtonView()
{
    Q_D(MButtonView);
    if (d->label) {
        delete d->label;
        d->label = 0;
    }
}

void MButtonView::resizeEvent(QGraphicsSceneResizeEvent *event)
{
    Q_D(MButtonView);

    MWidgetView::resizeEvent(event);

    d->calcIconTextRects();
}

void MButtonView::drawContents(QPainter *painter, const QStyleOptionGraphicsItem *option) const
{
    Q_UNUSED(option);

    Q_D(const MButtonView);
    mTimestamp("MButtonView", QString("start text=%1").arg(model()->text()));
    drawIcon(painter, d->iconRect);
    mTimestamp("MButtonView", QString("end text=%1").arg(model()->text()));
}

void MButtonView::drawIcon(QPainter *painter, const QRectF &iconRect) const
{
    if (model()->iconVisible()) {
        Q_D(const MButtonView);

        bool toggleState = d->toggleState();

        const QPixmap *pixmap = NULL;
        if (toggleState && d->toggledIcon)
            pixmap = d->toggledIcon;
        else
            pixmap = d->icon;

        if (pixmap)
            painter->drawPixmap(iconRect, *pixmap, QRectF(pixmap->rect()));
    }
}

/*MLabel* MButtonView::label()
{
    Q_D(const MButtonView);
    return d->label;
}*/

void MButtonView::applyStyle()
{
    Q_D(MButtonView);

    MWidgetView::applyStyle();

    d->refreshStyleMode();

    update();
}

void MButtonView::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
    Q_UNUSED(event);

    if (model()->down()) {
        return;
    }
    model()->setDown(true);

    style()->pressFeedback().play();
}

void MButtonView::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{
    Q_D(MButtonView);

    QPointF touch = event->scenePos();
    QRectF rect = d->controller->sceneBoundingRect();
    rect.adjust(-RELEASE_MISS_DELTA, -RELEASE_MISS_DELTA,
                RELEASE_MISS_DELTA, RELEASE_MISS_DELTA);

    if (rect.contains(touch)) {
        if (!model()->down()) {
            model()->setDown(true);
            style()->pressFeedback().play();
        }
    } else {
        if (model()->down()) {
            model()->setDown(false);
            style()->cancelFeedback().play();
        }
    }

}

void MButtonView::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
{
    Q_D(MButtonView);

    if (!model()->down()) {
        return;
    }
    model()->setDown(false);

    style()->releaseFeedback().play();

    QPointF touch = event->scenePos();
    QRectF rect = d->controller->sceneBoundingRect();
    rect.adjust(-RELEASE_MISS_DELTA, -RELEASE_MISS_DELTA,
                RELEASE_MISS_DELTA, RELEASE_MISS_DELTA);
    if (rect.contains(touch))
        model()->click();
}

void MButtonView::cancelEvent(MCancelEvent *event)
{
    Q_UNUSED(event);

    if (!model()->down()) {
        return;
    }

    style()->cancelFeedback().play();

    model()->setDown(false);
}

void MButtonView::updateData(const QList<const char *>& modifications)
{
    Q_D(MButtonView);

    MWidgetView::updateData(modifications);
    const char *member;
    foreach(member, modifications) {
        if (member == MButtonModel::Text) {
            d->label->setText(model()->text());
            d->calcIconTextRects();
        } else if (member == MButtonModel::TextVisible) {
            d->label->setVisible(model()->textVisible());
            d->calcIconTextRects();
        } else if (member == MButtonModel::IconID) {
            d->loadIcon(model()->iconID(), style()->iconSize());
            d->calcIconTextRects();
        } else if (member == MButtonModel::ToggledIconID) {
            d->loadIcon(model()->toggledIconID(), style()->iconSize(), QIcon::Selected);
            d->calcIconTextRects();
        } else if (member == MButtonModel::Icon) {
            d->loadIcon(model()->icon(), style()->iconSize());
            d->calcIconTextRects();
        } else if (member == MButtonModel::IconVisible) {
            d->calcIconTextRects();
        } else if (member == MButtonModel::Down || member == MButtonModel::Checked ||
                   member == MButtonModel::Checkable) {
            d->refreshStyleMode();
        }
    }
    update();
}

void MButtonView::setupModel()
{
    Q_D(MButtonView);

    MWidgetView::setupModel();
    QList<const char *> members;
    if (model()->icon().isNull())
        members << MButtonModel::IconID;
    else
        members << MButtonModel::Icon;
    if (!model()->toggledIconID().isEmpty())
        members << MButtonModel::ToggledIconID;

    updateData(members);

    d->label->setText(model()->text());
    d->label->setVisible(model()->textVisible());

    update();
}

QSizeF MButtonView::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
{
    Q_D(const MButtonView);

    if (which == Qt::MinimumSize || which == Qt::MaximumSize)
        return MWidgetView::sizeHint(which, constraint);

    if (style()->preferredSize().isValid())
        return style()->preferredSize();

    QSizeF iconSize(0, 0);
    if (model()->iconVisible() && d->icon)
        iconSize = d->icon->size();

    QSizeF textSize(0, 0);
    if (model()->textVisible() && !model()->text().isEmpty()) {
        QFontMetricsF fm(style()->font());
        textSize = fm.size(0, model()->text());
        textSize += QSizeF(style()->textMarginLeft() + style()->textMarginRight(), style()->textMarginTop() + style()->textMarginBottom());
    }

    qreal width = 0, height = 0;
    if (style()->iconAlign() == Qt::AlignTop || style()->iconAlign() == Qt::AlignBottom) {
        width  = qMax(iconSize.width(), textSize.width());
        height = iconSize.height() + textSize.height();
    } else {
        width  = iconSize.width() + textSize.width();
        height = qMax(iconSize.height(), textSize.height());
    }

    return QSizeF(width + style()->paddingLeft() + style()->paddingRight(), height + style()->paddingTop() + style()->paddingBottom());
}

M_REGISTER_VIEW_NEW(MButtonView, MButton)
<|endoftext|>


<commit_before>// __BEGIN_LICENSE__
// Copyright (C) 2006-2011 United States Government as represented by
// the Administrator of the National Aeronautics and Space Administration.
// All Rights Reserved.
// __END_LICENSE__

#ifdef _MSC_VER
#pragma warning(disable:4244)
#pragma warning(disable:4267)
#pragma warning(disable:4996)
#endif

#include <boost/program_options.hpp>
#include <boost/filesystem/operations.hpp>
#include <boost/filesystem/path.hpp>
namespace po = boost::program_options;
namespace fs = boost::filesystem;

#include <vw/Core/Debugging.h>
#include <vw/Math.h>
#include <vw/Image.h>
#include <vw/FileIO.h>
#include <vw/InterestPoint/InterestData.h>
#include <vw/Stereo/CorrelationView.h>
#include <vw/Stereo/CostFunctions.h>

using namespace vw;
using namespace vw::stereo;

int main( int argc, char *argv[] ) {
  try {

    std::string left_file_name, right_file_name;
    float log;
    int32 h_corr_min, h_corr_max;
    int32 v_corr_min, v_corr_max;
    int32 xkernel, ykernel;
    int lrthresh;
    int correlator_type;
    bool found_alignment = false;
    Matrix3x3 alignment;

    po::options_description desc("Options");
    desc.add_options()
      ("help,h", "Display this help message")
      ("left", po::value(&left_file_name), "Explicitly specify the \"left\" input file")
      ("right", po::value(&right_file_name), "Explicitly specify the \"right\" input file")
      ("log", po::value(&log)->default_value(1.4), "Apply LOG filter with the given sigma, or 0 to disable")
      ("h-corr-min", po::value(&h_corr_min)->default_value(-30), "Minimum horizontal disparity")
      ("h-corr-max", po::value(&h_corr_max)->default_value(-30), "Maximum horizontal disparity")
      ("v-corr-min", po::value(&v_corr_min)->default_value(-5), "Minimum vertical disparity")
      ("v-corr-max", po::value(&v_corr_max)->default_value(5), "Maximum vertical disparity")
      ("xkernel", po::value(&xkernel)->default_value(15), "Horizontal correlation kernel size")
      ("ykernel", po::value(&ykernel)->default_value(15), "Vertical correlation kernel size")
      ("lrthresh", po::value(&lrthresh)->default_value(2), "Left/right correspondence threshold")
      ("correlator-type", po::value(&correlator_type)->default_value(0), "0 - Abs difference; 1 - Sq Difference; 2 - NormXCorr")
      ("affine-subpix", "Enable affine adaptive sub-pixel correlation (slower, but more accurate)")
      ("pyramid", "Use the pyramid based correlator")
      ;
    po::positional_options_description p;
    p.add("left", 1);
    p.add("right", 1);

    po::variables_map vm;
    try {
      po::store( po::command_line_parser( argc, argv ).options(desc).positional(p).run(), vm );
      po::notify( vm );
    } catch (const po::error& e) {
      std::cout << "An error occured while parsing command line arguments.\n";
      std::cout << "\t" << e.what() << "\n\n";
      std::cout << desc << std::endl;
      return 1;
    }

    if( vm.count("help") ) {
      vw_out() << desc << std::endl;
      return 1;
    }

    if( vm.count("left") != 1 || vm.count("right") != 1 ) {
      vw_out() << "Error: Must specify one (and only one) left and right input file!" << std::endl;
      vw_out() << desc << std::endl;
      return 1;
    }

    std::string match_filename = fs::path( left_file_name ).replace_extension().string() + "__" + fs::path( right_file_name ).stem() + ".match";
    if ( fs::exists( match_filename ) ) {
      vw_out() << "Found a match file. Using it to pre-align images.\n";
      std::vector<ip::InterestPoint> matched_ip1, matched_ip2;
      ip::read_binary_match_file( match_filename,
                                  matched_ip1, matched_ip2 );
      std::vector<Vector3> ransac_ip1 = ip::iplist_to_vectorlist(matched_ip1);
      std::vector<Vector3> ransac_ip2 = ip::iplist_to_vectorlist(matched_ip2);
      vw::math::RandomSampleConsensus<vw::math::HomographyFittingFunctor, vw::math::InterestPointErrorMetric> ransac( vw::math::HomographyFittingFunctor(), vw::math::InterestPointErrorMetric(), 30 );
      alignment = ransac( ransac_ip2, ransac_ip1 );

      DiskImageView<PixelGray<float> > right_disk_image( right_file_name );
      right_file_name = "aligned_right.tif";
      write_image( right_file_name, transform(right_disk_image, HomographyTransform(alignment)),
                   TerminalProgressCallback( "tools.correlate", "Aligning: ") );
      found_alignment = true;
    }

    DiskImageView<PixelGray<float> > left_disk_image(left_file_name );
    DiskImageView<PixelGray<float> > right_disk_image(right_file_name );
    int cols = std::min(left_disk_image.cols(),right_disk_image.cols());
    int rows = std::min(left_disk_image.rows(),right_disk_image.rows());
    ImageViewRef<PixelGray<float> > left = edge_extend(left_disk_image,0,0,cols,rows);
    ImageViewRef<PixelGray<float> > right = edge_extend(right_disk_image,0,0,cols,rows);

    ImageViewRef<uint8> left_mask = select_channel(edge_mask(pixel_cast_rescale<uint8>(left)),1);
    ImageViewRef<uint8> right_mask = select_channel(edge_mask(pixel_cast_rescale<uint8>(right)),1);

    stereo::CostFunctionType corr_type = ABSOLUTE_DIFFERENCE;
    if (correlator_type == 1)
      corr_type = SQUARED_DIFFERENCE;
    else if (correlator_type == 2)
      corr_type = CROSS_CORRELATION;

    ImageView<PixelMask<Vector2f> > disparity_map;
    if (vm.count("pyramid")) {
      vw::Timer corr_timer("Correlation Time");
      disparity_map =
        stereo::pyramid_correlate( left, right, left_mask, right_mask,
                                   stereo::LaplacianOfGaussian(log),
                                   BBox2i(Vector2i(h_corr_min, v_corr_min),
                                          Vector2i(h_corr_max, v_corr_max)),
                                   Vector2i(xkernel, ykernel),
                                   corr_type, lrthresh );
    } else {
      vw::Timer corr_timer("Correlation Time");
      disparity_map =
        stereo::correlate( left, right,
                           stereo::LaplacianOfGaussian(log),
                           BBox2i(Vector2i(h_corr_min, v_corr_min),
                                  Vector2i(h_corr_max, v_corr_max)),
                           Vector2i(xkernel, ykernel),
                           corr_type, lrthresh );
    }

    ImageViewRef<PixelMask<Vector2f> > result = disparity_map;
    if ( found_alignment )
      result = transform_disparities(disparity_map, HomographyTransform(alignment) );

    // Write disparity debug images
    BBox2 disp_range = get_disparity_range(result);
    std::cout << "Found disparity range: " << disp_range << "\n";
    ImageViewRef<float32> horizontal = apply_mask(copy_mask(clamp(normalize(select_channel(result,0), disp_range.min().x(), disp_range.max().x(),0,1)),result));
    ImageViewRef<float32> vertical = apply_mask(copy_mask(clamp(normalize(select_channel(result,1), disp_range.min().y(), disp_range.max().y(),0,1)),result));

    write_image( "x_disparity.png", channel_cast_rescale<uint8>(horizontal) );
    write_image( "y_disparity.png", channel_cast_rescale<uint8>(vertical) );
  }
  catch (const vw::Exception& e) {
    std::cerr << "Error: " << e.what() << std::endl;
  }
  return 0;
}

<commit_msg>correlate: Write a better version that is more like my tests<commit_after>// __BEGIN_LICENSE__
// Copyright (C) 2006-2011 United States Government as represented by
// the Administrator of the National Aeronautics and Space Administration.
// All Rights Reserved.
// __END_LICENSE__

#ifdef _MSC_VER
#pragma warning(disable:4244)
#pragma warning(disable:4267)
#pragma warning(disable:4996)
#endif

#include <boost/program_options.hpp>
#include <boost/filesystem/operations.hpp>
#include <boost/filesystem/path.hpp>
namespace po = boost::program_options;
namespace fs = boost::filesystem;

#include <vw/Core/Debugging.h>
#include <vw/Math.h>
#include <vw/Image.h>
#include <vw/FileIO.h>
#include <vw/InterestPoint/InterestData.h>
#include <vw/Stereo/CorrelationView.h>
#include <vw/Stereo/CostFunctions.h>

using namespace vw;
using namespace vw::stereo;

int main( int argc, char *argv[] ) {
  try {

    std::string left_file_name, right_file_name;
    float log;
    int32 h_corr_min, h_corr_max;
    int32 v_corr_min, v_corr_max;
    int32 xkernel, ykernel;
    int lrthresh;
    int correlator_type;
    bool found_alignment = false;
    Matrix3x3 alignment;

    po::options_description desc("Options");
    desc.add_options()
      ("help,h", "Display this help message")
      ("left", po::value(&left_file_name), "Explicitly specify the \"left\" input file")
      ("right", po::value(&right_file_name), "Explicitly specify the \"right\" input file")
      ("log", po::value(&log)->default_value(1.4), "Apply LOG filter with the given sigma, or 0 to disable")
      ("h-corr-min", po::value(&h_corr_min)->default_value(-30), "Minimum horizontal disparity")
      ("h-corr-max", po::value(&h_corr_max)->default_value(-30), "Maximum horizontal disparity")
      ("v-corr-min", po::value(&v_corr_min)->default_value(-5), "Minimum vertical disparity")
      ("v-corr-max", po::value(&v_corr_max)->default_value(5), "Maximum vertical disparity")
      ("xkernel", po::value(&xkernel)->default_value(15), "Horizontal correlation kernel size")
      ("ykernel", po::value(&ykernel)->default_value(15), "Vertical correlation kernel size")
      ("lrthresh", po::value(&lrthresh)->default_value(2), "Left/right correspondence threshold")
      ("correlator-type", po::value(&correlator_type)->default_value(0), "0 - Abs difference; 1 - Sq Difference; 2 - NormXCorr")
      ("affine-subpix", "Enable affine adaptive sub-pixel correlation (slower, but more accurate)")
      ("pyramid", "Use the pyramid based correlator")
      ;
    po::positional_options_description p;
    p.add("left", 1);
    p.add("right", 1);

    po::variables_map vm;
    try {
      po::store( po::command_line_parser( argc, argv ).options(desc).positional(p).run(), vm );
      po::notify( vm );
    } catch (const po::error& e) {
      std::cout << "An error occured while parsing command line arguments.\n";
      std::cout << "\t" << e.what() << "\n\n";
      std::cout << desc << std::endl;
      return 1;
    }

    if( vm.count("help") ) {
      vw_out() << desc << std::endl;
      return 1;
    }

    if( vm.count("left") != 1 || vm.count("right") != 1 ) {
      vw_out() << "Error: Must specify one (and only one) left and right input file!" << std::endl;
      vw_out() << desc << std::endl;
      return 1;
    }

    std::string match_filename = fs::path( left_file_name ).replace_extension().string() + "__" + fs::path( right_file_name ).stem() + ".match";
    if ( fs::exists( match_filename ) ) {
      vw_out() << "Found a match file. Using it to pre-align images.\n";
      std::vector<ip::InterestPoint> matched_ip1, matched_ip2;
      ip::read_binary_match_file( match_filename,
                                  matched_ip1, matched_ip2 );
      std::vector<Vector3> ransac_ip1 = ip::iplist_to_vectorlist(matched_ip1);
      std::vector<Vector3> ransac_ip2 = ip::iplist_to_vectorlist(matched_ip2);
      vw::math::RandomSampleConsensus<vw::math::HomographyFittingFunctor, vw::math::InterestPointErrorMetric> ransac( vw::math::HomographyFittingFunctor(), vw::math::InterestPointErrorMetric(), 30 );
      alignment = ransac( ransac_ip2, ransac_ip1 );

      DiskImageView<PixelGray<float> > right_disk_image( right_file_name );
      right_file_name = "aligned_right.tif";
      write_image( right_file_name, transform(right_disk_image, HomographyTransform(alignment)),
                   TerminalProgressCallback( "tools.correlate", "Aligning: ") );
      found_alignment = true;
    }

    DiskImageView<PixelGray<float> > left_disk_image(left_file_name );
    DiskImageView<PixelGray<float> > right_disk_image(right_file_name );
    int cols = std::min(left_disk_image.cols(),right_disk_image.cols());
    int rows = std::min(left_disk_image.rows(),right_disk_image.rows());
    ImageViewRef<PixelGray<float> > left = edge_extend(left_disk_image,0,0,cols,rows);
    ImageViewRef<PixelGray<float> > right = edge_extend(right_disk_image,0,0,cols,rows);

    stereo::CostFunctionType corr_type = ABSOLUTE_DIFFERENCE;
    if (correlator_type == 1)
      corr_type = SQUARED_DIFFERENCE;
    else if (correlator_type == 2)
      corr_type = CROSS_CORRELATION;

    ImageViewRef<PixelMask<Vector2i> > disparity_map;
    if (vm.count("pyramid")) {
      disparity_map =
        stereo::pyramid_correlate( left, right,
                                   constant_view( uint8(255), left ),
                                   constant_view( uint8(255), right ),
                                   stereo::LaplacianOfGaussian(log),
                                   BBox2i(Vector2i(h_corr_min, v_corr_min),
                                          Vector2i(h_corr_max, v_corr_max)),
                                   Vector2i(xkernel, ykernel),
                                   corr_type, lrthresh );
    } else {
      disparity_map =
        stereo::correlate( left, right,
                           stereo::LaplacianOfGaussian(log),
                           BBox2i(Vector2i(h_corr_min, v_corr_min),
                                  Vector2i(h_corr_max, v_corr_max)),
                           Vector2i(xkernel, ykernel),
                           corr_type, lrthresh );
    }

    ImageViewRef<PixelMask<Vector2f> > result = pixel_cast<PixelMask<Vector2f> >(disparity_map);
    if ( found_alignment )
      result = pixel_cast<PixelMask<Vector2f> >(transform_disparities(disparity_map, HomographyTransform(alignment) ) );

    // Actually invoke the raster
    {
      vw::Timer corr_timer("Correlation Time");
      boost::scoped_ptr<DiskImageResource> r(DiskImageResource::create("disparity.tif",result.format()));
      r->set_block_write_size( Vector2i(1024,1024) );
      block_write_image( *r, result,
                         TerminalProgressCallback( "", "Rendering: ") );
    }

    // Write disparity debug images
    DiskImageView<PixelMask<Vector2f> > solution("disparity.tif");
    BBox2 disp_range = get_disparity_range(solution);
    std::cout << "Found disparity range: " << disp_range << "\n";

    write_image( "x_disparity.tif",
                 channel_cast<uint8>(apply_mask(copy_mask(clamp(normalize(select_channel(solution,0), disp_range.min().x(), disp_range.max().x(),0,255)),solution))) );
    write_image( "y_disparity.tif",
                 channel_cast<uint8>(apply_mask(copy_mask(clamp(normalize(select_channel(solution,1), disp_range.min().y(), disp_range.max().y(),0,255)),solution))) );
  }
  catch (const vw::Exception& e) {
    std::cerr << "Error: " << e.what() << std::endl;
  }
  return 0;
}

<|endoftext|>


<commit_before>/*****************************************************************************
*  Copyright 2005 Alt-N Technologies, Ltd.
*
*  Licensed under the Apache License, Version 2.0 (the "License");
*  you may not use this file except in compliance with the License.
*  You may obtain a copy of the License at
*
*      http://www.apache.org/licenses/LICENSE-2.0
*
*  This code incorporates intellectual property owned by Yahoo! and licensed
*  pursuant to the Yahoo! DomainKeys Patent License Agreement.
*
*  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.
*
*****************************************************************************/

#ifdef WIN32
#include <windows.h>
#else
#define strnicmp strncasecmp
#endif

#include <stdio.h>
#include <string.h>
#include <time.h>
#include <stdlib.h>

#include "dkim.h"
#include "dns.h"

// change these to your selector name, domain name, etc
#define MYSELECTOR	"MDaemon"
#define MYDOMAIN	"bardenhagen.com"
#define MYIDENTITY	"dkimtest@bardenhagen.com"

int DKIM_CALL SignThisHeader(const char* szHeader)
{
	if( strnicmp( szHeader, "X-", 2 ) == 0 )
	{
		return 0;
	}

	return 1;
}

int DKIM_CALL SelectorCallback(const char* szFQDN, char* szBuffer, int nBufLen )
{
	return 0;
}

void usage()
{

	printf( "usage: libdkimtest [-b<allman|ietf|both>] [-c<r|s|t|u>] [-d<domain>] [-l] [-h] [-i<you@yourdomain.com>] [-q] [-s] [-t] [-v] [-x<expire time>] [-z<hash>] <msgfile> <privkeyfile> <outfile>\n" );
	printf( "-b<standard> allman , ietf or both\n" );
	printf( "-c<canonicalization> r for relaxed [DEFAULT], s - simple, t relaxed/simple, u - simple/relaxed\n" );
	printf( "-d<domain> the domain tag, if not provided it will be determined from the sender/from header\n" );
	printf( "-l include body length tag\n" );
	printf( "-h this help\n" );
	printf( "-i<identity> the identity, if not provided it will not be included\n" );
	printf( "-s sign the message\n" );
	printf( "-t include a timestamp tag\n" );
	printf( "-v verify the message\n" );
	printf( "-x<expire_time> the expire time in seconds since epoch ( DEFAULT = current time + 604800)\n\t if set to - then it will not be included" );
	printf( "-z<hash>  1 for sha1, 2 for sha256, 3 for both\n" );
	printf( "-y<selector> the selector tag DEFAULT=MDaemon\n" );
}
int main(int argc, char* argv[])
{
	int n;
	const char* PrivKeyFile = "test.pem";
	const char* MsgFile = "test.msg";
	const char* OutFile = "signed.msg";
	int nPrivKeyLen;
	char PrivKey[2048];
	char Buffer[1024];
	int BufLen;
	char szSignature[10024];
	time_t t;
	DKIMContext ctxt;
	DKIMSignOptions opts = {0};

	opts.nHash = DKIM_HASH_SHA1_AND_256;

	time(&t);

	opts.nCanon = DKIM_SIGN_RELAXED;
	opts.nIncludeBodyLengthTag = 0;
	opts.nIncludeQueryMethod = 0;
	opts.nIncludeTimeStamp = 0;
	opts.expireTime = t + 604800;		// expires in 1 week
	strcpy( opts.szSelector, MYSELECTOR );
	strcpy( opts.szDomain, MYDOMAIN );
	strcpy( opts.szIdentity, MYIDENTITY );
	opts.pfnHeaderCallback = SignThisHeader;
	strcpy( opts.szRequiredHeaders, "NonExistant" );
	opts.nIncludeCopiedHeaders = 0;
	opts.nIncludeBodyHash = DKIM_BODYHASH_BOTH;

	int nArgParseState = 0;
	bool bSign = true;

	if( argc < 2 )
	{
		usage();
		return 1;
	}

	for( n = 1; n < argc; n++ )
	{
		if( argv[n][0] == '-' && strlen(argv[n]) > 1 )
		{
			switch( argv[n][1] )
			{
			case 'b':		// allman or ietf draft 1 or both
				opts.nIncludeBodyHash = atoi( &argv[n][2] );
				break;

			case 'c':		// canonicalization
				if( argv[n][2] == 'r' )
				{
					opts.nCanon = DKIM_SIGN_RELAXED;
				}
				else if( argv[n][2] == 's' )
				{
					opts.nCanon = DKIM_SIGN_SIMPLE;
				}
				else if( argv[n][2] == 't' )
				{
					opts.nCanon = DKIM_SIGN_RELAXED_SIMPLE;
				}
				else if( argv[n][2] == 'u' )
				{
					opts.nCanon = DKIM_SIGN_SIMPLE_RELAXED;
				}
				break;

			case 'd':
				strncpy( opts.szDomain, (const char*) (argv[n] + 2), sizeof(opts.szDomain) - 1 );
				break;
			case 'l':		// body length tag
				opts.nIncludeBodyLengthTag = 1;
				break;

			case 'h':
				usage();
				return 0;

			case 'i':		// identity
				if( argv[n][2] == '-' )
				{
					opts.szIdentity[0] = '\0';
				}
				else
				{
					strncpy( opts.szIdentity, argv[n] + 2, sizeof(opts.szIdentity) - 1 );
				}
				break;

			case 'q':		// query method tag
				opts.nIncludeQueryMethod = 1;
				break;

			case 's':		// sign
				bSign = true;
				break;

			case 't':		// timestamp tag
				opts.nIncludeTimeStamp = 1;
				break;

			case 'v':		// verify
				bSign = false;
				break;

			case 'x':		// expire time
				if( argv[n][2] == '-' )
				{
					opts.expireTime = 0;
				}
				else
				{
					opts.expireTime = t + atoi( argv[n] + 2  );
				}
				break;

			case 'y':
				strncpy( opts.szSelector, argv[n] + 2, sizeof(opts.szSelector) - 1 );
				break;

			case 'z':		// sign w/ sha1, sha256 or both
				opts.nHash = atoi( &argv[n][2] );
				break;
			}
		}
		else
		{
			switch( nArgParseState )
			{
			case 0:
				MsgFile = argv[n];
				break;
			case 1:
				PrivKeyFile = argv[n];
				break;
			case 2:
				OutFile = argv[n];
				break;
			}
			nArgParseState++;
		}
	}

	if( bSign )
	{
		FILE* PrivKeyFP = fopen( PrivKeyFile, "r" );

		if ( PrivKeyFP == NULL )
		{
		  printf( "dkimlibtest: can't open private key file %s\n", PrivKeyFile );
		  exit(1);
		}
		nPrivKeyLen = fread( PrivKey, 1, sizeof(PrivKey), PrivKeyFP );
		if (nPrivKeyLen == sizeof(PrivKey)) { /* TC9 */
		  printf( "dkimlibtest: private key buffer isn't big enough, use a smaller private key or recompile.\n");
		  exit(1);
		}
		PrivKey[nPrivKeyLen] = '\0';
		fclose(PrivKeyFP);

		FILE* MsgFP = fopen( MsgFile, "rb" );

		if ( MsgFP == NULL )
		{
			printf( "dkimlibtest: can't open msg file %s\n", MsgFile );
			exit(1);
		}

		n = DKIMSignInit( &ctxt, &opts );

		while (1) {

			BufLen = fread( Buffer, 1, sizeof(Buffer), MsgFP );

			if( BufLen > 0 )
			{
				DKIMSignProcess( &ctxt, Buffer, BufLen );
			}
			else
			{
				break;
			}
		}

		fclose( MsgFP );

		//n = DKIMSignGetSig( &ctxt, PrivKey, szSignature, sizeof(szSignature) );

		char* pSig = NULL;

		n = DKIMSignGetSig2( &ctxt, PrivKey, &pSig );

		strcpy( szSignature, pSig );

		DKIMSignFree( &ctxt );

		FILE* in = fopen( MsgFile, "rb" );
		FILE* out = fopen( OutFile, "wb+" );

		fwrite( szSignature, 1, strlen(szSignature), out );
		fwrite( "\r\n", 1, 2, out );

		while (1) {

			BufLen = fread( Buffer, 1, sizeof(Buffer), in );

			if( BufLen > 0 )
			{
				fwrite( Buffer, 1, BufLen, out );
			}
			else
			{
				break;
			}
		}

		fclose( in );
	}
	else
	{
		FILE* in = fopen( MsgFile, "rb" );

		DKIMVerifyOptions vopts = {0};
		vopts.pfnSelectorCallback = NULL; //SelectorCallback;

		n = DKIMVerifyInit( &ctxt, &vopts );

		while (1) {

			BufLen = fread( Buffer, 1, sizeof(Buffer), in );

			if( BufLen > 0 )
			{
				DKIMVerifyProcess( &ctxt, Buffer, BufLen );
			}
			else
			{
				break;
			}
		}

		n = DKIMVerifyResults( &ctxt );

		int nSigCount = 0;
		DKIMVerifyDetails* pDetails;
		char szPolicy[512];

		n = DKIMVerifyGetDetails(&ctxt, &nSigCount, &pDetails, szPolicy );

		for ( int i = 0; i < nSigCount; i++)
		{
			printf( "Signature #%d: ", i + 1 );

			if( pDetails[i].nResult >= 0 )
				printf( "Success\n" );
			else
				printf( "Failure\n" );
		}

		DKIMVerifyFree( &ctxt );
	}

	return 0;
}
<commit_msg>added error code to 'Failure' output<commit_after>/*****************************************************************************
*  Copyright 2005 Alt-N Technologies, Ltd.
*
*  Licensed under the Apache License, Version 2.0 (the "License");
*  you may not use this file except in compliance with the License.
*  You may obtain a copy of the License at
*
*      http://www.apache.org/licenses/LICENSE-2.0
*
*  This code incorporates intellectual property owned by Yahoo! and licensed
*  pursuant to the Yahoo! DomainKeys Patent License Agreement.
*
*  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.
*
*****************************************************************************/

#ifdef WIN32
#include <windows.h>
#else
#define strnicmp strncasecmp
#endif

#include <stdio.h>
#include <string.h>
#include <time.h>
#include <stdlib.h>

#include "dkim.h"
#include "dns.h"

// change these to your selector name, domain name, etc
#define MYSELECTOR	"MDaemon"
#define MYDOMAIN	"bardenhagen.com"
#define MYIDENTITY	"dkimtest@bardenhagen.com"

int DKIM_CALL SignThisHeader(const char* szHeader)
{
	if( strnicmp( szHeader, "X-", 2 ) == 0 )
	{
		return 0;
	}

	return 1;
}

int DKIM_CALL SelectorCallback(const char* szFQDN, char* szBuffer, int nBufLen )
{
	return 0;
}

void usage()
{

	printf( "usage: libdkimtest [-b<allman|ietf|both>] [-c<r|s|t|u>] [-d<domain>] [-l] [-h] [-i<you@yourdomain.com>] [-q] [-s] [-t] [-v] [-x<expire time>] [-z<hash>] <msgfile> <privkeyfile> <outfile>\n" );
	printf( "-b<standard> allman , ietf or both\n" );
	printf( "-c<canonicalization> r for relaxed [DEFAULT], s - simple, t relaxed/simple, u - simple/relaxed\n" );
	printf( "-d<domain> the domain tag, if not provided it will be determined from the sender/from header\n" );
	printf( "-l include body length tag\n" );
	printf( "-h this help\n" );
	printf( "-i<identity> the identity, if not provided it will not be included\n" );
	printf( "-s sign the message\n" );
	printf( "-t include a timestamp tag\n" );
	printf( "-v verify the message\n" );
	printf( "-x<expire_time> the expire time in seconds since epoch ( DEFAULT = current time + 604800)\n\t if set to - then it will not be included" );
	printf( "-z<hash>  1 for sha1, 2 for sha256, 3 for both\n" );
	printf( "-y<selector> the selector tag DEFAULT=MDaemon\n" );
}
int main(int argc, char* argv[])
{
	int n;
	const char* PrivKeyFile = "test.pem";
	const char* MsgFile = "test.msg";
	const char* OutFile = "signed.msg";
	int nPrivKeyLen;
	char PrivKey[2048];
	char Buffer[1024];
	int BufLen;
	char szSignature[10024];
	time_t t;
	DKIMContext ctxt;
	DKIMSignOptions opts = {0};

	opts.nHash = DKIM_HASH_SHA1_AND_256;

	time(&t);

	opts.nCanon = DKIM_SIGN_RELAXED;
	opts.nIncludeBodyLengthTag = 0;
	opts.nIncludeQueryMethod = 0;
	opts.nIncludeTimeStamp = 0;
	opts.expireTime = t + 604800;		// expires in 1 week
	strcpy( opts.szSelector, MYSELECTOR );
	strcpy( opts.szDomain, MYDOMAIN );
	strcpy( opts.szIdentity, MYIDENTITY );
	opts.pfnHeaderCallback = SignThisHeader;
	strcpy( opts.szRequiredHeaders, "NonExistant" );
	opts.nIncludeCopiedHeaders = 0;
	opts.nIncludeBodyHash = DKIM_BODYHASH_BOTH;

	int nArgParseState = 0;
	bool bSign = true;

	if( argc < 2 )
	{
		usage();
		return 1;
	}

	for( n = 1; n < argc; n++ )
	{
		if( argv[n][0] == '-' && strlen(argv[n]) > 1 )
		{
			switch( argv[n][1] )
			{
			case 'b':		// allman or ietf draft 1 or both
				opts.nIncludeBodyHash = atoi( &argv[n][2] );
				break;

			case 'c':		// canonicalization
				if( argv[n][2] == 'r' )
				{
					opts.nCanon = DKIM_SIGN_RELAXED;
				}
				else if( argv[n][2] == 's' )
				{
					opts.nCanon = DKIM_SIGN_SIMPLE;
				}
				else if( argv[n][2] == 't' )
				{
					opts.nCanon = DKIM_SIGN_RELAXED_SIMPLE;
				}
				else if( argv[n][2] == 'u' )
				{
					opts.nCanon = DKIM_SIGN_SIMPLE_RELAXED;
				}
				break;

			case 'd':
				strncpy( opts.szDomain, (const char*) (argv[n] + 2), sizeof(opts.szDomain) - 1 );
				break;
			case 'l':		// body length tag
				opts.nIncludeBodyLengthTag = 1;
				break;

			case 'h':
				usage();
				return 0;

			case 'i':		// identity
				if( argv[n][2] == '-' )
				{
					opts.szIdentity[0] = '\0';
				}
				else
				{
					strncpy( opts.szIdentity, argv[n] + 2, sizeof(opts.szIdentity) - 1 );
				}
				break;

			case 'q':		// query method tag
				opts.nIncludeQueryMethod = 1;
				break;

			case 's':		// sign
				bSign = true;
				break;

			case 't':		// timestamp tag
				opts.nIncludeTimeStamp = 1;
				break;

			case 'v':		// verify
				bSign = false;
				break;

			case 'x':		// expire time
				if( argv[n][2] == '-' )
				{
					opts.expireTime = 0;
				}
				else
				{
					opts.expireTime = t + atoi( argv[n] + 2  );
				}
				break;

			case 'y':
				strncpy( opts.szSelector, argv[n] + 2, sizeof(opts.szSelector) - 1 );
				break;

			case 'z':		// sign w/ sha1, sha256 or both
				opts.nHash = atoi( &argv[n][2] );
				break;
			}
		}
		else
		{
			switch( nArgParseState )
			{
			case 0:
				MsgFile = argv[n];
				break;
			case 1:
				PrivKeyFile = argv[n];
				break;
			case 2:
				OutFile = argv[n];
				break;
			}
			nArgParseState++;
		}
	}

	if( bSign )
	{
		FILE* PrivKeyFP = fopen( PrivKeyFile, "r" );

		if ( PrivKeyFP == NULL )
		{
		  printf( "dkimlibtest: can't open private key file %s\n", PrivKeyFile );
		  exit(1);
		}
		nPrivKeyLen = fread( PrivKey, 1, sizeof(PrivKey), PrivKeyFP );
		if (nPrivKeyLen == sizeof(PrivKey)) { /* TC9 */
		  printf( "dkimlibtest: private key buffer isn't big enough, use a smaller private key or recompile.\n");
		  exit(1);
		}
		PrivKey[nPrivKeyLen] = '\0';
		fclose(PrivKeyFP);

		FILE* MsgFP = fopen( MsgFile, "rb" );

		if ( MsgFP == NULL )
		{
			printf( "dkimlibtest: can't open msg file %s\n", MsgFile );
			exit(1);
		}

		n = DKIMSignInit( &ctxt, &opts );

		while (1) {

			BufLen = fread( Buffer, 1, sizeof(Buffer), MsgFP );

			if( BufLen > 0 )
			{
				DKIMSignProcess( &ctxt, Buffer, BufLen );
			}
			else
			{
				break;
			}
		}

		fclose( MsgFP );

		//n = DKIMSignGetSig( &ctxt, PrivKey, szSignature, sizeof(szSignature) );

		char* pSig = NULL;

		n = DKIMSignGetSig2( &ctxt, PrivKey, &pSig );

		strcpy( szSignature, pSig );

		DKIMSignFree( &ctxt );

		FILE* in = fopen( MsgFile, "rb" );
		FILE* out = fopen( OutFile, "wb+" );

		fwrite( szSignature, 1, strlen(szSignature), out );
		fwrite( "\r\n", 1, 2, out );

		while (1) {

			BufLen = fread( Buffer, 1, sizeof(Buffer), in );

			if( BufLen > 0 )
			{
				fwrite( Buffer, 1, BufLen, out );
			}
			else
			{
				break;
			}
		}

		fclose( in );
	}
	else
	{
		FILE* in = fopen( MsgFile, "rb" );

		DKIMVerifyOptions vopts = {0};
		vopts.pfnSelectorCallback = NULL; //SelectorCallback;

		n = DKIMVerifyInit( &ctxt, &vopts );

		while (1) {

			BufLen = fread( Buffer, 1, sizeof(Buffer), in );

			if( BufLen > 0 )
			{
				DKIMVerifyProcess( &ctxt, Buffer, BufLen );
			}
			else
			{
				break;
			}
		}

		n = DKIMVerifyResults( &ctxt );

		int nSigCount = 0;
		DKIMVerifyDetails* pDetails;
		char szPolicy[512];

		n = DKIMVerifyGetDetails(&ctxt, &nSigCount, &pDetails, szPolicy );

		for ( int i = 0; i < nSigCount; i++)
		{
			printf( "Signature #%d: ", i + 1 );

			if( pDetails[i].nResult >= 0 )
				printf( "Success\n" );
			else
				printf( "Failure %i\n", pDetails[i].nResult );
		}

		DKIMVerifyFree( &ctxt );
	}

	return 0;
}
<|endoftext|>


<commit_before>/*
 * ArcEmu MMORPG Server
 * Copyright (C) 2005-2007 Ascent Team <http://www.ascentemu.com/>
 * Copyright (C) 2008-2012 <http://www.ArcEmu.org/>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

#include "Master.h"
#include "Util\Util.h"

#ifndef WIN32
#include <sys/resource.h>
#endif
#include "System/CrashHandler.h"

#ifndef WIN32
int unix_main(int argc, char** argv)
{
	rlimit rl;
	if(getrlimit(RLIMIT_CORE, &rl) == -1)
		printf("getrlimit failed. This could be problem.\n");
	else
	{
		rl.rlim_cur = rl.rlim_max;
		if(setrlimit(RLIMIT_CORE, &rl) == -1)
			printf("setrlimit failed. Server may not save core.dump files.\n");
	}

	Master master;
	if(!master.Run(argc, argv))
		exit(-1);
	else
		exit(0);

	return 0;// shouldn't be reached
}

#else

bool run(int argc, char **argv)
{
	Master master;
	bool retval = master.Run(argc, argv);
	return retval;
}

int win32_main(int argc, char** argv)
{
	Arcemu::Shared::Util::SetThreadName("Main Thread");

	StartCrashHandler();

	//Andy: windows only, helps fight heap allocation on allocations lower then 16KB
	unsigned long arg = 2;
	HeapSetInformation(GetProcessHeap(), HeapCompatibilityInformation, &arg, sizeof(arg));

	THREAD_TRY_EXECUTION
	run(argc, argv);
	THREAD_HANDLE_CRASH

	exit(0);
}

#endif

int main(int argc, char** argv)
{
#ifdef WIN32
	win32_main(argc, argv);
#else
	unix_main(argc, argv);
#endif
}

<commit_msg>I accidentally, the slash<commit_after>/*
 * ArcEmu MMORPG Server
 * Copyright (C) 2005-2007 Ascent Team <http://www.ascentemu.com/>
 * Copyright (C) 2008-2012 <http://www.ArcEmu.org/>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

#include "Master.h"
#include "Util/Util.h"

#ifndef WIN32
#include <sys/resource.h>
#endif
#include "System/CrashHandler.h"

#ifndef WIN32
int unix_main(int argc, char** argv)
{
	rlimit rl;
	if(getrlimit(RLIMIT_CORE, &rl) == -1)
		printf("getrlimit failed. This could be problem.\n");
	else
	{
		rl.rlim_cur = rl.rlim_max;
		if(setrlimit(RLIMIT_CORE, &rl) == -1)
			printf("setrlimit failed. Server may not save core.dump files.\n");
	}

	Master master;
	if(!master.Run(argc, argv))
		exit(-1);
	else
		exit(0);

	return 0;// shouldn't be reached
}

#else

bool run(int argc, char **argv)
{
	Master master;
	bool retval = master.Run(argc, argv);
	return retval;
}

int win32_main(int argc, char** argv)
{
	Arcemu::Shared::Util::SetThreadName("Main Thread");

	StartCrashHandler();

	//Andy: windows only, helps fight heap allocation on allocations lower then 16KB
	unsigned long arg = 2;
	HeapSetInformation(GetProcessHeap(), HeapCompatibilityInformation, &arg, sizeof(arg));

	THREAD_TRY_EXECUTION
	run(argc, argv);
	THREAD_HANDLE_CRASH

	exit(0);
}

#endif

int main(int argc, char** argv)
{
#ifdef WIN32
	win32_main(argc, argv);
#else
	unix_main(argc, argv);
#endif
}

<|endoftext|>


<commit_before>/**
 * \file nblock_graph.cc
 *
 *
 *
 * \author Ethan Burns
 * \date 2008-10-20
 */

#include <assert.h>
#include <pthread.h>
#include <errno.h>

#include <limits>
#include <iostream>
#include <list>
#include <map>
#include <vector>

#include "../closed_list.h"
#include "../pq_open_list.h"
#include "../open_list.h"
#include "../projection.h"
#include "nblock.h"
#include "nblock_graph.h"

using namespace std;
using namespace WPBNF;

/**
 * Create the nblock with the given ID.
 */
NBlock *NBlockGraph::create_nblock(unsigned int id)
{
	NBlock *n = new NBlock(project, id);

	nblocks_created += 1;

	return n;
}

/**
 * Apparently gdb can't single step inside a c++ constructor... so we
 * just call this function in the constructor so that we can see what
 * is going on.
 */
void NBlockGraph::cpp_is_a_bad_language(const Projection *p,
					State *initial,
					AtomicInt *b /* bound */,
					double w /* weight */)
{
	unsigned int init_nblock = p->project(initial);

	nblocks_created = 0;
	project = p;
	num_sigma_zero = num_nblocks = p->get_num_nblocks();
	assert(init_nblock < num_nblocks);

	NBlock *n = map.get(init_nblock);
	n->open_fp.add(initial);
	n->closed.add(initial);
	free_list.add(n);

	done = false;
	bound = b;
	weight = w;

	nblocks_assigned = 0;
	nblocks_assigned_max = 0;
}

/**
 * Create a new NBlock graph.
 * \param p The projection function.
 */
NBlockGraph::NBlockGraph(const Projection *p,
			 State *initial,
			 AtomicInt *b /* bound */,
			 double w /* weight */)
	: map(p)
{
	cpp_is_a_bad_language(p, initial, b, w);
}

/**
 * Destroy an NBlock graph.
 */
NBlockGraph::~NBlockGraph()
{
}

/**
 * Get the next nblock for expansion, possibly release a finished
 * nblock.  The next nblock is the one with the minimum f-value.
 *
 * \note This call will block if there are currently no free nblocks.
 * \param finished If non-NULL, the finished nblock will be released
 *        into the next level's free_list.
 * \return The next NBlock to expand or NULL if there is nothing left
 *         to do.
 */
NBlock *NBlockGraph::next_nblock(NBlock *finished)
{
	NBlock *n = NULL;

	// Take the lock, but if someone else already has it, just
	// keep going.
	if (finished && !finished->open_fp.empty()) {
		if (!mutex.try_lock())
			return finished;
	} else {
		mutex.lock();
	}

	if (finished) {		// Release an NBlock
		assert(finished->sigma == 0);

		nblocks_assigned -= 1;

		// Possibly add this block back to the free list.
		finished->inuse = false;
		if (is_free(finished)) {
			free_list.add(finished);
			mutex.cond_signal();
		}

		update_scope_sigmas(finished, -1);
	}

retry:

	if (num_sigma_zero == num_nblocks && free_list.empty()) {
		set_done();
		goto out;
	}

	while (!done && free_list.empty())
		mutex.cond_wait();

	if (done)
		goto out;

	if (free_list.front()->best_value() >= (bound->read() * weight)) {
		prune_free_list();
		goto retry;
	}

	n = free_list.take();
	nblocks_assigned += 1;
	if (nblocks_assigned > nblocks_assigned_max)
		nblocks_assigned_max = nblocks_assigned;
	n->inuse = true;
	update_scope_sigmas(n, 1);

/*
  for (set<NBlock *>::iterator iter = n->interferes.begin();
  iter != n->interferes.end();
  iter++)
  assert((*iter)->sigma > 0);
*/
out:
	mutex.unlock();
	return n;
}

/**
 * Get the best NBlock in the interference scope of b which is not free.
 */
NBlock *NBlockGraph::best_in_scope(NBlock *block)
{
	NBlock *best_b = NULL;
	fp_type best_val = fp_infinity;

	for (unsigned int i = 0; i < block->ninterferes; i++) {
		NBlock *b = map.find(block->interferes[i]);
		if (!b)
			continue;
		if (b->open_fp.empty())
			continue;
		if (!best_b || b->open_fp.get_best_val() < best_val) {
			best_val = b->open_fp.get_best_val();
			best_b = b;
		}
	}

	return best_b;
}

/*
 * Remove all nblocks from the free_list.  The nodes in these nblocks
 * will remain in their open lists, for pruning later... if they ever
 * are added back to the free_list.  They can be added back to the
 * free_list if a processor searches one of their neighbors and they
 * gain a node worth looking at.
 */
void NBlockGraph::prune_free_list(void)
{
	free_list.reset();
}

/**
 * Get the NBlock given by the hash value.
 */
NBlock *NBlockGraph::get_nblock(unsigned int hash)
{
	return map.get(hash);
}

/**
 * Get the statistics on the maximum number of NBlocks assigned at one time.
 */
unsigned int NBlockGraph::get_max_assigned_nblocks(void) const
{

	return nblocks_assigned_max;
}

/**
 * Get the value of the best nblock on the free list.
 */
fp_type NBlockGraph::best_free_val(void)
{
	NBlock *b = NULL;
	b = free_list.front();
	if (b)
		return b->open_fp.get_best_val();
	return fp_infinity;
}

/**
 * Print an NBlock, but don't take the lock.
 */
void NBlockGraph::__print(ostream &o)
{

	o << "Number of NBlocks: " << num_nblocks << endl;
	o << "Number of NBlocks with sigma zero: " << num_sigma_zero << endl;
	o << "All Blocks:" << endl;
	for (unsigned int i = 0; i < num_nblocks; i += 1)
		if (map.find(i))
			map.find(i)->print(o);
}

/**
 * Print an NBlockGraph to the given stream.
 */
void NBlockGraph::print(ostream &o)
{
	mutex.lock();
	__print(o);
	mutex.lock();
}

/**
 * Update the sigmas by delta for all of the predecessors of y and all
 * of the predecessors of the successors of y.
 */
void NBlockGraph::update_scope_sigmas(NBlock *n, int delta)
{
	bool broadcast = false;
	assert(n->sigma == 0);

	/*
	  \A y' \in predecessors(y) /\ y' /= y,
	  \sigma(y') <- \sigma(y') +- 1

	  \A y' \in successors(y),
	  \A y'' \in predecessors(y'), /\ y'' /= y,
	  \sigma(y'') <- \sigma(y'') +- 1
	*/

	for (unsigned int i = 0; i < n->ninterferes; i++) {
		NBlock *m = map.get(n->interferes[i]);
		if (m->sigma == 0) {
			assert(delta > 0);
			if (is_free(m) && m->fp_pq_index != -1)
				free_list.remove(m->fp_pq_index);
			num_sigma_zero -= 1;
		}
		m->sigma += delta;
		if (m->sigma == 0) {
			if (m->hot)
				broadcast |= set_cold(m);
			if (is_free(m)) {
				free_list.add(m);
				broadcast = true;
			}
			num_sigma_zero += 1;
		}
	}

	if (broadcast)
		mutex.cond_broadcast();
}

/**
 * Sets the done flag.
 */
void NBlockGraph::set_done(void)
{
	done = true;
	mutex.cond_broadcast();
}

/**
 * Test if an NBlock is free.
 */
bool NBlockGraph::is_free(NBlock *b)
{
	return !b->inuse
		&& b->sigma == 0
		&& b->sigma_hot == 0
		&& !b->open_fp.empty();
}

/**
 * Mark an NBlock as hot, we want this one.
 */
bool NBlockGraph::set_hot(NBlock *b)
{
	fp_type f = b->open_fp.get_best_val();
	bool broadcast = false;

	if (!mutex.try_lock())
		return false;

	if (!b->hot && b->sigma > 0) {
		for (unsigned int i = 0; i < b->ninterferes; i++) {
			assert(b->id != b->interferes[i]);
			NBlock *m = map.get(b->interferes[i]);
			if (m->hot && m->open_fp.get_best_val() < f)
				goto out;
		}

		b->hot = true;
		for (unsigned int i = 0; i < b->ninterferes; i++) {
			assert(b->id != b->interferes[i]);
			NBlock *m = map.get(b->interferes[i]);
			if (is_free(m) && m->fp_pq_index != -1)
				free_list.remove(m->fp_pq_index);
			if (m->hot)
				broadcast |= set_cold(m);
			m->sigma_hot += 1;
		}
	}
out:
	if (broadcast)
		mutex.cond_broadcast();
	mutex.unlock();
	return true;
}

/**
 * Mark an NBlock as cold.  The mutex must be held *before* this
 * function is called.n
 */
bool NBlockGraph::set_cold(NBlock *b)
{
	bool broadcast = false;
	b->hot = false;
	for (unsigned int i = 0; i < b->ninterferes; i++) {
		assert(b->id != b->interferes[i]);
		NBlock *m = map.get(b->interferes[i]);
		m->sigma_hot -= 1;
		if (is_free(m)) {
			free_list.add(m);
			broadcast = true;
		}
	}

	return broadcast;
}

/**
 * We won't release block b, so set all hot blocks in its interference
 * scope back to cold.
 */
void NBlockGraph::wont_release(NBlock *b)
{
	bool broadcast = false;

	// Don't bother locking if nothing is hot anyway.
	if (b->sigma_hot == 0)
		return;

	if (!mutex.try_lock())
		return;

	for (unsigned int i = 0; i < b->ninterferes; i++) {
		NBlock *m = map.find(b->interferes[i]);
		if (!m)
			continue;
		if (m->hot)
			broadcast |= set_cold(m);
	}

	if (broadcast)
		mutex.cond_broadcast();

	mutex.unlock();
}

/**
 * Get the number of nblocks which were actually created.
 */
unsigned int NBlockGraph::get_ncreated_nblocks(void)
{
	return map.get_num_created();;
}
<commit_msg>Unlock at the end of the print function instead of locking again.<commit_after>/**
 * \file nblock_graph.cc
 *
 *
 *
 * \author Ethan Burns
 * \date 2008-10-20
 */

#include <assert.h>
#include <pthread.h>
#include <errno.h>

#include <limits>
#include <iostream>
#include <list>
#include <map>
#include <vector>

#include "../closed_list.h"
#include "../pq_open_list.h"
#include "../open_list.h"
#include "../projection.h"
#include "nblock.h"
#include "nblock_graph.h"

using namespace std;
using namespace WPBNF;

/**
 * Create the nblock with the given ID.
 */
NBlock *NBlockGraph::create_nblock(unsigned int id)
{
	NBlock *n = new NBlock(project, id);

	nblocks_created += 1;

	return n;
}

/**
 * Apparently gdb can't single step inside a c++ constructor... so we
 * just call this function in the constructor so that we can see what
 * is going on.
 */
void NBlockGraph::cpp_is_a_bad_language(const Projection *p,
					State *initial,
					AtomicInt *b /* bound */,
					double w /* weight */)
{
	unsigned int init_nblock = p->project(initial);

	nblocks_created = 0;
	project = p;
	num_sigma_zero = num_nblocks = p->get_num_nblocks();
	assert(init_nblock < num_nblocks);

	NBlock *n = map.get(init_nblock);
	n->open_fp.add(initial);
	n->closed.add(initial);
	free_list.add(n);

	done = false;
	bound = b;
	weight = w;

	nblocks_assigned = 0;
	nblocks_assigned_max = 0;
}

/**
 * Create a new NBlock graph.
 * \param p The projection function.
 */
NBlockGraph::NBlockGraph(const Projection *p,
			 State *initial,
			 AtomicInt *b /* bound */,
			 double w /* weight */)
	: map(p)
{
	cpp_is_a_bad_language(p, initial, b, w);
}

/**
 * Destroy an NBlock graph.
 */
NBlockGraph::~NBlockGraph()
{
}

/**
 * Get the next nblock for expansion, possibly release a finished
 * nblock.  The next nblock is the one with the minimum f-value.
 *
 * \note This call will block if there are currently no free nblocks.
 * \param finished If non-NULL, the finished nblock will be released
 *        into the next level's free_list.
 * \return The next NBlock to expand or NULL if there is nothing left
 *         to do.
 */
NBlock *NBlockGraph::next_nblock(NBlock *finished)
{
	NBlock *n = NULL;

	// Take the lock, but if someone else already has it, just
	// keep going.
	if (finished && !finished->open_fp.empty()) {
		if (!mutex.try_lock())
			return finished;
	} else {
		mutex.lock();
	}

	if (finished) {		// Release an NBlock
		assert(finished->sigma == 0);

		nblocks_assigned -= 1;

		// Possibly add this block back to the free list.
		finished->inuse = false;
		if (is_free(finished)) {
			free_list.add(finished);
			mutex.cond_signal();
		}

		update_scope_sigmas(finished, -1);
	}

retry:

	if (num_sigma_zero == num_nblocks && free_list.empty()) {
		set_done();
		goto out;
	}

	while (!done && free_list.empty())
		mutex.cond_wait();

	if (done)
		goto out;

	if (free_list.front()->best_value() >= (bound->read() * weight)) {
		prune_free_list();
		goto retry;
	}

	n = free_list.take();
	nblocks_assigned += 1;
	if (nblocks_assigned > nblocks_assigned_max)
		nblocks_assigned_max = nblocks_assigned;
	n->inuse = true;
	update_scope_sigmas(n, 1);

/*
  for (set<NBlock *>::iterator iter = n->interferes.begin();
  iter != n->interferes.end();
  iter++)
  assert((*iter)->sigma > 0);
*/
out:
	mutex.unlock();
	return n;
}

/**
 * Get the best NBlock in the interference scope of b which is not free.
 */
NBlock *NBlockGraph::best_in_scope(NBlock *block)
{
	NBlock *best_b = NULL;
	fp_type best_val = fp_infinity;

	for (unsigned int i = 0; i < block->ninterferes; i++) {
		NBlock *b = map.find(block->interferes[i]);
		if (!b)
			continue;
		if (b->open_fp.empty())
			continue;
		if (!best_b || b->open_fp.get_best_val() < best_val) {
			best_val = b->open_fp.get_best_val();
			best_b = b;
		}
	}

	return best_b;
}

/*
 * Remove all nblocks from the free_list.  The nodes in these nblocks
 * will remain in their open lists, for pruning later... if they ever
 * are added back to the free_list.  They can be added back to the
 * free_list if a processor searches one of their neighbors and they
 * gain a node worth looking at.
 */
void NBlockGraph::prune_free_list(void)
{
	free_list.reset();
}

/**
 * Get the NBlock given by the hash value.
 */
NBlock *NBlockGraph::get_nblock(unsigned int hash)
{
	return map.get(hash);
}

/**
 * Get the statistics on the maximum number of NBlocks assigned at one time.
 */
unsigned int NBlockGraph::get_max_assigned_nblocks(void) const
{

	return nblocks_assigned_max;
}

/**
 * Get the value of the best nblock on the free list.
 */
fp_type NBlockGraph::best_free_val(void)
{
	NBlock *b = NULL;
	b = free_list.front();
	if (b)
		return b->open_fp.get_best_val();
	return fp_infinity;
}

/**
 * Print an NBlock, but don't take the lock.
 */
void NBlockGraph::__print(ostream &o)
{

	o << "Number of NBlocks: " << num_nblocks << endl;
	o << "Number of NBlocks with sigma zero: " << num_sigma_zero << endl;
	o << "All Blocks:" << endl;
	for (unsigned int i = 0; i < num_nblocks; i += 1)
		if (map.find(i))
			map.find(i)->print(o);
}

/**
 * Print an NBlockGraph to the given stream.
 */
void NBlockGraph::print(ostream &o)
{
	mutex.lock();
	__print(o);
	mutex.unlock();
}

/**
 * Update the sigmas by delta for all of the predecessors of y and all
 * of the predecessors of the successors of y.
 */
void NBlockGraph::update_scope_sigmas(NBlock *n, int delta)
{
	bool broadcast = false;
	assert(n->sigma == 0);

	/*
	  \A y' \in predecessors(y) /\ y' /= y,
	  \sigma(y') <- \sigma(y') +- 1

	  \A y' \in successors(y),
	  \A y'' \in predecessors(y'), /\ y'' /= y,
	  \sigma(y'') <- \sigma(y'') +- 1
	*/

	for (unsigned int i = 0; i < n->ninterferes; i++) {
		NBlock *m = map.get(n->interferes[i]);
		if (m->sigma == 0) {
			assert(delta > 0);
			if (is_free(m) && m->fp_pq_index != -1)
				free_list.remove(m->fp_pq_index);
			num_sigma_zero -= 1;
		}
		m->sigma += delta;
		if (m->sigma == 0) {
			if (m->hot)
				broadcast |= set_cold(m);
			if (is_free(m)) {
				free_list.add(m);
				broadcast = true;
			}
			num_sigma_zero += 1;
		}
	}

	if (broadcast)
		mutex.cond_broadcast();
}

/**
 * Sets the done flag.
 */
void NBlockGraph::set_done(void)
{
	done = true;
	mutex.cond_broadcast();
}

/**
 * Test if an NBlock is free.
 */
bool NBlockGraph::is_free(NBlock *b)
{
	return !b->inuse
		&& b->sigma == 0
		&& b->sigma_hot == 0
		&& !b->open_fp.empty();
}

/**
 * Mark an NBlock as hot, we want this one.
 */
bool NBlockGraph::set_hot(NBlock *b)
{
	fp_type f = b->open_fp.get_best_val();
	bool broadcast = false;

	if (!mutex.try_lock())
		return false;

	if (!b->hot && b->sigma > 0) {
		for (unsigned int i = 0; i < b->ninterferes; i++) {
			assert(b->id != b->interferes[i]);
			NBlock *m = map.get(b->interferes[i]);
			if (m->hot && m->open_fp.get_best_val() < f)
				goto out;
		}

		b->hot = true;
		for (unsigned int i = 0; i < b->ninterferes; i++) {
			assert(b->id != b->interferes[i]);
			NBlock *m = map.get(b->interferes[i]);
			if (is_free(m) && m->fp_pq_index != -1)
				free_list.remove(m->fp_pq_index);
			if (m->hot)
				broadcast |= set_cold(m);
			m->sigma_hot += 1;
		}
	}
out:
	if (broadcast)
		mutex.cond_broadcast();
	mutex.unlock();
	return true;
}

/**
 * Mark an NBlock as cold.  The mutex must be held *before* this
 * function is called.n
 */
bool NBlockGraph::set_cold(NBlock *b)
{
	bool broadcast = false;
	b->hot = false;
	for (unsigned int i = 0; i < b->ninterferes; i++) {
		assert(b->id != b->interferes[i]);
		NBlock *m = map.get(b->interferes[i]);
		m->sigma_hot -= 1;
		if (is_free(m)) {
			free_list.add(m);
			broadcast = true;
		}
	}

	return broadcast;
}

/**
 * We won't release block b, so set all hot blocks in its interference
 * scope back to cold.
 */
void NBlockGraph::wont_release(NBlock *b)
{
	bool broadcast = false;

	// Don't bother locking if nothing is hot anyway.
	if (b->sigma_hot == 0)
		return;

	if (!mutex.try_lock())
		return;

	for (unsigned int i = 0; i < b->ninterferes; i++) {
		NBlock *m = map.find(b->interferes[i]);
		if (!m)
			continue;
		if (m->hot)
			broadcast |= set_cold(m);
	}

	if (broadcast)
		mutex.cond_broadcast();

	mutex.unlock();
}

/**
 * Get the number of nblocks which were actually created.
 */
unsigned int NBlockGraph::get_ncreated_nblocks(void)
{
	return map.get_num_created();;
}
<|endoftext|>