<commit_before>/**
 * \file
 * \brief Stack class implementation
 *
 * \author Copyright (C) 2014-2016 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/architecture/parameters.hpp"

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

#include <cstring>

namespace distortos
{

namespace architecture
{

namespace
{

/*---------------------------------------------------------------------------------------------------------------------+
| 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 0 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] 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, Thread& thread, void (& run)(Thread&),
		void (* preTerminationHook)(Thread&), void (& terminationHook)(Thread&))
{
	memset(storage, 0, size);
	return initializeStack(storage, size, 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_, 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()
{

}

}	// namespace architecture

}	// namespace distortos
<commit_msg>Add preprocessor validation of CONFIG_ARCHITECTURE_STACK_ALIGNMENT value<commit_after>/**
 * \file
 * \brief Stack class implementation
 *
 * \author Copyright (C) 2014-2016 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/architecture/parameters.hpp"

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

#include <cstring>

#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 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 0 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] 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, Thread& thread, void (& run)(Thread&),
		void (* preTerminationHook)(Thread&), void (& terminationHook)(Thread&))
{
	memset(storage, 0, size);
	return initializeStack(storage, size, 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_, 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()
{

}

}	// namespace architecture

}	// namespace distortos
<|endoftext|>


<commit_before>//=================================================================================================
//
//  MJP's DX11 Sample Framework
//  http://mynameismjp.wordpress.com/
//
//  All code and content licensed under Microsoft Public License (Ms-PL)
//
//=================================================================================================

/**
 * Modified for use in The Halfling Project - A Graphics Engine and Projects
 * The Halfling Project is the legal property of Adrian Astley
 * Copyright Adrian Astley 2013
 */

#include "common/sprite_font.h"

#include "common/halfling_sys.h"
#include "common/d3d_util.h"

#include <d3d11.h>
#include <algorithm>

namespace Common {

SpriteFont::SpriteFont()
	: m_size(0),
	  m_texHeight(0),
	  m_spaceWidth(0),
	  m_charHeight(0) {
}

SpriteFont::~SpriteFont() {

}

void SpriteFont::Initialize(const wchar *fontName, float fontSize, UINT fontStyle, bool antiAliased, ID3D11Device *device) {
	m_size = fontSize;

	Gdiplus::TextRenderingHint hint = antiAliased ? Gdiplus::TextRenderingHintAntiAliasGridFit : Gdiplus::TextRenderingHintSingleBitPerPixelGridFit;

	// Init GDI+
	ULONG_PTR token = NULL;
	Gdiplus::GdiplusStartupInput startupInput (NULL, true, true);
	Gdiplus::GdiplusStartupOutput startupOutput;
	HR(GdiplusStartup(&token, &startupInput, &startupOutput));

	// Create the font
	Gdiplus::Font font(fontName, fontSize, fontStyle, Gdiplus::UnitPixel, NULL);

	// Check for error during construction
	HR(font.GetLastStatus());

	// Create a temporary Bitmap and Graphics for figuring out the rough size required
	// for drawing all of the characters
	int size = static_cast<int>(fontSize * NumChars * 2) + 1;
	Gdiplus::Bitmap sizeBitmap(size, size, PixelFormat32bppARGB);
	HR(sizeBitmap.GetLastStatus());

	Gdiplus::Graphics sizeGraphics(&sizeBitmap);
	HR(sizeGraphics.GetLastStatus());
	HR(sizeGraphics.SetTextRenderingHint(hint));

	m_charHeight = font.GetHeight(&sizeGraphics) * 1.5f;

	wchar allChars[NumChars + 1];
	for (wchar i = 0; i < NumChars; ++i) {
		allChars[i] = i + StartChar;
	}
	allChars[NumChars] = 0;

	Gdiplus::RectF sizeRect;
	HR(sizeGraphics.MeasureString(allChars, NumChars, &font, Gdiplus::PointF(0, 0), &sizeRect));
	int numRows = static_cast<int>(sizeRect.Width / TexWidth) + 1;
	int texHeight = static_cast<int>(numRows * m_charHeight) + 1;

	// Create a temporary Bitmap and Graphics for drawing the characters one by one
	int tempSize = static_cast<int>(fontSize * 2);
	Gdiplus::Bitmap drawBitmap(tempSize, tempSize, PixelFormat32bppARGB);
	HR(drawBitmap.GetLastStatus());

	Gdiplus::Graphics drawGraphics(&drawBitmap);
	HR(drawGraphics.GetLastStatus());
	HR(drawGraphics.SetTextRenderingHint(hint));

	// Create a temporary Bitmap + Graphics for creating a full character set
	Gdiplus::Bitmap textBitmap (TexWidth, texHeight, PixelFormat32bppARGB);
	HR(textBitmap.GetLastStatus());

	Gdiplus::Graphics textGraphics (&textBitmap);
	HR(textGraphics.GetLastStatus());
	HR(textGraphics.Clear(Gdiplus::Color(0, 255, 255, 255)));
	HR(textGraphics.SetCompositingMode(Gdiplus::CompositingModeSourceCopy));

	// Solid brush for text rendering
	Gdiplus::SolidBrush brush (Gdiplus::Color(255, 255, 255, 255));
	HR(brush.GetLastStatus());

	// Draw all of the characters, and copy them to the full character set
	wchar charString [2];
	charString[1] = 0;
	int currentX = 0;
	int currentY = 0;
	for(uint64 i = 0; i < NumChars; ++i) {
		charString[0] = static_cast<wchar>(i + StartChar);

		// Draw the character
		HR(drawGraphics.Clear(Gdiplus::Color(0, 255, 255, 255)));
		HR(drawGraphics.DrawString(charString, 1, &font, Gdiplus::PointF(0, 0), &brush));

		// Figure out the amount of blank space before the character
		int minX = 0;
		for (int x = 0; x < tempSize; ++x) {
			for (int y = 0; y < tempSize; ++y) {
				Gdiplus::Color color;
				HR(drawBitmap.GetPixel(x, y, &color));
				if (color.GetAlpha() > 0) {
					minX = x;
					x = tempSize;
					break;
				}
			}
		}

		// Figure out the amount of blank space after the character
		int maxX = tempSize - 1;
		for (int x = tempSize - 1; x >= 0; --x) {
			for (int y = 0; y < tempSize; ++y) {
				Gdiplus::Color color;
				HR(drawBitmap.GetPixel(x, y, &color));
				if (color.GetAlpha() > 0) {
					maxX = x;
					x = -1;
					break;
				}
			}
		}

		int charWidth = maxX - minX + 1;

		// Figure out if we need to move to the next row
		if (currentX + charWidth >= TexWidth) {
			currentX = 0;
			currentY += static_cast<int>(m_charHeight) + 1;
		}

		// Fill out the structure describing the character position
		m_charDescs[i].X = static_cast<float>(currentX);
		m_charDescs[i].Y = static_cast<float>(currentY);
		m_charDescs[i].Width = static_cast<float>(charWidth);
		m_charDescs[i].Height = static_cast<float>(m_charHeight);

		// Copy the character over
		int height = static_cast<int>(m_charHeight + 1);
		HR(textGraphics.DrawImage(&drawBitmap, currentX, currentY, minX, 0, charWidth, height, Gdiplus::UnitPixel));

		currentX += charWidth + 1;
	}

	// Figure out the width of a space character
	charString[0] = ' ';
	charString[1] = 0;
	HR(drawGraphics.MeasureString(charString, 1, &font, Gdiplus::PointF(0, 0), &sizeRect));
	m_spaceWidth = sizeRect.Width;

	// Lock the bitmap for direct memory access
	Gdiplus::BitmapData bmData;
	HR(textBitmap.LockBits(&Gdiplus::Rect(0, 0, TexWidth, texHeight), Gdiplus::ImageLockModeRead, PixelFormat32bppARGB, &bmData));

	// Create a D3D texture, initalized with the bitmap data
	D3D11_TEXTURE2D_DESC texDesc;
	texDesc.Width = TexWidth;
	texDesc.Height = texHeight;
	texDesc.MipLevels = 1;
	texDesc.ArraySize = 1;
	texDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
	texDesc.SampleDesc.Count = 1;
	texDesc.SampleDesc.Quality = 0;
	texDesc.Usage = D3D11_USAGE_IMMUTABLE;
	texDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
	texDesc.CPUAccessFlags = 0;
	texDesc.MiscFlags = 0;

	D3D11_SUBRESOURCE_DATA data;
	data.pSysMem = bmData.Scan0;
	data.SysMemPitch = TexWidth * 4;
	data.SysMemSlicePitch = 0;

	HR(device->CreateTexture2D(&texDesc, &data, &m_texture));

	HR(textBitmap.UnlockBits(&bmData));

	// Create the shader resource view
	D3D11_SHADER_RESOURCE_VIEW_DESC srDesc;
	srDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
	srDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
	srDesc.Texture2D.MipLevels = 1;
	srDesc.Texture2D.MostDetailedMip = 0;

	HR(device->CreateShaderResourceView(m_texture, &srDesc, &m_SRV));

	// Shutdown GDI+
	Gdiplus::GdiplusShutdown(token);
}

ID3D11ShaderResourceView *SpriteFont::SRView() const {
	return m_SRV;
}

const SpriteFont::CharDesc *SpriteFont::CharDescriptors() const {
	return m_charDescs;
}

const SpriteFont::CharDesc &SpriteFont::GetCharDescriptor(wchar character) const {
	assert(character >= StartChar && character <= EndChar);
	return m_charDescs[character - StartChar];
}

float SpriteFont::Size() const {
	return m_size;
}

uint SpriteFont::TextureWidth() const {
	return TexWidth;
}

uint SpriteFont::TextureHeight() const {
	return m_texHeight;
}

float SpriteFont::SpaceWidth() const {
	return m_spaceWidth;
}

float SpriteFont::CharHeight() const {
	return m_charHeight;
}

ID3D11Texture2D *SpriteFont::Texture() const {
	return m_texture;
}

DirectX::XMFLOAT2 SpriteFont::MeasureText(const wchar* text) const {
	DirectX::XMFLOAT2 size(0.0f, 0.0f);
	DirectX::XMFLOAT2 curPos(0.0f, 0.0f);;

	size_t length = wcslen(text);

	for (uint64 i = 0; i < length; ++i) {
		wchar character = text[i];
		if (character == ' ') {
			curPos.x += SpaceWidth();
		} else if (character == '\n') {
			curPos.y += CharHeight();
			curPos.x = 0;
		} else {
			SpriteFont::CharDesc desc = GetCharDescriptor(character);
			curPos.x += desc.Width + 1;
		}

		size.x = std::max(curPos.x, size.x);
		size.y = std::max(curPos.y, size.y);
	}

	return size;
}

}<commit_msg>COMMON: Comment out GdiplusShutdown<commit_after>//=================================================================================================
//
//  MJP's DX11 Sample Framework
//  http://mynameismjp.wordpress.com/
//
//  All code and content licensed under Microsoft Public License (Ms-PL)
//
//=================================================================================================

/**
 * Modified for use in The Halfling Project - A Graphics Engine and Projects
 * The Halfling Project is the legal property of Adrian Astley
 * Copyright Adrian Astley 2013
 */

#include "common/sprite_font.h"

#include "common/halfling_sys.h"
#include "common/d3d_util.h"

#include <d3d11.h>
#include <algorithm>

namespace Common {

SpriteFont::SpriteFont()
	: m_size(0),
	  m_texHeight(0),
	  m_spaceWidth(0),
	  m_charHeight(0) {
}

SpriteFont::~SpriteFont() {

}

void SpriteFont::Initialize(const wchar *fontName, float fontSize, UINT fontStyle, bool antiAliased, ID3D11Device *device) {
	m_size = fontSize;

	Gdiplus::TextRenderingHint hint = antiAliased ? Gdiplus::TextRenderingHintAntiAliasGridFit : Gdiplus::TextRenderingHintSingleBitPerPixelGridFit;

	// Init GDI+
	ULONG_PTR token = NULL;
	Gdiplus::GdiplusStartupInput startupInput (NULL, true, true);
	Gdiplus::GdiplusStartupOutput startupOutput;
	HR(GdiplusStartup(&token, &startupInput, &startupOutput));

	// Create the font
	Gdiplus::Font font(fontName, fontSize, fontStyle, Gdiplus::UnitPixel, NULL);

	// Check for error during construction
	HR(font.GetLastStatus());

	// Create a temporary Bitmap and Graphics for figuring out the rough size required
	// for drawing all of the characters
	int size = static_cast<int>(fontSize * NumChars * 2) + 1;
	Gdiplus::Bitmap sizeBitmap(size, size, PixelFormat32bppARGB);
	HR(sizeBitmap.GetLastStatus());

	Gdiplus::Graphics sizeGraphics(&sizeBitmap);
	HR(sizeGraphics.GetLastStatus());
	HR(sizeGraphics.SetTextRenderingHint(hint));

	m_charHeight = font.GetHeight(&sizeGraphics) * 1.5f;

	wchar allChars[NumChars + 1];
	for (wchar i = 0; i < NumChars; ++i) {
		allChars[i] = i + StartChar;
	}
	allChars[NumChars] = 0;

	Gdiplus::RectF sizeRect;
	HR(sizeGraphics.MeasureString(allChars, NumChars, &font, Gdiplus::PointF(0, 0), &sizeRect));
	int numRows = static_cast<int>(sizeRect.Width / TexWidth) + 1;
	int texHeight = static_cast<int>(numRows * m_charHeight) + 1;

	// Create a temporary Bitmap and Graphics for drawing the characters one by one
	int tempSize = static_cast<int>(fontSize * 2);
	Gdiplus::Bitmap drawBitmap(tempSize, tempSize, PixelFormat32bppARGB);
	HR(drawBitmap.GetLastStatus());

	Gdiplus::Graphics drawGraphics(&drawBitmap);
	HR(drawGraphics.GetLastStatus());
	HR(drawGraphics.SetTextRenderingHint(hint));

	// Create a temporary Bitmap + Graphics for creating a full character set
	Gdiplus::Bitmap textBitmap (TexWidth, texHeight, PixelFormat32bppARGB);
	HR(textBitmap.GetLastStatus());

	Gdiplus::Graphics textGraphics (&textBitmap);
	HR(textGraphics.GetLastStatus());
	HR(textGraphics.Clear(Gdiplus::Color(0, 255, 255, 255)));
	HR(textGraphics.SetCompositingMode(Gdiplus::CompositingModeSourceCopy));

	// Solid brush for text rendering
	Gdiplus::SolidBrush brush (Gdiplus::Color(255, 255, 255, 255));
	HR(brush.GetLastStatus());

	// Draw all of the characters, and copy them to the full character set
	wchar charString [2];
	charString[1] = 0;
	int currentX = 0;
	int currentY = 0;
	for(uint64 i = 0; i < NumChars; ++i) {
		charString[0] = static_cast<wchar>(i + StartChar);

		// Draw the character
		HR(drawGraphics.Clear(Gdiplus::Color(0, 255, 255, 255)));
		HR(drawGraphics.DrawString(charString, 1, &font, Gdiplus::PointF(0, 0), &brush));

		// Figure out the amount of blank space before the character
		int minX = 0;
		for (int x = 0; x < tempSize; ++x) {
			for (int y = 0; y < tempSize; ++y) {
				Gdiplus::Color color;
				HR(drawBitmap.GetPixel(x, y, &color));
				if (color.GetAlpha() > 0) {
					minX = x;
					x = tempSize;
					break;
				}
			}
		}

		// Figure out the amount of blank space after the character
		int maxX = tempSize - 1;
		for (int x = tempSize - 1; x >= 0; --x) {
			for (int y = 0; y < tempSize; ++y) {
				Gdiplus::Color color;
				HR(drawBitmap.GetPixel(x, y, &color));
				if (color.GetAlpha() > 0) {
					maxX = x;
					x = -1;
					break;
				}
			}
		}

		int charWidth = maxX - minX + 1;

		// Figure out if we need to move to the next row
		if (currentX + charWidth >= TexWidth) {
			currentX = 0;
			currentY += static_cast<int>(m_charHeight) + 1;
		}

		// Fill out the structure describing the character position
		m_charDescs[i].X = static_cast<float>(currentX);
		m_charDescs[i].Y = static_cast<float>(currentY);
		m_charDescs[i].Width = static_cast<float>(charWidth);
		m_charDescs[i].Height = static_cast<float>(m_charHeight);

		// Copy the character over
		int height = static_cast<int>(m_charHeight + 1);
		HR(textGraphics.DrawImage(&drawBitmap, currentX, currentY, minX, 0, charWidth, height, Gdiplus::UnitPixel));

		currentX += charWidth + 1;
	}

	// Figure out the width of a space character
	charString[0] = ' ';
	charString[1] = 0;
	HR(drawGraphics.MeasureString(charString, 1, &font, Gdiplus::PointF(0, 0), &sizeRect));
	m_spaceWidth = sizeRect.Width;

	// Lock the bitmap for direct memory access
	Gdiplus::BitmapData bmData;
	HR(textBitmap.LockBits(&Gdiplus::Rect(0, 0, TexWidth, texHeight), Gdiplus::ImageLockModeRead, PixelFormat32bppARGB, &bmData));

	// Create a D3D texture, initalized with the bitmap data
	D3D11_TEXTURE2D_DESC texDesc;
	texDesc.Width = TexWidth;
	texDesc.Height = texHeight;
	texDesc.MipLevels = 1;
	texDesc.ArraySize = 1;
	texDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
	texDesc.SampleDesc.Count = 1;
	texDesc.SampleDesc.Quality = 0;
	texDesc.Usage = D3D11_USAGE_IMMUTABLE;
	texDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
	texDesc.CPUAccessFlags = 0;
	texDesc.MiscFlags = 0;

	D3D11_SUBRESOURCE_DATA data;
	data.pSysMem = bmData.Scan0;
	data.SysMemPitch = TexWidth * 4;
	data.SysMemSlicePitch = 0;

	HR(device->CreateTexture2D(&texDesc, &data, &m_texture));

	HR(textBitmap.UnlockBits(&bmData));

	// Create the shader resource view
	D3D11_SHADER_RESOURCE_VIEW_DESC srDesc;
	srDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
	srDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
	srDesc.Texture2D.MipLevels = 1;
	srDesc.Texture2D.MostDetailedMip = 0;

	HR(device->CreateShaderResourceView(m_texture, &srDesc, &m_SRV));

	// Shutdown GDI+
	//Gdiplus::GdiplusShutdown(token);
	// TODO: Figure out why this throws exceptions
}

ID3D11ShaderResourceView *SpriteFont::SRView() const {
	return m_SRV;
}

const SpriteFont::CharDesc *SpriteFont::CharDescriptors() const {
	return m_charDescs;
}

const SpriteFont::CharDesc &SpriteFont::GetCharDescriptor(wchar character) const {
	assert(character >= StartChar && character <= EndChar);
	return m_charDescs[character - StartChar];
}

float SpriteFont::Size() const {
	return m_size;
}

uint SpriteFont::TextureWidth() const {
	return TexWidth;
}

uint SpriteFont::TextureHeight() const {
	return m_texHeight;
}

float SpriteFont::SpaceWidth() const {
	return m_spaceWidth;
}

float SpriteFont::CharHeight() const {
	return m_charHeight;
}

ID3D11Texture2D *SpriteFont::Texture() const {
	return m_texture;
}

DirectX::XMFLOAT2 SpriteFont::MeasureText(const wchar* text) const {
	DirectX::XMFLOAT2 size(0.0f, 0.0f);
	DirectX::XMFLOAT2 curPos(0.0f, 0.0f);;

	size_t length = wcslen(text);

	for (uint64 i = 0; i < length; ++i) {
		wchar character = text[i];
		if (character == ' ') {
			curPos.x += SpaceWidth();
		} else if (character == '\n') {
			curPos.y += CharHeight();
			curPos.x = 0;
		} else {
			SpriteFont::CharDesc desc = GetCharDescriptor(character);
			curPos.x += desc.Width + 1;
		}

		size.x = std::max(curPos.x, size.x);
		size.y = std::max(curPos.y, size.y);
	}

	return size;
}

}<|endoftext|>


<commit_before>#ifndef JOINT_DEVKIT_STACKSTORAGE_HPP
#define JOINT_DEVKIT_STACKSTORAGE_HPP

#include <joint/devkit/Holder.hpp>

#include <array>

namespace joint {
namespace devkit
{

	template < typename T_ >
	T_ AlignUp(T_ value, T_ alignment)
	{ return alignment * ((value + alignment - 1) / alignment); }

	template < typename T_ >
	T_ AlignDown(T_ value, T_ alignment)
	{ return alignment * (value / alignment); }

	template < typename T_, size_t BytesSize_ >
	class StackStorage
	{
		using ElementStorage = typename std::aligned_storage<sizeof(T_), alignof(T_)>::type;
		using BufArray = std::array<ElementStorage, BytesSize_ / sizeof(T_)>;

		struct BlockDescriptor
		{
			size_t  			Count;
			ElementStorage*     Pointer;
		};

		using BlocksVector = std::vector<BlockDescriptor>;

	private:
		BufArray              _buf;
		size_t                _freeOfs;
		BlocksVector          _fallbackBlocks;

	public:
		StackStorage()
			: _freeOfs()
		{ }

		StackStorage(const StackStorage&) = delete;
		StackStorage* operator = (const StackStorage&) = delete;

		~StackStorage()
		{
			while (_freeOfs--)
				reinterpret_cast<T_&>(_buf[_freeOfs]).~T_();

			for (auto block : _fallbackBlocks)
			{
				auto count = block.Count;
				auto ptr = block.Pointer;
				for (size_t i = 0; i < count; ++i)
					reinterpret_cast<T_&>(ptr[i]).~T_();
				delete[] ptr;
			}
		}

		T_* Make(size_t count)
		{
			return AllocateAndConstruct(count, [&](T_* p) {
				size_t i = 0;
				auto sg(ScopeExit([&]() { while (i--) p[i].~T_(); }));
				for (; i < count; ++i)
					new(p + i) T_;
				sg.Cancel();
			});
		}

		template < typename... Args_ >
		T_& MakeSingle(Args_&&... args)
		{ return *AllocateAndConstruct(1, [&](T_* p, Args_&&... a) { new(p) T_(std::forward<Args_>(a)...); }, std::forward<Args_>(args)...); }

	private:
		template < typename ConstructFunc_, typename... Args_ >
		T_* AllocateAndConstruct(size_t count, ConstructFunc_&& constructFunc, Args_&&... args)
		{
			T_* result;
			if (_buf.size() >= _freeOfs + count)
			{
				auto ptr = &_buf[_freeOfs];
				_freeOfs += count;

				auto sg(ScopeExit([&]{ _freeOfs -= count; }));
				result = reinterpret_cast<T_*>(ptr);
				constructFunc(result, std::forward<Args_>(args)...);
				sg.Cancel();
			}
			else
			{
				static_assert(sizeof(ElementStorage) >= sizeof(T_), "sdfsdfgsdfg");
				auto ptr = new ElementStorage[count];
				_fallbackBlocks.push_back({ count, ptr });

				auto sg(ScopeExit([&]{ _fallbackBlocks.pop_back(); delete[] ptr; }));
				result = reinterpret_cast<T_*>(ptr);
				constructFunc(result, std::forward<Args_>(args)...);
				sg.Cancel();
			}

			return result;
		}
	};

}}

#endif
<commit_msg>Removed unnecessary parenthesis<commit_after>#ifndef JOINT_DEVKIT_STACKSTORAGE_HPP
#define JOINT_DEVKIT_STACKSTORAGE_HPP

#include <joint/devkit/Holder.hpp>

#include <array>

namespace joint {
namespace devkit
{

	template < typename T_ >
	T_ AlignUp(T_ value, T_ alignment)
	{ return alignment * ((value + alignment - 1) / alignment); }

	template < typename T_ >
	T_ AlignDown(T_ value, T_ alignment)
	{ return alignment * (value / alignment); }

	template < typename T_, size_t BytesSize_ >
	class StackStorage
	{
		using ElementStorage = typename std::aligned_storage<sizeof(T_), alignof(T_)>::type;
		using BufArray = std::array<ElementStorage, BytesSize_ / sizeof(T_)>;

		struct BlockDescriptor
		{
			size_t  			Count;
			ElementStorage*     Pointer;
		};

		using BlocksVector = std::vector<BlockDescriptor>;

	private:
		BufArray              _buf;
		size_t                _freeOfs;
		BlocksVector          _fallbackBlocks;

	public:
		StackStorage()
			: _freeOfs()
		{ }

		StackStorage(const StackStorage&) = delete;
		StackStorage* operator = (const StackStorage&) = delete;

		~StackStorage()
		{
			while (_freeOfs--)
				reinterpret_cast<T_&>(_buf[_freeOfs]).~T_();

			for (auto block : _fallbackBlocks)
			{
				auto count = block.Count;
				auto ptr = block.Pointer;
				for (size_t i = 0; i < count; ++i)
					reinterpret_cast<T_&>(ptr[i]).~T_();
				delete[] ptr;
			}
		}

		T_* Make(size_t count)
		{
			return AllocateAndConstruct(count, [&](T_* p) {
				size_t i = 0;
				auto sg(ScopeExit([&]{ while (i--) p[i].~T_(); }));
				for (; i < count; ++i)
					new(p + i) T_;
				sg.Cancel();
			});
		}

		template < typename... Args_ >
		T_& MakeSingle(Args_&&... args)
		{ return *AllocateAndConstruct(1, [&](T_* p, Args_&&... a) { new(p) T_(std::forward<Args_>(a)...); }, std::forward<Args_>(args)...); }

	private:
		template < typename ConstructFunc_, typename... Args_ >
		T_* AllocateAndConstruct(size_t count, ConstructFunc_&& constructFunc, Args_&&... args)
		{
			T_* result;
			if (_buf.size() >= _freeOfs + count)
			{
				auto ptr = &_buf[_freeOfs];
				_freeOfs += count;

				auto sg(ScopeExit([&]{ _freeOfs -= count; }));
				result = reinterpret_cast<T_*>(ptr);
				constructFunc(result, std::forward<Args_>(args)...);
				sg.Cancel();
			}
			else
			{
				static_assert(sizeof(ElementStorage) >= sizeof(T_), "sdfsdfgsdfg");
				auto ptr = new ElementStorage[count];
				_fallbackBlocks.push_back({ count, ptr });

				auto sg(ScopeExit([&]{ _fallbackBlocks.pop_back(); delete[] ptr; }));
				result = reinterpret_cast<T_*>(ptr);
				constructFunc(result, std::forward<Args_>(args)...);
				sg.Cancel();
			}

			return result;
		}
	};

}}

#endif
<|endoftext|>


<commit_before>/*
 * TTBlue Audio Object Base 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 "TTAudioObject.h"
#include "TTEnvironment.h"

// This coeff is used in GainDataspace mapping MIDI to and from linear gain
// so that MIDI=100 equals 0 dB and MIDI = 127 equals +10 dB
static const double kGainMidiPower = log(pow(10.,10./20.))/log(127./100.);
static const double kGainMidiPowerInv = 1./kGainMidiPower;

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

TTAudioObject::TTAudioObject(const char* name, TTUInt16 newMaxNumChannels)
	: TTObject(name)
{
	registerAttribute(TT("maxNumChannels"), kTypeUInt8,		&maxNumChannels,	(TTSetterMethod)&TTAudioObject::setMaxNumChannels);
	registerAttribute(TT("sr"),				kTypeUInt32,	&sr,				(TTSetterMethod)&TTAudioObject::setSr);
	registerAttribute(TT("bypass"),			kTypeBoolean,	&attrBypass,		(TTSetterMethod)&TTAudioObject::setBypass);
	registerAttribute(TT("mute"),			kTypeBoolean,	&attrMute,			(TTSetterMethod)&TTAudioObject::setMute);
	registerAttribute(TT("processInPlace"), kTypeBoolean,	&attrProcessInPlace);

	// Set Defaults...
	setAttributeValue(TT("maxNumChannels"),	newMaxNumChannels);
	setAttributeValue(TT("sr"),				ttEnvironment->sr);
	setProcess(&TTAudioObject::bypassProcess);
	setProcessWithSidechain(&TTAudioObject::bypassWithSidechainProcess);
	setAttributeValue(TT("bypass"),			*kTTBoolNo);
	setAttributeValue(TT("processInPlace"), *kTTBoolNo);
}

TTAudioObject::~TTAudioObject()
{
	;
}

TTErr TTAudioObject::setMaxNumChannels(const TTValue& newValue)
{
	TTValue	oldMaxNumChannels = maxNumChannels;

	maxNumChannels = newValue;
	sendMessage(TT("updateMaxNumChannels"), oldMaxNumChannels);
	return kTTErrNone;
}

TTErr TTAudioObject::setSr(const TTValue& newValue)
{
	sr = newValue;
	srInv = 1.0/sr;
	srMill = sr * 0.001;
	sendMessage(TT("updateSr"));
	return kTTErrNone;
}

TTErr TTAudioObject::bypassProcess(TTAudioSignal& in, TTAudioSignal& out)
{
	short			vs;
	TTSampleValue	*inSample,
	*outSample;
	short			numchannels = TTAudioSignal::getMinChannelCount(in, out);
	short			channel;

	for(channel=0; channel<numchannels; channel++){
		inSample = in.sampleVectors[channel];
		outSample = out.sampleVectors[channel];
		vs = in.getVectorSize();
		while(vs--)
			*outSample++ = *inSample++;
	}
	return kTTErrNone;
}

TTErr TTAudioObject::bypassWithSidechainProcess(TTAudioSignal& in1, TTAudioSignal& in2, TTAudioSignal& out1, TTAudioSignal& out2)
{
	TTUInt16		vs;
	TTSampleValue	*inSample,
	*outSample;
	TTUInt16		numChannelsMain = TTAudioSignal::getMinChannelCount(in1, out1);
	TTUInt16		numChannelsSidechain = TTAudioSignal::getMinChannelCount(in2, out2);
	TTUInt16		channel;

	for(channel=0; channel<numChannelsMain; channel++){
		inSample = in1.sampleVectors[channel];
		outSample = out1.sampleVectors[channel];
		vs = in1.getVectorSize();
		while(vs--)
			*outSample++ = *inSample++;
	}
	for(channel=0; channel<numChannelsSidechain; channel++){
		inSample = in2.sampleVectors[channel];
		outSample = out2.sampleVectors[channel];
		vs = in2.getVectorSize();
		while(vs--)
			*outSample++ = *inSample++;
	}
	return kTTErrNone;
}

TTErr TTAudioObject::muteProcess(TTAudioSignal& in, TTAudioSignal& out)
{
	short			vs;
	TTSampleValue*	outSample;
	short			numchannels = TTAudioSignal::getMinChannelCount(in, out);
	short			channel;

	for(channel=0; channel<numchannels; channel++){
		outSample = out.sampleVectors[channel];
		vs = out.getVectorSize();
		while(vs--)
			*outSample++ = 0.0;
	}
	return kTTErrNone;
}

TTErr TTAudioObject::muteWithSidechainProcess(TTAudioSignal& in1, TTAudioSignal& in2, TTAudioSignal& out1, TTAudioSignal& out2)
{
	TTUInt16		vs;
	TTSampleValue*	outSample;
	TTUInt16		numChannelsMain = TTAudioSignal::getMinChannelCount(in1, out1);
	TTUInt16		numChannelsSidechain = TTAudioSignal::getMinChannelCount(in2, out2);
	TTUInt16		channel;

	for(channel=0; channel<numChannelsMain; channel++){
		outSample = out1.sampleVectors[channel];
		vs = out1.getVectorSize();
		while(vs--)
			*outSample++ = 0.0;
	}
	for(channel=0; channel<numChannelsSidechain; channel++){
		outSample = out2.sampleVectors[channel];
		vs = out2.getVectorSize();
		while(vs--)
			*outSample++ = 0.0;
	}
	return kTTErrNone;
}

TTErr TTAudioObject::setProcess(TTProcessMethod newProcessMethod)
{
	processMethod = newProcessMethod;
	if(!attrBypass)
		currentProcessMethod = processMethod;
	return kTTErrNone;
}

TTErr TTAudioObject::setProcessWithSidechain(TTProcessWithSidechainMethod newProcessMethod)
{
	processWithSidechainMethod = newProcessMethod;
	if(!attrBypass)
		currentProcessWithSidechainMethod = processWithSidechainMethod;
	return kTTErrNone;
}

TTErr TTAudioObject::setBypass(const TTValue& value)
{
	attrBypass = value;
	if(attrBypass){
		currentProcessMethod = &TTAudioObject::bypassProcess;
		currentProcessWithSidechainMethod = &TTAudioObject::bypassWithSidechainProcess;
	}
	else if(attrMute){
		currentProcessMethod = &TTAudioObject::muteProcess;
		currentProcessWithSidechainMethod = &TTAudioObject::muteWithSidechainProcess;
	}
	else{
		currentProcessMethod = processMethod;
		currentProcessWithSidechainMethod = processWithSidechainMethod;
	}
	return kTTErrNone;
}

TTErr TTAudioObject::setMute(const TTValue& value)
{
	attrBypass = value;
	if(attrBypass){
		currentProcessMethod = &TTAudioObject::bypassProcess;
		currentProcessWithSidechainMethod = &TTAudioObject::bypassWithSidechainProcess;
	}
	else if(attrMute){
		currentProcessMethod = &TTAudioObject::muteProcess;
		currentProcessWithSidechainMethod = &TTAudioObject::muteWithSidechainProcess;
	}
	else{
		currentProcessMethod = processMethod;
		currentProcessWithSidechainMethod = processWithSidechainMethod;
	}
	return kTTErrNone;
}

TTErr TTAudioObject::process(TTAudioSignal& in, TTAudioSignal& out)
{
	TTErr	err;

	lock();
	err = (this->*currentProcessMethod)(in, out);
	unlock();
	return err;
}

TTErr TTAudioObject::process(TTAudioSignal& out)
{
	TTErr	err;

	lock();
	err = (this->*currentProcessMethod)(out, out);
	unlock();
	return err;
}

TTErr TTAudioObject::process(TTAudioSignal& in1, TTAudioSignal& in2, TTAudioSignal& out1, TTAudioSignal& out2)
{
	TTErr	err;

	lock();
	err = (this->*currentProcessWithSidechainMethod)(in1, in2, out1, out2);
	unlock();
	return err;
}

TTErr TTAudioObject::process(TTAudioSignal& in1, TTAudioSignal& in2, TTAudioSignal& out)
{
	TTErr	err;

	lock();
	err = (this->*currentProcessWithSidechainMethod)(in1, in2, out, out);
	unlock();
	return err;
}

#if 0
#pragma mark -
#pragma mark Utilities
#endif

// RADIANS CONVERSIONS: cannot make static because of access to a member data element
// hz-to-radians conversion
TTFloat64 TTAudioObject::hertzToRadians(const TTFloat64 hz)			// NOTE: Be sure to set the sr before calling this function
{
	return(hz * (kTTPi / (sr * 0.5)));
}

// radians-to-hz conversion
TTFloat64 TTAudioObject::radiansToHertz(const TTFloat64 radians)	// NOTE: Be sure to set the sr before calling this function
{
	return((radians * sr) / kTTTwoPi);
}

// degrees-to-radians conversion
TTFloat64 TTAudioObject::degreesToRadians(const TTFloat64 degrees)
{
	return((degrees * kTTPi) / 180.);
}

// radians-to-degrees conversion
TTFloat64 TTAudioObject::radiansToDegrees(const TTFloat64 radians)
{
	return((radians * 180.) / kTTPi);
}

// Decay Time (seconds) to feedback coefficient conversion
TTFloat64 TTAudioObject::decayToFeedback(const TTFloat64 decay_time, TTFloat64 delay)
{
	TTFloat64 	fb;

	delay = delay * 0.001;			// convert delay from milliseconds to seconds
	if(decay_time < 0){
		fb = delay / -decay_time;
		fb = fb * -60.;
		fb = pow(10., (fb / 20.));
		fb *= -1.;
	}
	else{
		fb = delay / decay_time;
		fb = fb * -60.;
		fb = pow(10., (fb / 20.));
	}
	return(fb);
}

// return the decay time based on the feedback coefficient
TTFloat64 TTAudioObject::feedbackToDecay(const TTFloat64 feedback, const TTFloat64 delay)
{
	TTFloat64 	decay_time;

	if(feedback > 0){
		decay_time = 20. * (log10(feedback));
		decay_time = -60.0 / decay_time;
		decay_time = decay_time * (delay);
	}
	else if(feedback < 0){
		decay_time = 20. * (log10(fabs(feedback)));
		decay_time = -60.0 / decay_time;
		decay_time = decay_time * (-delay);
	}
	else
		decay_time = 0;

	return(decay_time);
}

// ************* DECIBEL CONVERSIONS **************

// Amplitude to decibels
TTFloat64 TTAudioObject::linearToDb(const TTFloat64 value)
{
	if(value >= 0)
		return(20. * (log10(value)));
	else
	 	return 0;
}

// Decibels to amplitude
TTFloat64 TTAudioObject::dbToLinear(TTFloat64 value)
{
	return(pow(10., (value / 20.)));
}

TTFloat64 TTAudioObject::midiToLinearGain(TTFloat64 value)
{
	return pow(value * 0.01, kGainMidiPower);
}

TTFloat64 TTAudioObject::linearGainToMidi(TTFloat64 value)
{
	return 100.0 * pow(value, kGainMidiPowerInv);
}

// Deviate
TTFloat64 TTAudioObject::deviate(TTFloat64 value)
{
	value += (2.0 * (TTFloat32(rand()) / TTFloat32(RAND_MAX))) - 1.0;	// randomize input with +1 to -1 ms
	value = value * 0.001 * sr;											// convert from ms to samples
	value = (TTFloat32)prime(TTUInt32(value));							// find the nearest prime number (in samples)
	value = (value / sr) * 1000.0;										// convert back to ms

	return value;
}

// Prime
TTUInt32 TTAudioObject::prime(TTUInt32 value)
{
	long	candidate, last, i, isPrime;

   	if(value < 2)
  		candidate = 2;
	else if(value == 2)
		candidate = 3;
	else{
		candidate = value;
		if (candidate % 2 == 0)								// Test only odd numbers
			candidate--;
		do{
			isPrime = true;									// Assume glorious success
			candidate += 2;									// Bump to the next number to test
			last = TTUInt32(sqrt((TTFloat32)candidate));  	// We'll check to see if candidate has any factors, from 2 to last
			for (i=3; (i <= last) && isPrime; i+=2){		// Loop through odd numbers only
				if((candidate % i) == 0)
				isPrime = false;
			}
		}
		while (!isPrime);
	}
	return candidate;
}

<commit_msg>Fix for unitialized variable.<commit_after>/*
 * TTBlue Audio Object Base 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 "TTAudioObject.h"
#include "TTEnvironment.h"

// This coeff is used in GainDataspace mapping MIDI to and from linear gain
// so that MIDI=100 equals 0 dB and MIDI = 127 equals +10 dB
static const double kGainMidiPower = log(pow(10.,10./20.))/log(127./100.);
static const double kGainMidiPowerInv = 1./kGainMidiPower;

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

TTAudioObject::TTAudioObject(const char* name, TTUInt16 newMaxNumChannels)
	: TTObject(name), attrMute(0)
{
	registerAttribute(TT("maxNumChannels"), kTypeUInt8,		&maxNumChannels,	(TTSetterMethod)&TTAudioObject::setMaxNumChannels);
	registerAttribute(TT("sr"),				kTypeUInt32,	&sr,				(TTSetterMethod)&TTAudioObject::setSr);
	registerAttribute(TT("bypass"),			kTypeBoolean,	&attrBypass,		(TTSetterMethod)&TTAudioObject::setBypass);
	registerAttribute(TT("mute"),			kTypeBoolean,	&attrMute,			(TTSetterMethod)&TTAudioObject::setMute);
	registerAttribute(TT("processInPlace"), kTypeBoolean,	&attrProcessInPlace);

	// Set Defaults...
	setAttributeValue(TT("maxNumChannels"),	newMaxNumChannels);
	setAttributeValue(TT("sr"),				ttEnvironment->sr);
	setProcess(&TTAudioObject::bypassProcess);
	setProcessWithSidechain(&TTAudioObject::bypassWithSidechainProcess);
	setAttributeValue(TT("bypass"),			*kTTBoolNo);
	setAttributeValue(TT("processInPlace"), *kTTBoolNo);
}

TTAudioObject::~TTAudioObject()
{
	;
}

TTErr TTAudioObject::setMaxNumChannels(const TTValue& newValue)
{
	TTValue	oldMaxNumChannels = maxNumChannels;

	maxNumChannels = newValue;
	sendMessage(TT("updateMaxNumChannels"), oldMaxNumChannels);
	return kTTErrNone;
}

TTErr TTAudioObject::setSr(const TTValue& newValue)
{
	sr = newValue;
	srInv = 1.0/sr;
	srMill = sr * 0.001;
	sendMessage(TT("updateSr"));
	return kTTErrNone;
}

TTErr TTAudioObject::bypassProcess(TTAudioSignal& in, TTAudioSignal& out)
{
	short			vs;
	TTSampleValue	*inSample,
	*outSample;
	short			numchannels = TTAudioSignal::getMinChannelCount(in, out);
	short			channel;

	for(channel=0; channel<numchannels; channel++){
		inSample = in.sampleVectors[channel];
		outSample = out.sampleVectors[channel];
		vs = in.getVectorSize();
		while(vs--)
			*outSample++ = *inSample++;
	}
	return kTTErrNone;
}

TTErr TTAudioObject::bypassWithSidechainProcess(TTAudioSignal& in1, TTAudioSignal& in2, TTAudioSignal& out1, TTAudioSignal& out2)
{
	TTUInt16		vs;
	TTSampleValue	*inSample,
	*outSample;
	TTUInt16		numChannelsMain = TTAudioSignal::getMinChannelCount(in1, out1);
	TTUInt16		numChannelsSidechain = TTAudioSignal::getMinChannelCount(in2, out2);
	TTUInt16		channel;

	for(channel=0; channel<numChannelsMain; channel++){
		inSample = in1.sampleVectors[channel];
		outSample = out1.sampleVectors[channel];
		vs = in1.getVectorSize();
		while(vs--)
			*outSample++ = *inSample++;
	}
	for(channel=0; channel<numChannelsSidechain; channel++){
		inSample = in2.sampleVectors[channel];
		outSample = out2.sampleVectors[channel];
		vs = in2.getVectorSize();
		while(vs--)
			*outSample++ = *inSample++;
	}
	return kTTErrNone;
}

TTErr TTAudioObject::muteProcess(TTAudioSignal& in, TTAudioSignal& out)
{
	short			vs;
	TTSampleValue*	outSample;
	short			numchannels = TTAudioSignal::getMinChannelCount(in, out);
	short			channel;

	for(channel=0; channel<numchannels; channel++){
		outSample = out.sampleVectors[channel];
		vs = out.getVectorSize();
		while(vs--)
			*outSample++ = 0.0;
	}
	return kTTErrNone;
}

TTErr TTAudioObject::muteWithSidechainProcess(TTAudioSignal& in1, TTAudioSignal& in2, TTAudioSignal& out1, TTAudioSignal& out2)
{
	TTUInt16		vs;
	TTSampleValue*	outSample;
	TTUInt16		numChannelsMain = TTAudioSignal::getMinChannelCount(in1, out1);
	TTUInt16		numChannelsSidechain = TTAudioSignal::getMinChannelCount(in2, out2);
	TTUInt16		channel;

	for(channel=0; channel<numChannelsMain; channel++){
		outSample = out1.sampleVectors[channel];
		vs = out1.getVectorSize();
		while(vs--)
			*outSample++ = 0.0;
	}
	for(channel=0; channel<numChannelsSidechain; channel++){
		outSample = out2.sampleVectors[channel];
		vs = out2.getVectorSize();
		while(vs--)
			*outSample++ = 0.0;
	}
	return kTTErrNone;
}

TTErr TTAudioObject::setProcess(TTProcessMethod newProcessMethod)
{
	processMethod = newProcessMethod;
	if(!attrBypass)
		currentProcessMethod = processMethod;
	return kTTErrNone;
}

TTErr TTAudioObject::setProcessWithSidechain(TTProcessWithSidechainMethod newProcessMethod)
{
	processWithSidechainMethod = newProcessMethod;
	if(!attrBypass)
		currentProcessWithSidechainMethod = processWithSidechainMethod;
	return kTTErrNone;
}

TTErr TTAudioObject::setBypass(const TTValue& value)
{
	attrBypass = value;
	if(attrBypass){
		currentProcessMethod = &TTAudioObject::bypassProcess;
		currentProcessWithSidechainMethod = &TTAudioObject::bypassWithSidechainProcess;
	}
	else if(attrMute){
		currentProcessMethod = &TTAudioObject::muteProcess;
		currentProcessWithSidechainMethod = &TTAudioObject::muteWithSidechainProcess;
	}
	else{
		currentProcessMethod = processMethod;
		currentProcessWithSidechainMethod = processWithSidechainMethod;
	}
	return kTTErrNone;
}

TTErr TTAudioObject::setMute(const TTValue& value)
{
	attrBypass = value;
	if(attrBypass){
		currentProcessMethod = &TTAudioObject::bypassProcess;
		currentProcessWithSidechainMethod = &TTAudioObject::bypassWithSidechainProcess;
	}
	else if(attrMute){
		currentProcessMethod = &TTAudioObject::muteProcess;
		currentProcessWithSidechainMethod = &TTAudioObject::muteWithSidechainProcess;
	}
	else{
		currentProcessMethod = processMethod;
		currentProcessWithSidechainMethod = processWithSidechainMethod;
	}
	return kTTErrNone;
}

TTErr TTAudioObject::process(TTAudioSignal& in, TTAudioSignal& out)
{
	TTErr	err;

	lock();
	err = (this->*currentProcessMethod)(in, out);
	unlock();
	return err;
}

TTErr TTAudioObject::process(TTAudioSignal& out)
{
	TTErr	err;

	lock();
	err = (this->*currentProcessMethod)(out, out);
	unlock();
	return err;
}

TTErr TTAudioObject::process(TTAudioSignal& in1, TTAudioSignal& in2, TTAudioSignal& out1, TTAudioSignal& out2)
{
	TTErr	err;

	lock();
	err = (this->*currentProcessWithSidechainMethod)(in1, in2, out1, out2);
	unlock();
	return err;
}

TTErr TTAudioObject::process(TTAudioSignal& in1, TTAudioSignal& in2, TTAudioSignal& out)
{
	TTErr	err;

	lock();
	err = (this->*currentProcessWithSidechainMethod)(in1, in2, out, out);
	unlock();
	return err;
}

#if 0
#pragma mark -
#pragma mark Utilities
#endif

// RADIANS CONVERSIONS: cannot make static because of access to a member data element
// hz-to-radians conversion
TTFloat64 TTAudioObject::hertzToRadians(const TTFloat64 hz)			// NOTE: Be sure to set the sr before calling this function
{
	return(hz * (kTTPi / (sr * 0.5)));
}

// radians-to-hz conversion
TTFloat64 TTAudioObject::radiansToHertz(const TTFloat64 radians)	// NOTE: Be sure to set the sr before calling this function
{
	return((radians * sr) / kTTTwoPi);
}

// degrees-to-radians conversion
TTFloat64 TTAudioObject::degreesToRadians(const TTFloat64 degrees)
{
	return((degrees * kTTPi) / 180.);
}

// radians-to-degrees conversion
TTFloat64 TTAudioObject::radiansToDegrees(const TTFloat64 radians)
{
	return((radians * 180.) / kTTPi);
}

// Decay Time (seconds) to feedback coefficient conversion
TTFloat64 TTAudioObject::decayToFeedback(const TTFloat64 decay_time, TTFloat64 delay)
{
	TTFloat64 	fb;

	delay = delay * 0.001;			// convert delay from milliseconds to seconds
	if(decay_time < 0){
		fb = delay / -decay_time;
		fb = fb * -60.;
		fb = pow(10., (fb / 20.));
		fb *= -1.;
	}
	else{
		fb = delay / decay_time;
		fb = fb * -60.;
		fb = pow(10., (fb / 20.));
	}
	return(fb);
}

// return the decay time based on the feedback coefficient
TTFloat64 TTAudioObject::feedbackToDecay(const TTFloat64 feedback, const TTFloat64 delay)
{
	TTFloat64 	decay_time;

	if(feedback > 0){
		decay_time = 20. * (log10(feedback));
		decay_time = -60.0 / decay_time;
		decay_time = decay_time * (delay);
	}
	else if(feedback < 0){
		decay_time = 20. * (log10(fabs(feedback)));
		decay_time = -60.0 / decay_time;
		decay_time = decay_time * (-delay);
	}
	else
		decay_time = 0;

	return(decay_time);
}

// ************* DECIBEL CONVERSIONS **************

// Amplitude to decibels
TTFloat64 TTAudioObject::linearToDb(const TTFloat64 value)
{
	if(value >= 0)
		return(20. * (log10(value)));
	else
	 	return 0;
}

// Decibels to amplitude
TTFloat64 TTAudioObject::dbToLinear(TTFloat64 value)
{
	return(pow(10., (value / 20.)));
}

TTFloat64 TTAudioObject::midiToLinearGain(TTFloat64 value)
{
	return pow(value * 0.01, kGainMidiPower);
}

TTFloat64 TTAudioObject::linearGainToMidi(TTFloat64 value)
{
	return 100.0 * pow(value, kGainMidiPowerInv);
}

// Deviate
TTFloat64 TTAudioObject::deviate(TTFloat64 value)
{
	value += (2.0 * (TTFloat32(rand()) / TTFloat32(RAND_MAX))) - 1.0;	// randomize input with +1 to -1 ms
	value = value * 0.001 * sr;											// convert from ms to samples
	value = (TTFloat32)prime(TTUInt32(value));							// find the nearest prime number (in samples)
	value = (value / sr) * 1000.0;										// convert back to ms

	return value;
}

// Prime
TTUInt32 TTAudioObject::prime(TTUInt32 value)
{
	long	candidate, last, i, isPrime;

   	if(value < 2)
  		candidate = 2;
	else if(value == 2)
		candidate = 3;
	else{
		candidate = value;
		if (candidate % 2 == 0)								// Test only odd numbers
			candidate--;
		do{
			isPrime = true;									// Assume glorious success
			candidate += 2;									// Bump to the next number to test
			last = TTUInt32(sqrt((TTFloat32)candidate));  	// We'll check to see if candidate has any factors, from 2 to last
			for (i=3; (i <= last) && isPrime; i+=2){		// Loop through odd numbers only
				if((candidate % i) == 0)
				isPrime = false;
			}
		}
		while (!isPrime);
	}
	return candidate;
}

<|endoftext|>


<commit_before>#include "exception/Base.h"
#include "hardware/pcb/V6.h"
#include "data/Waveform.h"
#include "data/MEvent.h"

namespace blitzortung {
  namespace hardware {
    namespace pcb {

      const pt::time_duration V6::SAMPLE_RATE = pt::nanoseconds(3125);

      V6::V6(comm::Base& comm, gps::Base& gps) :
	Base(comm, gps, data::Format::CP(new data::Format(8,2,64))),
	logger_("hardware.pcb.V6")
      {
	if (logger_.isDebugEnabled())
	  logger_.debugStream() << "initialized";
      }

      V6::~V6() {
	if (logger_.isDebugEnabled())
	  logger_.debugStream() << "deleted";
      }

      data::Event::AP V6::parse(const std::vector<std::string> &fields) {
	if (logger_.isDebugEnabled())
	  logger_.debugStream() << "parse() called";

	data::Event::AP event;

	// parse lighning event information
	if (fields[0] == "BLSEQ") {

	  // read counter value
	  int counter = parseHex(fields[1]);

	  pt::ptime eventtime = gps_.getTime(counter);

	  if (gps_.isValid() && eventtime != pt::not_a_date_time) {
	    if (logger_.isInfoEnabled())
	      logger_.infoStream() << "ѕtring data size: " << fields[2].size();

	    event = parseData(eventtime, fields[2]);

	    if (logger_.isDebugEnabled())
	      logger_.debugStream() << "parse() event ready";

	  } else {
	    logger_.warnStream() << "GPS information is not yet valid -> no event created";
	  }

	} else {
	  logger_.errorStream() << "parse() data header '" << fields[0] << "' mismatch";
	}

	return event;
      }

      data::Event::AP V6::parseData(const pt::ptime& eventtime, const std::string& data) {

	int numberOfEvents = data.size() >> 2;

	if (logger_.isInfoEnabled())
	  logger_.infoStream() << "parseData() " << numberOfEvents << " to format " << *dataFormat_;

	data::Array::AP array(new data::Array(dataFormat_));

	for (int i=0; i < numberOfEvents; i++) {

	  int index = i << 2;

	  unsigned short xval = parseHex(data.substr(index, 2));
	  unsigned short yval = parseHex(data.substr(index + 2, 2));

	  array->set(xval, i, 0);
	  array->set(yval, i, 1);
	}

	data::Waveform::AP wfm(new data::Waveform(array, eventtime, SAMPLE_RATE));

	data::Event::AP event = data::MEvent::AP(new data::MEvent(wfm, gps_.getInfo(), data));

	if (logger_.isDebugEnabled())
	  logger_.debugStream() << "parseData() done";

	return event;
      }
    }
  }
}

<commit_msg>signed data fix<commit_after>#include "exception/Base.h"
#include "hardware/pcb/V6.h"
#include "data/Waveform.h"
#include "data/MEvent.h"

namespace blitzortung {
  namespace hardware {
    namespace pcb {

      const pt::time_duration V6::SAMPLE_RATE = pt::nanoseconds(3125);

      V6::V6(comm::Base& comm, gps::Base& gps) :
	Base(comm, gps, data::Format::CP(new data::Format(8,2,64))),
	logger_("hardware.pcb.V6")
      {
	if (logger_.isDebugEnabled())
	  logger_.debugStream() << "initialized";
      }

      V6::~V6() {
	if (logger_.isDebugEnabled())
	  logger_.debugStream() << "deleted";
      }

      data::Event::AP V6::parse(const std::vector<std::string> &fields) {
	if (logger_.isDebugEnabled())
	  logger_.debugStream() << "parse() called";

	data::Event::AP event;

	// parse lighning event information
	if (fields[0] == "BLSEQ") {

	  // read counter value
	  int counter = parseHex(fields[1]);

	  pt::ptime eventtime = gps_.getTime(counter);

	  if (gps_.isValid() && eventtime != pt::not_a_date_time) {
	    if (logger_.isInfoEnabled())
	      logger_.infoStream() << "ѕtring data size: " << fields[2].size();

	    event = parseData(eventtime, fields[2]);

	    if (logger_.isDebugEnabled())
	      logger_.debugStream() << "parse() event ready";

	  } else {
	    logger_.warnStream() << "GPS information is not yet valid -> no event created";
	  }

	} else {
	  logger_.errorStream() << "parse() data header '" << fields[0] << "' mismatch";
	}

	return event;
      }

      data::Event::AP V6::parseData(const pt::ptime& eventtime, const std::string& data) {

	int numberOfEvents = data.size() >> 2;

	if (logger_.isInfoEnabled())
	  logger_.infoStream() << "parseData() " << numberOfEvents << " to format " << *dataFormat_;

	data::Array::AP array(new data::Array(dataFormat_));

	int offset = 1 << (dataFormat_->getNumberOfBits() - 1);
	logger_.infoStream() << "offset: " << offset;

	for (int i=0; i < numberOfEvents; i++) {

	  int index = i << 2;

	  short xval = parseHex(data.substr(index, 2)) - offset;
	  short yval = parseHex(data.substr(index + 2, 2)) - offset;

	  array->set(xval, i, 0);
	  array->set(yval, i, 1);
	}

	data::Waveform::AP wfm(new data::Waveform(array, eventtime, SAMPLE_RATE));

	data::Event::AP event = data::MEvent::AP(new data::MEvent(wfm, gps_.getInfo(), data));

	if (logger_.isDebugEnabled())
	  logger_.debugStream() << "parseData() done";

	return event;
      }
    }
  }
}

<|endoftext|>


<commit_before>#include <list>
#include "DeEn.h"
#include "moses/Util.h"

using namespace std;

extern bool g_debug;

bool IsA(const Phrase &source, int pos, int offset, int factor, const string &str)
{
  pos += offset;
  if (pos >= source.size() || pos < 0) {
    return false;
  }

  const string &word = source[pos][factor];
  vector<string> soughts = Moses::Tokenize(str, " ");
  for (int i = 0; i < soughts.size(); ++i) {
    string &sought = soughts[i];
    bool found = (word == sought);
    if (found) {
      return true;
    }
  }
  return false;
}

bool Contains(const Phrase &source, int start, int end, int factor, const string &str)
{
  for (int pos = start; pos <= end; ++pos) {
    bool found = IsA(source, pos, 0, factor, str);
    if (found) {
      return true;
    }
  }
  return false;
}

void LabelDeEn(const Phrase &source, ostream &out)
{
  typedef pair<int,int> Range;
  typedef list<Range> Ranges;
  Ranges ranges;

  // find ranges to label
  for (int start = 0; start < source.size(); ++start) {
    for (int end = start; end < source.size(); ++end) {
     if (IsA(source, start, -1, 1, "vafin")
          && IsA(source, end, +1, 1, "vvinf vvpp")
          && !Contains(source, start, end, 1, "vafin vvinf vvpp vvfin")) {
       Range range(start, end);
       ranges.push_back(range);
      }
      else if ((start == 0 || IsA(source, start, -1, 1, "$,"))
          && IsA(source, end, +1, 0, "zu")
          && IsA(source, end, +2, 1, "vvinf")
          && !Contains(source, start, end, 1, "$,")) {
        Range range(start, end);
        ranges.push_back(range);
      }
    }
  }

  // output sentence, with labels
  for (int pos = 0; pos < source.size(); ++pos) {
    // output beginning of label
    for (Ranges::const_iterator iter = ranges.begin(); iter != ranges.end(); ++iter) {
      const Range &range = *iter;
      if (range.first == pos) {
        out << "<tree label=\"reorder-label\"> ";
      }
    }

    const Word &word = source[pos];
    out << word[0] << " ";

    for (Ranges::const_iterator iter = ranges.begin(); iter != ranges.end(); ++iter) {
      const Range &range = *iter;
      if (range.second == pos) {
        out << "</tree> ";
      }
    }
  }
  out << endl;

}
<commit_msg>add source labeller to EMS<commit_after>#include <list>
#include "DeEn.h"
#include "moses/Util.h"

using namespace std;

extern bool g_debug;

bool IsA(const Phrase &source, int pos, int offset, int factor, const string &str)
{
  pos += offset;
  if (pos >= source.size() || pos < 0) {
    return false;
  }

  const string &word = source[pos][factor];
  vector<string> soughts = Moses::Tokenize(str, " ");
  for (int i = 0; i < soughts.size(); ++i) {
    string &sought = soughts[i];
    bool found = (word == sought);
    if (found) {
      return true;
    }
  }
  return false;
}

bool Contains(const Phrase &source, int start, int end, int factor, const string &str)
{
  for (int pos = start; pos <= end; ++pos) {
    bool found = IsA(source, pos, 0, factor, str);
    if (found) {
      return true;
    }
  }
  return false;
}

void LabelDeEn(const Phrase &source, ostream &out)
{
  typedef pair<int,int> Range;
  typedef list<Range> Ranges;
  Ranges ranges;

  // find ranges to label
  for (int start = 0; start < source.size(); ++start) {
    for (int end = start; end < source.size(); ++end) {
     if (IsA(source, start, -1, 1, "VAFIN")
          && IsA(source, end, +1, 1, "VVINF VVPP")
          && !Contains(source, start, end, 1, "VAFIN VVINF VVPP VVFIN")) {
       Range range(start, end);
       ranges.push_back(range);
      }
      else if ((start == 0 || IsA(source, start, -1, 1, "$,"))
          && IsA(source, end, +1, 0, "zu")
          && IsA(source, end, +2, 1, "VVINF")
          && !Contains(source, start, end, 1, "$,")) {
        Range range(start, end);
        ranges.push_back(range);
      }
    }
  }

  // output sentence, with labels
  for (int pos = 0; pos < source.size(); ++pos) {
    // output beginning of label
    for (Ranges::const_iterator iter = ranges.begin(); iter != ranges.end(); ++iter) {
      const Range &range = *iter;
      if (range.first == pos) {
        out << "<tree label=\"reorder-label\"> ";
      }
    }

    const Word &word = source[pos];
    out << word[0] << " ";

    for (Ranges::const_iterator iter = ranges.begin(); iter != ranges.end(); ++iter) {
      const Range &range = *iter;
      if (range.second == pos) {
        out << "</tree> ";
      }
    }
  }
  out << endl;

}
<|endoftext|>


<commit_before>/**************************************************************************
 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
 *                                                                        *
 * Author: The ALICE Off-line Project.                                    *
 * Contributors are mentioned in the code where appropriate.              *
 *                                                                        *
 * Permission to use, copy, modify and distribute this software and its   *
 * documentation strictly for non-commercial purposes is hereby granted   *
 * without fee, provided that the above copyright notice appears in all   *
 * copies and that both the copyright notice and this permission notice   *
 * appear in the supporting documentation. The authors make no claims     *
 * about the suitability of this software for any purpose. It is          *
 * provided "as is" without express or implied warranty.                  *
 **************************************************************************/

/* $Id$ */

///////////////////////////////////////////////////////////////////////////////
//
// This class for running and define a Trigger Descriptor
//
// A Trigger Descriptor define a trigger setup for specific runnign
// condition (Pb-Pb, p-p, p-A, Calibration, etc).
// It keep:
//    - cluster detector (List of detectors involved)
//    - List of conditions
//
// Descriptors could be create in advance and store in a file.
//
//   Example how to create a Trigger Descriptor:
//
//   AliTriggerDescriptor descrip( "TEST", "Test Descriptor" );
//
//   // Define a Cluster Detector
//   descrip.AddDetectorCluster( "VZERO ZDC MUON" );
//
//   // Define the trigger conditions (see AliTriggerCondition.cxx)
//   descrip.AddCondition( "VZERO_TEST1_L0 & MUON_SPlus_LPt_L0 & ZDC_TEST2_L0", // condition
//                         "VO1_M1_ZDC2",      // short name
//                         "Dummy",            // short description
//                          0x0100 );          // class mask (set one bit)
//
//   descrip.AddCondition( "VZERO_TEST2_L0 & MUON_SMinus_HPt_L0 & ZDC_TEST1_L0",
//                         "VO2_M3_ZDC1",
//                         "Dummy",
//                          0x0200 );
//
//   descrip.AddCondition( "VZERO_TEST3_L0 | MUON_Unlike_LPt_L0 | ZDC_TEST3_L0",
//                         "VO3_M1_ZDC3",
//                         "Dummy",
//                          0x0400 );
//   descrip.CheckInputsConditions("Config.C");
//   descrip.Print();
//
//   // save the descriptor to file
//   // (default file name $ALICE_ROOT/data/triggerDescriptor.root)
//   descrip.WriteDescriptor(); or descrip.WriteDescriptor( filename );
//
///////////////////////////////////////////////////////////////////////////////

#include <TString.h>
#include <TObjArray.h>
#include <TSystem.h>
#include <TKey.h>
#include <TFile.h>

#include "AliLog.h"
#include "AliRun.h"
#include "AliRunLoader.h"
#include "AliModule.h"

#include "AliTriggerInput.h"
#include "AliTriggerDetector.h"
#include "AliTriggerCondition.h"
#include "AliTriggerDescriptor.h"

ClassImp(AliTriggerDescriptor)

//_____________________________________________________________________________
const char* AliTriggerDescriptor::fgkDetectorName[AliTriggerDescriptor::fgkNDetectors] =
             { "ITS", "TRD", "PHOS", "EMCAL", "MUON", "ZDC", "T0", "VZERO", "ACORDE", "TOF" };

const TString AliTriggerDescriptor::fgkDescriptorFileName("/data/triggerDescriptors.root");

//_____________________________________________________________________________
AliTriggerDescriptor::AliTriggerDescriptor():
  TNamed(),
  fDetectorCluster(""),
  fConditions()
{
}

//_____________________________________________________________________________
AliTriggerDescriptor::AliTriggerDescriptor( TString & name, TString & description ):
  TNamed( name, description ),
  fDetectorCluster(""),
  fConditions()
{
}

//_____________________________________________________________________________
AliTriggerDescriptor::AliTriggerDescriptor( const AliTriggerDescriptor& des ):
  TNamed( des ),
  fDetectorCluster( des.fDetectorCluster ),
  fConditions()
{
   // Copy constructor
   Int_t ncond = des.fConditions.GetEntriesFast();
   for( Int_t j=0; j<ncond; j++ ) {
      AddCondition( new AliTriggerCondition( *(AliTriggerCondition*)(des.fConditions.At( j )) ) );
   }
}

//______________________________________________________________________________
AliTriggerDescriptor& AliTriggerDescriptor::operator=(const AliTriggerDescriptor& des)
{
   // AliTriggerDescriptor assignment operator.

   if (this != &des) {
      TNamed::operator=(des);
      fDetectorCluster = des.fDetectorCluster;
      fConditions.Delete();
      Int_t ncond = des.fConditions.GetEntriesFast();
      for( Int_t j=0; j<ncond; j++ ) {
         AddCondition( new AliTriggerCondition( *(AliTriggerCondition*)(des.fConditions.At( j )) ) );
      }
   }
   return *this;
}

//_____________________________________________________________________________
Bool_t AliTriggerDescriptor::AddDetectorCluster( TString & cluster )
{
   // Add a List of Detectors to be read together (Detector Cluster)
   // Ej "TO VO ZDC MUON" or "ALL"

   TString olddet = fDetectorCluster;
   TString newdet = cluster;
   for( Int_t iDet = 0; iDet < fgkNDetectors; iDet++ ) {
      if( IsSelected( fgkDetectorName[iDet], newdet ) && !IsSelected( fgkDetectorName[iDet], olddet ) ) {
         // Add the detector
         fDetectorCluster.Append( " " );
         fDetectorCluster.Append( fgkDetectorName[iDet] );
      }
   }

   // check if there are no trigger detectors (E.g. TPC)
   if ((newdet.CompareTo("ALL") != 0) && !newdet.IsNull()) {
      AliError( Form("the following detectors are not trigger detectors: %s",
                newdet.Data() ) );
      return kFALSE;
   }

   return kTRUE;
}

//_____________________________________________________________________________
void AliTriggerDescriptor::AddCondition( TString & cond, TString & name, TString & description, ULong64_t mask   )
{
   // Add a new condition
   AliTriggerCondition* acond = new AliTriggerCondition( cond, name, description, mask );
   fConditions.AddLast( acond );
}

//_____________________________________________________________________________
AliTriggerDescriptor* AliTriggerDescriptor::LoadDescriptor( TString & descriptor, const char* filename )
{
   // Load one pre-created Descriptors from database/file that match
   // with the input string 'descriptor'
   // Ej: "Pb-Pb" or "p-p-DIMUON CALIBRATION-CENTRAL-BARREL"

   // Load the selected descriptor
   TString path;
   if( !filename[0] ) {
      path += gSystem->Getenv("ALICE_ROOT");
      path += fgkDescriptorFileName;
   }
   else
      path += filename;

   if( gSystem->AccessPathName( path.Data() ) ) {
      AliErrorGeneral( "AliTriggerDescriptor", Form( "file (%s) not found", path.Data() ) );
      return NULL;
   }

   TFile file( path.Data(), "READ" );
   AliTriggerDescriptor* des = (AliTriggerDescriptor*)(file.Get( descriptor.Data() ));

   file.Close();

   return des;
}

//_____________________________________________________________________________
TObjArray* AliTriggerDescriptor::GetAvailableDescriptors( const char* filename )
{
   // Return an array of descriptor in the file

   TString path;
   if( !filename[0] ) {
      path += gSystem->Getenv( "ALICE_ROOT" );
      path += fgkDescriptorFileName;
   }
   else
      path += filename;

   if( gSystem->AccessPathName( path.Data() ) ) {
      AliErrorGeneral( "AliTriggerDescriptor", Form( "file (%s) not found", path.Data() ) );
      return NULL;
   }

   TObjArray* desArray = new TObjArray();

   TFile file( path.Data(), "READ" );
   if( file.IsZombie() ) {
      AliErrorGeneral( "AliTriggerDescriptor", Form( "Error opening file (%s)", path.Data() ) );
      return NULL;
   }

   file.ReadAll();

   TKey* key;
   TIter next( file.GetListOfKeys() );
   while( (key = (TKey*)next()) ) {
      TObject* obj = key->ReadObj();
      if( obj->InheritsFrom( "AliTriggerDescriptor" ) ) {
         desArray->AddLast( obj );
      }
   }
   file.Close();

   return desArray;
}

//_____________________________________________________________________________
void AliTriggerDescriptor::WriteDescriptor( const char* filename )
{
   // Load one pre-created Descriptors from database/file that match
   // with the input string 'descriptor'
   // Ej: "Pb-Pb" or "p-p-DIMUON CALIBRATION-CENTRAL-BARREL"

   // Load the selected descriptor
   TString path;
   if( !filename[0] ) {
      path += gSystem->Getenv("ALICE_ROOT");
      path += fgkDescriptorFileName;
   }
   else
      path += filename;

   TFile file( path.Data(), "UPDATE" );
   if( file.IsZombie() ) {
      AliErrorGeneral( "AliTriggerDescriptor",
                        Form( "Can't open file (%s)", path.Data() ) );
      return;
   }

   Bool_t result = (Write( GetName(), TObject::kOverwrite ) != 0);
   if( !result )
      AliErrorGeneral( "AliTriggerDescriptor",
                        Form( "Can't write entry to file <%s>!", path.Data() ) );
   file.Close();
}

//_____________________________________________________________________________
Bool_t AliTriggerDescriptor::CheckInputsConditions( TString& configfile )
{
   // To be used on the pre-creation of Descriptors to check if the
   // conditions have valid inputs names.
   //
   // Initiate detectors modules from a Config file
   // Ask to each active module present in the fDetectorCluster
   // to create a Trigger detector and retrive the inputs from it
   // to create a list of inputs.
   // Each condition in the descriptor is then checked agains
   // the list of inputs

   if (!gAlice) {
      AliError( "no gAlice object. Restart aliroot and try again." );
      return kFALSE;
   }
   if (gAlice->Modules()->GetEntries() > 0) {
      AliError( "gAlice was already run. Restart aliroot and try again." );
      return kFALSE;
   }

   AliInfo( Form( "initializing gAlice with config file %s",
            configfile.Data() ) );
   StdoutToAliInfo( StderrToAliError(
      gAlice->Init( configfile.Data() );
   ););

   AliRunLoader* runLoader = gAlice->GetRunLoader();
   if( !runLoader ) {
      AliError( Form( "gAlice has no run loader object. "
                      "Check your config file: %s", configfile.Data() ) );
      return kFALSE;
   }

   // get the possible inputs to check the condition
   TObjArray inputs;
   TObjArray* detArray = runLoader->GetAliRun()->Detectors();

   TString detStr = fDetectorCluster;
   for( Int_t iDet = 0; iDet < detArray->GetEntriesFast(); iDet++ ) {
      AliModule* det = (AliModule*) detArray->At(iDet);
      if( !det || !det->IsActive() ) continue;
      if( IsSelected( det->GetName(), detStr ) ) {
         AliInfo( Form( "Creating inputs for %s", det->GetName() ) );
         AliTriggerDetector* dtrg = det->CreateTriggerDetector();
         dtrg->CreateInputs();
         TObjArray* detInp = dtrg->GetInputs();
         for( Int_t i=0; i<detInp->GetEntriesFast(); i++ ) {
            AliInfo( Form( "Adding input %s", ((AliTriggerInput*)detInp->At(i))->GetName() ) );
            inputs.AddLast( detInp->At(i) );
         }
      }
   }

   // check if the condition is compatible with the triggers inputs
   Int_t ncond = fConditions.GetEntriesFast();
   Bool_t check = kTRUE;
   ULong64_t mask = 0L;
   for( Int_t j=0; j<ncond; j++ ) {
      AliTriggerCondition* cond = (AliTriggerCondition*)(fConditions.At( j ));
      if( !(cond->CheckInputs( inputs )) ) check = kFALSE;
      else AliInfo( Form( "Condition (%s) inputs names OK, class mask (0x%Lx)",
                    cond->GetName(), cond->GetMask( ) ) );
      // check if condition mask is duplicated
      if( mask & cond->GetMask() ) {
         AliError( Form("Condition (%s). The class mask (0x%Lx) is ambiguous. It was previous defined",
                   cond->GetName(), cond->GetMask()  ) );
         check = kFALSE;
      }
      mask |= cond->GetMask();
   }

   return check;
}

//_____________________________________________________________________________
void AliTriggerDescriptor::Print( const Option_t*  ) const
{
   // Print
   cout << "Trigger Descriptor:"  << endl;
   cout << "  Name:             " << GetName() << endl;
   cout << "  Description:      " << GetTitle() << endl;
   cout << "  Detector Cluster: " << fDetectorCluster << endl;

//   Int_t ninputs = fInputs->GetEntriesFast();
//   for( Int_t i=0; i<ninputs; i++ ) {
//      AliTriggerInput* in = (AliTriggerInput*)fInputs->At(i)
//      in->Print();
//   }

   Int_t ncond = fConditions.GetEntriesFast();
   for( Int_t i=0; i<ncond; i++ ) {
      AliTriggerCondition* in = (AliTriggerCondition*)fConditions.At(i);
      in->Print();
   }
   cout << endl;
}

//////////////////////////////////////////////////////////////////////////////
// Helper method

//_____________________________________________________________________________
Bool_t AliTriggerDescriptor::IsSelected( TString detName, TString& detectors ) const
{
   // check whether detName is contained in detectors
   // if yes, it is removed from detectors

   // check if all detectors are selected
   if( (detectors.CompareTo("ALL") == 0 ) ||
        detectors.BeginsWith("ALL ") ||
        detectors.EndsWith(" ALL") ||
        detectors.Contains(" ALL ") ) {
      detectors = "ALL";
      return kTRUE;
   }

   // search for the given detector
   Bool_t result = kFALSE;
   if( (detectors.CompareTo( detName ) == 0) ||
        detectors.BeginsWith( detName+" " ) ||
        detectors.EndsWith( " "+detName ) ||
        detectors.Contains( " "+detName+" " ) ) {
      detectors.ReplaceAll( detName, "" );
      result = kTRUE;
   }

   // clean up the detectors string
   while( detectors.Contains("  ") )  detectors.ReplaceAll( "  ", " " );
   while( detectors.BeginsWith(" ") ) detectors.Remove( 0, 1 );
   while( detectors.EndsWith(" ") )   detectors.Remove( detectors.Length()-1, 1 );

   return result;
}
<commit_msg>Getting the trigger descriptors from CDB<commit_after>/**************************************************************************
 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
 *                                                                        *
 * Author: The ALICE Off-line Project.                                    *
 * Contributors are mentioned in the code where appropriate.              *
 *                                                                        *
 * Permission to use, copy, modify and distribute this software and its   *
 * documentation strictly for non-commercial purposes is hereby granted   *
 * without fee, provided that the above copyright notice appears in all   *
 * copies and that both the copyright notice and this permission notice   *
 * appear in the supporting documentation. The authors make no claims     *
 * about the suitability of this software for any purpose. It is          *
 * provided "as is" without express or implied warranty.                  *
 **************************************************************************/

/* $Id$ */

///////////////////////////////////////////////////////////////////////////////
//
// This class for running and define a Trigger Descriptor
//
// A Trigger Descriptor define a trigger setup for specific runnign
// condition (Pb-Pb, p-p, p-A, Calibration, etc).
// It keep:
//    - cluster detector (List of detectors involved)
//    - List of conditions
//
// Descriptors could be create in advance and store in a file.
//
//   Example how to create a Trigger Descriptor:
//
//   AliTriggerDescriptor descrip( "TEST", "Test Descriptor" );
//
//   // Define a Cluster Detector
//   descrip.AddDetectorCluster( "VZERO ZDC MUON" );
//
//   // Define the trigger conditions (see AliTriggerCondition.cxx)
//   descrip.AddCondition( "VZERO_TEST1_L0 & MUON_SPlus_LPt_L0 & ZDC_TEST2_L0", // condition
//                         "VO1_M1_ZDC2",      // short name
//                         "Dummy",            // short description
//                          0x0100 );          // class mask (set one bit)
//
//   descrip.AddCondition( "VZERO_TEST2_L0 & MUON_SMinus_HPt_L0 & ZDC_TEST1_L0",
//                         "VO2_M3_ZDC1",
//                         "Dummy",
//                          0x0200 );
//
//   descrip.AddCondition( "VZERO_TEST3_L0 | MUON_Unlike_LPt_L0 | ZDC_TEST3_L0",
//                         "VO3_M1_ZDC3",
//                         "Dummy",
//                          0x0400 );
//   descrip.CheckInputsConditions("Config.C");
//   descrip.Print();
//
//   // save the descriptor to file
//   // (default file name $ALICE_ROOT/data/triggerDescriptor.root)
//   descrip.WriteDescriptor(); or descrip.WriteDescriptor( filename );
//
///////////////////////////////////////////////////////////////////////////////

#include <TString.h>
#include <TObjArray.h>
#include <TSystem.h>
#include <TKey.h>
#include <TList.h>
#include <TMap.h>
#include <TFile.h>

#include "AliLog.h"
#include "AliRun.h"
#include "AliRunLoader.h"
#include "AliModule.h"

#include "AliCDBManager.h"
#include "AliCDBPath.h"
#include "AliCDBEntry.h"

#include "AliTriggerInput.h"
#include "AliTriggerDetector.h"
#include "AliTriggerCondition.h"
#include "AliTriggerDescriptor.h"

ClassImp(AliTriggerDescriptor)

//_____________________________________________________________________________
const char* AliTriggerDescriptor::fgkDetectorName[AliTriggerDescriptor::fgkNDetectors] =
             { "ITS", "TRD", "PHOS", "EMCAL", "MUON", "ZDC", "T0", "VZERO", "ACORDE", "TOF" };

const TString AliTriggerDescriptor::fgkDescriptorFileName("/data/triggerDescriptors.root");

//_____________________________________________________________________________
AliTriggerDescriptor::AliTriggerDescriptor():
  TNamed(),
  fDetectorCluster(""),
  fConditions()
{
}

//_____________________________________________________________________________
AliTriggerDescriptor::AliTriggerDescriptor( TString & name, TString & description ):
  TNamed( name, description ),
  fDetectorCluster(""),
  fConditions()
{
}

//_____________________________________________________________________________
AliTriggerDescriptor::AliTriggerDescriptor( const AliTriggerDescriptor& des ):
  TNamed( des ),
  fDetectorCluster( des.fDetectorCluster ),
  fConditions()
{
   // Copy constructor
   Int_t ncond = des.fConditions.GetEntriesFast();
   for( Int_t j=0; j<ncond; j++ ) {
      AddCondition( new AliTriggerCondition( *(AliTriggerCondition*)(des.fConditions.At( j )) ) );
   }
}

//______________________________________________________________________________
AliTriggerDescriptor& AliTriggerDescriptor::operator=(const AliTriggerDescriptor& des)
{
   // AliTriggerDescriptor assignment operator.

   if (this != &des) {
      TNamed::operator=(des);
      fDetectorCluster = des.fDetectorCluster;
      fConditions.Delete();
      Int_t ncond = des.fConditions.GetEntriesFast();
      for( Int_t j=0; j<ncond; j++ ) {
         AddCondition( new AliTriggerCondition( *(AliTriggerCondition*)(des.fConditions.At( j )) ) );
      }
   }
   return *this;
}

//_____________________________________________________________________________
Bool_t AliTriggerDescriptor::AddDetectorCluster( TString & cluster )
{
   // Add a List of Detectors to be read together (Detector Cluster)
   // Ej "TO VO ZDC MUON" or "ALL"

   TString olddet = fDetectorCluster;
   TString newdet = cluster;
   for( Int_t iDet = 0; iDet < fgkNDetectors; iDet++ ) {
      if( IsSelected( fgkDetectorName[iDet], newdet ) && !IsSelected( fgkDetectorName[iDet], olddet ) ) {
         // Add the detector
         fDetectorCluster.Append( " " );
         fDetectorCluster.Append( fgkDetectorName[iDet] );
      }
   }

   // check if there are no trigger detectors (E.g. TPC)
   if ((newdet.CompareTo("ALL") != 0) && !newdet.IsNull()) {
      AliError( Form("the following detectors are not trigger detectors: %s",
                newdet.Data() ) );
      return kFALSE;
   }

   return kTRUE;
}

//_____________________________________________________________________________
void AliTriggerDescriptor::AddCondition( TString & cond, TString & name, TString & description, ULong64_t mask   )
{
   // Add a new condition
   AliTriggerCondition* acond = new AliTriggerCondition( cond, name, description, mask );
   fConditions.AddLast( acond );
}

//_____________________________________________________________________________
AliTriggerDescriptor* AliTriggerDescriptor::LoadDescriptor( TString & descriptor, const char* filename )
{
   // Load one pre-created Descriptors from database/file that match
   // with the input string 'descriptor'
   // Ej: "Pb-Pb" or "p-p-DIMUON CALIBRATION-CENTRAL-BARREL"
   // Load the selected descriptor
  /*TString path;
   if( !filename[0] ) {
      path += gSystem->Getenv("ALICE_ROOT");
      path += fgkDescriptorFileName;
   }
   else
      path += filename;

   if( gSystem->AccessPathName( path.Data() ) ) {
      AliErrorGeneral( "AliTriggerDescriptor", Form( "file (%s) not found", path.Data() ) );
      return NULL;
   }

   TFile file( path.Data(), "READ" );
   AliTriggerDescriptor* des = (AliTriggerDescriptor*)(file.Get( descriptor.Data() ));

   file.Close();

   return des;*/
  AliTriggerDescriptor *des = 0x0;
  cout<<"GETTING TRIGGER DESCRIPTORS FROM CDB!!!"<<endl;

  AliCDBPath path("GRP","CTP","Trigger");

  AliCDBEntry *entry=AliCDBManager::Instance()->Get(path.GetPath());
  if(!entry) AliFatalClass("Couldn't load trigger description data from CDB!");

  TList *list = (TList *) entry->GetObject();
  for(Int_t i =  0; i < list->GetEntries(); i++) {
    TMap *map = (TMap *)list->At(i);
    des = (AliTriggerDescriptor *)map->GetValue(descriptor.Data());
    if(des) return des;
  }

  return des;
}

//_____________________________________________________________________________
TObjArray* AliTriggerDescriptor::GetAvailableDescriptors( const char* filename )
{
   // Return an array of descriptor in the file

   TString path;
   if( !filename[0] ) {
      path += gSystem->Getenv( "ALICE_ROOT" );
      path += fgkDescriptorFileName;
   }
   else
      path += filename;

   if( gSystem->AccessPathName( path.Data() ) ) {
      AliErrorGeneral( "AliTriggerDescriptor", Form( "file (%s) not found", path.Data() ) );
      return NULL;
   }

   TObjArray* desArray = new TObjArray();

   TFile file( path.Data(), "READ" );
   if( file.IsZombie() ) {
      AliErrorGeneral( "AliTriggerDescriptor", Form( "Error opening file (%s)", path.Data() ) );
      return NULL;
   }

   file.ReadAll();

   TKey* key;
   TIter next( file.GetListOfKeys() );
   while( (key = (TKey*)next()) ) {
      TObject* obj = key->ReadObj();
      if( obj->InheritsFrom( "AliTriggerDescriptor" ) ) {
         desArray->AddLast( obj );
      }
   }
   file.Close();

   return desArray;
}

//_____________________________________________________________________________
void AliTriggerDescriptor::WriteDescriptor( const char* filename )
{
   // Load one pre-created Descriptors from database/file that match
   // with the input string 'descriptor'
   // Ej: "Pb-Pb" or "p-p-DIMUON CALIBRATION-CENTRAL-BARREL"

   // Load the selected descriptor
   TString path;
   if( !filename[0] ) {
      path += gSystem->Getenv("ALICE_ROOT");
      path += fgkDescriptorFileName;
   }
   else
      path += filename;

   TFile file( path.Data(), "UPDATE" );
   if( file.IsZombie() ) {
      AliErrorGeneral( "AliTriggerDescriptor",
                        Form( "Can't open file (%s)", path.Data() ) );
      return;
   }

   Bool_t result = (Write( GetName(), TObject::kOverwrite ) != 0);
   if( !result )
      AliErrorGeneral( "AliTriggerDescriptor",
                        Form( "Can't write entry to file <%s>!", path.Data() ) );
   file.Close();
}

//_____________________________________________________________________________
Bool_t AliTriggerDescriptor::CheckInputsConditions( TString& configfile )
{
   // To be used on the pre-creation of Descriptors to check if the
   // conditions have valid inputs names.
   //
   // Initiate detectors modules from a Config file
   // Ask to each active module present in the fDetectorCluster
   // to create a Trigger detector and retrive the inputs from it
   // to create a list of inputs.
   // Each condition in the descriptor is then checked agains
   // the list of inputs

   if (!gAlice) {
      AliError( "no gAlice object. Restart aliroot and try again." );
      return kFALSE;
   }
   if (gAlice->Modules()->GetEntries() > 0) {
      AliError( "gAlice was already run. Restart aliroot and try again." );
      return kFALSE;
   }

   AliInfo( Form( "initializing gAlice with config file %s",
            configfile.Data() ) );
   StdoutToAliInfo( StderrToAliError(
      gAlice->Init( configfile.Data() );
   ););

   AliRunLoader* runLoader = gAlice->GetRunLoader();
   if( !runLoader ) {
      AliError( Form( "gAlice has no run loader object. "
                      "Check your config file: %s", configfile.Data() ) );
      return kFALSE;
   }

   // get the possible inputs to check the condition
   TObjArray inputs;
   TObjArray* detArray = runLoader->GetAliRun()->Detectors();

   TString detStr = fDetectorCluster;
   for( Int_t iDet = 0; iDet < detArray->GetEntriesFast(); iDet++ ) {
      AliModule* det = (AliModule*) detArray->At(iDet);
      if( !det || !det->IsActive() ) continue;
      if( IsSelected( det->GetName(), detStr ) ) {
         AliInfo( Form( "Creating inputs for %s", det->GetName() ) );
         AliTriggerDetector* dtrg = det->CreateTriggerDetector();
         dtrg->CreateInputs();
         TObjArray* detInp = dtrg->GetInputs();
         for( Int_t i=0; i<detInp->GetEntriesFast(); i++ ) {
            AliInfo( Form( "Adding input %s", ((AliTriggerInput*)detInp->At(i))->GetName() ) );
            inputs.AddLast( detInp->At(i) );
         }
      }
   }

   // check if the condition is compatible with the triggers inputs
   Int_t ncond = fConditions.GetEntriesFast();
   Bool_t check = kTRUE;
   ULong64_t mask = 0L;
   for( Int_t j=0; j<ncond; j++ ) {
      AliTriggerCondition* cond = (AliTriggerCondition*)(fConditions.At( j ));
      if( !(cond->CheckInputs( inputs )) ) check = kFALSE;
      else AliInfo( Form( "Condition (%s) inputs names OK, class mask (0x%Lx)",
                    cond->GetName(), cond->GetMask( ) ) );
      // check if condition mask is duplicated
      if( mask & cond->GetMask() ) {
         AliError( Form("Condition (%s). The class mask (0x%Lx) is ambiguous. It was previous defined",
                   cond->GetName(), cond->GetMask()  ) );
         check = kFALSE;
      }
      mask |= cond->GetMask();
   }

   return check;
}

//_____________________________________________________________________________
void AliTriggerDescriptor::Print( const Option_t*  ) const
{
   // Print
   cout << "Trigger Descriptor:"  << endl;
   cout << "  Name:             " << GetName() << endl;
   cout << "  Description:      " << GetTitle() << endl;
   cout << "  Detector Cluster: " << fDetectorCluster << endl;

//   Int_t ninputs = fInputs->GetEntriesFast();
//   for( Int_t i=0; i<ninputs; i++ ) {
//      AliTriggerInput* in = (AliTriggerInput*)fInputs->At(i)
//      in->Print();
//   }

   Int_t ncond = fConditions.GetEntriesFast();
   for( Int_t i=0; i<ncond; i++ ) {
      AliTriggerCondition* in = (AliTriggerCondition*)fConditions.At(i);
      in->Print();
   }
   cout << endl;
}

//////////////////////////////////////////////////////////////////////////////
// Helper method

//_____________________________________________________________________________
Bool_t AliTriggerDescriptor::IsSelected( TString detName, TString& detectors ) const
{
   // check whether detName is contained in detectors
   // if yes, it is removed from detectors

   // check if all detectors are selected
   if( (detectors.CompareTo("ALL") == 0 ) ||
        detectors.BeginsWith("ALL ") ||
        detectors.EndsWith(" ALL") ||
        detectors.Contains(" ALL ") ) {
      detectors = "ALL";
      return kTRUE;
   }

   // search for the given detector
   Bool_t result = kFALSE;
   if( (detectors.CompareTo( detName ) == 0) ||
        detectors.BeginsWith( detName+" " ) ||
        detectors.EndsWith( " "+detName ) ||
        detectors.Contains( " "+detName+" " ) ) {
      detectors.ReplaceAll( detName, "" );
      result = kTRUE;
   }

   // clean up the detectors string
   while( detectors.Contains("  ") )  detectors.ReplaceAll( "  ", " " );
   while( detectors.BeginsWith(" ") ) detectors.Remove( 0, 1 );
   while( detectors.EndsWith(" ") )   detectors.Remove( detectors.Length()-1, 1 );

   return result;
}
<|endoftext|>


<commit_before>#include <sys/socket.h>

#include "net/length.h"

#include "server.h"
#include "utils.h"
#include "client_binary.h"

//
// Xapian binary client
//

BinaryClient::BinaryClient(ev::loop_ref &loop, int sock_, DatabasePool *database_pool_, double active_timeout_, double idle_timeout_)
	: BaseClient(loop, sock_, database_pool_, active_timeout_, idle_timeout_),
	  RemoteProtocol(std::vector<std::string>(), active_timeout_, idle_timeout_, true),
	  database(NULL)
{
	log(this, "Got connection, %d binary client(s) connected.\n", ++total_clients);

	try {
		msg_update(std::string());
	} catch (const Xapian::NetworkError &e) {
		log(this, "ERROR: %s\n", e.get_msg().c_str());
	} catch (...) {
		log(this, "ERROR!\n");
	}
}

BinaryClient::~BinaryClient()
{
	if (database) {
		database_pool->checkin(&database);
	}
	log(this, "Lost connection, %d binary client(s) connected.\n", --total_clients);
}

void BinaryClient::read_cb(ev::io &watcher)
{
	char buf[1024];

	ssize_t received = ::recv(watcher.fd, buf, sizeof(buf), 0);

	if (received < 0) {
		perror("read error");
		return;
	}

	if (received == 0) {
		// The peer has closed its half side of the connection.
		log(this, "BROKEN PIPE!\n");
		destroy();
	} else {
		buffer.append(buf, received);
		if (buffer.length() >= 2) {
			const char *o = buffer.data();
			const char *p = o;
			const char *p_end = p + buffer.size();

			message_type type = static_cast<message_type>(*p++);
			size_t len;
			try {
				len = decode_length(&p, p_end, true);
			} catch (const Xapian::NetworkError & e) {
				return;
			}
			std::string data = std::string(p, len);
			buffer.erase(0, p - o + len);

			std::string buf = std::string(0, len + (p - o));
			log(this, "<<< '%s'\n", repr_string(buf).c_str());

			Buffer *msg = new Buffer(type, data.c_str(), data.size());

			messages_queue.push(msg);

			try {
				run_one();
			} catch (const Xapian::NetworkError &e) {
				log(this, "ERROR: %s\n", e.get_msg().c_str());
			} catch (...) {
				log(this, "ERROR!\n");
			}
		}
	}
}

message_type BinaryClient::get_message(double timeout, std::string & result, message_type required_type)
{
	Buffer* msg;
	if (!messages_queue.pop(msg)) {
		throw Xapian::NetworkError("No message available");
	}

	std::string buf(&msg->type, 1);
	buf += encode_length(msg->nbytes());
	buf += std::string(msg->dpos(), msg->nbytes());
	log(this, "get_message: '%s'\n", repr_string(buf).c_str());

	message_type type = static_cast<message_type>(msg->type);
	result.assign(msg->dpos(), msg->nbytes());

	delete msg;
	return type;
}

void BinaryClient::send_message(reply_type type, const std::string &message) {
	char type_as_char = static_cast<char>(type);
	std::string buf(&type_as_char, 1);
	buf += encode_length(message.size());
	buf += message;

	log(this, "send_message: '%s'\n", repr_string(buf).c_str());

	write(buf);
}

void BinaryClient::send_message(reply_type type, const std::string &message, double end_time)
{
	send_message(type, message);
}

Xapian::Database * BinaryClient::get_db(bool writable_)
{
	if (endpoints.empty()) {
		return NULL;
	}
	if (!database_pool->checkout(&database, endpoints, writable_)) {
		return NULL;
	}
	return database->db;
}

void BinaryClient::release_db(Xapian::Database *db_)
{
	if (database) {
		database_pool->checkin(&database);
	}
}

void BinaryClient::select_db(const std::vector<std::string> &dbpaths_, bool writable_)
{
	std::vector<std::string>::const_iterator i(dbpaths_.begin());
	for (; i != dbpaths_.end(); i++) {
		Endpoint endpoint = Endpoint(*i, std::string(), XAPIAND_BINARY_PORT_DEFAULT);
		endpoints.push_back(endpoint);
	}
	dbpaths = dbpaths_;
}
<commit_msg>Fixed buf initialization<commit_after>#include <sys/socket.h>

#include "net/length.h"

#include "server.h"
#include "utils.h"
#include "client_binary.h"

//
// Xapian binary client
//

BinaryClient::BinaryClient(ev::loop_ref &loop, int sock_, DatabasePool *database_pool_, double active_timeout_, double idle_timeout_)
	: BaseClient(loop, sock_, database_pool_, active_timeout_, idle_timeout_),
	  RemoteProtocol(std::vector<std::string>(), active_timeout_, idle_timeout_, true),
	  database(NULL)
{
	log(this, "Got connection, %d binary client(s) connected.\n", ++total_clients);

	try {
		msg_update(std::string());
	} catch (const Xapian::NetworkError &e) {
		log(this, "ERROR: %s\n", e.get_msg().c_str());
	} catch (...) {
		log(this, "ERROR!\n");
	}
}

BinaryClient::~BinaryClient()
{
	if (database) {
		database_pool->checkin(&database);
	}
	log(this, "Lost connection, %d binary client(s) connected.\n", --total_clients);
}

void BinaryClient::read_cb(ev::io &watcher)
{
	char buf[1024];

	ssize_t received = ::recv(watcher.fd, buf, sizeof(buf), 0);

	if (received < 0) {
		perror("read error");
		return;
	}

	if (received == 0) {
		// The peer has closed its half side of the connection.
		log(this, "BROKEN PIPE!\n");
		destroy();
	} else {
		buffer.append(buf, received);
		if (buffer.length() >= 2) {
			const char *o = buffer.data();
			const char *p = o;
			const char *p_end = p + buffer.size();

			message_type type = static_cast<message_type>(*p++);
			size_t len;
			try {
				len = decode_length(&p, p_end, true);
			} catch (const Xapian::NetworkError & e) {
				return;
			}
			std::string data = std::string(p, len);
			buffer.erase(0, p - o + len);

			std::string buf = std::string(o, len + (p - o));
			log(this, "<<< '%s'\n", repr_string(buf).c_str());

			Buffer *msg = new Buffer(type, data.c_str(), data.size());

			messages_queue.push(msg);

			try {
				run_one();
			} catch (const Xapian::NetworkError &e) {
				log(this, "ERROR: %s\n", e.get_msg().c_str());
			} catch (...) {
				log(this, "ERROR!\n");
			}
		}
	}
}

message_type BinaryClient::get_message(double timeout, std::string & result, message_type required_type)
{
	Buffer* msg;
	if (!messages_queue.pop(msg)) {
		throw Xapian::NetworkError("No message available");
	}

	std::string buf(&msg->type, 1);
	buf += encode_length(msg->nbytes());
	buf += std::string(msg->dpos(), msg->nbytes());
	log(this, "get_message: '%s'\n", repr_string(buf).c_str());

	message_type type = static_cast<message_type>(msg->type);
	result.assign(msg->dpos(), msg->nbytes());

	delete msg;
	return type;
}

void BinaryClient::send_message(reply_type type, const std::string &message) {
	char type_as_char = static_cast<char>(type);
	std::string buf(&type_as_char, 1);
	buf += encode_length(message.size());
	buf += message;

	log(this, "send_message: '%s'\n", repr_string(buf).c_str());

	write(buf);
}

void BinaryClient::send_message(reply_type type, const std::string &message, double end_time)
{
	send_message(type, message);
}

Xapian::Database * BinaryClient::get_db(bool writable_)
{
	if (endpoints.empty()) {
		return NULL;
	}
	if (!database_pool->checkout(&database, endpoints, writable_)) {
		return NULL;
	}
	return database->db;
}

void BinaryClient::release_db(Xapian::Database *db_)
{
	if (database) {
		database_pool->checkin(&database);
	}
}

void BinaryClient::select_db(const std::vector<std::string> &dbpaths_, bool writable_)
{
	std::vector<std::string>::const_iterator i(dbpaths_.begin());
	for (; i != dbpaths_.end(); i++) {
		Endpoint endpoint = Endpoint(*i, std::string(), XAPIAND_BINARY_PORT_DEFAULT);
		endpoints.push_back(endpoint);
	}
	dbpaths = dbpaths_;
}
<|endoftext|>