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

#include "InMemorySymbolIndex.h"
#include "IncludeFixer.h"
#include "IncludeFixerContext.h"
#include "SymbolIndexManager.h"
#include "YamlSymbolIndex.h"
#include "clang/Format/Format.h"
#include "clang/Frontend/TextDiagnosticPrinter.h"
#include "clang/Rewrite/Core/Rewriter.h"
#include "clang/Tooling/CommonOptionsParser.h"
#include "clang/Tooling/Core/Replacement.h"
#include "clang/Tooling/Tooling.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/YAMLTraits.h"

using namespace clang;
using namespace llvm;
using clang::include_fixer::IncludeFixerContext;

LLVM_YAML_IS_DOCUMENT_LIST_VECTOR(IncludeFixerContext)
LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(std::string)
LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(IncludeFixerContext::HeaderInfo)

namespace llvm {
namespace yaml {

template <> struct MappingTraits<tooling::Range> {
  struct NormalizedRange {
    NormalizedRange(const IO &) : Offset(0), Length(0) {}

    NormalizedRange(const IO &, const tooling::Range &R)
        : Offset(R.getOffset()), Length(R.getLength()) {}

    tooling::Range denormalize(const IO &) {
      return tooling::Range(Offset, Length);
    }

    unsigned Offset;
    unsigned Length;
  };
  static void mapping(IO &IO, tooling::Range &Info) {
    MappingNormalization<NormalizedRange, tooling::Range> Keys(IO, Info);
    IO.mapRequired("Offset", Keys->Offset);
    IO.mapRequired("Length", Keys->Length);
  }
};

template <> struct MappingTraits<IncludeFixerContext::HeaderInfo> {
  static void mapping(IO &io, IncludeFixerContext::HeaderInfo &Info) {
    io.mapRequired("Header", Info.Header);
    io.mapRequired("QualifiedName", Info.QualifiedName);
  }
};

template <> struct MappingTraits<IncludeFixerContext::QuerySymbolInfo> {
  static void mapping(IO &io, IncludeFixerContext::QuerySymbolInfo &Info) {
    io.mapRequired("RawIdentifier", Info.RawIdentifier);
    io.mapRequired("Range", Info.Range);
  }
};

template <> struct MappingTraits<IncludeFixerContext> {
  static void mapping(IO &IO, IncludeFixerContext &Context) {
    IO.mapRequired("QuerySymbolInfo", Context.QuerySymbol);
    IO.mapRequired("HeaderInfos", Context.HeaderInfos);
  }
};
} // namespace yaml
} // namespace llvm

namespace {
cl::OptionCategory IncludeFixerCategory("Tool options");

enum DatabaseFormatTy {
  fixed, ///< Hard-coded mapping.
  yaml,  ///< Yaml database created by find-all-symbols.
};

cl::opt<DatabaseFormatTy> DatabaseFormat(
    "db", cl::desc("Specify input format"),
    cl::values(clEnumVal(fixed, "Hard-coded mapping"),
               clEnumVal(yaml, "Yaml database created by find-all-symbols"),
               clEnumValEnd),
    cl::init(yaml), cl::cat(IncludeFixerCategory));

cl::opt<std::string> Input("input",
                           cl::desc("String to initialize the database"),
                           cl::cat(IncludeFixerCategory));

cl::opt<bool>
    MinimizeIncludePaths("minimize-paths",
                         cl::desc("Whether to minimize added include paths"),
                         cl::init(true), cl::cat(IncludeFixerCategory));

cl::opt<bool> Quiet("q", cl::desc("Reduce terminal output"), cl::init(false),
                    cl::cat(IncludeFixerCategory));

cl::opt<bool>
    STDINMode("stdin",
              cl::desc("Override source file's content (in the overlaying\n"
                       "virtual file system) with input from <stdin> and run\n"
                       "the tool on the new content with the compilation\n"
                       "options of the source file. This mode is currently\n"
                       "used for editor integration."),
              cl::init(false), cl::cat(IncludeFixerCategory));

cl::opt<bool> OutputHeaders(
    "output-headers",
    cl::desc("Print the symbol being queried and all its relevant headers in\n"
             "JSON format to stdout:\n"
             "  {\n"
             "    \"QuerySymbolInfo\": {\n"
             "       \"RawIdentifier\": \"foo\",\n"
             "       \"Range\": {\"Offset\": 0, \"Length\": 3}\n"
             "    },\n"
             "    \"HeaderInfos\": [ {\"Header\": \"\\\"foo_a.h\\\"\",\n"
             "                      \"QualifiedName\": \"a::foo\"} ]\n"
             "  }"),
    cl::init(false), cl::cat(IncludeFixerCategory));

cl::opt<std::string> InsertHeader(
    "insert-header",
    cl::desc("Insert a specific header. This should run with STDIN mode.\n"
             "The result is written to stdout. It is currently used for\n"
             "editor integration. Support YAML/JSON format:\n"
             "  -insert-header=\"{\n"
             "     QuerySymbolInfo: {\n"
             "       RawIdentifier: foo,\n"
             "       Range: {Offset: 0, Length: 3}\n"
             "     },\n"
             "     HeaderInfos: [ {Headers: \"\\\"foo_a.h\\\"\",\n"
             "                     QualifiedName: \"a::foo\"} ]}\""),
    cl::init(""), cl::cat(IncludeFixerCategory));

cl::opt<std::string>
    Style("style",
          cl::desc("Fallback style for reformatting after inserting new "
                   "headers if there is no clang-format config file found."),
          cl::init("llvm"), cl::cat(IncludeFixerCategory));

std::unique_ptr<include_fixer::SymbolIndexManager>
createSymbolIndexManager(StringRef FilePath) {
  auto SymbolIndexMgr = llvm::make_unique<include_fixer::SymbolIndexManager>();
  switch (DatabaseFormat) {
  case fixed: {
    // Parse input and fill the database with it.
    // <symbol>=<header><, header...>
    // Multiple symbols can be given, separated by semicolons.
    std::map<std::string, std::vector<std::string>> SymbolsMap;
    SmallVector<StringRef, 4> SemicolonSplits;
    StringRef(Input).split(SemicolonSplits, ";");
    std::vector<find_all_symbols::SymbolInfo> Symbols;
    for (StringRef Pair : SemicolonSplits) {
      auto Split = Pair.split('=');
      std::vector<std::string> Headers;
      SmallVector<StringRef, 4> CommaSplits;
      Split.second.split(CommaSplits, ",");
      for (size_t I = 0, E = CommaSplits.size(); I != E; ++I)
        Symbols.push_back(find_all_symbols::SymbolInfo(
            Split.first.trim(),
            find_all_symbols::SymbolInfo::SymbolKind::Unknown,
            CommaSplits[I].trim(), 1, {}, /*NumOccurrences=*/E - I));
    }
    SymbolIndexMgr->addSymbolIndex(
        llvm::make_unique<include_fixer::InMemorySymbolIndex>(Symbols));
    break;
  }
  case yaml: {
    llvm::ErrorOr<std::unique_ptr<include_fixer::YamlSymbolIndex>> DB(nullptr);
    if (!Input.empty()) {
      DB = include_fixer::YamlSymbolIndex::createFromFile(Input);
    } else {
      // If we don't have any input file, look in the directory of the first
      // file and its parents.
      SmallString<128> AbsolutePath(tooling::getAbsolutePath(FilePath));
      StringRef Directory = llvm::sys::path::parent_path(AbsolutePath);
      DB = include_fixer::YamlSymbolIndex::createFromDirectory(
          Directory, "find_all_symbols_db.yaml");
    }

    if (!DB) {
      llvm::errs() << "Couldn't find YAML db: " << DB.getError().message()
                   << '\n';
      return nullptr;
    }

    SymbolIndexMgr->addSymbolIndex(std::move(*DB));
    break;
  }
  }
  return SymbolIndexMgr;
}

void writeToJson(llvm::raw_ostream &OS, const IncludeFixerContext& Context) {
  OS << "{\n"
        "  \"QuerySymbolInfo\": {\n"
        "     \"RawIdentifier\": \""
     << Context.getSymbolIdentifier() << "\",\n";
  OS << "     \"Range\": {";
  OS << " \"Offset\":" << Context.getSymbolRange().getOffset() << ",";
  OS << " \"Length\":" << Context.getSymbolRange().getLength() << " }\n";
  OS << "  },\n";
  OS << "  \"HeaderInfos\": [\n";
  const auto &HeaderInfos = Context.getHeaderInfos();
  for (const auto &Info : HeaderInfos) {
    OS << "     {\"Header\": \"" << llvm::yaml::escape(Info.Header) << "\",\n"
       << "      \"QualifiedName\": \"" << Info.QualifiedName << "\"}";
    if (&Info != &HeaderInfos.back())
      OS << ",\n";
  }
  OS << "\n";
  OS << "  ]\n";
  OS << "}\n";
}

int includeFixerMain(int argc, const char **argv) {
  tooling::CommonOptionsParser options(argc, argv, IncludeFixerCategory);
  tooling::ClangTool tool(options.getCompilations(),
                          options.getSourcePathList());

  // In STDINMode, we override the file content with the <stdin> input.
  // Since `tool.mapVirtualFile` takes `StringRef`, we define `Code` outside of
  // the if-block so that `Code` is not released after the if-block.
  std::unique_ptr<llvm::MemoryBuffer> Code;
  if (STDINMode) {
    assert(options.getSourcePathList().size() == 1 &&
           "Expect exactly one file path in STDINMode.");
    llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> CodeOrErr =
        MemoryBuffer::getSTDIN();
    if (std::error_code EC = CodeOrErr.getError()) {
      errs() << EC.message() << "\n";
      return 1;
    }
    Code = std::move(CodeOrErr.get());
    if (Code->getBufferSize() == 0)
      return 0;  // Skip empty files.

    tool.mapVirtualFile(options.getSourcePathList().front(), Code->getBuffer());
  }

  StringRef FilePath = options.getSourcePathList().front();
  format::FormatStyle InsertStyle = format::getStyle("file", FilePath, Style);

  if (!InsertHeader.empty()) {
    if (!STDINMode) {
      errs() << "Should be running in STDIN mode\n";
      return 1;
    }

    llvm::yaml::Input yin(InsertHeader);
    IncludeFixerContext Context;
    yin >> Context;

    const auto &HeaderInfos = Context.getHeaderInfos();
    assert(!HeaderInfos.empty());
    // We only accept one unique header.
    // Check all elements in HeaderInfos have the same header.
    bool IsUniqueHeader = std::equal(
        HeaderInfos.begin()+1, HeaderInfos.end(), HeaderInfos.begin(),
        [](const IncludeFixerContext::HeaderInfo &LHS,
           const IncludeFixerContext::HeaderInfo &RHS) {
          return LHS.Header == RHS.Header;
        });
    if (!IsUniqueHeader) {
      errs() << "Expect exactly one unique header.\n";
      return 1;
    }

    auto Replacements = clang::include_fixer::createInsertHeaderReplacements(
        Code->getBuffer(), FilePath, Context.getHeaderInfos().front().Header,
        InsertStyle);
    if (!Replacements) {
      errs() << "Failed to create header insertion replacement: "
             << llvm::toString(Replacements.takeError()) << "\n";
      return 1;
    }

    // If a header have multiple symbols, we won't add the missing namespace
    // qualifiers because we don't know which one is exactly used.
    //
    // Check whether all elements in HeaderInfos have the same qualified name.
    bool IsUniqueQualifiedName = std::equal(
        HeaderInfos.begin() + 1, HeaderInfos.end(), HeaderInfos.begin(),
        [](const IncludeFixerContext::HeaderInfo &LHS,
           const IncludeFixerContext::HeaderInfo &RHS) {
          return LHS.QualifiedName == RHS.QualifiedName;
        });
    if (IsUniqueQualifiedName)
      Replacements->insert({FilePath, Context.getSymbolRange().getOffset(),
                            Context.getSymbolRange().getLength(),
                            Context.getHeaderInfos().front().QualifiedName});
    auto ChangedCode =
        tooling::applyAllReplacements(Code->getBuffer(), *Replacements);
    if (!ChangedCode) {
      llvm::errs() << llvm::toString(ChangedCode.takeError()) << "\n";
      return 1;
    }
    llvm::outs() << *ChangedCode;
    return 0;
  }

  // Set up data source.
  std::unique_ptr<include_fixer::SymbolIndexManager> SymbolIndexMgr =
      createSymbolIndexManager(options.getSourcePathList().front());
  if (!SymbolIndexMgr)
    return 1;

  // Now run our tool.
  include_fixer::IncludeFixerContext Context;
  include_fixer::IncludeFixerActionFactory Factory(*SymbolIndexMgr, Context,
                                                   Style, MinimizeIncludePaths);

  if (tool.run(&Factory) != 0) {
    llvm::errs()
        << "Clang died with a fatal error! (incorrect include paths?)\n";
    return 1;
  }

  if (OutputHeaders) {
    writeToJson(llvm::outs(), Context);
    return 0;
  }

  if (Context.getHeaderInfos().empty())
    return 0;

  auto Buffer = llvm::MemoryBuffer::getFile(FilePath);
  if (!Buffer) {
    errs() << "Couldn't open file: " << FilePath;
    return 1;
  }

  auto Replacements = clang::include_fixer::createInsertHeaderReplacements(
      /*Code=*/Buffer.get()->getBuffer(), FilePath,
      Context.getHeaderInfos().front().Header, InsertStyle);
  if (!Replacements) {
    errs() << "Failed to create header insertion replacement: "
           << llvm::toString(Replacements.takeError()) << "\n";
    return 1;
  }

  if (!Quiet)
    llvm::errs() << "Added #include" << Context.getHeaderInfos().front().Header;

  // Add missing namespace qualifiers to the unidentified symbol.
  Replacements->insert({FilePath, Context.getSymbolRange().getOffset(),
                        Context.getSymbolRange().getLength(),
                        Context.getHeaderInfos().front().QualifiedName});

  // Set up a new source manager for applying the resulting replacements.
  IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts(new DiagnosticOptions);
  DiagnosticsEngine Diagnostics(new DiagnosticIDs, &*DiagOpts);
  TextDiagnosticPrinter DiagnosticPrinter(outs(), &*DiagOpts);
  SourceManager SM(Diagnostics, tool.getFiles());
  Diagnostics.setClient(&DiagnosticPrinter, false);

  if (STDINMode) {
    auto ChangedCode =
        tooling::applyAllReplacements(Code->getBuffer(), *Replacements);
    if (!ChangedCode) {
      llvm::errs() << llvm::toString(ChangedCode.takeError()) << "\n";
      return 1;
    }
    llvm::outs() << *ChangedCode;
    return 0;
  }

  // Write replacements to disk.
  Rewriter Rewrites(SM, LangOptions());
  tooling::applyAllReplacements(*Replacements, Rewrites);
  return Rewrites.overwriteChangedFiles();
}

} // namespace

int main(int argc, const char **argv) {
  return includeFixerMain(argc, argv);
}
<commit_msg>[include-fixer] Make error messages a bit prettier and make sure to include a newline at the end.<commit_after>//===-- ClangIncludeFixer.cpp - Standalone include fixer ------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "InMemorySymbolIndex.h"
#include "IncludeFixer.h"
#include "IncludeFixerContext.h"
#include "SymbolIndexManager.h"
#include "YamlSymbolIndex.h"
#include "clang/Format/Format.h"
#include "clang/Frontend/TextDiagnosticPrinter.h"
#include "clang/Rewrite/Core/Rewriter.h"
#include "clang/Tooling/CommonOptionsParser.h"
#include "clang/Tooling/Core/Replacement.h"
#include "clang/Tooling/Tooling.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/YAMLTraits.h"

using namespace clang;
using namespace llvm;
using clang::include_fixer::IncludeFixerContext;

LLVM_YAML_IS_DOCUMENT_LIST_VECTOR(IncludeFixerContext)
LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(std::string)
LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(IncludeFixerContext::HeaderInfo)

namespace llvm {
namespace yaml {

template <> struct MappingTraits<tooling::Range> {
  struct NormalizedRange {
    NormalizedRange(const IO &) : Offset(0), Length(0) {}

    NormalizedRange(const IO &, const tooling::Range &R)
        : Offset(R.getOffset()), Length(R.getLength()) {}

    tooling::Range denormalize(const IO &) {
      return tooling::Range(Offset, Length);
    }

    unsigned Offset;
    unsigned Length;
  };
  static void mapping(IO &IO, tooling::Range &Info) {
    MappingNormalization<NormalizedRange, tooling::Range> Keys(IO, Info);
    IO.mapRequired("Offset", Keys->Offset);
    IO.mapRequired("Length", Keys->Length);
  }
};

template <> struct MappingTraits<IncludeFixerContext::HeaderInfo> {
  static void mapping(IO &io, IncludeFixerContext::HeaderInfo &Info) {
    io.mapRequired("Header", Info.Header);
    io.mapRequired("QualifiedName", Info.QualifiedName);
  }
};

template <> struct MappingTraits<IncludeFixerContext::QuerySymbolInfo> {
  static void mapping(IO &io, IncludeFixerContext::QuerySymbolInfo &Info) {
    io.mapRequired("RawIdentifier", Info.RawIdentifier);
    io.mapRequired("Range", Info.Range);
  }
};

template <> struct MappingTraits<IncludeFixerContext> {
  static void mapping(IO &IO, IncludeFixerContext &Context) {
    IO.mapRequired("QuerySymbolInfo", Context.QuerySymbol);
    IO.mapRequired("HeaderInfos", Context.HeaderInfos);
  }
};
} // namespace yaml
} // namespace llvm

namespace {
cl::OptionCategory IncludeFixerCategory("Tool options");

enum DatabaseFormatTy {
  fixed, ///< Hard-coded mapping.
  yaml,  ///< Yaml database created by find-all-symbols.
};

cl::opt<DatabaseFormatTy> DatabaseFormat(
    "db", cl::desc("Specify input format"),
    cl::values(clEnumVal(fixed, "Hard-coded mapping"),
               clEnumVal(yaml, "Yaml database created by find-all-symbols"),
               clEnumValEnd),
    cl::init(yaml), cl::cat(IncludeFixerCategory));

cl::opt<std::string> Input("input",
                           cl::desc("String to initialize the database"),
                           cl::cat(IncludeFixerCategory));

cl::opt<bool>
    MinimizeIncludePaths("minimize-paths",
                         cl::desc("Whether to minimize added include paths"),
                         cl::init(true), cl::cat(IncludeFixerCategory));

cl::opt<bool> Quiet("q", cl::desc("Reduce terminal output"), cl::init(false),
                    cl::cat(IncludeFixerCategory));

cl::opt<bool>
    STDINMode("stdin",
              cl::desc("Override source file's content (in the overlaying\n"
                       "virtual file system) with input from <stdin> and run\n"
                       "the tool on the new content with the compilation\n"
                       "options of the source file. This mode is currently\n"
                       "used for editor integration."),
              cl::init(false), cl::cat(IncludeFixerCategory));

cl::opt<bool> OutputHeaders(
    "output-headers",
    cl::desc("Print the symbol being queried and all its relevant headers in\n"
             "JSON format to stdout:\n"
             "  {\n"
             "    \"QuerySymbolInfo\": {\n"
             "       \"RawIdentifier\": \"foo\",\n"
             "       \"Range\": {\"Offset\": 0, \"Length\": 3}\n"
             "    },\n"
             "    \"HeaderInfos\": [ {\"Header\": \"\\\"foo_a.h\\\"\",\n"
             "                      \"QualifiedName\": \"a::foo\"} ]\n"
             "  }"),
    cl::init(false), cl::cat(IncludeFixerCategory));

cl::opt<std::string> InsertHeader(
    "insert-header",
    cl::desc("Insert a specific header. This should run with STDIN mode.\n"
             "The result is written to stdout. It is currently used for\n"
             "editor integration. Support YAML/JSON format:\n"
             "  -insert-header=\"{\n"
             "     QuerySymbolInfo: {\n"
             "       RawIdentifier: foo,\n"
             "       Range: {Offset: 0, Length: 3}\n"
             "     },\n"
             "     HeaderInfos: [ {Headers: \"\\\"foo_a.h\\\"\",\n"
             "                     QualifiedName: \"a::foo\"} ]}\""),
    cl::init(""), cl::cat(IncludeFixerCategory));

cl::opt<std::string>
    Style("style",
          cl::desc("Fallback style for reformatting after inserting new "
                   "headers if there is no clang-format config file found."),
          cl::init("llvm"), cl::cat(IncludeFixerCategory));

std::unique_ptr<include_fixer::SymbolIndexManager>
createSymbolIndexManager(StringRef FilePath) {
  auto SymbolIndexMgr = llvm::make_unique<include_fixer::SymbolIndexManager>();
  switch (DatabaseFormat) {
  case fixed: {
    // Parse input and fill the database with it.
    // <symbol>=<header><, header...>
    // Multiple symbols can be given, separated by semicolons.
    std::map<std::string, std::vector<std::string>> SymbolsMap;
    SmallVector<StringRef, 4> SemicolonSplits;
    StringRef(Input).split(SemicolonSplits, ";");
    std::vector<find_all_symbols::SymbolInfo> Symbols;
    for (StringRef Pair : SemicolonSplits) {
      auto Split = Pair.split('=');
      std::vector<std::string> Headers;
      SmallVector<StringRef, 4> CommaSplits;
      Split.second.split(CommaSplits, ",");
      for (size_t I = 0, E = CommaSplits.size(); I != E; ++I)
        Symbols.push_back(find_all_symbols::SymbolInfo(
            Split.first.trim(),
            find_all_symbols::SymbolInfo::SymbolKind::Unknown,
            CommaSplits[I].trim(), 1, {}, /*NumOccurrences=*/E - I));
    }
    SymbolIndexMgr->addSymbolIndex(
        llvm::make_unique<include_fixer::InMemorySymbolIndex>(Symbols));
    break;
  }
  case yaml: {
    llvm::ErrorOr<std::unique_ptr<include_fixer::YamlSymbolIndex>> DB(nullptr);
    if (!Input.empty()) {
      DB = include_fixer::YamlSymbolIndex::createFromFile(Input);
    } else {
      // If we don't have any input file, look in the directory of the first
      // file and its parents.
      SmallString<128> AbsolutePath(tooling::getAbsolutePath(FilePath));
      StringRef Directory = llvm::sys::path::parent_path(AbsolutePath);
      DB = include_fixer::YamlSymbolIndex::createFromDirectory(
          Directory, "find_all_symbols_db.yaml");
    }

    if (!DB) {
      llvm::errs() << "Couldn't find YAML db: " << DB.getError().message()
                   << '\n';
      return nullptr;
    }

    SymbolIndexMgr->addSymbolIndex(std::move(*DB));
    break;
  }
  }
  return SymbolIndexMgr;
}

void writeToJson(llvm::raw_ostream &OS, const IncludeFixerContext& Context) {
  OS << "{\n"
        "  \"QuerySymbolInfo\": {\n"
        "     \"RawIdentifier\": \""
     << Context.getSymbolIdentifier() << "\",\n";
  OS << "     \"Range\": {";
  OS << " \"Offset\":" << Context.getSymbolRange().getOffset() << ",";
  OS << " \"Length\":" << Context.getSymbolRange().getLength() << " }\n";
  OS << "  },\n";
  OS << "  \"HeaderInfos\": [\n";
  const auto &HeaderInfos = Context.getHeaderInfos();
  for (const auto &Info : HeaderInfos) {
    OS << "     {\"Header\": \"" << llvm::yaml::escape(Info.Header) << "\",\n"
       << "      \"QualifiedName\": \"" << Info.QualifiedName << "\"}";
    if (&Info != &HeaderInfos.back())
      OS << ",\n";
  }
  OS << "\n";
  OS << "  ]\n";
  OS << "}\n";
}

int includeFixerMain(int argc, const char **argv) {
  tooling::CommonOptionsParser options(argc, argv, IncludeFixerCategory);
  tooling::ClangTool tool(options.getCompilations(),
                          options.getSourcePathList());

  // In STDINMode, we override the file content with the <stdin> input.
  // Since `tool.mapVirtualFile` takes `StringRef`, we define `Code` outside of
  // the if-block so that `Code` is not released after the if-block.
  std::unique_ptr<llvm::MemoryBuffer> Code;
  if (STDINMode) {
    assert(options.getSourcePathList().size() == 1 &&
           "Expect exactly one file path in STDINMode.");
    llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> CodeOrErr =
        MemoryBuffer::getSTDIN();
    if (std::error_code EC = CodeOrErr.getError()) {
      errs() << EC.message() << "\n";
      return 1;
    }
    Code = std::move(CodeOrErr.get());
    if (Code->getBufferSize() == 0)
      return 0;  // Skip empty files.

    tool.mapVirtualFile(options.getSourcePathList().front(), Code->getBuffer());
  }

  StringRef FilePath = options.getSourcePathList().front();
  format::FormatStyle InsertStyle = format::getStyle("file", FilePath, Style);

  if (!InsertHeader.empty()) {
    if (!STDINMode) {
      errs() << "Should be running in STDIN mode\n";
      return 1;
    }

    llvm::yaml::Input yin(InsertHeader);
    IncludeFixerContext Context;
    yin >> Context;

    const auto &HeaderInfos = Context.getHeaderInfos();
    assert(!HeaderInfos.empty());
    // We only accept one unique header.
    // Check all elements in HeaderInfos have the same header.
    bool IsUniqueHeader = std::equal(
        HeaderInfos.begin()+1, HeaderInfos.end(), HeaderInfos.begin(),
        [](const IncludeFixerContext::HeaderInfo &LHS,
           const IncludeFixerContext::HeaderInfo &RHS) {
          return LHS.Header == RHS.Header;
        });
    if (!IsUniqueHeader) {
      errs() << "Expect exactly one unique header.\n";
      return 1;
    }

    auto Replacements = clang::include_fixer::createInsertHeaderReplacements(
        Code->getBuffer(), FilePath, Context.getHeaderInfos().front().Header,
        InsertStyle);
    if (!Replacements) {
      errs() << "Failed to create header insertion replacement: "
             << llvm::toString(Replacements.takeError()) << "\n";
      return 1;
    }

    // If a header have multiple symbols, we won't add the missing namespace
    // qualifiers because we don't know which one is exactly used.
    //
    // Check whether all elements in HeaderInfos have the same qualified name.
    bool IsUniqueQualifiedName = std::equal(
        HeaderInfos.begin() + 1, HeaderInfos.end(), HeaderInfos.begin(),
        [](const IncludeFixerContext::HeaderInfo &LHS,
           const IncludeFixerContext::HeaderInfo &RHS) {
          return LHS.QualifiedName == RHS.QualifiedName;
        });
    if (IsUniqueQualifiedName)
      Replacements->insert({FilePath, Context.getSymbolRange().getOffset(),
                            Context.getSymbolRange().getLength(),
                            Context.getHeaderInfos().front().QualifiedName});
    auto ChangedCode =
        tooling::applyAllReplacements(Code->getBuffer(), *Replacements);
    if (!ChangedCode) {
      llvm::errs() << llvm::toString(ChangedCode.takeError()) << "\n";
      return 1;
    }
    llvm::outs() << *ChangedCode;
    return 0;
  }

  // Set up data source.
  std::unique_ptr<include_fixer::SymbolIndexManager> SymbolIndexMgr =
      createSymbolIndexManager(options.getSourcePathList().front());
  if (!SymbolIndexMgr)
    return 1;

  // Now run our tool.
  include_fixer::IncludeFixerContext Context;
  include_fixer::IncludeFixerActionFactory Factory(*SymbolIndexMgr, Context,
                                                   Style, MinimizeIncludePaths);

  if (tool.run(&Factory) != 0) {
    llvm::errs()
        << "Clang died with a fatal error! (incorrect include paths?)\n";
    return 1;
  }

  if (OutputHeaders) {
    writeToJson(llvm::outs(), Context);
    return 0;
  }

  if (Context.getHeaderInfos().empty())
    return 0;

  auto Buffer = llvm::MemoryBuffer::getFile(FilePath);
  if (!Buffer) {
    errs() << "Couldn't open file: " << FilePath << ": "
           << Buffer.getError().message() << '\n';
    return 1;
  }

  auto Replacements = clang::include_fixer::createInsertHeaderReplacements(
      /*Code=*/Buffer.get()->getBuffer(), FilePath,
      Context.getHeaderInfos().front().Header, InsertStyle);
  if (!Replacements) {
    errs() << "Failed to create header insertion replacement: "
           << llvm::toString(Replacements.takeError()) << "\n";
    return 1;
  }

  if (!Quiet)
    errs() << "Added #include " << Context.getHeaderInfos().front().Header
           << '\n';

  // Add missing namespace qualifiers to the unidentified symbol.
  Replacements->insert({FilePath, Context.getSymbolRange().getOffset(),
                        Context.getSymbolRange().getLength(),
                        Context.getHeaderInfos().front().QualifiedName});

  // Set up a new source manager for applying the resulting replacements.
  IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts(new DiagnosticOptions);
  DiagnosticsEngine Diagnostics(new DiagnosticIDs, &*DiagOpts);
  TextDiagnosticPrinter DiagnosticPrinter(outs(), &*DiagOpts);
  SourceManager SM(Diagnostics, tool.getFiles());
  Diagnostics.setClient(&DiagnosticPrinter, false);

  if (STDINMode) {
    auto ChangedCode =
        tooling::applyAllReplacements(Code->getBuffer(), *Replacements);
    if (!ChangedCode) {
      llvm::errs() << llvm::toString(ChangedCode.takeError()) << "\n";
      return 1;
    }
    llvm::outs() << *ChangedCode;
    return 0;
  }

  // Write replacements to disk.
  Rewriter Rewrites(SM, LangOptions());
  tooling::applyAllReplacements(*Replacements, Rewrites);
  return Rewrites.overwriteChangedFiles();
}

} // namespace

int main(int argc, const char **argv) {
  return includeFixerMain(argc, argv);
}
<|endoftext|>


<commit_before>//========= Copyright  2014, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//

#include <stdio.h>
#include <string.h>
#include <assert.h>
#include "demofile.h"

uint32 ReadVarInt32( const char* buf, size_t bufLength, size_t& index )
{
	uint32 b;
	int count = 0;
	uint32 result = 0;

	do
	{
		if ( count == 5 )
		{
			// If we get here it means that the fifth bit had its
			// high bit set, which implies corrupt data.
			assert( 0 );
			return result;
		}
		else if ( index >= bufLength )
		{
			assert( 0 );
			return result;
		}

		b = buf[ index++ ];
		result |= ( b & 0x7F ) << ( 7 * count );
		++count;
	} while ( b & 0x80 );

	return result;
}

CDemoFile::CDemoFile()
{
}

CDemoFile::~CDemoFile()
{
	Close();
}

void CDemoFile::ReadSequenceInfo(int32 &nSeqNrIn, int32 &nSeqNrOut)
{
	if ( !m_fileBuffer.size() )
		return;

	nSeqNrIn = *( int32 * )( &m_fileBuffer[ m_fileBufferPos ] );
	m_fileBufferPos += sizeof( int32 );
	nSeqNrOut = *( int32 * )( &m_fileBuffer[ m_fileBufferPos ] );
	m_fileBufferPos += sizeof( int32 );
}

void CDemoFile::ReadCmdInfo( democmdinfo_t& info )
{
	if ( !m_fileBuffer.size() )
		return;

	memcpy( &info, &m_fileBuffer[ m_fileBufferPos ], sizeof( democmdinfo_t ) );
	m_fileBufferPos += sizeof( democmdinfo_t );
}

void CDemoFile::ReadCmdHeader( unsigned char& cmd, int32& tick, unsigned char& playerSlot )
{
	if ( !m_fileBuffer.size() )
		return;

	// Read the command
	cmd = *( unsigned char * )( &m_fileBuffer[ m_fileBufferPos ] );
	m_fileBufferPos += sizeof( unsigned char );

	if ( cmd <=0 )
	{
		fprintf( stderr, "CDemoFile::ReadCmdHeader: Missing end tag in demo file.\n");
		cmd = dem_stop;
		return;
	}

	assert( cmd >= 1 && cmd <= dem_lastcmd );

	// Read the timestamp
	tick = *( int32 * )( &m_fileBuffer[ m_fileBufferPos ] );
	m_fileBufferPos += sizeof( int32 );

	// read playerslot
	playerSlot = *( unsigned char * )( &m_fileBuffer[ m_fileBufferPos ] );
	m_fileBufferPos += sizeof( unsigned char );
}

int32 CDemoFile::ReadUserCmd( char *buffer, int32 &size )
{
	if ( !m_fileBuffer.size() )
		return 0;

	int32 outgoing_sequence = *( int32 * )( &m_fileBuffer[ m_fileBufferPos ] );
	m_fileBufferPos += sizeof( int32 );

	size = ReadRawData( buffer, size );

	return outgoing_sequence;
}

int32 CDemoFile::ReadRawData( char *buffer, int32 length )
{
	if ( !m_fileBuffer.size() )
		return 0;

	// read length of data block
	int32 size = *( int32 * )( &m_fileBuffer[ m_fileBufferPos ] );
	m_fileBufferPos += sizeof( int32 );

	if ( buffer && (length < size) )
	{
		fprintf( stderr, "CDemoFile::ReadRawData: buffer overflow (%i).\n", size );
		return -1;
	}

	if ( buffer )
	{
		// read data into buffer
		memcpy( buffer, &m_fileBuffer[ m_fileBufferPos ], size );
		m_fileBufferPos += size;
	}
	else
	{
		// just skip it
		m_fileBufferPos += size;
	}

	return size;
}

bool CDemoFile::Open( const char *name )
{
	Close();

	FILE *fp = NULL;
	fp = fopen(name, "rb" );
	if( fp )
	{
		size_t Length;

		fseek( fp, 0, SEEK_END );
		Length = ftell( fp );
		fseek( fp, 0, SEEK_SET );

		if( Length < sizeof( m_DemoHeader ) )
		{
			fprintf( stderr, "CDemoFile::Open: file too small. %s.\n", name );
			fclose( fp );
			return false;
		}

		fread( &m_DemoHeader, 1, sizeof( m_DemoHeader ), fp );
		Length -= sizeof( m_DemoHeader );

		if ( strcmp ( m_DemoHeader.demofilestamp, DEMO_HEADER_ID ) )
		{
			fprintf( stderr, "CDemoFile::Open: %s has invalid demo header ID.\n", m_szFileName );
			fclose( fp );
			return false;
		}

		if ( m_DemoHeader.demoprotocol != DEMO_PROTOCOL )
		{
			fprintf( stderr, "CDemoFile::Open: demo file protocol %i invalid, expected version is %i \n", m_DemoHeader.demoprotocol, DEMO_PROTOCOL );
			fclose( fp );
			return false;
		}

		m_fileBuffer.resize( Length );
		fread( &m_fileBuffer[ 0 ], 1, Length, fp );

		fclose( fp );
		fp = NULL;
	}

	if ( !m_fileBuffer.size() )
	{
		fprintf( stderr, "CDemoFile::Open: couldn't open file %s.\n", name );
		Close();
		return false;
	}

	m_fileBufferPos = 0;
	m_szFileName = name;
	return true;
}

void CDemoFile::Close()
{
	m_szFileName.clear();

	m_fileBufferPos = 0;
	m_fileBuffer.clear();
}
<commit_msg>Fix parameter to use C string<commit_after>//========= Copyright  2014, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//

#include <stdio.h>
#include <string.h>
#include <assert.h>
#include "demofile.h"

uint32 ReadVarInt32( const char* buf, size_t bufLength, size_t& index )
{
	uint32 b;
	int count = 0;
	uint32 result = 0;

	do
	{
		if ( count == 5 )
		{
			// If we get here it means that the fifth bit had its
			// high bit set, which implies corrupt data.
			assert( 0 );
			return result;
		}
		else if ( index >= bufLength )
		{
			assert( 0 );
			return result;
		}

		b = buf[ index++ ];
		result |= ( b & 0x7F ) << ( 7 * count );
		++count;
	} while ( b & 0x80 );

	return result;
}

CDemoFile::CDemoFile()
{
}

CDemoFile::~CDemoFile()
{
	Close();
}

void CDemoFile::ReadSequenceInfo(int32 &nSeqNrIn, int32 &nSeqNrOut)
{
	if ( !m_fileBuffer.size() )
		return;

	nSeqNrIn = *( int32 * )( &m_fileBuffer[ m_fileBufferPos ] );
	m_fileBufferPos += sizeof( int32 );
	nSeqNrOut = *( int32 * )( &m_fileBuffer[ m_fileBufferPos ] );
	m_fileBufferPos += sizeof( int32 );
}

void CDemoFile::ReadCmdInfo( democmdinfo_t& info )
{
	if ( !m_fileBuffer.size() )
		return;

	memcpy( &info, &m_fileBuffer[ m_fileBufferPos ], sizeof( democmdinfo_t ) );
	m_fileBufferPos += sizeof( democmdinfo_t );
}

void CDemoFile::ReadCmdHeader( unsigned char& cmd, int32& tick, unsigned char& playerSlot )
{
	if ( !m_fileBuffer.size() )
		return;

	// Read the command
	cmd = *( unsigned char * )( &m_fileBuffer[ m_fileBufferPos ] );
	m_fileBufferPos += sizeof( unsigned char );

	if ( cmd <=0 )
	{
		fprintf( stderr, "CDemoFile::ReadCmdHeader: Missing end tag in demo file.\n");
		cmd = dem_stop;
		return;
	}

	assert( cmd >= 1 && cmd <= dem_lastcmd );

	// Read the timestamp
	tick = *( int32 * )( &m_fileBuffer[ m_fileBufferPos ] );
	m_fileBufferPos += sizeof( int32 );

	// read playerslot
	playerSlot = *( unsigned char * )( &m_fileBuffer[ m_fileBufferPos ] );
	m_fileBufferPos += sizeof( unsigned char );
}

int32 CDemoFile::ReadUserCmd( char *buffer, int32 &size )
{
	if ( !m_fileBuffer.size() )
		return 0;

	int32 outgoing_sequence = *( int32 * )( &m_fileBuffer[ m_fileBufferPos ] );
	m_fileBufferPos += sizeof( int32 );

	size = ReadRawData( buffer, size );

	return outgoing_sequence;
}

int32 CDemoFile::ReadRawData( char *buffer, int32 length )
{
	if ( !m_fileBuffer.size() )
		return 0;

	// read length of data block
	int32 size = *( int32 * )( &m_fileBuffer[ m_fileBufferPos ] );
	m_fileBufferPos += sizeof( int32 );

	if ( buffer && (length < size) )
	{
		fprintf( stderr, "CDemoFile::ReadRawData: buffer overflow (%i).\n", size );
		return -1;
	}

	if ( buffer )
	{
		// read data into buffer
		memcpy( buffer, &m_fileBuffer[ m_fileBufferPos ], size );
		m_fileBufferPos += size;
	}
	else
	{
		// just skip it
		m_fileBufferPos += size;
	}

	return size;
}

bool CDemoFile::Open( const char *name )
{
	Close();

	FILE *fp = NULL;
	fp = fopen(name, "rb" );
	if( fp )
	{
		size_t Length;

		fseek( fp, 0, SEEK_END );
		Length = ftell( fp );
		fseek( fp, 0, SEEK_SET );

		if( Length < sizeof( m_DemoHeader ) )
		{
			fprintf( stderr, "CDemoFile::Open: file too small. %s.\n", name );
			fclose( fp );
			return false;
		}

		fread( &m_DemoHeader, 1, sizeof( m_DemoHeader ), fp );
		Length -= sizeof( m_DemoHeader );

		if ( strcmp ( m_DemoHeader.demofilestamp, DEMO_HEADER_ID ) )
		{
			fprintf( stderr, "CDemoFile::Open: %s has invalid demo header ID.\n", m_szFileName.c_str() );
			fclose( fp );
			return false;
		}

		if ( m_DemoHeader.demoprotocol != DEMO_PROTOCOL )
		{
			fprintf( stderr, "CDemoFile::Open: demo file protocol %i invalid, expected version is %i \n", m_DemoHeader.demoprotocol, DEMO_PROTOCOL );
			fclose( fp );
			return false;
		}

		m_fileBuffer.resize( Length );
		fread( &m_fileBuffer[ 0 ], 1, Length, fp );

		fclose( fp );
		fp = NULL;
	}

	if ( !m_fileBuffer.size() )
	{
		fprintf( stderr, "CDemoFile::Open: couldn't open file %s.\n", name );
		Close();
		return false;
	}

	m_fileBufferPos = 0;
	m_szFileName = name;
	return true;
}

void CDemoFile::Close()
{
	m_szFileName.clear();

	m_fileBufferPos = 0;
	m_fileBuffer.clear();
}
<|endoftext|>


<commit_before><commit_msg>Fix bug in offset<commit_after><|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: filew32.hxx,v $
 *
 *  $Revision: 1.6 $
 *
 *  last change: $Author: kz $ $Date: 2007-09-06 14:15:37 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    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.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef INCLUDED_STORE_FILEW32_HXX
#define INCLUDED_STORE_FILEW32_HXX

#ifdef _MSC_VER
#pragma warning(push,1) // disable warnings within system headers
#endif
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#ifdef _MSC_VER
#pragma warning(pop)
#endif

typedef HANDLE HSTORE;

/*========================================================================
 *
 * File I/O (inline) implementation.
 *
 *======================================================================*/
/*
 * __store_errcode_map.
 */
static const __store_errcode_mapping_st __store_errcode_map[] =
{
    { ERROR_SUCCESS,           store_E_None             },
    { ERROR_FILE_NOT_FOUND,    store_E_NotExists        },
    { ERROR_ACCESS_DENIED,     store_E_AccessViolation  },
    { ERROR_LOCK_FAILED,       store_E_LockingViolation },
    { ERROR_LOCK_VIOLATION,    store_E_LockingViolation },
    { ERROR_INVALID_HANDLE,    store_E_InvalidHandle    },
    { ERROR_INVALID_PARAMETER, store_E_InvalidParameter },
    { ERROR_DISK_FULL,         store_E_OutOfSpace       },
    { ERROR_HANDLE_DISK_FULL,  store_E_OutOfSpace       },
};

/*
 * __store_errno.
 */
inline sal_uInt32 __store_errno (void)
{
    return (sal_uInt32)::GetLastError();
}

/*
 * __store_malign.
 */
inline sal_uInt32 __store_malign (void)
{
    // Check Win32 platform.
    OSVERSIONINFO osinfo;

    osinfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
    ::GetVersionEx (&osinfo);

    if (osinfo.dwPlatformId == VER_PLATFORM_WIN32_NT)
    {
        // Determine memory allocation granularity.
        SYSTEM_INFO info;

        ::GetSystemInfo (&info);
        return ((sal_uInt32)(info.dwAllocationGranularity));
    }
    return (sal_uInt32)(-1);
}

/*
 * __store_fmap (readonly).
 */
inline HSTORE __store_fmap (HSTORE hFile)
{
    return ::CreateFileMapping (
        hFile, NULL, SEC_COMMIT | PAGE_READONLY, 0, 0, NULL);
}

/*
 * __store_funmap.
 */
inline void __store_funmap (HSTORE hMap)
{
    ::CloseHandle (hMap);
}

/*
 * __store_mmap (readonly).
 */
inline sal_uInt8* __store_mmap (HSTORE h, sal_uInt32 k, sal_uInt32 n)
{
    return (sal_uInt8*)::MapViewOfFile (h, FILE_MAP_READ, 0, k, n);
}

/*
 * __store_munmap.
 */
inline void __store_munmap (sal_uInt8 *p, sal_uInt32)
{
    ::UnmapViewOfFile (p);
}

/*
 * __store_fopen.
 */
inline storeError __store_fopen (
    const sal_Char *pszName, sal_uInt32 nMode, HSTORE &rhFile)
{
    // Access mode.
    DWORD nAccessMode = GENERIC_READ;

    if (nMode & store_File_OpenWrite)
        nAccessMode |= GENERIC_WRITE;

    if (nAccessMode == GENERIC_READ)
        nMode |= store_File_OpenNoCreate;

    // Share mode.
    DWORD nShareMode = FILE_SHARE_READ;
    if (!(nMode & store_File_OpenWrite))
        nShareMode |= FILE_SHARE_WRITE;

    // Open action.
    DWORD nOpenAction = 0;
    if (!(nMode & store_File_OpenNoCreate))
    {
        // Open always.
        if (nMode & store_File_OpenTruncate)
            nOpenAction = CREATE_ALWAYS;
        else
            nOpenAction = OPEN_ALWAYS;
    }
    else
    {
        // Open existing.
        if (nMode & store_File_OpenTruncate)
            nOpenAction = TRUNCATE_EXISTING;
        else
            nOpenAction = OPEN_EXISTING;
    }

    // Create file handle.
    rhFile = ::CreateFile (
        pszName,
        nAccessMode,
        nShareMode,
        (LPSECURITY_ATTRIBUTES)NULL,
        nOpenAction,
        (FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS),
        (HANDLE)NULL);

    // Check result and finish.
    if (rhFile == INVALID_HANDLE_VALUE)
    {
        rhFile = 0;
        return ERROR_FROM_NATIVE(::GetLastError());
    }
    return store_E_None;
}

/*
 * __store_fread.
 */
inline storeError __store_fread (
    HSTORE h, sal_uInt32 offset, void *p, sal_uInt32 n, sal_uInt32 &k)
{
    if (::SetFilePointer (h, offset, NULL, FILE_BEGIN) == (DWORD)(-1))
        return ERROR_FROM_NATIVE(::GetLastError());
    if (!::ReadFile (h, p, n, &k, NULL))
        return ERROR_FROM_NATIVE(::GetLastError());
    else
        return store_E_None;
}

/*
 * __store_fwrite.
 */
inline storeError __store_fwrite (
    HSTORE h, sal_uInt32 offset, const void *p, sal_uInt32 n, sal_uInt32 &k)
{
    if (::SetFilePointer (h, offset, NULL, FILE_BEGIN) == (DWORD)(-1))
        return ERROR_FROM_NATIVE(::GetLastError());
    if (!::WriteFile (h, p, n, &k, NULL))
        return ERROR_FROM_NATIVE(::GetLastError());
    else
        return store_E_None;
}

/*
 * __store_fseek.
 */
inline storeError __store_fseek (HSTORE h, sal_uInt32 n)
{
    DWORD k = ::SetFilePointer (h, n, NULL, FILE_BEGIN);
    if (k == (DWORD)(-1))
        return ERROR_FROM_NATIVE(::GetLastError());
    else
        return store_E_None;
}

/*
 * __store_fsize.
 */
inline storeError __store_fsize (HSTORE h, sal_uInt32 &k)
{
    k = (sal_uInt32)::GetFileSize (h, NULL);
    if (k == (sal_uInt32)(-1))
        return ERROR_FROM_NATIVE(::GetLastError());
    else
        return store_E_None;
}

/*
 * __store_ftrunc.
 */
inline storeError __store_ftrunc (HSTORE h, sal_uInt32 n)
{
    if (::SetFilePointer (h, n, NULL, FILE_BEGIN) == (DWORD)(-1))
        return ERROR_FROM_NATIVE(::GetLastError());
    if (!::SetEndOfFile (h))
        return ERROR_FROM_NATIVE(::GetLastError());
    else
        return store_E_None;
}

/*
 * __store_fsync.
 */
inline storeError __store_fsync (HSTORE h)
{
    if (!::FlushFileBuffers (h))
        return ERROR_FROM_NATIVE(::GetLastError());
    else
        return store_E_None;
}

/*
 * __store_fclose.
 */
inline storeError __store_fclose (HSTORE h)
{
    if (!::CloseHandle (h))
        return ERROR_FROM_NATIVE(::GetLastError());
    else
        return store_E_None;
}

#endif /* INCLUDED_STORE_FILEW32_HXX */
<commit_msg>INTEGRATION: CWS changefileheader (1.6.12); FILE MERGED 2008/03/31 15:27:47 rt 1.6.12.1: #i87441# Change license header to LPGL v3.<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: filew32.hxx,v $
 * $Revision: 1.7 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org 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 Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

#ifndef INCLUDED_STORE_FILEW32_HXX
#define INCLUDED_STORE_FILEW32_HXX

#ifdef _MSC_VER
#pragma warning(push,1) // disable warnings within system headers
#endif
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#ifdef _MSC_VER
#pragma warning(pop)
#endif

typedef HANDLE HSTORE;

/*========================================================================
 *
 * File I/O (inline) implementation.
 *
 *======================================================================*/
/*
 * __store_errcode_map.
 */
static const __store_errcode_mapping_st __store_errcode_map[] =
{
    { ERROR_SUCCESS,           store_E_None             },
    { ERROR_FILE_NOT_FOUND,    store_E_NotExists        },
    { ERROR_ACCESS_DENIED,     store_E_AccessViolation  },
    { ERROR_LOCK_FAILED,       store_E_LockingViolation },
    { ERROR_LOCK_VIOLATION,    store_E_LockingViolation },
    { ERROR_INVALID_HANDLE,    store_E_InvalidHandle    },
    { ERROR_INVALID_PARAMETER, store_E_InvalidParameter },
    { ERROR_DISK_FULL,         store_E_OutOfSpace       },
    { ERROR_HANDLE_DISK_FULL,  store_E_OutOfSpace       },
};

/*
 * __store_errno.
 */
inline sal_uInt32 __store_errno (void)
{
    return (sal_uInt32)::GetLastError();
}

/*
 * __store_malign.
 */
inline sal_uInt32 __store_malign (void)
{
    // Check Win32 platform.
    OSVERSIONINFO osinfo;

    osinfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
    ::GetVersionEx (&osinfo);

    if (osinfo.dwPlatformId == VER_PLATFORM_WIN32_NT)
    {
        // Determine memory allocation granularity.
        SYSTEM_INFO info;

        ::GetSystemInfo (&info);
        return ((sal_uInt32)(info.dwAllocationGranularity));
    }
    return (sal_uInt32)(-1);
}

/*
 * __store_fmap (readonly).
 */
inline HSTORE __store_fmap (HSTORE hFile)
{
    return ::CreateFileMapping (
        hFile, NULL, SEC_COMMIT | PAGE_READONLY, 0, 0, NULL);
}

/*
 * __store_funmap.
 */
inline void __store_funmap (HSTORE hMap)
{
    ::CloseHandle (hMap);
}

/*
 * __store_mmap (readonly).
 */
inline sal_uInt8* __store_mmap (HSTORE h, sal_uInt32 k, sal_uInt32 n)
{
    return (sal_uInt8*)::MapViewOfFile (h, FILE_MAP_READ, 0, k, n);
}

/*
 * __store_munmap.
 */
inline void __store_munmap (sal_uInt8 *p, sal_uInt32)
{
    ::UnmapViewOfFile (p);
}

/*
 * __store_fopen.
 */
inline storeError __store_fopen (
    const sal_Char *pszName, sal_uInt32 nMode, HSTORE &rhFile)
{
    // Access mode.
    DWORD nAccessMode = GENERIC_READ;

    if (nMode & store_File_OpenWrite)
        nAccessMode |= GENERIC_WRITE;

    if (nAccessMode == GENERIC_READ)
        nMode |= store_File_OpenNoCreate;

    // Share mode.
    DWORD nShareMode = FILE_SHARE_READ;
    if (!(nMode & store_File_OpenWrite))
        nShareMode |= FILE_SHARE_WRITE;

    // Open action.
    DWORD nOpenAction = 0;
    if (!(nMode & store_File_OpenNoCreate))
    {
        // Open always.
        if (nMode & store_File_OpenTruncate)
            nOpenAction = CREATE_ALWAYS;
        else
            nOpenAction = OPEN_ALWAYS;
    }
    else
    {
        // Open existing.
        if (nMode & store_File_OpenTruncate)
            nOpenAction = TRUNCATE_EXISTING;
        else
            nOpenAction = OPEN_EXISTING;
    }

    // Create file handle.
    rhFile = ::CreateFile (
        pszName,
        nAccessMode,
        nShareMode,
        (LPSECURITY_ATTRIBUTES)NULL,
        nOpenAction,
        (FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS),
        (HANDLE)NULL);

    // Check result and finish.
    if (rhFile == INVALID_HANDLE_VALUE)
    {
        rhFile = 0;
        return ERROR_FROM_NATIVE(::GetLastError());
    }
    return store_E_None;
}

/*
 * __store_fread.
 */
inline storeError __store_fread (
    HSTORE h, sal_uInt32 offset, void *p, sal_uInt32 n, sal_uInt32 &k)
{
    if (::SetFilePointer (h, offset, NULL, FILE_BEGIN) == (DWORD)(-1))
        return ERROR_FROM_NATIVE(::GetLastError());
    if (!::ReadFile (h, p, n, &k, NULL))
        return ERROR_FROM_NATIVE(::GetLastError());
    else
        return store_E_None;
}

/*
 * __store_fwrite.
 */
inline storeError __store_fwrite (
    HSTORE h, sal_uInt32 offset, const void *p, sal_uInt32 n, sal_uInt32 &k)
{
    if (::SetFilePointer (h, offset, NULL, FILE_BEGIN) == (DWORD)(-1))
        return ERROR_FROM_NATIVE(::GetLastError());
    if (!::WriteFile (h, p, n, &k, NULL))
        return ERROR_FROM_NATIVE(::GetLastError());
    else
        return store_E_None;
}

/*
 * __store_fseek.
 */
inline storeError __store_fseek (HSTORE h, sal_uInt32 n)
{
    DWORD k = ::SetFilePointer (h, n, NULL, FILE_BEGIN);
    if (k == (DWORD)(-1))
        return ERROR_FROM_NATIVE(::GetLastError());
    else
        return store_E_None;
}

/*
 * __store_fsize.
 */
inline storeError __store_fsize (HSTORE h, sal_uInt32 &k)
{
    k = (sal_uInt32)::GetFileSize (h, NULL);
    if (k == (sal_uInt32)(-1))
        return ERROR_FROM_NATIVE(::GetLastError());
    else
        return store_E_None;
}

/*
 * __store_ftrunc.
 */
inline storeError __store_ftrunc (HSTORE h, sal_uInt32 n)
{
    if (::SetFilePointer (h, n, NULL, FILE_BEGIN) == (DWORD)(-1))
        return ERROR_FROM_NATIVE(::GetLastError());
    if (!::SetEndOfFile (h))
        return ERROR_FROM_NATIVE(::GetLastError());
    else
        return store_E_None;
}

/*
 * __store_fsync.
 */
inline storeError __store_fsync (HSTORE h)
{
    if (!::FlushFileBuffers (h))
        return ERROR_FROM_NATIVE(::GetLastError());
    else
        return store_E_None;
}

/*
 * __store_fclose.
 */
inline storeError __store_fclose (HSTORE h)
{
    if (!::CloseHandle (h))
        return ERROR_FROM_NATIVE(::GetLastError());
    else
        return store_E_None;
}

#endif /* INCLUDED_STORE_FILEW32_HXX */
<|endoftext|>


<commit_before>// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey
// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/

#ifndef TAO_PEGTL_CONTRIB_PARSE_TREE_HPP
#define TAO_PEGTL_CONTRIB_PARSE_TREE_HPP

#include <cassert>
#include <memory>
#include <string>
#include <string_view>
#include <tuple>
#include <type_traits>
#include <typeindex>
#include <utility>
#include <vector>

#include "remove_first_state.hpp"
#include "shuffle_states.hpp"

#include "../apply_mode.hpp"
#include "../config.hpp"
#include "../demangle.hpp"
#include "../memory_input.hpp"
#include "../normal.hpp"
#include "../nothing.hpp"
#include "../parse.hpp"
#include "../rewind_mode.hpp"

#include "../internal/enable_control.hpp"
#include "../internal/iterator.hpp"
#include "../internal/try_catch_type.hpp"

namespace TAO_PEGTL_NAMESPACE::parse_tree
{
   template< typename T >
   struct basic_node
   {
      using node_t = T;
      using children_t = std::vector< std::unique_ptr< node_t > >;
      children_t children;

      std::string_view type;
      std::string source;

      TAO_PEGTL_NAMESPACE::internal::iterator m_begin;
      TAO_PEGTL_NAMESPACE::internal::iterator m_end;

      // each node will be default constructed
      basic_node() = default;

      // no copy/move is necessary
      // (nodes are always owned/handled by a std::unique_ptr)
      basic_node( const basic_node& ) = delete;
      basic_node( basic_node&& ) = delete;

      ~basic_node() = default;

      // no assignment either
      basic_node& operator=( const basic_node& ) = delete;
      basic_node& operator=( basic_node&& ) = delete;

      [[nodiscard]] bool is_root() const noexcept
      {
         return type.empty();
      }

      template< typename U >
      [[nodiscard]] bool is_type() const noexcept
      {
         return type == demangle< U >();
      }

      template< typename U >
      void set_type() noexcept
      {
         type = demangle< U >();
      }

      [[nodiscard]] position begin() const
      {
         return position( m_begin, source );
      }

      [[nodiscard]] position end() const
      {
         return position( m_end, source );
      }

      [[nodiscard]] bool has_content() const noexcept
      {
         return m_end.data != nullptr;
      }

      [[nodiscard]] std::string_view string_view() const noexcept
      {
         assert( has_content() );
         return std::string_view( m_begin.data, m_end.data - m_begin.data );
      }

      [[nodiscard]] std::string string() const
      {
         assert( has_content() );
         return std::string( m_begin.data, m_end.data );
      }

      template< tracking_mode P = tracking_mode::eager, typename Eol = eol::lf_crlf >
      [[nodiscard]] memory_input< P, Eol > as_memory_input() const
      {
         assert( has_content() );
         return { m_begin.data, m_end.data, source, m_begin.byte, m_begin.line, m_begin.byte_in_line };
      }

      template< typename... States >
      void remove_content( States&&... /*unused*/ ) noexcept
      {
         m_end.reset();
      }

      // all non-root nodes are initialized by calling this method
      template< typename Rule, typename ParseInput, typename... States >
      void start( const ParseInput& in, States&&... /*unused*/ )
      {
         set_type< Rule >();
         source = in.source();
         m_begin = TAO_PEGTL_NAMESPACE::internal::iterator( in.iterator() );
      }

      // if parsing of the rule succeeded, this method is called
      template< typename Rule, typename ParseInput, typename... States >
      void success( const ParseInput& in, States&&... /*unused*/ ) noexcept
      {
         m_end = TAO_PEGTL_NAMESPACE::internal::iterator( in.iterator() );
      }

      // if parsing of the rule failed, this method is called
      template< typename Rule, typename ParseInput, typename... States >
      void failure( const ParseInput& /*unused*/, States&&... /*unused*/ ) noexcept
      {}

      // if parsing succeeded and the (optional) transform call
      // did not discard the node, it is appended to its parent.
      // note that "child" is the node whose Rule just succeeded
      // and "*this" is the parent where the node should be appended.
      template< typename... States >
      void emplace_back( std::unique_ptr< node_t >&& child, States&&... /*unused*/ )
      {
         assert( child );
         children.emplace_back( std::move( child ) );
      }
   };

   struct node
      : basic_node< node >
   {};

   namespace internal
   {
      template< typename >
      inline constexpr bool is_try_catch_type = false;

      template< typename Exception, typename... Rules >
      inline constexpr bool is_try_catch_type< TAO_PEGTL_NAMESPACE::internal::try_catch_type< Exception, Rules... > > = true;

      template< typename Node >
      struct state
      {
         std::vector< std::unique_ptr< Node > > stack;

         state()
         {
            emplace_back();
         }

         void emplace_back()
         {
            stack.emplace_back( std::make_unique< Node >() );
         }

         [[nodiscard]] std::unique_ptr< Node >& back() noexcept
         {
            assert( !stack.empty() );
            return stack.back();
         }

         void pop_back() noexcept
         {
            assert( !stack.empty() );
            return stack.pop_back();
         }
      };

      template< typename Selector, typename... Parameters >
      void transform( Parameters&&... /*unused*/ ) noexcept
      {}

      template< typename Selector, typename ParseInput, typename Node, typename... States >
      auto transform( const ParseInput& in, std::unique_ptr< Node >& n, States&&... st ) noexcept( noexcept( Selector::transform( in, n, st... ) ) )
         -> decltype( Selector::transform( in, n, st... ), void() )
      {
         Selector::transform( in, n, st... );
      }

      template< typename Selector, typename ParseInput, typename Node, typename... States >
      auto transform( const ParseInput& /*unused*/, std::unique_ptr< Node >& n, States&&... st ) noexcept( noexcept( Selector::transform( n, st... ) ) )
         -> decltype( Selector::transform( n, st... ), void() )
      {
         Selector::transform( n, st... );
      }

      template< typename Rule, template< typename... > class Selector >
      inline constexpr bool is_selected_node = ( TAO_PEGTL_NAMESPACE::internal::enable_control< Rule > && Selector< Rule >::value );

      template< unsigned Level, typename Subs, template< typename... > class Selector >
      inline constexpr bool is_leaf{};

      template< typename... Rules, template< typename... > class Selector >
      inline constexpr bool is_leaf< 0, type_list< Rules... >, Selector > = ( sizeof...( Rules ) == 0 );

      template< unsigned Level, typename Rule, template< typename... > class Selector >
      inline constexpr bool is_unselected_branch = ( !is_selected_node< Rule, Selector > && is_leaf< Level, typename Rule::subs_t, Selector > );

      template< unsigned Level, typename... Rules, template< typename... > class Selector >
      inline constexpr bool is_leaf< Level, type_list< Rules... >, Selector > = ( is_unselected_branch< Level - 1, Rules, Selector > && ... );

      template< typename Node, template< typename... > class Selector, template< typename... > class Control >
      struct make_control
      {
         template< typename Rule, bool, bool >
         struct state_handler;

         template< typename Rule >
         using type = rotate_states_right< state_handler< Rule, is_selected_node< Rule, Selector >, is_leaf< 8, typename Rule::subs_t, Selector > > >;
      };

      template< typename Node, template< typename... > class Selector, template< typename... > class Control >
      template< typename Rule >
      struct make_control< Node, Selector, Control >::state_handler< Rule, false, true >
         : remove_first_state< Control< Rule > >
      {};

      template< typename Node, template< typename... > class Selector, template< typename... > class Control >
      template< typename Rule >
      struct make_control< Node, Selector, Control >::state_handler< Rule, false, false >
         : remove_first_state< Control< Rule > >
      {
         template< apply_mode A,
                   rewind_mode M,
                   template< typename... >
                   class Action,
                   template< typename... >
                   class Control2,
                   typename ParseInput,
                   typename... States >
         [[nodiscard]] static bool match( ParseInput& in, States&&... st )
         {
            auto& state = std::get< sizeof...( st ) - 1 >( std::tie( st... ) );
            if constexpr( is_try_catch_type< Rule > ) {
               internal::state< Node > tmp;
               tmp.emplace_back();
               tmp.stack.swap( state.stack );
               const bool result = Control< Rule >::template match< A, M, Action, Control2 >( in, st... );
               tmp.stack.swap( state.stack );
               if( result ) {
                  for( auto& c : tmp.back()->children ) {
                     state.back()->children.emplace_back( std::move( c ) );
                  }
               }
               return result;
            }
            else {
               state.emplace_back();
               const bool result = Control< Rule >::template match< A, M, Action, Control2 >( in, st... );
               if( result ) {
                  auto n = std::move( state.back() );
                  state.pop_back();
                  for( auto& c : n->children ) {
                     state.back()->children.emplace_back( std::move( c ) );
                  }
               }
               else {
                  state.pop_back();
               }
               return result;
            }
         }
      };

      template< typename Node, template< typename... > class Selector, template< typename... > class Control >
      template< typename Rule, bool B >
      struct make_control< Node, Selector, Control >::state_handler< Rule, true, B >
         : remove_first_state< Control< Rule > >
      {
         template< typename ParseInput, typename... States >
         static void start( const ParseInput& in, state< Node >& state, States&&... st )
         {
            Control< Rule >::start( in, st... );
            state.emplace_back();
            state.back()->template start< Rule >( in, st... );
         }

         template< typename ParseInput, typename... States >
         static void success( const ParseInput& in, state< Node >& state, States&&... st )
         {
            Control< Rule >::success( in, st... );
            auto n = std::move( state.back() );
            state.pop_back();
            n->template success< Rule >( in, st... );
            transform< Selector< Rule > >( in, n, st... );
            if( n ) {
               state.back()->emplace_back( std::move( n ), st... );
            }
         }

         template< typename ParseInput, typename... States >
         static void failure( const ParseInput& in, state< Node >& state, States&&... st ) noexcept( noexcept( Control< Rule >::failure( in, st... ) ) && noexcept( std::declval< Node& >().template failure< Rule >( in, st... ) ) )
         {
            Control< Rule >::failure( in, st... );
            state.back()->template failure< Rule >( in, st... );
            state.pop_back();
         }
      };

      template< typename >
      using store_all = std::true_type;

      template< typename >
      struct selector;

      template< typename T >
      struct selector< std::tuple< T > >
      {
         using type = typename T::type;
      };

      template< typename... Ts >
      struct selector< std::tuple< Ts... > >
      {
         static_assert( sizeof...( Ts ) == 0, "multiple matches found" );
         using type = std::false_type;
      };

      template< typename T >
      using selector_t = typename selector< T >::type;

      template< typename Rule, typename Collection >
      using select_tuple = std::conditional_t< Collection::template contains< Rule >, std::tuple< Collection >, std::tuple<> >;

   }  // namespace internal

   template< typename Rule, typename... Collections >
   using selector = internal::selector_t< decltype( std::tuple_cat( std::declval< internal::select_tuple< Rule, Collections > >()... ) ) >;

   template< typename Base >
   struct apply
      : std::true_type
   {
      template< typename... Rules >
      struct on
      {
         using type = Base;

         template< typename Rule >
         static constexpr bool contains = ( std::is_same_v< Rule, Rules > || ... );
      };
   };

   struct store_content
      : apply< store_content >
   {};

   // some nodes don't need to store their content
   struct remove_content
      : apply< remove_content >
   {
      template< typename Node, typename... States >
      static void transform( std::unique_ptr< Node >& n, States&&... st ) noexcept( noexcept( n->Node::remove_content( st... ) ) )
      {
         n->remove_content( st... );
      }
   };

   // if a node has only one child, replace the node with its child, otherwise remove content
   struct fold_one
      : apply< fold_one >
   {
      template< typename Node, typename... States >
      static void transform( std::unique_ptr< Node >& n, States&&... st ) noexcept( noexcept( n->children.size(), n->Node::remove_content( st... ) ) )
      {
         if( n->children.size() == 1 ) {
            n = std::move( n->children.front() );
         }
         else {
            n->remove_content( st... );
         }
      }
   };

   // if a node has no children, discard the node, otherwise remove content
   struct discard_empty
      : apply< discard_empty >
   {
      template< typename Node, typename... States >
      static void transform( std::unique_ptr< Node >& n, States&&... st ) noexcept( noexcept( n->children.empty(), n->Node::remove_content( st... ) ) )
      {
         if( n->children.empty() ) {
            n.reset();
         }
         else {
            n->remove_content( st... );
         }
      }
   };

   template< typename Rule,
             typename Node,
             template< typename... > class Selector = internal::store_all,
             template< typename... > class Action = nothing,
             template< typename... > class Control = normal,
             typename ParseInput,
             typename... States >
   [[nodiscard]] std::unique_ptr< Node > parse( ParseInput&& in, States&&... st )
   {
      internal::state< Node > state;
      if( !TAO_PEGTL_NAMESPACE::parse< Rule, Action, internal::make_control< Node, Selector, Control >::template type >( in, st..., state ) ) {
         return nullptr;
      }
      assert( state.stack.size() == 1 );
      return std::move( state.back() );
   }

   template< typename Rule,
             template< typename... > class Selector = internal::store_all,
             template< typename... > class Action = nothing,
             template< typename... > class Control = normal,
             typename ParseInput,
             typename... States >
   [[nodiscard]] std::unique_ptr< node > parse( ParseInput&& in, States&&... st )
   {
      return parse< Rule, node, Selector, Action, Control >( in, st... );
   }

}  // namespace TAO_PEGTL_NAMESPACE::parse_tree

#endif
<commit_msg>Simplify with unwind()<commit_after>// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey
// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/

#ifndef TAO_PEGTL_CONTRIB_PARSE_TREE_HPP
#define TAO_PEGTL_CONTRIB_PARSE_TREE_HPP

#include <cassert>
#include <memory>
#include <string>
#include <string_view>
#include <tuple>
#include <type_traits>
#include <typeindex>
#include <utility>
#include <vector>

#include "remove_first_state.hpp"
#include "shuffle_states.hpp"

#include "../apply_mode.hpp"
#include "../config.hpp"
#include "../demangle.hpp"
#include "../memory_input.hpp"
#include "../normal.hpp"
#include "../nothing.hpp"
#include "../parse.hpp"
#include "../rewind_mode.hpp"

#include "../internal/enable_control.hpp"
#include "../internal/iterator.hpp"

namespace TAO_PEGTL_NAMESPACE::parse_tree
{
   template< typename T >
   struct basic_node
   {
      using node_t = T;
      using children_t = std::vector< std::unique_ptr< node_t > >;
      children_t children;

      std::string_view type;
      std::string source;

      TAO_PEGTL_NAMESPACE::internal::iterator m_begin;
      TAO_PEGTL_NAMESPACE::internal::iterator m_end;

      // each node will be default constructed
      basic_node() = default;

      // no copy/move is necessary
      // (nodes are always owned/handled by a std::unique_ptr)
      basic_node( const basic_node& ) = delete;
      basic_node( basic_node&& ) = delete;

      ~basic_node() = default;

      // no assignment either
      basic_node& operator=( const basic_node& ) = delete;
      basic_node& operator=( basic_node&& ) = delete;

      [[nodiscard]] bool is_root() const noexcept
      {
         return type.empty();
      }

      template< typename U >
      [[nodiscard]] bool is_type() const noexcept
      {
         return type == demangle< U >();
      }

      template< typename U >
      void set_type() noexcept
      {
         type = demangle< U >();
      }

      [[nodiscard]] position begin() const
      {
         return position( m_begin, source );
      }

      [[nodiscard]] position end() const
      {
         return position( m_end, source );
      }

      [[nodiscard]] bool has_content() const noexcept
      {
         return m_end.data != nullptr;
      }

      [[nodiscard]] std::string_view string_view() const noexcept
      {
         assert( has_content() );
         return std::string_view( m_begin.data, m_end.data - m_begin.data );
      }

      [[nodiscard]] std::string string() const
      {
         assert( has_content() );
         return std::string( m_begin.data, m_end.data );
      }

      template< tracking_mode P = tracking_mode::eager, typename Eol = eol::lf_crlf >
      [[nodiscard]] memory_input< P, Eol > as_memory_input() const
      {
         assert( has_content() );
         return { m_begin.data, m_end.data, source, m_begin.byte, m_begin.line, m_begin.byte_in_line };
      }

      template< typename... States >
      void remove_content( States&&... /*unused*/ ) noexcept
      {
         m_end.reset();
      }

      // all non-root nodes are initialized by calling this method
      template< typename Rule, typename ParseInput, typename... States >
      void start( const ParseInput& in, States&&... /*unused*/ )
      {
         set_type< Rule >();
         source = in.source();
         m_begin = TAO_PEGTL_NAMESPACE::internal::iterator( in.iterator() );
      }

      // if parsing of the rule succeeded, this method is called
      template< typename Rule, typename ParseInput, typename... States >
      void success( const ParseInput& in, States&&... /*unused*/ ) noexcept
      {
         m_end = TAO_PEGTL_NAMESPACE::internal::iterator( in.iterator() );
      }

      // if parsing of the rule failed, this method is called
      template< typename Rule, typename ParseInput, typename... States >
      void failure( const ParseInput& /*unused*/, States&&... /*unused*/ ) noexcept
      {}

      // if parsing of the rule failed with an exception, this method is called
      template< typename Rule, typename ParseInput, typename... States >
      void unwind( const ParseInput& /*unused*/, States&&... /*unused*/ ) noexcept
      {}

      // if parsing succeeded and the (optional) transform call
      // did not discard the node, it is appended to its parent.
      // note that "child" is the node whose Rule just succeeded
      // and "*this" is the parent where the node should be appended.
      template< typename... States >
      void emplace_back( std::unique_ptr< node_t >&& child, States&&... /*unused*/ )
      {
         assert( child );
         children.emplace_back( std::move( child ) );
      }
   };

   struct node
      : basic_node< node >
   {};

   namespace internal
   {
      template< typename Node >
      struct state
      {
         std::vector< std::unique_ptr< Node > > stack;

         state()
         {
            emplace_back();
         }

         void emplace_back()
         {
            stack.emplace_back( std::make_unique< Node >() );
         }

         [[nodiscard]] std::unique_ptr< Node >& back() noexcept
         {
            assert( !stack.empty() );
            return stack.back();
         }

         void pop_back() noexcept
         {
            assert( !stack.empty() );
            return stack.pop_back();
         }
      };

      template< typename Selector, typename... Parameters >
      void transform( Parameters&&... /*unused*/ ) noexcept
      {}

      template< typename Selector, typename ParseInput, typename Node, typename... States >
      auto transform( const ParseInput& in, std::unique_ptr< Node >& n, States&&... st ) noexcept( noexcept( Selector::transform( in, n, st... ) ) )
         -> decltype( Selector::transform( in, n, st... ), void() )
      {
         Selector::transform( in, n, st... );
      }

      template< typename Selector, typename ParseInput, typename Node, typename... States >
      auto transform( const ParseInput& /*unused*/, std::unique_ptr< Node >& n, States&&... st ) noexcept( noexcept( Selector::transform( n, st... ) ) )
         -> decltype( Selector::transform( n, st... ), void() )
      {
         Selector::transform( n, st... );
      }

      template< typename Rule, template< typename... > class Selector >
      inline constexpr bool is_selected_node = ( TAO_PEGTL_NAMESPACE::internal::enable_control< Rule > && Selector< Rule >::value );

      template< unsigned Level, typename Subs, template< typename... > class Selector >
      inline constexpr bool is_leaf{};

      template< typename... Rules, template< typename... > class Selector >
      inline constexpr bool is_leaf< 0, type_list< Rules... >, Selector > = ( sizeof...( Rules ) == 0 );

      template< unsigned Level, typename Rule, template< typename... > class Selector >
      inline constexpr bool is_unselected_branch = ( !is_selected_node< Rule, Selector > && is_leaf< Level, typename Rule::subs_t, Selector > );

      template< unsigned Level, typename... Rules, template< typename... > class Selector >
      inline constexpr bool is_leaf< Level, type_list< Rules... >, Selector > = ( is_unselected_branch< Level - 1, Rules, Selector > && ... );

      template< typename Node, template< typename... > class Selector, template< typename... > class Control >
      struct make_control
      {
         template< typename Rule, bool, bool >
         struct state_handler;

         template< typename Rule >
         using type = rotate_states_right< state_handler< Rule, is_selected_node< Rule, Selector >, is_leaf< 8, typename Rule::subs_t, Selector > > >;
      };

      template< typename Node, template< typename... > class Selector, template< typename... > class Control >
      template< typename Rule >
      struct make_control< Node, Selector, Control >::state_handler< Rule, false, true >
         : remove_first_state< Control< Rule > >
      {};

      template< typename Node, template< typename... > class Selector, template< typename... > class Control >
      template< typename Rule >
      struct make_control< Node, Selector, Control >::state_handler< Rule, false, false >
         : remove_first_state< Control< Rule > >
      {
         template< typename ParseInput, typename... States >
         static void start( const ParseInput& /*unused*/, state< Node >& state, States&&... /*unused*/ )
         {
            state.emplace_back();
         }

         template< typename ParseInput, typename... States >
         static void success( const ParseInput& /*unused*/, state< Node >& state, States&&... /*unused*/ )
         {
            auto n = std::move( state.back() );
            state.pop_back();
            for( auto& c : n->children ) {
               state.back()->children.emplace_back( std::move( c ) );
            }
         }

         template< typename ParseInput, typename... States >
         static void failure( const ParseInput& /*unused*/, state< Node >& state, States&&... /*unused*/ )
         {
            state.pop_back();
         }

         template< typename ParseInput, typename... States >
         static void unwind( const ParseInput& /*unused*/, state< Node >& state, States&&... /*unused*/ )
         {
            state.pop_back();
         }
      };

      template< typename Node, template< typename... > class Selector, template< typename... > class Control >
      template< typename Rule, bool B >
      struct make_control< Node, Selector, Control >::state_handler< Rule, true, B >
         : remove_first_state< Control< Rule > >
      {
         template< typename ParseInput, typename... States >
         static void start( const ParseInput& in, state< Node >& state, States&&... st )
         {
            Control< Rule >::start( in, st... );
            state.emplace_back();
            state.back()->template start< Rule >( in, st... );
         }

         template< typename ParseInput, typename... States >
         static void success( const ParseInput& in, state< Node >& state, States&&... st )
         {
            Control< Rule >::success( in, st... );
            auto n = std::move( state.back() );
            state.pop_back();
            n->template success< Rule >( in, st... );
            transform< Selector< Rule > >( in, n, st... );
            if( n ) {
               state.back()->emplace_back( std::move( n ), st... );
            }
         }

         template< typename ParseInput, typename... States >
         static void failure( const ParseInput& in, state< Node >& state, States&&... st )
         {
            Control< Rule >::failure( in, st... );
            state.back()->template failure< Rule >( in, st... );
            state.pop_back();
         }

         template< typename ParseInput, typename... States >
         static void unwind( const ParseInput& in, state< Node >& state, States&&... st )
         {
            if constexpr( TAO_PEGTL_NAMESPACE::internal::has_unwind< Control< Rule >, void, ParseInput&, States... > ) {
               Control< Rule >::unwind( in, st... );
            }
            state.back()->template unwind< Rule >( in, st... );
            state.pop_back();
         }
      };

      template< typename >
      using store_all = std::true_type;

      template< typename >
      struct selector;

      template< typename T >
      struct selector< std::tuple< T > >
      {
         using type = typename T::type;
      };

      template< typename... Ts >
      struct selector< std::tuple< Ts... > >
      {
         static_assert( sizeof...( Ts ) == 0, "multiple matches found" );
         using type = std::false_type;
      };

      template< typename T >
      using selector_t = typename selector< T >::type;

      template< typename Rule, typename Collection >
      using select_tuple = std::conditional_t< Collection::template contains< Rule >, std::tuple< Collection >, std::tuple<> >;

   }  // namespace internal

   template< typename Rule, typename... Collections >
   using selector = internal::selector_t< decltype( std::tuple_cat( std::declval< internal::select_tuple< Rule, Collections > >()... ) ) >;

   template< typename Base >
   struct apply
      : std::true_type
   {
      template< typename... Rules >
      struct on
      {
         using type = Base;

         template< typename Rule >
         static constexpr bool contains = ( std::is_same_v< Rule, Rules > || ... );
      };
   };

   struct store_content
      : apply< store_content >
   {};

   // some nodes don't need to store their content
   struct remove_content
      : apply< remove_content >
   {
      template< typename Node, typename... States >
      static void transform( std::unique_ptr< Node >& n, States&&... st ) noexcept( noexcept( n->Node::remove_content( st... ) ) )
      {
         n->remove_content( st... );
      }
   };

   // if a node has only one child, replace the node with its child, otherwise remove content
   struct fold_one
      : apply< fold_one >
   {
      template< typename Node, typename... States >
      static void transform( std::unique_ptr< Node >& n, States&&... st ) noexcept( noexcept( n->children.size(), n->Node::remove_content( st... ) ) )
      {
         if( n->children.size() == 1 ) {
            n = std::move( n->children.front() );
         }
         else {
            n->remove_content( st... );
         }
      }
   };

   // if a node has no children, discard the node, otherwise remove content
   struct discard_empty
      : apply< discard_empty >
   {
      template< typename Node, typename... States >
      static void transform( std::unique_ptr< Node >& n, States&&... st ) noexcept( noexcept( n->children.empty(), n->Node::remove_content( st... ) ) )
      {
         if( n->children.empty() ) {
            n.reset();
         }
         else {
            n->remove_content( st... );
         }
      }
   };

   template< typename Rule,
             typename Node,
             template< typename... > class Selector = internal::store_all,
             template< typename... > class Action = nothing,
             template< typename... > class Control = normal,
             typename ParseInput,
             typename... States >
   [[nodiscard]] std::unique_ptr< Node > parse( ParseInput&& in, States&&... st )
   {
      internal::state< Node > state;
      if( !TAO_PEGTL_NAMESPACE::parse< Rule, Action, internal::make_control< Node, Selector, Control >::template type >( in, st..., state ) ) {
         return nullptr;
      }
      assert( state.stack.size() == 1 );
      return std::move( state.back() );
   }

   template< typename Rule,
             template< typename... > class Selector = internal::store_all,
             template< typename... > class Action = nothing,
             template< typename... > class Control = normal,
             typename ParseInput,
             typename... States >
   [[nodiscard]] std::unique_ptr< node > parse( ParseInput&& in, States&&... st )
   {
      return parse< Rule, node, Selector, Action, Control >( in, st... );
   }

}  // namespace TAO_PEGTL_NAMESPACE::parse_tree

#endif
<|endoftext|>


<commit_before>/************************************************************************/
/*                                                                      */
/*               Copyright 1998-2002 by Ullrich Koethe                  */
/*       Cognitive Systems Group, University of Hamburg, Germany        */
/*                                                                      */
/*    This file is part of the VIGRA computer vision library.           */
/*    You may use, modify, and distribute this software according       */
/*    to the terms stated in the LICENSE file included in               */
/*    the VIGRA distribution.                                           */
/*                                                                      */
/*    The VIGRA Website is                                              */
/*        http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/      */
/*    Please direct questions, bug reports, and contributions to        */
/*        koethe@informatik.uni-hamburg.de                              */
/*                                                                      */
/*  THIS SOFTWARE IS PROVIDED AS IS AND WITHOUT ANY EXPRESS OR          */
/*  IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED      */
/*  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */
/*                                                                      */
/************************************************************************/

#ifndef VIGRA_INTERPOLATING_ACCESSOR_HXX
#define VIGRA_INTERPOLATING_ACCESSOR_HXX

#include "vigra/accessor.hxx"
#include "vigra/diff2d.hxx"

namespace vigra {

/** \addtogroup DataAccessors
*/
//@{

/********************************************************/
/*                                                      */
/*                  InterpolatingAccessor               */
/*                                                      */
/********************************************************/

/** \brief Bilinear interpolation at non-integer positions.

    This accessor allows an image be accessed at arbitrary non-integer
    coordinates and performs an bi-linear interpolation to
    obtain a pixel value.
    It uses the given ACCESSOR (which is usually the
    accessor originally associated with the iterator)
    to access data.

    \#include "vigra/accessor.hxx"
    Namespace: vigra

     Required Interface:

    \code
    ITERATOR iter;
    ACCESSOR a;
    VALUETYPE destvalue;
    float s;
    int x, y;

    destvalue = s * a(iter, x, y) + s * a(iter, x, y);

    \endcode
*/
template <class ACCESSOR, class VALUETYPE>
class BilinearInterpolatingAccessor
{
  public:
    /** the iterators' pixel type
    */
    typedef VALUETYPE value_type;

    /** init from given accessor
    */
    BilinearInterpolatingAccessor(ACCESSOR a)
    : a_(a)
    {}

    /** Interpolate the data item at a non-integer position.
        Ensure that no outside pixels are accessed if
        (x, y) is near the image border (as long as
        0 <= x <= width-1, 0 <= y <= height-1).
    */
    template <class ITERATOR>
    value_type operator()(ITERATOR const & i, float x, float y) const
    {
        int ix = int(x);
        int iy = int(y);
        float dx = x - ix;
        float dy = y - iy;

        value_type ret;

        // avoid dereferencing the iterator outside its range
        if(dx == 0.0)
        {
            if(dy == 0.0)
            {
                ret = a_(i, Diff2D(ix, iy));
            }
            else
            {
                ret = detail::RequiresExplicitCast<value_type>::cast(
                  (1.0 - dy) * a_(i, Diff2D(ix, iy)) +
                  dy * a_(i, Diff2D(ix, iy + 1)));
            }
        }
        else
        {
            if(dy == 0.0)
            {
                ret = detail::RequiresExplicitCast<value_type>::cast(
                  (1.0 - dx) * a_(i, Diff2D(ix, iy)) +
                  dx * a_(i, Diff2D(ix + 1, iy)));
            }
            else
            {
                ret = detail::RequiresExplicitCast<value_type>::cast(
                  (1.0 - dx) * (1.0 - dy) * a_(i, Diff2D(ix, iy)) +
                  dx * (1.0 - dy) * a_(i, Diff2D(ix + 1, iy)) +
                  (1.0 - dx) * dy * a_(i, Diff2D(ix, iy + 1)) +
                  dx * dy * a_(i, Diff2D(ix + 1, iy + 1)));
            }
        }

        return ret;
    }

    /** Interpolate the data item at a non-integer position.
        This function works as long as 0 <= x < width-1,
        0 <= y < height-1. It is slightly faster than <TT>operator()</TT>.
    */
    template <class ITERATOR>
    value_type unchecked(ITERATOR const & i, float x, float y) const
    {
        int ix = int(x);
        int iy = int(y);
        float dx = x - ix;
        float dy = y - iy;
        return detail::RequiresExplicitCast<value_type>::cast(
               (1.0 - dx) * (1.0 - dy) * a_(i, Diff2D(ix, iy)) +
               dx * (1.0 - dy) * a_(i, Diff2D(ix + 1, iy)) +
               (1.0 - dx) * dy * a_(i, Diff2D(ix, iy + 1)) +
               dx * dy * a_(i, Diff2D(ix + 1, iy + 1)));
    }

  private:
    ACCESSOR a_;
};

//@}

} // namespace vigra

#endif /* VIGRA_INTERPOLATING_ACCESSOR_HXX */
<commit_msg>corrected class name in comment<commit_after>/************************************************************************/
/*                                                                      */
/*               Copyright 1998-2002 by Ullrich Koethe                  */
/*       Cognitive Systems Group, University of Hamburg, Germany        */
/*                                                                      */
/*    This file is part of the VIGRA computer vision library.           */
/*    You may use, modify, and distribute this software according       */
/*    to the terms stated in the LICENSE file included in               */
/*    the VIGRA distribution.                                           */
/*                                                                      */
/*    The VIGRA Website is                                              */
/*        http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/      */
/*    Please direct questions, bug reports, and contributions to        */
/*        koethe@informatik.uni-hamburg.de                              */
/*                                                                      */
/*  THIS SOFTWARE IS PROVIDED AS IS AND WITHOUT ANY EXPRESS OR          */
/*  IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED      */
/*  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */
/*                                                                      */
/************************************************************************/

#ifndef VIGRA_INTERPOLATING_ACCESSOR_HXX
#define VIGRA_INTERPOLATING_ACCESSOR_HXX

#include "vigra/accessor.hxx"
#include "vigra/diff2d.hxx"

namespace vigra {

/** \addtogroup DataAccessors
*/
//@{

/********************************************************/
/*                                                      */
/*            BilinearInterpolatingAccessor             */
/*                                                      */
/********************************************************/

/** \brief Bilinear interpolation at non-integer positions.

    This accessor allows an image be accessed at arbitrary non-integer
    coordinates and performs an bi-linear interpolation to
    obtain a pixel value.
    It uses the given ACCESSOR (which is usually the
    accessor originally associated with the iterator)
    to access data.

    \#include "vigra/accessor.hxx"
    Namespace: vigra

     Required Interface:

    \code
    ITERATOR iter;
    ACCESSOR a;
    VALUETYPE destvalue;
    float s;
    int x, y;

    destvalue = s * a(iter, x, y) + s * a(iter, x, y);

    \endcode
*/
template <class ACCESSOR, class VALUETYPE>
class BilinearInterpolatingAccessor
{
  public:
    /** the iterators' pixel type
    */
    typedef VALUETYPE value_type;

    /** init from given accessor
    */
    BilinearInterpolatingAccessor(ACCESSOR a)
    : a_(a)
    {}

    /** Interpolate the data item at a non-integer position.
        Ensure that no outside pixels are accessed if
        (x, y) is near the image border (as long as
        0 <= x <= width-1, 0 <= y <= height-1).
    */
    template <class ITERATOR>
    value_type operator()(ITERATOR const & i, float x, float y) const
    {
        int ix = int(x);
        int iy = int(y);
        float dx = x - ix;
        float dy = y - iy;

        value_type ret;

        // avoid dereferencing the iterator outside its range
        if(dx == 0.0)
        {
            if(dy == 0.0)
            {
                ret = a_(i, Diff2D(ix, iy));
            }
            else
            {
                ret = detail::RequiresExplicitCast<value_type>::cast(
                  (1.0 - dy) * a_(i, Diff2D(ix, iy)) +
                  dy * a_(i, Diff2D(ix, iy + 1)));
            }
        }
        else
        {
            if(dy == 0.0)
            {
                ret = detail::RequiresExplicitCast<value_type>::cast(
                  (1.0 - dx) * a_(i, Diff2D(ix, iy)) +
                  dx * a_(i, Diff2D(ix + 1, iy)));
            }
            else
            {
                ret = detail::RequiresExplicitCast<value_type>::cast(
                  (1.0 - dx) * (1.0 - dy) * a_(i, Diff2D(ix, iy)) +
                  dx * (1.0 - dy) * a_(i, Diff2D(ix + 1, iy)) +
                  (1.0 - dx) * dy * a_(i, Diff2D(ix, iy + 1)) +
                  dx * dy * a_(i, Diff2D(ix + 1, iy + 1)));
            }
        }

        return ret;
    }

    /** Interpolate the data item at a non-integer position.
        This function works as long as 0 <= x < width-1,
        0 <= y < height-1. It is slightly faster than <TT>operator()</TT>.
    */
    template <class ITERATOR>
    value_type unchecked(ITERATOR const & i, float x, float y) const
    {
        int ix = int(x);
        int iy = int(y);
        float dx = x - ix;
        float dy = y - iy;
        return detail::RequiresExplicitCast<value_type>::cast(
               (1.0 - dx) * (1.0 - dy) * a_(i, Diff2D(ix, iy)) +
               dx * (1.0 - dy) * a_(i, Diff2D(ix + 1, iy)) +
               (1.0 - dx) * dy * a_(i, Diff2D(ix, iy + 1)) +
               dx * dy * a_(i, Diff2D(ix + 1, iy + 1)));
    }

  private:
    ACCESSOR a_;
};

//@}

} // namespace vigra

#endif /* VIGRA_INTERPOLATING_ACCESSOR_HXX */
<|endoftext|>