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

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

#include "volumepopup.h"

#include "pulseaudiodevice.h"

#include <qtxdg/xdgicon.h>

#include <QtGui/QSlider>
#include <QtGui/QToolButton>
#include <QtGui/QVBoxLayout>
#include <QtGui/QApplication>
#include <QtGui/QDesktopWidget>

VolumePopup::VolumePopup(QWidget* parent):
    QWidget(parent,  Qt::Dialog | Qt::WindowStaysOnTopHint | Qt::CustomizeWindowHint | Qt::X11BypassWindowManagerHint),
    m_pos(0,0),
    m_anchor(Qt::TopLeftCorner)
{
    m_volumeSlider = new QSlider(Qt::Vertical, this);
    m_mixerButton = new QToolButton(this);
    m_mixerButton->setIcon(XdgIcon::fromTheme(QStringList() << "kmix"));

    QVBoxLayout *l = new QVBoxLayout(this);
    l->setSpacing(0);
    l->setMargin(0);

    l->addWidget(m_volumeSlider, 0, Qt::AlignHCenter);
    l->addWidget(m_mixerButton);

    setLayout(new QVBoxLayout(this));

    connect(m_mixerButton, SIGNAL(clicked()), this, SLOT(launchMixer()));
    connect(m_volumeSlider, SIGNAL(valueChanged(int)), this, SLOT(handleSliderValueChanged(int)));
}

VolumePopup::~VolumePopup()
{
}

void VolumePopup::enterEvent(QEvent *event)
{
    emit mouseEnter();
}

void VolumePopup::leaveEvent(QEvent *event)
{
    emit mouseExit();
}

void VolumePopup::launchMixer()
{
    qWarning("try to launch mixer.");
}

void VolumePopup::handleSliderValueChanged(int value)
{
    if (!m_device)
        return;

    m_device->setVolume(value);
}

void VolumePopup::resizeEvent(QResizeEvent *event)
{
    QWidget::resizeEvent(event);
    realign();
}

void VolumePopup::open(QPoint pos, Qt::Corner anchor)
{
    m_pos = pos;
    m_anchor = anchor;
    realign();
    show();
}

void VolumePopup::handleWheelEvent(QWheelEvent *event)
{
    m_volumeSlider->event(reinterpret_cast<QEvent*>(event));
}

void VolumePopup::setDevice(PulseAudioDevice *device)
{
    if (device == m_device)
        return;

    // disconnect old device
    disconnect(m_device, SIGNAL(volumeChanged(int)), m_volumeSlider, SLOT(setValue(int)));
    disconnect(m_volumeSlider, SIGNAL(valueChanged(int)), this, SLOT(handleSliderValueChanged(int)));

    m_device = device;
    connect(m_device, SIGNAL(volumeChanged(int)), m_volumeSlider, SLOT(setValue(int)));
    connect(m_volumeSlider, SIGNAL(valueChanged(int)), this, SLOT(handleSliderValueChanged(int)));
}

void VolumePopup::realign()
{
    QRect rect;
    rect.setSize(sizeHint());
    switch (m_anchor)
    {
    case Qt::TopLeftCorner:
        rect.moveTopLeft(m_pos);
        break;

    case Qt::TopRightCorner:
        rect.moveTopRight(m_pos);
        break;

    case Qt::BottomLeftCorner:
        rect.moveBottomLeft(m_pos);
        break;

    case Qt::BottomRightCorner:
        rect.moveBottomRight(m_pos);
        break;

    }

    QRect screen = QApplication::desktop()->availableGeometry(m_pos);

    if (rect.right() > screen.right())
        rect.moveRight(screen.right());

    if (rect.bottom() > screen.bottom())
        rect.moveBottom(screen.bottom());

    move(rect.topLeft());
}

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

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

#include "volumepopup.h"

#include "pulseaudiodevice.h"

#include <qtxdg/xdgicon.h>

#include <QtGui/QSlider>
#include <QtGui/QToolButton>
#include <QtGui/QVBoxLayout>
#include <QtGui/QApplication>
#include <QtGui/QDesktopWidget>

VolumePopup::VolumePopup(QWidget* parent):
    QWidget(parent,  Qt::Dialog | Qt::WindowStaysOnTopHint | Qt::CustomizeWindowHint | Qt::X11BypassWindowManagerHint),
    m_pos(0,0),
    m_anchor(Qt::TopLeftCorner),
    m_device(0)
{
    m_volumeSlider = new QSlider(Qt::Vertical, this);
    m_mixerButton = new QToolButton(this);
    m_mixerButton->setIcon(XdgIcon::fromTheme(QStringList() << "kmix"));

    QVBoxLayout *l = new QVBoxLayout(this);
    l->setSpacing(0);
    l->setMargin(0);

    l->addWidget(m_volumeSlider, 0, Qt::AlignHCenter);
    l->addWidget(m_mixerButton);

    setLayout(new QVBoxLayout(this));

    connect(m_mixerButton, SIGNAL(clicked()), this, SLOT(launchMixer()));
    connect(m_volumeSlider, SIGNAL(valueChanged(int)), this, SLOT(handleSliderValueChanged(int)));
}

VolumePopup::~VolumePopup()
{
}

void VolumePopup::enterEvent(QEvent *event)
{
    emit mouseEnter();
}

void VolumePopup::leaveEvent(QEvent *event)
{
    emit mouseExit();
}

void VolumePopup::launchMixer()
{
    qWarning("try to launch mixer.");
}

void VolumePopup::handleSliderValueChanged(int value)
{
    if (!m_device)
        return;

    m_device->setVolume(value);
}

void VolumePopup::resizeEvent(QResizeEvent *event)
{
    QWidget::resizeEvent(event);
    realign();
}

void VolumePopup::open(QPoint pos, Qt::Corner anchor)
{
    m_pos = pos;
    m_anchor = anchor;
    realign();
    show();
}

void VolumePopup::handleWheelEvent(QWheelEvent *event)
{
    m_volumeSlider->event(reinterpret_cast<QEvent*>(event));
}

void VolumePopup::setDevice(PulseAudioDevice *device)
{
    if (device == m_device)
        return;

    // disconnect old device
    if (m_device) {
        disconnect(m_device, SIGNAL(volumeChanged(int)), m_volumeSlider, SLOT(setValue(int)));
        disconnect(m_volumeSlider, SIGNAL(valueChanged(int)), this, SLOT(handleSliderValueChanged(int)));
    }

    m_device = device;
    connect(m_device, SIGNAL(volumeChanged(int)), m_volumeSlider, SLOT(setValue(int)));
    connect(m_volumeSlider, SIGNAL(valueChanged(int)), this, SLOT(handleSliderValueChanged(int)));
}

void VolumePopup::realign()
{
    QRect rect;
    rect.setSize(sizeHint());
    switch (m_anchor)
    {
    case Qt::TopLeftCorner:
        rect.moveTopLeft(m_pos);
        break;

    case Qt::TopRightCorner:
        rect.moveTopRight(m_pos);
        break;

    case Qt::BottomLeftCorner:
        rect.moveBottomLeft(m_pos);
        break;

    case Qt::BottomRightCorner:
        rect.moveBottomRight(m_pos);
        break;

    }

    QRect screen = QApplication::desktop()->availableGeometry(m_pos);

    if (rect.right() > screen.right())
        rect.moveRight(screen.right());

    if (rect.bottom() > screen.bottom())
        rect.moveBottom(screen.bottom());

    move(rect.topLeft());
}

<|endoftext|>


<commit_before>/*
 * Copyright (c) 2000-2004 The Regents of The University of Michigan
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders 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.
 */

///
/// @file sim/main.cc
///
#include <sys/types.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <signal.h>

#include <list>
#include <string>
#include <vector>

#include "base/copyright.hh"
#include "base/embedfile.hh"
#include "base/inifile.hh"
#include "base/misc.hh"
#include "base/pollevent.hh"
#include "base/statistics.hh"
#include "base/str.hh"
#include "base/time.hh"
#include "cpu/base_cpu.hh"
#include "cpu/full_cpu/smt.hh"
#include "sim/async.hh"
#include "sim/builder.hh"
#include "sim/configfile.hh"
#include "sim/host.hh"
#include "sim/sim_events.hh"
#include "sim/sim_exit.hh"
#include "sim/sim_object.hh"
#include "sim/stat_control.hh"
#include "sim/stats.hh"
#include "sim/universe.hh"
#include "sim/pyconfig/pyconfig.hh"

using namespace std;

// See async.h.
volatile bool async_event = false;
volatile bool async_dump = false;
volatile bool async_dumpreset = false;
volatile bool async_exit = false;
volatile bool async_io = false;
volatile bool async_alarm = false;

/// Stats signal handler.
void
dumpStatsHandler(int sigtype)
{
    async_event = true;
    async_dump = true;
}

void
dumprstStatsHandler(int sigtype)
{
    async_event = true;
    async_dumpreset = true;
}

/// Exit signal handler.
void
exitNowHandler(int sigtype)
{
    async_event = true;
    async_exit = true;
}

/// Abort signal handler.
void
abortHandler(int sigtype)
{
    cerr << "Program aborted at cycle " << curTick << endl;

#if TRACING_ON
    // dump trace buffer, if there is one
    Trace::theLog.dump(cerr);
#endif
}

/// Simulator executable name
const char *myProgName = "";

/// Show brief help message.
static void
showBriefHelp(ostream &out)
{
    out << "Usage: " << myProgName
        << " [-hnu] [-Dname[=def]] [-Uname] [-I[dir]] "
        << "<config-spec> [<config-spec> ...]\n"
        << "[] [<config file> ...]\n"
        << "   -h: print long help (including parameter listing)\n"
        << "   -u: don't quit on unreferenced parameters\n"
        << "   -D,-U,-I: passed to cpp for preprocessing .ini files\n"
        << "   <config-spec>: config file name (.ini or .py) or\n"
        << "                  single param (--<section>:<param>=<value>)"
        << endl;
}

/// Show verbose help message.  Includes parameter listing from
/// showBriefHelp(), plus an exhaustive list of ini-file parameters
/// and SimObjects (with their parameters).
static void
showLongHelp(ostream &out)
{
    showBriefHelp(out);

    out << endl
        << endl
        << "-----------------" << endl
        << "Global Parameters" << endl
        << "-----------------" << endl
        << endl;

    ParamContext::describeAllContexts(out);

    out << endl
        << endl
        << "-----------------" << endl
        << "Simulator Objects" << endl
        << "-----------------" << endl
        << endl;

    SimObjectClass::describeAllClasses(out);
}

/// Print welcome message.
static void
sayHello(ostream &out)
{
    extern const char *compileDate;	// from date.cc

    ccprintf(out, "M5 Simulator System\n");
    // display copyright
    ccprintf(out, "%s\n", briefCopyright);
    ccprintf(out, "M5 compiled on %d\n", compileDate);

    char *host = getenv("HOSTNAME");
    if (!host)
        host = getenv("HOST");

    if (host)
        ccprintf(out, "M5 executing on %s\n", host);

    ccprintf(out, "M5 simulation started %s\n", Time::start);
}

///
/// Echo the command line for posterity in such a way that it can be
/// used to rerun the same simulation (given the same .ini files).
///
static void
echoCommandLine(int argc, char **argv, ostream &out)
{
    out << "command line: " << argv[0];
    for (int i = 1; i < argc; i++) {
        string arg(argv[i]);

        out << ' ';

        // If the arg contains spaces, we need to quote it.
        // The rest of this is overkill to make it look purty.

        // print dashes first outside quotes
        int non_dash_pos = arg.find_first_not_of("-");
        out << arg.substr(0, non_dash_pos);	// print dashes
        string body = arg.substr(non_dash_pos);	// the rest

        // if it's an assignment, handle the lhs & rhs separately
        int eq_pos = body.find("=");
        if (eq_pos == string::npos) {
            out << quote(body);
        }
        else {
            string lhs(body.substr(0, eq_pos));
            string rhs(body.substr(eq_pos + 1));

            out << quote(lhs) << "=" << quote(rhs);
        }
    }
    out << endl << endl;
}

///
/// The simulator configuration database.  This is the union of all
/// specified .ini files.  This shouldn't need to be visible outside
/// this file, as it is passed as a parameter to all the param-parsing
/// routines.
///
static IniFile simConfigDB;

/// M5 entry point.
int
main(int argc, char **argv)
{
    // Save off program name
    myProgName = argv[0];

    signal(SIGFPE, SIG_IGN);		// may occur on misspeculated paths
    signal(SIGTRAP, SIG_IGN);
    signal(SIGUSR1, dumpStatsHandler);		// dump intermediate stats
    signal(SIGUSR2, dumprstStatsHandler);	// dump and reset stats
    signal(SIGINT, exitNowHandler);		// dump final stats and exit
    signal(SIGABRT, abortHandler);

    sayHello(cerr);

    // Initialize statistics database
    Stats::InitSimStats();

    vector<char *> cppArgs;

    // Should we quit if there are unreferenced parameters?  By
    // default, yes... it's a good way of catching typos in
    // section/parameter names (which otherwise go by silently).  Use
    // -u to override.
    bool quitOnUnreferenced = true;

    bool python_initialized = false;

    // Parse command-line options.
    // Since most of the complex options are handled through the
    // config database, we don't mess with getopts, and just parse
    // manually.
    for (int i = 1; i < argc; ++i) {
        char *arg_str = argv[i];

        // if arg starts with '-', parse as option,
        // else treat it as a configuration file name and load it
        if (arg_str[0] == '-') {

            // switch on second char
            switch (arg_str[1]) {
              case 'X': {
                  list<EmbedFile> lst;
                  EmbedMap::all(lst);
                  list<EmbedFile>::iterator i = lst.begin();
                  list<EmbedFile>::iterator end = lst.end();

                  while (i != end) {
                      cprintf("Embedded File: %s\n", i->name);
                      cout.write(i->data, i->length);
                      ++i;
                  }

                  return 0;
              }

              case 'h':
                // -h: show help
                showLongHelp(cerr);
                exit(1);

              case 'u':
                // -u: don't quit on unreferenced parameters
                quitOnUnreferenced = false;
                break;

              case 'D':
              case 'U':
                // cpp options: record & pass to cpp.  Note that these
                // cannot have spaces, i.e., '-Dname=val' is OK, but
                // '-D name=val' is not.  I don't consider this a
                // problem, since even though gnu cpp accepts the
                // latter, other cpp implementations do not (Tru64,
                // for one).
                cppArgs.push_back(arg_str);
                break;

              case 'I': {
                  // We push -I as an argument to cpp
                  cppArgs.push_back(arg_str);

                  string arg = arg_str + 2;
                  eat_white(arg);

                  // Send this as the python path
                  addPythonPath(arg);
              } break;

              case 'P':
                if (!python_initialized) {
                    initPythonConfig();
                    python_initialized = true;
                }
                writePythonString(arg_str + 2);
                writePythonString("\n");

              case 'E':
                if (putenv(arg_str + 2) == -1)
                    panic("putenv: %s\n", strerror(errno));
                break;

              case '-':
                // command-line configuration parameter:
                // '--<section>:<parameter>=<value>'
                if (!simConfigDB.add(arg_str + 2)) {
                    // parse error
                    ccprintf(cerr,
                             "Could not parse configuration argument '%s'\n"
                             "Expecting --<section>:<parameter>=<value>\n",
                             arg_str);
                    exit(0);
                }
                break;

              default:
                showBriefHelp(cerr);
                ccprintf(cerr, "Fatal: invalid argument '%s'\n", arg_str);
                exit(0);
            }
        }
        else {
            // no '-', treat as config file name

            // make STL string out of file name
            string filename(arg_str);

            int ext_loc = filename.rfind(".");

            string ext =
                (ext_loc != string::npos) ? filename.substr(ext_loc) : "";

            if (ext == ".ini") {
                if (!simConfigDB.loadCPP(filename, cppArgs)) {
                    cprintf("Error processing file %s\n", filename);
                    exit(1);
                }
            } else if (ext == ".py" || ext == ".mpy") {
                if (!python_initialized) {
                    initPythonConfig();
                    python_initialized = true;
                }
                loadPythonConfig(filename);
            }
            else {
                cprintf("Config file name '%s' must end in '.py' or '.ini'.\n",
                        filename);
                exit(1);
            }
        }
    }

    if (python_initialized && finishPythonConfig(simConfigDB)) {
        cprintf("Error processing python code\n");
        exit(1);
    }

    // The configuration database is now complete; start processing it.

    // Parse and check all non-config-hierarchy parameters.
    ParamContext::parseAllContexts(simConfigDB);
    ParamContext::checkAllContexts();

    // Print header info into stats file.  Can't do this sooner since
    // the stat file name is set via a .ini param... thus it just got
    // opened above during ParamContext::checkAllContexts().

    // Now process the configuration hierarchy and create the SimObjects.
    ConfigHierarchy configHierarchy(simConfigDB);
    configHierarchy.build();
    configHierarchy.createSimObjects();

    // Print hello message to stats file if it's actually a file.  If
    // it's not (i.e. it's cout or cerr) then we already did it above.
    if (outputStream != &cout && outputStream != &cerr)
        sayHello(*outputStream);

    // Echo command line and all parameter settings to stats file as well.
    echoCommandLine(argc, argv, *outputStream);
    ParamContext::showAllContexts(*configStream);

    // Do a second pass to finish initializing the sim objects
    SimObject::initAll();

    // Restore checkpointed state, if any.
    configHierarchy.unserializeSimObjects();

    // Done processing the configuration database.
    // Check for unreferenced entries.
    if (simConfigDB.printUnreferenced() && quitOnUnreferenced) {
        cerr << "Fatal: unreferenced .ini sections/entries." << endl
             << "If this is not an error, add 'unref_section_ok=y' or "
             << "'unref_entries_ok=y' to the appropriate sections "
             << "to suppress this message." << endl;
        exit(1);
    }

    SimObject::regAllStats();

    // uncomment the following to get PC-based execution-time profile
#ifdef DO_PROFILE
    init_profile((char *)&_init, (char *)&_fini);
#endif

    // Check to make sure that the stats package is properly initialized
    Stats::check();

    // Reset to put the stats in a consistent state.
    Stats::reset();

    // Nothing to simulate if we don't have at least one CPU somewhere.
    if (BaseCPU::numSimulatedCPUs() == 0) {
        cerr << "Fatal: no CPUs to simulate." << endl;
        exit(1);
    }

    warn("Entering event queue.  Starting simulation...\n");
    SimStartup();
    while (!mainEventQueue.empty()) {
        assert(curTick <= mainEventQueue.nextTick() &&
               "event scheduled in the past");

        // forward current cycle to the time of the first event on the
        // queue
        curTick = mainEventQueue.nextTick();
        mainEventQueue.serviceOne();

        if (async_event) {
            async_event = false;
            if (async_dump) {
                async_dump = false;

                using namespace Stats;
                SetupEvent(Dump, curTick);
            }

            if (async_dumpreset) {
                async_dumpreset = false;

                using namespace Stats;
                SetupEvent(Dump | Reset, curTick);
            }

            if (async_exit) {
                async_exit = false;
                new SimExitEvent("User requested STOP");
            }

            if (async_io || async_alarm) {
                async_io = false;
                async_alarm = false;
                pollQueue.service();
            }
        }
    }

    // This should never happen... every conceivable way for the
    // simulation to terminate (hit max cycles/insts, signal,
    // simulated system halts/exits) generates an exit event, so we
    // should never run out of events on the queue.
    exitNow("no events on event loop!  All CPUs must be idle.", 1);

    return 0;
}
<commit_msg>get the exit condition for the python code right<commit_after>/*
 * Copyright (c) 2000-2004 The Regents of The University of Michigan
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders 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.
 */

///
/// @file sim/main.cc
///
#include <sys/types.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <signal.h>

#include <list>
#include <string>
#include <vector>

#include "base/copyright.hh"
#include "base/embedfile.hh"
#include "base/inifile.hh"
#include "base/misc.hh"
#include "base/pollevent.hh"
#include "base/statistics.hh"
#include "base/str.hh"
#include "base/time.hh"
#include "cpu/base_cpu.hh"
#include "cpu/full_cpu/smt.hh"
#include "sim/async.hh"
#include "sim/builder.hh"
#include "sim/configfile.hh"
#include "sim/host.hh"
#include "sim/sim_events.hh"
#include "sim/sim_exit.hh"
#include "sim/sim_object.hh"
#include "sim/stat_control.hh"
#include "sim/stats.hh"
#include "sim/universe.hh"
#include "sim/pyconfig/pyconfig.hh"

using namespace std;

// See async.h.
volatile bool async_event = false;
volatile bool async_dump = false;
volatile bool async_dumpreset = false;
volatile bool async_exit = false;
volatile bool async_io = false;
volatile bool async_alarm = false;

/// Stats signal handler.
void
dumpStatsHandler(int sigtype)
{
    async_event = true;
    async_dump = true;
}

void
dumprstStatsHandler(int sigtype)
{
    async_event = true;
    async_dumpreset = true;
}

/// Exit signal handler.
void
exitNowHandler(int sigtype)
{
    async_event = true;
    async_exit = true;
}

/// Abort signal handler.
void
abortHandler(int sigtype)
{
    cerr << "Program aborted at cycle " << curTick << endl;

#if TRACING_ON
    // dump trace buffer, if there is one
    Trace::theLog.dump(cerr);
#endif
}

/// Simulator executable name
const char *myProgName = "";

/// Show brief help message.
static void
showBriefHelp(ostream &out)
{
    out << "Usage: " << myProgName
        << " [-hnu] [-Dname[=def]] [-Uname] [-I[dir]] "
        << "<config-spec> [<config-spec> ...]\n"
        << "[] [<config file> ...]\n"
        << "   -h: print long help (including parameter listing)\n"
        << "   -u: don't quit on unreferenced parameters\n"
        << "   -D,-U,-I: passed to cpp for preprocessing .ini files\n"
        << "   <config-spec>: config file name (.ini or .py) or\n"
        << "                  single param (--<section>:<param>=<value>)"
        << endl;
}

/// Show verbose help message.  Includes parameter listing from
/// showBriefHelp(), plus an exhaustive list of ini-file parameters
/// and SimObjects (with their parameters).
static void
showLongHelp(ostream &out)
{
    showBriefHelp(out);

    out << endl
        << endl
        << "-----------------" << endl
        << "Global Parameters" << endl
        << "-----------------" << endl
        << endl;

    ParamContext::describeAllContexts(out);

    out << endl
        << endl
        << "-----------------" << endl
        << "Simulator Objects" << endl
        << "-----------------" << endl
        << endl;

    SimObjectClass::describeAllClasses(out);
}

/// Print welcome message.
static void
sayHello(ostream &out)
{
    extern const char *compileDate;	// from date.cc

    ccprintf(out, "M5 Simulator System\n");
    // display copyright
    ccprintf(out, "%s\n", briefCopyright);
    ccprintf(out, "M5 compiled on %d\n", compileDate);

    char *host = getenv("HOSTNAME");
    if (!host)
        host = getenv("HOST");

    if (host)
        ccprintf(out, "M5 executing on %s\n", host);

    ccprintf(out, "M5 simulation started %s\n", Time::start);
}

///
/// Echo the command line for posterity in such a way that it can be
/// used to rerun the same simulation (given the same .ini files).
///
static void
echoCommandLine(int argc, char **argv, ostream &out)
{
    out << "command line: " << argv[0];
    for (int i = 1; i < argc; i++) {
        string arg(argv[i]);

        out << ' ';

        // If the arg contains spaces, we need to quote it.
        // The rest of this is overkill to make it look purty.

        // print dashes first outside quotes
        int non_dash_pos = arg.find_first_not_of("-");
        out << arg.substr(0, non_dash_pos);	// print dashes
        string body = arg.substr(non_dash_pos);	// the rest

        // if it's an assignment, handle the lhs & rhs separately
        int eq_pos = body.find("=");
        if (eq_pos == string::npos) {
            out << quote(body);
        }
        else {
            string lhs(body.substr(0, eq_pos));
            string rhs(body.substr(eq_pos + 1));

            out << quote(lhs) << "=" << quote(rhs);
        }
    }
    out << endl << endl;
}

///
/// The simulator configuration database.  This is the union of all
/// specified .ini files.  This shouldn't need to be visible outside
/// this file, as it is passed as a parameter to all the param-parsing
/// routines.
///
static IniFile simConfigDB;

/// M5 entry point.
int
main(int argc, char **argv)
{
    // Save off program name
    myProgName = argv[0];

    signal(SIGFPE, SIG_IGN);		// may occur on misspeculated paths
    signal(SIGTRAP, SIG_IGN);
    signal(SIGUSR1, dumpStatsHandler);		// dump intermediate stats
    signal(SIGUSR2, dumprstStatsHandler);	// dump and reset stats
    signal(SIGINT, exitNowHandler);		// dump final stats and exit
    signal(SIGABRT, abortHandler);

    sayHello(cerr);

    // Initialize statistics database
    Stats::InitSimStats();

    vector<char *> cppArgs;

    // Should we quit if there are unreferenced parameters?  By
    // default, yes... it's a good way of catching typos in
    // section/parameter names (which otherwise go by silently).  Use
    // -u to override.
    bool quitOnUnreferenced = true;

    bool python_initialized = false;

    // Parse command-line options.
    // Since most of the complex options are handled through the
    // config database, we don't mess with getopts, and just parse
    // manually.
    for (int i = 1; i < argc; ++i) {
        char *arg_str = argv[i];

        // if arg starts with '-', parse as option,
        // else treat it as a configuration file name and load it
        if (arg_str[0] == '-') {

            // switch on second char
            switch (arg_str[1]) {
              case 'X': {
                  list<EmbedFile> lst;
                  EmbedMap::all(lst);
                  list<EmbedFile>::iterator i = lst.begin();
                  list<EmbedFile>::iterator end = lst.end();

                  while (i != end) {
                      cprintf("Embedded File: %s\n", i->name);
                      cout.write(i->data, i->length);
                      ++i;
                  }

                  return 0;
              }

              case 'h':
                // -h: show help
                showLongHelp(cerr);
                exit(1);

              case 'u':
                // -u: don't quit on unreferenced parameters
                quitOnUnreferenced = false;
                break;

              case 'D':
              case 'U':
                // cpp options: record & pass to cpp.  Note that these
                // cannot have spaces, i.e., '-Dname=val' is OK, but
                // '-D name=val' is not.  I don't consider this a
                // problem, since even though gnu cpp accepts the
                // latter, other cpp implementations do not (Tru64,
                // for one).
                cppArgs.push_back(arg_str);
                break;

              case 'I': {
                  // We push -I as an argument to cpp
                  cppArgs.push_back(arg_str);

                  string arg = arg_str + 2;
                  eat_white(arg);

                  // Send this as the python path
                  addPythonPath(arg);
              } break;

              case 'P':
                if (!python_initialized) {
                    initPythonConfig();
                    python_initialized = true;
                }
                writePythonString(arg_str + 2);
                writePythonString("\n");

              case 'E':
                if (putenv(arg_str + 2) == -1)
                    panic("putenv: %s\n", strerror(errno));
                break;

              case '-':
                // command-line configuration parameter:
                // '--<section>:<parameter>=<value>'
                if (!simConfigDB.add(arg_str + 2)) {
                    // parse error
                    ccprintf(cerr,
                             "Could not parse configuration argument '%s'\n"
                             "Expecting --<section>:<parameter>=<value>\n",
                             arg_str);
                    exit(0);
                }
                break;

              default:
                showBriefHelp(cerr);
                ccprintf(cerr, "Fatal: invalid argument '%s'\n", arg_str);
                exit(0);
            }
        }
        else {
            // no '-', treat as config file name

            // make STL string out of file name
            string filename(arg_str);

            int ext_loc = filename.rfind(".");

            string ext =
                (ext_loc != string::npos) ? filename.substr(ext_loc) : "";

            if (ext == ".ini") {
                if (!simConfigDB.loadCPP(filename, cppArgs)) {
                    cprintf("Error processing file %s\n", filename);
                    exit(1);
                }
            } else if (ext == ".py" || ext == ".mpy") {
                if (!python_initialized) {
                    initPythonConfig();
                    python_initialized = true;
                }
                loadPythonConfig(filename);
            }
            else {
                cprintf("Config file name '%s' must end in '.py' or '.ini'.\n",
                        filename);
                exit(1);
            }
        }
    }

    if (python_initialized && !finishPythonConfig(simConfigDB)) {
        cprintf("Error processing python code\n");
        exit(1);
    }

    // The configuration database is now complete; start processing it.

    // Parse and check all non-config-hierarchy parameters.
    ParamContext::parseAllContexts(simConfigDB);
    ParamContext::checkAllContexts();

    // Print header info into stats file.  Can't do this sooner since
    // the stat file name is set via a .ini param... thus it just got
    // opened above during ParamContext::checkAllContexts().

    // Now process the configuration hierarchy and create the SimObjects.
    ConfigHierarchy configHierarchy(simConfigDB);
    configHierarchy.build();
    configHierarchy.createSimObjects();

    // Print hello message to stats file if it's actually a file.  If
    // it's not (i.e. it's cout or cerr) then we already did it above.
    if (outputStream != &cout && outputStream != &cerr)
        sayHello(*outputStream);

    // Echo command line and all parameter settings to stats file as well.
    echoCommandLine(argc, argv, *outputStream);
    ParamContext::showAllContexts(*configStream);

    // Do a second pass to finish initializing the sim objects
    SimObject::initAll();

    // Restore checkpointed state, if any.
    configHierarchy.unserializeSimObjects();

    // Done processing the configuration database.
    // Check for unreferenced entries.
    if (simConfigDB.printUnreferenced() && quitOnUnreferenced) {
        cerr << "Fatal: unreferenced .ini sections/entries." << endl
             << "If this is not an error, add 'unref_section_ok=y' or "
             << "'unref_entries_ok=y' to the appropriate sections "
             << "to suppress this message." << endl;
        exit(1);
    }

    SimObject::regAllStats();

    // uncomment the following to get PC-based execution-time profile
#ifdef DO_PROFILE
    init_profile((char *)&_init, (char *)&_fini);
#endif

    // Check to make sure that the stats package is properly initialized
    Stats::check();

    // Reset to put the stats in a consistent state.
    Stats::reset();

    // Nothing to simulate if we don't have at least one CPU somewhere.
    if (BaseCPU::numSimulatedCPUs() == 0) {
        cerr << "Fatal: no CPUs to simulate." << endl;
        exit(1);
    }

    warn("Entering event queue.  Starting simulation...\n");
    SimStartup();
    while (!mainEventQueue.empty()) {
        assert(curTick <= mainEventQueue.nextTick() &&
               "event scheduled in the past");

        // forward current cycle to the time of the first event on the
        // queue
        curTick = mainEventQueue.nextTick();
        mainEventQueue.serviceOne();

        if (async_event) {
            async_event = false;
            if (async_dump) {
                async_dump = false;

                using namespace Stats;
                SetupEvent(Dump, curTick);
            }

            if (async_dumpreset) {
                async_dumpreset = false;

                using namespace Stats;
                SetupEvent(Dump | Reset, curTick);
            }

            if (async_exit) {
                async_exit = false;
                new SimExitEvent("User requested STOP");
            }

            if (async_io || async_alarm) {
                async_io = false;
                async_alarm = false;
                pollQueue.service();
            }
        }
    }

    // This should never happen... every conceivable way for the
    // simulation to terminate (hit max cycles/insts, signal,
    // simulated system halts/exits) generates an exit event, so we
    // should never run out of events on the queue.
    exitNow("no events on event loop!  All CPUs must be idle.", 1);

    return 0;
}
<|endoftext|>


<commit_before>#include "global_state_annotation.h"

namespace fish_annotator {

GlobalStateAnnotation::GlobalStateAnnotation(
  std::map<std::string, bool> states)
  : states_(states) {
}

GlobalStateAnnotation::GlobalStateAnnotation()
  : states_() {
}

pt::ptree GlobalStateAnnotation::write() const {
  pt::ptree arr;
  for(auto state : states_) {
    pt::ptree tree;
    tree.put("state", state.first);
    tree.put("value", state.second);
    tree.put("type", "bool");
    arr.push_back(std::make_pair("", tree));
  }
  return arr;
}

void GlobalStateAnnotation::read(const pt::ptree &tree) {
  states_.clear();
  for(auto val : tree) {
    pt::ptree elem = val.second.get_child("");
    states_.insert(std::pair<std::string, bool>(
      elem.get<std::string>("state"),
      elem.get<std::string>("value") == "true"));
  }
}

std::string GlobalStateAnnotation::writeCsvHeader() {
  std::string header;
  for(auto state : states_) {
    header += ",";
    header += state.first;
  }
  return header;
}

std::string GlobalStateAnnotation::writeCsvValues() {
  std::string values;
  for (auto state : states_) {
    values += ",";
    values += state.second ? "1" : "0";
  }
  return values;
}

} // namespace fish_annotator
<commit_msg>Deserialize directly into bool<commit_after>#include "global_state_annotation.h"

namespace fish_annotator {

GlobalStateAnnotation::GlobalStateAnnotation(
  std::map<std::string, bool> states)
  : states_(states) {
}

GlobalStateAnnotation::GlobalStateAnnotation()
  : states_() {
}

pt::ptree GlobalStateAnnotation::write() const {
  pt::ptree arr;
  for(auto state : states_) {
    pt::ptree tree;
    tree.put("state", state.first);
    tree.put("value", state.second);
    tree.put("type", "bool");
    arr.push_back(std::make_pair("", tree));
  }
  return arr;
}

void GlobalStateAnnotation::read(const pt::ptree &tree) {
  states_.clear();
  for(auto val : tree) {
    pt::ptree elem = val.second.get_child("");
    states_.insert(std::pair<std::string, bool>(
      elem.get<std::string>("state"),
      elem.get<bool>("value")));
  }
}

std::string GlobalStateAnnotation::writeCsvHeader() {
  std::string header;
  for(auto state : states_) {
    header += ",";
    header += state.first;
  }
  return header;
}

std::string GlobalStateAnnotation::writeCsvValues() {
  std::string values;
  for (auto state : states_) {
    values += ",";
    values += state.second ? "1" : "0";
  }
  return values;
}

} // namespace fish_annotator
<|endoftext|>


<commit_before>// include google test
#include <gtest/gtest.h>

// include files to test
#include <common/PackedString.hpp>
#include <common/alphabets.hpp>
#include <common/AlphabetTraits.hpp>

class PackingTest : public ::testing::Test
{
public:
  std::vector<std::string> dna_seqs = {"", "A", "T", "C", "AC", "AAAAAAAA",
    "TTTTTT", "GG", "CACACACA", "ACTGGGCCATAATCTCTCATGGATGCTACGAGCTGATCGTAGCTGACTAGTCGA"};
};

TEST_F(PackingTest, TestPackedString1) {
  for (std::string dna : dna_seqs)
  {
    // first step: translate (in place)
    AlphabetTraits<DNA>::translateFromAscii(dna.begin(), dna.end(), dna.begin());
    // check that every letter's value is smaller than the total alphabet size
    for (char c : dna)
    {
      EXPECT_LT(static_cast<unsigned int>(c), AlphabetTraits<DNA>::getSize()) << "The value of the translated chars must be smaller than the size of the alphabet";
    }

    // then pack it
    PackedString<DNA> packedStr(dna);

    ASSERT_EQ(packedStr.size(), dna.size()) << "The packed sequence should be of same length as the original string.";

    // unpack it
    std::vector<DNA> unpacked_dna(packedStr.size());
    packedStr.unpackSequence(unpacked_dna.begin());

    // compare the vector and the given string
    for (unsigned int i = 0; i < dna.size(); ++i)
    {
      EXPECT_EQ(dna[i], unpacked_dna[i]) << "The unpacked char was not the same as the original char.";
    }
  }
}

TEST_F(PackingTest, TestPackedString2) {
  for (std::string dna : dna_seqs)
  {
    // translate into different container
    std::vector<char> dna_vec(dna.size());
    AlphabetTraits<DNA>::translateFromAscii(dna.begin(), dna.end(), dna_vec.begin());
    // check that every letter's value is smaller than the total alphabet size
    for (char c : dna_vec)
    {
      EXPECT_LT(static_cast<unsigned int>(c), AlphabetTraits<DNA>::getSize()) << "The value of the translated chars must be smaller than the size of the alphabet";
    }

    // then pack it
    PackedString<DNA> packedStr(dna_vec.begin(), dna_vec.end());

    ASSERT_EQ(packedStr.size(), dna.size()) << "The packed sequence should be of same length as the original string.";
    ASSERT_EQ(packedStr.size(), dna_vec.size()) << "The packed sequence should be of same length as the original string.";

    // unpack it
    std::string unpacked_dna(packedStr.size(),'X');
    packedStr.unpackSequence(unpacked_dna.begin());

    // translate back to ASCII (in place)
    AlphabetTraits<DNA>::translateToAscii(unpacked_dna.begin(), unpacked_dna.end(), unpacked_dna.begin());

    // compare the vector and the given string
    for (unsigned int i = 0; i < dna.size(); ++i)
    {
      EXPECT_EQ(dna[i], unpacked_dna[i]) << "The unpacked char was not the same as the original char.";
    }
  }
}<commit_msg>even more testing<commit_after>// include google test
#include <gtest/gtest.h>

// include files to test
#include <common/PackedString.hpp>
#include <common/alphabets.hpp>
#include <common/AlphabetTraits.hpp>

class PackingTest : public ::testing::Test
{
public:
  std::vector<std::string> dna_seqs = {"", "A", "T", "C", "AC", "AAAAAAAA",
    "TTTTTT", "GG", "CACACACA", "ACTGGGCCATAATCTCTCATGGATGCTACGAGCTGATCGTAGCTGACTAGTCGA",
    "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACTCTGCTCGTGATCGATCGATCGATCGATCGATCGACTAGCTAGCTACGTACGTACGTACGATCGATCGTACGATCGATCGATCGATCGATCGTACGTACGTACGTCAGCTAGCTCGATCGATATGCTAGATACACACACTACATACTCACATACACATCAACTCATACTTCATCAGACGATCGATCGATCTCGCTGATCGACTGTCGATCGTCGATCGTAGCTCGTAGCTCGTAGCTCG"
  };
};

TEST_F(PackingTest, TestPackedString1) {
  for (std::string dna : dna_seqs)
  {
    // first step: translate (in place)
    AlphabetTraits<DNA>::translateFromAscii(dna.begin(), dna.end(), dna.begin());
    // check that every letter's value is smaller than the total alphabet size
    for (char c : dna)
    {
      EXPECT_LT(static_cast<unsigned int>(c), AlphabetTraits<DNA>::getSize()) << "The value of the translated chars must be smaller than the size of the alphabet";
    }

    // then pack it
    PackedString<DNA> packedStr(dna);

    ASSERT_EQ(packedStr.size(), dna.size()) << "The packed sequence should be of same length as the original string.";

    // unpack it
    std::vector<DNA> unpacked_dna(packedStr.size());
    packedStr.unpackSequence(unpacked_dna.begin());

    // compare the vector and the given string
    for (unsigned int i = 0; i < dna.size(); ++i)
    {
      EXPECT_EQ(dna[i], unpacked_dna[i]) << "The unpacked char was not the same as the original char.";
    }
  }
}

TEST_F(PackingTest, TestPackedString2) {
  for (std::string dna : dna_seqs)
  {
    // translate into different container
    std::vector<char> dna_vec(dna.size());
    AlphabetTraits<DNA>::translateFromAscii(dna.begin(), dna.end(), dna_vec.begin());
    // check that every letter's value is smaller than the total alphabet size
    for (char c : dna_vec)
    {
      EXPECT_LT(static_cast<unsigned int>(c), AlphabetTraits<DNA>::getSize()) << "The value of the translated chars must be smaller than the size of the alphabet";
    }

    // then pack it
    PackedString<DNA> packedStr(dna_vec.begin(), dna_vec.end());

    ASSERT_EQ(packedStr.size(), dna.size()) << "The packed sequence should be of same length as the original string.";
    ASSERT_EQ(packedStr.size(), dna_vec.size()) << "The packed sequence should be of same length as the original string.";

    // unpack it into a basic_string<DNA> container
    std::basic_string<DNA> unpacked_dna(packedStr.size(),'X');
    packedStr.unpackSequence(unpacked_dna.begin());

    // compare the values using the [] operator
    for (unsigned int i = 0; i < packedStr.size(); ++i)
    {
      EXPECT_EQ(packedStr[i], unpacked_dna[i]) << "packed and unpacked strings have to compare equal";
    }

    // translate back to ASCII (in place)
    AlphabetTraits<DNA>::translateToAscii(unpacked_dna.begin(), unpacked_dna.end(), unpacked_dna.begin());

    // compare the vector and the given string
    for (unsigned int i = 0; i < dna.size(); ++i)
    {
      EXPECT_EQ(dna[i], unpacked_dna[i]) << "The unpacked char was not the same as the original char.";
    }
  }
}<|endoftext|>


<commit_before>/*
 *
 * Copyright 2015, Google Inc.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above
 * copyright notice, this list of conditions and the following disclaimer
 * in the documentation and/or other materials provided with the
 * distribution.
 *     * Neither the name of Google Inc. 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 <map>
#include <sstream>

#include "src/compiler/config.h"
#include "src/compiler/objective_c_generator.h"
#include "src/compiler/objective_c_generator_helpers.h"

#include <google/protobuf/compiler/objectivec/objectivec_helpers.h>

using ::google::protobuf::compiler::objectivec::ClassName;
using ::grpc::protobuf::io::Printer;
using ::grpc::protobuf::MethodDescriptor;
using ::grpc::protobuf::ServiceDescriptor;
using ::std::map;

namespace grpc_objective_c_generator {
namespace {

void PrintProtoRpcDeclarationAsPragma(Printer *printer,
                                      const MethodDescriptor *method,
                                      map< ::grpc::string, ::grpc::string> vars) {
  vars["client_stream"] = method->client_streaming() ? "stream " : "";
  vars["server_stream"] = method->server_streaming() ? "stream " : "";

  printer->Print(vars,
                 "#pragma mark $method_name$($client_stream$$request_type$)"
                 " returns ($server_stream$$response_type$)\n\n");
}

void PrintMethodSignature(Printer *printer, const MethodDescriptor *method,
                          const map< ::grpc::string, ::grpc::string> &vars) {
  // TODO(jcanizales): Print method comments.

  printer->Print(vars, "- ($return_type$)$method_name$With");
  if (method->client_streaming()) {
    printer->Print("RequestsWriter:(GRXWriter *)requestWriter");
  } else {
    printer->Print(vars, "Request:($request_class$ *)request");
  }

  // TODO(jcanizales): Put this on a new line and align colons.
  if (method->server_streaming()) {
    printer->Print(vars,
                   " eventHandler:(void(^)(BOOL done, "
                   "$response_class$ *_Nullable response, NSError *_Nullable error))eventHandler");
  } else {
    printer->Print(vars,
                   " handler:(void(^)($response_class$ *_Nullable response, "
                   "NSError *_Nullable error))handler");
  }
}

void PrintSimpleSignature(Printer *printer, const MethodDescriptor *method,
                          map< ::grpc::string, ::grpc::string> vars) {
  vars["method_name"] =
      grpc_generator::LowercaseFirstLetter(vars["method_name"]);
  vars["return_type"] = "void";
  PrintMethodSignature(printer, method, vars);
}

void PrintAdvancedSignature(Printer *printer, const MethodDescriptor *method,
                            map< ::grpc::string, ::grpc::string> vars) {
  vars["method_name"] = "RPCTo" + vars["method_name"];
  vars["return_type"] = "GRPCProtoCall *";
  PrintMethodSignature(printer, method, vars);
}

inline map< ::grpc::string, ::grpc::string> GetMethodVars(const MethodDescriptor *method) {
  map< ::grpc::string, ::grpc::string> res;
  res["method_name"] = method->name();
  res["request_type"] = method->input_type()->name();
  res["response_type"] = method->output_type()->name();
  res["request_class"] = ClassName(method->input_type());
  res["response_class"] = ClassName(method->output_type());
  return res;
}

void PrintMethodDeclarations(Printer *printer, const MethodDescriptor *method) {
  map< ::grpc::string, ::grpc::string> vars = GetMethodVars(method);

  PrintProtoRpcDeclarationAsPragma(printer, method, vars);

  PrintSimpleSignature(printer, method, vars);
  printer->Print(";\n\n");
  PrintAdvancedSignature(printer, method, vars);
  printer->Print(";\n\n\n");
}

void PrintSimpleImplementation(Printer *printer, const MethodDescriptor *method,
                               map< ::grpc::string, ::grpc::string> vars) {
  printer->Print("{\n");
  printer->Print(vars, "  [[self RPCTo$method_name$With");
  if (method->client_streaming()) {
    printer->Print("RequestsWriter:requestWriter");
  } else {
    printer->Print("Request:request");
  }
  if (method->server_streaming()) {
    printer->Print(" eventHandler:eventHandler] start];\n");
  } else {
    printer->Print(" handler:handler] start];\n");
  }
  printer->Print("}\n");
}

void PrintAdvancedImplementation(Printer *printer,
                                 const MethodDescriptor *method,
                                 map< ::grpc::string, ::grpc::string> vars) {
  printer->Print("{\n");
  printer->Print(vars, "  return [self RPCToMethod:@\"$method_name$\"\n");

  printer->Print("            requestsWriter:");
  if (method->client_streaming()) {
    printer->Print("requestWriter\n");
  } else {
    printer->Print("[GRXWriter writerWithValue:request]\n");
  }

  printer->Print(vars, "             responseClass:[$response_class$ class]\n");

  printer->Print("        responsesWriteable:[GRXWriteable ");
  if (method->server_streaming()) {
    printer->Print("writeableWithEventHandler:eventHandler]];\n");
  } else {
    printer->Print("writeableWithSingleHandler:handler]];\n");
  }

  printer->Print("}\n");
}

void PrintMethodImplementations(Printer *printer,
                                const MethodDescriptor *method) {
  map< ::grpc::string, ::grpc::string> vars = GetMethodVars(method);

  PrintProtoRpcDeclarationAsPragma(printer, method, vars);

  // TODO(jcanizales): Print documentation from the method.
  PrintSimpleSignature(printer, method, vars);
  PrintSimpleImplementation(printer, method, vars);

  printer->Print("// Returns a not-yet-started RPC object.\n");
  PrintAdvancedSignature(printer, method, vars);
  PrintAdvancedImplementation(printer, method, vars);
}

}  // namespace

::grpc::string GetHeader(const ServiceDescriptor *service) {
  ::grpc::string output;
  {
    // Scope the output stream so it closes and finalizes output to the string.
    grpc::protobuf::io::StringOutputStream output_stream(&output);
    Printer printer(&output_stream, '$');

    map< ::grpc::string, ::grpc::string> vars = {{"service_class", ServiceClassName(service)}};

    printer.Print(vars, "@protocol $service_class$ <NSObject>\n\n");

    for (int i = 0; i < service->method_count(); i++) {
      PrintMethodDeclarations(&printer, service->method(i));
    }
    printer.Print("@end\n\n");

    printer.Print(
        "// Basic service implementation, over gRPC, that only does"
        " marshalling and parsing.\n");
    printer.Print(vars,
                  "@interface $service_class$ :"
                  " GRPCProtoService<$service_class$>\n");
    printer.Print(
        "- (instancetype)initWithHost:(NSString *)host"
        " NS_DESIGNATED_INITIALIZER;\n");
    printer.Print("+ (instancetype)serviceWithHost:(NSString *)host;\n");
    printer.Print("@end\n");
  }
  return output;
}

::grpc::string GetSource(const ServiceDescriptor *service) {
 ::grpc::string output;
  {
    // Scope the output stream so it closes and finalizes output to the string.
    grpc::protobuf::io::StringOutputStream output_stream(&output);
    Printer printer(&output_stream, '$');

    map< ::grpc::string,::grpc::string> vars = {{"service_name", service->name()},
                                {"service_class", ServiceClassName(service)},
                                {"package", service->file()->package()}};

    printer.Print(vars,
                  "static NSString *const kPackageName = @\"$package$\";\n");
    printer.Print(
        vars, "static NSString *const kServiceName = @\"$service_name$\";\n\n");

    printer.Print(vars, "@implementation $service_class$\n\n");

    printer.Print("// Designated initializer\n");
    printer.Print("- (instancetype)initWithHost:(NSString *)host {\n");
    printer.Print(
        "  return (self = [super initWithHost:host"
        " packageName:kPackageName serviceName:kServiceName]);\n");
    printer.Print("}\n\n");
    printer.Print(
        "// Override superclass initializer to disallow different"
        " package and service names.\n");
    printer.Print("- (instancetype)initWithHost:(NSString *)host\n");
    printer.Print("                 packageName:(NSString *)packageName\n");
    printer.Print("                 serviceName:(NSString *)serviceName {\n");
    printer.Print("  return [self initWithHost:host];\n");
    printer.Print("}\n\n");
    printer.Print("+ (instancetype)serviceWithHost:(NSString *)host {\n");
    printer.Print("  return [[self alloc] initWithHost:host];\n");
    printer.Print("}\n\n\n");

    for (int i = 0; i < service->method_count(); i++) {
      PrintMethodImplementations(&printer, service->method(i));
    }

    printer.Print("@end\n");
  }
  return output;
}

}  // namespace grpc_objective_c_generator
<commit_msg>fix for #6834<commit_after>/*
 *
 * Copyright 2015, Google Inc.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above
 * copyright notice, this list of conditions and the following disclaimer
 * in the documentation and/or other materials provided with the
 * distribution.
 *     * Neither the name of Google Inc. 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 <map>
#include <sstream>

#include "src/compiler/config.h"
#include "src/compiler/objective_c_generator.h"
#include "src/compiler/objective_c_generator_helpers.h"

#include <google/protobuf/compiler/objectivec/objectivec_helpers.h>

using ::google::protobuf::compiler::objectivec::ClassName;
using ::grpc::protobuf::io::Printer;
using ::grpc::protobuf::MethodDescriptor;
using ::grpc::protobuf::ServiceDescriptor;
using ::std::map;

namespace grpc_objective_c_generator {
namespace {

void PrintProtoRpcDeclarationAsPragma(Printer *printer,
                                      const MethodDescriptor *method,
                                      map< ::grpc::string, ::grpc::string> vars) {
  vars["client_stream"] = method->client_streaming() ? "stream " : "";
  vars["server_stream"] = method->server_streaming() ? "stream " : "";

  printer->Print(vars,
                 "#pragma mark $method_name$($client_stream$$request_type$)"
                 " returns ($server_stream$$response_type$)\n\n");
}

void PrintMethodSignature(Printer *printer, const MethodDescriptor *method,
                          const map< ::grpc::string, ::grpc::string> &vars) {
  // TODO(jcanizales): Print method comments.

  printer->Print(vars, "- ($return_type$)$method_name$With");
  if (method->client_streaming()) {
    printer->Print("RequestsWriter:(GRXWriter *)requestWriter");
  } else {
    printer->Print(vars, "Request:($request_class$ *)request");
  }

  // TODO(jcanizales): Put this on a new line and align colons.
  if (method->server_streaming()) {
    printer->Print(vars,
                   " eventHandler:(void(^)(BOOL done, "
                   "$response_class$ *_Nullable response, NSError *_Nullable error))eventHandler");
  } else {
    printer->Print(vars,
                   " handler:(void(^)($response_class$ *_Nullable response, "
                   "NSError *_Nullable error))handler");
  }
}

void PrintSimpleSignature(Printer *printer, const MethodDescriptor *method,
                          map< ::grpc::string, ::grpc::string> vars) {
  vars["method_name"] =
      grpc_generator::LowercaseFirstLetter(vars["method_name"]);
  vars["return_type"] = "void";
  PrintMethodSignature(printer, method, vars);
}

void PrintAdvancedSignature(Printer *printer, const MethodDescriptor *method,
                            map< ::grpc::string, ::grpc::string> vars) {
  vars["method_name"] = "RPCTo" + vars["method_name"];
  vars["return_type"] = "GRPCProtoCall *";
  PrintMethodSignature(printer, method, vars);
}

inline map< ::grpc::string, ::grpc::string> GetMethodVars(const MethodDescriptor *method) {
  map< ::grpc::string, ::grpc::string> res;
  res["method_name"] = method->name();
  res["request_type"] = method->input_type()->name();
  res["response_type"] = method->output_type()->name();
  res["request_class"] = ClassName(method->input_type());
  res["response_class"] = ClassName(method->output_type());
  return res;
}

void PrintMethodDeclarations(Printer *printer, const MethodDescriptor *method) {
  map< ::grpc::string, ::grpc::string> vars = GetMethodVars(method);

  PrintProtoRpcDeclarationAsPragma(printer, method, vars);

  PrintSimpleSignature(printer, method, vars);
  printer->Print(";\n\n");
  PrintAdvancedSignature(printer, method, vars);
  printer->Print(";\n\n\n");
}

void PrintSimpleImplementation(Printer *printer, const MethodDescriptor *method,
                               map< ::grpc::string, ::grpc::string> vars) {
  printer->Print("{\n");
  printer->Print(vars, "  [[self RPCTo$method_name$With");
  if (method->client_streaming()) {
    printer->Print("RequestsWriter:requestWriter");
  } else {
    printer->Print("Request:request");
  }
  if (method->server_streaming()) {
    printer->Print(" eventHandler:eventHandler] start];\n");
  } else {
    printer->Print(" handler:handler] start];\n");
  }
  printer->Print("}\n");
}

void PrintAdvancedImplementation(Printer *printer,
                                 const MethodDescriptor *method,
                                 map< ::grpc::string, ::grpc::string> vars) {
  printer->Print("{\n");
  printer->Print(vars, "  return [self RPCToMethod:@\"$method_name$\"\n");

  printer->Print("            requestsWriter:");
  if (method->client_streaming()) {
    printer->Print("requestWriter\n");
  } else {
    printer->Print("[GRXWriter writerWithValue:request]\n");
  }

  printer->Print(vars, "             responseClass:[$response_class$ class]\n");

  printer->Print("        responsesWriteable:[GRXWriteable ");
  if (method->server_streaming()) {
    printer->Print("writeableWithEventHandler:eventHandler]];\n");
  } else {
    printer->Print("writeableWithSingleHandler:handler]];\n");
  }

  printer->Print("}\n");
}

void PrintMethodImplementations(Printer *printer,
                                const MethodDescriptor *method) {
  map< ::grpc::string, ::grpc::string> vars = GetMethodVars(method);

  PrintProtoRpcDeclarationAsPragma(printer, method, vars);

  // TODO(jcanizales): Print documentation from the method.
  PrintSimpleSignature(printer, method, vars);
  PrintSimpleImplementation(printer, method, vars);

  printer->Print("// Returns a not-yet-started RPC object.\n");
  PrintAdvancedSignature(printer, method, vars);
  PrintAdvancedImplementation(printer, method, vars);
}

}  // namespace

::grpc::string GetHeader(const ServiceDescriptor *service) {
  ::grpc::string output;
  {
    // Scope the output stream so it closes and finalizes output to the string.
    grpc::protobuf::io::StringOutputStream output_stream(&output);
    Printer printer(&output_stream, '$');

    map< ::grpc::string, ::grpc::string> vars = {{"service_class", ServiceClassName(service)}};

    printer.Print(vars, "@protocol $service_class$ <NSObject>\n\n");

    for (int i = 0; i < service->method_count(); i++) {
      PrintMethodDeclarations(&printer, service->method(i));
    }
    printer.Print("@end\n\n");

    printer.Print(
        "// Basic service implementation, over gRPC, that only does"
        " marshalling and parsing.\n");
    printer.Print(vars,
                  "@interface $service_class$ :"
                  " GRPCProtoService<$service_class$>\n");
    printer.Print(
        "- (instancetype)initWithHost:(NSString *)host"
        " NS_DESIGNATED_INITIALIZER;\n");
    printer.Print("+ (instancetype)serviceWithHost:(NSString *)host;\n");
    printer.Print("@end\n");
  }
  return output;
}

::grpc::string GetSource(const ServiceDescriptor *service) {
 ::grpc::string output;
  {
    // Scope the output stream so it closes and finalizes output to the string.
    grpc::protobuf::io::StringOutputStream output_stream(&output);
    Printer printer(&output_stream, '$');

    map< ::grpc::string,::grpc::string> vars = {{"service_name", service->name()},
                                {"service_class", ServiceClassName(service)},
                                {"package", service->file()->package()}};

    printer.Print(vars, "@implementation $service_class$\n\n");

    printer.Print("// Designated initializer\n");
    printer.Print("- (instancetype)initWithHost:(NSString *)host {\n");
    printer.Print(vars,
        "  return (self = [super initWithHost:host"
        " packageName:@\"$package$\" serviceName:@\"$service_name$\"]);\n");
    printer.Print("}\n\n");
    printer.Print(
        "// Override superclass initializer to disallow different"
        " package and service names.\n");
    printer.Print("- (instancetype)initWithHost:(NSString *)host\n");
    printer.Print("                 packageName:(NSString *)packageName\n");
    printer.Print("                 serviceName:(NSString *)serviceName {\n");
    printer.Print("  return [self initWithHost:host];\n");
    printer.Print("}\n\n");
    printer.Print("+ (instancetype)serviceWithHost:(NSString *)host {\n");
    printer.Print("  return [[self alloc] initWithHost:host];\n");
    printer.Print("}\n\n\n");

    for (int i = 0; i < service->method_count(); i++) {
      PrintMethodImplementations(&printer, service->method(i));
    }

    printer.Print("@end\n");
  }
  return output;
}

}  // namespace grpc_objective_c_generator
<|endoftext|>


<commit_before>/* rapicorn-zintern - small C source compression utility
 * Copyright (C) 2003-2006 Tim Janik
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * A copy of the GNU Lesser General Public License should ship along
 * with this library; if not, see http://www.gnu.org/copyleft/.
 */
#include <rapicorn-core/rapicorn-core.hh>
#include <glib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <zlib.h>

namespace Rapicorn {

static void     zintern_error  (const char     *format,
                                ...) RAPICORN_PRINTF (1, 2);

static void
zintern_error  (const char     *format,
                ...)
{
  gchar *buffer;
  va_list args;
  va_start (args, format);
  buffer = g_strdup_vprintf (format, args);
  va_end (args);
  g_printerr ("\nERROR: %s", buffer);
  _exit (1);
  g_free (buffer);
}

static bool use_compression = FALSE;
static bool use_base_name = FALSE;

typedef struct {
  uint pos;
  bool pad;
} Config;
static Config config_init = { 0, 0 };

static inline void
print_uchar (Config *config,
	     uint8 d)
{
  if (config->pos > 70)
    {
      printf ("\"\n  \"");
      config->pos = 3;
      config->pad = FALSE;
    }
  if (d < 33 || d > 126 || d == '?')
    {
      printf ("\\%o", d);
      config->pos += 1 + 1 + (d > 7) + (d > 63);
      config->pad = d < 64;
      return;
    }
  if (d == '\\')
    {
      printf ("\\\\");
      config->pos += 2;
    }
  else if (d == '"')
    {
      printf ("\\\"");
      config->pos += 2;
    }
  else if (config->pad && d >= '0' && d <= '9')
    {
      printf ("\"\"");
      printf ("%c", d);
      config->pos += 3;
    }
  else
    {
      printf ("%c", d);
      config->pos += 1;
    }
  config->pad = FALSE;
  return;
}

#define to_upper(c)     ((c) >='a' && (c) <='z' ? (c) - 'a' + 'A' : (c))
#define is_alnum(c)     (((c) >='A' && (c) <='Z') || ((c) >='a' && (c) <='z') || ((c) >='0' && (c) <='9'))
static String
to_cupper (const String &str)
{
  String s (str);
  for (uint i = 0; i < s.size(); i++)
    if (is_alnum (s[i]))
      s[i] = to_upper (s[i]);
    else
      s[i] = '_';
  return s;
}

static void
gen_zfile (const char *name,
	   const char *file)
{
  FILE *f = fopen (file, "r");
  uint8 *data = NULL;
  uint i, dlen = 0, mlen = 0;
  Bytef *cdata;
  uLongf clen;
  gchar *basefile = g_path_get_basename (file);
  String fname = use_base_name ? basefile : file;
  g_free (basefile); basefile = NULL;
  Config config;
  if (!f)
    zintern_error ("failed to open \"%s\": %s", file, g_strerror (errno));
  do
    {
      if (mlen <= dlen + 1024)
	{
	  mlen += 8192;
	  data = g_renew (uint8, data, mlen);
	}
      dlen += fread (data + dlen, 1, mlen - dlen, f);
    }
  while (!feof (f));

  if (ferror (f))
    zintern_error ("failed to read from \"%s\": %s", file, g_strerror (errno));

  if (use_compression)
    {
      int result;
      const char *err;
      clen = dlen + dlen / 100 + 64;
      cdata = g_new (uint8, clen);
      result = compress2 (cdata, &clen, data, dlen, Z_BEST_COMPRESSION);
      switch (result)
	{
	case Z_OK:
	  err = NULL;
	  break;
	case Z_MEM_ERROR:
	  err = "out of memory";
	  break;
	case Z_BUF_ERROR:
	  err = "insufficient buffer size";
	  break;
	default:
	  err = "unknown error";
	  break;
	}
      if (err)
	zintern_error ("while compressing \"%s\": %s", file, err);
    }
  else
    {
      clen = dlen;
      cdata = data;
    }

  g_print ("/* rapicorn-zintern file dump of %s */\n", file);

  config = config_init;
  printf ("#define %s_NAME \"", to_cupper (name).c_str());
  for (i = 0; i < fname.size(); i++)
    print_uchar (&config, fname[i]);
  printf ("\"\n");

  printf ("#define %s_SIZE (%u)\n", to_cupper (name).c_str(), dlen);

  config = config_init;
  printf ("static const unsigned char %s_DATA[%lu + 1] =\n", to_cupper (name).c_str(), clen);
  printf ("( \"");
  for (i = 0; i < clen; i++)
    print_uchar (&config, cdata[i]);
  printf ("\");\n");

  fclose (f);
  g_free (data);
  if (cdata != data)
    g_free (cdata);
}

static int
help (char *arg)
{
  g_printerr ("usage: rapicorn-zintern [-h] [-b] [-z] [[name file]...]\n");
  g_printerr ("  -h  Print usage information\n");
  g_printerr ("  -b  Strip directories from file names\n");
  g_printerr ("  -z  Compress data blocks with libz\n");
  g_printerr ("Parse (name, file) pairs and generate C source\n");
  g_printerr ("containing inlined data blocks of the files given.\n");
  return arg != NULL;
}

extern "C" int
main (int   argc,
      char *argv[])
{
  GSList *plist = NULL;

  InitValue ivalues[] = {
    { "stand-alone", "true" },
    { NULL }
  };
  // rapicorn_init_core (&argc, &argv, NULL, ivalues);

  for (int i = 1; i < argc; i++)
    {
      if (strcmp ("-z", argv[i]) == 0)
	{
	  use_compression = TRUE;
	}
      else if (strcmp ("-b", argv[i]) == 0)
	{
	  use_base_name = TRUE;
	}
      else if (strcmp ("-h", argv[i]) == 0)
	{
	  return help (NULL);
	}
      else
	plist = g_slist_append (plist, argv[i]);
    }

  if (argc <= 1)
    return help (NULL);

  while (plist && plist->next)
    {
      const char *name = (char*) plist->data;
      GSList *tmp = plist;
      plist = tmp->next;
      g_slist_free_1 (tmp);
      const char *file = (char*) plist->data;
      tmp = plist;
      plist = tmp->next;
      g_slist_free_1 (tmp);
      gen_zfile (name, file);
    }

  return 0;
}

} // Rapicorn
<commit_msg>rapicorn-zintern.cc: namespace fixes and cleanups.<commit_after>/* rapicorn-zintern - small C source compression utility
 * Copyright (C) 2003-2006 Tim Janik
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * A copy of the GNU Lesser General Public License should ship along
 * with this library; if not, see http://www.gnu.org/copyleft/.
 */
#include <rapicorn-core.hh>
#include <glib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <zlib.h>

namespace {
using namespace Rapicorn;

static void     zintern_error  (const char     *format,
                                ...) RAPICORN_PRINTF (1, 2);

static void
zintern_error  (const char     *format,
                ...)
{
  gchar *buffer;
  va_list args;
  va_start (args, format);
  buffer = g_strdup_vprintf (format, args);
  va_end (args);
  g_printerr ("\nERROR: %s", buffer);
  _exit (1);
  g_free (buffer);
}

static bool use_compression = FALSE;
static bool use_base_name = FALSE;

typedef struct {
  uint pos;
  bool pad;
} Config;
static Config config_init = { 0, 0 };

static inline void
print_uchar (Config *config,
	     uint8 d)
{
  if (config->pos > 70)
    {
      printf ("\"\n  \"");
      config->pos = 3;
      config->pad = FALSE;
    }
  if (d < 33 || d > 126 || d == '?')
    {
      printf ("\\%o", d);
      config->pos += 1 + 1 + (d > 7) + (d > 63);
      config->pad = d < 64;
      return;
    }
  if (d == '\\')
    {
      printf ("\\\\");
      config->pos += 2;
    }
  else if (d == '"')
    {
      printf ("\\\"");
      config->pos += 2;
    }
  else if (config->pad && d >= '0' && d <= '9')
    {
      printf ("\"\"");
      printf ("%c", d);
      config->pos += 3;
    }
  else
    {
      printf ("%c", d);
      config->pos += 1;
    }
  config->pad = FALSE;
  return;
}

#define to_upper(c)     ((c) >='a' && (c) <='z' ? (c) - 'a' + 'A' : (c))
#define is_alnum(c)     (((c) >='A' && (c) <='Z') || ((c) >='a' && (c) <='z') || ((c) >='0' && (c) <='9'))
static String
to_cupper (const String &str)
{
  String s (str);
  for (uint i = 0; i < s.size(); i++)
    if (is_alnum (s[i]))
      s[i] = to_upper (s[i]);
    else
      s[i] = '_';
  return s;
}

static void
gen_zfile (const char *name,
	   const char *file)
{
  FILE *f = fopen (file, "r");
  uint8 *data = NULL;
  uint i, dlen = 0, mlen = 0;
  Bytef *cdata;
  uLongf clen;
  gchar *basefile = g_path_get_basename (file);
  String fname = use_base_name ? basefile : file;
  g_free (basefile); basefile = NULL;
  Config config;
  if (!f)
    zintern_error ("failed to open \"%s\": %s", file, g_strerror (errno));
  do
    {
      if (mlen <= dlen + 1024)
	{
	  mlen += 8192;
	  data = g_renew (uint8, data, mlen);
	}
      dlen += fread (data + dlen, 1, mlen - dlen, f);
    }
  while (!feof (f));

  if (ferror (f))
    zintern_error ("failed to read from \"%s\": %s", file, g_strerror (errno));

  if (use_compression)
    {
      int result;
      const char *err;
      clen = dlen + dlen / 100 + 64;
      cdata = g_new (uint8, clen);
      result = compress2 (cdata, &clen, data, dlen, Z_BEST_COMPRESSION);
      switch (result)
	{
	case Z_OK:
	  err = NULL;
	  break;
	case Z_MEM_ERROR:
	  err = "out of memory";
	  break;
	case Z_BUF_ERROR:
	  err = "insufficient buffer size";
	  break;
	default:
	  err = "unknown error";
	  break;
	}
      if (err)
	zintern_error ("while compressing \"%s\": %s", file, err);
    }
  else
    {
      clen = dlen;
      cdata = data;
    }

  g_print ("/* rapicorn-zintern file dump of %s */\n", file);

  config = config_init;
  printf ("#define %s_NAME \"", to_cupper (name).c_str());
  for (i = 0; i < fname.size(); i++)
    print_uchar (&config, fname[i]);
  printf ("\"\n");

  printf ("#define %s_SIZE (%u)\n", to_cupper (name).c_str(), dlen);

  config = config_init;
  printf ("static const unsigned char %s_DATA[%lu + 1] =\n", to_cupper (name).c_str(), clen);
  printf ("( \"");
  for (i = 0; i < clen; i++)
    print_uchar (&config, cdata[i]);
  printf ("\");\n");

  fclose (f);
  g_free (data);
  if (cdata != data)
    g_free (cdata);
}

static int
help (char *arg)
{
  g_printerr ("usage: rapicorn-zintern [-h] [-b] [-z] [[name file]...]\n");
  g_printerr ("  -h  Print usage information\n");
  g_printerr ("  -b  Strip directories from file names\n");
  g_printerr ("  -z  Compress data blocks with libz\n");
  g_printerr ("Parse (name, file) pairs and generate C source\n");
  g_printerr ("containing inlined data blocks of the files given.\n");
  return arg != NULL;
}

extern "C" int
main (int   argc,
      char *argv[])
{
  GSList *plist = NULL;

  for (int i = 1; i < argc; i++)
    {
      if (strcmp ("-z", argv[i]) == 0)
	{
	  use_compression = TRUE;
	}
      else if (strcmp ("-b", argv[i]) == 0)
	{
	  use_base_name = TRUE;
	}
      else if (strcmp ("-h", argv[i]) == 0)
	{
	  return help (NULL);
	}
      else
	plist = g_slist_append (plist, argv[i]);
    }

  if (argc <= 1)
    return help (NULL);

  while (plist && plist->next)
    {
      const char *name = (char*) plist->data;
      GSList *tmp = plist;
      plist = tmp->next;
      g_slist_free_1 (tmp);
      const char *file = (char*) plist->data;
      tmp = plist;
      plist = tmp->next;
      g_slist_free_1 (tmp);
      gen_zfile (name, file);
    }

  return 0;
}

} // anon
<|endoftext|>


<commit_before>#include "Analog.h"
#include "..\sysex\SysEx.h"
#include "..\eeprom\Configuration.h"
#include "..\interface\settings\AnalogSettings.h"

Analog::Analog()    {

    //def const

}

void Analog::init() {

    const subtype analogEnabledSubtype       = { MAX_NUMBER_OF_ANALOG, 0, 1 };
    const subtype analogInvertedSubtype      = { MAX_NUMBER_OF_ANALOG, 0, 1 };
    const subtype analogTypeSubtype          = { MAX_NUMBER_OF_ANALOG, 0, ANALOG_TYPES-1 };
    const subtype analogMIDIidSubtype        = { MAX_NUMBER_OF_ANALOG, 0, 127 };
    const subtype analogCClowerLimitSubtype  = { MAX_NUMBER_OF_ANALOG, 0, 127 };
    const subtype analogCCupperLimitSubtype  = { MAX_NUMBER_OF_ANALOG, 0, 127 };

    const subtype *analogSubtypeArray[] = {

        &analogEnabledSubtype,
        &analogTypeSubtype,
        &analogInvertedSubtype,
        &analogMIDIidSubtype,
        &analogCClowerLimitSubtype,
        &analogCCupperLimitSubtype

    };

    //define message for sysex configuration
    sysEx.addMessageType(CONF_ENCODER_BLOCK, ANALOG_SUBTYPES);

    for (int i=0; i<ANALOG_SUBTYPES; i++)   {

        //define subtype messages
        sysEx.addMessageSubType(CONF_ENCODER_BLOCK, i, analogSubtypeArray[i]->parameters, analogSubtypeArray[i]->lowValue, analogSubtypeArray[i]->highValue);

    }

}

void Analog::update()   {

    if (!board.analogDataAvailable()) return;

    int16_t analogData;

    //check values
    for (int i=0; i<MAX_NUMBER_OF_ANALOG; i++)    {

        analogData = board.getAnalogValue(i); //get raw analog reading
        if (!getAnalogEnabled(i)) continue; //don't process component if it's not enabled
        addAnalogSample(i, analogData);
        if (!analogValueSampled(i)) continue;  //three samples are needed
        analogData = getMedianValue(i);  //get median value from three analog samples for better accuracy
        analogType type = getAnalogType(i);

        switch(type) {

            case potentiometer:
            checkPotentiometerValue(i, analogData);
            break;

            case fsr:
            checkFSRvalue(i, analogData);
            break;

            case ldr:
            break;

            default:
            return;

        }

    }

}

void Analog::addAnalogSample(uint8_t analogID, int16_t sample) {

    uint8_t sampleIndex = analogDebounceCounter[analogID];

    analogSample[analogID][sampleIndex] = sample;
    analogDebounceCounter[analogID]++;

}

bool Analog::analogValueSampled(uint8_t analogID) {

    if (analogDebounceCounter[analogID] == NUMBER_OF_SAMPLES) {

        analogDebounceCounter[analogID] = 0;
        return true;

    }   return false;

}

int16_t Analog::getMedianValue(uint8_t analogID)  {

    int16_t medianValue = 0;

    if ((analogSample[analogID][0] <= analogSample[analogID][1]) && (analogSample[analogID][0] <= analogSample[analogID][2]))
    medianValue = (analogSample[analogID][1] <= analogSample[analogID][2]) ? analogSample[analogID][1] : analogSample[analogID][2];

    else if ((analogSample[analogID][1] <= analogSample[analogID][0]) && (analogSample[analogID][1] <= analogSample[analogID][2]))
    medianValue = (analogSample[analogID][0] <= analogSample[analogID][2]) ? analogSample[analogID][0] : analogSample[analogID][2];

    else
    medianValue = (analogSample[analogID][0] <= analogSample[analogID][1]) ? analogSample[analogID][0] : analogSample[analogID][1];

    return medianValue;

}

bool Analog::getAnalogEnabled(uint8_t analogID) {

    return configuration.readParameter(CONF_ANALOG_BLOCK, analogEnabledSection, analogID);

}

bool Analog::getAnalogInvertState(uint8_t analogID) {

    return configuration.readParameter(CONF_ANALOG_BLOCK, analogInvertedSection, analogID);

}

analogType Analog::getAnalogType(uint8_t analogID) {

    return (analogType)configuration.readParameter(CONF_ANALOG_BLOCK, analogTypeSection, analogID);

}

uint8_t Analog::getMIDIid(uint8_t analogID)    {

    return configuration.readParameter(CONF_ANALOG_BLOCK, analogMIDIidSection, analogID);

}

uint8_t Analog::getCClimit(uint8_t analogID, ccLimitType type)  {

    switch(type)    {

        case ccLimitLow:
        return configuration.readParameter(CONF_ANALOG_BLOCK, analogCClowerLimitSection, analogID);
        break;

        case ccLimitHigh:
        return configuration.readParameter(CONF_ANALOG_BLOCK, analogCCupperLimitSection, analogID);
        break;

    }   return 0;

}

uint8_t Analog::getParameter(uint8_t messageType, uint8_t parameter) {

    switch(messageType) {

        case analogEnabledConf:
        return getAnalogEnabled(parameter);
        break;

        case analogInvertedConf:
        return getAnalogInvertState(parameter);
        break;

        case analogTypeConf:
        return getAnalogType(parameter);
        break;

        case analogMIDIidConf:
        return getMIDIid(parameter);
        break;

        case analogCClowerLimitConf:
        return getCClimit(parameter, ccLimitLow);
        break;

        case analogCCupperLimitConf:
        return getCClimit(parameter, ccLimitHigh);
        break;

    }   return 0;

}

bool Analog::setAnalogEnabled(uint8_t analogID, uint8_t state)    {

    return configuration.writeParameter(CONF_ANALOG_BLOCK, analogEnabledSection, analogID, state);

}

bool Analog::setAnalogInvertState(uint8_t analogID, uint8_t state) {

    return configuration.writeParameter(CONF_ANALOG_BLOCK, analogInvertedSection, analogID, state);

}

bool Analog::setAnalogType(uint8_t analogID, uint8_t type)    {

    return configuration.writeParameter(CONF_ANALOG_BLOCK, analogTypeSection, analogID, type);

}

bool Analog::setMIDIid(uint8_t analogID, uint8_t midiID)   {

    return configuration.writeParameter(CONF_ANALOG_BLOCK, analogMIDIidSection, analogID, midiID);

}

bool Analog::setCClimit(ccLimitType type, uint8_t analogID, uint8_t limit)  {

    switch (limit)  {

        case ccLimitLow:
        return configuration.writeParameter(CONF_ANALOG_BLOCK, analogCClowerLimitSection, analogID, limit);
        break;

        case ccLimitHigh:
        return configuration.writeParameter(CONF_ANALOG_BLOCK, analogCCupperLimitSection, analogID, limit);
        break;

        default:
        return false;
        break;

    }

}

bool Analog::setParameter(uint8_t messageType, uint8_t parameter, uint8_t newParameter)    {

    switch(messageType) {

        case analogEnabledConf:
        return setAnalogEnabled(parameter, newParameter);
        break;

        case analogInvertedConf:
        return setAnalogInvertState(parameter, newParameter);
        break;

        case analogTypeConf:
        return setAnalogType(parameter, newParameter);
        break;

        case analogMIDIidConf:
        return setMIDIid(parameter, newParameter);
        break;

        case analogCClowerLimitConf:
        return setCClimit(ccLimitLow, parameter, newParameter);
        break;

        case analogCCupperLimitConf:
        return setCClimit(ccLimitLow, parameter, newParameter);
        break;

    }   return false;

}

Analog analog;<commit_msg>fix potential bug when changing from fsr to pot<commit_after>#include "Analog.h"
#include "..\sysex\SysEx.h"
#include "..\eeprom\Configuration.h"
#include "..\interface\settings\AnalogSettings.h"

Analog::Analog()    {

    //def const

}

void Analog::init() {

    const subtype analogEnabledSubtype       = { MAX_NUMBER_OF_ANALOG, 0, 1 };
    const subtype analogInvertedSubtype      = { MAX_NUMBER_OF_ANALOG, 0, 1 };
    const subtype analogTypeSubtype          = { MAX_NUMBER_OF_ANALOG, 0, ANALOG_TYPES-1 };
    const subtype analogMIDIidSubtype        = { MAX_NUMBER_OF_ANALOG, 0, 127 };
    const subtype analogCClowerLimitSubtype  = { MAX_NUMBER_OF_ANALOG, 0, 127 };
    const subtype analogCCupperLimitSubtype  = { MAX_NUMBER_OF_ANALOG, 0, 127 };

    const subtype *analogSubtypeArray[] = {

        &analogEnabledSubtype,
        &analogTypeSubtype,
        &analogInvertedSubtype,
        &analogMIDIidSubtype,
        &analogCClowerLimitSubtype,
        &analogCCupperLimitSubtype

    };

    //define message for sysex configuration
    sysEx.addMessageType(CONF_ENCODER_BLOCK, ANALOG_SUBTYPES);

    for (int i=0; i<ANALOG_SUBTYPES; i++)   {

        //define subtype messages
        sysEx.addMessageSubType(CONF_ENCODER_BLOCK, i, analogSubtypeArray[i]->parameters, analogSubtypeArray[i]->lowValue, analogSubtypeArray[i]->highValue);

    }

}

void Analog::update()   {

    if (!board.analogDataAvailable()) return;

    int16_t analogData;

    //check values
    for (int i=0; i<MAX_NUMBER_OF_ANALOG; i++)    {

        analogData = board.getAnalogValue(i); //get raw analog reading
        if (!getAnalogEnabled(i)) continue; //don't process component if it's not enabled
        addAnalogSample(i, analogData);
        if (!analogValueSampled(i)) continue;  //three samples are needed
        analogData = getMedianValue(i);  //get median value from three analog samples for better accuracy
        analogType type = getAnalogType(i);

        switch(type) {

            case potentiometer:
            checkPotentiometerValue(i, analogData);
            break;

            case fsr:
            checkFSRvalue(i, analogData);
            break;

            case ldr:
            break;

            default:
            return;

        }

    }

}

void Analog::addAnalogSample(uint8_t analogID, int16_t sample) {

    uint8_t sampleIndex = analogDebounceCounter[analogID];

    analogSample[analogID][sampleIndex] = sample;
    analogDebounceCounter[analogID]++;

}

bool Analog::analogValueSampled(uint8_t analogID) {

    if (analogDebounceCounter[analogID] == NUMBER_OF_SAMPLES) {

        analogDebounceCounter[analogID] = 0;
        return true;

    }   return false;

}

int16_t Analog::getMedianValue(uint8_t analogID)  {

    int16_t medianValue = 0;

    if ((analogSample[analogID][0] <= analogSample[analogID][1]) && (analogSample[analogID][0] <= analogSample[analogID][2]))
    medianValue = (analogSample[analogID][1] <= analogSample[analogID][2]) ? analogSample[analogID][1] : analogSample[analogID][2];

    else if ((analogSample[analogID][1] <= analogSample[analogID][0]) && (analogSample[analogID][1] <= analogSample[analogID][2]))
    medianValue = (analogSample[analogID][0] <= analogSample[analogID][2]) ? analogSample[analogID][0] : analogSample[analogID][2];

    else
    medianValue = (analogSample[analogID][0] <= analogSample[analogID][1]) ? analogSample[analogID][0] : analogSample[analogID][1];

    return medianValue;

}

bool Analog::getAnalogEnabled(uint8_t analogID) {

    return configuration.readParameter(CONF_ANALOG_BLOCK, analogEnabledSection, analogID);

}

bool Analog::getAnalogInvertState(uint8_t analogID) {

    return configuration.readParameter(CONF_ANALOG_BLOCK, analogInvertedSection, analogID);

}

analogType Analog::getAnalogType(uint8_t analogID) {

    return (analogType)configuration.readParameter(CONF_ANALOG_BLOCK, analogTypeSection, analogID);

}

uint8_t Analog::getMIDIid(uint8_t analogID)    {

    return configuration.readParameter(CONF_ANALOG_BLOCK, analogMIDIidSection, analogID);

}

uint8_t Analog::getCClimit(uint8_t analogID, ccLimitType type)  {

    switch(type)    {

        case ccLimitLow:
        return configuration.readParameter(CONF_ANALOG_BLOCK, analogCClowerLimitSection, analogID);
        break;

        case ccLimitHigh:
        return configuration.readParameter(CONF_ANALOG_BLOCK, analogCCupperLimitSection, analogID);
        break;

    }   return 0;

}

uint8_t Analog::getParameter(uint8_t messageType, uint8_t parameter) {

    switch(messageType) {

        case analogEnabledConf:
        return getAnalogEnabled(parameter);
        break;

        case analogInvertedConf:
        return getAnalogInvertState(parameter);
        break;

        case analogTypeConf:
        return getAnalogType(parameter);
        break;

        case analogMIDIidConf:
        return getMIDIid(parameter);
        break;

        case analogCClowerLimitConf:
        return getCClimit(parameter, ccLimitLow);
        break;

        case analogCCupperLimitConf:
        return getCClimit(parameter, ccLimitHigh);
        break;

    }   return 0;

}

bool Analog::setAnalogEnabled(uint8_t analogID, uint8_t state)    {

    return configuration.writeParameter(CONF_ANALOG_BLOCK, analogEnabledSection, analogID, state);

}

bool Analog::setAnalogInvertState(uint8_t analogID, uint8_t state) {

    return configuration.writeParameter(CONF_ANALOG_BLOCK, analogInvertedSection, analogID, state);

}

bool Analog::setAnalogType(uint8_t analogID, uint8_t type)    {

    lastAnalogueValue[analogID] = 0;

    return configuration.writeParameter(CONF_ANALOG_BLOCK, analogTypeSection, analogID, type);

}

bool Analog::setMIDIid(uint8_t analogID, uint8_t midiID)   {

    return configuration.writeParameter(CONF_ANALOG_BLOCK, analogMIDIidSection, analogID, midiID);

}

bool Analog::setCClimit(ccLimitType type, uint8_t analogID, uint8_t limit)  {

    switch (limit)  {

        case ccLimitLow:
        return configuration.writeParameter(CONF_ANALOG_BLOCK, analogCClowerLimitSection, analogID, limit);
        break;

        case ccLimitHigh:
        return configuration.writeParameter(CONF_ANALOG_BLOCK, analogCCupperLimitSection, analogID, limit);
        break;

        default:
        return false;
        break;

    }

}

bool Analog::setParameter(uint8_t messageType, uint8_t parameter, uint8_t newParameter)    {

    switch(messageType) {

        case analogEnabledConf:
        return setAnalogEnabled(parameter, newParameter);
        break;

        case analogInvertedConf:
        return setAnalogInvertState(parameter, newParameter);
        break;

        case analogTypeConf:
        return setAnalogType(parameter, newParameter);
        break;

        case analogMIDIidConf:
        return setMIDIid(parameter, newParameter);
        break;

        case analogCClowerLimitConf:
        return setCClimit(ccLimitLow, parameter, newParameter);
        break;

        case analogCCupperLimitConf:
        return setCClimit(ccLimitLow, parameter, newParameter);
        break;

    }   return false;

}

Analog analog;<|endoftext|>


<commit_before>#include "ImageStreamer.hpp"
#include "ImageImporter.hpp"
#include "DeviceManager.hpp"
#include "Exception.hpp"
using namespace fast;

/**
 * Dummy function to get into the class again
 */
inline void stubStreamThread(ImageStreamer * streamer) {
    streamer->producerStream();
}

DynamicImage::pointer ImageStreamer::getOutput() {
    mOutput->setSource(mPtr.lock());
    mOutput->setStreamer(mPtr.lock());
    return mOutput;
}

ImageStreamer::ImageStreamer() {
    mOutput = DynamicImage::New();
    mStreamIsStarted = false;
    mIsModified = true;
    thread = NULL;
    mFirstFrameIsInserted = false;
    mHasReachedEnd = false;
    mDevice = DeviceManager::getInstance().getDefaultComputationDevice();
    mFilenameFormat = "";
}

void ImageStreamer::execute() {
    mOutput->setSource(mPtr.lock());
    mOutput->setStreamer(mPtr.lock());
    if(mFilenameFormat == "")
        throw Exception("No filename format was given to the ImageStreamer");
    if(!mStreamIsStarted) {
        mStreamIsStarted = true;
        thread = new boost::thread(&stubStreamThread, this);
    }

    // Wait here for first frame
    // TODO use condition variable instead
    while(!mFirstFrameIsInserted);
}

void ImageStreamer::setFilenameFormat(std::string str) {
    if(str.find("#") == std::string::npos)
        throw Exception("Filename format must include a hash tag # which will be replaced by a integer starting from 0.");
    mFilenameFormat = str;
}

void ImageStreamer::setDevice(ExecutionDevice::pointer device) {
    mDevice = device;
}

inline std::string intToString(int number) {
    std::stringstream ss;//create a stringstream
    ss << number;//add number to the stream
    return ss.str();//return a string with the contents of the stream
}

void ImageStreamer::producerStream() {
    int i = 0;
    while(true) {
        std::string filename = mFilenameFormat;
        filename.replace(
                filename.find("#"),
                1,
                intToString(i));
        try {
            ImageImporter::pointer importer = ImageImporter::New();
            importer->setFilename(filename);
            importer->setDevice(mDevice);
            Image::pointer image = importer->getOutput();
            image->update();
            DynamicImage::pointer ptr = mOutput;
            if(ptr.isValid()) {
                ptr->addFrame(image);
                mFirstFrameIsInserted = true;
            } else {
                std::cout << "DynamicImage object destroyed, stream can stop." << std::endl;
                break;
            }
            i++;
        } catch(FileNotFoundException &e) {
            std::cout << "Reached end of stream" << std::endl;
            mHasReachedEnd = true;
            // Reached end of stream
            break;
        }
    }
}

ImageStreamer::~ImageStreamer() {
    if(mStreamIsStarted) {
        std::cout << "Joining the thread" << std::endl;
        // TODO stop thread as well
        thread->join();
        delete thread;
    }
}
bool ImageStreamer::hasReachedEnd() const {
    return mHasReachedEnd;
}
<commit_msg>avoid deadlock when destroying streamer<commit_after>#include "ImageStreamer.hpp"
#include "ImageImporter.hpp"
#include "DeviceManager.hpp"
#include "Exception.hpp"
using namespace fast;

/**
 * Dummy function to get into the class again
 */
inline void stubStreamThread(ImageStreamer * streamer) {
    streamer->producerStream();
}

DynamicImage::pointer ImageStreamer::getOutput() {
    mOutput->setSource(mPtr.lock());
    mOutput->setStreamer(mPtr.lock());
    return mOutput;
}

ImageStreamer::ImageStreamer() {
    mOutput = DynamicImage::New();
    mStreamIsStarted = false;
    mIsModified = true;
    thread = NULL;
    mFirstFrameIsInserted = false;
    mHasReachedEnd = false;
    mDevice = DeviceManager::getInstance().getDefaultComputationDevice();
    mFilenameFormat = "";
}

void ImageStreamer::execute() {
    mOutput->setSource(mPtr.lock());
    mOutput->setStreamer(mPtr.lock());
    if(mFilenameFormat == "")
        throw Exception("No filename format was given to the ImageStreamer");
    if(!mStreamIsStarted) {
        mStreamIsStarted = true;
        thread = new boost::thread(&stubStreamThread, this);
    }

    // Wait here for first frame
    // TODO use condition variable instead
    while(!mFirstFrameIsInserted);
}

void ImageStreamer::setFilenameFormat(std::string str) {
    if(str.find("#") == std::string::npos)
        throw Exception("Filename format must include a hash tag # which will be replaced by a integer starting from 0.");
    mFilenameFormat = str;
}

void ImageStreamer::setDevice(ExecutionDevice::pointer device) {
    mDevice = device;
}

inline std::string intToString(int number) {
    std::stringstream ss;//create a stringstream
    ss << number;//add number to the stream
    return ss.str();//return a string with the contents of the stream
}

void ImageStreamer::producerStream() {
    int i = 0;
    while(true) {
        std::string filename = mFilenameFormat;
        filename.replace(
                filename.find("#"),
                1,
                intToString(i));
        try {
            ImageImporter::pointer importer = ImageImporter::New();
            importer->setFilename(filename);
            importer->setDevice(mDevice);
            Image::pointer image = importer->getOutput();
            image->update();
            DynamicImage::pointer ptr = mOutput;
            if(ptr.isValid()) {
                ptr->addFrame(image);
                mFirstFrameIsInserted = true;
            } else {
                std::cout << "DynamicImage object destroyed, stream can stop." << std::endl;
                break;
            }
            i++;
        } catch(FileNotFoundException &e) {
            std::cout << "Reached end of stream" << std::endl;
            mHasReachedEnd = true;
            // Reached end of stream
            break;
        }
    }
}

ImageStreamer::~ImageStreamer() {
    if(mStreamIsStarted) {
        if(thread->get_id() != boost::this_thread::get_id()) { // avoid deadlock
            thread->join();
        }
        delete thread;
    }
}
bool ImageStreamer::hasReachedEnd() const {
    return mHasReachedEnd;
}
<|endoftext|>