<commit_before>#include "MinVRSettings.h"
#include <stdlib.h>
#include <cstdlib>

string
MinVRSettings::getValueString(string settingName)
{
    map<string, TYPE_ID>::iterator i;
    i = keyword_to_type.find(settingName);
    if (i == keyword_to_type.end())
    {
	// translate input into a string
	string value_column = settingsToValues[settingName];

	// save it in the keyword_to_type lookup
	keyword_to_type[settingName] = STRING;

	// save it in the settingValues map
	settingValues[settingName] = value_column;
	return value_column;
    }
    else
    {
	// return saved value
	TYPE_ID t = i->second;
	if (t == STRING)
	{
	    return settingValues[settingName];
	}
	else
	{
	    cout << " getValueString (" << settingName << ") is not a string."
		 << endl;
	    //exit(1);
	}

    }
    return string();
}

int
MinVRSettings::getValueStringVector(string settingName,vector<string>& stringValues)
{
    //
}

int
MinVRSettings::getValueInt(string settingName)
{
    map<string, TYPE_ID>::iterator i;
    i = keyword_to_type.find(settingName);
    if (i == keyword_to_type.end())
    {
	// translate input into a string
	string value_column = settingsToValues[settingName];

	// save it in the keyword_to_type lookup
	keyword_to_type[settingName] = INT;

	int tmp_int = atoi(value_column.c_str());
	// save it in the settingValues map
	settingIntValues[settingName] = tmp_int;
	return tmp_int;
    }
    else
    {
	// return saved value
	TYPE_ID t = i->second;
	if (t == INT)
	{
	    return settingIntValues[settingName];
	}
	else
	{
	    cout << " getValueInt (" << settingName << ") is not an Int."
		 << endl;
	    //exit(1);
	}

    }
    return 1;
}

int
MinVRSettings::getValueIntVector(string settingName,vector<int>& intValues)
{
    //
    map<string, TYPE_ID>::iterator i;
    i = keyword_to_type.find(settingName);
    if (i == keyword_to_type.end())
    {
        // translate input into a string
        string value_column = settingsToValues[settingName];

        // save it in the keyword_to_type lookup
        keyword_to_type[settingName] = VEC_INT;

        intValues = string_int_vec(value_column);
        // save it in the settingValues map
        settingIntValuesVector[settingName] = intValues;
        return intValues.size();
    }
    else
    {
        // return saved value
        TYPE_ID t = i->second;
        if (t == VEC_INT)
        {
            intValues = settingIntValuesVector[settingName];
            return intValues.size();
        }
        else
        {
            cout << " getValueIntVector (" << settingName << ",intValues) is not a vector of integers."
                 << endl;
            //exit(1);
        }
    }
    return 0;
}

vector<int> MinVRSettings::string_int_vec(string value_column)
{
    //
    char * pch;
    vector<int> tmp;
    char* str=(char*)value_column.c_str();
    pch = strtok (str," \t,()");
    while (pch != NULL)
    {
        //printf ("%s\n",pch);
        tmp.push_back(atoi(pch));
        pch = strtok (NULL, " \t,()");
    }
    return tmp;
}

float
MinVRSettings::getValueFloat(string settingName)
{
    map<string, TYPE_ID>::iterator i;
    i = keyword_to_type.find(settingName);
    if (i == keyword_to_type.end())
    {
	// translate input into a string
	string value_column = settingsToValues[settingName];

	// save it in the keyword_to_type lookup
	keyword_to_type[settingName] = FLOAT;

	float tmp_float = (float)strtod(value_column.c_str(),NULL);
	// save it in the settingValues map
	settingFloatValues[settingName] = tmp_float;
	return tmp_float;
    }
    else
    {
	// return saved value
	TYPE_ID t = i->second;
	if (t == FLOAT)
	{
	    return settingFloatValues[settingName];
	}
	else
	{
	    cout << " getValueFloat (" << settingName << ") is not an Float."
		 << endl;
	    //exit(1);
	}

    }
    return 1;
}

int
MinVRSettings::getValueFloatVector(string settingName,vector<float>& floatValues)
{
    //
    map<string, TYPE_ID>::iterator i;
    i = keyword_to_type.find(settingName);
    if (i == keyword_to_type.end())
    {
        // translate input into a string
        string value_column = settingsToValues[settingName];

        // save it in the keyword_to_type lookup
        keyword_to_type[settingName] = VEC_FLOAT;

        floatValues = string_float_vec(value_column);
        // save it in the settingValues map
        settingFloatValuesVector[settingName] = floatValues;
        return floatValues.size();
    }
    else
    {
        // return saved value
        TYPE_ID t = i->second;
        if (t == VEC_FLOAT)
        {
            floatValues = settingFloatValuesVector[settingName];
            return floatValues.size();
        }
        else
        {
            cout << " getValueFloatVector (" << settingName << ",floatValues) is not a vector of floats."
                 << endl;
            //exit(1);
        }
    }
    return 0;
}

vector<float> MinVRSettings::string_float_vec(string value_column)
{
    //
    char * pch;
    vector<float> tmp;
    char* str=(char*)value_column.c_str();
    pch = strtok (str," \t,()");
    while (pch != NULL)
    {
        //printf ("%s\n",pch);
        tmp.push_back(strtod(pch,NULL));
        pch = strtok (NULL, " \t,()");
    }
    return tmp;
}

int
MinVRSettings::setValueString(string settingName, string settingValue)
{
    settingValues[settingName]=settingValue;
    return 0;
}

int
MinVRSettings::setValueInt(string settingName, int settingValue)
{
    settingIntValues[settingName]=settingValue;
    return 0;
}

int
MinVRSettings::setValueFloat(string settingName, float settingValue)
{
    settingFloatValues[settingName]=settingValue;
    return 0;
}

vector<std::string> MinVRSettings::string_float_vec_test(const std::string m_string)
{
    //
    char * pch;
    vector<string> tmp;
    char* str=(char*)m_string.c_str();
//    printf ("Splitting string \"%s\" into tokens:\n",str);
    pch = strtok (str," \t,()");
    while (pch != NULL)
    {
        //printf ("%s\n",pch);
        tmp.push_back(string(pch));
        pch = strtok (NULL, " \t,()");
    }
    return tmp;
}

int MinVRSettings::readValues(string settingFileName)
{
    // Read config settings from a file
    ifstream file(settingFileName.c_str());
    int i;
    char *pch, *str;
    string line, the_key, the_val;

    if (file.is_open())
    {
        while (!file.eof())
        {
            getline(file, line);
            i = line.find("#");
            if (i>=0)
                continue;

            str=(char*)line.c_str();
            pch = strtok (str," \t,()");
            if(pch)
            {
                the_key = string(pch);
                pch = strtok (NULL, "");
                if(pch)
                {
                    the_val = string(pch);
                    cout << "the_key = " << the_key << ", the_val = " << the_val << endl;
                    settingsToValues[the_key] = the_val;
                }
                else
                    settingsToValues[the_key] = "";
            }
        }
    }
    else
    {
        cout << "File " << settingFileName << "cannot be openned" << endl;
        return 1;
    }
    return 0;
}
<commit_msg>change to allow compilation under MSVC10<commit_after>#include "MinVRSettings.h"
#include <stdlib.h>
#include <cstdlib>

string
MinVRSettings::getValueString(string settingName)
{
    map<string, TYPE_ID>::iterator i;
    i = keyword_to_type.find(settingName);
    if (i == keyword_to_type.end())
    {
	// translate input into a string
	string value_column = settingsToValues[settingName];

	// save it in the keyword_to_type lookup
	keyword_to_type[settingName] = STRING;

	// save it in the settingValues map
	settingValues[settingName] = value_column;
	return value_column;
    }
    else
    {
	// return saved value
	TYPE_ID t = i->second;
	if (t == STRING)
	{
	    return settingValues[settingName];
	}
	else
	{
	    cout << " getValueString (" << settingName << ") is not a string."
		 << endl;
	    //exit(1);
	}

    }
    return string();
}

int    ls

MinVRSettings::getValueStringVector(string settingName,vector<string>& stringValues)
{
    //
	return 0;
}

int
MinVRSettings::getValueInt(string settingName)
{
    map<string, TYPE_ID>::iterator i;
    i = keyword_to_type.find(settingName);
    if (i == keyword_to_type.end())
    {
	// translate input into a string
	string value_column = settingsToValues[settingName];

	// save it in the keyword_to_type lookup
	keyword_to_type[settingName] = INT;

	int tmp_int = atoi(value_column.c_str());
	// save it in the settingValues map
	settingIntValues[settingName] = tmp_int;
	return tmp_int;
    }
    else
    {
	// return saved value
	TYPE_ID t = i->second;
	if (t == INT)
	{
	    return settingIntValues[settingName];
	}
	else
	{
	    cout << " getValueInt (" << settingName << ") is not an Int."
		 << endl;
	    //exit(1);
	}

    }
    return 1;
}

int
MinVRSettings::getValueIntVector(string settingName,vector<int>& intValues)
{
    //
    map<string, TYPE_ID>::iterator i;
    i = keyword_to_type.find(settingName);
    if (i == keyword_to_type.end())
    {
        // translate input into a string
        string value_column = settingsToValues[settingName];

        // save it in the keyword_to_type lookup
        keyword_to_type[settingName] = VEC_INT;

        intValues = string_int_vec(value_column);
        // save it in the settingValues map
        settingIntValuesVector[settingName] = intValues;
        return intValues.size();
    }
    else
    {
        // return saved value
        TYPE_ID t = i->second;
        if (t == VEC_INT)
        {
            intValues = settingIntValuesVector[settingName];
            return intValues.size();
        }
        else
        {
            cout << " getValueIntVector (" << settingName << ",intValues) is not a vector of integers."
                 << endl;
            //exit(1);
        }
    }
    return 0;
}

vector<int> MinVRSettings::string_int_vec(string value_column)
{
    //
    char * pch;
    vector<int> tmp;
    char* str=(char*)value_column.c_str();
    pch = strtok (str," \t,()");
    while (pch != NULL)
    {
        //printf ("%s\n",pch);
        tmp.push_back(atoi(pch));
        pch = strtok (NULL, " \t,()");
    }
    return tmp;
}

float
MinVRSettings::getValueFloat(string settingName)
{
    map<string, TYPE_ID>::iterator i;
    i = keyword_to_type.find(settingName);
    if (i == keyword_to_type.end())
    {
	// translate input into a string
	string value_column = settingsToValues[settingName];

	// save it in the keyword_to_type lookup
	keyword_to_type[settingName] = FLOAT;

	float tmp_float = (float)strtod(value_column.c_str(),NULL);
	// save it in the settingValues map
	settingFloatValues[settingName] = tmp_float;
	return tmp_float;
    }
    else
    {
	// return saved value
	TYPE_ID t = i->second;
	if (t == FLOAT)
	{
	    return settingFloatValues[settingName];
	}
	else
	{
	    cout << " getValueFloat (" << settingName << ") is not an Float."
		 << endl;
	    //exit(1);
	}

    }
    return 1;
}

int
MinVRSettings::getValueFloatVector(string settingName,vector<float>& floatValues)
{
    //
    map<string, TYPE_ID>::iterator i;
    i = keyword_to_type.find(settingName);
    if (i == keyword_to_type.end())
    {
        // translate input into a string
        string value_column = settingsToValues[settingName];

        // save it in the keyword_to_type lookup
        keyword_to_type[settingName] = VEC_FLOAT;

        floatValues = string_float_vec(value_column);
        // save it in the settingValues map
        settingFloatValuesVector[settingName] = floatValues;
        return floatValues.size();
    }
    else
    {
        // return saved value
        TYPE_ID t = i->second;
        if (t == VEC_FLOAT)
        {
            floatValues = settingFloatValuesVector[settingName];
            return floatValues.size();
        }
        else
        {
            cout << " getValueFloatVector (" << settingName << ",floatValues) is not a vector of floats."
                 << endl;
            //exit(1);
        }
    }
    return 0;
}

vector<float> MinVRSettings::string_float_vec(string value_column)
{
    //
    char * pch;
    vector<float> tmp;
    char* str=(char*)value_column.c_str();
    pch = strtok (str," \t,()");
    while (pch != NULL)
    {
        //printf ("%s\n",pch);
        tmp.push_back(strtod(pch,NULL));
        pch = strtok (NULL, " \t,()");
    }
    return tmp;
}

int
MinVRSettings::setValueString(string settingName, string settingValue)
{
    settingValues[settingName]=settingValue;
    return 0;
}

int
MinVRSettings::setValueInt(string settingName, int settingValue)
{
    settingIntValues[settingName]=settingValue;
    return 0;
}

int
MinVRSettings::setValueFloat(string settingName, float settingValue)
{
    settingFloatValues[settingName]=settingValue;
    return 0;
}

vector<std::string> MinVRSettings::string_float_vec_test(const std::string m_string)
{
    //
    char * pch;
    vector<string> tmp;
    char* str=(char*)m_string.c_str();
//    printf ("Splitting string \"%s\" into tokens:\n",str);
    pch = strtok (str," \t,()");
    while (pch != NULL)
    {
        //printf ("%s\n",pch);
        tmp.push_back(string(pch));
        pch = strtok (NULL, " \t,()");
    }
    return tmp;
}

int MinVRSettings::readValues(string settingFileName)
{
    // Read config settings from a file
    ifstream file(settingFileName.c_str());
    int i;
    char *pch, *str;
    string line, the_key, the_val;

    if (file.is_open())
    {
        while (!file.eof())
        {
            getline(file, line);
            i = line.find("#");
            if (i>=0)
                continue;

            str=(char*)line.c_str();
            pch = strtok (str," \t,()");
            if(pch)
            {
                the_key = string(pch);
                pch = strtok (NULL, "");
                if(pch)
                {
                    the_val = string(pch);
                    cout << "the_key = " << the_key << ", the_val = " << the_val << endl;
                    settingsToValues[the_key] = the_val;
                }
                else
                    settingsToValues[the_key] = "";
            }
        }
    }
    else
    {
        cout << "File " << settingFileName << "cannot be openned" << endl;
        return 1;
    }
    return 0;
}
<|endoftext|>


<commit_before>// Copyright (C) 2017 Elviss Strazdins
// This file is part of the Ouzel engine.

#include "SceneManager.h"
#include "Scene.h"
#include "core/Engine.h"
#include "Node.h"

namespace ouzel
{
    namespace scene
    {
        SceneManager::SceneManager()
        {
        }

        SceneManager::~SceneManager()
        {
        }

        void SceneManager::setScene(Scene* scene)
        {
            if (scene)
            {
                if (scene->sceneManger) scene->sceneManger->removeScene(scene);

                scene->sceneManger = this;

                scenes.push_back(scene);
            }
        }

        void SceneManager::setScene(std::unique_ptr<Scene>&& scene)
        {
            setScene(scene.get());
            ownedScenes.push_back(std::forward<std::unique_ptr<Scene>>(scene));
        }

        bool SceneManager::removeScene(Scene* scene)
        {
            bool result = false;

            std::vector<Scene*>::iterator sceneIterator = std::find(scenes.begin(), scenes.end(), scene);

            if (sceneIterator != scenes.end())
            {
                if (scene->entered) scene->leave();
                scene->sceneManger = nullptr;
                scenes.erase(sceneIterator);

                result = true;
            }

            std::vector<std::unique_ptr<Scene>>::iterator ownedIterator = std::find_if(ownedScenes.begin(), ownedScenes.end(), [scene](const std::unique_ptr<Scene>& other) {
                return other.get() == scene;
            });

            if (ownedIterator != ownedScenes.end())
            {
                ownedScenes.erase(ownedIterator);
            }

            return result;
        }

        void SceneManager::draw()
        {
            while (scenes.size() > 1)
            {
                removeScene(scenes.front());
            }

            if (!scenes.empty())
            {
                Scene* scene = scenes.back();
                if (!scene->entered) scene->enter();
                scene->draw();
            }
        }
    } // namespace scene
} // namespace ouzel
<commit_msg>Add missing algorithm include<commit_after>// Copyright (C) 2017 Elviss Strazdins
// This file is part of the Ouzel engine.

#include <algorithm>
#include "SceneManager.h"
#include "Scene.h"
#include "core/Engine.h"
#include "Node.h"

namespace ouzel
{
    namespace scene
    {
        SceneManager::SceneManager()
        {
        }

        SceneManager::~SceneManager()
        {
        }

        void SceneManager::setScene(Scene* scene)
        {
            if (scene)
            {
                if (scene->sceneManger) scene->sceneManger->removeScene(scene);

                scene->sceneManger = this;

                scenes.push_back(scene);
            }
        }

        void SceneManager::setScene(std::unique_ptr<Scene>&& scene)
        {
            setScene(scene.get());
            ownedScenes.push_back(std::forward<std::unique_ptr<Scene>>(scene));
        }

        bool SceneManager::removeScene(Scene* scene)
        {
            bool result = false;

            std::vector<Scene*>::iterator sceneIterator = std::find(scenes.begin(), scenes.end(), scene);

            if (sceneIterator != scenes.end())
            {
                if (scene->entered) scene->leave();
                scene->sceneManger = nullptr;
                scenes.erase(sceneIterator);

                result = true;
            }

            std::vector<std::unique_ptr<Scene>>::iterator ownedIterator = std::find_if(ownedScenes.begin(), ownedScenes.end(), [scene](const std::unique_ptr<Scene>& other) {
                return other.get() == scene;
            });

            if (ownedIterator != ownedScenes.end())
            {
                ownedScenes.erase(ownedIterator);
            }

            return result;
        }

        void SceneManager::draw()
        {
            while (scenes.size() > 1)
            {
                removeScene(scenes.front());
            }

            if (!scenes.empty())
            {
                Scene* scene = scenes.back();
                if (!scene->entered) scene->enter();
                scene->draw();
            }
        }
    } // namespace scene
} // namespace ouzel
<|endoftext|>


<commit_before>/**************************************************************************
 *
 * Copyright 2011 Jose Fonseca
 * All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 *
 **************************************************************************/

#include "glproc.hpp"

#if !defined(_WIN32)
#include <unistd.h> // for symlink
#include <dlfcn.h>
#endif

/*
 * Handle to the true OpenGL library.
 */
#if defined(_WIN32)
HINSTANCE __libGlHandle = NULL;
#else
void *__libGlHandle = NULL;
#endif

#if defined(_WIN32)

void *
__getPublicProcAddress(const char *procName)
{
    if (!__libGlHandle) {
        char szDll[MAX_PATH] = {0};

        if (!GetSystemDirectoryA(szDll, MAX_PATH)) {
            return NULL;
        }

        strcat(szDll, "\\\\opengl32.dll");

        __libGlHandle = LoadLibraryA(szDll);
        if (!__libGlHandle) {
            os::log("apitrace: error: couldn't load %s\n", szDll);
            return NULL;
        }
    }

    return (void *)GetProcAddress(__libGlHandle, procName);
}

void *
__getPrivateProcAddress(const char *procName) {
    return (void *)__wglGetProcAddress(procName);
}

#elif defined(__APPLE__)

/*
 * Path to the true OpenGL framework
 */
static const char *libgl_filename = "/System/Library/Frameworks/OpenGL.framework/OpenGL";

/*
 * Lookup a libGL symbol
 */
void * __libgl_sym(const char *symbol)
{
    void *result;

    if (!__libGlHandle) {
        /*
         * Unfortunately we can't just dlopen the true dynamic library because
         * DYLD_LIBRARY_PATH/DYLD_FRAMEWORK_PATH take precedence, even for
         * absolute paths.  So we create a temporary symlink, and dlopen that
         * instead.
         */

        char temp_filename[] = "/tmp/tmp.XXXXXX";

        if (mktemp(temp_filename) != NULL) {
            if (symlink(libgl_filename, temp_filename) == 0) {
                __libGlHandle = dlopen(temp_filename, RTLD_LOCAL | RTLD_NOW | RTLD_FIRST);
                remove(temp_filename);
            }
        }

        if (!__libGlHandle) {
            os::log("apitrace: error: couldn't load %s\n", libgl_filename);
            os::abort();
            return NULL;
        }
    }

    result = dlsym(__libGlHandle, symbol);

#ifndef RETRACE
    if (result == dlsym(RTLD_SELF, symbol)) {
        os::log("apitrace: error: symbol lookup recursion\n");
        os::abort();
        return NULL;
    }
#endif

    return result;
}

void *
__getPublicProcAddress(const char *procName)
{
    return __libgl_sym(procName);
}

void *
__getPrivateProcAddress(const char *procName)
{
    return __libgl_sym(procName);
}

#else

/*
 * Invoke the true dlopen() function.
 */
static void *
__dlopen(const char *filename, int flag)
{
    typedef void * (*PFNDLOPEN)(const char *, int);
    static PFNDLOPEN dlopen_ptr = NULL;

    if (!dlopen_ptr) {
        dlopen_ptr = (PFNDLOPEN)dlsym(RTLD_NEXT, "dlopen");
        if (!dlopen_ptr) {
            os::log("apitrace: error: dlsym(RTLD_NEXT, \"dlopen\") failed\n");
            return NULL;
        }
    }

    return dlopen_ptr(filename, flag);
}

/*
 * Lookup a libGL symbol
 */
void * __libgl_sym(const char *symbol)
{
    void *result;

    if (!__libGlHandle) {
        /*
         * The app doesn't directly link against libGL.so, nor does it directly
         * dlopen it.  So we have to load it ourselves.
         */

        const char * libgl_filename = getenv("TRACE_LIBGL");

        if (!libgl_filename) {
            /*
             * Try to use whatever libGL.so the library is linked against.
             */

            result = dlsym(RTLD_NEXT, symbol);
            if (result) {
                __libGlHandle = RTLD_NEXT;
                return result;
            }

            libgl_filename = "libGL.so.1";
        }

        /*
         * It would have been preferable to use RTLD_LOCAL to ensure that the
         * application can never access libGL.so symbols directly, but this
         * won't work, given libGL.so often loads a driver specific SO and
         * exposes symbols to it.
         */

        __libGlHandle = __dlopen(libgl_filename, RTLD_GLOBAL | RTLD_LAZY);
        if (!__libGlHandle) {
            os::log("apitrace: error: couldn't find libGL.so\n");
            return NULL;
        }
    }

    return dlsym(__libGlHandle, symbol);
}

void *
__getPublicProcAddress(const char *procName)
{
    return __libgl_sym(procName);
}

void *
__getPrivateProcAddress(const char *procName)
{
    return (void *)__glXGetProcAddressARB((const GLubyte *)procName);
}

#endif

<commit_msg>Don't change behavior of glproc code via RETRACE define.<commit_after>/**************************************************************************
 *
 * Copyright 2011 Jose Fonseca
 * All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 *
 **************************************************************************/

#include "glproc.hpp"

#if !defined(_WIN32)
#include <unistd.h> // for symlink
#include <dlfcn.h>
#endif

/*
 * Handle to the true OpenGL library.
 */
#if defined(_WIN32)
HINSTANCE __libGlHandle = NULL;
#else
void *__libGlHandle = NULL;
#endif

#if defined(_WIN32)

void *
__getPublicProcAddress(const char *procName)
{
    if (!__libGlHandle) {
        char szDll[MAX_PATH] = {0};

        if (!GetSystemDirectoryA(szDll, MAX_PATH)) {
            return NULL;
        }

        strcat(szDll, "\\\\opengl32.dll");

        __libGlHandle = LoadLibraryA(szDll);
        if (!__libGlHandle) {
            os::log("apitrace: error: couldn't load %s\n", szDll);
            return NULL;
        }
    }

    return (void *)GetProcAddress(__libGlHandle, procName);
}

void *
__getPrivateProcAddress(const char *procName) {
    return (void *)__wglGetProcAddress(procName);
}

#elif defined(__APPLE__)

/*
 * Path to the true OpenGL framework
 */
static const char *libgl_filename = "/System/Library/Frameworks/OpenGL.framework/OpenGL";

/*
 * Lookup a libGL symbol
 */
void * __libgl_sym(const char *symbol)
{
    void *result;

    if (!__libGlHandle) {
        /*
         * Unfortunately we can't just dlopen the true dynamic library because
         * DYLD_LIBRARY_PATH/DYLD_FRAMEWORK_PATH take precedence, even for
         * absolute paths.  So we create a temporary symlink, and dlopen that
         * instead.
         */

        char temp_filename[] = "/tmp/tmp.XXXXXX";

        if (mktemp(temp_filename) != NULL) {
            if (symlink(libgl_filename, temp_filename) == 0) {
                __libGlHandle = dlopen(temp_filename, RTLD_LOCAL | RTLD_NOW | RTLD_FIRST);
                remove(temp_filename);
            }
        }

        if (!__libGlHandle) {
            os::log("apitrace: error: couldn't load %s\n", libgl_filename);
            os::abort();
            return NULL;
        }
    }

    result = dlsym(__libGlHandle, symbol);

    if (resullt && result == dlsym(RTLD_SELF, symbol)) {
        os::log("apitrace: error: symbol lookup recursion\n");
        os::abort();
        return NULL;
    }

    return result;
}

void *
__getPublicProcAddress(const char *procName)
{
    return __libgl_sym(procName);
}

void *
__getPrivateProcAddress(const char *procName)
{
    return __libgl_sym(procName);
}

#else

/*
 * Invoke the true dlopen() function.
 */
static void *
__dlopen(const char *filename, int flag)
{
    typedef void * (*PFNDLOPEN)(const char *, int);
    static PFNDLOPEN dlopen_ptr = NULL;

    if (!dlopen_ptr) {
        dlopen_ptr = (PFNDLOPEN)dlsym(RTLD_NEXT, "dlopen");
        if (!dlopen_ptr) {
            os::log("apitrace: error: dlsym(RTLD_NEXT, \"dlopen\") failed\n");
            return NULL;
        }
    }

    return dlopen_ptr(filename, flag);
}

/*
 * Lookup a libGL symbol
 */
void * __libgl_sym(const char *symbol)
{
    void *result;

    if (!__libGlHandle) {
        /*
         * The app doesn't directly link against libGL.so, nor does it directly
         * dlopen it.  So we have to load it ourselves.
         */

        const char * libgl_filename = getenv("TRACE_LIBGL");

        if (!libgl_filename) {
            /*
             * Try to use whatever libGL.so the library is linked against.
             */

            result = dlsym(RTLD_NEXT, symbol);
            if (result) {
                __libGlHandle = RTLD_NEXT;
                return result;
            }

            libgl_filename = "libGL.so.1";
        }

        /*
         * It would have been preferable to use RTLD_LOCAL to ensure that the
         * application can never access libGL.so symbols directly, but this
         * won't work, given libGL.so often loads a driver specific SO and
         * exposes symbols to it.
         */

        __libGlHandle = __dlopen(libgl_filename, RTLD_GLOBAL | RTLD_LAZY);
        if (!__libGlHandle) {
            os::log("apitrace: error: couldn't find libGL.so\n");
            return NULL;
        }
    }

    return dlsym(__libGlHandle, symbol);
}

void *
__getPublicProcAddress(const char *procName)
{
    return __libgl_sym(procName);
}

void *
__getPrivateProcAddress(const char *procName)
{
    return (void *)__glXGetProcAddressARB((const GLubyte *)procName);
}

#endif

<|endoftext|>


<commit_before>#include <stdio.h>
#include <stdlib.h>
#include <vector>

#ifdef _WIN32
#include <windows.h>
#else
#include <stdint.h>
#include <unistd.h>
#include <cstdarg>
#include <cstddef>
#endif

#include "module.h"
#include "robot_module.h"
#include "test_robot_module.h"

/* GLOBALS CONFIG */

#define IID "RCT.Test_robot_module_v107"

const unsigned int COUNT_ROBOTS = 99;
const unsigned int COUNT_FUNCTIONS = 7;
const unsigned int COUNT_AXIS = 3;

#define ADD_ROBOT_AXIS(AXIS_NAME, UPPER_VALUE, LOWER_VALUE) \
  robot_axis[axis_id] = new AxisData;                       \
  robot_axis[axis_id]->axis_index = axis_id + 1;            \
  robot_axis[axis_id]->upper_value = UPPER_VALUE;           \
  robot_axis[axis_id]->lower_value = LOWER_VALUE;           \
  robot_axis[axis_id]->name = AXIS_NAME;                    \
  ++axis_id;

TestRobotModule::TestRobotModule() {
#if MODULE_API_VERSION > 000
  mi = new ModuleInfo;
  mi->uid = IID;
  mi->mode = ModuleInfo::Modes::PROD;
  mi->version = BUILD_NUMBER;
  mi->digest = NULL;
#endif

  {
    robot_functions = new FunctionData *[COUNT_FUNCTIONS];
    system_value function_id = 0;
    FunctionData::ParamTypes *pt;

    robot_functions[function_id] =
        new FunctionData(function_id + 1, 0, NULL, "none");
    function_id++;

    pt = new FunctionData::ParamTypes[1];
    pt[0] = FunctionData::ParamTypes::FLOAT;
    robot_functions[function_id] =
        new FunctionData(function_id + 1, 1, pt, "do_something");
    function_id++;

    pt = new FunctionData::ParamTypes[1];
    pt[0] = FunctionData::ParamTypes::FLOAT;
    robot_functions[function_id] =
        new FunctionData(function_id + 1, 1, pt, "get_some_value");
    function_id++;

    robot_functions[function_id] =
        new FunctionData(function_id + 1, 0, NULL, "throw_exception");
    function_id++;

    pt = new FunctionData::ParamTypes[2];
    pt[0] = FunctionData::ParamTypes::STRING;
    pt[1] = FunctionData::ParamTypes::FLOAT;
    robot_functions[function_id] =
        new FunctionData(function_id + 1, 2, pt, "print");
    function_id++;

    pt = new FunctionData::ParamTypes[1];
    pt[0] = FunctionData::ParamTypes::FLOAT;
    robot_functions[function_id] =
        new FunctionData(function_id + 1, 1, pt, "throw_value");
    function_id++;

    pt = new FunctionData::ParamTypes[1];
    pt[0] = FunctionData::ParamTypes::STRING;
    robot_functions[function_id] =
        new FunctionData(function_id + 1, 1, pt, "debug");
    function_id++;

  }
  {
    robot_axis = new AxisData *[COUNT_AXIS];
    system_value axis_id = 0;
    ADD_ROBOT_AXIS("X", 100, -100)
    ADD_ROBOT_AXIS("Y", 1, 0)
    ADD_ROBOT_AXIS("Z", 100, 0)
  }
}

#if MODULE_API_VERSION > 000
const struct ModuleInfo &TestRobotModule::getModuleInfo() { return *mi; }
#else
const char *TestRobotModule::getUID() { return IID; }
#endif

void TestRobotModule::prepare(colorPrintfModule_t *colorPrintf_p,
                              colorPrintfModuleVA_t *colorPrintfVA_p) {
  this->colorPrintf_p = colorPrintfVA_p;
}

FunctionData **TestRobotModule::getFunctions(unsigned int *count_functions) {
  (*count_functions) = COUNT_FUNCTIONS;
  return robot_functions;
}

AxisData **TestRobotModule::getAxis(unsigned int *count_axis) {
  (*count_axis) = COUNT_AXIS;
  return robot_axis;
}

void *TestRobotModule::writePC(unsigned int *buffer_length) {
  (*buffer_length) = 0;
  return NULL;
}

int TestRobotModule::init() {
  for (unsigned int i = 0; i < COUNT_ROBOTS; ++i) {
    aviable_connections.push_back(new TestRobot(i + 1));
  }
  return 0;
}

#if MODULE_API_VERSION > 100
int TestRobotModule::readPC(int pc_index, void *buffer, unsigned int buffer_length) {
  return 0;
}

int TestRobotModule::startProgram(int run_index, int pc_index) {
  return 0;
}

AviableRobotsResult *TestRobotModule::getAviableRobots(int run_index) {
  std::vector<TestRobot*> aviable_robots;
  for (auto i = aviable_connections.begin();
       i != aviable_connections.end(); ++i) {
    if ((*i)->isAviable) {
      aviable_robots.push_back(*i);
    }
  }

  unsigned int count_robots = aviable_robots.size();
  if (!count_robots) {
    return NULL;
  }
  Robot **robots = new Robot*[count_robots];
  for (unsigned int i = 0; i < count_robots; ++i) {
    robots[i] = aviable_robots[i];
  }

  return new AviableRobotsResult(robots, count_robots);
}
Robot *TestRobotModule::robotRequire(int run_index, Robot *robot) {
  for (auto i = aviable_connections.begin();
       i != aviable_connections.end(); ++i) {
    if ((*i)->isAviable) {
      if ((!robot) || (robot == (*i))) {
        (*i)->isAviable = false;
        return (*i);
      }
    }
  }
  return NULL;
}
#else
int TestRobotModule::startProgram(int run_index) { return 0; }

Robot *TestRobotModule::robotRequire() {
  for (auto i = aviable_connections.begin();
       i != aviable_connections.end(); ++i) {
    if ((*i)->isAviable) {
      (*i)->isAviable = false;
      return (*i);
    }
  }
  return NULL;
}
#endif

#if MODULE_API_VERSION > 100
void TestRobotModule::robotFree(int run_index, Robot *robot) {
#else
void TestRobotModule::robotFree(Robot *robot) {
#endif
  TestRobot *test_robot = reinterpret_cast<TestRobot *>(robot);
  for (auto i = aviable_connections.begin();
       i != aviable_connections.end(); ++i) {
    if ((*i) == test_robot) {
      test_robot->isAviable = true;
      return;
    }
  }
}

void TestRobotModule::final() {
  for (auto i = aviable_connections.begin();
       i != aviable_connections.end(); ++i) {
    delete (*i);
  }
  aviable_connections.clear();
}

int TestRobotModule::endProgram(int run_index) { return 0; }

void TestRobotModule::destroy() {
#if MODULE_API_VERSION > 000
  delete mi;
#endif

  for (unsigned int j = 0; j < COUNT_FUNCTIONS; ++j) {
    if (robot_functions[j]->count_params) {
      delete[] robot_functions[j]->params;
    }
    delete robot_functions[j];
  }
  for (unsigned int j = 0; j < COUNT_AXIS; ++j) {
    delete robot_axis[j];
  }
  delete[] robot_functions;
  delete[] robot_axis;
  delete this;
}

void TestRobotModule::colorPrintf(ConsoleColor colors, const char *mask, ...) {
  va_list args;
  va_start(args, mask);
  (*colorPrintf_p)(this, colors, mask, args);
  va_end(args);
}

TestRobot::TestRobot(unsigned int uniq_index) : isAviable(true) {
  uniq_name = new char[40];
  sprintf(uniq_name, "robot-%u", uniq_index);
}

void TestRobot::prepare(colorPrintfRobot_t *colorPrintf_p,
                        colorPrintfRobotVA_t *colorPrintfVA_p) {
  this->colorPrintf_p = colorPrintfVA_p;
}

#if MODULE_API_VERSION > 100
const char *TestRobot::getUniqName() {
  return uniq_name;
}

FunctionResult *TestRobot::executeFunction(int run_index, CommandMode mode,
                                           system_value command_index,
                                           void **args) {
#else
FunctionResult *TestRobot::executeFunction(CommandMode mode,
                                           system_value command_index,
                                           void **args) {
#endif

  FunctionResult *fr = NULL;

  switch (command_index) {
    case 1: {  // none
      break;
    }
    case 2: {  // do_something
      variable_value *vv = (variable_value *)args[0];
#ifdef _WIN32
      Sleep((DWORD)*vv);
#else
      usleep(((uint32_t)*vv) * 1000);
#endif
      break;
    }
    case 3: {  // get_some_value
      variable_value *vv = (variable_value *)args[0];
#if MODULE_API_VERSION > 000
      fr = new FunctionResult(FunctionResult::Types::VALUE, *vv);
#else
      fr = new FunctionResult(1, *vv);
#endif
      break;
    }
    case 4: {  // throw_exception
#if MODULE_API_VERSION > 000
      fr = new FunctionResult(FunctionResult::Types::EXCEPTION);
#else
      fr = new FunctionResult(0);
#endif

      break;
    }
    case 5: {  // print
      variable_value *vv = (variable_value *)args[1];
#ifdef _WIN32
      Sleep((DWORD)*vv);
#else
      usleep(((uint32_t)*vv) * 1000);
#endif
      const char *tmp = (const char *)args[0];
      colorPrintf(ConsoleColor(ConsoleColor::white), "%s", tmp);
      break;
    }
    case 6:{ // throw_value
            variable_value *vv = (variable_value *)args[0];
#if MODULE_API_VERSION > 000
      fr = new FunctionResult(FunctionResult::Types::EXCEPTION, *vv);
#else
      fr = new FunctionResult(0, *vv);
#endif
    }
    case 7: {  // debug
      const char *tmp = (const char *)args[0];
      colorPrintf(ConsoleColor(ConsoleColor::white), "%s", tmp);
      break;
    }
    default:
      break;
  }

  return fr;
}

void TestRobot::axisControl(system_value axis_index, variable_value value) {
  const char *name;
  switch (axis_index) {
    case 1: {
      name = "X";
      break;
    }
    case 2: {
      name = "Y";
      break;
    }
    case 3: {
      name = "Z";
      break;
    }
    default: {
      name = "O_o";
      break;
    };
  }
  colorPrintf(ConsoleColor(ConsoleColor::green), "change axis value: %s = %f\n",
              name, value);
}

TestRobot::~TestRobot() { delete[] uniq_name; }

void TestRobot::colorPrintf(ConsoleColor colors, const char *mask, ...) {
  va_list args;
  va_start(args, mask);
#if MODULE_API_VERSION > 100
  (*colorPrintf_p)(this, colors, mask, args);
#else
  (*colorPrintf_p)(this, uniq_name, colors, mask, args);
#endif
  va_end(args);
}

#if MODULE_API_VERSION > 000
PREFIX_FUNC_DLL unsigned short getRobotModuleApiVersion() {
  return MODULE_API_VERSION;
};
#endif

PREFIX_FUNC_DLL RobotModule *getRobotModuleObject() {
  return new TestRobotModule();
}<commit_msg>98-involved_robot_for_choice<commit_after>#include <stdio.h>
#include <stdlib.h>
#include <vector>

#ifdef _WIN32
#include <windows.h>
#else
#include <stdint.h>
#include <unistd.h>
#include <cstdarg>
#include <cstddef>
#endif

#include "module.h"
#include "robot_module.h"
#include "test_robot_module.h"

/* GLOBALS CONFIG */

#define IID "RCT.Test_robot_module_v107"

const unsigned int COUNT_ROBOTS = 99;
const unsigned int COUNT_FUNCTIONS = 7;
const unsigned int COUNT_AXIS = 3;

#define ADD_ROBOT_AXIS(AXIS_NAME, UPPER_VALUE, LOWER_VALUE) \
  robot_axis[axis_id] = new AxisData;                       \
  robot_axis[axis_id]->axis_index = axis_id + 1;            \
  robot_axis[axis_id]->upper_value = UPPER_VALUE;           \
  robot_axis[axis_id]->lower_value = LOWER_VALUE;           \
  robot_axis[axis_id]->name = AXIS_NAME;                    \
  ++axis_id;

TestRobotModule::TestRobotModule() {
#if MODULE_API_VERSION > 000
  mi = new ModuleInfo;
  mi->uid = IID;
  mi->mode = ModuleInfo::Modes::PROD;
  mi->version = BUILD_NUMBER;
  mi->digest = NULL;
#endif

  {
    robot_functions = new FunctionData *[COUNT_FUNCTIONS];
    system_value function_id = 0;
    FunctionData::ParamTypes *pt;

    robot_functions[function_id] =
        new FunctionData(function_id + 1, 0, NULL, "none");
    function_id++;

    pt = new FunctionData::ParamTypes[1];
    pt[0] = FunctionData::ParamTypes::FLOAT;
    robot_functions[function_id] =
        new FunctionData(function_id + 1, 1, pt, "do_something");
    function_id++;

    pt = new FunctionData::ParamTypes[1];
    pt[0] = FunctionData::ParamTypes::FLOAT;
    robot_functions[function_id] =
        new FunctionData(function_id + 1, 1, pt, "get_some_value");
    function_id++;

    robot_functions[function_id] =
        new FunctionData(function_id + 1, 0, NULL, "throw_exception");
    function_id++;

    pt = new FunctionData::ParamTypes[2];
    pt[0] = FunctionData::ParamTypes::STRING;
    pt[1] = FunctionData::ParamTypes::FLOAT;
    robot_functions[function_id] =
        new FunctionData(function_id + 1, 2, pt, "print");
    function_id++;

    pt = new FunctionData::ParamTypes[1];
    pt[0] = FunctionData::ParamTypes::FLOAT;
    robot_functions[function_id] =
        new FunctionData(function_id + 1, 1, pt, "throw_value");
    function_id++;

    pt = new FunctionData::ParamTypes[1];
    pt[0] = FunctionData::ParamTypes::STRING;
    robot_functions[function_id] =
        new FunctionData(function_id + 1, 1, pt, "debug");
    function_id++;

  }
  {
    robot_axis = new AxisData *[COUNT_AXIS];
    system_value axis_id = 0;
    ADD_ROBOT_AXIS("X", 100, -100)
    ADD_ROBOT_AXIS("Y", 1, 0)
    ADD_ROBOT_AXIS("Z", 100, 0)
  }
}

#if MODULE_API_VERSION > 000
const struct ModuleInfo &TestRobotModule::getModuleInfo() { return *mi; }
#else
const char *TestRobotModule::getUID() { return IID; }
#endif

void TestRobotModule::prepare(colorPrintfModule_t *colorPrintf_p,
                              colorPrintfModuleVA_t *colorPrintfVA_p) {
  this->colorPrintf_p = colorPrintfVA_p;
}

FunctionData **TestRobotModule::getFunctions(unsigned int *count_functions) {
  (*count_functions) = COUNT_FUNCTIONS;
  return robot_functions;
}

AxisData **TestRobotModule::getAxis(unsigned int *count_axis) {
  (*count_axis) = COUNT_AXIS;
  return robot_axis;
}

void *TestRobotModule::writePC(unsigned int *buffer_length) {
  (*buffer_length) = 0;
  return NULL;
}

int TestRobotModule::init() {
  for (unsigned int i = 0; i < COUNT_ROBOTS; ++i) {
    aviable_connections.push_back(new TestRobot(i + 1));
  }
  return 0;
}

#if MODULE_API_VERSION > 100
int TestRobotModule::readPC(int pc_index, void *buffer, unsigned int buffer_length) {
  return 0;
}

int TestRobotModule::startProgram(int run_index, int pc_index) {
  return 0;
}

AviableRobotsResult *TestRobotModule::getAviableRobots(int run_index) {
  unsigned int count_busy_robots = 0;
  unsigned int count_free_robots = 0;

  for (auto i = aviable_connections.begin();
       i != aviable_connections.end(); ++i) {
    if ((*i)->isAviable) {
      ++count_free_robots;
    } else {
      ++count_busy_robots;
    }
  }

  if (!count_busy_robots || !count_free_robots) {
    return NULL;
  }

  Robot **free_robots = new Robot*[count_free_robots];
  Robot **busy_robots = new Robot*[count_busy_robots];

  unsigned int index_busy = 0;
  unsigned int index_free = 0;
  for (auto i = aviable_connections.begin();
       i != aviable_connections.end(); ++i) {
    if ((*i)->isAviable) {
      busy_robots[index_busy++] = *i;
    } else {
      free_robots[index_free++] = *i;
    }
  }

  return new AviableRobotsResult(busy_robots, free_robots, count_busy_robots, count_free_robots);
}
Robot *TestRobotModule::robotRequire(int run_index, Robot *robot) {
  for (auto i = aviable_connections.begin();
       i != aviable_connections.end(); ++i) {
    if ((*i)->isAviable) {
      if ((!robot) || (robot == (*i))) {
        (*i)->isAviable = false;
        return (*i);
      }
    }
  }
  return NULL;
}
#else
int TestRobotModule::startProgram(int run_index) { return 0; }

Robot *TestRobotModule::robotRequire() {
  for (auto i = aviable_connections.begin();
       i != aviable_connections.end(); ++i) {
    if ((*i)->isAviable) {
      (*i)->isAviable = false;
      return (*i);
    }
  }
  return NULL;
}
#endif

#if MODULE_API_VERSION > 100
void TestRobotModule::robotFree(int run_index, Robot *robot) {
#else
void TestRobotModule::robotFree(Robot *robot) {
#endif
  TestRobot *test_robot = reinterpret_cast<TestRobot *>(robot);
  for (auto i = aviable_connections.begin();
       i != aviable_connections.end(); ++i) {
    if ((*i) == test_robot) {
      test_robot->isAviable = true;
      return;
    }
  }
}

void TestRobotModule::final() {
  for (auto i = aviable_connections.begin();
       i != aviable_connections.end(); ++i) {
    delete (*i);
  }
  aviable_connections.clear();
}

int TestRobotModule::endProgram(int run_index) { return 0; }

void TestRobotModule::destroy() {
#if MODULE_API_VERSION > 000
  delete mi;
#endif

  for (unsigned int j = 0; j < COUNT_FUNCTIONS; ++j) {
    if (robot_functions[j]->count_params) {
      delete[] robot_functions[j]->params;
    }
    delete robot_functions[j];
  }
  for (unsigned int j = 0; j < COUNT_AXIS; ++j) {
    delete robot_axis[j];
  }
  delete[] robot_functions;
  delete[] robot_axis;
  delete this;
}

void TestRobotModule::colorPrintf(ConsoleColor colors, const char *mask, ...) {
  va_list args;
  va_start(args, mask);
  (*colorPrintf_p)(this, colors, mask, args);
  va_end(args);
}

TestRobot::TestRobot(unsigned int uniq_index) : isAviable(true) {
  uniq_name = new char[40];
  sprintf(uniq_name, "robot-%u", uniq_index);
}

void TestRobot::prepare(colorPrintfRobot_t *colorPrintf_p,
                        colorPrintfRobotVA_t *colorPrintfVA_p) {
  this->colorPrintf_p = colorPrintfVA_p;
}

#if MODULE_API_VERSION > 100
const char *TestRobot::getUniqName() {
  return uniq_name;
}

FunctionResult *TestRobot::executeFunction(int run_index, CommandMode mode,
                                           system_value command_index,
                                           void **args) {
#else
FunctionResult *TestRobot::executeFunction(CommandMode mode,
                                           system_value command_index,
                                           void **args) {
#endif

  FunctionResult *fr = NULL;

  switch (command_index) {
    case 1: {  // none
      break;
    }
    case 2: {  // do_something
      variable_value *vv = (variable_value *)args[0];
#ifdef _WIN32
      Sleep((DWORD)*vv);
#else
      usleep(((uint32_t)*vv) * 1000);
#endif
      break;
    }
    case 3: {  // get_some_value
      variable_value *vv = (variable_value *)args[0];
#if MODULE_API_VERSION > 000
      fr = new FunctionResult(FunctionResult::Types::VALUE, *vv);
#else
      fr = new FunctionResult(1, *vv);
#endif
      break;
    }
    case 4: {  // throw_exception
#if MODULE_API_VERSION > 000
      fr = new FunctionResult(FunctionResult::Types::EXCEPTION);
#else
      fr = new FunctionResult(0);
#endif

      break;
    }
    case 5: {  // print
      variable_value *vv = (variable_value *)args[1];
#ifdef _WIN32
      Sleep((DWORD)*vv);
#else
      usleep(((uint32_t)*vv) * 1000);
#endif
      const char *tmp = (const char *)args[0];
      colorPrintf(ConsoleColor(ConsoleColor::white), "%s", tmp);
      break;
    }
    case 6:{ // throw_value
            variable_value *vv = (variable_value *)args[0];
#if MODULE_API_VERSION > 000
      fr = new FunctionResult(FunctionResult::Types::EXCEPTION, *vv);
#else
      fr = new FunctionResult(0, *vv);
#endif
    }
    case 7: {  // debug
      const char *tmp = (const char *)args[0];
      colorPrintf(ConsoleColor(ConsoleColor::white), "%s", tmp);
      break;
    }
    default:
      break;
  }

  return fr;
}

void TestRobot::axisControl(system_value axis_index, variable_value value) {
  const char *name;
  switch (axis_index) {
    case 1: {
      name = "X";
      break;
    }
    case 2: {
      name = "Y";
      break;
    }
    case 3: {
      name = "Z";
      break;
    }
    default: {
      name = "O_o";
      break;
    };
  }
  colorPrintf(ConsoleColor(ConsoleColor::green), "change axis value: %s = %f\n",
              name, value);
}

TestRobot::~TestRobot() { delete[] uniq_name; }

void TestRobot::colorPrintf(ConsoleColor colors, const char *mask, ...) {
  va_list args;
  va_start(args, mask);
#if MODULE_API_VERSION > 100
  (*colorPrintf_p)(this, colors, mask, args);
#else
  (*colorPrintf_p)(this, uniq_name, colors, mask, args);
#endif
  va_end(args);
}

#if MODULE_API_VERSION > 000
PREFIX_FUNC_DLL unsigned short getRobotModuleApiVersion() {
  return MODULE_API_VERSION;
};
#endif

PREFIX_FUNC_DLL RobotModule *getRobotModuleObject() {
  return new TestRobotModule();
}<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: opaquhdl.cxx,v $
 *
 *  $Revision: 1.5 $
 *
 *  last change: $Author: ihi $ $Date: 2006-08-29 11:02:09 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    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
 *
 ************************************************************************/

#ifndef _XMLOFF_PROPERTYHANDLER_OPAQUETYPES_HXX
#include "opaquhdl.hxx"
#endif

#ifndef _COM_SUN_STAR_UNO_ANY_HXX_
#include <com/sun/star/uno/Any.hxx>
#endif

#ifndef _RTL_USTRBUF_HXX_
#include <rtl/ustrbuf.hxx>
#endif

// --

#ifndef _XMLOFF_XMLTOKEN_HXX
#include "xmltoken.hxx"
#endif

#ifndef _XMLOFF_XMLUCONV_HXX
#include "xmluconv.hxx"
#endif

using namespace ::rtl;
using namespace ::com::sun::star::uno;
using namespace ::xmloff::token;

///////////////////////////////////////////////////////////////////////////////
//
// class XMLOpaquePropHdl
//

XMLOpaquePropHdl::~XMLOpaquePropHdl()
{
    // nothing to do
}

sal_Bool XMLOpaquePropHdl::importXML( const OUString& rStrImpValue, Any& rValue, const SvXMLUnitConverter& ) const
{
    sal_Bool bRet = sal_True;

    sal_Bool bValue = IsXMLToken( rStrImpValue, XML_OPAQUE_FOREGROUND );
    rValue <<= sal_Bool(bValue);
    bRet = sal_True;

    return bRet;
}

sal_Bool XMLOpaquePropHdl::exportXML( OUString& rStrExpValue, const Any& rValue, const SvXMLUnitConverter& ) const
{
    sal_Bool bRet = sal_False;
    sal_Bool bValue = sal_Bool();

    if (rValue >>= bValue)
    {
        if( bValue )
            rStrExpValue = GetXMLToken( XML_OPAQUE_FOREGROUND );
        else
            rStrExpValue = GetXMLToken( XML_OPAQUE_BACKGROUND );

        bRet = sal_True;
    }

    return bRet;
}
<commit_msg>INTEGRATION: CWS pchfix02 (1.4.34); FILE MERGED 2006/09/01 17:59:54 kaib 1.4.34.1: #i68856# Added header markers and pch files<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: opaquhdl.cxx,v $
 *
 *  $Revision: 1.6 $
 *
 *  last change: $Author: obo $ $Date: 2006-09-17 10:55:58 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    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
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_xmloff.hxx"

#ifndef _XMLOFF_PROPERTYHANDLER_OPAQUETYPES_HXX
#include "opaquhdl.hxx"
#endif

#ifndef _COM_SUN_STAR_UNO_ANY_HXX_
#include <com/sun/star/uno/Any.hxx>
#endif

#ifndef _RTL_USTRBUF_HXX_
#include <rtl/ustrbuf.hxx>
#endif

// --

#ifndef _XMLOFF_XMLTOKEN_HXX
#include "xmltoken.hxx"
#endif

#ifndef _XMLOFF_XMLUCONV_HXX
#include "xmluconv.hxx"
#endif

using namespace ::rtl;
using namespace ::com::sun::star::uno;
using namespace ::xmloff::token;

///////////////////////////////////////////////////////////////////////////////
//
// class XMLOpaquePropHdl
//

XMLOpaquePropHdl::~XMLOpaquePropHdl()
{
    // nothing to do
}

sal_Bool XMLOpaquePropHdl::importXML( const OUString& rStrImpValue, Any& rValue, const SvXMLUnitConverter& ) const
{
    sal_Bool bRet = sal_True;

    sal_Bool bValue = IsXMLToken( rStrImpValue, XML_OPAQUE_FOREGROUND );
    rValue <<= sal_Bool(bValue);
    bRet = sal_True;

    return bRet;
}

sal_Bool XMLOpaquePropHdl::exportXML( OUString& rStrExpValue, const Any& rValue, const SvXMLUnitConverter& ) const
{
    sal_Bool bRet = sal_False;
    sal_Bool bValue = sal_Bool();

    if (rValue >>= bValue)
    {
        if( bValue )
            rStrExpValue = GetXMLToken( XML_OPAQUE_FOREGROUND );
        else
            rStrExpValue = GetXMLToken( XML_OPAQUE_BACKGROUND );

        bRet = sal_True;
    }

    return bRet;
}
<|endoftext|>


<commit_before>// Copyright 2015 Adam Grandquist

#include "./test.hpp"

namespace ReQL {
extern "C" {
#include "./c/dev/connection.h"
}
}

#include "./catch.hpp"

#include <string>

using namespace ReQL;

TEST_CASE("c connection", "[c][connection]") {
  std::unique_ptr<ReQL_Conn_t> c(new ReQL_Conn_t);

  SECTION("reql_connection_init") {
    reql_connection_init(c.get());

    REQUIRE(reql_conn_addr(c.get()) == nullptr);
    REQUIRE(reql_conn_auth_key(c.get()) == nullptr);
    REQUIRE(reql_conn_auth_size(c.get()) == 0);
    REQUIRE(std::strncmp(reql_conn_port(c.get()), "28015", 5) == 0);
    REQUIRE(reql_conn_timeout(c.get()) == uint64_t(20));
  }

  reql_connection_init(c.get());

  SECTION("reql_conn_set_auth") {
    char key[] = "test";

    reql_conn_set_auth(c.get(), 4, key);

    REQUIRE(reql_conn_auth_key(c.get()) == key);
    REQUIRE(reql_conn_auth_size(c.get()) == 4);
  }

  SECTION("reql_conn_set_addr") {
    char key[] = "test";

    reql_conn_set_addr(c.get(), key);

    REQUIRE(reql_conn_addr(c.get()) == key);
  }

  SECTION("reql_conn_set_port") {
    char key[] = "test";

    reql_conn_set_port(c.get(), key);

    REQUIRE(reql_conn_port(c.get()) == key);
  }

  SECTION("reql_conn_set_timeout") {
    reql_conn_set_timeout(c.get(), 15);

    REQUIRE(reql_conn_timeout(c.get()) == uint64_t(15));
  }

  SECTION("reql_connect") {
    REQUIRE(reql_conn_open(c.get()) == 0);

    std::unique_ptr<std::uint8_t> buf(new std::uint8_t[100]);

    REQUIRE(reql_connect(c.get(), buf.get(), 100) == 0);

    buf.release();

    CHECK(reql_conn_open(c.get()) != 0);

    if (reql_conn_open(c.get()) != 0) {
      std::unique_ptr<ReQL_Cur_t> cur(new ReQL_Cur_t);
      std::unique_ptr<ReQL_Obj_t> q(new ReQL_Obj_t);

      reql_number_init(q.get(), 2.72);

      reql_run(cur.get(), q.get(), c.get(), nullptr);

      CHECK(reql_cur_open(cur.get()) != 0);

      if (reql_cur_open(cur.get()) != 0) {
        ReQL_Obj_t *result = reql_cursor_to_array(cur.get());

        CHECK(result != nullptr);

        reql_json_destroy(result);
      }

      cur.release();
    }
    reql_close_conn(c.get());

    REQUIRE(reql_conn_open(c.get()) == 0);

    reql_ensure_conn_close(c.get());

    c.release();
  }
}
<commit_msg>Move cursor allocation.<commit_after>// Copyright 2015 Adam Grandquist

#include "./test.hpp"

namespace ReQL {
extern "C" {
#include "./c/dev/connection.h"
}
}

#include "./catch.hpp"

#include <string>

using namespace ReQL;

TEST_CASE("c connection", "[c][connection]") {
  std::unique_ptr<ReQL_Conn_t> c(new ReQL_Conn_t);

  SECTION("reql_connection_init") {
    reql_connection_init(c.get());

    REQUIRE(reql_conn_addr(c.get()) == nullptr);
    REQUIRE(reql_conn_auth_key(c.get()) == nullptr);
    REQUIRE(reql_conn_auth_size(c.get()) == 0);
    REQUIRE(std::strncmp(reql_conn_port(c.get()), "28015", 5) == 0);
    REQUIRE(reql_conn_timeout(c.get()) == uint64_t(20));
  }

  reql_connection_init(c.get());

  SECTION("reql_conn_set_auth") {
    char key[] = "test";

    reql_conn_set_auth(c.get(), 4, key);

    REQUIRE(reql_conn_auth_key(c.get()) == key);
    REQUIRE(reql_conn_auth_size(c.get()) == 4);
  }

  SECTION("reql_conn_set_addr") {
    char key[] = "test";

    reql_conn_set_addr(c.get(), key);

    REQUIRE(reql_conn_addr(c.get()) == key);
  }

  SECTION("reql_conn_set_port") {
    char key[] = "test";

    reql_conn_set_port(c.get(), key);

    REQUIRE(reql_conn_port(c.get()) == key);
  }

  SECTION("reql_conn_set_timeout") {
    reql_conn_set_timeout(c.get(), 15);

    REQUIRE(reql_conn_timeout(c.get()) == uint64_t(15));
  }

  SECTION("reql_connect") {
    REQUIRE(reql_conn_open(c.get()) == 0);

    std::unique_ptr<std::uint8_t> buf(new std::uint8_t[100]);

    REQUIRE(reql_connect(c.get(), buf.get(), 100) == 0);

    buf.release();

    CHECK(reql_conn_open(c.get()) != 0);

    if (reql_conn_open(c.get()) != 0) {
      std::unique_ptr<ReQL_Obj_t> q(new ReQL_Obj_t);

      reql_number_init(q.get(), 2.72);

      std::unique_ptr<ReQL_Cur_t> cur(new ReQL_Cur_t);

      reql_run(cur.get(), q.get(), c.get(), nullptr);

      q.release();

      CHECK(reql_cur_open(cur.get()) != 0);

      if (reql_cur_open(cur.get()) != 0) {
        ReQL_Obj_t *result = reql_cursor_to_array(cur.get());

        CHECK(result != nullptr);

        reql_json_destroy(result);
      }

      cur.release();
    }

    reql_close_conn(c.get());

    REQUIRE(reql_conn_open(c.get()) == 0);

    reql_ensure_conn_close(c.get());

    c.release();
  }
}
<|endoftext|>


<commit_before>/*-----------------------------------------------------------------------------------------------
The MIT License (MIT)

Copyright (c) 2015-2019 OSRE ( Open Source Render Engine ) by Kim Kulling

Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-----------------------------------------------------------------------------------------------*/
#include <osre/Common/Environment.h>
#include <osre/Common/StringUtils.h>

namespace OSRE {
namespace Common {

Environment::Environment()
: mEnvVariables() {
    // empty
}

Environment::~Environment() {
    // empty
}

EnvVar* Environment::findVar(const c8* varName) const {
    if (nullptr == varName) {
        return nullptr;
    }
    EnvVar* var(nullptr);
    if (mEnvVariables.getValue(StringUtils::hashName(varName), var)) {
        return var;
    }

    return nullptr;
}

void Environment::addIntVar(const c8* name, int value) {
    if (nullptr != findVar(name)) {
        return;
    }

    EnvVar* var = new EnvVar(name, value);
    mEnvVariables.insert(StringUtils::hashName(var->m_name.c_str()), var);
}

void Environment::addStrVar(const c8* name, const c8* value) {
    if (nullptr != findVar(name)) {
        return;
    }

    EnvVar* var = new EnvVar(name, value);
    mEnvVariables.insert(StringUtils::hashName(name), var );
}

void Environment::addVariable( EnvVar *var) {
    if (nullptr == findVar(var->m_name.c_str())) {
        return;
    }

    mEnvVariables.insert(StringUtils::hashName(var->m_name.c_str()), var);
}

} // Namespace Common
} // Namespace OSRE
<commit_msg>Fix crash in environent.<commit_after>/*-----------------------------------------------------------------------------------------------
The MIT License (MIT)

Copyright (c) 2015-2019 OSRE ( Open Source Render Engine ) by Kim Kulling

Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-----------------------------------------------------------------------------------------------*/
#include <osre/Common/Environment.h>
#include <osre/Common/StringUtils.h>

namespace OSRE {
namespace Common {

Environment::Environment()
: mEnvVariables() {
    // empty
}

Environment::~Environment() {
    // empty
}

EnvVar* Environment::findVar(const c8* varName) const {
    if (nullptr == varName) {
        return nullptr;
    }
    EnvVar* var(nullptr);
    if ( !mEnvVariables.hasKey(StringUtils::hashName(varName)) ) {
        return nullptr;
    }
    if (mEnvVariables.getValue(StringUtils::hashName(varName), var)) {
        return var;
    }

    return nullptr;
}

void Environment::addIntVar(const c8* name, int value) {
    if (nullptr != findVar(name)) {
        return;
    }

    EnvVar* var = new EnvVar(name, value);
    mEnvVariables.insert(StringUtils::hashName(var->m_name.c_str()), var);
}

void Environment::addStrVar(const c8* name, const c8* value) {
    if (nullptr != findVar(name)) {
        return;
    }

    EnvVar* var = new EnvVar(name, value);
    mEnvVariables.insert(StringUtils::hashName(name), var );
}

void Environment::addVariable( EnvVar *var) {
    if (nullptr == findVar(var->m_name.c_str())) {
        return;
    }

    mEnvVariables.insert(StringUtils::hashName(var->m_name.c_str()), var);
}

} // Namespace Common
} // Namespace OSRE
<|endoftext|>


<commit_before>#ifndef GENERIC_CIFY_HPP
# define GENERIC_CIFY_HPP
# pragma once

#include <utility>

namespace generic
{

namespace
{

template <typename F, int I, typename L, typename R, typename ...A>
inline F cify(L&& l, R (*)(A...))
{
  static thread_local L l_(::std::forward<L>(l));
  static thread_local bool full;

  if (full)
  {
    l_.~L();
    new (static_cast<void*>(&l_)) L(::std::forward<L>(l));
  }
  else
  {
    full = true;
  }

  struct S
  {
    static R f(A... args) noexcept(noexcept(l_(::std::forward<A>(args)...)))
    {
      return l_(::std::forward<A>(args)...);
    }
  };

  return &S::f;
}

}

template <typename F, int I = 0, typename L>
inline F cify(L&& l)
{
  return cify<F, I>(::std::forward<L>(l), F());
}

}

#endif // GENERIC_CIFY_HPP
<commit_msg>some fixes<commit_after>#ifndef GENERIC_CIFY_HPP
# define GENERIC_CIFY_HPP
# pragma once

#include <utility>

namespace generic
{

namespace
{

template <typename F, int I, typename L, typename R, typename ...A>
inline F cify(L&& l, R (*)(A...))
{
  static thread_local L l_(::std::forward<L>(l));
  static thread_local bool full;

  if (full)
  {
    l_.~L();

    new (static_cast<void*>(&l_)) L(::std::forward<L>(l));
  }
  else
  {
    full = true;
  }

  struct S
  {
    static R f(A... args) noexcept(noexcept(l_(::std::forward<A>(args)...)))
    {
      return l_(::std::forward<A>(args)...);
    }
  };

  return &S::f;
}

}

template <typename F, int I = 0, typename L>
inline F cify(L&& l)
{
  return cify<F, I>(::std::forward<L>(l), F());
}

}

#endif // GENERIC_CIFY_HPP
<|endoftext|>


<commit_before>#include "Parser.h"
#include "Controler.h"

Parser::Parser()
{
	options = new vector<string>(NUM_OPTIONS);
	options->at(0)= "-o";
	options->at(1)= "-a";
	options->at(2)= "-p";
	options->at(3)= "-e";
}

Parser::~Parser()
{
	delete[] options;
}

void Parser::show_options()
{
	cout << "Options disponibles : " <<endl;
	cout << "----------------------" <<endl;
	cout << options->at(0)+" : desc" << endl;
	cout << options->at(1)+" : desc" << endl;
	cout << options->at(2)+" : desc" << endl;
	cout << options->at(3)+" : desc" << endl;
	cout << "help : description des options disponibles"<<endl;
}

void Parser::parsing_options(vector<string> opts)
{
    //AJOUTER : ON NE PEUT PAS AVOIR 2 FOIS LA MEME OPTION -> booleans, exception if déjà true
    for (unsigned int i=0; i< opts.size(); i++)
    {
        if (opts[i].compare(options->at(0)) == 0)
        {
            Controler::enable_o();
        }
        else if (opts[i].compare(options->at(1)) == 0)
        {
            Controler::enable_a();
        }
        else if (opts[i].compare(options->at(2)) == 0)
        {
            Controler::enable_p();
        }
        else if (opts[i].compare(options->at(3)) == 0)
        {
            Controler::enable_e();
        }
        else
        {
            throw 0;
        }
    }

}
<commit_msg>changeHelp<commit_after>#include "Parser.h"
#include "Controler.h"

Parser::Parser()
{
	options = new vector<string>(NUM_OPTIONS);
	options->at(0)= "-o";
	options->at(1)= "-a";
	options->at(2)= "-p";
	options->at(3)= "-e";
}

Parser::~Parser()
{
	delete[] options;
}

void Parser::show_options()
{
	cout << "Options disponibles : " <<endl;
	cout << "----------------------" <<endl;
	cout << options->at(0)+" : desc" << endl;
	cout << options->at(1)+" : desc" << endl;
	cout << options->at(2)+" : desc" << endl;
	cout << options->at(3)+" : desc" << endl;
	cout << "Sans argument : description des options disponibles"<<endl;
}

void Parser::parsing_options(vector<string> opts)
{
    //AJOUTER : ON NE PEUT PAS AVOIR 2 FOIS LA MEME OPTION -> booleans, exception if déjà true
    for (unsigned int i=0; i< opts.size(); i++)
    {
        if (opts[i].compare(options->at(0)) == 0)
        {
            Controler::enable_o();
        }
        else if (opts[i].compare(options->at(1)) == 0)
        {
            Controler::enable_a();
        }
        else if (opts[i].compare(options->at(2)) == 0)
        {
            Controler::enable_p();
        }
        else if (opts[i].compare(options->at(3)) == 0)
        {
            Controler::enable_e();
        }
        else
        {
            throw 0;
        }
    }

}
<|endoftext|>


<commit_before><commit_msg>somatic_report: Added additional texts.<commit_after><|endoftext|>


<commit_before>/* Begin CVS Header
   $Source: /Volumes/Home/Users/shoops/cvs/copasi_dev/copasi/optimization/COptMethodSteepestDescent.cpp,v $
   $Revision: 1.5 $
   $Name:  $
   $Author: ssahle $
   $Date: 2005/07/25 09:49:19 $
   End CVS Header */

#include "copasi.h"

#include "COptMethod.h"
#include "COptProblem.h"
#include "COptItem.h"
#include "COptTask.h"

#include "FminBrent.h"

#include "report/CCopasiObjectReference.h"

COptMethodSteepestDescent::COptMethodSteepestDescent(const CCopasiContainer * pParent):
    COptMethod(CCopasiMethod::SteepestDescent, pParent),
    mpDescent(new FDescentTemplate<COptMethodSteepestDescent>(this, &COptMethodSteepestDescent::descentLine))
{
  addParameter("Iteration Limit", CCopasiParameter::UINT, (unsigned C_INT32) 50);
  addParameter("Tolerance", CCopasiParameter::DOUBLE, (C_FLOAT64) 0.001);
}

COptMethodSteepestDescent::COptMethodSteepestDescent(const COptMethodSteepestDescent & src,
    const CCopasiContainer * pParent): COptMethod(src, pParent),
    mpDescent(new FDescentTemplate<COptMethodSteepestDescent>(this, &COptMethodSteepestDescent::descentLine))
{}

COptMethodSteepestDescent::~COptMethodSteepestDescent()
{
  pdelete(mpDescent);

  cleanup();
}

bool COptMethodSteepestDescent::setCallBack(CProcessReport * pCallBack)
{
  CCopasiMethod::setCallBack(pCallBack);

  /*  pCallBack->addItem(...);*/

  return true;
}

bool COptMethodSteepestDescent::optimise()
{
  if (!initialize()) return false;

  C_INT32 i, k;
  C_FLOAT64 tmp, x0, alpha, mn, mx, norm, daux, fmn, fmx;
  bool calc_grad;

  // initial point is first guess
  for (i = 0; i < mVariableSize; i++)
    mIndividual[i] = *(*mpOptItem)[i]->getObjectValue();

  fmx = mBestValue = evaluate();

  for (mCurrentIteration = 0; mCurrentIteration < mIterations && mContinue; mCurrentIteration++)
    {
      // calculate the direction of steepest descent
      // by central finite differences
      gradient();
      // minimise the function in this direction
      // find brackets for the minimisation
      //  mn = 0.0; md = 1.0;
      //  mnbrak(&mn, &md, &mx, &fmn, &fmd, &fmx, descent_line);
      // make sure that no parameter will exceed its bounds
      x0 = DBL_MAX;

      for (i = 0; i < mVariableSize; i++)
        {
          if (fabs(mGradient[i]) > DBL_EPSILON)
            {
              if (mGradient[i] > 0)
                {
                  tmp = *(*mpOptItem)[i]->getUpperBoundValue();
                }

              else
                {
                  tmp = *(*mpOptItem)[i]->getLowerBoundValue();
                }

              // calculate the size of the largest jump
              tmp = (tmp - mIndividual[i]) / mGradient[i];
              // keep it if it is the smallest
              if (tmp < x0) x0 = tmp;
            }
          else mGradient[i] = 0.0;
        }

      // we will move at a rate of 1/10 this size
      mn = mx = alpha = 0.0;

      for (k = 0, calc_grad = false; (k < 9) && !calc_grad; k++)
        {
          // set the minimum to the last successful step
          mn = mx;
          fmn = fmx;
          // increment alpha
          alpha += 0.1 * x0;
          // set the maximum to it
          mx = alpha;
          // take one step in that direction
          for (i = 0, norm = 0.0; i < mVariableSize; i++)
            {
              (*(*mpSetCalculateVariable)[i])(mIndividual[i] + alpha * mGradient[i]);
              if ((daux = fabs(alpha * mGradient[i])) > norm) norm = daux;
            }

          fmx = evaluate();

          // if this was an upward step find the minimum
          if (fmx > fmn)
            {
              //md = mn + (mx-mn)/2;
              //Brent(mn, md, mx, descent_line, &alpha, &tmp, 1e-6, 50);

              FminBrent(mn, mx, mpDescent, &alpha, &tmp, mTolerance, 5);
              // take one step in that direction
              for (i = 0, norm = 0.0; i < mVariableSize; i++)
                {
                  (*(*mpSetCalculateVariable)[i])(mIndividual[i] + alpha * mGradient[i]);
                  if ((daux = fabs(alpha * mGradient[i])) > norm) norm = daux;
                }

              fmx = evaluate();

              // time to evaluate the new steepest descent direction
              calc_grad = true;
            }
          // check if this aproximation is good enough
          if (fabs(fmx - mBestValue) < mTolerance)
            //   if(norm < mTolerance)
            {
              mBestValue = fmx;
              for (i = 0; i < mVariableSize; i++)
                mIndividual[i] = *(*mpOptItem)[i]->getObjectValue();
              // an acceptable solution
              return true;
            }
        }
      // this is the best approximation thus far
      mBestValue = fmx;
      for (i = 0; i < mVariableSize; i++)
        mIndividual[i] = *(*mpOptItem)[i]->getObjectValue();

      //if(callback != NULL) callback(mBestValue);
      if (mValue < mBestValue && !isnan(mValue))
        {
          mBestValue = mValue;
          mpOptProblem->setSolutionVariables(mIndividual);
          mContinue = mpOptProblem->setSolutionValue(mBestValue);

          // We found a new best value lets report it.
          //if (mpReport) mpReport->printBody();
          mpParentTask->doOutput();
        }
    }

  return false;
}

bool COptMethodSteepestDescent::cleanup()
{
  // pdelete all used variables
  return true;
}

bool COptMethodSteepestDescent::initialize()
{
  if (!COptMethod::initialize()) return false;

  mIterations = * getValue("Iteration Limit").pUINT;
  mTolerance = * getValue("Tolerance").pDOUBLE;

  mContinue = true;
  mVariableSize = mpOptItem->size();
  mIndividual.resize(mVariableSize);
  mGradient.resize(mVariableSize);

  return true;
}

void COptMethodSteepestDescent::gradient()
{
  unsigned C_INT32 i;

  C_FLOAT64 y;
  C_FLOAT64 x;

  y = evaluate();

  for (i = 0; i < mVariableSize && mContinue; i++)
    {
      if ((x = *(*mpOptItem)[i]->getObjectValue()) != 0.0)
        {
          (*(*mpSetCalculateVariable)[i])(x * 1.001);
          mGradient[i] = (y - evaluate()) / (x * 0.001);
        }

      else
        {
          (*(*mpSetCalculateVariable)[i])(1e-7);
          mGradient[i] = (y - evaluate()) / 1e-7;
        }

      (*(*mpSetCalculateVariable)[i])(x);
    }
}

const C_FLOAT64 COptMethodSteepestDescent::descentLine(const C_FLOAT64 & x)
{
  for (C_INT32 i = 0; i < mVariableSize; i++)
    (*(*mpSetCalculateVariable)[i])(mIndividual[i] + x * mGradient[i]);

  return evaluate();
}

// evaluate the fitness of one individual
const C_FLOAT64 & COptMethodSteepestDescent::evaluate()
{
  // evaluate the fitness
  mContinue = mpOptProblem->calculate();

  // check wheter the functional constraints are fulfilled
  if (!mpOptProblem->checkFunctionalConstraints())
    mValue = DBL_MAX;
  else
    mValue = mpOptProblem->getCalculateValue();

  return mpOptProblem->getCalculateValue();
}

void COptMethodSteepestDescent::initObjects()
{
  addObjectReference("Current Iteration", mCurrentIteration, CCopasiObject::ValueInt);
}
<commit_msg>Adding the missing report case<commit_after>/* Begin CVS Header
   $Source: /Volumes/Home/Users/shoops/cvs/copasi_dev/copasi/optimization/COptMethodSteepestDescent.cpp,v $
   $Revision: 1.6 $
   $Name:  $
   $Author: anuragr $
   $Date: 2005/07/28 00:12:29 $
   End CVS Header */

#include "copasi.h"

#include "COptMethod.h"
#include "COptProblem.h"
#include "COptItem.h"
#include "COptTask.h"

#include "FminBrent.h"

#include "report/CCopasiObjectReference.h"

COptMethodSteepestDescent::COptMethodSteepestDescent(const CCopasiContainer * pParent):
    COptMethod(CCopasiMethod::SteepestDescent, pParent),
    mpDescent(new FDescentTemplate<COptMethodSteepestDescent>(this, &COptMethodSteepestDescent::descentLine))
{
  addParameter("Iteration Limit", CCopasiParameter::UINT, (unsigned C_INT32) 50);
  addParameter("Tolerance", CCopasiParameter::DOUBLE, (C_FLOAT64) 0.001);
}

COptMethodSteepestDescent::COptMethodSteepestDescent(const COptMethodSteepestDescent & src,
    const CCopasiContainer * pParent): COptMethod(src, pParent),
    mpDescent(new FDescentTemplate<COptMethodSteepestDescent>(this, &COptMethodSteepestDescent::descentLine))
{}

COptMethodSteepestDescent::~COptMethodSteepestDescent()
{
  pdelete(mpDescent);

  cleanup();
}

bool COptMethodSteepestDescent::setCallBack(CProcessReport * pCallBack)
{
  CCopasiMethod::setCallBack(pCallBack);

  /*  pCallBack->addItem(...);*/

  return true;
}

bool COptMethodSteepestDescent::optimise()
{
  if (!initialize()) return false;

  C_INT32 i, k;
  C_FLOAT64 tmp, x0, alpha, mn, mx, norm, daux, fmn, fmx;
  bool calc_grad;

  // initial point is first guess
  for (i = 0; i < mVariableSize; i++)
    mIndividual[i] = *(*mpOptItem)[i]->getObjectValue();

  fmx = mBestValue = evaluate();

  for (mCurrentIteration = 0; mCurrentIteration < mIterations && mContinue; mCurrentIteration++)
    {
      // calculate the direction of steepest descent
      // by central finite differences
      gradient();
      // minimise the function in this direction
      // find brackets for the minimisation
      //  mn = 0.0; md = 1.0;
      //  mnbrak(&mn, &md, &mx, &fmn, &fmd, &fmx, descent_line);
      // make sure that no parameter will exceed its bounds
      x0 = DBL_MAX;

      for (i = 0; i < mVariableSize; i++)
        {
          if (fabs(mGradient[i]) > DBL_EPSILON)
            {
              if (mGradient[i] > 0)
                {
                  tmp = *(*mpOptItem)[i]->getUpperBoundValue();
                }

              else
                {
                  tmp = *(*mpOptItem)[i]->getLowerBoundValue();
                }

              // calculate the size of the largest jump
              tmp = (tmp - mIndividual[i]) / mGradient[i];
              // keep it if it is the smallest
              if (tmp < x0) x0 = tmp;
            }
          else mGradient[i] = 0.0;
        }

      // we will move at a rate of 1/10 this size
      mn = mx = alpha = 0.0;

      for (k = 0, calc_grad = false; (k < 9) && !calc_grad; k++)
        {
          // set the minimum to the last successful step
          mn = mx;
          fmn = fmx;
          // increment alpha
          alpha += 0.1 * x0;
          // set the maximum to it
          mx = alpha;
          // take one step in that direction
          for (i = 0, norm = 0.0; i < mVariableSize; i++)
            {
              (*(*mpSetCalculateVariable)[i])(mIndividual[i] + alpha * mGradient[i]);
              if ((daux = fabs(alpha * mGradient[i])) > norm) norm = daux;
            }

          fmx = evaluate();

          // if this was an upward step find the minimum
          if (fmx > fmn)
            {
              //md = mn + (mx-mn)/2;
              //Brent(mn, md, mx, descent_line, &alpha, &tmp, 1e-6, 50);

              FminBrent(mn, mx, mpDescent, &alpha, &tmp, mTolerance, 5);
              // take one step in that direction
              for (i = 0, norm = 0.0; i < mVariableSize; i++)
                {
                  (*(*mpSetCalculateVariable)[i])(mIndividual[i] + alpha * mGradient[i]);
                  if ((daux = fabs(alpha * mGradient[i])) > norm) norm = daux;
                }

              fmx = evaluate();

              // time to evaluate the new steepest descent direction
              calc_grad = true;
            }
          // check if this aproximation is good enough
          if (fabs(fmx - mBestValue) < mTolerance)
            //   if(norm < mTolerance)
            {
              // an acceptable solution
              mBestValue = fmx;
              for (i = 0; i < mVariableSize; i++)
                mIndividual[i] = *(*mpOptItem)[i]->getObjectValue();
              mpOptProblem->setSolutionVariables(mIndividual);
              mContinue = mpOptProblem->setSolutionValue(mBestValue);
              mpParentTask->doOutput();
              return true;
            }
        }
      // this is the best approximation thus far
      mBestValue = fmx;
      for (i = 0; i < mVariableSize; i++)
        mIndividual[i] = *(*mpOptItem)[i]->getObjectValue();

      //if(callback != NULL) callback(mBestValue);
      if (mValue < mBestValue && !isnan(mValue))
        {
          mBestValue = mValue;
          mpOptProblem->setSolutionVariables(mIndividual);
          mContinue = mpOptProblem->setSolutionValue(mBestValue);

          // We found a new best value lets report it.
          //if (mpReport) mpReport->printBody();
          mpParentTask->doOutput();
        }
    }

  return false;
}

bool COptMethodSteepestDescent::cleanup()
{
  // pdelete all used variables
  return true;
}

bool COptMethodSteepestDescent::initialize()
{
  if (!COptMethod::initialize()) return false;

  mIterations = * getValue("Iteration Limit").pUINT;
  mTolerance = * getValue("Tolerance").pDOUBLE;

  mContinue = true;
  mVariableSize = mpOptItem->size();
  mIndividual.resize(mVariableSize);
  mGradient.resize(mVariableSize);

  return true;
}

void COptMethodSteepestDescent::gradient()
{
  unsigned C_INT32 i;

  C_FLOAT64 y;
  C_FLOAT64 x;

  y = evaluate();

  for (i = 0; i < mVariableSize && mContinue; i++)
    {
      if ((x = *(*mpOptItem)[i]->getObjectValue()) != 0.0)
        {
          (*(*mpSetCalculateVariable)[i])(x * 1.001);
          mGradient[i] = (y - evaluate()) / (x * 0.001);
        }

      else
        {
          (*(*mpSetCalculateVariable)[i])(1e-7);
          mGradient[i] = (y - evaluate()) / 1e-7;
        }

      (*(*mpSetCalculateVariable)[i])(x);
    }
}

const C_FLOAT64 COptMethodSteepestDescent::descentLine(const C_FLOAT64 & x)
{
  for (C_INT32 i = 0; i < mVariableSize; i++)
    (*(*mpSetCalculateVariable)[i])(mIndividual[i] + x * mGradient[i]);

  return evaluate();
}

// evaluate the fitness of one individual
const C_FLOAT64 & COptMethodSteepestDescent::evaluate()
{
  // evaluate the fitness
  mContinue = mpOptProblem->calculate();

  // check wheter the functional constraints are fulfilled
  if (!mpOptProblem->checkFunctionalConstraints())
    mValue = DBL_MAX;
  else
    mValue = mpOptProblem->getCalculateValue();

  return mpOptProblem->getCalculateValue();
}

void COptMethodSteepestDescent::initObjects()
{
  addObjectReference("Current Iteration", mCurrentIteration, CCopasiObject::ValueInt);
}
<|endoftext|>


<commit_before>#ifndef BROKER_H_
#define BROKER_H_

#include "dtypes.hpp"
#include "message.hpp"
#include <vector>
#include <deque>
#include <string>
#include <unordered_map>
#include <memory>
#include <boost/algorithm/string.hpp>

class MqttSubscriber {
public:
    virtual void newMessage(const std::string& topic, const std::vector<ubyte>& payload) = 0;
};

using TopicParts = std::deque<std::string>;

class OldSubscription {
public:

    friend class SubscriptionTree;

    OldSubscription(MqttSubscriber& subscriber, MqttSubscribe::Topic topic,
                 TopicParts topicParts);

    void newMessage(const std::string& topic, const std::vector<ubyte>& payload);

    bool isSubscriber(const MqttSubscriber& subscriber) const;
    bool isSubscription(const MqttSubscriber& subscriber,
                        std::vector<std::string> topics) const;
    bool isTopic(const std::vector<std::string>& topics) const;

    ubyte qos() const { return _qos; }

private:
    MqttSubscriber& _subscriber;
    std::string _part;
    std::string _topic;
    ubyte _qos;
};

class SubscriptionTree {
private:

    struct Node {
        using NodePtr = Node*;
        Node(std::string pt, NodePtr pr):part(pt), parent(pr) {}
        ~Node() { for(auto l: leaves) delete l; }
        std::string part;
        NodePtr parent;
        std::unordered_map<std::string, NodePtr> branches;
        std::vector<OldSubscription*> leaves;
    };

public:

    using NodePtr = Node::NodePtr;

    SubscriptionTree();

    void addSubscription(OldSubscription* s, const TopicParts& parts);
    void removeSubscription(MqttSubscriber& subscriber,
                            std::unordered_map<std::string, NodePtr>& nodes);
    void removeSubscription(MqttSubscriber& subscriber,
                            std::vector<std::string> topic,
                            std::unordered_map<std::string, NodePtr>& nodes);
    void publish(std::string topic, TopicParts topParts,
                 const std::vector<ubyte>& payload);
    void publish(std::string topic,
                 TopicParts::const_iterator topPartsBegin,
                 TopicParts::const_iterator topPartsEnd,
                 const std::vector<ubyte>& payload,
                 std::unordered_map<std::string, NodePtr>& nodes);
    void publishLeaves(std::string topic, const std::vector<ubyte>& payload,
                       TopicParts::const_iterator topPartsBegin,
                       TopicParts::const_iterator topPartsEnd,
                       std::vector<OldSubscription*> subscriptions);
    void publishLeaf(OldSubscription* sub, std::string topic, const std::vector<ubyte>& payload);
    void useCache(bool u) { _useCache = u; }

    bool _useCache;
    std::unordered_map<std::string, std::vector<OldSubscription*>> _cache;
    std::unordered_map<std::string, NodePtr> _nodes;
    friend class OldMqttBroker;

    void addSubscriptionImpl(OldSubscription* s,
                             TopicParts parts,
                             NodePtr parent,
                             std::unordered_map<std::string, NodePtr>& nodes);
    NodePtr addOrFindNode(std::string part, NodePtr parent,
                        std::unordered_map<std::string, NodePtr>& nodes);
    void clearCache() { if(_useCache) _cache.clear(); }

    void removeNode(NodePtr parent, NodePtr child);
};

class OldMqttBroker {
public:

    void subscribe(MqttSubscriber& subscriber, std::vector<std::string> topics);
    void subscribe(MqttSubscriber& subscriber, std::vector<MqttSubscribe::Topic> topics);
    void unsubscribe(MqttSubscriber& subscriber);
    void unsubscribe(MqttSubscriber& subscriber, std::vector<std::string> topics);
    void publish(const std::string& topic, const std::string& payload);
    void publish(const std::string& topic, const std::vector<ubyte>& payload);

    void useCache(bool u) { _subscriptions.useCache(u); }

private:

    SubscriptionTree _subscriptions;

    void publish(const std::string& topic,
                 const TopicParts& topParts,
                 const std::vector<ubyte>& payload);
};

using NodePtr = SubscriptionTree::NodePtr;

#include "string_span.h"

template<typename S> class Subscription;

template<typename S>
class MqttBroker {
public:

    MqttBroker(bool useCache):
        _useCache{useCache}
    {
    }

    void publish(gsl::cstring_span<> topic, gsl::span<ubyte> bytes) {
        (void)topic;
        (void)bytes;
    }

    void subscribe(S& subscriber, std::vector<std::string> topics) {
        invalidateCache();
        for(const auto& topic: topics) {
            std::deque<std::string> subParts;
            boost::split(subParts, topic, boost::is_any_of("/"));
            auto node = addOrFindNode(_tree, subParts);
            node.leaves.emplace_back(Subscription<S>{subscriber, topic});
        }
    }

private:

    struct Node {
        std::unordered_map<std::string, Node*> children;
        std::vector<Subscription<S>> leaves;
    };

    bool _useCache;
    std::unordered_map<std::string, S&> _cache;
    Node _tree;

    void invalidateCache() {
        if(_useCache) _cache.clear();
    }

    static Node& addOrFindNode(Node& tree, std::deque<std::string>& parts) {
        if(parts.size() == 0) return tree;

        const auto& part = parts[0];
        //create if not already here
        if(tree.children.find(part) == tree.children.end()) {
            tree.children[part] = new Node{};
        }

        parts.pop_front();
        return addOrFindNode(tree, parts);
    }
};

template<typename S>
class Subscription {
public:

    Subscription(S&, const std::string&) {
    }
};

#endif // BROKER_H_
<commit_msg>One test passes, the other fails<commit_after>#ifndef BROKER_H_
#define BROKER_H_

#include "dtypes.hpp"
#include "message.hpp"
#include <vector>
#include <deque>
#include <string>
#include <unordered_map>
#include <memory>
#include <boost/algorithm/string.hpp>

class MqttSubscriber {
public:
    virtual void newMessage(const std::string& topic, const std::vector<ubyte>& payload) = 0;
};

using TopicParts = std::deque<std::string>;

class OldSubscription {
public:

    friend class SubscriptionTree;

    OldSubscription(MqttSubscriber& subscriber, MqttSubscribe::Topic topic,
                 TopicParts topicParts);

    void newMessage(const std::string& topic, const std::vector<ubyte>& payload);

    bool isSubscriber(const MqttSubscriber& subscriber) const;
    bool isSubscription(const MqttSubscriber& subscriber,
                        std::vector<std::string> topics) const;
    bool isTopic(const std::vector<std::string>& topics) const;

    ubyte qos() const { return _qos; }

private:
    MqttSubscriber& _subscriber;
    std::string _part;
    std::string _topic;
    ubyte _qos;
};

class SubscriptionTree {
private:

    struct Node {
        using NodePtr = Node*;
        Node(std::string pt, NodePtr pr):part(pt), parent(pr) {}
        ~Node() { for(auto l: leaves) delete l; }
        std::string part;
        NodePtr parent;
        std::unordered_map<std::string, NodePtr> branches;
        std::vector<OldSubscription*> leaves;
    };

public:

    using NodePtr = Node::NodePtr;

    SubscriptionTree();

    void addSubscription(OldSubscription* s, const TopicParts& parts);
    void removeSubscription(MqttSubscriber& subscriber,
                            std::unordered_map<std::string, NodePtr>& nodes);
    void removeSubscription(MqttSubscriber& subscriber,
                            std::vector<std::string> topic,
                            std::unordered_map<std::string, NodePtr>& nodes);
    void publish(std::string topic, TopicParts topParts,
                 const std::vector<ubyte>& payload);
    void publish(std::string topic,
                 TopicParts::const_iterator topPartsBegin,
                 TopicParts::const_iterator topPartsEnd,
                 const std::vector<ubyte>& payload,
                 std::unordered_map<std::string, NodePtr>& nodes);
    void publishLeaves(std::string topic, const std::vector<ubyte>& payload,
                       TopicParts::const_iterator topPartsBegin,
                       TopicParts::const_iterator topPartsEnd,
                       std::vector<OldSubscription*> subscriptions);
    void publishLeaf(OldSubscription* sub, std::string topic, const std::vector<ubyte>& payload);
    void useCache(bool u) { _useCache = u; }

    bool _useCache;
    std::unordered_map<std::string, std::vector<OldSubscription*>> _cache;
    std::unordered_map<std::string, NodePtr> _nodes;
    friend class OldMqttBroker;

    void addSubscriptionImpl(OldSubscription* s,
                             TopicParts parts,
                             NodePtr parent,
                             std::unordered_map<std::string, NodePtr>& nodes);
    NodePtr addOrFindNode(std::string part, NodePtr parent,
                        std::unordered_map<std::string, NodePtr>& nodes);
    void clearCache() { if(_useCache) _cache.clear(); }

    void removeNode(NodePtr parent, NodePtr child);
};

class OldMqttBroker {
public:

    void subscribe(MqttSubscriber& subscriber, std::vector<std::string> topics);
    void subscribe(MqttSubscriber& subscriber, std::vector<MqttSubscribe::Topic> topics);
    void unsubscribe(MqttSubscriber& subscriber);
    void unsubscribe(MqttSubscriber& subscriber, std::vector<std::string> topics);
    void publish(const std::string& topic, const std::string& payload);
    void publish(const std::string& topic, const std::vector<ubyte>& payload);

    void useCache(bool u) { _subscriptions.useCache(u); }

private:

    SubscriptionTree _subscriptions;

    void publish(const std::string& topic,
                 const TopicParts& topParts,
                 const std::vector<ubyte>& payload);
};

using NodePtr = SubscriptionTree::NodePtr;

#include "string_span.h"

template<typename S> class Subscription;

template<typename S>
class MqttBroker {
public:

    MqttBroker(bool useCache):
        _useCache{useCache}
    {
    }

    void publish(gsl::cstring_span<> topic, gsl::span<ubyte> bytes) {
        std::deque<std::string> pubParts;
        const auto topicStr = gsl::to_string(topic);
        boost::split(pubParts, topicStr, boost::is_any_of("/"));
        publishImpl(_tree, pubParts, topicStr, bytes);
    }

    void subscribe(S& subscriber, std::vector<std::string> topics) {
        std::vector<MqttSubscribe::Topic> newTopics(topics.size());
        std::transform(topics.cbegin(), topics.cend(), newTopics.begin(),
                       [](auto t) { return MqttSubscribe::Topic(t, 0); });
        subscribe(subscriber, newTopics);
    }

    void subscribe(S& subscriber, std::vector<MqttSubscribe::Topic> topics) {
        invalidateCache();
        for(const auto& topic: topics) {
            std::deque<std::string> subParts;
            boost::split(subParts, topic.topic, boost::is_any_of("/"));
            auto node = addOrFindNode(_tree, subParts);
            node.leaves.emplace_back(Subscription<S>{subscriber, topic.topic});
        }
    }

private:

    struct Node;
    using NodePtr = std::shared_ptr<Node>;

    struct Node {
        std::unordered_map<std::string, NodePtr> children;
        std::vector<Subscription<S>> leaves;
    };

    bool _useCache;
    std::unordered_map<std::string, std::vector<S*>> _cache;
    Node _tree;

    void invalidateCache() {
        if(_useCache) _cache.clear();
    }

    static Node& addOrFindNode(Node& tree, std::deque<std::string>& parts) {
        if(parts.size() == 0) return tree;

        const auto& part = parts[0];
        //create if not already here
        if(tree.children.find(part) == tree.children.end()) {
            tree.children.emplace(part, std::make_shared<Node>());
        }

        parts.pop_front();
        return addOrFindNode(tree, parts);
    }

    void publishImpl(Node& tree, std::deque<std::string>& pubParts, const std::string& topic, gsl::span<ubyte> bytes) {

        if(_useCache && _cache.find(topic) != _cache.end()) {
            for(auto subscriber: _cache[topic]) subscriber->newMessage(bytes);
            return;
        }

        if(pubParts.size() == 0) return;

        const auto front = pubParts[0];
        pubParts.pop_front();

        for(const auto& part: std::vector<std::string>{front, "#", "+"}) {
            if(tree.children.find(part) != tree.children.end()) {
                auto& node = *tree.children[part];
                if(pubParts.size() == 0 || part == "#") publishNode(node, topic, bytes);

                if(pubParts.size() == 0 && node.children.find("#") != node.children.end()) {
                    //So that "finance/#" matches "finance"
                    publishNode(*node.children["#"], topic, bytes);
                }

                publishImpl(node, pubParts, topic, bytes);
           }
        }
    }

    void publishNode(Node& node, const std::string& topic, gsl::span<ubyte> bytes) {
        for(auto& subscription: node.leaves) {
            subscription.subscriber.newMessage(bytes);
            if(_useCache) _cache[topic].emplace_back(&subscription.subscriber);
        }
    }
};

template<typename S>
class Subscription {
public:

    Subscription(S& subscriber, gsl::cstring_span<> topic):
        subscriber{subscriber}, topic{topic} {
    }

    S& subscriber;
    std::string topic;
};

#endif // BROKER_H_
<|endoftext|>