<commit_before>#include "selfdrive/ui/replay/route.h"

#include <QDir>
#include <QEventLoop>
#include <QJsonArray>
#include <QJsonDocument>
#include <QRegExp>
#include <QtConcurrent>

#include "selfdrive/hardware/hw.h"
#include "selfdrive/ui/qt/api.h"
#include "selfdrive/ui/replay/replay.h"
#include "selfdrive/ui/replay/util.h"

Route::Route(const QString &route, const QString &data_dir) : data_dir_(data_dir) {
  route_ = parseRoute(route);
}

RouteIdentifier Route::parseRoute(const QString &str) {
  QRegExp rx(R"(^([a-z0-9]{16})([|_/])(\d{4}-\d{2}-\d{2}--\d{2}-\d{2}-\d{2})(?:(--|/)(\d*))?$)");
  if (rx.indexIn(str) == -1) return {};

  const QStringList list = rx.capturedTexts();
  return {list[1], list[3], list[5].toInt(), list[1] + "|" + list[3]};
}

bool Route::load() {
  if (route_.str.isEmpty()) {
    qInfo() << "invalid route format";
    return false;
  }
  return data_dir_.isEmpty() ? loadFromServer() : loadFromLocal();
}

bool Route::loadFromServer() {
  QEventLoop loop;
  HttpRequest http(nullptr, !Hardware::PC());
  QObject::connect(&http, &HttpRequest::requestDone, [&](const QString &json, bool success) {
    loop.exit(success ? loadFromJson(json) : 0);
  });
  http.sendRequest("https://api.commadotai.com/v1/route/" + route_.str + "/files");
  return loop.exec();
}

bool Route::loadFromJson(const QString &json) {
  QRegExp rx(R"(\/(\d+)\/)");
  for (const auto &value : QJsonDocument::fromJson(json.trimmed().toUtf8()).object()) {
    for (const auto &url : value.toArray()) {
      QString url_str = url.toString();
      if (rx.indexIn(url_str) != -1) {
        addFileToSegment(rx.cap(1).toInt(), url_str);
      }
    }
  }
  return !segments_.empty();
}

bool Route::loadFromLocal() {
  QDir log_dir(data_dir_);
  for (const auto &folder : log_dir.entryList(QDir::Dirs | QDir::NoDot | QDir::NoDotDot, QDir::NoSort)) {
    int pos = folder.lastIndexOf("--");
    if (pos != -1 && folder.left(pos) == route_.timestamp) {
      const int seg_num = folder.mid(pos + 2).toInt();
      QDir segment_dir(log_dir.filePath(folder));
      for (const auto &f : segment_dir.entryList(QDir::Files)) {
        addFileToSegment(seg_num, segment_dir.absoluteFilePath(f));
      }
    }
  }
  return !segments_.empty();
}

void Route::addFileToSegment(int n, const QString &file) {
  const QString name = QUrl(file).fileName();
  if (name == "rlog.bz2") {
    segments_[n].rlog = file;
  } else if (name == "qlog.bz2") {
    segments_[n].qlog = file;
  } else if (name == "fcamera.hevc") {
    segments_[n].road_cam = file;
  } else if (name == "dcamera.hevc") {
    segments_[n].driver_cam = file;
  } else if (name == "ecamera.hevc") {
    segments_[n].wide_road_cam = file;
  } else if (name == "qcamera.ts") {
    segments_[n].qcamera = file;
  }
}

// class Segment

Segment::Segment(int n, const SegmentFile &files, uint32_t flags) : seg_num(n), flags(flags) {
  // [RoadCam, DriverCam, WideRoadCam, log]. fallback to qcamera/qlog
  const QString file_list[] = {
      (flags & REPLAY_FLAG_QCAMERA) || files.road_cam.isEmpty() ? files.qcamera : files.road_cam,
      flags & REPLAY_FLAG_DCAM ? files.driver_cam : "",
      flags & REPLAY_FLAG_ECAM ? files.wide_road_cam : "",
      files.rlog.isEmpty() ? files.qlog : files.rlog,
  };
  for (int i = 0; i < std::size(file_list); i++) {
    if (!file_list[i].isEmpty()) {
      loading_++;
      synchronizer_.addFuture(QtConcurrent::run([=] { loadFile(i, file_list[i].toStdString()); }));
    }
  }
}

Segment::~Segment() {
  disconnect();
  abort_ = true;
  synchronizer_.setCancelOnWait(true);
  synchronizer_.waitForFinished();
}

void Segment::loadFile(int id, const std::string file) {
  const bool local_cache = !(flags & REPLAY_FLAG_NO_FILE_CACHE);
  bool success = false;
  if (id < MAX_CAMERAS) {
    frames[id] = std::make_unique<FrameReader>();
    success = frames[id]->load(file, flags & REPLAY_FLAG_NO_CUDA, &abort_, local_cache, 20 * 1024 * 1024, 3);
  } else {
    log = std::make_unique<LogReader>();
    success = log->load(file, &abort_, local_cache, 0, 3);
  }

  if (!success) {
    // abort all loading jobs.
    abort_ = true;
  }

  if (--loading_ == 0) {
    emit loadFinished(!abort_);
  }
}
<commit_msg>replay/segment: pass member function pointer to QtConcurrent::run (#23312)<commit_after>#include "selfdrive/ui/replay/route.h"

#include <QDir>
#include <QEventLoop>
#include <QJsonArray>
#include <QJsonDocument>
#include <QRegExp>
#include <QtConcurrent>

#include "selfdrive/hardware/hw.h"
#include "selfdrive/ui/qt/api.h"
#include "selfdrive/ui/replay/replay.h"
#include "selfdrive/ui/replay/util.h"

Route::Route(const QString &route, const QString &data_dir) : data_dir_(data_dir) {
  route_ = parseRoute(route);
}

RouteIdentifier Route::parseRoute(const QString &str) {
  QRegExp rx(R"(^([a-z0-9]{16})([|_/])(\d{4}-\d{2}-\d{2}--\d{2}-\d{2}-\d{2})(?:(--|/)(\d*))?$)");
  if (rx.indexIn(str) == -1) return {};

  const QStringList list = rx.capturedTexts();
  return {list[1], list[3], list[5].toInt(), list[1] + "|" + list[3]};
}

bool Route::load() {
  if (route_.str.isEmpty()) {
    qInfo() << "invalid route format";
    return false;
  }
  return data_dir_.isEmpty() ? loadFromServer() : loadFromLocal();
}

bool Route::loadFromServer() {
  QEventLoop loop;
  HttpRequest http(nullptr, !Hardware::PC());
  QObject::connect(&http, &HttpRequest::requestDone, [&](const QString &json, bool success) {
    loop.exit(success ? loadFromJson(json) : 0);
  });
  http.sendRequest("https://api.commadotai.com/v1/route/" + route_.str + "/files");
  return loop.exec();
}

bool Route::loadFromJson(const QString &json) {
  QRegExp rx(R"(\/(\d+)\/)");
  for (const auto &value : QJsonDocument::fromJson(json.trimmed().toUtf8()).object()) {
    for (const auto &url : value.toArray()) {
      QString url_str = url.toString();
      if (rx.indexIn(url_str) != -1) {
        addFileToSegment(rx.cap(1).toInt(), url_str);
      }
    }
  }
  return !segments_.empty();
}

bool Route::loadFromLocal() {
  QDir log_dir(data_dir_);
  for (const auto &folder : log_dir.entryList(QDir::Dirs | QDir::NoDot | QDir::NoDotDot, QDir::NoSort)) {
    int pos = folder.lastIndexOf("--");
    if (pos != -1 && folder.left(pos) == route_.timestamp) {
      const int seg_num = folder.mid(pos + 2).toInt();
      QDir segment_dir(log_dir.filePath(folder));
      for (const auto &f : segment_dir.entryList(QDir::Files)) {
        addFileToSegment(seg_num, segment_dir.absoluteFilePath(f));
      }
    }
  }
  return !segments_.empty();
}

void Route::addFileToSegment(int n, const QString &file) {
  const QString name = QUrl(file).fileName();
  if (name == "rlog.bz2") {
    segments_[n].rlog = file;
  } else if (name == "qlog.bz2") {
    segments_[n].qlog = file;
  } else if (name == "fcamera.hevc") {
    segments_[n].road_cam = file;
  } else if (name == "dcamera.hevc") {
    segments_[n].driver_cam = file;
  } else if (name == "ecamera.hevc") {
    segments_[n].wide_road_cam = file;
  } else if (name == "qcamera.ts") {
    segments_[n].qcamera = file;
  }
}

// class Segment

Segment::Segment(int n, const SegmentFile &files, uint32_t flags) : seg_num(n), flags(flags) {
  // [RoadCam, DriverCam, WideRoadCam, log]. fallback to qcamera/qlog
  const std::array file_list = {
      (flags & REPLAY_FLAG_QCAMERA) || files.road_cam.isEmpty() ? files.qcamera : files.road_cam,
      flags & REPLAY_FLAG_DCAM ? files.driver_cam : "",
      flags & REPLAY_FLAG_ECAM ? files.wide_road_cam : "",
      files.rlog.isEmpty() ? files.qlog : files.rlog,
  };
  for (int i = 0; i < file_list.size(); ++i) {
    if (!file_list[i].isEmpty()) {
      ++loading_;
      synchronizer_.addFuture(QtConcurrent::run(this, &Segment::loadFile, i, file_list[i].toStdString()));
    }
  }
}

Segment::~Segment() {
  disconnect();
  abort_ = true;
  synchronizer_.setCancelOnWait(true);
  synchronizer_.waitForFinished();
}

void Segment::loadFile(int id, const std::string file) {
  const bool local_cache = !(flags & REPLAY_FLAG_NO_FILE_CACHE);
  bool success = false;
  if (id < MAX_CAMERAS) {
    frames[id] = std::make_unique<FrameReader>();
    success = frames[id]->load(file, flags & REPLAY_FLAG_NO_CUDA, &abort_, local_cache, 20 * 1024 * 1024, 3);
  } else {
    log = std::make_unique<LogReader>();
    success = log->load(file, &abort_, local_cache, 0, 3);
  }

  if (!success) {
    // abort all loading jobs.
    abort_ = true;
  }

  if (--loading_ == 0) {
    emit loadFinished(!abort_);
  }
}
<|endoftext|>


<commit_before>//===-- ARMSubtarget.cpp - ARM Subtarget Information ------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the ARM specific subclass of TargetSubtarget.
//
//===----------------------------------------------------------------------===//

#include "ARMSubtarget.h"
#include "ARMGenSubtarget.inc"
#include "ARMBaseRegisterInfo.h"
#include "llvm/GlobalValue.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/ADT/SmallVector.h"
using namespace llvm;

static cl::opt<bool>
ReserveR9("arm-reserve-r9", cl::Hidden,
          cl::desc("Reserve R9, making it unavailable as GPR"));

static cl::opt<bool>
DarwinUseMOVT("arm-darwin-use-movt", cl::init(true), cl::Hidden);

static cl::opt<bool>
StrictAlign("arm-strict-align", cl::Hidden,
            cl::desc("Disallow all unaligned memory accesses"));

ARMSubtarget::ARMSubtarget(const std::string &TT, const std::string &CPU,
                           const std::string &FS, bool isT)
  : ARMArchVersion(V4)
  , ARMProcFamily(Others)
  , ARMFPUType(None)
  , UseNEONForSinglePrecisionFP(false)
  , SlowFPVMLx(false)
  , HasVMLxForwarding(false)
  , SlowFPBrcc(false)
  , IsThumb(isT)
  , ThumbMode(Thumb1)
  , NoARM(false)
  , PostRAScheduler(false)
  , IsR9Reserved(ReserveR9)
  , UseMovt(false)
  , HasFP16(false)
  , HasD16(false)
  , HasHardwareDivide(false)
  , HasT2ExtractPack(false)
  , HasDataBarrier(false)
  , Pref32BitThumb(false)
  , AvoidCPSRPartialUpdate(false)
  , HasMPExtension(false)
  , FPOnlySP(false)
  , AllowsUnalignedMem(false)
  , stackAlignment(4)
  , CPUString(CPU)
  , TargetTriple(TT)
  , TargetABI(ARM_ABI_APCS) {
  // Determine default and user specified characteristics

  // When no arch is specified either by CPU or by attributes, make the default
  // ARMv4T.
  const char *ARMArchFeature = "";
  if (CPUString.empty())
    CPUString = "generic";
  if (CPUString == "generic" && (FS.empty() || FS == "generic")) {
    ARMArchVersion = V4T;
    ARMArchFeature = "+v4t";
  }

  // Set the boolean corresponding to the current target triple, or the default
  // if one cannot be determined, to true.
  unsigned Len = TT.length();
  unsigned Idx = 0;

  if (Len >= 5 && TT.substr(0, 4) == "armv")
    Idx = 4;
  else if (Len >= 6 && TT.substr(0, 5) == "thumb") {
    IsThumb = true;
    if (Len >= 7 && TT[5] == 'v')
      Idx = 6;
  }
  if (Idx) {
    unsigned SubVer = TT[Idx];
    if (SubVer >= '7' && SubVer <= '9') {
      ARMArchVersion = V7A;
      ARMArchFeature = "+v7a";
      if (Len >= Idx+2 && TT[Idx+1] == 'm') {
        ARMArchVersion = V7M;
        ARMArchFeature = "+v7m";
      }
    } else if (SubVer == '6') {
      ARMArchVersion = V6;
      ARMArchFeature = "+v6";
      if (Len >= Idx+3 && TT[Idx+1] == 't' && TT[Idx+2] == '2') {
        ARMArchVersion = V6T2;
        ARMArchFeature = "+v6t2";
      }
    } else if (SubVer == '5') {
      ARMArchVersion = V5T;
      ARMArchFeature = "+v5t";
      if (Len >= Idx+3 && TT[Idx+1] == 't' && TT[Idx+2] == 'e') {
        ARMArchVersion = V5TE;
        ARMArchFeature = "+v5te";
      }
    } else if (SubVer == '4') {
      if (Len >= Idx+2 && TT[Idx+1] == 't') {
        ARMArchVersion = V4T;
        ARMArchFeature = "+v4t";
      } else {
        ARMArchVersion = V4;
        ARMArchFeature = "";
      }
    }
  }

  if (TT.find("eabi") != std::string::npos)
    TargetABI = ARM_ABI_AAPCS;

  // Parse features string.  If the first entry in FS (the CPU) is missing,
  // insert the architecture feature derived from the target triple.  This is
  // important for setting features that are implied based on the architecture
  // version.
  std::string FSWithArch;
  if (FS.empty())
    FSWithArch = std::string(ARMArchFeature);
  else if (FS.find(',') == 0)
    FSWithArch = std::string(ARMArchFeature) + FS;
  else
    FSWithArch = FS;
  ParseSubtargetFeatures(FSWithArch, CPUString);

  // After parsing Itineraries, set ItinData.IssueWidth.
  computeIssueWidth();

  // Thumb2 implies at least V6T2.
  if (ARMArchVersion >= V6T2)
    ThumbMode = Thumb2;
  else if (ThumbMode >= Thumb2)
    ARMArchVersion = V6T2;

  if (isAAPCS_ABI())
    stackAlignment = 8;

  if (!isTargetDarwin())
    UseMovt = hasV6T2Ops();
  else {
    IsR9Reserved = ReserveR9 | (ARMArchVersion < V6);
    UseMovt = DarwinUseMOVT && hasV6T2Ops();
  }

  if (!isThumb() || hasThumb2())
    PostRAScheduler = true;

  // v6+ may or may not support unaligned mem access depending on the system
  // configuration.
  if (!StrictAlign && hasV6Ops() && isTargetDarwin())
    AllowsUnalignedMem = true;
}

/// GVIsIndirectSymbol - true if the GV will be accessed via an indirect symbol.
bool
ARMSubtarget::GVIsIndirectSymbol(const GlobalValue *GV,
                                 Reloc::Model RelocM) const {
  if (RelocM == Reloc::Static)
    return false;

  // Materializable GVs (in JIT lazy compilation mode) do not require an extra
  // load from stub.
  bool isDecl = GV->hasAvailableExternallyLinkage();
  if (GV->isDeclaration() && !GV->isMaterializable())
    isDecl = true;

  if (!isTargetDarwin()) {
    // Extra load is needed for all externally visible.
    if (GV->hasLocalLinkage() || GV->hasHiddenVisibility())
      return false;
    return true;
  } else {
    if (RelocM == Reloc::PIC_) {
      // If this is a strong reference to a definition, it is definitely not
      // through a stub.
      if (!isDecl && !GV->isWeakForLinker())
        return false;

      // Unless we have a symbol with hidden visibility, we have to go through a
      // normal $non_lazy_ptr stub because this symbol might be resolved late.
      if (!GV->hasHiddenVisibility())  // Non-hidden $non_lazy_ptr reference.
        return true;

      // If symbol visibility is hidden, we have a stub for common symbol
      // references and external declarations.
      if (isDecl || GV->hasCommonLinkage())
        // Hidden $non_lazy_ptr reference.
        return true;

      return false;
    } else {
      // If this is a strong reference to a definition, it is definitely not
      // through a stub.
      if (!isDecl && !GV->isWeakForLinker())
        return false;

      // Unless we have a symbol with hidden visibility, we have to go through a
      // normal $non_lazy_ptr stub because this symbol might be resolved late.
      if (!GV->hasHiddenVisibility())  // Non-hidden $non_lazy_ptr reference.
        return true;
    }
  }

  return false;
}

unsigned ARMSubtarget::getMispredictionPenalty() const {
  // If we have a reasonable estimate of the pipeline depth, then we can
  // estimate the penalty of a misprediction based on that.
  if (isCortexA8())
    return 13;
  else if (isCortexA9())
    return 8;

  // Otherwise, just return a sensible default.
  return 10;
}

void ARMSubtarget::computeIssueWidth() {
  unsigned allStage1Units = 0;
  for (const InstrItinerary *itin = InstrItins.Itineraries;
       itin->FirstStage != ~0U; ++itin) {
    const InstrStage *IS = InstrItins.Stages + itin->FirstStage;
    allStage1Units |= IS->getUnits();
  }
  InstrItins.IssueWidth = 0;
  while (allStage1Units) {
    ++InstrItins.IssueWidth;
    // clear the lowest bit
    allStage1Units ^= allStage1Units & ~(allStage1Units - 1);
  }
  assert(InstrItins.IssueWidth <= 2 && "itinerary bug, too many stage 1 units");
}

bool ARMSubtarget::enablePostRAScheduler(
           CodeGenOpt::Level OptLevel,
           TargetSubtarget::AntiDepBreakMode& Mode,
           RegClassVector& CriticalPathRCs) const {
  Mode = TargetSubtarget::ANTIDEP_CRITICAL;
  CriticalPathRCs.clear();
  CriticalPathRCs.push_back(&ARM::GPRRegClass);
  return PostRAScheduler && OptLevel >= CodeGenOpt::Default;
}
<commit_msg>Fix ARMSubtarget feature parsing.<commit_after>//===-- ARMSubtarget.cpp - ARM Subtarget Information ------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the ARM specific subclass of TargetSubtarget.
//
//===----------------------------------------------------------------------===//

#include "ARMSubtarget.h"
#include "ARMGenSubtarget.inc"
#include "ARMBaseRegisterInfo.h"
#include "llvm/GlobalValue.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/ADT/SmallVector.h"
using namespace llvm;

static cl::opt<bool>
ReserveR9("arm-reserve-r9", cl::Hidden,
          cl::desc("Reserve R9, making it unavailable as GPR"));

static cl::opt<bool>
DarwinUseMOVT("arm-darwin-use-movt", cl::init(true), cl::Hidden);

static cl::opt<bool>
StrictAlign("arm-strict-align", cl::Hidden,
            cl::desc("Disallow all unaligned memory accesses"));

ARMSubtarget::ARMSubtarget(const std::string &TT, const std::string &CPU,
                           const std::string &FS, bool isT)
  : ARMArchVersion(V4)
  , ARMProcFamily(Others)
  , ARMFPUType(None)
  , UseNEONForSinglePrecisionFP(false)
  , SlowFPVMLx(false)
  , HasVMLxForwarding(false)
  , SlowFPBrcc(false)
  , IsThumb(isT)
  , ThumbMode(Thumb1)
  , NoARM(false)
  , PostRAScheduler(false)
  , IsR9Reserved(ReserveR9)
  , UseMovt(false)
  , HasFP16(false)
  , HasD16(false)
  , HasHardwareDivide(false)
  , HasT2ExtractPack(false)
  , HasDataBarrier(false)
  , Pref32BitThumb(false)
  , AvoidCPSRPartialUpdate(false)
  , HasMPExtension(false)
  , FPOnlySP(false)
  , AllowsUnalignedMem(false)
  , stackAlignment(4)
  , CPUString(CPU)
  , TargetTriple(TT)
  , TargetABI(ARM_ABI_APCS) {
  // Determine default and user specified characteristics

  // When no arch is specified either by CPU or by attributes, make the default
  // ARMv4T.
  const char *ARMArchFeature = "";
  if (CPUString.empty())
    CPUString = "generic";
  if (CPUString == "generic" && (FS.empty() || FS == "generic")) {
    ARMArchVersion = V4T;
    ARMArchFeature = "+v4t";
  }

  // Set the boolean corresponding to the current target triple, or the default
  // if one cannot be determined, to true.
  unsigned Len = TT.length();
  unsigned Idx = 0;

  if (Len >= 5 && TT.substr(0, 4) == "armv")
    Idx = 4;
  else if (Len >= 6 && TT.substr(0, 5) == "thumb") {
    IsThumb = true;
    if (Len >= 7 && TT[5] == 'v')
      Idx = 6;
  }
  if (Idx) {
    unsigned SubVer = TT[Idx];
    if (SubVer >= '7' && SubVer <= '9') {
      ARMArchVersion = V7A;
      ARMArchFeature = "+v7a";
      if (Len >= Idx+2 && TT[Idx+1] == 'm') {
        ARMArchVersion = V7M;
        ARMArchFeature = "+v7m";
      }
    } else if (SubVer == '6') {
      ARMArchVersion = V6;
      ARMArchFeature = "+v6";
      if (Len >= Idx+3 && TT[Idx+1] == 't' && TT[Idx+2] == '2') {
        ARMArchVersion = V6T2;
        ARMArchFeature = "+v6t2";
      }
    } else if (SubVer == '5') {
      ARMArchVersion = V5T;
      ARMArchFeature = "+v5t";
      if (Len >= Idx+3 && TT[Idx+1] == 't' && TT[Idx+2] == 'e') {
        ARMArchVersion = V5TE;
        ARMArchFeature = "+v5te";
      }
    } else if (SubVer == '4') {
      if (Len >= Idx+2 && TT[Idx+1] == 't') {
        ARMArchVersion = V4T;
        ARMArchFeature = "+v4t";
      } else {
        ARMArchVersion = V4;
        ARMArchFeature = "";
      }
    }
  }

  if (TT.find("eabi") != std::string::npos)
    TargetABI = ARM_ABI_AAPCS;

  // Insert the architecture feature derived from the target triple into the
  // feature string. This is important for setting features that are implied
  // based on the architecture version.
  std::string FSWithArch = std::string(ARMArchFeature);
  if (FSWithArch.empty())
    FSWithArch = FS;
  else if (!FS.empty())
    FSWithArch = FSWithArch + "," + FS;
  ParseSubtargetFeatures(FSWithArch, CPUString);

  // After parsing Itineraries, set ItinData.IssueWidth.
  computeIssueWidth();

  // Thumb2 implies at least V6T2.
  if (ARMArchVersion >= V6T2)
    ThumbMode = Thumb2;
  else if (ThumbMode >= Thumb2)
    ARMArchVersion = V6T2;

  if (isAAPCS_ABI())
    stackAlignment = 8;

  if (!isTargetDarwin())
    UseMovt = hasV6T2Ops();
  else {
    IsR9Reserved = ReserveR9 | (ARMArchVersion < V6);
    UseMovt = DarwinUseMOVT && hasV6T2Ops();
  }

  if (!isThumb() || hasThumb2())
    PostRAScheduler = true;

  // v6+ may or may not support unaligned mem access depending on the system
  // configuration.
  if (!StrictAlign && hasV6Ops() && isTargetDarwin())
    AllowsUnalignedMem = true;
}

/// GVIsIndirectSymbol - true if the GV will be accessed via an indirect symbol.
bool
ARMSubtarget::GVIsIndirectSymbol(const GlobalValue *GV,
                                 Reloc::Model RelocM) const {
  if (RelocM == Reloc::Static)
    return false;

  // Materializable GVs (in JIT lazy compilation mode) do not require an extra
  // load from stub.
  bool isDecl = GV->hasAvailableExternallyLinkage();
  if (GV->isDeclaration() && !GV->isMaterializable())
    isDecl = true;

  if (!isTargetDarwin()) {
    // Extra load is needed for all externally visible.
    if (GV->hasLocalLinkage() || GV->hasHiddenVisibility())
      return false;
    return true;
  } else {
    if (RelocM == Reloc::PIC_) {
      // If this is a strong reference to a definition, it is definitely not
      // through a stub.
      if (!isDecl && !GV->isWeakForLinker())
        return false;

      // Unless we have a symbol with hidden visibility, we have to go through a
      // normal $non_lazy_ptr stub because this symbol might be resolved late.
      if (!GV->hasHiddenVisibility())  // Non-hidden $non_lazy_ptr reference.
        return true;

      // If symbol visibility is hidden, we have a stub for common symbol
      // references and external declarations.
      if (isDecl || GV->hasCommonLinkage())
        // Hidden $non_lazy_ptr reference.
        return true;

      return false;
    } else {
      // If this is a strong reference to a definition, it is definitely not
      // through a stub.
      if (!isDecl && !GV->isWeakForLinker())
        return false;

      // Unless we have a symbol with hidden visibility, we have to go through a
      // normal $non_lazy_ptr stub because this symbol might be resolved late.
      if (!GV->hasHiddenVisibility())  // Non-hidden $non_lazy_ptr reference.
        return true;
    }
  }

  return false;
}

unsigned ARMSubtarget::getMispredictionPenalty() const {
  // If we have a reasonable estimate of the pipeline depth, then we can
  // estimate the penalty of a misprediction based on that.
  if (isCortexA8())
    return 13;
  else if (isCortexA9())
    return 8;

  // Otherwise, just return a sensible default.
  return 10;
}

void ARMSubtarget::computeIssueWidth() {
  unsigned allStage1Units = 0;
  for (const InstrItinerary *itin = InstrItins.Itineraries;
       itin->FirstStage != ~0U; ++itin) {
    const InstrStage *IS = InstrItins.Stages + itin->FirstStage;
    allStage1Units |= IS->getUnits();
  }
  InstrItins.IssueWidth = 0;
  while (allStage1Units) {
    ++InstrItins.IssueWidth;
    // clear the lowest bit
    allStage1Units ^= allStage1Units & ~(allStage1Units - 1);
  }
  assert(InstrItins.IssueWidth <= 2 && "itinerary bug, too many stage 1 units");
}

bool ARMSubtarget::enablePostRAScheduler(
           CodeGenOpt::Level OptLevel,
           TargetSubtarget::AntiDepBreakMode& Mode,
           RegClassVector& CriticalPathRCs) const {
  Mode = TargetSubtarget::ANTIDEP_CRITICAL;
  CriticalPathRCs.clear();
  CriticalPathRCs.push_back(&ARM::GPRRegClass);
  return PostRAScheduler && OptLevel >= CodeGenOpt::Default;
}
<|endoftext|>


<commit_before>#pragma once

#include "motion/TrapezoidalMotion.hpp"
#include "MotionConstraints.hpp"
#include "MotionInstant.hpp"
#include <Configuration.hpp>
#include <Geometry2d/CompositeShape.hpp>
#include <Geometry2d/Point.hpp>
#include <Geometry2d/Segment.hpp>
#include <Geometry2d/Segment.hpp>
#include <planning/Path.hpp>

namespace Planning
{
	/**
	 * @brief Represents a straight-line path with a trapezoidal velocity profile
	 *
	 * @details The path represents a function of position given time that the robot should follow.
	 * The path is made up of other Paths and can be made up of CompositePaths.
	 */
	class TrapezoidalPath: public Path
	{

	private:
		const Geometry2d::Point startPos, endPos;
		const Geometry2d::Point pathDirection;
		const float startSpeed, endSpeed;

		const float pathLength;
		const float maxAcc;
		const float maxSpeed;

	public:
		TrapezoidalPath(Geometry2d::Point startPos, float startSpeed, Geometry2d::Point endPos, float endSpeed, float maxAcc, float maxSpeed) :
				startPos(startPos), startSpeed(startSpeed), endPos(endPos), endSpeed(endSpeed),
				pathLength((startPos - endPos).mag()), maxAcc(maxAcc), maxSpeed(maxSpeed),
				pathDirection((endPos - startPos).normalized()){
				}

		/** default path is empty */
		TrapezoidalPath(Geometry2d::Point startPos, float startSpeed, Geometry2d::Point endPos, float endSpeed, const MotionConstraints& constraints) :
				startPos(startPos), startSpeed(startSpeed), endPos(endPos), endSpeed(endSpeed),
				pathLength((startPos - endPos).mag()), maxAcc(constraints.maxAcceleration), maxSpeed(constraints.maxSpeed),
				pathDirection((endPos - startPos).normalized()){
					float minSpeed = maxSpeed;
					if (startSpeed<minSpeed) {
						startSpeed = minSpeed;
					}
				}

		virtual bool evaluate(float time, MotionInstant &targetMotionInstant) const override {
			float distance;
			float speedOut;
			bool valid = TrapezoidalMotion(
					pathLength, 	//PathLength
					maxSpeed,		//maxSpeed
					maxAcc,		//maxAcc
					time,	//time
					startSpeed,	//startSpeed
					endSpeed,	//endSpeed
					distance,		//posOut
					speedOut);	//speedOut
			targetMotionInstant.pos = pathDirection * distance + startPos;
			targetMotionInstant.vel = pathDirection * speedOut;
			return valid;
		}

		virtual bool hit(const Geometry2d::CompositeShape &shape, float &hitTime, float startTime = 0) const override {
			throw std::logic_error("This function is not implemented");
		}

		virtual void draw(SystemState * const state, const QColor &color = Qt::black, const QString &layer = "Motion") const override {
			Packet::DebugPath *dbg = state->logFrame->add_debug_paths();
			dbg->set_layer(state->findDebugLayer(layer));
			*dbg->add_points() = startPos;
			*dbg->add_points() = endPos;
		}

		virtual float getDuration() const override {
			static float duration = Trapezoidal::getTime(
					pathLength, //distance
					pathLength, //pathLength
					maxSpeed,
					maxAcc,
					startSpeed,
					endSpeed);

			return duration;
		}

		virtual std::unique_ptr<Path> subPath(float startTime = 0, float endTime = std::numeric_limits<float>::infinity()) const override {
			debugThrow("This function is not implemented");
			return nullptr;
		}

		virtual boost::optional<MotionInstant> destination() const override {
			static MotionInstant destination = MotionInstant(endPos, pathDirection*endSpeed);
			return destination;
		}
		virtual std::unique_ptr<Path> clone() const override {
			return std::unique_ptr<Path>(new TrapezoidalPath(startPos,startSpeed,endPos, endSpeed, maxAcc, maxSpeed));
		}
	};
}
<commit_msg>Fix TrapezoidalPath memoization<commit_after>#pragma once

#include "motion/TrapezoidalMotion.hpp"
#include "MotionConstraints.hpp"
#include "MotionInstant.hpp"
#include <Configuration.hpp>
#include <Geometry2d/CompositeShape.hpp>
#include <Geometry2d/Point.hpp>
#include <Geometry2d/Segment.hpp>
#include <Geometry2d/Segment.hpp>
#include <planning/Path.hpp>

namespace Planning
{
	/**
	 * @brief Represents a straight-line path with a trapezoidal velocity profile
	 *
	 * @details The path represents a function of position given time that the robot should follow.
	 * The path is made up of other Paths and can be made up of CompositePaths.
	 */
	class TrapezoidalPath: public Path
	{

	private:
		const Geometry2d::Point startPos, endPos;
		const Geometry2d::Point pathDirection;
		const float startSpeed, endSpeed;

		const float pathLength;
		const float maxAcc;
		const float maxSpeed;

		float duration;

	public:
		TrapezoidalPath(Geometry2d::Point startPos, float startSpeed, Geometry2d::Point endPos, float endSpeed, const MotionConstraints& constraints) :
				startPos(startPos), startSpeed(startSpeed), endPos(endPos), endSpeed(endSpeed),
				pathLength((startPos - endPos).mag()), maxAcc(constraints.maxAcceleration), maxSpeed(constraints.maxSpeed),
				pathDirection((endPos - startPos).normalized())	{

			float minSpeed = maxSpeed;
			if (startSpeed<minSpeed) {
				startSpeed = minSpeed;
			}

			//Precalculate the duration of the path
			duration = Trapezoidal::getTime(
						pathLength, //distance
						pathLength, //pathLength
						maxSpeed,
						maxAcc,
						startSpeed,
						endSpeed);
		}

		virtual bool evaluate(float time, MotionInstant &targetMotionInstant) const override {
			float distance;
			float speedOut;
			bool valid = TrapezoidalMotion(
					pathLength, 	//PathLength
					maxSpeed,		//maxSpeed
					maxAcc,		//maxAcc
					time,	//time
					startSpeed,	//startSpeed
					endSpeed,	//endSpeed
					distance,		//posOut
					speedOut);	//speedOut
			targetMotionInstant.pos = pathDirection * distance + startPos;
			targetMotionInstant.vel = pathDirection * speedOut;
			return valid;
		}

		virtual bool hit(const Geometry2d::CompositeShape &shape, float &hitTime, float startTime = 0) const override {
			throw std::logic_error("This function is not implemented");
		}

		virtual void draw(SystemState * const state, const QColor &color = Qt::black, const QString &layer = "Motion") const override {
			Packet::DebugPath *dbg = state->logFrame->add_debug_paths();
			dbg->set_layer(state->findDebugLayer(layer));
			*dbg->add_points() = startPos;
			*dbg->add_points() = endPos;
		}

		virtual float getDuration() const override {
			return duration;
		}

		virtual std::unique_ptr<Path> subPath(float startTime = 0, float endTime = std::numeric_limits<float>::infinity()) const override {
			debugThrow("This function is not implemented");
			return nullptr;
		}

		virtual boost::optional<MotionInstant> destination() const override {
			return MotionInstant(endPos, pathDirection*endSpeed);
		}
		virtual std::unique_ptr<Path> clone() const override {
			debugThrow("This function is not implemented");
			return nullptr;
		}
	};
}
<|endoftext|>


<commit_before>
#pragma once

namespace globjects
{

enum class UniformType : unsigned char
{
    NONE,

    FLOAT,
    INT,
    UNSIGNED_INT,
    BOOL,
    FLOAT_VEC2,
    FLOAT_VEC3,
    FLOAT_VEC4,
    INT_VEC2,
    INT_VEC3,
    INT_VEC4,
    UNSIGNED_INT_VEC2,
    UNSIGNED_INT_VEC3,
    UNSIGNED_INT_VEC4,
    FLOAT_MAT2,
    FLOAT_MAT3,
    FLOAT_MAT4,
    FLOAT_MAT2x3,
    FLOAT_MAT3x2,
    FLOAT_MAT2x4,
    FLOAT_MAT4x2,
    FLOAT_MAT3x4,
    FLOAT_MAT4x3,
    UNSIGNED_INT64,
    TEXTURE_HANDLE,

    VECTOR_FLOAT,
    VECTOR_INT,
    VECTOR_UNSIGNED_INT,
    VECTOR_BOOL,
    VECTOR_FLOAT_VEC2,
    VECTOR_FLOAT_VEC3,
    VECTOR_FLOAT_VEC4,
    VECTOR_INT_VEC2,
    VECTOR_INT_VEC3,
    VECTOR_INT_VEC4,
    VECTOR_UNSIGNED_INT_VEC2,
    VECTOR_UNSIGNED_INT_VEC3,
    VECTOR_UNSIGNED_INT_VEC4,
    VECTOR_FLOAT_MAT2,
    VECTOR_FLOAT_MAT3,
    VECTOR_FLOAT_MAT4,
    VECTOR_FLOAT_MAT2x3,
    VECTOR_FLOAT_MAT3x2,
    VECTOR_FLOAT_MAT2x4,
    VECTOR_FLOAT_MAT4x2,
    VECTOR_FLOAT_MAT3x4,
    VECTOR_FLOAT_MAT4x3,
    VECTOR_UNSIGNED_INT64,
    VECTOR_TEXTURE_HANDLE,

    ARRAY_FLOAT,
    ARRAY_INT,
    ARRAY_UNSIGNED_INT,
    ARRAY_BOOL,
    ARRAY_FLOAT_VEC2,
    ARRAY_FLOAT_VEC3,
    ARRAY_FLOAT_VEC4,
    ARRAY_INT_VEC2,
    ARRAY_INT_VEC3,
    ARRAY_INT_VEC4,
    ARRAY_UNSIGNED_INT_VEC2,
    ARRAY_UNSIGNED_INT_VEC3,
    ARRAY_UNSIGNED_INT_VEC4,
    ARRAY_FLOAT_MAT2,
    ARRAY_FLOAT_MAT3,
    ARRAY_FLOAT_MAT4,
    ARRAY_FLOAT_MAT2x3,
    ARRAY_FLOAT_MAT3x2,
    ARRAY_FLOAT_MAT2x4,
    ARRAY_FLOAT_MAT4x2,
    ARRAY_FLOAT_MAT3x4,
    ARRAY_FLOAT_MAT4x3,
    ARRAY_UNSIGNED_INT64,
    ARRAY_TEXTURE_HANDLE
};

template <typename ValueType>
struct UniformTypeHelper
{
    static const UniformType value = UniformType::NONE;
};

template <>
struct UniformTypeHelper<float>
{
    static const UniformType value = UniformType::FLOAT;
};

template <>
struct UniformTypeHelper<int>
{
    static const UniformType value = UniformType::INT;
};

template <>
struct UniformTypeHelper<unsigned int>
{
    static const UniformType value = UniformType::UNSIGNED_INT;
};

template <>
struct UniformTypeHelper<bool>
{
    static const UniformType value = UniformType::BOOL;
};

template <>
struct UniformTypeHelper<glm::vec2>
{
    static const UniformType value = UniformType::FLOAT_VEC2;
};

template <>
struct UniformTypeHelper<glm::vec3>
{
    static const UniformType value = UniformType::FLOAT_VEC3;
};

template <>
struct UniformTypeHelper<glm::vec4>
{
    static const UniformType value = UniformType::FLOAT_VEC4;
};

template <>
struct UniformTypeHelper<glm::ivec2>
{
    static const UniformType value = UniformType::INT_VEC2;
};

template <>
struct UniformTypeHelper<glm::ivec3>
{
    static const UniformType value = UniformType::INT_VEC3;
};

template <>
struct UniformTypeHelper<glm::ivec4>
{
    static const UniformType value = UniformType::INT_VEC4;
};

template <>
struct UniformTypeHelper<glm::uvec2>
{
    static const UniformType value = UniformType::UNSIGNED_INT_VEC2;
};

template <>
struct UniformTypeHelper<glm::uvec3>
{
    static const UniformType value = UniformType::UNSIGNED_INT_VEC3;
};

template <>
struct UniformTypeHelper<glm::uvec4>
{
    static const UniformType value = UniformType::UNSIGNED_INT_VEC4;
};

template <>
struct UniformTypeHelper<glm::mat2>
{
    static const UniformType value = UniformType::UNSIGNED_INT;
};

template <>
struct UniformTypeHelper<glm::mat3>
{
    static const UniformType value = UniformType::UNSIGNED_INT;
};

template <>
struct UniformTypeHelper<glm::mat4>
{
    static const UniformType value = UniformType::UNSIGNED_INT;
};

template <>
struct UniformTypeHelper<glm::mat2x3>
{
    static const UniformType value = UniformType::UNSIGNED_INT;
};

template <>
struct UniformTypeHelper<glm::mat3x2>
{
    static const UniformType value = UniformType::UNSIGNED_INT;
};

template <>
struct UniformTypeHelper<glm::mat2x4>
{
    static const UniformType value = UniformType::UNSIGNED_INT;
};

template <>
struct UniformTypeHelper<glm::mat4x2>
{
    static const UniformType value = UniformType::UNSIGNED_INT;
};

template <>
struct UniformTypeHelper<glm::mat3x4>
{
    static const UniformType value = UniformType::UNSIGNED_INT;
};

template <>
struct UniformTypeHelper<glm::mat4x3>
{
    static const UniformType value = UniformType::UNSIGNED_INT;
};

template <>
struct UniformTypeHelper<gl::GLuint64>
{
    static const UniformType value = UniformType::UNSIGNED_INT64;
};

template <>
struct UniformTypeHelper<TextureHandle>
{
    static const UniformType value = UniformType::TEXTURE_HANDLE;
};

template <>
struct UniformTypeHelper<std::vector<float>>
{
    static const UniformType value = UniformType::VECTOR_FLOAT;
};

template <>
struct UniformTypeHelper<std::vector<int>>
{
    static const UniformType value = UniformType::VECTOR_INT;
};

template <>
struct UniformTypeHelper<std::vector<unsigned int>>
{
    static const UniformType value = UniformType::VECTOR_UNSIGNED_INT;
};

template <>
struct UniformTypeHelper<std::vector<bool>>
{
    static const UniformType value = UniformType::VECTOR_BOOL;
};

template <>
struct UniformTypeHelper<std::vector<glm::vec2>>
{
    static const UniformType value = UniformType::VECTOR_FLOAT_VEC2;
};

template <>
struct UniformTypeHelper<std::vector<glm::vec3>>
{
    static const UniformType value = UniformType::VECTOR_FLOAT_VEC3;
};

template <>
struct UniformTypeHelper<std::vector<glm::vec4>>
{
    static const UniformType value = UniformType::VECTOR_FLOAT_VEC4;
};

template <>
struct UniformTypeHelper<std::vector<glm::ivec2>>
{
    static const UniformType value = UniformType::VECTOR_INT_VEC2;
};

template <>
struct UniformTypeHelper<std::vector<glm::ivec3>>
{
    static const UniformType value = UniformType::VECTOR_INT_VEC3;
};

template <>
struct UniformTypeHelper<std::vector<glm::ivec4>>
{
    static const UniformType value = UniformType::VECTOR_INT_VEC4;
};

template <>
struct UniformTypeHelper<std::vector<glm::uvec2>>
{
    static const UniformType value = UniformType::VECTOR_UNSIGNED_INT_VEC2;
};

template <>
struct UniformTypeHelper<std::vector<glm::uvec3>>
{
    static const UniformType value = UniformType::VECTOR_UNSIGNED_INT_VEC3;
};

template <>
struct UniformTypeHelper<std::vector<glm::uvec4>>
{
    static const UniformType value = UniformType::VECTOR_UNSIGNED_INT_VEC4;
};

template <>
struct UniformTypeHelper<std::vector<glm::mat2>>
{
    static const UniformType value = UniformType::VECTOR_UNSIGNED_INT;
};

template <>
struct UniformTypeHelper<std::vector<glm::mat3>>
{
    static const UniformType value = UniformType::VECTOR_UNSIGNED_INT;
};

template <>
struct UniformTypeHelper<std::vector<glm::mat4>>
{
    static const UniformType value = UniformType::VECTOR_UNSIGNED_INT;
};

template <>
struct UniformTypeHelper<std::vector<glm::mat2x3>>
{
    static const UniformType value = UniformType::VECTOR_UNSIGNED_INT;
};

template <>
struct UniformTypeHelper<std::vector<glm::mat3x2>>
{
    static const UniformType value = UniformType::VECTOR_UNSIGNED_INT;
};

template <>
struct UniformTypeHelper<std::vector<glm::mat2x4>>
{
    static const UniformType value = UniformType::VECTOR_UNSIGNED_INT;
};

template <>
struct UniformTypeHelper<std::vector<glm::mat4x2>>
{
    static const UniformType value = UniformType::VECTOR_UNSIGNED_INT;
};

template <>
struct UniformTypeHelper<std::vector<glm::mat3x4>>
{
    static const UniformType value = UniformType::VECTOR_UNSIGNED_INT;
};

template <>
struct UniformTypeHelper<std::vector<glm::mat4x3>>
{
    static const UniformType value = UniformType::VECTOR_UNSIGNED_INT;
};

template <>
struct UniformTypeHelper<std::vector<gl::GLuint64>>
{
    static const UniformType value = UniformType::VECTOR_UNSIGNED_INT64;
};

template <>
struct UniformTypeHelper<std::vector<TextureHandle>>
{
    static const UniformType value = UniformType::VECTOR_TEXTURE_HANDLE;
};

template <size_t Count>
struct UniformTypeHelper<std::array<float, Count>>
{
    static const UniformType value = UniformType::ARRAY_FLOAT;
};

template <size_t Count>
struct UniformTypeHelper<std::array<int, Count>>
{
    static const UniformType value = UniformType::ARRAY_INT;
};

template <size_t Count>
struct UniformTypeHelper<std::array<unsigned int, Count>>
{
    static const UniformType value = UniformType::ARRAY_UNSIGNED_INT;
};

template <size_t Count>
struct UniformTypeHelper<std::array<bool, Count>>
{
    static const UniformType value = UniformType::ARRAY_BOOL;
};

template <size_t Count>
struct UniformTypeHelper<std::array<glm::vec2, Count>>
{
    static const UniformType value = UniformType::ARRAY_FLOAT_VEC2;
};

template <size_t Count>
struct UniformTypeHelper<std::array<glm::vec3, Count>>
{
    static const UniformType value = UniformType::ARRAY_FLOAT_VEC3;
};

template <size_t Count>
struct UniformTypeHelper<std::array<glm::vec4, Count>>
{
    static const UniformType value = UniformType::ARRAY_FLOAT_VEC4;
};

template <size_t Count>
struct UniformTypeHelper<std::array<glm::ivec2, Count>>
{
    static const UniformType value = UniformType::ARRAY_INT_VEC2;
};

template <size_t Count>
struct UniformTypeHelper<std::array<glm::ivec3, Count>>
{
    static const UniformType value = UniformType::ARRAY_INT_VEC3;
};

template <size_t Count>
struct UniformTypeHelper<std::array<glm::ivec4, Count>>
{
    static const UniformType value = UniformType::ARRAY_INT_VEC4;
};

template <size_t Count>
struct UniformTypeHelper<std::array<glm::uvec2, Count>>
{
    static const UniformType value = UniformType::ARRAY_UNSIGNED_INT_VEC2;
};

template <size_t Count>
struct UniformTypeHelper<std::array<glm::uvec3, Count>>
{
    static const UniformType value = UniformType::ARRAY_UNSIGNED_INT_VEC3;
};

template <size_t Count>
struct UniformTypeHelper<std::array<glm::uvec4, Count>>
{
    static const UniformType value = UniformType::ARRAY_UNSIGNED_INT_VEC4;
};

template <size_t Count>
struct UniformTypeHelper<std::array<glm::mat2, Count>>
{
    static const UniformType value = UniformType::ARRAY_UNSIGNED_INT;
};

template <size_t Count>
struct UniformTypeHelper<std::array<glm::mat3, Count>>
{
    static const UniformType value = UniformType::ARRAY_UNSIGNED_INT;
};

template <size_t Count>
struct UniformTypeHelper<std::array<glm::mat4, Count>>
{
    static const UniformType value = UniformType::ARRAY_UNSIGNED_INT;
};

template <size_t Count>
struct UniformTypeHelper<std::array<glm::mat2x3, Count>>
{
    static const UniformType value = UniformType::ARRAY_UNSIGNED_INT;
};

template <size_t Count>
struct UniformTypeHelper<std::array<glm::mat3x2, Count>>
{
    static const UniformType value = UniformType::ARRAY_UNSIGNED_INT;
};

template <size_t Count>
struct UniformTypeHelper<std::array<glm::mat2x4, Count>>
{
    static const UniformType value = UniformType::ARRAY_UNSIGNED_INT;
};

template <size_t Count>
struct UniformTypeHelper<std::array<glm::mat4x2, Count>>
{
    static const UniformType value = UniformType::ARRAY_UNSIGNED_INT;
};

template <size_t Count>
struct UniformTypeHelper<std::array<glm::mat3x4, Count>>
{
    static const UniformType value = UniformType::ARRAY_UNSIGNED_INT;
};

template <size_t Count>
struct UniformTypeHelper<std::array<glm::mat4x3, Count>>
{
    static const UniformType value = UniformType::ARRAY_UNSIGNED_INT;
};

template <size_t Count>
struct UniformTypeHelper<std::array<gl::GLuint64, Count>>
{
    static const UniformType value = UniformType::ARRAY_UNSIGNED_INT64;
};

template <size_t Count>
struct UniformTypeHelper<std::array<TextureHandle, Count>>
{
    static const UniformType value = UniformType::ARRAY_TEXTURE_HANDLE;
};

template <typename T, std::size_t Count>
void AbstractUniform::setValue(const gl::GLint location, const std::array<T, Count> & value) const
{
    setValue(location, std::vector<T>(value.data(), value.data()+Count));
}

} // namespace globjects
<commit_msg>Fix uniform helper types (closes #391)<commit_after>
#pragma once

namespace globjects
{

enum class UniformType : unsigned char
{
    NONE,

    FLOAT,
    INT,
    UNSIGNED_INT,
    BOOL,
    FLOAT_VEC2,
    FLOAT_VEC3,
    FLOAT_VEC4,
    INT_VEC2,
    INT_VEC3,
    INT_VEC4,
    UNSIGNED_INT_VEC2,
    UNSIGNED_INT_VEC3,
    UNSIGNED_INT_VEC4,
    FLOAT_MAT2,
    FLOAT_MAT3,
    FLOAT_MAT4,
    FLOAT_MAT2x3,
    FLOAT_MAT3x2,
    FLOAT_MAT2x4,
    FLOAT_MAT4x2,
    FLOAT_MAT3x4,
    FLOAT_MAT4x3,
    UNSIGNED_INT64,
    TEXTURE_HANDLE,

    VECTOR_FLOAT,
    VECTOR_INT,
    VECTOR_UNSIGNED_INT,
    VECTOR_BOOL,
    VECTOR_FLOAT_VEC2,
    VECTOR_FLOAT_VEC3,
    VECTOR_FLOAT_VEC4,
    VECTOR_INT_VEC2,
    VECTOR_INT_VEC3,
    VECTOR_INT_VEC4,
    VECTOR_UNSIGNED_INT_VEC2,
    VECTOR_UNSIGNED_INT_VEC3,
    VECTOR_UNSIGNED_INT_VEC4,
    VECTOR_FLOAT_MAT2,
    VECTOR_FLOAT_MAT3,
    VECTOR_FLOAT_MAT4,
    VECTOR_FLOAT_MAT2x3,
    VECTOR_FLOAT_MAT3x2,
    VECTOR_FLOAT_MAT2x4,
    VECTOR_FLOAT_MAT4x2,
    VECTOR_FLOAT_MAT3x4,
    VECTOR_FLOAT_MAT4x3,
    VECTOR_UNSIGNED_INT64,
    VECTOR_TEXTURE_HANDLE,

    ARRAY_FLOAT,
    ARRAY_INT,
    ARRAY_UNSIGNED_INT,
    ARRAY_BOOL,
    ARRAY_FLOAT_VEC2,
    ARRAY_FLOAT_VEC3,
    ARRAY_FLOAT_VEC4,
    ARRAY_INT_VEC2,
    ARRAY_INT_VEC3,
    ARRAY_INT_VEC4,
    ARRAY_UNSIGNED_INT_VEC2,
    ARRAY_UNSIGNED_INT_VEC3,
    ARRAY_UNSIGNED_INT_VEC4,
    ARRAY_FLOAT_MAT2,
    ARRAY_FLOAT_MAT3,
    ARRAY_FLOAT_MAT4,
    ARRAY_FLOAT_MAT2x3,
    ARRAY_FLOAT_MAT3x2,
    ARRAY_FLOAT_MAT2x4,
    ARRAY_FLOAT_MAT4x2,
    ARRAY_FLOAT_MAT3x4,
    ARRAY_FLOAT_MAT4x3,
    ARRAY_UNSIGNED_INT64,
    ARRAY_TEXTURE_HANDLE
};

template <typename ValueType>
struct UniformTypeHelper
{
    static const UniformType value = UniformType::NONE;
};

template <>
struct UniformTypeHelper<float>
{
    static const UniformType value = UniformType::FLOAT;
};

template <>
struct UniformTypeHelper<int>
{
    static const UniformType value = UniformType::INT;
};

template <>
struct UniformTypeHelper<unsigned int>
{
    static const UniformType value = UniformType::UNSIGNED_INT;
};

template <>
struct UniformTypeHelper<bool>
{
    static const UniformType value = UniformType::BOOL;
};

template <>
struct UniformTypeHelper<glm::vec2>
{
    static const UniformType value = UniformType::FLOAT_VEC2;
};

template <>
struct UniformTypeHelper<glm::vec3>
{
    static const UniformType value = UniformType::FLOAT_VEC3;
};

template <>
struct UniformTypeHelper<glm::vec4>
{
    static const UniformType value = UniformType::FLOAT_VEC4;
};

template <>
struct UniformTypeHelper<glm::ivec2>
{
    static const UniformType value = UniformType::INT_VEC2;
};

template <>
struct UniformTypeHelper<glm::ivec3>
{
    static const UniformType value = UniformType::INT_VEC3;
};

template <>
struct UniformTypeHelper<glm::ivec4>
{
    static const UniformType value = UniformType::INT_VEC4;
};

template <>
struct UniformTypeHelper<glm::uvec2>
{
    static const UniformType value = UniformType::UNSIGNED_INT_VEC2;
};

template <>
struct UniformTypeHelper<glm::uvec3>
{
    static const UniformType value = UniformType::UNSIGNED_INT_VEC3;
};

template <>
struct UniformTypeHelper<glm::uvec4>
{
    static const UniformType value = UniformType::UNSIGNED_INT_VEC4;
};

template <>
struct UniformTypeHelper<glm::mat2>
{
    static const UniformType value = UniformType::FLOAT_MAT2;
};

template <>
struct UniformTypeHelper<glm::mat3>
{
    static const UniformType value = UniformType::FLOAT_MAT3;
};

template <>
struct UniformTypeHelper<glm::mat4>
{
    static const UniformType value = UniformType::FLOAT_MAT4;
};

template <>
struct UniformTypeHelper<glm::mat2x3>
{
    static const UniformType value = UniformType::FLOAT_MAT2x3;
};

template <>
struct UniformTypeHelper<glm::mat3x2>
{
    static const UniformType value = UniformType::FLOAT_MAT3x2;
};

template <>
struct UniformTypeHelper<glm::mat2x4>
{
    static const UniformType value = UniformType::FLOAT_MAT2x4;
};

template <>
struct UniformTypeHelper<glm::mat4x2>
{
    static const UniformType value = UniformType::FLOAT_MAT4x2;
};

template <>
struct UniformTypeHelper<glm::mat3x4>
{
    static const UniformType value = UniformType::FLOAT_MAT3x4;
};

template <>
struct UniformTypeHelper<glm::mat4x3>
{
    static const UniformType value = UniformType::FLOAT_MAT4x3;
};

template <>
struct UniformTypeHelper<gl::GLuint64>
{
    static const UniformType value = UniformType::UNSIGNED_INT64;
};

template <>
struct UniformTypeHelper<TextureHandle>
{
    static const UniformType value = UniformType::TEXTURE_HANDLE;
};

template <>
struct UniformTypeHelper<std::vector<float>>
{
    static const UniformType value = UniformType::VECTOR_FLOAT;
};

template <>
struct UniformTypeHelper<std::vector<int>>
{
    static const UniformType value = UniformType::VECTOR_INT;
};

template <>
struct UniformTypeHelper<std::vector<unsigned int>>
{
    static const UniformType value = UniformType::VECTOR_UNSIGNED_INT;
};

template <>
struct UniformTypeHelper<std::vector<bool>>
{
    static const UniformType value = UniformType::VECTOR_BOOL;
};

template <>
struct UniformTypeHelper<std::vector<glm::vec2>>
{
    static const UniformType value = UniformType::VECTOR_FLOAT_VEC2;
};

template <>
struct UniformTypeHelper<std::vector<glm::vec3>>
{
    static const UniformType value = UniformType::VECTOR_FLOAT_VEC3;
};

template <>
struct UniformTypeHelper<std::vector<glm::vec4>>
{
    static const UniformType value = UniformType::VECTOR_FLOAT_VEC4;
};

template <>
struct UniformTypeHelper<std::vector<glm::ivec2>>
{
    static const UniformType value = UniformType::VECTOR_INT_VEC2;
};

template <>
struct UniformTypeHelper<std::vector<glm::ivec3>>
{
    static const UniformType value = UniformType::VECTOR_INT_VEC3;
};

template <>
struct UniformTypeHelper<std::vector<glm::ivec4>>
{
    static const UniformType value = UniformType::VECTOR_INT_VEC4;
};

template <>
struct UniformTypeHelper<std::vector<glm::uvec2>>
{
    static const UniformType value = UniformType::VECTOR_UNSIGNED_INT_VEC2;
};

template <>
struct UniformTypeHelper<std::vector<glm::uvec3>>
{
    static const UniformType value = UniformType::VECTOR_UNSIGNED_INT_VEC3;
};

template <>
struct UniformTypeHelper<std::vector<glm::uvec4>>
{
    static const UniformType value = UniformType::VECTOR_UNSIGNED_INT_VEC4;
};

template <>
struct UniformTypeHelper<std::vector<glm::mat2>>
{
    static const UniformType value = UniformType::VECTOR_FLOAT_MAT2;
};

template <>
struct UniformTypeHelper<std::vector<glm::mat3>>
{
    static const UniformType value = UniformType::VECTOR_FLOAT_MAT3;
};

template <>
struct UniformTypeHelper<std::vector<glm::mat4>>
{
    static const UniformType value = UniformType::VECTOR_FLOAT_MAT4;
};

template <>
struct UniformTypeHelper<std::vector<glm::mat2x3>>
{
    static const UniformType value = UniformType::VECTOR_FLOAT_MAT2x3;
};

template <>
struct UniformTypeHelper<std::vector<glm::mat3x2>>
{
    static const UniformType value = UniformType::VECTOR_FLOAT_MAT3x2;
};

template <>
struct UniformTypeHelper<std::vector<glm::mat2x4>>
{
    static const UniformType value = UniformType::VECTOR_FLOAT_MAT2x4;
};

template <>
struct UniformTypeHelper<std::vector<glm::mat4x2>>
{
    static const UniformType value = UniformType::VECTOR_FLOAT_MAT4x2;
};

template <>
struct UniformTypeHelper<std::vector<glm::mat3x4>>
{
    static const UniformType value = UniformType::VECTOR_FLOAT_MAT3x4;
};

template <>
struct UniformTypeHelper<std::vector<glm::mat4x3>>
{
    static const UniformType value = UniformType::VECTOR_FLOAT_MAT4x3;
};

template <>
struct UniformTypeHelper<std::vector<gl::GLuint64>>
{
    static const UniformType value = UniformType::VECTOR_UNSIGNED_INT64;
};

template <>
struct UniformTypeHelper<std::vector<TextureHandle>>
{
    static const UniformType value = UniformType::VECTOR_TEXTURE_HANDLE;
};

template <size_t Count>
struct UniformTypeHelper<std::array<float, Count>>
{
    static const UniformType value = UniformType::ARRAY_FLOAT;
};

template <size_t Count>
struct UniformTypeHelper<std::array<int, Count>>
{
    static const UniformType value = UniformType::ARRAY_INT;
};

template <size_t Count>
struct UniformTypeHelper<std::array<unsigned int, Count>>
{
    static const UniformType value = UniformType::ARRAY_UNSIGNED_INT;
};

template <size_t Count>
struct UniformTypeHelper<std::array<bool, Count>>
{
    static const UniformType value = UniformType::ARRAY_BOOL;
};

template <size_t Count>
struct UniformTypeHelper<std::array<glm::vec2, Count>>
{
    static const UniformType value = UniformType::ARRAY_FLOAT_VEC2;
};

template <size_t Count>
struct UniformTypeHelper<std::array<glm::vec3, Count>>
{
    static const UniformType value = UniformType::ARRAY_FLOAT_VEC3;
};

template <size_t Count>
struct UniformTypeHelper<std::array<glm::vec4, Count>>
{
    static const UniformType value = UniformType::ARRAY_FLOAT_VEC4;
};

template <size_t Count>
struct UniformTypeHelper<std::array<glm::ivec2, Count>>
{
    static const UniformType value = UniformType::ARRAY_INT_VEC2;
};

template <size_t Count>
struct UniformTypeHelper<std::array<glm::ivec3, Count>>
{
    static const UniformType value = UniformType::ARRAY_INT_VEC3;
};

template <size_t Count>
struct UniformTypeHelper<std::array<glm::ivec4, Count>>
{
    static const UniformType value = UniformType::ARRAY_INT_VEC4;
};

template <size_t Count>
struct UniformTypeHelper<std::array<glm::uvec2, Count>>
{
    static const UniformType value = UniformType::ARRAY_UNSIGNED_INT_VEC2;
};

template <size_t Count>
struct UniformTypeHelper<std::array<glm::uvec3, Count>>
{
    static const UniformType value = UniformType::ARRAY_UNSIGNED_INT_VEC3;
};

template <size_t Count>
struct UniformTypeHelper<std::array<glm::uvec4, Count>>
{
    static const UniformType value = UniformType::ARRAY_UNSIGNED_INT_VEC4;
};

template <size_t Count>
struct UniformTypeHelper<std::array<glm::mat2, Count>>
{
    static const UniformType value = UniformType::ARRAY_FLOAT_MAT2;
};

template <size_t Count>
struct UniformTypeHelper<std::array<glm::mat3, Count>>
{
    static const UniformType value = UniformType::ARRAY_FLOAT_MAT3;
};

template <size_t Count>
struct UniformTypeHelper<std::array<glm::mat4, Count>>
{
    static const UniformType value = UniformType::ARRAY_FLOAT_MAT4;
};

template <size_t Count>
struct UniformTypeHelper<std::array<glm::mat2x3, Count>>
{
    static const UniformType value = UniformType::ARRAY_FLOAT_MAT2x3;
};

template <size_t Count>
struct UniformTypeHelper<std::array<glm::mat3x2, Count>>
{
    static const UniformType value = UniformType::ARRAY_FLOAT_MAT3x2;
};

template <size_t Count>
struct UniformTypeHelper<std::array<glm::mat2x4, Count>>
{
    static const UniformType value = UniformType::ARRAY_FLOAT_MAT2x4;
};

template <size_t Count>
struct UniformTypeHelper<std::array<glm::mat4x2, Count>>
{
    static const UniformType value = UniformType::ARRAY_FLOAT_MAT4x2;
};

template <size_t Count>
struct UniformTypeHelper<std::array<glm::mat3x4, Count>>
{
    static const UniformType value = UniformType::ARRAY_FLOAT_MAT3x4;
};

template <size_t Count>
struct UniformTypeHelper<std::array<glm::mat4x3, Count>>
{
    static const UniformType value = UniformType::ARRAY_FLOAT_MAT4x3;
};

template <size_t Count>
struct UniformTypeHelper<std::array<gl::GLuint64, Count>>
{
    static const UniformType value = UniformType::ARRAY_UNSIGNED_INT64;
};

template <size_t Count>
struct UniformTypeHelper<std::array<TextureHandle, Count>>
{
    static const UniformType value = UniformType::ARRAY_TEXTURE_HANDLE;
};

template <typename T, std::size_t Count>
void AbstractUniform::setValue(const gl::GLint location, const std::array<T, Count> & value) const
{
    setValue(location, std::vector<T>(value.data(), value.data()+Count));
}

} // namespace globjects
<|endoftext|>


<commit_before>/* BEGIN_COMMON_COPYRIGHT_HEADER
 * (c)LGPL2+
 *
 * Razor - a lightweight, Qt based, desktop toolset
 * http://razor-qt.org
 *
 * Copyright: 2012 Christian Surlykke
 *
 * This program or library is free software; you can redistribute it
 * and/or modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.

 * You should have received a copy of the GNU Lesser General
 * Public License along with this library; if not, write to the
 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301 USA
 *
 * END_COMMON_COPYRIGHT_HEADER */

#include <QtCore/QRect>
#include <QtGui/QApplication>
#include <QtGui/QDesktopWidget>
#include <QtGui/QPalette>
#include "mainwindow.h"
#include "loginform.h"

MainWindow::MainWindow(int screen, QWidget *parent)
    : QWidget(parent)
{
    setObjectName(QString("MainWindow_%1").arg(screen));

    QRect screenRect = QApplication::desktop()->screenGeometry(screen);
    setGeometry(screenRect);
    QImage image(QString(SHARE_DIR) + "/themes/light/simple_blue_widescreen.png");

    QPalette palette;
    palette.setBrush(this->backgroundRole(), QBrush(image.scaled(screenRect.width(), screenRect.right())));
    this->setPalette(palette);

    // display login dialog only in the main screen
    m_main = screen == QApplication::desktop()->primaryScreen();
    if (m_main)
    {
        LoginForm *loginForm = new LoginForm(this);
        int offsetX = 2*screenRect.width()/5 - loginForm->width()/2;
        if (offsetX < 40)
        {
            offsetX = 40;
        }
        int offsetY = screenRect.height()/2 - loginForm->height()/2;
        loginForm->move(offsetX, offsetY);
        loginForm->show();
    }
}

MainWindow::~MainWindow()
{
}
<commit_msg>lightdm: move cursor to the center of screen for miltiple screens seat - it allows to handle key-focus<commit_after>/* BEGIN_COMMON_COPYRIGHT_HEADER
 * (c)LGPL2+
 *
 * Razor - a lightweight, Qt based, desktop toolset
 * http://razor-qt.org
 *
 * Copyright: 2012 Christian Surlykke
 *
 * This program or library is free software; you can redistribute it
 * and/or modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.

 * You should have received a copy of the GNU Lesser General
 * Public License along with this library; if not, write to the
 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301 USA
 *
 * END_COMMON_COPYRIGHT_HEADER */

#include <QtCore/QRect>
#include <QtGui/QApplication>
#include <QtGui/QDesktopWidget>
#include <QtGui/QPalette>
#include <QtGui/QX11Info>

#include "mainwindow.h"
#include "loginform.h"

MainWindow::MainWindow(int screen, QWidget *parent)
    : QWidget(parent)
{
    setObjectName(QString("MainWindow_%1").arg(screen));

    QRect screenRect = QApplication::desktop()->screenGeometry(screen);
    setGeometry(screenRect);
    QImage image(QString(SHARE_DIR) + "/themes/light/simple_blue_widescreen.png");

    QPalette palette;
    palette.setBrush(this->backgroundRole(), QBrush(image.scaled(screenRect.width(), screenRect.right())));
    this->setPalette(palette);

    // display login dialog only in the main screen
    m_main = screen == QApplication::desktop()->primaryScreen();
    if (m_main)
    {
        LoginForm *loginForm = new LoginForm(this);
        int offsetX = 2*screenRect.width()/5 - loginForm->width()/2;
        if (offsetX < 40)
        {
            offsetX = 40;
        }
        int offsetY = screenRect.height()/2 - loginForm->height()/2;
        loginForm->move(offsetX, offsetY);
        loginForm->show();

        // This hack ensures that the primary screen will have focus
        // if there are more screens (move the mouse cursor in the center
        // of primary screen - not in the center of all X area). It
        // won't affect single-screen environments.
        int centerX = screenRect.width()/2 + screenRect.x();
        int centerY = screenRect.height()/2 + screenRect.y();
        QCursor::setPos(centerX, centerY);
    }
}

MainWindow::~MainWindow()
{
}
<|endoftext|>


<commit_before>
#include <QLineSeries>
#include <QMenu>
#include <QAction>
#include <QFileDialog>
#include <QFile>
#include <QDateTime>
#include <QMessageBox>
#include <QDateTimeAxis>
#include <QValueAxis>
#include <QPrinter>
#include <QPrintDialog>
#include <QVBoxLayout>
#include <QCheckBox>
#include <QPushButton>
#include <QToolButton>
#include <QDebug>

#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    ui->frame->hide();
    mChart = new QtCharts::QChart();

    mXaxis = new QtCharts::QDateTimeAxis();
    mXaxis->setTitleFont(QFont("", 12, QFont::Bold));
    mXaxis->setLabelsAngle(20);
    mChart->addAxis(mXaxis, Qt::AlignBottom);

    mYaxis = new QtCharts::QValueAxis();
    mYaxis->setTitleFont(QFont("", 12, QFont::Bold));
    mYaxis->setLabelFormat("%i");
    mYaxis->setTitleText("Values");
    mChart->addAxis(mYaxis, Qt::AlignLeft);

    ui->chartView->setChart(mChart);
    ui->chartView->setRenderHint(QPainter::Antialiasing);

    setupActions();
    setupMenus();

    connect(ui->minDate, &QDateTimeEdit::dateTimeChanged, [this](){
        QDateTime minDate = ui->minDate->dateTime();
        ui->maxDate->setMinimumDateTime(minDate);
    });
    connect(ui->maxDate, &QDateTimeEdit::dateTimeChanged, [this](){
        QDateTime maxDate = ui->maxDate->dateTime();
        ui->minDate->setMaximumDateTime(maxDate);
    });

}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::selectDataDialog(QWidget *parent, QList<QAction *> actions)
{
    QDialog *dialog  = new QDialog(parent);
    QVBoxLayout *layout = new QVBoxLayout(dialog);
    QLabel *lbl_select = new QLabel("Select Data:", dialog);
    QFrame *frame = new QFrame(dialog);
    QVBoxLayout *frameLayout = new QVBoxLayout(frame);
    layout->addWidget(lbl_select);
    layout->addWidget(frame);

    QHBoxLayout *btnLayout = new  QHBoxLayout(dialog);
    QPushButton *okBtn = new QPushButton("OK");
    connect (okBtn, &QPushButton::clicked, [dialog](){
        dialog->close();
    });
    QSpacerItem *spacer = new QSpacerItem(50,30, QSizePolicy::Expanding);
    btnLayout->addSpacerItem(spacer);
    btnLayout->addWidget(okBtn);

    layout->addLayout(btnLayout);
    foreach (QAction *action, actions)
    {
        QCheckBox *chkBox = new QCheckBox(action->text(), dialog);
        chkBox->setChecked(true);
        connect(chkBox, &QCheckBox::toggled, [action](bool clicked){
            action->toggle();
        });
        frameLayout->addWidget(chkBox);
    }

    dialog->exec();

}

void MainWindow::setupActions()
{
    mOpenFile = new QAction("Open File", this);
    connect(mOpenFile, &QAction::triggered, [this](){
        QString fileName = QFileDialog::getOpenFileName(this, "Open CSV file", "", tr("CSV Files (*.csv)"));
        if (!fileName.isEmpty())
        {
            readCSVFile(fileName);
        }
    });

    mPrintAction = new QAction("Print");
    connect(mPrintAction, &QAction::triggered, [this](){
        QPrinter printer;

        QPrintDialog dialog(&printer, this);
        dialog.setWindowTitle(tr("Print Document"));

        if (dialog.exec() != QDialog::Accepted) {
            return;
        }
        printer.setOrientation(QPrinter::Landscape);
        printer.setFullPage(true);
        QPainter painter;
        painter.begin(&printer);

        //double xscale = printer.pageRect().width()/double(ui->chartView->width());
        //double yscale = printer.pageRect().height()/double(ui->chartView->height());
        //double scale = qMin(xscale, yscale);

        //painter.translate(printer.paperRect().x() + printer.pageRect().width()/2,
          //                printer.paperRect().y() + printer.pageRect().height()/2);
        //painter.scale(scale, scale);
        //painter.translate(-ui->chartView->width()/2, -ui->chartView->height()/2);

        ui->chartView->render(&painter);
        painter.drawRect(printer.pageRect());
        //painter.drawRect(printer.paperRect());
    });

}

void MainWindow::setupMenus()
{
    mFileMenu = new QMenu("File", this);
    mFileMenu->addAction(mOpenFile);

    mDataMenu = new QMenu("Data", this);
    mLinesMenu = new QMenu("Lines", this);
    mDataMenu->addMenu(mLinesMenu);

    mPrintMenu = new QMenu("Print", this);
    mPrintMenu->addAction(mPrintAction);

    ui->menuBar->addMenu(mFileMenu);
    ui->menuBar->addMenu(mDataMenu);
    ui->menuBar->addMenu(mPrintMenu);
}

void MainWindow::readCSVFile(const QString &fileName)
{
    QFile file(fileName);
    if (file.open(QIODevice::ReadOnly))
    {
        QStringList dataSeries;
        QMap<QString, QList<float>> dataValues;
        if (!file.atEnd())
        {
            //read header
            QString header = file.readLine();
            QStringList headers = header.split(",");
            for (int i=1; i<headers.size(); i++)
            {
                dataSeries.append(headers[i]);
                dataValues.insert(headers[i], QList<float>());
            }
        }
        QList<QDateTime> timeStamps;
        QDateTime minDate, maxDate;
        while(!file.atEnd())
        {
            QString line = file.readLine();
            QStringList data = line.split(",");
            QDateTime ts = QDateTime::fromString(data[0], "M/d/yyyy hh:mm:ss AP");
            if (!ts.isValid())
                continue;

            timeStamps.append(ts);
            if (data.size()-1 != dataSeries.size())
            {
                /*QMessageBox::critical(this, "Error", "Error in csv file data");
                return;*/
                continue;
            }
            for (int i=1; i<data.size(); i++)
            {
                dataValues[dataSeries[i-1]].append(data[i].toFloat());
            }

        }
        if (!timeStamps.isEmpty())
        {
            maxDate = timeStamps[0];
            minDate = timeStamps[0];
        }
        foreach (QDateTime focusDate, timeStamps)
        {
            minDate = (focusDate < minDate)? focusDate : minDate;
            maxDate = (focusDate > maxDate)? focusDate : maxDate;
        }

        mSeriesMax.clear();
        mSeriesMin.clear();
        //min max calulcation
        QMapIterator<QString, QList<float>> i(dataValues);
        while (i.hasNext())
        {
            i.next();
            QString sName = i.key();
            QList<float> data = i.value();

            float min_ = *std::min_element(data.begin(), data.end());
            float max_ = *std::max_element(data.begin(), data.end());
            mSeriesMax[sName] = max_;
            mSeriesMin[sName] = min_;

        }
        mChart->removeAllSeries();
        mLinesMenu->clear();
        mShownSeries.clear();

        for (int i=0; i<dataSeries.size(); i++)
        {
            QString seriesName = dataSeries[i];
            QList<float> data = dataValues[seriesName];

            QtCharts::QLineSeries *series = new QtCharts::QLineSeries();
            series->setName(seriesName);
            for (int j=0; j<timeStamps.size(); j++)
            {
                series->append(timeStamps[j].toMSecsSinceEpoch(), data[j]);
            }
            mChart->addSeries(series);
            series->attachAxis(mXaxis);
            series->attachAxis(mYaxis);
            QAction *showSeries = new QAction(seriesName);
            showSeries->setCheckable(true);
            showSeries->setChecked(true);
            mShownSeries.insert(seriesName);
            connect(showSeries, &QAction::toggled, [this, series, dataValues](bool checked){
                float maximum = 0;
                float minimum = 65000;
                QString sName = series->name();
                if (checked)
                {
                    mShownSeries.insert(sName);

                    foreach (QString seriesName, mShownSeries)
                    {

                        minimum = (mSeriesMin[seriesName] < minimum)? mSeriesMin[seriesName] : minimum;
                        maximum = (mSeriesMax[seriesName] > maximum)? mSeriesMax[seriesName] : maximum;
                    }
                    mYaxis->setRange(minimum, maximum + 10);
                    mChart->addSeries(series);
                    series->attachAxis(mXaxis);
                    series->attachAxis(mYaxis);

                }
                else
                {
                    mShownSeries.remove(sName);
                    foreach (QString seriesName, mShownSeries)
                    {
;
                        minimum = (mSeriesMin[seriesName] < minimum)? mSeriesMin[seriesName] : minimum;
                        maximum = (mSeriesMax[seriesName] > maximum)? mSeriesMax[seriesName] : maximum;
                    }
                    mYaxis->setRange(minimum, maximum + 10);
                    mChart->removeSeries(series);

                }

            });
            mLinesMenu->addAction(showSeries);
        }
        ui->chartView->setChart(mChart);
        float maximum = 0;
        float minimum = 65000;
        foreach (QString seriesName, mShownSeries)
        {

            minimum = (mSeriesMin[seriesName] < minimum)? mSeriesMin[seriesName] : minimum;
            maximum = (mSeriesMax[seriesName] > maximum)? mSeriesMax[seriesName] : maximum;
        }

        QFileInfo fInfo(fileName);
        mChart->setTitleFont(QFont("Times New Roman", 14));
        mChart->setTitle("" + fInfo.baseName()+ "");
        mYaxis->setRange(minimum, maximum + 10);
        mXaxis->setTickCount(10);
        mXaxis->setGridLineVisible();
        mXaxis->setFormat("yy-MM-d hh:mm");
        mXaxis->setTitleText("Date");
        ui->maxDate->setMinimumDateTime(minDate);
        ui->maxDate->setMaximumDateTime(maxDate);
        ui->maxDate->setDateTime(maxDate);

        ui->minDate->setMinimumDateTime(minDate);
        ui->minDate->setMaximumDateTime(maxDate);
        ui->minDate->setDateTime(minDate);

        ui->frame->setVisible(true);
        selectDataDialog(this, mLinesMenu->actions());
    }
}

void MainWindow::on_pushButton_clicked()
{
    QDateTime minDate = ui->minDate->dateTime();
    QDateTime maxDate = ui->maxDate->dateTime();

    if (minDate < maxDate)
    {
        mXaxis->setRange(minDate, maxDate);
    }
    else
    {
        QMessageBox::warning(this, "Invalid Range", "Invalid range please check");
    }
}
<commit_msg>full page printing<commit_after>
#include <QLineSeries>
#include <QMenu>
#include <QAction>
#include <QFileDialog>
#include <QFile>
#include <QDateTime>
#include <QMessageBox>
#include <QDateTimeAxis>
#include <QValueAxis>
#include <QPrinter>
#include <QPrintDialog>
#include <QVBoxLayout>
#include <QCheckBox>
#include <QPushButton>
#include <QToolButton>
#include <QDebug>

#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    ui->frame->hide();
    mChart = new QtCharts::QChart();

    mXaxis = new QtCharts::QDateTimeAxis();
    mXaxis->setTitleFont(QFont("", 12, QFont::Bold));
    mXaxis->setLabelsAngle(20);
    mChart->addAxis(mXaxis, Qt::AlignBottom);

    mYaxis = new QtCharts::QValueAxis();
    mYaxis->setTitleFont(QFont("", 12, QFont::Bold));
    mYaxis->setLabelFormat("%i");
    mYaxis->setTitleText("Values");
    mChart->addAxis(mYaxis, Qt::AlignLeft);

    ui->chartView->setChart(mChart);
    ui->chartView->setRenderHint(QPainter::Antialiasing);

    setupActions();
    setupMenus();

    connect(ui->minDate, &QDateTimeEdit::dateTimeChanged, [this](){
        QDateTime minDate = ui->minDate->dateTime();
        ui->maxDate->setMinimumDateTime(minDate);
    });
    connect(ui->maxDate, &QDateTimeEdit::dateTimeChanged, [this](){
        QDateTime maxDate = ui->maxDate->dateTime();
        ui->minDate->setMaximumDateTime(maxDate);
    });

}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::selectDataDialog(QWidget *parent, QList<QAction *> actions)
{
    QDialog *dialog  = new QDialog(parent);
    QVBoxLayout *layout = new QVBoxLayout(dialog);
    QLabel *lbl_select = new QLabel("Select Data:", dialog);
    QFrame *frame = new QFrame(dialog);
    QVBoxLayout *frameLayout = new QVBoxLayout(frame);
    layout->addWidget(lbl_select);
    layout->addWidget(frame);

    QHBoxLayout *btnLayout = new  QHBoxLayout(dialog);
    QPushButton *okBtn = new QPushButton("OK");
    connect (okBtn, &QPushButton::clicked, [dialog](){
        dialog->close();
    });
    QSpacerItem *spacer = new QSpacerItem(50,30, QSizePolicy::Expanding);
    btnLayout->addSpacerItem(spacer);
    btnLayout->addWidget(okBtn);

    layout->addLayout(btnLayout);
    foreach (QAction *action, actions)
    {
        QCheckBox *chkBox = new QCheckBox(action->text(), dialog);
        chkBox->setChecked(true);
        connect(chkBox, &QCheckBox::toggled, [action](bool clicked){
            action->toggle();
        });
        frameLayout->addWidget(chkBox);
    }

    dialog->exec();

}

void MainWindow::setupActions()
{
    mOpenFile = new QAction("Open File", this);
    connect(mOpenFile, &QAction::triggered, [this](){
        QString fileName = QFileDialog::getOpenFileName(this, "Open CSV file", "", tr("CSV Files (*.csv)"));
        if (!fileName.isEmpty())
        {
            readCSVFile(fileName);
        }
    });

    mPrintAction = new QAction("Print");
    connect(mPrintAction, &QAction::triggered, [this](){
        QPrinter printer;

        QPrintDialog dialog(&printer, this);
        dialog.setWindowTitle(tr("Print Document"));

        if (dialog.exec() != QDialog::Accepted) {
            return;
        }
        printer.setOrientation(QPrinter::Landscape);
        printer.setFullPage(true);
        QPainter painter;
        painter.begin(&printer);

        //double xscale = printer.pageRect().width()/double(ui->chartView->width());
        //double yscale = printer.pageRect().height()/double(ui->chartView->height());
        //double scale = qMin(xscale, yscale);

        //painter.translate(printer.paperRect().x() + printer.pageRect().width()/2,
          //                printer.paperRect().y() + printer.pageRect().height()/2);
        //painter.scale(scale, scale);
        //painter.translate(-ui->chartView->width()/2, -ui->chartView->height()/2);

        ui->chartView->render(&painter, printer.pageRect(), ui->chartView->rect(),Qt::IgnoreAspectRatio);
        painter.drawRect(printer.pageRect());
        //painter.drawRect(printer.paperRect());
    });

}

void MainWindow::setupMenus()
{
    mFileMenu = new QMenu("File", this);
    mFileMenu->addAction(mOpenFile);

    mDataMenu = new QMenu("Data", this);
    mLinesMenu = new QMenu("Lines", this);
    mDataMenu->addMenu(mLinesMenu);

    mPrintMenu = new QMenu("Print", this);
    mPrintMenu->addAction(mPrintAction);

    ui->menuBar->addMenu(mFileMenu);
    ui->menuBar->addMenu(mDataMenu);
    ui->menuBar->addMenu(mPrintMenu);
}

void MainWindow::readCSVFile(const QString &fileName)
{
    QFile file(fileName);
    if (file.open(QIODevice::ReadOnly))
    {
        QStringList dataSeries;
        QMap<QString, QList<float>> dataValues;
        if (!file.atEnd())
        {
            //read header
            QString header = file.readLine();
            QStringList headers = header.split(",");
            for (int i=1; i<headers.size(); i++)
            {
                dataSeries.append(headers[i]);
                dataValues.insert(headers[i], QList<float>());
            }
        }
        QList<QDateTime> timeStamps;
        QDateTime minDate, maxDate;
        while(!file.atEnd())
        {
            QString line = file.readLine();
            QStringList data = line.split(",");
            QDateTime ts = QDateTime::fromString(data[0], "M/d/yyyy hh:mm:ss AP");
            if (!ts.isValid())
                continue;

            timeStamps.append(ts);
            if (data.size()-1 != dataSeries.size())
            {
                /*QMessageBox::critical(this, "Error", "Error in csv file data");
                return;*/
                continue;
            }
            for (int i=1; i<data.size(); i++)
            {
                dataValues[dataSeries[i-1]].append(data[i].toFloat());
            }

        }
        if (!timeStamps.isEmpty())
        {
            maxDate = timeStamps[0];
            minDate = timeStamps[0];
        }
        foreach (QDateTime focusDate, timeStamps)
        {
            minDate = (focusDate < minDate)? focusDate : minDate;
            maxDate = (focusDate > maxDate)? focusDate : maxDate;
        }

        mSeriesMax.clear();
        mSeriesMin.clear();
        //min max calulcation
        QMapIterator<QString, QList<float>> i(dataValues);
        while (i.hasNext())
        {
            i.next();
            QString sName = i.key();
            QList<float> data = i.value();

            float min_ = *std::min_element(data.begin(), data.end());
            float max_ = *std::max_element(data.begin(), data.end());
            mSeriesMax[sName] = max_;
            mSeriesMin[sName] = min_;

        }
        mChart->removeAllSeries();
        mLinesMenu->clear();
        mShownSeries.clear();

        for (int i=0; i<dataSeries.size(); i++)
        {
            QString seriesName = dataSeries[i];
            QList<float> data = dataValues[seriesName];

            QtCharts::QLineSeries *series = new QtCharts::QLineSeries();
            series->setName(seriesName);
            for (int j=0; j<timeStamps.size(); j++)
            {
                series->append(timeStamps[j].toMSecsSinceEpoch(), data[j]);
            }
            mChart->addSeries(series);
            series->attachAxis(mXaxis);
            series->attachAxis(mYaxis);
            QAction *showSeries = new QAction(seriesName);
            showSeries->setCheckable(true);
            showSeries->setChecked(true);
            mShownSeries.insert(seriesName);
            connect(showSeries, &QAction::toggled, [this, series, dataValues](bool checked){
                float maximum = 0;
                float minimum = 65000;
                QString sName = series->name();
                if (checked)
                {
                    mShownSeries.insert(sName);

                    foreach (QString seriesName, mShownSeries)
                    {

                        minimum = (mSeriesMin[seriesName] < minimum)? mSeriesMin[seriesName] : minimum;
                        maximum = (mSeriesMax[seriesName] > maximum)? mSeriesMax[seriesName] : maximum;
                    }
                    mYaxis->setRange(minimum, maximum + 10);
                    mChart->addSeries(series);
                    series->attachAxis(mXaxis);
                    series->attachAxis(mYaxis);

                }
                else
                {
                    mShownSeries.remove(sName);
                    foreach (QString seriesName, mShownSeries)
                    {
;
                        minimum = (mSeriesMin[seriesName] < minimum)? mSeriesMin[seriesName] : minimum;
                        maximum = (mSeriesMax[seriesName] > maximum)? mSeriesMax[seriesName] : maximum;
                    }
                    mYaxis->setRange(minimum, maximum + 10);
                    mChart->removeSeries(series);

                }

            });
            mLinesMenu->addAction(showSeries);
        }
        ui->chartView->setChart(mChart);
        float maximum = 0;
        float minimum = 65000;
        foreach (QString seriesName, mShownSeries)
        {

            minimum = (mSeriesMin[seriesName] < minimum)? mSeriesMin[seriesName] : minimum;
            maximum = (mSeriesMax[seriesName] > maximum)? mSeriesMax[seriesName] : maximum;
        }

        QFileInfo fInfo(fileName);
        mChart->setTitleFont(QFont("Times New Roman", 14));
        mChart->setTitle("" + fInfo.baseName()+ "");
        mYaxis->setRange(minimum, maximum + 10);
        mXaxis->setTickCount(10);
        mXaxis->setGridLineVisible();
        mXaxis->setFormat("yy-MM-d hh:mm");
        mXaxis->setTitleText("Date");
        ui->maxDate->setMinimumDateTime(minDate);
        ui->maxDate->setMaximumDateTime(maxDate);
        ui->maxDate->setDateTime(maxDate);

        ui->minDate->setMinimumDateTime(minDate);
        ui->minDate->setMaximumDateTime(maxDate);
        ui->minDate->setDateTime(minDate);

        ui->frame->setVisible(true);
        selectDataDialog(this, mLinesMenu->actions());
    }
}

void MainWindow::on_pushButton_clicked()
{
    QDateTime minDate = ui->minDate->dateTime();
    QDateTime maxDate = ui->maxDate->dateTime();

    if (minDate < maxDate)
    {
        mXaxis->setRange(minDate, maxDate);
    }
    else
    {
        QMessageBox::warning(this, "Invalid Range", "Invalid range please check");
    }
}
<|endoftext|>


<commit_before>//===-- asan_mem_test.cc --------------------------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file is a part of AddressSanitizer, an address sanity checker.
//
//===----------------------------------------------------------------------===//
#include "asan_test_utils.h"

template<typename T>
void MemSetOOBTestTemplate(size_t length) {
  if (length == 0) return;
  size_t size = Ident(sizeof(T) * length);
  T *array = Ident((T*)malloc(size));
  int element = Ident(42);
  int zero = Ident(0);
  void *(*MEMSET)(void *s, int c, size_t n) = Ident(memset);
  // memset interval inside array
  MEMSET(array, element, size);
  MEMSET(array, element, size - 1);
  MEMSET(array + length - 1, element, sizeof(T));
  MEMSET(array, element, 1);

  // memset 0 bytes
  MEMSET(array - 10, element, zero);
  MEMSET(array - 1, element, zero);
  MEMSET(array, element, zero);
  MEMSET(array + length, 0, zero);
  MEMSET(array + length + 1, 0, zero);

  // try to memset bytes to the right of array
  EXPECT_DEATH(MEMSET(array, 0, size + 1),
               RightOOBWriteMessage(0));
  EXPECT_DEATH(MEMSET((char*)(array + length) - 1, element, 6),
               RightOOBWriteMessage(0));
  EXPECT_DEATH(MEMSET(array + 1, element, size + sizeof(T)),
               RightOOBWriteMessage(0));
  // whole interval is to the right
  EXPECT_DEATH(MEMSET(array + length + 1, 0, 10),
               RightOOBWriteMessage(sizeof(T)));

  // try to memset bytes to the left of array
  EXPECT_DEATH(MEMSET((char*)array - 1, element, size),
               LeftOOBWriteMessage(1));
  EXPECT_DEATH(MEMSET((char*)array - 5, 0, 6),
               LeftOOBWriteMessage(5));
  if (length >= 100) {
    // Large OOB, we find it only if the redzone is large enough.
    EXPECT_DEATH(memset(array - 5, element, size + 5 * sizeof(T)),
                 LeftOOBWriteMessage(5 * sizeof(T)));
  }
  // whole interval is to the left
  EXPECT_DEATH(MEMSET(array - 2, 0, sizeof(T)),
               LeftOOBWriteMessage(2 * sizeof(T)));

  // try to memset bytes both to the left & to the right
  EXPECT_DEATH(MEMSET((char*)array - 2, element, size + 4),
               LeftOOBWriteMessage(2));

  free(array);
}

TEST(AddressSanitizer, MemSetOOBTest) {
  MemSetOOBTestTemplate<char>(100);
  MemSetOOBTestTemplate<int>(5);
  MemSetOOBTestTemplate<double>(256);
  // We can test arrays of structres/classes here, but what for?
}

// Try to allocate two arrays of 'size' bytes that are near each other.
// Strictly speaking we are not guaranteed to find such two pointers,
// but given the structure of asan's allocator we will.
static bool AllocateTwoAdjacentArrays(char **x1, char **x2, size_t size) {
  vector<char *> v;
  bool res = false;
  for (size_t i = 0; i < 1000U && !res; i++) {
    v.push_back(new char[size]);
    if (i == 0) continue;
    sort(v.begin(), v.end());
    for (size_t j = 1; j < v.size(); j++) {
      assert(v[j] > v[j-1]);
      if ((size_t)(v[j] - v[j-1]) < size * 2) {
        *x2 = v[j];
        *x1 = v[j-1];
        res = true;
        break;
      }
    }
  }

  for (size_t i = 0; i < v.size(); i++) {
    if (res && v[i] == *x1) continue;
    if (res && v[i] == *x2) continue;
    delete [] v[i];
  }
  return res;
}

TEST(AddressSanitizer, LargeOOBInMemset) {
  for (size_t size = 200; size < 100000; size += size / 2) {
    char *x1, *x2;
    if (!Ident(AllocateTwoAdjacentArrays)(&x1, &x2, size))
      continue;
    // fprintf(stderr, "  large oob memset: %p %p %zd\n", x1, x2, size);
    // Do a memset on x1 with huge out-of-bound access that will end up in x2.
    EXPECT_DEATH(Ident(memset)(x1, 0, size * 2),
                 "is located 0 bytes to the right");
    delete [] x1;
    delete [] x2;
    return;
  }
  assert(0 && "Did not find two adjacent malloc-ed pointers");
}

// Same test for memcpy and memmove functions
template <typename T, class M>
void MemTransferOOBTestTemplate(size_t length) {
  if (length == 0) return;
  size_t size = Ident(sizeof(T) * length);
  T *src = Ident((T*)malloc(size));
  T *dest = Ident((T*)malloc(size));
  int zero = Ident(0);

  // valid transfer of bytes between arrays
  M::transfer(dest, src, size);
  M::transfer(dest + 1, src, size - sizeof(T));
  M::transfer(dest, src + length - 1, sizeof(T));
  M::transfer(dest, src, 1);

  // transfer zero bytes
  M::transfer(dest - 1, src, 0);
  M::transfer(dest + length, src, zero);
  M::transfer(dest, src - 1, zero);
  M::transfer(dest, src, zero);

  // try to change mem to the right of dest
  EXPECT_DEATH(M::transfer(dest + 1, src, size),
               RightOOBWriteMessage(0));
  EXPECT_DEATH(M::transfer((char*)(dest + length) - 1, src, 5),
               RightOOBWriteMessage(0));

  // try to change mem to the left of dest
  EXPECT_DEATH(M::transfer(dest - 2, src, size),
               LeftOOBWriteMessage(2 * sizeof(T)));
  EXPECT_DEATH(M::transfer((char*)dest - 3, src, 4),
               LeftOOBWriteMessage(3));

  // try to access mem to the right of src
  EXPECT_DEATH(M::transfer(dest, src + 2, size),
               RightOOBReadMessage(0));
  EXPECT_DEATH(M::transfer(dest, (char*)(src + length) - 3, 6),
               RightOOBReadMessage(0));

  // try to access mem to the left of src
  EXPECT_DEATH(M::transfer(dest, src - 1, size),
               LeftOOBReadMessage(sizeof(T)));
  EXPECT_DEATH(M::transfer(dest, (char*)src - 6, 7),
               LeftOOBReadMessage(6));

  // Generally we don't need to test cases where both accessing src and writing
  // to dest address to poisoned memory.

  T *big_src = Ident((T*)malloc(size * 2));
  T *big_dest = Ident((T*)malloc(size * 2));
  // try to change mem to both sides of dest
  EXPECT_DEATH(M::transfer(dest - 1, big_src, size * 2),
               LeftOOBWriteMessage(sizeof(T)));
  // try to access mem to both sides of src
  EXPECT_DEATH(M::transfer(big_dest, src - 2, size * 2),
               LeftOOBReadMessage(2 * sizeof(T)));

  free(src);
  free(dest);
  free(big_src);
  free(big_dest);
}

class MemCpyWrapper {
 public:
  static void* transfer(void *to, const void *from, size_t size) {
    return Ident(memcpy)(to, from, size);
  }
};

TEST(AddressSanitizer, MemCpyOOBTest) {
  MemTransferOOBTestTemplate<char, MemCpyWrapper>(100);
  MemTransferOOBTestTemplate<int, MemCpyWrapper>(1024);
}

class MemMoveWrapper {
 public:
  static void* transfer(void *to, const void *from, size_t size) {
    return Ident(memmove)(to, from, size);
  }
};

TEST(AddressSanitizer, MemMoveOOBTest) {
  MemTransferOOBTestTemplate<char, MemMoveWrapper>(100);
  MemTransferOOBTestTemplate<int, MemMoveWrapper>(1024);
}

TEST(AddressSanitizer, MemCmpOOBTest) {
  size_t size = Ident(100);
  char *s1 = MallocAndMemsetString(size);
  char *s2 = MallocAndMemsetString(size);
  // Normal memcmp calls.
  Ident(memcmp(s1, s2, size));
  Ident(memcmp(s1 + size - 1, s2 + size - 1, 1));
  Ident(memcmp(s1 - 1, s2 - 1, 0));
  // One of arguments points to not allocated memory.
  EXPECT_DEATH(Ident(memcmp)(s1 - 1, s2, 1), LeftOOBReadMessage(1));
  EXPECT_DEATH(Ident(memcmp)(s1, s2 - 1, 1), LeftOOBReadMessage(1));
  EXPECT_DEATH(Ident(memcmp)(s1 + size, s2, 1), RightOOBReadMessage(0));
  EXPECT_DEATH(Ident(memcmp)(s1, s2 + size, 1), RightOOBReadMessage(0));
  // Hit unallocated memory and die.
  EXPECT_DEATH(Ident(memcmp)(s1 + 1, s2 + 1, size), RightOOBReadMessage(0));
  EXPECT_DEATH(Ident(memcmp)(s1 + size - 1, s2, 2), RightOOBReadMessage(0));
  // Zero bytes are not terminators and don't prevent from OOB.
  s1[size - 1] = '\0';
  s2[size - 1] = '\0';
  EXPECT_DEATH(Ident(memcmp)(s1, s2, size + 1), RightOOBReadMessage(0));

  // Even if the buffers differ in the first byte, we still assume that
  // memcmp may access the whole buffer and thus reporting the overflow here:
  s1[0] = 1;
  s2[0] = 123;
  EXPECT_DEATH(Ident(memcmp)(s1, s2, size + 1), RightOOBReadMessage(0));

  free(s1);
  free(s2);
}

<commit_msg>[asan] remove UB (comparison of two unrelated pointers) from a test<commit_after>//===-- asan_mem_test.cc --------------------------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file is a part of AddressSanitizer, an address sanity checker.
//
//===----------------------------------------------------------------------===//
#include "asan_test_utils.h"

template<typename T>
void MemSetOOBTestTemplate(size_t length) {
  if (length == 0) return;
  size_t size = Ident(sizeof(T) * length);
  T *array = Ident((T*)malloc(size));
  int element = Ident(42);
  int zero = Ident(0);
  void *(*MEMSET)(void *s, int c, size_t n) = Ident(memset);
  // memset interval inside array
  MEMSET(array, element, size);
  MEMSET(array, element, size - 1);
  MEMSET(array + length - 1, element, sizeof(T));
  MEMSET(array, element, 1);

  // memset 0 bytes
  MEMSET(array - 10, element, zero);
  MEMSET(array - 1, element, zero);
  MEMSET(array, element, zero);
  MEMSET(array + length, 0, zero);
  MEMSET(array + length + 1, 0, zero);

  // try to memset bytes to the right of array
  EXPECT_DEATH(MEMSET(array, 0, size + 1),
               RightOOBWriteMessage(0));
  EXPECT_DEATH(MEMSET((char*)(array + length) - 1, element, 6),
               RightOOBWriteMessage(0));
  EXPECT_DEATH(MEMSET(array + 1, element, size + sizeof(T)),
               RightOOBWriteMessage(0));
  // whole interval is to the right
  EXPECT_DEATH(MEMSET(array + length + 1, 0, 10),
               RightOOBWriteMessage(sizeof(T)));

  // try to memset bytes to the left of array
  EXPECT_DEATH(MEMSET((char*)array - 1, element, size),
               LeftOOBWriteMessage(1));
  EXPECT_DEATH(MEMSET((char*)array - 5, 0, 6),
               LeftOOBWriteMessage(5));
  if (length >= 100) {
    // Large OOB, we find it only if the redzone is large enough.
    EXPECT_DEATH(memset(array - 5, element, size + 5 * sizeof(T)),
                 LeftOOBWriteMessage(5 * sizeof(T)));
  }
  // whole interval is to the left
  EXPECT_DEATH(MEMSET(array - 2, 0, sizeof(T)),
               LeftOOBWriteMessage(2 * sizeof(T)));

  // try to memset bytes both to the left & to the right
  EXPECT_DEATH(MEMSET((char*)array - 2, element, size + 4),
               LeftOOBWriteMessage(2));

  free(array);
}

TEST(AddressSanitizer, MemSetOOBTest) {
  MemSetOOBTestTemplate<char>(100);
  MemSetOOBTestTemplate<int>(5);
  MemSetOOBTestTemplate<double>(256);
  // We can test arrays of structres/classes here, but what for?
}

// Try to allocate two arrays of 'size' bytes that are near each other.
// Strictly speaking we are not guaranteed to find such two pointers,
// but given the structure of asan's allocator we will.
static bool AllocateTwoAdjacentArrays(char **x1, char **x2, size_t size) {
  vector<uintptr_t> v;
  bool res = false;
  for (size_t i = 0; i < 1000U && !res; i++) {
    v.push_back(reinterpret_cast<uintptr_t>(new char[size]));
    if (i == 0) continue;
    sort(v.begin(), v.end());
    for (size_t j = 1; j < v.size(); j++) {
      assert(v[j] > v[j-1]);
      if ((size_t)(v[j] - v[j-1]) < size * 2) {
        *x2 = reinterpret_cast<char*>(v[j]);
        *x1 = reinterpret_cast<char*>(v[j-1]);
        res = true;
        break;
      }
    }
  }

  for (size_t i = 0; i < v.size(); i++) {
    char *p = reinterpret_cast<char *>(v[i]);
    if (res && p == *x1) continue;
    if (res && p == *x2) continue;
    delete [] p;
  }
  return res;
}

TEST(AddressSanitizer, LargeOOBInMemset) {
  for (size_t size = 200; size < 100000; size += size / 2) {
    char *x1, *x2;
    if (!Ident(AllocateTwoAdjacentArrays)(&x1, &x2, size))
      continue;
    // fprintf(stderr, "  large oob memset: %p %p %zd\n", x1, x2, size);
    // Do a memset on x1 with huge out-of-bound access that will end up in x2.
    EXPECT_DEATH(Ident(memset)(x1, 0, size * 2),
                 "is located 0 bytes to the right");
    delete [] x1;
    delete [] x2;
    return;
  }
  assert(0 && "Did not find two adjacent malloc-ed pointers");
}

// Same test for memcpy and memmove functions
template <typename T, class M>
void MemTransferOOBTestTemplate(size_t length) {
  if (length == 0) return;
  size_t size = Ident(sizeof(T) * length);
  T *src = Ident((T*)malloc(size));
  T *dest = Ident((T*)malloc(size));
  int zero = Ident(0);

  // valid transfer of bytes between arrays
  M::transfer(dest, src, size);
  M::transfer(dest + 1, src, size - sizeof(T));
  M::transfer(dest, src + length - 1, sizeof(T));
  M::transfer(dest, src, 1);

  // transfer zero bytes
  M::transfer(dest - 1, src, 0);
  M::transfer(dest + length, src, zero);
  M::transfer(dest, src - 1, zero);
  M::transfer(dest, src, zero);

  // try to change mem to the right of dest
  EXPECT_DEATH(M::transfer(dest + 1, src, size),
               RightOOBWriteMessage(0));
  EXPECT_DEATH(M::transfer((char*)(dest + length) - 1, src, 5),
               RightOOBWriteMessage(0));

  // try to change mem to the left of dest
  EXPECT_DEATH(M::transfer(dest - 2, src, size),
               LeftOOBWriteMessage(2 * sizeof(T)));
  EXPECT_DEATH(M::transfer((char*)dest - 3, src, 4),
               LeftOOBWriteMessage(3));

  // try to access mem to the right of src
  EXPECT_DEATH(M::transfer(dest, src + 2, size),
               RightOOBReadMessage(0));
  EXPECT_DEATH(M::transfer(dest, (char*)(src + length) - 3, 6),
               RightOOBReadMessage(0));

  // try to access mem to the left of src
  EXPECT_DEATH(M::transfer(dest, src - 1, size),
               LeftOOBReadMessage(sizeof(T)));
  EXPECT_DEATH(M::transfer(dest, (char*)src - 6, 7),
               LeftOOBReadMessage(6));

  // Generally we don't need to test cases where both accessing src and writing
  // to dest address to poisoned memory.

  T *big_src = Ident((T*)malloc(size * 2));
  T *big_dest = Ident((T*)malloc(size * 2));
  // try to change mem to both sides of dest
  EXPECT_DEATH(M::transfer(dest - 1, big_src, size * 2),
               LeftOOBWriteMessage(sizeof(T)));
  // try to access mem to both sides of src
  EXPECT_DEATH(M::transfer(big_dest, src - 2, size * 2),
               LeftOOBReadMessage(2 * sizeof(T)));

  free(src);
  free(dest);
  free(big_src);
  free(big_dest);
}

class MemCpyWrapper {
 public:
  static void* transfer(void *to, const void *from, size_t size) {
    return Ident(memcpy)(to, from, size);
  }
};

TEST(AddressSanitizer, MemCpyOOBTest) {
  MemTransferOOBTestTemplate<char, MemCpyWrapper>(100);
  MemTransferOOBTestTemplate<int, MemCpyWrapper>(1024);
}

class MemMoveWrapper {
 public:
  static void* transfer(void *to, const void *from, size_t size) {
    return Ident(memmove)(to, from, size);
  }
};

TEST(AddressSanitizer, MemMoveOOBTest) {
  MemTransferOOBTestTemplate<char, MemMoveWrapper>(100);
  MemTransferOOBTestTemplate<int, MemMoveWrapper>(1024);
}

TEST(AddressSanitizer, MemCmpOOBTest) {
  size_t size = Ident(100);
  char *s1 = MallocAndMemsetString(size);
  char *s2 = MallocAndMemsetString(size);
  // Normal memcmp calls.
  Ident(memcmp(s1, s2, size));
  Ident(memcmp(s1 + size - 1, s2 + size - 1, 1));
  Ident(memcmp(s1 - 1, s2 - 1, 0));
  // One of arguments points to not allocated memory.
  EXPECT_DEATH(Ident(memcmp)(s1 - 1, s2, 1), LeftOOBReadMessage(1));
  EXPECT_DEATH(Ident(memcmp)(s1, s2 - 1, 1), LeftOOBReadMessage(1));
  EXPECT_DEATH(Ident(memcmp)(s1 + size, s2, 1), RightOOBReadMessage(0));
  EXPECT_DEATH(Ident(memcmp)(s1, s2 + size, 1), RightOOBReadMessage(0));
  // Hit unallocated memory and die.
  EXPECT_DEATH(Ident(memcmp)(s1 + 1, s2 + 1, size), RightOOBReadMessage(0));
  EXPECT_DEATH(Ident(memcmp)(s1 + size - 1, s2, 2), RightOOBReadMessage(0));
  // Zero bytes are not terminators and don't prevent from OOB.
  s1[size - 1] = '\0';
  s2[size - 1] = '\0';
  EXPECT_DEATH(Ident(memcmp)(s1, s2, size + 1), RightOOBReadMessage(0));

  // Even if the buffers differ in the first byte, we still assume that
  // memcmp may access the whole buffer and thus reporting the overflow here:
  s1[0] = 1;
  s2[0] = 123;
  EXPECT_DEATH(Ident(memcmp)(s1, s2, size + 1), RightOOBReadMessage(0));

  free(s1);
  free(s2);
}

<|endoftext|>


<commit_before>
#include "glew.h"

#include <GL/glew.h>

#include <iostream>

namespace
{
    #include "gltest_data.inl"

    bool errors = false;
}

void glew_init()
{
    glewInit();
    glGetError();
}

inline void glError()
{
    GLenum error = glGetError();
    if (error != GL_NO_ERROR)
        std::cout << "Error: 0x" << std::hex << error << std::endl;
}

void glew_test()
{
    if (errors)
    {
        #include "gltest_error.inl"
    }
    else
    {
        #include "gltest.inl"
    }
}

void glew_error(bool enable)
{
    errors = enable;
}
<commit_msg>Fix CID #41484<commit_after>
#include "glew.h"

#include <GL/glew.h>

#include <iostream>

namespace
{
    #include "gltest_data.inl"

    bool errors = false;
}

void glew_init()
{
    glewInit();
    glGetError();
}

inline void glError()
{
    GLenum error = glGetError();
    if (error != GL_NO_ERROR)
        std::cout << "Error: " << error << std::endl;
}

void glew_test()
{
    if (errors)
    {
        #include "gltest_error.inl"
    }
    else
    {
        #include "gltest.inl"
    }
}

void glew_error(bool enable)
{
    errors = enable;
}
<|endoftext|>