<commit_before>/**
 * \file
 * \brief Stack class implementation
 *
 * \author Copyright (C) 2014-2017 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
 *
 * \par License
 * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
 * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#include "distortos/architecture/Stack.hpp"

#include "distortos/architecture/initializeStack.hpp"

#include "distortos/internal/memory/dummyDeleter.hpp"

#include <algorithm>

#if CONFIG_ARCHITECTURE_STACK_ALIGNMENT <= 0
#error "Stack alignment must be greater than 0!"
#endif	// CONFIG_ARCHITECTURE_STACK_ALIGNMENT <= 0

namespace distortos
{

namespace architecture
{

namespace
{

/*---------------------------------------------------------------------------------------------------------------------+
| local objects
+---------------------------------------------------------------------------------------------------------------------*/

/// alignment of stack, bytes
constexpr size_t stackAlignment {CONFIG_ARCHITECTURE_STACK_ALIGNMENT};

/// sentinel used for stack usage/overflow detection
constexpr uint32_t stackSentinel {0xed419f25};

/*---------------------------------------------------------------------------------------------------------------------+
| local functions' declarations
+---------------------------------------------------------------------------------------------------------------------*/

/**
 * \brief Adjusts storage's address to suit architecture's alignment requirements.
 *
 * \param [in] storage is a pointer to stack's storage
 * \param [in] alignment is the required stack alignment, bytes
 *
 * \return adjusted storage's address
 */

void* adjustStorage(void* const storage, const size_t alignment)
{
	return reinterpret_cast<void*>((reinterpret_cast<uintptr_t>(storage) + alignment - 1) / alignment * alignment);
}

/**
 * \brief Adjusts storage's size to suit architecture's alignment requirements.
 *
 * \param [in] storage is a pointer to stack's storage
 * \param [in] size is the size of stack's storage, bytes
 * \param [in] adjustedStorage is an adjusted storage's address
 * \param [in] alignment is the required stack alignment, bytes
 *
 * \return adjusted storage's size
 */

size_t adjustSize(void* const storage, const size_t size, void* const adjustedStorage, const size_t alignment)
{
	const auto storageEnd = reinterpret_cast<uintptr_t>(storage) + size;
	const auto adjustedStorageEnd = storageEnd / alignment * alignment;
	return adjustedStorageEnd - reinterpret_cast<decltype(adjustedStorageEnd)>(adjustedStorage);
}

/**
 * \brief Proxy for initializeStack() which fills stack with stack sentinel before actually initializing it.
 *
 * \param [in] storage is a pointer to stack's storage
 * \param [in] size is the size of stack's storage, bytes
 * \param [in] stackGuardSize is the size of "stack guard", bytes
 * \param [in] thread is a reference to Thread object passed to function
 * \param [in] run is a reference to Thread's "run" function
 * \param [in] preTerminationHook is a pointer to Thread's pre-termination hook, nullptr to skip
 * \param [in] terminationHook is a reference to Thread's termination hook
 *
 * \return value that can be used as thread's stack pointer, ready for context switching
 */

void* initializeStackProxy(void* const storage, const size_t size, const size_t stackGuardSize, Thread& thread,
		void (& run)(Thread&), void (* preTerminationHook)(Thread&), void (& terminationHook)(Thread&))
{
	std::fill_n(static_cast<std::decay<decltype(stackSentinel)>::type*>(storage), size / sizeof(stackSentinel),
			stackSentinel);
	return initializeStack(static_cast<uint8_t*>(storage) + stackGuardSize,
			size > stackGuardSize ? size - stackGuardSize : 0, thread, run, preTerminationHook, terminationHook);
}

}	// namespace

/*---------------------------------------------------------------------------------------------------------------------+
| public functions
+---------------------------------------------------------------------------------------------------------------------*/

Stack::Stack(StorageUniquePointer&& storageUniquePointer, const size_t size, Thread& thread, void (& run)(Thread&),
		void (* preTerminationHook)(Thread&), void (& terminationHook)(Thread&)) :
				storageUniquePointer_{std::move(storageUniquePointer)},
				adjustedStorage_{adjustStorage(storageUniquePointer_.get(), stackAlignment)},
				adjustedSize_{adjustSize(storageUniquePointer_.get(), size, adjustedStorage_, stackAlignment)},
				stackPointer_{initializeStackProxy(adjustedStorage_, adjustedSize_, stackGuardSize_, thread, run,
						preTerminationHook, terminationHook)}
{
	/// \todo implement minimal size check
}

Stack::Stack(void* const storage, const size_t size) :
		storageUniquePointer_{storage, internal::dummyDeleter<void*>},
		adjustedStorage_{storage},
		adjustedSize_{size},
		stackPointer_{}
{
	/// \todo implement minimal size check
}

Stack::~Stack()
{

}

bool Stack::checkStackGuard() const
{
	return std::all_of(static_cast<decltype(&stackSentinel)>(adjustedStorage_),
			static_cast<decltype(&stackSentinel)>(adjustedStorage_) + stackGuardSize_ / sizeof(stackSentinel),
			[](decltype(stackSentinel)& element)
			{
				return element == stackSentinel;
			});
}

size_t Stack::getHighWaterMark() const
{
	const auto begin =
			static_cast<decltype(&stackSentinel)>(adjustedStorage_) + stackGuardSize_ / sizeof(stackSentinel);
	const auto end = static_cast<decltype(&stackSentinel)>(adjustedStorage_) + adjustedSize_ / sizeof(stackSentinel);
	const auto usedElement = std::find_if_not(begin, end,
			[](decltype(stackSentinel)& element) -> bool
			{
				return element == stackSentinel;
			});
	return (end - usedElement) * sizeof(*begin);
}

}	// namespace architecture

}	// namespace distortos
<commit_msg>Explicitly state return type of lambda in Stack::checkStackGuard()<commit_after>/**
 * \file
 * \brief Stack class implementation
 *
 * \author Copyright (C) 2014-2017 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
 *
 * \par License
 * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
 * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#include "distortos/architecture/Stack.hpp"

#include "distortos/architecture/initializeStack.hpp"

#include "distortos/internal/memory/dummyDeleter.hpp"

#include <algorithm>

#if CONFIG_ARCHITECTURE_STACK_ALIGNMENT <= 0
#error "Stack alignment must be greater than 0!"
#endif	// CONFIG_ARCHITECTURE_STACK_ALIGNMENT <= 0

namespace distortos
{

namespace architecture
{

namespace
{

/*---------------------------------------------------------------------------------------------------------------------+
| local objects
+---------------------------------------------------------------------------------------------------------------------*/

/// alignment of stack, bytes
constexpr size_t stackAlignment {CONFIG_ARCHITECTURE_STACK_ALIGNMENT};

/// sentinel used for stack usage/overflow detection
constexpr uint32_t stackSentinel {0xed419f25};

/*---------------------------------------------------------------------------------------------------------------------+
| local functions' declarations
+---------------------------------------------------------------------------------------------------------------------*/

/**
 * \brief Adjusts storage's address to suit architecture's alignment requirements.
 *
 * \param [in] storage is a pointer to stack's storage
 * \param [in] alignment is the required stack alignment, bytes
 *
 * \return adjusted storage's address
 */

void* adjustStorage(void* const storage, const size_t alignment)
{
	return reinterpret_cast<void*>((reinterpret_cast<uintptr_t>(storage) + alignment - 1) / alignment * alignment);
}

/**
 * \brief Adjusts storage's size to suit architecture's alignment requirements.
 *
 * \param [in] storage is a pointer to stack's storage
 * \param [in] size is the size of stack's storage, bytes
 * \param [in] adjustedStorage is an adjusted storage's address
 * \param [in] alignment is the required stack alignment, bytes
 *
 * \return adjusted storage's size
 */

size_t adjustSize(void* const storage, const size_t size, void* const adjustedStorage, const size_t alignment)
{
	const auto storageEnd = reinterpret_cast<uintptr_t>(storage) + size;
	const auto adjustedStorageEnd = storageEnd / alignment * alignment;
	return adjustedStorageEnd - reinterpret_cast<decltype(adjustedStorageEnd)>(adjustedStorage);
}

/**
 * \brief Proxy for initializeStack() which fills stack with stack sentinel before actually initializing it.
 *
 * \param [in] storage is a pointer to stack's storage
 * \param [in] size is the size of stack's storage, bytes
 * \param [in] stackGuardSize is the size of "stack guard", bytes
 * \param [in] thread is a reference to Thread object passed to function
 * \param [in] run is a reference to Thread's "run" function
 * \param [in] preTerminationHook is a pointer to Thread's pre-termination hook, nullptr to skip
 * \param [in] terminationHook is a reference to Thread's termination hook
 *
 * \return value that can be used as thread's stack pointer, ready for context switching
 */

void* initializeStackProxy(void* const storage, const size_t size, const size_t stackGuardSize, Thread& thread,
		void (& run)(Thread&), void (* preTerminationHook)(Thread&), void (& terminationHook)(Thread&))
{
	std::fill_n(static_cast<std::decay<decltype(stackSentinel)>::type*>(storage), size / sizeof(stackSentinel),
			stackSentinel);
	return initializeStack(static_cast<uint8_t*>(storage) + stackGuardSize,
			size > stackGuardSize ? size - stackGuardSize : 0, thread, run, preTerminationHook, terminationHook);
}

}	// namespace

/*---------------------------------------------------------------------------------------------------------------------+
| public functions
+---------------------------------------------------------------------------------------------------------------------*/

Stack::Stack(StorageUniquePointer&& storageUniquePointer, const size_t size, Thread& thread, void (& run)(Thread&),
		void (* preTerminationHook)(Thread&), void (& terminationHook)(Thread&)) :
				storageUniquePointer_{std::move(storageUniquePointer)},
				adjustedStorage_{adjustStorage(storageUniquePointer_.get(), stackAlignment)},
				adjustedSize_{adjustSize(storageUniquePointer_.get(), size, adjustedStorage_, stackAlignment)},
				stackPointer_{initializeStackProxy(adjustedStorage_, adjustedSize_, stackGuardSize_, thread, run,
						preTerminationHook, terminationHook)}
{
	/// \todo implement minimal size check
}

Stack::Stack(void* const storage, const size_t size) :
		storageUniquePointer_{storage, internal::dummyDeleter<void*>},
		adjustedStorage_{storage},
		adjustedSize_{size},
		stackPointer_{}
{
	/// \todo implement minimal size check
}

Stack::~Stack()
{

}

bool Stack::checkStackGuard() const
{
	return std::all_of(static_cast<decltype(&stackSentinel)>(adjustedStorage_),
			static_cast<decltype(&stackSentinel)>(adjustedStorage_) + stackGuardSize_ / sizeof(stackSentinel),
			[](decltype(stackSentinel)& element) -> bool
			{
				return element == stackSentinel;
			});
}

size_t Stack::getHighWaterMark() const
{
	const auto begin =
			static_cast<decltype(&stackSentinel)>(adjustedStorage_) + stackGuardSize_ / sizeof(stackSentinel);
	const auto end = static_cast<decltype(&stackSentinel)>(adjustedStorage_) + adjustedSize_ / sizeof(stackSentinel);
	const auto usedElement = std::find_if_not(begin, end,
			[](decltype(stackSentinel)& element) -> bool
			{
				return element == stackSentinel;
			});
	return (end - usedElement) * sizeof(*begin);
}

}	// namespace architecture

}	// namespace distortos
<|endoftext|>


<commit_before>//
// Aspia Project
// Copyright (C) 2018 Dmitry Chapyshev <dmitry@aspia.ru>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
//

#include "base/thread_checker.h"

namespace aspia {

ThreadChecker::ThreadChecker()
{
    ensureAssigned();
}

bool ThreadChecker::calledOnValidThread() const
{
    std::scoped_lock lock(thread_id_lock_);
    if (thread_id_ == std::this_thread::get_id())
        return true;

    return false;
}

void ThreadChecker::detachFromThread()
{
    std::scoped_lock<std::mutex> lock(thread_id_lock_);
    thread_id_ = std::thread::id();
}

void ThreadChecker::ensureAssigned()
{
    std::scoped_lock lock(thread_id_lock_);
    thread_id_ = std::this_thread::get_id();
}

} // namespace aspia
<commit_msg>- Using C++17.<commit_after>//
// Aspia Project
// Copyright (C) 2018 Dmitry Chapyshev <dmitry@aspia.ru>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
//

#include "base/thread_checker.h"

namespace aspia {

ThreadChecker::ThreadChecker()
{
    ensureAssigned();
}

bool ThreadChecker::calledOnValidThread() const
{
    std::scoped_lock lock(thread_id_lock_);
    if (thread_id_ == std::this_thread::get_id())
        return true;

    return false;
}

void ThreadChecker::detachFromThread()
{
    std::scoped_lock lock(thread_id_lock_);
    thread_id_ = std::thread::id();
}

void ThreadChecker::ensureAssigned()
{
    std::scoped_lock lock(thread_id_lock_);
    thread_id_ = std::this_thread::get_id();
}

} // namespace aspia
<|endoftext|>


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

#include "TTAudioSignal.h"

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

TTAudioSignal::TTAudioSignal(TTUInt8 initialMaxNumChannels)
	: isLocallyOwned(false), maxNumChannels(0), vs(0), numChannels(0), sampleVectors(NULL)
{
	TTUInt8	i;

	maxNumChannels = initialMaxNumChannels;
	sampleVectors = (TTSampleVector *)malloc(sizeof(TTSampleVector) * maxNumChannels);
	for(i=0; i<maxNumChannels; i++)
		sampleVectors[i] = NULL;
}

TTAudioSignal::~TTAudioSignal()
{
	TTUInt32	i;

	if(isLocallyOwned){
		for(i=0; i<maxNumChannels; i++){
			free(sampleVectors[i]);
			sampleVectors[i] = NULL;
		}
		isLocallyOwned = false;
	}
	free(sampleVectors);
}

TTErr TTAudioSignal::setVector(TTUInt8 channel, TTUInt16 vectorSize, TTSampleVector newVector)
{
	TTUInt32	i;

	// could check against maxnumchannels here

	bitdepth = 64;
	vs = vectorSize;

	if(isLocallyOwned){
		for(i=0; i<maxNumChannels; i++){
			free(sampleVectors[i]);
			sampleVectors[i] = NULL;
		}
		isLocallyOwned = false;
	}
	sampleVectors[channel] = newVector;
	return kTTErrNone;
}

/*
	It sucks if someone sets a 32-bit audio vector, since we have translate it into a 64-bit buffer.
	There may be a better way to do this...

	For now, we don't simply reference the data passed in.  Instead we allocate our own buffer and copy the data.
	Unfortunately, this is very slow.

	Also note that we are relying on the vector size already being set!

	If we passed the vs in to this method, we could avoid having to realloc the memory every single time.
	This would probably be a very good idea.
*/
TTErr TTAudioSignal::setVector(TTUInt8 channel, TTUInt16 vectorSize, TTFloat32* newVector)
{
	TTUInt32	i;

	// 1. could check against maxnumchannels here

	// 2. allocate the vector if need be
	if(bitdepth != 32 || !isLocallyOwned || vectorSize != vs)
	{
		bitdepth = 32;
		vs = vectorSize;
		alloc();
	}

	// 3. copy the vector (from 32-bits to 64-bits)
	for(i=0; i<vectorSize; i++)
		sampleVectors[channel][i] = newVector[i];

	return kTTErrNone;
}

TTErr TTAudioSignal::getVector(TTUInt8 channel, TTUInt16 vectorSize, TTSampleVector returnedVector)
{
	returnedVector = sampleVectors[channel];
	return kTTErrNone;
}

TTErr TTAudioSignal::getVector(TTUInt8 channel, TTUInt16 vectorSize, TTFloat32* returnedVector)
{
	TTUInt16 i;

	for(i=0; i<vectorSize; i++)
		returnedVector[i] = (TTFloat32)sampleVectors[channel][i];
	return kTTErrNone;
}

TTErr TTAudioSignal::alloc()
{
	TTUInt32	i;

	if(isLocallyOwned){
		for(i=0; i<maxNumChannels; i++){
			free(sampleVectors[i]);
			sampleVectors[i] = NULL;
		}
	}
	for(i=0; i<maxNumChannels; i++)
		sampleVectors[i] = (TTSampleVector)malloc(sizeof(TTSampleValue) * vs);
	isLocallyOwned = true;
	return kTTErrNone;
}

TTErr TTAudioSignal::allocWithSize(TTUInt16 newVectorSize)
{
	if(newVectorSize != vs){
		vs = newVectorSize;
		return alloc();
	}
	else
		return kTTErrNone;
}

TTUInt8 TTAudioSignal::getMinChannelCount(TTAudioSignal& signal1, TTAudioSignal& signal2)
{
	if(signal1.numChannels > signal2.numChannels)
		return signal2.numChannels;
	else
		return signal1.numChannels;
}

TTUInt8 TTAudioSignal::getMinChannelCount(TTAudioSignal& signal1, TTAudioSignal& signal2, TTAudioSignal& signal3)
{
	TTUInt8	numChannels = signal1.numChannels;

	if(signal2.numChannels < numChannels)
		numChannels = signal2.numChannels;
	if(signal3.numChannels < numChannels)
		numChannels = signal3.numChannels;

	return numChannels;
}

TTUInt8 TTAudioSignal::getMaxChannelCount(TTAudioSignal& signal1, TTAudioSignal& signal2)
{
	if(signal1.numChannels < signal2.numChannels)
		return signal2.numChannels;
	else
		return signal1.numChannels;
}

TTUInt8 TTAudioSignal::getMaxChannelCount(TTAudioSignal& signal1, TTAudioSignal& signal2, TTAudioSignal& signal3)
{
	TTUInt8	numChannels = signal1.numChannels;

	if(signal2.numChannels > numChannels)
		numChannels = signal2.numChannels;
	if(signal3.numChannels > numChannels)
		numChannels = signal3.numChannels;

	return numChannels;
}

TTUInt8 TTAudioSignal::getNumChannels(TTAudioSignal& signal)
{
	return signal.numChannels;
}

// TODO: The old tt audio signal could point to external memory, or allocate its own for the vectors
// This enum was used to keep trac of which was the case:
// enum selectors{
//	k_mode_local = 1,
//	k_mode_external = 0,
//};

// TODO: implement clear() method -- ZERO OUT A VECTOR'S CONTENTS
TTErr TTAudioSignal::clear()
{
	TTUInt8		channel;
	TTUInt16	i;

	if(!sampleVectors)
		return kTTErrGeneric;

	for(channel=0; channel<numChannels; channel++){
		for(i=0; i<vs; i++)
			sampleVectors[channel][i] = 0.0;
	}
	return kTTErrNone;
}

// TODO: implement fill() method --- SET ALL VALUES IN THE SIGNAL TO A CONSTANT

<commit_msg>Fixes committed by Dave to the Jamoma repository.  This includes not malloc() ing zero-sized memory, and not freeing memory that is not owned locally.<commit_after>/*
 * TTBlue Audio Signal Class
 * Copyright © 2008, Timothy Place
 *
 * License: This code is licensed under the terms of the GNU LGPL
 * http://www.gnu.org/licenses/lgpl.html
 */

#include "TTAudioSignal.h"

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

TTAudioSignal::TTAudioSignal(TTUInt8 initialMaxNumChannels)
	: isLocallyOwned(false), maxNumChannels(0), vs(0), numChannels(0), sampleVectors(NULL)
{
	TTUInt8	i;

	maxNumChannels = initialMaxNumChannels;
	if(maxNumChannels) {
		sampleVectors = (TTSampleVector *)malloc(sizeof(TTSampleVector) * maxNumChannels);
		for(i=0; i<maxNumChannels; i++)
			sampleVectors[i] = NULL;
	}
}

TTAudioSignal::~TTAudioSignal()
{
	TTUInt32	i;

	if(isLocallyOwned){
		for(i=0; i<maxNumChannels; i++){
			free(sampleVectors[i]);
			sampleVectors[i] = NULL;
		}
		isLocallyOwned = false;
	}
	free(sampleVectors);
}

TTErr TTAudioSignal::setVector(TTUInt8 channel, TTUInt16 vectorSize, TTSampleVector newVector)
{
	TTUInt32	i;

	// could check against maxnumchannels here

	bitdepth = 64;
	vs = vectorSize;

	if(isLocallyOwned){
		for(i=0; i<maxNumChannels; i++){
			free(sampleVectors[i]);
			sampleVectors[i] = NULL;
		}
		isLocallyOwned = false;
	}
	sampleVectors[channel] = newVector;
	return kTTErrNone;
}

/*
	It sucks if someone sets a 32-bit audio vector, since we have translate it into a 64-bit buffer.
	There may be a better way to do this...

	For now, we don't simply reference the data passed in.  Instead we allocate our own buffer and copy the data.
	Unfortunately, this is very slow.

	Also note that we are relying on the vector size already being set!

	If we passed the vs in to this method, we could avoid having to realloc the memory every single time.
	This would probably be a very good idea.
*/
TTErr TTAudioSignal::setVector(TTUInt8 channel, TTUInt16 vectorSize, TTFloat32* newVector)
{
	TTUInt32	i;

	// 1. could check against maxnumchannels here

	// 2. allocate the vector if need be
	if(bitdepth != 32 || !isLocallyOwned || vectorSize != vs)
	{
		bitdepth = 32;
		vs = vectorSize;
		alloc();
	}

	// 3. copy the vector (from 32-bits to 64-bits)
	for(i=0; i<vectorSize; i++)
		sampleVectors[channel][i] = newVector[i];

	return kTTErrNone;
}

TTErr TTAudioSignal::getVector(TTUInt8 channel, TTUInt16 vectorSize, TTSampleVector returnedVector)
{
	returnedVector = sampleVectors[channel];
	return kTTErrNone;
}

TTErr TTAudioSignal::getVector(TTUInt8 channel, TTUInt16 vectorSize, TTFloat32* returnedVector)
{
	TTUInt16 i;

	for(i=0; i<vectorSize; i++)
		returnedVector[i] = (TTFloat32)sampleVectors[channel][i];
	return kTTErrNone;
}

TTErr TTAudioSignal::alloc()
{
	TTUInt32	i;
	if(isLocallyOwned){
		for(i=0; i<maxNumChannels; i++){
			free(sampleVectors[i]);
			sampleVectors[i] = NULL;
		}
	}

	for(i=0; i<maxNumChannels; i++) {
		sampleVectors[i] = (TTSampleVector)malloc(sizeof(TTSampleValue) * vs);
	}
	isLocallyOwned = maxNumChannels > 0 ? true : false;
	return kTTErrNone;
}

TTErr TTAudioSignal::allocWithSize(TTUInt16 newVectorSize)
{
	if(newVectorSize != vs){
		vs = newVectorSize;
		return alloc();
	}
	else
		return kTTErrNone;
}

TTUInt8 TTAudioSignal::getMinChannelCount(TTAudioSignal& signal1, TTAudioSignal& signal2)
{
	if(signal1.numChannels > signal2.numChannels)
		return signal2.numChannels;
	else
		return signal1.numChannels;
}

TTUInt8 TTAudioSignal::getMinChannelCount(TTAudioSignal& signal1, TTAudioSignal& signal2, TTAudioSignal& signal3)
{
	TTUInt8	numChannels = signal1.numChannels;

	if(signal2.numChannels < numChannels)
		numChannels = signal2.numChannels;
	if(signal3.numChannels < numChannels)
		numChannels = signal3.numChannels;

	return numChannels;
}

TTUInt8 TTAudioSignal::getMaxChannelCount(TTAudioSignal& signal1, TTAudioSignal& signal2)
{
	if(signal1.numChannels < signal2.numChannels)
		return signal2.numChannels;
	else
		return signal1.numChannels;
}

TTUInt8 TTAudioSignal::getMaxChannelCount(TTAudioSignal& signal1, TTAudioSignal& signal2, TTAudioSignal& signal3)
{
	TTUInt8	numChannels = signal1.numChannels;

	if(signal2.numChannels > numChannels)
		numChannels = signal2.numChannels;
	if(signal3.numChannels > numChannels)
		numChannels = signal3.numChannels;

	return numChannels;
}

TTUInt8 TTAudioSignal::getNumChannels(TTAudioSignal& signal)
{
	return signal.numChannels;
}

// TODO: The old tt audio signal could point to external memory, or allocate its own for the vectors
// This enum was used to keep trac of which was the case:
// enum selectors{
//	k_mode_local = 1,
//	k_mode_external = 0,
//};

// TODO: implement clear() method -- ZERO OUT A VECTOR'S CONTENTS
TTErr TTAudioSignal::clear()
{
	TTUInt8		channel;
	TTUInt16	i;

	if(!sampleVectors)
		return kTTErrGeneric;

	for(channel=0; channel<numChannels; channel++){
		for(i=0; i<vs; i++)
			sampleVectors[channel][i] = 0.0;
	}
	return kTTErrNone;
}

// TODO: implement fill() method --- SET ALL VALUES IN THE SIGNAL TO A CONSTANT

<|endoftext|>


<commit_before>#include <sys/types.h>
#include <sys/mman.h>
#include <stdlib.h>
#include <unistd.h>
//#include "atexit.h"
//#include "thread_private.h"

#include <iostream>
#include <vector>
#include <unordered_map>
#include <map>
#include <algorithm>
#include <sstream>

#include "xstring.h"

#define NO_ALLOC_MACRO_OVERRIDE

// NEED TWO MEM_TRACKER header files
// one for this .cc file
// another one for the target source files
#include "mem_tracker.h"

using namespace std;

/** actually define the global (extern-ed) variables here
 *  and do some initialization directly at the beginning of main() */
unsigned long long CALL_COUNT_NEW;
unsigned long long CALL_COUNT_DELETE;
unsigned long long MEMORY_COUNT_NEW;
unsigned long long MEMORY_COUNT_DELETE;

/** this flag activates the tracking */
bool USE_MEM_TRACKER;

/** temporary save variables provided during "delete" call " */
const char* ____DELETE_FILENAME____;
size_t ____DELETE_LINE____;

/** the two main "databases" for the pointers */
tPtrDataStorage ALLOCATED_PTRS;
tPtrDataList ARCHIVED_PTRS;

/** no args ctor */
PtrData::PtrData()
  : p(nullptr), size(0), allocated(false), deleted(false),
    new_call(), delete_call() { }

/** copy ctor */
PtrData::PtrData(const PtrData& obj)
  : p(obj.p), size(obj.size), allocated(obj.allocated), deleted(obj.deleted),
    new_call(obj.new_call), delete_call(obj.delete_call) { }

/** keeps all the data for one pointer */
PtrData::PtrData(void* ptr, const size_t& len)
  : p(ptr), size(len), allocated(true), deleted(false),
    new_call(), delete_call() { }

/** handle new-call */
void* __handle_new_request(size_t size, const char* fn, size_t line) _GLIBCXX_THROW(std::bad_alloc) {
  if(USE_MEM_TRACKER) {
    CALL_COUNT_NEW++;
    MEMORY_COUNT_NEW += size;
  }
  void* out = malloc(size);

  if(USE_MEM_TRACKER) {
    USE_MEM_TRACKER = false;
    ALLOCATED_PTRS[out] = PtrData(out, size);
    ALLOCATED_PTRS[out].new_call = make_pair(string(fn), line);
    USE_MEM_TRACKER = true;
  }
  return out;
}

/** save meta-data (filename, lineno) into tmp-vars for __handle_delete_request */
void __handle_delete_meta_data(const char* fn, const size_t& line) {
  ____DELETE_FILENAME____ = fn;
  ____DELETE_LINE____ = line;
}

/** handle delete-call */
void __handle_delete_request(void* ptr) {
  if(USE_MEM_TRACKER) {
    tPtrDataStorageIter i = ALLOCATED_PTRS.find(ptr);
    if(i != ALLOCATED_PTRS.end()) {
      USE_MEM_TRACKER = false;

      // move PtrData instance from ALLOCATED to ARCHIVED
      ARCHIVED_PTRS.push_back(ALLOCATED_PTRS[ptr]);
      ALLOCATED_PTRS.erase(ptr);

      ARCHIVED_PTRS.back().deleted = true;
      ARCHIVED_PTRS.back().delete_call = \
                                         make_pair(string(____DELETE_FILENAME____), ____DELETE_LINE____);

      CALL_COUNT_DELETE++;
      MEMORY_COUNT_DELETE += ARCHIVED_PTRS.back().size;

      USE_MEM_TRACKER = true;
    }
  }
  free(ptr);
}

/** Global "new" operator overload */
void* operator new(size_t size, const char* fn, size_t line) _GLIBCXX_THROW(std::bad_alloc) {
  return __handle_new_request(size, fn, line);
}
void* operator new[](size_t size, const char* fn, size_t line) _GLIBCXX_THROW(std::bad_alloc) {
  return __handle_new_request(size, fn, line);
}

/** Global "delete" operator overload */
void operator delete(void* ptr) _GLIBCXX_USE_NOEXCEPT {
  __handle_delete_request(ptr);
}
void operator delete[](void* ptr) _GLIBCXX_USE_NOEXCEPT {
  __handle_delete_request(ptr);
}

/** return delete or new statistics */
string __print_memory_details(bool delete_mode, bool verbose) {
  stringstream ss;
  tOpPtrDataMap pos2ptr;
  tPtrDataList data;

  // generate reverse table
  if(!delete_mode) {
    for(tPtrDataStorage::value_type& i : ALLOCATED_PTRS) {
      pos2ptr[i.second.new_call].push_back(i.second);
      data.push_back(i.second);
    }
  } else {
    for(PtrData& i : ARCHIVED_PTRS) {
      pos2ptr[i.delete_call].push_back(i);
      data.push_back(i);
    }
  }

  // directly return, if no details are available
  if(data.size() == 0)
    return "";

  // find PtrData instance allocating most bytes
  tPtrDataIter max_iter = std::max_element(data.begin(), data.end(), \
                          [](const PtrData& a, const PtrData& b) \
  { return (a.size <= b.size); } \
                                          );

  // calc/set formatting vars
  size_t max_size = max_iter->size;
  size_t max_width = 0;
  size_t max_cols = 6;
  while(max_size) {
    max_size /= 10.0;
    max_width++;
  }

  // go over generated map and gen. results
  for(tOpPtrDataIter i=pos2ptr.begin(); i!=pos2ptr.end(); ++i) {
    // calculate sum of bytes alloced/deleted
    unsigned long long sum = 0;
    std::for_each(i->second.begin(), i->second.end(), \
    [&](const PtrData& x) {
      sum += x.size;
    }
                 );

    ss << "[i] " << setw(5) << i->first.first << setw(10) <<
       " line: " << setw(6) << i->first.second << setw(10) <<
       "#calls: " << setw(8) << i->second.size() << setw(10) <<
       " bytes: " << setw(16) << sum << endl;

    // print: ptr-addr[size] x (max_cols) each line
    size_t col = 0;
    if(verbose) {
      ss << "[E]    ";
      for(tPtrDataIter p=i->second.begin(); p!=i->second.end(); ++p, col++) {
        ss << p->p << "[" << setw(max_width) << p->size << "]";
        ss << (((p+1) != i->second.end()) ? ", " : "\n");
        if((col % max_cols) == (max_cols - 1))
          ss << endl << "       ";
      }
    }
  }
  return ss.str();
}

/** show some results and hints to search the leaks */
string get_memory_tracker_results(bool verbose) {
  long m_diff = (MEMORY_COUNT_NEW - MEMORY_COUNT_DELETE);
  long ptr_diff = CALL_COUNT_NEW - CALL_COUNT_DELETE;
  stringstream ss;

  ss << endl;
  ss << "[STATS] Memory tracking overview:" << endl;
  ss << endl;
  string sep = " | ";
  size_t pad = 14;
  size_t loff = 8;
  size_t hline = 82;
  ss << setw(pad+loff) << "tracked" << sep << setw(pad) << "tracked" << sep <<
     setw(pad) << "leaked" << sep << setw(pad) << "leaked" << sep << endl;

  ss << setw(pad+loff) << "calls" << sep << setw(pad) << "bytes" << sep <<
     setw(pad) << "calls" << sep << setw(pad) << "bytes" << sep << endl;

  ss << setw(hline) << setfill('-') << "" << setfill(' ') << endl;

  ss << setw(loff) << "NEW" << setw(pad) << CALL_COUNT_NEW << sep <<
     setw(pad) << MEMORY_COUNT_NEW << sep << setw(pad) << "n/a" << sep <<
     setw(pad) << "n/a" << sep << endl;

  ss << setw(hline) << setfill('-') << "" << setfill(' ') << endl;

  ss << setw(loff) << "DELETE" << setw(pad) << CALL_COUNT_DELETE << sep <<
     setw(pad) << MEMORY_COUNT_DELETE << sep << setw(pad) << ptr_diff << sep <<
     setw(pad) << m_diff << sep << endl;

  if(m_diff > 0) {
    ss << endl;
    ss << "[LEAK DATA] showing not deleted (bad) calls:" << endl;
    ss << __print_memory_details(false, verbose);
  } else
    cout << "[+] no leaks found!" << endl;

  ss << endl;

  if(verbose) {
    if(CALL_COUNT_DELETE > 0) {
      ss << "[DELETE DATA] showing deleted (good) calls:" << endl;
      ss << __print_memory_details(true, verbose);
      ss << endl;
    } else
      cout << "[i] no delete calls tracked..." << endl;
  }

  return ss.str();
}

// saving pointer to original ::exit() function call
auto original_exit = &::exit;

/** To avoid a segfault on exit, if MEM_TRACKER is used.
 *  (Segfault due to the automated cleanup of MemTracker datastructures on leaving scope) */
void exit(int status) throw() {
  ALLOCATED_PTRS.clear();
  ARCHIVED_PTRS.clear();
  // calling "real" exit()
  original_exit(status);
}

/** initilize the memory tracker variables */
void init_memory_tracker() {
  CALL_COUNT_NEW = 0;
  CALL_COUNT_DELETE = 0;
  MEMORY_COUNT_NEW = 0;
  MEMORY_COUNT_DELETE = 0;

  ____DELETE_FILENAME____ = "";
  ____DELETE_LINE____ = 0;

  // set to true to start tracking!
  USE_MEM_TRACKER = false;

  ALLOCATED_PTRS.clear();
  ARCHIVED_PTRS.clear();
}
<commit_msg>fixed segfault exit behavior<commit_after>#include <sys/types.h>
#include <sys/mman.h>
#include <stdlib.h>
#include <unistd.h>
//#include "atexit.h"
//#include "thread_private.h"

#include <iostream>
#include <vector>
#include <unordered_map>
#include <map>
#include <algorithm>
#include <sstream>

#include "xstring.h"

#define NO_ALLOC_MACRO_OVERRIDE

// NEED TWO MEM_TRACKER header files
// one for this .cc file
// another one for the target source files
#include "mem_tracker.h"

using namespace std;

/** actually define the global (extern-ed) variables here
 *  and do some initialization directly at the beginning of main() */
unsigned long long CALL_COUNT_NEW;
unsigned long long CALL_COUNT_DELETE;
unsigned long long MEMORY_COUNT_NEW;
unsigned long long MEMORY_COUNT_DELETE;

/** this flag activates the tracking */
bool USE_MEM_TRACKER;

/** temporary save variables provided during "delete" call " */
const char* ____DELETE_FILENAME____;
size_t ____DELETE_LINE____;

/** the two main "databases" for the pointers */
tPtrDataStorage ALLOCATED_PTRS;
tPtrDataList ARCHIVED_PTRS;

/** no args ctor */
PtrData::PtrData()
  : p(nullptr), size(0), allocated(false), deleted(false),
    new_call(), delete_call() { }

/** copy ctor */
PtrData::PtrData(const PtrData& obj)
  : p(obj.p), size(obj.size), allocated(obj.allocated), deleted(obj.deleted),
    new_call(obj.new_call), delete_call(obj.delete_call) { }

/** keeps all the data for one pointer */
PtrData::PtrData(void* ptr, const size_t& len)
  : p(ptr), size(len), allocated(true), deleted(false),
    new_call(), delete_call() { }

/** handle new-call */
void* __handle_new_request(size_t size, const char* fn, size_t line) _GLIBCXX_THROW(std::bad_alloc) {
  if(USE_MEM_TRACKER) {
    CALL_COUNT_NEW++;
    MEMORY_COUNT_NEW += size;
  }
  void* out = malloc(size);

  if(USE_MEM_TRACKER) {
    USE_MEM_TRACKER = false;
    ALLOCATED_PTRS[out] = PtrData(out, size);
    ALLOCATED_PTRS[out].new_call = make_pair(string(fn), line);
    USE_MEM_TRACKER = true;
  }
  return out;
}

/** save meta-data (filename, lineno) into tmp-vars for __handle_delete_request */
void __handle_delete_meta_data(const char* fn, const size_t& line) {
  ____DELETE_FILENAME____ = fn;
  ____DELETE_LINE____ = line;
}

/** handle delete-call */
void __handle_delete_request(void* ptr) {
  if(USE_MEM_TRACKER) {
    tPtrDataStorageIter i = ALLOCATED_PTRS.find(ptr);
    if(i != ALLOCATED_PTRS.end()) {
      USE_MEM_TRACKER = false;

      // move PtrData instance from ALLOCATED to ARCHIVED
      ARCHIVED_PTRS.push_back(ALLOCATED_PTRS[ptr]);
      ALLOCATED_PTRS.erase(ptr);

      ARCHIVED_PTRS.back().deleted = true;
      ARCHIVED_PTRS.back().delete_call = \
                                         make_pair(string(____DELETE_FILENAME____), ____DELETE_LINE____);

      CALL_COUNT_DELETE++;
      MEMORY_COUNT_DELETE += ARCHIVED_PTRS.back().size;

      USE_MEM_TRACKER = true;
    }
  }
  free(ptr);
}

/** Global "new" operator overload */
void* operator new(size_t size, const char* fn, size_t line) _GLIBCXX_THROW(std::bad_alloc) {
  return __handle_new_request(size, fn, line);
}
void* operator new[](size_t size, const char* fn, size_t line) _GLIBCXX_THROW(std::bad_alloc) {
  return __handle_new_request(size, fn, line);
}

/** Global "delete" operator overload */
void operator delete(void* ptr) _GLIBCXX_USE_NOEXCEPT {
  __handle_delete_request(ptr);
}
void operator delete[](void* ptr) _GLIBCXX_USE_NOEXCEPT {
  __handle_delete_request(ptr);
}

/** return delete or new statistics */
string __print_memory_details(bool delete_mode, bool verbose) {
  stringstream ss;
  tOpPtrDataMap pos2ptr;
  tPtrDataList data;

  // generate reverse table
  if(!delete_mode) {
    for(tPtrDataStorage::value_type& i : ALLOCATED_PTRS) {
      pos2ptr[i.second.new_call].push_back(i.second);
      data.push_back(i.second);
    }
  } else {
    for(PtrData& i : ARCHIVED_PTRS) {
      pos2ptr[i.delete_call].push_back(i);
      data.push_back(i);
    }
  }

  // directly return, if no details are available
  if(data.size() == 0)
    return "";

  // find PtrData instance allocating most bytes
  tPtrDataIter max_iter = std::max_element(data.begin(), data.end(), \
                          [](const PtrData& a, const PtrData& b) \
  { return (a.size <= b.size); } \
                                          );

  // calc/set formatting vars
  size_t max_size = max_iter->size;
  size_t max_width = 0;
  size_t max_cols = 6;
  while(max_size) {
    max_size /= 10.0;
    max_width++;
  }

  // go over generated map and gen. results
  for(tOpPtrDataIter i=pos2ptr.begin(); i!=pos2ptr.end(); ++i) {
    // calculate sum of bytes alloced/deleted
    unsigned long long sum = 0;
    std::for_each(i->second.begin(), i->second.end(), \
    [&](const PtrData& x) {
      sum += x.size;
    }
                 );

    ss << "[i] " << setw(5) << i->first.first << setw(10) <<
       " line: " << setw(6) << i->first.second << setw(10) <<
       "#calls: " << setw(8) << i->second.size() << setw(10) <<
       " bytes: " << setw(16) << sum << endl;

    // print: ptr-addr[size] x (max_cols) each line
    size_t col = 0;
    if(verbose) {
      ss << "[E]    ";
      for(tPtrDataIter p=i->second.begin(); p!=i->second.end(); ++p, col++) {
        ss << p->p << "[" << setw(max_width) << p->size << "]";
        ss << (((p+1) != i->second.end()) ? ", " : "\n");
        if((col % max_cols) == (max_cols - 1))
          ss << endl << "       ";
      }
    }
  }
  return ss.str();
}

/** show some results and hints to search the leaks */
string get_memory_tracker_results(bool verbose) {
  long m_diff = (MEMORY_COUNT_NEW - MEMORY_COUNT_DELETE);
  long ptr_diff = CALL_COUNT_NEW - CALL_COUNT_DELETE;
  stringstream ss;

  ss << endl;
  ss << "[STATS] Memory tracking overview:" << endl;
  ss << endl;
  string sep = " | ";
  size_t pad = 14;
  size_t loff = 8;
  size_t hline = 82;
  ss << setw(pad+loff) << "tracked" << sep << setw(pad) << "tracked" << sep <<
     setw(pad) << "leaked" << sep << setw(pad) << "leaked" << sep << endl;

  ss << setw(pad+loff) << "calls" << sep << setw(pad) << "bytes" << sep <<
     setw(pad) << "calls" << sep << setw(pad) << "bytes" << sep << endl;

  ss << setw(hline) << setfill('-') << "" << setfill(' ') << endl;

  ss << setw(loff) << "NEW" << setw(pad) << CALL_COUNT_NEW << sep <<
     setw(pad) << MEMORY_COUNT_NEW << sep << setw(pad) << "n/a" << sep <<
     setw(pad) << "n/a" << sep << endl;

  ss << setw(hline) << setfill('-') << "" << setfill(' ') << endl;

  ss << setw(loff) << "DELETE" << setw(pad) << CALL_COUNT_DELETE << sep <<
     setw(pad) << MEMORY_COUNT_DELETE << sep << setw(pad) << ptr_diff << sep <<
     setw(pad) << m_diff << sep << endl;

  if(m_diff > 0) {
    ss << endl;
    ss << "[LEAK DATA] showing not deleted (bad) calls:" << endl;
    ss << __print_memory_details(false, verbose);
  } else
    cout << "[+] no leaks found!" << endl;

  ss << endl;

  if(verbose) {
    if(CALL_COUNT_DELETE > 0) {
      ss << "[DELETE DATA] showing deleted (good) calls:" << endl;
      ss << __print_memory_details(true, verbose);
      ss << endl;
    } else
      cout << "[i] no delete calls tracked..." << endl;
  }

  return ss.str();
}

/** To avoid a segfault on exit, if MEM_TRACKER is used.
 *  (Segfault due to the automated cleanup of MemTracker datastructures on leaving scope) */
void exit(int status) throw() {
  ALLOCATED_PTRS.clear();
  ARCHIVED_PTRS.clear();
  // calling "real" exit()
  _exit(status);
}

/** initilize the memory tracker variables */
void init_memory_tracker() {
  CALL_COUNT_NEW = 0;
  CALL_COUNT_DELETE = 0;
  MEMORY_COUNT_NEW = 0;
  MEMORY_COUNT_DELETE = 0;

  ____DELETE_FILENAME____ = "";
  ____DELETE_LINE____ = 0;

  // set to true to start tracking!
  USE_MEM_TRACKER = false;

  ALLOCATED_PTRS.clear();
  ARCHIVED_PTRS.clear();
}
<|endoftext|>


<commit_before>#include <glow/memory.h>

#include <glow/global.h>
#include <glow/Extension.h>

namespace {

GLint getMemoryInformation(GLenum pname)
{
    if (!glow::hasExtension("NVX_gpu_memory_info"))
        return -1;

    return glow::getInteger(pname);
}

}

namespace glow
{

namespace memory
{

GLint total()
{
    return getMemoryInformation(GPU_MEMORY_INFO_TOTAL_AVAILABLE_MEMORY_NVX);
}

GLint dedicated()
{
    return getMemoryInformation(GPU_MEMORY_INFO_DEDICATED_VIDMEM_NVX);
}

GLint available()
{
    return getMemoryInformation(GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX);
}

GLint evicted()
{
    return getMemoryInformation(GPU_MEMORY_INFO_EVICTED_MEMORY_NVX);
}

GLint evictionCount()
{
    return getMemoryInformation(GPU_MEMORY_INFO_EVICTION_COUNT_NVX);
}

}
}
<commit_msg>Add missing GL_ prefixes to previously removed constants<commit_after>#include <glow/memory.h>

#include <glow/global.h>
#include <glow/Extension.h>

namespace {

GLint getMemoryInformation(GLenum pname)
{
    if (!glow::hasExtension("NVX_gpu_memory_info"))
        return -1;

    return glow::getInteger(pname);
}

}

namespace glow
{

namespace memory
{

GLint total()
{
    return getMemoryInformation(GL_GPU_MEMORY_INFO_TOTAL_AVAILABLE_MEMORY_NVX);
}

GLint dedicated()
{
    return getMemoryInformation(GL_GPU_MEMORY_INFO_DEDICATED_VIDMEM_NVX);
}

GLint available()
{
    return getMemoryInformation(GL_GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX);
}

GLint evicted()
{
    return getMemoryInformation(GL_GPU_MEMORY_INFO_EVICTED_MEMORY_NVX);
}

GLint evictionCount()
{
    return getMemoryInformation(GL_GPU_MEMORY_INFO_EVICTION_COUNT_NVX);
}

}
}
<|endoftext|>


<commit_before>#include <cassert>

#include <GL/glew.h>

#include <glow/logging.h>
#include <glow/global.h>
#include <glow/Error.h>

#include <GLFW/glfw3.h> // specifies APIENTRY, should be after Error.h include,
                        // which requires APIENTRY in windows..
#include <glowwindow/Context.h>

using namespace glow;

namespace glowwindow
{

Context::Context()
: m_swapInterval(VerticalSyncronization)
, m_window(nullptr)
{
}

Context::~Context()
{
    release();
}

GLFWwindow * Context::window()
{
    return m_window;
}

bool Context::create(const ContextFormat & format, const int width, const int height, GLFWmonitor * monitor)
{
    if (isValid())
    {
        warning() << "Context is already valid. Create was probably called before.";
        return true;
    }

    if (!glfwInit())
    {
        fatal() << "Could not initialize GLFW.";
        return false;
    }

    m_format = format;
    prepareFormat(m_format);

    /*
     * GLFW3 does not set default hint values on window creation so at least
     * the default values must be set before glfwCreateWindow can be called.
     * c.f. http://www.glfw.org/docs/latest/group__window.html#ga4fd9e504bb937e79588a0ffdca9f620b
     */
    glfwDefaultWindowHints();
    m_window = glfwCreateWindow(width, height, "glow", monitor, nullptr);

    if (!m_window)
    {
        fatal() << "Context creation failed (GLFW).";
        release();
        return false;
    }

    makeCurrent();

    if (!glow::init())
    {
        fatal() << "GLOW/GLEW initialization failed.";
        release();
        return false;
    }

    glfwSwapInterval(m_swapInterval);

    doneCurrent();

    // TODO: gather actual context format information and verify
    //ContextFormat::verify(format, m_format);

    return true;
}

void Context::prepareFormat(const ContextFormat & format)
{
    Version version = validateVersion(format.version());

    if (!format.version().isNull() && format.version() != version)
    {
        glow::warning() << "Changed unsupported OpenGL version from " << format.version() << " to " << version << ".";
    }

    glfwDefaultWindowHints();

    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, version.majorVersion);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, version.minorVersion);

    glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
    if (version >= Version(3, 2))
    {
        glfwWindowHint(GLFW_OPENGL_PROFILE, format.profile() == ContextFormat::CoreProfile ? GLFW_OPENGL_CORE_PROFILE : GLFW_OPENGL_COMPAT_PROFILE);
    }

    glfwWindowHint(GLFW_DEPTH_BITS, format.depthBufferSize());
    glfwWindowHint(GLFW_STENCIL_BITS, format.stencilBufferSize());
    glfwWindowHint(GLFW_RED_BITS, format.redBufferSize());
    glfwWindowHint(GLFW_GREEN_BITS, format.greenBufferSize());
    glfwWindowHint(GLFW_BLUE_BITS, format.blueBufferSize());
    glfwWindowHint(GLFW_ALPHA_BITS, format.alphaBufferSize());
    glfwWindowHint(GLFW_SAMPLES, format.samples());
}

void Context::release()
{
    if (!isValid())
        return;

    glfwDestroyWindow(m_window);
    m_window = nullptr;
}

void Context::swap()
{
    if (!isValid())
        return;

    glfwSwapBuffers(m_window);
}

bool Context::isValid() const
{
	return m_window != nullptr;
}

const ContextFormat & Context::format() const
{
	return m_format;
}

const std::string Context::swapIntervalString(const SwapInterval swapInterval)
{
	switch(swapInterval)
	{
        case NoVerticalSyncronization:
            return "NoVerticalSyncronization";
        case VerticalSyncronization:
            return "VerticalSyncronization";
        case AdaptiveVerticalSyncronization:
            return "AdaptiveVerticalSyncronization";
        default:
            return "";
	};
}

Context::SwapInterval Context::swapInterval() const
{
	return m_swapInterval;
}

void Context::setSwapInterval(const SwapInterval interval)
{
	if (interval == m_swapInterval)
		return;

    m_swapInterval = interval;

    makeCurrent();
    glfwSwapInterval(m_swapInterval);
    doneCurrent();
}

void Context::makeCurrent()
{
    if (!isValid())
        return;

    glfwMakeContextCurrent(m_window);
}

void Context::doneCurrent()
{
    if (!isValid())
        return;

    glfwMakeContextCurrent(0);
}

Version Context::maximumSupportedVersion()
{
    Version maxVersion;

    GLFWwindow * versionCheckWindow = glfwCreateWindow(1, 1, "VersionCheck", nullptr, nullptr);

    if (versionCheckWindow)
    {
        glfwMakeContextCurrent(versionCheckWindow);

        if (glow::init())
        {
            maxVersion = glow::Version::current();
        }

        glfwDestroyWindow(versionCheckWindow);
   }

    return maxVersion;
}

Version Context::validateVersion(const Version & version)
{
    Version maxVersion = maximumSupportedVersion();
    if (maxVersion.isNull())
    {
        maxVersion = Version(3, 0);
    }

    if (version.isNull() || version > maxVersion)
    {
        return maxVersion;
    }

    if (!version.isValid())
    {
        Version nearestValidVersion = version.nearestValidVersion();
        if (nearestValidVersion > maxVersion)
        {
            return maxVersion;
        }

        return nearestValidVersion;
    }

    return version;
}

} // namespace glowwindow
<commit_msg>(1) Removed the call to glfwDefaultWindowHints() from Context::create() so that the hints set in prepareFomrate() are not overridden.<commit_after>#include <cassert>

#include <GL/glew.h>

#include <glow/logging.h>
#include <glow/global.h>
#include <glow/Error.h>

#include <GLFW/glfw3.h> // specifies APIENTRY, should be after Error.h include,
                        // which requires APIENTRY in windows..
#include <glowwindow/Context.h>

using namespace glow;

namespace glowwindow
{

Context::Context()
: m_swapInterval(VerticalSyncronization)
, m_window(nullptr)
{
}

Context::~Context()
{
    release();
}

GLFWwindow * Context::window()
{
    return m_window;
}

bool Context::create(const ContextFormat & format, const int width, const int height, GLFWmonitor * monitor)
{
    if (isValid())
    {
        warning() << "Context is already valid. Create was probably called before.";
        return true;
    }

    if (!glfwInit())
    {
        fatal() << "Could not initialize GLFW.";
        return false;
    }

    m_format = format;
    prepareFormat(m_format);

        m_window = glfwCreateWindow(width, height, "glow", monitor, nullptr);

    if (!m_window)
    {
        fatal() << "Context creation failed (GLFW).";
        release();
        return false;
    }

    makeCurrent();

    if (!glow::init())
    {
        fatal() << "GLOW/GLEW initialization failed.";
        release();
        return false;
    }

    glfwSwapInterval(m_swapInterval);

    doneCurrent();

    // TODO: gather actual context format information and verify
    //ContextFormat::verify(format, m_format);

    return true;
}

void Context::prepareFormat(const ContextFormat & format)
{
    Version version = validateVersion(format.version());

    if (!format.version().isNull() && format.version() != version)
    {
        glow::warning() << "Changed unsupported OpenGL version from " << format.version() << " to " << version << ".";
    }

    /*
     * GLFW3 does not set default hint values on window creation so at least
     * the default values must be set before glfwCreateWindow can be called.
     * c.f. http://www.glfw.org/docs/latest/group__window.html#ga4fd9e504bb937e79588a0ffdca9f620b
     */
    glfwDefaultWindowHints();

    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, version.majorVersion);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, version.minorVersion);

    glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
    if (version >= Version(3, 2))
    {
        glfwWindowHint(GLFW_OPENGL_PROFILE, format.profile() == ContextFormat::CoreProfile ? GLFW_OPENGL_CORE_PROFILE : GLFW_OPENGL_COMPAT_PROFILE);
    }

    glfwWindowHint(GLFW_DEPTH_BITS, format.depthBufferSize());
    glfwWindowHint(GLFW_STENCIL_BITS, format.stencilBufferSize());
    glfwWindowHint(GLFW_RED_BITS, format.redBufferSize());
    glfwWindowHint(GLFW_GREEN_BITS, format.greenBufferSize());
    glfwWindowHint(GLFW_BLUE_BITS, format.blueBufferSize());
    glfwWindowHint(GLFW_ALPHA_BITS, format.alphaBufferSize());
    glfwWindowHint(GLFW_SAMPLES, format.samples());
}

void Context::release()
{
    if (!isValid())
        return;

    glfwDestroyWindow(m_window);
    m_window = nullptr;
}

void Context::swap()
{
    if (!isValid())
        return;

    glfwSwapBuffers(m_window);
}

bool Context::isValid() const
{
	return m_window != nullptr;
}

const ContextFormat & Context::format() const
{
	return m_format;
}

const std::string Context::swapIntervalString(const SwapInterval swapInterval)
{
	switch(swapInterval)
	{
        case NoVerticalSyncronization:
            return "NoVerticalSyncronization";
        case VerticalSyncronization:
            return "VerticalSyncronization";
        case AdaptiveVerticalSyncronization:
            return "AdaptiveVerticalSyncronization";
        default:
            return "";
	};
}

Context::SwapInterval Context::swapInterval() const
{
	return m_swapInterval;
}

void Context::setSwapInterval(const SwapInterval interval)
{
	if (interval == m_swapInterval)
		return;

    m_swapInterval = interval;

    makeCurrent();
    glfwSwapInterval(m_swapInterval);
    doneCurrent();
}

void Context::makeCurrent()
{
    if (!isValid())
        return;

    glfwMakeContextCurrent(m_window);
}

void Context::doneCurrent()
{
    if (!isValid())
        return;

    glfwMakeContextCurrent(0);
}

Version Context::maximumSupportedVersion()
{
    Version maxVersion;

    GLFWwindow * versionCheckWindow = glfwCreateWindow(1, 1, "VersionCheck", nullptr, nullptr);

    if (versionCheckWindow)
    {
        glfwMakeContextCurrent(versionCheckWindow);

        if (glow::init())
        {
            maxVersion = glow::Version::current();
        }

        glfwDestroyWindow(versionCheckWindow);
   }

    return maxVersion;
}

Version Context::validateVersion(const Version & version)
{
    Version maxVersion = maximumSupportedVersion();
    if (maxVersion.isNull())
    {
        maxVersion = Version(3, 0);
    }

    if (version.isNull() || version > maxVersion)
    {
        return maxVersion;
    }

    if (!version.isValid())
    {
        Version nearestValidVersion = version.nearestValidVersion();
        if (nearestValidVersion > maxVersion)
        {
            return maxVersion;
        }

        return nearestValidVersion;
    }

    return version;
}

} // namespace glowwindow
<|endoftext|>


<commit_before>
// MIT License
//
// Copyright (c) 2017 Thibault Martinez
//
// 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 <iota/constants.hpp>
#include <iota/crypto/sponge_factory.hpp>
#include <iota/models/transaction.hpp>
#include <iota/types/trinary.hpp>

namespace IOTA {

namespace Models {

const std::pair<int, int> Transaction::SignatureFragmentsOffset = { 0, 2187 };
const std::pair<int, int> Transaction::AddressOffset            = { 2187, 2268 };
const std::pair<int, int> Transaction::ValueOffset              = { 6804, 6837 };
const std::pair<int, int> Transaction::TagOffset                = { 2295, 2322 };
const std::pair<int, int> Transaction::TimestampOffset          = { 6966, 6993 };
const std::pair<int, int> Transaction::CurrentIndexOffset       = { 6993, 7020 };
const std::pair<int, int> Transaction::LastIndexOffset          = { 7020, 7047 };
const std::pair<int, int> Transaction::BundleOffset             = { 2349, 2430 };
const std::pair<int, int> Transaction::TrunkOffset              = { 2430, 2511 };
const std::pair<int, int> Transaction::BranchOffset             = { 2511, 2592 };
const std::pair<int, int> Transaction::NonceOffset              = { 2592, 2673 };

Transaction::Transaction() : value_(0), timestamp_(0), currentIndex_(0), lastIndex_(0) {
}

Transaction::Transaction(const std::string& trytes) {
  initFromTrytes(trytes);
}

Transaction::Transaction(const std::string& signatureFragments, int64_t currentIndex,
                         int64_t lastIndex, const std::string& nonce, const std::string& hash,
                         const std::string& tag, int64_t timestamp,
                         const std::string& trunkTransaction, const std::string& branchTransaction,
                         const std::string& address, int64_t value, const std::string& bundle)
    : hash_(hash),
      signatureFragments_(signatureFragments),
      address_(address),
      value_(value),
      tag_(tag),
      timestamp_(timestamp),
      currentIndex_(currentIndex),
      lastIndex_(lastIndex),
      bundle_(bundle),
      trunkTransaction_(trunkTransaction),
      branchTransaction_(branchTransaction),
      nonce_(nonce) {
}

Transaction::Transaction(const std::string& address, int64_t value, const std::string& tag,
                         int64_t timestamp)
    : address_(address),
      value_(value),
      tag_(tag),
      timestamp_(timestamp),
      currentIndex_(0),
      lastIndex_(0) {
}

bool
Transaction::isTailTransaction() const {
  return getCurrentIndex() == 0;
}

const std::string&
Transaction::getHash() const {
  return hash_;
}

void
Transaction::setHash(const std::string& hash) {
  hash_ = hash;
}

const std::string&
Transaction::getSignatureFragments() const {
  return signatureFragments_;
}

void
Transaction::setSignatureFragments(const std::string& signatureFragments) {
  signatureFragments_ = signatureFragments;
}

const std::string&
Transaction::getAddress() const {
  return address_;
}

void
Transaction::setAddress(const std::string& address) {
  address_ = address;
}

int64_t
Transaction::getValue() const {
  return value_;
}

void
Transaction::setValue(int64_t value) {
  value_ = value;
}

const std::string&
Transaction::getTag() const {
  return tag_;
}

void
Transaction::setTag(const std::string& tag) {
  tag_ = tag;
}

int64_t
Transaction::getTimestamp() const {
  return timestamp_;
}

void
Transaction::setTimestamp(int64_t timestamp) {
  timestamp_ = timestamp;
}

int64_t
Transaction::getCurrentIndex() const {
  return currentIndex_;
}

void
Transaction::setCurrentIndex(int64_t currentIndex) {
  currentIndex_ = currentIndex;
}

int64_t
Transaction::getLastIndex() const {
  return lastIndex_;
}

void
Transaction::setLastIndex(int64_t lastIndex) {
  lastIndex_ = lastIndex;
}

const std::string&
Transaction::getBundle() const {
  return bundle_;
}

void
Transaction::setBundle(const std::string& bundle) {
  bundle_ = bundle;
}

const std::string&
Transaction::getTrunkTransaction() const {
  return trunkTransaction_;
}

void
Transaction::setTrunkTransaction(const std::string& trunkTransaction) {
  trunkTransaction_ = trunkTransaction;
}

const std::string&
Transaction::getBranchTransaction() const {
  return branchTransaction_;
}

void
Transaction::setBranchTransaction(const std::string& branchTransaction) {
  branchTransaction_ = branchTransaction;
}

const std::string&
Transaction::getNonce() const {
  return nonce_;
}

void
Transaction::setNonce(const std::string& nonce) {
  nonce_ = nonce;
}

bool
Transaction::getPersistence() const {
  return persistence_;
}

void
Transaction::setPersistence(bool persistence) {
  persistence_ = persistence;
}

bool
Transaction::operator==(Transaction rhs) const {
  return hash_ == rhs.getHash();
}

bool
Transaction::operator!=(Transaction rhs) const {
  return !operator==(rhs);
}

std::string
Transaction::toTrytes() const {
  auto value = IOTA::Types::tritsToTrytes(IOTA::Types::intToTrits(getValue(), SeedLength));
  auto timestamp =
      IOTA::Types::tritsToTrytes(IOTA::Types::intToTrits(getTimestamp(), TryteAlphabetLength));
  auto currentIndex =
      IOTA::Types::tritsToTrytes(IOTA::Types::intToTrits(getCurrentIndex(), TryteAlphabetLength));
  auto lastIndex =
      IOTA::Types::tritsToTrytes(IOTA::Types::intToTrits(getLastIndex(), TryteAlphabetLength));

  return getSignatureFragments() + getAddress() + value + getTag() + timestamp + currentIndex +
         lastIndex + getBundle() + getTrunkTransaction() + getBranchTransaction() + getNonce();
}

void
Transaction::initFromTrytes(const std::string& trytes) {
  if (trytes.empty()) {
    return;
  }

  //! TODO: length check
  //! what length are we supposed to receive?

  // validity check
  for (int i = 2279; i < 2295; i++) {
    if (trytes[i] != '9') {
      return;
    }
  }

  auto transactionTrits = IOTA::Types::trytesToTrits(trytes);
  auto hash             = IOTA::Types::Trits(TritHashLength);

  // generate the correct transaction hash
  auto curl = IOTA::Crypto::create(IOTA::Crypto::SpongeType::CURL);
  curl->absorb(transactionTrits);
  curl->squeeze(hash);

  //! Hash
  setHash(IOTA::Types::tritsToTrytes(hash));
  //! Signature
  setSignatureFragments(
      trytes.substr(SignatureFragmentsOffset.first,
                    SignatureFragmentsOffset.second - SignatureFragmentsOffset.first));
  //! Address
  setAddress(trytes.substr(AddressOffset.first, AddressOffset.second - AddressOffset.first));
  //! Value
  setValue(IOTA::Types::tritsToInt<int64_t>(IOTA::Types::Trits(
      std::vector<int8_t>{ std::begin(transactionTrits) + ValueOffset.first,
                           std::begin(transactionTrits) + ValueOffset.second })));
  //! Tag
  setTag(trytes.substr(TagOffset.first, TagOffset.second - TagOffset.first));
  //! Timestamp
  setTimestamp(IOTA::Types::tritsToInt<int64_t>(IOTA::Types::Trits(
      std::vector<int8_t>{ std::begin(transactionTrits) + TimestampOffset.first,
                           std::begin(transactionTrits) + TimestampOffset.second })));
  //! Current Index
  setCurrentIndex(IOTA::Types::tritsToInt<int64_t>(IOTA::Types::Trits(
      std::vector<int8_t>{ std::begin(transactionTrits) + CurrentIndexOffset.first,
                           std::begin(transactionTrits) + CurrentIndexOffset.second })));
  //! Last Index
  setLastIndex(IOTA::Types::tritsToInt<int64_t>(IOTA::Types::Trits(
      std::vector<int8_t>{ std::begin(transactionTrits) + LastIndexOffset.first,
                           std::begin(transactionTrits) + LastIndexOffset.second })));
  //! Bundle
  setBundle(trytes.substr(BundleOffset.first, BundleOffset.second - BundleOffset.first));
  //! Trunk Transaction
  setTrunkTransaction(trytes.substr(TrunkOffset.first, TrunkOffset.second - TrunkOffset.first));
  //! Branch Transaction
  setBranchTransaction(trytes.substr(BranchOffset.first, BranchOffset.second - BranchOffset.first));
  //! Nonce
  setNonce(trytes.substr(NonceOffset.first, NonceOffset.second - NonceOffset.first));
}

}  // namespace Models

}  // namespace IOTA
<commit_msg>explicit init of bool Transaction::persistence_ to false (apparently default is false on macOS but true on debian?)<commit_after>
// MIT License
//
// Copyright (c) 2017 Thibault Martinez
//
// 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 <iota/constants.hpp>
#include <iota/crypto/sponge_factory.hpp>
#include <iota/models/transaction.hpp>
#include <iota/types/trinary.hpp>

namespace IOTA {

namespace Models {

const std::pair<int, int> Transaction::SignatureFragmentsOffset = { 0, 2187 };
const std::pair<int, int> Transaction::AddressOffset            = { 2187, 2268 };
const std::pair<int, int> Transaction::ValueOffset              = { 6804, 6837 };
const std::pair<int, int> Transaction::TagOffset                = { 2295, 2322 };
const std::pair<int, int> Transaction::TimestampOffset          = { 6966, 6993 };
const std::pair<int, int> Transaction::CurrentIndexOffset       = { 6993, 7020 };
const std::pair<int, int> Transaction::LastIndexOffset          = { 7020, 7047 };
const std::pair<int, int> Transaction::BundleOffset             = { 2349, 2430 };
const std::pair<int, int> Transaction::TrunkOffset              = { 2430, 2511 };
const std::pair<int, int> Transaction::BranchOffset             = { 2511, 2592 };
const std::pair<int, int> Transaction::NonceOffset              = { 2592, 2673 };

Transaction::Transaction()
    : value_(0), timestamp_(0), currentIndex_(0), lastIndex_(0), persistence_(false) {
}

Transaction::Transaction(const std::string& trytes) : persistence_(false) {
  initFromTrytes(trytes);
}

Transaction::Transaction(const std::string& signatureFragments, int64_t currentIndex,
                         int64_t lastIndex, const std::string& nonce, const std::string& hash,
                         const std::string& tag, int64_t timestamp,
                         const std::string& trunkTransaction, const std::string& branchTransaction,
                         const std::string& address, int64_t value, const std::string& bundle)
    : hash_(hash),
      signatureFragments_(signatureFragments),
      address_(address),
      value_(value),
      tag_(tag),
      timestamp_(timestamp),
      currentIndex_(currentIndex),
      lastIndex_(lastIndex),
      bundle_(bundle),
      trunkTransaction_(trunkTransaction),
      branchTransaction_(branchTransaction),
      nonce_(nonce),
      persistence_(false) {
}

Transaction::Transaction(const std::string& address, int64_t value, const std::string& tag,
                         int64_t timestamp)
    : address_(address),
      value_(value),
      tag_(tag),
      timestamp_(timestamp),
      currentIndex_(0),
      lastIndex_(0) {
}

bool
Transaction::isTailTransaction() const {
  return getCurrentIndex() == 0;
}

const std::string&
Transaction::getHash() const {
  return hash_;
}

void
Transaction::setHash(const std::string& hash) {
  hash_ = hash;
}

const std::string&
Transaction::getSignatureFragments() const {
  return signatureFragments_;
}

void
Transaction::setSignatureFragments(const std::string& signatureFragments) {
  signatureFragments_ = signatureFragments;
}

const std::string&
Transaction::getAddress() const {
  return address_;
}

void
Transaction::setAddress(const std::string& address) {
  address_ = address;
}

int64_t
Transaction::getValue() const {
  return value_;
}

void
Transaction::setValue(int64_t value) {
  value_ = value;
}

const std::string&
Transaction::getTag() const {
  return tag_;
}

void
Transaction::setTag(const std::string& tag) {
  tag_ = tag;
}

int64_t
Transaction::getTimestamp() const {
  return timestamp_;
}

void
Transaction::setTimestamp(int64_t timestamp) {
  timestamp_ = timestamp;
}

int64_t
Transaction::getCurrentIndex() const {
  return currentIndex_;
}

void
Transaction::setCurrentIndex(int64_t currentIndex) {
  currentIndex_ = currentIndex;
}

int64_t
Transaction::getLastIndex() const {
  return lastIndex_;
}

void
Transaction::setLastIndex(int64_t lastIndex) {
  lastIndex_ = lastIndex;
}

const std::string&
Transaction::getBundle() const {
  return bundle_;
}

void
Transaction::setBundle(const std::string& bundle) {
  bundle_ = bundle;
}

const std::string&
Transaction::getTrunkTransaction() const {
  return trunkTransaction_;
}

void
Transaction::setTrunkTransaction(const std::string& trunkTransaction) {
  trunkTransaction_ = trunkTransaction;
}

const std::string&
Transaction::getBranchTransaction() const {
  return branchTransaction_;
}

void
Transaction::setBranchTransaction(const std::string& branchTransaction) {
  branchTransaction_ = branchTransaction;
}

const std::string&
Transaction::getNonce() const {
  return nonce_;
}

void
Transaction::setNonce(const std::string& nonce) {
  nonce_ = nonce;
}

bool
Transaction::getPersistence() const {
  return persistence_;
}

void
Transaction::setPersistence(bool persistence) {
  persistence_ = persistence;
}

bool
Transaction::operator==(Transaction rhs) const {
  return hash_ == rhs.getHash();
}

bool
Transaction::operator!=(Transaction rhs) const {
  return !operator==(rhs);
}

std::string
Transaction::toTrytes() const {
  auto value = IOTA::Types::tritsToTrytes(IOTA::Types::intToTrits(getValue(), SeedLength));
  auto timestamp =
      IOTA::Types::tritsToTrytes(IOTA::Types::intToTrits(getTimestamp(), TryteAlphabetLength));
  auto currentIndex =
      IOTA::Types::tritsToTrytes(IOTA::Types::intToTrits(getCurrentIndex(), TryteAlphabetLength));
  auto lastIndex =
      IOTA::Types::tritsToTrytes(IOTA::Types::intToTrits(getLastIndex(), TryteAlphabetLength));

  return getSignatureFragments() + getAddress() + value + getTag() + timestamp + currentIndex +
         lastIndex + getBundle() + getTrunkTransaction() + getBranchTransaction() + getNonce();
}

void
Transaction::initFromTrytes(const std::string& trytes) {
  if (trytes.empty()) {
    return;
  }

  //! TODO: length check
  //! what length are we supposed to receive?

  // validity check
  for (int i = 2279; i < 2295; i++) {
    if (trytes[i] != '9') {
      return;
    }
  }

  auto transactionTrits = IOTA::Types::trytesToTrits(trytes);
  auto hash             = IOTA::Types::Trits(TritHashLength);

  // generate the correct transaction hash
  auto curl = IOTA::Crypto::create(IOTA::Crypto::SpongeType::CURL);
  curl->absorb(transactionTrits);
  curl->squeeze(hash);

  //! Hash
  setHash(IOTA::Types::tritsToTrytes(hash));
  //! Signature
  setSignatureFragments(
      trytes.substr(SignatureFragmentsOffset.first,
                    SignatureFragmentsOffset.second - SignatureFragmentsOffset.first));
  //! Address
  setAddress(trytes.substr(AddressOffset.first, AddressOffset.second - AddressOffset.first));
  //! Value
  setValue(IOTA::Types::tritsToInt<int64_t>(IOTA::Types::Trits(
      std::vector<int8_t>{ std::begin(transactionTrits) + ValueOffset.first,
                           std::begin(transactionTrits) + ValueOffset.second })));
  //! Tag
  setTag(trytes.substr(TagOffset.first, TagOffset.second - TagOffset.first));
  //! Timestamp
  setTimestamp(IOTA::Types::tritsToInt<int64_t>(IOTA::Types::Trits(
      std::vector<int8_t>{ std::begin(transactionTrits) + TimestampOffset.first,
                           std::begin(transactionTrits) + TimestampOffset.second })));
  //! Current Index
  setCurrentIndex(IOTA::Types::tritsToInt<int64_t>(IOTA::Types::Trits(
      std::vector<int8_t>{ std::begin(transactionTrits) + CurrentIndexOffset.first,
                           std::begin(transactionTrits) + CurrentIndexOffset.second })));
  //! Last Index
  setLastIndex(IOTA::Types::tritsToInt<int64_t>(IOTA::Types::Trits(
      std::vector<int8_t>{ std::begin(transactionTrits) + LastIndexOffset.first,
                           std::begin(transactionTrits) + LastIndexOffset.second })));
  //! Bundle
  setBundle(trytes.substr(BundleOffset.first, BundleOffset.second - BundleOffset.first));
  //! Trunk Transaction
  setTrunkTransaction(trytes.substr(TrunkOffset.first, TrunkOffset.second - TrunkOffset.first));
  //! Branch Transaction
  setBranchTransaction(trytes.substr(BranchOffset.first, BranchOffset.second - BranchOffset.first));
  //! Nonce
  setNonce(trytes.substr(NonceOffset.first, NonceOffset.second - NonceOffset.first));
}

}  // namespace Models

}  // namespace IOTA
<|endoftext|>


<commit_before>#include <iostream>
#include <map>
#include <Ice/Ice.h>
#include "server.h"

// TODO: remove this global variable
Ice::CommunicatorPtr ic;

class MetaServer : public Player::IMetaServer
{
	public:
		MetaServer();

		virtual void add(const std::string& endpointStr, const Player::Song& s, const Ice::Current& c);
		virtual void remove(const Player::MediaInfo& media, const Ice::Current& c);
		virtual Player::MediaInfoSeq find(const std::string& s, const Ice::Current& c);

		virtual Player::StreamToken setupStreaming(const Player::MediaInfo& media, const Ice::Current& c);
		virtual void play(const Player::StreamToken& token, const Ice::Current& c);
		virtual void stop(const Player::StreamToken& token, const Ice::Current& c);

	private:
		/* std::map<std::string, Player::IMusicServerPrx> serverList; */
		std::map<std::string, std::string> serverList;
};

MetaServer::MetaServer()
{
	serverList.emplace("MusicServer:default -h onche.ovh -p 10001", "onche.ovh");
}

void MetaServer::add(const std::string& endpointStr, const Player::Song& s, const Ice::Current& c)
{
	std::cout << "Adding to " << endpointStr << " : " << s.artist << " - " << s.title << " - " << s.path << '\n';
	Ice::ObjectPrx base = ic->stringToProxy(endpointStr);
	Player::IMusicServerPrx srv = Player::IMusicServerPrx::checkedCast(base);
	if (srv)
		srv->add(s);
}

void MetaServer::remove(const Player::MediaInfo& media, const Ice::Current& c)
{
	std::cout << "Removing on " << media.endpointStr << " : " << media.media.path << '\n';
	Ice::ObjectPrx base = ic->stringToProxy(media.endpointStr);
	Player::IMusicServerPrx srv = Player::IMusicServerPrx::checkedCast(base);
	if (srv)
		srv->remove(media.media.path);
}

Player::MediaInfoSeq MetaServer::find(const std::string& s, const Ice::Current& c)
{
	std::cout << "Searching for: " << s << '\n';
	Player::MediaInfoSeq medias;

	for (const auto& it : serverList) {
		Ice::ObjectPrx base = ic->stringToProxy(it.first);
		Player::IMusicServerPrx srv = Player::IMusicServerPrx::checkedCast(base);

		if (srv) {
			auto results = srv->find(s);
			for (const auto& r : results) {
				Player::MediaInfo m;
				m.endpointStr = it.first;
				m.media = r;
				medias.push_back(m);
			}
		}
	}
	return medias;
}

Player::StreamToken MetaServer::setupStreaming(const Player::MediaInfo& media, const Ice::Current& c)
{
	std::cout << "Setup stream on " << media.endpointStr << ", " << media.media.path << '\n';
	Player::StreamToken token;
	Ice::ObjectPrx base = ic->stringToProxy(media.endpointStr);
	Player::IMusicServerPrx srv = Player::IMusicServerPrx::checkedCast(base);

	if (srv) {
		Ice::IPConnectionInfo* ipConInfo = dynamic_cast<Ice::IPConnectionInfo*>(c.con->getInfo().get());
		token = srv->setupStreaming(media.media.path, ipConInfo->remoteAddress, std::to_string(ipConInfo->remotePort));
		token.endpointStr = media.endpointStr;
		try {
			token.streamingURL = "http://" + serverList.at(media.endpointStr) + ":8090" + '/' + token.streamingURL; // prepend http://hostname:8090
		}
		catch (const std::exception& e) {
			return Player::StreamToken();
		}
	}

	return token;
}

void MetaServer::play(const Player::StreamToken& token, const Ice::Current& c)
{
	Ice::ObjectPrx base = ic->stringToProxy(token.endpointStr);
	Player::IMusicServerPrx srv = Player::IMusicServerPrx::checkedCast(base);

	if (srv)
		srv->play(token);
}

void MetaServer::stop(const Player::StreamToken& token, const Ice::Current& c)
{
	Ice::ObjectPrx base = ic->stringToProxy(token.endpointStr);
	Player::IMusicServerPrx srv = Player::IMusicServerPrx::checkedCast(base);

	if (srv)
		srv->stop(token);
}

int main(int argc, char **argv)
{
	int status = 0;

	try {
		ic = Ice::initialize(argc, argv);
		Ice::ObjectAdapterPtr adapter = ic->createObjectAdapterWithEndpoints("MetaServerAdapter", "default -p 10000");
		Ice::ObjectPtr object = new MetaServer;
		adapter->add(object, ic->stringToIdentity("MetaServer"));
		adapter->activate();
		ic->waitForShutdown();
	}
	catch (const Ice::Exception& e) {
		std::cerr << e << std::endl;
		status = 1;
	}
	catch (const std::exception& e) {
		std::cerr << e.what() << std::endl;
		status = 1;
	}
	catch (...) {
		status = 1;
	}

	if (ic) {
		try {
			ic->destroy();
		}
		catch (const Ice::Exception& e) {
			std::cerr << e << std::endl;
			status = 1;
		}
	}

	return status;
}
<commit_msg>global ice communicator removed<commit_after>#include <iostream>
#include <map>
#include <Ice/Ice.h>
#include "server.h"

class MetaServer : public Player::IMetaServer
{
	public:
		MetaServer();

		virtual void add(const std::string& endpointStr, const Player::Song& s, const Ice::Current& c);
		virtual void remove(const Player::MediaInfo& media, const Ice::Current& c);
		virtual Player::MediaInfoSeq find(const std::string& s, const Ice::Current& c);

		virtual Player::StreamToken setupStreaming(const Player::MediaInfo& media, const Ice::Current& c);
		virtual void play(const Player::StreamToken& token, const Ice::Current& c);
		virtual void stop(const Player::StreamToken& token, const Ice::Current& c);

		void setCommunicator(const Ice::CommunicatorPtr ic) { this->ic = ic; }

	private:
		Ice::CommunicatorPtr ic = nullptr;

		/* std::map<std::string, Player::IMusicServerPrx> serverList; */
		std::map<std::string, std::string> serverList;
};

MetaServer::MetaServer()
{
	serverList.emplace("MusicServer:default -h onche.ovh -p 10001", "onche.ovh");
}

void MetaServer::add(const std::string& endpointStr, const Player::Song& s, const Ice::Current& c)
{
	std::cout << "Adding to " << endpointStr << " : " << s.artist << " - " << s.title << " - " << s.path << '\n';
	Ice::ObjectPrx base = ic->stringToProxy(endpointStr);
	Player::IMusicServerPrx srv = Player::IMusicServerPrx::checkedCast(base);
	if (srv)
		srv->add(s);
}

void MetaServer::remove(const Player::MediaInfo& media, const Ice::Current& c)
{
	std::cout << "Removing on " << media.endpointStr << " : " << media.media.path << '\n';
	Ice::ObjectPrx base = ic->stringToProxy(media.endpointStr);
	Player::IMusicServerPrx srv = Player::IMusicServerPrx::checkedCast(base);
	if (srv)
		srv->remove(media.media.path);
}

Player::MediaInfoSeq MetaServer::find(const std::string& s, const Ice::Current& c)
{
	std::cout << "Searching for: " << s << '\n';
	Player::MediaInfoSeq medias;

	for (const auto& it : serverList) {
		Ice::ObjectPrx base = ic->stringToProxy(it.first);
		Player::IMusicServerPrx srv = Player::IMusicServerPrx::checkedCast(base);

		if (srv) {
			auto results = srv->find(s);
			for (const auto& r : results) {
				Player::MediaInfo m;
				m.endpointStr = it.first;
				m.media = r;
				medias.push_back(m);
			}
		}
	}
	return medias;
}

Player::StreamToken MetaServer::setupStreaming(const Player::MediaInfo& media, const Ice::Current& c)
{
	std::cout << "Setup stream on " << media.endpointStr << ", " << media.media.path << '\n';
	Player::StreamToken token;
	Ice::ObjectPrx base = ic->stringToProxy(media.endpointStr);
	Player::IMusicServerPrx srv = Player::IMusicServerPrx::checkedCast(base);

	if (srv) {
		Ice::IPConnectionInfo* ipConInfo = dynamic_cast<Ice::IPConnectionInfo*>(c.con->getInfo().get());
		token = srv->setupStreaming(media.media.path, ipConInfo->remoteAddress, std::to_string(ipConInfo->remotePort));
		token.endpointStr = media.endpointStr;
		try {
			token.streamingURL = "http://" + serverList.at(media.endpointStr) + ":8090" + '/' + token.streamingURL; // prepend http://hostname:8090
		}
		catch (const std::exception& e) {
			return Player::StreamToken();
		}
	}

	return token;
}

void MetaServer::play(const Player::StreamToken& token, const Ice::Current& c)
{
	Ice::ObjectPrx base = ic->stringToProxy(token.endpointStr);
	Player::IMusicServerPrx srv = Player::IMusicServerPrx::checkedCast(base);

	if (srv)
		srv->play(token);
}

void MetaServer::stop(const Player::StreamToken& token, const Ice::Current& c)
{
	Ice::ObjectPrx base = ic->stringToProxy(token.endpointStr);
	Player::IMusicServerPrx srv = Player::IMusicServerPrx::checkedCast(base);

	if (srv)
		srv->stop(token);
}

int main(int argc, char **argv)
{
	Ice::CommunicatorPtr ic;
	int status = 0;

	try {
		ic = Ice::initialize(argc, argv);
		Ice::ObjectAdapterPtr adapter = ic->createObjectAdapterWithEndpoints("MetaServerAdapter", "default -p 10000");
		MetaServer* srv = new MetaServer;
		srv->setCommunicator(ic);
		Ice::ObjectPtr object = srv;
		adapter->add(object, ic->stringToIdentity("MetaServer"));
		adapter->activate();
		ic->waitForShutdown();
	}
	catch (const Ice::Exception& e) {
		std::cerr << e << std::endl;
		status = 1;
	}
	catch (const std::exception& e) {
		std::cerr << e.what() << std::endl;
		status = 1;
	}
	catch (...) {
		status = 1;
	}

	if (ic) {
		try {
			ic->destroy();
		}
		catch (const Ice::Exception& e) {
			std::cerr << e << std::endl;
			status = 1;
		}
	}

	return status;
}
<|endoftext|>