<commit_before>//#define DEBUG_AGENT
#include "agent.hpp"

#include <atomic>
#include <cassert>
#include <chrono>
#include <cstdlib>
#include <functional>
#include <thread>

#include <QApplication>
#include <QtCore/QAbstractEventDispatcher>
#include <QtCore/QThread>

#include "agent_qtmonkey_communication.hpp"
#include "common.hpp"
#include "script.hpp"
#include "script_api.hpp"
#include "script_runner.hpp"
#include "user_events_analyzer.hpp"

using qt_monkey_agent::Agent;
using qt_monkey_agent::Private::PacketTypeForMonkey;
using qt_monkey_agent::Private::CommunicationAgentPart;
using qt_monkey_agent::Private::ScriptRunner;

Agent *Agent::gAgent_ = nullptr;

#define GET_THREAD(__name__)                                                   \
    auto __name__ = static_cast<AgentThread *>(thread_);                       \
    if (__name__->isFinished()) {                                              \
        return;                                                                \
    }

#ifdef DEBUG_AGENT
#define DBGPRINT(fmt, ...) qDebug(fmt, __VA_ARGS__)
#else
#define DBGPRINT(fmt, ...)                                                     \
    do {                                                                       \
    } while (false)
#endif

namespace
{
class FuncEvent final : public QEvent
{
public:
    FuncEvent(QEvent::Type type, std::function<void()> func)
        : QEvent(type), func_(std::move(func))
    {
    }
    void exec() { func_(); }
private:
    std::function<void()> func_;
};

class EventsReciever final : public QObject
{
public:
    EventsReciever()
    {
        eventType_ = static_cast<QEvent::Type>(QEvent::registerEventType());
    }
    void customEvent(QEvent *event) override
    {
        if (event->type() != eventType_)
            return;

        static_cast<FuncEvent *>(event)->exec();
    }
    QEvent::Type eventType() const { return eventType_; }
private:
    std::atomic<QEvent::Type> eventType_;
};

class AgentThread final : public QThread
{
public:
    AgentThread(QObject *parent) : QThread(parent) {}
    bool isNotReady() { return !ready_.exchange(false); }
    void run() override
    {
        CommunicationAgentPart client;
        if (!client.connectToMonkey()) {
            qWarning(
                "%s",
                qPrintable(
                    T_("%1: can not connect to qt monkey").arg(Q_FUNC_INFO)));
            return;
        }
        connect(&client, SIGNAL(error(const QString &)), parent(),
                SLOT(onCommunicationError(const QString &)),
                Qt::DirectConnection);
        connect(&client,
                SIGNAL(runScript(const qt_monkey_agent::Private::Script &)),
                parent(), SLOT(onRunScriptCommand(
                              const qt_monkey_agent::Private::Script &)),
                Qt::DirectConnection);
        EventsReciever eventReciever;
        objInThread_ = &eventReciever;
        channelWithMonkey_ = &client;
        ready_ = true;
        exec();
    }

    CommunicationAgentPart *channelWithMonkey() { return channelWithMonkey_; }

    void runInThread(std::function<void()> func)
    {
        assert(objInThread_ != nullptr);
        QCoreApplication::postEvent(
            objInThread_,
            new FuncEvent(objInThread_->eventType(), std::move(func)));
    }

private:
    std::atomic<bool> ready_{false};
    EventsReciever *objInThread_{nullptr};
    CommunicationAgentPart *channelWithMonkey_{nullptr};
};
}

Agent::Agent(const QKeySequence &showObjectShortcut,
             std::list<CustomEventAnalyzer> customEventAnalyzers,
             PopulateScriptContext psc)
    : eventAnalyzer_(new UserEventsAnalyzer(
          *this, showObjectShortcut, std::move(customEventAnalyzers), this)),
      populateScriptContextCallback_(std::move(psc))
{
    // make sure that type is referenced, fix bug with qt4 and static lib
    qMetaTypeId<qt_monkey_agent::Private::Script>();
    eventType_ = static_cast<QEvent::Type>(QEvent::registerEventType());
    connect(qApp, SIGNAL(aboutToQuit()), this, SLOT(onAppAboutToQuit()));
    connect(eventAnalyzer_, SIGNAL(userEventInScriptForm(const QString &)),
            this, SLOT(onUserEventInScriptForm(const QString &)));
    connect(eventAnalyzer_, SIGNAL(scriptLog(const QString &)), this,
            SLOT(onScriptLog(const QString &)));
    QCoreApplication::instance()->installEventFilter(eventAnalyzer_);
    thread_ = new AgentThread(this);
    thread_->start();
    while (!thread_->isFinished()
           && static_cast<AgentThread *>(thread_)->isNotReady())
        ;
    assert(gAgent_ == nullptr);
    gAgent_ = this;
}

void Agent::onCommunicationError(const QString &err)
{
    qFatal("%s: communication error %s", Q_FUNC_INFO, qPrintable(err));
    std::abort();
}

Agent::~Agent()
{
    GET_THREAD(thread)

    thread->runInThread(
        [this, thread] { thread->channelWithMonkey()->flushSendData(); });
    QCoreApplication::processEvents(QEventLoop::AllEvents, 1000 /*ms*/);
    thread->quit();
    thread->wait();
}

void Agent::onUserEventInScriptForm(const QString &script)
{
    if (script.isEmpty())
        return;
    GET_THREAD(thread)
    thread->channelWithMonkey()->sendCommand(
        PacketTypeForMonkey::NewUserAppEvent, script);
}

void Agent::onRunScriptCommand(const Private::Script &script)
{
    GET_THREAD(thread)
    assert(QThread::currentThread() == thread_);
    DBGPRINT("%s: run script", Q_FUNC_INFO);
    ScriptAPI api{*this};
    ScriptRunner sr{api, populateScriptContextCallback_};
    QString errMsg;
    {
        CurrentScriptContext context(&sr, curScriptRunner_);
        sr.runScript(script, errMsg);
    }
    if (!errMsg.isEmpty()) {
        qWarning("AGENT: %s: script return error", Q_FUNC_INFO);
        thread->channelWithMonkey()->sendCommand(
            PacketTypeForMonkey::ScriptError, errMsg);
    } else {
        DBGPRINT("%s: sync with gui", Q_FUNC_INFO);
        // if all ok, sync with gui, so user recieve all events
        // before script exit
        runCodeInGuiThreadSync([] {
            qt_monkey_common::processEventsFor(300 /*ms*/);
            DBGPRINT("%s: wait done", Q_FUNC_INFO);
            return QString();
        });
    }
    DBGPRINT("%s: report about script end", Q_FUNC_INFO);
    thread->channelWithMonkey()->sendCommand(PacketTypeForMonkey::ScriptEnd,
                                             QString());
}

void Agent::sendToLog(QString msg)
{
    DBGPRINT("%s: msg %s", Q_FUNC_INFO, qPrintable(msg));
    GET_THREAD(thread)
    thread->channelWithMonkey()->sendCommand(PacketTypeForMonkey::ScriptLog,
                                             std::move(msg));
}

void Agent::scriptCheckPoint()
{
    assert(QThread::currentThread() == thread_);
    assert(curScriptRunner_ != nullptr);
    const int lineno = curScriptRunner_->currentLineNum();
    DBGPRINT("%s: lineno %d", Q_FUNC_INFO, lineno);
}

QString Agent::runCodeInGuiThreadSync(std::function<QString()> func)
{
    assert(QThread::currentThread() == thread_);
    QString res;
    QCoreApplication::postEvent(this,
                                new FuncEvent(eventType_, [func, this, &res] {
                                    res = func();
                                    guiRunSem_.release();
                                }));
    guiRunSem_.acquire();
    return res;
}

void Agent::customEvent(QEvent *event)
{
    assert(QThread::currentThread() != thread_);
    if (event->type() != eventType_)
        return;
    static_cast<FuncEvent *>(event)->exec();
}

void Agent::throwScriptError(QString msg)
{
    assert(QThread::currentThread() == thread_);
    assert(curScriptRunner_ != nullptr);
    curScriptRunner_->throwError(std::move(msg));
}

QString Agent::runCodeInGuiThreadSyncWithTimeout(std::function<QString()> func,
                                                 int timeoutSecs)
{
    assert(QThread::currentThread() == thread_);
    QWidget *wasDialog = nullptr;
    runCodeInGuiThreadSync([&wasDialog] {
        wasDialog = qApp->activeModalWidget();
        return QString();
    });

    std::shared_ptr<QSemaphore> waitSem{new QSemaphore};
    std::shared_ptr<QString> res{new QString};
    QCoreApplication::postEvent(this,
                                new FuncEvent(eventType_, [func, waitSem, res] {
                                    *res = func();
                                    waitSem->release();
                                }));

    QWidget *nowDialog = nullptr;
    runCodeInGuiThreadSync(
        [&nowDialog] { /*this code send event internally, so
                         if new QEventLoop was created, it will
                         be executed after handling of event posted above
                        */
                       auto dispatcher = QAbstractEventDispatcher::instance(
                           QThread::currentThread());
                       if (dispatcher == nullptr)
                           return QStringLiteral("no event dispatcher");
                       // if @func cause dialog close, then process all events,
                       // to prevent post of next event to QDialog's QEventLoop
                       dispatcher->processEvents(
                           QEventLoop::ExcludeUserInputEvents);
                       nowDialog = qApp->activeModalWidget();
                       return QString();
        });
    if (nowDialog != wasDialog) {
        DBGPRINT("%s: dialog has changed\n", Q_FUNC_INFO);
        // it may not return, if @func cause new QEventLoop creation, so
        const int timeoutMsec = timeoutSecs * 1000;
        const int waitIntervalMsec = 100;
        const int N = timeoutMsec / waitIntervalMsec + 1;
        for (int attempt = 0; attempt < N; ++attempt) {
            if (waitSem->tryAcquire(1, waitIntervalMsec))
                return *res;
        }
        DBGPRINT("%s: timeout occuire", Q_FUNC_INFO);
    } else {
        DBGPRINT("%s: wait of finished event handling", Q_FUNC_INFO);
        waitSem->acquire();
        DBGPRINT("%s: wait of finished event handling DONE", Q_FUNC_INFO);
    }

    return QString();
}

void Agent::onAppAboutToQuit()
{
    qDebug("%s: begin", Q_FUNC_INFO);
    qt_monkey_common::processEventsFor(300 /*ms*/);
}

void Agent::onScriptLog(const QString &msg)
{
    assert(QThread::currentThread() != thread_);
    GET_THREAD(thread)
    thread->channelWithMonkey()->sendCommand(PacketTypeForMonkey::ScriptLog,
                                             msg);
}
<commit_msg>agent: handle no dispatcher error<commit_after>//#define DEBUG_AGENT
#include "agent.hpp"

#include <atomic>
#include <cassert>
#include <chrono>
#include <cstdlib>
#include <functional>
#include <thread>

#include <QApplication>
#include <QtCore/QAbstractEventDispatcher>
#include <QtCore/QThread>

#include "agent_qtmonkey_communication.hpp"
#include "common.hpp"
#include "script.hpp"
#include "script_api.hpp"
#include "script_runner.hpp"
#include "user_events_analyzer.hpp"

using qt_monkey_agent::Agent;
using qt_monkey_agent::Private::PacketTypeForMonkey;
using qt_monkey_agent::Private::CommunicationAgentPart;
using qt_monkey_agent::Private::ScriptRunner;

Agent *Agent::gAgent_ = nullptr;

#define GET_THREAD(__name__)                                                   \
    auto __name__ = static_cast<AgentThread *>(thread_);                       \
    if (__name__->isFinished()) {                                              \
        return;                                                                \
    }

#ifdef DEBUG_AGENT
#define DBGPRINT(fmt, ...) qDebug(fmt, __VA_ARGS__)
#else
#define DBGPRINT(fmt, ...)                                                     \
    do {                                                                       \
    } while (false)
#endif

namespace
{
class FuncEvent final : public QEvent
{
public:
    FuncEvent(QEvent::Type type, std::function<void()> func)
        : QEvent(type), func_(std::move(func))
    {
    }
    void exec() { func_(); }
private:
    std::function<void()> func_;
};

class EventsReciever final : public QObject
{
public:
    EventsReciever()
    {
        eventType_ = static_cast<QEvent::Type>(QEvent::registerEventType());
    }
    void customEvent(QEvent *event) override
    {
        if (event->type() != eventType_)
            return;

        static_cast<FuncEvent *>(event)->exec();
    }
    QEvent::Type eventType() const { return eventType_; }
private:
    std::atomic<QEvent::Type> eventType_;
};

class AgentThread final : public QThread
{
public:
    AgentThread(QObject *parent) : QThread(parent) {}
    bool isNotReady() { return !ready_.exchange(false); }
    void run() override
    {
        CommunicationAgentPart client;
        if (!client.connectToMonkey()) {
            qWarning(
                "%s",
                qPrintable(
                    T_("%1: can not connect to qt monkey").arg(Q_FUNC_INFO)));
            return;
        }
        connect(&client, SIGNAL(error(const QString &)), parent(),
                SLOT(onCommunicationError(const QString &)),
                Qt::DirectConnection);
        connect(&client,
                SIGNAL(runScript(const qt_monkey_agent::Private::Script &)),
                parent(), SLOT(onRunScriptCommand(
                              const qt_monkey_agent::Private::Script &)),
                Qt::DirectConnection);
        EventsReciever eventReciever;
        objInThread_ = &eventReciever;
        channelWithMonkey_ = &client;
        ready_ = true;
        exec();
    }

    CommunicationAgentPart *channelWithMonkey() { return channelWithMonkey_; }

    void runInThread(std::function<void()> func)
    {
        assert(objInThread_ != nullptr);
        QCoreApplication::postEvent(
            objInThread_,
            new FuncEvent(objInThread_->eventType(), std::move(func)));
    }

private:
    std::atomic<bool> ready_{false};
    EventsReciever *objInThread_{nullptr};
    CommunicationAgentPart *channelWithMonkey_{nullptr};
};
}

Agent::Agent(const QKeySequence &showObjectShortcut,
             std::list<CustomEventAnalyzer> customEventAnalyzers,
             PopulateScriptContext psc)
    : eventAnalyzer_(new UserEventsAnalyzer(
          *this, showObjectShortcut, std::move(customEventAnalyzers), this)),
      populateScriptContextCallback_(std::move(psc))
{
    // make sure that type is referenced, fix bug with qt4 and static lib
    qMetaTypeId<qt_monkey_agent::Private::Script>();
    eventType_ = static_cast<QEvent::Type>(QEvent::registerEventType());
    connect(qApp, SIGNAL(aboutToQuit()), this, SLOT(onAppAboutToQuit()));
    connect(eventAnalyzer_, SIGNAL(userEventInScriptForm(const QString &)),
            this, SLOT(onUserEventInScriptForm(const QString &)));
    connect(eventAnalyzer_, SIGNAL(scriptLog(const QString &)), this,
            SLOT(onScriptLog(const QString &)));
    QCoreApplication::instance()->installEventFilter(eventAnalyzer_);
    thread_ = new AgentThread(this);
    thread_->start();
    while (!thread_->isFinished()
           && static_cast<AgentThread *>(thread_)->isNotReady())
        ;
    assert(gAgent_ == nullptr);
    gAgent_ = this;
}

void Agent::onCommunicationError(const QString &err)
{
    qFatal("%s: communication error %s", Q_FUNC_INFO, qPrintable(err));
    std::abort();
}

Agent::~Agent()
{
    GET_THREAD(thread)

    thread->runInThread(
        [this, thread] { thread->channelWithMonkey()->flushSendData(); });
    QCoreApplication::processEvents(QEventLoop::AllEvents, 1000 /*ms*/);
    thread->quit();
    thread->wait();
}

void Agent::onUserEventInScriptForm(const QString &script)
{
    if (script.isEmpty())
        return;
    GET_THREAD(thread)
    thread->channelWithMonkey()->sendCommand(
        PacketTypeForMonkey::NewUserAppEvent, script);
}

void Agent::onRunScriptCommand(const Private::Script &script)
{
    GET_THREAD(thread)
    assert(QThread::currentThread() == thread_);
    DBGPRINT("%s: run script", Q_FUNC_INFO);
    ScriptAPI api{*this};
    ScriptRunner sr{api, populateScriptContextCallback_};
    QString errMsg;
    {
        CurrentScriptContext context(&sr, curScriptRunner_);
        sr.runScript(script, errMsg);
    }
    if (!errMsg.isEmpty()) {
        qWarning("AGENT: %s: script return error", Q_FUNC_INFO);
        thread->channelWithMonkey()->sendCommand(
            PacketTypeForMonkey::ScriptError, errMsg);
    } else {
        DBGPRINT("%s: sync with gui", Q_FUNC_INFO);
        // if all ok, sync with gui, so user recieve all events
        // before script exit
        runCodeInGuiThreadSync([] {
            qt_monkey_common::processEventsFor(300 /*ms*/);
            DBGPRINT("%s: wait done", Q_FUNC_INFO);
            return QString();
        });
    }
    DBGPRINT("%s: report about script end", Q_FUNC_INFO);
    thread->channelWithMonkey()->sendCommand(PacketTypeForMonkey::ScriptEnd,
                                             QString());
}

void Agent::sendToLog(QString msg)
{
    DBGPRINT("%s: msg %s", Q_FUNC_INFO, qPrintable(msg));
    GET_THREAD(thread)
    thread->channelWithMonkey()->sendCommand(PacketTypeForMonkey::ScriptLog,
                                             std::move(msg));
}

void Agent::scriptCheckPoint()
{
    assert(QThread::currentThread() == thread_);
    assert(curScriptRunner_ != nullptr);
    const int lineno = curScriptRunner_->currentLineNum();
    DBGPRINT("%s: lineno %d", Q_FUNC_INFO, lineno);
}

QString Agent::runCodeInGuiThreadSync(std::function<QString()> func)
{
    assert(QThread::currentThread() == thread_);
    QString res;
    QCoreApplication::postEvent(this,
                                new FuncEvent(eventType_, [func, this, &res] {
                                    res = func();
                                    guiRunSem_.release();
                                }));
    guiRunSem_.acquire();
    return res;
}

void Agent::customEvent(QEvent *event)
{
    assert(QThread::currentThread() != thread_);
    if (event->type() != eventType_)
        return;
    static_cast<FuncEvent *>(event)->exec();
}

void Agent::throwScriptError(QString msg)
{
    assert(QThread::currentThread() == thread_);
    assert(curScriptRunner_ != nullptr);
    curScriptRunner_->throwError(std::move(msg));
}

QString Agent::runCodeInGuiThreadSyncWithTimeout(std::function<QString()> func,
                                                 int timeoutSecs)
{
    assert(QThread::currentThread() == thread_);
    QWidget *wasDialog = nullptr;
    runCodeInGuiThreadSync([&wasDialog] {
        wasDialog = qApp->activeModalWidget();
        return QString();
    });

    std::shared_ptr<QSemaphore> waitSem{new QSemaphore};
    std::shared_ptr<QString> res{new QString};
    QCoreApplication::postEvent(this,
                                new FuncEvent(eventType_, [func, waitSem, res] {
                                    *res = func();
                                    waitSem->release();
                                }));

    QWidget *nowDialog = nullptr;
    const QString errMsg = runCodeInGuiThreadSync(
        [&nowDialog] { /*this code send event internally, so
                         if new QEventLoop was created, it will
                         be executed after handling of event posted above
                        */
                       auto dispatcher = QAbstractEventDispatcher::instance(
                           QThread::currentThread());
                       if (dispatcher == nullptr)
                           return QStringLiteral("no event dispatcher");
                       // if @func cause dialog close, then process all events,
                       // to prevent post of next event to QDialog's QEventLoop
                       dispatcher->processEvents(
                           QEventLoop::ExcludeUserInputEvents);
                       nowDialog = qApp->activeModalWidget();
                       return QString();
        });
    if (!errMsg.isEmpty()) {
        qWarning("%s: get errMsg %s", Q_FUNC_INFO, qPrintable(errMsg));
        return errMsg;
    }
    if (nowDialog != wasDialog) {
        DBGPRINT("%s: dialog has changed\n", Q_FUNC_INFO);
        // it may not return, if @func cause new QEventLoop creation, so
        const int timeoutMsec = timeoutSecs * 1000;
        const int waitIntervalMsec = 100;
        const int N = timeoutMsec / waitIntervalMsec + 1;
        for (int attempt = 0; attempt < N; ++attempt) {
            if (waitSem->tryAcquire(1, waitIntervalMsec))
                return *res;
        }
        DBGPRINT("%s: timeout occuire", Q_FUNC_INFO);
    } else {
        DBGPRINT("%s: wait of finished event handling", Q_FUNC_INFO);
        waitSem->acquire();
        DBGPRINT("%s: wait of finished event handling DONE", Q_FUNC_INFO);
    }

    return QString();
}

void Agent::onAppAboutToQuit()
{
    qDebug("%s: begin", Q_FUNC_INFO);
    qt_monkey_common::processEventsFor(300 /*ms*/);
}

void Agent::onScriptLog(const QString &msg)
{
    assert(QThread::currentThread() != thread_);
    GET_THREAD(thread)
    thread->channelWithMonkey()->sendCommand(PacketTypeForMonkey::ScriptLog,
                                             msg);
}
<|endoftext|>


<commit_before>// Copyright 2008, 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 "base/call_wrapper.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace {

int global_int = 0;
void set_global_int_5() {
  global_int = 5;
}
void set_global_int(int x) {
  global_int = x;
}
void set_int(int* p, int x) {
  *p = x;
}
void set_int_add2(int* p, int x, int y) {
  *p = x + y;
}
void set_int_add3(int* p, int x, int y, int z) {
  *p = x + y + z;
}
void set_int_add4(int* p, int x, int y, int z, int w) {
  *p = x + y + z + w;
}

}  // namespace

TEST(CallWrapperTest, FunctionCall) {
  // Function call with 0 arguments.
  {
    EXPECT_EQ(0, global_int);
    CallWrapper* wrapper = NewFunctionCallWrapper(set_global_int_5);

    EXPECT_EQ(0, global_int);
    wrapper->Run();
    EXPECT_EQ(5, global_int);
  }
  // Function call with 1 argument.
  {
    EXPECT_EQ(5, global_int);
    CallWrapper* wrapper = NewFunctionCallWrapper(set_global_int, 0);

    EXPECT_EQ(5, global_int);
    wrapper->Run();
    EXPECT_EQ(0, global_int);
  }
  // Function call with 2 arguments.
  {
    int stack_int = 4;
    CallWrapper* wrapper;

    wrapper = NewFunctionCallWrapper(set_int, &global_int, 8);
    EXPECT_EQ(4, stack_int);
    EXPECT_EQ(0, global_int);
    wrapper->Run();
    EXPECT_EQ(4, stack_int);
    EXPECT_EQ(8, global_int);

    wrapper = NewFunctionCallWrapper(set_int, &stack_int, 8);
    EXPECT_EQ(4, stack_int);
    EXPECT_EQ(8, global_int);
    wrapper->Run();
    EXPECT_EQ(8, stack_int);
    EXPECT_EQ(8, global_int);
  }
  // Function call with 3-5 arguments.
  {
    int stack_int = 12;
    CallWrapper* wrapper;

    wrapper = NewFunctionCallWrapper(set_int_add2, &stack_int, 1, 6);
    EXPECT_EQ(12, stack_int);
    wrapper->Run();
    EXPECT_EQ(7, stack_int);

    wrapper = NewFunctionCallWrapper(set_int_add3, &stack_int, 1, 6, 2);
    EXPECT_EQ(7, stack_int);
    wrapper->Run();
    EXPECT_EQ(9, stack_int);

    wrapper = NewFunctionCallWrapper(set_int_add4, &stack_int, 1, 6, 2, 3);
    EXPECT_EQ(9, stack_int);
    wrapper->Run();
    EXPECT_EQ(12, stack_int);
  }
}

namespace {

class Incrementer {
 public:
  Incrementer(int* ptr) : ptr_(ptr) { }
  void IncrementBy(int x) { *ptr_ += x; }
  void Increment() { IncrementBy(1); }
  void SetIntAdd2(int x, int y) { *ptr_ = x + y; }
  void SetIntAdd3(int x, int y, int z) { *ptr_ = x + y + z; }
  void SetIntAdd4(int x, int y, int z, int w) { *ptr_ = x + y + z + w; }
 private:
  int* ptr_;
};

}  // namespace

TEST(CallWrapperTest, MethodCall) {
  // Method call with 0 and 1 arguments.
  {
    int stack_int = 0;
    Incrementer incr(&stack_int);
    CallWrapper* wrapper;

    wrapper = NewMethodCallWrapper(&incr, &Incrementer::Increment);
    EXPECT_EQ(0, stack_int);
    wrapper->Run();
    EXPECT_EQ(1, stack_int);

    wrapper = NewMethodCallWrapper(&incr, &Incrementer::IncrementBy, 10);
    EXPECT_EQ(1, stack_int);
    wrapper->Run();
    EXPECT_EQ(11, stack_int);
  }
  // Method call with 2-5 arguments.
  {
    int stack_int = 0;
    Incrementer incr(&stack_int);
    CallWrapper* wrapper;

    wrapper = NewMethodCallWrapper(&incr, &Incrementer::SetIntAdd2, 1, 5);
    EXPECT_EQ(0, stack_int);
    wrapper->Run();
    EXPECT_EQ(6, stack_int);

    wrapper = NewMethodCallWrapper(&incr, &Incrementer::SetIntAdd3, 1, 5, 7);
    EXPECT_EQ(6, stack_int);
    wrapper->Run();
    EXPECT_EQ(13, stack_int);

    wrapper = NewMethodCallWrapper(&incr, &Incrementer::SetIntAdd4, 1, 5, 7, 2);
    EXPECT_EQ(13, stack_int);
    wrapper->Run();
    EXPECT_EQ(15, stack_int);
  }
}
<commit_msg>Clean up some method naming style.<commit_after>// Copyright 2008, 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 "base/call_wrapper.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace {

int global_int = 0;

void SetGlobalInt5() {
  global_int = 5;
}
void SetGlobalInt(int x) {
  global_int = x;
}
void SetInt(int* p, int x) {
  *p = x;
}
void SetIntAdd2(int* p, int x, int y) {
  *p = x + y;
}
void SetIntAdd3(int* p, int x, int y, int z) {
  *p = x + y + z;
}
void SetIntAdd4(int* p, int x, int y, int z, int w) {
  *p = x + y + z + w;
}

}  // namespace

TEST(CallWrapperTest, FunctionCall) {
  // Function call with 0 arguments.
  {
    EXPECT_EQ(0, global_int);
    CallWrapper* wrapper = NewFunctionCallWrapper(SetGlobalInt5);

    EXPECT_EQ(0, global_int);
    wrapper->Run();
    EXPECT_EQ(5, global_int);
  }
  // Function call with 1 argument.
  {
    EXPECT_EQ(5, global_int);
    CallWrapper* wrapper = NewFunctionCallWrapper(SetGlobalInt, 0);

    EXPECT_EQ(5, global_int);
    wrapper->Run();
    EXPECT_EQ(0, global_int);
  }
  // Function call with 2 arguments.
  {
    int stack_int = 4;
    CallWrapper* wrapper;

    wrapper = NewFunctionCallWrapper(SetInt, &global_int, 8);
    EXPECT_EQ(4, stack_int);
    EXPECT_EQ(0, global_int);
    wrapper->Run();
    EXPECT_EQ(4, stack_int);
    EXPECT_EQ(8, global_int);

    wrapper = NewFunctionCallWrapper(SetInt, &stack_int, 8);
    EXPECT_EQ(4, stack_int);
    EXPECT_EQ(8, global_int);
    wrapper->Run();
    EXPECT_EQ(8, stack_int);
    EXPECT_EQ(8, global_int);
  }
  // Function call with 3-5 arguments.
  {
    int stack_int = 12;
    CallWrapper* wrapper;

    wrapper = NewFunctionCallWrapper(SetIntAdd2, &stack_int, 1, 6);
    EXPECT_EQ(12, stack_int);
    wrapper->Run();
    EXPECT_EQ(7, stack_int);

    wrapper = NewFunctionCallWrapper(SetIntAdd3, &stack_int, 1, 6, 2);
    EXPECT_EQ(7, stack_int);
    wrapper->Run();
    EXPECT_EQ(9, stack_int);

    wrapper = NewFunctionCallWrapper(SetIntAdd4, &stack_int, 1, 6, 2, 3);
    EXPECT_EQ(9, stack_int);
    wrapper->Run();
    EXPECT_EQ(12, stack_int);
  }
}

namespace {

class Incrementer {
 public:
  Incrementer(int* ptr) : ptr_(ptr) { }
  void IncrementBy(int x) { *ptr_ += x; }
  void Increment() { IncrementBy(1); }
  void SetIntAdd2(int x, int y) { *ptr_ = x + y; }
  void SetIntAdd3(int x, int y, int z) { *ptr_ = x + y + z; }
  void SetIntAdd4(int x, int y, int z, int w) { *ptr_ = x + y + z + w; }
 private:
  int* ptr_;
};

}  // namespace

TEST(CallWrapperTest, MethodCall) {
  // Method call with 0 and 1 arguments.
  {
    int stack_int = 0;
    Incrementer incr(&stack_int);
    CallWrapper* wrapper;

    wrapper = NewMethodCallWrapper(&incr, &Incrementer::Increment);
    EXPECT_EQ(0, stack_int);
    wrapper->Run();
    EXPECT_EQ(1, stack_int);

    wrapper = NewMethodCallWrapper(&incr, &Incrementer::IncrementBy, 10);
    EXPECT_EQ(1, stack_int);
    wrapper->Run();
    EXPECT_EQ(11, stack_int);
  }
  // Method call with 2-5 arguments.
  {
    int stack_int = 0;
    Incrementer incr(&stack_int);
    CallWrapper* wrapper;

    wrapper = NewMethodCallWrapper(&incr, &Incrementer::SetIntAdd2, 1, 5);
    EXPECT_EQ(0, stack_int);
    wrapper->Run();
    EXPECT_EQ(6, stack_int);

    wrapper = NewMethodCallWrapper(&incr, &Incrementer::SetIntAdd3, 1, 5, 7);
    EXPECT_EQ(6, stack_int);
    wrapper->Run();
    EXPECT_EQ(13, stack_int);

    wrapper = NewMethodCallWrapper(&incr, &Incrementer::SetIntAdd4, 1, 5, 7, 2);
    EXPECT_EQ(13, stack_int);
    wrapper->Run();
    EXPECT_EQ(15, stack_int);
  }
}
<|endoftext|>


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

#include "webkit/glue/user_agent.h"

#if defined(OS_POSIX) && !defined(OS_MACOSX)
#include <sys/utsname.h>
#endif

#include "base/string_util.h"
#include "base/stringprintf.h"
#include "base/sys_info.h"

// Generated
#include "webkit_version.h"  // NOLINT

namespace webkit_glue {

// Forward declare GetProductVersionInfo.  This is implemented in
// renderer_glue.cc as part of the renderer lib.
std::string GetProductVersion();

std::string GetWebKitVersion() {
  return base::StringPrintf("%d.%d (%s)",
                            WEBKIT_VERSION_MAJOR,
                            WEBKIT_VERSION_MINOR,
                            WEBKIT_SVN_REVISION);
}

std::string GetWebKitRevision() {
  return WEBKIT_SVN_REVISION;
}

std::string BuildOSCpuInfo() {
  std::string os_cpu;

#if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_CHROMEOS)
  int32 os_major_version = 0;
  int32 os_minor_version = 0;
  int32 os_bugfix_version = 0;
  base::SysInfo::OperatingSystemVersionNumbers(&os_major_version,
                                               &os_minor_version,
                                               &os_bugfix_version);
#endif
#if defined(OS_POSIX) && !defined(OS_MACOSX)
  // Should work on any Posix system.
  struct utsname unixinfo;
  uname(&unixinfo);

  std::string cputype;
  // special case for biarch systems
  if (strcmp(unixinfo.machine, "x86_64") == 0 &&
      sizeof(void*) == sizeof(int32)) {  // NOLINT
    cputype.assign("i686 (x86_64)");
  } else {
    cputype.assign(unixinfo.machine);
  }
#endif

  base::StringAppendF(
      &os_cpu,
#if defined(OS_WIN)
      "Windows NT %d.%d",
      os_major_version,
      os_minor_version
#elif defined(OS_MACOSX)
      "Intel Mac OS X %d_%d_%d",
      os_major_version,
      os_minor_version,
      os_bugfix_version
#elif defined(OS_CHROMEOS)
      "CrOS %s %d.%d.%d",
      cputype.c_str(),  // e.g. i686
      os_major_version,
      os_minor_version,
      os_bugfix_version
#else
      "%s %s",
      unixinfo.sysname,  // e.g. Linux
      cputype.c_str()    // e.g. i686
#endif
  );  // NOLINT

  return os_cpu;
}

void BuildUserAgent(bool mimic_windows, std::string* result) {
  const char kUserAgentPlatform[] =
#if defined(OS_WIN)
      "Windows";
#elif defined(OS_MACOSX)
      "Macintosh";
#elif defined(USE_X11)
      "X11";              // strange, but that's what Firefox uses
#else
      "?";
#endif

  // Get the product name and version, and replace Safari's Version/X string
  // with it.  This is done to expose our product name in a manner that is
  // maximally compatible with Safari, we hope!!
  std::string product = GetProductVersion();

  // Derived from Safari's UA string.
  base::StringAppendF(
      result,
      "Mozilla/5.0 (%s; %s) AppleWebKit/%d.%d"
      " (KHTML, like Gecko) %s Safari/%d.%d",
      mimic_windows ? "Windows" : kUserAgentPlatform,
      ((mimic_windows ? "Windows " : "") + BuildOSCpuInfo()).c_str(),
      WEBKIT_VERSION_MAJOR,
      WEBKIT_VERSION_MINOR,
      product.c_str(),
      WEBKIT_VERSION_MAJOR,
      WEBKIT_VERSION_MINOR);
}

}  // namespace webkit_glue

<commit_msg>Drop "Windows;" from the UA string.  This parallels https://bugs.webkit.org/show_bug.cgi?id=54567 and also matches a change in Firefox 4.<commit_after>// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "webkit/glue/user_agent.h"

#if defined(OS_POSIX) && !defined(OS_MACOSX)
#include <sys/utsname.h>
#endif

#include "base/string_util.h"
#include "base/stringprintf.h"
#include "base/sys_info.h"

// Generated
#include "webkit_version.h"  // NOLINT

namespace webkit_glue {

// Forward declare GetProductVersionInfo.  This is implemented in
// renderer_glue.cc as part of the renderer lib.
std::string GetProductVersion();

std::string GetWebKitVersion() {
  return base::StringPrintf("%d.%d (%s)",
                            WEBKIT_VERSION_MAJOR,
                            WEBKIT_VERSION_MINOR,
                            WEBKIT_SVN_REVISION);
}

std::string GetWebKitRevision() {
  return WEBKIT_SVN_REVISION;
}

std::string BuildOSCpuInfo() {
  std::string os_cpu;

#if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_CHROMEOS)
  int32 os_major_version = 0;
  int32 os_minor_version = 0;
  int32 os_bugfix_version = 0;
  base::SysInfo::OperatingSystemVersionNumbers(&os_major_version,
                                               &os_minor_version,
                                               &os_bugfix_version);
#endif
#if defined(OS_POSIX) && !defined(OS_MACOSX)
  // Should work on any Posix system.
  struct utsname unixinfo;
  uname(&unixinfo);

  std::string cputype;
  // special case for biarch systems
  if (strcmp(unixinfo.machine, "x86_64") == 0 &&
      sizeof(void*) == sizeof(int32)) {  // NOLINT
    cputype.assign("i686 (x86_64)");
  } else {
    cputype.assign(unixinfo.machine);
  }
#endif

  base::StringAppendF(
      &os_cpu,
#if defined(OS_WIN)
      "Windows NT %d.%d",
      os_major_version,
      os_minor_version
#elif defined(OS_MACOSX)
      "Intel Mac OS X %d_%d_%d",
      os_major_version,
      os_minor_version,
      os_bugfix_version
#elif defined(OS_CHROMEOS)
      "CrOS %s %d.%d.%d",
      cputype.c_str(),   // e.g. i686
      os_major_version,
      os_minor_version,
      os_bugfix_version
#else
      "%s %s",
      unixinfo.sysname,  // e.g. Linux
      cputype.c_str()    // e.g. i686
#endif
  );  // NOLINT

  return os_cpu;
}

void BuildUserAgent(bool mimic_windows, std::string* result) {
  const char kUserAgentPlatform[] =
#if defined(OS_WIN)
      "";
#elif defined(OS_MACOSX)
      "Macintosh; ";
#elif defined(USE_X11)
      "X11; ";           // strange, but that's what Firefox uses
#else
      "Unknown; ";
#endif

  // Get the product name and version, and replace Safari's Version/X string
  // with it.  This is done to expose our product name in a manner that is
  // maximally compatible with Safari, we hope!!
  std::string product = GetProductVersion();

  // Derived from Safari's UA string.
  base::StringAppendF(
      result,
      "Mozilla/5.0 (%s%s) AppleWebKit/%d.%d"
      " (KHTML, like Gecko) %s Safari/%d.%d",
      mimic_windows ? "Windows " : kUserAgentPlatform,
      BuildOSCpuInfo().c_str(),
      WEBKIT_VERSION_MAJOR,
      WEBKIT_VERSION_MINOR,
      product.c_str(),
      WEBKIT_VERSION_MAJOR,
      WEBKIT_VERSION_MINOR);
}

}  // namespace webkit_glue

<|endoftext|>


<commit_before>/**
 * @file		componentpack.hpp
 * @brief		header file for component
 * @author		Byunghun Hwang<bhhwang@nsynapse.com>
 * @date 		2015. 8. 27
 * @details	component class header may be required this header
 */

#ifndef _COSSB_COMPONENTPACK_HPP_
#define _COSSB_COMPONENTPACK_HPP_

#if defined(__unix__) || defined(__gnu_linux__) || defined(linux) || defined(__linux__)

#include "logger.hpp"	//for base logger
#include "broker.hpp"	//for topic/message broker
#include "base/task.hpp"	//for task

#endif

#endif /* _COSSB_COMPONENTPACK_HPP_ */
<commit_msg>add exception header file<commit_after>/**
 * @file		componentpack.hpp
 * @brief		header file for component
 * @author		Byunghun Hwang<bhhwang@nsynapse.com>
 * @date 		2015. 8. 27
 * @details	component class header may be required this header
 */

#ifndef _COSSB_COMPONENTPACK_HPP_
#define _COSSB_COMPONENTPACK_HPP_

#if defined(__unix__) || defined(__gnu_linux__) || defined(linux) || defined(__linux__)

#include "logger.hpp"
#include "broker.hpp"
#include "base/task.hpp"
#include "exception.hpp"

#endif

#endif /* _COSSB_COMPONENTPACK_HPP_ */
<|endoftext|>


<commit_before>/*
 * TTBlue Library
 * Copyright © 2008, Timothy Place
 *
 * License: This code is licensed under the terms of the GNU LGPL
 * http://www.gnu.org/licenses/lgpl.html
 */

#include "TTBlue.h"
#include "TTSymbolTable.h"
#include "TTEnvironment.h"
#include "TTSymbolCache.h"
#include "TTValueCache.h"

static bool TTBlueHasInitialized = false;

void TTBlueRegisterInternalClasses();
TTObject* TTBlueInstantiateInternalClass(TTSymbol* className, TTValue& arguments);

/****************************************************************************************************/
void TTBlueInit()
{
	if(!TTBlueHasInitialized){
		ttSymbolTable = new TTSymbolTable;
		ttEnvironment = new TTEnvironment;

		TTSymbolCacheInit();
		TTValueCacheInit();

#ifdef TT_DEBUG
		TTLogMessage("TTBlue -- Version %s -- Debugging Enabled\n", TT_VERSION_STRING);
#else
		TTLogMessage("TTBlue -- Version %s\n", TT_VERSION_STRING);
#endif

		TTBlueRegisterInternalClasses();

		// do we need to do anything with the global object?
		// init the queue -- runs in a new thread

		TTBlueHasInitialized = true;
	}
}

/****************************************************************************************************/
#include "TTBuffer.h"
#include "TTCrossfade.h"
#include "TTDegrade.h"
#include "TTDelay.h"
#include "TTOperator.h"
#include "TTOverdrive.h"

void TTBlueRegisterInternalClasses()
{
	TTClassRegister(TT("buffer"),		"audio, buffer, storage",			&TTBlueInstantiateInternalClass);
	TTClassRegister(TT("crossfade"),	"audio, processor, mixing",			&TTBlueInstantiateInternalClass);
	TTClassRegister(TT("degrade"),		"audio, processor, distortion",		&TTBlueInstantiateInternalClass);
	TTClassRegister(TT("delay"),		"audio, processor, delay",			&TTBlueInstantiateInternalClass);
	TTClassRegister(TT("operator"),		"audio, processor, math",			&TTBlueInstantiateInternalClass);
	TTClassRegister(TT("overdrive"),	"audio, processor",					&TTBlueInstantiateInternalClass);
}

TTObject* TTBlueInstantiateInternalClass(TTSymbol* className, TTValue& arguments)
{
	if(className == TT("buffer"))
		return new TTBuffer;
	else if(className == TT("crossfade"))
		return new TTCrossfade(arguments);
	else if(className == TT("degrade"))
		return new TTDegrade(arguments);
	else if(className == TT("delay"))
		return new TTDelay(arguments);
	else if(className == TT("operator"))
		return new TTOperator(arguments);
	else if(className == TT("overdrive"))
		return new TTOverdrive(arguments);

	else{
		TTLogError("TTBlue: cannot instantiate object of %s class.  No such class.", className->getCString());
		return NULL;
	}
}

<commit_msg>We are now registering all of the internal classes so that they can be queried and instantiated using the environment.<commit_after>/*
 * TTBlue Library
 * Copyright © 2008, Timothy Place
 *
 * License: This code is licensed under the terms of the GNU LGPL
 * http://www.gnu.org/licenses/lgpl.html
 */

#include "TTBlue.h"
#include "TTSymbolTable.h"
#include "TTEnvironment.h"
#include "TTSymbolCache.h"
#include "TTValueCache.h"

static bool TTBlueHasInitialized = false;

void TTBlueRegisterInternalClasses();
TTObject* TTBlueInstantiateInternalClass(TTSymbol* className, TTValue& arguments);

/****************************************************************************************************/
void TTBlueInit()
{
	if(!TTBlueHasInitialized){
		ttSymbolTable = new TTSymbolTable;
		ttEnvironment = new TTEnvironment;

		TTSymbolCacheInit();
		TTValueCacheInit();

#ifdef TT_DEBUG
		TTLogMessage("TTBlue -- Version %s -- Debugging Enabled\n", TT_VERSION_STRING);
#else
		TTLogMessage("TTBlue -- Version %s\n", TT_VERSION_STRING);
#endif

		TTBlueRegisterInternalClasses();

		// do we need to do anything with the global object?
		// init the queue -- runs in a new thread

		TTBlueHasInitialized = true;
	}
}

/****************************************************************************************************/

// Analysis
#include "TTZerocross.h"

// Data

// Dynamics
#include "TTBalance.h"
#include "TTGain.h"
#include "TTLimiter.h"
#include "TTPulseSub.h"

// Generators
#include "TTAdsr.h"
#include "TTNoise.h"
#include "TTPhasor.h"
#include "TTRamp.h"
#include "TTWavetable.h"

// Filtering
#include "TTAllpass.h"
#include "TTAverage.h"
#include "TTBandpassButterworth2.h"
#include "TTBandrejectButterworth2.h"
#include "TTDCBlock.h"

#include "TTHighpassButterworth1.h"
#include "TTHighpassButterworth2.h"
#include "TTHighpassButterworth3.h"
#include "TTHighpassButterworth4.h"
#include "TTHighpassLinkwitzRiley2.h"
#include "TTHighpassLinkwitzRiley4.h"

#include "TTLowpassButterworth1.h"
#include "TTLowpassButterworth2.h"
#include "TTLowpassButterworth3.h"
#include "TTLowpassButterworth4.h"
#include "TTLowpassLinkwitzRiley2.h"
#include "TTLowpassLinkwitzRiley4.h"

#include "TTLowpassOnePole.h"
#include "TTLowpassTwoPole.h"
#include "TTLowpassFourPole.h"
#include "TTSvf.h"

// Misc
#include "TTBuffer.h"
#include "TTCrossfade.h"
#include "TTDegrade.h"
#include "TTDelay.h"
#include "TTOperator.h"
#include "TTOverdrive.h"

void TTBlueRegisterInternalClasses()
{
	// Analysis
	TTClassRegister(TT("zerocross"),					"audio, analysis, frequency",										&TTBlueInstantiateInternalClass);

	// Data

	// Dynamics
	TTClassRegister(TT("balance"),						"audio, processor, dynamics",										&TTBlueInstantiateInternalClass);
	TTClassRegister(TT("gain"),							"audio, processor, dynamics",										&TTBlueInstantiateInternalClass);
	TTClassRegister(TT("limiter"),						"audio, processor, dynamics, limiter",								&TTBlueInstantiateInternalClass);
	TTClassRegister(TT("pulsesub"),						"audio, processor, dynamics, envelope",								&TTBlueInstantiateInternalClass);

	// Generators
	TTClassRegister(TT("adsr"),							"audio, generator, envelope",										&TTBlueInstantiateInternalClass);
	TTClassRegister(TT("noise"),						"audio, generator, noise",											&TTBlueInstantiateInternalClass);
	TTClassRegister(TT("phasor"),						"audio, generator, oscillator",										&TTBlueInstantiateInternalClass);
	TTClassRegister(TT("ramp"),							"audio, generator",													&TTBlueInstantiateInternalClass);
	TTClassRegister(TT("wavetable"),					"audio, generator, oscillator, buffer",								&TTBlueInstantiateInternalClass);

	// Filtering
	TTClassRegister(TT("allpass"),						"audio, processor, filter, allpass",								&TTBlueInstantiateInternalClass);
	TTClassRegister(TT("average"),						"audio, processor, filter, lowpass, envelope",						&TTBlueInstantiateInternalClass);
	TTClassRegister(TT("bandpass.butterworth.2"),		"audio, processor, filter, bandpass, butterworth",					&TTBlueInstantiateInternalClass);
	TTClassRegister(TT("bandreject.butterworth.2"),		"audio, processor, filter, notch",									&TTBlueInstantiateInternalClass);
	TTClassRegister(TT("dcblock"),						"audio, processor, filter",											&TTBlueInstantiateInternalClass);

	TTClassRegister(TT("highpass.butterworth.1"),		"audio, processor, filter, highpass, butterworth",					&TTBlueInstantiateInternalClass);
	TTClassRegister(TT("highpass.butterworth.2"),		"audio, processor, filter, highpass, butterworth",					&TTBlueInstantiateInternalClass);
	TTClassRegister(TT("highpass.butterworth.3"),		"audio, processor, filter, highpass, butterworth",					&TTBlueInstantiateInternalClass);
	TTClassRegister(TT("highpass.butterworth.4"),		"audio, processor, filter, highpass, butterworth",					&TTBlueInstantiateInternalClass);
	TTClassRegister(TT("highpass.linkwitzriley.2"),		"audio, processor, filter, highpass",								&TTBlueInstantiateInternalClass);
	TTClassRegister(TT("highpass.linkwitzriley.4"),		"audio, processor, filter, highpass, crossover",					&TTBlueInstantiateInternalClass);

	TTClassRegister(TT("lowpass.butterworth.1"),		"audio, processor, filter, lowpass, butterworth",					&TTBlueInstantiateInternalClass);
	TTClassRegister(TT("lowpass.butterworth.2"),		"audio, processor, filter, lowpass, butterworth",					&TTBlueInstantiateInternalClass);
	TTClassRegister(TT("lowpass.butterworth.3"),		"audio, processor, filter, lowpass, butterworth",					&TTBlueInstantiateInternalClass);
	TTClassRegister(TT("lowpass.butterworth.4"),		"audio, processor, filter, lowpass, butterworth",					&TTBlueInstantiateInternalClass);
	TTClassRegister(TT("lowpass.linkwitzriley.2"),		"audio, processor, filter, lowpass",								&TTBlueInstantiateInternalClass);
	TTClassRegister(TT("lowpass.linkwitzriley.4"),		"audio, processor, filter, lowpass, crossover",						&TTBlueInstantiateInternalClass);

	TTClassRegister(TT("lowpass.1"),					"audio, processor, filter, lowpass",								&TTBlueInstantiateInternalClass);
	TTClassRegister(TT("lowpass.2"),					"audio, processor, filter, lowpass",								&TTBlueInstantiateInternalClass);
	TTClassRegister(TT("lowpass.4"),					"audio, processor, filter, lowpass",								&TTBlueInstantiateInternalClass);

	TTClassRegister(TT("svf"),							"audio, processor, filter, lowpass, highpass, bandpass, notch",		&TTBlueInstantiateInternalClass);

	// Misc
	TTClassRegister(TT("buffer"),						"audio, buffer, storage",											&TTBlueInstantiateInternalClass);
	TTClassRegister(TT("crossfade"),					"audio, processor, mixing",											&TTBlueInstantiateInternalClass);
	TTClassRegister(TT("degrade"),						"audio, processor, distortion",										&TTBlueInstantiateInternalClass);
	TTClassRegister(TT("delay"),						"audio, processor, delay",											&TTBlueInstantiateInternalClass);
	TTClassRegister(TT("operator"),						"audio, processor, math",											&TTBlueInstantiateInternalClass);
	TTClassRegister(TT("overdrive"),					"audio, processor",													&TTBlueInstantiateInternalClass);
}

TTObject* TTBlueInstantiateInternalClass(TTSymbol* className, TTValue& arguments)
{
	// Analysis
	if(className == TT("zerocross"))
		return new TTZerocross(arguments);

	// Data

	// Dynamics
	else if(className == TT("balance"))
		return new TTBalance(arguments);
	else if(className == TT("gain"))
		return new TTGain(arguments);
	else if(className == TT("limiter"))
		return new TTLimiter(arguments);
	else if(className == TT("pulsesub"))
		return new TTPulseSub(arguments);

	// Generators
	else if(className == TT("adsr"))
		return new TTAdsr(arguments);
	else if(className == TT("noise"))
		return new TTNoise(arguments);
	else if(className == TT("phasor"))
		return new TTPhasor(arguments);
	else if(className == TT("ramp"))
		return new TTRamp(arguments);
	else if(className == TT("wavetable"))
		return new TTWavetable(arguments);

	// Filtering
	else if(className == TT("allpass"))
		return new TTAllpass(arguments);
	else if(className == TT("average"))
		return new TTAverage(arguments);
	else if(className == TT("bandpass.butterworth.2"))
		return new TTBandpassButterworth2(arguments);
	else if(className == TT("bandreject.butterworth.2"))
		return new TTBandRejectButterworth2(arguments);
	else if(className == TT("dcblock"))
		return new TTDCBlock(arguments);

	else if(className == TT("highpass.butterworth.1"))
		return new TTHighpassButterworth1(arguments);
	else if(className == TT("highpass.butterworth.2"))
		return new TTHighpassButterworth2(arguments);
	else if(className == TT("highpass.butterworth.3"))
		return new TTHighpassButterworth3(arguments);
	else if(className == TT("highpass.butterworth.4"))
		return new TTHighpassButterworth4(arguments);
	else if(className == TT("highpass.linkwitzriley.2"))
		return new TTHighpassLinkwitzRiley2(arguments);
	else if(className == TT("highpass.linkwitzriley.4"))
		return new TTHighpassLinkwitzRiley4(arguments);

	else if(className == TT("lowpass.butterworth.1"))
		return new TTLowpassButterworth1(arguments);
	else if(className == TT("lowpass.butterworth.2"))
		return new TTLowpassButterworth2(arguments);
	else if(className == TT("lowpass.butterworth.3"))
		return new TTLowpassButterworth3(arguments);
	else if(className == TT("lowpass.butterworth.4"))
		return new TTLowpassButterworth4(arguments);
	else if(className == TT("lowpass.linkwitzriley.2"))
		return new TTLowpassLinkwitzRiley2(arguments);
	else if(className == TT("lowpass.linkwitzriley.4"))
		return new TTLowpassLinkwitzRiley4(arguments);

	else if(className == TT("lowpass.1"))
		return new TTLowpassOnePole(arguments);
	else if(className == TT("lowpass.2"))
		return new TTLowpassTwoPole(arguments);
	else if(className == TT("lowpass.4"))
		return new TTLowpassFourPole(arguments);

	else if(className == TT("svf"))
		return new TTSvf(arguments);

	// Misc
	else if(className == TT("buffer"))
		return new TTBuffer;
	else if(className == TT("crossfade"))
		return new TTCrossfade(arguments);
	else if(className == TT("degrade"))
		return new TTDegrade(arguments);
	else if(className == TT("delay"))
		return new TTDelay(arguments);
	else if(className == TT("operator"))
		return new TTOperator(arguments);
	else if(className == TT("overdrive"))
		return new TTOverdrive(arguments);

	else{
		TTLogError("TTBlue: cannot instantiate object of %s class.  No such class.", className->getCString());
		return NULL;
	}
}

<|endoftext|>


<commit_before>#pragma once

#include <string>
#include <string_view>
#include <vector>
#include <cctype>
#include <algorithm>
#include <cstring>
#include <iterator>
#include <utility>
#include <initializer_list>
#include <numeric>
#include <functional>
#include <cassert>
#include <limits>
#include <charconv>

#include "acmacs-base/sfinae.hh"
#include "acmacs-base/to-string.hh"

// ----------------------------------------------------------------------

namespace std
{
    inline unsigned long stoul(std::string_view src) { return stoul(std::string(src)); }
    inline unsigned long stoul(const std::string& src, int base) { return stoul(src, nullptr, base); }
    inline unsigned long stoul(std::string_view src, int base) { return stoul(std::string(src), nullptr, base); }
}

// ----------------------------------------------------------------------

namespace string
{
      // ----------------------------------------------------------------------

    inline std::string first_letter_of_words(std::string_view s)
    {
        std::string result;
        bool add = true;
        for (char c: s) {
            if (c == ' ') {
                add = true;
            }
            else if (add) {
                result.push_back(c);
                add = false;
            }
        }
        return result;
    }

      // ----------------------------------------------------------------------

      // ----------------------------------------------------------------------

    inline std::string replace(std::string_view source, std::string_view look_for, std::string_view replace_with)
    {
        std::string result;
        std::string::size_type start = 0;
        while (true) {
            const auto pos = source.find(look_for, start);
            if (pos != std::string::npos) {
                result.append(source.begin() + static_cast<std::string::difference_type>(start), source.begin() + static_cast<std::string::difference_type>(pos));
                result.append(replace_with);
                start = pos + look_for.size();
            }
            else {
                result.append(source.begin() + static_cast<std::string::difference_type>(start), source.end());
                break;
            }
        }
        return result;
    }

    inline std::string replace(std::string_view source, char look_for, char replace_with)
    {
        std::string result(source.size(), ' ');
        std::transform(std::begin(source), std::end(source), std::begin(result), [=](char c) { if (c == look_for) return replace_with; else return c; });
        return result;
    }

    template <typename ... Args> inline std::string replace(std::string_view source, std::string_view l1, std::string_view r1, std::string_view l2, std::string_view r2, Args ... args)
    {
        return replace(replace(source, l1, r1), l2, r2, args ...);
    }

    inline std::string replace_spaces(std::string_view source, char replacement)
    {
        std::string result(source.size(), replacement);
        std::transform(source.begin(), source.end(), result.begin(), [replacement](char c) {
            if (std::isspace(c))
                c = replacement;
            return c;
        });
        return result;
    }

    // ----------------------------------------------------------------------

    namespace _internal
    {
        template <typename Iter, typename F> inline std::string transform(Iter first, Iter last, F func)
        {
            std::string result(static_cast<size_t>(last - first), '?');
            std::transform(first, last, result.begin(), func);
            return result;
        }

        template <typename Iter, typename F> inline std::string copy_if(Iter first, Iter last, F func)
        {
            std::string result;
            std::copy_if(first, last, std::back_inserter(result), func);
            return result;
        }
    }

    inline std::string lower(std::string_view source) { return _internal::transform(source.begin(), source.end(), ::tolower); }
    inline std::string lower(const char* source) { return _internal::transform(source, source + std::strlen(source), ::tolower); }
    inline std::string lower(char* source) { return lower(const_cast<const char*>(source)); }
    template <typename Iter> inline std::string lower(Iter beg, Iter end) { return _internal::transform(beg, end, ::tolower); }

    inline std::string upper(std::string_view source) { return _internal::transform(source.begin(), source.end(), ::toupper); }
    inline std::string upper(const char* source) { return _internal::transform(source, source + std::strlen(source), ::toupper); }
    inline std::string upper(char* source) { return upper(const_cast<const char*>(source)); }
    template <typename Iter> inline std::string upper(Iter beg, Iter end) { return _internal::transform(beg, end, ::toupper); }

    inline std::string capitalize(std::string_view source)
    {
        std::string result;
        if (!source.empty()) {
            std::transform(source.begin(), source.begin() + 1, std::back_inserter(result), ::toupper);
            std::transform(source.begin() + 1, source.end(), std::back_inserter(result), ::tolower);
        }
        return result;
    }

    inline std::string remove_spaces(std::string_view source) { return _internal::copy_if(source.begin(), source.end(), [](auto c) -> bool { return !std::isspace(c); }); }
    inline std::string remove_spaces(const char* source) { return remove_spaces(std::string_view(source, std::strlen(source))); }
    inline std::string remove_spaces(char* source) { return remove_spaces(std::string_view(source, std::strlen(source))); }

    // changes subsequent spaces into one space
    inline std::string collapse_spaces(std::string_view source)
    {
        return _internal::copy_if(source.begin(), source.end(), [prev_was_space=false](auto c) mutable -> bool {
            const auto space = std::isspace(c);
            const auto result = !(prev_was_space && space);
            prev_was_space = space;
            return result;
        });
    }
    inline std::string collapse_spaces(const char* source) { return collapse_spaces(std::string_view(source, std::strlen(source))); }
    inline std::string collapse_spaces(char* source) { return collapse_spaces(std::string_view(source, std::strlen(source))); }

      // ----------------------------------------------------------------------
      // ends_with
      // ----------------------------------------------------------------------

    inline bool ends_with(std::string_view data, const char* end)
    {
        const std::string_view end_view{end};
        return std::string_view(data.data() + data.size() - end_view.size(), end_view.size()) == end_view;
    }

      // ----------------------------------------------------------------------
      // compare
      // ----------------------------------------------------------------------

    inline int compare(const char* a, size_t al, const char* b, size_t bl)
    {
        auto r = std::memcmp(a, b, std::min(al, bl));
        if (r == 0 && al != bl)
            return al < bl ? -1 : 1;
        else
            return r;
    }

    inline int compare(std::string_view s1, std::string_view s2) { return compare(s1.data(), s1.size(), s2.data(), s2.size()); }

    inline int compare(std::initializer_list<std::string_view> as, std::initializer_list<std::string_view> bs)
    {
        assert(as.size() == bs.size());
        for (auto ap = as.begin(), bp = bs.begin(); ap != as.end(); ++ap, ++bp) {
            if (const auto r = compare(*ap, *bp); r != 0)
                return r;
        }
        return 0;
    }

// ----------------------------------------------------------------------

    template <typename S> inline std::string_view string_view(const S& aSrc, size_t aOffset)
    {
        return std::string_view(aSrc.data() + aOffset, aSrc.size() - aOffset);
    }

// ----------------------------------------------------------------------

    namespace detail
    {
        template <typename S> inline std::string concat_to_string(S src, [[maybe_unused]] size_t precision = 6)
        {
            if constexpr (std::is_convertible_v<S, std::string>)
                return static_cast<std::string>(src);
            else if constexpr (std::is_same_v<S, double> || std::is_same_v<S, long double>)
                return acmacs::to_string(src, precision);
            else
                return acmacs::to_string(src);
        }
    }

    template <typename S1, typename S2, typename... Args> inline std::string concat(S1 s1, S2 s2, Args... args)
    {
        auto result = detail::concat_to_string(s1);
        result.append(detail::concat_to_string(s2));
        if constexpr (sizeof...(args) > 0)
            return concat(result, args...);
        else
            return result;
    }

    template <typename S1, typename S2, typename... Args> inline std::string concat_precise(S1 s1, S2 s2, Args... args)
    {
        auto result = detail::concat_to_string(s1, 32);
        result.append(detail::concat_to_string(s2, 32));
        if constexpr (sizeof...(args) > 0)
            return concat_precise(result, args...);
        else
            return result;
    }

// ----------------------------------------------------------------------

} // namespace string

// ----------------------------------------------------------------------
/// Local Variables:
/// eval: (if (fboundp 'eu-rename-buffer) (eu-rename-buffer))
/// End:
<commit_msg>minor fix<commit_after>#pragma once

#include <string>
#include <string_view>
#include <vector>
#include <cctype>
#include <algorithm>
#include <cstring>
#include <iterator>
#include <utility>
#include <initializer_list>
#include <numeric>
#include <functional>
#include <cassert>
#include <limits>
#include <charconv>

#include "acmacs-base/sfinae.hh"
#include "acmacs-base/debug.hh"
#include "acmacs-base/to-string.hh"

// ----------------------------------------------------------------------

namespace std
{
    inline unsigned long stoul(std::string_view src) { return stoul(std::string(src)); }
    inline unsigned long stoul(const std::string& src, int base) { return stoul(src, nullptr, base); }
    inline unsigned long stoul(std::string_view src, int base) { return stoul(std::string(src), nullptr, base); }
}

// ----------------------------------------------------------------------

namespace string
{
      // ----------------------------------------------------------------------

    inline std::string first_letter_of_words(std::string_view source)
    {
        std::string result;
        bool add = true;
        for (char c: source) {
            if (c == ' ') {
                add = true;
            }
            else if (add) {
                result.push_back(c);
                add = false;
            }
        }
        return result;
    }

      // ----------------------------------------------------------------------

      // ----------------------------------------------------------------------

    inline std::string replace(std::string_view source, std::string_view look_for, std::string_view replace_with)
    {
        std::string result;
        std::string::size_type start = 0;
        while (true) {
            const auto pos = source.find(look_for, start);
            if (pos != std::string::npos) {
                result.append(source.begin() + static_cast<std::string::difference_type>(start), source.begin() + static_cast<std::string::difference_type>(pos));
                result.append(replace_with);
                start = pos + look_for.size();
            }
            else {
                result.append(source.begin() + static_cast<std::string::difference_type>(start), source.end());
                break;
            }
        }
        return result;
    }

    inline std::string replace(std::string_view source, char look_for, char replace_with)
    {
        std::string result(source.size(), ' ');
        std::transform(std::begin(source), std::end(source), std::begin(result), [=](char c) { if (c == look_for) return replace_with; else return c; });
        return result;
    }

    template <typename ... Args> inline std::string replace(std::string_view source, std::string_view l1, std::string_view r1, std::string_view l2, std::string_view r2, Args ... args)
    {
        return replace(replace(source, l1, r1), l2, r2, args ...);
    }

    inline std::string replace_spaces(std::string_view source, char replacement)
    {
        std::string result(source.size(), replacement);
        std::transform(source.begin(), source.end(), result.begin(), [replacement](char c) {
            if (std::isspace(c))
                c = replacement;
            return c;
        });
        return result;
    }

    // ----------------------------------------------------------------------

    namespace _internal
    {
        template <typename Iter, typename F> inline std::string transform(Iter first, Iter last, F func)
        {
            std::string result(static_cast<size_t>(last - first), '?');
            std::transform(first, last, result.begin(), func);
            return result;
        }

        template <typename Iter, typename F> inline std::string copy_if(Iter first, Iter last, F func)
        {
            std::string result;
            std::copy_if(first, last, std::back_inserter(result), func);
            return result;
        }
    }

    inline std::string lower(std::string_view source) { return _internal::transform(source.begin(), source.end(), ::tolower); }
    inline std::string lower(const char* source) { return _internal::transform(source, source + std::strlen(source), ::tolower); }
    inline std::string lower(char* source) { return lower(const_cast<const char*>(source)); }
    template <typename Iter> inline std::string lower(Iter beg, Iter end) { return _internal::transform(beg, end, ::tolower); }

    inline std::string upper(std::string_view source) { return _internal::transform(source.begin(), source.end(), ::toupper); }
    inline std::string upper(const char* source) { return _internal::transform(source, source + std::strlen(source), ::toupper); }
    inline std::string upper(char* source) { return upper(const_cast<const char*>(source)); }
    template <typename Iter> inline std::string upper(Iter beg, Iter end) { return _internal::transform(beg, end, ::toupper); }

    inline std::string capitalize(std::string_view source)
    {
        std::string result;
        if (!source.empty()) {
            std::transform(source.begin(), source.begin() + 1, std::back_inserter(result), ::toupper);
            std::transform(source.begin() + 1, source.end(), std::back_inserter(result), ::tolower);
        }
        return result;
    }

    inline std::string remove_spaces(std::string_view source) { return _internal::copy_if(source.begin(), source.end(), [](auto c) -> bool { return !std::isspace(c); }); }
    inline std::string remove_spaces(const char* source) { return remove_spaces(std::string_view(source, std::strlen(source))); }
    inline std::string remove_spaces(char* source) { return remove_spaces(std::string_view(source, std::strlen(source))); }

    // changes subsequent spaces into one space
    inline std::string collapse_spaces(std::string_view source)
    {
        return _internal::copy_if(source.begin(), source.end(), [prev_was_space=false](auto c) mutable -> bool {
            const auto space = std::isspace(c);
            const auto result = !(prev_was_space && space);
            prev_was_space = space;
            return result;
        });
    }
    inline std::string collapse_spaces(const char* source) { return collapse_spaces(std::string_view(source, std::strlen(source))); }
    inline std::string collapse_spaces(char* source) { return collapse_spaces(std::string_view(source, std::strlen(source))); }

      // ----------------------------------------------------------------------
      // ends_with
      // ----------------------------------------------------------------------

    inline bool ends_with(std::string_view data, const char* end)
    {
        const std::string_view end_view{end};
        return std::string_view(data.data() + data.size() - end_view.size(), end_view.size()) == end_view;
    }

      // ----------------------------------------------------------------------
      // compare
      // ----------------------------------------------------------------------

    inline int compare(const char* a, size_t al, const char* b, size_t bl)
    {
        auto r = std::memcmp(a, b, std::min(al, bl));
        if (r == 0 && al != bl)
            return al < bl ? -1 : 1;
        else
            return r;
    }

    inline int compare(std::string_view s1, std::string_view s2) { return compare(s1.data(), s1.size(), s2.data(), s2.size()); }

    inline int compare(std::initializer_list<std::string_view> as, std::initializer_list<std::string_view> bs)
    {
        assert(as.size() == bs.size());
        for (auto ap = as.begin(), bp = bs.begin(); ap != as.end(); ++ap, ++bp) {
            if (const auto r = compare(*ap, *bp); r != 0)
                return r;
        }
        return 0;
    }

// ----------------------------------------------------------------------

    template <typename S> inline std::string_view string_view(const S& aSrc, size_t aOffset)
    {
        return std::string_view(aSrc.data() + aOffset, aSrc.size() - aOffset);
    }

// ----------------------------------------------------------------------

    namespace detail
    {
        template <typename S> inline std::string concat_to_string(S src, [[maybe_unused]] size_t precision = 6)
        {
            if constexpr (std::is_convertible_v<S, std::string>)
                return static_cast<std::string>(src);
            else if constexpr (std::is_same_v<S, double> || std::is_same_v<S, long double>)
                return acmacs::to_string(src, precision);
            else
                return acmacs::to_string(src);
        }
    }

    template <typename S1, typename S2, typename... Args> inline std::string concat(S1 s1, S2 s2, Args... args)
    {
        auto result = detail::concat_to_string(s1);
        result.append(detail::concat_to_string(s2));
        if constexpr (sizeof...(args) > 0)
            return concat(result, args...);
        else
            return result;
    }

    template <typename S1, typename S2, typename... Args> inline std::string concat_precise(S1 s1, S2 s2, Args... args)
    {
        auto result = detail::concat_to_string(s1, 32);
        result.append(detail::concat_to_string(s2, 32));
        if constexpr (sizeof...(args) > 0)
            return concat_precise(result, args...);
        else
            return result;
    }

// ----------------------------------------------------------------------

} // namespace string

// ----------------------------------------------------------------------
/// Local Variables:
/// eval: (if (fboundp 'eu-rename-buffer) (eu-rename-buffer))
/// End:
<|endoftext|>


<commit_before>#include "FitsObject.h"
#include <stdexcept>

using namespace std;

    Fits::Fits(const string &filename)
: m_status(0), m_filename(filename)
{
    fits_open_file(&this->m_fptr, this->m_filename.c_str(), READWRITE, &this->m_status);
    this->check();
}

Fits::Fits() {}

Fits::~Fits()
{
    fits_close_file(this->m_fptr, &this->m_status);
    this->check();
}

void Fits::check()
{
    if (this->m_status)
    {
        char buf[FLEN_STATUS];
        fits_get_errstatus(this->m_status, buf);

        /* Have to set the status back to 0 otherwise
         * when the destructor is called and the file is closed
         * then another exception will be thrown */
        this->m_status = 0;
        throw runtime_error(buf);
    }
}

void Fits::moveHDU(const string &hduname)
{
    fits_movnam_hdu(this->m_fptr, ANY_HDU, const_cast<char*>(hduname.c_str()), 0, &this->m_status);
    this->check();
}

void Fits::moveHDU(int hdunum)
{
    int hdutype;
    fits_movabs_hdu(this->m_fptr, hdunum, &hdutype, &this->m_status);
    this->check();
}

void Fits::checkForTable()
{
    /* Checks for a table extension */
    int hdutype;
    fits_get_hdu_type(this->m_fptr, &hdutype, &this->m_status);
    this->check();

    if ((hdutype != ASCII_TBL) && (hdutype != BINARY_TBL))
    {
        throw runtime_error("Non-table hdu found");
    }
}

int Fits::columnNumber(const std::string &colname)
{
    this->checkForTable();

    int colnum;
    fits_get_colnum(this->m_fptr, CASEINSEN, const_cast<char*>(colname.c_str()), &colnum, &this->m_status);
    this->check();

    return colnum;

}

long Fits::nrows()
{
    // Ensure the current hdu is a (binary) table
    this->checkForTable();

    int hdutype;
    fits_get_hdu_type(this->m_fptr, &hdutype, &this->m_status);
    this->check();

    if ((hdutype != ASCII_TBL) && (hdutype != BINARY_TBL))
    {
        throw runtime_error("Non-table hdu found");
    }

    long nrows;
    fits_get_num_rows(this->m_fptr, &nrows, &this->m_status);
    this->check();

    return nrows;

}

fitsfile **Fits::fptr() { return &this->m_fptr; }
int &Fits::status() { return this->m_status; }

void Fits::check(int status)
{
    if (status)
    {
        char buf[FLEN_STATUS];
        fits_get_errstatus(status, buf);
        throw runtime_error(buf);
    }
}

const string Fits::hduname()
{
    char buf[FLEN_VALUE];
    fits_read_key(this->m_fptr, TSTRING, "EXTNAME", buf, NULL, &this->m_status);
    this->check();
    return string(buf);
}

NewFits::NewFits(const string &filename)
{
    this->m_filename = filename;
    this->m_status = 0;

    fits_create_file(&this->m_fptr, filename.c_str(), &this->m_status);
    this->check();

    /* Ensure the basic keywords are there */
    long naxes[] = {0, 0};
    fits_create_img(this->m_fptr, BYTE_IMG, 0, naxes, &this->m_status);
    this->check();
}
<commit_msg>clearing error messages<commit_after>#include "FitsObject.h"
#include <stdexcept>

using namespace std;

    Fits::Fits(const string &filename)
: m_status(0), m_filename(filename)
{
    fits_open_file(&this->m_fptr, this->m_filename.c_str(), READWRITE, &this->m_status);
    this->check();
}

Fits::Fits() {}

Fits::~Fits()
{
    fits_close_file(this->m_fptr, &this->m_status);
    this->check();
}

void Fits::check()
{
    if (this->m_status)
    {
        char buf[FLEN_STATUS];
        fits_get_errstatus(this->m_status, buf);

        /* Have to set the status back to 0 otherwise
         * when the destructor is called and the file is closed
         * then another exception will be thrown */
        this->m_status = 0;
        /* Ensure the marks are not visible */
        fits_clear_errmsg();
        throw runtime_error(buf);
    }
}

void Fits::moveHDU(const string &hduname)
{
    fits_movnam_hdu(this->m_fptr, ANY_HDU, const_cast<char*>(hduname.c_str()), 0, &this->m_status);
    this->check();
}

void Fits::moveHDU(int hdunum)
{
    int hdutype;
    fits_movabs_hdu(this->m_fptr, hdunum, &hdutype, &this->m_status);
    this->check();
}

void Fits::checkForTable()
{
    /* Checks for a table extension */
    int hdutype;
    fits_get_hdu_type(this->m_fptr, &hdutype, &this->m_status);
    this->check();

    if ((hdutype != ASCII_TBL) && (hdutype != BINARY_TBL))
    {
        throw runtime_error("Non-table hdu found");
    }
}

int Fits::columnNumber(const std::string &colname)
{
    this->checkForTable();

    int colnum;
    fits_get_colnum(this->m_fptr, CASEINSEN, const_cast<char*>(colname.c_str()), &colnum, &this->m_status);
    this->check();

    return colnum;

}

long Fits::nrows()
{
    // Ensure the current hdu is a (binary) table
    this->checkForTable();

    int hdutype;
    fits_get_hdu_type(this->m_fptr, &hdutype, &this->m_status);
    this->check();

    if ((hdutype != ASCII_TBL) && (hdutype != BINARY_TBL))
    {
        throw runtime_error("Non-table hdu found");
    }

    long nrows;
    fits_get_num_rows(this->m_fptr, &nrows, &this->m_status);
    this->check();

    return nrows;

}

fitsfile **Fits::fptr() { return &this->m_fptr; }
int &Fits::status() { return this->m_status; }

void Fits::check(int status)
{
    if (status)
    {
        char buf[FLEN_STATUS];
        fits_get_errstatus(status, buf);
        throw runtime_error(buf);
    }
}

const string Fits::hduname()
{
    char buf[FLEN_VALUE];
    fits_read_key(this->m_fptr, TSTRING, "EXTNAME", buf, NULL, &this->m_status);
    this->check();
    return string(buf);
}

NewFits::NewFits(const string &filename)
{
    this->m_filename = filename;
    this->m_status = 0;

    fits_create_file(&this->m_fptr, filename.c_str(), &this->m_status);
    this->check();

    /* Ensure the basic keywords are there */
    long naxes[] = {0, 0};
    fits_create_img(this->m_fptr, BYTE_IMG, 0, naxes, &this->m_status);
    this->check();
}
<|endoftext|>


<commit_before>#include <IOKit/IOLib.h>
#include <sys/errno.h>

#include "ButtonStatus.hpp"
#include "CommonData.hpp"
#include "Config.hpp"
#include "Core.hpp"
#include "EventInputQueue.hpp"
#include "EventOutputQueue.hpp"
#include "EventWatcher.hpp"
#include "GlobalLock.hpp"
#include "IOLogWrapper.hpp"
#include "KeyCodeModifierFlagPairs.hpp"
#include "KeyboardRepeat.hpp"
#include "ListHookedConsumer.hpp"
#include "ListHookedKeyboard.hpp"
#include "ListHookedPointing.hpp"
#include "ModifierName.hpp"
#include "Params.hpp"
#include "PressDownKeys.hpp"
#include "PressingPhysicalKeys.hpp"
#include "RemapClass.hpp"
#include "RemapFunc/PointingRelativeToScroll.hpp"
#include "RemapFunc/common/DependingPressingPeriodKeyToKey.hpp"
#include "TimerWrapper.hpp"
#include "VirtualKey.hpp"

namespace org_pqrs_Karabiner {
namespace Core {
namespace {
IOWorkLoop* workLoop = NULL;
}

void
start(void) {
  GlobalLock::initialize();
  CommonData::initialize();
  KeyCodeModifierFlagPairs::initialize();
  ModifierName::initialize();
  EventWatcher::initialize();
  PressingPhysicalKeys::initialize();
  PressDownKeys::initialize();
  ButtonStatus::initialize();

  workLoop = IOWorkLoop::workLoop();
  if (!workLoop) {
    IOLOG_ERROR("IOWorkLoop::workLoop failed\n");
  } else {
    ListHookedDevice::initializeAll(*workLoop);

    KeyboardRepeat::initialize(*workLoop);
    EventInputQueue::initialize(*workLoop);
    VirtualKey::initialize(*workLoop);
    EventOutputQueue::initialize(*workLoop);
    RemapFunc::DependingPressingPeriodKeyToKey::static_initialize(*workLoop);
    RemapFunc::PointingRelativeToScroll::static_initialize(*workLoop);
    ListHookedKeyboard::static_initialize(*workLoop);
    RemapClassManager::initialize(*workLoop);
  }

  Config::sysctl_register();
}

void
stop(void) {
  // Destroy global lock.
  // Then, all callbacks and hooked functions become inactive.
  GlobalLock::terminate();

  // ------------------------------------------------------------
  ListHookedDevice::terminateAll();

  // ------------------------------------------------------------
  // call terminate
  Config::sysctl_unregister();

  RemapClassManager::terminate();
  KeyboardRepeat::terminate();
  EventInputQueue::terminate();
  VirtualKey::terminate();
  EventOutputQueue::terminate();
  RemapFunc::DependingPressingPeriodKeyToKey::static_terminate();
  RemapFunc::PointingRelativeToScroll::static_terminate();
  ListHookedKeyboard::static_terminate();

  if (workLoop) {
    workLoop->release();
    workLoop = NULL;
  }

  EventWatcher::terminate();
  PressDownKeys::terminate();
  PressingPhysicalKeys::terminate();

  CommonData::terminate();
}

// ======================================================================
bool
IOHIKeyboard_gIOMatchedNotification_callback(void* target, void* refCon, IOService* newService, IONotifier* notifier) {
  GlobalLock::ScopedLock lk;
  if (!lk) return false;

  IOLOG_DEBUG("%s newService:%p\n", __FUNCTION__, newService);

  IOHIDevice* device = OSDynamicCast(IOHIKeyboard, newService);
  if (!device) return false;

  ListHookedKeyboard::instance().push_back(new ListHookedKeyboard::Item(device));
  ListHookedConsumer::instance().push_back(new ListHookedConsumer::Item(device));
  return true;
}

bool
IOHIKeyboard_gIOTerminatedNotification_callback(void* target, void* refCon, IOService* newService, IONotifier* notifier) {
  GlobalLock::ScopedLock lk;
  if (!lk) return false;

  IOLOG_DEBUG("%s newService:%p\n", __FUNCTION__, newService);

  IOHIDevice* device = OSDynamicCast(IOHIKeyboard, newService);
  if (!device) return false;

  ListHookedKeyboard::instance().erase(device);
  ListHookedConsumer::instance().erase(device);
  return true;
}

bool
IOHIPointing_gIOMatchedNotification_callback(void* target, void* refCon, IOService* newService, IONotifier* notifier) {
  GlobalLock::ScopedLock lk;
  if (!lk) return false;

  IOLOG_DEBUG("%s newService:%p\n", __FUNCTION__, newService);

  IOHIDevice* device = OSDynamicCast(IOHIPointing, newService);
  if (!device) return false;

  ListHookedPointing::instance().push_back(new ListHookedPointing::Item(device));
  return true;
}

bool
IOHIPointing_gIOTerminatedNotification_callback(void* target, void* refCon, IOService* newService, IONotifier* notifier) {
  GlobalLock::ScopedLock lk;
  if (!lk) return false;

  IOLOG_DEBUG("%s newService:%p\n", __FUNCTION__, newService);

  IOHIDevice* device = OSDynamicCast(IOHIPointing, newService);
  if (!device) return false;

  ListHookedPointing::instance().erase(device);
  return true;
}

// ======================================================================
namespace {
void
resetWhenPressingPhysicalKeysIsEmpty(void) {
  if (PressingPhysicalKeys::empty()) {
    IOLOG_DEVEL("resetWhenPressingPhysicalKeysIsEmpty\n");
    PressingPhysicalKeys::clear();
    KeyboardRepeat::cancel();
    EventWatcher::reset();
    FlagStatus::globalFlagStatus().reset();
    ButtonStatus::reset();
    VirtualKey::reset();
    EventOutputQueue::FireModifiers::fire(FlagStatus::globalFlagStatus().makeFlags());
    EventOutputQueue::FireRelativePointer::fire();
    PressDownKeys::clear();
  }
}
}

// ======================================================================
void
remap_KeyboardEventCallback(const Params_Base& paramsBase) {
  auto params = paramsBase.get_Params_KeyboardEventCallBack();
  if (!params) return;

  RemapParams remapParams(*params);

  // Call `prepare` before FlagStatus::set.
  //
  // For example, with this autogen:
  //
  //    <autogen>
  //      __HoldingKeyToKey__
  //      KeyCode::I,
  //      __{ KeyCode::A }__
  //      __{ KeyCode::B }__
  //    </autogen>
  //
  // Hitting `i` and `shift` immediately,
  // `a` and `shift` should be sent.
  //
  // If we call prepare after FlagStatus::set,
  // `shift-a` will be sent. It's not intended.

  RemapClassManager::prepare(remapParams);

  FlagStatus::globalFlagStatus().set(params->key, params->flags);

  RemapClassManager::remap(remapParams);

  // ------------------------------------------------------------
  if (!remapParams.isremapped) {
    Params_KeyboardEventCallBack p(params->eventType,
                                   FlagStatus::globalFlagStatus().makeFlags(),
                                   params->key,
                                   params->charCode,
                                   params->charSet,
                                   params->origCharCode,
                                   params->origCharSet,
                                   params->keyboardType,
                                   false);
    KeyboardRepeat::set(p);
    EventOutputQueue::FireKey::fire(p);
  }

  resetWhenPressingPhysicalKeysIsEmpty();

  RemapFunc::PointingRelativeToScroll::cancelScroll();
}

void
remap_KeyboardSpecialEventCallback(const Params_Base& paramsBase) {
  auto params = paramsBase.get_Params_KeyboardSpecialEventCallback();
  if (!params) return;

  RemapParams remapParams(*params);
  RemapClassManager::prepare(remapParams);
  RemapClassManager::remap(remapParams);

  // ----------------------------------------
  if (!remapParams.isremapped) {
    Params_KeyboardSpecialEventCallback p(params->eventType,
                                          FlagStatus::globalFlagStatus().makeFlags(),
                                          params->key,
                                          params->flavor,
                                          params->guid,
                                          false);
    KeyboardRepeat::set(p);
    EventOutputQueue::FireConsumer::fire(p);
  }

  resetWhenPressingPhysicalKeysIsEmpty();

  RemapFunc::PointingRelativeToScroll::cancelScroll();
}

void
remap_RelativePointerEventCallback(const Params_Base& paramsBase) {
  auto params = paramsBase.get_Params_RelativePointerEventCallback();
  if (!params) return;

  ButtonStatus::set(params->ex_button, params->ex_isbuttondown);

  RemapParams remapParams(*params);
  RemapClassManager::prepare(remapParams);
  RemapClassManager::remap(remapParams);

  // ------------------------------------------------------------
  if (!remapParams.isremapped) {
    EventOutputQueue::FireRelativePointer::fire(ButtonStatus::makeButtons(), params->dx, params->dy);
  }

  if (params->ex_button != PointingButton::NONE) {
    resetWhenPressingPhysicalKeysIsEmpty();
  }
}

void
remap_ScrollWheelEventCallback(const Params_Base& paramsBase) {
  auto params = paramsBase.get_Params_ScrollWheelEventCallback();
  if (!params) return;

  RemapParams remapParams(*params);
  RemapClassManager::prepare(remapParams);
  RemapClassManager::remap(remapParams);

  if (!remapParams.isremapped) {
    EventOutputQueue::FireScrollWheel::fire(*params);
    RemapFunc::PointingRelativeToScroll::cancelScroll();
  }
}
}
}
<commit_msg>update comment<commit_after>#include <IOKit/IOLib.h>
#include <sys/errno.h>

#include "ButtonStatus.hpp"
#include "CommonData.hpp"
#include "Config.hpp"
#include "Core.hpp"
#include "EventInputQueue.hpp"
#include "EventOutputQueue.hpp"
#include "EventWatcher.hpp"
#include "GlobalLock.hpp"
#include "IOLogWrapper.hpp"
#include "KeyCodeModifierFlagPairs.hpp"
#include "KeyboardRepeat.hpp"
#include "ListHookedConsumer.hpp"
#include "ListHookedKeyboard.hpp"
#include "ListHookedPointing.hpp"
#include "ModifierName.hpp"
#include "Params.hpp"
#include "PressDownKeys.hpp"
#include "PressingPhysicalKeys.hpp"
#include "RemapClass.hpp"
#include "RemapFunc/PointingRelativeToScroll.hpp"
#include "RemapFunc/common/DependingPressingPeriodKeyToKey.hpp"
#include "TimerWrapper.hpp"
#include "VirtualKey.hpp"

namespace org_pqrs_Karabiner {
namespace Core {
namespace {
IOWorkLoop* workLoop = NULL;
}

void
start(void) {
  GlobalLock::initialize();
  CommonData::initialize();
  KeyCodeModifierFlagPairs::initialize();
  ModifierName::initialize();
  EventWatcher::initialize();
  PressingPhysicalKeys::initialize();
  PressDownKeys::initialize();
  ButtonStatus::initialize();

  workLoop = IOWorkLoop::workLoop();
  if (!workLoop) {
    IOLOG_ERROR("IOWorkLoop::workLoop failed\n");
  } else {
    ListHookedDevice::initializeAll(*workLoop);

    KeyboardRepeat::initialize(*workLoop);
    EventInputQueue::initialize(*workLoop);
    VirtualKey::initialize(*workLoop);
    EventOutputQueue::initialize(*workLoop);
    RemapFunc::DependingPressingPeriodKeyToKey::static_initialize(*workLoop);
    RemapFunc::PointingRelativeToScroll::static_initialize(*workLoop);
    ListHookedKeyboard::static_initialize(*workLoop);
    RemapClassManager::initialize(*workLoop);
  }

  Config::sysctl_register();
}

void
stop(void) {
  // Destroy global lock.
  // Then, all callbacks and hooked functions become inactive.
  GlobalLock::terminate();

  // ------------------------------------------------------------
  ListHookedDevice::terminateAll();

  // ------------------------------------------------------------
  // call terminate
  Config::sysctl_unregister();

  RemapClassManager::terminate();
  KeyboardRepeat::terminate();
  EventInputQueue::terminate();
  VirtualKey::terminate();
  EventOutputQueue::terminate();
  RemapFunc::DependingPressingPeriodKeyToKey::static_terminate();
  RemapFunc::PointingRelativeToScroll::static_terminate();
  ListHookedKeyboard::static_terminate();

  if (workLoop) {
    workLoop->release();
    workLoop = NULL;
  }

  EventWatcher::terminate();
  PressDownKeys::terminate();
  PressingPhysicalKeys::terminate();

  CommonData::terminate();
}

// ======================================================================
bool
IOHIKeyboard_gIOMatchedNotification_callback(void* target, void* refCon, IOService* newService, IONotifier* notifier) {
  GlobalLock::ScopedLock lk;
  if (!lk) return false;

  IOLOG_DEBUG("%s newService:%p\n", __FUNCTION__, newService);

  IOHIDevice* device = OSDynamicCast(IOHIKeyboard, newService);
  if (!device) return false;

  ListHookedKeyboard::instance().push_back(new ListHookedKeyboard::Item(device));
  ListHookedConsumer::instance().push_back(new ListHookedConsumer::Item(device));
  return true;
}

bool
IOHIKeyboard_gIOTerminatedNotification_callback(void* target, void* refCon, IOService* newService, IONotifier* notifier) {
  GlobalLock::ScopedLock lk;
  if (!lk) return false;

  IOLOG_DEBUG("%s newService:%p\n", __FUNCTION__, newService);

  IOHIDevice* device = OSDynamicCast(IOHIKeyboard, newService);
  if (!device) return false;

  ListHookedKeyboard::instance().erase(device);
  ListHookedConsumer::instance().erase(device);
  return true;
}

bool
IOHIPointing_gIOMatchedNotification_callback(void* target, void* refCon, IOService* newService, IONotifier* notifier) {
  GlobalLock::ScopedLock lk;
  if (!lk) return false;

  IOLOG_DEBUG("%s newService:%p\n", __FUNCTION__, newService);

  IOHIDevice* device = OSDynamicCast(IOHIPointing, newService);
  if (!device) return false;

  ListHookedPointing::instance().push_back(new ListHookedPointing::Item(device));
  return true;
}

bool
IOHIPointing_gIOTerminatedNotification_callback(void* target, void* refCon, IOService* newService, IONotifier* notifier) {
  GlobalLock::ScopedLock lk;
  if (!lk) return false;

  IOLOG_DEBUG("%s newService:%p\n", __FUNCTION__, newService);

  IOHIDevice* device = OSDynamicCast(IOHIPointing, newService);
  if (!device) return false;

  ListHookedPointing::instance().erase(device);
  return true;
}

// ======================================================================
namespace {
void
resetWhenPressingPhysicalKeysIsEmpty(void) {
  if (PressingPhysicalKeys::empty()) {
    IOLOG_DEVEL("resetWhenPressingPhysicalKeysIsEmpty\n");
    PressingPhysicalKeys::clear();
    KeyboardRepeat::cancel();
    EventWatcher::reset();
    FlagStatus::globalFlagStatus().reset();
    ButtonStatus::reset();
    VirtualKey::reset();
    EventOutputQueue::FireModifiers::fire(FlagStatus::globalFlagStatus().makeFlags());
    EventOutputQueue::FireRelativePointer::fire();
    PressDownKeys::clear();
  }
}
}

// ======================================================================
void
remap_KeyboardEventCallback(const Params_Base& paramsBase) {
  auto params = paramsBase.get_Params_KeyboardEventCallBack();
  if (!params) return;

  RemapParams remapParams(*params);

  // Call `prepare` before FlagStatus::set.
  //
  // For example, with this autogen:
  //
  //    <autogen>
  //      __HoldingKeyToKey__
  //      KeyCode::I,
  //      __{ KeyCode::A }__
  //      __{ KeyCode::B }__
  //    </autogen>
  //
  // Hitting `i` and `shift` immediately (`i` down, `shift` down, `i` up, `shift` up),
  // `a` and `shift` should be sent (`a` down, `shift` down, `a` up, `shift` up).
  //
  // If we call prepare after FlagStatus::set,
  // `shift-a` will be sent. It's not intended.

  RemapClassManager::prepare(remapParams);

  FlagStatus::globalFlagStatus().set(params->key, params->flags);

  RemapClassManager::remap(remapParams);

  // ------------------------------------------------------------
  if (!remapParams.isremapped) {
    Params_KeyboardEventCallBack p(params->eventType,
                                   FlagStatus::globalFlagStatus().makeFlags(),
                                   params->key,
                                   params->charCode,
                                   params->charSet,
                                   params->origCharCode,
                                   params->origCharSet,
                                   params->keyboardType,
                                   false);
    KeyboardRepeat::set(p);
    EventOutputQueue::FireKey::fire(p);
  }

  resetWhenPressingPhysicalKeysIsEmpty();

  RemapFunc::PointingRelativeToScroll::cancelScroll();
}

void
remap_KeyboardSpecialEventCallback(const Params_Base& paramsBase) {
  auto params = paramsBase.get_Params_KeyboardSpecialEventCallback();
  if (!params) return;

  RemapParams remapParams(*params);
  RemapClassManager::prepare(remapParams);
  RemapClassManager::remap(remapParams);

  // ----------------------------------------
  if (!remapParams.isremapped) {
    Params_KeyboardSpecialEventCallback p(params->eventType,
                                          FlagStatus::globalFlagStatus().makeFlags(),
                                          params->key,
                                          params->flavor,
                                          params->guid,
                                          false);
    KeyboardRepeat::set(p);
    EventOutputQueue::FireConsumer::fire(p);
  }

  resetWhenPressingPhysicalKeysIsEmpty();

  RemapFunc::PointingRelativeToScroll::cancelScroll();
}

void
remap_RelativePointerEventCallback(const Params_Base& paramsBase) {
  auto params = paramsBase.get_Params_RelativePointerEventCallback();
  if (!params) return;

  ButtonStatus::set(params->ex_button, params->ex_isbuttondown);

  RemapParams remapParams(*params);
  RemapClassManager::prepare(remapParams);
  RemapClassManager::remap(remapParams);

  // ------------------------------------------------------------
  if (!remapParams.isremapped) {
    EventOutputQueue::FireRelativePointer::fire(ButtonStatus::makeButtons(), params->dx, params->dy);
  }

  if (params->ex_button != PointingButton::NONE) {
    resetWhenPressingPhysicalKeysIsEmpty();
  }
}

void
remap_ScrollWheelEventCallback(const Params_Base& paramsBase) {
  auto params = paramsBase.get_Params_ScrollWheelEventCallback();
  if (!params) return;

  RemapParams remapParams(*params);
  RemapClassManager::prepare(remapParams);
  RemapClassManager::remap(remapParams);

  if (!remapParams.isremapped) {
    EventOutputQueue::FireScrollWheel::fire(*params);
    RemapFunc::PointingRelativeToScroll::cancelScroll();
  }
}
}
}
<|endoftext|>