<commit_before>#include "picturemodel.h"

#include <QFile>
#include <QImageReader>
#include <QModelIndex>
#include <QDeclarativePropertyMap>
#include <QFileInfo>

PictureModel::PictureModel(QObject *parent)
    : MediaModel(MediaModel::Picture, parent)
{
    QHash<int, QByteArray> roleNames = MediaModel::roleNames();
    roleNames[ResolutionRole] = "resolution";
    roleNames[UserCommentsRole] = "userComments";
    roleNames[ImageDescriptionRole] = "imageDescription";
    roleNames[CreationTimeRole] = "creationTime";
    roleNames[CameraMakeRole] = "cameraMake";
    roleNames[CameraModelRole] = "cameraModel";
    roleNames[LatitudeRole] = "latitude";
    roleNames[LongitudeRole] = "longitude";
    roleNames[AltitudeRole] = "altitude";
    roleNames[OrientationRole] = "orientation";
    roleNames[ExifPropertiesRole] = "exifProperties";
    setRoleNames(roleNames);
}

PictureModel::~PictureModel()
{
}

QVariant PictureModel::data(MediaInfo *mediaInfo, int role) const
{
    PictureInfo *pictureInfo = static_cast<PictureInfo *>(mediaInfo);
    if (role == Qt::DisplayRole)
        return mediaInfo->name;
    if (role == ResolutionRole)
        return pictureInfo->resolution;
    else if (role == UserCommentsRole)
        return pictureInfo->exifProperties["userComments"];
    else if (role == ImageDescriptionRole)
        return pictureInfo->exifProperties["imageDescription"];
    else if (role == CreationTimeRole)
        return pictureInfo->exifProperties["creationTime"];
    else if (role == CameraMakeRole)
        return pictureInfo->exifProperties["cameraMake"];
    else if (role == CameraModelRole)
        return pictureInfo->exifProperties["cameraModel"];
    else if (role == LatitudeRole)
        return pictureInfo->exifProperties["latitude"];
    else if (role == LongitudeRole)
        return pictureInfo->exifProperties["longitude"];
    else if (role == AltitudeRole)
        return pictureInfo->exifProperties["altitude"];
    else if (role == OrientationRole)
        return pictureInfo->exifProperties["orientation"];
    else if (role == ExifPropertiesRole) {
        return pictureInfo->exifProperties;
    }
    return QVariant();
}

MediaInfo *PictureModel::readMediaInfo(const QString &filePath)
{
    QImageReader imageReader(filePath);
    if (!imageReader.canRead())
        return 0;

    QImage image = imageReader.read();
    if (image.isNull())
        return 0;

    PictureInfo *info = new PictureInfo;
    info->resolution = image.size();

    // check if we already have a local cover art for this file
    QFileInfo fileInfo(filePath);
    QFileInfo thumbnailInfo = generateThumbnailFileInfo(fileInfo);

    if (thumbnailInfo.exists()) {
        info->thumbnail = thumbnailInfo.filePath();
    } else {
        QImage tmp = image.width() <= previewWidth() ? image: image.scaledToWidth(previewWidth(), Qt::SmoothTransformation);
        if(tmp.save(thumbnailInfo.filePath()))
            info->thumbnail = thumbnailInfo.filePath();
        else
            info->thumbnail = themeResourcePath() + "/media/DefaultPicture.png";
    }

    ExifReader exifReader(filePath);
    info->exifProperties["userComments"] = exifReader.userComments();
    info->exifProperties["imageDescription"] = exifReader.imageDescription();
    info->exifProperties["creationTime"] = exifReader.creationTime();
    info->exifProperties["cameraModel"] = exifReader.cameraModel();
    info->exifProperties["cameraMake"] = exifReader.cameraMake();

    bool ok1, ok2, ok3;
    double lat = exifReader.latitude(&ok1);
    double log = exifReader.longitude(&ok2);
    if (ok1 && ok2) {
        info->exifProperties["latitude"] = lat;
        info->exifProperties["longitude"] = log;
    }
    info->exifProperties["altitude"] = exifReader.altitude(&ok3);

    info->exifProperties["orientation"] = exifReader.orientation();
    info->exifProperties["aperture"] = exifReader.aperture();
    info->exifProperties["focalLength"] = exifReader.focalLength();
    info->exifProperties["exposureMode"] = exifReader.exposureMode();
    info->exifProperties["whiteBalance"] = exifReader.whiteBalance();
    info->exifProperties["lightSource"] = exifReader.lightSource();
    info->exifProperties["isoSpeed"] = exifReader.isoSpeed();
    info->exifProperties["digitalZoomRatio"] = exifReader.digitalZoomRatio();
    info->exifProperties["flashUsage"] = exifReader.flashUsage();
    info->exifProperties["exposureTime"] = exifReader.exposureTime();
    info->exifProperties["colorSpace"] = exifReader.colorSpace();

    return info;
}

<commit_msg>Rotate/Mirror based on exif orientation<commit_after>#include "picturemodel.h"

#include <QFile>
#include <QImageReader>
#include <QModelIndex>
#include <QDeclarativePropertyMap>
#include <QFileInfo>

PictureModel::PictureModel(QObject *parent)
    : MediaModel(MediaModel::Picture, parent)
{
    QHash<int, QByteArray> roleNames = MediaModel::roleNames();
    roleNames[ResolutionRole] = "resolution";
    roleNames[UserCommentsRole] = "userComments";
    roleNames[ImageDescriptionRole] = "imageDescription";
    roleNames[CreationTimeRole] = "creationTime";
    roleNames[CameraMakeRole] = "cameraMake";
    roleNames[CameraModelRole] = "cameraModel";
    roleNames[LatitudeRole] = "latitude";
    roleNames[LongitudeRole] = "longitude";
    roleNames[AltitudeRole] = "altitude";
    roleNames[OrientationRole] = "orientation";
    roleNames[ExifPropertiesRole] = "exifProperties";
    setRoleNames(roleNames);
}

PictureModel::~PictureModel()
{
}

QVariant PictureModel::data(MediaInfo *mediaInfo, int role) const
{
    PictureInfo *pictureInfo = static_cast<PictureInfo *>(mediaInfo);
    if (role == Qt::DisplayRole)
        return mediaInfo->name;
    if (role == ResolutionRole)
        return pictureInfo->resolution;
    else if (role == UserCommentsRole)
        return pictureInfo->exifProperties["userComments"];
    else if (role == ImageDescriptionRole)
        return pictureInfo->exifProperties["imageDescription"];
    else if (role == CreationTimeRole)
        return pictureInfo->exifProperties["creationTime"];
    else if (role == CameraMakeRole)
        return pictureInfo->exifProperties["cameraMake"];
    else if (role == CameraModelRole)
        return pictureInfo->exifProperties["cameraModel"];
    else if (role == LatitudeRole)
        return pictureInfo->exifProperties["latitude"];
    else if (role == LongitudeRole)
        return pictureInfo->exifProperties["longitude"];
    else if (role == AltitudeRole)
        return pictureInfo->exifProperties["altitude"];
    else if (role == OrientationRole)
        return pictureInfo->exifProperties["orientation"];
    else if (role == ExifPropertiesRole) {
        return pictureInfo->exifProperties;
    }
    return QVariant();
}

MediaInfo *PictureModel::readMediaInfo(const QString &filePath)
{
    QImageReader imageReader(filePath);
    if (!imageReader.canRead())
        return 0;

    QImage image = imageReader.read();
    if (image.isNull())
        return 0;

    PictureInfo *info = new PictureInfo;
    info->resolution = image.size();

    ExifReader exifReader(filePath);
    info->exifProperties["userComments"] = exifReader.userComments();
    info->exifProperties["imageDescription"] = exifReader.imageDescription();
    info->exifProperties["creationTime"] = exifReader.creationTime();
    info->exifProperties["cameraModel"] = exifReader.cameraModel();
    info->exifProperties["cameraMake"] = exifReader.cameraMake();

    bool ok1, ok2, ok3;
    double lat = exifReader.latitude(&ok1);
    double log = exifReader.longitude(&ok2);
    if (ok1 && ok2) {
        info->exifProperties["latitude"] = lat;
        info->exifProperties["longitude"] = log;
    }
    info->exifProperties["altitude"] = exifReader.altitude(&ok3);

    info->exifProperties["orientation"] = exifReader.orientation();
    info->exifProperties["aperture"] = exifReader.aperture();
    info->exifProperties["focalLength"] = exifReader.focalLength();
    info->exifProperties["exposureMode"] = exifReader.exposureMode();
    info->exifProperties["whiteBalance"] = exifReader.whiteBalance();
    info->exifProperties["lightSource"] = exifReader.lightSource();
    info->exifProperties["isoSpeed"] = exifReader.isoSpeed();
    info->exifProperties["digitalZoomRatio"] = exifReader.digitalZoomRatio();
    info->exifProperties["flashUsage"] = exifReader.flashUsage();
    info->exifProperties["exposureTime"] = exifReader.exposureTime();
    info->exifProperties["colorSpace"] = exifReader.colorSpace();

    // check if we already have a local cover art for this file
    QFileInfo fileInfo(filePath);
    QFileInfo thumbnailInfo = generateThumbnailFileInfo(fileInfo);

    if (thumbnailInfo.exists()) {
        info->thumbnail = thumbnailInfo.filePath();
    } else {
        QImage tmp = image.width() <= previewWidth() ? image: image.scaledToWidth(previewWidth(), Qt::SmoothTransformation);
        ExifReader::Orientation orientation = static_cast<ExifReader::Orientation>(info->exifProperties["orientation"].toInt());
        QTransform transform;
        switch (orientation) {
        case ExifReader::FlipHorizontal: tmp = tmp.mirrored(true, false); tmp = tmp.transformed(transform); break;
        case ExifReader::Rotate180: transform.rotate(180); tmp = tmp.transformed(transform); break;
        case ExifReader::FlipVertical: tmp = tmp.mirrored(false, true); tmp = tmp.transformed(transform); break;
        case ExifReader::Transpose: tmp = tmp.mirrored(true, true); break;
        case ExifReader::Rotate90: transform.rotate(90); tmp = tmp.transformed(transform); break;
        case ExifReader::Transverse: /* wth */ break;
        case ExifReader::Rotate270: transform.rotate(270); tmp = tmp.transformed(transform); break;
        default: break;
        }

        if(tmp.save(thumbnailInfo.filePath()))
            info->thumbnail = thumbnailInfo.filePath();
        else
            info->thumbnail = themeResourcePath() + "/media/DefaultPicture.png";
    }

    return info;
}

<|endoftext|>


<commit_before>#include "process.hpp"
#include <windows.h>
#include <cstring>
#include <TlHelp32.h>
#include <stdexcept>

Process::Data::Data(): id(0), handle(NULL) {}

namespace {
  // Simple HANDLE wrapper to close it automatically from the destructor.
  class Handle {
  public:
    Handle() : handle(INVALID_HANDLE_VALUE) { }
    ~Handle() {
      close();
    }
    void close() {
      if (handle != INVALID_HANDLE_VALUE)
        ::CloseHandle(handle);
    }
    HANDLE detach() {
      HANDLE old_handle = handle;
      handle = INVALID_HANDLE_VALUE;
      return old_handle;
    }
    operator HANDLE() const { return handle; }
    HANDLE* operator&() { return &handle; }
  private:
    HANDLE handle;
  };

  //Based on the discussion thread: https://www.reddit.com/r/cpp/comments/3vpjqg/a_new_platform_independent_process_library_for_c11/cxq1wsj
  std::mutex create_process_mutex;
}

//Based on the example at https://msdn.microsoft.com/en-us/library/windows/desktop/ms682499(v=vs.85).aspx.
Process::id_type Process::open(const string_type &command, const string_type &path) {
  if(open_stdin)
    stdin_fd=std::make_unique<fd_type>(NULL);
  if(read_stdout)
    stdout_fd=std::make_unique<fd_type>(NULL);
  if(read_stderr)
    stderr_fd=std::make_unique<fd_type>(NULL);

  Handle stdin_rd_p;
  Handle stdin_wr_p;
  Handle stdout_rd_p;
  Handle stdout_wr_p;
  Handle stderr_rd_p;
  Handle stderr_wr_p;

  SECURITY_ATTRIBUTES security_attributes;

  security_attributes.nLength = sizeof(SECURITY_ATTRIBUTES);
  security_attributes.bInheritHandle = TRUE;
  security_attributes.lpSecurityDescriptor = NULL;

  std::lock_guard<std::mutex> lock(create_process_mutex);
  if(stdin_fd) {
    if (!CreatePipe(&stdin_rd_p, &stdin_wr_p, &security_attributes, 0) ||
        !SetHandleInformation(stdin_wr_p, HANDLE_FLAG_INHERIT, 0))
      return 0;
  }
  if(stdout_fd) {
    if (!CreatePipe(&stdout_rd_p, &stdout_wr_p, &security_attributes, 0) ||
        !SetHandleInformation(stdout_rd_p, HANDLE_FLAG_INHERIT, 0)) {
      return 0;
    }
  }
  if(stderr_fd) {
    if (!CreatePipe(&stderr_rd_p, &stderr_wr_p, &security_attributes, 0) ||
        !SetHandleInformation(stderr_rd_p, HANDLE_FLAG_INHERIT, 0)) {
      return 0;
    }
  }

  PROCESS_INFORMATION process_info;
  STARTUPINFO startup_info;

  ZeroMemory(&process_info, sizeof(PROCESS_INFORMATION));

  ZeroMemory(&startup_info, sizeof(STARTUPINFO));
  startup_info.cb = sizeof(STARTUPINFO);
  startup_info.hStdInput = stdin_rd_p;
  startup_info.hStdOutput = stdout_wr_p;
  startup_info.hStdError = stderr_wr_p;
  if(stdin_fd || stdout_fd || stderr_fd)
    startup_info.dwFlags |= STARTF_USESTDHANDLES;

  string_type process_command=command;
#ifdef MSYS_PROCESS_USE_SH
  size_t pos=0;
  while((pos=process_command.find('\\', pos))!=string_type::npos) {
    process_command.replace(pos, 1, "\\\\\\\\");
    pos+=4;
  }
  pos=0;
  while((pos=process_command.find('\"', pos))!=string_type::npos) {
    process_command.replace(pos, 1, "\\\"");
    pos+=2;
  }
  process_command.insert(0, "sh -c \"");
  process_command+="\"";
#endif

  BOOL bSuccess = CreateProcess(NULL, process_command.empty()?NULL:&process_command[0], NULL, NULL, TRUE, 0,
                                NULL, path.empty()?NULL:path.c_str(), &startup_info, &process_info);

  if(!bSuccess) {
    CloseHandle(process_info.hProcess);
    CloseHandle(process_info.hThread);
    return 0;
  }
  else {
    CloseHandle(process_info.hThread);
  }

  if(stdin_fd) *stdin_fd=stdin_wr_p.detach();
  if(stdout_fd) *stdout_fd=stdout_rd_p.detach();
  if(stderr_fd) *stderr_fd=stderr_rd_p.detach();

  closed=false;
  data.id=process_info.dwProcessId;
  data.handle=process_info.hProcess;
  return process_info.dwProcessId;
}

void Process::async_read() {
  if(data.id==0)
    return;
  if(stdout_fd) {
    stdout_thread=std::thread([this](){
      DWORD n;
      auto buffer = std::make_unique<char[]>(buffer_size);
      for (;;) {
        BOOL bSuccess = ReadFile(*stdout_fd, static_cast<CHAR*>(buffer.get()), static_cast<DWORD>(buffer_size), &n, NULL);
        if(!bSuccess || n == 0)
          break;
        read_stdout(buffer.get(), static_cast<size_t>(n));
      }
    });
  }
  if(stderr_fd) {
    stderr_thread=std::thread([this](){
      DWORD n;
      auto buffer = std::make_unique<char[]>(buffer_size);
      for (;;) {
        BOOL bSuccess = ReadFile(*stderr_fd, static_cast<CHAR*>(buffer.get()), static_cast<DWORD>(buffer_size), &n, NULL);
        if(!bSuccess || n == 0)
          break;
        read_stderr(buffer.get(), static_cast<size_t>(n));
      }
    });
  }
}

int Process::get_exit_status() {
  if(data.id==0)
    return -1;
  DWORD exit_status;
  WaitForSingleObject(data.handle, INFINITE);
  if(!GetExitCodeProcess(data.handle, &exit_status))
    exit_status=-1;
  {
    std::lock_guard<std::mutex> lock(close_mutex);
    CloseHandle(data.handle);
    closed=true;
  }
  close_fds();

  return static_cast<int>(exit_status);
}

void Process::close_fds() {
  if(stdout_thread.joinable())
    stdout_thread.join();
  if(stderr_thread.joinable())
    stderr_thread.join();

  if(stdin_fd)
    close_stdin();
  if(stdout_fd) {
    if(*stdout_fd!=NULL) CloseHandle(*stdout_fd);
    stdout_fd.reset();
  }
  if(stderr_fd) {
    if(*stderr_fd!=NULL) CloseHandle(*stderr_fd);
    stderr_fd.reset();
  }
}

bool Process::write(const char *bytes, size_t n) {
  if(!open_stdin)
    throw std::invalid_argument("Can't write to an unopened stdin pipe. Please set open_stdin=true when constructing the process.");

  std::lock_guard<std::mutex> lock(stdin_mutex);
  if(stdin_fd) {
    DWORD written;
    BOOL bSuccess=WriteFile(*stdin_fd, bytes, static_cast<DWORD>(n), &written, NULL);
    if(!bSuccess || written==0) {
      return false;
    }
    else {
      return true;
    }
  }
  return false;
}

void Process::close_stdin() {
  std::lock_guard<std::mutex> lock(stdin_mutex);
  if(stdin_fd) {
    if(*stdin_fd!=NULL) CloseHandle(*stdin_fd);
    stdin_fd.reset();
  }
}

//Based on http://stackoverflow.com/a/1173396
void Process::kill(bool force) {
  std::lock_guard<std::mutex> lock(close_mutex);
  if(data.id>0 && !closed) {
    HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    if(snapshot) {
      PROCESSENTRY32 process;
      ZeroMemory(&process, sizeof(process));
      process.dwSize = sizeof(process);
      if(Process32First(snapshot, &process)) {
        do {
          if(process.th32ParentProcessID==data.id) {
            HANDLE process_handle = OpenProcess(PROCESS_TERMINATE, FALSE, process.th32ProcessID);
            if(process_handle) {
              TerminateProcess(process_handle, 2);
              CloseHandle(process_handle);
            }
          }
        } while (Process32Next(snapshot, &process));
      }
      CloseHandle(snapshot);
    }
    TerminateProcess(data.handle, 2);
  }
}

//Based on http://stackoverflow.com/a/1173396
void Process::kill(id_type id, bool force) {
  if(id==0)
    return;
  HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
  if(snapshot) {
    PROCESSENTRY32 process;
    ZeroMemory(&process, sizeof(process));
    process.dwSize = sizeof(process);
    if(Process32First(snapshot, &process)) {
      do {
        if(process.th32ParentProcessID==id) {
          HANDLE process_handle = OpenProcess(PROCESS_TERMINATE, FALSE, process.th32ProcessID);
          if(process_handle) {
            TerminateProcess(process_handle, 2);
            CloseHandle(process_handle);
          }
        }
      } while (Process32Next(snapshot, &process));
    }
    CloseHandle(snapshot);
  }
  HANDLE process_handle = OpenProcess(PROCESS_TERMINATE, FALSE, id);
  if(process_handle) TerminateProcess(process_handle, 2);
}
<commit_msg>Replaced C-Style NULL macro usage in WinAPI calls with C++11's nullptr.<commit_after>#include "process.hpp"
#include <windows.h>
#include <cstring>
#include <TlHelp32.h>
#include <stdexcept>

Process::Data::Data(): id(0), handle(NULL) {}

namespace {
  // Simple HANDLE wrapper to close it automatically from the destructor.
  class Handle {
  public:
    Handle() : handle(INVALID_HANDLE_VALUE) { }
    ~Handle() {
      close();
    }
    void close() {
      if (handle != INVALID_HANDLE_VALUE)
        ::CloseHandle(handle);
    }
    HANDLE detach() {
      HANDLE old_handle = handle;
      handle = INVALID_HANDLE_VALUE;
      return old_handle;
    }
    operator HANDLE() const { return handle; }
    HANDLE* operator&() { return &handle; }
  private:
    HANDLE handle;
  };

  //Based on the discussion thread: https://www.reddit.com/r/cpp/comments/3vpjqg/a_new_platform_independent_process_library_for_c11/cxq1wsj
  std::mutex create_process_mutex;
}

//Based on the example at https://msdn.microsoft.com/en-us/library/windows/desktop/ms682499(v=vs.85).aspx.
Process::id_type Process::open(const string_type &command, const string_type &path) {
  if(open_stdin)
    stdin_fd=std::make_unique<fd_type>(NULL);
  if(read_stdout)
    stdout_fd=std::make_unique<fd_type>(NULL);
  if(read_stderr)
    stderr_fd=std::make_unique<fd_type>(NULL);

  Handle stdin_rd_p;
  Handle stdin_wr_p;
  Handle stdout_rd_p;
  Handle stdout_wr_p;
  Handle stderr_rd_p;
  Handle stderr_wr_p;

  SECURITY_ATTRIBUTES security_attributes;

  security_attributes.nLength = sizeof(SECURITY_ATTRIBUTES);
  security_attributes.bInheritHandle = TRUE;
  security_attributes.lpSecurityDescriptor = nullptr;

  std::lock_guard<std::mutex> lock(create_process_mutex);
  if(stdin_fd) {
    if (!CreatePipe(&stdin_rd_p, &stdin_wr_p, &security_attributes, 0) ||
        !SetHandleInformation(stdin_wr_p, HANDLE_FLAG_INHERIT, 0))
      return 0;
  }
  if(stdout_fd) {
    if (!CreatePipe(&stdout_rd_p, &stdout_wr_p, &security_attributes, 0) ||
        !SetHandleInformation(stdout_rd_p, HANDLE_FLAG_INHERIT, 0)) {
      return 0;
    }
  }
  if(stderr_fd) {
    if (!CreatePipe(&stderr_rd_p, &stderr_wr_p, &security_attributes, 0) ||
        !SetHandleInformation(stderr_rd_p, HANDLE_FLAG_INHERIT, 0)) {
      return 0;
    }
  }

  PROCESS_INFORMATION process_info;
  STARTUPINFO startup_info;

  ZeroMemory(&process_info, sizeof(PROCESS_INFORMATION));

  ZeroMemory(&startup_info, sizeof(STARTUPINFO));
  startup_info.cb = sizeof(STARTUPINFO);
  startup_info.hStdInput = stdin_rd_p;
  startup_info.hStdOutput = stdout_wr_p;
  startup_info.hStdError = stderr_wr_p;
  if(stdin_fd || stdout_fd || stderr_fd)
    startup_info.dwFlags |= STARTF_USESTDHANDLES;

  string_type process_command=command;
#ifdef MSYS_PROCESS_USE_SH
  size_t pos=0;
  while((pos=process_command.find('\\', pos))!=string_type::npos) {
    process_command.replace(pos, 1, "\\\\\\\\");
    pos+=4;
  }
  pos=0;
  while((pos=process_command.find('\"', pos))!=string_type::npos) {
    process_command.replace(pos, 1, "\\\"");
    pos+=2;
  }
  process_command.insert(0, "sh -c \"");
  process_command+="\"";
#endif

  BOOL bSuccess = CreateProcess(nullptr, process_command.empty()?nullptr:&process_command[0], nullptr, nullptr, TRUE, 0,
                                nullptr, path.empty()?nullptr:path.c_str(), &startup_info, &process_info);

  if(!bSuccess) {
    CloseHandle(process_info.hProcess);
    CloseHandle(process_info.hThread);
    return 0;
  }
  else {
    CloseHandle(process_info.hThread);
  }

  if(stdin_fd) *stdin_fd=stdin_wr_p.detach();
  if(stdout_fd) *stdout_fd=stdout_rd_p.detach();
  if(stderr_fd) *stderr_fd=stderr_rd_p.detach();

  closed=false;
  data.id=process_info.dwProcessId;
  data.handle=process_info.hProcess;
  return process_info.dwProcessId;
}

void Process::async_read() {
  if(data.id==0)
    return;
  if(stdout_fd) {
    stdout_thread=std::thread([this](){
      DWORD n;
      auto buffer = std::make_unique<char[]>(buffer_size);
      for (;;) {
        BOOL bSuccess = ReadFile(*stdout_fd, static_cast<CHAR*>(buffer.get()), static_cast<DWORD>(buffer_size), &n, nullptr);
        if(!bSuccess || n == 0)
          break;
        read_stdout(buffer.get(), static_cast<size_t>(n));
      }
    });
  }
  if(stderr_fd) {
    stderr_thread=std::thread([this](){
      DWORD n;
      auto buffer = std::make_unique<char[]>(buffer_size);
      for (;;) {
        BOOL bSuccess = ReadFile(*stderr_fd, static_cast<CHAR*>(buffer.get()), static_cast<DWORD>(buffer_size), &n, nullptr);
        if(!bSuccess || n == 0)
          break;
        read_stderr(buffer.get(), static_cast<size_t>(n));
      }
    });
  }
}

int Process::get_exit_status() {
  if(data.id==0)
    return -1;
  DWORD exit_status;
  WaitForSingleObject(data.handle, INFINITE);
  if(!GetExitCodeProcess(data.handle, &exit_status))
    exit_status=-1;
  {
    std::lock_guard<std::mutex> lock(close_mutex);
    CloseHandle(data.handle);
    closed=true;
  }
  close_fds();

  return static_cast<int>(exit_status);
}

void Process::close_fds() {
  if(stdout_thread.joinable())
    stdout_thread.join();
  if(stderr_thread.joinable())
    stderr_thread.join();

  if(stdin_fd)
    close_stdin();
  if(stdout_fd) {
    if(*stdout_fd!=NULL) CloseHandle(*stdout_fd);
    stdout_fd.reset();
  }
  if(stderr_fd) {
    if(*stderr_fd!=NULL) CloseHandle(*stderr_fd);
    stderr_fd.reset();
  }
}

bool Process::write(const char *bytes, size_t n) {
  if(!open_stdin)
    throw std::invalid_argument("Can't write to an unopened stdin pipe. Please set open_stdin=true when constructing the process.");

  std::lock_guard<std::mutex> lock(stdin_mutex);
  if(stdin_fd) {
    DWORD written;
    BOOL bSuccess=WriteFile(*stdin_fd, bytes, static_cast<DWORD>(n), &written, nullptr);
    if(!bSuccess || written==0) {
      return false;
    }
    else {
      return true;
    }
  }
  return false;
}

void Process::close_stdin() {
  std::lock_guard<std::mutex> lock(stdin_mutex);
  if(stdin_fd) {
    if(*stdin_fd!=NULL) CloseHandle(*stdin_fd);
    stdin_fd.reset();
  }
}

//Based on http://stackoverflow.com/a/1173396
void Process::kill(bool force) {
  std::lock_guard<std::mutex> lock(close_mutex);
  if(data.id>0 && !closed) {
    HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    if(snapshot) {
      PROCESSENTRY32 process;
      ZeroMemory(&process, sizeof(process));
      process.dwSize = sizeof(process);
      if(Process32First(snapshot, &process)) {
        do {
          if(process.th32ParentProcessID==data.id) {
            HANDLE process_handle = OpenProcess(PROCESS_TERMINATE, FALSE, process.th32ProcessID);
            if(process_handle) {
              TerminateProcess(process_handle, 2);
              CloseHandle(process_handle);
            }
          }
        } while (Process32Next(snapshot, &process));
      }
      CloseHandle(snapshot);
    }
    TerminateProcess(data.handle, 2);
  }
}

//Based on http://stackoverflow.com/a/1173396
void Process::kill(id_type id, bool force) {
  if(id==0)
    return;
  HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
  if(snapshot) {
    PROCESSENTRY32 process;
    ZeroMemory(&process, sizeof(process));
    process.dwSize = sizeof(process);
    if(Process32First(snapshot, &process)) {
      do {
        if(process.th32ParentProcessID==id) {
          HANDLE process_handle = OpenProcess(PROCESS_TERMINATE, FALSE, process.th32ProcessID);
          if(process_handle) {
            TerminateProcess(process_handle, 2);
            CloseHandle(process_handle);
          }
        }
      } while (Process32Next(snapshot, &process));
    }
    CloseHandle(snapshot);
  }
  HANDLE process_handle = OpenProcess(PROCESS_TERMINATE, FALSE, id);
  if(process_handle) TerminateProcess(process_handle, 2);
}
<|endoftext|>


<commit_before>/*
 * This istream filter removes HTTP chunking.
 *
 * author: Max Kellermann <mk@cm4all.com>
 */

#include "istream_dechunk.hxx"
#include "istream-internal.h"
#include "pool.hxx"
#include "util/Cast.hxx"

#include <assert.h>
#include <string.h>

enum istream_dechunk_state {
    NONE,
    CLOSED,
    SIZE,
    AFTER_SIZE,
    DATA,
    AFTER_DATA,
    TRAILER,
    TRAILER_DATA,
    EOF_DETECTED
};

struct istream_dechunk {
    struct istream output;

    struct istream *input;

    enum istream_dechunk_state state;

    size_t size;
    bool had_input, had_output;

    void (*eof_callback)(void *ctx);
    void *callback_ctx;
};

static GQuark
dechunk_quark(void)
{
    return g_quark_from_static_string("dechunk");
}

static void
dechunk_abort(struct istream_dechunk *dechunk, GError *error)
{
    assert(dechunk->state != EOF_DETECTED && dechunk->state != CLOSED);
    assert(dechunk->input != nullptr);

    dechunk->state = CLOSED;

    istream_free_handler(&dechunk->input);
    istream_deinit_abort(&dechunk->output, error);
}

/**
 * @return false if the istream_dechunk has been aborted indirectly
 * (by a callback)
 */
static bool
dechunk_eof_detected(struct istream_dechunk *dechunk)
{
    assert(dechunk->input != nullptr);
    assert(dechunk->state == TRAILER);
    assert(dechunk->size == 0);

    dechunk->state = EOF_DETECTED;

    dechunk->eof_callback(dechunk->callback_ctx);

    assert(dechunk->input != nullptr);
    assert(dechunk->state == EOF_DETECTED);

    pool_ref(dechunk->output.pool);
    istream_deinit_eof(&dechunk->output);

    if (dechunk->state == CLOSED) {
        assert(dechunk->input == nullptr);

        pool_unref(dechunk->output.pool);
        return false;
    } else {
        /* we must deinitialize the "input" after emitting "eof",
           because we must give the callback a chance to call
           dechunk_input_abort() on us; if we'd clear the handler too
           early, we wouldn't receive that event, and
           dechunk_input_data() couldn't change its return value to
           0 */
        assert(dechunk->input != nullptr);

        istream_handler_clear(dechunk->input);
        dechunk->input = nullptr;
        pool_unref(dechunk->output.pool);
        return true;
    }
}

static size_t
dechunk_feed(struct istream_dechunk *dechunk, const void *data0, size_t length)
{
    const char *data = (const char *)data0;
    size_t position = 0, digit, size, nbytes;

    assert(dechunk->input != nullptr);

    dechunk->had_input = true;

    while (position < length) {
        switch (dechunk->state) {
        case NONE:
        case SIZE:
            if (data[position] >= '0' && data[position] <= '9') {
                digit = data[position] - '0';
            } else if (data[position] >= 'a' && data[position] <= 'f') {
                digit = data[position] - 'a' + 0xa;
            } else if (data[position] >= 'A' && data[position] <= 'F') {
                digit = data[position] - 'A' + 0xa;
            } else if (dechunk->state == SIZE) {
                dechunk->state = AFTER_SIZE;
                ++position;
                continue;
            } else {
                GError *error =
                    g_error_new_literal(dechunk_quark(), 0,
                                        "chunk length expected");
                dechunk_abort(dechunk, error);
                return 0;
            }

            if (dechunk->state == NONE) {
                dechunk->state = SIZE;
                dechunk->size = 0;
            }

            ++position;
            dechunk->size = dechunk->size * 0x10 + digit;
            break;

        case CLOSED:
            assert(0);
            break;

        case AFTER_SIZE:
            if (data[position++] == '\n') {
                if (dechunk->size == 0)
                    dechunk->state = TRAILER;
                else
                    dechunk->state = DATA;
            }
            break;

        case DATA:
            assert(dechunk->size > 0);

            size = length - position;
            if (size > dechunk->size)
                size = dechunk->size;
            dechunk->had_output = true;
            nbytes = istream_invoke_data(&dechunk->output, data + position, size);
            assert(nbytes <= size);

            if (nbytes == 0)
                return dechunk->state == CLOSED ? 0 : position;

            dechunk->size -= nbytes;
            if (dechunk->size == 0)
                dechunk->state = AFTER_DATA;

            position += nbytes;
            break;

        case AFTER_DATA:
            if (data[position] == '\n') {
                dechunk->state = NONE;
            } else if (data[position] != '\r') {
                GError *error =
                    g_error_new_literal(dechunk_quark(), 0,
                                        "newline expected");
                dechunk_abort(dechunk, error);
                return 0;
            }
            ++position;
            break;

        case TRAILER:
            if (data[position] == '\n') {
                return dechunk_eof_detected(dechunk) ? position + 1 : 0;
            } else if (data[position] == '\r') {
                ++position;
            } else {
                ++position;
                dechunk->state = TRAILER_DATA;
            }
            break;

        case TRAILER_DATA:
            if (data[position++] == '\n')
                dechunk->state = TRAILER;
            break;

        case EOF_DETECTED:
            assert(0);
            return 0;
        }
    }

    return position;
}

/*
 * istream handler
 *
 */

static size_t
dechunk_input_data(const void *data, size_t length, void *ctx)
{
    struct istream_dechunk *dechunk = (struct istream_dechunk *)ctx;

    const ScopePoolRef ref(*dechunk->output.pool TRACE_ARGS);
    return dechunk_feed(dechunk, data, length);
}

static void
dechunk_input_eof(void *ctx)
{
    struct istream_dechunk *dechunk = (struct istream_dechunk *)ctx;

    assert(dechunk->state != EOF_DETECTED && dechunk->state != CLOSED);

    dechunk->state = CLOSED;

    dechunk->input = nullptr;

    GError *error =
        g_error_new_literal(dechunk_quark(), 0,
                            "premature EOF in dechunker");
    istream_deinit_abort(&dechunk->output, error);
}

static void
dechunk_input_abort(GError *error, void *ctx)
{
    struct istream_dechunk *dechunk = (struct istream_dechunk *)ctx;

    dechunk->input = nullptr;

    if (dechunk->state != EOF_DETECTED)
        istream_deinit_abort(&dechunk->output, error);
    else
        g_error_free(error);

    dechunk->state = CLOSED;
}

static const struct istream_handler dechunk_input_handler = {
    .data = dechunk_input_data,
    .eof = dechunk_input_eof,
    .abort = dechunk_input_abort,
};

/*
 * istream implementation
 *
 */

static inline struct istream_dechunk *
istream_to_dechunk(struct istream *istream)
{
    return &ContainerCast2(*istream, &istream_dechunk::output);
}

static off_t
istream_dechunk_available(struct istream *istream, bool partial)
{
    struct istream_dechunk *dechunk = istream_to_dechunk(istream);

    if (partial && dechunk->state == DATA)
        return (off_t)dechunk->size;

    return (off_t)-1;
}

static void
istream_dechunk_read(struct istream *istream)
{
    struct istream_dechunk *dechunk = istream_to_dechunk(istream);

    pool_ref(dechunk->output.pool);

    dechunk->had_output = false;

    do {
        dechunk->had_input = false;
        istream_read(dechunk->input);
    } while (dechunk->input != nullptr && dechunk->had_input &&
             !dechunk->had_output);

    pool_unref(dechunk->output.pool);
}

static void
istream_dechunk_close(struct istream *istream)
{
    struct istream_dechunk *dechunk = istream_to_dechunk(istream);

    assert(dechunk->state != EOF_DETECTED);

    dechunk->state = CLOSED;

    istream_free_handler(&dechunk->input);
    istream_deinit(&dechunk->output);
}

static const struct istream_class istream_dechunk = {
    .available = istream_dechunk_available,
    .read = istream_dechunk_read,
    .close = istream_dechunk_close,
};

/*
 * constructor
 *
 */

struct istream *
istream_dechunk_new(struct pool *pool, struct istream *input,
                    void (*eof_callback)(void *ctx), void *callback_ctx)
{
    struct istream_dechunk *dechunk = istream_new_macro(pool, dechunk);

    assert(input != nullptr);
    assert(!istream_has_handler(input));
    assert(eof_callback != nullptr);

    dechunk->state = NONE;
    dechunk->eof_callback = eof_callback;
    dechunk->callback_ctx = callback_ctx;

    istream_assign_handler(&dechunk->input, input,
                           &dechunk_input_handler, dechunk,
                           0);

    return istream_struct_cast(&dechunk->output);
}
<commit_msg>istream_dechunk: rename the struct to CamelCase<commit_after>/*
 * This istream filter removes HTTP chunking.
 *
 * author: Max Kellermann <mk@cm4all.com>
 */

#include "istream_dechunk.hxx"
#include "istream-internal.h"
#include "pool.hxx"
#include "util/Cast.hxx"

#include <assert.h>
#include <string.h>

enum istream_dechunk_state {
    NONE,
    CLOSED,
    SIZE,
    AFTER_SIZE,
    DATA,
    AFTER_DATA,
    TRAILER,
    TRAILER_DATA,
    EOF_DETECTED
};

struct DechunkIstream {
    struct istream output;

    struct istream *input;

    enum istream_dechunk_state state;

    size_t size;
    bool had_input, had_output;

    void (*const eof_callback)(void *ctx);
    void *const callback_ctx;

    DechunkIstream(struct pool &p, struct istream &_input,
                   void (*_eof_callback)(void *ctx), void *_callback_ctx);
};

static GQuark
dechunk_quark(void)
{
    return g_quark_from_static_string("dechunk");
}

static void
dechunk_abort(DechunkIstream *dechunk, GError *error)
{
    assert(dechunk->state != EOF_DETECTED && dechunk->state != CLOSED);
    assert(dechunk->input != nullptr);

    dechunk->state = CLOSED;

    istream_free_handler(&dechunk->input);
    istream_deinit_abort(&dechunk->output, error);
}

/**
 * @return false if the istream_dechunk has been aborted indirectly
 * (by a callback)
 */
static bool
dechunk_eof_detected(DechunkIstream *dechunk)
{
    assert(dechunk->input != nullptr);
    assert(dechunk->state == TRAILER);
    assert(dechunk->size == 0);

    dechunk->state = EOF_DETECTED;

    dechunk->eof_callback(dechunk->callback_ctx);

    assert(dechunk->input != nullptr);
    assert(dechunk->state == EOF_DETECTED);

    pool_ref(dechunk->output.pool);
    istream_deinit_eof(&dechunk->output);

    if (dechunk->state == CLOSED) {
        assert(dechunk->input == nullptr);

        pool_unref(dechunk->output.pool);
        return false;
    } else {
        /* we must deinitialize the "input" after emitting "eof",
           because we must give the callback a chance to call
           dechunk_input_abort() on us; if we'd clear the handler too
           early, we wouldn't receive that event, and
           dechunk_input_data() couldn't change its return value to
           0 */
        assert(dechunk->input != nullptr);

        istream_handler_clear(dechunk->input);
        dechunk->input = nullptr;
        pool_unref(dechunk->output.pool);
        return true;
    }
}

static size_t
dechunk_feed(DechunkIstream *dechunk, const void *data0, size_t length)
{
    const char *data = (const char *)data0;
    size_t position = 0, digit, size, nbytes;

    assert(dechunk->input != nullptr);

    dechunk->had_input = true;

    while (position < length) {
        switch (dechunk->state) {
        case NONE:
        case SIZE:
            if (data[position] >= '0' && data[position] <= '9') {
                digit = data[position] - '0';
            } else if (data[position] >= 'a' && data[position] <= 'f') {
                digit = data[position] - 'a' + 0xa;
            } else if (data[position] >= 'A' && data[position] <= 'F') {
                digit = data[position] - 'A' + 0xa;
            } else if (dechunk->state == SIZE) {
                dechunk->state = AFTER_SIZE;
                ++position;
                continue;
            } else {
                GError *error =
                    g_error_new_literal(dechunk_quark(), 0,
                                        "chunk length expected");
                dechunk_abort(dechunk, error);
                return 0;
            }

            if (dechunk->state == NONE) {
                dechunk->state = SIZE;
                dechunk->size = 0;
            }

            ++position;
            dechunk->size = dechunk->size * 0x10 + digit;
            break;

        case CLOSED:
            assert(0);
            break;

        case AFTER_SIZE:
            if (data[position++] == '\n') {
                if (dechunk->size == 0)
                    dechunk->state = TRAILER;
                else
                    dechunk->state = DATA;
            }
            break;

        case DATA:
            assert(dechunk->size > 0);

            size = length - position;
            if (size > dechunk->size)
                size = dechunk->size;
            dechunk->had_output = true;
            nbytes = istream_invoke_data(&dechunk->output, data + position, size);
            assert(nbytes <= size);

            if (nbytes == 0)
                return dechunk->state == CLOSED ? 0 : position;

            dechunk->size -= nbytes;
            if (dechunk->size == 0)
                dechunk->state = AFTER_DATA;

            position += nbytes;
            break;

        case AFTER_DATA:
            if (data[position] == '\n') {
                dechunk->state = NONE;
            } else if (data[position] != '\r') {
                GError *error =
                    g_error_new_literal(dechunk_quark(), 0,
                                        "newline expected");
                dechunk_abort(dechunk, error);
                return 0;
            }
            ++position;
            break;

        case TRAILER:
            if (data[position] == '\n') {
                return dechunk_eof_detected(dechunk) ? position + 1 : 0;
            } else if (data[position] == '\r') {
                ++position;
            } else {
                ++position;
                dechunk->state = TRAILER_DATA;
            }
            break;

        case TRAILER_DATA:
            if (data[position++] == '\n')
                dechunk->state = TRAILER;
            break;

        case EOF_DETECTED:
            assert(0);
            return 0;
        }
    }

    return position;
}

/*
 * istream handler
 *
 */

static size_t
dechunk_input_data(const void *data, size_t length, void *ctx)
{
    DechunkIstream *dechunk = (DechunkIstream *)ctx;

    const ScopePoolRef ref(*dechunk->output.pool TRACE_ARGS);
    return dechunk_feed(dechunk, data, length);
}

static void
dechunk_input_eof(void *ctx)
{
    DechunkIstream *dechunk = (DechunkIstream *)ctx;

    assert(dechunk->state != EOF_DETECTED && dechunk->state != CLOSED);

    dechunk->state = CLOSED;

    dechunk->input = nullptr;

    GError *error =
        g_error_new_literal(dechunk_quark(), 0,
                            "premature EOF in dechunker");
    istream_deinit_abort(&dechunk->output, error);
}

static void
dechunk_input_abort(GError *error, void *ctx)
{
    DechunkIstream *dechunk = (DechunkIstream *)ctx;

    dechunk->input = nullptr;

    if (dechunk->state != EOF_DETECTED)
        istream_deinit_abort(&dechunk->output, error);
    else
        g_error_free(error);

    dechunk->state = CLOSED;
}

static const struct istream_handler dechunk_input_handler = {
    .data = dechunk_input_data,
    .eof = dechunk_input_eof,
    .abort = dechunk_input_abort,
};

/*
 * istream implementation
 *
 */

static inline DechunkIstream *
istream_to_dechunk(struct istream *istream)
{
    return &ContainerCast2(*istream, &DechunkIstream::output);
}

static off_t
istream_dechunk_available(struct istream *istream, bool partial)
{
    DechunkIstream *dechunk = istream_to_dechunk(istream);

    if (partial && dechunk->state == DATA)
        return (off_t)dechunk->size;

    return (off_t)-1;
}

static void
istream_dechunk_read(struct istream *istream)
{
    DechunkIstream *dechunk = istream_to_dechunk(istream);

    pool_ref(dechunk->output.pool);

    dechunk->had_output = false;

    do {
        dechunk->had_input = false;
        istream_read(dechunk->input);
    } while (dechunk->input != nullptr && dechunk->had_input &&
             !dechunk->had_output);

    pool_unref(dechunk->output.pool);
}

static void
istream_dechunk_close(struct istream *istream)
{
    DechunkIstream *dechunk = istream_to_dechunk(istream);

    assert(dechunk->state != EOF_DETECTED);

    dechunk->state = CLOSED;

    istream_free_handler(&dechunk->input);
    istream_deinit(&dechunk->output);
}

static const struct istream_class istream_dechunk = {
    .available = istream_dechunk_available,
    .read = istream_dechunk_read,
    .close = istream_dechunk_close,
};

/*
 * constructor
 *
 */

inline DechunkIstream::DechunkIstream(struct pool &p, struct istream &_input,
                                      void (*_eof_callback)(void *ctx),
                                      void *_callback_ctx)
    :state(NONE),
     eof_callback(_eof_callback), callback_ctx(_callback_ctx)
{
    istream_init(&output, &istream_dechunk, &p);

    istream_assign_handler(&input, &_input,
                           &dechunk_input_handler, this,
                           0);
}

struct istream *
istream_dechunk_new(struct pool *pool, struct istream *input,
                    void (*eof_callback)(void *ctx), void *callback_ctx)
{
    assert(input != nullptr);
    assert(!istream_has_handler(input));
    assert(eof_callback != nullptr);

    auto *dechunk = NewFromPool<DechunkIstream>(*pool, *pool, *input,
                                                eof_callback, callback_ctx);
    return &dechunk->output;
}
<|endoftext|>


<commit_before>/*
 * Unit tests for libkvkontakte.
 * Copyright (C) 2015  Alexander Potashev <aspotashev@gmail.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

#include "test_database.h"

#include <libkvkontakte/cidsnamesjob.h>

#include <qtest_kde.h>

using namespace Vkontakte;

TestDatabaseMethods::TestDatabaseMethods()
    : VkTestBase()
{
}

void TestDatabaseMethods::initTestCase()
{
    authenticate();
}

void TestDatabaseMethods::testCountriesById()
{
    CidsNamesJob* const job = new CidsNamesJob(
        "database.getCountriesById", accessToken(), QIntList() << 1 << 2 << 3);
    job->exec();
    QVERIFY(!job->error());

    QMap<int, QString> names = job->names();
    QCOMPARE(names.size(), 3);
    QCOMPARE(names[1], QString::fromUtf8("Россия")); // Russia
    QCOMPARE(names[2], QString::fromUtf8("Украина")); // Ukraine
    QCOMPARE(names[3], QString::fromUtf8("Беларусь")); // Belarus
}

void TestDatabaseMethods::testCitiesById()
{
    CidsNamesJob* const job = new CidsNamesJob(
        "database.getCitiesById", accessToken(), QIntList() << 1 << 2 << 4);
    job->exec();
    QVERIFY(!job->error());

    QMap<int, QString> names = job->names();
    QCOMPARE(names.size(), 3);
    QCOMPARE(names[1], QString::fromUtf8("Москва")); // Moscow
    QCOMPARE(names[2], QString::fromUtf8("Санкт-Петербург")); // Saint-Petersburg
    QCOMPARE(names[4], QString::fromUtf8("Herzliya"));
}

QTEST_KDEMAIN(TestDatabaseMethods, GUI)
#include "test_database.moc"
<commit_msg>test_database: VK API methods "database.get[...]ById" do not require auth token<commit_after>/*
 * Unit tests for libkvkontakte.
 * Copyright (C) 2015  Alexander Potashev <aspotashev@gmail.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

#include "test_database.h"

#include <libkvkontakte/cidsnamesjob.h>

#include <qtest_kde.h>

using namespace Vkontakte;

TestDatabaseMethods::TestDatabaseMethods()
    : VkTestBase()
{
}

void TestDatabaseMethods::initTestCase()
{
}

void TestDatabaseMethods::testCountriesById()
{
    CidsNamesJob* const job = new CidsNamesJob(
        "database.getCountriesById", QString(), QIntList() << 1 << 2 << 3);
    job->exec();
    QVERIFY(!job->error());

    QMap<int, QString> names = job->names();
    QCOMPARE(names.size(), 3);
    QCOMPARE(names[1], QString::fromUtf8("Россия")); // Russia
    QCOMPARE(names[2], QString::fromUtf8("Украина")); // Ukraine
    QCOMPARE(names[3], QString::fromUtf8("Беларусь")); // Belarus
}

void TestDatabaseMethods::testCitiesById()
{
    CidsNamesJob* const job = new CidsNamesJob(
        "database.getCitiesById", QString(), QIntList() << 1 << 2 << 4);
    job->exec();
    QVERIFY(!job->error());

    QMap<int, QString> names = job->names();
    QCOMPARE(names.size(), 3);
    QCOMPARE(names[1], QString::fromUtf8("Москва")); // Moscow
    QCOMPARE(names[2], QString::fromUtf8("Санкт-Петербург")); // Saint-Petersburg
    QCOMPARE(names[4], QString::fromUtf8("Herzliya"));
}

QTEST_KDEMAIN(TestDatabaseMethods, GUI)
#include "test_database.moc"
<|endoftext|>


<commit_before>// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "flutter/lib/ui/painting/image_decoding.h"

#include "flutter/common/threads.h"
#include "flutter/glue/trace_event.h"
#include "flutter/lib/ui/painting/image.h"
#include "flutter/lib/ui/painting/resource_context.h"
#include "lib/ftl/functional/make_copyable.h"
#include "lib/tonic/dart_persistent_value.h"
#include "lib/tonic/dart_state.h"
#include "lib/tonic/logging/dart_invoke.h"
#include "lib/tonic/typed_data/uint8_list.h"
#include "third_party/skia/include/core/SkImageGenerator.h"

#ifdef OS_ANDROID
#include <GLES2/gl2.h>
#endif

using tonic::DartInvoke;
using tonic::DartPersistentValue;
using tonic::ToDart;

namespace blink {
namespace {

sk_sp<SkImage> DecodeImage(sk_sp<SkData> buffer) {
  TRACE_EVENT0("blink", "DecodeImage");

  if (buffer == nullptr || buffer->isEmpty()) {
    return nullptr;
  }

  auto raster_image = SkImage::MakeFromEncoded(std::move(buffer));

  if (raster_image == nullptr) {
    return nullptr;
  }

  if (auto context = ResourceContext::Get()) {
    // TODO: Supply actual destination color space once available
    if (auto texture_image =
            raster_image->makeTextureImage(context, nullptr)) {
#ifdef OS_ANDROID
      glFlush();
#endif
      return texture_image;
    }
  }

  return raster_image;
}

void InvokeImageCallback(sk_sp<SkImage> image,
                         std::unique_ptr<DartPersistentValue> callback) {
  tonic::DartState* dart_state = callback->dart_state().get();
  if (!dart_state)
    return;
  tonic::DartState::Scope scope(dart_state);
  if (!image) {
    DartInvoke(callback->value(), {Dart_Null()});
  } else {
    ftl::RefPtr<CanvasImage> resultImage = CanvasImage::Create();
    resultImage->set_image(std::move(image));
    DartInvoke(callback->value(), {ToDart(resultImage)});
  }
}

void DecodeImageAndInvokeImageCallback(
    std::unique_ptr<DartPersistentValue> callback,
    sk_sp<SkData> buffer) {
  sk_sp<SkImage> image = DecodeImage(std::move(buffer));
  Threads::UI()->PostTask(
      ftl::MakeCopyable([ callback = std::move(callback), image ]() mutable {
        InvokeImageCallback(image, std::move(callback));
      }));
}

void DecodeImageFromList(Dart_NativeArguments args) {
  Dart_Handle exception = nullptr;

  tonic::Uint8List list =
      tonic::DartConverter<tonic::Uint8List>::FromArguments(args, 0, exception);
  if (exception) {
    Dart_ThrowException(exception);
    return;
  }

  Dart_Handle callback_handle = Dart_GetNativeArgument(args, 1);
  if (!Dart_IsClosure(callback_handle)) {
    Dart_ThrowException(ToDart("Callback must be a function"));
    return;
  }

  auto buffer = SkData::MakeWithCopy(list.data(), list.num_elements());

  Threads::IO()->PostTask(ftl::MakeCopyable([
    callback = std::make_unique<DartPersistentValue>(
        tonic::DartState::Current(), callback_handle),
    buffer = std::move(buffer)
  ]() mutable {
    DecodeImageAndInvokeImageCallback(std::move(callback), std::move(buffer));
  }));
}

}  // namespace

void ImageDecoding::RegisterNatives(tonic::DartLibraryNatives* natives) {
  natives->Register({
      {"decodeImageFromList", DecodeImageFromList, 2, true},
  });
}

}  // namespace blink
<commit_msg>Include build_config (for OS_ANDROID) in image_decoding.cc (#3537)<commit_after>// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "flutter/lib/ui/painting/image_decoding.h"

#include "flutter/common/threads.h"
#include "flutter/glue/trace_event.h"
#include "flutter/lib/ui/painting/image.h"
#include "flutter/lib/ui/painting/resource_context.h"
#include "lib/ftl/build_config.h"
#include "lib/ftl/functional/make_copyable.h"
#include "lib/tonic/dart_persistent_value.h"
#include "lib/tonic/dart_state.h"
#include "lib/tonic/logging/dart_invoke.h"
#include "lib/tonic/typed_data/uint8_list.h"
#include "third_party/skia/include/core/SkImageGenerator.h"

#ifdef OS_ANDROID
#include <GLES2/gl2.h>
#endif

using tonic::DartInvoke;
using tonic::DartPersistentValue;
using tonic::ToDart;

namespace blink {
namespace {

sk_sp<SkImage> DecodeImage(sk_sp<SkData> buffer) {
  TRACE_EVENT0("blink", "DecodeImage");

  if (buffer == nullptr || buffer->isEmpty()) {
    return nullptr;
  }

  auto raster_image = SkImage::MakeFromEncoded(std::move(buffer));

  if (raster_image == nullptr) {
    return nullptr;
  }

  if (auto context = ResourceContext::Get()) {
    // TODO: Supply actual destination color space once available
    if (auto texture_image =
            raster_image->makeTextureImage(context, nullptr)) {
#ifdef OS_ANDROID
      glFlush();
#endif
      return texture_image;
    }
  }

  return raster_image;
}

void InvokeImageCallback(sk_sp<SkImage> image,
                         std::unique_ptr<DartPersistentValue> callback) {
  tonic::DartState* dart_state = callback->dart_state().get();
  if (!dart_state)
    return;
  tonic::DartState::Scope scope(dart_state);
  if (!image) {
    DartInvoke(callback->value(), {Dart_Null()});
  } else {
    ftl::RefPtr<CanvasImage> resultImage = CanvasImage::Create();
    resultImage->set_image(std::move(image));
    DartInvoke(callback->value(), {ToDart(resultImage)});
  }
}

void DecodeImageAndInvokeImageCallback(
    std::unique_ptr<DartPersistentValue> callback,
    sk_sp<SkData> buffer) {
  sk_sp<SkImage> image = DecodeImage(std::move(buffer));
  Threads::UI()->PostTask(
      ftl::MakeCopyable([ callback = std::move(callback), image ]() mutable {
        InvokeImageCallback(image, std::move(callback));
      }));
}

void DecodeImageFromList(Dart_NativeArguments args) {
  Dart_Handle exception = nullptr;

  tonic::Uint8List list =
      tonic::DartConverter<tonic::Uint8List>::FromArguments(args, 0, exception);
  if (exception) {
    Dart_ThrowException(exception);
    return;
  }

  Dart_Handle callback_handle = Dart_GetNativeArgument(args, 1);
  if (!Dart_IsClosure(callback_handle)) {
    Dart_ThrowException(ToDart("Callback must be a function"));
    return;
  }

  auto buffer = SkData::MakeWithCopy(list.data(), list.num_elements());

  Threads::IO()->PostTask(ftl::MakeCopyable([
    callback = std::make_unique<DartPersistentValue>(
        tonic::DartState::Current(), callback_handle),
    buffer = std::move(buffer)
  ]() mutable {
    DecodeImageAndInvokeImageCallback(std::move(callback), std::move(buffer));
  }));
}

}  // namespace

void ImageDecoding::RegisterNatives(tonic::DartLibraryNatives* natives) {
  natives->Register({
      {"decodeImageFromList", DecodeImageFromList, 2, true},
  });
}

}  // namespace blink
<|endoftext|>


<commit_before>#include "mbed.h"
#include "QEI.h"

Ticker pen_control;
AnalogIn potentio(PA_0);
DigitalIn sw(USER_BUTTON);
DigitalOut led(LED1);
PwmOut maxon_r(PB_3);
PwmOut maxon_l(PB_4);
PwmOut maxon_sd(PB_5);

const float pi = 3.1415926535f;
const float sampling_time = 0.01f; //10ms
const float adv_to_rad = 2.0f * pi * (333.0f / 360.0f) * (1.0f / 4096.0f);

float target_theta = pi;

float x0 = 0.f;
float theta0 = 0.f;
float thetai = 0.f;

float kp = 30.0;
float ki = 0.5;
float kd = 0.5;

void pen_control_handler()
{
    int adv = potentio.read_u16() >> 4; //stm32f401 adv: 12bit
    float theta = target_theta - adv * adv_to_rad;
    float dtheta = (theta - theta0) / sampling_time;
    theta0 = theta;
    thetai += theta * sampling_time;
    printf("theta: %lf\t\t", theta * 180.0f / pi);

    if(thetai > 10000.0f){
        thetai = 10000.0f;
    }
    else if(thetai < -10000.0f){
        thetai = -10000.0f;
    }

    float duty_ratio = theta * kp + thetai * ki + dtheta * kd;
    printf("dr: %3lf\t", duty_ratio);

    if(duty_ratio > 0.3f){
        duty_ratio = 0.3f;
    }
    else if(duty_ratio < -0.3f){
        duty_ratio = -0.3f;
    }

    printf("(%lf)\r\n", duty_ratio);

    if(duty_ratio >= 0.0f){
        maxon_r = duty_ratio;
        maxon_l = 0.0f;
    }
    else{
        maxon_r = 0.0f;
        maxon_l = -duty_ratio;
    }
}

int main()
{
    led = 1;

    sw.mode(PullUp);

    maxon_r.period_us(100);
    maxon_l.period_us(100);
    maxon_sd = 1.0f;
    maxon_r = 0.0f;
    maxon_l = 0.0f;

    printf("\r\nwaiting start signal...\r\n");

    while(sw){
        led = led ^ 1;
        wait(1.0f);
    }

    target_theta = (potentio.read_u16() >> 4) * adv_to_rad;
    printf("target_theta: %lf\r\n", target_theta * 180.0f / pi);

    wait(1.0f);

    pen_control.attach(&pen_control_handler, sampling_time);

    while(1){
        wait(1.0f);
    }
}

<commit_msg>updated main_pid.cpp<commit_after>#include "mbed.h"
#include "QEI.h"

Serial pc(USBTX, USBRX);
Ticker pen_control;
AnalogIn potentio(PA_0);
DigitalIn sw(USER_BUTTON);
DigitalOut led(LED1);
DigitalOut maxon_sd(PB_5);
PwmOut maxon_l(PB_3);
PwmOut maxon_r(PB_4);

const float pi = 3.1415926535f;
const float sampling_time = 0.01f; //10ms
const float adv_to_rad = 2.0f * pi * (333.3f / 360.0f) * (1.0f / 4096.0f);

float target_theta = 269.6f / 180.0f * pi;

float theta0 = 0.0f;
float thetai = 0.0f;

float theta_lpf = 0.0f;
float lpf_gain = 0.3f;

float kp = 0.0f;
float ki = 0.0f;
float kd = 0.0f;

float low_pass_filter(float val, float pre_val, float gamma)
{
    return gamma * pre_val + (1.0f - gamma) * val;
}

void pen_control_handler()
{
    int adv = potentio.read_u16() >> 4; //stm32f401 adv: 12bit
    float theta = low_pass_filter((float)(adv * adv_to_rad), theta_lpf, lpf_gain);
    theta_lpf = theta;

    theta = target_theta - theta;
    float dtheta = (theta - theta0) / sampling_time;
    theta0 = theta;
    thetai += theta * sampling_time;
    //printf("theta: %lf\t\t", theta * 180.0f / pi);

    if(thetai > 10000.0f){
        thetai = 10000.0f;
    }
    else if(thetai < -10000.0f){
        thetai = -10000.0f;
    }

    float duty_ratio = theta * kp + thetai * ki + dtheta * kd;
    //printf("dr: %3lf\t", duty_ratio);

    if(duty_ratio > 0.2f){
        duty_ratio = 0.2f;
    }
    else if(duty_ratio < -0.2f){
        duty_ratio = -0.2f;
    }

    //printf("(%lf)\r\n", duty_ratio);

    if(fabs(theta * 180.0f / pi) > 45){
        maxon_r = 0.0f;
        maxon_l = 0.0f;
        return;
    }

    if(duty_ratio >= 0.0f){
        maxon_r = duty_ratio;
        maxon_l = 0.0f;
    }
    else{
        maxon_r = 0.0f;
        maxon_l = -duty_ratio;
    }
}

int main()
{
    led = 1;

    sw.mode(PullUp);

    maxon_sd = 1;
    maxon_r.period_us(100);
    maxon_l.period_us(100);
    maxon_r = 0.0f;
    maxon_l = 0.0f;

    printf("\r\nwaiting start signal...\r\n");

    while(sw){
        led = led ^ 1;
        wait(1.0f);
    }

#if 1
    target_theta = (potentio.read_u16() >> 4) * adv_to_rad;
    printf("target_theta: %lf\r\n", target_theta * 180.0f / pi);
#endif

    wait(1.0f);

    pen_control.attach(&pen_control_handler, sampling_time);

    while(1){
        while(pc.readable()){
            char buf = pc.getc();
            switch(buf){
                case 'q':
                    kp += 0.05f;
                    printf("kp: %lf\tki: %lf\tkd: %lf\r\n", kp, ki, kd);
                    break;
                case 'a':
                    kp -= 0.05f;
                    printf("kp: %lf\tki: %lf\tkd: %lf\r\n", kp, ki, kd);
                    break;
                case 'w':
                    ki += 0.0005f;
                    printf("kp: %lf\tki: %lf\tkd: %lf\r\n", kp, ki, kd);
                    break;
                case 's':
                    ki -= 0.0005f;
                    printf("kp: %lf\tki: %lf\tkd: %lf\r\n", kp, ki, kd);
                    break;
                case 'e':
                    kd += 0.0005f;
                    printf("kp: %lf\tki: %lf\tkd: %lf\r\n", kp, ki, kd);
                    break;
                case 'd':
                    kd -= 0.0005f;
                    printf("kp: %lf\tki: %lf\tkd: %lf\r\n", kp, ki, kd);
                    break;
                case 'r':
                    target_theta += 0.001f;
                    printf("target_theta: %lf\r\n", target_theta * 180.0f / pi);
                    break;
                case 'f':
                    target_theta -= 0.001f;
                    printf("target_theta: %lf\r\n", target_theta * 180.0f / pi);
                    break;
                case 't':
                    lpf_gain += 0.1f;
                    if(lpf_gain > 1){
                        lpf_gain = 1.0f;
                    }
                    printf("lpf_gain: %lf\r\n", lpf_gain);
                    break;
                case 'g':
                    lpf_gain -= 0.1f;
                    if(lpf_gain < 0){
                        lpf_gain = 0.0f;
                    }
                    printf("lpf_gain: %lf\r\n", lpf_gain);
                    break;
            }
        }
        wait(0.5f);
    }
}

<|endoftext|>


<commit_before>
#include "plaintextedit.h"
#include "state.h"

// ---------------------------------------------------------------------
PlainTextEdit::PlainTextEdit(QWidget *parent) : QPlainTextEdit(parent)
{
#ifdef QT_OS_ANDROID
  setStyleSheet(scrollbarstyle(config.ScrollBarSize*DM_density));
#endif
  setSizePolicy (QSizePolicy::Expanding, QSizePolicy::Expanding);
  acceptKeyBack=false;
}

// ---------------------------------------------------------------------
void PlainTextEdit::keyReleaseEvent(QKeyEvent *event)
{
#ifdef QT_OS_ANDROID
  if ((event->key()==Qt::Key_Back) && (!acceptKeyBack)) {
    QPlainTextEdit::keyReleaseEvent(event);
    event->ignore();
    return;
  } else QPlainTextEdit::keyReleaseEvent(event);
#else
  QPlainTextEdit::keyReleaseEvent(event);
#endif
}
<commit_msg>Revert "plaintextedit resize"<commit_after>
#include "plaintextedit.h"
#include "state.h"

// ---------------------------------------------------------------------
PlainTextEdit::PlainTextEdit(QWidget *parent) : QPlainTextEdit(parent)
{
#ifdef QT_OS_ANDROID
  setStyleSheet(scrollbarstyle(config.ScrollBarSize*DM_density));
#endif
  acceptKeyBack=false;
}

// ---------------------------------------------------------------------
void PlainTextEdit::keyReleaseEvent(QKeyEvent *event)
{
#ifdef QT_OS_ANDROID
  if ((event->key()==Qt::Key_Back) && (!acceptKeyBack)) {
    QPlainTextEdit::keyReleaseEvent(event);
    event->ignore();
    return;
  } else QPlainTextEdit::keyReleaseEvent(event);
#else
  QPlainTextEdit::keyReleaseEvent(event);
#endif
}
<|endoftext|>


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

#include <gtest/gtest.h>
#include "actionspace/ObjectOrientedActionSpace.hpp"
#include "utils/utils.hpp"

class OOActionSpaceFixture: public ::testing::Test {
 public:
    OOActionSpaceFixture() : \
         m_actionspace(
            libcozmo::utils::linspace(0.0, 5.0, 3.0),
            std::vector<double>{4.0, 1.1},
            Eigen::Vector2d(6.0, 3.1),
            Eigen::Vector2d(5.0, 2.1),
            5) {}

    aikido::statespace::SE2::State create_object_state() {
        Eigen::Isometry2d transform(Eigen::Isometry2d::Identity());
        transform.linear() = Eigen::Rotation2Dd(M_PI/4).matrix();
        transform.translation() = Eigen::Vector2d(15, 15);
        aikido::statespace::SE2::State state;
        state.setIsometry(transform);
        return state;
    }

    libcozmo::actionspace::ObjectOrientedActionSpace m_actionspace;
    aikido::statespace::SE2::State object_state;

};

/// Check that correct amount of actions were generated
/// 4 sides, 5 edge offset, 3 speed --> 60 actions total
TEST_F(OOActionSpaceFixture, ActionSpaceSizeTest) {
    EXPECT_EQ(60, m_actionspace.size());
}

/// Check that valid/invalid IDs are handled correctly
TEST_F(OOActionSpaceFixture, IsValidActionIDTest) {
    EXPECT_FALSE(m_actionspace.is_valid_action_id(-1));
    EXPECT_TRUE(m_actionspace.is_valid_action_id(10));
}

TEST_F(OOActionSpaceFixture, ActionSimilarityTest) {
    double similarity;
    bool result = m_actionspace.action_similarity(0, 4, &similarity);
    ASSERT_TRUE(result);
    EXPECT_NEAR(2.549, similarity, 0.001);

    result = m_actionspace.action_similarity(72, 1, &similarity);
    ASSERT_FALSE(result);
}

/// Check that actions on opposite sides of the object have the same speed and
/// aspect ratio but opposite edge offsets and heading offsets that differ by pi
TEST_F(OOActionSpaceFixture, UniqueActionTest) {
    for (int i = 0; i < m_actionspace.size()/2; ++i) {
        const auto action1 =
            static_cast<
                libcozmo::actionspace::
                    ObjectOrientedActionSpace::Action*>(
                    m_actionspace.get_action(i));
        const auto action2 =
            static_cast<
                libcozmo::actionspace::
                    ObjectOrientedActionSpace::Action*>(
                    m_actionspace.get_action(i + m_actionspace.size()/2));

        EXPECT_EQ(action1->speed(), action2->speed());
        EXPECT_EQ(action1->aspect_ratio(), action2->aspect_ratio());
        EXPECT_EQ(action1->edge_offset(), -1*action2->edge_offset());
        EXPECT_EQ(action1->heading_offset(), action2->heading_offset() - M_PI);
    }
}

TEST_F(OOActionSpaceFixture, ActionGenerationTest) {
    // Tests a valid action
    libcozmo::actionspace::ObjectOrientedActionSpace::Action* action =
        static_cast<
            libcozmo::actionspace::ObjectOrientedActionSpace::Action*>(
            m_actionspace.get_action(4));
    EXPECT_EQ(2.5, action->speed());
    EXPECT_NEAR(0, action->heading_offset(), 0.001);
    EXPECT_EQ(-0.5, action->edge_offset());
    EXPECT_NEAR(1.1, action->aspect_ratio(), 0.01);

    // Tests nullptr action
    action = static_cast<
        libcozmo::actionspace::ObjectOrientedActionSpace::Action*>(
        m_actionspace.get_action(-1));
    EXPECT_TRUE(action == nullptr);
}

TEST_F(OOActionSpaceFixture, GetObjectOrientedActionTest) {
    libcozmo::actionspace::ObjectOrientedActionSpace::CozmoAction
        action(0.0, Eigen::Vector3d(0, 0, 0));
    m_actionspace.get_generic_to_object_oriented_action(
        4,
        object_state,
        &action);
    EXPECT_NEAR(action.start_pose().x(), 8.989592, 0.001);
    EXPECT_NEAR(action.start_pose().y(), 8.989592, 0.001);
    EXPECT_NEAR(action.start_pose().z(), M_PI/4, 0.001);

    m_actionspace.get_generic_to_object_oriented_action(
        40,
        object_state,
        &action);
    EXPECT_NEAR(action.start_pose().x(), 12.52512, 0.001);
    EXPECT_NEAR(action.start_pose().y(), 12.52512, 0.001);
    EXPECT_NEAR(action.start_pose().z(), M_PI + M_PI/4, 0.001);
}

TEST_F(OOActionSpaceFixture, ActionVectorTest) {
    // Tests action vector generation for Generic Action
    libcozmo::actionspace::ObjectOrientedActionSpace::Action* action =
        static_cast<
            libcozmo::actionspace::ObjectOrientedActionSpace::Action*>(
            m_actionspace.get_action(4));
    Eigen::VectorXd action_vector = action->vector();
    EXPECT_NEAR(2.5, action_vector[0], 0.00001);
    EXPECT_NEAR(1.1, action_vector[1], 0.00001);
    EXPECT_NEAR(-0.5, action_vector[2], 0.00001);
    EXPECT_NEAR(0, action_vector[3], 0.00001);
}

TEST_F(OOActionSpaceFixture, CozmoActionVectorTest) {
    // Tests action vector generation for OOAction
    libcozmo::actionspace::ObjectOrientedActionSpace::
        CozmoAction action(3.0, Eigen::Vector3d{1, 2, 3});
    Eigen::VectorXd action_vector = action.vector();
    EXPECT_NEAR(3.0, action_vector[0], 0.00001);
    EXPECT_NEAR(1, action_vector[1], 0.00001);
    EXPECT_NEAR(2, action_vector[2], 0.00001);
    EXPECT_NEAR(3, action_vector[3], 0.00001);
}

int main(int argc, char **argv) {
    testing::InitGoogleTest(&argc, argv);
    int ret = RUN_ALL_TESTS();
    return ret;
}
<commit_msg>accidentally removed object state creation, all working now<commit_after>////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2019, Brian Lee, Eric Pan, Vinitha Ranganeni
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
//     1. Redistributions of source code must retain the above copyright notice
//        this list of conditions and the following disclaimer.
//     2. Redistributions in binary form must reproduce the above copyright
//        notice, this list of conditions and the following disclaimer in the
//        documentation and/or other materials provided with the distribution.
//     3. Neither the name of the copyright holder nor the names of its
//        contributors may be used to endorse or promote products derived from
//        this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
////////////////////////////////////////////////////////////////////////////////

#include <gtest/gtest.h>
#include "actionspace/ObjectOrientedActionSpace.hpp"
#include "utils/utils.hpp"

class OOActionSpaceFixture: public ::testing::Test {
 public:
    OOActionSpaceFixture() : \
         m_actionspace(
            libcozmo::utils::linspace(0.0, 5.0, 3.0),
            std::vector<double>{4.0, 1.1},
            Eigen::Vector2d(6.0, 3.1),
            Eigen::Vector2d(5.0, 2.1),
            5) {
            object_state = create_object_state();
            }

    aikido::statespace::SE2::State create_object_state() {
        Eigen::Isometry2d transform(Eigen::Isometry2d::Identity());
        transform.linear() = Eigen::Rotation2Dd(M_PI/4).matrix();
        transform.translation() = Eigen::Vector2d(15, 15);
        aikido::statespace::SE2::State state;
        state.setIsometry(transform);
        return state;
    }

    libcozmo::actionspace::ObjectOrientedActionSpace m_actionspace;
    aikido::statespace::SE2::State object_state;

};

/// Check that correct amount of actions were generated
/// 4 sides, 5 edge offset, 3 speed --> 60 actions total
TEST_F(OOActionSpaceFixture, ActionSpaceSizeTest) {
    EXPECT_EQ(60, m_actionspace.size());
}

/// Check that valid/invalid IDs are handled correctly
TEST_F(OOActionSpaceFixture, IsValidActionIDTest) {
    EXPECT_FALSE(m_actionspace.is_valid_action_id(-1));
    EXPECT_TRUE(m_actionspace.is_valid_action_id(10));
}

TEST_F(OOActionSpaceFixture, ActionSimilarityTest) {
    double similarity;
    bool result = m_actionspace.action_similarity(0, 4, &similarity);
    ASSERT_TRUE(result);
    EXPECT_NEAR(2.549, similarity, 0.001);

    result = m_actionspace.action_similarity(72, 1, &similarity);
    ASSERT_FALSE(result);
}

/// Check that actions on opposite sides of the object have the same speed and
/// aspect ratio but opposite edge offsets and heading offsets that differ by pi
TEST_F(OOActionSpaceFixture, UniqueActionTest) {
    for (int i = 0; i < m_actionspace.size()/2; ++i) {
        const auto action1 =
            static_cast<
                libcozmo::actionspace::
                    ObjectOrientedActionSpace::Action*>(
                    m_actionspace.get_action(i));
        const auto action2 =
            static_cast<
                libcozmo::actionspace::
                    ObjectOrientedActionSpace::Action*>(
                    m_actionspace.get_action(i + m_actionspace.size()/2));

        EXPECT_EQ(action1->speed(), action2->speed());
        EXPECT_EQ(action1->aspect_ratio(), action2->aspect_ratio());
        EXPECT_EQ(action1->edge_offset(), -1*action2->edge_offset());
        EXPECT_EQ(action1->heading_offset(), action2->heading_offset() - M_PI);
    }
}

TEST_F(OOActionSpaceFixture, ActionGenerationTest) {
    // Tests a valid action
    libcozmo::actionspace::ObjectOrientedActionSpace::Action* action =
        static_cast<
            libcozmo::actionspace::ObjectOrientedActionSpace::Action*>(
            m_actionspace.get_action(4));
    EXPECT_EQ(2.5, action->speed());
    EXPECT_NEAR(0, action->heading_offset(), 0.001);
    EXPECT_EQ(-0.5, action->edge_offset());
    EXPECT_NEAR(1.1, action->aspect_ratio(), 0.01);

    // Tests nullptr action
    action = static_cast<
        libcozmo::actionspace::ObjectOrientedActionSpace::Action*>(
        m_actionspace.get_action(-1));
    EXPECT_TRUE(action == nullptr);
}

TEST_F(OOActionSpaceFixture, GetObjectOrientedActionTest) {
    libcozmo::actionspace::ObjectOrientedActionSpace::CozmoAction
        action(0.0, Eigen::Vector3d(0, 0, 0));
    m_actionspace.get_generic_to_object_oriented_action(
        4,
        object_state,
        &action);
    EXPECT_NEAR(action.start_pose().x(), 8.989592, 0.001);
    EXPECT_NEAR(action.start_pose().y(), 8.989592, 0.001);
    EXPECT_NEAR(action.start_pose().z(), M_PI/4, 0.001);

    m_actionspace.get_generic_to_object_oriented_action(
        40,
        object_state,
        &action);
    EXPECT_NEAR(action.start_pose().x(), 12.52512, 0.001);
    EXPECT_NEAR(action.start_pose().y(), 12.52512, 0.001);
    EXPECT_NEAR(action.start_pose().z(), M_PI + M_PI/4, 0.001);
}

TEST_F(OOActionSpaceFixture, ActionVectorTest) {
    // Tests action vector generation for Generic Action
    libcozmo::actionspace::ObjectOrientedActionSpace::Action* action =
        static_cast<
            libcozmo::actionspace::ObjectOrientedActionSpace::Action*>(
            m_actionspace.get_action(4));
    Eigen::VectorXd action_vector = action->vector();
    EXPECT_NEAR(2.5, action_vector[0], 0.00001);
    EXPECT_NEAR(1.1, action_vector[1], 0.00001);
    EXPECT_NEAR(-0.5, action_vector[2], 0.00001);
    EXPECT_NEAR(0, action_vector[3], 0.00001);
}

TEST_F(OOActionSpaceFixture, CozmoActionVectorTest) {
    // Tests action vector generation for OOAction
    libcozmo::actionspace::ObjectOrientedActionSpace::
        CozmoAction action(3.0, Eigen::Vector3d{1, 2, 3});
    Eigen::VectorXd action_vector = action.vector();
    EXPECT_NEAR(3.0, action_vector[0], 0.00001);
    EXPECT_NEAR(1, action_vector[1], 0.00001);
    EXPECT_NEAR(2, action_vector[2], 0.00001);
    EXPECT_NEAR(3, action_vector[3], 0.00001);
}

int main(int argc, char **argv) {
    testing::InitGoogleTest(&argc, argv);
    int ret = RUN_ALL_TESTS();
    return ret;
}
<|endoftext|>


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

#include "trafficgraphwidget.h"
#include "clientmodel.h"

#include <QPainter>
#include <QColor>
#include <QTimer>

#include <cmath>

#define DESIRED_SAMPLES         800

#define XMARGIN                 10
#define YMARGIN                 10

TrafficGraphWidget::TrafficGraphWidget(QWidget *parent) :
    QWidget(parent),
    timer(0),
    fMax(0.0f),
    nMins(0),
    vSamplesIn(),
    vSamplesOut(),
    nLastBytesIn(0),
    nLastBytesOut(0),
    clientModel(0)
{
    timer = new QTimer(this);
    connect(timer, SIGNAL(timeout()), SLOT(updateRates()));
}

void TrafficGraphWidget::setClientModel(ClientModel *model)
{
    clientModel = model;
    if(model) {
        nLastBytesIn = model->getTotalBytesRecv();
        nLastBytesOut = model->getTotalBytesSent();
    }
}

int TrafficGraphWidget::getGraphRangeMins() const
{
    return nMins;
}

void TrafficGraphWidget::paintPath(QPainterPath &path, QQueue<float> &samples)
{
    int h = height() - YMARGIN * 2, w = width() - XMARGIN * 2;
    int sampleCount = samples.size(), x = XMARGIN + w, y;
    if(sampleCount > 0) {
        path.moveTo(x, YMARGIN + h);
        for(int i = 0; i < sampleCount; ++i) {
            x = XMARGIN + w - w * i / DESIRED_SAMPLES;
            y = YMARGIN + h - (int)(h * samples.at(i) / fMax);
            path.lineTo(x, y);
        }
        path.lineTo(x, YMARGIN + h);
    }
}

void TrafficGraphWidget::paintEvent(QPaintEvent *)
{
    QPainter painter(this);
    painter.fillRect(rect(), Qt::black);

    if(fMax <= 0.0f) return;

    QColor axisCol(Qt::gray);
    int h = height() - YMARGIN * 2;
    painter.setPen(axisCol);
    painter.drawLine(XMARGIN, YMARGIN + h, width() - XMARGIN, YMARGIN + h);

    // decide what order of magnitude we are
    int base = floor(log10(fMax));
    float val = pow(10.0f, base);

    const QString units     = tr("KB/s");
    const float yMarginText = 2.0;

    // draw lines
    painter.setPen(axisCol);
    painter.drawText(XMARGIN, YMARGIN + h - h * val / fMax-yMarginText, QString("%1 %2").arg(val).arg(units));
    for(float y = val; y < fMax; y += val) {
        int yy = YMARGIN + h - h * y / fMax;
        painter.drawLine(XMARGIN, yy, width() - XMARGIN, yy);
    }
    // if we drew 3 or fewer lines, break them up at the next lower order of magnitude
    if(fMax / val <= 3.0f) {
        axisCol = axisCol.darker();
        val = pow(10.0f, base - 1);
        painter.setPen(axisCol);
        painter.drawText(XMARGIN, YMARGIN + h - h * val / fMax-yMarginText, QString("%1 %2").arg(val).arg(units));
        int count = 1;
        for(float y = val; y < fMax; y += val, count++) {
            // don't overwrite lines drawn above
            if(count % 10 == 0)
                continue;
            int yy = YMARGIN + h - h * y / fMax;
            painter.drawLine(XMARGIN, yy, width() - XMARGIN, yy);
        }
    }

    if(!vSamplesIn.empty()) {
        QPainterPath p;
        paintPath(p, vSamplesIn);
        painter.fillPath(p, QColor(0, 255, 0, 128));
        painter.setPen(Qt::green);
        painter.drawPath(p);
    }
    if(!vSamplesOut.empty()) {
        QPainterPath p;
        paintPath(p, vSamplesOut);
        painter.fillPath(p, QColor(255, 0, 0, 128));
        painter.setPen(Qt::red);
        painter.drawPath(p);
    }
}

void TrafficGraphWidget::updateRates()
{
    if(!clientModel) return;

    quint64 bytesIn = clientModel->getTotalBytesRecv(),
            bytesOut = clientModel->getTotalBytesSent();
    float inRate = (bytesIn - nLastBytesIn) / 1024.0f * 1000 / timer->interval();
    float outRate = (bytesOut - nLastBytesOut) / 1024.0f * 1000 / timer->interval();
    vSamplesIn.push_front(inRate);
    vSamplesOut.push_front(outRate);
    nLastBytesIn = bytesIn;
    nLastBytesOut = bytesOut;

    while(vSamplesIn.size() > DESIRED_SAMPLES) {
        vSamplesIn.pop_back();
    }
    while(vSamplesOut.size() > DESIRED_SAMPLES) {
        vSamplesOut.pop_back();
    }

    float tmax = 0.0f;
    foreach(float f, vSamplesIn) {
        if(f > tmax) tmax = f;
    }
    foreach(float f, vSamplesOut) {
        if(f > tmax) tmax = f;
    }
    fMax = tmax;
    update();
}

void TrafficGraphWidget::setGraphRangeMins(int mins)
{
    nMins = mins;
    int msecsPerSample = nMins * 60 * 1000 / DESIRED_SAMPLES;
    timer->stop();
    timer->setInterval(msecsPerSample);

    clear();
}

void TrafficGraphWidget::clear()
{
    timer->stop();

    vSamplesOut.clear();
    vSamplesIn.clear();
    fMax = 0.0f;

    if(clientModel) {
        nLastBytesIn = clientModel->getTotalBytesRecv();
        nLastBytesOut = clientModel->getTotalBytesSent();
    }
    timer->start();
}
<commit_msg>Fix https://github.com/bitcoin/bitcoin/issues/19510<commit_after>// Copyright (c) 2011-2013 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "trafficgraphwidget.h"
#include "clientmodel.h"

#include <QPainter>
#include <QPainterPath>
#include <QColor>
#include <QTimer>

#include <cmath>

#define DESIRED_SAMPLES         800

#define XMARGIN                 10
#define YMARGIN                 10

TrafficGraphWidget::TrafficGraphWidget(QWidget *parent) :
    QWidget(parent),
    timer(0),
    fMax(0.0f),
    nMins(0),
    vSamplesIn(),
    vSamplesOut(),
    nLastBytesIn(0),
    nLastBytesOut(0),
    clientModel(0)
{
    timer = new QTimer(this);
    connect(timer, SIGNAL(timeout()), SLOT(updateRates()));
}

void TrafficGraphWidget::setClientModel(ClientModel *model)
{
    clientModel = model;
    if(model) {
        nLastBytesIn = model->getTotalBytesRecv();
        nLastBytesOut = model->getTotalBytesSent();
    }
}

int TrafficGraphWidget::getGraphRangeMins() const
{
    return nMins;
}

void TrafficGraphWidget::paintPath(QPainterPath &path, QQueue<float> &samples)
{
    int h = height() - YMARGIN * 2, w = width() - XMARGIN * 2;
    int sampleCount = samples.size(), x = XMARGIN + w, y;
    if(sampleCount > 0) {
        path.moveTo(x, YMARGIN + h);
        for(int i = 0; i < sampleCount; ++i) {
            x = XMARGIN + w - w * i / DESIRED_SAMPLES;
            y = YMARGIN + h - (int)(h * samples.at(i) / fMax);
            path.lineTo(x, y);
        }
        path.lineTo(x, YMARGIN + h);
    }
}

void TrafficGraphWidget::paintEvent(QPaintEvent *)
{
    QPainter painter(this);
    painter.fillRect(rect(), Qt::black);

    if(fMax <= 0.0f) return;

    QColor axisCol(Qt::gray);
    int h = height() - YMARGIN * 2;
    painter.setPen(axisCol);
    painter.drawLine(XMARGIN, YMARGIN + h, width() - XMARGIN, YMARGIN + h);

    // decide what order of magnitude we are
    int base = floor(log10(fMax));
    float val = pow(10.0f, base);

    const QString units     = tr("KB/s");
    const float yMarginText = 2.0;

    // draw lines
    painter.setPen(axisCol);
    painter.drawText(XMARGIN, YMARGIN + h - h * val / fMax-yMarginText, QString("%1 %2").arg(val).arg(units));
    for(float y = val; y < fMax; y += val) {
        int yy = YMARGIN + h - h * y / fMax;
        painter.drawLine(XMARGIN, yy, width() - XMARGIN, yy);
    }
    // if we drew 3 or fewer lines, break them up at the next lower order of magnitude
    if(fMax / val <= 3.0f) {
        axisCol = axisCol.darker();
        val = pow(10.0f, base - 1);
        painter.setPen(axisCol);
        painter.drawText(XMARGIN, YMARGIN + h - h * val / fMax-yMarginText, QString("%1 %2").arg(val).arg(units));
        int count = 1;
        for(float y = val; y < fMax; y += val, count++) {
            // don't overwrite lines drawn above
            if(count % 10 == 0)
                continue;
            int yy = YMARGIN + h - h * y / fMax;
            painter.drawLine(XMARGIN, yy, width() - XMARGIN, yy);
        }
    }

    if(!vSamplesIn.empty()) {
        QPainterPath p;
        paintPath(p, vSamplesIn);
        painter.fillPath(p, QColor(0, 255, 0, 128));
        painter.setPen(Qt::green);
        painter.drawPath(p);
    }
    if(!vSamplesOut.empty()) {
        QPainterPath p;
        paintPath(p, vSamplesOut);
        painter.fillPath(p, QColor(255, 0, 0, 128));
        painter.setPen(Qt::red);
        painter.drawPath(p);
    }
}

void TrafficGraphWidget::updateRates()
{
    if(!clientModel) return;

    quint64 bytesIn = clientModel->getTotalBytesRecv(),
            bytesOut = clientModel->getTotalBytesSent();
    float inRate = (bytesIn - nLastBytesIn) / 1024.0f * 1000 / timer->interval();
    float outRate = (bytesOut - nLastBytesOut) / 1024.0f * 1000 / timer->interval();
    vSamplesIn.push_front(inRate);
    vSamplesOut.push_front(outRate);
    nLastBytesIn = bytesIn;
    nLastBytesOut = bytesOut;

    while(vSamplesIn.size() > DESIRED_SAMPLES) {
        vSamplesIn.pop_back();
    }
    while(vSamplesOut.size() > DESIRED_SAMPLES) {
        vSamplesOut.pop_back();
    }

    float tmax = 0.0f;
    foreach(float f, vSamplesIn) {
        if(f > tmax) tmax = f;
    }
    foreach(float f, vSamplesOut) {
        if(f > tmax) tmax = f;
    }
    fMax = tmax;
    update();
}

void TrafficGraphWidget::setGraphRangeMins(int mins)
{
    nMins = mins;
    int msecsPerSample = nMins * 60 * 1000 / DESIRED_SAMPLES;
    timer->stop();
    timer->setInterval(msecsPerSample);

    clear();
}

void TrafficGraphWidget::clear()
{
    timer->stop();

    vSamplesOut.clear();
    vSamplesIn.clear();
    fMax = 0.0f;

    if(clientModel) {
        nLastBytesIn = clientModel->getTotalBytesRecv();
        nLastBytesOut = clientModel->getTotalBytesSent();
    }
    timer->start();
}
<|endoftext|>


<commit_before>#include "translator/scorers.h"
#include "common/io.h"

namespace marian {

Ptr<Scorer> scorerByType(const std::string& fname,
                         float weight,
                         const std::string& model,
                         Ptr<Options> options) {
  options->set("inference", true);
  std::string type = options->get<std::string>("type");

  // @TODO: solve this better
  if(type == "lm" && options->has("input")) {
    size_t index = options->get<std::vector<std::string>>("input").size();
    options->set("index", index);
  }

  bool skipCost = options->get<bool>("skip-cost");
  auto encdec = models::from_options(
      options, skipCost ? models::usage::raw : models::usage::translation);

  LOG(info, "Loading scorer of type {} as feature {}", type, fname);

  return New<ScorerWrapper>(encdec, fname, weight, model);
}

Ptr<Scorer> scorerByType(const std::string& fname,
                         float weight,
                         const void* ptr,
                         Ptr<Options> options) {
  options->set("inference", true);
  std::string type = options->get<std::string>("type");

  // @TODO: solve this better
  if(type == "lm" && options->has("input")) {
    size_t index = options->get<std::vector<std::string>>("input").size();
    options->set("index", index);
  }

  bool skipCost = options->get<bool>("skip-cost");
  auto encdec = models::from_options(
      options, skipCost ? models::usage::raw : models::usage::translation);

  LOG(info, "Loading scorer of type {} as feature {}", type, fname);

  return New<ScorerWrapper>(encdec, fname, weight, ptr);
}

std::vector<Ptr<Scorer>> createScorers(Ptr<Options> options) {
  std::vector<Ptr<Scorer>> scorers;

  auto models = options->get<std::vector<std::string>>("models");

  std::vector<float> weights(models.size(), 1.f);
  if(options->has("weights"))
    weights = options->get<std::vector<float>>("weights");

  size_t i = 0;
  for(auto model : models) {
    std::string fname = "F" + std::to_string(i);

    // load options specific for the scorer
    auto modelOptions = New<Options>(*options);
    try {
      if(!options->get<bool>("ignore-model-config"))
        io::getYamlFromModel(modelOptions->getOptions(), "special::model.yml", model);
    } catch(std::runtime_error&) {
      LOG(warn, "No model settings found in model file");
    }

    scorers.push_back(scorerByType(fname, weights[i], model, modelOptions));
    i++;
  }

  return scorers;
}

std::vector<Ptr<Scorer>> createScorers(Ptr<Options> options, const std::vector<const void*>& ptrs) {
  std::vector<Ptr<Scorer>> scorers;

  std::vector<float> weights(ptrs.size(), 1.f);
  if(options->has("weights"))
    weights = options->get<std::vector<float>>("weights");

  size_t i = 0;
  for(auto ptr : ptrs) {
    std::string fname = "F" + std::to_string(i);

    // load options specific for the scorer
    auto modelOptions = New<Options>(*options);
    try {
      if(!options->get<bool>("ignore-model-config"))
        io::getYamlFromModel(modelOptions->getOptions(), "special::model.yml", ptr);
    } catch(std::runtime_error&) {
      LOG(warn, "No model settings found in model file");
    }

    scorers.push_back(scorerByType(fname, weights[i], ptr, modelOptions));
    i++;
  }

  return scorers;
}

}  // namespace marian
<commit_msg>Fix model::special.yml<commit_after>#include "translator/scorers.h"
#include "common/io.h"

namespace marian {

Ptr<Scorer> scorerByType(const std::string& fname,
                         float weight,
                         const std::string& model,
                         Ptr<Options> options) {
  options->set("inference", true);
  std::string type = options->get<std::string>("type");

  // @TODO: solve this better
  if(type == "lm" && options->has("input")) {
    size_t index = options->get<std::vector<std::string>>("input").size();
    options->set("index", index);
  }

  bool skipCost = options->get<bool>("skip-cost");
  auto encdec = models::from_options(
      options, skipCost ? models::usage::raw : models::usage::translation);

  LOG(info, "Loading scorer of type {} as feature {}", type, fname);

  return New<ScorerWrapper>(encdec, fname, weight, model);
}

Ptr<Scorer> scorerByType(const std::string& fname,
                         float weight,
                         const void* ptr,
                         Ptr<Options> options) {
  options->set("inference", true);
  std::string type = options->get<std::string>("type");

  // @TODO: solve this better
  if(type == "lm" && options->has("input")) {
    size_t index = options->get<std::vector<std::string>>("input").size();
    options->set("index", index);
  }

  bool skipCost = options->get<bool>("skip-cost");
  auto encdec = models::from_options(
      options, skipCost ? models::usage::raw : models::usage::translation);

  LOG(info, "Loading scorer of type {} as feature {}", type, fname);

  return New<ScorerWrapper>(encdec, fname, weight, ptr);
}

std::vector<Ptr<Scorer>> createScorers(Ptr<Options> options) {
  std::vector<Ptr<Scorer>> scorers;

  auto models = options->get<std::vector<std::string>>("models");

  std::vector<float> weights(models.size(), 1.f);
  if(options->has("weights"))
    weights = options->get<std::vector<float>>("weights");

  size_t i = 0;
  for(auto model : models) {
    std::string fname = "F" + std::to_string(i);

    // load options specific for the scorer
    auto modelOptions = New<Options>(*options);
    try {
      if(!options->get<bool>("ignore-model-config"))
        io::getYamlFromModel(modelOptions->getOptions(), "special:model.yml", model);
    } catch(std::runtime_error&) {
      LOG(warn, "No model settings found in model file");
    }

    scorers.push_back(scorerByType(fname, weights[i], model, modelOptions));
    i++;
  }

  return scorers;
}

std::vector<Ptr<Scorer>> createScorers(Ptr<Options> options, const std::vector<const void*>& ptrs) {
  std::vector<Ptr<Scorer>> scorers;

  std::vector<float> weights(ptrs.size(), 1.f);
  if(options->has("weights"))
    weights = options->get<std::vector<float>>("weights");

  size_t i = 0;
  for(auto ptr : ptrs) {
    std::string fname = "F" + std::to_string(i);

    // load options specific for the scorer
    auto modelOptions = New<Options>(*options);
    try {
      if(!options->get<bool>("ignore-model-config"))
        io::getYamlFromModel(modelOptions->getOptions(), "special:model.yml", ptr);
    } catch(std::runtime_error&) {
      LOG(warn, "No model settings found in model file");
    }

    scorers.push_back(scorerByType(fname, weights[i], ptr, modelOptions));
    i++;
  }

  return scorers;
}

}  // namespace marian
<|endoftext|>


<commit_before>/*
    Copyright (c) 2006 Volker Krause <volker.krause@rwth-aachen.de>

    This library is free software; you can redistribute it and/or modify it
    under the terms of the GNU Library General Public License as published by
    the Free Software Foundation; either version 2 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 Library General Public
    License for more details.

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

#include "collection.h"
#include "collectionfetchjob.h"
#include "messagecollection.h"

#include <QTimer>

using namespace PIM;

// ### just for testing, remove as soon as we have a real backend
#define DUMMY_FETCH_JOB
#ifdef DUMMY_FETCH_JOB
#include <QHash>
static Collection* col = 0;
QHash<DataReference, Collection*> global_collection_map;
#endif

PIM::CollectionFetchJob::CollectionFetchJob( const DataReference & ref )
{
#ifdef DUMMY_FETCH_JOB
  if ( global_collection_map.contains( ref ) ) {
    Collection *c = global_collection_map.value( ref );
    if ( dynamic_cast<MessageCollection*>( c ) )
      col = new MessageCollection( *static_cast<MessageCollection*>( c ) );
    else
      col = new Collection( *c );
  } else
    col = 0;
#else
  Q_UNUSED( ref );
#endif
}

PIM::CollectionFetchJob::~CollectionFetchJob()
{
}

Collection * PIM::CollectionFetchJob::collection() const
{
#ifdef DUMMY_FETCH_JOB
  return col;
#else
  return 0;
#endif
}

void PIM::CollectionFetchJob::emitDone()
{
  emit done( this );
}

void PIM::CollectionFetchJob::doStart()
{
  QTimer::singleShot( 0, this, SLOT( emitDone() ) );
}

#include "collectionfetchjob.moc"
<commit_msg>trying to fix crash (CID 1334)<commit_after>/*
    Copyright (c) 2006 Volker Krause <volker.krause@rwth-aachen.de>

    This library is free software; you can redistribute it and/or modify it
    under the terms of the GNU Library General Public License as published by
    the Free Software Foundation; either version 2 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 Library General Public
    License for more details.

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

#include "collection.h"
#include "collectionfetchjob.h"
#include "messagecollection.h"

#include <QTimer>

using namespace PIM;

// ### just for testing, remove as soon as we have a real backend
#define DUMMY_FETCH_JOB
#ifdef DUMMY_FETCH_JOB
#include <QHash>
static Collection* col = 0;
QHash<DataReference, Collection*> global_collection_map;
#endif

PIM::CollectionFetchJob::CollectionFetchJob( const DataReference & ref )
{
#ifdef DUMMY_FETCH_JOB
  if ( global_collection_map.contains( ref ) ) {
    Collection *c = global_collection_map.value( ref );
    if ( dynamic_cast<MessageCollection*>( c ) )
      col = new MessageCollection( *static_cast<MessageCollection*>( c ) );
    else
      // FIXME: dereferencing 0 will always crash. what's intended ????
      col = 0; // new Collection( *c );
  } else
    col = 0;
#else
  Q_UNUSED( ref );
#endif
}

PIM::CollectionFetchJob::~CollectionFetchJob()
{
}

Collection * PIM::CollectionFetchJob::collection() const
{
#ifdef DUMMY_FETCH_JOB
  return col;
#else
  return 0;
#endif
}

void PIM::CollectionFetchJob::emitDone()
{
  emit done( this );
}

void PIM::CollectionFetchJob::doStart()
{
  QTimer::singleShot( 0, this, SLOT( emitDone() ) );
}

#include "collectionfetchjob.moc"
<|endoftext|>