<commit_before>// Copyright 2010-2012 RethinkDB, all rights reserved.
#include "extproc/spawner.hpp"

#include <signal.h>             // sigaction
#include <sys/prctl.h>          // prctl
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/un.h>
#include <sys/wait.h>           // waitpid
#include <unistd.h>             // setpgid

#include "arch/fd_send_recv.hpp"
#include "extproc/job.hpp"
#include "utils.hpp"

namespace extproc {

// Checks that we only create one spawner. This is an ugly restriction, but it
// means we can put the SIGCHLD-handling logic in here, so that it is properly
// scoped to the lifetime of the spawner.
//
// TODO(rntz): More general way of handling SIGCHLD.
static pid_t spawner_pid = -1;

static void sigchld_handler(int signo) {
    guarantee(signo == SIGCHLD);
    guarantee(spawner_pid > 0);

    int status;
    pid_t pid = waitpid(-1, &status, WNOHANG);
    guarantee_err(-1 != pid, "could not waitpid()");

    // We might spawn processes other than the spawner, whose deaths we ignore.
    // waitpid() might also return 0, indicating some event other than child
    // process termination (ie. SIGSTOP or SIGCONT). We ignore this.
    if (pid == spawner_pid) {
        crash_or_trap("Spawner process died!");
    }
}

spawner_t::spawner_t(info_t *info)
    : pid_(info->pid), socket_(&info->socket)
{
    guarantee(-1 == spawner_pid);
    spawner_pid = pid_;

    // Check that the spawner hasn't already exited.
    guarantee(0 == waitpid(pid_, NULL, WNOHANG),
              "spawner process already died!");

    // Establish SIGCHLD handler for spawner.
    struct sigaction act;
    memset(&act, 0, sizeof(act));
    act.sa_handler = sigchld_handler;
    guarantee_err(0 == sigemptyset(&act.sa_mask), "could not empty signal mask");
    guarantee_err(0 == sigaction(SIGCHLD, &act, NULL), "could not set SIGCHLD handler");
}

spawner_t::~spawner_t() {
    // De-establish SIGCHLD handler.
    struct sigaction act;
    memset(&act, 0, sizeof(act));
    act.sa_handler = SIG_DFL;
    guarantee_err(0 == sigemptyset(&act.sa_mask), "could not empty signal mask");
    guarantee_err(0 == sigaction(SIGCHLD, &act, NULL), "could not unset SIGCHLD handler");

    guarantee(spawner_pid > 0);
    spawner_pid = -1;
}

void spawner_t::create(info_t *info) {
    int fds[2];
    guarantee_err(0 == socketpair(AF_UNIX, SOCK_STREAM, 0, fds),
                  "could not create socketpair for spawner");

    pid_t pid = fork();
    guarantee_err(-1 != pid, "could not fork spawner process");

    if (0 == pid) {
        // We're the child; run the spawner.
        guarantee_err(0 == close(fds[0]), "could not close fd");
        exec_spawner(fds[1]);
        unreachable();
    }

    // We're the parent. Return.
    guarantee_err(0 == close(fds[1]), "could not close fd");
    info->pid = pid;
    info->socket.reset(fds[0]);
}

pid_t spawner_t::spawn_process(scoped_fd_t *socket) {
    assert_thread();

    // Create a socket pair.
    fd_t fds[2];
    int res = socketpair(AF_UNIX, SOCK_STREAM, 0, fds);
    if (res) return -1;

    // We need to send the fd & receive the pid atomically with respect to other
    // calls to spawn_process().
    mutex_t::acq_t lock(&mutex_);

    // Send one half to the spawner process.
    guarantee(0 == socket_.send_fd(fds[1]));
    guarantee_err(0 == close(fds[1]), "could not close fd");
    socket->reset(fds[0]);

    // Receive the pid from the spawner process.
    pid_t pid;
    guarantee(sizeof(pid) == force_read(&socket_, &pid, sizeof(pid)));
    guarantee(pid > 0);

    return pid;
}

// ---------- Spawner & worker processes ----------
// Runs the spawner process. Does not return.
void spawner_t::exec_spawner(fd_t socket) {
    // We set our PGID to our own PID (rather than inheriting our parent's PGID)
    // so that a signal (eg. SIGINT) sent to the parent's PGID (by eg. hitting
    // Ctrl-C at a terminal) will not propagate to us or our children.
    //
    // This is desirable because the RethinkDB engine deliberately crashes with
    // an error message if the spawner or a worker process dies; but a
    // command-line SIGINT should trigger a clean shutdown, not a crash.
    //
    // TODO(rntz): This is an ugly, hackish way to handle the problem.
    guarantee_err(0 == setpgid(0, 0), "spawner: could not set PGID");

    // We ignore SIGCHLD so that we don't accumulate zombie children.
    {
        // NB. According to `man 2 sigaction` on linux, POSIX.1-2001 says that
        // this will prevent zombies, but may not be "fully portable".
        struct sigaction act;
        memset(&act, 0, sizeof(act));
        act.sa_handler = SIG_IGN;

        guarantee_err(0 == sigaction(SIGCHLD, &act, NULL),
                      "spawner: Could not ignore SIGCHLD");
    }

    for (;;) {
        // Get an fd from our parent.
        fd_t fd;
        fd_recv_result_t fdres = recv_fds(socket, 1, &fd);
        if (fdres == FD_RECV_EOF) {
            // Other end shut down cleanly; we should too.
            exit(EXIT_SUCCESS);
        } else if (fdres != FD_RECV_OK) {
            exit(EXIT_FAILURE);
        }

        // Fork a worker process.
        pid_t pid = fork();
        if (-1 == pid)
            exit(EXIT_FAILURE);

        if (0 == pid) {
            // We're the child/worker.
            guarantee_err(0 == close(socket), "worker: could not close fd");
            exec_worker(fd);
            unreachable();
        }

        // We're the parent.
        guarantee_err(0 == close(fd), "spawner: couldn't close fd");

        // Send back its pid. Wish we could use unix_socket_stream_t for this,
        // but its destructor calls shutdown(), and we can't have that happening
        // in the worker child.
        const char *buf = reinterpret_cast<const char *>(&pid);
        size_t sz = sizeof(pid);
        while (sz) {
            ssize_t w = write(socket, buf, sz);
            if (w == -1 && errno == EINTR) continue;
            guarantee_err(w > 0, "spawner: could not write() to engine socket");
            guarantee((size_t)w <= sz);
            sz -= w, buf += w;
        }
    }
}

// Runs the worker process. Does not return.
void spawner_t::exec_worker(fd_t sockfd) {
    // Makes sure we get SIGTERMed when our parent (the spawner) dies.
    // TODO(rntz): prctl is linux-specific.
    int res = prctl(PR_SET_PDEATHSIG, SIGTERM);
    guarantee_err(res == 0, "worker: could not set parent-death signal");

    // Receive one job and run it.
    scoped_fd_t fd(sockfd);
    job_t::control_t control(getpid(), &fd);
    exit(job_t::accept_job(&control, NULL));
}

} // namespace extproc
<commit_msg>Commented out prctl function and include.<commit_after>// Copyright 2010-2012 RethinkDB, all rights reserved.
#include "extproc/spawner.hpp"

#include <signal.h>             // sigaction
// TODO(OSX) How are we going to detect parent death?
// #include <sys/prctl.h>          // prctl
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/un.h>
#include <sys/wait.h>           // waitpid
#include <unistd.h>             // setpgid

#include "arch/fd_send_recv.hpp"
#include "extproc/job.hpp"
#include "utils.hpp"

namespace extproc {

// Checks that we only create one spawner. This is an ugly restriction, but it
// means we can put the SIGCHLD-handling logic in here, so that it is properly
// scoped to the lifetime of the spawner.
//
// TODO(rntz): More general way of handling SIGCHLD.
static pid_t spawner_pid = -1;

static void sigchld_handler(int signo) {
    guarantee(signo == SIGCHLD);
    guarantee(spawner_pid > 0);

    int status;
    pid_t pid = waitpid(-1, &status, WNOHANG);
    guarantee_err(-1 != pid, "could not waitpid()");

    // We might spawn processes other than the spawner, whose deaths we ignore.
    // waitpid() might also return 0, indicating some event other than child
    // process termination (ie. SIGSTOP or SIGCONT). We ignore this.
    if (pid == spawner_pid) {
        crash_or_trap("Spawner process died!");
    }
}

spawner_t::spawner_t(info_t *info)
    : pid_(info->pid), socket_(&info->socket)
{
    guarantee(-1 == spawner_pid);
    spawner_pid = pid_;

    // Check that the spawner hasn't already exited.
    guarantee(0 == waitpid(pid_, NULL, WNOHANG),
              "spawner process already died!");

    // Establish SIGCHLD handler for spawner.
    struct sigaction act;
    memset(&act, 0, sizeof(act));
    act.sa_handler = sigchld_handler;
    guarantee_err(0 == sigemptyset(&act.sa_mask), "could not empty signal mask");
    guarantee_err(0 == sigaction(SIGCHLD, &act, NULL), "could not set SIGCHLD handler");
}

spawner_t::~spawner_t() {
    // De-establish SIGCHLD handler.
    struct sigaction act;
    memset(&act, 0, sizeof(act));
    act.sa_handler = SIG_DFL;
    guarantee_err(0 == sigemptyset(&act.sa_mask), "could not empty signal mask");
    guarantee_err(0 == sigaction(SIGCHLD, &act, NULL), "could not unset SIGCHLD handler");

    guarantee(spawner_pid > 0);
    spawner_pid = -1;
}

void spawner_t::create(info_t *info) {
    int fds[2];
    guarantee_err(0 == socketpair(AF_UNIX, SOCK_STREAM, 0, fds),
                  "could not create socketpair for spawner");

    pid_t pid = fork();
    guarantee_err(-1 != pid, "could not fork spawner process");

    if (0 == pid) {
        // We're the child; run the spawner.
        guarantee_err(0 == close(fds[0]), "could not close fd");
        exec_spawner(fds[1]);
        unreachable();
    }

    // We're the parent. Return.
    guarantee_err(0 == close(fds[1]), "could not close fd");
    info->pid = pid;
    info->socket.reset(fds[0]);
}

pid_t spawner_t::spawn_process(scoped_fd_t *socket) {
    assert_thread();

    // Create a socket pair.
    fd_t fds[2];
    int res = socketpair(AF_UNIX, SOCK_STREAM, 0, fds);
    if (res) return -1;

    // We need to send the fd & receive the pid atomically with respect to other
    // calls to spawn_process().
    mutex_t::acq_t lock(&mutex_);

    // Send one half to the spawner process.
    guarantee(0 == socket_.send_fd(fds[1]));
    guarantee_err(0 == close(fds[1]), "could not close fd");
    socket->reset(fds[0]);

    // Receive the pid from the spawner process.
    pid_t pid;
    guarantee(sizeof(pid) == force_read(&socket_, &pid, sizeof(pid)));
    guarantee(pid > 0);

    return pid;
}

// ---------- Spawner & worker processes ----------
// Runs the spawner process. Does not return.
void spawner_t::exec_spawner(fd_t socket) {
    // We set our PGID to our own PID (rather than inheriting our parent's PGID)
    // so that a signal (eg. SIGINT) sent to the parent's PGID (by eg. hitting
    // Ctrl-C at a terminal) will not propagate to us or our children.
    //
    // This is desirable because the RethinkDB engine deliberately crashes with
    // an error message if the spawner or a worker process dies; but a
    // command-line SIGINT should trigger a clean shutdown, not a crash.
    //
    // TODO(rntz): This is an ugly, hackish way to handle the problem.
    guarantee_err(0 == setpgid(0, 0), "spawner: could not set PGID");

    // We ignore SIGCHLD so that we don't accumulate zombie children.
    {
        // NB. According to `man 2 sigaction` on linux, POSIX.1-2001 says that
        // this will prevent zombies, but may not be "fully portable".
        struct sigaction act;
        memset(&act, 0, sizeof(act));
        act.sa_handler = SIG_IGN;

        guarantee_err(0 == sigaction(SIGCHLD, &act, NULL),
                      "spawner: Could not ignore SIGCHLD");
    }

    for (;;) {
        // Get an fd from our parent.
        fd_t fd;
        fd_recv_result_t fdres = recv_fds(socket, 1, &fd);
        if (fdres == FD_RECV_EOF) {
            // Other end shut down cleanly; we should too.
            exit(EXIT_SUCCESS);
        } else if (fdres != FD_RECV_OK) {
            exit(EXIT_FAILURE);
        }

        // Fork a worker process.
        pid_t pid = fork();
        if (-1 == pid)
            exit(EXIT_FAILURE);

        if (0 == pid) {
            // We're the child/worker.
            guarantee_err(0 == close(socket), "worker: could not close fd");
            exec_worker(fd);
            unreachable();
        }

        // We're the parent.
        guarantee_err(0 == close(fd), "spawner: couldn't close fd");

        // Send back its pid. Wish we could use unix_socket_stream_t for this,
        // but its destructor calls shutdown(), and we can't have that happening
        // in the worker child.
        const char *buf = reinterpret_cast<const char *>(&pid);
        size_t sz = sizeof(pid);
        while (sz) {
            ssize_t w = write(socket, buf, sz);
            if (w == -1 && errno == EINTR) continue;
            guarantee_err(w > 0, "spawner: could not write() to engine socket");
            guarantee((size_t)w <= sz);
            sz -= w, buf += w;
        }
    }
}

// Runs the worker process. Does not return.
void spawner_t::exec_worker(fd_t sockfd) {
    // Makes sure we get SIGTERMed when our parent (the spawner) dies.
    // TODO(rntz): prctl is linux-specific.
    // TODO(OSX) How are we going to detect parent death?
    // int res = prctl(PR_SET_PDEATHSIG, SIGTERM);
    // guarantee_err(res == 0, "worker: could not set parent-death signal");

    // Receive one job and run it.
    scoped_fd_t fd(sockfd);
    job_t::control_t control(getpid(), &fd);
    exit(job_t::accept_job(&control, NULL));
}

} // namespace extproc
<|endoftext|>


<commit_before>// Copyright (c) 2013 - 2015, German Neuroinformatics Node (G-Node)
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted under the terms of the BSD License. See
// LICENSE file in the root of the Project.

#include <nix/file/FeatureFS.hpp>

#include <nix/util/util.hpp>
#include <nix/DataArray.hpp>
#include <nix/file/DataArrayFS.hpp>

using namespace std;
using namespace nix::base;

namespace nix {
namespace file {

string linkTypeToString(LinkType link_type) {
    static vector<string> type_names = {"tagged", "untagged", "indexed"};
    return type_names[static_cast<int>(link_type)];
}

LinkType linkTypeFromString(const string &str) {
    if (str == "tagged")
        return LinkType::Tagged;
    else if (str == "untagged")
        return LinkType::Untagged;
    else if (str == "indexed")
        return LinkType::Indexed;
    else
        throw runtime_error("Unable to create a LinkType from the string: " + str);
}

FeatureFS::FeatureFS(const shared_ptr<IFile> &file, const shared_ptr<IBlock> &block, const string &loc)
    : EntityFS(file, loc), block(block)
{
}

FeatureFS::FeatureFS(const shared_ptr<IFile> &file, const shared_ptr<IBlock> &block, const string &loc,
                     const string &id, DataArray data, LinkType link_type)
    : FeatureFS(file, block, loc, id, data, link_type, util::getTime())
{
}

FeatureFS::FeatureFS(const shared_ptr<IFile> &file, const shared_ptr<IBlock> &block, const string &loc,
                     const string &id, DataArray data, LinkType link_type, time_t time)
    : EntityFS(file, loc, id, time), block(block)
{
    linkType(link_type);
    // TODO: the line below currently throws an exception if the DataArray
    // is not in block - to consider if we prefer copying it to the block
    this->data(data.id());
}

void FeatureFS::linkType(LinkType link_type) {
    // linkTypeToString will generate an error if link_type is invalid
    setAttr("link_type", linkTypeToString(link_type));
    forceUpdatedAt();
}

void FeatureFS::data(const std::string &name_or_id) {
    if (name_or_id.empty())
        throw EmptyString("data(id)");
    if (!block->hasDataArray(name_or_id))
        throw std::runtime_error("FeatureFS::data: DataArray not found in block!");

    auto target = dynamic_pointer_cast<DataArrayFS>(block->getDataArray(name_or_id));
    // FIXME create Link
    //group().createLink(target->group(), "data");
    forceUpdatedAt();
}

shared_ptr<IDataArray> FeatureFS::data() const {
    shared_ptr<IDataArray> da;
    /*
    bool error = false;

    if (group().hasGroup("data")) {
        Group other_group = group().openGroup("data", false);
        da = make_shared<DataArrayHDF5>(file(), block, other_group);
        if (!block->hasDataArray(da->id())) error = true;
    }
    else error = true;

    // NOTE: we check that link exists in both places, here & in entity
    // if error = true it was missing in one of the two
    if (error)
        throw std::runtime_error("FeatureHDF5::data: DataArray not found!");
    */
    return da;
}

LinkType FeatureFS::linkType() const {
    if (hasAttr("link_type")) {
        string link_type;
        getAttr("link_type", link_type);
        return linkTypeFromString(link_type);
    } else {
        throw MissingAttr("data");
    }
}

FeatureFS::~FeatureFS() {}

} // ns nix::file
} // ns nix
<commit_msg>[file backend/Feature] correct creation of feature with the id being the name<commit_after>// Copyright (c) 2013 - 2015, German Neuroinformatics Node (G-Node)
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted under the terms of the BSD License. See
// LICENSE file in the root of the Project.

#include <nix/file/FeatureFS.hpp>

#include <nix/util/util.hpp>
#include <nix/DataArray.hpp>
#include <nix/file/DataArrayFS.hpp>

using namespace std;
using namespace nix::base;

namespace nix {
namespace file {

string linkTypeToString(LinkType link_type) {
    static vector<string> type_names = {"tagged", "untagged", "indexed"};
    return type_names[static_cast<int>(link_type)];
}

LinkType linkTypeFromString(const string &str) {
    if (str == "tagged")
        return LinkType::Tagged;
    else if (str == "untagged")
        return LinkType::Untagged;
    else if (str == "indexed")
        return LinkType::Indexed;
    else
        throw runtime_error("Unable to create a LinkType from the string: " + str);
}

FeatureFS::FeatureFS(const shared_ptr<IFile> &file, const shared_ptr<IBlock> &block, const string &loc)
    : EntityFS(file, loc), block(block)
{
}

FeatureFS::FeatureFS(const shared_ptr<IFile> &file, const shared_ptr<IBlock> &block, const string &loc,
                     const string &id, DataArray data, LinkType link_type)
    : FeatureFS(file, block, loc, id, data, link_type, util::getTime())
{
}

FeatureFS::FeatureFS(const shared_ptr<IFile> &file, const shared_ptr<IBlock> &block, const string &loc,
                     const string &id, DataArray data, LinkType link_type, time_t time)
    : EntityFS(file, (boost::filesystem::path(loc) / boost::filesystem::path(id)).string(), id, time), block(block)
{
    linkType(link_type);
    // TODO: the line below currently throws an exception if the DataArray
    // is not in block - to consider if we prefer copying it to the block
    this->data(data.id());
}

void FeatureFS::linkType(LinkType link_type) {
    // linkTypeToString will generate an error if link_type is invalid
    setAttr("link_type", linkTypeToString(link_type));
    forceUpdatedAt();
}

void FeatureFS::data(const std::string &name_or_id) {
    if (name_or_id.empty())
        throw EmptyString("data(id)");
    if (!block->hasDataArray(name_or_id))
        throw std::runtime_error("FeatureFS::data: DataArray not found in block!");

    auto target = dynamic_pointer_cast<DataArrayFS>(block->getDataArray(name_or_id));
    createDirectoryLink(target->location(), "data");
    forceUpdatedAt();
}

shared_ptr<IDataArray> FeatureFS::data() const {
    shared_ptr<IDataArray> da;
    boost::optional<boost::filesystem::path> p = findByNameOrAttribute("name", "data");
    if (p) {
        DataArrayFS a(file(), block, p->string());
        return make_shared<DataArrayFS>(a);
    }
    return da;
}

LinkType FeatureFS::linkType() const {
    if (hasAttr("link_type")) {
        string link_type;
        getAttr("link_type", link_type);
        return linkTypeFromString(link_type);
    } else {
        throw MissingAttr("data");
    }
}

FeatureFS::~FeatureFS() {}

} // ns nix::file
} // ns nix
<|endoftext|>


<commit_before>/*
    Copyright 2008 Brain Research Institute, Melbourne, Australia

    Written by J-Donald Tournier, 27/06/08.

    This file is part of MRtrix.

    MRtrix 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 3 of the License, or
    (at your option) any later version.

    MRtrix 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 MRtrix.  If not, see <http://www.gnu.org/licenses/>.

*/

#include <fcntl.h>
#include <unistd.h>
#include <zlib.h>

#ifdef WINDOWS
#include <windows.h>
#else
#include <sys/mman.h>
#endif

#include "file/path.h"
#include "file/mmap.h"
#include "file/config.h"

namespace MR
{
  namespace File
  {

    void MMap::map()
    {
      DEBUG ("memory-mapping file \"" + Entry::name + "\"...");

      struct stat sbuf;
      if (stat (Entry::name.c_str(), &sbuf))
        throw Exception ("cannot stat file \"" + Entry::name + "\": " + strerror (errno));

      mtime = sbuf.st_mtime;

      if (start + msize > sbuf.st_size)
        throw Exception ("file \"" + Entry::name + "\" is smaller than expected");

      if (msize < 0)
        msize = sbuf.st_size - start;

      if ( (fd = open (Entry::name.c_str(), (readwrite ? O_RDWR : O_RDONLY), 0644)) < 0)
        throw Exception ("error opening file \"" + Entry::name + "\": " + strerror (errno));

      try {
#ifdef WINDOWS
        HANDLE handle = CreateFileMapping ( (HANDLE) _get_osfhandle (fd), NULL,
                                            (readwrite ? PAGE_READWRITE : PAGE_READONLY), 0, start + msize, NULL);
        if (!handle) throw 0;
        addr = static_cast<uint8_t*> (MapViewOfFile (handle, (readwrite ? FILE_MAP_ALL_ACCESS : FILE_MAP_READ), 0, 0, start + msize));
        if (!addr) throw 0;
        CloseHandle (handle);
#else
        addr = static_cast<uint8_t*> (mmap ( (char*) 0, start + msize,
                                               (readwrite ? PROT_READ | PROT_WRITE : PROT_READ), MAP_SHARED, fd, 0));
        if (addr == MAP_FAILED) throw 0;
#endif
      }
      catch (...) {
        close (fd);
        addr = NULL;
        throw Exception ("memory-mapping failed for file \"" + Entry::name + "\": " + strerror (errno));
      }

      DEBUG ("file \"" + Entry::name + "\" mapped at " + str ( (void*) addr) + ", size " + str (msize)
             + " (read-" + (readwrite ? "write" : "only") + ")");
    }

    MMap::~MMap()
    {
      if (!addr) return;
      DEBUG ("unmapping file \"" + Entry::name + "\"");
#ifdef WINDOWS
      if (!UnmapViewOfFile ( (LPVOID) addr))
#else
      if (munmap (addr, msize))
#endif
        ERROR ("error unmapping file \"" + Entry::name + "\": " + strerror (errno));
      close (fd);
    }

    bool MMap::changed () const
    {
      assert (fd >= 0);
      struct stat sbuf;
      if (fstat (fd, &sbuf)) return (false);
      if (int64_t (msize) != sbuf.st_size) return (true);
      if (mtime != sbuf.st_mtime) return (true);
      return (false);
    }

  }
}

<commit_msg>Solve name clashes with <windows.h> on mingw.<commit_after>/*
    Copyright 2008 Brain Research Institute, Melbourne, Australia

    Written by J-Donald Tournier, 27/06/08.

    This file is part of MRtrix.

    MRtrix 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 3 of the License, or
    (at your option) any later version.

    MRtrix 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 MRtrix.  If not, see <http://www.gnu.org/licenses/>.

*/

#include <fcntl.h>
#include <unistd.h>
#include <zlib.h>

#ifdef WINDOWS
#pragma push_macro("ERROR")
#include <windows.h>
#pragma pop_macro("ERROR")
#else
#include <sys/mman.h>
#endif

#include "file/path.h"
#include "file/mmap.h"
#include "file/config.h"

namespace MR
{
  namespace File
  {

    void MMap::map()
    {
      DEBUG ("memory-mapping file \"" + Entry::name + "\"...");

      struct stat sbuf;
      if (stat (Entry::name.c_str(), &sbuf))
        throw Exception ("cannot stat file \"" + Entry::name + "\": " + strerror (errno));

      mtime = sbuf.st_mtime;

      if (start + msize > sbuf.st_size)
        throw Exception ("file \"" + Entry::name + "\" is smaller than expected");

      if (msize < 0)
        msize = sbuf.st_size - start;

      if ( (fd = open (Entry::name.c_str(), (readwrite ? O_RDWR : O_RDONLY), 0644)) < 0)
        throw Exception ("error opening file \"" + Entry::name + "\": " + strerror (errno));

      try {
#ifdef WINDOWS
        HANDLE handle = CreateFileMapping ( (HANDLE) _get_osfhandle (fd), NULL,
                                            (readwrite ? PAGE_READWRITE : PAGE_READONLY), 0, start + msize, NULL);
        if (!handle) throw 0;
        addr = static_cast<uint8_t*> (MapViewOfFile (handle, (readwrite ? FILE_MAP_ALL_ACCESS : FILE_MAP_READ), 0, 0, start + msize));
        if (!addr) throw 0;
        CloseHandle (handle);
#else
        addr = static_cast<uint8_t*> (mmap ( (char*) 0, start + msize,
                                               (readwrite ? PROT_READ | PROT_WRITE : PROT_READ), MAP_SHARED, fd, 0));
        if (addr == MAP_FAILED) throw 0;
#endif
      }
      catch (...) {
        close (fd);
        addr = NULL;
        throw Exception ("memory-mapping failed for file \"" + Entry::name + "\": " + strerror (errno));
      }

      DEBUG ("file \"" + Entry::name + "\" mapped at " + str ( (void*) addr) + ", size " + str (msize)
             + " (read-" + (readwrite ? "write" : "only") + ")");
    }

    MMap::~MMap()
    {
      if (!addr) return;
      DEBUG ("unmapping file \"" + Entry::name + "\"");
#ifdef WINDOWS
      if (!UnmapViewOfFile ( (LPVOID) addr))
#else
      if (munmap (addr, msize))
#endif
        ERROR ("error unmapping file \"" + Entry::name + "\": " + strerror (errno));
      close (fd);
    }

    bool MMap::changed () const
    {
      assert (fd >= 0);
      struct stat sbuf;
      if (fstat (fd, &sbuf)) return (false);
      if (int64_t (msize) != sbuf.st_size) return (true);
      if (mtime != sbuf.st_mtime) return (true);
      return (false);
    }

  }
}

<|endoftext|>


<commit_before>/***************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact:  Qt Software Information (qt-info@nokia.com)
**
**
** Non-Open Source Usage
**
** Licensees may use this file in accordance with the Qt Beta Version
** License Agreement, Agreement version 2.2 provided with the Software or,
** alternatively, in accordance with the terms contained in a written
** agreement between you and Nokia.
**
** GNU General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU General
** Public License versions 2.0 or 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the packaging
** of this file.  Please review the following information to ensure GNU
** General Public Licensing requirements will be met:
**
** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
** http://www.gnu.org/copyleft/gpl.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt GPL Exception
** version 1.2, included in the file GPL_EXCEPTION.txt in this package.
**
***************************************************************************/

#include "gdbmacrosbuildstep.h"

#include "makestep.h"
#include "qmakestep.h"
#include "qt4project.h"
#include "qt4projectmanagerconstants.h"

#include <utils/qtcassert.h>

using namespace Qt4ProjectManager;
using namespace Qt4ProjectManager::Internal;

GdbMacrosBuildStep::GdbMacrosBuildStep(Qt4Project *project)
    : BuildStep(project), m_project(project)
{
}

GdbMacrosBuildStep::~GdbMacrosBuildStep()
{
}

bool GdbMacrosBuildStep::init(const QString &buildConfiguration)
{
    m_buildDirectory = m_project->buildDirectory(buildConfiguration);
    m_qmake = m_project->qtVersion(buildConfiguration)->qmakeCommand();
    m_buildConfiguration = buildConfiguration;
    qDebug()<<"m_buildDirectory "<<m_buildDirectory;
    qDebug()<<"m_qmake "<<m_qmake;
    return true;
}

void GdbMacrosBuildStep::run(QFutureInterface<bool> & fi)
{
    // TODO CONFIG handling

    QString dumperPath = ExtensionSystem::PluginManager::instance()->getObject<Core::ICore>()
                ->resourcePath() + "/gdbmacros/";
    QStringList files;
    files << "gdbmacros.cpp"
          << "gdbmacros.pro";

    QString destDir = m_buildDirectory + "/qtc-gdbmacros/";
    QDir dir;
    dir.mkpath(destDir);
    foreach (const QString &file, files) {
        QFile destination(destDir + file);
        if (destination.exists())
            destination.remove();
        QFile::copy(dumperPath + file, destDir + file);
        qDebug()<<"copying"<<(dumperPath + file)<<" to "<< (destDir + file);
    }

    Qt4Project *qt4Project = static_cast<Qt4Project *>(project());

    QProcess qmake;
    qmake.setEnvironment(qt4Project->environment(m_buildConfiguration).toStringList());
    qmake.setWorkingDirectory(destDir);
    QStringList configarguments;
    QStringList makeArguments;

    // Find qmake step...
    QMakeStep *qmakeStep = qt4Project->qmakeStep();
    // Find out which configuration is used in this build configuration
    // and what kind of CONFIG we need to pass to qmake for that
    if (qmakeStep->value(m_buildConfiguration, "buildConfiguration").isValid()) {
        QtVersion::QmakeBuildConfig defaultBuildConfiguration = qt4Project->qtVersion(m_buildConfiguration)->defaultBuildConfig();
        QtVersion::QmakeBuildConfig projectBuildConfiguration = QtVersion::QmakeBuildConfig(qmakeStep->value(m_buildConfiguration, "buildConfiguration").toInt());
        if ((defaultBuildConfiguration & QtVersion::BuildAll) && !(projectBuildConfiguration & QtVersion::BuildAll))
            configarguments << "CONFIG-=debug_and_release";
        if (!(defaultBuildConfiguration & QtVersion::BuildAll) && (projectBuildConfiguration & QtVersion::BuildAll))
            configarguments << "CONFIG+=debug_and_release";
        if ((defaultBuildConfiguration & QtVersion::DebugBuild) && !(projectBuildConfiguration & QtVersion::DebugBuild))
            configarguments << "CONFIG+=release";
        if (!(defaultBuildConfiguration & QtVersion::DebugBuild) && (projectBuildConfiguration & QtVersion::DebugBuild))
            configarguments << "CONFIG+=debug";
        if (projectBuildConfiguration & QtVersion::BuildAll)
            makeArguments << (projectBuildConfiguration & QtVersion::DebugBuild ? "debug" : "release");

    } else {
        // Old style with CONFIG+=debug_and_release
        qDebug() << "OLD STYLE CONF";
        configarguments << "CONFIG+=debug_and_release";
        const MakeStep *ms = qt4Project->makeStep();
        QStringList makeargs = ms->value(m_buildConfiguration, "makeargs").toStringList();
        if (makeargs.contains("debug")) {
            makeArguments <<  "debug";
        } else if (makeargs.contains("release")) {
            makeArguments << "release";
        }
    }

    QString mkspec = qt4Project->qtVersion(m_buildConfiguration)->mkspec();
    qmake.start(m_qmake, QStringList()<<"-spec"<<mkspec<<configarguments<<"gdbmacros.pro");
    qmake.waitForFinished();
    qDebug()<<qmake.readAllStandardError()<<qmake.readAllStandardOutput();

    qmake.start(qt4Project->qtVersion(m_buildConfiguration)->makeCommand(), makeArguments);
    qmake.waitForFinished();
    qDebug()<<qmake.readAllStandardError()<<qmake.readAllStandardOutput();

    fi.reportResult(true);
}

QString GdbMacrosBuildStep::name()
{
    return Constants::GDBMACROSBUILDSTEP;
}

QString GdbMacrosBuildStep::displayName()
{
    return "Gdb Macros Build";
}

ProjectExplorer::BuildStepConfigWidget *GdbMacrosBuildStep::createConfigWidget()
{
    return new GdbMacrosBuildStepConfigWidget;
}

bool GdbMacrosBuildStep::immutable() const
{
    return false;
}

bool GdbMacrosBuildStepFactory::canCreate(const QString &name) const
{
    return name == Constants::GDBMACROSBUILDSTEP;
}

ProjectExplorer::BuildStep *GdbMacrosBuildStepFactory::create(ProjectExplorer::Project *pro, const QString &name) const
{
    QTC_ASSERT(name == Constants::GDBMACROSBUILDSTEP, return 0);
    Qt4Project *qt4project = qobject_cast<Qt4Project *>(pro);
    QTC_ASSERT(qt4project, return 0);
    return new GdbMacrosBuildStep(qt4project);
}

QStringList GdbMacrosBuildStepFactory::canCreateForProject(ProjectExplorer::Project *pro) const
{
    QStringList results;
    if (qobject_cast<Qt4Project *>(pro))
        results <<  Constants::GDBMACROSBUILDSTEP;
    return results;
}

QString GdbMacrosBuildStepFactory::displayNameForName(const QString &name) const
{
    if (name == Constants::GDBMACROSBUILDSTEP)
        return "Gdb Macros Build";
    else
        return QString::null;
}

QString GdbMacrosBuildStepConfigWidget::displayName() const
{
    return "Gdb Macros Build";
}

void GdbMacrosBuildStepConfigWidget::init(const QString & /*buildConfiguration*/)
{
    // TODO
}
<commit_msg>Fixes:    Noisy debugt output from gdbmacrosbuildstep.cpp<commit_after>/***************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact:  Qt Software Information (qt-info@nokia.com)
**
**
** Non-Open Source Usage
**
** Licensees may use this file in accordance with the Qt Beta Version
** License Agreement, Agreement version 2.2 provided with the Software or,
** alternatively, in accordance with the terms contained in a written
** agreement between you and Nokia.
**
** GNU General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU General
** Public License versions 2.0 or 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the packaging
** of this file.  Please review the following information to ensure GNU
** General Public Licensing requirements will be met:
**
** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
** http://www.gnu.org/copyleft/gpl.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt GPL Exception
** version 1.2, included in the file GPL_EXCEPTION.txt in this package.
**
***************************************************************************/

#include "gdbmacrosbuildstep.h"

#include "makestep.h"
#include "qmakestep.h"
#include "qt4project.h"
#include "qt4projectmanagerconstants.h"

#include <utils/qtcassert.h>

using namespace Qt4ProjectManager;
using namespace Qt4ProjectManager::Internal;

GdbMacrosBuildStep::GdbMacrosBuildStep(Qt4Project *project)
    : BuildStep(project), m_project(project)
{
}

GdbMacrosBuildStep::~GdbMacrosBuildStep()
{
}

bool GdbMacrosBuildStep::init(const QString &buildConfiguration)
{
    m_buildDirectory = m_project->buildDirectory(buildConfiguration);
    m_qmake = m_project->qtVersion(buildConfiguration)->qmakeCommand();
    m_buildConfiguration = buildConfiguration;
    return true;
}

void GdbMacrosBuildStep::run(QFutureInterface<bool> & fi)
{
    // TODO CONFIG handling

    QString dumperPath = ExtensionSystem::PluginManager::instance()->getObject<Core::ICore>()
                ->resourcePath() + "/gdbmacros/";
    QStringList files;
    files << "gdbmacros.cpp"
          << "gdbmacros.pro";

    QString destDir = m_buildDirectory + "/qtc-gdbmacros/";
    QDir dir;
    dir.mkpath(destDir);
    foreach (const QString &file, files) {
        QFile destination(destDir + file);
        if (destination.exists())
            destination.remove();
        QFile::copy(dumperPath + file, destDir + file);
    }

    Qt4Project *qt4Project = static_cast<Qt4Project *>(project());

    QProcess qmake;
    qmake.setEnvironment(qt4Project->environment(m_buildConfiguration).toStringList());
    qmake.setWorkingDirectory(destDir);
    QStringList configarguments;
    QStringList makeArguments;

    // Find qmake step...
    QMakeStep *qmakeStep = qt4Project->qmakeStep();
    // Find out which configuration is used in this build configuration
    // and what kind of CONFIG we need to pass to qmake for that
    if (qmakeStep->value(m_buildConfiguration, "buildConfiguration").isValid()) {
        QtVersion::QmakeBuildConfig defaultBuildConfiguration = qt4Project->qtVersion(m_buildConfiguration)->defaultBuildConfig();
        QtVersion::QmakeBuildConfig projectBuildConfiguration = QtVersion::QmakeBuildConfig(qmakeStep->value(m_buildConfiguration, "buildConfiguration").toInt());
        if ((defaultBuildConfiguration & QtVersion::BuildAll) && !(projectBuildConfiguration & QtVersion::BuildAll))
            configarguments << "CONFIG-=debug_and_release";
        if (!(defaultBuildConfiguration & QtVersion::BuildAll) && (projectBuildConfiguration & QtVersion::BuildAll))
            configarguments << "CONFIG+=debug_and_release";
        if ((defaultBuildConfiguration & QtVersion::DebugBuild) && !(projectBuildConfiguration & QtVersion::DebugBuild))
            configarguments << "CONFIG+=release";
        if (!(defaultBuildConfiguration & QtVersion::DebugBuild) && (projectBuildConfiguration & QtVersion::DebugBuild))
            configarguments << "CONFIG+=debug";
        if (projectBuildConfiguration & QtVersion::BuildAll)
            makeArguments << (projectBuildConfiguration & QtVersion::DebugBuild ? "debug" : "release");

    } else {
        // Old style with CONFIG+=debug_and_release
        configarguments << "CONFIG+=debug_and_release";
        const MakeStep *ms = qt4Project->makeStep();
        QStringList makeargs = ms->value(m_buildConfiguration, "makeargs").toStringList();
        if (makeargs.contains("debug")) {
            makeArguments <<  "debug";
        } else if (makeargs.contains("release")) {
            makeArguments << "release";
        }
    }

    QString mkspec = qt4Project->qtVersion(m_buildConfiguration)->mkspec();
    qmake.start(m_qmake, QStringList()<<"-spec"<<mkspec<<configarguments<<"gdbmacros.pro");
    qmake.waitForFinished();

    qmake.start(qt4Project->qtVersion(m_buildConfiguration)->makeCommand(), makeArguments);
    qmake.waitForFinished();

    fi.reportResult(true);
}

QString GdbMacrosBuildStep::name()
{
    return Constants::GDBMACROSBUILDSTEP;
}

QString GdbMacrosBuildStep::displayName()
{
    return "Gdb Macros Build";
}

ProjectExplorer::BuildStepConfigWidget *GdbMacrosBuildStep::createConfigWidget()
{
    return new GdbMacrosBuildStepConfigWidget;
}

bool GdbMacrosBuildStep::immutable() const
{
    return false;
}

bool GdbMacrosBuildStepFactory::canCreate(const QString &name) const
{
    return name == Constants::GDBMACROSBUILDSTEP;
}

ProjectExplorer::BuildStep *GdbMacrosBuildStepFactory::create(ProjectExplorer::Project *pro, const QString &name) const
{
    QTC_ASSERT(name == Constants::GDBMACROSBUILDSTEP, return 0);
    Qt4Project *qt4project = qobject_cast<Qt4Project *>(pro);
    QTC_ASSERT(qt4project, return 0);
    return new GdbMacrosBuildStep(qt4project);
}

QStringList GdbMacrosBuildStepFactory::canCreateForProject(ProjectExplorer::Project *pro) const
{
    QStringList results;
    if (qobject_cast<Qt4Project *>(pro))
        results <<  Constants::GDBMACROSBUILDSTEP;
    return results;
}

QString GdbMacrosBuildStepFactory::displayNameForName(const QString &name) const
{
    if (name == Constants::GDBMACROSBUILDSTEP)
        return "Gdb Macros Build";
    else
        return QString::null;
}

QString GdbMacrosBuildStepConfigWidget::displayName() const
{
    return "Gdb Macros Build";
}

void GdbMacrosBuildStepConfigWidget::init(const QString & /*buildConfiguration*/)
{
    // TODO
}
<|endoftext|>


<commit_before>/*ckwg +5
 * Copyright 2011 by Kitware, Inc. All Rights Reserved. Please refer to
 * KITWARE_LICENSE.TXT for licensing information, or contact General Counsel,
 * Kitware, Inc., 28 Corporate Drive, Clifton Park, NY 12065.
 */

#include "layered_image_reader_process.h"

#include <processes/helpers/image/format.h>
#include <processes/helpers/image/read.h>

#include <vistk/utilities/timestamp.h>
#include <vistk/utilities/path.h>

#include <vistk/pipeline/config.h>
#include <vistk/pipeline/datum.h>
#include <vistk/pipeline/process_exception.h>
#include <vistk/pipeline/stamp.h>

#include <boost/algorithm/string/predicate.hpp>
#include <boost/foreach.hpp>
#include <boost/format.hpp>
#include <boost/make_shared.hpp>

#include <string>

/**
 * \file layered_image_reader_process.cxx
 *
 * \brief Implementation of the layered image reader process.
 */

namespace vistk
{

class layered_image_reader_process::priv
{
  public:
    typedef port_t layer_t;
    typedef std::vector<layer_t> layers_t;

    priv(port_type_t const& port_type);
    priv(config::value_t const& fmt, read_func_t func, port_type_t const& port_type, layers_t const& layers_);
    ~priv();

    typedef boost::basic_format<config::value_t::value_type> format_t;

    format_t format;
    read_func_t const read;
    port_type_t const port_type_output;

    layers_t layers;

    static config::key_t const config_pixtype;
    static config::key_t const config_pixfmt;
    static config::key_t const config_format;
    static config::value_t const default_pixtype;
    static config::value_t const default_pixfmt;
    static config::value_t const default_format;
    static port_t const port_timestamp;
    static port_t const port_image_prefix;
};

config::key_t const layered_image_reader_process::priv::config_pixtype = config::key_t("pixtype");
config::key_t const layered_image_reader_process::priv::config_pixfmt = config::key_t("pixfmt");
config::key_t const layered_image_reader_process::priv::config_format = config::key_t("format");
config::value_t const layered_image_reader_process::priv::default_pixtype = config::value_t(pixtypes::pixtype_byte());
config::value_t const layered_image_reader_process::priv::default_pixfmt = config::value_t(pixfmts::pixfmt_rgb());
config::value_t const layered_image_reader_process::priv::default_format = config::value_t("image-%1%-%2%.png");
process::port_t const layered_image_reader_process::priv::port_timestamp = process::port_t("timestamp");
process::port_t const layered_image_reader_process::priv::port_image_prefix = process::port_t("image/");

layered_image_reader_process
::layered_image_reader_process(config_t const& config)
  : process(config)
{
  /// \todo There should probably be timestamp input rather than manually keeping track of the frame.

  declare_configuration_key(priv::config_pixtype, boost::make_shared<conf_info>(
    priv::default_pixtype,
    config::description_t("The pixel type of the input images.")));
  declare_configuration_key(priv::config_pixfmt, boost::make_shared<conf_info>(
    priv::default_pixfmt,
    config::description_t("The pixel format of the input images.")));
  declare_configuration_key(priv::config_format, boost::make_shared<conf_info>(
    priv::default_format,
    config::description_t("The format string for the input layers.")));

  pixtype_t const pixtype = config_value<pixtype_t>(priv::config_pixtype);
  pixfmt_t const pixfmt = config_value<pixfmt_t>(priv::config_pixfmt);

  port_type_t const port_type = port_type_for_pixtype(pixtype, pixfmt);

  d.reset(new priv(port_type));

  port_flags_t required;

  required.insert(flag_required);

  declare_input_port(priv::port_timestamp, boost::make_shared<port_info>(
    "timestamp",
    required,
    port_description_t("The timestamp to use when reading masks.")));
}

layered_image_reader_process
::~layered_image_reader_process()
{
}

void
layered_image_reader_process
::_init()
{
  // Configure the process.
  {
    pixtype_t const pixtype = config_value<pixtype_t>(priv::config_pixtype);
    config::value_t const format = config_value<config::value_t>(priv::config_format);

    read_func_t const func = read_for_pixtype(pixtype);

    d.reset(new priv(format, func, d->port_type_output, d->layers));
  }

  if (!d->read)
  {
    static std::string const reason = "A read function for the "
                                      "given pixtype could not be found";

    throw invalid_configuration_exception(name(), reason);
  }

  process::_init();
}

void
layered_image_reader_process
::_step()
{
  timestamp const ts = grab_from_port_as<timestamp>(priv::port_timestamp);

  BOOST_FOREACH (priv::layer_t const& layer, d->layers)
  {
    d->format.clear();

    try
    {
      d->format % layer;
      d->format % ts.frame();
    }
    catch (boost::io::format_error&)
    {
    }

    path_t const path = boost::str(d->format);

    datum_t const dat = d->read(path);

    push_datum_to_port(priv::port_image_prefix + layer, dat);
  }

  process::_step();
}

process::port_info_t
layered_image_reader_process
::_output_port_info(port_t const& port)
{
  if (boost::starts_with(port, priv::port_image_prefix))
  {
    priv::layer_t const layer = port.substr(priv::port_image_prefix.size());

    priv::layers_t::const_iterator const i = std::find(d->layers.begin(), d->layers.end(), layer);

    if (i == d->layers.end())
    {
      d->layers.push_back(layer);

      port_flags_t required;

      required.insert(flag_required);

      declare_output_port(port, boost::make_shared<port_info>(
        d->port_type_output,
        required,
        port_description_t("The \'" + layer + "\' layer of the image.")));
    }
  }

  return process::_output_port_info(port);
}

layered_image_reader_process::priv
::priv(port_type_t const& port_type)
  : port_type_output(port_type)
{
}

layered_image_reader_process::priv
::priv(config::value_t const& fmt, read_func_t func, port_type_t const& port_type, layers_t const& layers_)
  : format(fmt)
  , read(func)
  , port_type_output(port_type)
  , layers(layers_)
{
}

layered_image_reader_process::priv
::~priv()
{
}

}
<commit_msg>Remove an unnecessary include<commit_after>/*ckwg +5
 * Copyright 2011 by Kitware, Inc. All Rights Reserved. Please refer to
 * KITWARE_LICENSE.TXT for licensing information, or contact General Counsel,
 * Kitware, Inc., 28 Corporate Drive, Clifton Park, NY 12065.
 */

#include "layered_image_reader_process.h"

#include <processes/helpers/image/format.h>
#include <processes/helpers/image/read.h>

#include <vistk/utilities/timestamp.h>
#include <vistk/utilities/path.h>

#include <vistk/pipeline/config.h>
#include <vistk/pipeline/datum.h>
#include <vistk/pipeline/process_exception.h>

#include <boost/algorithm/string/predicate.hpp>
#include <boost/foreach.hpp>
#include <boost/format.hpp>
#include <boost/make_shared.hpp>

#include <string>

/**
 * \file layered_image_reader_process.cxx
 *
 * \brief Implementation of the layered image reader process.
 */

namespace vistk
{

class layered_image_reader_process::priv
{
  public:
    typedef port_t layer_t;
    typedef std::vector<layer_t> layers_t;

    priv(port_type_t const& port_type);
    priv(config::value_t const& fmt, read_func_t func, port_type_t const& port_type, layers_t const& layers_);
    ~priv();

    typedef boost::basic_format<config::value_t::value_type> format_t;

    format_t format;
    read_func_t const read;
    port_type_t const port_type_output;

    layers_t layers;

    static config::key_t const config_pixtype;
    static config::key_t const config_pixfmt;
    static config::key_t const config_format;
    static config::value_t const default_pixtype;
    static config::value_t const default_pixfmt;
    static config::value_t const default_format;
    static port_t const port_timestamp;
    static port_t const port_image_prefix;
};

config::key_t const layered_image_reader_process::priv::config_pixtype = config::key_t("pixtype");
config::key_t const layered_image_reader_process::priv::config_pixfmt = config::key_t("pixfmt");
config::key_t const layered_image_reader_process::priv::config_format = config::key_t("format");
config::value_t const layered_image_reader_process::priv::default_pixtype = config::value_t(pixtypes::pixtype_byte());
config::value_t const layered_image_reader_process::priv::default_pixfmt = config::value_t(pixfmts::pixfmt_rgb());
config::value_t const layered_image_reader_process::priv::default_format = config::value_t("image-%1%-%2%.png");
process::port_t const layered_image_reader_process::priv::port_timestamp = process::port_t("timestamp");
process::port_t const layered_image_reader_process::priv::port_image_prefix = process::port_t("image/");

layered_image_reader_process
::layered_image_reader_process(config_t const& config)
  : process(config)
{
  /// \todo There should probably be timestamp input rather than manually keeping track of the frame.

  declare_configuration_key(priv::config_pixtype, boost::make_shared<conf_info>(
    priv::default_pixtype,
    config::description_t("The pixel type of the input images.")));
  declare_configuration_key(priv::config_pixfmt, boost::make_shared<conf_info>(
    priv::default_pixfmt,
    config::description_t("The pixel format of the input images.")));
  declare_configuration_key(priv::config_format, boost::make_shared<conf_info>(
    priv::default_format,
    config::description_t("The format string for the input layers.")));

  pixtype_t const pixtype = config_value<pixtype_t>(priv::config_pixtype);
  pixfmt_t const pixfmt = config_value<pixfmt_t>(priv::config_pixfmt);

  port_type_t const port_type = port_type_for_pixtype(pixtype, pixfmt);

  d.reset(new priv(port_type));

  port_flags_t required;

  required.insert(flag_required);

  declare_input_port(priv::port_timestamp, boost::make_shared<port_info>(
    "timestamp",
    required,
    port_description_t("The timestamp to use when reading masks.")));
}

layered_image_reader_process
::~layered_image_reader_process()
{
}

void
layered_image_reader_process
::_init()
{
  // Configure the process.
  {
    pixtype_t const pixtype = config_value<pixtype_t>(priv::config_pixtype);
    config::value_t const format = config_value<config::value_t>(priv::config_format);

    read_func_t const func = read_for_pixtype(pixtype);

    d.reset(new priv(format, func, d->port_type_output, d->layers));
  }

  if (!d->read)
  {
    static std::string const reason = "A read function for the "
                                      "given pixtype could not be found";

    throw invalid_configuration_exception(name(), reason);
  }

  process::_init();
}

void
layered_image_reader_process
::_step()
{
  timestamp const ts = grab_from_port_as<timestamp>(priv::port_timestamp);

  BOOST_FOREACH (priv::layer_t const& layer, d->layers)
  {
    d->format.clear();

    try
    {
      d->format % layer;
      d->format % ts.frame();
    }
    catch (boost::io::format_error&)
    {
    }

    path_t const path = boost::str(d->format);

    datum_t const dat = d->read(path);

    push_datum_to_port(priv::port_image_prefix + layer, dat);
  }

  process::_step();
}

process::port_info_t
layered_image_reader_process
::_output_port_info(port_t const& port)
{
  if (boost::starts_with(port, priv::port_image_prefix))
  {
    priv::layer_t const layer = port.substr(priv::port_image_prefix.size());

    priv::layers_t::const_iterator const i = std::find(d->layers.begin(), d->layers.end(), layer);

    if (i == d->layers.end())
    {
      d->layers.push_back(layer);

      port_flags_t required;

      required.insert(flag_required);

      declare_output_port(port, boost::make_shared<port_info>(
        d->port_type_output,
        required,
        port_description_t("The \'" + layer + "\' layer of the image.")));
    }
  }

  return process::_output_port_info(port);
}

layered_image_reader_process::priv
::priv(port_type_t const& port_type)
  : port_type_output(port_type)
{
}

layered_image_reader_process::priv
::priv(config::value_t const& fmt, read_func_t func, port_type_t const& port_type, layers_t const& layers_)
  : format(fmt)
  , read(func)
  , port_type_output(port_type)
  , layers(layers_)
{
}

layered_image_reader_process::priv
::~priv()
{
}

}
<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights.  These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include <QtTest/QtTest>
#include <QDebug>
#include <qmediaobject.h>
#include <qmediacontrol.h>
#include <qmediaservice.h>
#include <qmediarecordercontrol.h>
#include <qmediarecorder.h>
#include <qaudioendpointselector.h>
#include <qaudioencodercontrol.h>
#include <qmediacontainercontrol.h>
#include <qaudioformat.h>
#include <qaudiocapturesource.h>

#define QTRY_COMPARE(a,e)                       \
    for (int _i = 0; _i < 5000; _i += 100) {    \
        if ((a) == (e)) break;                  \
        QTest::qWait(100);                      \
    }                                           \
    QCOMPARE(a, e)

#define QTRY_VERIFY(a)                       \
    for (int _i = 0; _i < 5000; _i += 100) {    \
        if (a) break;                  \
        QTest::qWait(100);                      \
    }                                           \
    QVERIFY(a)

QT_USE_NAMESPACE
class tst_QMediaRecorder: public QObject
{
    Q_OBJECT

public slots:
    void initTestCase();
    void cleanupTestCase();

private slots:
    void testAudioSink();
    void testAudioRecord();
    void testAudioRecordWithAMR();
    void testAudioEndPointSelector();
    void testAudioEncoderControl();
    void testMediaFormatsControl();
    void testDefaultAudioEncodingSettings();

private:
    QUrl recordPathAudio(QDir outputDir);

    QAudioEncoderControl *audioEncoder;
    QAudioEndpointSelector *audioEndpoint;
    QMediaRecorder  *audiocapture;
    QAudioCaptureSource *captureSource;
};

void tst_QMediaRecorder::initTestCase()
{
    qRegisterMetaType<QMediaRecorder::State>("QMediaRecorder::State");
    qRegisterMetaType<QMediaRecorder::Error>("QMediaRecorder::Error");

    captureSource = new QAudioCaptureSource;
    audiocapture = new QMediaRecorder(captureSource);

    audioEndpoint = qobject_cast<QAudioEndpointSelector*>(audiocapture->service()->requestControl(QAudioEndpointSelector_iid));
    audioEncoder = qobject_cast<QAudioEncoderControl*>(audiocapture->service()->requestControl(QAudioEncoderControl_iid));
}

void tst_QMediaRecorder::cleanupTestCase()
{
    delete audiocapture;
    delete captureSource;
}

QUrl tst_QMediaRecorder::recordPathAudio(QDir outputDir)
{
    int lastImage = 0;
    int fileCount = 0;
    foreach( QString fileName, outputDir.entryList(QStringList() << "testclip_*.amr") ) {
        int imgNumber = fileName.mid(5, fileName.size()-9).toInt();
        lastImage = qMax(lastImage, imgNumber);
        if (outputDir.exists(fileName))
            fileCount+=1;
    }
    lastImage+=fileCount;

    QUrl location(QDir::toNativeSeparators(outputDir.canonicalPath()+QString("/testclip_%1.amr").arg(lastImage+1,4,10,QLatin1Char('0'))));
    return location;
}

void tst_QMediaRecorder::testAudioSink()
{
    audiocapture->setOutputLocation(QUrl("test.tmp"));
    QUrl s = audiocapture->outputLocation();
    QCOMPARE(s.toString(), QString("test.tmp"));
}

void tst_QMediaRecorder::testAudioRecord()
{
    QSignalSpy stateSignal(audiocapture,SIGNAL(stateChanged(QMediaRecorder::State)));
    QCOMPARE(audiocapture->state(), QMediaRecorder::StoppedState);
    QTest::qWait(500);  // wait for recorder to initialize itself
    audiocapture->setOutputLocation(recordPathAudio(QDir::rootPath()));
    audiocapture->record();
    QTRY_COMPARE(stateSignal.count(), 1); // wait for callbacks to complete in symbian API
    QCOMPARE(audiocapture->state(), QMediaRecorder::RecordingState);
    QCOMPARE(audiocapture->error(), QMediaRecorder::NoError);
    QCOMPARE(audiocapture->errorString(), QString());
    QCOMPARE(stateSignal.count(), 1);
    audiocapture->pause();
    QTRY_COMPARE(stateSignal.count(), 2); // wait for callbacks to complete in symbian API
    QCOMPARE(audiocapture->state(), QMediaRecorder::PausedState);
    QCOMPARE(stateSignal.count(), 2);
    audiocapture->stop();
    QTRY_COMPARE(stateSignal.count(), 3); // wait for callbacks to complete in symbian API
    QCOMPARE(audiocapture->state(), QMediaRecorder::StoppedState);
    QCOMPARE(stateSignal.count(), 3);
}

void tst_QMediaRecorder::testAudioRecordWithAMR()
{
    QSignalSpy stateSignal(audiocapture,SIGNAL(stateChanged(QMediaRecorder::State)));
    QCOMPARE(audiocapture->state(), QMediaRecorder::StoppedState);
    audiocapture->setOutputLocation(recordPathAudio(QDir::rootPath()));
    QAudioEncoderSettings audioSettings;
    QVideoEncoderSettings videoSettings;
    audioSettings.setCodec("AMR");
    QString format = audiocapture->containerMimeType();
    format = QString("audio/amr");
    audiocapture->setEncodingSettings(audioSettings,videoSettings,format);
    audiocapture->record();
    QTRY_COMPARE(stateSignal.count(), 1); // wait for callbacks to complete in symbian API
    QCOMPARE(audiocapture->state(), QMediaRecorder::RecordingState);
    QCOMPARE(audiocapture->error(), QMediaRecorder::NoError);
    QCOMPARE(audiocapture->errorString(), QString());
    QCOMPARE(stateSignal.count(), 1);
    audiocapture->pause();
    QTRY_COMPARE(stateSignal.count(), 2); // wait for callbacks to complete in symbian API
    QCOMPARE(audiocapture->state(), QMediaRecorder::PausedState);
    QCOMPARE(stateSignal.count(), 2);
    audiocapture->stop();
    QTRY_COMPARE(stateSignal.count(), 3); // wait for callbacks to complete in symbian API
    QCOMPARE(audiocapture->state(), QMediaRecorder::StoppedState);
    QCOMPARE(stateSignal.count(), 3);
}

void tst_QMediaRecorder::testAudioEndPointSelector()
{
    QSignalSpy audioSignal(audioEndpoint,SIGNAL(activeEndpointChanged(QString)));
    QVERIFY(audioEndpoint->availableEndpoints().count() == 1);
    QVERIFY(audioEndpoint->defaultEndpoint().compare("") == 0);
    audioEndpoint->setActiveEndpoint("device2");
    QVERIFY(audioEndpoint->activeEndpoint().compare("device2") == 0);
    QVERIFY(audioSignal.count() == 1);
    QVERIFY(audioEndpoint->endpointDescription("device2").compare("") == 0);
}

void tst_QMediaRecorder::testAudioEncoderControl()
{
    QStringList codecs = audiocapture->supportedAudioCodecs();
    QVERIFY(codecs.count() == 2);
    QVERIFY(audiocapture->audioCodecDescription("PCM") == "Pulse code modulation");
    QStringList options = audioEncoder->supportedEncodingOptions("PCM");
    QCOMPARE(options.count(), 3);
    QCOMPARE(audiocapture->supportedAudioSampleRates().count(), 12);
    audioEncoder->setEncodingOption("PCM", "channels", QVariant(2));
    QCOMPARE(audioEncoder->encodingOption("PCM","channels").toInt(), 2);
    audioEncoder->setEncodingOption("PCM", "quality", QVariant(int(QtMultimedia::NormalQuality)));
    QCOMPARE(audioEncoder->encodingOption("PCM","quality").toInt(), int(QtMultimedia::NormalQuality));
    audioEncoder->setEncodingOption("PCM", "samplerate", QVariant(44100));
    QCOMPARE(audioEncoder->encodingOption("PCM","samplerate").toInt(), 44100);
}

void tst_QMediaRecorder::testMediaFormatsControl()
{
    //audioocontainer types
    QCOMPARE(audiocapture->supportedContainers(), QStringList() << "audio/wav" << "audio/amr");
    QCOMPARE(audiocapture->containerDescription("audio/wav"), QString("WAV Write Format"));
    QCOMPARE(audiocapture->containerDescription("audio/amr"), QString("AMR Write Format"));
}

void tst_QMediaRecorder::testDefaultAudioEncodingSettings()
{
    QAudioEncoderSettings audioSettings = audiocapture->audioSettings();
    QCOMPARE(audioSettings.codec(), QString("AMR"));
    QString format = audiocapture->containerMimeType();
    QCOMPARE(format, QString("audio/amr"));
}

QTEST_MAIN(tst_QMediaRecorder)

#include "tst_qmediarecorder_s60.moc"
<commit_msg>QAudioCaptureSource has the service.<commit_after>/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights.  These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include <QtTest/QtTest>
#include <QDebug>
#include <qmediaobject.h>
#include <qmediacontrol.h>
#include <qmediaservice.h>
#include <qmediarecordercontrol.h>
#include <qmediarecorder.h>
#include <qaudioendpointselector.h>
#include <qaudioencodercontrol.h>
#include <qmediacontainercontrol.h>
#include <qaudioformat.h>
#include <qaudiocapturesource.h>

#define QTRY_COMPARE(a,e)                       \
    for (int _i = 0; _i < 5000; _i += 100) {    \
        if ((a) == (e)) break;                  \
        QTest::qWait(100);                      \
    }                                           \
    QCOMPARE(a, e)

#define QTRY_VERIFY(a)                       \
    for (int _i = 0; _i < 5000; _i += 100) {    \
        if (a) break;                  \
        QTest::qWait(100);                      \
    }                                           \
    QVERIFY(a)

QT_USE_NAMESPACE
class tst_QMediaRecorder: public QObject
{
    Q_OBJECT

public slots:
    void initTestCase();
    void cleanupTestCase();

private slots:
    void testAudioSink();
    void testAudioRecord();
    void testAudioRecordWithAMR();
    void testAudioEndPointSelector();
    void testAudioEncoderControl();
    void testMediaFormatsControl();
    void testDefaultAudioEncodingSettings();

private:
    QUrl recordPathAudio(QDir outputDir);

    QAudioEncoderControl *audioEncoder;
    QAudioEndpointSelector *audioEndpoint;
    QMediaRecorder  *audiocapture;
    QAudioCaptureSource *captureSource;
};

void tst_QMediaRecorder::initTestCase()
{
    qRegisterMetaType<QMediaRecorder::State>("QMediaRecorder::State");
    qRegisterMetaType<QMediaRecorder::Error>("QMediaRecorder::Error");

    captureSource = new QAudioCaptureSource;
    audiocapture = new QMediaRecorder(captureSource);

    audioEndpoint = qobject_cast<QAudioEndpointSelector*>(captureSource->service()->requestControl(QAudioEndpointSelector_iid));
    audioEncoder = qobject_cast<QAudioEncoderControl*>(captureSource->service()->requestControl(QAudioEncoderControl_iid));
}

void tst_QMediaRecorder::cleanupTestCase()
{
    delete audiocapture;
    delete captureSource;
}

QUrl tst_QMediaRecorder::recordPathAudio(QDir outputDir)
{
    int lastImage = 0;
    int fileCount = 0;
    foreach( QString fileName, outputDir.entryList(QStringList() << "testclip_*.amr") ) {
        int imgNumber = fileName.mid(5, fileName.size()-9).toInt();
        lastImage = qMax(lastImage, imgNumber);
        if (outputDir.exists(fileName))
            fileCount+=1;
    }
    lastImage+=fileCount;

    QUrl location(QDir::toNativeSeparators(outputDir.canonicalPath()+QString("/testclip_%1.amr").arg(lastImage+1,4,10,QLatin1Char('0'))));
    return location;
}

void tst_QMediaRecorder::testAudioSink()
{
    audiocapture->setOutputLocation(QUrl("test.tmp"));
    QUrl s = audiocapture->outputLocation();
    QCOMPARE(s.toString(), QString("test.tmp"));
}

void tst_QMediaRecorder::testAudioRecord()
{
    QSignalSpy stateSignal(audiocapture,SIGNAL(stateChanged(QMediaRecorder::State)));
    QCOMPARE(audiocapture->state(), QMediaRecorder::StoppedState);
    QTest::qWait(500);  // wait for recorder to initialize itself
    audiocapture->setOutputLocation(recordPathAudio(QDir::rootPath()));
    audiocapture->record();
    QTRY_COMPARE(stateSignal.count(), 1); // wait for callbacks to complete in symbian API
    QCOMPARE(audiocapture->state(), QMediaRecorder::RecordingState);
    QCOMPARE(audiocapture->error(), QMediaRecorder::NoError);
    QCOMPARE(audiocapture->errorString(), QString());
    QCOMPARE(stateSignal.count(), 1);
    audiocapture->pause();
    QTRY_COMPARE(stateSignal.count(), 2); // wait for callbacks to complete in symbian API
    QCOMPARE(audiocapture->state(), QMediaRecorder::PausedState);
    QCOMPARE(stateSignal.count(), 2);
    audiocapture->stop();
    QTRY_COMPARE(stateSignal.count(), 3); // wait for callbacks to complete in symbian API
    QCOMPARE(audiocapture->state(), QMediaRecorder::StoppedState);
    QCOMPARE(stateSignal.count(), 3);
}

void tst_QMediaRecorder::testAudioRecordWithAMR()
{
    QSignalSpy stateSignal(audiocapture,SIGNAL(stateChanged(QMediaRecorder::State)));
    QCOMPARE(audiocapture->state(), QMediaRecorder::StoppedState);
    audiocapture->setOutputLocation(recordPathAudio(QDir::rootPath()));
    QAudioEncoderSettings audioSettings;
    QVideoEncoderSettings videoSettings;
    audioSettings.setCodec("AMR");
    QString format = audiocapture->containerMimeType();
    format = QString("audio/amr");
    audiocapture->setEncodingSettings(audioSettings,videoSettings,format);
    audiocapture->record();
    QTRY_COMPARE(stateSignal.count(), 1); // wait for callbacks to complete in symbian API
    QCOMPARE(audiocapture->state(), QMediaRecorder::RecordingState);
    QCOMPARE(audiocapture->error(), QMediaRecorder::NoError);
    QCOMPARE(audiocapture->errorString(), QString());
    QCOMPARE(stateSignal.count(), 1);
    audiocapture->pause();
    QTRY_COMPARE(stateSignal.count(), 2); // wait for callbacks to complete in symbian API
    QCOMPARE(audiocapture->state(), QMediaRecorder::PausedState);
    QCOMPARE(stateSignal.count(), 2);
    audiocapture->stop();
    QTRY_COMPARE(stateSignal.count(), 3); // wait for callbacks to complete in symbian API
    QCOMPARE(audiocapture->state(), QMediaRecorder::StoppedState);
    QCOMPARE(stateSignal.count(), 3);
}

void tst_QMediaRecorder::testAudioEndPointSelector()
{
    QSignalSpy audioSignal(audioEndpoint,SIGNAL(activeEndpointChanged(QString)));
    QVERIFY(audioEndpoint->availableEndpoints().count() == 1);
    QVERIFY(audioEndpoint->defaultEndpoint().compare("") == 0);
    audioEndpoint->setActiveEndpoint("device2");
    QVERIFY(audioEndpoint->activeEndpoint().compare("device2") == 0);
    QVERIFY(audioSignal.count() == 1);
    QVERIFY(audioEndpoint->endpointDescription("device2").compare("") == 0);
}

void tst_QMediaRecorder::testAudioEncoderControl()
{
    QStringList codecs = audiocapture->supportedAudioCodecs();
    QVERIFY(codecs.count() == 2);
    QVERIFY(audiocapture->audioCodecDescription("PCM") == "Pulse code modulation");
    QStringList options = audioEncoder->supportedEncodingOptions("PCM");
    QCOMPARE(options.count(), 3);
    QCOMPARE(audiocapture->supportedAudioSampleRates().count(), 12);
    audioEncoder->setEncodingOption("PCM", "channels", QVariant(2));
    QCOMPARE(audioEncoder->encodingOption("PCM","channels").toInt(), 2);
    audioEncoder->setEncodingOption("PCM", "quality", QVariant(int(QtMultimedia::NormalQuality)));
    QCOMPARE(audioEncoder->encodingOption("PCM","quality").toInt(), int(QtMultimedia::NormalQuality));
    audioEncoder->setEncodingOption("PCM", "samplerate", QVariant(44100));
    QCOMPARE(audioEncoder->encodingOption("PCM","samplerate").toInt(), 44100);
}

void tst_QMediaRecorder::testMediaFormatsControl()
{
    //audioocontainer types
    QCOMPARE(audiocapture->supportedContainers(), QStringList() << "audio/wav" << "audio/amr");
    QCOMPARE(audiocapture->containerDescription("audio/wav"), QString("WAV Write Format"));
    QCOMPARE(audiocapture->containerDescription("audio/amr"), QString("AMR Write Format"));
}

void tst_QMediaRecorder::testDefaultAudioEncodingSettings()
{
    QAudioEncoderSettings audioSettings = audiocapture->audioSettings();
    QCOMPARE(audioSettings.codec(), QString("AMR"));
    QString format = audiocapture->containerMimeType();
    QCOMPARE(format, QString("audio/amr"));
}

QTEST_MAIN(tst_QMediaRecorder)

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


<commit_before><commit_msg>fix for test include header The include path was made for a windows enviroment, silly me. Fixed that now<commit_after><|endoftext|>


<commit_before>#ifndef TURBO_MEMORY_BLOCK_HPP
#define TURBO_MEMORY_BLOCK_HPP

#include <cstdint>
#include <memory>
#include <stdexcept>
#include <turbo/container/mpmc_ring_queue.hpp>

namespace turbo {
namespace memory {

class out_of_memory_error : public std::runtime_error
{
public:
    explicit out_of_memory_error(const std::string& what);
    explicit out_of_memory_error(const char* what);
};

class invalid_size_error : public std::invalid_argument
{
public:
    explicit invalid_size_error(const std::string& what);
    explicit invalid_size_error(const char* what);
};

class invalid_alignment_error : public std::invalid_argument
{
public:
    explicit invalid_alignment_error(const std::string& what);
    explicit invalid_alignment_error(const char* what);
};

class invalid_pointer_error : public std::invalid_argument
{
public:
    explicit invalid_pointer_error(const std::string& what);
    explicit invalid_pointer_error(const char* what);
};

class block
{
public:
    typedef std::uint32_t capacity_type;
    block(std::size_t value_size, capacity_type capacity);
    block(std::size_t value_size, capacity_type capacity, std::size_t alignment);
    inline std::size_t get_capacity() const { return capacity_; }
    inline std::size_t get_usable_size() const { return usable_size_; }
    inline const void* get_base_address() const { return base_; }
    void* allocate();
    void free(void* pointer);
private:
    typedef turbo::container::mpmc_ring_queue<capacity_type> free_list_type;
    block() = delete;
    block(const block&) = delete;
    block(block&&) = delete;
    block& operator=(const block&) = delete;
    block& operator=(block&&) = delete;
    std::size_t value_size_;
    std::size_t capacity_;
    std::size_t usable_size_;
    std::unique_ptr<std::uint8_t[]> storage_;
    std::uint8_t* base_;
    free_list_type free_list_;
};

} // namespace memory
} // namespace turbo

#endif
<commit_msg>added symbol declaration attribute<commit_after>#ifndef TURBO_MEMORY_BLOCK_HPP
#define TURBO_MEMORY_BLOCK_HPP

#include <cstdint>
#include <memory>
#include <stdexcept>
#include <turbo/container/mpmc_ring_queue.hpp>
#include <turbo/toolset/attribute.hpp>

namespace turbo {
namespace memory {

class out_of_memory_error : public std::runtime_error
{
public:
    explicit out_of_memory_error(const std::string& what);
    explicit out_of_memory_error(const char* what);
};

class invalid_size_error : public std::invalid_argument
{
public:
    explicit invalid_size_error(const std::string& what);
    explicit invalid_size_error(const char* what);
};

class invalid_alignment_error : public std::invalid_argument
{
public:
    explicit invalid_alignment_error(const std::string& what);
    explicit invalid_alignment_error(const char* what);
};

class invalid_pointer_error : public std::invalid_argument
{
public:
    explicit invalid_pointer_error(const std::string& what);
    explicit invalid_pointer_error(const char* what);
};

class TURBO_SYMBOL_DECL block
{
public:
    typedef std::uint32_t capacity_type;
    block(std::size_t value_size, capacity_type capacity);
    block(std::size_t value_size, capacity_type capacity, std::size_t alignment);
    inline std::size_t get_capacity() const { return capacity_; }
    inline std::size_t get_usable_size() const { return usable_size_; }
    inline const void* get_base_address() const { return base_; }
    void* allocate();
    void free(void* pointer);
private:
    typedef turbo::container::mpmc_ring_queue<capacity_type> free_list_type;
    block() = delete;
    block(const block&) = delete;
    block(block&&) = delete;
    block& operator=(const block&) = delete;
    block& operator=(block&&) = delete;
    std::size_t value_size_;
    std::size_t capacity_;
    std::size_t usable_size_;
    std::unique_ptr<std::uint8_t[]> storage_;
    std::uint8_t* base_;
    free_list_type free_list_;
};

} // namespace memory
} // namespace turbo

#endif
<|endoftext|>


<commit_before>#include <debug.hpp>
#include <item.hpp>
#include <dish.hpp>
#include <food.hpp>

#include <QString>

#include <mainWindow.hpp>
#include "ui_mainWindow.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow {parent},
    ui {new Ui::MainWindow},
    itemStringList {new QStringList},
    dishStringList {new QStringList},
    itemListModel {new QStringListModel {*itemStringList, NULL}},
    dishListModel {new QStringListModel {*dishStringList, NULL}},
    itemForm {new ItemForm} {

    ui->setupUi(this);

    ui->listView_1->setModel(itemListModel);
    ui->listView_2->setModel(dishListModel);

    for ( auto& entry: itemForm->avaliableItems ) {
        itemStringList->append(QString::fromStdString(entry->getName()));
    }

    for ( auto& entry: itemForm->avaliableDish ) {
        dishStringList->append(QString::fromStdString(entry->getName()));
    }

    itemListModel->setStringList(*itemStringList);
    dishListModel->setStringList(*dishStringList);

    PRINT_OBJ("MainWindow created");
}

MainWindow::~MainWindow() {
    delete ui;
    delete itemStringList;
    delete dishStringList;
    delete itemListModel;
    delete dishListModel;

    PRINT_OBJ("MainWindow destroyed");
}

void MainWindow::on_pushButton_1_clicked() {
    NewIngridientWindow newIngridientWindow;

    QObject::connect(&newIngridientWindow, SIGNAL(itemObjectReady(Item *)), this, SLOT(addNewItemObject(Item *)));
    QObject::connect(&newIngridientWindow, SIGNAL(foodObjectReady(Food *)), this, SLOT(addNewFoodObject(Food *)));

    newIngridientWindow.exec();
}

void MainWindow::on_pushButton_2_clicked() {
    QModelIndexList selected = ui->listView_1->selectionModel()->selectedIndexes();

    if ( !selected.isEmpty() ) {
        const QModelIndex index = itemListModel->index(selected.first().row()?selected.first().row()-1:0);
        std::list<Item *>::iterator item = itemForm->avaliableItems.begin();

        std::advance(item, selected.first().row());
        itemForm->avaliableItems.erase(item);

        itemStringList->removeAt(selected.first().row());
        itemListModel->setStringList(*itemStringList);

        if ( itemStringList->size() ) {
            ui->listView_1->setCurrentIndex(index);
            displayListViewInfoItem(index);
        }

        ui->textEdit_1->clear();
   }
}

void MainWindow::on_pushButton_3_clicked() {
    NewDishWindow newDishWindow;

    newDishWindow.exec();
}

void MainWindow::on_pushButton_5_clicked() {
    if ( infoWindowType == ITEM || infoWindowType == FOOD ) {
        NewIngridientWindow newIngridientWindow;

        newIngridientWindow.exec();
    } else if ( infoWindowType == DISH ) {
        NewDishWindow newDishWindow;

        newDishWindow.exec();
    }
}

void MainWindow::on_listView_1_clicked(const QModelIndex &index) {
    displayListViewInfoItem(index);

    PRINT_DEBUG("Clicked item/food: " << index.data().toString().toStdString());
}

void MainWindow::on_listView_2_clicked(const QModelIndex &index) {
    displayListViewInfoDish(index);

    PRINT_DEBUG("Clicked dish: " << index.data().toString().toStdString());
}

void MainWindow::on_listView_1_entered(const QModelIndex &index) {
    displayListViewInfoItem(index);

    PRINT_DEBUG("Entered item/food: " << index.data().toString().toStdString());
}

void MainWindow::on_listView_2_entered(const QModelIndex &index) {
    displayListViewInfoDish(index);

    PRINT_DEBUG("Entered dish: " << index.data().toString().toStdString());
}

void MainWindow::addNewItemObject(Item *item) {
    QModelIndex index;

    itemStringList->append(QString::fromStdString(item->getName()));
    itemListModel->setStringList(*itemStringList);

    itemForm->avaliableItems.push_back(item);

    index = itemListModel->index(itemForm->avaliableItems.size()-1);
    ui->listView_1->setCurrentIndex(index);
    displayListViewInfoItem(index);

    PRINT_DEBUG("New item added");
}

void MainWindow::addNewFoodObject(Food *food) {
    QModelIndex index;

    itemStringList->append(QString::fromStdString(food->getName()));
    itemListModel->setStringList(*itemStringList);

    itemForm->avaliableItems.push_back(food);

    index = itemListModel->index(itemForm->avaliableItems.size()-1);
    ui->listView_1->setCurrentIndex(index);
    displayListViewInfoItem(index);

    PRINT_DEBUG("New food added");
}

void MainWindow::displayListViewInfoItem(const QModelIndex &index) {
    std::list<Item *>::iterator item = itemForm->avaliableItems.begin();
    QString itemInfo;

    std::advance(item, index.row());

    if ( dynamic_cast<Food *>(*item) ) {
        infoWindowType = FOOD;
    } else {
        infoWindowType = ITEM;
    }

    itemInfo += "Name: " + QString::fromStdString((*item)->getName()) + "\n";
    itemInfo += "Price: " + QString::number((*item)->getPrice()) + "\n";
    itemInfo += "Mass: " + QString::number((*item)->getMass()) + "\n";

    if ( infoWindowType == FOOD ) {
       itemInfo += "Fats: " + QString::number((*item)->getFats()) + "\n";
       itemInfo += "Proteins: "+ QString::number((*item)->getProteins()) + "\n";
       itemInfo += "Carbohydrates: " + QString::number((*item)->getCarbohydrates()) + "\n";
       itemInfo += "Calories: " + QString::number((*item)->getCalories()) + "\n";
    }

    ui->textEdit_1->setText(itemInfo);
}

void MainWindow::displayListViewInfoDish(const QModelIndex &index) {
    std::list<Dish *>::iterator item = itemForm->avaliableDish.begin();
    QString itemInfo;

    std::advance(item, index.row());

    infoWindowType = DISH;

    itemInfo += "Name: " + QString::fromStdString((*item)->getName()) + "\n";
    itemInfo += "Price: " + QString::number((*item)->getPrice()) + "\n";
    itemInfo += "Mass: " + QString::number((*item)->getMass()) + "\n";
    itemInfo += "Fats: " + QString::number((*item)->getFats()) + "\n";
    itemInfo += "Proteins: " + QString::number((*item)->getProteins()) + "\n";
    itemInfo += "Carbohydrates: " + QString::number((*item)->getCarbohydrates()) + "\n";
    itemInfo += "Calories: " + QString::number((*item)->getCalories()) + "\n\n";
    itemInfo += "Amount of people: " + QString::number((*item)->getAmountOfPeople()) + "\n\n";
    itemInfo += "Ingridients:\n";

    for ( auto& entry: (*item)->getIngridientMap() ) {
        itemInfo += QString::fromStdString(entry.first.getName()) + " (";
        itemInfo += QString::number(entry.second) + ")\n";
    }

    ui->textEdit_1->setText(itemInfo);
}
<commit_msg>mainWindow: Clear stats view only in case of empty list<commit_after>#include <debug.hpp>
#include <item.hpp>
#include <dish.hpp>
#include <food.hpp>

#include <QString>

#include <mainWindow.hpp>
#include "ui_mainWindow.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow {parent},
    ui {new Ui::MainWindow},
    itemStringList {new QStringList},
    dishStringList {new QStringList},
    itemListModel {new QStringListModel {*itemStringList, NULL}},
    dishListModel {new QStringListModel {*dishStringList, NULL}},
    itemForm {new ItemForm} {

    ui->setupUi(this);

    ui->listView_1->setModel(itemListModel);
    ui->listView_2->setModel(dishListModel);

    for ( auto& entry: itemForm->avaliableItems ) {
        itemStringList->append(QString::fromStdString(entry->getName()));
    }

    for ( auto& entry: itemForm->avaliableDish ) {
        dishStringList->append(QString::fromStdString(entry->getName()));
    }

    itemListModel->setStringList(*itemStringList);
    dishListModel->setStringList(*dishStringList);

    PRINT_OBJ("MainWindow created");
}

MainWindow::~MainWindow() {
    delete ui;
    delete itemStringList;
    delete dishStringList;
    delete itemListModel;
    delete dishListModel;

    PRINT_OBJ("MainWindow destroyed");
}

void MainWindow::on_pushButton_1_clicked() {
    NewIngridientWindow newIngridientWindow;

    QObject::connect(&newIngridientWindow, SIGNAL(itemObjectReady(Item *)), this, SLOT(addNewItemObject(Item *)));
    QObject::connect(&newIngridientWindow, SIGNAL(foodObjectReady(Food *)), this, SLOT(addNewFoodObject(Food *)));

    newIngridientWindow.exec();
}

void MainWindow::on_pushButton_2_clicked() {
    QModelIndexList selected = ui->listView_1->selectionModel()->selectedIndexes();

    if ( !selected.isEmpty() ) {
        const QModelIndex index = itemListModel->index(selected.first().row()?selected.first().row()-1:0);
        std::list<Item *>::iterator item = itemForm->avaliableItems.begin();

        std::advance(item, selected.first().row());
        itemForm->avaliableItems.erase(item);

        itemStringList->removeAt(selected.first().row());
        itemListModel->setStringList(*itemStringList);

        if ( itemStringList->size() ) {
            ui->listView_1->setCurrentIndex(index);
            displayListViewInfoItem(index);
        } else {
            ui->textEdit_1->clear();
        }
   }
}

void MainWindow::on_pushButton_3_clicked() {
    NewDishWindow newDishWindow;

    newDishWindow.exec();
}

void MainWindow::on_pushButton_5_clicked() {
    if ( infoWindowType == ITEM || infoWindowType == FOOD ) {
        NewIngridientWindow newIngridientWindow;

        newIngridientWindow.exec();
    } else if ( infoWindowType == DISH ) {
        NewDishWindow newDishWindow;

        newDishWindow.exec();
    }
}

void MainWindow::on_listView_1_clicked(const QModelIndex &index) {
    displayListViewInfoItem(index);

    PRINT_DEBUG("Clicked item/food: " << index.data().toString().toStdString());
}

void MainWindow::on_listView_2_clicked(const QModelIndex &index) {
    displayListViewInfoDish(index);

    PRINT_DEBUG("Clicked dish: " << index.data().toString().toStdString());
}

void MainWindow::on_listView_1_entered(const QModelIndex &index) {
    displayListViewInfoItem(index);

    PRINT_DEBUG("Entered item/food: " << index.data().toString().toStdString());
}

void MainWindow::on_listView_2_entered(const QModelIndex &index) {
    displayListViewInfoDish(index);

    PRINT_DEBUG("Entered dish: " << index.data().toString().toStdString());
}

void MainWindow::addNewItemObject(Item *item) {
    QModelIndex index;

    itemStringList->append(QString::fromStdString(item->getName()));
    itemListModel->setStringList(*itemStringList);

    itemForm->avaliableItems.push_back(item);

    index = itemListModel->index(itemForm->avaliableItems.size()-1);
    ui->listView_1->setCurrentIndex(index);
    displayListViewInfoItem(index);

    PRINT_DEBUG("New item added");
}

void MainWindow::addNewFoodObject(Food *food) {
    QModelIndex index;

    itemStringList->append(QString::fromStdString(food->getName()));
    itemListModel->setStringList(*itemStringList);

    itemForm->avaliableItems.push_back(food);

    index = itemListModel->index(itemForm->avaliableItems.size()-1);
    ui->listView_1->setCurrentIndex(index);
    displayListViewInfoItem(index);

    PRINT_DEBUG("New food added");
}

void MainWindow::displayListViewInfoItem(const QModelIndex &index) {
    std::list<Item *>::iterator item = itemForm->avaliableItems.begin();
    QString itemInfo;

    std::advance(item, index.row());

    if ( dynamic_cast<Food *>(*item) ) {
        infoWindowType = FOOD;
    } else {
        infoWindowType = ITEM;
    }

    itemInfo += "Name: " + QString::fromStdString((*item)->getName()) + "\n";
    itemInfo += "Price: " + QString::number((*item)->getPrice()) + "\n";
    itemInfo += "Mass: " + QString::number((*item)->getMass()) + "\n";

    if ( infoWindowType == FOOD ) {
       itemInfo += "Fats: " + QString::number((*item)->getFats()) + "\n";
       itemInfo += "Proteins: "+ QString::number((*item)->getProteins()) + "\n";
       itemInfo += "Carbohydrates: " + QString::number((*item)->getCarbohydrates()) + "\n";
       itemInfo += "Calories: " + QString::number((*item)->getCalories()) + "\n";
    }

    ui->textEdit_1->setText(itemInfo);
}

void MainWindow::displayListViewInfoDish(const QModelIndex &index) {
    std::list<Dish *>::iterator item = itemForm->avaliableDish.begin();
    QString itemInfo;

    std::advance(item, index.row());

    infoWindowType = DISH;

    itemInfo += "Name: " + QString::fromStdString((*item)->getName()) + "\n";
    itemInfo += "Price: " + QString::number((*item)->getPrice()) + "\n";
    itemInfo += "Mass: " + QString::number((*item)->getMass()) + "\n";
    itemInfo += "Fats: " + QString::number((*item)->getFats()) + "\n";
    itemInfo += "Proteins: " + QString::number((*item)->getProteins()) + "\n";
    itemInfo += "Carbohydrates: " + QString::number((*item)->getCarbohydrates()) + "\n";
    itemInfo += "Calories: " + QString::number((*item)->getCalories()) + "\n\n";
    itemInfo += "Amount of people: " + QString::number((*item)->getAmountOfPeople()) + "\n\n";
    itemInfo += "Ingridients:\n";

    for ( auto& entry: (*item)->getIngridientMap() ) {
        itemInfo += QString::fromStdString(entry.first.getName()) + " (";
        itemInfo += QString::number(entry.second) + ")\n";
    }

    ui->textEdit_1->setText(itemInfo);
}
<|endoftext|>