<commit_before>//===--- swift-syntax-test.cpp - Reflection Syntax testing application ----===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
// This is a host-side tool to perform round-trip testing of "full-fidelity"
// lexing and parsing. That is, when this application ingests a .swift file,
// it should be able to create a list of full tokens, or a full-fidelity AST,
// print them, and get the same file back out. This ensures that we aren't
// losing any source information in these structures.
//
//===----------------------------------------------------------------------===//

#include "swift/AST/DiagnosticEngine.h"
#include "swift/AST/DiagnosticsFrontend.h"
#include "swift/Basic/LangOptions.h"
#include "swift/Basic/LLVMInitialize.h"
#include "swift/Basic/SourceManager.h"
#include "swift/Frontend/Frontend.h"
#include "swift/Frontend/PrintingDiagnosticConsumer.h"
#include "swift/Syntax/Serialization/SyntaxDeserialization.h"
#include "swift/Parse/Lexer.h"
#include "swift/Parse/Parser.h"
#include "swift/Subsystems.h"
#include "swift/Syntax/Serialization/SyntaxSerialization.h"
#include "swift/Syntax/SyntaxData.h"
#include "swift/Syntax/SyntaxNodes.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/raw_ostream.h"

using namespace swift;
using namespace swift::syntax;
using llvm::StringRef;

enum class ActionType {
  DumpRawTokenSyntax,
  FullLexRoundTrip,
  FullParseRoundTrip,
  SerializeRawTree,
  DeserializeRawTree,
  ParseOnly,
  ParserGen,
  EOFPos,
  None
};

namespace options {
static llvm::cl::OptionCategory Category("swift-syntax-test Options");
static llvm::cl::opt<ActionType>
Action(llvm::cl::desc("Action (required):"),
       llvm::cl::init(ActionType::None),
       llvm::cl::values(
        clEnumValN(ActionType::DumpRawTokenSyntax,
                   "dump-full-tokens",
                   "Lex the source file and dump the tokens "
                   "and their absolute line/column locations"),
        clEnumValN(ActionType::FullLexRoundTrip,
                   "round-trip-lex",
                   "Lex the source file and print it back out for "
                   "comparing against the original"),
        clEnumValN(ActionType::FullParseRoundTrip,
                   "round-trip-parse",
                   "Parse the source file and print it back out for "
                   "comparing against the input"),
        clEnumValN(ActionType::ParseOnly,
                   "parse-only",
                   "Parse the source file with syntax nodes and exit"),
        clEnumValN(ActionType::ParserGen,
                   "parse-gen",
                   "Parse the source file and print it back out for "
                   "comparing against the input"),
        clEnumValN(ActionType::SerializeRawTree,
                   "serialize-raw-tree",
                   "Parse the source file and serialize the raw tree"
                   "to JSON"),
        clEnumValN(ActionType::DeserializeRawTree,
                   "deserialize-raw-tree",
                   "Parse the JSON file from the serialized raw tree"
                   "to the original"),
        clEnumValN(ActionType::EOFPos,
                   "eof",
                   "Parse the source file, calculate the absolute position"
                   "of the EOF token, and dump the buffer from the start of the"
                   "file to the EOF token")));

static llvm::cl::opt<std::string>
InputSourceFilename("input-source-filename",
                    llvm::cl::desc("Path to the input .swift file"));

static llvm::cl::opt<std::string>
OutputFilename("output-filename",
               llvm::cl::desc("Path to the output file"));

static llvm::cl::opt<bool>
PrintNodeKind("print-node-kind",
              llvm::cl::desc("To print syntax node kind"),
              llvm::cl::cat(Category),
              llvm::cl::init(false));

static llvm::cl::opt<bool>
PrintTrivialNodeKind("print-trivial-node-kind",
                     llvm::cl::desc("To print trivial syntax node kind"),
                     llvm::cl::cat(Category),
                     llvm::cl::init(false));

static llvm::cl::opt<bool>
VerifySyntaxTree("verify-syntax-tree",
                 llvm::cl::desc("Emit warnings for unknown nodes"),
                 llvm::cl::cat(Category),
                 llvm::cl::init(true));

static llvm::cl::opt<bool>
Visual("v",
       llvm::cl::desc("Print visually"),
       llvm::cl::cat(Category),
       llvm::cl::init(false));
} // end namespace options

namespace {
int getTokensFromFile(unsigned BufferID,
                      LangOptions &LangOpts,
                      SourceManager &SourceMgr,
                      swift::DiagnosticEngine &Diags,
                      std::vector<std::pair<RC<syntax::RawSyntax>,
                      syntax::AbsolutePosition>> &Tokens) {
  Tokens = tokenizeWithTrivia(LangOpts, SourceMgr, BufferID,
                              /*Offset=*/0, /*EndOffset=*/0,
                              &Diags);
  return EXIT_SUCCESS;
}

int
getTokensFromFile(const StringRef InputFilename,
                  LangOptions &LangOpts,
                  SourceManager &SourceMgr,
                  DiagnosticEngine &Diags,
                  std::vector<std::pair<RC<syntax::RawSyntax>,
                                        syntax::AbsolutePosition>> &Tokens) {
  auto Buffer = llvm::MemoryBuffer::getFile(InputFilename);
  if (!Buffer) {
    Diags.diagnose(SourceLoc(), diag::cannot_open_file,
                   InputFilename, Buffer.getError().message());
    return EXIT_FAILURE;
  }

  auto BufferID = SourceMgr.addNewSourceBuffer(std::move(Buffer.get()));
  return getTokensFromFile(BufferID, LangOpts, SourceMgr, Diags, Tokens);
}

void anchorForGetMainExecutable() {}

SourceFile *getSourceFile(CompilerInstance &Instance,
                          StringRef InputFileName,
                          const char *MainExecutablePath) {
  CompilerInvocation Invocation;
  Invocation.getLangOptions().BuildSyntaxTree = true;
  Invocation.getLangOptions().VerifySyntaxTree = options::VerifySyntaxTree;
  Invocation.getFrontendOptions().InputsAndOutputs.addInputFile(InputFileName);
  Invocation.setMainExecutablePath(
    llvm::sys::fs::getMainExecutable(MainExecutablePath,
      reinterpret_cast<void *>(&anchorForGetMainExecutable)));

  Invocation.setModuleName("Test");
  PrintingDiagnosticConsumer DiagPrinter;
  Instance.addDiagnosticConsumer(&DiagPrinter);
  if (Instance.setup(Invocation)) {
    return nullptr;
  }

  // First, parse the file normally and get the regular old AST.
  Instance.performParseOnly();

  SourceFile *SF = nullptr;
  for (auto Unit : Instance.getMainModule()->getFiles()) {
    SF = dyn_cast<SourceFile>(Unit);
    if (SF != nullptr) {
      break;
    }
  }
  assert(SF && "No source file");
  return SF;
}

int doFullLexRoundTrip(const StringRef InputFilename) {
  LangOptions LangOpts;
  SourceManager SourceMgr;
  DiagnosticEngine Diags(SourceMgr);
  PrintingDiagnosticConsumer DiagPrinter;
  Diags.addConsumer(DiagPrinter);

  std::vector<std::pair<RC<syntax::RawSyntax>,
                                   syntax::AbsolutePosition>> Tokens;
  if (getTokensFromFile(InputFilename, LangOpts, SourceMgr,
                        Diags, Tokens) == EXIT_FAILURE) {
    return EXIT_FAILURE;
  }

  for (auto TokAndPos : Tokens) {
    TokAndPos.first->print(llvm::outs(), {});
  }

  return EXIT_SUCCESS;
}

int doDumpRawTokenSyntax(const StringRef InputFilename) {
  LangOptions LangOpts;
  SourceManager SourceMgr;
  DiagnosticEngine Diags(SourceMgr);
  PrintingDiagnosticConsumer DiagPrinter;
  Diags.addConsumer(DiagPrinter);

  std::vector<std::pair<RC<syntax::RawSyntax>,
                        syntax::AbsolutePosition>> Tokens;
  if (getTokensFromFile(InputFilename, LangOpts, SourceMgr,
                        Diags, Tokens) == EXIT_FAILURE) {
    return EXIT_FAILURE;
  }

  for (auto TokAndPos : Tokens) {
    TokAndPos.second.printLineAndColumn(llvm::outs());
    llvm::outs() << "\n";
    TokAndPos.first->dump(llvm::outs());
    llvm::outs() << "\n";
  }

  return EXIT_SUCCESS;
}

int doFullParseRoundTrip(const char *MainExecutablePath,
                         const StringRef InputFileName) {
  CompilerInstance Instance;
  SourceFile *SF = getSourceFile(Instance, InputFileName, MainExecutablePath);
  SF->getSyntaxRoot().print(llvm::outs(), {});
  return EXIT_SUCCESS;
}

int doSerializeRawTree(const char *MainExecutablePath,
                       const StringRef InputFileName) {
  CompilerInstance Instance;
  SourceFile *SF = getSourceFile(Instance, InputFileName, MainExecutablePath);

  auto Root = SF->getSyntaxRoot().getRaw();
  swift::json::Output out(llvm::outs());
  out << *Root;
  llvm::outs() << "\n";

  return EXIT_SUCCESS;
}

int doDeserializeRawTree(const char *MainExecutablePath,
                         const StringRef InputFileName,
                         const StringRef OutputFileName) {

  auto Buffer = llvm::MemoryBuffer::getFile(InputFileName);
  std::error_code errorCode;
  auto os = llvm::make_unique<llvm::raw_fd_ostream>(
              OutputFileName, errorCode, llvm::sys::fs::F_None);
  swift::json::SyntaxDeserializer deserializer(llvm::MemoryBufferRef(*(Buffer.get())));
  swift::SyntaxPrintOptions opt;
  deserializer.getSourceFileSyntax()->print(*os);
  return EXIT_SUCCESS;
}

int doParseOnly(const char *MainExecutablePath,
                  const StringRef InputFileName) {
  CompilerInstance Instance;
  SourceFile *SF = getSourceFile(Instance, InputFileName, MainExecutablePath);
  return SF ? EXIT_SUCCESS : EXIT_FAILURE;
}

int dumpParserGen(const char *MainExecutablePath,
                  const StringRef InputFileName) {
  CompilerInstance Instance;
  SourceFile *SF = getSourceFile(Instance, InputFileName, MainExecutablePath);
  SyntaxPrintOptions Opts;
  Opts.PrintSyntaxKind = options::PrintNodeKind;
  Opts.Visual = options::Visual;
  Opts.PrintTrivialNodeKind = options::PrintTrivialNodeKind;
  SF->getSyntaxRoot().print(llvm::outs(), Opts);
  return 0;
}

int dumpEOFSourceLoc(const char *MainExecutablePath,
                     const StringRef InputFileName) {
  CompilerInstance Instance;
  SourceFile *SF = getSourceFile(Instance, InputFileName, MainExecutablePath);
  auto BufferId = *SF->getBufferID();
  SyntaxPrintOptions Opts;
  auto Root = SF->getSyntaxRoot();
  auto AbPos = Root.getEOFToken().getAbsolutePosition();

  SourceManager &SourceMgr = SF->getASTContext().SourceMgr;
  auto StartLoc = SourceMgr.getLocForBufferStart(BufferId);
  auto EndLoc = SourceMgr.getLocForOffset(BufferId, AbPos.getOffset());

  // To ensure the correctness of position when translated to line & column pair.
  if (SourceMgr.getLineAndColumn(EndLoc) != AbPos.getLineAndColumn()) {
    llvm::outs() << "locations should be identical";
    return EXIT_FAILURE;
  }
  llvm::outs() << CharSourceRange(SourceMgr, StartLoc, EndLoc).str();
  return 0;
}
}// end of anonymous namespace

int main(int argc, char *argv[]) {
  PROGRAM_START(argc, argv);
  llvm::cl::ParseCommandLineOptions(argc, argv, "Swift Syntax Test\n");

  int ExitCode = EXIT_SUCCESS;

  if (options::InputSourceFilename.empty()) {
    llvm::errs() << "input source file is required\n";
    ExitCode = EXIT_FAILURE;
  }

  if (ExitCode == EXIT_FAILURE) {
    llvm::cl::PrintHelpMessage();
    return ExitCode;
  }

  switch (options::Action) {
  case ActionType::DumpRawTokenSyntax:
    ExitCode = doDumpRawTokenSyntax(options::InputSourceFilename);
    break;
  case ActionType::FullLexRoundTrip:
    ExitCode = doFullLexRoundTrip(options::InputSourceFilename);
    break;
  case ActionType::FullParseRoundTrip:
    ExitCode = doFullParseRoundTrip(argv[0], options::InputSourceFilename);
    break;
  case ActionType::SerializeRawTree:
    ExitCode = doSerializeRawTree(argv[0], options::InputSourceFilename);
    break;
  case ActionType::DeserializeRawTree:
    ExitCode = doDeserializeRawTree(argv[0], options::InputSourceFilename, options::OutputFilename);
    break;
  case ActionType::ParseOnly:
    ExitCode = doParseOnly(argv[0], options::InputSourceFilename);
    break;
  case ActionType::ParserGen:
    ExitCode = dumpParserGen(argv[0], options::InputSourceFilename);
    break;
  case ActionType::EOFPos:
    ExitCode = dumpEOFSourceLoc(argv[0], options::InputSourceFilename);
    break;
  case ActionType::None:
    llvm::errs() << "an action is required\n";
    llvm::cl::PrintHelpMessage();
    ExitCode = EXIT_FAILURE;
    break;
  }

  return ExitCode;
}
<commit_msg>[swift-syntax-test] Add batch option to execute action for every swift file in directory<commit_after>//===--- swift-syntax-test.cpp - Reflection Syntax testing application ----===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
// This is a host-side tool to perform round-trip testing of "full-fidelity"
// lexing and parsing. That is, when this application ingests a .swift file,
// it should be able to create a list of full tokens, or a full-fidelity AST,
// print them, and get the same file back out. This ensures that we aren't
// losing any source information in these structures.
//
//===----------------------------------------------------------------------===//

#include "swift/AST/DiagnosticEngine.h"
#include "swift/AST/DiagnosticsFrontend.h"
#include "swift/Basic/LangOptions.h"
#include "swift/Basic/LLVMInitialize.h"
#include "swift/Basic/SourceManager.h"
#include "swift/Frontend/Frontend.h"
#include "swift/Frontend/PrintingDiagnosticConsumer.h"
#include "swift/Syntax/Serialization/SyntaxDeserialization.h"
#include "swift/Parse/Lexer.h"
#include "swift/Parse/Parser.h"
#include "swift/Subsystems.h"
#include "swift/Syntax/Serialization/SyntaxSerialization.h"
#include "swift/Syntax/SyntaxData.h"
#include "swift/Syntax/SyntaxNodes.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/raw_ostream.h"

using namespace swift;
using namespace swift::syntax;
using llvm::StringRef;

enum class ActionType {
  DumpRawTokenSyntax,
  FullLexRoundTrip,
  FullParseRoundTrip,
  SerializeRawTree,
  DeserializeRawTree,
  ParseOnly,
  ParserGen,
  EOFPos,
  None
};

namespace options {
static llvm::cl::OptionCategory Category("swift-syntax-test Options");
static llvm::cl::opt<ActionType>
Action(llvm::cl::desc("Action (required):"),
       llvm::cl::init(ActionType::None),
       llvm::cl::values(
        clEnumValN(ActionType::DumpRawTokenSyntax,
                   "dump-full-tokens",
                   "Lex the source file and dump the tokens "
                   "and their absolute line/column locations"),
        clEnumValN(ActionType::FullLexRoundTrip,
                   "round-trip-lex",
                   "Lex the source file and print it back out for "
                   "comparing against the original"),
        clEnumValN(ActionType::FullParseRoundTrip,
                   "round-trip-parse",
                   "Parse the source file and print it back out for "
                   "comparing against the input"),
        clEnumValN(ActionType::ParseOnly,
                   "parse-only",
                   "Parse the source file with syntax nodes and exit"),
        clEnumValN(ActionType::ParserGen,
                   "parse-gen",
                   "Parse the source file and print it back out for "
                   "comparing against the input"),
        clEnumValN(ActionType::SerializeRawTree,
                   "serialize-raw-tree",
                   "Parse the source file and serialize the raw tree"
                   "to JSON"),
        clEnumValN(ActionType::DeserializeRawTree,
                   "deserialize-raw-tree",
                   "Parse the JSON file from the serialized raw tree"
                   "to the original"),
        clEnumValN(ActionType::EOFPos,
                   "eof",
                   "Parse the source file, calculate the absolute position"
                   "of the EOF token, and dump the buffer from the start of the"
                   "file to the EOF token")));

static llvm::cl::opt<std::string>
InputSourceFilename("input-source-filename",
                    llvm::cl::desc("Path to the input .swift file"));

static llvm::cl::opt<std::string>
InputSourceDirectory("input-source-directory",
                     llvm::cl::desc("Directory to be scanned recursively and"
                                    "run the selected action on every .swift"
                                    "file"));

static llvm::cl::opt<std::string>
OutputFilename("output-filename",
               llvm::cl::desc("Path to the output file"));

static llvm::cl::opt<bool>
PrintNodeKind("print-node-kind",
              llvm::cl::desc("To print syntax node kind"),
              llvm::cl::cat(Category),
              llvm::cl::init(false));

static llvm::cl::opt<bool>
PrintTrivialNodeKind("print-trivial-node-kind",
                     llvm::cl::desc("To print trivial syntax node kind"),
                     llvm::cl::cat(Category),
                     llvm::cl::init(false));

static llvm::cl::opt<bool>
VerifySyntaxTree("verify-syntax-tree",
                 llvm::cl::desc("Emit warnings for unknown nodes"),
                 llvm::cl::cat(Category),
                 llvm::cl::init(true));

static llvm::cl::opt<bool>
Visual("v",
       llvm::cl::desc("Print visually"),
       llvm::cl::cat(Category),
       llvm::cl::init(false));
} // end namespace options

namespace {
int getTokensFromFile(unsigned BufferID,
                      LangOptions &LangOpts,
                      SourceManager &SourceMgr,
                      swift::DiagnosticEngine &Diags,
                      std::vector<std::pair<RC<syntax::RawSyntax>,
                      syntax::AbsolutePosition>> &Tokens) {
  Tokens = tokenizeWithTrivia(LangOpts, SourceMgr, BufferID,
                              /*Offset=*/0, /*EndOffset=*/0,
                              &Diags);
  return EXIT_SUCCESS;
}

int
getTokensFromFile(const StringRef InputFilename,
                  LangOptions &LangOpts,
                  SourceManager &SourceMgr,
                  DiagnosticEngine &Diags,
                  std::vector<std::pair<RC<syntax::RawSyntax>,
                                        syntax::AbsolutePosition>> &Tokens) {
  auto Buffer = llvm::MemoryBuffer::getFile(InputFilename);
  if (!Buffer) {
    Diags.diagnose(SourceLoc(), diag::cannot_open_file,
                   InputFilename, Buffer.getError().message());
    return EXIT_FAILURE;
  }

  auto BufferID = SourceMgr.addNewSourceBuffer(std::move(Buffer.get()));
  return getTokensFromFile(BufferID, LangOpts, SourceMgr, Diags, Tokens);
}

void anchorForGetMainExecutable() {}

SourceFile *getSourceFile(CompilerInstance &Instance,
                          StringRef InputFileName,
                          const char *MainExecutablePath) {
  CompilerInvocation Invocation;
  Invocation.getLangOptions().BuildSyntaxTree = true;
  Invocation.getLangOptions().VerifySyntaxTree = options::VerifySyntaxTree;
  Invocation.getFrontendOptions().InputsAndOutputs.addInputFile(InputFileName);
  Invocation.setMainExecutablePath(
    llvm::sys::fs::getMainExecutable(MainExecutablePath,
      reinterpret_cast<void *>(&anchorForGetMainExecutable)));

  Invocation.setModuleName("Test");
  PrintingDiagnosticConsumer DiagPrinter;
  Instance.addDiagnosticConsumer(&DiagPrinter);
  if (Instance.setup(Invocation)) {
    return nullptr;
  }

  // First, parse the file normally and get the regular old AST.
  Instance.performParseOnly();

  SourceFile *SF = nullptr;
  for (auto Unit : Instance.getMainModule()->getFiles()) {
    SF = dyn_cast<SourceFile>(Unit);
    if (SF != nullptr) {
      break;
    }
  }
  assert(SF && "No source file");
  return SF;
}

int doFullLexRoundTrip(const StringRef InputFilename) {
  LangOptions LangOpts;
  SourceManager SourceMgr;
  DiagnosticEngine Diags(SourceMgr);
  PrintingDiagnosticConsumer DiagPrinter;
  Diags.addConsumer(DiagPrinter);

  std::vector<std::pair<RC<syntax::RawSyntax>,
                                   syntax::AbsolutePosition>> Tokens;
  if (getTokensFromFile(InputFilename, LangOpts, SourceMgr,
                        Diags, Tokens) == EXIT_FAILURE) {
    return EXIT_FAILURE;
  }

  for (auto TokAndPos : Tokens) {
    TokAndPos.first->print(llvm::outs(), {});
  }

  return EXIT_SUCCESS;
}

int doDumpRawTokenSyntax(const StringRef InputFilename) {
  LangOptions LangOpts;
  SourceManager SourceMgr;
  DiagnosticEngine Diags(SourceMgr);
  PrintingDiagnosticConsumer DiagPrinter;
  Diags.addConsumer(DiagPrinter);

  std::vector<std::pair<RC<syntax::RawSyntax>,
                        syntax::AbsolutePosition>> Tokens;
  if (getTokensFromFile(InputFilename, LangOpts, SourceMgr,
                        Diags, Tokens) == EXIT_FAILURE) {
    return EXIT_FAILURE;
  }

  for (auto TokAndPos : Tokens) {
    TokAndPos.second.printLineAndColumn(llvm::outs());
    llvm::outs() << "\n";
    TokAndPos.first->dump(llvm::outs());
    llvm::outs() << "\n";
  }

  return EXIT_SUCCESS;
}

int doFullParseRoundTrip(const char *MainExecutablePath,
                         const StringRef InputFileName) {
  CompilerInstance Instance;
  SourceFile *SF = getSourceFile(Instance, InputFileName, MainExecutablePath);
  SF->getSyntaxRoot().print(llvm::outs(), {});
  return EXIT_SUCCESS;
}

int doSerializeRawTree(const char *MainExecutablePath,
                       const StringRef InputFileName) {
  CompilerInstance Instance;
  SourceFile *SF = getSourceFile(Instance, InputFileName, MainExecutablePath);

  auto Root = SF->getSyntaxRoot().getRaw();
  swift::json::Output out(llvm::outs());
  out << *Root;
  llvm::outs() << "\n";

  return EXIT_SUCCESS;
}

int doDeserializeRawTree(const char *MainExecutablePath,
                         const StringRef InputFileName,
                         const StringRef OutputFileName) {

  auto Buffer = llvm::MemoryBuffer::getFile(InputFileName);
  std::error_code errorCode;
  auto os = llvm::make_unique<llvm::raw_fd_ostream>(
              OutputFileName, errorCode, llvm::sys::fs::F_None);
  swift::json::SyntaxDeserializer deserializer(llvm::MemoryBufferRef(*(Buffer.get())));
  swift::SyntaxPrintOptions opt;
  deserializer.getSourceFileSyntax()->print(*os);
  return EXIT_SUCCESS;
}

int doParseOnly(const char *MainExecutablePath,
                  const StringRef InputFileName) {
  CompilerInstance Instance;
  SourceFile *SF = getSourceFile(Instance, InputFileName, MainExecutablePath);
  return SF ? EXIT_SUCCESS : EXIT_FAILURE;
}

int dumpParserGen(const char *MainExecutablePath,
                  const StringRef InputFileName) {
  CompilerInstance Instance;
  SourceFile *SF = getSourceFile(Instance, InputFileName, MainExecutablePath);
  SyntaxPrintOptions Opts;
  Opts.PrintSyntaxKind = options::PrintNodeKind;
  Opts.Visual = options::Visual;
  Opts.PrintTrivialNodeKind = options::PrintTrivialNodeKind;
  SF->getSyntaxRoot().print(llvm::outs(), Opts);
  return 0;
}

int dumpEOFSourceLoc(const char *MainExecutablePath,
                     const StringRef InputFileName) {
  CompilerInstance Instance;
  SourceFile *SF = getSourceFile(Instance, InputFileName, MainExecutablePath);
  auto BufferId = *SF->getBufferID();
  SyntaxPrintOptions Opts;
  auto Root = SF->getSyntaxRoot();
  auto AbPos = Root.getEOFToken().getAbsolutePosition();

  SourceManager &SourceMgr = SF->getASTContext().SourceMgr;
  auto StartLoc = SourceMgr.getLocForBufferStart(BufferId);
  auto EndLoc = SourceMgr.getLocForOffset(BufferId, AbPos.getOffset());

  // To ensure the correctness of position when translated to line & column pair.
  if (SourceMgr.getLineAndColumn(EndLoc) != AbPos.getLineAndColumn()) {
    llvm::outs() << "locations should be identical";
    return EXIT_FAILURE;
  }
  llvm::outs() << CharSourceRange(SourceMgr, StartLoc, EndLoc).str();
  return 0;
}
}// end of anonymous namespace

int invokeCommand(const char *MainExecutablePath,
                  const StringRef InputSourceFilename) {
  int ExitCode = EXIT_SUCCESS;

  switch (options::Action) {
    case ActionType::DumpRawTokenSyntax:
      ExitCode = doDumpRawTokenSyntax(InputSourceFilename);
      break;
    case ActionType::FullLexRoundTrip:
      ExitCode = doFullLexRoundTrip(InputSourceFilename);
      break;
    case ActionType::FullParseRoundTrip:
      ExitCode = doFullParseRoundTrip(MainExecutablePath, InputSourceFilename);
      break;
    case ActionType::SerializeRawTree:
      ExitCode = doSerializeRawTree(MainExecutablePath, InputSourceFilename);
      break;
    case ActionType::DeserializeRawTree:
      ExitCode = doDeserializeRawTree(MainExecutablePath, InputSourceFilename,
                                      options::OutputFilename);
      break;
    case ActionType::ParseOnly:
      ExitCode = doParseOnly(MainExecutablePath, InputSourceFilename);
      break;
    case ActionType::ParserGen:
      ExitCode = dumpParserGen(MainExecutablePath, InputSourceFilename);
      break;
    case ActionType::EOFPos:
      ExitCode = dumpEOFSourceLoc(MainExecutablePath, InputSourceFilename);
      break;
    case ActionType::None:
      llvm::errs() << "an action is required\n";
      llvm::cl::PrintHelpMessage();
      ExitCode = EXIT_FAILURE;
      break;
  }

  return ExitCode;
}

int main(int argc, char *argv[]) {
  PROGRAM_START(argc, argv);
  llvm::cl::ParseCommandLineOptions(argc, argv, "Swift Syntax Test\n");

  int ExitCode = EXIT_SUCCESS;

  if (options::InputSourceFilename.empty() &&
      options::InputSourceDirectory.empty()) {
    llvm::errs() << "input source file is required\n";
    ExitCode = EXIT_FAILURE;
  }

  if (!options::InputSourceFilename.empty() &&
      !options::InputSourceDirectory.empty()) {
    llvm::errs() << "input-source-filename and input-source-directory cannot "
                    "be used together\n\n";
    ExitCode = EXIT_FAILURE;
  }

  if (options::Action == ActionType::None) {
    llvm::errs() << "an action is required\n";
    ExitCode = EXIT_FAILURE;
  }

  if (ExitCode == EXIT_FAILURE) {
    llvm::cl::PrintHelpMessage();
    return ExitCode;
  }

  if (!options::InputSourceFilename.empty()) {
    ExitCode = invokeCommand(argv[0], options::InputSourceFilename);
  } else {
    assert(!options::InputSourceDirectory.empty());
    std::error_code errorCode;
    llvm::sys::fs::recursive_directory_iterator DI(options::InputSourceDirectory, errorCode);
    llvm::sys::fs::recursive_directory_iterator endIterator;
    for (; DI != endIterator; DI.increment(errorCode)) {
      auto entry = *DI;
      auto path = entry.path();
      if (!llvm::sys::fs::is_directory(path) &&
          StringRef(path).endswith(".swift")) {
        ExitCode = invokeCommand(argv[0], path);
      }
    }
  }

  return ExitCode;
}
<|endoftext|>


<commit_before>// Licensed GNU LGPL v3 or later: http://www.gnu.org/licenses/lgpl.html
#include "clientapi.hh"

namespace Rapicorn {

uint64          uithread_bootup         (int *argcp, char **argv, const StringVector &args);
static void     clientglue_setup        (Plic::Connection *connection);

static struct __StaticCTorTest { int v; __StaticCTorTest() : v (0x120caca0) { v += 0x300000; } } __staticctortest;

/**
 * Initialize Rapicorn core via init_core(), and then starts a seperately
 * running UI thread. This UI thread initializes all UI related components
 * and the global Application object. After initialization, it enters the
 * main event loop for UI processing.
 * @param app_ident     Identifier for this application, this is used to distinguish
 *                      persistent application resources and window configurations
 *                      from other applications.
 * @param argcp         Pointer to @a argc as passed into main().
 * @param argv          The @a argv argument as passed into main().
 * @param args          Internal initialization arguments, see init_core() for details.
 */
Application_SmartHandle
init_app (const String       &app_ident,
          int                *argcp,
          char              **argv,
          const StringVector &args)
{
  // assert global_ctors work
  if (__staticctortest.v != 0x123caca0)
    fatal ("librapicornui: link error: C++ constructors have not been executed");
  // initialize core
  if (program_ident().empty())
    init_core (app_ident, argcp, argv, args);
  else if (app_ident != program_ident())
    fatal ("librapicornui: application identifier changed during ui initialization");
  // boot up UI thread
  uint64 appid = uithread_bootup (argcp, argv, args);
  assert (appid != 0);
  // initialize clientglue bits
  clientglue_setup (uithread_connection());
  // construct smart handle
  Plic::FieldBuffer8 fb (1);
  fb.add_int64 (appid);
  Plic::FieldReader fbr (fb);
  return Application_SmartHandle (fbr);
}

uint64
server_init_app (const String       &app_ident,
                 int                *argcp,
                 char              **argv,
                 const StringVector &args)
{
  Application_SmartHandle app = init_app (app_ident, argcp, argv, args);
  return app._rpc_id();
}

/**
 * This function calls shutdown_app() first, to properly terminate Rapicorn's
 * concurrently running ui-thread, and then terminates the program via
 * exit(3posix). This function does not return.
 * @param status        The exit status returned to the parent process.
 */
void
exit (int status)
{
  exit (shutdown_app (status));
}

} // Rapicorn

namespace { // Anon
static Plic::Connection *_clientglue_connection = NULL;
};
#define PLIC_CONNECTION()       (*_clientglue_connection)

#include "clientapi.cc"

#include <rcore/testutils.hh>
namespace Rapicorn {
void
init_test_app (const String       &app_ident,
               int                *argcp,
               char              **argv,
               const StringVector &args)
{
  init_core_test (app_ident, argcp, argv, args);
  init_app (app_ident, argcp, argv, args);
}

static void
clientglue_setup (Plic::Connection *connection)
{
  return_if_fail (_clientglue_connection == NULL);
  _clientglue_connection = connection;
}

} // Rapicorn
<commit_msg>UI: started client connection implementation<commit_after>// Licensed GNU LGPL v3 or later: http://www.gnu.org/licenses/lgpl.html
#include "clientapi.hh"

namespace Rapicorn {

uint64          uithread_bootup         (int *argcp, char **argv, const StringVector &args);
static void     clientglue_setup        (Plic::Connection *connection);

static struct __StaticCTorTest { int v; __StaticCTorTest() : v (0x120caca0) { v += 0x300000; } } __staticctortest;

/**
 * Initialize Rapicorn core via init_core(), and then starts a seperately
 * running UI thread. This UI thread initializes all UI related components
 * and the global Application object. After initialization, it enters the
 * main event loop for UI processing.
 * @param app_ident     Identifier for this application, this is used to distinguish
 *                      persistent application resources and window configurations
 *                      from other applications.
 * @param argcp         Pointer to @a argc as passed into main().
 * @param argv          The @a argv argument as passed into main().
 * @param args          Internal initialization arguments, see init_core() for details.
 */
Application_SmartHandle
init_app (const String       &app_ident,
          int                *argcp,
          char              **argv,
          const StringVector &args)
{
  // assert global_ctors work
  if (__staticctortest.v != 0x123caca0)
    fatal ("librapicornui: link error: C++ constructors have not been executed");
  // initialize core
  if (program_ident().empty())
    init_core (app_ident, argcp, argv, args);
  else if (app_ident != program_ident())
    fatal ("librapicornui: application identifier changed during ui initialization");
  // boot up UI thread
  uint64 appid = uithread_bootup (argcp, argv, args);
  assert (appid != 0);
  // initialize clientglue bits
  clientglue_setup (uithread_connection());
  // construct smart handle
  Plic::FieldBuffer8 fb (1);
  fb.add_int64 (appid);
  Plic::FieldReader fbr (fb);
  return Application_SmartHandle::_new (fbr);
}

uint64
server_init_app (const String       &app_ident,
                 int                *argcp,
                 char              **argv,
                 const StringVector &args)
{
  Application_SmartHandle app = init_app (app_ident, argcp, argv, args);
  return app._rpc_id();
}

/**
 * This function calls shutdown_app() first, to properly terminate Rapicorn's
 * concurrently running ui-thread, and then terminates the program via
 * exit(3posix). This function does not return.
 * @param status        The exit status returned to the parent process.
 */
void
exit (int status)
{
  exit (shutdown_app (status));
}

} // Rapicorn

// === clientapi.cc helpers ===
namespace { // Anon
static Plic::Connection *_clientglue_connection = NULL;
class ClientConnection {
  // this should one day be linked with the server side connection and implement Plic::Connection itself
  typedef std::map <Plic::uint64, Plic::NonCopyable*> ContextMap;
  ContextMap context_map;
public:
  Plic::NonCopyable*
  find_context (Plic::uint64 ipcid)
  {
    ContextMap::iterator it = context_map.find (ipcid);
    return LIKELY (it != context_map.end()) ? it->second : NULL;
  }
  void
  add_context (Plic::uint64 ipcid, Plic::NonCopyable *ctx)
  {
    context_map[ipcid] = ctx;
  }
};
static __thread ClientConnection *ccon = NULL;
static inline void
connection_context4id (Plic::uint64 ipcid, Plic::NonCopyable *ctx)
{
  if (!ccon)
    {
      assert (_clientglue_connection != NULL);
      ccon = new ClientConnection();
    }
  ccon->add_context (ipcid, ctx);
}
template<class Context> static inline Context*
connection_id2context (Plic::uint64 ipcid)
{
  Plic::NonCopyable *ctx = LIKELY (ccon) ? ccon->find_context (ipcid) : NULL;
  if (UNLIKELY (!ctx))
    ctx = new Context (ipcid);
  return static_cast<Context*> (ctx);
}
static inline Plic::uint64
connection_handle2id (const Plic::SmartHandle &h)
{
  return h._rpc_id();
}

#define PLIC_CONNECTION()       (*_clientglue_connection)
} // Anon
#include "clientapi.cc"

#include <rcore/testutils.hh>
namespace Rapicorn {
void
init_test_app (const String       &app_ident,
               int                *argcp,
               char              **argv,
               const StringVector &args)
{
  init_core_test (app_ident, argcp, argv, args);
  init_app (app_ident, argcp, argv, args);
}

static void
clientglue_setup (Plic::Connection *connection)
{
  return_if_fail (_clientglue_connection == NULL);
  _clientglue_connection = connection;
}

} // Rapicorn
<|endoftext|>


<commit_before>/* Rapicorn
 * Copyright (C) 2006 Tim Janik
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * A copy of the GNU Lesser General Public License should ship along
 * with this library; if not, see http://www.gnu.org/copyleft/.
 */
#include "paintitems.hh"
#include "itemimpl.hh"
#include "factory.hh"
#include "painter.hh"

namespace Rapicorn {

static DataKey<SizePolicyType> size_policy_key;

const PropertyList&
Arrow::list_properties()
{
  static Property *properties[] = {
    MakeProperty (Arrow, arrow_dir,   _("Arrow Direction"), _("The direction the arrow points to"), "rw"),
    MakeProperty (Arrow, size_policy, _("Size Policy"),     _("Policy which determines coupling of width and height"), "rw"),
  };
  static const PropertyList property_list (properties, Item::list_properties());
  return property_list;
}

class ArrowImpl : public virtual ItemImpl, public virtual Arrow {
  DirType m_dir;
public:
  explicit ArrowImpl() :
    m_dir (DIR_RIGHT)
  {}
  ~ArrowImpl()
  {}
  virtual void    arrow_dir (DirType dir)       { m_dir = dir; expose(); }
  virtual DirType arrow_dir () const            { return m_dir; }
  virtual void
  size_policy (SizePolicyType spol)
  {
    if (!spol)
      delete_data (&size_policy_key);
    else
      set_data (&size_policy_key, spol);
  }
  virtual SizePolicyType
  size_policy () const
  {
    SizePolicyType spol = get_data (&size_policy_key);
    return spol;
  }
protected:
  virtual void
  size_request (Requisition &requisition)
  {
    requisition.width = 3;
    requisition.height = 3;
  }
  virtual void
  size_allocate (Allocation area)
  {
    allocation (area);
    SizePolicyType spol = size_policy();
    if (spol == SIZE_POLICY_WIDTH_FROM_HEIGHT)
      tune_requisition (area.height, -1);
    else if (spol == SIZE_POLICY_HEIGHT_FROM_WIDTH)
      tune_requisition (-1, area.width);
  }
  virtual void
  render (Display &display)
  {
    IRect ia = allocation();
    int x = ia.x, y = ia.y, width = ia.width, height = ia.height;
    if (width >= 2 && height >= 2)
      {
        Plane &plane = display.create_plane();
        Painter painter (plane);
        painter.draw_dir_arrow (x, y, width, height, foreground(), m_dir);
      }
  }
};
static const ItemFactory<ArrowImpl> arrow_factory ("Rapicorn::Factory::Arrow");

void
DotGrid::dot_type (FrameType ft)
{
  normal_dot (ft);
  impressed_dot (ft);
}

const PropertyList&
DotGrid::list_properties()
{
  static Property *properties[] = {
    MakeProperty (DotGrid, normal_dot, _("Normal Dot"), _("The kind of dot-frame to draw in normal state"), "rw"),
    MakeProperty (DotGrid, impressed_dot, _("Impresed Dot"), _("The kind of dot-frame to draw in impressed state"), "rw"),
    MakeProperty (DotGrid, dot_type, _("Dot Type"), _("The kind of dot-frame to draw in all states"), "w"),
    MakeProperty (DotGrid, n_hdots, _("H-Dot #"), _("The number of horizontal dots to be drawn"), 0u, 99999u, 3u, "rw"),
    MakeProperty (DotGrid, n_vdots, _("V-Dot #"), _("The number of vertical dots to be drawn"), 0u, 99999u, 3u, "rw"),
    MakeProperty (DotGrid, right_padding_dots, _("Right Padding Dots"), _("Amount of padding in dots to add at the child's right side"), 0, 65535, 3, "rw"),
    MakeProperty (DotGrid, top_padding_dots, _("Top Padding Dots"), _("Amount of padding in dots to add at the child's top side"), 0, 65535, 3, "rw"),
    MakeProperty (DotGrid, left_padding_dots, _("Left Padding Dots"), _("Amount of padding in dots to add at the child's left side"), 0, 65535, 3, "rw"),
    MakeProperty (DotGrid, bottom_padding_dots, _("Bottom Padding Dots"), _("Amount of padding in dots to add at the child's bottom side"), 0, 65535, 3, "rw"),
  };
  static const PropertyList property_list (properties, Item::list_properties());
  return property_list;
}

class DotGridImpl : public virtual ItemImpl, public virtual DotGrid {
  FrameType m_normal_dot, m_impressed_dot;
  uint      m_n_hdots, m_n_vdots;
  uint16    m_right_padding_dots, m_top_padding_dots, m_left_padding_dots, m_bottom_padding_dots;
public:
  explicit DotGridImpl() :
    m_normal_dot (FRAME_IN),
    m_impressed_dot (FRAME_IN),
    m_n_hdots (1), m_n_vdots (1),
    m_right_padding_dots (0), m_top_padding_dots (0),
    m_left_padding_dots (0), m_bottom_padding_dots (0)
  {}
  ~DotGridImpl()
  {}
  virtual void      impressed_dot (FrameType ft)        { m_impressed_dot = ft; expose(); }
  virtual FrameType impressed_dot () const              { return m_impressed_dot; }
  virtual void      normal_dot    (FrameType ft)        { m_normal_dot = ft; expose(); }
  virtual FrameType normal_dot    () const              { return m_normal_dot; }
  FrameType         current_dot   () const              { return branch_impressed() ? impressed_dot() : normal_dot(); }
  virtual void      n_hdots       (uint   num)          { m_n_hdots = num; expose(); }
  virtual uint      n_hdots       () const              { return m_n_hdots; }
  virtual void      n_vdots       (uint   num)          { m_n_vdots = num; expose(); }
  virtual uint      n_vdots       () const              { return m_n_vdots; }
  virtual uint      right_padding_dots () const         { return m_right_padding_dots; }
  virtual void      right_padding_dots (uint c)         { m_right_padding_dots = c; expose(); }
  virtual uint      top_padding_dots  () const          { return m_top_padding_dots; }
  virtual void      top_padding_dots  (uint c)          { m_top_padding_dots = c; expose(); }
  virtual uint      left_padding_dots  () const         { return m_left_padding_dots; }
  virtual void      left_padding_dots  (uint c)         { m_left_padding_dots = c; expose(); }
  virtual uint      bottom_padding_dots  () const       { return m_bottom_padding_dots; }
  virtual void      bottom_padding_dots  (uint c)       { m_bottom_padding_dots = c; expose(); }
  virtual void
  size_request (Requisition &requisition)
  {
    uint ythick = 1, xthick = 1;
    requisition.width = m_n_hdots * (xthick + xthick) + MAX (m_n_hdots - 1, 0) * xthick;
    requisition.height = m_n_vdots * (ythick + ythick) + MAX (m_n_vdots - 1, 0) * ythick;
    requisition.width += (m_right_padding_dots + m_left_padding_dots) * 3 * xthick;
    requisition.height += (m_top_padding_dots + m_bottom_padding_dots) * 3 * ythick;
  }
  virtual void
  size_allocate (Allocation area)
  {
    allocation (area);
  }
  virtual void
  render (Display &display)
  {
    int ythick = 1, xthick = 1, n_hdots = m_n_hdots, n_vdots = m_n_vdots;
    IRect ia = allocation();
    int x = ia.x, y = ia.y, width = ia.width, height = ia.height;
    int rq_width = m_n_hdots * (xthick + xthick) + MAX (n_hdots - 1, 0) * xthick;
    int rq_height = m_n_vdots * (ythick + ythick) + MAX (n_vdots - 1, 0) * ythick;
    /* split up extra width */
    uint hpadding = m_right_padding_dots + m_left_padding_dots;
    double halign = hpadding ? m_left_padding_dots * 1.0 / hpadding : 0.5;
    if (rq_width < width)
      x += ifloor ((width - rq_width) * halign);
    /* split up extra height */
    uint vpadding = m_top_padding_dots + m_bottom_padding_dots;
    double valign = vpadding ? m_bottom_padding_dots * 1.0 / vpadding : 0.5;
    if (rq_height < height)
      y += ifloor ((height - rq_height) * valign);
    /* draw dots */
    if (width >= 2 * xthick && height >= 2 * ythick && n_hdots && n_vdots)
      {
        /* limit n_hdots */
        if (rq_width > width)
          {
            int w = width - 2 * xthick;         /* dot1 */
            n_hdots = 1 + w / (3 * xthick);
          }
        /* limit n_vdots */
        if (rq_height > height)
          {
            int h = height - 2 * ythick;        /* dot1 */
            n_vdots = 1 + h / (3 * ythick);
          }
        Color color = 0x80000000;
        Plane &plane = display.create_plane();
        Painter rp (plane);
        for (int j = 0; j < n_vdots; j++)
          {
            int xtmp = 0;
            for (int i = 0; i < n_hdots; i++)
              {
                rp.draw_shaded_rect (x + xtmp, y + 2 * ythick - 1, dark_shadow(),
                                     x + xtmp + 2 * xthick - 1, y, light_glint());
                xtmp += 3 * xthick;
              }
            y += 3 * ythick;
          }
      }
  }
};
static const ItemFactory<DotGridImpl> dot_grid_factory ("Rapicorn::Factory::DotGrid");

/* --- DrawableImpl --- */
Drawable::Drawable() :
  sig_draw (*this, &Drawable::draw)
{}

class DrawableImpl : public virtual ItemImpl, public virtual Drawable {
public:
  virtual void
  size_request (Requisition &requisition)
  {
    requisition.width = 320;
    requisition.height = 200;
  }
  virtual void
  size_allocate (Allocation area)
  {
    allocation (area);
  }
  virtual void
  render (Display &display)
  {
    sig_draw.emit (display);
  }
  virtual void
  draw (Display &display)
  {}
};
static const ItemFactory<DrawableImpl> drawable_factory ("Rapicorn::Factory::Drawable");

} // Rapicorn
<commit_msg>UI: use cairo to paint arrows<commit_after>/* Rapicorn
 * Copyright (C) 2006 Tim Janik
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * A copy of the GNU Lesser General Public License should ship along
 * with this library; if not, see http://www.gnu.org/copyleft/.
 */
#include "paintitems.hh"
#include "itemimpl.hh"
#include "factory.hh"
#include "painter.hh"

namespace Rapicorn {

static DataKey<SizePolicyType> size_policy_key;

const PropertyList&
Arrow::list_properties()
{
  static Property *properties[] = {
    MakeProperty (Arrow, arrow_dir,   _("Arrow Direction"), _("The direction the arrow points to"), "rw"),
    MakeProperty (Arrow, size_policy, _("Size Policy"),     _("Policy which determines coupling of width and height"), "rw"),
  };
  static const PropertyList property_list (properties, Item::list_properties());
  return property_list;
}

class ArrowImpl : public virtual ItemImpl, public virtual Arrow {
  DirType m_dir;
public:
  explicit ArrowImpl() :
    m_dir (DIR_RIGHT)
  {}
  ~ArrowImpl()
  {}
  virtual void    arrow_dir (DirType dir)       { m_dir = dir; expose(); }
  virtual DirType arrow_dir () const            { return m_dir; }
  virtual void
  size_policy (SizePolicyType spol)
  {
    if (!spol)
      delete_data (&size_policy_key);
    else
      set_data (&size_policy_key, spol);
  }
  virtual SizePolicyType
  size_policy () const
  {
    SizePolicyType spol = get_data (&size_policy_key);
    return spol;
  }
protected:
  virtual void
  size_request (Requisition &requisition)
  {
    requisition.width = 3;
    requisition.height = 3;
  }
  virtual void
  size_allocate (Allocation area)
  {
    allocation (area);
    SizePolicyType spol = size_policy();
    if (spol == SIZE_POLICY_WIDTH_FROM_HEIGHT)
      tune_requisition (area.height, -1);
    else if (spol == SIZE_POLICY_HEIGHT_FROM_WIDTH)
      tune_requisition (-1, area.width);
  }
  virtual void
  render (Display &display)
  {
    IRect ia = allocation();
    int x = ia.x, y = ia.y, width = ia.width, height = ia.height;
    if (width >= 2 && height >= 2)
      {
        cairo_t *cairo = display.create_cairo();
        CPainter painter (cairo);
        painter.draw_dir_arrow (x, y, width, height, foreground(), m_dir);
      }
  }
};
static const ItemFactory<ArrowImpl> arrow_factory ("Rapicorn::Factory::Arrow");

void
DotGrid::dot_type (FrameType ft)
{
  normal_dot (ft);
  impressed_dot (ft);
}

const PropertyList&
DotGrid::list_properties()
{
  static Property *properties[] = {
    MakeProperty (DotGrid, normal_dot, _("Normal Dot"), _("The kind of dot-frame to draw in normal state"), "rw"),
    MakeProperty (DotGrid, impressed_dot, _("Impresed Dot"), _("The kind of dot-frame to draw in impressed state"), "rw"),
    MakeProperty (DotGrid, dot_type, _("Dot Type"), _("The kind of dot-frame to draw in all states"), "w"),
    MakeProperty (DotGrid, n_hdots, _("H-Dot #"), _("The number of horizontal dots to be drawn"), 0u, 99999u, 3u, "rw"),
    MakeProperty (DotGrid, n_vdots, _("V-Dot #"), _("The number of vertical dots to be drawn"), 0u, 99999u, 3u, "rw"),
    MakeProperty (DotGrid, right_padding_dots, _("Right Padding Dots"), _("Amount of padding in dots to add at the child's right side"), 0, 65535, 3, "rw"),
    MakeProperty (DotGrid, top_padding_dots, _("Top Padding Dots"), _("Amount of padding in dots to add at the child's top side"), 0, 65535, 3, "rw"),
    MakeProperty (DotGrid, left_padding_dots, _("Left Padding Dots"), _("Amount of padding in dots to add at the child's left side"), 0, 65535, 3, "rw"),
    MakeProperty (DotGrid, bottom_padding_dots, _("Bottom Padding Dots"), _("Amount of padding in dots to add at the child's bottom side"), 0, 65535, 3, "rw"),
  };
  static const PropertyList property_list (properties, Item::list_properties());
  return property_list;
}

class DotGridImpl : public virtual ItemImpl, public virtual DotGrid {
  FrameType m_normal_dot, m_impressed_dot;
  uint      m_n_hdots, m_n_vdots;
  uint16    m_right_padding_dots, m_top_padding_dots, m_left_padding_dots, m_bottom_padding_dots;
public:
  explicit DotGridImpl() :
    m_normal_dot (FRAME_IN),
    m_impressed_dot (FRAME_IN),
    m_n_hdots (1), m_n_vdots (1),
    m_right_padding_dots (0), m_top_padding_dots (0),
    m_left_padding_dots (0), m_bottom_padding_dots (0)
  {}
  ~DotGridImpl()
  {}
  virtual void      impressed_dot (FrameType ft)        { m_impressed_dot = ft; expose(); }
  virtual FrameType impressed_dot () const              { return m_impressed_dot; }
  virtual void      normal_dot    (FrameType ft)        { m_normal_dot = ft; expose(); }
  virtual FrameType normal_dot    () const              { return m_normal_dot; }
  FrameType         current_dot   () const              { return branch_impressed() ? impressed_dot() : normal_dot(); }
  virtual void      n_hdots       (uint   num)          { m_n_hdots = num; expose(); }
  virtual uint      n_hdots       () const              { return m_n_hdots; }
  virtual void      n_vdots       (uint   num)          { m_n_vdots = num; expose(); }
  virtual uint      n_vdots       () const              { return m_n_vdots; }
  virtual uint      right_padding_dots () const         { return m_right_padding_dots; }
  virtual void      right_padding_dots (uint c)         { m_right_padding_dots = c; expose(); }
  virtual uint      top_padding_dots  () const          { return m_top_padding_dots; }
  virtual void      top_padding_dots  (uint c)          { m_top_padding_dots = c; expose(); }
  virtual uint      left_padding_dots  () const         { return m_left_padding_dots; }
  virtual void      left_padding_dots  (uint c)         { m_left_padding_dots = c; expose(); }
  virtual uint      bottom_padding_dots  () const       { return m_bottom_padding_dots; }
  virtual void      bottom_padding_dots  (uint c)       { m_bottom_padding_dots = c; expose(); }
  virtual void
  size_request (Requisition &requisition)
  {
    uint ythick = 1, xthick = 1;
    requisition.width = m_n_hdots * (xthick + xthick) + MAX (m_n_hdots - 1, 0) * xthick;
    requisition.height = m_n_vdots * (ythick + ythick) + MAX (m_n_vdots - 1, 0) * ythick;
    requisition.width += (m_right_padding_dots + m_left_padding_dots) * 3 * xthick;
    requisition.height += (m_top_padding_dots + m_bottom_padding_dots) * 3 * ythick;
  }
  virtual void
  size_allocate (Allocation area)
  {
    allocation (area);
  }
  virtual void
  render (Display &display)
  {
    int ythick = 1, xthick = 1, n_hdots = m_n_hdots, n_vdots = m_n_vdots;
    IRect ia = allocation();
    int x = ia.x, y = ia.y, width = ia.width, height = ia.height;
    int rq_width = m_n_hdots * (xthick + xthick) + MAX (n_hdots - 1, 0) * xthick;
    int rq_height = m_n_vdots * (ythick + ythick) + MAX (n_vdots - 1, 0) * ythick;
    /* split up extra width */
    uint hpadding = m_right_padding_dots + m_left_padding_dots;
    double halign = hpadding ? m_left_padding_dots * 1.0 / hpadding : 0.5;
    if (rq_width < width)
      x += ifloor ((width - rq_width) * halign);
    /* split up extra height */
    uint vpadding = m_top_padding_dots + m_bottom_padding_dots;
    double valign = vpadding ? m_bottom_padding_dots * 1.0 / vpadding : 0.5;
    if (rq_height < height)
      y += ifloor ((height - rq_height) * valign);
    /* draw dots */
    if (width >= 2 * xthick && height >= 2 * ythick && n_hdots && n_vdots)
      {
        /* limit n_hdots */
        if (rq_width > width)
          {
            int w = width - 2 * xthick;         /* dot1 */
            n_hdots = 1 + w / (3 * xthick);
          }
        /* limit n_vdots */
        if (rq_height > height)
          {
            int h = height - 2 * ythick;        /* dot1 */
            n_vdots = 1 + h / (3 * ythick);
          }
        Color color = 0x80000000;
        Plane &plane = display.create_plane();
        Painter rp (plane);
        for (int j = 0; j < n_vdots; j++)
          {
            int xtmp = 0;
            for (int i = 0; i < n_hdots; i++)
              {
                rp.draw_shaded_rect (x + xtmp, y + 2 * ythick - 1, dark_shadow(),
                                     x + xtmp + 2 * xthick - 1, y, light_glint());
                xtmp += 3 * xthick;
              }
            y += 3 * ythick;
          }
      }
  }
};
static const ItemFactory<DotGridImpl> dot_grid_factory ("Rapicorn::Factory::DotGrid");

/* --- DrawableImpl --- */
Drawable::Drawable() :
  sig_draw (*this, &Drawable::draw)
{}

class DrawableImpl : public virtual ItemImpl, public virtual Drawable {
public:
  virtual void
  size_request (Requisition &requisition)
  {
    requisition.width = 320;
    requisition.height = 200;
  }
  virtual void
  size_allocate (Allocation area)
  {
    allocation (area);
  }
  virtual void
  render (Display &display)
  {
    sig_draw.emit (display);
  }
  virtual void
  draw (Display &display)
  {}
};
static const ItemFactory<DrawableImpl> drawable_factory ("Rapicorn::Factory::Drawable");

} // Rapicorn
<|endoftext|>


<commit_before>////////////////////////////////////////////////////////////////////////////////
/// @brief vocbase manager
///
/// @file
///
/// DISCLAIMER
///
/// Copyright 2004-2013 triAGENS GmbH, Cologne, Germany
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///
///     http://www.apache.org/licenses/LICENSE-2.0
///
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
///
/// Copyright holder is triAGENS GmbH, Cologne, Germany
///
/// @author Dr. Frank Celler
/// @author Copyright 2011-2013, triAGENS GmbH, Cologne, Germany
////////////////////////////////////////////////////////////////////////////////

#include "RestServer/VocbaseManager.h"

#include "build.h"

#include "Logger/Logger.h"
#include "Rest/ConnectionInfo.h"
#include "Basics/StringUtils.h"
#include "RestServer/VocbaseContext.h"
#include "BasicsC/tri-strings.h"
#include "VocBase/auth.h"
#include "Actions/actions.h"

#include "HttpServer/ApplicationEndpointServer.h"
#include "V8/JSLoader.h"
#include "V8/v8-conv.h"
#include "V8/v8-globals.h"
#include "V8/v8-utils.h"

using namespace std;
using namespace triagens::basics;
using namespace triagens::arango;
using namespace triagens::rest;

// -----------------------------------------------------------------------------
// --SECTION--                                                            static
// -----------------------------------------------------------------------------

////////////////////////////////////////////////////////////////////////////////
/// @brief the global manager
////////////////////////////////////////////////////////////////////////////////

VocbaseManager VocbaseManager::manager;

////////////////////////////////////////////////////////////////////////////////
/// @brief add the context to a request
////////////////////////////////////////////////////////////////////////////////

bool VocbaseManager::setRequestContext(triagens::rest::HttpRequest* request) {
  TRI_vocbase_t* vb = VocbaseManager::manager.lookupVocbaseByHttpRequest(request);

  triagens::arango::VocbaseContext* vc = new triagens::arango::VocbaseContext(request, &VocbaseManager::manager);

  vc->setVocbase(vb);

  request->addRequestContext(vc);

  return true;
}

// -----------------------------------------------------------------------------
// --SECTION--                                                            public
// -----------------------------------------------------------------------------

////////////////////////////////////////////////////////////////////////////////
/// @addtogroup ArangoDB
/// @{
////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////
/// @brief add system vocbase
////////////////////////////////////////////////////////////////////////////////

void VocbaseManager::addSystemVocbase (TRI_vocbase_t* vocbase) {
  WRITE_LOCKER(_rwLock);
  _vocbase = vocbase;
  std::map<std::string, std::string> m;
  _authCache[vocbase] = m;
}

////////////////////////////////////////////////////////////////////////////////
/// @brief add user vocbase
////////////////////////////////////////////////////////////////////////////////

void VocbaseManager::addUserVocbase (TRI_vocbase_t* vocbase) {
  {
    WRITE_LOCKER(_rwLock);
    _vocbases[vocbase->_name] = vocbase;
    std::map<std::string, std::string> m;
    _authCache[vocbase] = m;
  }

  if (true) { //(vocbase->_needAuth) {
    TRI_ReloadAuthInfo(vocbase);
  }
}

////////////////////////////////////////////////////////////////////////////////
/// @brief close user vocbases
////////////////////////////////////////////////////////////////////////////////

void VocbaseManager::closeUserVocbases () {
  WRITE_LOCKER(_rwLock);

  std::map<std::string, TRI_vocbase_t*>::iterator i = _vocbases.begin();
  for (; i != _vocbases.end(); ++i) {
    TRI_vocbase_t* vocbase = i->second;
    TRI_DestroyVocBase(vocbase);
    TRI_Free(TRI_UNKNOWN_MEM_ZONE, vocbase);
  }

  _vocbases.clear();
}

////////////////////////////////////////////////////////////////////////////////
/// @brief look vocbase by name
////////////////////////////////////////////////////////////////////////////////

TRI_vocbase_t* VocbaseManager::lookupVocbaseByName (string const& name) {
  if (name == "_system") {
    return _vocbase;
  }

  READ_LOCKER(_rwLock);
  map<string, TRI_vocbase_s*>::iterator find = _vocbases.find(name);
  if (find != _vocbases.end()) {
    return find->second;
  }

  return 0;
}

////////////////////////////////////////////////////////////////////////////////
/// @brief check if name and path is not used
////////////////////////////////////////////////////////////////////////////////

bool VocbaseManager::canAddVocbase (std::string const& name, std::string const& path) {
  // loop over all vocbases and check name and path

  READ_LOCKER(_rwLock);

  // system vocbase
  if (name == string(_vocbase->_name)) {
    return false;
  }
  if (path == string(_vocbase->_path)) {
    return false;
  }

  // user vocbases
  std::map<std::string, TRI_vocbase_t*>::iterator i = _vocbases.begin();
  for (; i != _vocbases.end(); ++i) {
    TRI_vocbase_t* vocbase = i->second;
    if (name == string(vocbase->_name)) {
      return false;
    }
    if (path == string(vocbase->_path)) {
      return false;
    }
  }

  return true;
}

////////////////////////////////////////////////////////////////////////////////
/// @brief run version check
/// @return bool             returns false if the version check fails
////////////////////////////////////////////////////////////////////////////////

bool VocbaseManager::runVersionCheck (TRI_vocbase_t* vocbase, v8::Handle<v8::Context> context) {
  if (! _startupLoader) {
    LOGGER_ERROR("Javascript start up loader not found.");
    return false;
  }

  v8::HandleScope scope;
  TRI_v8_global_t* v8g = (TRI_v8_global_t*) v8::Isolate::GetCurrent()->GetData();
  TRI_vocbase_t* orig = (TRI_vocbase_t*) v8g->_vocbase;
  v8g->_vocbase = vocbase;

  v8::Handle<v8::Value> result = _startupLoader->executeGlobalScript(context, "server/version-check.js");

  v8g->_vocbase = orig;

  return TRI_ObjectToBoolean(result);
}

////////////////////////////////////////////////////////////////////////////////
/// @brief initialize foxx
////////////////////////////////////////////////////////////////////////////////

void VocbaseManager::initializeFoxx (TRI_vocbase_t* vocbase, v8::Handle<v8::Context> context) {
  TRI_vocbase_t* orig = 0;
  {
    v8::HandleScope scope;
    TRI_v8_global_t* v8g = (TRI_v8_global_t*) v8::Isolate::GetCurrent()->GetData();
    orig = (TRI_vocbase_t*) v8g->_vocbase;
    v8g->_vocbase = vocbase;
  }

  v8::HandleScope scope;
  TRI_ExecuteJavaScriptString(context,
                              v8::String::New("require(\"internal\").initializeFoxx()"),
                              v8::String::New("initialize foxx"),
                              false);
  {
    v8::HandleScope scope;
    TRI_v8_global_t* v8g = (TRI_v8_global_t*) v8::Isolate::GetCurrent()->GetData();
    v8g->_vocbase = orig;
  }
}

////////////////////////////////////////////////////////////////////////////////
/// @brief add an endpoint
////////////////////////////////////////////////////////////////////////////////

bool VocbaseManager::addEndpoint (std::string const& name) {

  if (_endpointServer) {
    return _endpointServer->addEndpoint(name);
  }

  return false;
}

////////////////////////////////////////////////////////////////////////////////
/// @brief look vocbase by http request
////////////////////////////////////////////////////////////////////////////////

TRI_vocbase_t* VocbaseManager::lookupVocbaseByHttpRequest (
                                        triagens::rest::HttpRequest* request) {
  ConnectionInfo ci = request->connectionInfo();

  string prefix = (ci.serverPort > 0)
          ? "tcp://" + triagens::basics::StringUtils::tolower(ci.serverAddress)
          + ":" + basics::StringUtils::itoa(ci.serverPort)
          : "unix:///localhost";

  return lookupVocbaseByPrefix(prefix);
}

////////////////////////////////////////////////////////////////////////////////
/// @brief look vocbase by prefix
////////////////////////////////////////////////////////////////////////////////

TRI_vocbase_t* VocbaseManager::lookupVocbaseByPrefix (
                                                    std::string const& prefix) {
  READ_LOCKER(_rwLock);
  map<string, TRI_vocbase_s*>::iterator find = _prefix2Vocbases.find(prefix);
  if (find != _prefix2Vocbases.end()) {
    return find->second;
  }

  // return default
  return _vocbase;
}

////////////////////////////////////////////////////////////////////////////////
/// @brief add prefix to database mapping
////////////////////////////////////////////////////////////////////////////////

void VocbaseManager::addPrefixMapping (std::string const& prefix,
                                       std::string const& name) {
  TRI_vocbase_t* vocbase = lookupVocbaseByName(name);

  if (vocbase) {
    WRITE_LOCKER(_rwLock);
    _prefix2Vocbases[triagens::basics::StringUtils::tolower(prefix)] = vocbase;
  }

}

////////////////////////////////////////////////////////////////////////////////
/// @brief authenticate a request
////////////////////////////////////////////////////////////////////////////////

bool VocbaseManager::authenticate (TRI_vocbase_t* vocbase,
                                   triagens::rest::HttpRequest* request) {

  if (!vocbase) {
    // unknown vocbase
     return false;
  }

  std::map<TRI_vocbase_t*, std::map<std::string, std::string> >::iterator mapIter;

  bool found;
  char const* auth = request->header("authorization", found);

  if (found) {
    if (! TRI_CaseEqualString2(auth, "basic ", 6)) {
      return false;
    }

    auth += 6;

    while (*auth == ' ') {
      ++auth;
    }

    {
      READ_LOCKER(_rwLock);

      mapIter = _authCache.find(vocbase);
      if (mapIter == _authCache.end()) {
        // unknown vocbase
        return false;
      }

      map<string,string>::iterator i = mapIter->second.find(auth);

      if (i != mapIter->second.end()) {
        request->setUser(i->second);
        return true;
      }
    }

    string up = StringUtils::decodeBase64(auth);
//    vector<string> split = StringUtils::split(up, ":");
//
//    if (split.size() != 2) {
//      return false;
//    }
//
//    bool res = TRI_CheckAuthenticationAuthInfo2(vocbase, split[0].c_str(), split[1].c_str());

    std::string::size_type n = up.find(':', 0);
    if (n == std::string::npos || n == 0 || n+1 > up.size()) {
      return false;
    }

    bool res = TRI_CheckAuthenticationAuthInfo2(vocbase, up.substr(0, n).c_str(), up.substr(n+1).c_str());

    if (res) {
      WRITE_LOCKER(_rwLock);

      mapIter = _authCache.find(vocbase);
      if (mapIter == _authCache.end()) {
        // unknown vocbase
        return false;
      }

      mapIter->second[auth] = up.substr(0, n);
      request->setUser(up.substr(0, n));

      // TODO: create a user object for the VocbaseContext
    }

    return res;
  }

  return false;
}

////////////////////////////////////////////////////////////////////////////////
/// @brief reload auth info
////////////////////////////////////////////////////////////////////////////////

bool VocbaseManager::reloadAuthInfo (TRI_vocbase_t* vocbase) {
  std::map<TRI_vocbase_t*, std::map<std::string, std::string> >::iterator mapIter;

  {
    WRITE_LOCKER(_rwLock);

    mapIter = _authCache.find(vocbase);
    if (mapIter != _authCache.end()) {
      mapIter->second.clear();
    }

  }

  return TRI_ReloadAuthInfo(vocbase);
}

////////////////////////////////////////////////////////////////////////////////
/// @brief get list of database names
////////////////////////////////////////////////////////////////////////////////

vector<TRI_vocbase_t*> VocbaseManager::vocbases () {
  vector<TRI_vocbase_t*> result;
  result.push_back(_vocbase);

  std::map<std::string, TRI_vocbase_t*>::iterator i = _vocbases.begin();

  for (; i != _vocbases.end(); ++i) {
    result.push_back(i->second);
  }

  return result;
}

////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////

// -----------------------------------------------------------------------------
// --SECTION--                                                       END-OF-FILE
// -----------------------------------------------------------------------------

// Local Variables:
// mode: outline-minor
// outline-regexp: "/// @brief\\|/// {@inheritDoc}\\|/// @addtogroup\\|/// @page\\|// --SECTION--\\|/// @\\}"
// End:
<commit_msg>added a log message<commit_after>////////////////////////////////////////////////////////////////////////////////
/// @brief vocbase manager
///
/// @file
///
/// DISCLAIMER
///
/// Copyright 2004-2013 triAGENS GmbH, Cologne, Germany
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///
///     http://www.apache.org/licenses/LICENSE-2.0
///
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
///
/// Copyright holder is triAGENS GmbH, Cologne, Germany
///
/// @author Dr. Frank Celler
/// @author Copyright 2011-2013, triAGENS GmbH, Cologne, Germany
////////////////////////////////////////////////////////////////////////////////

#include "RestServer/VocbaseManager.h"

#include "build.h"

#include "Logger/Logger.h"
#include "Rest/ConnectionInfo.h"
#include "Basics/StringUtils.h"
#include "RestServer/VocbaseContext.h"
#include "BasicsC/tri-strings.h"
#include "VocBase/auth.h"
#include "Actions/actions.h"

#include "HttpServer/ApplicationEndpointServer.h"
#include "V8/JSLoader.h"
#include "V8/v8-conv.h"
#include "V8/v8-globals.h"
#include "V8/v8-utils.h"

using namespace std;
using namespace triagens::basics;
using namespace triagens::arango;
using namespace triagens::rest;

// -----------------------------------------------------------------------------
// --SECTION--                                                            static
// -----------------------------------------------------------------------------

////////////////////////////////////////////////////////////////////////////////
/// @brief the global manager
////////////////////////////////////////////////////////////////////////////////

VocbaseManager VocbaseManager::manager;

////////////////////////////////////////////////////////////////////////////////
/// @brief add the context to a request
////////////////////////////////////////////////////////////////////////////////

bool VocbaseManager::setRequestContext(triagens::rest::HttpRequest* request) {
  TRI_vocbase_t* vb = VocbaseManager::manager.lookupVocbaseByHttpRequest(request);

  triagens::arango::VocbaseContext* vc = new triagens::arango::VocbaseContext(request, &VocbaseManager::manager);

  vc->setVocbase(vb);

  request->addRequestContext(vc);

  return true;
}

// -----------------------------------------------------------------------------
// --SECTION--                                                            public
// -----------------------------------------------------------------------------

////////////////////////////////////////////////////////////////////////////////
/// @addtogroup ArangoDB
/// @{
////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////
/// @brief add system vocbase
////////////////////////////////////////////////////////////////////////////////

void VocbaseManager::addSystemVocbase (TRI_vocbase_t* vocbase) {
  WRITE_LOCKER(_rwLock);
  _vocbase = vocbase;
  std::map<std::string, std::string> m;
  _authCache[vocbase] = m;
}

////////////////////////////////////////////////////////////////////////////////
/// @brief add user vocbase
////////////////////////////////////////////////////////////////////////////////

void VocbaseManager::addUserVocbase (TRI_vocbase_t* vocbase) {
  {
    WRITE_LOCKER(_rwLock);
    _vocbases[vocbase->_name] = vocbase;
    std::map<std::string, std::string> m;
    _authCache[vocbase] = m;
  }

  if (true) { //(vocbase->_needAuth) {
    TRI_ReloadAuthInfo(vocbase);
  }
}

////////////////////////////////////////////////////////////////////////////////
/// @brief close user vocbases
////////////////////////////////////////////////////////////////////////////////

void VocbaseManager::closeUserVocbases () {
  WRITE_LOCKER(_rwLock);

  std::map<std::string, TRI_vocbase_t*>::iterator i = _vocbases.begin();
  for (; i != _vocbases.end(); ++i) {
    TRI_vocbase_t* vocbase = i->second;
    TRI_DestroyVocBase(vocbase);
    TRI_Free(TRI_UNKNOWN_MEM_ZONE, vocbase);
  }

  _vocbases.clear();
}

////////////////////////////////////////////////////////////////////////////////
/// @brief look vocbase by name
////////////////////////////////////////////////////////////////////////////////

TRI_vocbase_t* VocbaseManager::lookupVocbaseByName (string const& name) {
  if (name == "_system") {
    return _vocbase;
  }

  READ_LOCKER(_rwLock);
  map<string, TRI_vocbase_s*>::iterator find = _vocbases.find(name);
  if (find != _vocbases.end()) {
    return find->second;
  }

  return 0;
}

////////////////////////////////////////////////////////////////////////////////
/// @brief check if name and path is not used
////////////////////////////////////////////////////////////////////////////////

bool VocbaseManager::canAddVocbase (std::string const& name, std::string const& path) {
  // loop over all vocbases and check name and path

  READ_LOCKER(_rwLock);

  // system vocbase
  if (name == string(_vocbase->_name)) {
    return false;
  }
  if (path == string(_vocbase->_path)) {
    return false;
  }

  // user vocbases
  std::map<std::string, TRI_vocbase_t*>::iterator i = _vocbases.begin();
  for (; i != _vocbases.end(); ++i) {
    TRI_vocbase_t* vocbase = i->second;
    if (name == string(vocbase->_name)) {
      return false;
    }
    if (path == string(vocbase->_path)) {
      return false;
    }
  }

  return true;
}

////////////////////////////////////////////////////////////////////////////////
/// @brief run version check
/// @return bool             returns false if the version check fails
////////////////////////////////////////////////////////////////////////////////

bool VocbaseManager::runVersionCheck (TRI_vocbase_t* vocbase, v8::Handle<v8::Context> context) {
  if (! _startupLoader) {
    LOGGER_ERROR("Javascript start up loader not found.");
    return false;
  }

  v8::HandleScope scope;
  TRI_v8_global_t* v8g = (TRI_v8_global_t*) v8::Isolate::GetCurrent()->GetData();
  TRI_vocbase_t* orig = (TRI_vocbase_t*) v8g->_vocbase;
  v8g->_vocbase = vocbase;

  v8::Handle<v8::Value> result = _startupLoader->executeGlobalScript(context, "server/version-check.js");

  v8g->_vocbase = orig;

  return TRI_ObjectToBoolean(result);
}

////////////////////////////////////////////////////////////////////////////////
/// @brief initialize foxx
////////////////////////////////////////////////////////////////////////////////

void VocbaseManager::initializeFoxx (TRI_vocbase_t* vocbase, v8::Handle<v8::Context> context) {
  TRI_vocbase_t* orig = 0;
  {
    v8::HandleScope scope;
    TRI_v8_global_t* v8g = (TRI_v8_global_t*) v8::Isolate::GetCurrent()->GetData();
    orig = (TRI_vocbase_t*) v8g->_vocbase;
    v8g->_vocbase = vocbase;
  }

  v8::HandleScope scope;
  TRI_ExecuteJavaScriptString(context,
                              v8::String::New("require(\"internal\").initializeFoxx()"),
                              v8::String::New("initialize foxx"),
                              false);
  {
    v8::HandleScope scope;
    TRI_v8_global_t* v8g = (TRI_v8_global_t*) v8::Isolate::GetCurrent()->GetData();
    v8g->_vocbase = orig;
  }
}

////////////////////////////////////////////////////////////////////////////////
/// @brief add an endpoint
////////////////////////////////////////////////////////////////////////////////

bool VocbaseManager::addEndpoint (std::string const& name) {

  if (_endpointServer) {
    return _endpointServer->addEndpoint(name);
  }

  return false;
}

////////////////////////////////////////////////////////////////////////////////
/// @brief look vocbase by http request
////////////////////////////////////////////////////////////////////////////////

TRI_vocbase_t* VocbaseManager::lookupVocbaseByHttpRequest (
                                        triagens::rest::HttpRequest* request) {
  ConnectionInfo ci = request->connectionInfo();

  string prefix = (ci.serverPort > 0)
          ? "tcp://" + triagens::basics::StringUtils::tolower(ci.serverAddress)
          + ":" + basics::StringUtils::itoa(ci.serverPort)
          : "unix:///localhost";

  return lookupVocbaseByPrefix(prefix);
}

////////////////////////////////////////////////////////////////////////////////
/// @brief look vocbase by prefix
////////////////////////////////////////////////////////////////////////////////

TRI_vocbase_t* VocbaseManager::lookupVocbaseByPrefix (
                                                    std::string const& prefix) {
  READ_LOCKER(_rwLock);
  map<string, TRI_vocbase_s*>::iterator find = _prefix2Vocbases.find(prefix);
  if (find != _prefix2Vocbases.end()) {
    return find->second;
  }

  // return default
  return _vocbase;
}

////////////////////////////////////////////////////////////////////////////////
/// @brief add prefix to database mapping
////////////////////////////////////////////////////////////////////////////////

void VocbaseManager::addPrefixMapping (std::string const& prefix,
                                       std::string const& name) {
  TRI_vocbase_t* vocbase = lookupVocbaseByName(name);

  if (vocbase) {
    LOGGER_INFO("added prefix mapping '" << prefix << "' -> '" << name << "'");

    WRITE_LOCKER(_rwLock);
    _prefix2Vocbases[triagens::basics::StringUtils::tolower(prefix)] = vocbase;
  }

}

////////////////////////////////////////////////////////////////////////////////
/// @brief authenticate a request
////////////////////////////////////////////////////////////////////////////////

bool VocbaseManager::authenticate (TRI_vocbase_t* vocbase,
                                   triagens::rest::HttpRequest* request) {

  if (!vocbase) {
    // unknown vocbase
     return false;
  }

  std::map<TRI_vocbase_t*, std::map<std::string, std::string> >::iterator mapIter;

  bool found;
  char const* auth = request->header("authorization", found);

  if (found) {
    if (! TRI_CaseEqualString2(auth, "basic ", 6)) {
      return false;
    }

    auth += 6;

    while (*auth == ' ') {
      ++auth;
    }

    {
      READ_LOCKER(_rwLock);

      mapIter = _authCache.find(vocbase);
      if (mapIter == _authCache.end()) {
        // unknown vocbase
        return false;
      }

      map<string,string>::iterator i = mapIter->second.find(auth);

      if (i != mapIter->second.end()) {
        request->setUser(i->second);
        return true;
      }
    }

    string up = StringUtils::decodeBase64(auth);
//    vector<string> split = StringUtils::split(up, ":");
//
//    if (split.size() != 2) {
//      return false;
//    }
//
//    bool res = TRI_CheckAuthenticationAuthInfo2(vocbase, split[0].c_str(), split[1].c_str());

    std::string::size_type n = up.find(':', 0);
    if (n == std::string::npos || n == 0 || n+1 > up.size()) {
      return false;
    }

    bool res = TRI_CheckAuthenticationAuthInfo2(vocbase, up.substr(0, n).c_str(), up.substr(n+1).c_str());

    if (res) {
      WRITE_LOCKER(_rwLock);

      mapIter = _authCache.find(vocbase);
      if (mapIter == _authCache.end()) {
        // unknown vocbase
        return false;
      }

      mapIter->second[auth] = up.substr(0, n);
      request->setUser(up.substr(0, n));

      // TODO: create a user object for the VocbaseContext
    }

    return res;
  }

  return false;
}

////////////////////////////////////////////////////////////////////////////////
/// @brief reload auth info
////////////////////////////////////////////////////////////////////////////////

bool VocbaseManager::reloadAuthInfo (TRI_vocbase_t* vocbase) {
  std::map<TRI_vocbase_t*, std::map<std::string, std::string> >::iterator mapIter;

  {
    WRITE_LOCKER(_rwLock);

    mapIter = _authCache.find(vocbase);
    if (mapIter != _authCache.end()) {
      mapIter->second.clear();
    }

  }

  return TRI_ReloadAuthInfo(vocbase);
}

////////////////////////////////////////////////////////////////////////////////
/// @brief get list of database names
////////////////////////////////////////////////////////////////////////////////

vector<TRI_vocbase_t*> VocbaseManager::vocbases () {
  vector<TRI_vocbase_t*> result;
  result.push_back(_vocbase);

  std::map<std::string, TRI_vocbase_t*>::iterator i = _vocbases.begin();

  for (; i != _vocbases.end(); ++i) {
    result.push_back(i->second);
  }

  return result;
}

////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////

// -----------------------------------------------------------------------------
// --SECTION--                                                       END-OF-FILE
// -----------------------------------------------------------------------------

// Local Variables:
// mode: outline-minor
// outline-regexp: "/// @brief\\|/// {@inheritDoc}\\|/// @addtogroup\\|/// @page\\|// --SECTION--\\|/// @\\}"
// End:
<|endoftext|>