<commit_before>/*
 * Copyright (c) 2007-2008 Mauro Iazzi
 *
 * 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.
 *
 */

#ifndef __LQT_COMMON_HPP
#define __LQT_COMMON_HPP

extern "C" {
#include <lua.h>
#include <lualib.h>
#include <lauxlib.h>
}

//#include <iostream>

//#define lqtL_register(L, p, n) ( (void)L, (void)p, (void)n )
//#define lqtL_unregister(L, p) ( (void)L, (void)p )

#define LQT_POINTERS "Registry Pointers"
#define LQT_REFS "Registry References"
#define LQT_ENUMS "Registry Enumerations"

extern void lqtL_register(lua_State *, const void *);
extern void lqtL_unregister(lua_State *, const void *);

//extern int& lqtL_tointref (lua_State *, int);

//extern void lqtL_pusharguments (lua_State *, char**);
//extern char** lqtL_toarguments (lua_State *, int);
//extern bool lqtL_testarguments (lua_State *, int);

//extern void lqtL_manageudata (lua_State *, int);
//extern void lqtL_unmanageudata (lua_State *, int);
extern void lqtL_pushudata (lua_State *, const void *, const char *);
extern void lqtL_passudata (lua_State *, const void *, const char *);
extern void lqtL_copyudata (lua_State *, const void *, const char *);
extern void * lqtL_toudata (lua_State *, int, const char *);
extern bool lqtL_testudata (lua_State *, int, const char *);
//#define lqtL_checkudata(a...) luaL_checkudata(a)
extern void * lqtL_checkudata (lua_State *, int, const char *);
#define lqtL_isudata lqtL_testudata

extern void lqtL_pushenum (lua_State *, int, const char *);
extern bool lqtL_isenum (lua_State *, int, const char *);
extern int lqtL_toenum (lua_State *, int, const char *);

extern bool lqtL_isinteger (lua_State *, int);
extern bool lqtL_isnumber (lua_State *, int);
extern bool lqtL_isstring (lua_State *, int);
extern bool lqtL_isboolean (lua_State *, int);

extern bool lqtL_missarg (lua_State *, int, int);
//extern int lqtL_baseindex (lua_State *, int, int);

//extern int lqtL_gc (lua_State *);
//extern int lqtL_index (lua_State *);
//extern int lqtL_newindex (lua_State *);

typedef struct {
	const char *name;
	int value;
} lqt_Enum;

typedef struct {
	lqt_Enum *enums;
	const char *name;
} lqt_Enumlist;

extern int lqtL_createenumlist (lua_State *, lqt_Enumlist[]);

typedef struct {
	const char *basename;
} lqt_Base;

typedef struct {
	luaL_Reg *mt;
	lqt_Base *bases;
	const char * name;
} lqt_Class;

extern int lqtL_createclasses (lua_State *, lqt_Class *);
extern int lqtL_createclass (lua_State *, const char *, luaL_Reg *, lqt_Base *);

/* functions to get/push special types */

extern void * lqtL_getref (lua_State *, size_t);
extern int * lqtL_tointref (lua_State *, int);
extern char ** lqtL_toarguments (lua_State *, int);
extern void lqtL_pusharguments (lua_State *, char **);

extern int lqtL_getflags (lua_State *, int, const char *);
extern void lqtL_pushflags (lua_State *, int, const char *);

extern "C" int luaopen_qtbase (lua_State *);

#endif // __LQT_COMMON_HPP

<commit_msg>added the offset in the structure that describes bases<commit_after>/*
 * Copyright (c) 2007-2008 Mauro Iazzi
 *
 * 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.
 *
 */

#ifndef __LQT_COMMON_HPP
#define __LQT_COMMON_HPP

extern "C" {
#include <lua.h>
#include <lualib.h>
#include <lauxlib.h>
}

//#include <iostream>

//#define lqtL_register(L, p, n) ( (void)L, (void)p, (void)n )
//#define lqtL_unregister(L, p) ( (void)L, (void)p )

#define LQT_POINTERS "Registry Pointers"
#define LQT_REFS "Registry References"
#define LQT_ENUMS "Registry Enumerations"

extern void lqtL_register(lua_State *, const void *);
extern void lqtL_unregister(lua_State *, const void *);

//extern int& lqtL_tointref (lua_State *, int);

//extern void lqtL_pusharguments (lua_State *, char**);
//extern char** lqtL_toarguments (lua_State *, int);
//extern bool lqtL_testarguments (lua_State *, int);

//extern void lqtL_manageudata (lua_State *, int);
//extern void lqtL_unmanageudata (lua_State *, int);
extern void lqtL_pushudata (lua_State *, const void *, const char *);
extern void lqtL_passudata (lua_State *, const void *, const char *);
extern void lqtL_copyudata (lua_State *, const void *, const char *);
extern void * lqtL_toudata (lua_State *, int, const char *);
extern bool lqtL_testudata (lua_State *, int, const char *);
//#define lqtL_checkudata(a...) luaL_checkudata(a)
extern void * lqtL_checkudata (lua_State *, int, const char *);
#define lqtL_isudata lqtL_testudata

extern void lqtL_pushenum (lua_State *, int, const char *);
extern bool lqtL_isenum (lua_State *, int, const char *);
extern int lqtL_toenum (lua_State *, int, const char *);

extern bool lqtL_isinteger (lua_State *, int);
extern bool lqtL_isnumber (lua_State *, int);
extern bool lqtL_isstring (lua_State *, int);
extern bool lqtL_isboolean (lua_State *, int);

extern bool lqtL_missarg (lua_State *, int, int);
//extern int lqtL_baseindex (lua_State *, int, int);

//extern int lqtL_gc (lua_State *);
//extern int lqtL_index (lua_State *);
//extern int lqtL_newindex (lua_State *);

typedef struct {
	const char *name;
	int value;
} lqt_Enum;

typedef struct {
	lqt_Enum *enums;
	const char *name;
} lqt_Enumlist;

extern int lqtL_createenumlist (lua_State *, lqt_Enumlist[]);

typedef struct {
	const char *basename;
	ptrdiff_t offset;
} lqt_Base;

typedef struct {
	luaL_Reg *mt;
	lqt_Base *bases;
	const char * name;
} lqt_Class;

extern int lqtL_createclasses (lua_State *, lqt_Class *);
extern int lqtL_createclass (lua_State *, const char *, luaL_Reg *, lqt_Base *);

/* functions to get/push special types */

extern void * lqtL_getref (lua_State *, size_t);
extern int * lqtL_tointref (lua_State *, int);
extern char ** lqtL_toarguments (lua_State *, int);
extern void lqtL_pusharguments (lua_State *, char **);

extern int lqtL_getflags (lua_State *, int, const char *);
extern void lqtL_pushflags (lua_State *, int, const char *);

extern "C" int luaopen_qtbase (lua_State *);

#endif // __LQT_COMMON_HPP

<|endoftext|>


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

#include "SoundDataWave.h"
#include "core/Application.h"
#include "files/FileSystem.h"
#include "utils/Log.h"
#include "utils/Utils.h"

namespace ouzel
{
    namespace audio
    {
        SoundDataWave::SoundDataWave()
        {
        }

        SoundDataWave::~SoundDataWave()
        {
        }

        bool SoundDataWave::initFromFile(const std::string& newFilename)
        {
            filename = newFilename;

            std::vector<uint8_t> newData;
            if (!sharedApplication->getFileSystem()->readFile(newFilename, newData))
            {
                return false;
            }

            return initFromBuffer(newData);
        }

        bool SoundDataWave::initFromBuffer(const std::vector<uint8_t>& newData)
        {
            ready = false;

            uint32_t offset = 0;

            if (newData.size() < 16) // RIFF + size + WAVE
            {
                Log(Log::Level::ERR) << "Failed to load sound file, file too small";
                return false;
            }

            if (newData[offset + 0] != 'R' ||
                newData[offset + 1] != 'I' ||
                newData[offset + 2] != 'F' ||
                newData[offset + 3] != 'F')
            {
                Log(Log::Level::ERR) << "Failed to load sound file, not a RIFF format";
                return false;
            }

            offset += 4;

            uint32_t length = decodeUInt32Little(newData.data() + offset);

            offset += 4;

            if (newData.size() != length + 8)
            {
                Log(Log::Level::ERR) << "Failed to load sound file, size mismatch";
            }

            if (newData[offset + 0] != 'W' ||
                newData[offset + 1] != 'A' ||
                newData[offset + 2] != 'V' ||
                newData[offset + 3] != 'E')
            {
                Log(Log::Level::ERR) << "Failed to load sound file, not a WAVE file";
                return false;
            }

            offset += 4;

            bool formatChunkFound = false;
            bool dataChunkFound = false;

            uint16_t bitsPerSample = 0;
            std::vector<uint8_t> soundData;

            for (; offset < newData.size();)
            {
                if (newData.size() < offset + 8)
                {
                    Log(Log::Level::ERR) << "Failed to load sound file, not enough data to read chunk";
                    return false;
                }

                uint8_t chunkHeader[4];
                chunkHeader[0] = newData[offset + 0];
                chunkHeader[1] = newData[offset + 1];
                chunkHeader[2] = newData[offset + 2];
                chunkHeader[3] = newData[offset + 3];

                offset += 4;

                uint32_t chunkSize = decodeUInt32Little(newData.data() + offset);
                offset += 4;

                if (newData.size() < offset + chunkSize)
                {
                    Log(Log::Level::ERR) << "Failed to load sound file, not enough data to read chunk";
                    return false;
                }

                if (chunkHeader[0] == 'f' && chunkHeader[1] == 'm' && chunkHeader[2] == 't' && chunkHeader[3] == ' ')
                {
                    if (chunkSize < 16)
                    {
                        Log(Log::Level::ERR) << "Failed to load sound file, not enough data to read chunk";
                        return false;
                    }

                    uint32_t i = offset;

                    formatTag = decodeUInt16Little(newData.data() + i);
                    i += 2;

                    if (formatTag != 1)
                    {
                        Log(Log::Level::ERR) << "Failed to load sound file, bad format tag";
                        return false;
                    }

                    channels = decodeUInt16Little(newData.data() + i);
                    i += 2;

                    samplesPerSecond = decodeUInt32Little(newData.data() + i);
                    i += 4;

                    i += 4; // average bytes per second

                    i += 2; // block align

                    bitsPerSample = decodeUInt16Little(newData.data() + i);
                    i += 2;

                    formatChunkFound = true;
                }
                else if (chunkHeader[0] == 'd' && chunkHeader[1] == 'a' && chunkHeader[2] == 't' && chunkHeader[3] == 'a')
                {
                    soundData.assign(newData.begin() + static_cast<int>(offset), newData.begin() + static_cast<int>(offset + chunkSize));

                    dataChunkFound = true;
                }

                offset += ((chunkSize + 1) & 0xFFFFFFFE);
            }

            if (!formatChunkFound)
            {
                Log(Log::Level::ERR) << "Failed to load sound file, failed to find a format chunk";
                return false;
            }

            if (!dataChunkFound)
            {
                Log(Log::Level::ERR) << "Failed to load sound file, failed to find a data chunk";
                return false;
            }

            if (bitsPerSample != 8 && bitsPerSample != 16 &&
                bitsPerSample != 24 && bitsPerSample != 32)
            {
                Log(Log::Level::ERR) << "Failed to load sound file, unsupported bit depth";
                return false;
            }

            if (bitsPerSample == 16)
            {
                data = std::move(soundData);
            }
            else
            {
                uint32_t bytesPerSample = bitsPerSample / 8;
                uint32_t samples = static_cast<uint32_t>(soundData.size() / bytesPerSample);

                for (uint32_t position = 0; position < samples * bytesPerSample; position += bytesPerSample)
                {
                    int16_t sample = 0;

                    if (bitsPerSample < 16) // signed 8-bit sample
                    {
                        sample = static_cast<int16_t>((static_cast<int32_t>(soundData[position]) << (16 - bitsPerSample)) - 32768);
                    }
                    else if (bitsPerSample > 16)
                    {
                        sample = static_cast<int16_t>(static_cast<int32_t>(soundData[position + bytesPerSample - 2]) |
                                                      static_cast<int32_t>(soundData[position + bytesPerSample - 1]) << 8);
                    }

                    // encode sample as little endian integer
                    data.push_back(static_cast<uint8_t>(sample));
                    data.push_back(static_cast<uint8_t>(sample >> 8));
                }
            }

            ready = true;

            return true;
        }

        void SoundDataWave::getData(std::vector<uint8_t>& buffer)
        {
            buffer = data;
        }
    } // namespace audio
} // namespace ouzel
<commit_msg>Reserve the buffer for PCM data<commit_after>// Copyright (C) 2017 Elviss Strazdins
// This file is part of the Ouzel engine.

#include "SoundDataWave.h"
#include "core/Application.h"
#include "files/FileSystem.h"
#include "utils/Log.h"
#include "utils/Utils.h"

namespace ouzel
{
    namespace audio
    {
        SoundDataWave::SoundDataWave()
        {
        }

        SoundDataWave::~SoundDataWave()
        {
        }

        bool SoundDataWave::initFromFile(const std::string& newFilename)
        {
            filename = newFilename;

            std::vector<uint8_t> newData;
            if (!sharedApplication->getFileSystem()->readFile(newFilename, newData))
            {
                return false;
            }

            return initFromBuffer(newData);
        }

        bool SoundDataWave::initFromBuffer(const std::vector<uint8_t>& newData)
        {
            ready = false;

            uint32_t offset = 0;

            if (newData.size() < 16) // RIFF + size + WAVE
            {
                Log(Log::Level::ERR) << "Failed to load sound file, file too small";
                return false;
            }

            if (newData[offset + 0] != 'R' ||
                newData[offset + 1] != 'I' ||
                newData[offset + 2] != 'F' ||
                newData[offset + 3] != 'F')
            {
                Log(Log::Level::ERR) << "Failed to load sound file, not a RIFF format";
                return false;
            }

            offset += 4;

            uint32_t length = decodeUInt32Little(newData.data() + offset);

            offset += 4;

            if (newData.size() != length + 8)
            {
                Log(Log::Level::ERR) << "Failed to load sound file, size mismatch";
            }

            if (newData[offset + 0] != 'W' ||
                newData[offset + 1] != 'A' ||
                newData[offset + 2] != 'V' ||
                newData[offset + 3] != 'E')
            {
                Log(Log::Level::ERR) << "Failed to load sound file, not a WAVE file";
                return false;
            }

            offset += 4;

            bool formatChunkFound = false;
            bool dataChunkFound = false;

            uint16_t bitsPerSample = 0;
            std::vector<uint8_t> soundData;

            for (; offset < newData.size();)
            {
                if (newData.size() < offset + 8)
                {
                    Log(Log::Level::ERR) << "Failed to load sound file, not enough data to read chunk";
                    return false;
                }

                uint8_t chunkHeader[4];
                chunkHeader[0] = newData[offset + 0];
                chunkHeader[1] = newData[offset + 1];
                chunkHeader[2] = newData[offset + 2];
                chunkHeader[3] = newData[offset + 3];

                offset += 4;

                uint32_t chunkSize = decodeUInt32Little(newData.data() + offset);
                offset += 4;

                if (newData.size() < offset + chunkSize)
                {
                    Log(Log::Level::ERR) << "Failed to load sound file, not enough data to read chunk";
                    return false;
                }

                if (chunkHeader[0] == 'f' && chunkHeader[1] == 'm' && chunkHeader[2] == 't' && chunkHeader[3] == ' ')
                {
                    if (chunkSize < 16)
                    {
                        Log(Log::Level::ERR) << "Failed to load sound file, not enough data to read chunk";
                        return false;
                    }

                    uint32_t i = offset;

                    formatTag = decodeUInt16Little(newData.data() + i);
                    i += 2;

                    if (formatTag != 1)
                    {
                        Log(Log::Level::ERR) << "Failed to load sound file, bad format tag";
                        return false;
                    }

                    channels = decodeUInt16Little(newData.data() + i);
                    i += 2;

                    samplesPerSecond = decodeUInt32Little(newData.data() + i);
                    i += 4;

                    i += 4; // average bytes per second

                    i += 2; // block align

                    bitsPerSample = decodeUInt16Little(newData.data() + i);
                    i += 2;

                    formatChunkFound = true;
                }
                else if (chunkHeader[0] == 'd' && chunkHeader[1] == 'a' && chunkHeader[2] == 't' && chunkHeader[3] == 'a')
                {
                    soundData.assign(newData.begin() + static_cast<int>(offset), newData.begin() + static_cast<int>(offset + chunkSize));

                    dataChunkFound = true;
                }

                offset += ((chunkSize + 1) & 0xFFFFFFFE);
            }

            if (!formatChunkFound)
            {
                Log(Log::Level::ERR) << "Failed to load sound file, failed to find a format chunk";
                return false;
            }

            if (!dataChunkFound)
            {
                Log(Log::Level::ERR) << "Failed to load sound file, failed to find a data chunk";
                return false;
            }

            if (bitsPerSample != 8 && bitsPerSample != 16 &&
                bitsPerSample != 24 && bitsPerSample != 32)
            {
                Log(Log::Level::ERR) << "Failed to load sound file, unsupported bit depth";
                return false;
            }

            if (bitsPerSample == 16)
            {
                data = std::move(soundData);
            }
            else
            {
                uint32_t bytesPerSample = bitsPerSample / 8;
                uint32_t samples = static_cast<uint32_t>(soundData.size() / bytesPerSample);

                data.reserve(samples * 2);

                for (uint32_t position = 0; position < samples * bytesPerSample; position += bytesPerSample)
                {
                    int16_t sample = 0;

                    if (bitsPerSample < 16) // signed 8-bit sample
                    {
                        sample = static_cast<int16_t>((static_cast<int32_t>(soundData[position]) << (16 - bitsPerSample)) - 32768);
                    }
                    else if (bitsPerSample > 16)
                    {
                        sample = static_cast<int16_t>(static_cast<int32_t>(soundData[position + bytesPerSample - 2]) |
                                                      static_cast<int32_t>(soundData[position + bytesPerSample - 1]) << 8);
                    }

                    // encode sample as little endian integer
                    data.push_back(static_cast<uint8_t>(sample));
                    data.push_back(static_cast<uint8_t>(sample >> 8));
                }
            }

            ready = true;

            return true;
        }

        void SoundDataWave::getData(std::vector<uint8_t>& buffer)
        {
            buffer = data;
        }
    } // namespace audio
} // namespace ouzel
<|endoftext|>


<commit_before>#include "persistence/sqlite/sqlitebackend.h"

#include <cassert>

namespace persistence
{
  namespace detail
  {
    bool DataStreamManager::collectNewStreams()
    {
      assert(_uninitializedStreams.size() == 0);
      std::swap(_uninitializedStreams, _newStreams);
      return !_uninitializedStreams.empty();
    }

    template<class Func>
    void DataStreamManager::initialize(Func initializerFunction)
    {
      for (auto& uninitializedStream : _uninitializedStreams)
      {
        boost::apply_visitor([&](auto& stream) { initializerFunction(*stream); }, uninitializedStream);
        _activeStreams.push_back(std::move(uninitializedStream));
      }
      _uninitializedStreams.clear();
    }

    template<class T, class Func>
    void DataStreamManager::foreachActiveStream(Func func)
    {
      for (auto& activeStream : _activeStreams)
      {
        if (activeStream.type() == typeid(std::shared_ptr<DataStream<T>>))
          func(*boost::get<std::shared_ptr<DataStream<T>>>(activeStream));
      }
    }
  } // namespace detail

  namespace sqlite
  {
    SqliteBackend::SqliteBackend(const std::string& databasePath)
        : _storage(databasePath), _nextOperationId(1), _backendThread(), _quitBackendThread(false),
          _workAvailableCondition(), _queueMutex(), _operationsQueue()
    {
    }

    op::Task<op::OperationResults> SqliteBackend::queueOperation(op::Operations operations)
    {
      // Create a task
      auto sharedState = std::make_shared<op::TaskSharedState<op::OperationResults>>(_nextOperationId++);
      op::Task<op::OperationResults> task(sharedState);

      std::unique_lock<std::mutex> lock(_queueMutex);
      auto pair = QueuedOperation{std::move(operations), sharedState};
      _operationsQueue.push_back(std::move(pair));
      lock.unlock();
      _workAvailableCondition.notify_one();

      return task;
    }

    void SqliteBackend::start(persistence::ResultIntegrator& resultIntegrator)
    {
      assert(!_backendThread.joinable());
      _backendThread = std::thread([this, &resultIntegrator]() { this->threadMain(resultIntegrator); });
    }

    void SqliteBackend::stopAndJoin()
    {
      assert(_backendThread.joinable());

      _quitBackendThread = true;
      _workAvailableCondition.notify_one();
      _backendThread.join();
    }

    void SqliteBackend::threadMain(persistence::ResultIntegrator& resultIntegrator)
    {
      while (!_quitBackendThread)
      {
        // Get the tasks we are going to process (This is the only part which is guarded by the mutex)
        std::unique_lock<std::mutex> lock(_queueMutex);
        std::vector<QueuedOperation> newTasks;
        std::swap(newTasks, _operationsQueue);
        const bool hasUninitializedStreams = _dataStreams.collectNewStreams();
        // Sleep until there is work to do
        if (newTasks.empty() && !hasUninitializedStreams)
          _workAvailableCondition.wait(lock);
        lock.unlock();

        // Initialize new data streams
        _dataStreams.initialize([this](auto& stream) { initializeStream(stream); });

        // Process tasks
        for (auto& operationsMessage : newTasks)
        {
          op::OperationResults results;
          _storage.beginTransaction();
          for (auto& operation : operationsMessage.first)
            boost::apply_visitor([this, &results](auto& op) { return this->executeOperation(results, op); }, operation);
          _storage.commitTransaction();
          operationsMessage.second->setCompleted(std::move(results));
          _taskCompletedSignal(operationsMessage.second->uniqueId());
        }

        // Notify the client that the streams may have new data...
        // TODO: Signaling here is not ideal. We might trigger the signal even if nothing changed with the stream.
        _streamsUpdatedSignal();
      }
    }

    void SqliteBackend::executeOperation(op::OperationResults& results, op::EraseAllData&)
    {
      _storage.deleteAll();
      results.push_back(op::EraseAllDataResult());

      _dataStreams.foreachActiveStream<hotel::Reservation>([](DataStream<hotel::Reservation>& stream) { stream.clear(); });
      _dataStreams.foreachActiveStream<hotel::Hotel>([](DataStream<hotel::Hotel>& stream) { stream.clear(); });
    }

    void SqliteBackend::executeOperation(op::OperationResults& results, op::LoadInitialData&)
    {
      // TODO: Remove this! This makes no sense in a stream world!
      auto hotels = _storage.loadHotels();
      auto planning = _storage.loadPlanning(hotels->allRoomIDs());
      results.push_back(op::LoadInitialDataResult{std::move(hotels), std::move(planning)});
    }

    void SqliteBackend::executeOperation(op::OperationResults& results, op::StoreNewHotel& op)
    {
      assert(op.newHotel != nullptr);
      if (op.newHotel == nullptr)
        return;

      _storage.storeNewHotel(*op.newHotel);

      _dataStreams.foreachActiveStream<hotel::Hotel>([&op](DataStream<hotel::Hotel>& stream) { stream.addItems({*op.newHotel}); });
      results.push_back(op::StoreNewHotelResult{std::move(op.newHotel)});
    }

    void SqliteBackend::executeOperation(op::OperationResults& results, op::StoreNewReservation& op)
    {
      if (op.newReservation == nullptr)
        results.push_back(op::NoResult());

      // "Unknown" is not a valid reservation status for serialization
      if (op.newReservation->status() == hotel::Reservation::Unknown)
        op.newReservation->setStatus(hotel::Reservation::New);
      _storage.storeNewReservationAndAtoms(*op.newReservation);

      _dataStreams.foreachActiveStream<hotel::Reservation>([&op](DataStream<hotel::Reservation>& stream) { stream.addItems({*op.newReservation}); });
      results.push_back(op::StoreNewReservationResult{std::move(op.newReservation)});
    }

    void SqliteBackend::executeOperation(op::OperationResults& results, op::StoreNewPerson& op)
    {
      // TODO: Implement this
      std::cout << "STUB: This functionality has not yet been implemented..." << std::endl;

      results.push_back(op::NoResult());
    }

    void SqliteBackend::executeOperation(op::OperationResults& results, op::DeleteReservation& op)
    {
      _storage.deleteReservationById(op.reservationId);
      _dataStreams.foreachActiveStream<hotel::Reservation>([&op](DataStream<hotel::Reservation>& stream) { stream.removeItems({op.reservationId}); });
      results.push_back(op::DeleteReservationResult{op.reservationId});
    }

    void SqliteBackend::initializeStream(DataStream<hotel::Hotel>& dataStream)
    {
      // TODO: loadHotels() should already return the correct type!
      auto hotelsCollection = _storage.loadHotels();
      // Create a vector of hotels
      std::vector<hotel::Hotel> hotels;
      for (auto& hotel : hotelsCollection->hotels())
        hotels.push_back(*hotel);
      dataStream.addItems(std::move(hotels));
    }

    void SqliteBackend::initializeStream(DataStream<hotel::Reservation>& dataStream)
    {
      auto reservations = _storage.loadReservations();
      dataStream.addItems(std::move(*reservations));
    }

  } // namespace sqlite
} // namespace persistence
<commit_msg>Small change which should fix CI<commit_after>#include "persistence/sqlite/sqlitebackend.h"

#include <cassert>

namespace persistence
{
  namespace detail
  {
    bool DataStreamManager::collectNewStreams()
    {
      assert(_uninitializedStreams.size() == 0);
      std::swap(_uninitializedStreams, _newStreams);
      return !_uninitializedStreams.empty();
    }

    template<class Func>
    void DataStreamManager::initialize(Func initializerFunction)
    {
      for (auto& uninitializedStream : _uninitializedStreams)
      {
        boost::apply_visitor([&](auto& stream) { initializerFunction(*stream); }, uninitializedStream);
        _activeStreams.push_back(std::move(uninitializedStream));
      }
      _uninitializedStreams.clear();
    }

    template<class T, class Func>
    void DataStreamManager::foreachActiveStream(Func func)
    {
      for (auto& activeStream : _activeStreams)
      {
        if (activeStream.type() == typeid(std::shared_ptr<DataStream<T>>))
          func(*boost::get<std::shared_ptr<DataStream<T>>>(activeStream));
      }
    }
  } // namespace detail

  namespace sqlite
  {
    SqliteBackend::SqliteBackend(const std::string& databasePath)
        : _storage(databasePath), _nextOperationId(1), _backendThread(), _quitBackendThread(false),
          _workAvailableCondition(), _queueMutex(), _operationsQueue()
    {
    }

    op::Task<op::OperationResults> SqliteBackend::queueOperation(op::Operations operations)
    {
      // Create a task
      auto sharedState = std::make_shared<op::TaskSharedState<op::OperationResults>>(_nextOperationId++);
      op::Task<op::OperationResults> task(sharedState);

      std::unique_lock<std::mutex> lock(_queueMutex);
      auto pair = QueuedOperation{std::move(operations), sharedState};
      _operationsQueue.push_back(std::move(pair));
      lock.unlock();
      _workAvailableCondition.notify_one();

      return task;
    }

    void SqliteBackend::start(persistence::ResultIntegrator& resultIntegrator)
    {
      assert(!_backendThread.joinable());
      _backendThread = std::thread([this, &resultIntegrator]() { this->threadMain(resultIntegrator); });
    }

    void SqliteBackend::stopAndJoin()
    {
      assert(_backendThread.joinable());

      _quitBackendThread = true;
      _workAvailableCondition.notify_one();
      _backendThread.join();
    }

    void SqliteBackend::threadMain(persistence::ResultIntegrator& resultIntegrator)
    {
      while (!_quitBackendThread)
      {
        // Get the tasks we are going to process (This is the only part which is guarded by the mutex)
        std::unique_lock<std::mutex> lock(_queueMutex);
        std::vector<QueuedOperation> newTasks;
        std::swap(newTasks, _operationsQueue);
        const bool hasUninitializedStreams = _dataStreams.collectNewStreams();
        // Sleep until there is work to do
        if (newTasks.empty() && !hasUninitializedStreams)
          _workAvailableCondition.wait(lock);
        lock.unlock();

        // Initialize new data streams
        _dataStreams.initialize([this](auto& stream) { this->initializeStream(stream); });

        // Process tasks
        for (auto& operationsMessage : newTasks)
        {
          op::OperationResults results;
          _storage.beginTransaction();
          for (auto& operation : operationsMessage.first)
            boost::apply_visitor([this, &results](auto& op) { return this->executeOperation(results, op); }, operation);
          _storage.commitTransaction();
          operationsMessage.second->setCompleted(std::move(results));
          _taskCompletedSignal(operationsMessage.second->uniqueId());
        }

        // Notify the client that the streams may have new data...
        // TODO: Signaling here is not ideal. We might trigger the signal even if nothing changed with the stream.
        _streamsUpdatedSignal();
      }
    }

    void SqliteBackend::executeOperation(op::OperationResults& results, op::EraseAllData&)
    {
      _storage.deleteAll();
      results.push_back(op::EraseAllDataResult());

      _dataStreams.foreachActiveStream<hotel::Reservation>([](DataStream<hotel::Reservation>& stream) { stream.clear(); });
      _dataStreams.foreachActiveStream<hotel::Hotel>([](DataStream<hotel::Hotel>& stream) { stream.clear(); });
    }

    void SqliteBackend::executeOperation(op::OperationResults& results, op::LoadInitialData&)
    {
      // TODO: Remove this! This makes no sense in a stream world!
      auto hotels = _storage.loadHotels();
      auto planning = _storage.loadPlanning(hotels->allRoomIDs());
      results.push_back(op::LoadInitialDataResult{std::move(hotels), std::move(planning)});
    }

    void SqliteBackend::executeOperation(op::OperationResults& results, op::StoreNewHotel& op)
    {
      assert(op.newHotel != nullptr);
      if (op.newHotel == nullptr)
        return;

      _storage.storeNewHotel(*op.newHotel);

      _dataStreams.foreachActiveStream<hotel::Hotel>([&op](DataStream<hotel::Hotel>& stream) { stream.addItems({*op.newHotel}); });
      results.push_back(op::StoreNewHotelResult{std::move(op.newHotel)});
    }

    void SqliteBackend::executeOperation(op::OperationResults& results, op::StoreNewReservation& op)
    {
      if (op.newReservation == nullptr)
        results.push_back(op::NoResult());

      // "Unknown" is not a valid reservation status for serialization
      if (op.newReservation->status() == hotel::Reservation::Unknown)
        op.newReservation->setStatus(hotel::Reservation::New);
      _storage.storeNewReservationAndAtoms(*op.newReservation);

      _dataStreams.foreachActiveStream<hotel::Reservation>([&op](DataStream<hotel::Reservation>& stream) { stream.addItems({*op.newReservation}); });
      results.push_back(op::StoreNewReservationResult{std::move(op.newReservation)});
    }

    void SqliteBackend::executeOperation(op::OperationResults& results, op::StoreNewPerson& op)
    {
      // TODO: Implement this
      std::cout << "STUB: This functionality has not yet been implemented..." << std::endl;

      results.push_back(op::NoResult());
    }

    void SqliteBackend::executeOperation(op::OperationResults& results, op::DeleteReservation& op)
    {
      _storage.deleteReservationById(op.reservationId);
      _dataStreams.foreachActiveStream<hotel::Reservation>([&op](DataStream<hotel::Reservation>& stream) { stream.removeItems({op.reservationId}); });
      results.push_back(op::DeleteReservationResult{op.reservationId});
    }

    void SqliteBackend::initializeStream(DataStream<hotel::Hotel>& dataStream)
    {
      // TODO: loadHotels() should already return the correct type!
      auto hotelsCollection = _storage.loadHotels();
      // Create a vector of hotels
      std::vector<hotel::Hotel> hotels;
      for (auto& hotel : hotelsCollection->hotels())
        hotels.push_back(*hotel);
      dataStream.addItems(std::move(hotels));
    }

    void SqliteBackend::initializeStream(DataStream<hotel::Reservation>& dataStream)
    {
      auto reservations = _storage.loadReservations();
      dataStream.addItems(std::move(*reservations));
    }

  } // namespace sqlite
} // namespace persistence
<|endoftext|>


<commit_before>/*
 * Askname - A program that the user to enter  and then great them
 *
 * Author Moses Olawoyin <m.bastford@gmail.com>
 *
 * Date - 07 March 2015
 *
 */
#include <iostream>

int main (int argc, char *argv[])
{
    std::string name;

    std::cout << "What is your name? ";
    std::cin >> name;

   if(name != "")
   {
       std::cout << "How are you, " <<  name <<std::endl;
   }
   else
   {
       std::cout << "Howdy, coward" << std::endl;

   }

   return 0;
}
<commit_msg>ask name condition fixed. closes #37<commit_after>/*
 * Askname - A program that the user to enter  and then great them
 *
 * Author Moses Olawoyin <m.bastford@gmail.com>
 *
 * Date - 07 March 2015
 *
 */
#include <iostream>

int main (int argc, char *argv[])
{
    std::string name;

    std::cout << "What is your name? ";
    std::getline( std::cin, name);

   if(name != "")
   {
       std::cout << "How are you, " <<  name <<std::endl;
   }
   else
   {
       std::cout << "Howdy, coward" << std::endl;

   }

   return 0;
}
<|endoftext|>


<commit_before><commit_msg>:white_check_mark: test(chunk): updated the test for chunk<commit_after><|endoftext|>


<commit_before>/*
 * Copyright (c) 2007-2009 Digital Bazaar, Inc. All rights reserved.
 */
#include "db/net/DefaultBandwidthThrottler.h"

#include "db/rt/System.h"
#include "db/rt/Thread.h"
#include "db/util/Math.h"

#include <math.h>

using namespace db::net;
using namespace db::rt;
using namespace db::util;

DefaultBandwidthThrottler::DefaultBandwidthThrottler(int rateLimit)
{
   // initialize the last request time
   mLastRequestTime = System::getCurrentMilliseconds();

   // initialize the available number of bytes
   mAvailableBytes = 0;

   // set the rate limit (will also reset the window time if necessary)
   setRateLimit(rateLimit);
}

DefaultBandwidthThrottler::~DefaultBandwidthThrottler()
{
}

bool DefaultBandwidthThrottler::requestBytes(int count, int& permitted)
{
   bool rval = true;

   if(getRateLimit() > 0)
   {
      mLock.lock();
      {
         // limit the bandwidth
         rval = limitBandwidth();

         // get the available bytes
         int available = (uint64_t)Math::MAX_INT_VALUE ?
            Math::MAX_INT_VALUE : (int)mAvailableBytes;
         permitted = (available > count ? count : available);

         // increment the bytes granted
         mBytesGranted += permitted;

         // subtract the number of permitted bytes from the available bytes
         mAvailableBytes -= permitted;

         // update last request time
         mLastRequestTime = System::getCurrentMilliseconds();
      }
      mLock.unlock();
   }
   else
   {
      // no rate limit, return the count
      permitted = count;
   }

   return rval;
}

int DefaultBandwidthThrottler::getAvailableBytes()
{
   int rval = 0;

   mLock.lock();
   {
      if(mRateLimit > 0)
      {
         rval = mAvailableBytes;
      }
      else
      {
         rval = Math::MAX_INT_VALUE;
      }
   }
   mLock.unlock();

   return rval;
}

void DefaultBandwidthThrottler::setRateLimit(int rateLimit)
{
   mLock.lock();
   {
      // set new rate limit
      mRateLimit = rateLimit;
      if(mRateLimit > 0)
      {
         // reset the window time
         resetWindowTime();

         // update the available byte time
         updateAvailableByteTime();
      }
   }
   mLock.unlock();
}

int DefaultBandwidthThrottler::getRateLimit()
{
   return mRateLimit;
}

void DefaultBandwidthThrottler::resetWindowTime()
{
   // set the current window time
   mWindowTime = System::getCurrentMilliseconds();

   // reset the bytes already granted in this window
   mBytesGranted = 0;
}

void DefaultBandwidthThrottler::updateWindowTime()
{
   // get the current time
   uint64_t now = System::getCurrentMilliseconds();

   // Cap the number of bytes granted per window at maximum uint value
   // so that there isn't any overflow. This should also be a sufficiently
   // large enough number such that rate calculations aren't affected
   // very often at all.
   if(mBytesGranted > 0xffffffff)
   {
      resetWindowTime();
   }
   else if(now - mLastRequestTime > 3000)
   {
      // If it has been more than 3 seconds since the last request
      // for bytes, then reset the time window.
      //
      // 3 seconds was chosen because the minimum rate limit is
      // 1 byte per second. So if a request is made at that rate limit
      // then at least one byte would be available after one second.
      //
      // If it subsequently actually takes one second to transfer the
      // byte, then the next request would be somewhere shortly after
      // 2 seconds.
      //
      // It is assumed that any request more than a second later
      // involves a different transfer so we shouldn't store up a
      // lot of available bytes (by failing to reset the window) for
      // that transfer artificially bloating its rate.
      //
      // If the assumption fails, and, for instance, it takes more
      // than one second for a single byte to be transferred or bytes
      // are only requested ever so often, then the requester will
      // have to wait a maximum of one second to acquire another byte.
      resetWindowTime();
   }
}

inline uint64_t DefaultBandwidthThrottler::getWindowTime()
{
   return mWindowTime;
}

void DefaultBandwidthThrottler::updateAvailableByteTime()
{
   // the amount of time until a byte is available is 1000 milliseconds
   // divided by the rate in bytes/second, with a minimum of 1 millisecond
   mAvailableByteTime = (uint64_t)roundl(1000. / getRateLimit());
   mAvailableByteTime = (1 > mAvailableByteTime) ? 1 : mAvailableByteTime;
}

inline uint64_t DefaultBandwidthThrottler::getAvailableByteTime()
{
   return mAvailableByteTime;
}

void DefaultBandwidthThrottler::updateAvailableBytes()
{
   // get the passed time in the current window
   double passedTime = System::getCurrentMilliseconds() - getWindowTime();

   // determine how many bytes are available given the passed time --
   // use the floor so as not to go over the rate limit
   mAvailableBytes = (uint64_t)floorl(passedTime / 1000. * getRateLimit());

   // subtract the number of bytes already granted in this window
   mAvailableBytes = (mBytesGranted > mAvailableBytes) ?
      0 : mAvailableBytes - mBytesGranted;
}

bool DefaultBandwidthThrottler::limitBandwidth()
{
   bool rval = true;

   // update the window time
   updateWindowTime();

   // update the number of available bytes
   updateAvailableBytes();

   // while there aren't any available bytes, sleep for the available byte time
   while(rval && mAvailableBytes == 0)
   {
      // unlock to sleep
      mLock.unlock();
      rval = Thread::sleep(getAvailableByteTime());
      mLock.lock();

      // update the number of available bytes
      updateAvailableBytes();
   }

   return rval;
}
<commit_msg>Fixed typo.<commit_after>/*
 * Copyright (c) 2007-2009 Digital Bazaar, Inc. All rights reserved.
 */
#include "db/net/DefaultBandwidthThrottler.h"

#include "db/rt/System.h"
#include "db/rt/Thread.h"
#include "db/util/Math.h"

#include <math.h>

using namespace db::net;
using namespace db::rt;
using namespace db::util;

DefaultBandwidthThrottler::DefaultBandwidthThrottler(int rateLimit)
{
   // initialize the last request time
   mLastRequestTime = System::getCurrentMilliseconds();

   // initialize the available number of bytes
   mAvailableBytes = 0;

   // set the rate limit (will also reset the window time if necessary)
   setRateLimit(rateLimit);
}

DefaultBandwidthThrottler::~DefaultBandwidthThrottler()
{
}

bool DefaultBandwidthThrottler::requestBytes(int count, int& permitted)
{
   bool rval = true;

   if(getRateLimit() > 0)
   {
      mLock.lock();
      {
         // limit the bandwidth
         rval = limitBandwidth();

         // get the available bytes
         int available = (mAvailableBytes >= (uint64_t)Math::MAX_INT_VALUE) ?
            Math::MAX_INT_VALUE : (int)mAvailableBytes;
         permitted = (available > count ? count : available);

         // increment the bytes granted
         mBytesGranted += permitted;

         // subtract the number of permitted bytes from the available bytes
         mAvailableBytes -= permitted;

         // update last request time
         mLastRequestTime = System::getCurrentMilliseconds();
      }
      mLock.unlock();
   }
   else
   {
      // no rate limit, return the count
      permitted = count;
   }

   return rval;
}

int DefaultBandwidthThrottler::getAvailableBytes()
{
   int rval = 0;

   mLock.lock();
   {
      if(mRateLimit > 0)
      {
         rval = mAvailableBytes;
      }
      else
      {
         rval = Math::MAX_INT_VALUE;
      }
   }
   mLock.unlock();

   return rval;
}

void DefaultBandwidthThrottler::setRateLimit(int rateLimit)
{
   mLock.lock();
   {
      // set new rate limit
      mRateLimit = rateLimit;
      if(mRateLimit > 0)
      {
         // reset the window time
         resetWindowTime();

         // update the available byte time
         updateAvailableByteTime();
      }
   }
   mLock.unlock();
}

int DefaultBandwidthThrottler::getRateLimit()
{
   return mRateLimit;
}

void DefaultBandwidthThrottler::resetWindowTime()
{
   // set the current window time
   mWindowTime = System::getCurrentMilliseconds();

   // reset the bytes already granted in this window
   mBytesGranted = 0;
}

void DefaultBandwidthThrottler::updateWindowTime()
{
   // get the current time
   uint64_t now = System::getCurrentMilliseconds();

   // Cap the number of bytes granted per window at maximum uint value
   // so that there isn't any overflow. This should also be a sufficiently
   // large enough number such that rate calculations aren't affected
   // very often at all.
   if(mBytesGranted > 0xffffffff)
   {
      resetWindowTime();
   }
   else if(now - mLastRequestTime > 3000)
   {
      // If it has been more than 3 seconds since the last request
      // for bytes, then reset the time window.
      //
      // 3 seconds was chosen because the minimum rate limit is
      // 1 byte per second. So if a request is made at that rate limit
      // then at least one byte would be available after one second.
      //
      // If it subsequently actually takes one second to transfer the
      // byte, then the next request would be somewhere shortly after
      // 2 seconds.
      //
      // It is assumed that any request more than a second later
      // involves a different transfer so we shouldn't store up a
      // lot of available bytes (by failing to reset the window) for
      // that transfer artificially bloating its rate.
      //
      // If the assumption fails, and, for instance, it takes more
      // than one second for a single byte to be transferred or bytes
      // are only requested ever so often, then the requester will
      // have to wait a maximum of one second to acquire another byte.
      resetWindowTime();
   }
}

inline uint64_t DefaultBandwidthThrottler::getWindowTime()
{
   return mWindowTime;
}

void DefaultBandwidthThrottler::updateAvailableByteTime()
{
   // the amount of time until a byte is available is 1000 milliseconds
   // divided by the rate in bytes/second, with a minimum of 1 millisecond
   mAvailableByteTime = (uint64_t)roundl(1000. / getRateLimit());
   mAvailableByteTime = (1 > mAvailableByteTime) ? 1 : mAvailableByteTime;
}

inline uint64_t DefaultBandwidthThrottler::getAvailableByteTime()
{
   return mAvailableByteTime;
}

void DefaultBandwidthThrottler::updateAvailableBytes()
{
   // get the passed time in the current window
   double passedTime = System::getCurrentMilliseconds() - getWindowTime();

   // determine how many bytes are available given the passed time --
   // use the floor so as not to go over the rate limit
   mAvailableBytes = (uint64_t)floorl(passedTime / 1000. * getRateLimit());

   // subtract the number of bytes already granted in this window
   mAvailableBytes = (mBytesGranted > mAvailableBytes) ?
      0 : mAvailableBytes - mBytesGranted;
}

bool DefaultBandwidthThrottler::limitBandwidth()
{
   bool rval = true;

   // update the window time
   updateWindowTime();

   // update the number of available bytes
   updateAvailableBytes();

   // while there aren't any available bytes, sleep for the available byte time
   while(rval && mAvailableBytes == 0)
   {
      // unlock to sleep
      mLock.unlock();
      rval = Thread::sleep(getAvailableByteTime());
      mLock.lock();

      // update the number of available bytes
      updateAvailableBytes();
   }

   return rval;
}
<|endoftext|>


<commit_before>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2011 Artem Pavlenko
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

#ifndef POSTGIS_CONNECTION_HPP
#define POSTGIS_CONNECTION_HPP

// mapnik
#include <mapnik/debug.hpp>
#include <mapnik/datasource.hpp>
#include <mapnik/timer.hpp>

// boost
#include <boost/make_shared.hpp>

// std
#include <sstream>
#include <iostream>

extern "C" {
#include "libpq-fe.h"
}

#include "resultset.hpp"

class Connection
{
public:
    Connection(std::string const& connection_str,boost::optional<std::string> const& password)
        : cursorId(0),
          closed_(false),
          pending_(false)
    {
        std::string connect_with_pass = connection_str;
        if (password && !password->empty())
        {
            connect_with_pass += " password=" + *password;
        }
        conn_ = PQconnectdb(connect_with_pass.c_str());
        MAPNIK_LOG_DEBUG(postgis) << "postgis_connection: postgresql connection create - " << this;
        if (PQstatus(conn_) != CONNECTION_OK)
        {
            std::string err_msg = "Postgis Plugin: ";
            err_msg += status();
            err_msg += "\nConnection string: '";
            err_msg += connection_str;
            err_msg += "'\n";
            MAPNIK_LOG_DEBUG(postgis) << "postgis_connection: creation failed, closing connection - " << this;
            close();
            throw mapnik::datasource_exception(err_msg);
        }
    }

    ~Connection()
    {
        if (! closed_)
        {
            PQfinish(conn_);
            MAPNIK_LOG_DEBUG(postgis) << "postgis_connection: postgresql connection closed - " << this;
            closed_ = true;
        }
    }

    bool execute(std::string const& sql) const
    {
#ifdef MAPNIK_STATS
        mapnik::progress_timer __stats__(std::clog, std::string("postgis_connection::execute ") + sql);
#endif

        PGresult *result = PQexec(conn_, sql.c_str());
        bool ok = (result && (PQresultStatus(result) == PGRES_COMMAND_OK));
        PQclear(result);
        return ok;
    }

    boost::shared_ptr<ResultSet> executeQuery(std::string const& sql, int type = 0) const
    {
#ifdef MAPNIK_STATS
        mapnik::progress_timer __stats__(std::clog, std::string("postgis_connection::execute_query ") + sql);
#endif

        PGresult* result = 0;
        if (type == 1)
        {
            result = PQexecParams(conn_,sql.c_str(), 0, 0, 0, 0, 0, 1);
        }
        else
        {
            result = PQexec(conn_, sql.c_str());
        }

        if (! result || (PQresultStatus(result) != PGRES_TUPLES_OK))
        {
            std::string err_msg = "Postgis Plugin: ";
            err_msg += status();
            err_msg += "\nin executeQuery Full sql was: '";
            err_msg += sql;
            err_msg += "'\n";
            if (result)
            {
                PQclear(result);
            }
            throw mapnik::datasource_exception(err_msg);
        }

        return boost::make_shared<ResultSet>(result);
    }

    std::string status() const
    {
        std::string status;
        if (conn_)
        {
            status = PQerrorMessage(conn_);
        }
        else
        {
            status = "Uninitialized connection";
        }
        return status;
    }

    bool executeAsyncQuery(std::string const& sql, int type = 0)
    {
        int result = 0;
        if (type == 1)
        {
            result = PQsendQueryParams(conn_,sql.c_str(), 0, 0, 0, 0, 0, 1);
        }
        else
        {
            result = PQsendQuery(conn_, sql.c_str());
        }
        if (result != 1)
        {
            std::string err_msg = "Postgis Plugin: ";
            err_msg += status();
            err_msg += "\nin executeAsyncQuery Full sql was: '";
            err_msg += sql;
            err_msg += "'\n";
            clearAsyncResult(PQgetResult(conn_));
            close();
            throw mapnik::datasource_exception(err_msg);
        }
        pending_ = true;
        return result;
    }

    boost::shared_ptr<ResultSet> getNextAsyncResult()
    {
        PGresult *result = PQgetResult(conn_);
        if( result && (PQresultStatus(result) != PGRES_TUPLES_OK))
        {
            std::string err_msg = "Postgis Plugin: ";
            err_msg += status();
            err_msg += "\nin getNextAsyncResult";
            clearAsyncResult(result);
            // We need to guarde against losing the connection
            // (i.e db restart) so here we invalidate the full connection
            close();
            throw mapnik::datasource_exception(err_msg);
        }
       return boost::make_shared<ResultSet>(result);
    }

    boost::shared_ptr<ResultSet> getAsyncResult()
    {
        PGresult *result = PQgetResult(conn_);
        if ( !result || (PQresultStatus(result) != PGRES_TUPLES_OK))
        {
            std::string err_msg = "Postgis Plugin: ";
            err_msg += status();
            err_msg += "\nin getAsyncResult";
            clearAsyncResult(result);
            // We need to be guarded against losing the connection
            // (i.e db restart), we invalidate the full connection
            close();
            throw mapnik::datasource_exception(err_msg);
        }
        return boost::make_shared<ResultSet>(result);
    }

    std::string client_encoding() const
    {
        return PQparameterStatus(conn_, "client_encoding");
    }

    bool isOK() const
    {
        return (!closed_) && (PQstatus(conn_) != CONNECTION_BAD);
    }

    bool isPending() const
    {
        return pending_;
    }

    void close()
    {
        if (! closed_)
        {
            PQfinish(conn_);
            MAPNIK_LOG_DEBUG(postgis) << "postgis_connection: closing connection (close)- " << this;
            closed_ = true;
        }
    }

    std::string new_cursor_name()
    {
        std::ostringstream s;
        s << "mapnik_" << (cursorId++);
        return s.str();
    }

private:
    PGconn *conn_;
    int cursorId;
    bool closed_;
    bool pending_;

    void clearAsyncResult(PGresult *result)
    {
        // Clear all pending results
        while(result)
        {
           PQclear(result);
           result = PQgetResult(conn_);
        }
        pending_ = false;
    }
};

#endif //CONNECTION_HPP
<commit_msg>Make sure status() returns a message also on bad connection<commit_after>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2011 Artem Pavlenko
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

#ifndef POSTGIS_CONNECTION_HPP
#define POSTGIS_CONNECTION_HPP

// mapnik
#include <mapnik/debug.hpp>
#include <mapnik/datasource.hpp>
#include <mapnik/timer.hpp>

// boost
#include <boost/make_shared.hpp>

// std
#include <sstream>
#include <iostream>

extern "C" {
#include "libpq-fe.h"
}

#include "resultset.hpp"

class Connection
{
public:
    Connection(std::string const& connection_str,boost::optional<std::string> const& password)
        : cursorId(0),
          closed_(false),
          pending_(false)
    {
        std::string connect_with_pass = connection_str;
        if (password && !password->empty())
        {
            connect_with_pass += " password=" + *password;
        }
        conn_ = PQconnectdb(connect_with_pass.c_str());
        MAPNIK_LOG_DEBUG(postgis) << "postgis_connection: postgresql connection create - " << this;
        if (PQstatus(conn_) != CONNECTION_OK)
        {
            std::string err_msg = "Postgis Plugin: ";
            err_msg += status();
            err_msg += "\nConnection string: '";
            err_msg += connection_str;
            err_msg += "'\n";
            MAPNIK_LOG_DEBUG(postgis) << "postgis_connection: creation failed, closing connection - " << this;
            close();
            throw mapnik::datasource_exception(err_msg);
        }
    }

    ~Connection()
    {
        if (! closed_)
        {
            PQfinish(conn_);
            MAPNIK_LOG_DEBUG(postgis) << "postgis_connection: postgresql connection closed - " << this;
            closed_ = true;
        }
    }

    bool execute(std::string const& sql) const
    {
#ifdef MAPNIK_STATS
        mapnik::progress_timer __stats__(std::clog, std::string("postgis_connection::execute ") + sql);
#endif

        PGresult *result = PQexec(conn_, sql.c_str());
        bool ok = (result && (PQresultStatus(result) == PGRES_COMMAND_OK));
        PQclear(result);
        return ok;
    }

    boost::shared_ptr<ResultSet> executeQuery(std::string const& sql, int type = 0) const
    {
#ifdef MAPNIK_STATS
        mapnik::progress_timer __stats__(std::clog, std::string("postgis_connection::execute_query ") + sql);
#endif

        PGresult* result = 0;
        if (type == 1)
        {
            result = PQexecParams(conn_,sql.c_str(), 0, 0, 0, 0, 0, 1);
        }
        else
        {
            result = PQexec(conn_, sql.c_str());
        }

        if (! result || (PQresultStatus(result) != PGRES_TUPLES_OK))
        {
            std::string err_msg = "Postgis Plugin: ";
            err_msg += status();
            err_msg += "\nin executeQuery Full sql was: '";
            err_msg += sql;
            err_msg += "'\n";
            if (result)
            {
                PQclear(result);
            }
            throw mapnik::datasource_exception(err_msg);
        }

        return boost::make_shared<ResultSet>(result);
    }

    std::string status() const
    {
        std::string status;
        if (conn_)
        {
            if ( isOK() ) return PQerrorMessage(conn_);
            else return "Bad connection";
        }
        else
        {
            status = "Uninitialized connection";
        }
        return status;
    }

    bool executeAsyncQuery(std::string const& sql, int type = 0)
    {
        int result = 0;
        if (type == 1)
        {
            result = PQsendQueryParams(conn_,sql.c_str(), 0, 0, 0, 0, 0, 1);
        }
        else
        {
            result = PQsendQuery(conn_, sql.c_str());
        }
        if (result != 1)
        {
            std::string err_msg = "Postgis Plugin: ";
            err_msg += status();
            err_msg += "\nin executeAsyncQuery Full sql was: '";
            err_msg += sql;
            err_msg += "'\n";
            clearAsyncResult(PQgetResult(conn_));
            close();
            throw mapnik::datasource_exception(err_msg);
        }
        pending_ = true;
        return result;
    }

    boost::shared_ptr<ResultSet> getNextAsyncResult()
    {
        PGresult *result = PQgetResult(conn_);
        if( result && (PQresultStatus(result) != PGRES_TUPLES_OK))
        {
            std::string err_msg = "Postgis Plugin: ";
            err_msg += status();
            err_msg += "\nin getNextAsyncResult";
            clearAsyncResult(result);
            // We need to guarde against losing the connection
            // (i.e db restart) so here we invalidate the full connection
            close();
            throw mapnik::datasource_exception(err_msg);
        }
       return boost::make_shared<ResultSet>(result);
    }

    boost::shared_ptr<ResultSet> getAsyncResult()
    {
        PGresult *result = PQgetResult(conn_);
        if ( !result || (PQresultStatus(result) != PGRES_TUPLES_OK))
        {
            std::string err_msg = "Postgis Plugin: ";
            err_msg += status();
            err_msg += "\nin getAsyncResult";
            clearAsyncResult(result);
            // We need to be guarded against losing the connection
            // (i.e db restart), we invalidate the full connection
            close();
            throw mapnik::datasource_exception(err_msg);
        }
        return boost::make_shared<ResultSet>(result);
    }

    std::string client_encoding() const
    {
        return PQparameterStatus(conn_, "client_encoding");
    }

    bool isOK() const
    {
        return (!closed_) && (PQstatus(conn_) != CONNECTION_BAD);
    }

    bool isPending() const
    {
        return pending_;
    }

    void close()
    {
        if (! closed_)
        {
            PQfinish(conn_);
            MAPNIK_LOG_DEBUG(postgis) << "postgis_connection: closing connection (close)- " << this;
            closed_ = true;
        }
    }

    std::string new_cursor_name()
    {
        std::ostringstream s;
        s << "mapnik_" << (cursorId++);
        return s.str();
    }

private:
    PGconn *conn_;
    int cursorId;
    bool closed_;
    bool pending_;

    void clearAsyncResult(PGresult *result)
    {
        // Clear all pending results
        while(result)
        {
           PQclear(result);
           result = PQgetResult(conn_);
        }
        pending_ = false;
    }
};

#endif //CONNECTION_HPP
<|endoftext|>


<commit_before><commit_msg>Tabpage doesn't crash on load and traverses configurations<commit_after><|endoftext|>


<commit_before>#include "archive.hpp"
#include "../huffman/compress.hpp"
#include "../binary/bin_stream.hpp"

#include<fstream>
#include<vector>

void archive_files(const std::vector<std::string>& filenames, std::ostream& out_stream) {
	std::ostreambuf_iterator<char> out_iterator(out_stream);

	for(auto& fn : filenames) {
		for(char c : fn) *out_iterator = c;
		*out_iterator = '\0';
	}
	*out_iterator = '\0';

	BinaryWrite bin_out(out_iterator);

	for(auto& fn : filenames) {
		std::ifstream in(fn);
		auto freq_table = readTable(in);
		in.close();
		in.open(fn);
		compress(freq_table, in, bin_out);
	}
}

void archive(const char* in_file, const char* out_file) {
	std::ofstream out(out_file);
	archive(in_file, out);
}

void archive(const char* in_file, std::ostream& out_stream) {
	throw "Not implemented";
}

void archive(std::istream& in_stream, std::ostream& out_stream) {
	std::vector<std::string> filenames;
	std::string fn;

	while(std::getline(in_stream, fn))
		filenames.push_back(fn);

	archive_files(filenames, out_stream);
}
<commit_msg>Implement archive directory<commit_after>#include "archive.hpp"
#include "../huffman/compress.hpp"
#include "../binary/bin_stream.hpp"

#include<fstream>
#include<vector>
#include<experimental/filesystem>

void archive_files(const std::vector<std::string>& filenames, std::ostream& out_stream) {
	std::ostreambuf_iterator<char> out_iterator(out_stream);

	for(auto& fn : filenames) { // TODO: must strip base path
		for(char c : fn) *out_iterator = c;
		*out_iterator = '\0';
	}
	*out_iterator = '\0';

	BinaryWrite bin_out(out_iterator);

	for(auto& fn : filenames) {
		std::ifstream in(fn);
		auto freq_table = readTable(in);
		in.close();
		in.open(fn);
		compress(freq_table, in, bin_out);
	}
}

void archive(const char* in_file, const char* out_file) {
	std::ofstream out(out_file);
	archive(in_file, out);
}

void archive(const char* in_file, std::ostream& out_stream) {
	namespace fs = std::experimental::filesystem;

	std::vector<std::string> filenames;

	if(fs::is_regular_file(in_file)) {
		filenames.push_back(in_file);
	} else if(fs::is_directory(in_file)) {
		for(auto& p: fs::recursive_directory_iterator(in_file)) {
			if(!fs::is_regular_file(p)) continue;
			filenames.push_back(p.path());
		}
	} // else not supported, yet!

	archive_files(filenames, out_stream);
}

void archive(std::istream& in_stream, std::ostream& out_stream) {
	std::vector<std::string> filenames;
	std::string fn;

	while(std::getline(in_stream, fn))
		filenames.push_back(fn);

	archive_files(filenames, out_stream);
}
<|endoftext|>


<commit_before>/* This software is released under the BSD License.
 |
 | Copyright (c) 2010, Kevin P. Barry [the resourcerver project]
 | All rights reserved.
 |
 | Redistribution  and  use  in  source  and   binary  forms,  with  or  without
 | modification, are permitted provided that the following conditions are met:
 |
 | - Redistributions of source code must retain the above copyright notice, this
 |   list of conditions and the following disclaimer.
 |
 | - Redistributions in binary  form must reproduce the  above copyright notice,
 |   this list  of conditions and the following disclaimer in  the documentation
 |   and/or other materials provided with the distribution.
 |
 | - Neither the  name  of  the  Resourcerver  Project  nor  the  names  of  its
 |   contributors may be  used to endorse or promote products  derived from this
 |   software without specific prior written permission.
 |
 | THIS SOFTWARE IS  PROVIDED BY THE COPYRIGHT HOLDERS AND  CONTRIBUTORS "AS IS"
 | AND ANY  EXPRESS OR IMPLIED  WARRANTIES,  INCLUDING, BUT  NOT LIMITED TO, THE
 | IMPLIED WARRANTIES OF  MERCHANTABILITY  AND FITNESS FOR A  PARTICULAR PURPOSE
 | ARE DISCLAIMED.  IN  NO EVENT SHALL  THE COPYRIGHT  OWNER  OR CONTRIBUTORS BE
 | LIABLE  FOR  ANY  DIRECT,   INDIRECT,  INCIDENTAL,   SPECIAL,  EXEMPLARY,  OR
 | CONSEQUENTIAL   DAMAGES  (INCLUDING,  BUT  NOT  LIMITED  TO,  PROCUREMENT  OF
 | SUBSTITUTE GOODS OR SERVICES;  LOSS  OF USE,  DATA,  OR PROFITS;  OR BUSINESS
 | INTERRUPTION)  HOWEVER  CAUSED  AND ON  ANY  THEORY OF LIABILITY,  WHETHER IN
 | CONTRACT,  STRICT  LIABILITY, OR  TORT (INCLUDING  NEGLIGENCE  OR  OTHERWISE)
 | ARISING IN ANY  WAY OUT OF  THE USE OF THIS SOFTWARE, EVEN  IF ADVISED OF THE
 | POSSIBILITY OF SUCH DAMAGE.
 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/

extern "C" {
#include "api-trigger.h"
}

#include "plugin-dev/manual-command.hpp"

extern "C" {
#include "plugins/rsvp-trigger.h"
#include "plugins/rsvp-trigger-hook.h"
}

#include <stdio.h> //'snprintf'
#include <string.h> //'strlen', etc.

#include "plugin-macro.hpp"
#include "plugin-trigger.hpp"

extern "C" {
#include "attributes.h"
}

PLUGIN_DEFAULT_RESPONSE(trigger, struct trigger_source_info)

PLUGIN_BASIC_DEFINITIONS(trigger)

extern int rsvp_trigger_load(struct local_commands *lLoader)
{
	PLUGIN_LOAD_START(trigger, lLoader)

	PLUGIN_LOAD_SINGLE(trigger, system_trigger, lLoader,
	  type_resource_client, type_resource_client,
	  command_null, &rsvp_trigger_system_trigger::generate)

	  PLUGIN_LOAD_END(trigger)
}

PLUGIN_DEFAULT_LOAD(rsvp_trigger_load)

command_event __rsvp_trigger_hook_system_trigger(const struct trigger_source_info *sSource, text_info)
{ return default_response(sSource, request_system_trigger); }

command_handle trigger_system_trigger(text_info tTarget, uint8_t aAction, text_info tType)
{ return manual_command(tTarget, new rsvp_trigger_system_trigger(aAction, tType)); }

text_info PLUGIN_COMMAND_REQUEST(system_trigger) = "system trigger";

text_info PLUGIN_COMMAND_TAG(trigger, system_trigger) = "trigger_system_trigger";

text_info PLUGIN_COMMAND_INFO(trigger, system_trigger) = "trigger a system action";
<commit_msg>gamma.8 - fixed link error in "rsvp-trigger"<commit_after>/* This software is released under the BSD License.
 |
 | Copyright (c) 2010, Kevin P. Barry [the resourcerver project]
 | All rights reserved.
 |
 | Redistribution  and  use  in  source  and   binary  forms,  with  or  without
 | modification, are permitted provided that the following conditions are met:
 |
 | - Redistributions of source code must retain the above copyright notice, this
 |   list of conditions and the following disclaimer.
 |
 | - Redistributions in binary  form must reproduce the  above copyright notice,
 |   this list  of conditions and the following disclaimer in  the documentation
 |   and/or other materials provided with the distribution.
 |
 | - Neither the  name  of  the  Resourcerver  Project  nor  the  names  of  its
 |   contributors may be  used to endorse or promote products  derived from this
 |   software without specific prior written permission.
 |
 | THIS SOFTWARE IS  PROVIDED BY THE COPYRIGHT HOLDERS AND  CONTRIBUTORS "AS IS"
 | AND ANY  EXPRESS OR IMPLIED  WARRANTIES,  INCLUDING, BUT  NOT LIMITED TO, THE
 | IMPLIED WARRANTIES OF  MERCHANTABILITY  AND FITNESS FOR A  PARTICULAR PURPOSE
 | ARE DISCLAIMED.  IN  NO EVENT SHALL  THE COPYRIGHT  OWNER  OR CONTRIBUTORS BE
 | LIABLE  FOR  ANY  DIRECT,   INDIRECT,  INCIDENTAL,   SPECIAL,  EXEMPLARY,  OR
 | CONSEQUENTIAL   DAMAGES  (INCLUDING,  BUT  NOT  LIMITED  TO,  PROCUREMENT  OF
 | SUBSTITUTE GOODS OR SERVICES;  LOSS  OF USE,  DATA,  OR PROFITS;  OR BUSINESS
 | INTERRUPTION)  HOWEVER  CAUSED  AND ON  ANY  THEORY OF LIABILITY,  WHETHER IN
 | CONTRACT,  STRICT  LIABILITY, OR  TORT (INCLUDING  NEGLIGENCE  OR  OTHERWISE)
 | ARISING IN ANY  WAY OUT OF  THE USE OF THIS SOFTWARE, EVEN  IF ADVISED OF THE
 | POSSIBILITY OF SUCH DAMAGE.
 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/

extern "C" {
#include "api-trigger.h"
}

#include "plugin-dev/manual-command.hpp"

extern "C" {
#include "plugins/rsvp-trigger.h"
#include "plugins/rsvp-trigger-hook.h"
}

#include <stdio.h> //'snprintf'
#include <string.h> //'strlen', etc.

#include "plugin-macro.hpp"
#include "plugin-trigger.hpp"

extern "C" {
#include "attributes.h"
}

PLUGIN_DEFAULT_RESPONSE(trigger, struct trigger_source_info)

PLUGIN_BASIC_DEFINITIONS(trigger)

extern int rsvp_trigger_load(struct local_commands *lLoader)
{
	PLUGIN_LOAD_START(trigger, lLoader)

	PLUGIN_LOAD_SINGLE(trigger, system_trigger, lLoader,
	  type_resource_client, type_resource_client,
	  command_null, &rsvp_trigger_system_trigger::generate)

	  PLUGIN_LOAD_END(trigger)
}

PLUGIN_DEFAULT_LOAD(rsvp_trigger_load)

command_event __rsvp_trigger_hook_system_trigger(const struct trigger_source_info *sSource, uint8_t, text_info)
{ return default_response(sSource, request_system_trigger); }

command_handle trigger_system_trigger(text_info tTarget, uint8_t aAction, text_info tType)
{ return manual_command(tTarget, new rsvp_trigger_system_trigger(aAction, tType)); }

text_info PLUGIN_COMMAND_REQUEST(system_trigger) = "system trigger";

text_info PLUGIN_COMMAND_TAG(trigger, system_trigger) = "trigger_system_trigger";

text_info PLUGIN_COMMAND_INFO(trigger, system_trigger) = "trigger a system action";
<|endoftext|>


<commit_before>// Copyright (c) 2014 Ollix. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// ---
// Author: olliwang@ollix.com (Olli Wang)

#include <algorithm>
#include <cstdlib>

#include "moui/opengl_hook.h"
#include "nanovg.h"

// Makes sure the nanovg implementation loaded once to prevent "undefined
// symbols" or "duplicate symbols" issues. Only includes the "nanovg_hook.h"
// header file in other modules to use nanovg.
#if defined MOUI_GL2
#  define NANOVG_GL2_IMPLEMENTATION
#elif defined MOUI_GLES2
#  define NANOVG_GLES2_IMPLEMENTATION
#elif defined MOUI_GL3
#  define NANOVG_GL3_IMPLEMENTATION
#elif defined MOUI_GLES3
#  define NANOVG_GLES3_IMPLEMENTATION
#endif
#include "nanovg_gl.h"
#include "nanovg_gl_utils.h"

namespace {

// Flips the passed image vertically.
void ImageFlipVertical(unsigned char* image, int width, int height) {
  const int kStride = width * 4;
  int i = 0, j = height - 1, k;
  while (i < j) {
    unsigned char* ri = &image[i * kStride];
    unsigned char* rj = &image[j * kStride];
    for (k = 0; k < kStride; k++) {
      unsigned char t = ri[k];
      ri[k] = rj[k];
      rj[k] = t;
    }
    i++;
    j--;
  }
}

// Sets the alpha value of every pixel of the passed image.
void ImageSetAlpha(unsigned char* image, int width, int height,
                   unsigned char alpha) {
  const int kStride = width * 4;
  int x, y;
  for (y = 0; y < height; y++) {
    unsigned char* row = &image[y * kStride];
    for (x = 0; x < width; x++)
      row[x * 4 + 3] = alpha;
  }
}

// Returns the data of the image snapshot from the current framebuffer.
// The returned image data should be freed manually when no longer needed.
// `NULL` is returned on failure.
unsigned char* ImageSnapshot(const int x, const int y, const int width,
                             const int height) {
  unsigned char* image = \
      reinterpret_cast<unsigned char*>(std::malloc(width * height * 4));
  if (image == NULL)
    return NULL;

  glReadPixels(x, y, width, height, GL_RGBA, GL_UNSIGNED_BYTE, image);
  return image;
}

// Unpremultiplies the alpha value of every pixel of the passed image.
void ImageUnpremultiplyAlpha(unsigned char* image, int width, int height) {
  const int kStride = width * 4;
  int x, y;

  // Unpremultiply
  for (y = 0; y < height; y++) {
    unsigned char* row = &image[y * kStride];
    for (x = 0; x < width; x++) {
      int r = row[0], g = row[1], b = row[2], a = row[3];
      if (a != 0) {
        row[0] = static_cast<int>(std::min(r * 255 / a, 255));
        row[1] = static_cast<int>(std::min(g * 255 / a, 255));
        row[2] = static_cast<int>(std::min(b * 255 / a, 255));
      }
      row += 4;
    }
  }

  // Defringe
  for (y = 0; y < height; y++) {
    unsigned char* row = &image[y * kStride];
    for (x = 0; x < width; x++) {
      int r = 0, g = 0, b = 0, a = row[3], n = 0;
      if (a == 0) {
        if (x-1 > 0 && row[-1] != 0) {
          r += row[-4];
          g += row[-3];
          b += row[-2];
          n++;
        }
        if (x+1 < width && row[7] != 0) {
          r += row[4];
          g += row[5];
          b += row[6];
          n++;
        }
        if (y-1 > 0 && row[-kStride + 3] != 0) {
          r += row[-kStride];
          g += row[-kStride + 1];
          b += row[-kStride + 2];
          n++;
        }
        if (y+1 < height && row[kStride + 3] != 0) {
          r += row[kStride];
          g += row[kStride + 1];
          b += row[kStride + 2];
          n++;
        }
        if (n > 0) {
          row[0] = r / n;
          row[1] = g / n;
          row[2] = b / n;
        }
      }
      row += 4;
    }
  }
}

}  // namespace

namespace moui {

bool nvgCompareColor(const NVGcolor& color1, const NVGcolor& color2) {
  return color1.r == color2.r && color1.g == color2.g &&
         color1.b == color2.b && color1.a == color2.a;
}

int nvgCreateImageSnapshot(NVGcontext* context, const int x, const int y,
                           const int width, const int height,
                           const float scale_factor) {
  const int kScaledWidth = width * scale_factor;
  const int kScaledHeight = height * scale_factor;
  unsigned char* image = ImageSnapshot(x * scale_factor, y * scale_factor,
                                       kScaledWidth, kScaledHeight);
  if (image == NULL)
    return -1;

  const int kIdentifier = nvgCreateImageRGBA(
      context, kScaledWidth, kScaledHeight,
      NVG_IMAGE_FLIPY | NVG_IMAGE_PREMULTIPLIED, image);
  delete image;
  return kIdentifier;
}

void nvgDeleteFramebuffer(NVGcontext* context, NVGLUframebuffer** framebuffer) {
  if (*framebuffer == nullptr)
    return;
  nvgluDeleteFramebuffer(context, *framebuffer);
  *framebuffer = nullptr;
}

}  // namespace moui
<commit_msg>Fixes `nvgDeleteFramebuffer()`.<commit_after>// Copyright (c) 2014 Ollix. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// ---
// Author: olliwang@ollix.com (Olli Wang)

#include <algorithm>
#include <cstdlib>

#include "moui/opengl_hook.h"
#include "nanovg.h"

// Makes sure the nanovg implementation loaded once to prevent "undefined
// symbols" or "duplicate symbols" issues. Only includes the "nanovg_hook.h"
// header file in other modules to use nanovg.
#if defined MOUI_GL2
#  define NANOVG_GL2_IMPLEMENTATION
#elif defined MOUI_GLES2
#  define NANOVG_GLES2_IMPLEMENTATION
#elif defined MOUI_GL3
#  define NANOVG_GL3_IMPLEMENTATION
#elif defined MOUI_GLES3
#  define NANOVG_GLES3_IMPLEMENTATION
#endif
#include "nanovg_gl.h"
#include "nanovg_gl_utils.h"

namespace {

// Flips the passed image vertically.
void ImageFlipVertical(unsigned char* image, int width, int height) {
  const int kStride = width * 4;
  int i = 0, j = height - 1, k;
  while (i < j) {
    unsigned char* ri = &image[i * kStride];
    unsigned char* rj = &image[j * kStride];
    for (k = 0; k < kStride; k++) {
      unsigned char t = ri[k];
      ri[k] = rj[k];
      rj[k] = t;
    }
    i++;
    j--;
  }
}

// Sets the alpha value of every pixel of the passed image.
void ImageSetAlpha(unsigned char* image, int width, int height,
                   unsigned char alpha) {
  const int kStride = width * 4;
  int x, y;
  for (y = 0; y < height; y++) {
    unsigned char* row = &image[y * kStride];
    for (x = 0; x < width; x++)
      row[x * 4 + 3] = alpha;
  }
}

// Returns the data of the image snapshot from the current framebuffer.
// The returned image data should be freed manually when no longer needed.
// `NULL` is returned on failure.
unsigned char* ImageSnapshot(const int x, const int y, const int width,
                             const int height) {
  unsigned char* image = \
      reinterpret_cast<unsigned char*>(std::malloc(width * height * 4));
  if (image == NULL)
    return NULL;

  glReadPixels(x, y, width, height, GL_RGBA, GL_UNSIGNED_BYTE, image);
  return image;
}

// Unpremultiplies the alpha value of every pixel of the passed image.
void ImageUnpremultiplyAlpha(unsigned char* image, int width, int height) {
  const int kStride = width * 4;
  int x, y;

  // Unpremultiply
  for (y = 0; y < height; y++) {
    unsigned char* row = &image[y * kStride];
    for (x = 0; x < width; x++) {
      int r = row[0], g = row[1], b = row[2], a = row[3];
      if (a != 0) {
        row[0] = static_cast<int>(std::min(r * 255 / a, 255));
        row[1] = static_cast<int>(std::min(g * 255 / a, 255));
        row[2] = static_cast<int>(std::min(b * 255 / a, 255));
      }
      row += 4;
    }
  }

  // Defringe
  for (y = 0; y < height; y++) {
    unsigned char* row = &image[y * kStride];
    for (x = 0; x < width; x++) {
      int r = 0, g = 0, b = 0, a = row[3], n = 0;
      if (a == 0) {
        if (x-1 > 0 && row[-1] != 0) {
          r += row[-4];
          g += row[-3];
          b += row[-2];
          n++;
        }
        if (x+1 < width && row[7] != 0) {
          r += row[4];
          g += row[5];
          b += row[6];
          n++;
        }
        if (y-1 > 0 && row[-kStride + 3] != 0) {
          r += row[-kStride];
          g += row[-kStride + 1];
          b += row[-kStride + 2];
          n++;
        }
        if (y+1 < height && row[kStride + 3] != 0) {
          r += row[kStride];
          g += row[kStride + 1];
          b += row[kStride + 2];
          n++;
        }
        if (n > 0) {
          row[0] = r / n;
          row[1] = g / n;
          row[2] = b / n;
        }
      }
      row += 4;
    }
  }
}

}  // namespace

namespace moui {

bool nvgCompareColor(const NVGcolor& color1, const NVGcolor& color2) {
  return color1.r == color2.r && color1.g == color2.g &&
         color1.b == color2.b && color1.a == color2.a;
}

int nvgCreateImageSnapshot(NVGcontext* context, const int x, const int y,
                           const int width, const int height,
                           const float scale_factor) {
  const int kScaledWidth = width * scale_factor;
  const int kScaledHeight = height * scale_factor;
  unsigned char* image = ImageSnapshot(x * scale_factor, y * scale_factor,
                                       kScaledWidth, kScaledHeight);
  if (image == NULL)
    return -1;

  const int kIdentifier = nvgCreateImageRGBA(
      context, kScaledWidth, kScaledHeight,
      NVG_IMAGE_FLIPY | NVG_IMAGE_PREMULTIPLIED, image);
  delete image;
  return kIdentifier;
}

void nvgDeleteFramebuffer(NVGcontext* context, NVGLUframebuffer** framebuffer) {
  if (context == nullptr || *framebuffer == nullptr) {
    return;
  }
  nvgluDeleteFramebuffer(context, *framebuffer);
  *framebuffer = nullptr;
}

}  // namespace moui
<|endoftext|>