<commit_before>
#include <sstream>

#include "flame/base.h"
#include "pyflame.h"

#define TRY PyMachine *machine = (PyMachine*)raw; try

namespace {

struct PyMachine {
    PyObject_HEAD

    PyObject *weak;
    Machine *machine;
};

static
int PyMachine_init(PyObject *raw, PyObject *args, PyObject *kws)
{
    TRY {
        assert(!machine->weak);

        std::auto_ptr<Config> C(PyGLPSParse2Config(raw, args, kws));

        machine->machine = new Machine(*C);

        return 0;
    } CATCH3(key_error, KeyError, -1)
      CATCH3(std::invalid_argument, ValueError, -1)
      CATCH3(std::exception, RuntimeError, -1)
}

static
void PyMachine_free(PyObject *raw)
{
    TRY {
        std::auto_ptr<Machine> S(machine->machine);
        machine->machine = NULL;

        if(machine->weak)
            PyObject_ClearWeakRefs(raw);

        Py_TYPE(raw)->tp_free(raw);
    } CATCH2V(std::exception, RuntimeError)
}

static
PyObject *PyMachine_str(PyObject *raw)
{
    TRY {
        std::ostringstream strm;
        strm << *(machine->machine);
        return PyString_FromString(strm.str().c_str());
    } CATCH()
}

static
PyObject *PyMachine_conf(PyObject *raw, PyObject *args, PyObject *kws)
{
    TRY {
        PyObject *pyindex = Py_None;
        const char *pnames[] = {"index", NULL};
        if(!PyArg_ParseTupleAndKeywords(args, kws, "|O", (char**)pnames, &pyindex))
            return NULL;

        Config C;
        if(pyindex==Py_None) {
            C = machine->machine->conf();
        } else {
            long index = PyInt_AsLong(pyindex);
            if(index<0 || (unsigned long)index>=machine->machine->size())
                return PyErr_Format(PyExc_IndexError, "Element index out of range");
            C = (*machine->machine)[index]->conf();
        }
        C.flatten();

        return conf2dict(&C);
    } CATCH()
}

static
PyObject *PyMachine_allocState(PyObject *raw, PyObject *args, PyObject *kws)
{
    TRY {
        PyObject *d = Py_None, *W = Py_False;
        const char *pnames[] = {"config", "inherit", NULL};
        if(!PyArg_ParseTupleAndKeywords(args, kws, "|OO", (char**)pnames, &d, &W))
            return NULL;

        Config C;
        if(d==Py_None) {
            C = machine->machine->conf();
        } else if(PyDict_Check(d)) {
            if(PyObject_IsTrue(W)) {
                C = machine->machine->conf();
                C.push_scope();
            }
            Dict2Config(C, d);
        } else {
            return PyErr_Format(PyExc_ValueError, "allocState() needs config=None or {}");
        }
        std::auto_ptr<StateBase> state(machine->machine->allocState(C));
        PyObject *ret = wrapstate(state.get());
        state.release();
        return ret;
    } CATCH()
}

struct PyStoreObserver : public Observer
{
    PyRef<> list;
    PyStoreObserver()
        :list(PyList_New(0))
    {}
    virtual ~PyStoreObserver() {}
    virtual void view(const ElementVoid* elem, const StateBase* state)
    {
        PyRef<> tuple(PyTuple_New(2));
        std::auto_ptr<StateBase> tmpstate(state->clone());
        PyRef<> statecopy(wrapstate(tmpstate.get()));
        tmpstate.release();

        PyTuple_SET_ITEM(tuple.py(), 0, PyInt_FromSize_t(elem->index));
        PyTuple_SET_ITEM(tuple.py(), 1, statecopy.release());
        if(PyList_Append(list.py(), tuple.py()))
            throw std::runtime_error(""); // a py exception is active
    }
};

struct PyScopedObserver
{
    Machine *machine;
    std::vector<size_t> observed;
    PyScopedObserver(Machine *m) : machine(m) {}
    ~PyScopedObserver() {
        for(size_t i=0; i<observed.size(); i++) {
            (*machine)[i]->set_observer(NULL);
        }
    }
    void observe(size_t i, Observer *o)
    {
        if(i>=machine->size())
            throw std::runtime_error("element index out of range");
        if((*machine)[i]->observer())
            throw std::runtime_error("element already observed");
        observed.push_back(i);
        (*machine)[i]->set_observer(o);
    }
};

static
PyObject *PyMachine_propagate(PyObject *raw, PyObject *args, PyObject *kws)
{

    TRY {
        PyObject *state, *toobserv = Py_None;
        unsigned long start = 0, max = (unsigned long)-1;
        const char *pnames[] = {"state", "start", "max", "observe", NULL};
        if(!PyArg_ParseTupleAndKeywords(args, kws, "O|kkO", (char**)pnames, &state, &start, &max, &toobserv))
            return NULL;

        PyStoreObserver observer;
        PyScopedObserver observing(machine->machine);

        if(toobserv!=Py_None) {
            PyRef<> iter(PyObject_GetIter(toobserv)), item;

            while(item.reset(PyIter_Next(iter.py()), PyRef<>::allow_null())) {
                Py_ssize_t num = PyNumber_AsSsize_t(item.py(), PyExc_ValueError);
                if(PyErr_Occurred())
                    throw std::runtime_error(""); // caller will get active python exception

                observing.observe(num, &observer);

            }
        }

        machine->machine->propagate(unwrapstate(state), start, max);
        if(toobserv) {
            return observer.list.release();
        } else {
            Py_RETURN_NONE;
        }
    } CATCH2(std::invalid_argument, ValueError)
    CATCH()
}

static
PyObject *PyMachine_reconfigure(PyObject *raw, PyObject *args, PyObject *kws)
{
    TRY{
        unsigned long idx;
        PyObject *conf;
        const char *pnames[] = {"index", "config", NULL};
        if(!PyArg_ParseTupleAndKeywords(args, kws, "kO!|", (char**)pnames, &idx, &PyDict_Type, &conf))
            return NULL;

        if(idx>=machine->machine->size())
            return PyErr_Format(PyExc_ValueError, "invalid element index %lu", idx);

        // TODO: only allow existing elements to be changed.
        //       allow unassign
        Config newconf((*machine->machine)[idx]->conf());

        Dict2Config(newconf, conf, 3); // set depth=3 to prevent recursion

        machine->machine->reconfigure(idx, newconf);

        Py_RETURN_NONE;
    } CATCH2(std::invalid_argument, ValueError)
    CATCH()
}

static
Py_ssize_t PyMachine_len(PyObject *raw)
{
    TRY{
        return machine->machine->size();
    }CATCH1(-1)
}

static PyMethodDef PyMachine_methods[] = {
    {"conf", (PyCFunction)&PyMachine_conf, METH_VARARGS|METH_KEYWORDS,
     "conf() -> {} Machine config\n"
     "conf(index) -> {} Element config"},
    {"allocState", (PyCFunction)&PyMachine_allocState, METH_VARARGS|METH_KEYWORDS,
     "allocState() -> State\n"
     "allocState({'variable':int|str}) -> State\n"
     "Allocate a new State based on this Machine's configuration."
     "  Optionally provide additional configuration"},
    {"propagate", (PyCFunction)&PyMachine_propagate, METH_VARARGS|METH_KEYWORDS,
     "propagate(State, start=0, max=-1, observe=None)\n"
     "propagate(State, start=0, max=-1, observe=[1,4,...]) -> [(index,State), ...]\n"
     "Propagate the provided State through the simulation.\n"
     "\n"
     "start and max selects through which element the State will be passed.\n"
     "\n"
     "observe may be None or an iterable yielding element indicies.\n"
     "In the second form propagate() returns a list of tuples with the output State of the selected elements."
    },
    {"reconfigure", (PyCFunction)&PyMachine_reconfigure, METH_VARARGS|METH_KEYWORDS,
     "reconfigure(index, {'variable':int|str})\n"
     "Change the configuration of an element."},
    {NULL, NULL, 0, NULL}
};

static PySequenceMethods PyMachine_seq = {
    &PyMachine_len
};

static PyTypeObject PyMachineType = {
#if PY_MAJOR_VERSION >= 3
    PyVarObject_HEAD_INIT(NULL, 0)
#else
    PyObject_HEAD_INIT(NULL)
    0,
#endif
    "flame._internal.Machine",
    sizeof(PyMachine),
};

} // namespace

static const char pymdoc[] =
        "Machine(config, path=None, extra=None)\n"
        "Machine(config, path='/directry/', extra={'variable':float|str}})\n"
        "\n"
        "A Machine() the primary interface to the FLAME simulation engine.\n"
        "\n"
        "The 'config' argument may be a file-like object (with read())"
        " or a buffer which will be parsed with the GLPS parser (see GLPSParser::parse).\n"
        " Or it may be a dictionary.\n"
        "\n"
        ">>> with open('some.lat', 'rb') as F:\n"
        "      M = Machine(F)\n"
        ">>>\n"
        ;

int registerModMachine(PyObject *mod)
{
    PyMachineType.tp_doc = pymdoc;
    PyMachineType.tp_str = &PyMachine_str;

    PyMachineType.tp_new = &PyType_GenericNew;
    PyMachineType.tp_init = &PyMachine_init;
    PyMachineType.tp_dealloc = &PyMachine_free;

    PyMachineType.tp_weaklistoffset = offsetof(PyMachine, weak);

    PyMachineType.tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE;
    PyMachineType.tp_methods = PyMachine_methods;
    PyMachineType.tp_as_sequence = &PyMachine_seq;

    if(PyType_Ready(&PyMachineType))
        return -1;

    Py_INCREF((PyObject*)&PyMachineType);
    if(PyModule_AddObject(mod, "Machine", (PyObject*)&PyMachineType)) {
        Py_DECREF((PyObject*)&PyMachineType);
        return -1;
    }

    return 0;
}
<commit_msg>minor<commit_after>
#include <sstream>

#include "flame/base.h"
#include "pyflame.h"

#define TRY PyMachine *machine = (PyMachine*)raw; try

namespace {

struct PyMachine {
    PyObject_HEAD

    PyObject *weak;
    Machine *machine;
};

static
int PyMachine_init(PyObject *raw, PyObject *args, PyObject *kws)
{
    TRY {
        assert(!machine->weak);

        std::auto_ptr<Config> C(PyGLPSParse2Config(raw, args, kws));

        machine->machine = new Machine(*C);

        return 0;
    } CATCH3(key_error, KeyError, -1)
      CATCH3(std::invalid_argument, ValueError, -1)
      CATCH3(std::exception, RuntimeError, -1)
}

static
void PyMachine_free(PyObject *raw)
{
    TRY {
        std::auto_ptr<Machine> S(machine->machine);
        machine->machine = NULL;

        if(machine->weak)
            PyObject_ClearWeakRefs(raw);

        Py_TYPE(raw)->tp_free(raw);
    } CATCH2V(std::exception, RuntimeError)
}

static
PyObject *PyMachine_str(PyObject *raw)
{
    TRY {
        std::ostringstream strm;
        strm << *(machine->machine);
        return PyString_FromString(strm.str().c_str());
    } CATCH()
}

static
PyObject *PyMachine_conf(PyObject *raw, PyObject *args, PyObject *kws)
{
    TRY {
        PyObject *pyindex = Py_None;
        const char *pnames[] = {"index", NULL};
        if(!PyArg_ParseTupleAndKeywords(args, kws, "|O", (char**)pnames, &pyindex))
            return NULL;

        Config C;
        if(pyindex==Py_None) {
            C = machine->machine->conf();
        } else if(PyNumber_Check(pyindex)) {
            PyRef<> pylong(PyNumber_Long(pyindex));
            long index = PyLong_AsLong(pylong.py());
            if(index<0 || (unsigned long)index>=machine->machine->size())
                return PyErr_Format(PyExc_IndexError, "Element index out of range");
            C = (*machine->machine)[index]->conf();
        } else {
            return PyErr_Format(PyExc_ValueError, "'index' must be an integer or None");
        }
        C.flatten();

        return conf2dict(&C);
    } CATCH()
}

static
PyObject *PyMachine_allocState(PyObject *raw, PyObject *args, PyObject *kws)
{
    TRY {
        PyObject *d = Py_None, *W = Py_False;
        const char *pnames[] = {"config", "inherit", NULL};
        if(!PyArg_ParseTupleAndKeywords(args, kws, "|OO", (char**)pnames, &d, &W))
            return NULL;

        Config C;
        if(d==Py_None) {
            C = machine->machine->conf();
        } else if(PyDict_Check(d)) {
            if(PyObject_IsTrue(W)) {
                C = machine->machine->conf();
                C.push_scope();
            }
            Dict2Config(C, d);
        } else {
            return PyErr_Format(PyExc_ValueError, "allocState() needs config=None or {}");
        }
        std::auto_ptr<StateBase> state(machine->machine->allocState(C));
        PyObject *ret = wrapstate(state.get());
        state.release();
        return ret;
    } CATCH()
}

struct PyStoreObserver : public Observer
{
    PyRef<> list;
    PyStoreObserver()
        :list(PyList_New(0))
    {}
    virtual ~PyStoreObserver() {}
    virtual void view(const ElementVoid* elem, const StateBase* state)
    {
        PyRef<> tuple(PyTuple_New(2));
        std::auto_ptr<StateBase> tmpstate(state->clone());
        PyRef<> statecopy(wrapstate(tmpstate.get()));
        tmpstate.release();

        PyTuple_SET_ITEM(tuple.py(), 0, PyInt_FromSize_t(elem->index));
        PyTuple_SET_ITEM(tuple.py(), 1, statecopy.release());
        if(PyList_Append(list.py(), tuple.py()))
            throw std::runtime_error(""); // a py exception is active
    }
};

struct PyScopedObserver
{
    Machine *machine;
    std::vector<size_t> observed;
    PyScopedObserver(Machine *m) : machine(m) {}
    ~PyScopedObserver() {
        for(size_t i=0; i<observed.size(); i++) {
            (*machine)[i]->set_observer(NULL);
        }
    }
    void observe(size_t i, Observer *o)
    {
        if(i>=machine->size())
            throw std::runtime_error("element index out of range");
        if((*machine)[i]->observer())
            throw std::runtime_error("element already observed");
        observed.push_back(i);
        (*machine)[i]->set_observer(o);
    }
};

static
PyObject *PyMachine_propagate(PyObject *raw, PyObject *args, PyObject *kws)
{

    TRY {
        PyObject *state, *toobserv = Py_None;
        unsigned long start = 0, max = (unsigned long)-1;
        const char *pnames[] = {"state", "start", "max", "observe", NULL};
        if(!PyArg_ParseTupleAndKeywords(args, kws, "O|kkO", (char**)pnames, &state, &start, &max, &toobserv))
            return NULL;

        PyStoreObserver observer;
        PyScopedObserver observing(machine->machine);

        if(toobserv!=Py_None) {
            PyRef<> iter(PyObject_GetIter(toobserv)), item;

            while(item.reset(PyIter_Next(iter.py()), PyRef<>::allow_null())) {
                Py_ssize_t num = PyNumber_AsSsize_t(item.py(), PyExc_ValueError);
                if(PyErr_Occurred())
                    throw std::runtime_error(""); // caller will get active python exception

                observing.observe(num, &observer);

            }
        }

        machine->machine->propagate(unwrapstate(state), start, max);
        if(toobserv) {
            return observer.list.release();
        } else {
            Py_RETURN_NONE;
        }
    } CATCH2(std::invalid_argument, ValueError)
    CATCH()
}

static
PyObject *PyMachine_reconfigure(PyObject *raw, PyObject *args, PyObject *kws)
{
    TRY{
        unsigned long idx;
        PyObject *conf, *replace = Py_False;
        const char *pnames[] = {"index", "config", "replace", NULL};
        if(!PyArg_ParseTupleAndKeywords(args, kws, "kO!|O", (char**)pnames, &idx, &PyDict_Type, &conf, &replace))
            return NULL;

        if(idx>=machine->machine->size())
            return PyErr_Format(PyExc_ValueError, "invalid element index %lu", idx);

        Config newconf;
        if(!PyObject_IsTrue(replace))
            newconf = (*machine->machine)[idx]->conf();

        Dict2Config(newconf, conf, 3); // set depth=3 to prevent recursion

        machine->machine->reconfigure(idx, newconf);

        Py_RETURN_NONE;
    } CATCH2(std::invalid_argument, ValueError)
    CATCH()
}

static
Py_ssize_t PyMachine_len(PyObject *raw)
{
    TRY{
        return machine->machine->size();
    }CATCH1(-1)
}

static PyMethodDef PyMachine_methods[] = {
    {"conf", (PyCFunction)&PyMachine_conf, METH_VARARGS|METH_KEYWORDS,
     "conf() -> {} Machine config\n"
     "conf(index) -> {} Element config"},
    {"allocState", (PyCFunction)&PyMachine_allocState, METH_VARARGS|METH_KEYWORDS,
     "allocState() -> State\n"
     "allocState({'variable':int|str}) -> State\n"
     "Allocate a new State based on this Machine's configuration."
     "  Optionally provide additional configuration"},
    {"propagate", (PyCFunction)&PyMachine_propagate, METH_VARARGS|METH_KEYWORDS,
     "propagate(State, start=0, max=-1, observe=None)\n"
     "propagate(State, start=0, max=-1, observe=[1,4,...]) -> [(index,State), ...]\n"
     "Propagate the provided State through the simulation.\n"
     "\n"
     "start and max selects through which element the State will be passed.\n"
     "\n"
     "observe may be None or an iterable yielding element indicies.\n"
     "In the second form propagate() returns a list of tuples with the output State of the selected elements."
    },
    {"reconfigure", (PyCFunction)&PyMachine_reconfigure, METH_VARARGS|METH_KEYWORDS,
     "reconfigure(index, {'variable':int|str})\n"
     "Change the configuration of an element."},
    {NULL, NULL, 0, NULL}
};

static PySequenceMethods PyMachine_seq = {
    &PyMachine_len
};

static PyTypeObject PyMachineType = {
#if PY_MAJOR_VERSION >= 3
    PyVarObject_HEAD_INIT(NULL, 0)
#else
    PyObject_HEAD_INIT(NULL)
    0,
#endif
    "flame._internal.Machine",
    sizeof(PyMachine),
};

} // namespace

static const char pymdoc[] =
        "Machine(config, path=None, extra=None)\n"
        "Machine(config, path='/directry/', extra={'variable':float|str}})\n"
        "\n"
        "A Machine() the primary interface to the FLAME simulation engine.\n"
        "\n"
        "The 'config' argument may be a file-like object (with read())"
        " or a buffer which will be parsed with the GLPS parser (see GLPSParser::parse).\n"
        " Or it may be a dictionary.\n"
        "\n"
        ">>> with open('some.lat', 'rb') as F:\n"
        "      M = Machine(F)\n"
        ">>>\n"
        ;

int registerModMachine(PyObject *mod)
{
    PyMachineType.tp_doc = pymdoc;
    PyMachineType.tp_str = &PyMachine_str;

    PyMachineType.tp_new = &PyType_GenericNew;
    PyMachineType.tp_init = &PyMachine_init;
    PyMachineType.tp_dealloc = &PyMachine_free;

    PyMachineType.tp_weaklistoffset = offsetof(PyMachine, weak);

    PyMachineType.tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE;
    PyMachineType.tp_methods = PyMachine_methods;
    PyMachineType.tp_as_sequence = &PyMachine_seq;

    if(PyType_Ready(&PyMachineType))
        return -1;

    Py_INCREF((PyObject*)&PyMachineType);
    if(PyModule_AddObject(mod, "Machine", (PyObject*)&PyMachineType)) {
        Py_DECREF((PyObject*)&PyMachineType);
        return -1;
    }

    return 0;
}
<|endoftext|>


<commit_before>// Copyright (C) 2013 Jérôme Leclercq
// This file is part of the "Nazara Engine - Core module"
// For conditions of distribution and use, see copyright notice in Config.hpp

#include <Nazara/Core/MemoryStream.hpp>
#include <algorithm>
#include <cstring>
#include <Nazara/Core/Debug.hpp>

NzMemoryStream::NzMemoryStream(const void* ptr, nzUInt64 size) :
m_ptr(reinterpret_cast<const nzUInt8*>(ptr)),
m_pos(0),
m_size(size)
{
}

NzMemoryStream::~NzMemoryStream()
{
}

bool NzMemoryStream::EndOfStream() const
{
	return m_pos == m_size;
}

nzUInt64 NzMemoryStream::GetCursorPos() const
{
	return m_pos;
}

nzUInt64 NzMemoryStream::GetSize() const
{
	return m_size;
}

std::size_t NzMemoryStream::Read(void* buffer, std::size_t size)
{
	unsigned int readSize = std::min(static_cast<unsigned int>(size), static_cast<unsigned int>(m_size-m_pos));
	std::memcpy(buffer, &m_ptr[m_pos], readSize);
	m_pos += readSize;

	return readSize;
}

bool NzMemoryStream::SetCursorPos(nzUInt64 offset)
{
	m_pos = std::min(offset, m_size);

	return true;
}
<commit_msg>Fixed MemoryStream::Read crash when just skipping (null buffer)<commit_after>// Copyright (C) 2013 Jérôme Leclercq
// This file is part of the "Nazara Engine - Core module"
// For conditions of distribution and use, see copyright notice in Config.hpp

#include <Nazara/Core/MemoryStream.hpp>
#include <algorithm>
#include <cstring>
#include <Nazara/Core/Debug.hpp>

NzMemoryStream::NzMemoryStream(const void* ptr, nzUInt64 size) :
m_ptr(reinterpret_cast<const nzUInt8*>(ptr)),
m_pos(0),
m_size(size)
{
}

NzMemoryStream::~NzMemoryStream()
{
}

bool NzMemoryStream::EndOfStream() const
{
	return m_pos == m_size;
}

nzUInt64 NzMemoryStream::GetCursorPos() const
{
	return m_pos;
}

nzUInt64 NzMemoryStream::GetSize() const
{
	return m_size;
}

std::size_t NzMemoryStream::Read(void* buffer, std::size_t size)
{
	unsigned int readSize = std::min(static_cast<unsigned int>(size), static_cast<unsigned int>(m_size-m_pos));

	if (buffer)
		std::memcpy(buffer, &m_ptr[m_pos], readSize);

	m_pos += readSize;

	return readSize;
}

bool NzMemoryStream::SetCursorPos(nzUInt64 offset)
{
	m_pos = std::min(offset, m_size);

	return true;
}
<|endoftext|>


<commit_before>
#include <sstream>

#include "scsi/base.h"
#include "pyscsi.h"

#define NO_IMPORT_ARRAY
#define PY_ARRAY_UNIQUE_SYMBOL USCSI_PyArray_API
#include <numpy/ndarrayobject.h>

#define TRY PyMachine *machine = (PyMachine*)raw; try

namespace {

struct PyMachine {
    PyObject_HEAD

    PyObject *weak;
    Machine *machine;
};

static
int PyMachine_init(PyObject *raw, PyObject *args, PyObject *kws)
{
    TRY {
        PyObject *conf;
        const char *pnames[] = {"config", NULL};
        if(!PyArg_ParseTupleAndKeywords(args, kws, "|O!", (char**)pnames, &PyDict_Type, &conf))
            return -1;

        assert(!machine->weak);

        std::auto_ptr<Config> C(dict2conf(conf));
        machine->machine = new Machine(*C);

        return 0;
    } CATCH3(key_error, KeyError, -1)
      CATCH3(std::invalid_argument, ValueError, -1)
      CATCH3(std::exception, RuntimeError, -1)
}

static
void PyMachine_free(PyObject *raw)
{
    TRY {
        std::auto_ptr<Machine> S(machine->machine);
        machine->machine = NULL;

        if(machine->weak)
            PyObject_ClearWeakRefs(raw);

        Py_TYPE(raw)->tp_free(raw);
    } CATCH2V(std::exception, RuntimeError)
}

static
PyObject *PyMachine_str(PyObject *raw)
{
    TRY {
        std::ostringstream strm;
        strm << *(machine->machine);
        return PyString_FromString(strm.str().c_str());
    } CATCH()
}

static
PyObject *PyMachine_allocState(PyObject *raw, PyObject *args, PyObject *kws)
{
    TRY {
        PyObject *d;
        const char *pnames[] = {"config", NULL};
        if(!PyArg_ParseTupleAndKeywords(args, kws, "O|", (char**)pnames, &d))
            return NULL;

        std::auto_ptr<Config> C(dict2conf(d));
        std::auto_ptr<StateBase> state(machine->machine->allocState(*C));
        PyObject *ret = wrapstate(state.get());
        state.release();
        return ret;
    } CATCH()
}

static
PyObject *PyMachine_propagate(PyObject *raw, PyObject *args, PyObject *kws)
{

    TRY {
        PyObject *state;
        unsigned long start = 0, max = (unsigned long)-1;
        const char *pnames[] = {"state", "start", "max", NULL};
        if(!PyArg_ParseTupleAndKeywords(args, kws, "O|kk", (char**)pnames, &state, &start, &max))
            return NULL;

        machine->machine->propagate(unwrapstate(state), start, max);
        Py_RETURN_NONE;
    } CATCH2(std::invalid_argument, ValueError)
    CATCH()
}

static PyMethodDef PyMachine_methods[] = {
    {"allocState", (PyCFunction)&PyMachine_allocState, METH_VARARGS|METH_KEYWORDS,
     "Allocate a new State based on this Machine's configuration"},
    {"propagate", (PyCFunction)&PyMachine_propagate, METH_VARARGS|METH_KEYWORDS,
     "Propagate the provided State through the simulation"},
    {NULL, NULL, 0, NULL}
};

static PyTypeObject PyMachineType = {
#if PY_MAJOR_VERSION >= 3
    PyVarObject_HEAD_INIT(NULL, 0)
#else
    PyObject_HEAD_INIT(NULL)
    0,
#endif
    "uscsi._internal.Machine",
    sizeof(PyMachine),
};

} // namespace

static const char pymdoc[] =
        "Simulation execution engine.\n"
        "\n"
        "A Machine object is responsible for carrying out calculations\n"
        "based on a Config provided when it was constructed.\n"
        "\n"
        "See the allocState and propagate methods.\n"
        ;

int registerModMachine(PyObject *mod)
{
    PyMachineType.tp_doc = pymdoc;
    PyMachineType.tp_str = &PyMachine_str;

    PyMachineType.tp_new = &PyType_GenericNew;
    PyMachineType.tp_init = &PyMachine_init;
    PyMachineType.tp_dealloc = &PyMachine_free;

    PyMachineType.tp_weaklistoffset = offsetof(PyMachine, weak);

    PyMachineType.tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE;
    PyMachineType.tp_methods = PyMachine_methods;

    if(PyType_Ready(&PyMachineType))
        return -1;

    Py_INCREF(&PyMachineType);
    if(PyModule_AddObject(mod, "Machine", (PyObject*)&PyMachineType)) {
        Py_DECREF(&PyMachineType);
        return -1;
    }

    return 0;
}
<commit_msg>python: build Machine with string input<commit_after>
#include <sstream>

#include "scsi/base.h"
#include "pyscsi.h"

#define NO_IMPORT_ARRAY
#define PY_ARRAY_UNIQUE_SYMBOL USCSI_PyArray_API
#include <numpy/ndarrayobject.h>

#define TRY PyMachine *machine = (PyMachine*)raw; try

namespace {

struct PyMachine {
    PyObject_HEAD

    PyObject *weak;
    Machine *machine;
};

static
int PyMachine_init(PyObject *raw, PyObject *args, PyObject *kws)
{
    TRY {
        PyObject *conf = NULL;
        const char *pnames[] = {"config", NULL};
        if(!PyArg_ParseTupleAndKeywords(args, kws, "O|", (char**)pnames, &conf))
            return -1;

        assert(!machine->weak);

        Py_buffer buf;
        std::auto_ptr<Config> C;

        if(PyDict_Check(conf)) {
            C.reset(dict2conf(conf));

        } else if(!PyObject_GetBuffer(conf, &buf, PyBUF_SIMPLE)) {
            GLPSParser parser;
            C.reset(parser.parse((const char*)buf.buf, buf.len));

            PyBuffer_Release(&buf);
        } else {
            throw std::invalid_argument("'config' must be dict or byte buffer");
        }

        machine->machine = new Machine(*C);

        return 0;
    } CATCH3(key_error, KeyError, -1)
      CATCH3(std::invalid_argument, ValueError, -1)
      CATCH3(std::exception, RuntimeError, -1)
}

static
void PyMachine_free(PyObject *raw)
{
    TRY {
        std::auto_ptr<Machine> S(machine->machine);
        machine->machine = NULL;

        if(machine->weak)
            PyObject_ClearWeakRefs(raw);

        Py_TYPE(raw)->tp_free(raw);
    } CATCH2V(std::exception, RuntimeError)
}

static
PyObject *PyMachine_str(PyObject *raw)
{
    TRY {
        std::ostringstream strm;
        strm << *(machine->machine);
        return PyString_FromString(strm.str().c_str());
    } CATCH()
}

static
PyObject *PyMachine_allocState(PyObject *raw, PyObject *args, PyObject *kws)
{
    TRY {
        PyObject *d;
        const char *pnames[] = {"config", NULL};
        if(!PyArg_ParseTupleAndKeywords(args, kws, "O|", (char**)pnames, &d))
            return NULL;

        std::auto_ptr<Config> C(dict2conf(d));
        std::auto_ptr<StateBase> state(machine->machine->allocState(*C));
        PyObject *ret = wrapstate(state.get());
        state.release();
        return ret;
    } CATCH()
}

static
PyObject *PyMachine_propagate(PyObject *raw, PyObject *args, PyObject *kws)
{

    TRY {
        PyObject *state;
        unsigned long start = 0, max = (unsigned long)-1;
        const char *pnames[] = {"state", "start", "max", NULL};
        if(!PyArg_ParseTupleAndKeywords(args, kws, "O|kk", (char**)pnames, &state, &start, &max))
            return NULL;

        machine->machine->propagate(unwrapstate(state), start, max);
        Py_RETURN_NONE;
    } CATCH2(std::invalid_argument, ValueError)
    CATCH()
}

static PyMethodDef PyMachine_methods[] = {
    {"allocState", (PyCFunction)&PyMachine_allocState, METH_VARARGS|METH_KEYWORDS,
     "Allocate a new State based on this Machine's configuration"},
    {"propagate", (PyCFunction)&PyMachine_propagate, METH_VARARGS|METH_KEYWORDS,
     "Propagate the provided State through the simulation"},
    {NULL, NULL, 0, NULL}
};

static PyTypeObject PyMachineType = {
#if PY_MAJOR_VERSION >= 3
    PyVarObject_HEAD_INIT(NULL, 0)
#else
    PyObject_HEAD_INIT(NULL)
    0,
#endif
    "uscsi._internal.Machine",
    sizeof(PyMachine),
};

} // namespace

static const char pymdoc[] =
        "Simulation execution engine.\n"
        "\n"
        "A Machine object is responsible for carrying out calculations\n"
        "based on a Config provided when it was constructed.\n"
        "\n"
        "See the allocState and propagate methods.\n"
        ;

int registerModMachine(PyObject *mod)
{
    PyMachineType.tp_doc = pymdoc;
    PyMachineType.tp_str = &PyMachine_str;

    PyMachineType.tp_new = &PyType_GenericNew;
    PyMachineType.tp_init = &PyMachine_init;
    PyMachineType.tp_dealloc = &PyMachine_free;

    PyMachineType.tp_weaklistoffset = offsetof(PyMachine, weak);

    PyMachineType.tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE;
    PyMachineType.tp_methods = PyMachine_methods;

    if(PyType_Ready(&PyMachineType))
        return -1;

    Py_INCREF(&PyMachineType);
    if(PyModule_AddObject(mod, "Machine", (PyObject*)&PyMachineType)) {
        Py_DECREF(&PyMachineType);
        return -1;
    }

    return 0;
}
<|endoftext|>


<commit_before>#include "ObstaclePlatformAnimator.hpp"

#include "commons.hpp"
#include "AnimatorHolder.hpp"

void ObstaclePlatformAnimator::Start(
 ObstaclePlatform *_platform,
 MovingAnimation *_animation,
 timestamp_t startingTime)
{
	platform = _platform;
	animation = _animation;
	lastTime = startingTime;
	state = ANIMATOR_RUNNING;
	AnimatorHolder::MarkAsRunning(this);
} // Start

void ObstaclePlatformAnimator::Progress(timestamp_t currTime) {
	std::cerr<<"Progress "<<currTime<<" "<<lastTime<<" ";
	delay_t delay = animation->GetDelay();
	timestamp_t diff = timestamp_diff(currTime, lastTime);
	std::cerr<<diff<<" diff>=delau"<<(diff>=delay)<<std::endl;
	if (diff >= delay) { // should progress
		// Move the thing
		platform->Move(animation->GetDx(), animation->GetDy());
		// Ignore continuity and stuff
		if (!animation->GetContinuous()) {
			state = ANIMATOR_FINISHED;
			NotifyStopped();
		}
		// Update last time
		lastTime += delay;
	}
} // Progress

bool ObstaclePlatformAnimator::ShouldProgress(timestamp_t currTime) {
	return timestamp_diff(currTime, lastTime) >= animation->GetDelay();
} // ShouldProgress

ObstaclePlatform *ObstaclePlatformAnimator::getPlatform(void) const {
	return platform;
} // getPlatform

MovingAnimation *ObstaclePlatformAnimator::getAnimation(void) const {
	return animation;
} // getAnimation

ObstaclePlatformAnimator::ObstaclePlatformAnimator(bool _register) :
	Animator(_register),
	platform(CAST(ObstaclePlatform*, 0)),
	animation(CAST(MovingAnimation*, 0)),
	lastTime(CAST(timestamp_t, 0)) { }
ObstaclePlatformAnimator::~ObstaclePlatformAnimator(void) { }
<commit_msg>Removed blabing messaged from ObstaclePlatformAnimator<commit_after>#include "ObstaclePlatformAnimator.hpp"

#include "commons.hpp"
#include "AnimatorHolder.hpp"

void ObstaclePlatformAnimator::Start(
 ObstaclePlatform *_platform,
 MovingAnimation *_animation,
 timestamp_t startingTime)
{
	platform = _platform;
	animation = _animation;
	lastTime = startingTime;
	state = ANIMATOR_RUNNING;
	AnimatorHolder::MarkAsRunning(this);
} // Start

void ObstaclePlatformAnimator::Progress(timestamp_t currTime) {
	delay_t delay = animation->GetDelay();
	timestamp_t diff = timestamp_diff(currTime, lastTime);
	if (diff >= delay) { // should progress
		// Move the thing
		platform->Move(animation->GetDx(), animation->GetDy());
		// Ignore continuity and stuff
		if (!animation->GetContinuous()) {
			state = ANIMATOR_FINISHED;
			NotifyStopped();
		}
		// Update last time
		lastTime += delay;
	}
} // Progress

bool ObstaclePlatformAnimator::ShouldProgress(timestamp_t currTime) {
	return timestamp_diff(currTime, lastTime) >= animation->GetDelay();
} // ShouldProgress

ObstaclePlatform *ObstaclePlatformAnimator::getPlatform(void) const {
	return platform;
} // getPlatform

MovingAnimation *ObstaclePlatformAnimator::getAnimation(void) const {
	return animation;
} // getAnimation

ObstaclePlatformAnimator::ObstaclePlatformAnimator(bool _register) :
	Animator(_register),
	platform(CAST(ObstaclePlatform*, 0)),
	animation(CAST(MovingAnimation*, 0)),
	lastTime(CAST(timestamp_t, 0)) { }
ObstaclePlatformAnimator::~ObstaclePlatformAnimator(void) { }
<|endoftext|>


<commit_before>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkTextActor.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) 1993-2002 Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/
#include "vtkTextActor.h"
#include "vtkObjectFactory.h"

vtkCxxRevisionMacro(vtkTextActor, "1.4");
vtkStandardNewMacro(vtkTextActor);
// ----------------------------------------------------------------------------
vtkTextActor::vtkTextActor()
{
  // to remain compatible with code using vtkActor2D, we must set
  // position coord to Viewport, not Normalized Viewport
  // so...compute equivalent coords for initial position
  this->PositionCoordinate->SetCoordinateSystemToViewport();
  //
  this->AdjustedPositionCoordinate = vtkCoordinate::New();
  this->AdjustedPositionCoordinate->SetCoordinateSystemToNormalizedViewport();
  // create default text mapper
  vtkTextMapper *mapper = vtkTextMapper::New();
  this->SetMapper(mapper);
  mapper->Delete();
  //
  this->LastOrigin[0]     = 0;
  this->LastOrigin[1]     = 0;
  this->LastSize[0]       = 0;
  this->LastSize[1]       = 0;
  this->MinimumSize[0]    = 10;
  this->MinimumSize[1]    = 10;
  this->MaximumLineHeight = 1.0;
  this->ScaledText        = 0;
  this->AlignmentPoint    = 0;
}
// ----------------------------------------------------------------------------
vtkTextActor::~vtkTextActor()
{
  this->AdjustedPositionCoordinate->Delete();
}
// ----------------------------------------------------------------------------
void vtkTextActor::SetMapper(vtkTextMapper *mapper)
{ // this is the public method
    this->vtkActor2D::SetMapper( mapper );
}
// ----------------------------------------------------------------------------
void vtkTextActor::SetMapper(vtkMapper2D *mapper)
{
  if (mapper->IsA("vtkTextMapper"))
    {
    this->SetMapper( (vtkTextMapper *)mapper );
    }
  else
    {
    vtkErrorMacro("Must use vtkTextMapper for this class");
    }
  }
// ----------------------------------------------------------------------------
void vtkTextActor::ShallowCopy(vtkProp *prop)
{
  vtkTextActor *a = vtkTextActor::SafeDownCast(prop);
  if ( a != NULL )
    {
    this->SetPosition2(a->GetPosition2());
    this->SetMinimumSize(a->GetMinimumSize());
    this->SetMaximumLineHeight(a->GetMaximumLineHeight());
    this->SetScaledText(a->GetScaledText());
    this->SetAlignmentPoint(a->GetAlignmentPoint());
    }
  // Now do superclass (mapper is handled by it as well).
  this->vtkActor2D::ShallowCopy(prop);
}
// ----------------------------------------------------------------------------
// Release any graphics resources that are being consumed by this actor.
// The parameter window could be used to determine which graphic
// resources to release.
void vtkTextActor::ReleaseGraphicsResources(vtkWindow *win)
{
  this->vtkActor2D::ReleaseGraphicsResources(win);
}
// ----------------------------------------------------------------------------
int vtkTextActor::RenderOverlay(vtkViewport *viewport)
{
  // Everything is built in RenderOpaqueGeometry, just have to render
  this->vtkActor2D::RenderOverlay(viewport);
  return 1;
}
// ----------------------------------------------------------------------------
int vtkTextActor::RenderOpaqueGeometry(vtkViewport *viewport)
{
  int size[2];
  int fontSize=0, oldfontsize=0;

  vtkTextMapper *mapper = (vtkTextMapper *)this->GetMapper();
  if (!mapper)
    {
    return 0;
    }

  // we don't need to do anything additional, just pass the call
  // right through to the actor
  if (!this->ScaledText)
    {
    int *point1, *point2;
    float u, v;
    point1 = this->PositionCoordinate->GetComputedViewportValue(viewport);
    point2 = this->Position2Coordinate->GetComputedViewportValue(viewport);
    size[0] = point2[0] - point1[0];
    size[1] = point2[1] - point1[1];
    switch (this->AlignmentPoint)
      {
      case 0:
        u = point1[0];
        v = point1[1];
        break;
      case 1:
        u = point1[0] + size[0]/2;
        v = point1[1];
        break;
      case 2:
        u = point2[0];
        v = point1[1];
        break;
      case 3:
        u = point1[0];
        v = point1[1] + size[1]/2;
        break;
      case 4:
        u = point1[0] + size[0]/2;
        v = point1[1] + size[1]/2;
        break;
      case 5:
        u = point2[0];
        v = point1[1] + size[1]/2;
        break;
      case 6:
        u = point1[0];
        v = point2[1];
        break;
      case 7:
        u = point1[0] + size[0]/2;
        v = point2[1];
        break;
      case 8:
        u = point2[0];
        v = point2[1];
        break;
      }

    viewport->ViewportToNormalizedViewport(u, v);
    this->AdjustedPositionCoordinate->SetValue(u,v);
    this->vtkActor2D::RenderOpaqueGeometry(viewport);
    return 1;
    }

  // Check to see whether we have to rebuild everything
  if (viewport->GetMTime() > this->BuildTime ||
      ( viewport->GetVTKWindow() &&
        viewport->GetVTKWindow()->GetMTime() > this->BuildTime ) )
    {
    // if the viewport has changed we may - or may not need
    // to rebuild, it depends on if the projected coords change
    int *point1, *point2;
    point1 = this->PositionCoordinate->GetComputedViewportValue(viewport);
    point2 = this->Position2Coordinate->GetComputedViewportValue(viewport);
    size[0] = point2[0] - point1[0];
    size[1] = point2[1] - point1[1];
    if (this->LastSize[0] != size[0]     || this->LastSize[1] != size[1] ||
        this->LastOrigin[0] != point1[0] || this->LastOrigin[1] != point1[1])
      {
      this->Modified();
      }
    }

  // Check to see whether we have to rebuild everything
  if ( this->GetMTime() > this->BuildTime)
    {
    vtkDebugMacro(<<"Rebuilding text");

    // get the viewport size in display coordinates
    int *point1, *point2;
    point1 = this->PositionCoordinate->GetComputedViewportValue(viewport);
    point2 = this->Position2Coordinate->GetComputedViewportValue(viewport);
    size[0] = point2[0] - point1[0];
    size[1] = point2[1] - point1[1];
    this->LastOrigin[0] = point1[0];
    this->LastOrigin[1] = point1[1];

    //  Lets try to minimize the number of times we change the font size.
    //  If the width of the font box has not changed by more than a pixel
    // (numerical issues)  do not recompute font size.
    if (this->LastSize[0] < size[0]-1 || this->LastSize[1] < size[1]-1 ||
        this->LastSize[0] > size[0]+1 || this->LastSize[1] > size[1]+1)
      {
      this->LastSize[0] = size[0];
      this->LastSize[1] = size[1];

      // limit by minimum size
      if (this->MinimumSize[0] > size[0])
        {
        size[0] = this->MinimumSize[0];
        }
      if (this->MinimumSize[1] > size[1])
        {
        size[1] = this->MinimumSize[1];
        }
      // Update all the composing objects
      // find the best size for the font
      int tempi[2];
      // use the last size as a first guess
      fontSize = mapper->GetFontSize();
      oldfontsize = fontSize;
      mapper->GetSize(viewport,tempi);
      int lineMax = (int)(size[1]*this->MaximumLineHeight
                          * mapper->GetNumberOfLines());

      // while the size is too small increase it
      while (tempi[1] < size[1] &&
             tempi[0] < size[0] &&
             tempi[1] < lineMax &&
             fontSize < 100)
        {
        fontSize++;
        mapper->SetFontSize(fontSize);
        mapper->GetSize(viewport,tempi);
        }
      // while the size is too large decrease it
      while ((tempi[1] > size[1] || tempi[0] > size[0] || tempi[1] > lineMax)
             && fontSize > 0)
        {
        fontSize--;
        mapper->SetFontSize(fontSize);
        mapper->GetSize(viewport,tempi);
        }

      }

      if (oldfontsize!=fontSize)
        { // don't do this after this->BuildTime.Modified(); !!!!
        this->Modified();
        }

    // now set the position of the Text
    int fpos[2];
    switch (mapper->GetJustification())
      {
      case VTK_TEXT_LEFT:
        fpos[0] = point1[0];
        break;
      case VTK_TEXT_CENTERED:
        fpos[0] = point1[0] + size[0]/2;
        break;
      case VTK_TEXT_RIGHT:
        fpos[0] = point1[0]+size[0];
        break;
      }
    switch (mapper->GetVerticalJustification())
      {
      case VTK_TEXT_TOP:
        fpos[1] = point1[1] + size[1];
        break;
      case VTK_TEXT_CENTERED:
        fpos[1] = point1[1] + size[1]/2;
        break;
      case VTK_TEXT_BOTTOM:
        fpos[1] = point1[1];
        break;
      }

    float u = fpos[0], v = fpos[1];
    viewport->ViewportToNormalizedViewport(u, v);
    this->AdjustedPositionCoordinate->SetValue(u,v);
    this->BuildTime.Modified();
    }

  // Everything is built, just have to render
  this->vtkActor2D::RenderOpaqueGeometry(viewport);
  return 1;
}
// ----------------------------------------------------------------------------
void vtkTextActor::PrintSelf(ostream& os, vtkIndent indent)
{
  this->Superclass::PrintSelf(os,indent);

  os << indent << "MaximumLineHeight: " << this->MaximumLineHeight << endl;
  os << indent << "MinimumSize: " << this->MinimumSize[0] << " " << this->MinimumSize[1] << endl;
  os << indent << "ScaledText: " << this->ScaledText << endl;
  os << indent << "AlignmentPoint: " << this->AlignmentPoint << endl;
}
// ----------------------------------------------------------------------------
#define SetStuffMacro(function,param)          \
    vtkTextMapper *mapper = (vtkTextMapper *)this->GetMapper(); \
    if (!mapper) { return; }                   \
    unsigned long mtime1 = mapper->GetMTime(); \
    mapper->Set##function(param);              \
    unsigned long mtime2 = mapper->GetMTime(); \
    if (mtime1 != mtime2)                      \
      {                                        \
      this->Modified();                        \
      }

#define GetStuffMacro(function,default)        \
    vtkTextMapper *mapper = (vtkTextMapper *)this->GetMapper(); \
    if (!mapper) { return default; }           \
    return mapper->Get##function();            \

void vtkTextActor::SetInput(const char *inputString)
{
    SetStuffMacro(Input,inputString);
}
// ----------------------------------------------------------------------------
char *vtkTextActor::GetInput(void)
{
    GetStuffMacro(Input,NULL);
}
// ----------------------------------------------------------------------------
void vtkTextActor::SetFontSize(int size)
{
    SetStuffMacro(FontSize,size);
}
// ----------------------------------------------------------------------------
int vtkTextActor::GetFontSize(void)
{
    GetStuffMacro(FontSize,0);
}
// ----------------------------------------------------------------------------
void vtkTextActor::SetBold(int val)
{
    SetStuffMacro(Bold,val);
}
// ----------------------------------------------------------------------------
int vtkTextActor::GetBold(void)
{
    GetStuffMacro(Bold,0);
}
// ----------------------------------------------------------------------------
void vtkTextActor::SetItalic(int val)
{
    SetStuffMacro(Italic,val);
}
// ----------------------------------------------------------------------------
int vtkTextActor::GetItalic(void)
{
    GetStuffMacro(Italic,0);
}
// ----------------------------------------------------------------------------
void vtkTextActor::SetShadow(int val)
{
    SetStuffMacro(Shadow,val);
}
// ----------------------------------------------------------------------------
int vtkTextActor::GetShadow(void)
{
    GetStuffMacro(Shadow,0);
}
// ----------------------------------------------------------------------------
void vtkTextActor::SetFontFamily(int val)
{
    SetStuffMacro(FontFamily,val);
}
// ----------------------------------------------------------------------------
int vtkTextActor::GetFontFamily(void)
{
    GetStuffMacro(FontFamily,0);
}
// ----------------------------------------------------------------------------
void vtkTextActor::SetJustification(int val)
{
    SetStuffMacro(Justification,val);
}
// ----------------------------------------------------------------------------
int vtkTextActor::GetJustification(void)
{
    GetStuffMacro(Justification,0);
}
// ----------------------------------------------------------------------------
void vtkTextActor::SetVerticalJustification(int val)
{
    SetStuffMacro(VerticalJustification,val);
}
// ----------------------------------------------------------------------------
int vtkTextActor::GetVerticalJustification(void)
{
    GetStuffMacro(VerticalJustification,0);
}
// ----------------------------------------------------------------------------
void vtkTextActor::SetLineOffset(float val)
{
    SetStuffMacro(LineOffset,val);
}
// ----------------------------------------------------------------------------
float vtkTextActor::GetLineOffset(void)
{
    GetStuffMacro(LineOffset,0);
}
// ----------------------------------------------------------------------------
void vtkTextActor::SetLineSpacing(float val)
{
    SetStuffMacro(LineSpacing,val);
}
// ----------------------------------------------------------------------------
float vtkTextActor::GetLineSpacing(void)
{
    GetStuffMacro(LineSpacing,0);
}
// ----------------------------------------------------------------------------
int vtkTextActor::GetNumberOfLines(const char *input)
{
    vtkTextMapper *mapper = (vtkTextMapper *)this->GetMapper();
    if (mapper)
      {
      return mapper->GetNumberOfLines(input);
      }
    else
      {
      return 0;
      }
}
// ----------------------------------------------------------------------------
int vtkTextActor::GetNumberOfLines(void)
{
    GetStuffMacro(NumberOfLines,0);
}
// ----------------------------------------------------------------------------
void vtkTextActor::GetSize(vtkViewport *v, int size[2])
{
    vtkTextMapper *mapper = (vtkTextMapper *)this->GetMapper();
    if (mapper)
      {
      mapper->GetSize(v, size);
      }
}
// ----------------------------------------------------------------------------
int vtkTextActor::GetWidth(vtkViewport*v)
{
    vtkTextMapper *mapper = (vtkTextMapper *)this->GetMapper();
    if (mapper)
      {
      return mapper->GetWidth(v);
      }
    else
      {
      return 0;
      }
}
// ----------------------------------------------------------------------------
int vtkTextActor::GetHeight(vtkViewport*v)
{
    vtkTextMapper *mapper = (vtkTextMapper *)this->GetMapper();
    if (mapper)
      {
      return mapper->GetHeight(v);
      }
    else
      {
      return 0;
      }
}

<commit_msg>FIX: returns status of call to parent's method, instead of just 1<commit_after>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkTextActor.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) 1993-2002 Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/
#include "vtkTextActor.h"
#include "vtkObjectFactory.h"

vtkCxxRevisionMacro(vtkTextActor, "1.5");
vtkStandardNewMacro(vtkTextActor);
// ----------------------------------------------------------------------------
vtkTextActor::vtkTextActor()
{
  // to remain compatible with code using vtkActor2D, we must set
  // position coord to Viewport, not Normalized Viewport
  // so...compute equivalent coords for initial position
  this->PositionCoordinate->SetCoordinateSystemToViewport();
  //
  this->AdjustedPositionCoordinate = vtkCoordinate::New();
  this->AdjustedPositionCoordinate->SetCoordinateSystemToNormalizedViewport();
  // create default text mapper
  vtkTextMapper *mapper = vtkTextMapper::New();
  this->SetMapper(mapper);
  mapper->Delete();
  //
  this->LastOrigin[0]     = 0;
  this->LastOrigin[1]     = 0;
  this->LastSize[0]       = 0;
  this->LastSize[1]       = 0;
  this->MinimumSize[0]    = 10;
  this->MinimumSize[1]    = 10;
  this->MaximumLineHeight = 1.0;
  this->ScaledText        = 0;
  this->AlignmentPoint    = 0;
}
// ----------------------------------------------------------------------------
vtkTextActor::~vtkTextActor()
{
  this->AdjustedPositionCoordinate->Delete();
}
// ----------------------------------------------------------------------------
void vtkTextActor::SetMapper(vtkTextMapper *mapper)
{ // this is the public method
    this->vtkActor2D::SetMapper( mapper );
}
// ----------------------------------------------------------------------------
void vtkTextActor::SetMapper(vtkMapper2D *mapper)
{
  if (mapper->IsA("vtkTextMapper"))
    {
    this->SetMapper( (vtkTextMapper *)mapper );
    }
  else
    {
    vtkErrorMacro("Must use vtkTextMapper for this class");
    }
  }
// ----------------------------------------------------------------------------
void vtkTextActor::ShallowCopy(vtkProp *prop)
{
  vtkTextActor *a = vtkTextActor::SafeDownCast(prop);
  if ( a != NULL )
    {
    this->SetPosition2(a->GetPosition2());
    this->SetMinimumSize(a->GetMinimumSize());
    this->SetMaximumLineHeight(a->GetMaximumLineHeight());
    this->SetScaledText(a->GetScaledText());
    this->SetAlignmentPoint(a->GetAlignmentPoint());
    }
  // Now do superclass (mapper is handled by it as well).
  this->vtkActor2D::ShallowCopy(prop);
}
// ----------------------------------------------------------------------------
// Release any graphics resources that are being consumed by this actor.
// The parameter window could be used to determine which graphic
// resources to release.
void vtkTextActor::ReleaseGraphicsResources(vtkWindow *win)
{
  this->vtkActor2D::ReleaseGraphicsResources(win);
}
// ----------------------------------------------------------------------------
int vtkTextActor::RenderOverlay(vtkViewport *viewport)
{
  // Everything is built in RenderOpaqueGeometry, just have to render
  return this->vtkActor2D::RenderOverlay(viewport);
}
// ----------------------------------------------------------------------------
int vtkTextActor::RenderOpaqueGeometry(vtkViewport *viewport)
{
  int size[2];
  int fontSize=0, oldfontsize=0;

  vtkTextMapper *mapper = (vtkTextMapper *)this->GetMapper();
  if (!mapper)
    {
    return 0;
    }

  // we don't need to do anything additional, just pass the call
  // right through to the actor
  if (!this->ScaledText)
    {
    int *point1, *point2;
    float u, v;
    point1 = this->PositionCoordinate->GetComputedViewportValue(viewport);
    point2 = this->Position2Coordinate->GetComputedViewportValue(viewport);
    size[0] = point2[0] - point1[0];
    size[1] = point2[1] - point1[1];
    switch (this->AlignmentPoint)
      {
      case 0:
        u = point1[0];
        v = point1[1];
        break;
      case 1:
        u = point1[0] + size[0]/2;
        v = point1[1];
        break;
      case 2:
        u = point2[0];
        v = point1[1];
        break;
      case 3:
        u = point1[0];
        v = point1[1] + size[1]/2;
        break;
      case 4:
        u = point1[0] + size[0]/2;
        v = point1[1] + size[1]/2;
        break;
      case 5:
        u = point2[0];
        v = point1[1] + size[1]/2;
        break;
      case 6:
        u = point1[0];
        v = point2[1];
        break;
      case 7:
        u = point1[0] + size[0]/2;
        v = point2[1];
        break;
      case 8:
        u = point2[0];
        v = point2[1];
        break;
      }

    viewport->ViewportToNormalizedViewport(u, v);
    this->AdjustedPositionCoordinate->SetValue(u,v);
    this->vtkActor2D::RenderOpaqueGeometry(viewport);
    return 1;
    }

  // Check to see whether we have to rebuild everything
  if (viewport->GetMTime() > this->BuildTime ||
      ( viewport->GetVTKWindow() &&
        viewport->GetVTKWindow()->GetMTime() > this->BuildTime ) )
    {
    // if the viewport has changed we may - or may not need
    // to rebuild, it depends on if the projected coords change
    int *point1, *point2;
    point1 = this->PositionCoordinate->GetComputedViewportValue(viewport);
    point2 = this->Position2Coordinate->GetComputedViewportValue(viewport);
    size[0] = point2[0] - point1[0];
    size[1] = point2[1] - point1[1];
    if (this->LastSize[0] != size[0]     || this->LastSize[1] != size[1] ||
        this->LastOrigin[0] != point1[0] || this->LastOrigin[1] != point1[1])
      {
      this->Modified();
      }
    }

  // Check to see whether we have to rebuild everything
  if ( this->GetMTime() > this->BuildTime)
    {
    vtkDebugMacro(<<"Rebuilding text");

    // get the viewport size in display coordinates
    int *point1, *point2;
    point1 = this->PositionCoordinate->GetComputedViewportValue(viewport);
    point2 = this->Position2Coordinate->GetComputedViewportValue(viewport);
    size[0] = point2[0] - point1[0];
    size[1] = point2[1] - point1[1];
    this->LastOrigin[0] = point1[0];
    this->LastOrigin[1] = point1[1];

    //  Lets try to minimize the number of times we change the font size.
    //  If the width of the font box has not changed by more than a pixel
    // (numerical issues)  do not recompute font size.
    if (this->LastSize[0] < size[0]-1 || this->LastSize[1] < size[1]-1 ||
        this->LastSize[0] > size[0]+1 || this->LastSize[1] > size[1]+1)
      {
      this->LastSize[0] = size[0];
      this->LastSize[1] = size[1];

      // limit by minimum size
      if (this->MinimumSize[0] > size[0])
        {
        size[0] = this->MinimumSize[0];
        }
      if (this->MinimumSize[1] > size[1])
        {
        size[1] = this->MinimumSize[1];
        }
      // Update all the composing objects
      // find the best size for the font
      int tempi[2];
      // use the last size as a first guess
      fontSize = mapper->GetFontSize();
      oldfontsize = fontSize;
      mapper->GetSize(viewport,tempi);
      int lineMax = (int)(size[1]*this->MaximumLineHeight
                          * mapper->GetNumberOfLines());

      // while the size is too small increase it
      while (tempi[1] < size[1] &&
             tempi[0] < size[0] &&
             tempi[1] < lineMax &&
             fontSize < 100)
        {
        fontSize++;
        mapper->SetFontSize(fontSize);
        mapper->GetSize(viewport,tempi);
        }
      // while the size is too large decrease it
      while ((tempi[1] > size[1] || tempi[0] > size[0] || tempi[1] > lineMax)
             && fontSize > 0)
        {
        fontSize--;
        mapper->SetFontSize(fontSize);
        mapper->GetSize(viewport,tempi);
        }

      }

      if (oldfontsize!=fontSize)
        { // don't do this after this->BuildTime.Modified(); !!!!
        this->Modified();
        }

    // now set the position of the Text
    int fpos[2];
    switch (mapper->GetJustification())
      {
      case VTK_TEXT_LEFT:
        fpos[0] = point1[0];
        break;
      case VTK_TEXT_CENTERED:
        fpos[0] = point1[0] + size[0]/2;
        break;
      case VTK_TEXT_RIGHT:
        fpos[0] = point1[0]+size[0];
        break;
      }
    switch (mapper->GetVerticalJustification())
      {
      case VTK_TEXT_TOP:
        fpos[1] = point1[1] + size[1];
        break;
      case VTK_TEXT_CENTERED:
        fpos[1] = point1[1] + size[1]/2;
        break;
      case VTK_TEXT_BOTTOM:
        fpos[1] = point1[1];
        break;
      }

    float u = fpos[0], v = fpos[1];
    viewport->ViewportToNormalizedViewport(u, v);
    this->AdjustedPositionCoordinate->SetValue(u,v);
    this->BuildTime.Modified();
    }

  // Everything is built, just have to render
  this->vtkActor2D::RenderOpaqueGeometry(viewport);
  return 1;
}
// ----------------------------------------------------------------------------
void vtkTextActor::PrintSelf(ostream& os, vtkIndent indent)
{
  this->Superclass::PrintSelf(os,indent);

  os << indent << "MaximumLineHeight: " << this->MaximumLineHeight << endl;
  os << indent << "MinimumSize: " << this->MinimumSize[0] << " " << this->MinimumSize[1] << endl;
  os << indent << "ScaledText: " << this->ScaledText << endl;
  os << indent << "AlignmentPoint: " << this->AlignmentPoint << endl;
}
// ----------------------------------------------------------------------------
#define SetStuffMacro(function,param)          \
    vtkTextMapper *mapper = (vtkTextMapper *)this->GetMapper(); \
    if (!mapper) { return; }                   \
    unsigned long mtime1 = mapper->GetMTime(); \
    mapper->Set##function(param);              \
    unsigned long mtime2 = mapper->GetMTime(); \
    if (mtime1 != mtime2)                      \
      {                                        \
      this->Modified();                        \
      }

#define GetStuffMacro(function,default)        \
    vtkTextMapper *mapper = (vtkTextMapper *)this->GetMapper(); \
    if (!mapper) { return default; }           \
    return mapper->Get##function();            \

void vtkTextActor::SetInput(const char *inputString)
{
    SetStuffMacro(Input,inputString);
}
// ----------------------------------------------------------------------------
char *vtkTextActor::GetInput(void)
{
    GetStuffMacro(Input,NULL);
}
// ----------------------------------------------------------------------------
void vtkTextActor::SetFontSize(int size)
{
    SetStuffMacro(FontSize,size);
}
// ----------------------------------------------------------------------------
int vtkTextActor::GetFontSize(void)
{
    GetStuffMacro(FontSize,0);
}
// ----------------------------------------------------------------------------
void vtkTextActor::SetBold(int val)
{
    SetStuffMacro(Bold,val);
}
// ----------------------------------------------------------------------------
int vtkTextActor::GetBold(void)
{
    GetStuffMacro(Bold,0);
}
// ----------------------------------------------------------------------------
void vtkTextActor::SetItalic(int val)
{
    SetStuffMacro(Italic,val);
}
// ----------------------------------------------------------------------------
int vtkTextActor::GetItalic(void)
{
    GetStuffMacro(Italic,0);
}
// ----------------------------------------------------------------------------
void vtkTextActor::SetShadow(int val)
{
    SetStuffMacro(Shadow,val);
}
// ----------------------------------------------------------------------------
int vtkTextActor::GetShadow(void)
{
    GetStuffMacro(Shadow,0);
}
// ----------------------------------------------------------------------------
void vtkTextActor::SetFontFamily(int val)
{
    SetStuffMacro(FontFamily,val);
}
// ----------------------------------------------------------------------------
int vtkTextActor::GetFontFamily(void)
{
    GetStuffMacro(FontFamily,0);
}
// ----------------------------------------------------------------------------
void vtkTextActor::SetJustification(int val)
{
    SetStuffMacro(Justification,val);
}
// ----------------------------------------------------------------------------
int vtkTextActor::GetJustification(void)
{
    GetStuffMacro(Justification,0);
}
// ----------------------------------------------------------------------------
void vtkTextActor::SetVerticalJustification(int val)
{
    SetStuffMacro(VerticalJustification,val);
}
// ----------------------------------------------------------------------------
int vtkTextActor::GetVerticalJustification(void)
{
    GetStuffMacro(VerticalJustification,0);
}
// ----------------------------------------------------------------------------
void vtkTextActor::SetLineOffset(float val)
{
    SetStuffMacro(LineOffset,val);
}
// ----------------------------------------------------------------------------
float vtkTextActor::GetLineOffset(void)
{
    GetStuffMacro(LineOffset,0);
}
// ----------------------------------------------------------------------------
void vtkTextActor::SetLineSpacing(float val)
{
    SetStuffMacro(LineSpacing,val);
}
// ----------------------------------------------------------------------------
float vtkTextActor::GetLineSpacing(void)
{
    GetStuffMacro(LineSpacing,0);
}
// ----------------------------------------------------------------------------
int vtkTextActor::GetNumberOfLines(const char *input)
{
    vtkTextMapper *mapper = (vtkTextMapper *)this->GetMapper();
    if (mapper)
      {
      return mapper->GetNumberOfLines(input);
      }
    else
      {
      return 0;
      }
}
// ----------------------------------------------------------------------------
int vtkTextActor::GetNumberOfLines(void)
{
    GetStuffMacro(NumberOfLines,0);
}
// ----------------------------------------------------------------------------
void vtkTextActor::GetSize(vtkViewport *v, int size[2])
{
    vtkTextMapper *mapper = (vtkTextMapper *)this->GetMapper();
    if (mapper)
      {
      mapper->GetSize(v, size);
      }
}
// ----------------------------------------------------------------------------
int vtkTextActor::GetWidth(vtkViewport*v)
{
    vtkTextMapper *mapper = (vtkTextMapper *)this->GetMapper();
    if (mapper)
      {
      return mapper->GetWidth(v);
      }
    else
      {
      return 0;
      }
}
// ----------------------------------------------------------------------------
int vtkTextActor::GetHeight(vtkViewport*v)
{
    vtkTextMapper *mapper = (vtkTextMapper *)this->GetMapper();
    if (mapper)
      {
      return mapper->GetHeight(v);
      }
    else
      {
      return 0;
      }
}

<|endoftext|>


<commit_before>//
//  DB.cpp
//  Openbiz-RestModel
//
//  Created by Jixian Wang on 14-10-7.
//  Copyright (c) 2014年 openbiz. All rights reserved.
//

#include <iostream>
#include <stdexcept>
#include <vector>
#include <regex>
#include <cstdio>
#include "DB.h"
#include "PlatformMacros.h"
#include "FileUtils.h"
#include "sqlite3_json_extension.h"

#define OPENBIZ_CACHE_CREATE_TABLE_SQL(tableName) \
"CREATE TABLE IF NOT EXISTS `"+tableName+"` (`id` PRIMARY KEY, `timestamp` NUMERIC, `data` TEXT);"

#define OPENBIZ_CACHE_DROP_TABLE_SQL(tableName) \
"DROP TABLE IF EXISTS `"+tableName+"` ;"

#define OPENBIZ_CACHE_CHECK_TABLE_EXISTS_SQL \
"SELECT 1 FROM `sqlite_master` WHERE `type`='table' AND `name`= ? ;"

#define OPENBIZ_CACHE_CHECK_RECORD_EXISTS_SQL(tableName) \
"SELECT `id`,`data`,`timestamp` FROM `"+tableName+"` WHERE `id`= ? ;"

#define OPENBIZ_CACHE_FETCH_RECORD_SQL(tableName) \
"SELECT `id`,`data`,`timestamp` FROM `"+tableName+"` WHERE `id`= ? ;"

#define OPENBIZ_CACHE_FETCH_RECORDS_SQL(tableName) \
"SELECT `id`,`data`,`timestamp` FROM `"+tableName+"` LIMIT ?,?;"

#define OPENBIZ_CACHE_QUERY_RECORDS_SQL(tableName) \
"SELECT `id`,`data`,`timestamp` FROM `"+tableName+"` WHERE JSON_CONTAINS(?,data) LIMIT ?,?;"

#define OPENBIZ_CACHE_COUNT_FETCHED_RECORDS_SQL(tableName) \
"SELECT count(data) AS total FROM `"+tableName+"`;"

#define OPENBIZ_CACHE_COUNT_FOUND_RECORDS_SQL(tableName) \
"SELECT count(data) AS total FROM `"+tableName+"` WHERE JSON_CONTAINS(?,data);"

#define OPENBIZ_CACHE_UPDATE_RECORD_SQL(tableName) \
"UPDATE `"+tableName+"` SET `timestamp`=datetime(),`data`= ? WHERE id= ? ;"

#define OPENBIZ_CACHE_INSERT_RECORD_SQL(tableName) \
"INSERT INTO `"+tableName+"` (`id`,`timestamp`,`data`) VALUES (?, datetime(), ?); "

#define OPENBIZ_CACHE_REMOVE_RECORD_SQL(tableName) \
"DELETE FROM `"+tableName+"` WHERE `id`= ? ; "

#define OPENBIZ_CACHE_REMOVE_ALL_RECORDS_SQL(tableName) \
"DELETE FROM `"+tableName+"` ;"

using namespace std;

namespace openbiz
{
    namespace core
    {
        DB* DB::_instance = nullptr;
        sqlite3* DB::_db = nullptr;
        string DB::_dbName = "";
        std::mutex DB::_mtx;
        DB::~DB(){};
        DB::DB(){};

        DB* DB::getInstance()
        {
            if (_instance == nullptr)
            {
                _instance = new DB();
            }
            return _instance;
        }

        const sqlite3* DB::db(){
            if(_db==nullptr)
            {
                throw std::runtime_error("Please define a db name");
            }
            return _db;
        };

        void DB::initialize(const std::string &dbName)
        {
            if(!dbName.empty()){
                if(!_db){
                    const std::string path = ext::FileUtils::getInstance()->getWritablePath();
                    const std::string dbFullname = path + "/" + dbName;
                    int result = sqlite3_open(dbFullname.c_str(),&_db);
                    DB::_dbName = dbName;
                    if(result == SQLITE_OK){
                        //register sqlite json extension to db connection instance
                        sqlite3_json_extension_init(_db,NULL);
                    }
                    else{
                        throw std::runtime_error("Con't open database file: "+dbFullname);
                    }
                }
            }else{
                throw std::runtime_error("Please define a db name");
            }
        }

        void DB::dropDatabase()
        {
            if(!DB::_dbName.empty()){
                _mtx.lock();
                sqlite3_close(_db);
                _mtx.unlock();
                _db = nullptr;
                const std::string path = ext::FileUtils::getInstance()->getWritablePath();
                const std::string dbFullname = path + "/" + DB::_dbName;
                std::remove(dbFullname.c_str());
            }
            destroyInstance();

        }

        void DB::ensureTableExists(const std::string &tableName) const
        {
            if(!isTableExists(tableName)){
                _mtx.lock();
                sqlite3_stmt *stmt;
                int rc;
                string sqlString(OPENBIZ_CACHE_CREATE_TABLE_SQL(tableName));
                const char* sql = sqlString.c_str();
                rc = sqlite3_prepare_v2(_db, sql, -1, &stmt, NULL);
                rc = sqlite3_bind_text(stmt, 1,
                                       tableName.c_str(),static_cast<int>(tableName.size()), SQLITE_STATIC);
                rc = sqlite3_step(stmt);
                sqlite3_finalize(stmt);
                _mtx.unlock();
            }
            return;
        }

        const bool DB::isTableExists(const std::string &tableName) const
        {
            _mtx.lock();
            sqlite3_stmt *stmt;
            int rc;
            string sqlString(OPENBIZ_CACHE_CHECK_TABLE_EXISTS_SQL);
            const char* sql = sqlString.c_str();
            rc = sqlite3_prepare_v2(_db, sql, -1, &stmt, NULL);
            rc = sqlite3_bind_text(stmt, 1,
                                   tableName.c_str(),static_cast<int>(tableName.size()), SQLITE_STATIC);
            rc = sqlite3_step(stmt);
            sqlite3_finalize(stmt);
            _mtx.unlock();
            if(rc == SQLITE_ROW){
                return true;
            }
            return false;
        }

        const bool DB::isRecordExists(const std::string &tableName,
                                      const std::string &recordId) const
        {
            _mtx.lock();
            sqlite3_stmt *stmt;
            int rc;
            string sqlString(OPENBIZ_CACHE_CHECK_RECORD_EXISTS_SQL(tableName));
            const char* sql = sqlString.c_str();
            rc = sqlite3_prepare_v2(_db, sql, -1, &stmt, NULL);
            rc = sqlite3_bind_text(stmt, 1,
                                   recordId.c_str(),static_cast<int>(recordId.size()), SQLITE_STATIC);
            rc = sqlite3_step(stmt);
            sqlite3_finalize(stmt);
            _mtx.unlock();
            if(rc == SQLITE_ROW){
                return true;
            }
            return false;
        }

        const bool DB::removeRecord(const std::string &tableName,
                                    const std::string &recordId) const
        {
            _mtx.lock();
            sqlite3_stmt *stmt;
            int rc;
            string sqlString(OPENBIZ_CACHE_REMOVE_RECORD_SQL(tableName));
            const char* sql = sqlString.c_str();
            rc = sqlite3_prepare_v2(_db, sql, -1, &stmt, NULL);
            rc = sqlite3_bind_text(stmt, 1,
                                   recordId.c_str(),static_cast<int>(recordId.size()), SQLITE_STATIC);
            rc = sqlite3_step(stmt);
            sqlite3_finalize(stmt);
            _mtx.unlock();
            if(rc == SQLITE_DONE){
                return true;
            }
            return false;
        }

        const bool DB::removeAllRecords(const std::string &tableName) const
        {
            _mtx.lock();
            sqlite3_stmt *stmt;
            int rc;
            string sqlString(OPENBIZ_CACHE_REMOVE_ALL_RECORDS_SQL(tableName));
            const char* sql = sqlString.c_str();
            rc = sqlite3_prepare_v2(_db, sql, -1, &stmt, NULL);
            rc = sqlite3_step(stmt);
            sqlite3_finalize(stmt);
            _mtx.unlock();
            if(rc == SQLITE_DONE){
                return true;
            }
            return false;
        }

        const DB::Record* DB::fetchRecord(const std::string &tableName,
                                          const std::string &recordId) const
        {
            _mtx.lock();
            DB::Record* record = nullptr;
            sqlite3_stmt *stmt;
            int rc;
            string sqlString(OPENBIZ_CACHE_FETCH_RECORD_SQL(tableName));
            const char* sql = sqlString.c_str();
            rc = sqlite3_prepare_v2(_db, sql, -1, &stmt, NULL);
            rc = sqlite3_bind_text(stmt, 1,
                                   recordId.c_str(),static_cast<int>(recordId.size()), SQLITE_STATIC);
            rc = sqlite3_step(stmt);
            if(rc == SQLITE_ROW){
                record = new DB::Record;
                record->Id      = std::string(reinterpret_cast<const char*>(sqlite3_column_text(stmt, 0)));
                record->data    = std::string(reinterpret_cast<const char*>(sqlite3_column_text(stmt, 1)));
                record->timestamp = static_cast<time_t>((sqlite3_column_int(stmt,2)));
            }
            sqlite3_finalize(stmt);
            _mtx.unlock();
            return record;
        }

        const bool DB::insertRecord(const std::string &tableName,
                                    const std::string &recordId,
                                    const std::string &data) const
        {
            _mtx.lock();
            sqlite3_stmt *stmt;
            int rc;
            string sqlString(OPENBIZ_CACHE_INSERT_RECORD_SQL(tableName));
            const char* sql =sqlString.c_str();

            rc = sqlite3_prepare(_db, sql, -1, &stmt, NULL);
            rc = sqlite3_bind_text(stmt, 1,
                                   recordId.c_str(),static_cast<int>(recordId.size()), SQLITE_STATIC);
            rc = sqlite3_bind_text(stmt, 2,
                                   data.c_str(),static_cast<int>(data.size()), SQLITE_STATIC);
            rc = sqlite3_step(stmt);
            sqlite3_finalize(stmt);
            _mtx.unlock();
            if(rc == SQLITE_DONE){
                return true;
            }
            return false;
        };

        const bool DB::updateRecord(const std::string &tableName,
                                    const std::string &recordId,
                                    const std::string &data) const
        {
            _mtx.lock();
            sqlite3_stmt *stmt;
            int rc;
            string sqlString(OPENBIZ_CACHE_UPDATE_RECORD_SQL(tableName));
            const char* sql = sqlString.c_str();
            rc = sqlite3_prepare_v2(_db, sql, -1, &stmt, NULL);
            rc = sqlite3_bind_text(stmt, 1,
                                   recordId.c_str(),static_cast<int>(recordId.size()), SQLITE_STATIC);
            rc = sqlite3_bind_text(stmt, 2,
                                   data.c_str(),static_cast<int>(data.size()), SQLITE_STATIC);
            rc = sqlite3_step(stmt);
            sqlite3_finalize(stmt);
            _mtx.unlock();
            if(rc == SQLITE_DONE){
                return true;
            }
            return false;
        };

        const std::vector<DB::Record*> *DB::fetchRecords(const std::string &tableName, int offset, int limit) const
        {
            _mtx.lock();
            std::vector<DB::Record*> *records = new std::vector<DB::Record*>;

            sqlite3_stmt *stmt;
            int rc;
            string sqlString(OPENBIZ_CACHE_FETCH_RECORDS_SQL(tableName));
            const char* sql = sqlString.c_str();
            rc = sqlite3_prepare_v2(_db, sql, -1, &stmt, NULL);
            rc = sqlite3_bind_int(stmt, 1, offset);
            rc = sqlite3_bind_int(stmt, 2, limit);
            rc = sqlite3_step(stmt);

            while(rc == SQLITE_ROW)
            {
                DB::Record *record = new DB::Record;
                record->Id      = std::string(reinterpret_cast<const char*>(sqlite3_column_text(stmt, 0)));
                record->data    = std::string(reinterpret_cast<const char*>(sqlite3_column_text(stmt, 1)));
                record->timestamp = static_cast<time_t>((sqlite3_column_int(stmt,2)));
                records->push_back(record);
                rc = sqlite3_step(stmt);
            }
            sqlite3_finalize(stmt);
            _mtx.unlock();
            return records;
        };

        const std::vector<DB::Record*> *DB::fetchRecords(const std::string &tableName, const std::string &keyword, int offset, int limit) const
        {
            _mtx.lock();
            std::vector<DB::Record*> *records = new std::vector<DB::Record*>;

            sqlite3_stmt *stmt;
            int rc;
            string sqlString(OPENBIZ_CACHE_QUERY_RECORDS_SQL(tableName));
            const char* sql = sqlString.c_str();
            rc = sqlite3_prepare_v2(_db, sql, -1, &stmt, NULL);
            rc = sqlite3_bind_text(stmt, 1,
                                   keyword.c_str(),static_cast<int>(keyword.size()), SQLITE_STATIC);
            rc = sqlite3_bind_int(stmt, 2, offset);
            rc = sqlite3_bind_int(stmt, 3, limit);
            rc = sqlite3_step(stmt);

            while(rc == SQLITE_ROW)
            {
                DB::Record *record = new DB::Record;
                record->Id      = std::string(reinterpret_cast<const char*>(sqlite3_column_text(stmt, 0)));
                record->data    = std::string(reinterpret_cast<const char*>(sqlite3_column_text(stmt, 1)));
                record->timestamp = static_cast<time_t>((sqlite3_column_int(stmt,2)));
                records->push_back(record);
                rc = sqlite3_step(stmt);
            }
            sqlite3_finalize(stmt);
            _mtx.unlock();
            return records;
        };

        unsigned int DB::countRecords(const std::string &tableName)
        {
            _mtx.lock();
            sqlite3_stmt *stmt;
            int rc;
            string sqlString(OPENBIZ_CACHE_COUNT_FETCHED_RECORDS_SQL(tableName));
            const char* sql = sqlString.c_str();
            rc = sqlite3_prepare_v2(_db, sql, -1, &stmt, NULL);
            rc = sqlite3_step(stmt);
            sqlite3_finalize(stmt);
            _mtx.unlock();
            if(rc == SQLITE_ROW){
                return sqlite3_column_int(stmt,0);
            }

            return 0;
        };

        unsigned int DB::countRecords(const std::string &tableName,const std::string &keyword)
        {
            _mtx.lock();
            sqlite3_stmt *stmt;
            int rc;
            string sqlString(OPENBIZ_CACHE_COUNT_FOUND_RECORDS_SQL(tableName));
            const char* sql = sqlString.c_str();
            rc = sqlite3_prepare_v2(_db, sql, -1, &stmt, NULL);
            rc = sqlite3_bind_text(stmt, 1,
                                   keyword.c_str(),static_cast<int>(keyword.size()), SQLITE_STATIC);
            rc = sqlite3_step(stmt);
            sqlite3_finalize(stmt);
            _mtx.unlock();

            if(rc == SQLITE_ROW){
                return sqlite3_column_int(stmt,0);
            }
            return 0;
        };

        void DB::destroyInstance(){
            _mtx.lock();
            if(_db!=NULL){
                sqlite3_close(_db);
            }
            _mtx.unlock();
            OPENBIZ_SAFE_DELETE(_instance);
        };
    }
}
<commit_msg>add mutex lock for sqlte db<commit_after>//
//  DB.cpp
//  Openbiz-RestModel
//
//  Created by Jixian Wang on 14-10-7.
//  Copyright (c) 2014年 openbiz. All rights reserved.
//

#include <iostream>
#include <stdexcept>
#include <vector>
#include <regex>
#include <cstdio>
#include "DB.h"
#include "PlatformMacros.h"
#include "FileUtils.h"
#include "sqlite3_json_extension.h"

#define OPENBIZ_CACHE_CREATE_TABLE_SQL(tableName) \
"CREATE TABLE IF NOT EXISTS `"+tableName+"` (`id` PRIMARY KEY, `timestamp` NUMERIC, `data` TEXT);"

#define OPENBIZ_CACHE_DROP_TABLE_SQL(tableName) \
"DROP TABLE IF EXISTS `"+tableName+"` ;"

#define OPENBIZ_CACHE_CHECK_TABLE_EXISTS_SQL \
"SELECT 1 FROM `sqlite_master` WHERE `type`='table' AND `name`= ? ;"

#define OPENBIZ_CACHE_CHECK_RECORD_EXISTS_SQL(tableName) \
"SELECT `id`,`data`,`timestamp` FROM `"+tableName+"` WHERE `id`= ? ;"

#define OPENBIZ_CACHE_FETCH_RECORD_SQL(tableName) \
"SELECT `id`,`data`,`timestamp` FROM `"+tableName+"` WHERE `id`= ? ;"

#define OPENBIZ_CACHE_FETCH_RECORDS_SQL(tableName) \
"SELECT `id`,`data`,`timestamp` FROM `"+tableName+"` LIMIT ?,?;"

#define OPENBIZ_CACHE_QUERY_RECORDS_SQL(tableName) \
"SELECT `id`,`data`,`timestamp` FROM `"+tableName+"` WHERE JSON_CONTAINS(?,data) LIMIT ?,?;"

#define OPENBIZ_CACHE_COUNT_FETCHED_RECORDS_SQL(tableName) \
"SELECT count(data) AS total FROM `"+tableName+"`;"

#define OPENBIZ_CACHE_COUNT_FOUND_RECORDS_SQL(tableName) \
"SELECT count(data) AS total FROM `"+tableName+"` WHERE JSON_CONTAINS(?,data);"

#define OPENBIZ_CACHE_UPDATE_RECORD_SQL(tableName) \
"UPDATE `"+tableName+"` SET `timestamp`=datetime(),`data`= ? WHERE id= ? ;"

#define OPENBIZ_CACHE_INSERT_RECORD_SQL(tableName) \
"INSERT INTO `"+tableName+"` (`id`,`timestamp`,`data`) VALUES (?, datetime(), ?); "

#define OPENBIZ_CACHE_REMOVE_RECORD_SQL(tableName) \
"DELETE FROM `"+tableName+"` WHERE `id`= ? ; "

#define OPENBIZ_CACHE_REMOVE_ALL_RECORDS_SQL(tableName) \
"DELETE FROM `"+tableName+"` ;"

using namespace std;

namespace openbiz
{
    namespace core
    {
        DB* DB::_instance = nullptr;
        sqlite3* DB::_db = nullptr;
        string DB::_dbName = "";
        std::mutex DB::_mtx;
        DB::~DB(){};
        DB::DB(){};

        DB* DB::getInstance()
        {
            if (_instance == nullptr)
            {
                _instance = new DB();
            }
            return _instance;
        }

        const sqlite3* DB::db(){
            if(_db==nullptr)
            {
                throw std::runtime_error("Please define a db name");
            }
            return _db;
        };

        void DB::initialize(const std::string &dbName)
        {
            if(!dbName.empty()){
                if(!_db){
                    const std::string path = ext::FileUtils::getInstance()->getWritablePath();
                    const std::string dbFullname = path + "/" + dbName;
                    int result = sqlite3_open(dbFullname.c_str(),&_db);
                    DB::_dbName = dbName;
                    if(result == SQLITE_OK){
                        //register sqlite json extension to db connection instance
                        sqlite3_json_extension_init(_db,NULL);
                    }
                    else{
                        throw std::runtime_error("Con't open database file: "+dbFullname);
                    }
                }
            }else{
                throw std::runtime_error("Please define a db name");
            }
        }

        void DB::dropDatabase()
        {
            if(!DB::_dbName.empty()){
                _mtx.lock();
                sqlite3_close(_db);
                _mtx.unlock();
                _db = nullptr;
                const std::string path = ext::FileUtils::getInstance()->getWritablePath();
                const std::string dbFullname = path + "/" + DB::_dbName;
                std::remove(dbFullname.c_str());
            }
            destroyInstance();

        }

        void DB::ensureTableExists(const std::string &tableName) const
        {
            if(!isTableExists(tableName)){
                _mtx.lock();
                sqlite3_stmt *stmt;
                int rc;
                string sqlString(OPENBIZ_CACHE_CREATE_TABLE_SQL(tableName));
                const char* sql = sqlString.c_str();
                rc = sqlite3_prepare_v2(_db, sql, -1, &stmt, NULL);
                rc = sqlite3_bind_text(stmt, 1,
                                       tableName.c_str(),static_cast<int>(tableName.size()), SQLITE_STATIC);
                rc = sqlite3_step(stmt);
                sqlite3_finalize(stmt);
                _mtx.unlock();
            }
            return;
        }

        const bool DB::isTableExists(const std::string &tableName) const
        {
            _mtx.lock();
            sqlite3_stmt *stmt;
            int rc;
            string sqlString(OPENBIZ_CACHE_CHECK_TABLE_EXISTS_SQL);
            const char* sql = sqlString.c_str();
            rc = sqlite3_prepare_v2(_db, sql, -1, &stmt, NULL);
            rc = sqlite3_bind_text(stmt, 1,
                                   tableName.c_str(),static_cast<int>(tableName.size()), SQLITE_STATIC);
            rc = sqlite3_step(stmt);
            sqlite3_finalize(stmt);
            _mtx.unlock();
            if(rc == SQLITE_ROW){
                return true;
            }
            return false;
        }

        const bool DB::isRecordExists(const std::string &tableName,
                                      const std::string &recordId) const
        {
            _mtx.lock();
            sqlite3_stmt *stmt;
            int rc;
            string sqlString(OPENBIZ_CACHE_CHECK_RECORD_EXISTS_SQL(tableName));
            const char* sql = sqlString.c_str();
            rc = sqlite3_prepare_v2(_db, sql, -1, &stmt, NULL);
            rc = sqlite3_bind_text(stmt, 1,
                                   recordId.c_str(),static_cast<int>(recordId.size()), SQLITE_STATIC);
            rc = sqlite3_step(stmt);
            sqlite3_finalize(stmt);
            _mtx.unlock();
            if(rc == SQLITE_ROW){
                return true;
            }
            return false;
        }

        const bool DB::removeRecord(const std::string &tableName,
                                    const std::string &recordId) const
        {
            _mtx.lock();
            sqlite3_stmt *stmt;
            int rc;
            string sqlString(OPENBIZ_CACHE_REMOVE_RECORD_SQL(tableName));
            const char* sql = sqlString.c_str();
            rc = sqlite3_prepare_v2(_db, sql, -1, &stmt, NULL);
            rc = sqlite3_bind_text(stmt, 1,
                                   recordId.c_str(),static_cast<int>(recordId.size()), SQLITE_STATIC);
            rc = sqlite3_step(stmt);
            sqlite3_finalize(stmt);
            _mtx.unlock();
            if(rc == SQLITE_DONE){
                return true;
            }
            return false;
        }

        const bool DB::removeAllRecords(const std::string &tableName) const
        {
            _mtx.lock();
            sqlite3_stmt *stmt;
            int rc;
            string sqlString(OPENBIZ_CACHE_REMOVE_ALL_RECORDS_SQL(tableName));
            const char* sql = sqlString.c_str();
            rc = sqlite3_prepare_v2(_db, sql, -1, &stmt, NULL);
            rc = sqlite3_step(stmt);
            sqlite3_finalize(stmt);
            _mtx.unlock();
            if(rc == SQLITE_DONE){
                return true;
            }
            return false;
        }

        const DB::Record* DB::fetchRecord(const std::string &tableName,
                                          const std::string &recordId) const
        {
            _mtx.lock();
            DB::Record* record = nullptr;
            sqlite3_stmt *stmt;
            int rc;
            string sqlString(OPENBIZ_CACHE_FETCH_RECORD_SQL(tableName));
            const char* sql = sqlString.c_str();
            rc = sqlite3_prepare_v2(_db, sql, -1, &stmt, NULL);
            rc = sqlite3_bind_text(stmt, 1,
                                   recordId.c_str(),static_cast<int>(recordId.size()), SQLITE_STATIC);
            rc = sqlite3_step(stmt);
            if(rc == SQLITE_ROW){
                record = new DB::Record;
                record->Id      = std::string(reinterpret_cast<const char*>(sqlite3_column_text(stmt, 0)));
                record->data    = std::string(reinterpret_cast<const char*>(sqlite3_column_text(stmt, 1)));
                record->timestamp = static_cast<time_t>((sqlite3_column_int(stmt,2)));
            }
            sqlite3_finalize(stmt);
            _mtx.unlock();
            return record;
        }

        const bool DB::insertRecord(const std::string &tableName,
                                    const std::string &recordId,
                                    const std::string &data) const
        {
            _mtx.lock();
            sqlite3_stmt *stmt;
            int rc;
            string sqlString(OPENBIZ_CACHE_INSERT_RECORD_SQL(tableName));
            const char* sql =sqlString.c_str();

            rc = sqlite3_prepare(_db, sql, -1, &stmt, NULL);
            rc = sqlite3_bind_text(stmt, 1,
                                   recordId.c_str(),static_cast<int>(recordId.size()), SQLITE_STATIC);
            rc = sqlite3_bind_text(stmt, 2,
                                   data.c_str(),static_cast<int>(data.size()), SQLITE_STATIC);
            rc = sqlite3_step(stmt);
            sqlite3_finalize(stmt);
            _mtx.unlock();
            if(rc == SQLITE_DONE){
                return true;
            }
            return false;
        };

        const bool DB::updateRecord(const std::string &tableName,
                                    const std::string &recordId,
                                    const std::string &data) const
        {
            _mtx.lock();
            sqlite3_stmt *stmt;
            int rc;
            string sqlString(OPENBIZ_CACHE_UPDATE_RECORD_SQL(tableName));
            const char* sql = sqlString.c_str();
            rc = sqlite3_prepare_v2(_db, sql, -1, &stmt, NULL);
            rc = sqlite3_bind_text(stmt, 1,
                                   recordId.c_str(),static_cast<int>(recordId.size()), SQLITE_STATIC);
            rc = sqlite3_bind_text(stmt, 2,
                                   data.c_str(),static_cast<int>(data.size()), SQLITE_STATIC);
            rc = sqlite3_step(stmt);
            sqlite3_finalize(stmt);
            _mtx.unlock();
            if(rc == SQLITE_DONE){
                return true;
            }
            return false;
        };

        const std::vector<DB::Record*> *DB::fetchRecords(const std::string &tableName, int offset, int limit) const
        {
            _mtx.lock();
            std::vector<DB::Record*> *records = new std::vector<DB::Record*>;

            sqlite3_stmt *stmt;
            int rc;
            string sqlString(OPENBIZ_CACHE_FETCH_RECORDS_SQL(tableName));
            const char* sql = sqlString.c_str();
            rc = sqlite3_prepare_v2(_db, sql, -1, &stmt, NULL);
            rc = sqlite3_bind_int(stmt, 1, offset);
            rc = sqlite3_bind_int(stmt, 2, limit);
            rc = sqlite3_step(stmt);

            while(rc == SQLITE_ROW)
            {
                DB::Record *record = new DB::Record;
                record->Id      = std::string(reinterpret_cast<const char*>(sqlite3_column_text(stmt, 0)));
                record->data    = std::string(reinterpret_cast<const char*>(sqlite3_column_text(stmt, 1)));
                record->timestamp = static_cast<time_t>((sqlite3_column_int(stmt,2)));
                records->push_back(record);
                rc = sqlite3_step(stmt);
            }
            sqlite3_finalize(stmt);
            _mtx.unlock();
            return records;
        };

        const std::vector<DB::Record*> *DB::fetchRecords(const std::string &tableName, const std::string &keyword, int offset, int limit) const
        {
            _mtx.lock();
            std::vector<DB::Record*> *records = new std::vector<DB::Record*>;

            sqlite3_stmt *stmt;
            int rc;
            string sqlString(OPENBIZ_CACHE_QUERY_RECORDS_SQL(tableName));
            const char* sql = sqlString.c_str();
            rc = sqlite3_prepare_v2(_db, sql, -1, &stmt, NULL);
            rc = sqlite3_bind_text(stmt, 1,
                                   keyword.c_str(),static_cast<int>(keyword.size()), SQLITE_STATIC);
            rc = sqlite3_bind_int(stmt, 2, offset);
            rc = sqlite3_bind_int(stmt, 3, limit);
            rc = sqlite3_step(stmt);

            while(rc == SQLITE_ROW)
            {
                DB::Record *record = new DB::Record;
                record->Id      = std::string(reinterpret_cast<const char*>(sqlite3_column_text(stmt, 0)));
                record->data    = std::string(reinterpret_cast<const char*>(sqlite3_column_text(stmt, 1)));
                record->timestamp = static_cast<time_t>((sqlite3_column_int(stmt,2)));
                records->push_back(record);
                rc = sqlite3_step(stmt);
            }
            sqlite3_finalize(stmt);
            _mtx.unlock();
            return records;
        };

        unsigned int DB::countRecords(const std::string &tableName)
        {
            _mtx.lock();
            sqlite3_stmt *stmt;
            int rc;
            string sqlString(OPENBIZ_CACHE_COUNT_FETCHED_RECORDS_SQL(tableName));
            const char* sql = sqlString.c_str();
            rc = sqlite3_prepare_v2(_db, sql, -1, &stmt, NULL);
            rc = sqlite3_step(stmt);
            sqlite3_finalize(stmt);
            _mtx.unlock();
            int result = 0;
            if(rc == SQLITE_ROW){
                result =  sqlite3_column_int(stmt,0);
            }
            sqlite3_finalize(stmt);
            _mtx.unlock();
            return result;
        };

        unsigned int DB::countRecords(const std::string &tableName,const std::string &keyword)
        {
            _mtx.lock();
            sqlite3_stmt *stmt;
            int rc;
            string sqlString(OPENBIZ_CACHE_COUNT_FOUND_RECORDS_SQL(tableName));
            const char* sql = sqlString.c_str();
            rc = sqlite3_prepare_v2(_db, sql, -1, &stmt, NULL);
            rc = sqlite3_bind_text(stmt, 1,
                                   keyword.c_str(),static_cast<int>(keyword.size()), SQLITE_STATIC);
            rc = sqlite3_step(stmt);
            sqlite3_finalize(stmt);
            _mtx.unlock();
            int result = 0;
            if(rc == SQLITE_ROW){
                result = sqlite3_column_int(stmt,0);
            }
            sqlite3_finalize(stmt);
            _mtx.unlock();
            return result;
        };

        void DB::destroyInstance(){
            _mtx.lock();
            if(_db!=NULL){
                sqlite3_close(_db);
            }
            _mtx.unlock();
            OPENBIZ_SAFE_DELETE(_instance);
        };
    }
}
<|endoftext|>