<commit_before>//===--- tools/extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp ----------=== //
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
///
///  \file This file implements ClangTidyDiagnosticConsumer, ClangTidyMessage,
///  ClangTidyContext and ClangTidyError classes.
///
///  This tool uses the Clang Tooling infrastructure, see
///    http://clang.llvm.org/docs/HowToSetupToolingForLLVM.html
///  for details on setting it up with LLVM source tree.
///
//===----------------------------------------------------------------------===//

#include "ClangTidyDiagnosticConsumer.h"
#include "ClangTidyOptions.h"
#include "clang/Basic/DiagnosticOptions.h"
#include "clang/Frontend/DiagnosticRenderer.h"
#include "llvm/ADT/SmallString.h"
#include <set>
#include <tuple>
using namespace clang;
using namespace tidy;

namespace {
class ClangTidyDiagnosticRenderer : public DiagnosticRenderer {
public:
  ClangTidyDiagnosticRenderer(const LangOptions &LangOpts,
                              DiagnosticOptions *DiagOpts,
                              ClangTidyError &Error)
      : DiagnosticRenderer(LangOpts, DiagOpts), Error(Error) {}

protected:
  void emitDiagnosticMessage(SourceLocation Loc, PresumedLoc PLoc,
                             DiagnosticsEngine::Level Level, StringRef Message,
                             ArrayRef<CharSourceRange> Ranges,
                             const SourceManager *SM,
                             DiagOrStoredDiag Info) override {
    ClangTidyMessage TidyMessage = Loc.isValid()
                                       ? ClangTidyMessage(Message, *SM, Loc)
                                       : ClangTidyMessage(Message);
    if (Level == DiagnosticsEngine::Note) {
      Error.Notes.push_back(TidyMessage);
      return;
    }
    assert(Error.Message.Message.empty() &&
           "Overwriting a diagnostic message");
    Error.Message = TidyMessage;
  }

  void emitDiagnosticLoc(SourceLocation Loc, PresumedLoc PLoc,
                         DiagnosticsEngine::Level Level,
                         ArrayRef<CharSourceRange> Ranges,
                         const SourceManager &SM) override {}

  void emitBasicNote(StringRef Message) override {
    Error.Notes.push_back(ClangTidyMessage(Message));
  }

  void emitCodeContext(SourceLocation Loc, DiagnosticsEngine::Level Level,
                       SmallVectorImpl<CharSourceRange> &Ranges,
                       ArrayRef<FixItHint> Hints,
                       const SourceManager &SM) override {
    assert(Loc.isValid());
    for (const auto &FixIt : Hints) {
      CharSourceRange Range = FixIt.RemoveRange;
      assert(Range.getBegin().isValid() && Range.getEnd().isValid() &&
             "Invalid range in the fix-it hint.");
      assert(Range.getBegin().isFileID() && Range.getEnd().isFileID() &&
             "Only file locations supported in fix-it hints.");

      Error.Fix.insert(tooling::Replacement(SM, Range, FixIt.CodeToInsert));
    }
  }

  void emitIncludeLocation(SourceLocation Loc, PresumedLoc PLoc,
                           const SourceManager &SM) override {}

  void emitImportLocation(SourceLocation Loc, PresumedLoc PLoc,
                          StringRef ModuleName,
                          const SourceManager &SM) override {}

  void emitBuildingModuleLocation(SourceLocation Loc, PresumedLoc PLoc,
                                  StringRef ModuleName,
                                  const SourceManager &SM) override {}

  void endDiagnostic(DiagOrStoredDiag D,
                     DiagnosticsEngine::Level Level) override {
    assert(!Error.Message.Message.empty() && "Message has not been set");
  }

private:
  ClangTidyError &Error;
};
} // end anonymous namespace

ClangTidyMessage::ClangTidyMessage(StringRef Message) : Message(Message) {}

ClangTidyMessage::ClangTidyMessage(StringRef Message,
                                   const SourceManager &Sources,
                                   SourceLocation Loc)
    : Message(Message) {
  assert(Loc.isValid() && Loc.isFileID());
  FilePath = Sources.getFilename(Loc);
  FileOffset = Sources.getFileOffset(Loc);
}

ClangTidyError::ClangTidyError(StringRef CheckName,
                               ClangTidyError::Level DiagLevel)
    : CheckName(CheckName), DiagLevel(DiagLevel) {}

// Returns true if GlobList starts with the negative indicator ('-'), removes it
// from the GlobList.
static bool ConsumeNegativeIndicator(StringRef &GlobList) {
  if (GlobList.startswith("-")) {
    GlobList = GlobList.substr(1);
    return true;
  }
  return false;
}
// Converts first glob from the comma-separated list of globs to Regex and
// removes it and the trailing comma from the GlobList.
static llvm::Regex ConsumeGlob(StringRef &GlobList) {
  StringRef Glob = GlobList.substr(0, GlobList.find(','));
  GlobList = GlobList.substr(Glob.size() + 1);
  llvm::SmallString<128> RegexText("^");
  StringRef MetaChars("()^$|*+?.[]\\{}");
  for (char C : Glob) {
    if (C == '*')
      RegexText.push_back('.');
    else if (MetaChars.find(C) != StringRef::npos)
      RegexText.push_back('\\');
    RegexText.push_back(C);
  }
  RegexText.push_back('$');
  return llvm::Regex(RegexText);
}

ChecksFilter::ChecksFilter(StringRef GlobList)
    : Positive(!ConsumeNegativeIndicator(GlobList)),
      Regex(ConsumeGlob(GlobList)),
      NextFilter(GlobList.empty() ? nullptr : new ChecksFilter(GlobList)) {}

bool ChecksFilter::isCheckEnabled(StringRef Name, bool Enabled) {
  if (Regex.match(Name))
    Enabled = Positive;

  if (NextFilter)
    Enabled = NextFilter->isCheckEnabled(Name, Enabled);
  return Enabled;
}

ClangTidyContext::ClangTidyContext(ClangTidyOptionsProvider *OptionsProvider)
    : DiagEngine(nullptr), OptionsProvider(OptionsProvider) {
  // Before the first translation unit we can get errors related to command-line
  // parsing, use empty string for the file name in this case.
  setCurrentFile("");
}

DiagnosticBuilder ClangTidyContext::diag(
    StringRef CheckName, SourceLocation Loc, StringRef Description,
    DiagnosticIDs::Level Level /* = DiagnosticIDs::Warning*/) {
  assert(Loc.isValid());
  bool Invalid;
  const char *CharacterData =
      DiagEngine->getSourceManager().getCharacterData(Loc, &Invalid);
  if (!Invalid) {
    const char *P = CharacterData;
    while (*P != '\0' && *P != '\r' && *P != '\n')
      ++P;
    StringRef RestOfLine(CharacterData, P - CharacterData + 1);
    // FIXME: Handle /\bNOLINT\b(\([^)]*\))?/ as cpplint.py does.
    if (RestOfLine.find("NOLINT") != StringRef::npos) {
      Level = DiagnosticIDs::Ignored;
      ++Stats.ErrorsIgnoredNOLINT;
    }
  }
  unsigned ID = DiagEngine->getDiagnosticIDs()->getCustomDiagID(
      Level, (Description + " [" + CheckName + "]").str());
  if (CheckNamesByDiagnosticID.count(ID) == 0)
    CheckNamesByDiagnosticID.insert(std::make_pair(ID, CheckName.str()));
  return DiagEngine->Report(Loc, ID);
}

void ClangTidyContext::setDiagnosticsEngine(DiagnosticsEngine *Engine) {
  DiagEngine = Engine;
}

void ClangTidyContext::setSourceManager(SourceManager *SourceMgr) {
  DiagEngine->setSourceManager(SourceMgr);
}

void ClangTidyContext::setCurrentFile(StringRef File) {
  CurrentFile = File;
  CheckFilter.reset(new ChecksFilter(getOptions().Checks));
}

const ClangTidyGlobalOptions &ClangTidyContext::getGlobalOptions() const {
  return OptionsProvider->getGlobalOptions();
}

const ClangTidyOptions &ClangTidyContext::getOptions() const {
  return OptionsProvider->getOptions(CurrentFile);
}

ChecksFilter &ClangTidyContext::getChecksFilter() {
  assert(CheckFilter != nullptr);
  return *CheckFilter;
}

/// \brief Store a \c ClangTidyError.
void ClangTidyContext::storeError(const ClangTidyError &Error) {
  Errors.push_back(Error);
}

StringRef ClangTidyContext::getCheckName(unsigned DiagnosticID) const {
  llvm::DenseMap<unsigned, std::string>::const_iterator I =
      CheckNamesByDiagnosticID.find(DiagnosticID);
  if (I != CheckNamesByDiagnosticID.end())
    return I->second;
  return "";
}

ClangTidyDiagnosticConsumer::ClangTidyDiagnosticConsumer(ClangTidyContext &Ctx)
    : Context(Ctx), LastErrorRelatesToUserCode(false),
      LastErrorPassesLineFilter(false) {
  IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions();
  Diags.reset(new DiagnosticsEngine(
      IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs), &*DiagOpts, this,
      /*ShouldOwnClient=*/false));
  Context.setDiagnosticsEngine(Diags.get());
}

void ClangTidyDiagnosticConsumer::finalizeLastError() {
  if (!Errors.empty()) {
    ClangTidyError &Error = Errors.back();
    if (!Context.getChecksFilter().isCheckEnabled(Error.CheckName) &&
        Error.DiagLevel != ClangTidyError::Error) {
      ++Context.Stats.ErrorsIgnoredCheckFilter;
      Errors.pop_back();
    } else if (!LastErrorRelatesToUserCode) {
      ++Context.Stats.ErrorsIgnoredNonUserCode;
      Errors.pop_back();
    } else if (!LastErrorPassesLineFilter) {
      ++Context.Stats.ErrorsIgnoredLineFilter;
      Errors.pop_back();
    } else {
      ++Context.Stats.ErrorsDisplayed;
    }
  }
  LastErrorRelatesToUserCode = false;
  LastErrorPassesLineFilter = false;
}

void ClangTidyDiagnosticConsumer::HandleDiagnostic(
    DiagnosticsEngine::Level DiagLevel, const Diagnostic &Info) {
  if (DiagLevel == DiagnosticsEngine::Note) {
    assert(!Errors.empty() &&
           "A diagnostic note can only be appended to a message.");
  } else {
    // FIXME: Pass all errors here regardless of filters and non-user code.
    finalizeLastError();
    StringRef WarningOption =
        Context.DiagEngine->getDiagnosticIDs()->getWarningOptionForDiag(
            Info.getID());
    std::string CheckName = !WarningOption.empty()
                                ? ("clang-diagnostic-" + WarningOption).str()
                                : Context.getCheckName(Info.getID()).str();

    ClangTidyError::Level Level = ClangTidyError::Warning;
    if (DiagLevel == DiagnosticsEngine::Error ||
        DiagLevel == DiagnosticsEngine::Fatal) {
      Level = ClangTidyError::Error;
      LastErrorRelatesToUserCode = true;
      LastErrorPassesLineFilter = true;
    }
    Errors.push_back(ClangTidyError(CheckName, Level));
  }

  // FIXME: Provide correct LangOptions for each file.
  LangOptions LangOpts;
  ClangTidyDiagnosticRenderer Converter(
      LangOpts, &Context.DiagEngine->getDiagnosticOptions(), Errors.back());
  SmallString<100> Message;
  Info.FormatDiagnostic(Message);
  SourceManager *Sources = nullptr;
  if (Info.hasSourceManager())
    Sources = &Info.getSourceManager();
  Converter.emitDiagnostic(Info.getLocation(), DiagLevel, Message,
                           Info.getRanges(), Info.getFixItHints(), Sources);

  checkFilters(Info.getLocation());
}

void ClangTidyDiagnosticConsumer::BeginSourceFile(const LangOptions &LangOpts,
                                                  const Preprocessor *PP) {
  // Before the first translation unit we don't need HeaderFilter, as we
  // shouldn't get valid source locations in diagnostics.
  HeaderFilter.reset(new llvm::Regex(Context.getOptions().HeaderFilterRegex));
}

bool ClangTidyDiagnosticConsumer::passesLineFilter(StringRef FileName,
                                                   unsigned LineNumber) const {
  if (Context.getGlobalOptions().LineFilter.empty())
    return true;
  for (const FileFilter& Filter : Context.getGlobalOptions().LineFilter) {
    if (FileName.endswith(Filter.Name)) {
      if (Filter.LineRanges.empty())
        return true;
      for (const FileFilter::LineRange &Range : Filter.LineRanges) {
        if (Range.first <= LineNumber && LineNumber <= Range.second)
          return true;
      }
      return false;
    }
  }
  return false;
}

void ClangTidyDiagnosticConsumer::checkFilters(SourceLocation Location) {
  // Invalid location may mean a diagnostic in a command line, don't skip these.
  if (!Location.isValid()) {
    LastErrorRelatesToUserCode = true;
    LastErrorPassesLineFilter = true;
    return;
  }

  const SourceManager &Sources = Diags->getSourceManager();
  if (Sources.isInSystemHeader(Location))
    return;

  // FIXME: We start with a conservative approach here, but the actual type of
  // location needed depends on the check (in particular, where this check wants
  // to apply fixes).
  FileID FID = Sources.getDecomposedExpansionLoc(Location).first;
  const FileEntry *File = Sources.getFileEntryForID(FID);

  // -DMACRO definitions on the command line have locations in a virtual buffer
  // that doesn't have a FileEntry. Don't skip these as well.
  if (!File) {
    LastErrorRelatesToUserCode = true;
    LastErrorPassesLineFilter = true;
    return;
  }

  StringRef FileName(File->getName());
  assert(LastErrorRelatesToUserCode || Sources.isInMainFile(Location) ||
         HeaderFilter != nullptr);
  LastErrorRelatesToUserCode = LastErrorRelatesToUserCode ||
                               Sources.isInMainFile(Location) ||
                               HeaderFilter->match(FileName);

  unsigned LineNumber = Sources.getExpansionLineNumber(Location);
  LastErrorPassesLineFilter =
      LastErrorPassesLineFilter || passesLineFilter(FileName, LineNumber);
}

namespace {
struct LessClangTidyError {
  bool operator()(const ClangTidyError *LHS, const ClangTidyError *RHS) const {
    const ClangTidyMessage &M1 = LHS->Message;
    const ClangTidyMessage &M2 = RHS->Message;

    return std::tie(M1.FilePath, M1.FileOffset, M1.Message) <
           std::tie(M2.FilePath, M2.FileOffset, M2.Message);
  }
};
} // end anonymous namespace

// Flushes the internal diagnostics buffer to the ClangTidyContext.
void ClangTidyDiagnosticConsumer::finish() {
  finalizeLastError();
  std::set<const ClangTidyError*, LessClangTidyError> UniqueErrors;
  for (const ClangTidyError &Error : Errors)
    UniqueErrors.insert(&Error);

  for (const ClangTidyError *Error : UniqueErrors)
    Context.storeError(*Error);
  Errors.clear();
}
<commit_msg>Track changes from clang r211448.<commit_after>//===--- tools/extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp ----------=== //
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
///
///  \file This file implements ClangTidyDiagnosticConsumer, ClangTidyMessage,
///  ClangTidyContext and ClangTidyError classes.
///
///  This tool uses the Clang Tooling infrastructure, see
///    http://clang.llvm.org/docs/HowToSetupToolingForLLVM.html
///  for details on setting it up with LLVM source tree.
///
//===----------------------------------------------------------------------===//

#include "ClangTidyDiagnosticConsumer.h"
#include "ClangTidyOptions.h"
#include "clang/Basic/DiagnosticOptions.h"
#include "clang/Frontend/DiagnosticRenderer.h"
#include "llvm/ADT/SmallString.h"
#include <set>
#include <tuple>
using namespace clang;
using namespace tidy;

namespace {
class ClangTidyDiagnosticRenderer : public DiagnosticRenderer {
public:
  ClangTidyDiagnosticRenderer(const LangOptions &LangOpts,
                              DiagnosticOptions *DiagOpts,
                              ClangTidyError &Error)
      : DiagnosticRenderer(LangOpts, DiagOpts), Error(Error) {}

protected:
  void emitDiagnosticMessage(SourceLocation Loc, PresumedLoc PLoc,
                             DiagnosticsEngine::Level Level, StringRef Message,
                             ArrayRef<CharSourceRange> Ranges,
                             const SourceManager *SM,
                             DiagOrStoredDiag Info) override {
    ClangTidyMessage TidyMessage = Loc.isValid()
                                       ? ClangTidyMessage(Message, *SM, Loc)
                                       : ClangTidyMessage(Message);
    if (Level == DiagnosticsEngine::Note) {
      Error.Notes.push_back(TidyMessage);
      return;
    }
    assert(Error.Message.Message.empty() &&
           "Overwriting a diagnostic message");
    Error.Message = TidyMessage;
  }

  void emitDiagnosticLoc(SourceLocation Loc, PresumedLoc PLoc,
                         DiagnosticsEngine::Level Level,
                         ArrayRef<CharSourceRange> Ranges,
                         const SourceManager &SM) override {}

  void emitCodeContext(SourceLocation Loc, DiagnosticsEngine::Level Level,
                       SmallVectorImpl<CharSourceRange> &Ranges,
                       ArrayRef<FixItHint> Hints,
                       const SourceManager &SM) override {
    assert(Loc.isValid());
    for (const auto &FixIt : Hints) {
      CharSourceRange Range = FixIt.RemoveRange;
      assert(Range.getBegin().isValid() && Range.getEnd().isValid() &&
             "Invalid range in the fix-it hint.");
      assert(Range.getBegin().isFileID() && Range.getEnd().isFileID() &&
             "Only file locations supported in fix-it hints.");

      Error.Fix.insert(tooling::Replacement(SM, Range, FixIt.CodeToInsert));
    }
  }

  void emitIncludeLocation(SourceLocation Loc, PresumedLoc PLoc,
                           const SourceManager &SM) override {}

  void emitImportLocation(SourceLocation Loc, PresumedLoc PLoc,
                          StringRef ModuleName,
                          const SourceManager &SM) override {}

  void emitBuildingModuleLocation(SourceLocation Loc, PresumedLoc PLoc,
                                  StringRef ModuleName,
                                  const SourceManager &SM) override {}

  void endDiagnostic(DiagOrStoredDiag D,
                     DiagnosticsEngine::Level Level) override {
    assert(!Error.Message.Message.empty() && "Message has not been set");
  }

private:
  ClangTidyError &Error;
};
} // end anonymous namespace

ClangTidyMessage::ClangTidyMessage(StringRef Message) : Message(Message) {}

ClangTidyMessage::ClangTidyMessage(StringRef Message,
                                   const SourceManager &Sources,
                                   SourceLocation Loc)
    : Message(Message) {
  assert(Loc.isValid() && Loc.isFileID());
  FilePath = Sources.getFilename(Loc);
  FileOffset = Sources.getFileOffset(Loc);
}

ClangTidyError::ClangTidyError(StringRef CheckName,
                               ClangTidyError::Level DiagLevel)
    : CheckName(CheckName), DiagLevel(DiagLevel) {}

// Returns true if GlobList starts with the negative indicator ('-'), removes it
// from the GlobList.
static bool ConsumeNegativeIndicator(StringRef &GlobList) {
  if (GlobList.startswith("-")) {
    GlobList = GlobList.substr(1);
    return true;
  }
  return false;
}
// Converts first glob from the comma-separated list of globs to Regex and
// removes it and the trailing comma from the GlobList.
static llvm::Regex ConsumeGlob(StringRef &GlobList) {
  StringRef Glob = GlobList.substr(0, GlobList.find(','));
  GlobList = GlobList.substr(Glob.size() + 1);
  llvm::SmallString<128> RegexText("^");
  StringRef MetaChars("()^$|*+?.[]\\{}");
  for (char C : Glob) {
    if (C == '*')
      RegexText.push_back('.');
    else if (MetaChars.find(C) != StringRef::npos)
      RegexText.push_back('\\');
    RegexText.push_back(C);
  }
  RegexText.push_back('$');
  return llvm::Regex(RegexText);
}

ChecksFilter::ChecksFilter(StringRef GlobList)
    : Positive(!ConsumeNegativeIndicator(GlobList)),
      Regex(ConsumeGlob(GlobList)),
      NextFilter(GlobList.empty() ? nullptr : new ChecksFilter(GlobList)) {}

bool ChecksFilter::isCheckEnabled(StringRef Name, bool Enabled) {
  if (Regex.match(Name))
    Enabled = Positive;

  if (NextFilter)
    Enabled = NextFilter->isCheckEnabled(Name, Enabled);
  return Enabled;
}

ClangTidyContext::ClangTidyContext(ClangTidyOptionsProvider *OptionsProvider)
    : DiagEngine(nullptr), OptionsProvider(OptionsProvider) {
  // Before the first translation unit we can get errors related to command-line
  // parsing, use empty string for the file name in this case.
  setCurrentFile("");
}

DiagnosticBuilder ClangTidyContext::diag(
    StringRef CheckName, SourceLocation Loc, StringRef Description,
    DiagnosticIDs::Level Level /* = DiagnosticIDs::Warning*/) {
  assert(Loc.isValid());
  bool Invalid;
  const char *CharacterData =
      DiagEngine->getSourceManager().getCharacterData(Loc, &Invalid);
  if (!Invalid) {
    const char *P = CharacterData;
    while (*P != '\0' && *P != '\r' && *P != '\n')
      ++P;
    StringRef RestOfLine(CharacterData, P - CharacterData + 1);
    // FIXME: Handle /\bNOLINT\b(\([^)]*\))?/ as cpplint.py does.
    if (RestOfLine.find("NOLINT") != StringRef::npos) {
      Level = DiagnosticIDs::Ignored;
      ++Stats.ErrorsIgnoredNOLINT;
    }
  }
  unsigned ID = DiagEngine->getDiagnosticIDs()->getCustomDiagID(
      Level, (Description + " [" + CheckName + "]").str());
  if (CheckNamesByDiagnosticID.count(ID) == 0)
    CheckNamesByDiagnosticID.insert(std::make_pair(ID, CheckName.str()));
  return DiagEngine->Report(Loc, ID);
}

void ClangTidyContext::setDiagnosticsEngine(DiagnosticsEngine *Engine) {
  DiagEngine = Engine;
}

void ClangTidyContext::setSourceManager(SourceManager *SourceMgr) {
  DiagEngine->setSourceManager(SourceMgr);
}

void ClangTidyContext::setCurrentFile(StringRef File) {
  CurrentFile = File;
  CheckFilter.reset(new ChecksFilter(getOptions().Checks));
}

const ClangTidyGlobalOptions &ClangTidyContext::getGlobalOptions() const {
  return OptionsProvider->getGlobalOptions();
}

const ClangTidyOptions &ClangTidyContext::getOptions() const {
  return OptionsProvider->getOptions(CurrentFile);
}

ChecksFilter &ClangTidyContext::getChecksFilter() {
  assert(CheckFilter != nullptr);
  return *CheckFilter;
}

/// \brief Store a \c ClangTidyError.
void ClangTidyContext::storeError(const ClangTidyError &Error) {
  Errors.push_back(Error);
}

StringRef ClangTidyContext::getCheckName(unsigned DiagnosticID) const {
  llvm::DenseMap<unsigned, std::string>::const_iterator I =
      CheckNamesByDiagnosticID.find(DiagnosticID);
  if (I != CheckNamesByDiagnosticID.end())
    return I->second;
  return "";
}

ClangTidyDiagnosticConsumer::ClangTidyDiagnosticConsumer(ClangTidyContext &Ctx)
    : Context(Ctx), LastErrorRelatesToUserCode(false),
      LastErrorPassesLineFilter(false) {
  IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions();
  Diags.reset(new DiagnosticsEngine(
      IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs), &*DiagOpts, this,
      /*ShouldOwnClient=*/false));
  Context.setDiagnosticsEngine(Diags.get());
}

void ClangTidyDiagnosticConsumer::finalizeLastError() {
  if (!Errors.empty()) {
    ClangTidyError &Error = Errors.back();
    if (!Context.getChecksFilter().isCheckEnabled(Error.CheckName) &&
        Error.DiagLevel != ClangTidyError::Error) {
      ++Context.Stats.ErrorsIgnoredCheckFilter;
      Errors.pop_back();
    } else if (!LastErrorRelatesToUserCode) {
      ++Context.Stats.ErrorsIgnoredNonUserCode;
      Errors.pop_back();
    } else if (!LastErrorPassesLineFilter) {
      ++Context.Stats.ErrorsIgnoredLineFilter;
      Errors.pop_back();
    } else {
      ++Context.Stats.ErrorsDisplayed;
    }
  }
  LastErrorRelatesToUserCode = false;
  LastErrorPassesLineFilter = false;
}

void ClangTidyDiagnosticConsumer::HandleDiagnostic(
    DiagnosticsEngine::Level DiagLevel, const Diagnostic &Info) {
  if (DiagLevel == DiagnosticsEngine::Note) {
    assert(!Errors.empty() &&
           "A diagnostic note can only be appended to a message.");
  } else {
    // FIXME: Pass all errors here regardless of filters and non-user code.
    finalizeLastError();
    StringRef WarningOption =
        Context.DiagEngine->getDiagnosticIDs()->getWarningOptionForDiag(
            Info.getID());
    std::string CheckName = !WarningOption.empty()
                                ? ("clang-diagnostic-" + WarningOption).str()
                                : Context.getCheckName(Info.getID()).str();

    ClangTidyError::Level Level = ClangTidyError::Warning;
    if (DiagLevel == DiagnosticsEngine::Error ||
        DiagLevel == DiagnosticsEngine::Fatal) {
      Level = ClangTidyError::Error;
      LastErrorRelatesToUserCode = true;
      LastErrorPassesLineFilter = true;
    }
    Errors.push_back(ClangTidyError(CheckName, Level));
  }

  // FIXME: Provide correct LangOptions for each file.
  LangOptions LangOpts;
  ClangTidyDiagnosticRenderer Converter(
      LangOpts, &Context.DiagEngine->getDiagnosticOptions(), Errors.back());
  SmallString<100> Message;
  Info.FormatDiagnostic(Message);
  SourceManager *Sources = nullptr;
  if (Info.hasSourceManager())
    Sources = &Info.getSourceManager();
  Converter.emitDiagnostic(Info.getLocation(), DiagLevel, Message,
                           Info.getRanges(), Info.getFixItHints(), Sources);

  checkFilters(Info.getLocation());
}

void ClangTidyDiagnosticConsumer::BeginSourceFile(const LangOptions &LangOpts,
                                                  const Preprocessor *PP) {
  // Before the first translation unit we don't need HeaderFilter, as we
  // shouldn't get valid source locations in diagnostics.
  HeaderFilter.reset(new llvm::Regex(Context.getOptions().HeaderFilterRegex));
}

bool ClangTidyDiagnosticConsumer::passesLineFilter(StringRef FileName,
                                                   unsigned LineNumber) const {
  if (Context.getGlobalOptions().LineFilter.empty())
    return true;
  for (const FileFilter& Filter : Context.getGlobalOptions().LineFilter) {
    if (FileName.endswith(Filter.Name)) {
      if (Filter.LineRanges.empty())
        return true;
      for (const FileFilter::LineRange &Range : Filter.LineRanges) {
        if (Range.first <= LineNumber && LineNumber <= Range.second)
          return true;
      }
      return false;
    }
  }
  return false;
}

void ClangTidyDiagnosticConsumer::checkFilters(SourceLocation Location) {
  // Invalid location may mean a diagnostic in a command line, don't skip these.
  if (!Location.isValid()) {
    LastErrorRelatesToUserCode = true;
    LastErrorPassesLineFilter = true;
    return;
  }

  const SourceManager &Sources = Diags->getSourceManager();
  if (Sources.isInSystemHeader(Location))
    return;

  // FIXME: We start with a conservative approach here, but the actual type of
  // location needed depends on the check (in particular, where this check wants
  // to apply fixes).
  FileID FID = Sources.getDecomposedExpansionLoc(Location).first;
  const FileEntry *File = Sources.getFileEntryForID(FID);

  // -DMACRO definitions on the command line have locations in a virtual buffer
  // that doesn't have a FileEntry. Don't skip these as well.
  if (!File) {
    LastErrorRelatesToUserCode = true;
    LastErrorPassesLineFilter = true;
    return;
  }

  StringRef FileName(File->getName());
  assert(LastErrorRelatesToUserCode || Sources.isInMainFile(Location) ||
         HeaderFilter != nullptr);
  LastErrorRelatesToUserCode = LastErrorRelatesToUserCode ||
                               Sources.isInMainFile(Location) ||
                               HeaderFilter->match(FileName);

  unsigned LineNumber = Sources.getExpansionLineNumber(Location);
  LastErrorPassesLineFilter =
      LastErrorPassesLineFilter || passesLineFilter(FileName, LineNumber);
}

namespace {
struct LessClangTidyError {
  bool operator()(const ClangTidyError *LHS, const ClangTidyError *RHS) const {
    const ClangTidyMessage &M1 = LHS->Message;
    const ClangTidyMessage &M2 = RHS->Message;

    return std::tie(M1.FilePath, M1.FileOffset, M1.Message) <
           std::tie(M2.FilePath, M2.FileOffset, M2.Message);
  }
};
} // end anonymous namespace

// Flushes the internal diagnostics buffer to the ClangTidyContext.
void ClangTidyDiagnosticConsumer::finish() {
  finalizeLastError();
  std::set<const ClangTidyError*, LessClangTidyError> UniqueErrors;
  for (const ClangTidyError &Error : Errors)
    UniqueErrors.insert(&Error);

  for (const ClangTidyError *Error : UniqueErrors)
    Context.storeError(*Error);
  Errors.clear();
}
<|endoftext|>


<commit_before>/* medBrowserArea.cpp ---
 *
 * Author: Julien Wintz
 * Copyright (C) 2008 - Julien Wintz, Inria.
 * Created: Fri Sep 25 12:23:43 2009 (+0200)
 * Version: $Id$
 * Last-Updated: Sat Mar 20 20:06:27 2010 (+0100)
 *           By: Julien Wintz
 *     Update #: 289
 */

/* Commentary:
 *
 */

/* Change log:
 *
 */

#include "medBrowserArea.h"

#include <QtGui>

#include <medSql/medDatabaseController.h>
#include <medSql/medDatabaseExporter.h>
#include <medSql/medDatabaseImporter.h>
#include <medSql/medDatabaseModel.h>
#include <medSql/medDatabaseView.h>
#include <medSql/medDatabasePreview.h>

#include <medGui/medProgressionStack.h>
#include <medGui/medToolBox.h>
#include <medGui/medToolBoxContainer.h>

// /////////////////////////////////////////////////////////////////
// medBrowserArea
// /////////////////////////////////////////////////////////////////

class medBrowserAreaPrivate
{
public:
    medToolBoxContainer *toolbox_container;

    medDatabasePreview *preview;
    medDatabaseModel *model;
    medDatabaseView *view;

    QTreeView *filesystem_view;
    QFileSystemModel *filesystem_model;

    QStatusBar *status;

    medProgressionStack *progression_stack;
};

medBrowserArea::medBrowserArea(QWidget *parent) : QWidget(parent), d(new medBrowserAreaPrivate)
{
    d->preview = new medDatabasePreview(this);

    d->model = new medDatabaseModel;

    d->view = new medDatabaseView(this);
    d->view->setModel(d->model);

    // connect(d->preview, SIGNAL(patientClicked(int)), d->view, SLOT(onPatientClicked(int)));
    // connect(d->preview, SIGNAL(studyClicked(int)), d->view, SLOT(onStudyClicked(int)));
    // connect(d->preview, SIGNAL(seriesClicked(int)), d->view, SLOT(onSeriesClicked(int)));
    // connect(d->preview, SIGNAL(imageClicked(int)), d->view, SLOT(onImageClicked(int)));

    connect(d->view, SIGNAL(patientClicked(int)), d->preview, SLOT(onPatientClicked(int)));
    connect(d->view, SIGNAL(seriesClicked(int)), d->preview, SLOT(onSeriesClicked(int)));

    // Database widget /////////////////////////////////////////////////

    QWidget *database_widget = new QWidget(this);

    QVBoxLayout *database_layout = new QVBoxLayout(database_widget);
    database_layout->setContentsMargins(0, 0, 0, 0);
    database_layout->setSpacing(0);
    database_layout->addWidget(d->view);
    database_layout->addWidget(d->preview);

    // Filesystem widget ///////////////////////////////////////////////

    d->filesystem_model = new QFileSystemModel;
    d->filesystem_model->setRootPath(QDir::rootPath());

    d->filesystem_view = new QTreeView(this);
    d->filesystem_view->setFrameStyle(QFrame::NoFrame);
    d->filesystem_view->setAttribute(Qt::WA_MacShowFocusRect, false);
    d->filesystem_view->setUniformRowHeights(true);
    d->filesystem_view->setAlternatingRowColors(true);
    d->filesystem_view->setSortingEnabled(true);
    d->filesystem_view->setModel(d->filesystem_model);
    d->filesystem_view->setCurrentIndex(d->filesystem_model->index(QDir::homePath()));
    d->filesystem_view->setExpanded(d->filesystem_view->currentIndex(), true);
    d->filesystem_view->header()->setResizeMode(QHeaderView::Stretch);

    // Pacs widget ///////////////////////////////////////////////

    QTreeView *pacs_widget = new QTreeView(this);
    pacs_widget->setFrameStyle(QFrame::NoFrame);
    pacs_widget->setAttribute(Qt::WA_MacShowFocusRect, false);
    pacs_widget->setUniformRowHeights(true);
    pacs_widget->setAlternatingRowColors(true);
    pacs_widget->setSortingEnabled(true);

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

    QStackedWidget *stack = new QStackedWidget(this);
    stack->addWidget(database_widget);
    stack->addWidget(d->filesystem_view);
    stack->addWidget(pacs_widget);

    // Source selector ///////////////////////////////////////////////

    QWidget *database_page = new QWidget(this);

    QPushButton *database_page_expand_all_button = new QPushButton("All", database_page);
    QPushButton *database_page_collapse_all_button = new QPushButton("All", database_page);

    connect(database_page_expand_all_button, SIGNAL(clicked()), d->view, SLOT(expandAll()));
    connect(database_page_collapse_all_button, SIGNAL(clicked()), d->view, SLOT(collapseAll()));

    QFormLayout *database_page_layout = new QFormLayout(database_page);
    database_page_layout->addRow("Expand:", database_page_expand_all_button);
    database_page_layout->addRow("Collapse:", database_page_collapse_all_button);
    database_page_layout->setFormAlignment(Qt::AlignHCenter);

    QWidget *filesystem_page = new QWidget(this);

    QPushButton *filesystem_import_button = new QPushButton("Import", filesystem_page);
    QPushButton *filesystem_export_button = new QPushButton("Export", filesystem_page);

    QFormLayout *filesystem_page_layout = new QFormLayout(filesystem_page);
    filesystem_page_layout->addRow("Current item:", filesystem_import_button);
    filesystem_page_layout->addRow("Current item:", filesystem_export_button);
    filesystem_page_layout->setFormAlignment(Qt::AlignHCenter);

    connect(filesystem_import_button, SIGNAL(clicked()), this, SLOT(onFileSystemImportClicked()));
    connect(filesystem_export_button, SIGNAL(clicked()), this, SLOT(onFileSystemExportClicked()));

    QWidget *pacs_page = new QWidget(this);

    QFormLayout *pacs_page_layout = new QFormLayout(pacs_page);
    pacs_page_layout->addRow("Url:", new QLineEdit(pacs_page));
    pacs_page_layout->addRow("Login:", new QLineEdit(pacs_page));
    pacs_page_layout->addRow("Password:", new QLineEdit(pacs_page));
    pacs_page_layout->addWidget(new QPushButton("Connect", pacs_page));
    pacs_page_layout->setFormAlignment(Qt::AlignHCenter);

    medToolBoxTab *tab = new medToolBoxTab(this);
    tab->addTab(database_page, "Db");
    tab->addTab(filesystem_page, "Fs");
    tab->addTab(pacs_page, "Pc");
    connect(tab, SIGNAL(currentChanged(int)), stack, SLOT(setCurrentIndex(int)));

    medToolBox *sourceSelectorToolBox = new medToolBox(this);
    sourceSelectorToolBox->setTitle("Source selector");
    sourceSelectorToolBox->setWidget(tab);

    // Jobs //////////////////////////////////////////

    d->progression_stack = new medProgressionStack(filesystem_page);

    medToolBox *jobsToolBox = new medToolBox(this);
    jobsToolBox->setTitle("Jobs");
    jobsToolBox->setWidget(d->progression_stack);
    jobsToolBox->setVisible(false);

    connect(d->progression_stack, SIGNAL(shown()), jobsToolBox, SLOT(show()));
    connect(d->progression_stack, SIGNAL(hidden()), jobsToolBox, SLOT(hide()));

    // Toolbox container /////////////////////////////////////////////

    d->toolbox_container = new medToolBoxContainer(this);
    d->toolbox_container->setFixedWidth(300);
    d->toolbox_container->addToolBox(sourceSelectorToolBox);
    d->toolbox_container->addToolBox(jobsToolBox);

    // Layout /////////////////////////////////////////////

    QHBoxLayout *layout = new QHBoxLayout(this);
    layout->setContentsMargins(0, 0, 0, 0);
    layout->setSpacing(0);
    layout->addWidget(d->toolbox_container);
    layout->addWidget(stack);
}

medBrowserArea::~medBrowserArea(void)
{
    delete d->preview;
    delete d->model;
    delete d->view;
    delete d;

    d = NULL;
}

void medBrowserArea::setup(QStatusBar *status)
{
    d->status = status;
}

void medBrowserArea::setdw(QStatusBar *status)
{
    d->status = status;
}

medDatabaseView *medBrowserArea::view(void)
{
    return d->view;
}

medDatabaseModel *medBrowserArea::model(void)
{
    return d->model;
}

void medBrowserArea::onFileSystemImportClicked(void)
{
    QFileInfo info(d->filesystem_model->filePath(d->filesystem_view->currentIndex()));

    medDatabaseImporter *importer = new medDatabaseImporter(info.absoluteFilePath());

    connect(importer, SIGNAL(progressed(int)), d->progression_stack, SLOT(setProgress(int)));
    connect(importer, SIGNAL(done()), this, SLOT(onFileImported()));

    d->progression_stack->setLabel(importer, info.baseName());

    QThreadPool::globalInstance()->start(importer);
}

void medBrowserArea::onFileSystemExportClicked(void)
{
    medDatabaseExporter *exporter = new medDatabaseExporter;

    connect(exporter, SIGNAL(progressed(int)), d->progression_stack, SLOT(setProgress(int)));

    QThreadPool::globalInstance()->start(exporter);
}

void medBrowserArea::onFileImported(void)
{
    medDatabaseController::instance()->import("");

    d->preview->reset();
    d->preview->init();
    d->preview->update();
}
<commit_msg>File system view columns made resizable<commit_after>/* medBrowserArea.cpp ---
 *
 * Author: Julien Wintz
 * Copyright (C) 2008 - Julien Wintz, Inria.
 * Created: Fri Sep 25 12:23:43 2009 (+0200)
 * Version: $Id$
 * Last-Updated: Thu Mar 25 18:43:40 2010 (+0100)
 *           By: Julien Wintz
 *     Update #: 290
 */

/* Commentary:
 *
 */

/* Change log:
 *
 */

#include "medBrowserArea.h"

#include <QtGui>

#include <medSql/medDatabaseController.h>
#include <medSql/medDatabaseExporter.h>
#include <medSql/medDatabaseImporter.h>
#include <medSql/medDatabaseModel.h>
#include <medSql/medDatabaseView.h>
#include <medSql/medDatabasePreview.h>

#include <medGui/medProgressionStack.h>
#include <medGui/medToolBox.h>
#include <medGui/medToolBoxContainer.h>

// /////////////////////////////////////////////////////////////////
// medBrowserArea
// /////////////////////////////////////////////////////////////////

class medBrowserAreaPrivate
{
public:
    medToolBoxContainer *toolbox_container;

    medDatabasePreview *preview;
    medDatabaseModel *model;
    medDatabaseView *view;

    QTreeView *filesystem_view;
    QFileSystemModel *filesystem_model;

    QStatusBar *status;

    medProgressionStack *progression_stack;
};

medBrowserArea::medBrowserArea(QWidget *parent) : QWidget(parent), d(new medBrowserAreaPrivate)
{
    d->preview = new medDatabasePreview(this);

    d->model = new medDatabaseModel;

    d->view = new medDatabaseView(this);
    d->view->setModel(d->model);

    // connect(d->preview, SIGNAL(patientClicked(int)), d->view, SLOT(onPatientClicked(int)));
    // connect(d->preview, SIGNAL(studyClicked(int)), d->view, SLOT(onStudyClicked(int)));
    // connect(d->preview, SIGNAL(seriesClicked(int)), d->view, SLOT(onSeriesClicked(int)));
    // connect(d->preview, SIGNAL(imageClicked(int)), d->view, SLOT(onImageClicked(int)));

    connect(d->view, SIGNAL(patientClicked(int)), d->preview, SLOT(onPatientClicked(int)));
    connect(d->view, SIGNAL(seriesClicked(int)), d->preview, SLOT(onSeriesClicked(int)));

    // Database widget /////////////////////////////////////////////////

    QWidget *database_widget = new QWidget(this);

    QVBoxLayout *database_layout = new QVBoxLayout(database_widget);
    database_layout->setContentsMargins(0, 0, 0, 0);
    database_layout->setSpacing(0);
    database_layout->addWidget(d->view);
    database_layout->addWidget(d->preview);

    // Filesystem widget ///////////////////////////////////////////////

    d->filesystem_model = new QFileSystemModel;
    d->filesystem_model->setRootPath(QDir::rootPath());

    d->filesystem_view = new QTreeView(this);
    d->filesystem_view->setFrameStyle(QFrame::NoFrame);
    d->filesystem_view->setAttribute(Qt::WA_MacShowFocusRect, false);
    d->filesystem_view->setUniformRowHeights(true);
    d->filesystem_view->setAlternatingRowColors(true);
    d->filesystem_view->setSortingEnabled(true);
    d->filesystem_view->setModel(d->filesystem_model);
    d->filesystem_view->setCurrentIndex(d->filesystem_model->index(QDir::homePath()));
    d->filesystem_view->setExpanded(d->filesystem_view->currentIndex(), true);
    d->filesystem_view->header()->setResizeMode(QHeaderView::Interactive);

    // Pacs widget ///////////////////////////////////////////////

    QTreeView *pacs_widget = new QTreeView(this);
    pacs_widget->setFrameStyle(QFrame::NoFrame);
    pacs_widget->setAttribute(Qt::WA_MacShowFocusRect, false);
    pacs_widget->setUniformRowHeights(true);
    pacs_widget->setAlternatingRowColors(true);
    pacs_widget->setSortingEnabled(true);

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

    QStackedWidget *stack = new QStackedWidget(this);
    stack->addWidget(database_widget);
    stack->addWidget(d->filesystem_view);
    stack->addWidget(pacs_widget);

    // Source selector ///////////////////////////////////////////////

    QWidget *database_page = new QWidget(this);

    QPushButton *database_page_expand_all_button = new QPushButton("All", database_page);
    QPushButton *database_page_collapse_all_button = new QPushButton("All", database_page);

    connect(database_page_expand_all_button, SIGNAL(clicked()), d->view, SLOT(expandAll()));
    connect(database_page_collapse_all_button, SIGNAL(clicked()), d->view, SLOT(collapseAll()));

    QFormLayout *database_page_layout = new QFormLayout(database_page);
    database_page_layout->addRow("Expand:", database_page_expand_all_button);
    database_page_layout->addRow("Collapse:", database_page_collapse_all_button);
    database_page_layout->setFormAlignment(Qt::AlignHCenter);

    QWidget *filesystem_page = new QWidget(this);

    QPushButton *filesystem_import_button = new QPushButton("Import", filesystem_page);
    QPushButton *filesystem_export_button = new QPushButton("Export", filesystem_page);

    QFormLayout *filesystem_page_layout = new QFormLayout(filesystem_page);
    filesystem_page_layout->addRow("Current item:", filesystem_import_button);
    filesystem_page_layout->addRow("Current item:", filesystem_export_button);
    filesystem_page_layout->setFormAlignment(Qt::AlignHCenter);

    connect(filesystem_import_button, SIGNAL(clicked()), this, SLOT(onFileSystemImportClicked()));
    connect(filesystem_export_button, SIGNAL(clicked()), this, SLOT(onFileSystemExportClicked()));

    QWidget *pacs_page = new QWidget(this);

    QFormLayout *pacs_page_layout = new QFormLayout(pacs_page);
    pacs_page_layout->addRow("Url:", new QLineEdit(pacs_page));
    pacs_page_layout->addRow("Login:", new QLineEdit(pacs_page));
    pacs_page_layout->addRow("Password:", new QLineEdit(pacs_page));
    pacs_page_layout->addWidget(new QPushButton("Connect", pacs_page));
    pacs_page_layout->setFormAlignment(Qt::AlignHCenter);

    medToolBoxTab *tab = new medToolBoxTab(this);
    tab->addTab(database_page, "Db");
    tab->addTab(filesystem_page, "Fs");
    tab->addTab(pacs_page, "Pc");
    connect(tab, SIGNAL(currentChanged(int)), stack, SLOT(setCurrentIndex(int)));

    medToolBox *sourceSelectorToolBox = new medToolBox(this);
    sourceSelectorToolBox->setTitle("Source selector");
    sourceSelectorToolBox->setWidget(tab);

    // Jobs //////////////////////////////////////////

    d->progression_stack = new medProgressionStack(filesystem_page);

    medToolBox *jobsToolBox = new medToolBox(this);
    jobsToolBox->setTitle("Jobs");
    jobsToolBox->setWidget(d->progression_stack);
    jobsToolBox->setVisible(false);

    connect(d->progression_stack, SIGNAL(shown()), jobsToolBox, SLOT(show()));
    connect(d->progression_stack, SIGNAL(hidden()), jobsToolBox, SLOT(hide()));

    // Toolbox container /////////////////////////////////////////////

    d->toolbox_container = new medToolBoxContainer(this);
    d->toolbox_container->setFixedWidth(300);
    d->toolbox_container->addToolBox(sourceSelectorToolBox);
    d->toolbox_container->addToolBox(jobsToolBox);

    // Layout /////////////////////////////////////////////

    QHBoxLayout *layout = new QHBoxLayout(this);
    layout->setContentsMargins(0, 0, 0, 0);
    layout->setSpacing(0);
    layout->addWidget(d->toolbox_container);
    layout->addWidget(stack);
}

medBrowserArea::~medBrowserArea(void)
{
    delete d->preview;
    delete d->model;
    delete d->view;
    delete d;

    d = NULL;
}

void medBrowserArea::setup(QStatusBar *status)
{
    d->status = status;
}

void medBrowserArea::setdw(QStatusBar *status)
{
    d->status = status;
}

medDatabaseView *medBrowserArea::view(void)
{
    return d->view;
}

medDatabaseModel *medBrowserArea::model(void)
{
    return d->model;
}

void medBrowserArea::onFileSystemImportClicked(void)
{
    QFileInfo info(d->filesystem_model->filePath(d->filesystem_view->currentIndex()));

    medDatabaseImporter *importer = new medDatabaseImporter(info.absoluteFilePath());

    connect(importer, SIGNAL(progressed(int)), d->progression_stack, SLOT(setProgress(int)));
    connect(importer, SIGNAL(done()), this, SLOT(onFileImported()));

    d->progression_stack->setLabel(importer, info.baseName());

    QThreadPool::globalInstance()->start(importer);
}

void medBrowserArea::onFileSystemExportClicked(void)
{
    medDatabaseExporter *exporter = new medDatabaseExporter;

    connect(exporter, SIGNAL(progressed(int)), d->progression_stack, SLOT(setProgress(int)));

    QThreadPool::globalInstance()->start(exporter);
}

void medBrowserArea::onFileImported(void)
{
    medDatabaseController::instance()->import("");

    d->preview->reset();
    d->preview->init();
    d->preview->update();
}
<|endoftext|>


<commit_before>#include "HttpSrv.h"

HttpSrv::Connection::Connection(int _sock,
								ResponseInfoPtr _resp_info,
								boost::function<void(int, HttpSrv::RequestPtr)> _onRequest):
		m_sock(_sock),
		alive(true),
		closing(false),
		m_resp_info(_resp_info),
		m_http_status_code(200),
		m_onRequest(_onRequest) {

	http_parser_init(&m_parser, HTTP_REQUEST);
	m_parser.data = (void*)this;
	m_parser_settings.on_message_begin = HttpSrv_onMessageBegin;
	m_parser_settings.on_url = &HttpSrv_onUrl;
	m_parser_settings.on_status = &HttpSrv_onStatus;
	m_parser_settings.on_header_field = &HttpSrv_onHeadersField;
	m_parser_settings.on_header_value = &HttpSrv_onHeadersValue;
	m_parser_settings.on_headers_complete = &HttpSrv_onHeadersComplete;
	m_parser_settings.on_body = &HttpSrv_onBody;
	m_parser_settings.on_message_complete = &HttpSrv_onMessageComplete;
}

HttpSrv::Connection::~Connection() {
	std::cout << "http connection closed\n";
}

void HttpSrv::Connection::setHttpStatus(int _code) {
	m_http_status_code = _code;
}

void HttpSrv::Connection::addHeader(const std::string &_header) {

	m_headers.push_back(_header);
}

void HttpSrv::Connection::setCookie(const std::string &_name, const std::string &_value) {

	m_headers.push_back(std::string("Set-Cookie: ") + _name + "=" + _value + "; expires=Sat, 31 Dec 2039 23:59:59 GMT");
}

void HttpSrv::Connection::sendResponse(const std::string &_content) {

	//Sat, 28 Dec 2013 18:33:30 GMT
	char content_len_c[50];
	sprintf(content_len_c, "%d", (int)_content.size());
	std::string content_len(content_len_c);

	//char time_c[50];
	//sprintf(time_c, "%d", asctime(0));

	char time_c[50];
	sprintf(time_c, "%d", (int)time(0));

	std::string response = "HTTP/1.1 " + inttostr(m_http_status_code) + "\r\n"
						"Content-Type: "+m_resp_info->content_type+"\r\n"
						"Date: "+time_c+"\r\n"
						"Server: "+m_resp_info->server_name+"\r\n"
						//"Connection: keep-alive\r\n"
						"Transfer-Encoding: none\r\n"
						"Access-Control-Allow-Origin: *\r\n"
						"Connection: close\r\n";

	for (int i = 0; i<m_headers.size(); i++)
		response += m_headers[i] + "\r\n";

	response +=	"Content-Length: "+content_len+"\r\n\r\n"+_content;
	size_t nsent = ::send(m_sock, response.c_str(), response.size(), 0);

	std::cout << "send: " << response << std::endl;

	if (nsent<=0 || nsent < response.size())
		std::cout << "HttpSrv::Connection::sendResponse SEND ERROR!!_____________"
				<< nsent << std::endl;
}

void HttpSrv::Connection::close() {
	std::cout << "HttpSrv::Connection::close\n";
	closing = true;
}

int HttpSrv::Connection::getSock() {

	return m_sock;
}

void HttpSrv::Connection::performRecv() {

	std::string readbf;
	char bf[2049];
	int nread = ::recv(m_sock, bf, 2048, MSG_DONTWAIT);

	while (true) {
		if (nread > 0) {

			bf[ nread ] = '\0';
			std::string add (bf);
			readbf.append( add );
			nread = ::recv(m_sock, bf, 2048, MSG_DONTWAIT);
		}
		else if (errno == EWOULDBLOCK || errno == EAGAIN) {

			//std::cout << "HttpSrv::Connection::recv EWOULDBLOCK || EAGAIN\n";
			break;
		}
		else if (errno == EBADF) {
			std::cout << "HttpSrv::Connection::recv EBADF\n";
			break;
		} else if (errno == ECONNREFUSED) {
			std::cout << "HttpSrv::Connection::recv ECONNREFUSED\n";
			break;
		} else if (errno == EFAULT) {
			std::cout << "HttpSrv::Connection::recv EFAULT\n";
			break;
		} else if (errno == EINTR) {
			std::cout << "HttpSrv::Connection::recv EINTR\n";
			break;
		} else if (errno == EINVAL) {
			std::cout << "HttpSrv::Connection::recv EINVAL\n";
			break;
		} else if (errno == ENOMEM) {
			std::cout << "HttpSrv::Connection::recv ENOMEM\n";
			break;
		} else if (errno == ENOTCONN) {
			std::cout << "HttpSrv::Connection::recv ENOTCONN\n";
			break;
		} else if (errno == ENOTSOCK) {
			std::cout << "HttpSrv::Connection::recv ENOTSOCK\n";
			break;
		} else if (nread == 0) {
			break;
		}
	}

	//std::cout << "recv: " << readbf << std::endl;
	//m_readbf += std::string(bf);
	if (readbf.size() > 0) {
		m_req_text += readbf;
		std::cout << m_req_text << std::endl;
		http_parser_execute(&m_parser, &m_parser_settings, readbf.c_str(), readbf.size());
	}
}

void HttpSrv::Connection::performSend() {

}
<commit_msg>Fix http connection closing<commit_after>#include "HttpSrv.h"

HttpSrv::Connection::Connection(int _sock,
								ResponseInfoPtr _resp_info,
								boost::function<void(int, HttpSrv::RequestPtr)> _onRequest):
		m_sock(_sock),
		alive(true),
		closing(false),
		m_resp_info(_resp_info),
		m_http_status_code(200),
		m_onRequest(_onRequest) {

	http_parser_init(&m_parser, HTTP_REQUEST);
	m_parser.data = (void*)this;
	m_parser_settings.on_message_begin = HttpSrv_onMessageBegin;
	m_parser_settings.on_url = &HttpSrv_onUrl;
	m_parser_settings.on_status = &HttpSrv_onStatus;
	m_parser_settings.on_header_field = &HttpSrv_onHeadersField;
	m_parser_settings.on_header_value = &HttpSrv_onHeadersValue;
	m_parser_settings.on_headers_complete = &HttpSrv_onHeadersComplete;
	m_parser_settings.on_body = &HttpSrv_onBody;
	m_parser_settings.on_message_complete = &HttpSrv_onMessageComplete;
}

HttpSrv::Connection::~Connection() {
	std::cout << "http connection closed\n";
}

void HttpSrv::Connection::setHttpStatus(int _code) {
	m_http_status_code = _code;
}

void HttpSrv::Connection::addHeader(const std::string &_header) {

	m_headers.push_back(_header);
}

void HttpSrv::Connection::setCookie(const std::string &_name, const std::string &_value) {

	m_headers.push_back(std::string("Set-Cookie: ") + _name + "=" + _value + "; expires=Sat, 31 Dec 2039 23:59:59 GMT");
}

void HttpSrv::Connection::sendResponse(const std::string &_content) {

	//Sat, 28 Dec 2013 18:33:30 GMT
	char content_len_c[50];
	sprintf(content_len_c, "%d", (int)_content.size());
	std::string content_len(content_len_c);

	//char time_c[50];
	//sprintf(time_c, "%d", asctime(0));

	char time_c[50];
	sprintf(time_c, "%d", (int)time(0));

	std::string response = "HTTP/1.1 " + inttostr(m_http_status_code) + "\r\n"
						"Content-Type: "+m_resp_info->content_type+"\r\n"
						"Date: "+time_c+"\r\n"
						"Server: "+m_resp_info->server_name+"\r\n"
						//"Connection: keep-alive\r\n"
						"Transfer-Encoding: none\r\n"
						"Access-Control-Allow-Origin: *\r\n"
						"Connection: close\r\n";

	for (int i = 0; i<m_headers.size(); i++)
		response += m_headers[i] + "\r\n";

	response +=	"Content-Length: "+content_len+"\r\n\r\n"+_content;
	size_t nsent = ::send(m_sock, response.c_str(), response.size(), 0);

	std::cout << "send: " << response << std::endl;

	if (nsent<=0 || nsent < response.size())
		std::cout << "HttpSrv::Connection::sendResponse SEND ERROR!!_____________"
				<< nsent << std::endl;
}

void HttpSrv::Connection::close() {
	std::cout << "HttpSrv::Connection::close\n";
	closing = true;
}

int HttpSrv::Connection::getSock() {

	return m_sock;
}

void HttpSrv::Connection::performRecv() {

	std::string readbf;
	char bf[2049];
	int nread = ::recv(m_sock, bf, 2048, MSG_DONTWAIT);

	while (true) {
		if (nread > 0) {

			bf[ nread ] = '\0';
			std::string add (bf);
			readbf.append( add );
			nread = ::recv(m_sock, bf, 2048, MSG_DONTWAIT);
		}
		else if (errno == EWOULDBLOCK || errno == EAGAIN) {

			//std::cout << "HttpSrv::Connection::recv EWOULDBLOCK || EAGAIN\n";
			break;
		}
		else if (errno == EBADF) {

			std::cout << "HttpSrv::Connection::recv EBADF\n";
			close();
			return;
		} else if (errno == ECONNREFUSED) {
			std::cout << "HttpSrv::Connection::recv ECONNREFUSED\n";
			close();
			return;
		} else if (errno == EFAULT) {
			std::cout << "HttpSrv::Connection::recv EFAULT\n";
			close();
			return;
		} else if (errno == EINTR) {
			std::cout << "HttpSrv::Connection::recv EINTR\n";
			close();
			return;
		} else if (errno == EINVAL) {
			std::cout << "HttpSrv::Connection::recv EINVAL\n";
			close();
			return;
		} else if (errno == ENOMEM) {
			std::cout << "HttpSrv::Connection::recv ENOMEM\n";
			close();
			return;
		} else if (errno == ENOTCONN) {
			std::cout << "HttpSrv::Connection::recv ENOTCONN\n";
			close();
			return;
		} else if (errno == ENOTSOCK) {
			std::cout << "HttpSrv::Connection::recv ENOTSOCK\n";
			close();
			return;
		} else if (nread == 0) {
			break;
		}
	}

	//std::cout << "recv: " << readbf << std::endl;
	//m_readbf += std::string(bf);
	if (readbf.size() > 0) {
		m_req_text += readbf;
		std::cout << m_req_text << std::endl;
		http_parser_execute(&m_parser, &m_parser_settings, readbf.c_str(), readbf.size());
	}
}

void HttpSrv::Connection::performSend() {

}
<|endoftext|>


<commit_before>// IFC SDK : IFC2X3 C++ Early Classes
// Copyright (C) 2009 CSTB
//
// 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.
// The full license is in Licence.txt file included with this
// distribution or is available at :
//     http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html
//
// 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.

#include <ifc2x3/SPFReader.h>
#include <ifc2x3/SPFWriter.h>
#include <ifc2x3/ExpressDataSet.h>
#include <ifc2x3/IfcProject.h>
#include <ifc2x3/IfcLocalPlacement.h>
#include <ifc2x3/IfcAxis2Placement.h>
#include <ifc2x3/IfcAxis2Placement2D.h>
#include <ifc2x3/IfcAxis2Placement3D.h>

#include <Step/CallBack.h>

#include <iostream>

#include "BrepBuilder.h"

class ConsoleCallBack : public Step::CallBack
{
public:
    ConsoleCallBack() : _max(1) {}
    virtual void setMaximum(size_t max) { _max = max; }
    virtual void setProgress(size_t progress) { std::cerr << double(progress)/double(_max)*100.0 << "%" << std::endl; }
protected:
    size_t _max;
};

int main(int argc, char **argv)
{
    std::cout << "Simple read Brep geometry example of Ifc2x3 SDK" << std::endl;

    if (argc < 2)
    {
        std::cout << "no ifc file to read in command line ." << std::endl;
        return 1;
    }

    bool inMemory = true;
    if (argc < 4)
    {
        inMemory = false;
    }

    // ** open, load, close the file
    std::ifstream ifcFile;
    ifcFile.open(argv[1]);

    ifc2x3::SPFReader reader;
    ConsoleCallBack cb;
    reader.setCallBack(&cb);

    if ( ifcFile.is_open() )
    {
        std::cout << "reading file ..." << std::endl;
    }
    else
    {
        std::cout << "ERROR: failed to open <" << argv[1] << ">" << std::endl;
        return 1;
    }

    // get length of file
    ifcFile.seekg (0, ifcFile.end);
    std::ifstream::pos_type length = ifcFile.tellg();
    ifcFile.seekg (0, ifcFile.beg);

    bool result = reader.read(ifcFile, inMemory ? length : (std::ifstream::pos_type)0);
    ifcFile.close();

    if (result)
        std::cout << "OK!!" << std::endl;
    else
    {
        std::cout << "Ho no, there is a PROBLEM!!" << std::endl;
        std::vector<std::string> errors = reader.errors();
        std::vector<std::string>::iterator it = errors.begin();
        while(it != errors.end())
        {
            std::cout << *it << std::endl;
            ++it;
        }

        return 1;
    }

    // ** get the model
    ifc2x3::ExpressDataSet * expressDataSet = dynamic_cast<ifc2x3::ExpressDataSet*>(reader.getExpressDataSet());

    if (expressDataSet == NULL)
    {
        std::cout << "Ho no ... there is no ExpressDataSet." << std::endl;
        return (2);
    }

    // ** Instantiate the model
    expressDataSet->instantiateAll();

    // ** Check the root of the model
    Step::RefLinkedList< ifc2x3::IfcProject > projects = expressDataSet->getAllIfcProject();
    if ( projects.size() == 0 ) {
        std::cout << "Strange ... there is no IfcProject" << std::endl;
    } else if ( projects.size() > 1 ) {
        std::cout << "Strange ... there more than one IfcProject" << std::endl;
    } else {
        Step::RefPtr< ifc2x3::IfcProject > project = &*(projects.begin());
        std::cout << "Project name is: " << project->getName().toISO_8859(Step::String::Western_European) << std::endl;
        if ( Step::isUnset(project->getLongName().toISO_8859(Step::String::Western_European) ) ) {
            project->setLongName("Je lui donne le nom que je veux");
        }
        std::cout << "Project long name is: " << project->getLongName().toISO_8859(Step::String::Western_European)  << std::endl;
    }

 return 0;
}
<commit_msg>start to add visitor<commit_after>// IFC SDK : IFC2X3 C++ Early Classes
// Copyright (C) 2009 CSTB
//
// 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.
// The full license is in Licence.txt file included with this
// distribution or is available at :
//     http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html
//
// 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.

#include <ifc2x3/SPFReader.h>
#include <ifc2x3/SPFWriter.h>
#include <ifc2x3/ExpressDataSet.h>
#include <ifc2x3/IfcProject.h>
#include <ifc2x3/IfcLocalPlacement.h>
#include <ifc2x3/IfcAxis2Placement.h>
#include <ifc2x3/IfcAxis2Placement2D.h>
#include <ifc2x3/IfcAxis2Placement3D.h>

#include <Step/CallBack.h>

#include <iostream>

#include "BrepBuilder.h"
#include "BrepReaderVisitor.h"

class ConsoleCallBack : public Step::CallBack
{
public:
    ConsoleCallBack() : _max(1) {}
    virtual void setMaximum(size_t max) { _max = max; }
    virtual void setProgress(size_t progress) { std::cerr << double(progress)/double(_max)*100.0 << "%" << std::endl; }
protected:
    size_t _max;
};

int main(int argc, char **argv)
{
    std::cout << "Simple read Brep geometry example of Ifc2x3 SDK" << std::endl;

    if (argc < 2)
    {
        std::cout << "no ifc file to read in command line ." << std::endl;
        return 1;
    }

    bool inMemory = true;
    if (argc < 4)
    {
        inMemory = false;
    }

    // ** open, load, close the file
    std::ifstream ifcFile;
    ifcFile.open(argv[1]);

    ifc2x3::SPFReader reader;
    ConsoleCallBack cb;
    reader.setCallBack(&cb);

    if ( ifcFile.is_open() )
    {
        std::cout << "reading file ..." << std::endl;
    }
    else
    {
        std::cout << "ERROR: failed to open <" << argv[1] << ">" << std::endl;
        return 1;
    }

    // get length of file
    ifcFile.seekg (0, ifcFile.end);
    std::ifstream::pos_type length = ifcFile.tellg();
    ifcFile.seekg (0, ifcFile.beg);

    bool result = reader.read(ifcFile, inMemory ? length : (std::ifstream::pos_type)0);
    ifcFile.close();

    if (result)
        std::cout << "OK!!" << std::endl;
    else
    {
        std::cout << "Ho no, there is a PROBLEM!!" << std::endl;
        std::vector<std::string> errors = reader.errors();
        std::vector<std::string>::iterator it = errors.begin();
        while(it != errors.end())
        {
            std::cout << *it << std::endl;
            ++it;
        }

        return 1;
    }

    // ** get the model
    ifc2x3::ExpressDataSet * expressDataSet = dynamic_cast<ifc2x3::ExpressDataSet*>(reader.getExpressDataSet());

    if (expressDataSet == NULL)
    {
        std::cout << "Ho no ... there is no ExpressDataSet." << std::endl;
        return (2);
    }

    // ** Instantiate the model
    expressDataSet->instantiateAll();

    // ** Get buildingElement
    Step::RefLinkedList< ifc2x3::IfcBuildingElement > elements = expressDataSet->getAllIfcBuildingElement();
    if ( elements.size() == 0 )
    {
        std::cout << "Strange ... there is no IfcBuildingElement" << std::endl;
    }
    else
    {
        Step::RefPtr< ifc2x3::IfcBuildingElement > element = &*(elements.begin());
        Step::RefLinkedList_iterator<ifc2x3::IfcBuildingElement> it,end;

        it = expressDataSet->getAllIfcBuildingElement().begin();
        end = expressDataSet->getAllIfcBuildingElement().end();

        while (it != end)
        {
            BrepReaderVisitor visitor();
            //(*it).acceptVisitor(&visitor);
            ++it;
        }
    }

 return 0;
}
<|endoftext|>


<commit_before>// @(#)root/eve:$Id$
// Author: Matevz Tadel 2007

/**************************************************************************
 * Copyright(c) 1998-2008, ALICE Experiment at CERN, all rights reserved. *
 * See http://aliceinfo.cern.ch/Offline/AliRoot/License.html for          *
 * full copyright notice.                                                 *
 **************************************************************************/

#include "AliEveV0Editor.h"
#include "AliEveV0.h"

#include "TVirtualPad.h"
#include "TColor.h"

// Cleanup these includes:
#include "TGLabel.h"
#include "TGButton.h"
#include "TGNumberEntry.h"
#include "TGColorSelect.h"
#include "TGDoubleSlider.h"

//______________________________________________________________________________
// GUI editor for AliEveV0.
//

ClassImp(AliEveV0Editor)

//______________________________________________________________________________
AliEveV0Editor::AliEveV0Editor(const TGWindow *p, Int_t width, Int_t height,
                               UInt_t options, Pixel_t back) :
  TGedFrame(p, width, height, options | kVerticalFrame, back),
  fM(0),
  fInfoLabel0(0),
  fInfoLabel1(0),
  fInfoLabelNegDaughter(0),
  fInfoLabelPosDaughter(0),
  fXButton(0)
  // Initialize widget pointers to 0
{
  // Constructor.

  MakeTitle("AliEveV0");

  fInfoLabel0 = new TGLabel(this);
  fInfoLabel0->SetTextJustify(kTextLeft);
  AddFrame(fInfoLabel0, new TGLayoutHints(kLHintsLeft|kLHintsExpandX,
                                          8, 0, 2, 0));

  fInfoLabel1 = new TGLabel(this);
  fInfoLabel1->SetTextJustify(kTextLeft);
  AddFrame(fInfoLabel1, new TGLayoutHints(kLHintsLeft|kLHintsExpandX,
                                          8, 0, 2, 0));

  fInfoLabelNegDaughter = new TGLabel(this);
  fInfoLabelNegDaughter->SetTextJustify(kTextLeft);
  AddFrame(fInfoLabelNegDaughter, new TGLayoutHints(kLHintsLeft|kLHintsExpandX,
						    8, 0, 2, 0));

  fInfoLabelPosDaughter = new TGLabel(this);
  fInfoLabelPosDaughter->SetTextJustify(kTextLeft);
  AddFrame(fInfoLabelPosDaughter, new TGLayoutHints(kLHintsLeft|kLHintsExpandX,
						    8, 0, 2, 0));

  fXButton = new TGTextButton(this, "Detailed View");
  AddFrame(fXButton, new TGLayoutHints(kLHintsLeft|kLHintsExpandX, 1, 1, 0, 0));
  fXButton->Connect("Clicked()", "AliEveV0Editor", this, "DisplayDetailed()");
}

/******************************************************************************/

//______________________________________________________________________________
void AliEveV0Editor::SetModel(TObject* obj)
{
  // Set model object.

  fM = dynamic_cast<AliEveV0*>(obj);

  // Set values of widgets
  fInfoLabel0->SetText(Form("Radius = %f, DCA = %f", fM->GetRadius(), fM->GetDaughterDCA()));
  fInfoLabel1->SetText(Form("Pt = %f", fM->GetPt()));
  fInfoLabelNegDaughter->SetText(Form("Neg. Daughter Prob= %.2f for Pdg= %d", fM->GetNegMaxProbPid(), fM->GetNegMaxProbPdg()));
  fInfoLabelPosDaughter->SetText(Form("Pos. Daughter Prob= %.2f for Pdg= %d", fM->GetPosMaxProbPid(), fM->GetPosMaxProbPdg()));

}

/******************************************************************************/

// Implements callback/slot methods

//______________________________________________________________________________
// void AliEveV0Editor::DoXYZZ()
// {
//    // Slot for XYZZ.
//
//    fM->SetXYZZ(fXYZZ->GetValue());
//    Update();
// }

#include <TEveManager.h>
#include <TEveWindow.h>
#include <TEveViewer.h>
#include <TEveScene.h>
#include <TEveGeoNode.h>
#include <TEveProjectionManager.h>

#include <TGLCamera.h>
#include <TGLViewer.h>
#include "TGLCameraOverlay.h"

#include <TLatex.h>
#include <TRootEmbeddedCanvas.h>
#include <TInterpreter.h>

void AliEveV0Editor::DisplayDetailed()
{
  TEveWindowSlot *slot = TEveWindow::CreateWindowMainFrame();
  TEveWindowPack *pack = slot->MakePack();
  pack->SetShowTitleBar(kFALSE);
  pack->SetHorizontal();

  //
  // This part is for getting the different objects to display
  //
  char displayInfo[100] = {0};
  sprintf(displayInfo,"pt = %.3f",fM->GetPt());
  TEveLine *lv0TransverseMomentumDirection = new TEveLine(displayInfo);
  lv0TransverseMomentumDirection->SetLineColor(kOrange+8);
  lv0TransverseMomentumDirection->SetLineWidth(2);
  lv0TransverseMomentumDirection->SetLineStyle(2);
  lv0TransverseMomentumDirection->SetLineWidth(2);
  Float_t scalePt = 100.; // this needs to be available as a ruler
  lv0TransverseMomentumDirection->SetPoint(0,fM->fRecDecayV.fX, fM->fRecDecayV.fY, fM->fRecDecayV.fZ);
  lv0TransverseMomentumDirection->SetPoint(1,scalePt*fM->fRecDecayP.fX, scalePt*fM->fRecDecayP.fY,0);

  TEvePointSet *pvlocation = new TEvePointSet("PV location");
  pvlocation->SetNextPoint(fM->fRecBirthV.fX, fM->fRecBirthV.fY, fM->fRecBirthV.fZ);
  pvlocation->SetTitle("pv location");
  pvlocation->SetMarkerStyle(4);
  pvlocation->SetMarkerSize(2.5);
  pvlocation->SetMarkerColor(7);

  TEvePointSet *v0location = new TEvePointSet("V0 location");
  v0location->SetNextPoint(fM->fRecDecayV.fX, fM->fRecDecayV.fY, fM->fRecDecayV.fZ);
  v0location->SetTitle("v0 location");
  v0location->SetMarkerStyle(4);
  v0location->SetMarkerSize(2.5);
  v0location->SetMarkerColor(kOrange+8);

  //
  // This part is for the bending plane view
  //
  pack->NewSlot()->MakeCurrent();
  TEveViewer *bpViewer = gEve->SpawnNewViewer("V0 bending plane View");
  TEveScene  *bpScene  = gEve->SpawnNewScene("V0 bending plane Scene");

  TEveUtil::LoadMacro("geom_gentle.C");
  Long_t result = gInterpreter->ProcessLine("geom_gentle_rphi()");
  if (result)
  {
    TEveGeoShape *geomRPhi = reinterpret_cast<TEveGeoShape*>(result);
    geomRPhi->IncDenyDestroy();
    TEveProjectionManager *projMgr = new TEveProjectionManager();
    projMgr->ImportElements(geomRPhi, bpScene);
  }
  else
  {
    Warning("DisplayDetailed", "Import of R-Phi geometry failed.");
  }

  bpViewer->AddScene(bpScene);
  bpScene->AddElement(fM);
  bpScene->AddElement(lv0TransverseMomentumDirection);
  bpScene->AddElement(pvlocation);
  bpScene->AddElement(v0location);

  // This is the to-do list for the bending plane:
  // 1. fix the view to orthographic XOY (no rotation allowed but moving the center ok) ->done!
  // 2. show axis and tickles along X and Y ->done!
  //       -> note for the projection the cartesian scales are not very useful
  //       -> propose a phi and R scale which rotates with a reset at 0;
  //       -> propose a transformation for an eta scale (keep the z one);
  // 3. show the center, the main vertex and the detectors for this view ->done!
  // 4. show V0 direction in the bending plane with arrow length proportional to pT ->done!
  // 5. show angles with respect to axis (phi angle) ->almost.
  // 6. show clusters in the ITS and in the TPC associated with the daughter tracks
  //       -> include a radius cut for plotting only ITS and TPC
  bpViewer->GetGLViewer()->SetCurrentCamera(TGLViewer::kCameraOrthoXOY);
  bpViewer->GetGLViewer()->ResetCamerasAfterNextUpdate();
  TGLViewer *lbpGLViewer = bpViewer->GetGLViewer();
  TGLCameraOverlay* co = lbpGLViewer->GetCameraOverlay();
  co->SetShowOrthographic(true); //(false);
  co->SetOrthographicMode(TGLCameraOverlay::kAxis); // ::kPlaneIntersect or ::kBar
  // end of the bending plane part

  //
  // This part is for the decay plane view
  //
  pack->NewSlot()->MakeCurrent();
  TEveViewer *dpViewer = gEve->SpawnNewViewer("V0 decay plane View");
  TEveScene  *dpScene  = gEve->SpawnNewScene("V0 decay plane Scene");

  dpViewer->AddScene(dpScene);

  result = gInterpreter->ProcessLine("geom_gentle(kFALSE)");
  if (result)
  {
    TEveGeoShape *geom = reinterpret_cast<TEveGeoShape*>(result);
    geom->IncDenyDestroy();
    geom->FindChild("TRD+TOF")->SetRnrState(kFALSE);
    geom->FindChild("PHOS")   ->SetRnrState(kFALSE);
    geom->FindChild("HMPID")  ->SetRnrState(kFALSE);
    dpScene->AddElement(geom);
  }
  else
  {
    Warning("DisplayDetailed", "Import of 3D geometry failed.");
  }

  dpScene->AddElement(fM);
  dpScene->AddElement(lv0TransverseMomentumDirection);
  dpScene->AddElement(pvlocation);
  dpScene->AddElement(v0location);

  // This is the to-do list for the decay plane:
  // 1. fix the view to decay plane (no rotation allowed but moving the center ok)
  // 2. show V0 direction with a vertical arrow length proportional to pT -> done!
  // 3. show the center, the main vertex and the detectors for this view -> done!
  // 4. show the x,y and z axis and the different angles
  //       -> this needs a referential object that we can move around
  //          or fix to a selected point (origin being the default)
  // 5. draw the dca between daughters and the extrapolation to the main vertex.
  //       -> this is an issue since we only store the distance: check with J.Belikov
  // 6. show clusters in the ITS and in the TPC associated with the daughter tracks
  //       -> include a radius cut for plotting only ITS and TPC
  dpViewer->GetGLViewer()->ResetCamerasAfterNextUpdate();
  TGLCamera& dpCam = dpViewer->GetGLViewer()->CurrentCamera();
  dpCam.SetExternalCenter(kTRUE);
  dpCam.SetCenterVec(fM->fRecDecayV.fX, fM->fRecDecayV.fY, fM->fRecDecayV.fZ);
  // end of the decay plane part

  //
  // This part is for displaying the information
  //
  slot = pack->NewSlot();

  TEveWindowFrame *frame = slot->MakeFrame(new TRootEmbeddedCanvas());
  frame->SetElementName("Details");

  // Print and show detailed information about the V0
  // Calculation of the invariant mass with the max prob PID hypothesis first
  // pseudorapidity, phi angle, pt, radius, dcas
  char info[100] = {0};
  sprintf(info,"#phi = %.3frad = %.1f",fM->GetPhi(),57.296*fM->GetPhi());
  TLatex* ltx = new TLatex(0.05, 0.9, info);
  ltx->SetTextSize(0.08);
  ltx->Draw();

  sprintf(info,"radius = %.3f [cm]",fM->GetRadius());
  ltx->DrawLatex(0.05, 0.8, info);

  sprintf(info,"p_{T} = %.3f [GeV/c]",fM->GetPt());
  ltx->DrawLatex(0.05, 0.7, info);

  sprintf(info,"daughters dca = %.3f [cm]",fM->GetDaughterDCA());
  ltx->DrawLatex(0.05, 0.6, info);

  sprintf(info,"#eta = - ln( tan(#theta/2) ) = %.3f",fM->GetEta());
  ltx->DrawLatex(0.05, 0.5, info);

  sprintf(info,"mass_{K^{0}_{s}} = %.3f [GeV/c^{2}]",fM->GetK0sInvMass());
  ltx->DrawLatex(0.05, 0.3, info);

  sprintf(info,"mass_{#Lambda} = %.3f [GeV/c^{2}]",fM->GetLambdaInvMass());
  ltx->DrawLatex(0.05, 0.2, info);

  sprintf(info,"mass_{#bar{#Lambda}} = %.3f [GeV/c^{2}]",fM->GetAntiLambdaInvMass());
  ltx->DrawLatex(0.05, 0.1, info);

  gEve->Redraw3D();
}
<commit_msg>From Boris: add clusters associated with V0 daughters to the detailed view. Some cleanup.<commit_after>// @(#)root/eve:$Id$
// Author: Matevz Tadel 2007

/**************************************************************************
 * Copyright(c) 1998-2008, ALICE Experiment at CERN, all rights reserved. *
 * See http://aliceinfo.cern.ch/Offline/AliRoot/License.html for          *
 * full copyright notice.                                                 *
 **************************************************************************/

#include "AliEveV0Editor.h"
#include "AliEveV0.h"

#include "TVirtualPad.h"
#include "TColor.h"

// Cleanup these includes:
#include "TGLabel.h"
#include "TGButton.h"
#include "TGNumberEntry.h"
#include "TGColorSelect.h"
#include "TGDoubleSlider.h"

//______________________________________________________________________________
// GUI editor for AliEveV0.
//

ClassImp(AliEveV0Editor)

//______________________________________________________________________________
AliEveV0Editor::AliEveV0Editor(const TGWindow *p, Int_t width, Int_t height,
                               UInt_t options, Pixel_t back) :
  TGedFrame(p, width, height, options | kVerticalFrame, back),
  fM(0),
  fInfoLabel0(0),
  fInfoLabel1(0),
  fInfoLabelNegDaughter(0),
  fInfoLabelPosDaughter(0),
  fXButton(0)
  // Initialize widget pointers to 0
{
  // Constructor.

  MakeTitle("AliEveV0");

  fInfoLabel0 = new TGLabel(this);
  fInfoLabel0->SetTextJustify(kTextLeft);
  AddFrame(fInfoLabel0, new TGLayoutHints(kLHintsLeft|kLHintsExpandX,
                                          8, 0, 2, 0));

  fInfoLabel1 = new TGLabel(this);
  fInfoLabel1->SetTextJustify(kTextLeft);
  AddFrame(fInfoLabel1, new TGLayoutHints(kLHintsLeft|kLHintsExpandX,
                                          8, 0, 2, 0));

  fInfoLabelNegDaughter = new TGLabel(this);
  fInfoLabelNegDaughter->SetTextJustify(kTextLeft);
  AddFrame(fInfoLabelNegDaughter, new TGLayoutHints(kLHintsLeft|kLHintsExpandX,
						    8, 0, 2, 0));

  fInfoLabelPosDaughter = new TGLabel(this);
  fInfoLabelPosDaughter->SetTextJustify(kTextLeft);
  AddFrame(fInfoLabelPosDaughter, new TGLayoutHints(kLHintsLeft|kLHintsExpandX,
						    8, 0, 2, 0));

  fXButton = new TGTextButton(this, "Detailed View");
  AddFrame(fXButton, new TGLayoutHints(kLHintsLeft|kLHintsExpandX, 1, 1, 0, 0));
  fXButton->Connect("Clicked()", "AliEveV0Editor", this, "DisplayDetailed()");
}

/******************************************************************************/

//______________________________________________________________________________
void AliEveV0Editor::SetModel(TObject* obj)
{
  // Set model object.

  fM = dynamic_cast<AliEveV0*>(obj);

  // Set values of widgets
  fInfoLabel0->SetText(Form("Radius = %f, DCA = %f", fM->GetRadius(), fM->GetDaughterDCA()));
  fInfoLabel1->SetText(Form("Pt = %f", fM->GetPt()));
  fInfoLabelNegDaughter->SetText(Form("Neg. Daughter Prob= %.2f for Pdg= %d", fM->GetNegMaxProbPid(), fM->GetNegMaxProbPdg()));
  fInfoLabelPosDaughter->SetText(Form("Pos. Daughter Prob= %.2f for Pdg= %d", fM->GetPosMaxProbPid(), fM->GetPosMaxProbPdg()));

}

/******************************************************************************/

// Implements callback/slot methods

//______________________________________________________________________________
// void AliEveV0Editor::DoXYZZ()
// {
//    // Slot for XYZZ.
//
//    fM->SetXYZZ(fXYZZ->GetValue());
//    Update();
// }

#include <TEveManager.h>
#include <TEveWindow.h>
#include <TEveViewer.h>
#include <TEveScene.h>
#include <TEveGeoNode.h>
#include <TEveProjectionManager.h>

#include <TGLCamera.h>
#include <TGLViewer.h>
#include "TGLCameraOverlay.h"

#include <TLatex.h>
#include <TRootEmbeddedCanvas.h>
#include <TInterpreter.h>

void AliEveV0Editor::DisplayDetailed()
{
  TEveWindowSlot *slot = TEveWindow::CreateWindowMainFrame();
  TEveWindowPack *pack = slot->MakePack();
  pack->SetShowTitleBar(kFALSE);
  pack->SetHorizontal();

  //
  // This part is for getting the different objects to display
  //
  char displayInfo[100] = {0};
  sprintf(displayInfo,"pt = %.3f",fM->GetPt());
  TEveLine *lv0TransverseMomentumDirection = new TEveLine(displayInfo);
  lv0TransverseMomentumDirection->SetLineColor(kOrange+8);
  lv0TransverseMomentumDirection->SetLineWidth(2);
  lv0TransverseMomentumDirection->SetLineStyle(2);
  lv0TransverseMomentumDirection->SetLineWidth(2);
  Float_t scalePt = 100.; // this needs to be available as a ruler
  lv0TransverseMomentumDirection->SetPoint(0,fM->fRecDecayV.fX, fM->fRecDecayV.fY, fM->fRecDecayV.fZ);
  lv0TransverseMomentumDirection->SetPoint(1,scalePt*fM->fRecDecayP.fX, scalePt*fM->fRecDecayP.fY,0);

  TEvePointSet *pvlocation = new TEvePointSet("PV location");
  pvlocation->SetNextPoint(fM->fRecBirthV.fX, fM->fRecBirthV.fY, fM->fRecBirthV.fZ);
  pvlocation->SetTitle("pv location");
  pvlocation->SetMarkerStyle(4);
  pvlocation->SetMarkerSize(2.5);
  pvlocation->SetMarkerColor(7);

  TEvePointSet *v0location = new TEvePointSet("V0 location");
  v0location->SetNextPoint(fM->fRecDecayV.fX, fM->fRecDecayV.fY, fM->fRecDecayV.fZ);
  v0location->SetTitle("v0 location");
  v0location->SetMarkerStyle(4);
  v0location->SetMarkerSize(2.5);
  v0location->SetMarkerColor(kOrange+8);

  TEveUtil::LoadMacro("clusters_from_index.C");

  TEveTrack *negTrack = fM->GetNegTrack();
  TEveTrack *posTrack = fM->GetPosTrack();

  char macroWithIndex[100] = {0};
  Int_t daughterIndex = 0;
  TEvePointSet *negDaughterCluster = 0;
  TEvePointSet *posDaughterCluster = 0;

  daughterIndex = negTrack->GetIndex();
  sprintf(macroWithIndex,"clusters_from_index(%d)",daughterIndex);
  Long_t negResult = gInterpreter->ProcessLine(macroWithIndex);
  if (negResult) {
    negDaughterCluster = reinterpret_cast<TEvePointSet*>(negResult);
    if (negDaughterCluster){
      negDaughterCluster->SetMarkerStyle(4);
      negDaughterCluster->SetMarkerSize(1.5);
      negDaughterCluster->SetMarkerColor(kBlue+3);
    }
  }
  else
  {
    Warning("DisplayDetailed", "Import of negative daughter's clusters failed.");
  }

  daughterIndex = posTrack->GetIndex();
  sprintf(macroWithIndex,"clusters_from_index(%d)",daughterIndex);
  Long_t posResult = gInterpreter->ProcessLine(macroWithIndex);
  if (posResult) {
    posDaughterCluster = reinterpret_cast<TEvePointSet*>(posResult);
    if (posDaughterCluster){
      posDaughterCluster->SetMarkerStyle(4);
      posDaughterCluster->SetMarkerSize(1.5);
      posDaughterCluster->SetMarkerColor(kRed+3);
    }
  }
  else
  {
    Warning("DisplayDetailed", "Import of positive daughter's clusters failed.");
  }

  //
  // This part is for the bending plane view
  //
  pack->NewSlot()->MakeCurrent();
  TEveViewer *bpViewer = gEve->SpawnNewViewer("V0 bending plane View");
  TEveScene  *bpScene  = gEve->SpawnNewScene("V0 bending plane Scene");

  TEveUtil::LoadMacro("geom_gentle.C");
  Long_t result = gInterpreter->ProcessLine("geom_gentle_rphi()");
  if (result)
  {
    TEveGeoShape *geomRPhi = reinterpret_cast<TEveGeoShape*>(result);
    geomRPhi->IncDenyDestroy();
    TEveProjectionManager *projMgr = new TEveProjectionManager();
    projMgr->ImportElements(geomRPhi, bpScene);
  }
  else
  {
    Warning("DisplayDetailed", "Import of R-Phi geometry failed.");
  }

  bpViewer->AddScene(bpScene);
  bpScene->AddElement(fM);
  bpScene->AddElement(lv0TransverseMomentumDirection);
  bpScene->AddElement(pvlocation);
  bpScene->AddElement(v0location);

  if (negDaughterCluster) bpScene->AddElement(negDaughterCluster);
  if (posDaughterCluster) bpScene->AddElement(posDaughterCluster);

  // This is the to-do list for the bending plane:
  // 1. fix the view to orthographic XOY (no rotation allowed but moving the center ok) ->done!
  // 2. show axis and tickles along X and Y ->done!
  //       -> note for the projection the cartesian scales are not very useful
  //       -> propose a phi and R scale which rotates with a reset at 0;
  //       -> propose a transformation for an eta scale (keep the z one);
  // 3. show the center, the main vertex and the detectors for this view ->done!
  // 4. show V0 direction in the bending plane with arrow length proportional to pT ->done!
  // 5. show angles with respect to axis (phi angle) ->almost.
  // 6. show clusters in the ITS and in the TPC associated with the daughter tracks
  //       -> include a radius cut for plotting only ITS and TPC ->done!
  bpViewer->GetGLViewer()->SetCurrentCamera(TGLViewer::kCameraOrthoXOY);
  bpViewer->GetGLViewer()->ResetCamerasAfterNextUpdate();
  TGLViewer *lbpGLViewer = bpViewer->GetGLViewer();
  TGLCameraOverlay* co = lbpGLViewer->GetCameraOverlay();
  co->SetShowOrthographic(true); //(false);
  co->SetOrthographicMode(TGLCameraOverlay::kAxis); // ::kPlaneIntersect or ::kBar
  // end of the bending plane part

  //
  // This part is for the decay plane view
  //
  pack->NewSlot()->MakeCurrent();
  TEveViewer *dpViewer = gEve->SpawnNewViewer("V0 decay plane View");
  TEveScene  *dpScene  = gEve->SpawnNewScene("V0 decay plane Scene");

  dpViewer->AddScene(dpScene);

  result = gInterpreter->ProcessLine("geom_gentle(kFALSE)");
  if (result)
  {
    TEveGeoShape *geom = reinterpret_cast<TEveGeoShape*>(result);
    geom->IncDenyDestroy();
    geom->FindChild("TRD+TOF")->SetRnrState(kFALSE);
    geom->FindChild("PHOS")   ->SetRnrState(kFALSE);
    geom->FindChild("HMPID")  ->SetRnrState(kFALSE);
    dpScene->AddElement(geom);
  }
  else
  {
    Warning("DisplayDetailed", "Import of 3D geometry failed.");
  }

  dpScene->AddElement(fM);
  dpScene->AddElement(lv0TransverseMomentumDirection);
  dpScene->AddElement(pvlocation);
  dpScene->AddElement(v0location);
  if (negDaughterCluster) dpScene->AddElement(negDaughterCluster);
  if (posDaughterCluster) dpScene->AddElement(posDaughterCluster);

  // This is the to-do list for the decay plane:
  // 1. fix the view to decay plane (no rotation allowed but moving the center ok)
  // 2. show V0 direction with a vertical arrow length proportional to pT -> done!
  // 3. show the center, the main vertex and the detectors for this view -> done!
  // 4. show the x,y and z axis and the different angles
  //       -> this needs a referential object that we can move around
  //          or fix to a selected point (origin being the default)
  // 5. draw the dca between daughters and the extrapolation to the main vertex.
  //       -> this is an issue since we only store the distance: check with J.Belikov
  // 6. show clusters in the ITS and in the TPC associated with the daughter tracks
  //       -> include a radius cut for plotting only ITS and TPC ->done!
  dpViewer->GetGLViewer()->ResetCamerasAfterNextUpdate();
  TGLCamera& dpCam = dpViewer->GetGLViewer()->CurrentCamera();
  dpCam.SetExternalCenter(kTRUE);
  dpCam.SetCenterVec(fM->fRecDecayV.fX, fM->fRecDecayV.fY, fM->fRecDecayV.fZ);
  dpCam.RotateRad(0,-TMath::Pi()/2.); // RotateRad rotates in radians (hRotate,vRotate)
  //  Here rotate the _view_ (not the camera) by (fM->GetPhi() - TMath::Pi()/2.)

  // In the end maybe truck and rotate properly...
  //  dpCam.Truck(0,200);// Truck center wrt the view panel: (x=0 pixels, y pixels)
  //  dpCam.Rotate(0,50,0,0); // Rotate in pixels (xDelta,yDelta)

  // end of the decay plane part

  //
  // This part is for displaying the information
  //
  slot = pack->NewSlot();

  TEveWindowFrame *frame = slot->MakeFrame(new TRootEmbeddedCanvas());
  frame->SetElementName("Details");

  // Print and show detailed information about the V0
  // Calculation of the invariant mass with the max prob PID hypothesis first
  // pseudorapidity, phi angle, pt, radius, dcas
  char info[100] = {0};
  sprintf(info,"#phi = %.3frad = %.1f",fM->GetPhi(),(180./TMath::Pi())*fM->GetPhi());
  TLatex* ltx = new TLatex(0.05, 0.9, info);
  ltx->SetTextSize(0.08);
  ltx->Draw();

  sprintf(info,"radius = %.3f [cm]",fM->GetRadius());
  ltx->DrawLatex(0.05, 0.8, info);

  sprintf(info,"p_{T} = %.3f [GeV/c]",fM->GetPt());
  ltx->DrawLatex(0.05, 0.7, info);

  sprintf(info,"daughters dca = %.3f [cm]",fM->GetDaughterDCA());
  ltx->DrawLatex(0.05, 0.6, info);

  sprintf(info,"#eta = - ln( tan(#theta/2) ) = %.3f",fM->GetEta());
  ltx->DrawLatex(0.05, 0.5, info);

  sprintf(info,"mass_{K^{0}_{s}} = %.3f [GeV/c^{2}]",fM->GetK0sInvMass());
  ltx->DrawLatex(0.05, 0.3, info);

  sprintf(info,"mass_{#Lambda} = %.3f [GeV/c^{2}]",fM->GetLambdaInvMass());
  ltx->DrawLatex(0.05, 0.2, info);

  sprintf(info,"mass_{#bar{#Lambda}} = %.3f [GeV/c^{2}]",fM->GetAntiLambdaInvMass());
  ltx->DrawLatex(0.05, 0.1, info);

  gEve->Redraw3D();
}
<|endoftext|>


<commit_before>#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
const int MAXN = 20000 + 10,MAXM = 200000 + 10;

struct egde
{
	int v,next;
}e[MAXM];

int n,m,ans,cnt = 1,mx = -1;
int a[MAXM],b[MAXM],c[MAXM];
int head[MAXN],col[MAXN];
bool flag;

void adde(int u,int v)
{
	e[cnt].v = v;
	e[cnt].next = head[u];
	head[u] = cnt++;
}

void build(int mid)
{
	memset(head,-1,sizeof(head));
	for(int i = 1;i <= m;i++)if(c[i] > mid)
	{
		adde(a[i],b[i]);
		adde(b[i],a[i]);
	}
}

void dfs(int u)
{
	if(!flag)return;
	for(int i = head[u];i != -1;i = e[i].next)
	{
		int v = e[i].v;
		if(col[v] == -1)
		{
			col[v] = col[u] ^ 1;
			dfs(v);
		}
		else if(col[u] == col[v])
		{
			flag = 0;
			return;
		}
	}
}

void work()
{
	int l = 0,r = mx,mid;
	while(l <= r)
	{
		mid = (l + r) >> 1;
		build(mid);
		memset(col,-1,sizeof(col));
		flag = 1;
		for(int i = 1;i <= n;i++)
		{
			if(col[i] == -1)
			{
				col[i] = 0;
				dfs(i);
			}
			if(!flag)break;
		}
		if(flag)
		{
			ans = mid;
			r = mid - 1;
		}
		else l = mid + 1;
	}
}

int main()
{
	scanf("%d%d",&n,&m);
	for(int i = 1;i <= m;i++)
	{
		scanf("%d%d%d",&a[i],&b[i],&c[i]);
		if (c[i] > mx) mx = c[i];
	}
	work();
	printf("%d\n",ans);
	return 0;
}
<commit_msg>code style<commit_after>#include <stdio.h>
#include <string.h>
#define true 1
#define false 0

const int MAXN = 20000 + 10,MAXM = 200000 + 10;

struct egde {
  int v,next;
}e[MAXM];

int n,m,ans,cnt = 1,mx = -1;
int a[MAXM],b[MAXM],c[MAXM];
int head[MAXN],col[MAXN];
int flag;

void adde(int u,int v) {
  e[cnt].v = v;
  e[cnt].next = head[u];
  head[u] = cnt++;
}

void build(int mid) {
  int i;
  memset(head, -1, sizeof(head));
  for(i = 1; i <= m; i++)
    if(c[i] > mid) {
      adde(a[i],b[i]);
      adde(b[i],a[i]);
    }
}

void dfs(int u) {
  if(!flag) return;
  int i;
  for(i = head[u]; i != -1; i = e[i].next) {
    int v = e[i].v;
    if(col[v] == -1) {
      col[v] = col[u] ^ 1;
      dfs(v);
    }
    else if(col[u] == col[v]) {
      flag = 0;
      return;
    }
  }
}

void work() {
  int l = 0, r = mx, mid, i;
  while(l <= r) {
    mid = (l + r) >> 1;
    build(mid);
    memset(col, -1, sizeof(col));
    flag = 1;
    for(i = 1; i <= n; i++) {
      if(col[i] == -1) {
	col[i] = 0;
	dfs(i);
      }
      if(!flag) break;
    }
    if(flag) {
      ans = mid;
      r = mid - 1;
    }
    else l = mid + 1;
  }
}

int main() {
  int i;
  scanf("%d %d", &n, &m);
  for(i = 1; i <= m; i++) {
    scanf("%d %d %d", &a[i], &b[i], &c[i]);
    if (c[i] > mx) mx = c[i];
  }
  work();
  printf("%d\n", ans);
  return 0;
}
<|endoftext|>


<commit_before>#include <QtCore/QMap>
#include <QtCore/QRegExp>
#include "iTCHMethod.h"

namespace {
  // Initialize static values for JSON RPC conversion and checking
  cons char JSON_METHOD_REG_EXP[] = "\\{\\s*\"method\":\\s*\"(.*)\"\\s*,\\s*\"params\":\\s*\\[(.*)\\]\\s*,\\s*\"id\":\\s*(.*)\\s*\\}"
  const QRegExp __jsonMethodRegExp(JSON_METHOD_REG_EXP, Qt::CaseSensitive, QRegExp::RegExp2);

  class __SupportedMethodsMap : public QMap<iTCHMethod::SupportedMethods, QString>
  {
    (*this)[iTCHMethod::METHOD_IITUNES_BACKTRACK] = "IiTunes::BackTrack";
    (*this)[iTCHMethod::METHOD_IITUNES_FASTFORWARD] = "IiTunes::FastForward";
    (*this)[iTCHMethod::METHOD_IITUNES_NEXTTRACK] = "IiTunes::NextTrack";
    (*this)[iTCHMethod::METHOD_IITUNES_PAUSE] = "IiTunes::Pause";
    (*this)[iTCHMethod::METHOD_IITUNES_PLAY] = "IiTunes::Play";
    (*this)[iTCHMethod::METHOD_IITUNES_PLAYPAUSE] = "IiTunes::PlayPause";
    (*this)[iTCHMethod::METHOD_IITUNES_PREVIOUSTRACK] = "IiTunes::PreviousTrack";
    (*this)[iTCHMethod::METHOD_IITUNES_RESUME] = "IiTunes::Resume";
    (*this)[iTCHMethod::METHOD_IITUNES_REWIND] = "IiTunes::Rewind";
    (*this)[iTCHMethod::METHOD_IITUNES_STOP] = "IiTunes::Stop";
    (*this)[iTCHMethod::METHOD_IITUNES_GET_SOUNDVOLUME] = "IiTunes::get_SoundVolume";
    (*this)[iTCHMethod::METHOD_IITUNES_PUT_SOUNDVOLUME] = "IiTunes::put_SoundVolume";
    (*this)[iTCHMethod::METHOD_IITUNES_GET_MUTE] = "IiTunes::get_Mute";
    (*this)[iTCHMethod::METHOD_IITUNES_PUT_MUTE] = "IiTunes::put_Mute";
    (*this)[iTCHMethod::METHOD_IITUNES_GET_PLAYERPOSITION] = "IiTunes::get_playerPosition";
    (*this)[iTCHMethod::METHOD_IITUNES_PUT_PLAYERPOSITION] = "IiTunes::put_PlayerPosition";
    (*this)[iTCHMethod::METHOD_IITCHSERVER_GET_PLAYERSTATE] = "iTCHServer::getPlayserState";
    (*this)[iTCHMethod::METHOD_IITCHSERVER_GET_CURRENTTRACK] = "iTCHServer::getCurrentTrack";
    (*this)[iTCHMethod::METHOD_IITCHSERVER_GET_CURRENTPLAYLIST] = "iTCHServer::getCurrentPlaylist";
    (*this)[iTCHMethod::METHOD_IITCHCLIENT_VOLUMECHANGED] = "iTCHClient::volumeChanged";
    (*this)[iTCHMethod::METHOD_IITCHCLIENT_PLAYINGSTARTED] = "iTCHClient::playingStarted";
    (*this)[iTCHMethod::METHOD_IITCHCLIENT_PLAYINGSTOPPED] = "iTCHClient::playingStopped";
    (*this)[iTCHMethod::METHOD_IITCHCLIENT_TRACKINFOCHANGED] = "iTCHClient::trackInfoChanged";
  }
} __supportedMethods;

iTCHMethod::iTCHMethod(const iTCHMethod& method) :
  method_(method.method_),
  params_(method.params_),
  id_(method.id_)
{
}

iTCHMethod::iTCHMethod(SupportedMethods method, const QStringList &params, unsigned int id) :
  params_(params),
  id_(id)
{
  setMethod(method);
}

iTCHMethod::iTCHMethod(const QString &json) :
  id_(0)
{
  fromJsonRpc(json);
}

void iTCHMethod::setMethod(SupportedMethods method)
{
  // Check for supported method name
  if (!__supportedMethods.contains(method))
  {
    throw InvalidValueException(QString("Unsupported method: %1").arg(method));
  }

  method_ = method;
}

QString iTCHMethod::toJsonRpc() const
{
  // Initialize JSON-RPC string with method name
  if (!__supportedMethods.contains(method_))
  {
    throw InvalidValueException(QString("Unsupported method: %1").arg(method_));
  }

  QString json = QString("{ \"method\": \"%1\", \"params\": [").arg(__supportedMethods[method_]);

  // Add paramters to JSON-RPC params list
  if (!params_.empty())
  {
    QStringList::const_iterator paramsIterator = params_.constBegin();

    // Add first parameter to list
    json += (*paramsIterator++);

    // Add remaining parameters with comma separation
    for (; paramsIterator != params_.constEnd(); ++paramsIterator)
    {
      json += QString(", %1").arg(*paramsIterator);
    }
  }

  // Append the id number
  json += QString("], \"id\": %1}").arg((id_ > 0) ? QString::number(id_) : "null");

  return json;
}

void iTCHMethod::fromJsonRpc(const QString &json)
{
  // Extract method, parameters, and id
  int pos = __jsonMethodRegExp.indexIn(json);

  // Check for valid JSON RPC message
  if (pos < 0)
  {
    throw InvalidValueException(QString("Invalid JSON-RPC message: not correctly formatted"));
  }

  int n = __jsonMethodRegExp.numCaptures();
  if (n != 3)
  {
    throw InvalidValueException(QString("Invalid JSON-RPC message: incorrect number of parameters (had %1, needs 3)").arg(n));
  }

  // Extract the method name (checks for supported method)
  QString method = __jsonMethodRegExp.cap(1);
  if (!__supportedMethods.values().contains(method))
  {
    throw InvalidValueException(QString("Invalid JSON-RPC message: unsupported method %1)").arg(method));
  }

  // Get key for method
  method_ = __supportedMethods.key(method);

  // Extract the
  QString params = __jsonMethodRegExp.cap(2);
  params_ = params.split(QRegExp("\\s*,\\s*"), QString::SkipEmptyParts);

  QString id = __jsonMethodRegExp.cap(3);
  bool valid;
  id_ = (id == "null") ? 0 : id.toInt(&valid);
}
<commit_msg>Fixed syntax errors from last merge<commit_after>#include <QtCore/QMap>
#include <QtCore/QRegExp>
#include "iTCHMethod.h"

namespace {
  // Initialize static values for JSON RPC conversion and checking
  const char JSON_METHOD_REG_EXP[] = "\\{\\s*\"method\":\\s*\"(.*)\"\\s*,\\s*\"params\":\\s*\\[(.*)\\]\\s*,\\s*\"id\":\\s*(.*)\\s*\\}";
  const QRegExp __jsonMethodRegExp(JSON_METHOD_REG_EXP, Qt::CaseSensitive, QRegExp::RegExp2);

  class __SupportedMethodsMap : public QMap<iTCHMethod::SupportedMethods, QString>
  {
  public:
    __SupportedMethodsMap()
    {
      (*this)[iTCHMethod::METHOD_IITUNES_BACKTRACK] = "IiTunes::BackTrack";
      (*this)[iTCHMethod::METHOD_IITUNES_FASTFORWARD] = "IiTunes::FastForward";
      (*this)[iTCHMethod::METHOD_IITUNES_NEXTTRACK] = "IiTunes::NextTrack";
      (*this)[iTCHMethod::METHOD_IITUNES_PAUSE] = "IiTunes::Pause";
      (*this)[iTCHMethod::METHOD_IITUNES_PLAY] = "IiTunes::Play";
      (*this)[iTCHMethod::METHOD_IITUNES_PLAYPAUSE] = "IiTunes::PlayPause";
      (*this)[iTCHMethod::METHOD_IITUNES_PREVIOUSTRACK] = "IiTunes::PreviousTrack";
      (*this)[iTCHMethod::METHOD_IITUNES_RESUME] = "IiTunes::Resume";
      (*this)[iTCHMethod::METHOD_IITUNES_REWIND] = "IiTunes::Rewind";
      (*this)[iTCHMethod::METHOD_IITUNES_STOP] = "IiTunes::Stop";
      (*this)[iTCHMethod::METHOD_IITUNES_GET_SOUNDVOLUME] = "IiTunes::get_SoundVolume";
      (*this)[iTCHMethod::METHOD_IITUNES_PUT_SOUNDVOLUME] = "IiTunes::put_SoundVolume";
      (*this)[iTCHMethod::METHOD_IITUNES_GET_MUTE] = "IiTunes::get_Mute";
      (*this)[iTCHMethod::METHOD_IITUNES_PUT_MUTE] = "IiTunes::put_Mute";
      (*this)[iTCHMethod::METHOD_IITUNES_GET_PLAYERPOSITION] = "IiTunes::get_playerPosition";
      (*this)[iTCHMethod::METHOD_IITUNES_PUT_PLAYERPOSITION] = "IiTunes::put_PlayerPosition";
      (*this)[iTCHMethod::METHOD_IITCHSERVER_GET_PLAYERSTATE] = "iTCHServer::getPlayserState";
      (*this)[iTCHMethod::METHOD_IITCHSERVER_GET_CURRENTTRACK] = "iTCHServer::getCurrentTrack";
      (*this)[iTCHMethod::METHOD_IITCHSERVER_GET_CURRENTPLAYLIST] = "iTCHServer::getCurrentPlaylist";
      (*this)[iTCHMethod::METHOD_IITCHCLIENT_VOLUMECHANGED] = "iTCHClient::volumeChanged";
      (*this)[iTCHMethod::METHOD_IITCHCLIENT_PLAYINGSTARTED] = "iTCHClient::playingStarted";
      (*this)[iTCHMethod::METHOD_IITCHCLIENT_PLAYINGSTOPPED] = "iTCHClient::playingStopped";
      (*this)[iTCHMethod::METHOD_IITCHCLIENT_TRACKINFOCHANGED] = "iTCHClient::trackInfoChanged";
    }
  } __supportedMethods;
}

iTCHMethod::iTCHMethod(const iTCHMethod& method) :
  method_(method.method_),
  params_(method.params_),
  id_(method.id_)
{
}

iTCHMethod::iTCHMethod(SupportedMethods method, const QStringList &params, unsigned int id) :
  params_(params),
  id_(id)
{
  setMethod(method);
}

iTCHMethod::iTCHMethod(const QString &json) :
  id_(0)
{
  fromJsonRpc(json);
}

void iTCHMethod::setMethod(SupportedMethods method)
{
  // Check for supported method name
  if (!__supportedMethods.contains(method))
  {
    throw InvalidValueException(QString("Unsupported method: %1").arg(method));
  }

  method_ = method;
}

QString iTCHMethod::toJsonRpc() const
{
  // Initialize JSON-RPC string with method name
  if (!__supportedMethods.contains(method_))
  {
    throw InvalidValueException(QString("Unsupported method: %1").arg(method_));
  }

  QString json = QString("{ \"method\": \"%1\", \"params\": [").arg(__supportedMethods[method_]);

  // Add paramters to JSON-RPC params list
  if (!params_.empty())
  {
    QStringList::const_iterator paramsIterator = params_.constBegin();

    // Add first parameter to list
    json += (*paramsIterator++);

    // Add remaining parameters with comma separation
    for (; paramsIterator != params_.constEnd(); ++paramsIterator)
    {
      json += QString(", %1").arg(*paramsIterator);
    }
  }

  // Append the id number
  json += QString("], \"id\": %1}").arg((id_ > 0) ? QString::number(id_) : "null");

  return json;
}

void iTCHMethod::fromJsonRpc(const QString &json)
{
  // Extract method, parameters, and id
  int pos = __jsonMethodRegExp.indexIn(json);

  // Check for valid JSON RPC message
  if (pos < 0)
  {
    throw InvalidValueException(QString("Invalid JSON-RPC message: not correctly formatted"));
  }

  int n = __jsonMethodRegExp.numCaptures();
  if (n != 3)
  {
    throw InvalidValueException(QString("Invalid JSON-RPC message: incorrect number of parameters (had %1, needs 3)").arg(n));
  }

  // Extract the method name (checks for supported method)
  QString method = __jsonMethodRegExp.cap(1);
  if (!__supportedMethods.values().contains(method))
  {
    throw InvalidValueException(QString("Invalid JSON-RPC message: unsupported method %1)").arg(method));
  }

  // Get key for method
  method_ = __supportedMethods.key(method);

  // Extract the
  QString params = __jsonMethodRegExp.cap(2);
  params_ = params.split(QRegExp("\\s*,\\s*"), QString::SkipEmptyParts);

  QString id = __jsonMethodRegExp.cap(3);
  bool valid;
  id_ = (id == "null") ? 0 : id.toInt(&valid);
}
<|endoftext|>