<commit_before>#include "selection_shader.h"
#include "matrix.h"
#include "util.h"

namespace konstructs {
    using namespace Eigen;

    static Matrix<float, 3, 24> wireframe(const float scale) {
        Matrix<float, 3, 24> m;
        m.col(0) << -1, -1, -1;
        m.col(1) << -1, -1, +1;
        m.col(2) << -1, -1, -1;
        m.col(3) << -1, +1, -1;
        m.col(4) << -1, -1, -1;
        m.col(5) << +1, -1, -1;
        m.col(6) << -1, -1, +1;
        m.col(7) << -1, +1, +1;
        m.col(8) << -1, -1, +1;
        m.col(9) << +1, -1, +1;
        m.col(10) << -1, +1, -1;
        m.col(11) << -1, +1, +1;
        m.col(12) << -1, +1, -1;
        m.col(13) << +1, +1, -1;
        m.col(14) << -1, +1, +1;
        m.col(15) << +1, +1, +1;
        m.col(16) << +1, -1, -1;
        m.col(17) << +1, -1, +1;
        m.col(18) << +1, -1, -1;
        m.col(19) << +1, +1, -1;
        m.col(20) << +1, -1, +1;
        m.col(21) << +1, +1, +1;
        m.col(22) << +1, +1, -1;
        m.col(23) << +1, +1, +1;
        m *= scale;
        return m;
    }

    SelectionShader::SelectionShader(const int _radius, const float _fov,
                                     const float _near_distance, const float scale) :
        ShaderProgram(
        "chunk",
        "#version 330\n"
        "uniform mat4 matrix;\n"
        "uniform mat4 translation;\n"
        "in vec4 position;\n"
        "void main() {\n"
        "    vec4 global_position = translation * position;\n"
        "    gl_Position = matrix * global_position;\n"
        "}\n",
        "#version 330\n"
        "out vec4 frag_color;\n"
        "const float pi = 3.14159265;\n"
        "void main() {\n"
        "    frag_color = vec4(1.0, 1.0, 1.0, 1.0);\n"
        "}\n",
        GL_LINES),
        position_attr(attributeId("position")),
        matrix(uniformId("matrix")),
        translation(uniformId("translation")),
        radius(_radius),
        fov(_fov),
        near_distance(_near_distance),
        model(position_attr, wireframe(scale))
    {}

    void SelectionShader::render(const Player &p, const int width, const int height,
                                const Vector3i &selected) {
        bind([&](Context c) {
                c.enable(GL_DEPTH_TEST);
                float aspect_ratio = (float)width / (float)height;
                float max_distance = (radius - 1) * CHUNK_SIZE;
                const Matrix4f m = matrix::projection_perspective(fov, aspect_ratio, near_distance, max_distance) * p.view();
                c.set(matrix, m);
                c.set(translation, Affine3f(Translation3f(selected.cast<float>())).matrix());
                c.draw(&model);
                c.disable(GL_DEPTH_TEST);
            });
    }

};
<commit_msg>replace the white selection with a black one.<commit_after>#include "selection_shader.h"
#include "matrix.h"
#include "util.h"

namespace konstructs {
    using namespace Eigen;

    static Matrix<float, 3, 24> wireframe(const float scale) {
        Matrix<float, 3, 24> m;
        m.col(0) << -1, -1, -1;
        m.col(1) << -1, -1, +1;
        m.col(2) << -1, -1, -1;
        m.col(3) << -1, +1, -1;
        m.col(4) << -1, -1, -1;
        m.col(5) << +1, -1, -1;
        m.col(6) << -1, -1, +1;
        m.col(7) << -1, +1, +1;
        m.col(8) << -1, -1, +1;
        m.col(9) << +1, -1, +1;
        m.col(10) << -1, +1, -1;
        m.col(11) << -1, +1, +1;
        m.col(12) << -1, +1, -1;
        m.col(13) << +1, +1, -1;
        m.col(14) << -1, +1, +1;
        m.col(15) << +1, +1, +1;
        m.col(16) << +1, -1, -1;
        m.col(17) << +1, -1, +1;
        m.col(18) << +1, -1, -1;
        m.col(19) << +1, +1, -1;
        m.col(20) << +1, -1, +1;
        m.col(21) << +1, +1, +1;
        m.col(22) << +1, +1, -1;
        m.col(23) << +1, +1, +1;
        m *= scale;
        return m;
    }

    SelectionShader::SelectionShader(const int _radius, const float _fov,
                                     const float _near_distance, const float scale) :
        ShaderProgram(
        "chunk",
        "#version 330\n"
        "uniform mat4 matrix;\n"
        "uniform mat4 translation;\n"
        "in vec4 position;\n"
        "void main() {\n"
        "    vec4 global_position = translation * position;\n"
        "    gl_Position = matrix * global_position;\n"
        "}\n",
        "#version 330\n"
        "out vec4 frag_color;\n"
        "void main() {\n"
        "    frag_color = vec4(0.1, 0.1, 0.1, 1.0);\n"
        "}\n",
        GL_LINES),
        position_attr(attributeId("position")),
        matrix(uniformId("matrix")),
        translation(uniformId("translation")),
        radius(_radius),
        fov(_fov),
        near_distance(_near_distance),
        model(position_attr, wireframe(scale))
    {}

    void SelectionShader::render(const Player &p, const int width, const int height,
                                const Vector3i &selected) {
        bind([&](Context c) {
                c.enable(GL_DEPTH_TEST);
                float aspect_ratio = (float)width / (float)height;
                float max_distance = (radius - 1) * CHUNK_SIZE;
                const Matrix4f m = matrix::projection_perspective(fov, aspect_ratio, near_distance, max_distance) * p.view();
                c.set(matrix, m);
                c.set(translation, Affine3f(Translation3f(selected.cast<float>())).matrix());
                c.draw(&model);
                c.disable(GL_DEPTH_TEST);
            });
    }

};
<|endoftext|>


<commit_before>//===- FileCheck.cpp - Check that File's Contents match what is expected --===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// FileCheck does a line-by line check of a file that validates whether it
// contains the expected content.  This is useful for regression tests etc.
//
// This program exits with an error status of 2 on error, exit status of 0 if
// the file matched the expected contents, and exit status of 1 if it did not
// contain the expected contents.
//
//===----------------------------------------------------------------------===//

#include "llvm/Support/CommandLine.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/PrettyStackTrace.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/System/Signals.h"
using namespace llvm;

static cl::opt<std::string>
CheckFilename(cl::Positional, cl::desc("<check-file>"), cl::Required);

static cl::opt<std::string>
InputFilename("input-file", cl::desc("File to check (defaults to stdin)"),
              cl::init("-"), cl::value_desc("filename"));

static cl::opt<std::string>
CheckPrefix("check-prefix", cl::init("CHECK"),
            cl::desc("Prefix to use from check file (defaults to 'CHECK')"));

static cl::opt<bool>
NoCanonicalizeWhiteSpace("strict-whitespace",
              cl::desc("Do not treat all horizontal whitespace as equivalent"));

class Pattern {
  /// Str - The string to match.
  std::string Str;
public:

  Pattern(StringRef S) : Str(S.str()) {
    // Remove duplicate spaces in the check strings if requested.
    if (!NoCanonicalizeWhiteSpace)
      CanonicalizeCheckString();
  }

  /// Match - Match the pattern string against the input buffer Buffer.  This
  /// returns the position that is matched or npos if there is no match.  If
  /// there is a match, the size of the matched string is returned in MatchLen.
  size_t Match(StringRef Buffer, size_t &MatchLen) const {
    MatchLen = Str.size();
    return Buffer.find(Str);
  }

private:
  /// CanonicalizeCheckString - Replace all sequences of horizontal whitespace
  /// in the check strings with a single space.
  void CanonicalizeCheckString() {
    for (unsigned C = 0; C != Str.size(); ++C) {
      // If C is not a horizontal whitespace, skip it.
      if (Str[C] != ' ' && Str[C] != '\t')
        continue;

      // Replace the character with space, then remove any other space
      // characters after it.
      Str[C] = ' ';

      while (C+1 != Str.size() &&
             (Str[C+1] == ' ' || Str[C+1] == '\t'))
        Str.erase(Str.begin()+C+1);
    }
  }
};

/// CheckString - This is a check that we found in the input file.
struct CheckString {
  /// Pat - The pattern to match.
  Pattern Pat;

  /// Loc - The location in the match file that the check string was specified.
  SMLoc Loc;

  /// IsCheckNext - This is true if this is a CHECK-NEXT: directive (as opposed
  /// to a CHECK: directive.
  bool IsCheckNext;

  /// NotStrings - These are all of the strings that are disallowed from
  /// occurring between this match string and the previous one (or start of
  /// file).
  std::vector<std::pair<SMLoc, std::string> > NotStrings;

  CheckString(const Pattern &P, SMLoc L, bool isCheckNext)
    : Pat(P), Loc(L), IsCheckNext(isCheckNext) {}
};

/// ReadCheckFile - Read the check file, which specifies the sequence of
/// expected strings.  The strings are added to the CheckStrings vector.
static bool ReadCheckFile(SourceMgr &SM,
                          std::vector<CheckString> &CheckStrings) {
  // Open the check file, and tell SourceMgr about it.
  std::string ErrorStr;
  MemoryBuffer *F =
    MemoryBuffer::getFileOrSTDIN(CheckFilename.c_str(), &ErrorStr);
  if (F == 0) {
    errs() << "Could not open check file '" << CheckFilename << "': "
           << ErrorStr << '\n';
    return true;
  }
  SM.AddNewSourceBuffer(F, SMLoc());

  // Find all instances of CheckPrefix followed by : in the file.
  StringRef Buffer = F->getBuffer();

  std::vector<std::pair<SMLoc, std::string> > NotMatches;

  while (1) {
    // See if Prefix occurs in the memory buffer.
    Buffer = Buffer.substr(Buffer.find(CheckPrefix));

    // If we didn't find a match, we're done.
    if (Buffer.empty())
      break;

    const char *CheckPrefixStart = Buffer.data();

    // When we find a check prefix, keep track of whether we find CHECK: or
    // CHECK-NEXT:
    bool IsCheckNext = false, IsCheckNot = false;

    // Verify that the : is present after the prefix.
    if (Buffer[CheckPrefix.size()] == ':') {
      Buffer = Buffer.substr(CheckPrefix.size()+1);
    } else if (Buffer.size() > CheckPrefix.size()+6 &&
               memcmp(Buffer.data()+CheckPrefix.size(), "-NEXT:", 6) == 0) {
      Buffer = Buffer.substr(CheckPrefix.size()+7);
      IsCheckNext = true;
    } else if (Buffer.size() > CheckPrefix.size()+5 &&
               memcmp(Buffer.data()+CheckPrefix.size(), "-NOT:", 5) == 0) {
      Buffer = Buffer.substr(CheckPrefix.size()+6);
      IsCheckNot = true;
    } else {
      Buffer = Buffer.substr(1);
      continue;
    }

    // Okay, we found the prefix, yay.  Remember the rest of the line, but
    // ignore leading and trailing whitespace.
    Buffer = Buffer.substr(Buffer.find_first_not_of(" \t"));

    // Scan ahead to the end of line.
    size_t EOL = Buffer.find_first_of("\n\r");
    if (EOL == StringRef::npos) EOL = Buffer.size();

    // Ignore trailing whitespace.
    while (EOL && (Buffer[EOL-1] == ' ' || Buffer[EOL-1] == '\t'))
      --EOL;

    // Check that there is something on the line.
    if (EOL == 0) {
      SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()),
                      "found empty check string with prefix '"+CheckPrefix+":'",
                      "error");
      return true;
    }

    StringRef PatternStr = Buffer.substr(0, EOL);

    // Handle CHECK-NOT.
    if (IsCheckNot) {
      NotMatches.push_back(std::make_pair(SMLoc::getFromPointer(Buffer.data()),
                                          PatternStr.str()));
      Buffer = Buffer.substr(EOL);
      continue;
    }

    // Verify that CHECK-NEXT lines have at least one CHECK line before them.
    if (IsCheckNext && CheckStrings.empty()) {
      SM.PrintMessage(SMLoc::getFromPointer(CheckPrefixStart),
                      "found '"+CheckPrefix+"-NEXT:' without previous '"+
                      CheckPrefix+ ": line", "error");
      return true;
    }

    Pattern P(PatternStr);

    // Okay, add the string we captured to the output vector and move on.
    CheckStrings.push_back(CheckString(P,
                                       SMLoc::getFromPointer(Buffer.data()),
                                       IsCheckNext));
    std::swap(NotMatches, CheckStrings.back().NotStrings);

    Buffer = Buffer.substr(EOL);
  }

  if (CheckStrings.empty()) {
    errs() << "error: no check strings found with prefix '" << CheckPrefix
           << ":'\n";
    return true;
  }

  if (!NotMatches.empty()) {
    errs() << "error: '" << CheckPrefix
           << "-NOT:' not supported after last check line.\n";
    return true;
  }

  return false;
}

/// CanonicalizeInputFile - Remove duplicate horizontal space from the specified
/// memory buffer, free it, and return a new one.
static MemoryBuffer *CanonicalizeInputFile(MemoryBuffer *MB) {
  SmallVector<char, 16> NewFile;
  NewFile.reserve(MB->getBufferSize());

  for (const char *Ptr = MB->getBufferStart(), *End = MB->getBufferEnd();
       Ptr != End; ++Ptr) {
    // If C is not a horizontal whitespace, skip it.
    if (*Ptr != ' ' && *Ptr != '\t') {
      NewFile.push_back(*Ptr);
      continue;
    }

    // Otherwise, add one space and advance over neighboring space.
    NewFile.push_back(' ');
    while (Ptr+1 != End &&
           (Ptr[1] == ' ' || Ptr[1] == '\t'))
      ++Ptr;
  }

  // Free the old buffer and return a new one.
  MemoryBuffer *MB2 =
    MemoryBuffer::getMemBufferCopy(NewFile.data(),
                                   NewFile.data() + NewFile.size(),
                                   MB->getBufferIdentifier());

  delete MB;
  return MB2;
}

static void PrintCheckFailed(const SourceMgr &SM, const CheckString &CheckStr,
                             StringRef Buffer) {
  // Otherwise, we have an error, emit an error message.
  SM.PrintMessage(CheckStr.Loc, "expected string not found in input",
                  "error");

  // Print the "scanning from here" line.  If the current position is at the
  // end of a line, advance to the start of the next line.
  Buffer = Buffer.substr(Buffer.find_first_not_of(" \t\n\r"));

  SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()), "scanning from here",
                  "note");
}

/// CountNumNewlinesBetween - Count the number of newlines in the specified
/// range.
static unsigned CountNumNewlinesBetween(StringRef Range) {
  unsigned NumNewLines = 0;
  while (1) {
    // Scan for newline.
    Range = Range.substr(Range.find_first_of("\n\r"));
    if (Range.empty()) return NumNewLines;

    ++NumNewLines;

    // Handle \n\r and \r\n as a single newline.
    if (Range.size() > 1 &&
        (Range[1] == '\n' || Range[1] == '\r') &&
        (Range[0] != Range[1]))
      Range = Range.substr(1);
    Range = Range.substr(1);
  }
}

int main(int argc, char **argv) {
  sys::PrintStackTraceOnErrorSignal();
  PrettyStackTraceProgram X(argc, argv);
  cl::ParseCommandLineOptions(argc, argv);

  SourceMgr SM;

  // Read the expected strings from the check file.
  std::vector<CheckString> CheckStrings;
  if (ReadCheckFile(SM, CheckStrings))
    return 2;

  // Open the file to check and add it to SourceMgr.
  std::string ErrorStr;
  MemoryBuffer *F =
    MemoryBuffer::getFileOrSTDIN(InputFilename.c_str(), &ErrorStr);
  if (F == 0) {
    errs() << "Could not open input file '" << InputFilename << "': "
           << ErrorStr << '\n';
    return true;
  }

  // Remove duplicate spaces in the input file if requested.
  if (!NoCanonicalizeWhiteSpace)
    F = CanonicalizeInputFile(F);

  SM.AddNewSourceBuffer(F, SMLoc());

  // Check that we have all of the expected strings, in order, in the input
  // file.
  StringRef Buffer = F->getBuffer();

  const char *LastMatch = Buffer.data();

  for (unsigned StrNo = 0, e = CheckStrings.size(); StrNo != e; ++StrNo) {
    const CheckString &CheckStr = CheckStrings[StrNo];

    StringRef SearchFrom = Buffer;

    // Find StrNo in the file.
    size_t MatchLen = 0;
    Buffer = Buffer.substr(CheckStr.Pat.Match(Buffer, MatchLen));

    // If we didn't find a match, reject the input.
    if (Buffer.empty()) {
      PrintCheckFailed(SM, CheckStr, SearchFrom);
      return 1;
    }

    StringRef SkippedRegion(LastMatch, Buffer.data()-LastMatch);

    // If this check is a "CHECK-NEXT", verify that the previous match was on
    // the previous line (i.e. that there is one newline between them).
    if (CheckStr.IsCheckNext) {
      // Count the number of newlines between the previous match and this one.
      assert(LastMatch != F->getBufferStart() &&
             "CHECK-NEXT can't be the first check in a file");

      unsigned NumNewLines = CountNumNewlinesBetween(SkippedRegion);
      if (NumNewLines == 0) {
        SM.PrintMessage(CheckStr.Loc,
                    CheckPrefix+"-NEXT: is on the same line as previous match",
                        "error");
        SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()),
                        "'next' match was here", "note");
        SM.PrintMessage(SMLoc::getFromPointer(LastMatch),
                        "previous match was here", "note");
        return 1;
      }

      if (NumNewLines != 1) {
        SM.PrintMessage(CheckStr.Loc,
                        CheckPrefix+
                        "-NEXT: is not on the line after the previous match",
                        "error");
        SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()),
                        "'next' match was here", "note");
        SM.PrintMessage(SMLoc::getFromPointer(LastMatch),
                        "previous match was here", "note");
        return 1;
      }
    }

    // If this match had "not strings", verify that they don't exist in the
    // skipped region.
    for (unsigned i = 0, e = CheckStr.NotStrings.size(); i != e; ++i) {
      size_t Pos = SkippedRegion.find(CheckStr.NotStrings[i].second);
      if (Pos == StringRef::npos) continue;

      SM.PrintMessage(SMLoc::getFromPointer(LastMatch+Pos),
                      CheckPrefix+"-NOT: string occurred!", "error");
      SM.PrintMessage(CheckStr.NotStrings[i].first,
                      CheckPrefix+"-NOT: pattern specified here", "note");
      return 1;
    }

    // Otherwise, everything is good.  Step over the matched text and remember
    // the position after the match as the end of the last match.
    Buffer = Buffer.substr(MatchLen);
    LastMatch = Buffer.data();
  }

  return 0;
}
<commit_msg>change 'not' matching to use Pattern, move pattern parsing logic into the Pattern class.<commit_after>//===- FileCheck.cpp - Check that File's Contents match what is expected --===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// FileCheck does a line-by line check of a file that validates whether it
// contains the expected content.  This is useful for regression tests etc.
//
// This program exits with an error status of 2 on error, exit status of 0 if
// the file matched the expected contents, and exit status of 1 if it did not
// contain the expected contents.
//
//===----------------------------------------------------------------------===//

#include "llvm/Support/CommandLine.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/PrettyStackTrace.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/System/Signals.h"
using namespace llvm;

static cl::opt<std::string>
CheckFilename(cl::Positional, cl::desc("<check-file>"), cl::Required);

static cl::opt<std::string>
InputFilename("input-file", cl::desc("File to check (defaults to stdin)"),
              cl::init("-"), cl::value_desc("filename"));

static cl::opt<std::string>
CheckPrefix("check-prefix", cl::init("CHECK"),
            cl::desc("Prefix to use from check file (defaults to 'CHECK')"));

static cl::opt<bool>
NoCanonicalizeWhiteSpace("strict-whitespace",
              cl::desc("Do not treat all horizontal whitespace as equivalent"));

//===----------------------------------------------------------------------===//
// Pattern Handling Code.
//===----------------------------------------------------------------------===//

class Pattern {
  /// Str - The string to match.
  std::string Str;
public:

  Pattern() { }

  bool ParsePattern(StringRef PatternStr, SourceMgr &SM);

  /// Match - Match the pattern string against the input buffer Buffer.  This
  /// returns the position that is matched or npos if there is no match.  If
  /// there is a match, the size of the matched string is returned in MatchLen.
  size_t Match(StringRef Buffer, size_t &MatchLen) const {
    MatchLen = Str.size();
    return Buffer.find(Str);
  }

private:
  /// CanonicalizeCheckString - Replace all sequences of horizontal whitespace
  /// in the check strings with a single space.
  void CanonicalizeCheckString() {
    for (unsigned C = 0; C != Str.size(); ++C) {
      // If C is not a horizontal whitespace, skip it.
      if (Str[C] != ' ' && Str[C] != '\t')
        continue;

      // Replace the character with space, then remove any other space
      // characters after it.
      Str[C] = ' ';

      while (C+1 != Str.size() &&
             (Str[C+1] == ' ' || Str[C+1] == '\t'))
        Str.erase(Str.begin()+C+1);
    }
  }
};

bool Pattern::ParsePattern(StringRef PatternStr, SourceMgr &SM) {
  // Ignore trailing whitespace.
  while (!PatternStr.empty() &&
         (PatternStr.back() == ' ' || PatternStr.back() == '\t'))
    PatternStr = PatternStr.substr(0, PatternStr.size()-1);

  // Check that there is something on the line.
  if (PatternStr.empty()) {
    SM.PrintMessage(SMLoc::getFromPointer(PatternStr.data()),
                    "found empty check string with prefix '"+CheckPrefix+":'",
                    "error");
    return true;
  }

  Str = PatternStr.str();

  // Remove duplicate spaces in the check strings if requested.
  if (!NoCanonicalizeWhiteSpace)
    CanonicalizeCheckString();

  return false;
}

//===----------------------------------------------------------------------===//
// Check Strings.
//===----------------------------------------------------------------------===//

/// CheckString - This is a check that we found in the input file.
struct CheckString {
  /// Pat - The pattern to match.
  Pattern Pat;

  /// Loc - The location in the match file that the check string was specified.
  SMLoc Loc;

  /// IsCheckNext - This is true if this is a CHECK-NEXT: directive (as opposed
  /// to a CHECK: directive.
  bool IsCheckNext;

  /// NotStrings - These are all of the strings that are disallowed from
  /// occurring between this match string and the previous one (or start of
  /// file).
  std::vector<std::pair<SMLoc, Pattern> > NotStrings;

  CheckString(const Pattern &P, SMLoc L, bool isCheckNext)
    : Pat(P), Loc(L), IsCheckNext(isCheckNext) {}
};

/// ReadCheckFile - Read the check file, which specifies the sequence of
/// expected strings.  The strings are added to the CheckStrings vector.
static bool ReadCheckFile(SourceMgr &SM,
                          std::vector<CheckString> &CheckStrings) {
  // Open the check file, and tell SourceMgr about it.
  std::string ErrorStr;
  MemoryBuffer *F =
    MemoryBuffer::getFileOrSTDIN(CheckFilename.c_str(), &ErrorStr);
  if (F == 0) {
    errs() << "Could not open check file '" << CheckFilename << "': "
           << ErrorStr << '\n';
    return true;
  }
  SM.AddNewSourceBuffer(F, SMLoc());

  // Find all instances of CheckPrefix followed by : in the file.
  StringRef Buffer = F->getBuffer();

  std::vector<std::pair<SMLoc, Pattern> > NotMatches;

  while (1) {
    // See if Prefix occurs in the memory buffer.
    Buffer = Buffer.substr(Buffer.find(CheckPrefix));

    // If we didn't find a match, we're done.
    if (Buffer.empty())
      break;

    const char *CheckPrefixStart = Buffer.data();

    // When we find a check prefix, keep track of whether we find CHECK: or
    // CHECK-NEXT:
    bool IsCheckNext = false, IsCheckNot = false;

    // Verify that the : is present after the prefix.
    if (Buffer[CheckPrefix.size()] == ':') {
      Buffer = Buffer.substr(CheckPrefix.size()+1);
    } else if (Buffer.size() > CheckPrefix.size()+6 &&
               memcmp(Buffer.data()+CheckPrefix.size(), "-NEXT:", 6) == 0) {
      Buffer = Buffer.substr(CheckPrefix.size()+7);
      IsCheckNext = true;
    } else if (Buffer.size() > CheckPrefix.size()+5 &&
               memcmp(Buffer.data()+CheckPrefix.size(), "-NOT:", 5) == 0) {
      Buffer = Buffer.substr(CheckPrefix.size()+6);
      IsCheckNot = true;
    } else {
      Buffer = Buffer.substr(1);
      continue;
    }

    // Okay, we found the prefix, yay.  Remember the rest of the line, but
    // ignore leading and trailing whitespace.
    Buffer = Buffer.substr(Buffer.find_first_not_of(" \t"));

    // Scan ahead to the end of line.
    size_t EOL = Buffer.find_first_of("\n\r");

    // Parse the pattern.
    Pattern P;
    if (P.ParsePattern(Buffer.substr(0, EOL), SM))
      return true;

    Buffer = Buffer.substr(EOL);

    // Verify that CHECK-NEXT lines have at least one CHECK line before them.
    if (IsCheckNext && CheckStrings.empty()) {
      SM.PrintMessage(SMLoc::getFromPointer(CheckPrefixStart),
                      "found '"+CheckPrefix+"-NEXT:' without previous '"+
                      CheckPrefix+ ": line", "error");
      return true;
    }

    // Handle CHECK-NOT.
    if (IsCheckNot) {
      NotMatches.push_back(std::make_pair(SMLoc::getFromPointer(Buffer.data()),
                                          P));
      continue;
    }

    // Okay, add the string we captured to the output vector and move on.
    CheckStrings.push_back(CheckString(P,
                                       SMLoc::getFromPointer(Buffer.data()),
                                       IsCheckNext));
    std::swap(NotMatches, CheckStrings.back().NotStrings);
  }

  if (CheckStrings.empty()) {
    errs() << "error: no check strings found with prefix '" << CheckPrefix
           << ":'\n";
    return true;
  }

  if (!NotMatches.empty()) {
    errs() << "error: '" << CheckPrefix
           << "-NOT:' not supported after last check line.\n";
    return true;
  }

  return false;
}

/// CanonicalizeInputFile - Remove duplicate horizontal space from the specified
/// memory buffer, free it, and return a new one.
static MemoryBuffer *CanonicalizeInputFile(MemoryBuffer *MB) {
  SmallVector<char, 16> NewFile;
  NewFile.reserve(MB->getBufferSize());

  for (const char *Ptr = MB->getBufferStart(), *End = MB->getBufferEnd();
       Ptr != End; ++Ptr) {
    // If C is not a horizontal whitespace, skip it.
    if (*Ptr != ' ' && *Ptr != '\t') {
      NewFile.push_back(*Ptr);
      continue;
    }

    // Otherwise, add one space and advance over neighboring space.
    NewFile.push_back(' ');
    while (Ptr+1 != End &&
           (Ptr[1] == ' ' || Ptr[1] == '\t'))
      ++Ptr;
  }

  // Free the old buffer and return a new one.
  MemoryBuffer *MB2 =
    MemoryBuffer::getMemBufferCopy(NewFile.data(),
                                   NewFile.data() + NewFile.size(),
                                   MB->getBufferIdentifier());

  delete MB;
  return MB2;
}

static void PrintCheckFailed(const SourceMgr &SM, const CheckString &CheckStr,
                             StringRef Buffer) {
  // Otherwise, we have an error, emit an error message.
  SM.PrintMessage(CheckStr.Loc, "expected string not found in input",
                  "error");

  // Print the "scanning from here" line.  If the current position is at the
  // end of a line, advance to the start of the next line.
  Buffer = Buffer.substr(Buffer.find_first_not_of(" \t\n\r"));

  SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()), "scanning from here",
                  "note");
}

/// CountNumNewlinesBetween - Count the number of newlines in the specified
/// range.
static unsigned CountNumNewlinesBetween(StringRef Range) {
  unsigned NumNewLines = 0;
  while (1) {
    // Scan for newline.
    Range = Range.substr(Range.find_first_of("\n\r"));
    if (Range.empty()) return NumNewLines;

    ++NumNewLines;

    // Handle \n\r and \r\n as a single newline.
    if (Range.size() > 1 &&
        (Range[1] == '\n' || Range[1] == '\r') &&
        (Range[0] != Range[1]))
      Range = Range.substr(1);
    Range = Range.substr(1);
  }
}

int main(int argc, char **argv) {
  sys::PrintStackTraceOnErrorSignal();
  PrettyStackTraceProgram X(argc, argv);
  cl::ParseCommandLineOptions(argc, argv);

  SourceMgr SM;

  // Read the expected strings from the check file.
  std::vector<CheckString> CheckStrings;
  if (ReadCheckFile(SM, CheckStrings))
    return 2;

  // Open the file to check and add it to SourceMgr.
  std::string ErrorStr;
  MemoryBuffer *F =
    MemoryBuffer::getFileOrSTDIN(InputFilename.c_str(), &ErrorStr);
  if (F == 0) {
    errs() << "Could not open input file '" << InputFilename << "': "
           << ErrorStr << '\n';
    return true;
  }

  // Remove duplicate spaces in the input file if requested.
  if (!NoCanonicalizeWhiteSpace)
    F = CanonicalizeInputFile(F);

  SM.AddNewSourceBuffer(F, SMLoc());

  // Check that we have all of the expected strings, in order, in the input
  // file.
  StringRef Buffer = F->getBuffer();

  const char *LastMatch = Buffer.data();

  for (unsigned StrNo = 0, e = CheckStrings.size(); StrNo != e; ++StrNo) {
    const CheckString &CheckStr = CheckStrings[StrNo];

    StringRef SearchFrom = Buffer;

    // Find StrNo in the file.
    size_t MatchLen = 0;
    Buffer = Buffer.substr(CheckStr.Pat.Match(Buffer, MatchLen));

    // If we didn't find a match, reject the input.
    if (Buffer.empty()) {
      PrintCheckFailed(SM, CheckStr, SearchFrom);
      return 1;
    }

    StringRef SkippedRegion(LastMatch, Buffer.data()-LastMatch);

    // If this check is a "CHECK-NEXT", verify that the previous match was on
    // the previous line (i.e. that there is one newline between them).
    if (CheckStr.IsCheckNext) {
      // Count the number of newlines between the previous match and this one.
      assert(LastMatch != F->getBufferStart() &&
             "CHECK-NEXT can't be the first check in a file");

      unsigned NumNewLines = CountNumNewlinesBetween(SkippedRegion);
      if (NumNewLines == 0) {
        SM.PrintMessage(CheckStr.Loc,
                    CheckPrefix+"-NEXT: is on the same line as previous match",
                        "error");
        SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()),
                        "'next' match was here", "note");
        SM.PrintMessage(SMLoc::getFromPointer(LastMatch),
                        "previous match was here", "note");
        return 1;
      }

      if (NumNewLines != 1) {
        SM.PrintMessage(CheckStr.Loc,
                        CheckPrefix+
                        "-NEXT: is not on the line after the previous match",
                        "error");
        SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()),
                        "'next' match was here", "note");
        SM.PrintMessage(SMLoc::getFromPointer(LastMatch),
                        "previous match was here", "note");
        return 1;
      }
    }

    // If this match had "not strings", verify that they don't exist in the
    // skipped region.
    for (unsigned i = 0, e = CheckStr.NotStrings.size(); i != e; ++i) {
      size_t MatchLen = 0;
      size_t Pos = CheckStr.NotStrings[i].second.Match(SkippedRegion, MatchLen);
      if (Pos == StringRef::npos) continue;

      SM.PrintMessage(SMLoc::getFromPointer(LastMatch+Pos),
                      CheckPrefix+"-NOT: string occurred!", "error");
      SM.PrintMessage(CheckStr.NotStrings[i].first,
                      CheckPrefix+"-NOT: pattern specified here", "note");
      return 1;
    }

    // Otherwise, everything is good.  Step over the matched text and remember
    // the position after the match as the end of the last match.
    Buffer = Buffer.substr(MatchLen);
    LastMatch = Buffer.data();
  }

  return 0;
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2014 odan
 * License: MIT License
 */

#ifndef INCLUDED_RNGLIB_HPP
#define INCLUDED_RNGLIB_HPP

#include "RNGLib/LCG.hpp"
#include "RNGLib/Calc5GenSeed.hpp"
#include "RNGLib/Parameters5Gen.hpp"
#include "RNGLib/ConstantParameters5Gen.hpp"
#include "RNGLib/ROMType.hpp"
#include "RNGLib/MT.hpp"

#include "RNGLib/DateTime/DateTime.hpp"
#include "RNGLib/DateTime/DateTimeRange.hpp"
#include "RNGLib/DateTime/DateTimeIterator.hpp"

#endif
<commit_msg>RNGLib.hppにCalcOffsetのincludeを追加<commit_after>/*
 * Copyright (c) 2014 odan
 * License: MIT License
 */

#ifndef INCLUDED_RNGLIB_HPP
#define INCLUDED_RNGLIB_HPP

#include "RNGLib/LCG.hpp"
#include "RNGLib/Calc5GenSeed.hpp"
#include "RNGLib/Parameters5Gen.hpp"
#include "RNGLib/ConstantParameters5Gen.hpp"
#include "RNGLib/ROMType.hpp"
#include "RNGLib/MT.hpp"
#include "RNGLib/CalcOffset.hpp"

#include "RNGLib/DateTime/DateTime.hpp"
#include "RNGLib/DateTime/DateTimeRange.hpp"
#include "RNGLib/DateTime/DateTimeIterator.hpp"

#endif
<|endoftext|>


<commit_before>// Copyright (c) 2011-2013 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "peertablemodel.h"

#include "clientmodel.h"
#include "guiconstants.h"
#include "guiutil.h"

#include "net.h"
#include "sync.h"

#include <QDebug>
#include <QList>
#include <QTimer>

bool NodeLessThan::operator()(const CNodeCombinedStats &left, const CNodeCombinedStats &right) const
{
    const CNodeStats *pLeft = &(left.nodeStats);
    const CNodeStats *pRight = &(right.nodeStats);

    if (order == Qt::DescendingOrder)
        std::swap(pLeft, pRight);

    switch(column)
    {
    case PeerTableModel::Address:
        return pLeft->addrName.compare(pRight->addrName) < 0;
    case PeerTableModel::Subversion:
        return pLeft->cleanSubVer.compare(pRight->cleanSubVer) < 0;
    case PeerTableModel::Ping:
        return pLeft->dPingTime < pRight->dPingTime;
    }

    return false;
}

// private implementation
class PeerTablePriv
{
public:
    /** Local cache of peer information */
    QList<CNodeCombinedStats> cachedNodeStats;
    /** Column to sort nodes by */
    int sortColumn;
    /** Order (ascending or descending) to sort nodes by */
    Qt::SortOrder sortOrder;
    /** Index of rows by node ID */
    std::map<NodeId, int> mapNodeRows;

    /** Pull a full list of peers from vNodes into our cache */
    void refreshPeers()
    {
        {
            TRY_LOCK(cs_vNodes, lockNodes);
            if (!lockNodes)
            {
                // skip the refresh if we can't immediately get the lock
                return;
            }
            cachedNodeStats.clear();
#if QT_VERSION >= 0x040700
            cachedNodeStats.reserve(vNodes.size());
#endif
            BOOST_FOREACH(CNode* pnode, vNodes)
            {
                CNodeCombinedStats stats;
                stats.nodeStateStats.nMisbehavior = 0;
                //stats.nodeStateStats.nSyncHeight = -1; //introduce after headers first
                stats.fNodeStateStatsAvailable = false;
                pnode->copyStats(stats.nodeStats);
                cachedNodeStats.append(stats);
            }
        }

        // Try to retrieve the CNodeStateStats for each node.
        BOOST_FOREACH(CNodeCombinedStats &stats, cachedNodeStats)
            stats.fNodeStateStatsAvailable = GetNodeStateStats(stats.nodeStats.nodeid, stats.nodeStateStats);

        if (sortColumn >= 0)
            // sort cacheNodeStats (use stable sort to prevent rows jumping around unneceesarily)
            qStableSort(cachedNodeStats.begin(), cachedNodeStats.end(), NodeLessThan(sortColumn, sortOrder));

        // build index map
        mapNodeRows.clear();
        int row = 0;
        BOOST_FOREACH(CNodeCombinedStats &stats, cachedNodeStats)
            mapNodeRows.insert(std::pair<NodeId, int>(stats.nodeStats.nodeid, row++));
    }

    int size()
    {
        return cachedNodeStats.size();
    }

    CNodeCombinedStats *index(int idx)
    {
        if(idx >= 0 && idx < cachedNodeStats.size()) {
            return &cachedNodeStats[idx];
        } else {
            return 0;
        }
    }
};

PeerTableModel::PeerTableModel(ClientModel *parent) :
    QAbstractTableModel(parent),
    clientModel(parent),
    timer(0)
{
    columns << tr("Address/Hostname") << tr("User Agent") << tr("Ping Time");
    priv = new PeerTablePriv();
    // default to unsorted
    priv->sortColumn = -1;

    // set up timer for auto refresh
    timer = new QTimer();
    connect(timer, SIGNAL(timeout()), SLOT(refresh()));
    timer->setInterval(MODEL_UPDATE_DELAY);

    // load initial data
    refresh();
}

void PeerTableModel::startAutoRefresh()
{
    timer->start();
}

void PeerTableModel::stopAutoRefresh()
{
    timer->stop();
}

int PeerTableModel::rowCount(const QModelIndex &parent) const
{
    Q_UNUSED(parent);
    return priv->size();
}

int PeerTableModel::columnCount(const QModelIndex &parent) const
{
    Q_UNUSED(parent);
    return columns.length();;
}

QVariant PeerTableModel::data(const QModelIndex &index, int role) const
{
    if(!index.isValid())
        return QVariant();

    CNodeCombinedStats *rec = static_cast<CNodeCombinedStats*>(index.internalPointer());

    if (role == Qt::DisplayRole) {
        switch(index.column())
        {
        case Address:
            return QString::fromStdString(rec->nodeStats.addrName);
        case Subversion:
            return QString::fromStdString(rec->nodeStats.cleanSubVer);
        case Ping:
            return GUIUtil::formatPingTime(rec->nodeStats.dPingTime);
        }
    } else if (role == Qt::TextAlignmentRole) {
        if (index.column() == Ping)
            return (int)(Qt::AlignRight | Qt::AlignVCenter);
    }

    return QVariant();
}

QVariant PeerTableModel::headerData(int section, Qt::Orientation orientation, int role) const
{
    if(orientation == Qt::Horizontal)
    {
        if(role == Qt::DisplayRole && section < columns.size())
        {
            return columns[section];
        }
    }
    return QVariant();
}

Qt::ItemFlags PeerTableModel::flags(const QModelIndex &index) const
{
    if(!index.isValid())
        return 0;

    Qt::ItemFlags retval = Qt::ItemIsSelectable | Qt::ItemIsEnabled;
    return retval;
}

QModelIndex PeerTableModel::index(int row, int column, const QModelIndex &parent) const
{
    Q_UNUSED(parent);
    CNodeCombinedStats *data = priv->index(row);

    if (data)
    {
        return createIndex(row, column, data);
    }
    else
    {
        return QModelIndex();
    }
}

const CNodeCombinedStats *PeerTableModel::getNodeStats(int idx)
{
    return priv->index(idx);
}

void PeerTableModel::refresh()
{
    emit layoutAboutToBeChanged();
    priv->refreshPeers();
    emit layoutChanged();
}

int PeerTableModel::getRowByNodeId(NodeId nodeid)
{
    std::map<NodeId, int>::iterator it = priv->mapNodeRows.find(nodeid);
    if (it == priv->mapNodeRows.end())
        return -1;

    return it->second;
}

void PeerTableModel::sort(int column, Qt::SortOrder order)
{
    priv->sortColumn = column;
    priv->sortOrder = order;
    refresh();
}
<commit_msg>[Qt] Add TRY_LOCK back to peertablemodel<commit_after>// Copyright (c) 2011-2013 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "peertablemodel.h"

#include "clientmodel.h"
#include "guiconstants.h"
#include "guiutil.h"

#include "net.h"
#include "sync.h"

#include <QDebug>
#include <QList>
#include <QTimer>

bool NodeLessThan::operator()(const CNodeCombinedStats &left, const CNodeCombinedStats &right) const
{
    const CNodeStats *pLeft = &(left.nodeStats);
    const CNodeStats *pRight = &(right.nodeStats);

    if (order == Qt::DescendingOrder)
        std::swap(pLeft, pRight);

    switch(column)
    {
    case PeerTableModel::Address:
        return pLeft->addrName.compare(pRight->addrName) < 0;
    case PeerTableModel::Subversion:
        return pLeft->cleanSubVer.compare(pRight->cleanSubVer) < 0;
    case PeerTableModel::Ping:
        return pLeft->dPingTime < pRight->dPingTime;
    }

    return false;
}

// private implementation
class PeerTablePriv
{
public:
    /** Local cache of peer information */
    QList<CNodeCombinedStats> cachedNodeStats;
    /** Column to sort nodes by */
    int sortColumn;
    /** Order (ascending or descending) to sort nodes by */
    Qt::SortOrder sortOrder;
    /** Index of rows by node ID */
    std::map<NodeId, int> mapNodeRows;

    /** Pull a full list of peers from vNodes into our cache */
    void refreshPeers()
    {
        {
            TRY_LOCK(cs_vNodes, lockNodes);
            if (!lockNodes)
            {
                // skip the refresh if we can't immediately get the lock
                return;
            }
            cachedNodeStats.clear();
#if QT_VERSION >= 0x040700
            cachedNodeStats.reserve(vNodes.size());
#endif
            BOOST_FOREACH(CNode* pnode, vNodes)
            {
                CNodeCombinedStats stats;
                stats.nodeStateStats.nMisbehavior = 0;
                //stats.nodeStateStats.nSyncHeight = -1; //introduce after headers first
                stats.fNodeStateStatsAvailable = false;
                pnode->copyStats(stats.nodeStats);
                cachedNodeStats.append(stats);
            }
        }

        // Try to retrieve the CNodeStateStats for each node.
        {
            TRY_LOCK(cs_main, lockMain);
            if (lockMain)
            {
                BOOST_FOREACH(CNodeCombinedStats &stats, cachedNodeStats)
                    stats.fNodeStateStatsAvailable = GetNodeStateStats(stats.nodeStats.nodeid, stats.nodeStateStats);
            }
        }

        if (sortColumn >= 0)
            // sort cacheNodeStats (use stable sort to prevent rows jumping around unneceesarily)
            qStableSort(cachedNodeStats.begin(), cachedNodeStats.end(), NodeLessThan(sortColumn, sortOrder));

        // build index map
        mapNodeRows.clear();
        int row = 0;
        BOOST_FOREACH(CNodeCombinedStats &stats, cachedNodeStats)
            mapNodeRows.insert(std::pair<NodeId, int>(stats.nodeStats.nodeid, row++));
    }

    int size()
    {
        return cachedNodeStats.size();
    }

    CNodeCombinedStats *index(int idx)
    {
        if(idx >= 0 && idx < cachedNodeStats.size()) {
            return &cachedNodeStats[idx];
        } else {
            return 0;
        }
    }
};

PeerTableModel::PeerTableModel(ClientModel *parent) :
    QAbstractTableModel(parent),
    clientModel(parent),
    timer(0)
{
    columns << tr("Address/Hostname") << tr("User Agent") << tr("Ping Time");
    priv = new PeerTablePriv();
    // default to unsorted
    priv->sortColumn = -1;

    // set up timer for auto refresh
    timer = new QTimer();
    connect(timer, SIGNAL(timeout()), SLOT(refresh()));
    timer->setInterval(MODEL_UPDATE_DELAY);

    // load initial data
    refresh();
}

void PeerTableModel::startAutoRefresh()
{
    timer->start();
}

void PeerTableModel::stopAutoRefresh()
{
    timer->stop();
}

int PeerTableModel::rowCount(const QModelIndex &parent) const
{
    Q_UNUSED(parent);
    return priv->size();
}

int PeerTableModel::columnCount(const QModelIndex &parent) const
{
    Q_UNUSED(parent);
    return columns.length();;
}

QVariant PeerTableModel::data(const QModelIndex &index, int role) const
{
    if(!index.isValid())
        return QVariant();

    CNodeCombinedStats *rec = static_cast<CNodeCombinedStats*>(index.internalPointer());

    if (role == Qt::DisplayRole) {
        switch(index.column())
        {
        case Address:
            return QString::fromStdString(rec->nodeStats.addrName);
        case Subversion:
            return QString::fromStdString(rec->nodeStats.cleanSubVer);
        case Ping:
            return GUIUtil::formatPingTime(rec->nodeStats.dPingTime);
        }
    } else if (role == Qt::TextAlignmentRole) {
        if (index.column() == Ping)
            return (int)(Qt::AlignRight | Qt::AlignVCenter);
    }

    return QVariant();
}

QVariant PeerTableModel::headerData(int section, Qt::Orientation orientation, int role) const
{
    if(orientation == Qt::Horizontal)
    {
        if(role == Qt::DisplayRole && section < columns.size())
        {
            return columns[section];
        }
    }
    return QVariant();
}

Qt::ItemFlags PeerTableModel::flags(const QModelIndex &index) const
{
    if(!index.isValid())
        return 0;

    Qt::ItemFlags retval = Qt::ItemIsSelectable | Qt::ItemIsEnabled;
    return retval;
}

QModelIndex PeerTableModel::index(int row, int column, const QModelIndex &parent) const
{
    Q_UNUSED(parent);
    CNodeCombinedStats *data = priv->index(row);

    if (data)
    {
        return createIndex(row, column, data);
    }
    else
    {
        return QModelIndex();
    }
}

const CNodeCombinedStats *PeerTableModel::getNodeStats(int idx)
{
    return priv->index(idx);
}

void PeerTableModel::refresh()
{
    emit layoutAboutToBeChanged();
    priv->refreshPeers();
    emit layoutChanged();
}

int PeerTableModel::getRowByNodeId(NodeId nodeid)
{
    std::map<NodeId, int>::iterator it = priv->mapNodeRows.find(nodeid);
    if (it == priv->mapNodeRows.end())
        return -1;

    return it->second;
}

void PeerTableModel::sort(int column, Qt::SortOrder order)
{
    priv->sortColumn = column;
    priv->sortOrder = order;
    refresh();
}
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2015 Dan Leinir Turthra Jensen <admin@leinir.dk>
 *
 * 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) version 3, or any
 * later version accepted by the membership of KDE e.V. (or its
 * successor approved by the membership of KDE e.V.), which shall
 * act as a proxy defined in Section 6 of version 3 of the license.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

#include "BookModel.h"

#include "KFileMetaData/UserMetaData"

struct BookPage {
    BookPage() {}
    QString url;
    QString title;
};

class BookModel::Private {
public:
    Private()
        : currentPage(-1)
    {}
    QString filename;
    QString author;
    QString publisher;
    QList<BookPage*> entries;
    int currentPage;
};

BookModel::BookModel(QObject* parent)
    : QAbstractListModel(parent)
    , d(new Private)
{
}

BookModel::~BookModel()
{
    delete d;
}

QHash<int, QByteArray> BookModel::roleNames() const
{
    QHash<int, QByteArray> roles;
    roles[UrlRole] = "url";
    roles[TitleRole] = "title";
    return roles;
}

QVariant BookModel::data(const QModelIndex& index, int role) const
{
    QVariant result;
    if(index.isValid() && index.row() > -1 && index.row() < d->entries.count())
    {
        const BookPage* entry = d->entries[index.row()];
        switch(role)
        {
            case UrlRole:
                result.setValue(entry->url);
                break;
            case TitleRole:
                result.setValue(entry->title);
                break;
            default:
                result.setValue(QString("Unknown role"));
                break;
        }
    }
    return result;
}

int BookModel::rowCount(const QModelIndex& parent) const
{
    if(parent.isValid())
        return 0;
    return d->entries.count();
}

void BookModel::addPage(QString url, QString title)
{
    BookPage* page = new BookPage();
    page->url = url;
    page->title = title;

    beginInsertRows(QModelIndex(), d->entries.count(), d->entries.count());
    d->entries.append(page);
    emit pageCountChanged();
    endInsertRows();
}

QString BookModel::filename() const
{
    return d->filename;
}

void BookModel::setFilename(QString newFilename)
{
    d->filename = newFilename;
    emit filenameChanged();
}

QString BookModel::author() const
{
    return d->author;
}

void BookModel::setAuthor(QString newAuthor)
{
    d->author = newAuthor;
    emit authorChanged();
}

QString BookModel::publisher() const
{
    return d->publisher;
}

void BookModel::setPublisher(QString newPublisher)
{
    d->publisher = newPublisher;
    emit publisherChanged();
}

int BookModel::pageCount() const
{
    return d->entries.count();
}

int BookModel::currentPage() const
{
    return d->currentPage;
}
#include "QDebug"
void BookModel::setCurrentPage(int newCurrentPage, bool updateFilesystem)
{
//     qDebug() << Q_FUNC_INFO << d->filename << newCurrentPage << updateFilesystem;
    if(updateFilesystem)
    {
        KFileMetaData::UserMetaData data(d->filename);
        data.setAttribute("peruse.currentPage", QString::number(newCurrentPage));
    }
    d->currentPage = newCurrentPage;
    emit currentPageChanged();
}
<commit_msg>Stray include leftovers--<commit_after>/*
 * Copyright (C) 2015 Dan Leinir Turthra Jensen <admin@leinir.dk>
 *
 * 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) version 3, or any
 * later version accepted by the membership of KDE e.V. (or its
 * successor approved by the membership of KDE e.V.), which shall
 * act as a proxy defined in Section 6 of version 3 of the license.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

#include "BookModel.h"

#include "KFileMetaData/UserMetaData"

struct BookPage {
    BookPage() {}
    QString url;
    QString title;
};

class BookModel::Private {
public:
    Private()
        : currentPage(-1)
    {}
    QString filename;
    QString author;
    QString publisher;
    QList<BookPage*> entries;
    int currentPage;
};

BookModel::BookModel(QObject* parent)
    : QAbstractListModel(parent)
    , d(new Private)
{
}

BookModel::~BookModel()
{
    delete d;
}

QHash<int, QByteArray> BookModel::roleNames() const
{
    QHash<int, QByteArray> roles;
    roles[UrlRole] = "url";
    roles[TitleRole] = "title";
    return roles;
}

QVariant BookModel::data(const QModelIndex& index, int role) const
{
    QVariant result;
    if(index.isValid() && index.row() > -1 && index.row() < d->entries.count())
    {
        const BookPage* entry = d->entries[index.row()];
        switch(role)
        {
            case UrlRole:
                result.setValue(entry->url);
                break;
            case TitleRole:
                result.setValue(entry->title);
                break;
            default:
                result.setValue(QString("Unknown role"));
                break;
        }
    }
    return result;
}

int BookModel::rowCount(const QModelIndex& parent) const
{
    if(parent.isValid())
        return 0;
    return d->entries.count();
}

void BookModel::addPage(QString url, QString title)
{
    BookPage* page = new BookPage();
    page->url = url;
    page->title = title;

    beginInsertRows(QModelIndex(), d->entries.count(), d->entries.count());
    d->entries.append(page);
    emit pageCountChanged();
    endInsertRows();
}

QString BookModel::filename() const
{
    return d->filename;
}

void BookModel::setFilename(QString newFilename)
{
    d->filename = newFilename;
    emit filenameChanged();
}

QString BookModel::author() const
{
    return d->author;
}

void BookModel::setAuthor(QString newAuthor)
{
    d->author = newAuthor;
    emit authorChanged();
}

QString BookModel::publisher() const
{
    return d->publisher;
}

void BookModel::setPublisher(QString newPublisher)
{
    d->publisher = newPublisher;
    emit publisherChanged();
}

int BookModel::pageCount() const
{
    return d->entries.count();
}

int BookModel::currentPage() const
{
    return d->currentPage;
}

void BookModel::setCurrentPage(int newCurrentPage, bool updateFilesystem)
{
//     qDebug() << Q_FUNC_INFO << d->filename << newCurrentPage << updateFilesystem;
    if(updateFilesystem)
    {
        KFileMetaData::UserMetaData data(d->filename);
        data.setAttribute("peruse.currentPage", QString::number(newCurrentPage));
    }
    d->currentPage = newCurrentPage;
    emit currentPageChanged();
}
<|endoftext|>


<commit_before><commit_msg>remove unused variable<commit_after><|endoftext|>


<commit_before>#include <iostream>
#include <fstream>
#include <boost/regex.hpp>
#include "Reseed.h"
#include "Log.h"
#include "util.h"

namespace i2p
{
namespace data
{

	static std::vector<std::string> httpReseedHostList = {
				"http://193.150.121.66/netDb/",
				"http://netdb.i2p2.no/",
				"http://reseed.i2p-projekt.de/",
				"http://cowpuncher.drollette.com/netdb/",
				"http://i2p.mooo.com/netDb/",
				"http://reseed.info/",
				"http://reseed.pkol.de/",
				"http://uk.reseed.i2p2.no/",
				"http://i2p-netdb.innovatio.no/",
				"http://ieb9oopo.mooo.com"
			};

	//TODO: Implement v2 reseeding. Lightweight zip library is needed.
	//TODO: Implement SU3, utils.
	Reseeder::Reseeder()
	{
	}

	Reseeder::~Reseeder()
	{
	}

	bool Reseeder::reseedNow()
	{
		try
		{
			std::string reseedHost = httpReseedHostList[(rand() % httpReseedHostList.size())];
			LogPrint("Reseeding from ", reseedHost);
			std::string content = i2p::util::http::httpRequest(reseedHost);
			if (content == "")
			{
				LogPrint("Reseed failed");
				return false;
			}
			boost::regex e("<\\s*A\\s+[^>]*href\\s*=\\s*\"([^\"]*)\"", boost::regex::normal | boost::regbase::icase);
			boost::sregex_token_iterator i(content.begin(), content.end(), e, 1);
			boost::sregex_token_iterator j;
			//TODO: Ugly code, try to clean up.
			//TODO: Try to reduce N number of variables
			std::string name;
			std::string routerInfo;
			std::string tmpUrl;
			std::string filename;
			std::string ignoreFileSuffix = ".zip";
			while (i != j)
			{
				name = *i++;
				if (name.find(ignoreFileSuffix)!=std::string::npos)
					continue;
				LogPrint("Downloading ", name);
				tmpUrl = reseedHost;
				tmpUrl.append(name);
				routerInfo = i2p::util::http::httpRequest(tmpUrl);
				filename = "netDb/r";
				filename += name.at(11); // first char in id
				filename.append("/");
				filename.append(name.c_str());
				std::ofstream outfile (filename, std::ios::binary);
				outfile << routerInfo;
				outfile.close();
			}
			return true;
		}
		catch (std::exception& ex)
		{
			//TODO: error reporting
			return false;
		}
		return false;
	}

}
}

<commit_msg>Fixing reseed<commit_after>#include <iostream>
#include <fstream>
#include <boost/regex.hpp>
#include <boost/filesystem.hpp>
#include "Reseed.h"
#include "Log.h"
#include "util.h"

namespace i2p
{
namespace data
{

	static std::vector<std::string> httpReseedHostList = {
				"http://193.150.121.66/netDb/",
				"http://netdb.i2p2.no/",
				"http://reseed.i2p-projekt.de/",
				"http://cowpuncher.drollette.com/netdb/",
				"http://i2p.mooo.com/netDb/",
				"http://reseed.info/",
				"http://reseed.pkol.de/",
				"http://uk.reseed.i2p2.no/",
				"http://i2p-netdb.innovatio.no/",
				"http://ieb9oopo.mooo.com"
			};

	//TODO: Implement v2 reseeding. Lightweight zip library is needed.
	//TODO: Implement SU3, utils.
	Reseeder::Reseeder()
	{
	}

	Reseeder::~Reseeder()
	{
	}

	bool Reseeder::reseedNow()
	{
		try
		{
			std::string reseedHost = httpReseedHostList[(rand() % httpReseedHostList.size())];
			LogPrint("Reseeding from ", reseedHost);
			std::string content = i2p::util::http::httpRequest(reseedHost);
			if (content == "")
			{
				LogPrint("Reseed failed");
				return false;
			}
			boost::regex e("<\\s*A\\s+[^>]*href\\s*=\\s*\"([^\"]*)\"", boost::regex::normal | boost::regbase::icase);
			boost::sregex_token_iterator i(content.begin(), content.end(), e, 1);
			boost::sregex_token_iterator j;
			//TODO: Ugly code, try to clean up.
			//TODO: Try to reduce N number of variables
			std::string name;
			std::string routerInfo;
			std::string tmpUrl;
			std::string filename;
			std::string ignoreFileSuffix = ".zip";
			boost::filesystem::path root = i2p::util::filesystem::GetDataDir();
			while (i != j)
			{
				name = *i++;
				if (name.find(ignoreFileSuffix)!=std::string::npos)
					continue;
				LogPrint("Downloading ", name);
				tmpUrl = reseedHost;
				tmpUrl.append(name);
				routerInfo = i2p::util::http::httpRequest(tmpUrl);
				if (routerInfo.size()==0)
					continue;
				filename = root.string();
#ifndef _WIN32
				filename += "/netDb/r";
#else
				filename += "\\netDb\\r";
#endif
				filename += name.at(11); // first char in id
#ifndef _WIN32
				filename.append("/");
#else
				filename.append("\\");
#endif
				filename.append(name.c_str());
				std::ofstream outfile (filename, std::ios::binary);
				outfile << routerInfo;
				outfile.close();
			}
			return true;
		}
		catch (std::exception& ex)
		{
			//TODO: error reporting
			return false;
		}
		return false;
	}

}
}

<|endoftext|>


<commit_before>#include <speck/speck.h>
#include <stdio.h>
#include <string.h>
#include <cstdlib>

// https://eprint.iacr.org/2013/404.pdf
//
// Speck128/128
//  Key:        0f0e0d0c0b0a0908 0706050403020100
//  Plaintext:  6c61766975716520 7469206564616d20
//  Ciphertext: a65d985179783265 7860fedf5c570d18
static const uint64_t s_key[2] = {0x0706050403020100, 0x0f0e0d0c0b0a0908};
static const uint64_t s_plain_text[2] = {0x7469206564616d20, 0x6c61766975716520};
static const uint64_t s_cipher_text[2] = {0x7860fedf5c570d18, 0xa65d985179783265};
static const uint8_t s_plain_text_stream[16] = {
        0x20, 0x6d, 0x61, 0x64, 0x65, 0x20, 0x69, 0x74, 0x20, 0x65, 0x71, 0x75, 0x69, 0x76, 0x61, 0x6c,
};
static const uint8_t s_cipher_text_stream[16] = {
        0x18, 0x0d, 0x57, 0x5c, 0xdf, 0xfe, 0x60, 0x78, 0x65, 0x32, 0x78, 0x79, 0x51, 0x98, 0x5d, 0xa6,
};

int main() {

    // block encrypt & decrypt
    {
        speck_ctx_t *ctx = speck_init(SPECK_ENCRYPT_TYPE_128_128, SPECK_BLOCK_CIPHER_MODE_ECB, s_key);
        if(!ctx) return 1;

        uint64_t plain_text[2];
        uint64_t cipher_text[2];
        uint64_t decrypted_text[2];

        plain_text[0] = 0x7469206564616d20;
        plain_text[1] = 0x6c61766975716520;

        printf("ECB block encrypt decrypt\n");

        speck_encrypt(ctx, plain_text, cipher_text);
        printf("%20s 0x%llx 0x%llx\n", "encrypted : ", cipher_text[1], cipher_text[0]);
        if(!(cipher_text[0] == s_cipher_text[0] && cipher_text[1] == s_cipher_text[1])) {
            return 1;
        }

        speck_decrypt(ctx, cipher_text, decrypted_text);
        printf("%20s 0x%llx 0x%llx\n", "decrypted : ", decrypted_text[1], decrypted_text[0]);
        if(!(decrypted_text[0] == s_plain_text[0] && decrypted_text[1] == s_plain_text[1])) {
            return 1;
        }

        printf("\n");

        speck_finish(&ctx);
    }

    // ECB stream encrypt & decrypt
    {
        speck_ctx_t *ctx = speck_init(SPECK_ENCRYPT_TYPE_128_128, SPECK_BLOCK_CIPHER_MODE_ECB, s_key);
        if(!ctx) return 1;

        int i;
        size_t siz = 16;
        unsigned char *plain_text = (unsigned char*) calloc(1, siz);
        unsigned char *crypted_text = (unsigned char*) calloc(1, siz);
        unsigned char *decrypted_text = (unsigned char*) calloc(1, siz);

        memcpy(plain_text, s_plain_text_stream, sizeof(s_cipher_text_stream));

        printf("ECB stream ph1\n");

        printf("%20s ", "plain text :");
        for(i=siz-1;i >=0;i--)
            printf("%02x ", plain_text[i]);
        printf("\n");

        speck_encrypt_ex(ctx, plain_text, crypted_text, siz);
        printf("%20s ", "encrypted text :");
        for(i=siz-1;i >=0;i--)
            printf("%02x ", crypted_text[i]);
        printf("\n");
        // check
        for (int i = 0; i < siz; i++) {
            if (s_cipher_text_stream[i] != crypted_text[i]) {
                printf("encrypted error idx:%d  0x%02x != 0x%02x\n", i, s_cipher_text_stream[i], crypted_text[i]);
                return 1;
            }
        }

        speck_decrypt_ex(ctx, crypted_text, decrypted_text, siz);
        printf("%20s ", "decrypted text :");
        for(int i=siz-1;i >=0;i--)
            printf("%02x ", decrypted_text[i]);
        printf("\n");

        // check
        for (int i = 0; i < siz; i++) {
            if (s_plain_text_stream[i] != decrypted_text[i]) {
                printf("decrypted error idx:%d  0x%02x != 0x%02x\n", i, s_plain_text_stream[i], decrypted_text[i]);
                return 1;
            }
        }
        printf("\n");

        free(decrypted_text);
        free(crypted_text);
        free(plain_text);

        speck_finish(&ctx);
    }

    // ECB stream encrypt & decrypt ph2
    {
        speck_ctx_t *ctx = speck_init(SPECK_ENCRYPT_TYPE_128_128, SPECK_BLOCK_CIPHER_MODE_ECB, s_key);
        if(!ctx) return 1;

        size_t siz = 128;
        int i;
        unsigned char *plain_text = (unsigned char*)calloc(1, siz);
        unsigned char *crypted_text = (unsigned char*)calloc(1, siz);
        unsigned char *decrypted_text = (unsigned char*)calloc(1, siz);

        printf("ECB stream ph2\n");

        memcpy(plain_text, "abcdefghijklmnopqrstyvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ", siz);
        printf("%20s ", "plain text :");
        for(i=siz-1;i>=0;i--)
            printf("%02x ", plain_text[i]);
        printf("\n");

        speck_encrypt_ex(ctx, plain_text, crypted_text, siz);
        printf("%20s ", "encrypted text :");
        for(i=siz-1;i>=0;i--)
            printf("%02x ", crypted_text[i]);
        printf("\n");

        speck_decrypt_ex(ctx, crypted_text, decrypted_text, siz);
        printf("%20s ", "decrypted text :");
        for(i=siz-1;i>=0;i--)
            printf("%02x ", decrypted_text[i]);
        printf("\n");

        // check
        for (int i = 0; i < siz; i++) {
            if (plain_text[i] != decrypted_text[i]) {
                printf("decrypted error idx:%d  0x%02x != 0x%02x\n", i, plain_text[i], decrypted_text[i]);
                return 1;
            }
        }
        printf("\n");

        free(decrypted_text);
        free(crypted_text);
        free(plain_text);

        speck_finish(&ctx);
    }

    return 0;
}
<commit_msg>fix coverity detect<commit_after>#include <speck/speck.h>
#include <stdio.h>
#include <string.h>
#include <cstdlib>

// https://eprint.iacr.org/2013/404.pdf
//
// Speck128/128
//  Key:        0f0e0d0c0b0a0908 0706050403020100
//  Plaintext:  6c61766975716520 7469206564616d20
//  Ciphertext: a65d985179783265 7860fedf5c570d18
static const uint64_t s_key[2] = {0x0706050403020100, 0x0f0e0d0c0b0a0908};
static const uint64_t s_plain_text[2] = {0x7469206564616d20, 0x6c61766975716520};
static const uint64_t s_cipher_text[2] = {0x7860fedf5c570d18, 0xa65d985179783265};
static const uint8_t s_plain_text_stream[16] = {
        0x20, 0x6d, 0x61, 0x64, 0x65, 0x20, 0x69, 0x74, 0x20, 0x65, 0x71, 0x75, 0x69, 0x76, 0x61, 0x6c,
};
static const uint8_t s_cipher_text_stream[16] = {
        0x18, 0x0d, 0x57, 0x5c, 0xdf, 0xfe, 0x60, 0x78, 0x65, 0x32, 0x78, 0x79, 0x51, 0x98, 0x5d, 0xa6,
};

int main() {

    // block encrypt & decrypt
    {
        speck_ctx_t *ctx = speck_init(SPECK_ENCRYPT_TYPE_128_128, SPECK_BLOCK_CIPHER_MODE_ECB, s_key);
        if(!ctx) return 1;

        uint64_t plain_text[2];
        uint64_t cipher_text[2];
        uint64_t decrypted_text[2];

        plain_text[0] = 0x7469206564616d20;
        plain_text[1] = 0x6c61766975716520;

        printf("ECB block encrypt decrypt\n");

        speck_encrypt(ctx, plain_text, cipher_text);
        printf("%20s 0x%llx 0x%llx\n", "encrypted : ", cipher_text[1], cipher_text[0]);
        if(!(cipher_text[0] == s_cipher_text[0] && cipher_text[1] == s_cipher_text[1])) {
            return 1;
        }

        speck_decrypt(ctx, cipher_text, decrypted_text);
        printf("%20s 0x%llx 0x%llx\n", "decrypted : ", decrypted_text[1], decrypted_text[0]);
        if(!(decrypted_text[0] == s_plain_text[0] && decrypted_text[1] == s_plain_text[1])) {
            return 1;
        }

        printf("\n");

        speck_finish(&ctx);
    }

    // ECB stream encrypt & decrypt
    {
        speck_ctx_t *ctx = speck_init(SPECK_ENCRYPT_TYPE_128_128, SPECK_BLOCK_CIPHER_MODE_ECB, s_key);
        if(!ctx) return 1;

        int i;
        size_t siz = 16;
        unsigned char *plain_text = (unsigned char*) calloc(1, siz);
        unsigned char *crypted_text = (unsigned char*) calloc(1, siz);
        unsigned char *decrypted_text = (unsigned char*) calloc(1, siz);

        memcpy(plain_text, s_plain_text_stream, sizeof(s_cipher_text_stream));

        printf("ECB stream ph1\n");

        printf("%20s ", "plain text :");
        for(i=siz-1;i >=0;i--)
            printf("%02x ", plain_text[i]);
        printf("\n");

        speck_encrypt_ex(ctx, plain_text, crypted_text, siz);
        printf("%20s ", "encrypted text :");
        for(i=siz-1;i >=0;i--)
            printf("%02x ", crypted_text[i]);
        printf("\n");
        // check
        for (int i = 0; i < siz; i++) {
            if (s_cipher_text_stream[i] != crypted_text[i]) {
                printf("encrypted error idx:%d  0x%02x != 0x%02x\n", i, s_cipher_text_stream[i], crypted_text[i]);
                return 1;
            }
        }

        speck_decrypt_ex(ctx, crypted_text, decrypted_text, siz);
        printf("%20s ", "decrypted text :");
        for(int i=siz-1;i >=0;i--)
            printf("%02x ", decrypted_text[i]);
        printf("\n");

        // check
        for (int i = 0; i < siz; i++) {
            if (s_plain_text_stream[i] != decrypted_text[i]) {
                printf("decrypted error idx:%d  0x%02x != 0x%02x\n", i, s_plain_text_stream[i], decrypted_text[i]);
                return 1;
            }
        }
        printf("\n");

        free(decrypted_text);
        free(crypted_text);
        free(plain_text);

        speck_finish(&ctx);
    }

    // ECB stream encrypt & decrypt ph2
    {
        speck_ctx_t *ctx = speck_init(SPECK_ENCRYPT_TYPE_128_128, SPECK_BLOCK_CIPHER_MODE_ECB, s_key);
        if(!ctx) return 1;

        size_t siz = 80;
        int i;
        unsigned char *plain_text = (unsigned char*)calloc(1, siz);
        unsigned char *crypted_text = (unsigned char*)calloc(1, siz);
        unsigned char *decrypted_text = (unsigned char*)calloc(1, siz);

        printf("ECB stream ph2\n");

        char *test = "abcdefghijklmnopqrstyvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstyvwxyz";
        memcpy(plain_text, test, strlen(test));
        printf("%20s ", "plain text :");
        for(i=siz-1;i>=0;i--)
            printf("%02x ", plain_text[i]);
        printf("\n");

        speck_encrypt_ex(ctx, plain_text, crypted_text, siz);
        printf("%20s ", "encrypted text :");
        for(i=siz-1;i>=0;i--)
            printf("%02x ", crypted_text[i]);
        printf("\n");

        speck_decrypt_ex(ctx, crypted_text, decrypted_text, siz);
        printf("%20s ", "decrypted text :");
        for(i=siz-1;i>=0;i--)
            printf("%02x ", decrypted_text[i]);
        printf("\n");

        // check
        for (int i = 0; i < siz; i++) {
            if (plain_text[i] != decrypted_text[i]) {
                printf("decrypted error idx:%d  0x%02x != 0x%02x\n", i, plain_text[i], decrypted_text[i]);
                return 1;
            }
        }
        printf("\n");

        free(decrypted_text);
        free(crypted_text);
        free(plain_text);

        speck_finish(&ctx);
    }

    return 0;
}
<|endoftext|>


<commit_before>/***********************************************************************************************************************
*                                                                                *
* SPLASH build system v0.2                                                                                *
*                                                                                *
* Copyright (c) 2016 Andrew D. Zonenberg                                                                               *
* All rights reserved.                                                                                *
*                                                                                *
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the     *
* following conditions are met:                                                                                *
*                                                                                *
*    * Redistributions of source code must retain the above copyright notice, this list of conditions, and the         *
*      following disclaimer.                                                                                *
*                                                                                *
*    * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the       *
*      following disclaimer in the documentation and/or other materials provided with the distribution.                *
*                                                                                *
*    * Neither the name of the author nor the names of any contributors may be used to endorse or promote products     *
*      derived from this software without specific prior written permission.                                           *
*                                                                                *
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED   *
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL *
* THE AUTHORS BE HELD LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES        *
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR       *
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE       *
* POSSIBILITY OF SUCH DAMAGE.                                                                                *
*                                                                                *
***********************************************************************************************************************/

#include "splashbuild.h"

using namespace std;

void ShowUsage();
void ShowVersion();

//map of toolchain hashes to toolchain objects
map<string, Toolchain*> g_toolchains;

/**
	@brief Program entry point
 */
int main(int argc, char* argv[])
{
	string ctl_server;

	LogSink::Severity console_verbosity = LogSink::NOTICE;

	//TODO: argument for this?
	int port = 49000;

	//Parse command-line arguments
	for(int i=1; i<argc; i++)
	{
		string s(argv[i]);

		//Let the logger eat its args first
		if(ParseLoggerArguments(i, argc, argv, console_verbosity))
			continue;

		else if(s == "--help")
		{
			ShowUsage();
			return 0;
		}

		else if(s == "--version")
		{
			ShowVersion();
			return 0;
		}

		//Last args without switche is control server.
		//TODO: mandatory arguments to introduce these?
		else
			ctl_server = argv[i];

	}

	//Set up logging
	g_log_sinks.emplace(g_log_sinks.begin(), new STDLogSink(console_verbosity));

	//Print header
	if(console_verbosity >= LogSink::NOTICE)
	{
		ShowVersion();
		printf("\n");
	}

	//Connect to the server
	LogVerbose("Connecting to server...\n");
	Socket sock(AF_INET, SOCK_STREAM, IPPROTO_TCP);
	sock.Connect(ctl_server, port);

	//Get the serverHello
	msgServerHello shi;
	if(!sock.RecvLooped((unsigned char*)&shi, sizeof(shi)))
	{
		LogWarning("Connection dropped (while reading serverHello)\n");
		return 1;
	}
	if(shi.serverVersion != 1)
	{
		LogWarning("Connection dropped (bad version number in serverHello)\n");
		return 1;
	}
	if(shi.type != MSG_TYPE_SERVERHELLO)
	{
		LogWarning("Connection dropped (bad message type in serverHello)\n");
		return 1;
	}

	//Send the clientHello
	msgClientHello chi(CLIENT_BUILD);
	if(!sock.SendLooped((unsigned char*)&chi, sizeof(chi)))
	{
		LogWarning("Connection dropped (while sending clientHello)\n");
		return 1;
	}
	string hostname = ShellCommand("hostname", true);
	if(!sock.SendPascalString(hostname))
	{
		LogWarning("Connection dropped (while sending clientHello.hostname)\n");
		return 1;
	}

	//Validate the connection
	if(chi.magic != shi.magic)
	{
		LogWarning("Connection dropped (bad magic number in serverHello)\n");
		return 1;
	}

	//Look for compilers
	LogVerbose("Enumerating compilers...\n");
	FindLinkers();
	FindCPPCompilers();
	FindFPGACompilers();

	//Get some basic metadata about our hardware and tell the server
	msgBuildInfo binfo;
	binfo.cpuCount = atoi(ShellCommand("cat /proc/cpuinfo  | grep processor | wc -l").c_str());
	binfo.cpuSpeed = atoi(ShellCommand("cat /proc/cpuinfo | grep bogo | head -n 1 | cut -d : -f 2").c_str());
	binfo.ramSize = atol(ShellCommand("cat /proc/meminfo  | grep MemTotal  | cut -d : -f 2").c_str()) / 1024;
	binfo.toolchainCount = g_toolchains.size();
	if(!sock.SendLooped((unsigned char*)&binfo, sizeof(binfo)))
	{
		LogWarning("Connection dropped (while sending buildInfo)\n");
		return 1;
	}

	//Report the toolchains we found to the server
	for(auto it : g_toolchains)
	{
		auto t = it.second;

		vector<string> langs;
		t->GetSupportedLanguages(langs);
		auto triplets = t->GetTargetTriplets();

		//DEBUG: Print it out
		//t->DebugPrint();

		//Send the toolchain header to the server
		msgAddCompiler tadd;
		tadd.compilerType = t->GetType();
		tadd.versionNum =	(t->GetMajorVersion() << 24) |
							(t->GetMinorVersion() << 16) |
							(t->GetPatchVersion() << 8);
		tadd.numLangs = langs.size();
		tadd.numTriplets = triplets.size();
		if(!sock.SendLooped((unsigned char*)&tadd, sizeof(tadd)))
		{
			LogWarning("Connection dropped (while sending addCompiler)\n");
			return 1;
		}

		//Send supplemental payload data
		if(!sock.SendPascalString(t->GetHash()))
		{
			LogWarning("Connection dropped (while sending addCompiler)\n");
			return 1;
		}
		if(!sock.SendPascalString(t->GetVersionString()))
		{
			LogWarning("Connection dropped (while sending addCompiler)\n");
			return 1;
		}
		vector<Toolchain::Language> dlangs = t->GetSupportedLanguages();
		for(auto x : dlangs)
		{
			uint8_t l = x;
			if(!sock.SendLooped((unsigned char*)&l, 1))
			{
				LogWarning("Connection dropped (while sending addCompiler)\n");
				return 1;
			}
		}
		for(auto x : triplets)
		{
			if(!sock.SendPascalString(x))
			{
				LogWarning("Connection dropped (while sending addCompiler)\n");
				return 1;
			}
		}
	}

	//TODO: Sit around and wait for stuff to come in

	//clean up
	for(auto x : g_toolchains)
		delete x.second;
	g_toolchains.clear();

	return 0;
}

void ShowVersion()
{
	printf(
		"SPLASH build server daemon by Andrew D. Zonenberg.\n"
		"\n"
		"License: 3-clause BSD\n"
		"This is free software: you are free to change and redistribute it.\n"
		"There is NO WARRANTY, to the extent permitted by law.\n");
}

void ShowUsage()
{
	printf("Usage: splashbuild ctlserver\n");
	exit(0);
}
<commit_msg>Updated log severity code for new logtools<commit_after>/***********************************************************************************************************************
*                                                                                *
* SPLASH build system v0.2                                                                                *
*                                                                                *
* Copyright (c) 2016 Andrew D. Zonenberg                                                                               *
* All rights reserved.                                                                                *
*                                                                                *
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the     *
* following conditions are met:                                                                                *
*                                                                                *
*    * Redistributions of source code must retain the above copyright notice, this list of conditions, and the         *
*      following disclaimer.                                                                                *
*                                                                                *
*    * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the       *
*      following disclaimer in the documentation and/or other materials provided with the distribution.                *
*                                                                                *
*    * Neither the name of the author nor the names of any contributors may be used to endorse or promote products     *
*      derived from this software without specific prior written permission.                                           *
*                                                                                *
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED   *
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL *
* THE AUTHORS BE HELD LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES        *
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR       *
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE       *
* POSSIBILITY OF SUCH DAMAGE.                                                                                *
*                                                                                *
***********************************************************************************************************************/

#include "splashbuild.h"

using namespace std;

void ShowUsage();
void ShowVersion();

//map of toolchain hashes to toolchain objects
map<string, Toolchain*> g_toolchains;

/**
	@brief Program entry point
 */
int main(int argc, char* argv[])
{
	string ctl_server;

	Severity console_verbosity = Severity::NOTICE;

	//TODO: argument for this?
	int port = 49000;

	//Parse command-line arguments
	for(int i=1; i<argc; i++)
	{
		string s(argv[i]);

		//Let the logger eat its args first
		if(ParseLoggerArguments(i, argc, argv, console_verbosity))
			continue;

		else if(s == "--help")
		{
			ShowUsage();
			return 0;
		}

		else if(s == "--version")
		{
			ShowVersion();
			return 0;
		}

		//Last args without switche is control server.
		//TODO: mandatory arguments to introduce these?
		else
			ctl_server = argv[i];

	}

	//Set up logging
	g_log_sinks.emplace(g_log_sinks.begin(), new STDLogSink(console_verbosity));

	//Print header
	if(console_verbosity >= Severity::NOTICE)
	{
		ShowVersion();
		printf("\n");
	}

	//Connect to the server
	LogVerbose("Connecting to server...\n");
	Socket sock(AF_INET, SOCK_STREAM, IPPROTO_TCP);
	sock.Connect(ctl_server, port);

	//Get the serverHello
	msgServerHello shi;
	if(!sock.RecvLooped((unsigned char*)&shi, sizeof(shi)))
	{
		LogWarning("Connection dropped (while reading serverHello)\n");
		return 1;
	}
	if(shi.serverVersion != 1)
	{
		LogWarning("Connection dropped (bad version number in serverHello)\n");
		return 1;
	}
	if(shi.type != MSG_TYPE_SERVERHELLO)
	{
		LogWarning("Connection dropped (bad message type in serverHello)\n");
		return 1;
	}

	//Send the clientHello
	msgClientHello chi(CLIENT_BUILD);
	if(!sock.SendLooped((unsigned char*)&chi, sizeof(chi)))
	{
		LogWarning("Connection dropped (while sending clientHello)\n");
		return 1;
	}
	string hostname = ShellCommand("hostname", true);
	if(!sock.SendPascalString(hostname))
	{
		LogWarning("Connection dropped (while sending clientHello.hostname)\n");
		return 1;
	}

	//Validate the connection
	if(chi.magic != shi.magic)
	{
		LogWarning("Connection dropped (bad magic number in serverHello)\n");
		return 1;
	}

	//Look for compilers
	LogVerbose("Enumerating compilers...\n");
	FindLinkers();
	FindCPPCompilers();
	FindFPGACompilers();

	//Get some basic metadata about our hardware and tell the server
	msgBuildInfo binfo;
	binfo.cpuCount = atoi(ShellCommand("cat /proc/cpuinfo  | grep processor | wc -l").c_str());
	binfo.cpuSpeed = atoi(ShellCommand("cat /proc/cpuinfo | grep bogo | head -n 1 | cut -d : -f 2").c_str());
	binfo.ramSize = atol(ShellCommand("cat /proc/meminfo  | grep MemTotal  | cut -d : -f 2").c_str()) / 1024;
	binfo.toolchainCount = g_toolchains.size();
	if(!sock.SendLooped((unsigned char*)&binfo, sizeof(binfo)))
	{
		LogWarning("Connection dropped (while sending buildInfo)\n");
		return 1;
	}

	//Report the toolchains we found to the server
	for(auto it : g_toolchains)
	{
		auto t = it.second;

		vector<string> langs;
		t->GetSupportedLanguages(langs);
		auto triplets = t->GetTargetTriplets();

		//DEBUG: Print it out
		//t->DebugPrint();

		//Send the toolchain header to the server
		msgAddCompiler tadd;
		tadd.compilerType = t->GetType();
		tadd.versionNum =	(t->GetMajorVersion() << 24) |
							(t->GetMinorVersion() << 16) |
							(t->GetPatchVersion() << 8);
		tadd.numLangs = langs.size();
		tadd.numTriplets = triplets.size();
		if(!sock.SendLooped((unsigned char*)&tadd, sizeof(tadd)))
		{
			LogWarning("Connection dropped (while sending addCompiler)\n");
			return 1;
		}

		//Send supplemental payload data
		if(!sock.SendPascalString(t->GetHash()))
		{
			LogWarning("Connection dropped (while sending addCompiler)\n");
			return 1;
		}
		if(!sock.SendPascalString(t->GetVersionString()))
		{
			LogWarning("Connection dropped (while sending addCompiler)\n");
			return 1;
		}
		vector<Toolchain::Language> dlangs = t->GetSupportedLanguages();
		for(auto x : dlangs)
		{
			uint8_t l = x;
			if(!sock.SendLooped((unsigned char*)&l, 1))
			{
				LogWarning("Connection dropped (while sending addCompiler)\n");
				return 1;
			}
		}
		for(auto x : triplets)
		{
			if(!sock.SendPascalString(x))
			{
				LogWarning("Connection dropped (while sending addCompiler)\n");
				return 1;
			}
		}
	}

	//TODO: Sit around and wait for stuff to come in

	//clean up
	for(auto x : g_toolchains)
		delete x.second;
	g_toolchains.clear();

	return 0;
}

void ShowVersion()
{
	printf(
		"SPLASH build server daemon by Andrew D. Zonenberg.\n"
		"\n"
		"License: 3-clause BSD\n"
		"This is free software: you are free to change and redistribute it.\n"
		"There is NO WARRANTY, to the extent permitted by law.\n");
}

void ShowUsage()
{
	printf("Usage: splashbuild ctlserver\n");
	exit(0);
}
<|endoftext|>


<commit_before>// Copyright 2016 Tom Barthel-Steer
// http://www.tomsteer.net
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Parts of this file from Electronic Theatre Controls Inc, License info below
//
// Copyright (c) 2015 Electronic Theatre Controls, http://www.etcconnect.com
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

#include "streamingacn.h"
#include "sacnlistener.h"

#include <QCoreApplication>
#include <QThread>
#include <QSharedPointer>
#include <QMessageBox>

sACNSource::sACNSource()
{
    src_valid = false;
    lastseq = 0;
    waited_for_dd = false;
    doing_dmx = false; //if true, we are processing dmx data from this source
    doing_per_channel = false;  //If true, we are tracking per-channel priority messages for this source
    isPreview = false;
    universe = 0;
    memset(level_array, -1, 512);
    memset(priority_array, -1, 512);
    priority = 0;
    fpsTimer.start();
    fpsCounter = 0;
    fps = 0;
    seqErr = 0;
    jumps = 0;
}

QString sACNSource::cid_string()
{
    char buffer[CID::CIDSTRINGBYTES];
    CID::CIDIntoString(this->src_cid, buffer);

    return QString(buffer);
}

sACNManager *sACNManager::m_instance = NULL;

sACNManager *sACNManager::getInstance()
{
    if(!m_instance)
        m_instance = new sACNManager();
    return m_instance;
}

sACNManager::sACNManager() : QObject()
{

}

static void strongPointerDelete(sACNListener *obj)
{
    obj->deleteLater();
    sACNManager::getInstance()->listenerDelete(obj);
}

QSharedPointer<sACNListener> sACNManager::getListener(int universe)
{
    QMutexLocker locker(&sACNManager_mutex);
    // Notes on the memory management of sACNListeners :
    // This function creates a QSharedPointer to the listener, which is handed to the classes that
    // want to use it. It stores a QWeakPointer, which gets set to null when all instances of the shared
    // pointer are gone

    QSharedPointer<sACNListener> strongPointer;
    if(!m_listenerHash.contains(universe))
    {
        qDebug() << "Creating Listener for universe " << universe;

        // Create thread and move listener to thread
        QThread *thread = new QThread;
        thread->setObjectName(QString("Universe %1 RX").arg(universe));

        sACNListener *listener = new sACNListener(universe);
        listener->moveToThread(thread);
        connect(thread, SIGNAL(started()), listener, SLOT(startReception()));
        connect(thread, SIGNAL(finished()), listener, SLOT(deleteLater()));
        connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
        thread->start(QThread::HighPriority);

        m_listenerThreads[universe] = thread;

        // Create strong pointer to return
        strongPointer = QSharedPointer<sACNListener>(listener, strongPointerDelete);
        m_listenerHash[universe] = strongPointer.toWeakRef();
        m_objToUniverse[listener] = universe;
    }
    else
    {
        strongPointer = m_listenerHash[universe].toStrongRef();
    }
    if(strongPointer.isNull())
    {
        QMessageBox msgBox;
        msgBox.setText("Unable to allocate listener object\r\n\r\nsACNView must close now");
        msgBox.exec();
        qApp->exit(-1);
    }
    return strongPointer;
}

void sACNManager::listenerDelete(QObject *obj)
{
    QMutexLocker locker(&sACNManager_mutex);
    int universe = m_objToUniverse[obj];

    qDebug() << "Destroying Listener for universe " << universe;

    m_listenerHash.remove(universe);

    m_objToUniverse.remove(obj);

    m_listenerThreads[universe]->exit();
    m_listenerThreads[universe]->wait();
    m_listenerThreads.remove(universe);
}
<commit_msg>Fix level array initializer<commit_after>// Copyright 2016 Tom Barthel-Steer
// http://www.tomsteer.net
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Parts of this file from Electronic Theatre Controls Inc, License info below
//
// Copyright (c) 2015 Electronic Theatre Controls, http://www.etcconnect.com
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

#include "streamingacn.h"
#include "sacnlistener.h"

#include <QCoreApplication>
#include <QThread>
#include <QSharedPointer>
#include <QMessageBox>

sACNSource::sACNSource()
{
    src_valid = false;
    lastseq = 0;
    waited_for_dd = false;
    doing_dmx = false; //if true, we are processing dmx data from this source
    doing_per_channel = false;  //If true, we are tracking per-channel priority messages for this source
    isPreview = false;
    universe = 0;
    std::fill(level_array, level_array + sizeof(level_array), 0);
    std::fill(priority_array, priority_array + sizeof(priority_array), 0);
    priority = 0;
    fpsTimer.start();
    fpsCounter = 0;
    fps = 0;
    seqErr = 0;
    jumps = 0;
}

QString sACNSource::cid_string()
{
    char buffer[CID::CIDSTRINGBYTES];
    CID::CIDIntoString(this->src_cid, buffer);

    return QString(buffer);
}

sACNManager *sACNManager::m_instance = NULL;

sACNManager *sACNManager::getInstance()
{
    if(!m_instance)
        m_instance = new sACNManager();
    return m_instance;
}

sACNManager::sACNManager() : QObject()
{

}

static void strongPointerDelete(sACNListener *obj)
{
    obj->deleteLater();
    sACNManager::getInstance()->listenerDelete(obj);
}

QSharedPointer<sACNListener> sACNManager::getListener(int universe)
{
    QMutexLocker locker(&sACNManager_mutex);
    // Notes on the memory management of sACNListeners :
    // This function creates a QSharedPointer to the listener, which is handed to the classes that
    // want to use it. It stores a QWeakPointer, which gets set to null when all instances of the shared
    // pointer are gone

    QSharedPointer<sACNListener> strongPointer;
    if(!m_listenerHash.contains(universe))
    {
        qDebug() << "Creating Listener for universe " << universe;

        // Create thread and move listener to thread
        QThread *thread = new QThread;
        thread->setObjectName(QString("Universe %1 RX").arg(universe));

        sACNListener *listener = new sACNListener(universe);
        listener->moveToThread(thread);
        connect(thread, SIGNAL(started()), listener, SLOT(startReception()));
        connect(thread, SIGNAL(finished()), listener, SLOT(deleteLater()));
        connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
        thread->start(QThread::HighPriority);

        m_listenerThreads[universe] = thread;

        // Create strong pointer to return
        strongPointer = QSharedPointer<sACNListener>(listener, strongPointerDelete);
        m_listenerHash[universe] = strongPointer.toWeakRef();
        m_objToUniverse[listener] = universe;
    }
    else
    {
        strongPointer = m_listenerHash[universe].toStrongRef();
    }
    if(strongPointer.isNull())
    {
        QMessageBox msgBox;
        msgBox.setText("Unable to allocate listener object\r\n\r\nsACNView must close now");
        msgBox.exec();
        qApp->exit(-1);
    }
    return strongPointer;
}

void sACNManager::listenerDelete(QObject *obj)
{
    QMutexLocker locker(&sACNManager_mutex);
    int universe = m_objToUniverse[obj];

    qDebug() << "Destroying Listener for universe " << universe;

    m_listenerHash.remove(universe);

    m_objToUniverse.remove(obj);

    m_listenerThreads[universe]->exit();
    m_listenerThreads[universe]->wait();
    m_listenerThreads.remove(universe);
}
<|endoftext|>