<commit_before>//===-- clang-format/ClangFormat.cpp - Clang format tool ------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
///
/// \file
/// \brief This file implements a clang-format tool that automatically formats
/// (fragments of) C++ code.
///
//===----------------------------------------------------------------------===//

#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/DiagnosticOptions.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/Version.h"
#include "clang/Format/Format.h"
#include "clang/Lex/Lexer.h"
#include "clang/Rewrite/Core/Rewriter.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Signals.h"

using namespace llvm;

static cl::opt<bool> Help("h", cl::desc("Alias for -help"), cl::Hidden);

// Mark all our options with this category, everything else (except for -version
// and -help) will be hidden.
static cl::OptionCategory ClangFormatCategory("Clang-format options");

static cl::list<unsigned>
    Offsets("offset",
            cl::desc("Format a range starting at this byte offset.\n"
                     "Multiple ranges can be formatted by specifying\n"
                     "several -offset and -length pairs.\n"
                     "Can only be used with one input file."),
            cl::cat(ClangFormatCategory));
static cl::list<unsigned>
    Lengths("length",
            cl::desc("Format a range of this length (in bytes).\n"
                     "Multiple ranges can be formatted by specifying\n"
                     "several -offset and -length pairs.\n"
                     "When only a single -offset is specified without\n"
                     "-length, clang-format will format up to the end\n"
                     "of the file.\n"
                     "Can only be used with one input file."),
            cl::cat(ClangFormatCategory));
static cl::list<std::string>
LineRanges("lines", cl::desc("<start line>:<end line> - format a range of\n"
                             "lines (both 1-based).\n"
                             "Multiple ranges can be formatted by specifying\n"
                             "several -lines arguments.\n"
                             "Can't be used with -offset and -length.\n"
                             "Can only be used with one input file."),
           cl::cat(ClangFormatCategory));
static cl::opt<std::string>
    Style("style",
          cl::desc(clang::format::StyleOptionHelpDescription),
          cl::init("file"), cl::cat(ClangFormatCategory));
static cl::opt<std::string>
FallbackStyle("fallback-style",
              cl::desc("The name of the predefined style used as a fallback in "
                       "case clang-format is invoked with -style=file, but can "
                       "not find the .clang-format file to use."),
              cl::init("LLVM"), cl::cat(ClangFormatCategory));

static cl::opt<std::string>
AssumeFilename("assume-filename",
               cl::desc("When reading from stdin, clang-format assumes this\n"
                        "filename to look for a style config file (with\n"
                        "-style=file)."),
               cl::cat(ClangFormatCategory));

static cl::opt<bool> Inplace("i",
                             cl::desc("Inplace edit <file>s, if specified."),
                             cl::cat(ClangFormatCategory));

static cl::opt<bool> OutputXML("output-replacements-xml",
                               cl::desc("Output replacements as XML."),
                               cl::cat(ClangFormatCategory));
static cl::opt<bool>
    DumpConfig("dump-config",
               cl::desc("Dump configuration options to stdout and exit.\n"
                        "Can be used with -style option."),
               cl::cat(ClangFormatCategory));
static cl::opt<unsigned>
    Cursor("cursor",
           cl::desc("The position of the cursor when invoking\n"
                    "clang-format from an editor integration"),
           cl::init(0), cl::cat(ClangFormatCategory));

static cl::list<std::string> FileNames(cl::Positional, cl::desc("[<file> ...]"),
                                       cl::cat(ClangFormatCategory));

namespace clang {
namespace format {

static FileID createInMemoryFile(StringRef FileName, const MemoryBuffer *Source,
                                 SourceManager &Sources, FileManager &Files) {
  const FileEntry *Entry = Files.getVirtualFile(FileName == "-" ? "<stdin>" :
                                                    FileName,
                                                Source->getBufferSize(), 0);
  Sources.overrideFileContents(Entry, Source, true);
  return Sources.createFileID(Entry, SourceLocation(), SrcMgr::C_User);
}

// Parses <start line>:<end line> input to a pair of line numbers.
// Returns true on error.
static bool parseLineRange(StringRef Input, unsigned &FromLine,
                           unsigned &ToLine) {
  std::pair<StringRef, StringRef> LineRange = Input.split(':');
  return LineRange.first.getAsInteger(0, FromLine) ||
         LineRange.second.getAsInteger(0, ToLine);
}

static bool fillRanges(SourceManager &Sources, FileID ID,
                       const MemoryBuffer *Code,
                       std::vector<CharSourceRange> &Ranges) {
  if (!LineRanges.empty()) {
    if (!Offsets.empty() || !Lengths.empty()) {
      llvm::errs() << "error: cannot use -lines with -offset/-length\n";
      return true;
    }

    for (unsigned i = 0, e = LineRanges.size(); i < e; ++i) {
      unsigned FromLine, ToLine;
      if (parseLineRange(LineRanges[i], FromLine, ToLine)) {
        llvm::errs() << "error: invalid <start line>:<end line> pair\n";
        return true;
      }
      if (FromLine > ToLine) {
        llvm::errs() << "error: start line should be less than end line\n";
        return true;
      }
      SourceLocation Start = Sources.translateLineCol(ID, FromLine, 1);
      SourceLocation End = Sources.translateLineCol(ID, ToLine, UINT_MAX);
      if (Start.isInvalid() || End.isInvalid())
        return true;
      Ranges.push_back(CharSourceRange::getCharRange(Start, End));
    }
    return false;
  }

  if (Offsets.empty())
    Offsets.push_back(0);
  if (Offsets.size() != Lengths.size() &&
      !(Offsets.size() == 1 && Lengths.empty())) {
    llvm::errs()
        << "error: number of -offset and -length arguments must match.\n";
    return true;
  }
  for (unsigned i = 0, e = Offsets.size(); i != e; ++i) {
    if (Offsets[i] >= Code->getBufferSize()) {
      llvm::errs() << "error: offset " << Offsets[i]
                   << " is outside the file\n";
      return true;
    }
    SourceLocation Start =
        Sources.getLocForStartOfFile(ID).getLocWithOffset(Offsets[i]);
    SourceLocation End;
    if (i < Lengths.size()) {
      if (Offsets[i] + Lengths[i] > Code->getBufferSize()) {
        llvm::errs() << "error: invalid length " << Lengths[i]
                     << ", offset + length (" << Offsets[i] + Lengths[i]
                     << ") is outside the file.\n";
        return true;
      }
      End = Start.getLocWithOffset(Lengths[i]);
    } else {
      End = Sources.getLocForEndOfFile(ID);
    }
    Ranges.push_back(CharSourceRange::getCharRange(Start, End));
  }
  return false;
}

static void outputReplacementXML(StringRef Text) {
  size_t From = 0;
  size_t Index;
  while ((Index = Text.find_first_of("\n\r", From)) != StringRef::npos) {
    llvm::outs() << Text.substr(From, Index - From);
    switch (Text[Index]) {
    case '\n':
      llvm::outs() << "
";
      break;
    case '\r':
      llvm::outs() << "
";
      break;
    default:
      llvm_unreachable("Unexpected character encountered!");
    }
    From = Index + 1;
  }
  llvm::outs() << Text.substr(From);
}

// Returns true on error.
static bool format(StringRef FileName) {
  FileManager Files((FileSystemOptions()));
  DiagnosticsEngine Diagnostics(
      IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs),
      new DiagnosticOptions);
  SourceManager Sources(Diagnostics, Files);
  OwningPtr<MemoryBuffer> Code;
  if (error_code ec = MemoryBuffer::getFileOrSTDIN(FileName, Code)) {
    llvm::errs() << ec.message() << "\n";
    return true;
  }
  if (Code->getBufferSize() == 0)
    return false; // Empty files are formatted correctly.
  FileID ID = createInMemoryFile(FileName, Code.get(), Sources, Files);
  std::vector<CharSourceRange> Ranges;
  if (fillRanges(Sources, ID, Code.get(), Ranges))
    return true;

  FormatStyle FormatStyle = getStyle(
      Style, (FileName == "-") ? AssumeFilename : FileName, FallbackStyle);
  Lexer Lex(ID, Sources.getBuffer(ID), Sources,
            getFormattingLangOpts(FormatStyle.Standard));
  tooling::Replacements Replaces = reformat(FormatStyle, Lex, Sources, Ranges);
  if (OutputXML) {
    llvm::outs()
        << "<?xml version='1.0'?>\n<replacements xml:space='preserve'>\n";
    for (tooling::Replacements::const_iterator I = Replaces.begin(),
                                               E = Replaces.end();
         I != E; ++I) {
      llvm::outs() << "<replacement "
                   << "offset='" << I->getOffset() << "' "
                   << "length='" << I->getLength() << "'>";
      outputReplacementXML(I->getReplacementText());
      llvm::outs() << "</replacement>\n";
    }
    llvm::outs() << "</replacements>\n";
  } else {
    Rewriter Rewrite(Sources, LangOptions());
    tooling::applyAllReplacements(Replaces, Rewrite);
    if (Inplace) {
      if (Rewrite.overwriteChangedFiles())
        return true;
    } else {
      if (Cursor.getNumOccurrences() != 0)
        outs() << "{ \"Cursor\": " << tooling::shiftedCodePosition(
                                          Replaces, Cursor) << " }\n";
      Rewrite.getEditBuffer(ID).write(outs());
    }
  }
  return false;
}

}  // namespace format
}  // namespace clang

static void PrintVersion() {
  raw_ostream &OS = outs();
  OS << clang::getClangToolFullVersion("clang-format") << '\n';
}

int main(int argc, const char **argv) {
  llvm::sys::PrintStackTraceOnErrorSignal();

  // Hide unrelated options.
  StringMap<cl::Option*> Options;
  cl::getRegisteredOptions(Options);
  for (StringMap<cl::Option *>::iterator I = Options.begin(), E = Options.end();
       I != E; ++I) {
    if (I->second->Category != &ClangFormatCategory && I->first() != "help" &&
        I->first() != "version")
      I->second->setHiddenFlag(cl::ReallyHidden);
  }

  cl::SetVersionPrinter(PrintVersion);
  cl::ParseCommandLineOptions(
      argc, argv,
      "A tool to format C/C++/Obj-C code.\n\n"
      "If no arguments are specified, it formats the code from standard input\n"
      "and writes the result to the standard output.\n"
      "If <file>s are given, it reformats the files. If -i is specified\n"
      "together with <file>s, the files are edited in-place. Otherwise, the\n"
      "result is written to the standard output.\n");

  if (Help)
    cl::PrintHelpMessage();

  if (DumpConfig) {
    std::string Config =
        clang::format::configurationAsText(clang::format::getStyle(
            Style, FileNames.empty() ? AssumeFilename : FileNames[0],
            FallbackStyle));
    llvm::outs() << Config << "\n";
    return 0;
  }

  bool Error = false;
  switch (FileNames.size()) {
  case 0:
    Error = clang::format::format("-");
    break;
  case 1:
    Error = clang::format::format(FileNames[0]);
    break;
  default:
    if (!Offsets.empty() || !Lengths.empty() || !LineRanges.empty()) {
      llvm::errs() << "error: -offset, -length and -lines can only be used for "
                      "single file.\n";
      return 1;
    }
    for (unsigned i = 0; i < FileNames.size(); ++i)
      Error |= clang::format::format(FileNames[i]);
    break;
  }
  return Error ? 1 : 0;
}
<commit_msg>Add newlines to fallback-style description. Patch by Kamal Essoufi\!<commit_after>//===-- clang-format/ClangFormat.cpp - Clang format tool ------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
///
/// \file
/// \brief This file implements a clang-format tool that automatically formats
/// (fragments of) C++ code.
///
//===----------------------------------------------------------------------===//

#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/DiagnosticOptions.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/Version.h"
#include "clang/Format/Format.h"
#include "clang/Lex/Lexer.h"
#include "clang/Rewrite/Core/Rewriter.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Signals.h"

using namespace llvm;

static cl::opt<bool> Help("h", cl::desc("Alias for -help"), cl::Hidden);

// Mark all our options with this category, everything else (except for -version
// and -help) will be hidden.
static cl::OptionCategory ClangFormatCategory("Clang-format options");

static cl::list<unsigned>
    Offsets("offset",
            cl::desc("Format a range starting at this byte offset.\n"
                     "Multiple ranges can be formatted by specifying\n"
                     "several -offset and -length pairs.\n"
                     "Can only be used with one input file."),
            cl::cat(ClangFormatCategory));
static cl::list<unsigned>
    Lengths("length",
            cl::desc("Format a range of this length (in bytes).\n"
                     "Multiple ranges can be formatted by specifying\n"
                     "several -offset and -length pairs.\n"
                     "When only a single -offset is specified without\n"
                     "-length, clang-format will format up to the end\n"
                     "of the file.\n"
                     "Can only be used with one input file."),
            cl::cat(ClangFormatCategory));
static cl::list<std::string>
LineRanges("lines", cl::desc("<start line>:<end line> - format a range of\n"
                             "lines (both 1-based).\n"
                             "Multiple ranges can be formatted by specifying\n"
                             "several -lines arguments.\n"
                             "Can't be used with -offset and -length.\n"
                             "Can only be used with one input file."),
           cl::cat(ClangFormatCategory));
static cl::opt<std::string>
    Style("style",
          cl::desc(clang::format::StyleOptionHelpDescription),
          cl::init("file"), cl::cat(ClangFormatCategory));
static cl::opt<std::string>
FallbackStyle("fallback-style",
              cl::desc("The name of the predefined style used as a\n"
                       "fallback in case clang-format is invoked with\n"
                       "-style=file, but can not find the .clang-format\n"
                       "file to use."),
              cl::init("LLVM"), cl::cat(ClangFormatCategory));

static cl::opt<std::string>
AssumeFilename("assume-filename",
               cl::desc("When reading from stdin, clang-format assumes this\n"
                        "filename to look for a style config file (with\n"
                        "-style=file)."),
               cl::cat(ClangFormatCategory));

static cl::opt<bool> Inplace("i",
                             cl::desc("Inplace edit <file>s, if specified."),
                             cl::cat(ClangFormatCategory));

static cl::opt<bool> OutputXML("output-replacements-xml",
                               cl::desc("Output replacements as XML."),
                               cl::cat(ClangFormatCategory));
static cl::opt<bool>
    DumpConfig("dump-config",
               cl::desc("Dump configuration options to stdout and exit.\n"
                        "Can be used with -style option."),
               cl::cat(ClangFormatCategory));
static cl::opt<unsigned>
    Cursor("cursor",
           cl::desc("The position of the cursor when invoking\n"
                    "clang-format from an editor integration"),
           cl::init(0), cl::cat(ClangFormatCategory));

static cl::list<std::string> FileNames(cl::Positional, cl::desc("[<file> ...]"),
                                       cl::cat(ClangFormatCategory));

namespace clang {
namespace format {

static FileID createInMemoryFile(StringRef FileName, const MemoryBuffer *Source,
                                 SourceManager &Sources, FileManager &Files) {
  const FileEntry *Entry = Files.getVirtualFile(FileName == "-" ? "<stdin>" :
                                                    FileName,
                                                Source->getBufferSize(), 0);
  Sources.overrideFileContents(Entry, Source, true);
  return Sources.createFileID(Entry, SourceLocation(), SrcMgr::C_User);
}

// Parses <start line>:<end line> input to a pair of line numbers.
// Returns true on error.
static bool parseLineRange(StringRef Input, unsigned &FromLine,
                           unsigned &ToLine) {
  std::pair<StringRef, StringRef> LineRange = Input.split(':');
  return LineRange.first.getAsInteger(0, FromLine) ||
         LineRange.second.getAsInteger(0, ToLine);
}

static bool fillRanges(SourceManager &Sources, FileID ID,
                       const MemoryBuffer *Code,
                       std::vector<CharSourceRange> &Ranges) {
  if (!LineRanges.empty()) {
    if (!Offsets.empty() || !Lengths.empty()) {
      llvm::errs() << "error: cannot use -lines with -offset/-length\n";
      return true;
    }

    for (unsigned i = 0, e = LineRanges.size(); i < e; ++i) {
      unsigned FromLine, ToLine;
      if (parseLineRange(LineRanges[i], FromLine, ToLine)) {
        llvm::errs() << "error: invalid <start line>:<end line> pair\n";
        return true;
      }
      if (FromLine > ToLine) {
        llvm::errs() << "error: start line should be less than end line\n";
        return true;
      }
      SourceLocation Start = Sources.translateLineCol(ID, FromLine, 1);
      SourceLocation End = Sources.translateLineCol(ID, ToLine, UINT_MAX);
      if (Start.isInvalid() || End.isInvalid())
        return true;
      Ranges.push_back(CharSourceRange::getCharRange(Start, End));
    }
    return false;
  }

  if (Offsets.empty())
    Offsets.push_back(0);
  if (Offsets.size() != Lengths.size() &&
      !(Offsets.size() == 1 && Lengths.empty())) {
    llvm::errs()
        << "error: number of -offset and -length arguments must match.\n";
    return true;
  }
  for (unsigned i = 0, e = Offsets.size(); i != e; ++i) {
    if (Offsets[i] >= Code->getBufferSize()) {
      llvm::errs() << "error: offset " << Offsets[i]
                   << " is outside the file\n";
      return true;
    }
    SourceLocation Start =
        Sources.getLocForStartOfFile(ID).getLocWithOffset(Offsets[i]);
    SourceLocation End;
    if (i < Lengths.size()) {
      if (Offsets[i] + Lengths[i] > Code->getBufferSize()) {
        llvm::errs() << "error: invalid length " << Lengths[i]
                     << ", offset + length (" << Offsets[i] + Lengths[i]
                     << ") is outside the file.\n";
        return true;
      }
      End = Start.getLocWithOffset(Lengths[i]);
    } else {
      End = Sources.getLocForEndOfFile(ID);
    }
    Ranges.push_back(CharSourceRange::getCharRange(Start, End));
  }
  return false;
}

static void outputReplacementXML(StringRef Text) {
  size_t From = 0;
  size_t Index;
  while ((Index = Text.find_first_of("\n\r", From)) != StringRef::npos) {
    llvm::outs() << Text.substr(From, Index - From);
    switch (Text[Index]) {
    case '\n':
      llvm::outs() << "
";
      break;
    case '\r':
      llvm::outs() << "
";
      break;
    default:
      llvm_unreachable("Unexpected character encountered!");
    }
    From = Index + 1;
  }
  llvm::outs() << Text.substr(From);
}

// Returns true on error.
static bool format(StringRef FileName) {
  FileManager Files((FileSystemOptions()));
  DiagnosticsEngine Diagnostics(
      IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs),
      new DiagnosticOptions);
  SourceManager Sources(Diagnostics, Files);
  OwningPtr<MemoryBuffer> Code;
  if (error_code ec = MemoryBuffer::getFileOrSTDIN(FileName, Code)) {
    llvm::errs() << ec.message() << "\n";
    return true;
  }
  if (Code->getBufferSize() == 0)
    return false; // Empty files are formatted correctly.
  FileID ID = createInMemoryFile(FileName, Code.get(), Sources, Files);
  std::vector<CharSourceRange> Ranges;
  if (fillRanges(Sources, ID, Code.get(), Ranges))
    return true;

  FormatStyle FormatStyle = getStyle(
      Style, (FileName == "-") ? AssumeFilename : FileName, FallbackStyle);
  Lexer Lex(ID, Sources.getBuffer(ID), Sources,
            getFormattingLangOpts(FormatStyle.Standard));
  tooling::Replacements Replaces = reformat(FormatStyle, Lex, Sources, Ranges);
  if (OutputXML) {
    llvm::outs()
        << "<?xml version='1.0'?>\n<replacements xml:space='preserve'>\n";
    for (tooling::Replacements::const_iterator I = Replaces.begin(),
                                               E = Replaces.end();
         I != E; ++I) {
      llvm::outs() << "<replacement "
                   << "offset='" << I->getOffset() << "' "
                   << "length='" << I->getLength() << "'>";
      outputReplacementXML(I->getReplacementText());
      llvm::outs() << "</replacement>\n";
    }
    llvm::outs() << "</replacements>\n";
  } else {
    Rewriter Rewrite(Sources, LangOptions());
    tooling::applyAllReplacements(Replaces, Rewrite);
    if (Inplace) {
      if (Rewrite.overwriteChangedFiles())
        return true;
    } else {
      if (Cursor.getNumOccurrences() != 0)
        outs() << "{ \"Cursor\": " << tooling::shiftedCodePosition(
                                          Replaces, Cursor) << " }\n";
      Rewrite.getEditBuffer(ID).write(outs());
    }
  }
  return false;
}

}  // namespace format
}  // namespace clang

static void PrintVersion() {
  raw_ostream &OS = outs();
  OS << clang::getClangToolFullVersion("clang-format") << '\n';
}

int main(int argc, const char **argv) {
  llvm::sys::PrintStackTraceOnErrorSignal();

  // Hide unrelated options.
  StringMap<cl::Option*> Options;
  cl::getRegisteredOptions(Options);
  for (StringMap<cl::Option *>::iterator I = Options.begin(), E = Options.end();
       I != E; ++I) {
    if (I->second->Category != &ClangFormatCategory && I->first() != "help" &&
        I->first() != "version")
      I->second->setHiddenFlag(cl::ReallyHidden);
  }

  cl::SetVersionPrinter(PrintVersion);
  cl::ParseCommandLineOptions(
      argc, argv,
      "A tool to format C/C++/Obj-C code.\n\n"
      "If no arguments are specified, it formats the code from standard input\n"
      "and writes the result to the standard output.\n"
      "If <file>s are given, it reformats the files. If -i is specified\n"
      "together with <file>s, the files are edited in-place. Otherwise, the\n"
      "result is written to the standard output.\n");

  if (Help)
    cl::PrintHelpMessage();

  if (DumpConfig) {
    std::string Config =
        clang::format::configurationAsText(clang::format::getStyle(
            Style, FileNames.empty() ? AssumeFilename : FileNames[0],
            FallbackStyle));
    llvm::outs() << Config << "\n";
    return 0;
  }

  bool Error = false;
  switch (FileNames.size()) {
  case 0:
    Error = clang::format::format("-");
    break;
  case 1:
    Error = clang::format::format(FileNames[0]);
    break;
  default:
    if (!Offsets.empty() || !Lengths.empty() || !LineRanges.empty()) {
      llvm::errs() << "error: -offset, -length and -lines can only be used for "
                      "single file.\n";
      return 1;
    }
    for (unsigned i = 0; i < FileNames.size(); ++i)
      Error |= clang::format::format(FileNames[i]);
    break;
  }
  return Error ? 1 : 0;
}
<|endoftext|>


<commit_before>/*
    Copyright 2008 Brain Research Institute, Melbourne, Australia

    Written by J-Donald Tournier, 27/11/09.

    This file is part of MRtrix.

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

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

    You should have received a copy of the GNU General Public License
    along with MRtrix.  If not, see <http://www.gnu.org/licenses/>.

*/

#include "command.h"
#include "progressbar.h"
#include "memory.h"
#include "image.h"
// #include "header.h"
#include "algo/threaded_loop.h"
#include "math/math.h"
#include "math/median.h"

#include <limits>
#include <vector>

using namespace MR;
using namespace App;

const char* operations[] = {
  "mean",
  "median",
  "sum",
  "product",
  "rms",
  "var",
  "std",
  "min",
  "max",
  "absmax", // Maximum of absolute values
  "magmax", // Value for which the magnitude is the maximum (i.e. preserves signed-ness)
  NULL
};

void usage ()
{
  DESCRIPTION
    + "compute summary statistic on image intensities either across images, "
    "or along a specified axis for a single image. Supported operations are:"

    + "mean, median, sum, product, rms (root-mean-square value), var (unbiased variance), "
    "std (unbiased standard deviation), min, max, absmax (maximum absolute value), "
    "magmax (value with maximum absolute value, preserving its sign)."

    + "See also 'mrcalc' to compute per-voxel operations.";

  ARGUMENTS
  + Argument ("input", "the input image.").type_image_in ().allow_multiple()
  + Argument ("operation", "the operation to apply, one of: " + join(operations, ", ") + ".").type_choice (operations)
  + Argument ("output", "the output image.").type_image_out ();

  OPTIONS
  + Option ("axis", "perform operation along a specified axis of a single input image")
    + Argument ("index").type_integer();

}

typedef float value_type;

class Mean {
  public:
    Mean () : sum (0.0), count (0) { }
    void operator() (value_type val) {
      if (std::isfinite (val)) {
        sum += val;
        ++count;
      }
    }
    value_type result () const {
      if (!count)
        return NAN;
      return sum / count;
    }
    double sum;
    size_t count;
};

class Median {
  public:
    Median () { }
    void operator() (value_type val) {
      if (!std::isnan (val))
        values.push_back(val);
    }
    value_type result () {
      return Math::median(values);
    }
    std::vector<value_type> values;
};

class Sum {
  public:
    Sum () : sum (0.0) { }
    void operator() (value_type val) {
      if (std::isfinite (val))
        sum += val;
    }
    value_type result () const {
      return sum;
    }
    double sum;
};

class Product {
  public:
    Product () : product (0.0) { }
    void operator() (value_type val) {
      if (std::isfinite (val))
        product += val;
    }
    value_type result () const {
      return product;
    }
    double product;
};

class RMS {
  public:
    RMS() : sum (0.0), count (0) { }
    void operator() (value_type val) {
      if (std::isfinite (val)) {
        sum += Math::pow2 (val);
        ++count;
      }
    }
    value_type result() const {
      if (!count)
        return NAN;
      return std::sqrt(sum / count);
    }
    double sum;
    size_t count;
};

class Var {
  public:
    Var () : sum (0.0), sum_sqr (0.0), count (0) { }
    void operator() (value_type val) {
      if (std::isfinite (val)) {
        sum += val;
        sum_sqr += Math::pow2 (val);
        ++count;
      }
    }
    value_type result () const {
      if (count < 2)
        return NAN;
      return  (sum_sqr - Math::pow2 (sum) / static_cast<double> (count)) / (static_cast<double> (count) - 1.0);
    }
    double sum, sum_sqr;
    size_t count;
};

class Std : public Var {
  public:
    Std() : Var() { }
    value_type result () const { return std::sqrt (Var::result()); }
};

class Min {
  public:
    Min () : min (std::numeric_limits<value_type>::infinity()) { }
    void operator() (value_type val) {
      if (std::isfinite (val) && val < min)
        min = val;
    }
    value_type result () const { return std::isfinite (min) ? min : NAN; }
    value_type min;
};

class Max {
  public:
    Max () : max (-std::numeric_limits<value_type>::infinity()) { }
    void operator() (value_type val) {
      if (std::isfinite (val) && val > max)
        max = val;
    }
    value_type result () const { return std::isfinite (max) ? max : NAN; }
    value_type max;
};

class AbsMax {
  public:
    AbsMax () : max (-std::numeric_limits<value_type>::infinity()) { }
    void operator() (value_type val) {
      if (std::isfinite (val) && std::abs(val) > max)
        max = std::abs(val);
    }
    value_type result () const { return std::isfinite (max) ? max : NAN; }
    value_type max;
};

class MagMax {
  public:
    MagMax () : max (-std::numeric_limits<value_type>::infinity()) { }
    MagMax (const int i) : max (-std::numeric_limits<value_type>::infinity()) { }
    void operator() (value_type val) {
      if (std::isfinite (val) && (!std::isfinite (max) || std::abs(val) > std::abs (max)))
        max = val;
    }
    value_type result () const { return std::isfinite (max) ? max : NAN; }
    value_type max;
};

template <class Operation>
class AxisKernel {
  public:
    AxisKernel (size_t axis) : axis (axis) { }

    template <class InputImageType, class OutputImageType>
      void operator() (InputImageType& in, OutputImageType& out) {
        Operation op;
        for (in[axis] = 0; in[axis] < in.size(axis); ++in[axis])
          op (in.value());
        out.value() = op.result();
      }
  protected:
    const size_t axis;
};

class ImageKernelBase {
  public:
    ImageKernelBase (const std::string& path) :
      output_path (path) { }
    virtual ~ImageKernelBase() { }
    virtual void process (const Header& image_in) = 0;
  protected:
    const std::string output_path;
};

template <class Operation>
class ImageKernel : public ImageKernelBase {
  protected:
    class InitFunctor {
      public:
        template <class ImageType>
          void operator() (ImageType& out) const { out.value() = Operation(); }
    };
    class ProcessFunctor {
      public:
        template <class ImageType1, class ImageType2>
          void operator() (ImageType1& out, ImageType2& in) const {
            Operation op = out.value();
            op (in.value());
            out.value() = op;
          }
    };
    class ResultFunctor {
      public:
        template <class ImageType1, class ImageType2>
          void operator() (ImageType1& out, ImageType2& in) const {
            Operation op = in.value();
            out.value() = op.result();
          }
    };

  public:
    ImageKernel (const Header& header, const std::string& path) :
      ImageKernelBase (path),
      header (header),
      image (header) {
        ThreadedLoop (image).run (InitFunctor(), image);
      }

    ~ImageKernel()
    {
      Image<value_type> out (output_path, header);
      ThreadedLoop (image).run (ResultFunctor(), out, image);
    }

    void process (const Header& image_in)
    {
      Image<value_type> in (image_in);
      ThreadedLoop (image).run (ProcessFunctor(), image, in);
    }

  protected:
    const Header& header;
    Image<Operation> image;

};

void run ()
{
  const size_t num_inputs = argument.size() - 2;
  const int op = argument[num_inputs];
  const std::string& output_path = argument.back();

  Options opt = get_options ("axis");
  if (opt.size()) {

    if (num_inputs != 1)
      throw Exception ("Option -axis only applies if a single input image is used");

    const size_t axis = opt[0][0];

    auto image_in = Header::open (argument[0]).get_image<value_type>().with_direct_io (Stride::contiguous_along_axis (axis));

    if (axis >= image_in.ndim())
      throw Exception ("Cannot perform operation along axis " + str (axis) + "; image only has " + str(image_in.ndim()) + " axes");

    Header header_out (image_in.header());

    header_out.datatype() = DataType::Float32;
    header_out.size(axis) = 1;
    squeeze_dim (header_out);

    auto image_out = Header::create (output_path, header_out).get_image<float>();
    // auto image_out = Header::allocate (header_out).get_image<float>();
    // Image image_out (output_path, header_out);

    ThreadedLoop loop (std::string("computing ") + operations[op] + " along axis " + str(axis) + "...", image_out);

    switch (op) {
      case 0: loop.run  (AxisKernel<Mean>   (axis), image_in, image_out); return;
      case 1: loop.run  (AxisKernel<Median> (axis), image_in, image_out); return;
      case 2: loop.run  (AxisKernel<Sum>    (axis), image_in, image_out); return;
      case 3: loop.run  (AxisKernel<Product>(axis), image_in, image_out); return;
      case 4: loop.run  (AxisKernel<RMS>    (axis), image_in, image_out); return;
      case 5: loop.run  (AxisKernel<Var>    (axis), image_in, image_out); return;
      case 6: loop.run  (AxisKernel<Std>    (axis), image_in, image_out); return;
      case 7: loop.run  (AxisKernel<Min>    (axis), image_in, image_out); return;
      case 8: loop.run  (AxisKernel<Max>    (axis), image_in, image_out); return;
      case 9: loop.run  (AxisKernel<AbsMax> (axis), image_in, image_out); return;
      case 10: loop.run (AxisKernel<MagMax> (axis), image_in, image_out); return;
      default: assert (0);
    }

  } else {

    if (num_inputs < 2)
      throw Exception ("mrmath requires either multiple input images, or the -axis option to be provided");

    // Pre-load all image headers
    std::vector<std::unique_ptr<Header>> headers_in;

    // Header of first input image is the template to which all other input images are compared
    // auto header = Header::open (argument[0]);
    headers_in.push_back (std::unique_ptr<Header> (new Header::open (argument[0])));
    Header header (*headers_in[0]);

    // Wipe any excess unary-dimensional axes
    while (header.dim (header.ndim() - 1) == 1)
      header.set_ndim (header.ndim() - 1);

    // Verify that dimensions of all input images adequately match
    for (size_t i = 1; i != num_inputs; ++i) {
      const std::string path = argument[i];
      headers_in.push_back (std::unique_ptr<Header> (new Header::open (path)));
      const Header& temp (*headers_in[i]);
      if (temp.ndim() < header.ndim())
        throw Exception ("Image " + path + " has fewer axes than first imput image " + header.name());
      for (size_t axis = 0; axis != header.ndim(); ++axis) {
        if (temp.dim(axis) != header.dim(axis))
          throw Exception ("Dimensions of image " + path + " do not match those of first input image " + header.name());
      }
      for (size_t axis = header.ndim(); axis != temp.ndim(); ++axis) {
        if (temp.dim(axis) != 1)
          throw Exception ("Image " + path + " has axis with non-unary dimension beyond first input image " + header.name());
      }
    }

    // Instantiate a kernel depending on the operation requested
    std::unique_ptr<ImageKernelBase> kernel;
    switch (op) {
      case 0:  kernel.reset (new ImageKernel<Mean>    (header, output_path)); break;
      case 1:  kernel.reset (new ImageKernel<Median>  (header, output_path)); break;
      case 2:  kernel.reset (new ImageKernel<Sum>     (header, output_path)); break;
      case 3:  kernel.reset (new ImageKernel<Product> (header, output_path)); break;
      case 4:  kernel.reset (new ImageKernel<RMS>     (header, output_path)); break;
      case 5:  kernel.reset (new ImageKernel<Var>     (header, output_path)); break;
      case 6:  kernel.reset (new ImageKernel<Std>     (header, output_path)); break;
      case 7:  kernel.reset (new ImageKernel<Min>     (header, output_path)); break;
      case 8:  kernel.reset (new ImageKernel<Max>     (header, output_path)); break;
      case 9:  kernel.reset (new ImageKernel<AbsMax>  (header, output_path)); break;
      case 10: kernel.reset (new ImageKernel<MagMax>  (header, output_path)); break;
      default: assert (0);
    }

    // Feed the input images to the kernel one at a time
    {
      ProgressBar progress (std::string("computing ") + operations[op] + " across "
          + str(headers_in.size()) + " images...", num_inputs);
      for (size_t i = 0; i != headers_in.size(); ++i) {
        kernel->process (*headers_in[i]);
        ++progress;
      }
    }

    // Image output is handled by the kernel destructor

  }

}

<commit_msg>syntax overhaul: mrmath: still incomplete<commit_after>/*
    Copyright 2008 Brain Research Institute, Melbourne, Australia

    Written by J-Donald Tournier, 27/11/09.

    This file is part of MRtrix.

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

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

    You should have received a copy of the GNU General Public License
    along with MRtrix.  If not, see <http://www.gnu.org/licenses/>.

*/

#include "command.h"
#include "progressbar.h"
#include "memory.h"
#include "image.h"
// #include "header.h"
#include "algo/threaded_loop.h"
#include "math/math.h"
#include "math/median.h"

#include <limits>
#include <vector>

using namespace MR;
using namespace App;

const char* operations[] = {
  "mean",
  "median",
  "sum",
  "product",
  "rms",
  "var",
  "std",
  "min",
  "max",
  "absmax", // Maximum of absolute values
  "magmax", // Value for which the magnitude is the maximum (i.e. preserves signed-ness)
  NULL
};

void usage ()
{
  DESCRIPTION
    + "compute summary statistic on image intensities either across images, "
    "or along a specified axis for a single image. Supported operations are:"

    + "mean, median, sum, product, rms (root-mean-square value), var (unbiased variance), "
    "std (unbiased standard deviation), min, max, absmax (maximum absolute value), "
    "magmax (value with maximum absolute value, preserving its sign)."

    + "See also 'mrcalc' to compute per-voxel operations.";

  ARGUMENTS
  + Argument ("input", "the input image.").type_image_in ().allow_multiple()
  + Argument ("operation", "the operation to apply, one of: " + join(operations, ", ") + ".").type_choice (operations)
  + Argument ("output", "the output image.").type_image_out ();

  OPTIONS
  + Option ("axis", "perform operation along a specified axis of a single input image")
    + Argument ("index").type_integer();

}

typedef float value_type;

class Mean {
  public:
    Mean () : sum (0.0), count (0) { }
    void operator() (value_type val) {
      if (std::isfinite (val)) {
        sum += val;
        ++count;
      }
    }
    value_type result () const {
      if (!count)
        return NAN;
      return sum / count;
    }
    double sum;
    size_t count;
};

class Median {
  public:
    Median () { }
    void operator() (value_type val) {
      if (!std::isnan (val))
        values.push_back(val);
    }
    value_type result () {
      return Math::median(values);
    }
    std::vector<value_type> values;
};

class Sum {
  public:
    Sum () : sum (0.0) { }
    void operator() (value_type val) {
      if (std::isfinite (val))
        sum += val;
    }
    value_type result () const {
      return sum;
    }
    double sum;
};

class Product {
  public:
    Product () : product (0.0) { }
    void operator() (value_type val) {
      if (std::isfinite (val))
        product += val;
    }
    value_type result () const {
      return product;
    }
    double product;
};

class RMS {
  public:
    RMS() : sum (0.0), count (0) { }
    void operator() (value_type val) {
      if (std::isfinite (val)) {
        sum += Math::pow2 (val);
        ++count;
      }
    }
    value_type result() const {
      if (!count)
        return NAN;
      return std::sqrt(sum / count);
    }
    double sum;
    size_t count;
};

class Var {
  public:
    Var () : sum (0.0), sum_sqr (0.0), count (0) { }
    void operator() (value_type val) {
      if (std::isfinite (val)) {
        sum += val;
        sum_sqr += Math::pow2 (val);
        ++count;
      }
    }
    value_type result () const {
      if (count < 2)
        return NAN;
      return  (sum_sqr - Math::pow2 (sum) / static_cast<double> (count)) / (static_cast<double> (count) - 1.0);
    }
    double sum, sum_sqr;
    size_t count;
};

class Std : public Var {
  public:
    Std() : Var() { }
    value_type result () const { return std::sqrt (Var::result()); }
};

class Min {
  public:
    Min () : min (std::numeric_limits<value_type>::infinity()) { }
    void operator() (value_type val) {
      if (std::isfinite (val) && val < min)
        min = val;
    }
    value_type result () const { return std::isfinite (min) ? min : NAN; }
    value_type min;
};

class Max {
  public:
    Max () : max (-std::numeric_limits<value_type>::infinity()) { }
    void operator() (value_type val) {
      if (std::isfinite (val) && val > max)
        max = val;
    }
    value_type result () const { return std::isfinite (max) ? max : NAN; }
    value_type max;
};

class AbsMax {
  public:
    AbsMax () : max (-std::numeric_limits<value_type>::infinity()) { }
    void operator() (value_type val) {
      if (std::isfinite (val) && std::abs(val) > max)
        max = std::abs(val);
    }
    value_type result () const { return std::isfinite (max) ? max : NAN; }
    value_type max;
};

class MagMax {
  public:
    MagMax () : max (-std::numeric_limits<value_type>::infinity()) { }
    MagMax (const int i) : max (-std::numeric_limits<value_type>::infinity()) { }
    void operator() (value_type val) {
      if (std::isfinite (val) && (!std::isfinite (max) || std::abs(val) > std::abs (max)))
        max = val;
    }
    value_type result () const { return std::isfinite (max) ? max : NAN; }
    value_type max;
};

template <class Operation>
class AxisKernel {
  public:
    AxisKernel (size_t axis) : axis (axis) { }

    template <class InputImageType, class OutputImageType>
      void operator() (InputImageType& in, OutputImageType& out) {
        Operation op;
        for (in[axis] = 0; in[axis] < in.size(axis); ++in[axis])
          op (in.value());
        out.value() = op.result();
      }
  protected:
    const size_t axis;
};

class ImageKernelBase {
  public:
    ImageKernelBase (const std::string& path) :
      output_path (path) { }
    virtual ~ImageKernelBase() { }
    virtual void process (const Header& image_in) = 0;
  protected:
    const std::string output_path;
};

template <class Operation>
class ImageKernel : public ImageKernelBase {
  protected:
    class InitFunctor {
      public:
        template <class ImageType>
          void operator() (ImageType& out) const { out.value() = Operation(); }
    };
    class ProcessFunctor {
      public:
        template <class ImageType1, class ImageType2>
          void operator() (ImageType1& out, ImageType2& in) const {
            Operation op = out.value();
            op (in.value());
            out.value() = op;
          }
    };
    class ResultFunctor {
      public:
        template <class ImageType1, class ImageType2>
          void operator() (ImageType1& out, ImageType2& in) const {
            Operation op = in.value();
            out.value() = op.result();
          }
    };

  public:
    ImageKernel (const Header& header, const std::string& path) :
      ImageKernelBase (path),
      header (header){
        image = header.get_image<float>();
        ThreadedLoop (image).run (InitFunctor(), image);
      }

    ~ImageKernel()
    {
      Image<value_type> out (output_path, header);
      ThreadedLoop (image).run (ResultFunctor(), out, image);
    }

    void process (const Header& image_in)
    {
      Image<value_type> in (image_in);
      ThreadedLoop (image).run (ProcessFunctor(), image, in);
    }

  protected:
    const Header& header;
    Image<float> image;
    // Image<Operation> image;
};

void run ()
{
  const size_t num_inputs = argument.size() - 2;
  const int op = argument[num_inputs];
  const std::string& output_path = argument.back();

  Options opt = get_options ("axis");
  if (opt.size()) {

    if (num_inputs != 1)
      throw Exception ("Option -axis only applies if a single input image is used");

    const size_t axis = opt[0][0];

    auto image_in = Header::open (argument[0]).get_image<value_type>().with_direct_io (Stride::contiguous_along_axis (axis));

    if (axis >= image_in.ndim())
      throw Exception ("Cannot perform operation along axis " + str (axis) + "; image only has " + str(image_in.ndim()) + " axes");

    Header header_out (image_in.header());

    header_out.datatype() = DataType::Float32;
    header_out.size(axis) = 1;
    squeeze_dim (header_out);

    auto image_out = Header::create (output_path, header_out).get_image<float>();
    // auto image_out = Header::allocate (header_out).get_image<float>();
    // Image image_out (output_path, header_out);

    ThreadedLoop loop (std::string("computing ") + operations[op] + " along axis " + str(axis) + "...", image_out);

    switch (op) {
      case 0: loop.run  (AxisKernel<Mean>   (axis), image_in, image_out); return;
      case 1: loop.run  (AxisKernel<Median> (axis), image_in, image_out); return;
      case 2: loop.run  (AxisKernel<Sum>    (axis), image_in, image_out); return;
      case 3: loop.run  (AxisKernel<Product>(axis), image_in, image_out); return;
      case 4: loop.run  (AxisKernel<RMS>    (axis), image_in, image_out); return;
      case 5: loop.run  (AxisKernel<Var>    (axis), image_in, image_out); return;
      case 6: loop.run  (AxisKernel<Std>    (axis), image_in, image_out); return;
      case 7: loop.run  (AxisKernel<Min>    (axis), image_in, image_out); return;
      case 8: loop.run  (AxisKernel<Max>    (axis), image_in, image_out); return;
      case 9: loop.run  (AxisKernel<AbsMax> (axis), image_in, image_out); return;
      case 10: loop.run (AxisKernel<MagMax> (axis), image_in, image_out); return;
      default: assert (0);
    }

  } else {

    if (num_inputs < 2)
      throw Exception ("mrmath requires either multiple input images, or the -axis option to be provided");

    // Pre-load all image headers
    std::vector<Header> headers_in;
    // std::vector<std::unique_ptr<Header>> headers_in;

    // Header of first input image is the template to which all other input images are compared
    // auto header = Header::open (argument[0]);
    // headers_in.push_back (std::unique_ptr<Header> (new Header (Header::open (argument[0]))));
    headers_in.push_back (Header::open (argument[0]));
    Header header (headers_in[0]);

    // Wipe any excess unary-dimensional axes
    while (header.size (header.ndim() - 1) == 1)
      header.set_ndim (header.ndim() - 1);

    // Verify that dimensions of all input images adequately match
    for (size_t i = 1; i != num_inputs; ++i) {
      const std::string path = argument[i];
      // headers_in.push_back (std::unique_ptr<Header> (new Header (Header::open (path))));
      headers_in.push_back (Header::open (path));
      const Header temp (headers_in[i]);
      if (temp.ndim() < header.ndim())
        throw Exception ("Image " + path + " has fewer axes than first imput image " + header.name());
      for (size_t axis = 0; axis != header.ndim(); ++axis) {
        if (temp.size(axis) != header.size(axis))
          throw Exception ("Dimensions of image " + path + " do not match those of first input image " + header.name());
      }
      for (size_t axis = header.ndim(); axis != temp.ndim(); ++axis) {
        if (temp.size(axis) != 1)
          throw Exception ("Image " + path + " has axis with non-unary dimension beyond first input image " + header.name());
      }
    }

    // Instantiate a kernel depending on the operation requested
    std::unique_ptr<ImageKernelBase> kernel;
    switch (op) {
      case 0:  kernel.reset (new ImageKernel<Mean>    (header, output_path)); break;
      case 1:  kernel.reset (new ImageKernel<Median>  (header, output_path)); break;
      case 2:  kernel.reset (new ImageKernel<Sum>     (header, output_path)); break;
      case 3:  kernel.reset (new ImageKernel<Product> (header, output_path)); break;
      case 4:  kernel.reset (new ImageKernel<RMS>     (header, output_path)); break;
      case 5:  kernel.reset (new ImageKernel<Var>     (header, output_path)); break;
      case 6:  kernel.reset (new ImageKernel<Std>     (header, output_path)); break;
      case 7:  kernel.reset (new ImageKernel<Min>     (header, output_path)); break;
      case 8:  kernel.reset (new ImageKernel<Max>     (header, output_path)); break;
      case 9:  kernel.reset (new ImageKernel<AbsMax>  (header, output_path)); break;
      case 10: kernel.reset (new ImageKernel<MagMax>  (header, output_path)); break;
      default: assert (0);
    }

    // Feed the input images to the kernel one at a time
    {
      ProgressBar progress (std::string("computing ") + operations[op] + " across "
          + str(headers_in.size()) + " images...", num_inputs);
      for (size_t i = 0; i != headers_in.size(); ++i) {
        kernel->process (headers_in[i]);
        ++progress;
      }
    }

    // Image output is handled by the kernel destructor

  }

}

<|endoftext|>


<commit_before>// Copyright (c) 2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "base/test_file_util.h"

#include <windows.h>

#include <vector>

#include "base/file_util.h"
#include "base/scoped_handle.h"

namespace file_util {

// We could use GetSystemInfo to get the page size, but this serves
// our purpose fine since 4K is the page size on x86 as well as x64.
static const ptrdiff_t kPageSize = 4096;

bool EvictFileFromSystemCache(const wchar_t* file) {
  // Request exclusive access to the file and overwrite it with no buffering.
  ScopedHandle file_handle(
      CreateFile(file, GENERIC_READ | GENERIC_WRITE, 0, NULL,
                 OPEN_EXISTING, FILE_FLAG_NO_BUFFERING, NULL));
  if (!file_handle)
    return false;

  // Get some attributes to restore later.
  BY_HANDLE_FILE_INFORMATION bhi = {0};
  CHECK(::GetFileInformationByHandle(file_handle, &bhi));

  // Execute in chunks. It could be optimized. We want to do few of these since
  // these operations will be slow without the cache.

  // Non-buffered reads and writes need to be sector aligned and since sector
  // sizes typically range from 512-4096 bytes, we just use the page size.
  // The buffer size is twice the size of a page (minus one) since we need to
  // get an aligned pointer into the buffer that we can use.
  char buffer[2 * kPageSize - 1];
  // Get an aligned pointer into buffer.
  char* read_write = reinterpret_cast<char*>(
      reinterpret_cast<ptrdiff_t>(buffer + kPageSize - 1) & ~(kPageSize - 1));
  DCHECK((reinterpret_cast<int>(read_write) % kPageSize) == 0);

  // If the file size isn't a multiple of kPageSize, we'll need special
  // processing.
  bool file_is_page_aligned = true;
  int total_bytes = 0;
  DWORD bytes_read, bytes_written;
  for (;;) {
    bytes_read = 0;
    ReadFile(file_handle, read_write, kPageSize, &bytes_read, NULL);
    if (bytes_read == 0)
      break;

    if (bytes_read < kPageSize) {
      // Zero out the remaining part of the buffer.
      // WriteFile will fail if we provide a buffer size that isn't a
      // sector multiple, so we'll have to write the entire buffer with
      // padded zeros and then use SetEndOfFile to truncate the file.
      ZeroMemory(read_write + bytes_read, kPageSize - bytes_read);
      file_is_page_aligned = false;
    }

    // Move back to the position we just read from.
    // Note that SetFilePointer will also fail if total_bytes isn't sector
    // aligned, but that shouldn't happen here.
    DCHECK((total_bytes % kPageSize) == 0);
    SetFilePointer(file_handle, total_bytes, NULL, FILE_BEGIN);
    if (!WriteFile(file_handle, read_write, kPageSize, &bytes_written, NULL) ||
        bytes_written != kPageSize) {
      DCHECK(false);
      return false;
    }

    total_bytes += bytes_read;

    // If this is false, then we just processed the last portion of the file.
    if (!file_is_page_aligned)
      break;
  }

  if (!file_is_page_aligned) {
    // The size of the file isn't a multiple of the page size, so we'll have
    // to open the file again, this time without the FILE_FLAG_NO_BUFFERING
    // flag and use SetEndOfFile to mark EOF.
    file_handle.Set(CreateFile(file, GENERIC_WRITE, 0, NULL, OPEN_EXISTING,
                               0, NULL));
    CHECK(SetFilePointer(file_handle, total_bytes, NULL, FILE_BEGIN) !=
          INVALID_SET_FILE_POINTER);
    CHECK(::SetEndOfFile(file_handle));
  }

  // Restore the file attributes.
  CHECK(::SetFileTime(file_handle, &bhi.ftCreationTime, &bhi.ftLastAccessTime,
                      &bhi.ftLastWriteTime));

  return true;
}

// Like CopyFileNoCache but recursively copies all files and subdirectories
// in the given input directory to the output directory.
bool CopyRecursiveDirNoCache(const std::wstring& source_dir,
                             const std::wstring& dest_dir) {
  // Try to create the directory if it doesn't already exist.
  if (!CreateDirectory(dest_dir)) {
    if (GetLastError() != ERROR_ALREADY_EXISTS)
      return false;
  }

  std::vector<std::wstring> files_copied;

  std::wstring src(source_dir);
  file_util::AppendToPath(&src, L"*");

  WIN32_FIND_DATA fd;
  HANDLE fh = FindFirstFile(src.c_str(), &fd);
  if (fh == INVALID_HANDLE_VALUE)
    return false;

  do {
    std::wstring cur_file(fd.cFileName);
    if (cur_file == L"." || cur_file == L"..")
      continue;  // Skip these special entries.

    std::wstring cur_source_path(source_dir);
    file_util::AppendToPath(&cur_source_path, cur_file);

    std::wstring cur_dest_path(dest_dir);
    file_util::AppendToPath(&cur_dest_path, cur_file);

    if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
      // Recursively copy a subdirectory. We stripped "." and ".." already.
      if (!CopyRecursiveDirNoCache(cur_source_path, cur_dest_path)) {
        FindClose(fh);
        return false;
      }
    } else {
      // Copy the file.
      if (!::CopyFile(cur_source_path.c_str(), cur_dest_path.c_str(), false)) {
        FindClose(fh);
        return false;
      }

      // We don't check for errors from this function, often, we are copying
      // files that are in the repository, and they will have read-only set.
      // This will prevent us from evicting from the cache, but these don't
      // matter anyway.
      EvictFileFromSystemCache(cur_dest_path.c_str());
    }
  } while (FindNextFile(fh, &fd));

  FindClose(fh);
  return true;
}

}  // namespace file_util

<commit_msg>Fix CloseHandle blunder.  I was thinking that the handle would be closed by Set, but of course I need to close the handle before the CreateFile call... doh!<commit_after>// Copyright (c) 2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "base/test_file_util.h"

#include <windows.h>

#include <vector>

#include "base/file_util.h"
#include "base/scoped_handle.h"

namespace file_util {

// We could use GetSystemInfo to get the page size, but this serves
// our purpose fine since 4K is the page size on x86 as well as x64.
static const ptrdiff_t kPageSize = 4096;

bool EvictFileFromSystemCache(const wchar_t* file) {
  // Request exclusive access to the file and overwrite it with no buffering.
  ScopedHandle file_handle(
      CreateFile(file, GENERIC_READ | GENERIC_WRITE, 0, NULL,
                 OPEN_EXISTING, FILE_FLAG_NO_BUFFERING, NULL));
  if (!file_handle)
    return false;

  // Get some attributes to restore later.
  BY_HANDLE_FILE_INFORMATION bhi = {0};
  CHECK(::GetFileInformationByHandle(file_handle, &bhi));

  // Execute in chunks. It could be optimized. We want to do few of these since
  // these operations will be slow without the cache.

  // Non-buffered reads and writes need to be sector aligned and since sector
  // sizes typically range from 512-4096 bytes, we just use the page size.
  // The buffer size is twice the size of a page (minus one) since we need to
  // get an aligned pointer into the buffer that we can use.
  char buffer[2 * kPageSize - 1];
  // Get an aligned pointer into buffer.
  char* read_write = reinterpret_cast<char*>(
      reinterpret_cast<ptrdiff_t>(buffer + kPageSize - 1) & ~(kPageSize - 1));
  DCHECK((reinterpret_cast<int>(read_write) % kPageSize) == 0);

  // If the file size isn't a multiple of kPageSize, we'll need special
  // processing.
  bool file_is_page_aligned = true;
  int total_bytes = 0;
  DWORD bytes_read, bytes_written;
  for (;;) {
    bytes_read = 0;
    ReadFile(file_handle, read_write, kPageSize, &bytes_read, NULL);
    if (bytes_read == 0)
      break;

    if (bytes_read < kPageSize) {
      // Zero out the remaining part of the buffer.
      // WriteFile will fail if we provide a buffer size that isn't a
      // sector multiple, so we'll have to write the entire buffer with
      // padded zeros and then use SetEndOfFile to truncate the file.
      ZeroMemory(read_write + bytes_read, kPageSize - bytes_read);
      file_is_page_aligned = false;
    }

    // Move back to the position we just read from.
    // Note that SetFilePointer will also fail if total_bytes isn't sector
    // aligned, but that shouldn't happen here.
    DCHECK((total_bytes % kPageSize) == 0);
    SetFilePointer(file_handle, total_bytes, NULL, FILE_BEGIN);
    if (!WriteFile(file_handle, read_write, kPageSize, &bytes_written, NULL) ||
        bytes_written != kPageSize) {
      DCHECK(false);
      return false;
    }

    total_bytes += bytes_read;

    // If this is false, then we just processed the last portion of the file.
    if (!file_is_page_aligned)
      break;
  }

  if (!file_is_page_aligned) {
    // The size of the file isn't a multiple of the page size, so we'll have
    // to open the file again, this time without the FILE_FLAG_NO_BUFFERING
    // flag and use SetEndOfFile to mark EOF.
    file_handle.Set(NULL);
    file_handle.Set(CreateFile(file, GENERIC_WRITE, 0, NULL, OPEN_EXISTING,
                               0, NULL));
    CHECK(SetFilePointer(file_handle, total_bytes, NULL, FILE_BEGIN) !=
          INVALID_SET_FILE_POINTER);
    CHECK(::SetEndOfFile(file_handle));
  }

  // Restore the file attributes.
  CHECK(::SetFileTime(file_handle, &bhi.ftCreationTime, &bhi.ftLastAccessTime,
                      &bhi.ftLastWriteTime));

  return true;
}

// Like CopyFileNoCache but recursively copies all files and subdirectories
// in the given input directory to the output directory.
bool CopyRecursiveDirNoCache(const std::wstring& source_dir,
                             const std::wstring& dest_dir) {
  // Try to create the directory if it doesn't already exist.
  if (!CreateDirectory(dest_dir)) {
    if (GetLastError() != ERROR_ALREADY_EXISTS)
      return false;
  }

  std::vector<std::wstring> files_copied;

  std::wstring src(source_dir);
  file_util::AppendToPath(&src, L"*");

  WIN32_FIND_DATA fd;
  HANDLE fh = FindFirstFile(src.c_str(), &fd);
  if (fh == INVALID_HANDLE_VALUE)
    return false;

  do {
    std::wstring cur_file(fd.cFileName);
    if (cur_file == L"." || cur_file == L"..")
      continue;  // Skip these special entries.

    std::wstring cur_source_path(source_dir);
    file_util::AppendToPath(&cur_source_path, cur_file);

    std::wstring cur_dest_path(dest_dir);
    file_util::AppendToPath(&cur_dest_path, cur_file);

    if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
      // Recursively copy a subdirectory. We stripped "." and ".." already.
      if (!CopyRecursiveDirNoCache(cur_source_path, cur_dest_path)) {
        FindClose(fh);
        return false;
      }
    } else {
      // Copy the file.
      if (!::CopyFile(cur_source_path.c_str(), cur_dest_path.c_str(), false)) {
        FindClose(fh);
        return false;
      }

      // We don't check for errors from this function, often, we are copying
      // files that are in the repository, and they will have read-only set.
      // This will prevent us from evicting from the cache, but these don't
      // matter anyway.
      EvictFileFromSystemCache(cur_dest_path.c_str());
    }
  } while (FindNextFile(fh, &fd));

  FindClose(fh);
  return true;
}

}  // namespace file_util

<|endoftext|>


<commit_before>#include "player.hpp"

namespace msrv {
namespace player_foobar2000 {

namespace {

class TrackQueryImpl : public TrackQuery
{
public:
    TrackQueryImpl(TitleFormatVector columnsVal)
        : columns(std::move(columnsVal))
    {
    }

    TitleFormatVector columns;
};

inline double clampVolume(double value)
{
    return std::max(std::min(value, 0.0), static_cast<double>(playback_control::volume_mute));
}

}

std::vector<std::string> PlayerImpl::evaluatePlaybackColumns(const TitleFormatVector& compiledColumns)
{
    std::vector<std::string> result;
    result.reserve(compiledColumns.size());

    pfc::string8 buffer;

    for (auto& compiledColumn : compiledColumns)
    {
        auto ret = playbackControl_->playback_format_title(
            nullptr,
            buffer,
            compiledColumn,
            nullptr,
            playback_control::display_level_all);

        if (!ret)
        {
            result.clear();
            return result;
        }

        result.emplace_back(buffer.get_ptr(), buffer.get_length());
    }

    return result;
}

PlaybackState PlayerImpl::getPlaybackState()
{
    if (playbackControl_->is_paused())
       return PlaybackState::PAUSED;

    if (playbackControl_->is_playing())
        return PlaybackState::PLAYING;

    return PlaybackState::STOPPED;
}

void PlayerImpl::queryVolume(VolumeInfo* volume)
{
    volume->type = VolumeType::DB;
    volume->min = playback_control::volume_mute;
    volume->max = 0.0;
    volume->value = playbackControl_->get_volume();
    volume->isMuted = playbackControl_->is_muted();
}

void PlayerImpl::queryActiveItem(ActiveItemInfo* info, TrackQuery* queryPtr)
{
    t_size activePlaylist;
    t_size activeItem;

    info->position = playbackControl_->playback_get_position();
    info->duration = playbackControl_->playback_get_length_ex();

    if (queryPtr)
    {
        info->columns = evaluatePlaybackColumns(
            static_cast<TrackQueryImpl*>(queryPtr)->columns);
    }

    if (playlistManager_->get_playing_item_location(&activePlaylist, &activeItem))
    {
        info->playlistId = playlists_->getId(activePlaylist);
        info->playlistIndex = activePlaylist;
        info->index = activeItem;
    }
    else
    {
        info->playlistIndex = -1;
        info->index = -1;
    }
}

PlayerStatePtr PlayerImpl::queryPlayerState(TrackQuery* activeItemQuery)
{
    playlists_->ensureInitialized();

    auto state = std::make_unique<PlayerState>();

    state->playbackState = getPlaybackState();
    queryVolume(&state->volume);
    queryActiveItem(&state->activeItem, activeItemQuery);
    state->playbackMode = playlistManager_->playback_order_get_active();
    state->playbackModes = &playbackModes_;

    return state;
}

void PlayerImpl::playCurrent()
{
    playbackControl_->play_or_unpause();
}

void PlayerImpl::playItem(const PlaylistRef& plref, int32_t itemIndex)
{
    auto playlist = playlists_->resolve(plref);

    if (isValidItemIndex(playlist, itemIndex))
        playlistManager_->playlist_execute_default_action(playlist, itemIndex);
}

void PlayerImpl::playRandom()
{
    playbackControl_->start(playback_control::track_command_rand);
}

void PlayerImpl::playNext()
{
    playbackControl_->next();
}

void PlayerImpl::playPrevious()
{
    playbackControl_->previous();
}

void PlayerImpl::stop()
{
    playbackControl_->stop();
}

void PlayerImpl::pause()
{
    playbackControl_->pause(true);
}

void PlayerImpl::togglePause()
{
    playbackControl_->toggle_pause();
}

void PlayerImpl::setMuted(Switch val)
{
    switch (val)
    {
    case Switch::FALSE:
        if (playbackControl_->is_muted())
            playbackControl_->volume_mute_toggle();
        break;

    case Switch::TRUE:
        if (!playbackControl_->is_muted())
            playbackControl_->volume_mute_toggle();
        break;

    case Switch::TOGGLE:
        playbackControl_->volume_mute_toggle();
        break;
    }
}

void PlayerImpl::seekAbsolute(double offsetSeconds)
{
    playbackControl_->playback_seek(offsetSeconds);
}

void PlayerImpl::seekRelative(double offsetSeconds)
{
    playbackControl_->playback_seek_delta(offsetSeconds);
}

void PlayerImpl::setVolume(double val)
{
    playbackControl_->set_volume(static_cast<float>(clampVolume(val)));
}

void PlayerImpl::initPlaybackModes()
{
    t_size count = playlistManager_->playback_order_get_count();

    playbackModes_.reserve(count);

    for (t_size i = 0; i < count; i++)
        playbackModes_.emplace_back(playlistManager_->playback_order_get_name(i));
}

void PlayerImpl::setPlaybackMode(int32_t val)
{
    t_size count = playlistManager_->playback_order_get_count();

    if (val < 0 || static_cast<t_size>(val) >= count)
        throw InvalidRequestException("Invalid playback mode");

    playlistManager_->playback_order_set_active(val);
}

TrackQueryPtr PlayerImpl::createTrackQuery(const std::vector<std::string>& columns)
{
    return std::make_unique<TrackQueryImpl>(compileColumns(columns));
}

}}
<commit_msg>player_control.cpp: activate playlist when playing item (fixes #55)<commit_after>#include "player.hpp"

namespace msrv {
namespace player_foobar2000 {

namespace {

class TrackQueryImpl : public TrackQuery
{
public:
    TrackQueryImpl(TitleFormatVector columnsVal)
        : columns(std::move(columnsVal))
    {
    }

    TitleFormatVector columns;
};

inline double clampVolume(double value)
{
    return std::max(std::min(value, 0.0), static_cast<double>(playback_control::volume_mute));
}

}

std::vector<std::string> PlayerImpl::evaluatePlaybackColumns(const TitleFormatVector& compiledColumns)
{
    std::vector<std::string> result;
    result.reserve(compiledColumns.size());

    pfc::string8 buffer;

    for (auto& compiledColumn : compiledColumns)
    {
        auto ret = playbackControl_->playback_format_title(
            nullptr,
            buffer,
            compiledColumn,
            nullptr,
            playback_control::display_level_all);

        if (!ret)
        {
            result.clear();
            return result;
        }

        result.emplace_back(buffer.get_ptr(), buffer.get_length());
    }

    return result;
}

PlaybackState PlayerImpl::getPlaybackState()
{
    if (playbackControl_->is_paused())
       return PlaybackState::PAUSED;

    if (playbackControl_->is_playing())
        return PlaybackState::PLAYING;

    return PlaybackState::STOPPED;
}

void PlayerImpl::queryVolume(VolumeInfo* volume)
{
    volume->type = VolumeType::DB;
    volume->min = playback_control::volume_mute;
    volume->max = 0.0;
    volume->value = playbackControl_->get_volume();
    volume->isMuted = playbackControl_->is_muted();
}

void PlayerImpl::queryActiveItem(ActiveItemInfo* info, TrackQuery* queryPtr)
{
    t_size activePlaylist;
    t_size activeItem;

    info->position = playbackControl_->playback_get_position();
    info->duration = playbackControl_->playback_get_length_ex();

    if (queryPtr)
    {
        info->columns = evaluatePlaybackColumns(
            static_cast<TrackQueryImpl*>(queryPtr)->columns);
    }

    if (playlistManager_->get_playing_item_location(&activePlaylist, &activeItem))
    {
        info->playlistId = playlists_->getId(activePlaylist);
        info->playlistIndex = activePlaylist;
        info->index = activeItem;
    }
    else
    {
        info->playlistIndex = -1;
        info->index = -1;
    }
}

PlayerStatePtr PlayerImpl::queryPlayerState(TrackQuery* activeItemQuery)
{
    playlists_->ensureInitialized();

    auto state = std::make_unique<PlayerState>();

    state->playbackState = getPlaybackState();
    queryVolume(&state->volume);
    queryActiveItem(&state->activeItem, activeItemQuery);
    state->playbackMode = playlistManager_->playback_order_get_active();
    state->playbackModes = &playbackModes_;

    return state;
}

void PlayerImpl::playCurrent()
{
    playbackControl_->play_or_unpause();
}

void PlayerImpl::playItem(const PlaylistRef& plref, int32_t itemIndex)
{
    auto playlist = playlists_->resolve(plref);

    if (!isValidItemIndex(playlist, itemIndex))
        return;

    playlistManager_->set_active_playlist(playlist);
    playlistManager_->playlist_execute_default_action(playlist, itemIndex);
}

void PlayerImpl::playRandom()
{
    playbackControl_->start(playback_control::track_command_rand);
}

void PlayerImpl::playNext()
{
    playbackControl_->next();
}

void PlayerImpl::playPrevious()
{
    playbackControl_->previous();
}

void PlayerImpl::stop()
{
    playbackControl_->stop();
}

void PlayerImpl::pause()
{
    playbackControl_->pause(true);
}

void PlayerImpl::togglePause()
{
    playbackControl_->toggle_pause();
}

void PlayerImpl::setMuted(Switch val)
{
    switch (val)
    {
    case Switch::FALSE:
        if (playbackControl_->is_muted())
            playbackControl_->volume_mute_toggle();
        break;

    case Switch::TRUE:
        if (!playbackControl_->is_muted())
            playbackControl_->volume_mute_toggle();
        break;

    case Switch::TOGGLE:
        playbackControl_->volume_mute_toggle();
        break;
    }
}

void PlayerImpl::seekAbsolute(double offsetSeconds)
{
    playbackControl_->playback_seek(offsetSeconds);
}

void PlayerImpl::seekRelative(double offsetSeconds)
{
    playbackControl_->playback_seek_delta(offsetSeconds);
}

void PlayerImpl::setVolume(double val)
{
    playbackControl_->set_volume(static_cast<float>(clampVolume(val)));
}

void PlayerImpl::initPlaybackModes()
{
    t_size count = playlistManager_->playback_order_get_count();

    playbackModes_.reserve(count);

    for (t_size i = 0; i < count; i++)
        playbackModes_.emplace_back(playlistManager_->playback_order_get_name(i));
}

void PlayerImpl::setPlaybackMode(int32_t val)
{
    t_size count = playlistManager_->playback_order_get_count();

    if (val < 0 || static_cast<t_size>(val) >= count)
        throw InvalidRequestException("Invalid playback mode");

    playlistManager_->playback_order_set_active(val);
}

TrackQueryPtr PlayerImpl::createTrackQuery(const std::vector<std::string>& columns)
{
    return std::make_unique<TrackQueryImpl>(compileColumns(columns));
}

}}
<|endoftext|>


<commit_before>#include <iostream>
#include <fstream>
#include <QUrl>
#include <QFileInfo>
#include "kernel.h"
#include "ilwisdata.h"
#include "resource.h"
#include "identity.h"
#include "OperationExpression.h"
#include "operationmetadata.h"
#include "operation.h"
#include "commandhandler.h"
#include "script.h"
#include "parserlexer/IlwisScriptLexer.h"
#include "parserlexer/IlwisScriptParser.h"
#include "symboltable.h"

using namespace Ilwis;
OperationImplementation *Script::create(quint64 metaid, const Ilwis::OperationExpression &expr)
{
    return new Script(metaid, expr);
}

Script::Script()
{
}

Script::Script(quint64 metaid,const Ilwis::OperationExpression &expr) : OperationImplementation(metaid, expr)
{
}

OperationImplementation::State Script::prepare() {
    QString txt = _expression.parm(0).value();
    QUrl url(txt);
    if ( url.isValid() && url.scheme() == "file") {
        QFileInfo inf( url.toLocalFile());
        bool exists = inf.exists();
        if (exists && inf.suffix() == "isf") {
            std::string text;
            std::ifstream in(inf.absoluteFilePath().toLatin1(), std::ios_base::in);
            if(in.is_open() && in.good()) {
                while(!in.eof()) {
                    std::string line;
                    std::getline(in, line);
                    text += line + ";";
                }
                char *buf = new char[text.size()];
                memcpy(buf,text.c_str(), text.size());
                _buffer.reset( buf );
                _bufferSize = text.size();
                return sPREPARED;
            }
        } else {
            return sPREPAREFAILED;
        }
    } else {
        return sPREPARED;
    }

    return sNOTPREPARED;
}

bool Script::execute(ExecutionContext *ctx)
{
    if (_prepState == sNOTPREPARED)
        if((_prepState = prepare()) != sPREPARED)
            return false;

    ANTLR3_UINT8 * bufferData = (ANTLR3_UINT8 *) _buffer.get();
    for(int i=0; i < _bufferSize; ++i) {
        if ( bufferData[i] == '\n') { //replace newlines with ; which are the actual seperators
            bufferData[i]=';';
        }
    }
    if ( bufferData[_bufferSize - 1] != ';')
        bufferData[_bufferSize - 1] = ';';

    pANTLR3_INPUT_STREAM input = antlr3StringStreamNew(bufferData,  ANTLR3_ENC_8BIT,  _bufferSize, (pANTLR3_UINT8)"ScriptText");
    if(input == NULL)
        return false;

    pilwisscriptLexer lxr = ilwisscriptLexerNew(input);
    if(lxr == NULL)
        return false;

    //Creates an empty token stream.
    pANTLR3_COMMON_TOKEN_STREAM tstream = antlr3CommonTokenStreamSourceNew(ANTLR3_SIZE_HINT, TOKENSOURCE(lxr));
    if(tstream == NULL)
        return false;

    //Creates a parser.
    pilwisscriptParser psr = ilwisscriptParserNew(tstream);
    if(psr == NULL)
        return false;

    //Run the parser rule. This also runs the lexer to create the token stream.
    ASTNode *scr = psr->script(psr);
    SymbolTable symbols;
    bool ok = scr->evaluate(symbols, 1000);
    return ok;

}

quint64 Script::createMetadata()
{
    QString urlTxt = QString("ilwis://operations/script");
    QUrl url(urlTxt);
    Resource res(url, itOPERATIONMETADATA);
    res.addProperty("namespace","ilwis");
    res.addProperty("longname","ilwisscript");
    res.addProperty("syntax","script file|script scriptline(,scriptline)*");
    res.addProperty("inparameters","1");
    res.addProperty("pin_1_type", itFILE | itSTRING);
    res.addProperty("pin_1_name", TR("input script file"));
    res.addProperty("pin_1_domain","none");
    res.addProperty("pin_1_desc",TR("input file containing script commands"));
    res.addProperty("outparameters",1);
    res.addProperty("pout_1_type", itBOOL);
    res.addProperty("pout_1_name", TR("succes"));
    res.addProperty("pout_1_domain","bool");
    res.addProperty("pout_1_desc",TR("returns the succes of the execution of the script"));

    res.prepare();
    urlTxt += "=" + QString::number(res.id());
    res.setUrl(QUrl(urlTxt));
//    IOperationMetaData md;
//    if(!md.prepare(res)) {
//        return i64UNDEF;
//    }
    mastercatalog()->addItems({res});
    return res.id();
}
<commit_msg>added preparse stage for if statements<commit_after>#include <iostream>
#include <fstream>
#include <QUrl>
#include <QFileInfo>
#include "kernel.h"
#include "ilwisdata.h"
#include "resource.h"
#include "identity.h"
#include "OperationExpression.h"
#include "operationmetadata.h"
#include "operation.h"
#include "commandhandler.h"
#include "script.h"
#include "parserlexer/IlwisScriptLexer.h"
#include "parserlexer/IlwisScriptParser.h"
#include "symboltable.h"

using namespace Ilwis;
OperationImplementation *Script::create(quint64 metaid, const Ilwis::OperationExpression &expr)
{
    return new Script(metaid, expr);
}

Script::Script()
{
}

Script::Script(quint64 metaid,const Ilwis::OperationExpression &expr) : OperationImplementation(metaid, expr)
{
}

OperationImplementation::State Script::prepare() {
    QString txt = _expression.parm(0).value();
    QUrl url(txt);
    if ( url.isValid() && url.scheme() == "file") {
        QFileInfo inf( url.toLocalFile());
        bool exists = inf.exists();
        if (exists && inf.suffix() == "isf") {
            std::string text;
            std::ifstream in(inf.absoluteFilePath().toLatin1(), std::ios_base::in);
            bool ignorenl=false;
            if(in.is_open() && in.good()) {
                while(!in.eof()) {
                    std::string line;
                    std::getline(in, line);
                    if (line.find("if ") != std::string::npos){
                        ignorenl=true;
                    }
                    if (line.find("endif") != std::string::npos){
                        ignorenl=false;
                    }
                    text += line + (ignorenl ? " " : ";");
                }
                char *buf = new char[text.size()];
                memcpy(buf,text.c_str(), text.size());
                _buffer.reset( buf );
                _bufferSize = text.size();
                return sPREPARED;
            }
        } else {
            return sPREPAREFAILED;
        }
    } else {
        return sPREPARED;
    }

    return sNOTPREPARED;
}

bool Script::execute(ExecutionContext *ctx)
{
    if (_prepState == sNOTPREPARED)
        if((_prepState = prepare()) != sPREPARED)
            return false;

    ANTLR3_UINT8 * bufferData = (ANTLR3_UINT8 *) _buffer.get();

    pANTLR3_INPUT_STREAM input = antlr3StringStreamNew(bufferData,  ANTLR3_ENC_8BIT,  _bufferSize, (pANTLR3_UINT8)"ScriptText");
    if(input == NULL)
        return false;

    pilwisscriptLexer lxr = ilwisscriptLexerNew(input);
    if(lxr == NULL)
        return false;

    //Creates an empty token stream.
    pANTLR3_COMMON_TOKEN_STREAM tstream = antlr3CommonTokenStreamSourceNew(ANTLR3_SIZE_HINT, TOKENSOURCE(lxr));
    if(tstream == NULL)
        return false;

    //Creates a parser.
    pilwisscriptParser psr = ilwisscriptParserNew(tstream);
    if(psr == NULL)
        return false;

    //Run the parser rule. This also runs the lexer to create the token stream.
    ASTNode *scr = psr->script(psr);
    SymbolTable symbols;
    bool ok = scr->evaluate(symbols, 1000);
    return ok;

}

quint64 Script::createMetadata()
{
    QString urlTxt = QString("ilwis://operations/script");
    QUrl url(urlTxt);
    Resource res(url, itOPERATIONMETADATA);
    res.addProperty("namespace","ilwis");
    res.addProperty("longname","ilwisscript");
    res.addProperty("syntax","script file|script scriptline(,scriptline)*");
    res.addProperty("inparameters","1");
    res.addProperty("pin_1_type", itFILE | itSTRING);
    res.addProperty("pin_1_name", TR("input script file"));
    res.addProperty("pin_1_domain","none");
    res.addProperty("pin_1_desc",TR("input file containing script commands"));
    res.addProperty("outparameters",1);
    res.addProperty("pout_1_type", itBOOL);
    res.addProperty("pout_1_name", TR("succes"));
    res.addProperty("pout_1_domain","bool");
    res.addProperty("pout_1_desc",TR("returns the succes of the execution of the script"));

    res.prepare();
    urlTxt += "=" + QString::number(res.id());
    res.setUrl(QUrl(urlTxt));
//    IOperationMetaData md;
//    if(!md.prepare(res)) {
//        return i64UNDEF;
//    }
    mastercatalog()->addItems({res});
    return res.id();
}
<|endoftext|>


<commit_before>#include "ChatBot.h"

// Konstruktor
ChatBot::ChatBot()
{

}
// Destruktor
ChatBot::~ChatBot()
{

}

// Verbindung zum Server aufbauen
void ChatBot::connectToServer(const char *host, int port)
{
    // Socket wird erstellt
    sock = socket(AF_INET, SOCK_STREAM, 0);
    if (sock < 0)
    {
        perror("Fehler Socket");
        disconnect();
        exit(1);
    }

    // Host wird ueberprueft
    hostent *hp = gethostbyname(host);
    if (!hp)
    {
        perror("Host nicht gefunden...");
        disconnect();
        exit(1);
    }

    // Serverinformation wird festgelegt
    sockaddr_in sin;
    memset((char*)&sin, 0, sizeof(sin));
    sin.sin_family = AF_INET;
    memcpy((char*)&sin.sin_addr, hp->h_addr, hp->h_length);
    sin.sin_port = htons(port);
    memset(&(sin.sin_zero), 0, 8*sizeof(char));

    // Verbindung mit dem Server
    if (connect(sock, (sockaddr*) &sin, sizeof(sin)) == -1)
    {
        perror("Verbindung fehlgeschlagen...");
        disconnect();
        exit(1);
    }
}

// Verbindung trennen
void ChatBot::disconnect()
{
    close(sock);
}

// Funktion um Nachrichten an den Server zu schicken
void ChatBot::sendToServer(string m)
{
    send(sock, m.c_str(), m.length(), 0);
}

void ChatBot::pingpong(string m)
{

}
void ChatBot::botIdentify(string nick, string user, string pw)
{

}

void ChatBot::botSkills(string m)
{

}

void ChatBot::botLoop()
{

}
<commit_msg>Bot als Klasse angelegt. Verbindung mit Server funktioniert<commit_after>#include "ChatBot.h"

// Konstruktor
ChatBot::ChatBot()
{

}
// Destruktor
ChatBot::~ChatBot()
{

}

// Verbindung zum Server aufbauen
void ChatBot::connectToServer(const char *host, int port)
{
    // Socket wird erstellt
    sock = socket(AF_INET, SOCK_STREAM, 0);
    if (sock < 0)
    {
        perror("Fehler Socket");
        disconnect();
        exit(1);
    }

    // Host wird ueberprueft
    hostent *hp = gethostbyname(host);
    if (!hp)
    {
        perror("Host nicht gefunden...");
        disconnect();
        exit(1);
    }

    // Serverinformation wird festgelegt
    sockaddr_in sin;
    memset((char*)&sin, 0, sizeof(sin));
    sin.sin_family = AF_INET;
    memcpy((char*)&sin.sin_addr, hp->h_addr, hp->h_length);
    sin.sin_port = htons(port);
    memset(&(sin.sin_zero), 0, 8*sizeof(char));

    // Verbindung mit dem Server
    if (connect(sock, (sockaddr*) &sin, sizeof(sin)) == -1)
    {
        perror("Verbindung fehlgeschlagen...");
        disconnect();
        exit(1);
    }
}

// Verbindung trennen
void ChatBot::disconnect()
{
    close(sock);
}

// Funktion um Nachrichten an den Server zu schicken
void ChatBot::sendToServer(string m)
{
    send(sock, m.c_str(), m.length(), 0);
}

void ChatBot::pingpong(string m)
{

}
void ChatBot::botIdentify(string nick, string user, string pw)
{

}

void ChatBot::botSkills(string m)
{

}

void ChatBot::botLoop()
{

}
<|endoftext|>