<commit_before>/******************************************************************************
* Copyright (c) 2011, Michael P. Gerlek (mpg@flaxen.com)
*
* 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 Hobu, Inc. or Flaxen Geo Consulting 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.
****************************************************************************/

#ifndef _WIN32
#include <dlfcn.h>
#endif

#include <pdal/plang/Environment.hpp>
#include <pdal/plang/Redirector.hpp>
#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION
#define PY_ARRAY_UNIQUE_SYMBOL PDAL_ARRAY_API
#include <numpy/arrayobject.h>

#include <sstream>
#include <mutex>

#ifdef PDAL_COMPILER_MSVC
#  pragma warning(disable: 4127)  // conditional expression is constant
#endif

#include <Python.h>
#include <pystate.h>
#undef toupper
#undef tolower
#undef isspace

// See ticket #1010.  This function runs when libplang is loaded.  It makes
// sure python symbols can be found by extention module .so's since on some
// platforms (notably Ubuntu), they aren't linked with libpython even though
// they depend on it.  If a platform doesn't support
// __attribute__ ((constructor)) this does nothing.  We'll have to deal with
// those as they come up.
#ifndef _WIN32
__attribute__ ((constructor))
static void loadPython()
{
    std::cerr << "Force load python.\n";
    ::dlopen(PDAL_PYTHON_LIBRARY, RTLD_LAZY | RTLD_GLOBAL);
}
#endif

// http://www.linuxjournal.com/article/3641
// http://www.codeproject.com/Articles/11805/Embedding-Python-in-C-C-Part-I
// http://stackoverflow.com/questions/6596016/python-threads-in-c

namespace pdal
{
namespace plang
{

static Environment* g_environment=0;

EnvironmentPtr Environment::get()
{
    static std::once_flag flag;

    auto init = []()
    {
        g_environment = new Environment();
    };

    std::call_once(flag, init);

    return g_environment;
}

Environment::Environment()
{
    // This awfulness is due to the import_array MACRO that returns a value
    // in some cases and returns nothing at other times.  Defining
    // NUMPY_IMPORT_ARRAY_RETVAL to nothing makes it so we don't ever return
    // a value.  The function needs to be stuck in a function to deal with
    // the return.
    auto initNumpy = []()
    {
#undef NUMPY_IMPORT_ARRAY_RETVAL
#define NUMPY_IMPORT_ARRAY_RETVAL
        import_array();
    };

    PyImport_AppendInittab(const_cast<char*>("redirector"), redirector_init);

    Py_Initialize();
    initNumpy();
    PyImport_ImportModule("redirector");
}

Environment::~Environment()
{
    Py_Finalize();
}

void Environment::set_stdout(std::ostream* ostr)
{
    m_redirector.set_stdout(ostr);
}

void Environment::reset_stdout()
{
    m_redirector.reset_stdout();
}

std::string getTraceback()
{
    // get exception info
    PyObject *type, *value, *traceback;
    PyErr_Fetch(&type, &value, &traceback);
    PyErr_NormalizeException(&type, &value, &traceback);

    std::ostringstream mssg;
    if (traceback)
    {
        PyObject* tracebackModule;
        PyObject* tracebackDictionary;
        PyObject* tracebackFunction;

        tracebackModule = PyImport_ImportModule("traceback");
        if (!tracebackModule)
            throw pdal::pdal_error("Unable to load traceback module.");

        tracebackDictionary = PyModule_GetDict(tracebackModule);
        if (!tracebackDictionary)
            throw pdal::pdal_error("Unable to load traceback dictionary.");
        tracebackFunction =
            PyDict_GetItemString(tracebackDictionary, "format_exception");
        if (!tracebackFunction)
            throw pdal::pdal_error("Unable to find traceback function.");

        if (!PyCallable_Check(tracebackFunction))
            throw pdal::pdal_error("Invalid traceback function.");

        // create an argument for "format exception"
        PyObject* args = PyTuple_New(3);
        PyTuple_SetItem(args, 0, type);
        PyTuple_SetItem(args, 1, value);
        PyTuple_SetItem(args, 2, traceback);

        // get a list of string describing what went wrong
        PyObject* output = PyObject_CallObject(tracebackFunction, args);

        // print error message
        int n = PyList_Size(output);

        for (int i = 0; i < n; i++)
        {
            PyObject* l = PyList_GetItem(output, i);
            if (!l)
                throw pdal::pdal_error("unable to get list item in getTraceback");
            PyObject* r = PyObject_Repr(l);
            if (!r)
                throw pdal::pdal_error("unable to get repr in getTraceback");
            Py_ssize_t size;
#if PY_MAJOR_VERSION >= 3
            char* d = PyUnicode_AsUTF8AndSize(r, &size);
#else
            char* d = PyString_AsString(r);
#endif
            mssg << d;
        }

        // clean up
        Py_XDECREF(args);
        Py_XDECREF(output);
    }
    else if (value != NULL)
    {
        PyObject* r = PyObject_Repr(value);
        if (!r)
            throw pdal::pdal_error("couldn't make string representation of traceback value");
        Py_ssize_t size;
#if PY_MAJOR_VERSION >= 3
            char* d = PyUnicode_AsUTF8AndSize(r, &size);
#else
            char* d = PyString_AsString(r);
#endif
        mssg << d;
    }
    else
        mssg << "unknown error that we are unable to get a traceback for."
            "Was it already printed/taken?";

    Py_XDECREF(value);
    Py_XDECREF(type);
    Py_XDECREF(traceback);

    return mssg.str();
}

PyObject *fromMetadata(MetadataNode m)
{
    std::string name = m.name();
    std::string value = m.value();
    std::string type = m.type();
    std::string description = m.description();

    MetadataNodeList children = m.children();
    PyObject *submeta = NULL;
    if (children.size())
    {
        submeta = PyList_New(0);
        for (MetadataNode& child : children)
            PyList_Append(submeta, fromMetadata(child));
    }
    PyObject *data = PyTuple_New(5);
    PyTuple_SetItem(data, 0, PyUnicode_FromString(name.data()));
    PyTuple_SetItem(data, 1, PyUnicode_FromString(value.data()));
    PyTuple_SetItem(data, 2, PyUnicode_FromString(type.data()));
    PyTuple_SetItem(data, 3, PyUnicode_FromString(description.data()));
    PyTuple_SetItem(data, 4, submeta);

    return data;
}

std::string readPythonString(PyObject* list, Py_ssize_t index)
{
    std::stringstream ss;

    PyObject* o = PyTuple_GetItem(list, index);
    if (!o)
    {
        std::stringstream oss;
        oss << "Unable to get list item number " << index << " for list of length " << PyTuple_Size(list);
        throw pdal_error(oss.str());
    }
    PyObject* r = PyObject_Repr(o);
    if (!r)
        throw pdal::pdal_error("unable to get repr in readPythonString");
    Py_ssize_t size;
#if PY_MAJOR_VERSION >= 3
            char* d = PyUnicode_AsUTF8AndSize(r, &size);
#else
            char* d = PyString_AsString(r);
#endif
    ss << d;

    return ss.str();
}
void addMetadata(PyObject *list, MetadataNode m)
{

    if (!PyList_Check(list))
        return;

    for (Py_ssize_t i = 0; i < PyList_Size(list); ++i)
    {
        PyObject *tuple = PyList_GetItem(list, i);
        if (!PyTuple_Check(tuple) || PyTuple_Size(tuple) != 5)
            continue;

        std::string name = readPythonString(tuple, 0);
        std::string value = readPythonString(tuple, 1);

        std::string type = readPythonString(tuple, 2);
        if (type.empty())
            type = Metadata::inferType(value);

        std::string description = readPythonString(tuple, 3);

        PyObject *submeta = PyTuple_GetItem(tuple, 4);
        MetadataNode child =  m.addWithType(name, value, type, description);
        if (submeta)
            addMetadata(submeta, child);
    }
}

int Environment::getPythonDataType(Dimension::Type::Enum t)
{
    using namespace Dimension;

    switch (t)
    {
    case Type::Float:
        return NPY_FLOAT;
    case Type::Double:
        return NPY_DOUBLE;
    case Type::Signed8:
        return NPY_BYTE;
    case Type::Signed16:
        return NPY_SHORT;
    case Type::Signed32:
        return NPY_INT;
    case Type::Signed64:
        return NPY_LONGLONG;
    case Type::Unsigned8:
        return NPY_UBYTE;
    case Type::Unsigned16:
        return NPY_USHORT;
    case Type::Unsigned32:
        return NPY_UINT;
    case Type::Unsigned64:
        return NPY_ULONGLONG;
    default:
        return -1;
    }
    assert(0);

    return -1;
}

} // namespace plang
} // namespace pdal

<commit_msg>Remove debug.<commit_after>/******************************************************************************
* Copyright (c) 2011, Michael P. Gerlek (mpg@flaxen.com)
*
* 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 Hobu, Inc. or Flaxen Geo Consulting 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.
****************************************************************************/

#ifndef _WIN32
#include <dlfcn.h>
#endif

#include <pdal/plang/Environment.hpp>
#include <pdal/plang/Redirector.hpp>
#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION
#define PY_ARRAY_UNIQUE_SYMBOL PDAL_ARRAY_API
#include <numpy/arrayobject.h>

#include <sstream>
#include <mutex>

#ifdef PDAL_COMPILER_MSVC
#  pragma warning(disable: 4127)  // conditional expression is constant
#endif

#include <Python.h>
#include <pystate.h>
#undef toupper
#undef tolower
#undef isspace

// See ticket #1010.  This function runs when libplang is loaded.  It makes
// sure python symbols can be found by extention module .so's since on some
// platforms (notably Ubuntu), they aren't linked with libpython even though
// they depend on it.  If a platform doesn't support
// __attribute__ ((constructor)) this does nothing.  We'll have to deal with
// those as they come up.
#ifndef _WIN32
__attribute__ ((constructor))
static void loadPython()
{
    ::dlopen(PDAL_PYTHON_LIBRARY, RTLD_LAZY | RTLD_GLOBAL);
}
#endif

// http://www.linuxjournal.com/article/3641
// http://www.codeproject.com/Articles/11805/Embedding-Python-in-C-C-Part-I
// http://stackoverflow.com/questions/6596016/python-threads-in-c

namespace pdal
{
namespace plang
{

static Environment* g_environment=0;

EnvironmentPtr Environment::get()
{
    static std::once_flag flag;

    auto init = []()
    {
        g_environment = new Environment();
    };

    std::call_once(flag, init);

    return g_environment;
}

Environment::Environment()
{
    // This awfulness is due to the import_array MACRO that returns a value
    // in some cases and returns nothing at other times.  Defining
    // NUMPY_IMPORT_ARRAY_RETVAL to nothing makes it so we don't ever return
    // a value.  The function needs to be stuck in a function to deal with
    // the return.
    auto initNumpy = []()
    {
#undef NUMPY_IMPORT_ARRAY_RETVAL
#define NUMPY_IMPORT_ARRAY_RETVAL
        import_array();
    };

    PyImport_AppendInittab(const_cast<char*>("redirector"), redirector_init);

    Py_Initialize();
    initNumpy();
    PyImport_ImportModule("redirector");
}

Environment::~Environment()
{
    Py_Finalize();
}

void Environment::set_stdout(std::ostream* ostr)
{
    m_redirector.set_stdout(ostr);
}

void Environment::reset_stdout()
{
    m_redirector.reset_stdout();
}

std::string getTraceback()
{
    // get exception info
    PyObject *type, *value, *traceback;
    PyErr_Fetch(&type, &value, &traceback);
    PyErr_NormalizeException(&type, &value, &traceback);

    std::ostringstream mssg;
    if (traceback)
    {
        PyObject* tracebackModule;
        PyObject* tracebackDictionary;
        PyObject* tracebackFunction;

        tracebackModule = PyImport_ImportModule("traceback");
        if (!tracebackModule)
            throw pdal::pdal_error("Unable to load traceback module.");

        tracebackDictionary = PyModule_GetDict(tracebackModule);
        if (!tracebackDictionary)
            throw pdal::pdal_error("Unable to load traceback dictionary.");
        tracebackFunction =
            PyDict_GetItemString(tracebackDictionary, "format_exception");
        if (!tracebackFunction)
            throw pdal::pdal_error("Unable to find traceback function.");

        if (!PyCallable_Check(tracebackFunction))
            throw pdal::pdal_error("Invalid traceback function.");

        // create an argument for "format exception"
        PyObject* args = PyTuple_New(3);
        PyTuple_SetItem(args, 0, type);
        PyTuple_SetItem(args, 1, value);
        PyTuple_SetItem(args, 2, traceback);

        // get a list of string describing what went wrong
        PyObject* output = PyObject_CallObject(tracebackFunction, args);

        // print error message
        int n = PyList_Size(output);

        for (int i = 0; i < n; i++)
        {
            PyObject* l = PyList_GetItem(output, i);
            if (!l)
                throw pdal::pdal_error("unable to get list item in getTraceback");
            PyObject* r = PyObject_Repr(l);
            if (!r)
                throw pdal::pdal_error("unable to get repr in getTraceback");
            Py_ssize_t size;
#if PY_MAJOR_VERSION >= 3
            char* d = PyUnicode_AsUTF8AndSize(r, &size);
#else
            char* d = PyString_AsString(r);
#endif
            mssg << d;
        }

        // clean up
        Py_XDECREF(args);
        Py_XDECREF(output);
    }
    else if (value != NULL)
    {
        PyObject* r = PyObject_Repr(value);
        if (!r)
            throw pdal::pdal_error("couldn't make string representation of traceback value");
        Py_ssize_t size;
#if PY_MAJOR_VERSION >= 3
            char* d = PyUnicode_AsUTF8AndSize(r, &size);
#else
            char* d = PyString_AsString(r);
#endif
        mssg << d;
    }
    else
        mssg << "unknown error that we are unable to get a traceback for."
            "Was it already printed/taken?";

    Py_XDECREF(value);
    Py_XDECREF(type);
    Py_XDECREF(traceback);

    return mssg.str();
}

PyObject *fromMetadata(MetadataNode m)
{
    std::string name = m.name();
    std::string value = m.value();
    std::string type = m.type();
    std::string description = m.description();

    MetadataNodeList children = m.children();
    PyObject *submeta = NULL;
    if (children.size())
    {
        submeta = PyList_New(0);
        for (MetadataNode& child : children)
            PyList_Append(submeta, fromMetadata(child));
    }
    PyObject *data = PyTuple_New(5);
    PyTuple_SetItem(data, 0, PyUnicode_FromString(name.data()));
    PyTuple_SetItem(data, 1, PyUnicode_FromString(value.data()));
    PyTuple_SetItem(data, 2, PyUnicode_FromString(type.data()));
    PyTuple_SetItem(data, 3, PyUnicode_FromString(description.data()));
    PyTuple_SetItem(data, 4, submeta);

    return data;
}

std::string readPythonString(PyObject* list, Py_ssize_t index)
{
    std::stringstream ss;

    PyObject* o = PyTuple_GetItem(list, index);
    if (!o)
    {
        std::stringstream oss;
        oss << "Unable to get list item number " << index << " for list of length " << PyTuple_Size(list);
        throw pdal_error(oss.str());
    }
    PyObject* r = PyObject_Repr(o);
    if (!r)
        throw pdal::pdal_error("unable to get repr in readPythonString");
    Py_ssize_t size;
#if PY_MAJOR_VERSION >= 3
            char* d = PyUnicode_AsUTF8AndSize(r, &size);
#else
            char* d = PyString_AsString(r);
#endif
    ss << d;

    return ss.str();
}
void addMetadata(PyObject *list, MetadataNode m)
{

    if (!PyList_Check(list))
        return;

    for (Py_ssize_t i = 0; i < PyList_Size(list); ++i)
    {
        PyObject *tuple = PyList_GetItem(list, i);
        if (!PyTuple_Check(tuple) || PyTuple_Size(tuple) != 5)
            continue;

        std::string name = readPythonString(tuple, 0);
        std::string value = readPythonString(tuple, 1);

        std::string type = readPythonString(tuple, 2);
        if (type.empty())
            type = Metadata::inferType(value);

        std::string description = readPythonString(tuple, 3);

        PyObject *submeta = PyTuple_GetItem(tuple, 4);
        MetadataNode child =  m.addWithType(name, value, type, description);
        if (submeta)
            addMetadata(submeta, child);
    }
}

int Environment::getPythonDataType(Dimension::Type::Enum t)
{
    using namespace Dimension;

    switch (t)
    {
    case Type::Float:
        return NPY_FLOAT;
    case Type::Double:
        return NPY_DOUBLE;
    case Type::Signed8:
        return NPY_BYTE;
    case Type::Signed16:
        return NPY_SHORT;
    case Type::Signed32:
        return NPY_INT;
    case Type::Signed64:
        return NPY_LONGLONG;
    case Type::Unsigned8:
        return NPY_UBYTE;
    case Type::Unsigned16:
        return NPY_USHORT;
    case Type::Unsigned32:
        return NPY_UINT;
    case Type::Unsigned64:
        return NPY_ULONGLONG;
    default:
        return -1;
    }
    assert(0);

    return -1;
}

} // namespace plang
} // namespace pdal

<|endoftext|>


<commit_before>//
//  libavg - Media Playback Engine.
//  Copyright (C) 2003-2011 Ulrich von Zadow
//
//  This library is free software; you can redistribute it and/or
//  modify it under the terms of the GNU Lesser General Public
//  License as published by the Free Software Foundation; either
//  version 2 of the License, or (at your option) any later version.
//
//  This library is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
//  Lesser General Public License for more details.
//
//  You should have received a copy of the GNU Lesser General Public
//  License along with this library; if not, write to the Free Software
//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//
//  Current versions can be found at www.libavg.de
//

#include "Player.h"

#include "../base/TestSuite.h"
#include "../base/Exception.h"
#include "../base/Logger.h"
#include "../graphics/ShaderRegistry.h"

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string>

using namespace avg;
using namespace std;

class PlayerTest: public Test {
public:
    PlayerTest()
        : Test("PlayerTest", 2)
    {
    }

    void runTests()
    {
        Player player;
        player.loadString(
        "    <?xml version=\"1.0\"?>"
        "    <avg width=\"160\" height=\"120\">"
        "      <words text=\"foo\"/>"
        "    </avg>"
        );
        player.disablePython();
        if (!getenv("AVG_CONSOLE_TEST")) {
#ifdef WIN32
            player.initPlayback("./shaders");
#else
            player.initPlayback("../graphics/shaders/");
#endif
            player.doFrame(false);
            player.cleanup();
        }
        try {
            throw bad_cast();
        } catch (bad_cast&) {

        }
    }
};

class PlayerTestSuite: public TestSuite {
public:
    PlayerTestSuite()
        : TestSuite("PlayerTestSuite")
    {
        addTest(TestPtr(new PlayerTest));
    }
};

int main(int nargs, char** args)
{
    PlayerTestSuite suite;
    suite.runTests();
    bool bOK = suite.isOk();

    if (bOK) {
        return 0;
    } else {
        return 1;
    }
}

<commit_msg>Windows testplayer fix.<commit_after>//
//  libavg - Media Playback Engine.
//  Copyright (C) 2003-2011 Ulrich von Zadow
//
//  This library is free software; you can redistribute it and/or
//  modify it under the terms of the GNU Lesser General Public
//  License as published by the Free Software Foundation; either
//  version 2 of the License, or (at your option) any later version.
//
//  This library is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
//  Lesser General Public License for more details.
//
//  You should have received a copy of the GNU Lesser General Public
//  License along with this library; if not, write to the Free Software
//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//
//  Current versions can be found at www.libavg.de
//

#include "Player.h"

#include "../base/TestSuite.h"
#include "../base/Exception.h"
#include "../base/Logger.h"
#include "../graphics/ShaderRegistry.h"

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string>

#ifdef WIN32
#include <direct.h>
#endif

using namespace avg;
using namespace std;

class PlayerTest: public Test {
public:
    PlayerTest()
        : Test("PlayerTest", 2)
    {
    }

    void runTests()
    {
        Player player;
        player.loadString(
        "    <?xml version=\"1.0\"?>"
        "    <avg width=\"160\" height=\"120\">"
        "      <words text=\"foo\"/>"
        "    </avg>"
        );
        player.disablePython();
        if (!getenv("AVG_CONSOLE_TEST")) {
#ifdef WIN32
            char sz[1024];
            _getcwd(sz, 1024);
            cerr << "Current directory: " << sz << endl;
            player.initPlayback("../../graphics/shaders");
#else
            player.initPlayback("../graphics/shaders/");
#endif
            player.doFrame(false);
            player.cleanup();
        }
        try {
            throw bad_cast();
        } catch (bad_cast&) {

        }
    }
};

class PlayerTestSuite: public TestSuite {
public:
    PlayerTestSuite()
        : TestSuite("PlayerTestSuite")
    {
        addTest(TestPtr(new PlayerTest));
    }
};

int main(int nargs, char** args)
{
    PlayerTestSuite suite;
    suite.runTests();
    bool bOK = suite.isOk();

    if (bOK) {
        return 0;
    } else {
        return 1;
    }
}

<|endoftext|>


<commit_before>/**
 * @file
 *
 * @brief Source for leaf plugin
 *
 * @copyright BSD License (see LICENSE.md or https://www.libelektra.org)
 *
 */

#include "leaf.hpp"

#include <kdbhelper.h>

using elektra::LeafDelegate;

using CppKey = kdb::Key;
using CppKeySet = kdb::KeySet;

namespace
{

/**
 * @brief This function returns a key set containing the plugin contract.
 *
 * @return A key set specifying the capabilities of the plugin
 */
CppKeySet getContract ()
{
	return CppKeySet{ 30,
			  keyNew ("system/elektra/modules/leaf", KEY_VALUE, "leaf plugin waits for your orders", KEY_END),
			  keyNew ("system/elektra/modules/leaf/exports", KEY_END),
			  keyNew ("system/elektra/modules/leaf/exports/open", KEY_FUNC, elektraLeafOpen, KEY_END),
			  keyNew ("system/elektra/modules/leaf/exports/close", KEY_FUNC, elektraLeafClose, KEY_END),
			  keyNew ("system/elektra/modules/leaf/exports/get", KEY_FUNC, elektraLeafGet, KEY_END),
			  keyNew ("system/elektra/modules/leaf/exports/set", KEY_FUNC, elektraLeafSet, KEY_END),
#include ELEKTRA_README (leaf)
			  keyNew ("system/elektra/modules/leaf/infos/version", KEY_VALUE, PLUGINVERSION, KEY_END),
			  KS_END };
}

} // end namespace

extern "C" {

typedef Delegator<LeafDelegate> delegator;

/** @see elektraDocOpen */
int elektraLeafOpen (Plugin * handle, Key * key)
{
	// After the call to `delegator::open` you can retrieve a pointer to the delegate via `coderDelegator::get (handle)`
	return delegator::open (handle, key);
}

/** @see elektraDocClose */
int elektraLeafClose (Plugin * handle, Key * key)
{
	return delegator::close (handle, key);
}

/** @see elektraDocGet */
int elektraLeafGet (Plugin * handle ELEKTRA_UNUSED, KeySet * returned, Key * parentKey)
{
	CppKeySet keys{ returned };
	CppKey parent{ parentKey };

	if (parent.getName () == "system/elektra/modules/leaf")
	{
		keys.append (getContract ());
		parent.release ();
		keys.release ();
		return ELEKTRA_PLUGIN_STATUS_SUCCESS;
	}
	int status = delegator::get (handle)->convertToDirectories (keys);

	parent.release ();
	keys.release ();
	return status;
}

/** @see elektraDocSet */
int elektraLeafSet (Plugin * handle, KeySet * returned ELEKTRA_UNUSED, Key * parentKey ELEKTRA_UNUSED)
{
	CppKeySet keys{ returned };

	int status = delegator::get (handle)->convertToLeaves (keys);

	keys.release ();
	return status;
}

Plugin * ELEKTRA_PLUGIN_EXPORT (leaf)
{
	// clang-format off
	return elektraPluginExport ("leaf",
		ELEKTRA_PLUGIN_OPEN,	&elektraLeafOpen,
		ELEKTRA_PLUGIN_CLOSE,	&elektraLeafClose,
		ELEKTRA_PLUGIN_GET,	&elektraLeafGet,
		ELEKTRA_PLUGIN_SET,	&elektraLeafSet,
		ELEKTRA_PLUGIN_END);
}

} // end extern "C"
<commit_msg>Leaf: Catch exceptions in `get`/`set` functions<commit_after>/**
 * @file
 *
 * @brief Source for leaf plugin
 *
 * @copyright BSD License (see LICENSE.md or https://www.libelektra.org)
 *
 */

#include "leaf.hpp"

#include <kdbhelper.h>

using std::exception;

using elektra::LeafDelegate;

using CppKey = kdb::Key;
using CppKeySet = kdb::KeySet;

namespace
{

/**
 * @brief This function returns a key set containing the plugin contract.
 *
 * @return A key set specifying the capabilities of the plugin
 */
CppKeySet getContract ()
{
	return CppKeySet{ 30,
			  keyNew ("system/elektra/modules/leaf", KEY_VALUE, "leaf plugin waits for your orders", KEY_END),
			  keyNew ("system/elektra/modules/leaf/exports", KEY_END),
			  keyNew ("system/elektra/modules/leaf/exports/open", KEY_FUNC, elektraLeafOpen, KEY_END),
			  keyNew ("system/elektra/modules/leaf/exports/close", KEY_FUNC, elektraLeafClose, KEY_END),
			  keyNew ("system/elektra/modules/leaf/exports/get", KEY_FUNC, elektraLeafGet, KEY_END),
			  keyNew ("system/elektra/modules/leaf/exports/set", KEY_FUNC, elektraLeafSet, KEY_END),
#include ELEKTRA_README (leaf)
			  keyNew ("system/elektra/modules/leaf/infos/version", KEY_VALUE, PLUGINVERSION, KEY_END),
			  KS_END };
}

} // end namespace

extern "C" {

typedef Delegator<LeafDelegate> delegator;

/** @see elektraDocOpen */
int elektraLeafOpen (Plugin * handle, Key * key)
{
	// After the call to `delegator::open` you can retrieve a pointer to the delegate via `coderDelegator::get (handle)`
	return delegator::open (handle, key);
}

/** @see elektraDocClose */
int elektraLeafClose (Plugin * handle, Key * key)
{
	return delegator::close (handle, key);
}

/** @see elektraDocGet */
int elektraLeafGet (Plugin * handle ELEKTRA_UNUSED, KeySet * returned, Key * parentKey)
{
	CppKeySet keys{ returned };
	CppKey parent{ parentKey };

	if (parent.getName () == "system/elektra/modules/leaf")
	{
		keys.append (getContract ());
		parent.release ();
		keys.release ();
		return ELEKTRA_PLUGIN_STATUS_SUCCESS;
	}

	int status = ELEKTRA_PLUGIN_STATUS_ERROR;
	try
	{
		status = delegator::get (handle)->convertToDirectories (keys);
	}
	catch (exception const & error)
	{
		ELEKTRA_SET_ERROR (ELEKTRA_ERROR_UNCAUGHT_EXCEPTION, *parent, error.what ());
	}

	parent.release ();
	keys.release ();
	return status;
}

/** @see elektraDocSet */
int elektraLeafSet (Plugin * handle, KeySet * returned ELEKTRA_UNUSED, Key * parentKey ELEKTRA_UNUSED)
{
	CppKeySet keys{ returned };
	CppKey parent{ parentKey };

	int status = ELEKTRA_PLUGIN_STATUS_ERROR;
	try
	{
		status = delegator::get (handle)->convertToLeaves (keys);
	}
	catch (exception const & error)
	{
		ELEKTRA_SET_ERROR (ELEKTRA_ERROR_UNCAUGHT_EXCEPTION, *parent, error.what ());
	}

	parent.release ();
	keys.release ();
	return status;
}

Plugin * ELEKTRA_PLUGIN_EXPORT (leaf)
{
	// clang-format off
	return elektraPluginExport ("leaf",
		ELEKTRA_PLUGIN_OPEN,	&elektraLeafOpen,
		ELEKTRA_PLUGIN_CLOSE,	&elektraLeafClose,
		ELEKTRA_PLUGIN_GET,	&elektraLeafGet,
		ELEKTRA_PLUGIN_SET,	&elektraLeafSet,
		ELEKTRA_PLUGIN_END);
}

} // end extern "C"
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2019 Tuukka Norri
 * This code is licensed under MIT license (see LICENSE for details).
 */

#include <range/v3/all.hpp>
#include <vcf2multialign/can_handle_variant_alts.hh>
#include <vcf2multialign/preprocess/sample_sorter.hh>
#include <vcf2multialign/variant_format.hh>

namespace lb	= libbio;
namespace v2m	= vcf2multialign;

namespace vcf2multialign {

	bool sample_sorter::check_variant_for_sample_and_update_state(std::size_t const sample_idx, lb::variant const &var, std::uint8_t const alt_idx)
	{
		// Check the output position of the given sample.
		// FIXME: log if skipped.
		if (can_handle_variant_alt(var.alts()[alt_idx]))
		{
			auto const pos(var.zero_based_pos());
			if (m_end_positions_by_sample[sample_idx] <= pos)
			{
				auto const end_pos(variant_end_pos(var));
				libbio_assert_lt(sample_idx, m_end_positions_by_sample.size());
				m_end_positions_by_sample[sample_idx] = end_pos;
				return true;
			}
		}

		return false;
	}

	// Called before processing the next subgraph.
	void sample_sorter::prepare_for_next_subgraph()
	{
		m_path_counter = 1;
		std::fill(m_src_paths.begin(), m_src_paths.end(), 0);
		std::fill(m_end_positions_by_sample.begin(), m_end_positions_by_sample.end(), 0);
	}

	void sample_sorter::sort_by_variant_and_alt(lb::variant const &var, std::uint8_t const expected_alt_idx)
	{
		auto const *gt_field(get_variant_format(var).gt);

		// Reset variant-specific state.
		for (auto &word : m_branches_by_path_index.word_range() | ranges::view::take(1 + m_path_counter / branch_vector::ELEMENT_COUNT))
			word.store(0, std::memory_order_release);

		// Check which paths branch by setting a bit mask in m_branches_by_path_index.
		// The branching ones will have 0x3 in the end.
		{
			std::size_t sample_idx(0);
			for (auto const path_idx : m_src_paths)
			{
				// Convert to donor and chr indices.
				// If the ALT cannot be handled, use REF in alt_idx_.
				auto const [donor_idx, chr_idx] = m_sample_indexer->donor_and_chr_idx(sample_idx);
				auto const &sample(var.samples()[donor_idx]);
				auto const &gt((*gt_field)(sample));
				auto const alt_idx(gt[chr_idx].alt);
				auto const alt_idx_(check_variant_for_sample_and_update_state(sample_idx, var, chr_idx) ? alt_idx : 0);

				m_branches_by_path_index.fetch_or(path_idx, (expected_alt_idx == alt_idx_) ? 0x1 : 0x2, std::memory_order_release);
				++sample_idx;
			}
		}

		// Assign numbers to the branching paths.
		for (auto const &tup : ranges::view::enumerate(m_branches_by_path_index) | ranges::view::take(m_path_counter))
		{
			auto const [path_idx, val] = tup;
			if (0x3 == val.load(std::memory_order_acquire))
			{
				libbio_assert_lt(path_idx, m_branching_paths.size());
				m_branching_paths[path_idx] = m_path_counter++;
			}
		}

		// Assign path numbers to samples.
		{
			std::size_t sample_idx(0);
			for (auto const src_path_idx : m_src_paths)
			{
				auto const [donor_idx, chr_idx] = m_sample_indexer->donor_and_chr_idx(sample_idx);
				auto const &sample(var.samples()[donor_idx]);
				auto const &gt((*gt_field)(sample));
				auto const alt_idx(gt[chr_idx].alt);

				libbio_assert_lt(src_path_idx, m_branching_paths.size());
				auto const dst_path_idx(
					(m_branches_by_path_index.load(src_path_idx, std::memory_order_acquire) != 0x3 || expected_alt_idx == alt_idx)
					? src_path_idx
					: m_branching_paths[src_path_idx]
				);
				libbio_assert_lt(sample_idx, m_dst_paths.size());
				m_dst_paths[sample_idx] = dst_path_idx;
			}
		}

		using std::swap;
		swap(m_src_paths, m_dst_paths);
	}
}
<commit_msg>Fix bugs, number the paths in a more natural order<commit_after>/*
 * Copyright (c) 2019 Tuukka Norri
 * This code is licensed under MIT license (see LICENSE for details).
 */

#include <range/v3/all.hpp>
#include <vcf2multialign/can_handle_variant_alts.hh>
#include <vcf2multialign/preprocess/sample_sorter.hh>
#include <vcf2multialign/variant_format.hh>

namespace lb	= libbio;
namespace v2m	= vcf2multialign;

namespace vcf2multialign {

	bool sample_sorter::check_variant_for_sample_and_update_state(std::size_t const sample_idx, lb::variant const &var, std::uint8_t const alt_idx)
	{
		// Check the output position of the given sample. REF can always be handled.
		// FIXME: log if skipped.
		// If the current sample has zero, do not change its end position.
		if (0 == alt_idx)
			return true;

		if (can_handle_variant_alt(var.alts()[alt_idx - 1]))
		{
			auto const pos(var.zero_based_pos());
			if (m_end_positions_by_sample[sample_idx] <= pos)
			{
				auto const end_pos(variant_end_pos(var));
				libbio_assert_lt(sample_idx, m_end_positions_by_sample.size());
				m_end_positions_by_sample[sample_idx] = end_pos;
				return true;
			}
		}

		return false;
	}

	// Called before processing the next subgraph.
	void sample_sorter::prepare_for_next_subgraph()
	{
		m_path_counter = 1;
		std::fill(m_src_paths.begin(), m_src_paths.end(), 0);
		std::fill(m_end_positions_by_sample.begin(), m_end_positions_by_sample.end(), 0);
	}

	void sample_sorter::sort_by_variant_and_alt(lb::variant const &var, std::uint8_t const expected_alt_idx)
	{
		// FIXME: currently the variable naming is slightly confusing as alt_idx and expected_alt_idx are 1-based but var.alts() expects a zero-based index.
		auto const *gt_field(get_variant_format(var).gt);

		// Reset variant-specific state.
		for (auto &word : m_branches_by_path_index.word_range() | ranges::view::take(1 + m_path_counter / branch_vector::ELEMENT_COUNT))
			word.store(0, std::memory_order_release);

		// Check which paths branch by setting a bit mask in m_branches_by_path_index.
		// The branching ones will have 0x3 in the end.
		{
			std::size_t sample_idx(0);
			for (auto const path_idx : m_src_paths)
			{
				// Convert to donor and chr indices.
				// If the ALT cannot be handled, use REF in alt_idx_.
				auto const [donor_idx, chr_idx] = m_sample_indexer->donor_and_chr_idx(sample_idx);
				auto const &sample(var.samples()[donor_idx]);
				auto const &gt((*gt_field)(sample));
				auto const alt_idx(gt[chr_idx].alt);
				auto const alt_idx_(check_variant_for_sample_and_update_state(sample_idx, var, alt_idx) ? alt_idx : 0);

				auto const val((expected_alt_idx == alt_idx_) ? 0x2 : 0x1);
				//std::cerr << "1 donor_idx: " << donor_idx << " chr_idx: " << +chr_idx << " expected_alt_idx: " << +expected_alt_idx << " alt_idx: " << alt_idx << " alt_idx_: " << alt_idx_ << " path_idx: " << path_idx << " val: " << val << std::endl;
				m_branches_by_path_index.fetch_or(path_idx, val, std::memory_order_release);
				++sample_idx;
			}
		}

		// Assign numbers to the branching paths.
		for (auto const &tup : ranges::view::enumerate(m_branches_by_path_index) | ranges::view::take(m_path_counter))
		{
			auto const [path_idx, val] = tup;
			auto const mask(val.load(std::memory_order_acquire));
			//std::cerr << "2 path_idx: " << path_idx << " mask: " << mask << std::endl;
			if (0x3 == mask)
			{
				libbio_assert_lt(path_idx, m_branching_paths.size());
				m_branching_paths[path_idx] = m_path_counter++;
			}
		}

		// Assign path numbers to samples.
		{
			std::size_t sample_idx(0);
			for (auto const src_path_idx : m_src_paths)
			{
				auto const [donor_idx, chr_idx] = m_sample_indexer->donor_and_chr_idx(sample_idx);
				auto const &sample(var.samples()[donor_idx]);
				auto const &gt((*gt_field)(sample));
				auto const alt_idx(gt[chr_idx].alt);

				libbio_assert_lt(src_path_idx, m_branching_paths.size());
				auto const dst_path_idx(
					(m_branches_by_path_index.load(src_path_idx, std::memory_order_acquire) == 0x3 && expected_alt_idx == alt_idx)
					? m_branching_paths[src_path_idx]
					: src_path_idx
				);
				libbio_assert_lt(sample_idx, m_dst_paths.size());
				//std::cerr << "3 sample_idx: " << sample_idx << " dst_path_idx: " << dst_path_idx << std::endl;
				m_dst_paths[sample_idx] = dst_path_idx;
				++sample_idx;
			}
		}

		using std::swap;
		swap(m_src_paths, m_dst_paths);
	}
}
<|endoftext|>


<commit_before>//===-- ConstString.cpp -----------------------------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "lldb/Core/ConstString.h"
#include "lldb/Core/Stream.h"
#include "lldb/Host/Mutex.h"
#include "llvm/ADT/StringMap.h"

#import <mutex>

using namespace lldb_private;

class Pool
{
public:
    typedef const char * StringPoolValueType;
    typedef llvm::StringMap<StringPoolValueType, llvm::BumpPtrAllocator> StringPool;
    typedef llvm::StringMapEntry<StringPoolValueType> StringPoolEntryType;

    //------------------------------------------------------------------
    // Default constructor
    //
    // Initialize the member variables and create the empty string.
    //------------------------------------------------------------------
    Pool () :
        m_mutex (Mutex::eMutexTypeRecursive),
        m_string_map ()
    {
    }

    //------------------------------------------------------------------
    // Destructor
    //------------------------------------------------------------------
    ~Pool ()
    {
    }

    static StringPoolEntryType &
    GetStringMapEntryFromKeyData (const char *keyData)
    {
        char *ptr = const_cast<char*>(keyData) - sizeof (StringPoolEntryType);
        return *reinterpret_cast<StringPoolEntryType*>(ptr);
    }

    size_t
    GetConstCStringLength (const char *ccstr) const
    {
        if (ccstr)
        {
            const StringPoolEntryType&entry = GetStringMapEntryFromKeyData (ccstr);
            return entry.getKey().size();
        }
        return 0;
    }

    StringPoolValueType
    GetMangledCounterpart (const char *ccstr) const
    {
        if (ccstr)
            return GetStringMapEntryFromKeyData (ccstr).getValue();
        return 0;
    }

    bool
    SetMangledCounterparts (const char *key_ccstr, const char *value_ccstr)
    {
        if (key_ccstr && value_ccstr)
        {
            GetStringMapEntryFromKeyData (key_ccstr).setValue(value_ccstr);
            GetStringMapEntryFromKeyData (value_ccstr).setValue(key_ccstr);
            return true;
        }
        return false;
    }

    const char *
    GetConstCString (const char *cstr)
    {
        if (cstr)
            return GetConstCStringWithLength (cstr, strlen (cstr));
        return NULL;
    }

    const char *
    GetConstCStringWithLength (const char *cstr, size_t cstr_len)
    {
        if (cstr)
        {
            Mutex::Locker locker (m_mutex);
            llvm::StringRef string_ref (cstr, cstr_len);
            StringPoolEntryType& entry = *m_string_map.insert (std::make_pair (string_ref, (StringPoolValueType)NULL)).first;
            return entry.getKeyData();
        }
        return NULL;
    }

    const char *
    GetConstCStringWithStringRef (const llvm::StringRef &string_ref)
    {
        if (string_ref.data())
        {
            Mutex::Locker locker (m_mutex);
            StringPoolEntryType& entry = *m_string_map.insert (std::make_pair (string_ref, (StringPoolValueType)NULL)).first;
            return entry.getKeyData();
        }
        return NULL;
    }

    const char *
    GetConstCStringAndSetMangledCounterPart (const char *demangled_cstr, const char *mangled_ccstr)
    {
        if (demangled_cstr)
        {
            Mutex::Locker locker (m_mutex);
            // Make string pool entry with the mangled counterpart already set
            StringPoolEntryType& entry = *m_string_map.insert (std::make_pair (llvm::StringRef (demangled_cstr), mangled_ccstr)).first;

            // Extract the const version of the demangled_cstr
            const char *demangled_ccstr = entry.getKeyData();
            // Now assign the demangled const string as the counterpart of the
            // mangled const string...
            GetStringMapEntryFromKeyData (mangled_ccstr).setValue(demangled_ccstr);
            // Return the constant demangled C string
            return demangled_ccstr;
        }
        return NULL;
    }

    const char *
    GetConstTrimmedCStringWithLength (const char *cstr, size_t cstr_len)
    {
        if (cstr)
        {
            const size_t trimmed_len = std::min<size_t> (strlen (cstr), cstr_len);
            return GetConstCStringWithLength (cstr, trimmed_len);
        }
        return NULL;
    }

    //------------------------------------------------------------------
    // Return the size in bytes that this object and any items in its
    // collection of uniqued strings + data count values takes in
    // memory.
    //------------------------------------------------------------------
    size_t
    MemorySize() const
    {
        Mutex::Locker locker (m_mutex);
        size_t mem_size = sizeof(Pool);
        const_iterator end = m_string_map.end();
        for (const_iterator pos = m_string_map.begin(); pos != end; ++pos)
        {
            mem_size += sizeof(StringPoolEntryType) + pos->getKey().size();
        }
        return mem_size;
    }

protected:
    //------------------------------------------------------------------
    // Typedefs
    //------------------------------------------------------------------
    typedef StringPool::iterator iterator;
    typedef StringPool::const_iterator const_iterator;

    //------------------------------------------------------------------
    // Member variables
    //------------------------------------------------------------------
    mutable Mutex m_mutex;
    StringPool m_string_map;
};

//----------------------------------------------------------------------
// Frameworks and dylibs aren't supposed to have global C++
// initializers so we hide the string pool in a static function so
// that it will get initialized on the first call to this static
// function.
//
// Note, for now we make the string pool a pointer to the pool, because
// we can't guarantee that some objects won't get destroyed after the
// global destructor chain is run, and trying to make sure no destructors
// touch ConstStrings is difficult.  So we leak the pool instead.
//----------------------------------------------------------------------
static Pool &
StringPool()
{
    static std::once_flag g_pool_initialization_flag;
    static Pool *g_string_pool = NULL;

    std::call_once(g_pool_initialization_flag, [] () {
        g_string_pool = new Pool();
    });

    return *g_string_pool;
}

ConstString::ConstString (const char *cstr) :
    m_string (StringPool().GetConstCString (cstr))
{
}

ConstString::ConstString (const char *cstr, size_t cstr_len) :
    m_string (StringPool().GetConstCStringWithLength (cstr, cstr_len))
{
}

ConstString::ConstString (const llvm::StringRef &s) :
    m_string (StringPool().GetConstCStringWithLength (s.data(), s.size()))
{
}

bool
ConstString::operator < (const ConstString& rhs) const
{
    if (m_string == rhs.m_string)
        return false;

    llvm::StringRef lhs_string_ref (m_string, StringPool().GetConstCStringLength (m_string));
    llvm::StringRef rhs_string_ref (rhs.m_string, StringPool().GetConstCStringLength (rhs.m_string));

    // If both have valid C strings, then return the comparison
    if (lhs_string_ref.data() && rhs_string_ref.data())
        return lhs_string_ref < rhs_string_ref;

    // Else one of them was NULL, so if LHS is NULL then it is less than
    return lhs_string_ref.data() == NULL;
}

Stream&
lldb_private::operator << (Stream& s, const ConstString& str)
{
    const char *cstr = str.GetCString();
    if (cstr)
        s << cstr;

    return s;
}

size_t
ConstString::GetLength () const
{
    return StringPool().GetConstCStringLength (m_string);
}

int
ConstString::Compare (const ConstString& lhs, const ConstString& rhs)
{
    // If the iterators are the same, this is the same string
    const char *lhs_cstr = lhs.m_string;
    const char *rhs_cstr = rhs.m_string;
    if (lhs_cstr == rhs_cstr)
        return 0;
    if (lhs_cstr && rhs_cstr)
    {
        llvm::StringRef lhs_string_ref (lhs_cstr, StringPool().GetConstCStringLength (lhs_cstr));
        llvm::StringRef rhs_string_ref (rhs_cstr, StringPool().GetConstCStringLength (rhs_cstr));
        return lhs_string_ref.compare(rhs_string_ref);
    }

    if (lhs_cstr)
        return +1;  // LHS isn't NULL but RHS is
    else
        return -1;  // LHS is NULL but RHS isn't
}

void
ConstString::Dump(Stream *s, const char *fail_value) const
{
    if (s)
    {
        const char *cstr = AsCString (fail_value);
        if (cstr)
            s->PutCString (cstr);
    }
}

void
ConstString::DumpDebug(Stream *s) const
{
    const char *cstr = GetCString ();
    size_t cstr_len = GetLength();
    // Only print the parens if we have a non-NULL string
    const char *parens = cstr ? "\"" : "";
    s->Printf("%*p: ConstString, string = %s%s%s, length = %" PRIu64,
              static_cast<int>(sizeof(void*) * 2),
              static_cast<const void*>(this), parens, cstr, parens,
              static_cast<uint64_t>(cstr_len));
}

void
ConstString::SetCString (const char *cstr)
{
    m_string = StringPool().GetConstCString (cstr);
}

void
ConstString::SetString (const llvm::StringRef &s)
{
    m_string = StringPool().GetConstCStringWithLength (s.data(), s.size());
}

void
ConstString::SetCStringWithMangledCounterpart (const char *demangled, const ConstString &mangled)
{
    m_string = StringPool().GetConstCStringAndSetMangledCounterPart (demangled, mangled.m_string);
}

bool
ConstString::GetMangledCounterpart (ConstString &counterpart) const
{
    counterpart.m_string = StringPool().GetMangledCounterpart(m_string);
    return (bool)counterpart;
}

void
ConstString::SetCStringWithLength (const char *cstr, size_t cstr_len)
{
    m_string = StringPool().GetConstCStringWithLength(cstr, cstr_len);
}

void
ConstString::SetTrimmedCStringWithLength (const char *cstr, size_t cstr_len)
{
    m_string = StringPool().GetConstTrimmedCStringWithLength (cstr, cstr_len);
}

size_t
ConstString::StaticMemorySize()
{
    // Get the size of the static string pool
    return StringPool().MemorySize();
}
<commit_msg>In C++, it's #include not #import<commit_after>//===-- ConstString.cpp -----------------------------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "lldb/Core/ConstString.h"
#include "lldb/Core/Stream.h"
#include "lldb/Host/Mutex.h"
#include "llvm/ADT/StringMap.h"

#include <mutex>

using namespace lldb_private;

class Pool
{
public:
    typedef const char * StringPoolValueType;
    typedef llvm::StringMap<StringPoolValueType, llvm::BumpPtrAllocator> StringPool;
    typedef llvm::StringMapEntry<StringPoolValueType> StringPoolEntryType;

    //------------------------------------------------------------------
    // Default constructor
    //
    // Initialize the member variables and create the empty string.
    //------------------------------------------------------------------
    Pool () :
        m_mutex (Mutex::eMutexTypeRecursive),
        m_string_map ()
    {
    }

    //------------------------------------------------------------------
    // Destructor
    //------------------------------------------------------------------
    ~Pool ()
    {
    }

    static StringPoolEntryType &
    GetStringMapEntryFromKeyData (const char *keyData)
    {
        char *ptr = const_cast<char*>(keyData) - sizeof (StringPoolEntryType);
        return *reinterpret_cast<StringPoolEntryType*>(ptr);
    }

    size_t
    GetConstCStringLength (const char *ccstr) const
    {
        if (ccstr)
        {
            const StringPoolEntryType&entry = GetStringMapEntryFromKeyData (ccstr);
            return entry.getKey().size();
        }
        return 0;
    }

    StringPoolValueType
    GetMangledCounterpart (const char *ccstr) const
    {
        if (ccstr)
            return GetStringMapEntryFromKeyData (ccstr).getValue();
        return 0;
    }

    bool
    SetMangledCounterparts (const char *key_ccstr, const char *value_ccstr)
    {
        if (key_ccstr && value_ccstr)
        {
            GetStringMapEntryFromKeyData (key_ccstr).setValue(value_ccstr);
            GetStringMapEntryFromKeyData (value_ccstr).setValue(key_ccstr);
            return true;
        }
        return false;
    }

    const char *
    GetConstCString (const char *cstr)
    {
        if (cstr)
            return GetConstCStringWithLength (cstr, strlen (cstr));
        return NULL;
    }

    const char *
    GetConstCStringWithLength (const char *cstr, size_t cstr_len)
    {
        if (cstr)
        {
            Mutex::Locker locker (m_mutex);
            llvm::StringRef string_ref (cstr, cstr_len);
            StringPoolEntryType& entry = *m_string_map.insert (std::make_pair (string_ref, (StringPoolValueType)NULL)).first;
            return entry.getKeyData();
        }
        return NULL;
    }

    const char *
    GetConstCStringWithStringRef (const llvm::StringRef &string_ref)
    {
        if (string_ref.data())
        {
            Mutex::Locker locker (m_mutex);
            StringPoolEntryType& entry = *m_string_map.insert (std::make_pair (string_ref, (StringPoolValueType)NULL)).first;
            return entry.getKeyData();
        }
        return NULL;
    }

    const char *
    GetConstCStringAndSetMangledCounterPart (const char *demangled_cstr, const char *mangled_ccstr)
    {
        if (demangled_cstr)
        {
            Mutex::Locker locker (m_mutex);
            // Make string pool entry with the mangled counterpart already set
            StringPoolEntryType& entry = *m_string_map.insert (std::make_pair (llvm::StringRef (demangled_cstr), mangled_ccstr)).first;

            // Extract the const version of the demangled_cstr
            const char *demangled_ccstr = entry.getKeyData();
            // Now assign the demangled const string as the counterpart of the
            // mangled const string...
            GetStringMapEntryFromKeyData (mangled_ccstr).setValue(demangled_ccstr);
            // Return the constant demangled C string
            return demangled_ccstr;
        }
        return NULL;
    }

    const char *
    GetConstTrimmedCStringWithLength (const char *cstr, size_t cstr_len)
    {
        if (cstr)
        {
            const size_t trimmed_len = std::min<size_t> (strlen (cstr), cstr_len);
            return GetConstCStringWithLength (cstr, trimmed_len);
        }
        return NULL;
    }

    //------------------------------------------------------------------
    // Return the size in bytes that this object and any items in its
    // collection of uniqued strings + data count values takes in
    // memory.
    //------------------------------------------------------------------
    size_t
    MemorySize() const
    {
        Mutex::Locker locker (m_mutex);
        size_t mem_size = sizeof(Pool);
        const_iterator end = m_string_map.end();
        for (const_iterator pos = m_string_map.begin(); pos != end; ++pos)
        {
            mem_size += sizeof(StringPoolEntryType) + pos->getKey().size();
        }
        return mem_size;
    }

protected:
    //------------------------------------------------------------------
    // Typedefs
    //------------------------------------------------------------------
    typedef StringPool::iterator iterator;
    typedef StringPool::const_iterator const_iterator;

    //------------------------------------------------------------------
    // Member variables
    //------------------------------------------------------------------
    mutable Mutex m_mutex;
    StringPool m_string_map;
};

//----------------------------------------------------------------------
// Frameworks and dylibs aren't supposed to have global C++
// initializers so we hide the string pool in a static function so
// that it will get initialized on the first call to this static
// function.
//
// Note, for now we make the string pool a pointer to the pool, because
// we can't guarantee that some objects won't get destroyed after the
// global destructor chain is run, and trying to make sure no destructors
// touch ConstStrings is difficult.  So we leak the pool instead.
//----------------------------------------------------------------------
static Pool &
StringPool()
{
    static std::once_flag g_pool_initialization_flag;
    static Pool *g_string_pool = NULL;

    std::call_once(g_pool_initialization_flag, [] () {
        g_string_pool = new Pool();
    });

    return *g_string_pool;
}

ConstString::ConstString (const char *cstr) :
    m_string (StringPool().GetConstCString (cstr))
{
}

ConstString::ConstString (const char *cstr, size_t cstr_len) :
    m_string (StringPool().GetConstCStringWithLength (cstr, cstr_len))
{
}

ConstString::ConstString (const llvm::StringRef &s) :
    m_string (StringPool().GetConstCStringWithLength (s.data(), s.size()))
{
}

bool
ConstString::operator < (const ConstString& rhs) const
{
    if (m_string == rhs.m_string)
        return false;

    llvm::StringRef lhs_string_ref (m_string, StringPool().GetConstCStringLength (m_string));
    llvm::StringRef rhs_string_ref (rhs.m_string, StringPool().GetConstCStringLength (rhs.m_string));

    // If both have valid C strings, then return the comparison
    if (lhs_string_ref.data() && rhs_string_ref.data())
        return lhs_string_ref < rhs_string_ref;

    // Else one of them was NULL, so if LHS is NULL then it is less than
    return lhs_string_ref.data() == NULL;
}

Stream&
lldb_private::operator << (Stream& s, const ConstString& str)
{
    const char *cstr = str.GetCString();
    if (cstr)
        s << cstr;

    return s;
}

size_t
ConstString::GetLength () const
{
    return StringPool().GetConstCStringLength (m_string);
}

int
ConstString::Compare (const ConstString& lhs, const ConstString& rhs)
{
    // If the iterators are the same, this is the same string
    const char *lhs_cstr = lhs.m_string;
    const char *rhs_cstr = rhs.m_string;
    if (lhs_cstr == rhs_cstr)
        return 0;
    if (lhs_cstr && rhs_cstr)
    {
        llvm::StringRef lhs_string_ref (lhs_cstr, StringPool().GetConstCStringLength (lhs_cstr));
        llvm::StringRef rhs_string_ref (rhs_cstr, StringPool().GetConstCStringLength (rhs_cstr));
        return lhs_string_ref.compare(rhs_string_ref);
    }

    if (lhs_cstr)
        return +1;  // LHS isn't NULL but RHS is
    else
        return -1;  // LHS is NULL but RHS isn't
}

void
ConstString::Dump(Stream *s, const char *fail_value) const
{
    if (s)
    {
        const char *cstr = AsCString (fail_value);
        if (cstr)
            s->PutCString (cstr);
    }
}

void
ConstString::DumpDebug(Stream *s) const
{
    const char *cstr = GetCString ();
    size_t cstr_len = GetLength();
    // Only print the parens if we have a non-NULL string
    const char *parens = cstr ? "\"" : "";
    s->Printf("%*p: ConstString, string = %s%s%s, length = %" PRIu64,
              static_cast<int>(sizeof(void*) * 2),
              static_cast<const void*>(this), parens, cstr, parens,
              static_cast<uint64_t>(cstr_len));
}

void
ConstString::SetCString (const char *cstr)
{
    m_string = StringPool().GetConstCString (cstr);
}

void
ConstString::SetString (const llvm::StringRef &s)
{
    m_string = StringPool().GetConstCStringWithLength (s.data(), s.size());
}

void
ConstString::SetCStringWithMangledCounterpart (const char *demangled, const ConstString &mangled)
{
    m_string = StringPool().GetConstCStringAndSetMangledCounterPart (demangled, mangled.m_string);
}

bool
ConstString::GetMangledCounterpart (ConstString &counterpart) const
{
    counterpart.m_string = StringPool().GetMangledCounterpart(m_string);
    return (bool)counterpart;
}

void
ConstString::SetCStringWithLength (const char *cstr, size_t cstr_len)
{
    m_string = StringPool().GetConstCStringWithLength(cstr, cstr_len);
}

void
ConstString::SetTrimmedCStringWithLength (const char *cstr, size_t cstr_len)
{
    m_string = StringPool().GetConstTrimmedCStringWithLength (cstr, cstr_len);
}

size_t
ConstString::StaticMemorySize()
{
    // Get the size of the static string pool
    return StringPool().MemorySize();
}
<|endoftext|>


<commit_before>#ifdef WIN32
#define _USE_MATH_DEFINES
#include <cmath>
#endif

#include "PhysicsObject.h"
#include <math.h>

namespace Physics
{

void Object::ApplyImpulse ( vec2 impulse )
{
    velocity += (impulse / mass);
}

void Object::ApplyAngularImpulse ( float impulse )
{
    angularVelocity += (impulse / mass);
}

void Object::SetVelocity ( vec2 velocityNew )
{
	velocity = velocityNew;
}

void Object::Init ()
{
	velocity.X() = 0;
	velocity.Y() = 0;
	angle = 0;
	angularVelocity = 0;
	torque = 0;
}

const float fluidDragRho = 1.204; // this is the density of air at 20 degrees celsius

void Object::Update ( float timestep, float friction )
{
    // step 1: apply resistive force
	vec2 dragForce = -velocity.UnitVector() * fluidDragRho * velocity.ModulusSquared() * /* (2.0f * M_PI * collisionRadius) */ friction;
	//ALASTAIR: what's this 2*pi*r stuff? It's what's causing the problem!
	//on second thought, why is there drag in space??
//	force += dragForce;
    // step 2: update velocity from force
    velocity += (force * timestep);
    // step 3: update position from velocity
    position += (velocity * timestep);
    // step 4: update angular velocity from torque
    angularVelocity += (torque * timestep);
    // step 5: update angle from angular velocity
    angle += (angularVelocity * timestep);
    // step 6: limit angle to 0...2pi
    if (angle > 2.0f*M_PI)
        angle = fmodf(angle, 2.0f*M_PI);
    while (angle < 0.0f)
        angle += 2.0f*M_PI;
    // step 7: clear torque and force
    torque = 0.0f;
    force = vec2(0.0f, 0.0f);
}

/*
obj1 is the ship or planet, while obj2 is the projectile (which has an insignificant radius)
*/
bool Object::Collision( vec2 obj1, vec2 obj2, float radius )
{
	if ( hypotf(obj1.X() - obj2.X(), obj1.Y() - obj2.Y()) <= radius)
	{
		return true;
	}
	return false;
}

/*
obj1 and obj2 both have radii (ship to ship, ship to planet collisions)
*/
bool Object::Collision( vec2 obj1, vec2 obj2, float radius1, float radius2 )
{
	if ( hypotf(obj1.X() - obj2.X(), obj1.Y() - obj2.Y()) <= (radius1 + radius2) * (radius1 + radius2))
	{
		return true;
	}
	return false;
}

}
<commit_msg>Fixed very frustrating bug in the collision detection system. Radar dots are now green.<commit_after>#ifdef WIN32
#define _USE_MATH_DEFINES
#include <cmath>
#endif

#include "PhysicsObject.h"
#include <math.h>

namespace Physics
{

void Object::ApplyImpulse ( vec2 impulse )
{
    velocity += (impulse / mass);
}

void Object::ApplyAngularImpulse ( float impulse )
{
    angularVelocity += (impulse / mass);
}

void Object::SetVelocity ( vec2 velocityNew )
{
	velocity = velocityNew;
}

void Object::Init ()
{
	velocity.X() = 0;
	velocity.Y() = 0;
	angle = 0;
	angularVelocity = 0;
	torque = 0;
}

const float fluidDragRho = 1.204; // this is the density of air at 20 degrees celsius

void Object::Update ( float timestep, float friction )
{
    // step 1: apply resistive force
	vec2 dragForce = -velocity.UnitVector() * fluidDragRho * velocity.ModulusSquared() * /* (2.0f * M_PI * collisionRadius) */ friction;
	//ALASTAIR: what's this 2*pi*r stuff? It's what's causing the problem!
	//on second thought, why is there drag in space??
//	force += dragForce;
    // step 2: update velocity from force
    velocity += (force * timestep);
    // step 3: update position from velocity
    position += (velocity * timestep);
    // step 4: update angular velocity from torque
    angularVelocity += (torque * timestep);
    // step 5: update angle from angular velocity
    angle += (angularVelocity * timestep);
    // step 6: limit angle to 0...2pi
    if (angle > 2.0f*M_PI)
        angle = fmodf(angle, 2.0f*M_PI);
    while (angle < 0.0f)
        angle += 2.0f*M_PI;
    // step 7: clear torque and force
    torque = 0.0f;
    force = vec2(0.0f, 0.0f);
}

/*
obj1 is the ship or planet, while obj2 is the projectile (which has an insignificant radius)
*/
bool Object::Collision( vec2 obj1, vec2 obj2, float radius )
{
	if ( hypotf(obj1.X() - obj2.X(), obj1.Y() - obj2.Y()) <= radius)
	{
		return true;
	}
	return false;
}

/*
obj1 and obj2 both have radii (ship to ship, ship to planet collisions)
*/
bool Object::Collision( vec2 obj1, vec2 obj2, float radius1, float radius2 )
{
	if ( hypotf(obj1.X() - obj2.X(), obj1.Y() - obj2.Y()) <= (radius1 + radius2))
	{
		return true;
	}
	return false;
}

}
<|endoftext|>


<commit_before>// Copyright (c) 2011 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 "printing/pdf_metafile_cg_mac.h"

#include "base/file_path.h"
#include "base/logging.h"
#include "base/mac/mac_util.h"
#include "base/mac/scoped_cftyperef.h"
#include "base/sys_string_conversions.h"
#include "base/threading/thread_local.h"
#include "ui/gfx/rect.h"
#include "ui/gfx/size.h"

using base::mac::ScopedCFTypeRef;

namespace {

// What is up with this ugly hack? <http://crbug.com/64641>, that's what.
// The bug: Printing certain PDFs crashes. The cause: When printing, the
// renderer process assembles pages one at a time, in PDF format, to send to the
// browser process. When printing a PDF, the PDF plugin returns output in PDF
// format. There is a bug in 10.5 and 10.6 (<rdar://9018916>,
// <http://www.openradar.me/9018916>) where reference counting is broken when
// drawing certain PDFs into PDF contexts. So at the high-level, a PdfMetafileCg
// is used to hold the destination context, and then about five layers down on
// the callstack, a PdfMetafileCg is used to hold the source PDF. If the source
// PDF is drawn into the destination PDF context and then released, accessing
// the destination PDF context will crash. So the outermost instantiation of
// PdfMetafileCg creates a pool for deeper instantiations to dump their used
// PDFs into rather than releasing them. When the top-level PDF is closed, then
// it's safe to clear the pool. A thread local is used to allow this to work in
// single-process mode. TODO(avi): This Apple bug appears fixed in 10.7; when
// 10.7 is the minimum required version for Chromium, remove this hack.

base::ThreadLocalPointer<struct __CFSet> thread_pdf_docs;

}  // namespace

namespace printing {

PdfMetafileCg::PdfMetafileCg()
    : page_is_open_(false),
      thread_pdf_docs_owned_(false) {
  if (!thread_pdf_docs.Get() && base::mac::IsOSSnowLeopardOrEarlier()) {
    thread_pdf_docs_owned_ = true;
    thread_pdf_docs.Set(CFSetCreateMutable(kCFAllocatorDefault,
                                           0,
                                           &kCFTypeSetCallBacks));
  }
}

PdfMetafileCg::~PdfMetafileCg() {
  DCHECK(CalledOnValidThread());
  if (pdf_doc_ && thread_pdf_docs.Get()) {
    // Transfer ownership to the pool.
    CFSetAddValue(thread_pdf_docs.Get(), pdf_doc_);
  }

  if (thread_pdf_docs_owned_) {
    CFRelease(thread_pdf_docs.Get());
    thread_pdf_docs.Set(NULL);
  }
}

bool PdfMetafileCg::Init() {
  // Ensure that Init hasn't already been called.
  DCHECK(!context_.get());
  DCHECK(!pdf_data_.get());

  pdf_data_.reset(CFDataCreateMutable(kCFAllocatorDefault, 0));
  if (!pdf_data_.get()) {
    LOG(ERROR) << "Failed to create pdf data for metafile";
    return false;
  }
  ScopedCFTypeRef<CGDataConsumerRef> pdf_consumer(
      CGDataConsumerCreateWithCFData(pdf_data_));
  if (!pdf_consumer.get()) {
    LOG(ERROR) << "Failed to create data consumer for metafile";
    pdf_data_.reset(NULL);
    return false;
  }
  context_.reset(CGPDFContextCreate(pdf_consumer, NULL, NULL));
  if (!context_.get()) {
    LOG(ERROR) << "Failed to create pdf context for metafile";
    pdf_data_.reset(NULL);
  }

  return true;
}

bool PdfMetafileCg::InitFromData(const void* src_buffer,
                                 uint32 src_buffer_size) {
  DCHECK(!context_.get());
  DCHECK(!pdf_data_.get());

  if (!src_buffer || src_buffer_size == 0) {
    return false;
  }

  pdf_data_.reset(CFDataCreateMutable(kCFAllocatorDefault, src_buffer_size));
  CFDataAppendBytes(pdf_data_, static_cast<const UInt8*>(src_buffer),
                    src_buffer_size);

  return true;
}

SkDevice* PdfMetafileCg::StartPageForVectorCanvas(
    int page_number, const gfx::Size& page_size, const gfx::Rect& content_area,
    const float& scale_factor) {
  NOTIMPLEMENTED();
  return NULL;
}

bool PdfMetafileCg::StartPage(const gfx::Size& page_size,
                              const gfx::Rect& content_area,
                              const float& scale_factor) {
  DCHECK(context_.get());
  DCHECK(!page_is_open_);

  double height = page_size.height();
  double width = page_size.width();

  CGRect bounds = CGRectMake(0, 0, width, height);
  CGContextBeginPage(context_, &bounds);
  page_is_open_ = true;
  CGContextSaveGState(context_);

  // Flip the context.
  CGContextTranslateCTM(context_, 0, height);
  CGContextScaleCTM(context_, scale_factor, -scale_factor);

  // Move to the context origin.
  CGContextTranslateCTM(context_, content_area.x(), content_area.y());

  return context_.get() != NULL;
}

bool PdfMetafileCg::FinishPage() {
  DCHECK(context_.get());
  DCHECK(page_is_open_);

  CGContextRestoreGState(context_);
  CGContextEndPage(context_);
  page_is_open_ = false;
  return true;
}

bool PdfMetafileCg::FinishDocument() {
  DCHECK(context_.get());
  DCHECK(!page_is_open_);

#ifndef NDEBUG
  // Check that the context will be torn down properly; if it's not, pdf_data_
  // will be incomplete and generate invalid PDF files/documents.
  if (context_.get()) {
    CFIndex extra_retain_count = CFGetRetainCount(context_.get()) - 1;
    if (extra_retain_count > 0) {
      LOG(ERROR) << "Metafile context has " << extra_retain_count
                 << " extra retain(s) on Close";
    }
  }
#endif
  CGPDFContextClose(context_.get());
  context_.reset(NULL);
  return true;
}

bool PdfMetafileCg::RenderPage(unsigned int page_number,
                               CGContextRef context,
                               const CGRect rect,
                               bool shrink_to_fit,
                               bool stretch_to_fit,
                               bool center_horizontally,
                               bool center_vertically) const {
  CGPDFDocumentRef pdf_doc = GetPDFDocument();
  if (!pdf_doc) {
    LOG(ERROR) << "Unable to create PDF document from data";
    return false;
  }
  CGPDFPageRef pdf_page = CGPDFDocumentGetPage(pdf_doc, page_number);
  CGRect source_rect = CGPDFPageGetBoxRect(pdf_page, kCGPDFMediaBox);
  float scaling_factor = 1.0;
  // See if we need to scale the output.
  bool scaling_needed =
      (shrink_to_fit && ((source_rect.size.width > rect.size.width) ||
                         (source_rect.size.height > rect.size.height))) ||
      (stretch_to_fit && (source_rect.size.width < rect.size.width) &&
          (source_rect.size.height < rect.size.height));
  if (scaling_needed) {
    float x_scaling_factor = rect.size.width / source_rect.size.width;
    float y_scaling_factor = rect.size.height / source_rect.size.height;
    if (x_scaling_factor > y_scaling_factor) {
      scaling_factor = y_scaling_factor;
    } else {
      scaling_factor = x_scaling_factor;
    }
  }
  // Some PDFs have a non-zero origin. Need to take that into account.
  float x_offset = rect.origin.x - (source_rect.origin.x * scaling_factor);
  float y_offset = rect.origin.y - (source_rect.origin.y * scaling_factor);

  if (center_vertically) {
    x_offset += (rect.size.width -
                     (source_rect.size.width * scaling_factor))/2;
  }
  if (center_horizontally) {
    y_offset += (rect.size.height -
                     (source_rect.size.height * scaling_factor))/2;
  } else {
    // Since 0 y begins at the bottom, we need to adjust so the output appears
    // nearer the top if we are not centering horizontally.
    y_offset += rect.size.height - (source_rect.size.height * scaling_factor);
  }
  CGContextSaveGState(context);
  CGContextTranslateCTM(context, x_offset, y_offset);
  CGContextScaleCTM(context, scaling_factor, scaling_factor);
  CGContextDrawPDFPage(context, pdf_page);
  CGContextRestoreGState(context);
  return true;
}

unsigned int PdfMetafileCg::GetPageCount() const {
  CGPDFDocumentRef pdf_doc = GetPDFDocument();
  return pdf_doc ? CGPDFDocumentGetNumberOfPages(pdf_doc) : 0;
}

gfx::Rect PdfMetafileCg::GetPageBounds(unsigned int page_number) const {
  CGPDFDocumentRef pdf_doc = GetPDFDocument();
  if (!pdf_doc) {
    LOG(ERROR) << "Unable to create PDF document from data";
    return gfx::Rect();
  }
  if (page_number > GetPageCount()) {
    LOG(ERROR) << "Invalid page number: " << page_number;
    return gfx::Rect();
  }
  CGPDFPageRef pdf_page = CGPDFDocumentGetPage(pdf_doc, page_number);
  CGRect page_rect = CGPDFPageGetBoxRect(pdf_page, kCGPDFMediaBox);
  return gfx::Rect(page_rect);
}

uint32 PdfMetafileCg::GetDataSize() const {
  // PDF data is only valid/complete once the context is released.
  DCHECK(!context_);

  if (!pdf_data_)
    return 0;
  return static_cast<uint32>(CFDataGetLength(pdf_data_));
}

bool PdfMetafileCg::GetData(void* dst_buffer, uint32 dst_buffer_size) const {
  // PDF data is only valid/complete once the context is released.
  DCHECK(!context_);
  DCHECK(pdf_data_);
  DCHECK(dst_buffer);
  DCHECK_GT(dst_buffer_size, 0U);

  uint32 data_size = GetDataSize();
  if (dst_buffer_size > data_size) {
    return false;
  }

  CFDataGetBytes(pdf_data_, CFRangeMake(0, dst_buffer_size),
                 static_cast<UInt8*>(dst_buffer));
  return true;
}

bool PdfMetafileCg::SaveTo(const FilePath& file_path) const {
  DCHECK(pdf_data_.get());
  DCHECK(!context_.get());

  std::string path_string = file_path.value();
  ScopedCFTypeRef<CFURLRef> path_url(CFURLCreateFromFileSystemRepresentation(
      kCFAllocatorDefault, reinterpret_cast<const UInt8*>(path_string.c_str()),
      path_string.length(), false));
  SInt32 error_code;
  CFURLWriteDataAndPropertiesToResource(path_url, pdf_data_, NULL, &error_code);
  return error_code == 0;
}

CGContextRef PdfMetafileCg::context() const {
  return context_.get();
}

CGPDFDocumentRef PdfMetafileCg::GetPDFDocument() const {
  // Make sure that we have data, and that it's not being modified any more.
  DCHECK(pdf_data_.get());
  DCHECK(!context_.get());

  if (!pdf_doc_.get()) {
    ScopedCFTypeRef<CGDataProviderRef> pdf_data_provider(
        CGDataProviderCreateWithCFData(pdf_data_));
    pdf_doc_.reset(CGPDFDocumentCreateWithProvider(pdf_data_provider));
  }
  return pdf_doc_.get();
}

}  // namespace printing
<commit_msg>Fixed bug in which the margin sizes vary (depending on the scale factor) while printing on the mac.<commit_after>// Copyright (c) 2011 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 "printing/pdf_metafile_cg_mac.h"

#include "base/file_path.h"
#include "base/logging.h"
#include "base/mac/mac_util.h"
#include "base/mac/scoped_cftyperef.h"
#include "base/sys_string_conversions.h"
#include "base/threading/thread_local.h"
#include "ui/gfx/rect.h"
#include "ui/gfx/size.h"

using base::mac::ScopedCFTypeRef;

namespace {

// What is up with this ugly hack? <http://crbug.com/64641>, that's what.
// The bug: Printing certain PDFs crashes. The cause: When printing, the
// renderer process assembles pages one at a time, in PDF format, to send to the
// browser process. When printing a PDF, the PDF plugin returns output in PDF
// format. There is a bug in 10.5 and 10.6 (<rdar://9018916>,
// <http://www.openradar.me/9018916>) where reference counting is broken when
// drawing certain PDFs into PDF contexts. So at the high-level, a PdfMetafileCg
// is used to hold the destination context, and then about five layers down on
// the callstack, a PdfMetafileCg is used to hold the source PDF. If the source
// PDF is drawn into the destination PDF context and then released, accessing
// the destination PDF context will crash. So the outermost instantiation of
// PdfMetafileCg creates a pool for deeper instantiations to dump their used
// PDFs into rather than releasing them. When the top-level PDF is closed, then
// it's safe to clear the pool. A thread local is used to allow this to work in
// single-process mode. TODO(avi): This Apple bug appears fixed in 10.7; when
// 10.7 is the minimum required version for Chromium, remove this hack.

base::ThreadLocalPointer<struct __CFSet> thread_pdf_docs;

}  // namespace

namespace printing {

PdfMetafileCg::PdfMetafileCg()
    : page_is_open_(false),
      thread_pdf_docs_owned_(false) {
  if (!thread_pdf_docs.Get() && base::mac::IsOSSnowLeopardOrEarlier()) {
    thread_pdf_docs_owned_ = true;
    thread_pdf_docs.Set(CFSetCreateMutable(kCFAllocatorDefault,
                                           0,
                                           &kCFTypeSetCallBacks));
  }
}

PdfMetafileCg::~PdfMetafileCg() {
  DCHECK(CalledOnValidThread());
  if (pdf_doc_ && thread_pdf_docs.Get()) {
    // Transfer ownership to the pool.
    CFSetAddValue(thread_pdf_docs.Get(), pdf_doc_);
  }

  if (thread_pdf_docs_owned_) {
    CFRelease(thread_pdf_docs.Get());
    thread_pdf_docs.Set(NULL);
  }
}

bool PdfMetafileCg::Init() {
  // Ensure that Init hasn't already been called.
  DCHECK(!context_.get());
  DCHECK(!pdf_data_.get());

  pdf_data_.reset(CFDataCreateMutable(kCFAllocatorDefault, 0));
  if (!pdf_data_.get()) {
    LOG(ERROR) << "Failed to create pdf data for metafile";
    return false;
  }
  ScopedCFTypeRef<CGDataConsumerRef> pdf_consumer(
      CGDataConsumerCreateWithCFData(pdf_data_));
  if (!pdf_consumer.get()) {
    LOG(ERROR) << "Failed to create data consumer for metafile";
    pdf_data_.reset(NULL);
    return false;
  }
  context_.reset(CGPDFContextCreate(pdf_consumer, NULL, NULL));
  if (!context_.get()) {
    LOG(ERROR) << "Failed to create pdf context for metafile";
    pdf_data_.reset(NULL);
  }

  return true;
}

bool PdfMetafileCg::InitFromData(const void* src_buffer,
                                 uint32 src_buffer_size) {
  DCHECK(!context_.get());
  DCHECK(!pdf_data_.get());

  if (!src_buffer || src_buffer_size == 0) {
    return false;
  }

  pdf_data_.reset(CFDataCreateMutable(kCFAllocatorDefault, src_buffer_size));
  CFDataAppendBytes(pdf_data_, static_cast<const UInt8*>(src_buffer),
                    src_buffer_size);

  return true;
}

SkDevice* PdfMetafileCg::StartPageForVectorCanvas(
    int page_number, const gfx::Size& page_size, const gfx::Rect& content_area,
    const float& scale_factor) {
  NOTIMPLEMENTED();
  return NULL;
}

bool PdfMetafileCg::StartPage(const gfx::Size& page_size,
                              const gfx::Rect& content_area,
                              const float& scale_factor) {
  DCHECK(context_.get());
  DCHECK(!page_is_open_);

  double height = page_size.height();
  double width = page_size.width();

  CGRect bounds = CGRectMake(0, 0, width, height);
  CGContextBeginPage(context_, &bounds);
  page_is_open_ = true;
  CGContextSaveGState(context_);

  // Move to the context origin.
  CGContextTranslateCTM(context_, content_area.x(), -content_area.y());

  // Flip the context.
  CGContextTranslateCTM(context_, 0, height);
  CGContextScaleCTM(context_, scale_factor, -scale_factor);

  return context_.get() != NULL;
}

bool PdfMetafileCg::FinishPage() {
  DCHECK(context_.get());
  DCHECK(page_is_open_);

  CGContextRestoreGState(context_);
  CGContextEndPage(context_);
  page_is_open_ = false;
  return true;
}

bool PdfMetafileCg::FinishDocument() {
  DCHECK(context_.get());
  DCHECK(!page_is_open_);

#ifndef NDEBUG
  // Check that the context will be torn down properly; if it's not, pdf_data_
  // will be incomplete and generate invalid PDF files/documents.
  if (context_.get()) {
    CFIndex extra_retain_count = CFGetRetainCount(context_.get()) - 1;
    if (extra_retain_count > 0) {
      LOG(ERROR) << "Metafile context has " << extra_retain_count
                 << " extra retain(s) on Close";
    }
  }
#endif
  CGPDFContextClose(context_.get());
  context_.reset(NULL);
  return true;
}

bool PdfMetafileCg::RenderPage(unsigned int page_number,
                               CGContextRef context,
                               const CGRect rect,
                               bool shrink_to_fit,
                               bool stretch_to_fit,
                               bool center_horizontally,
                               bool center_vertically) const {
  CGPDFDocumentRef pdf_doc = GetPDFDocument();
  if (!pdf_doc) {
    LOG(ERROR) << "Unable to create PDF document from data";
    return false;
  }
  CGPDFPageRef pdf_page = CGPDFDocumentGetPage(pdf_doc, page_number);
  CGRect source_rect = CGPDFPageGetBoxRect(pdf_page, kCGPDFMediaBox);
  float scaling_factor = 1.0;
  // See if we need to scale the output.
  bool scaling_needed =
      (shrink_to_fit && ((source_rect.size.width > rect.size.width) ||
                         (source_rect.size.height > rect.size.height))) ||
      (stretch_to_fit && (source_rect.size.width < rect.size.width) &&
          (source_rect.size.height < rect.size.height));
  if (scaling_needed) {
    float x_scaling_factor = rect.size.width / source_rect.size.width;
    float y_scaling_factor = rect.size.height / source_rect.size.height;
    if (x_scaling_factor > y_scaling_factor) {
      scaling_factor = y_scaling_factor;
    } else {
      scaling_factor = x_scaling_factor;
    }
  }
  // Some PDFs have a non-zero origin. Need to take that into account.
  float x_offset = rect.origin.x - (source_rect.origin.x * scaling_factor);
  float y_offset = rect.origin.y - (source_rect.origin.y * scaling_factor);

  if (center_vertically) {
    x_offset += (rect.size.width -
                     (source_rect.size.width * scaling_factor))/2;
  }
  if (center_horizontally) {
    y_offset += (rect.size.height -
                     (source_rect.size.height * scaling_factor))/2;
  } else {
    // Since 0 y begins at the bottom, we need to adjust so the output appears
    // nearer the top if we are not centering horizontally.
    y_offset += rect.size.height - (source_rect.size.height * scaling_factor);
  }
  CGContextSaveGState(context);
  CGContextTranslateCTM(context, x_offset, y_offset);
  CGContextScaleCTM(context, scaling_factor, scaling_factor);
  CGContextDrawPDFPage(context, pdf_page);
  CGContextRestoreGState(context);
  return true;
}

unsigned int PdfMetafileCg::GetPageCount() const {
  CGPDFDocumentRef pdf_doc = GetPDFDocument();
  return pdf_doc ? CGPDFDocumentGetNumberOfPages(pdf_doc) : 0;
}

gfx::Rect PdfMetafileCg::GetPageBounds(unsigned int page_number) const {
  CGPDFDocumentRef pdf_doc = GetPDFDocument();
  if (!pdf_doc) {
    LOG(ERROR) << "Unable to create PDF document from data";
    return gfx::Rect();
  }
  if (page_number > GetPageCount()) {
    LOG(ERROR) << "Invalid page number: " << page_number;
    return gfx::Rect();
  }
  CGPDFPageRef pdf_page = CGPDFDocumentGetPage(pdf_doc, page_number);
  CGRect page_rect = CGPDFPageGetBoxRect(pdf_page, kCGPDFMediaBox);
  return gfx::Rect(page_rect);
}

uint32 PdfMetafileCg::GetDataSize() const {
  // PDF data is only valid/complete once the context is released.
  DCHECK(!context_);

  if (!pdf_data_)
    return 0;
  return static_cast<uint32>(CFDataGetLength(pdf_data_));
}

bool PdfMetafileCg::GetData(void* dst_buffer, uint32 dst_buffer_size) const {
  // PDF data is only valid/complete once the context is released.
  DCHECK(!context_);
  DCHECK(pdf_data_);
  DCHECK(dst_buffer);
  DCHECK_GT(dst_buffer_size, 0U);

  uint32 data_size = GetDataSize();
  if (dst_buffer_size > data_size) {
    return false;
  }

  CFDataGetBytes(pdf_data_, CFRangeMake(0, dst_buffer_size),
                 static_cast<UInt8*>(dst_buffer));
  return true;
}

bool PdfMetafileCg::SaveTo(const FilePath& file_path) const {
  DCHECK(pdf_data_.get());
  DCHECK(!context_.get());

  std::string path_string = file_path.value();
  ScopedCFTypeRef<CFURLRef> path_url(CFURLCreateFromFileSystemRepresentation(
      kCFAllocatorDefault, reinterpret_cast<const UInt8*>(path_string.c_str()),
      path_string.length(), false));
  SInt32 error_code;
  CFURLWriteDataAndPropertiesToResource(path_url, pdf_data_, NULL, &error_code);
  return error_code == 0;
}

CGContextRef PdfMetafileCg::context() const {
  return context_.get();
}

CGPDFDocumentRef PdfMetafileCg::GetPDFDocument() const {
  // Make sure that we have data, and that it's not being modified any more.
  DCHECK(pdf_data_.get());
  DCHECK(!context_.get());

  if (!pdf_doc_.get()) {
    ScopedCFTypeRef<CGDataProviderRef> pdf_data_provider(
        CGDataProviderCreateWithCFData(pdf_data_));
    pdf_doc_.reset(CGPDFDocumentCreateWithProvider(pdf_data_provider));
  }
  return pdf_doc_.get();
}

}  // namespace printing
<|endoftext|>


<commit_before>#include "GameObject.h"
#include "Macros.h"

#include "Math\Matrix.h"

#include "Shader.h"
#include "Texture.h"
#include "Model.h"
#include "Camera.h"

#include <stdio.h>

#define GLEW_STATIC
#include <glew\glew.h>
#include <GLFW\glfw3.h>

GameObjectType GameObject::getType() const {
	return this->type;
}

const char* GameObject::getName() const {
	return this->name;
}

void GameObject::setModel( Model* const inModel ) {
	printf( "      Setting model...\n" );
	this->model = inModel;
}

void GameObject::setTexture( Texture* const inTexture ) {
	printf( "      Setting texture...\n" );
	this->texture = inTexture;
}

void GameObject::setShader( Shader* const inShader ) {
	printf( "      Setting shader...\n" );
	this->shader = inShader;
}

void GameObject::update( const double gameTime ) const {
	// Add update logic here
	UNUSED( gameTime );
}

void GameObject::draw(Camera* const camera) const {
	GLuint shaderProgram = this->shader->getShaderID();

	Matrix viewMatrix(camera->getViewMatrix());
	Matrix projectionMatrix(camera->getProjectionMatrix());

	glUseProgram(shaderProgram);

	auto modelMatrixLoc = glGetUniformLocation(shaderProgram, "modelMatrix");
	auto viewMatrixLoc = glGetUniformLocation(shaderProgram, "viewMatrix");
	auto projectionMatrixLoc = glGetUniformLocation(shaderProgram, "projectionMatrix");

	// Since the matrix class has an overloaded 'double *' operator to transparently
	// cast to a c-style array, we can easily send the matrix to OpenGL just by putting
	// the matrix object in the last parameter!
	glUniformMatrix4fv(modelMatrixLoc, 1, false, this->model->getModelMatrix()->AsFloatArray());
	glUniformMatrix4fv(viewMatrixLoc, 1, false, viewMatrix);
	glUniformMatrix4fv(projectionMatrixLoc, 1, false, projectionMatrix);

	auto cameraPosLoc = glGetUniformLocation(shaderProgram, "cameraPos");

	glUniform4f(cameraPosLoc, camera->getPosition()[0], camera->getPosition()[1], camera->getPosition()[2], camera->getPosition()[3]);

	auto specColorLoc = glGetUniformLocation(shaderProgram, "specularColor");
	auto shinyLoc = glGetUniformLocation(shaderProgram, "shininess");

	glUniform4f(specColorLoc, 1, 1, 1, 1);
	glUniform1f(shinyLoc, 50);

	// TEXTURES
	glBindTexture(GL_TEXTURE_2D, textureID);

	auto vertPosLoc = glGetAttribLocation(shaderProgram, "vertexPos");
	auto vertColorLoc = glGetAttribLocation(shaderProgram, "vertexColor");
	auto vertNormalLoc = glGetAttribLocation(shaderProgram, "vertexNormal");
	auto uvLoc = glGetAttribLocation(shaderProgram, "UV");

	glBindBuffer(GL_ARRAY_BUFFER, this->vertex_buffer);

	glVertexAttribPointer(vertPosLoc, 4, GL_FLOAT, false, sizeof(vert), static_cast< void * >(nullptr));
	glEnableVertexAttribArray(vertPosLoc);

	glVertexAttribPointer(vertColorLoc, 4, GL_FLOAT, false, sizeof(vert), reinterpret_cast< void * >(sizeof(point)));
	glEnableVertexAttribArray(vertColorLoc);

	glVertexAttribPointer(vertNormalLoc, 4, GL_FLOAT, false, sizeof(vert), reinterpret_cast< void * >(2 * sizeof(point)));
	glEnableVertexAttribArray(vertNormalLoc);

	glVertexAttribPointer(uvLoc, 4, GL_FLOAT, false, sizeof(vert), reinterpret_cast< void * >(2 * sizeof(point) + sizeof(vector)));
	glEnableVertexAttribArray(uvLoc);

	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, this->index_buffer);
	glDrawElements(GL_TRIANGLES, this->p_model->getNumFaces(), GL_UNSIGNED_INT, nullptr);
}

GameObject::GameObject( const GameObjectType inType, const char* inName )
	: type( inType ), name( inName ), model( nullptr ), texture( nullptr ), shader( nullptr ) {
	printf( "    Creating game object...\n" );
}

GameObject::~GameObject() { }<commit_msg>Render: - Refactor gameObject to prep for rendering<commit_after>#include "GameObject.h"
#include "Macros.h"

#include "Math\Matrix.h"

#include "Vertex.h"
#include "Shader.h"
#include "Texture.h"
#include "Model.h"
#include "Camera.h"

#include <stdio.h>

#define GLEW_STATIC
#include <glew\glew.h>
#include <GLFW\glfw3.h>

GameObjectType GameObject::getType() const {
	return this->type;
}

const char* GameObject::getName() const {
	return this->name;
}

void GameObject::setModel( Model* const inModel ) {
	printf( "      Setting model...\n" );
	this->model = inModel;
}

void GameObject::setTexture( Texture* const inTexture ) {
	printf( "      Setting texture...\n" );
	this->texture = inTexture;
}

void GameObject::setShader( Shader* const inShader ) {
	printf( "      Setting shader...\n" );
	this->shader = inShader;
}

void GameObject::update( const double gameTime ) const {
	// Add update logic here
	UNUSED( gameTime );
}

void GameObject::draw(Camera* const camera) const {
	GLuint shaderProgram = this->shader->getShaderID();
	GLuint textureID = this->texture->getTextureID();

	Matrix viewMatrix(camera->getViewMatrix());
	Matrix projectionMatrix(camera->getProjectionMatrix());

	glUseProgram(shaderProgram);

	auto modelMatrixLoc = glGetUniformLocation(shaderProgram, "modelMatrix");
	auto viewMatrixLoc = glGetUniformLocation(shaderProgram, "viewMatrix");
	auto projectionMatrixLoc = glGetUniformLocation(shaderProgram, "projectionMatrix");

	// Since the matrix class has an overloaded 'double *' operator to transparently
	// cast to a c-style array, we can easily send the matrix to OpenGL just by putting
	// the matrix object in the last parameter!
	glUniformMatrix4fv(modelMatrixLoc, 1, false, this->model->getModelMatrix()->AsFloatArray());
	glUniformMatrix4fv(viewMatrixLoc, 1, false, viewMatrix);
	glUniformMatrix4fv(projectionMatrixLoc, 1, false, projectionMatrix);

	auto cameraPosLoc = glGetUniformLocation(shaderProgram, "cameraPos");

	glUniform4f(cameraPosLoc, camera->getPosition()[x], camera->getPosition()[y], camera->getPosition()[z], camera->getPosition()[w]);

	auto specColorLoc = glGetUniformLocation(shaderProgram, "specularColor");
	auto shinyLoc = glGetUniformLocation(shaderProgram, "shininess");

	glUniform4f(specColorLoc, 1, 1, 1, 1);
	glUniform1f(shinyLoc, 50);

	// TEXTURES
	glBindTexture(GL_TEXTURE_2D, textureID);

	auto vertPosLoc = glGetAttribLocation(shaderProgram, "vertexPos");
	auto vertColorLoc = glGetAttribLocation(shaderProgram, "vertexColor");
	auto vertNormalLoc = glGetAttribLocation(shaderProgram, "vertexNormal");
	auto uvLoc = glGetAttribLocation(shaderProgram, "UV");

	glBindBuffer(GL_ARRAY_BUFFER, this->model->getVboVerts());

	glVertexAttribPointer(vertPosLoc, 4, GL_FLOAT, false, sizeof(Vertex), static_cast< void * >(nullptr));
	glEnableVertexAttribArray(vertPosLoc);

	glVertexAttribPointer(vertNormalLoc, 4, GL_FLOAT, false, sizeof(Vertex), reinterpret_cast< void * >(sizeof(Vect)));
	glEnableVertexAttribArray(vertNormalLoc);

	glVertexAttribPointer(vertColorLoc, 4, GL_FLOAT, false, sizeof(Vertex), reinterpret_cast< void * >(2 * sizeof(Vect)));
	glEnableVertexAttribArray(vertColorLoc);

	glVertexAttribPointer(uvLoc, 4, GL_FLOAT, false, sizeof(Vertex), reinterpret_cast< void * >(3 * sizeof(Vect)));
	glEnableVertexAttribArray(uvLoc);

	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, this->model->getVboFaces());
	glDrawElements(GL_TRIANGLES, this->model->getNumFaces(), GL_UNSIGNED_INT, nullptr);
}

GameObject::GameObject( const GameObjectType inType, const char* inName )
	: type( inType ), name( inName ), model( nullptr ), texture( nullptr ), shader( nullptr ) {
	printf( "    Creating game object...\n" );
}

GameObject::~GameObject() { }<|endoftext|>


<commit_before>/*
    Copyright (C) 2009 Matthias Kretz <kretz@kde.org>

    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License as
    published by the Free Software Foundation; either version 2 of
    the License, or (at your option) version 3.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

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

*/

#include <unistd.h>
#include <sched.h>
#include <signal.h>
#include <cstdio>
#include <cstring>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/select.h>

int main(int, char **argv)
{
  sched_param param;
  sched_getparam( 0, &param );
  param.sched_priority = 2;
  if ( 0 != sched_setscheduler( 0, SCHED_FIFO, &param ) ) {
    perror( "1. fail" );
  }

  const pid_t pid = fork();
  if ( pid == 0 ) {
    // I'm the child

    // make the child realtime prio, but less than the parent
    sched_param param2;
    sched_getparam( 0, &param2 );
    param2.sched_priority = 1;
    if ( 0 != sched_setscheduler( 0, SCHED_FIFO, &param2 ) ) {
      perror( "2. fail" );
    } else {
      printf("running %s with SCHED_FIFO\n", argv[0]);
    }

    // drop privileges
    if ( geteuid() != getuid() ) {
      seteuid( getuid() );
      if ( geteuid() != getuid() ) {
        return -1;
      }

      execv( argv[0], argv );
      perror( argv[0] );
      return -1;
    }
    fprintf(stderr, "you need to make benchmark suid root\n");
    return -1;
  }

  timeval timeout;
  for ( int i = 0; i < 600; ++i ) {
    timeout.tv_sec =  1;
    timeout.tv_usec = 0;
    select( 0, 0, 0, 0, &timeout );
    if ( pid == waitpid( pid, 0, WNOHANG ) ) {
      return 0;
    }
  }

  printf("%s took too long (> 10 min) and was killed\n", argv[0]);
  kill( pid, SIGKILL );

  return -1;
}
<commit_msg>the kill timeout is not long enough for memio to finish on my laptop, give it another 3 minutes<commit_after>/*
    Copyright (C) 2009 Matthias Kretz <kretz@kde.org>

    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License as
    published by the Free Software Foundation; either version 2 of
    the License, or (at your option) version 3.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

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

*/

#include <unistd.h>
#include <sched.h>
#include <signal.h>
#include <cstdio>
#include <cstring>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/select.h>

int main(int, char **argv)
{
  sched_param param;
  sched_getparam( 0, &param );
  param.sched_priority = 2;
  if ( 0 != sched_setscheduler( 0, SCHED_FIFO, &param ) ) {
    perror( "1. fail" );
  }

  const pid_t pid = fork();
  if ( pid == 0 ) {
    // I'm the child

    // make the child realtime prio, but less than the parent
    sched_param param2;
    sched_getparam( 0, &param2 );
    param2.sched_priority = 1;
    if ( 0 != sched_setscheduler( 0, SCHED_FIFO, &param2 ) ) {
      perror( "2. fail" );
    } else {
      printf("running %s with SCHED_FIFO\n", argv[0]);
    }

    // drop privileges
    if ( geteuid() != getuid() ) {
      seteuid( getuid() );
      if ( geteuid() != getuid() ) {
        return -1;
      }

      execv( argv[0], argv );
      perror( argv[0] );
      return -1;
    }
    fprintf(stderr, "you need to make benchmark suid root\n");
    return -1;
  }

  timeval timeout;
  for ( int i = 0; i < 780; ++i ) {
    timeout.tv_sec =  1;
    timeout.tv_usec = 0;
    select( 0, 0, 0, 0, &timeout );
    if ( pid == waitpid( pid, 0, WNOHANG ) ) {
      return 0;
    }
  }

  printf("%s took too long (> 13 min) and was killed\n", argv[0]);
  kill( pid, SIGKILL );

  return -1;
}
<|endoftext|>