<commit_before>#include "a_filter.h"
#include "a_system.h"

#include "m_trig.h"

#include "u_misc.h"

namespace a {

///! filter
filter::~filter() {
    // Empty
}

///! filterInstance
filterInstance::~filterInstance() {
    // Empty
}
void filterInstance::setFilterParam(int, float) {
    // Empty
}
void filterInstance::fadeFilterParam(int, float, float, float, float) {
    // Rmpty
}
void filterInstance::oscFilterParam(int, float, float, float, float) {
    // Empty
}

///! echoFilter
echoFilterInstance::echoFilterInstance(echoFilter *parent)
    : m_parent(parent)
    , m_offset(0)
{
}

void echoFilterInstance::filter(float *buffer, size_t samples, size_t channels, float sampleRate, float) {
    if (m_buffer.empty()) {
        const size_t length = m::ceil(m_parent->m_delay * sampleRate) * channels;
        m_buffer.resize(length);
    }
    const size_t bufferLength = m_buffer.size() / channels;
    const float decay = m_parent->m_decay;
    for (size_t i = 0; i < samples; i++) {
        for (size_t j = 0; j < channels; j++) {
            const size_t c = j * bufferLength;
            const size_t b = j * samples;
            float sample = buffer[i + b] + m_buffer[m_offset + c] * decay;
            m_buffer[m_offset + c] = sample;
            buffer[i + b] = sample;
        }
        m_offset = (m_offset + 1) % bufferLength;
    }
}

echoFilterInstance::~echoFilterInstance() {
    // Empty
}

echoFilter::echoFilter()
    : m_delay(1.0f)
    , m_decay(0.5f)
{
}

void echoFilter::setParams(float delay, float decay) {
    m_delay = delay;
    m_decay = decay;
}

filterInstance *echoFilter::create() {
    return new echoFilterInstance(this);
}

///! BQRFilterInstance
BQRFilterInstance::BQRFilterInstance(BQRFilter *parent)
    : m_parent(parent)
    , m_filterType(m_parent->m_filterType)
    , m_sampleRate(m_parent->m_sampleRate)
    , m_frequency(m_parent->m_frequency)
    , m_resonance(m_parent->m_resonance)
    , m_active(false)
    , m_dirty(false)
{
    calcParams();
}

void BQRFilterInstance::filter(float *buffer, size_t samples, size_t channels, float time, float) {
    if (!m_active) return;

    if (m_frequencyFader.m_active > 0) {
        m_dirty = true;
        m_frequency = m_frequencyFader(time);
    }

    if (m_resonanceFader.m_active > 0) {
        m_dirty = true;
        m_resonance = m_resonanceFader(time);
    }

    if (m_sampleRateFader.m_active > 0) {
        m_dirty = true;
        m_sampleRate = m_sampleRateFader(time);
    }

    if (m_dirty)
        calcParams();

    for (size_t s = 0, c = 0; s < channels; s++) {
        for (size_t i = 0; i < samples; i += 2, c++) {
            // filter the inputs
            float x = buffer[c];
            m_y2[s] = (m_a.x * x) + (m_a.y * m_x1[s]) + (m_a.z * m_x2[s])
                                  - (m_b.x * m_y1[s]) - (m_b.y * m_y2[s]);
            buffer[c++] = m_y2[s];
            // permute filter ops to reduce movement
            m_x2[s] = buffer[c];
            m_y1[s] = (m_a.y * x) + (m_a.x * m_x2[s]) + (m_a.z * m_x1[s])
                                  - (m_b.x * m_y2[s]) - (m_b.y * m_y1[s]);
            buffer[c] = m_y1[s];
            // move it a little
            m_x1[s] = m_x2[s];
            m_x2[s] = x;
        }
        // apply a very small impulse to prevent underflow
        m_y1[s] += 1.0e-26f;
    }
}

void BQRFilterInstance::setFilterParam(int attrib, float value) {
    switch (attrib) {
    case BQRFilter::kFrequency:
        m_dirty = true;
        m_frequencyFader.m_active = 0;
        m_frequency = value;
        break;
    case BQRFilter::kSampleRate:
        m_dirty = true;
        m_sampleRateFader.m_active = 0;
        m_sampleRate = value;
        break;
    case BQRFilter::kResonance:
        m_dirty = true;
        m_resonanceFader.m_active = 0;
        m_resonance = value;
        break;
    }
}

void BQRFilterInstance::fadeFilterParam(int attrib, float from, float to, float time, float startTime) {
    if (from == to || time <= 0.0f)
        return;
    switch (attrib) {
    case BQRFilter::kFrequency:
        m_frequencyFader.lerp(from, to, time, startTime);
        break;
    case BQRFilter::kSampleRate:
        m_sampleRateFader.lerp(from, to, time, startTime);
        break;
    case BQRFilter::kResonance:
        m_sampleRateFader.lerp(from, to, time, startTime);
        break;
    }
}

void BQRFilterInstance::oscFilterParam(int attrib, float from, float to, float time, float startTime) {
    if (from == to || time <= 0.0f)
        return;
    switch (attrib) {
    case BQRFilter::kFrequency:
        m_frequencyFader.lfo(from, to, time, startTime);
        break;
    case BQRFilter::kSampleRate:
        m_sampleRateFader.lfo(from, to, time, startTime);
        break;
    case BQRFilter::kResonance:
        m_resonanceFader.lfo(from, to, time, startTime);
        break;
    }
}

BQRFilterInstance::~BQRFilterInstance() {
    // Empty
}

void BQRFilterInstance::calcParams() {
    const m::vec2 omega = m::sincos((2.0f * m::kPi * m_frequency) / m_sampleRate);
    const float alpha = omega.x / (2.0f * m_resonance);
    const float scalar = 1.0f / (1.0f + alpha);
    switch (m_filterType) {
    case BQRFilter::kNone:
        m_active = false;
        break;
    case BQRFilter::kLowPass:
        m_a.x = 0.5f * (1.0f - omega.y) * scalar;
        m_a.y = (1.0f - omega.y) * scalar;
        m_a.z = m_a.x;
        m_b.x = -2.0f * omega.y * scalar;
        m_b.y = (1.0f - alpha) * scalar;
        m_active = true;
        break;
    case BQRFilter::kHighPass:
        m_a.x = 0.5f * (1.0f + omega.y) * scalar;
        m_a.y = -(1.0f + omega.y) * scalar;
        m_a.z = m_a.x;
        m_b.x = -2.0f * omega.y * scalar;
        m_b.y = (1.0f - alpha) * scalar;
        m_active = true;
        break;
    case BQRFilter::kBandPass:
        m_a.x = alpha * scalar;
        m_a.y = 0.0f;
        m_a.z = -m_a.x;
        m_b.x = -2.0f * omega.y * scalar;
        m_b.y = (1.0f - alpha) * scalar;
        m_active = true;
        break;
    }
}

BQRFilter::BQRFilter()
{
    // Empty
}

void BQRFilter::setParams(int type, float sampleRate, float frequency, float resonance) {
    m_filterType = type;
    m_sampleRate = sampleRate;
    m_frequency = frequency;
    m_resonance = resonance;
}

BQRFilter::~BQRFilter() {
    // Empty
}

BQRFilterInstance *BQRFilter::create() {
    return new BQRFilterInstance(this);
}

///! DCRemovalFilterInstance
DCRemovalFilterInstance::DCRemovalFilterInstance(DCRemovalFilter *parent)
    : m_offset(0)
    , m_parent(parent)
{
}

void DCRemovalFilterInstance::filter(float *buffer, size_t samples, size_t channels, float sampleRate, float) {
    if (m_buffer.empty()) {
        m_buffer.resize(size_t(m::ceil(m_parent->m_length * sampleRate)) * channels);
        m_totals.resize(channels);
    }
    size_t bufferLength = m_buffer.size() / channels;
    for (size_t i = 0; i < samples; i++) {
        for (size_t j = 0; j < channels; j++) {
            const int c = j * bufferLength;
            const int b = j * samples;
            float n = buffer[i + b];
            m_totals[j] -= m_buffer[m_offset + c];
            m_totals[j] += n;
            m_buffer[m_offset + c] = n;
            n -= m_totals[j] / bufferLength;
            buffer[i + b] += (n - buffer[i + b]) * m_parent->m_length;
        }
        m_offset = (m_offset + 1) % bufferLength;
    }
}

DCRemovalFilterInstance::~DCRemovalFilterInstance() {
    // Empty
}

DCRemovalFilter::DCRemovalFilter()
    : m_length(0.1f)
{
}

void DCRemovalFilter::setParams(float length) {
    m_length = length;
}

filterInstance *DCRemovalFilter::create() {
    return new DCRemovalFilterInstance(this);
}

}
<commit_msg>Default values for BQR filters<commit_after>#include "a_filter.h"
#include "a_system.h"

#include "m_trig.h"

#include "u_misc.h"

namespace a {

///! filter
filter::~filter() {
    // Empty
}

///! filterInstance
filterInstance::~filterInstance() {
    // Empty
}
void filterInstance::setFilterParam(int, float) {
    // Empty
}
void filterInstance::fadeFilterParam(int, float, float, float, float) {
    // Rmpty
}
void filterInstance::oscFilterParam(int, float, float, float, float) {
    // Empty
}

///! echoFilter
echoFilterInstance::echoFilterInstance(echoFilter *parent)
    : m_parent(parent)
    , m_offset(0)
{
}

void echoFilterInstance::filter(float *buffer, size_t samples, size_t channels, float sampleRate, float) {
    if (m_buffer.empty()) {
        const size_t length = m::ceil(m_parent->m_delay * sampleRate) * channels;
        m_buffer.resize(length);
    }
    const size_t bufferLength = m_buffer.size() / channels;
    const float decay = m_parent->m_decay;
    for (size_t i = 0; i < samples; i++) {
        for (size_t j = 0; j < channels; j++) {
            const size_t c = j * bufferLength;
            const size_t b = j * samples;
            float sample = buffer[i + b] + m_buffer[m_offset + c] * decay;
            m_buffer[m_offset + c] = sample;
            buffer[i + b] = sample;
        }
        m_offset = (m_offset + 1) % bufferLength;
    }
}

echoFilterInstance::~echoFilterInstance() {
    // Empty
}

echoFilter::echoFilter()
    : m_delay(1.0f)
    , m_decay(0.5f)
{
}

void echoFilter::setParams(float delay, float decay) {
    m_delay = delay;
    m_decay = decay;
}

filterInstance *echoFilter::create() {
    return new echoFilterInstance(this);
}

///! BQRFilterInstance
BQRFilterInstance::BQRFilterInstance(BQRFilter *parent)
    : m_parent(parent)
    , m_filterType(m_parent->m_filterType)
    , m_sampleRate(m_parent->m_sampleRate)
    , m_frequency(m_parent->m_frequency)
    , m_resonance(m_parent->m_resonance)
    , m_active(false)
    , m_dirty(false)
{
    calcParams();
}

void BQRFilterInstance::filter(float *buffer, size_t samples, size_t channels, float time, float) {
    if (!m_active) return;

    if (m_frequencyFader.m_active > 0) {
        m_dirty = true;
        m_frequency = m_frequencyFader(time);
    }

    if (m_resonanceFader.m_active > 0) {
        m_dirty = true;
        m_resonance = m_resonanceFader(time);
    }

    if (m_sampleRateFader.m_active > 0) {
        m_dirty = true;
        m_sampleRate = m_sampleRateFader(time);
    }

    if (m_dirty)
        calcParams();

    for (size_t s = 0, c = 0; s < channels; s++) {
        for (size_t i = 0; i < samples; i += 2, c++) {
            // filter the inputs
            float x = buffer[c];
            m_y2[s] = (m_a.x * x) + (m_a.y * m_x1[s]) + (m_a.z * m_x2[s])
                                  - (m_b.x * m_y1[s]) - (m_b.y * m_y2[s]);
            buffer[c++] = m_y2[s];
            // permute filter ops to reduce movement
            m_x2[s] = buffer[c];
            m_y1[s] = (m_a.y * x) + (m_a.x * m_x2[s]) + (m_a.z * m_x1[s])
                                  - (m_b.x * m_y2[s]) - (m_b.y * m_y1[s]);
            buffer[c] = m_y1[s];
            // move it a little
            m_x1[s] = m_x2[s];
            m_x2[s] = x;
        }
        // apply a very small impulse to prevent underflow
        m_y1[s] += 1.0e-26f;
    }
}

void BQRFilterInstance::setFilterParam(int attrib, float value) {
    switch (attrib) {
    case BQRFilter::kFrequency:
        m_dirty = true;
        m_frequencyFader.m_active = 0;
        m_frequency = value;
        break;
    case BQRFilter::kSampleRate:
        m_dirty = true;
        m_sampleRateFader.m_active = 0;
        m_sampleRate = value;
        break;
    case BQRFilter::kResonance:
        m_dirty = true;
        m_resonanceFader.m_active = 0;
        m_resonance = value;
        break;
    }
}

void BQRFilterInstance::fadeFilterParam(int attrib, float from, float to, float time, float startTime) {
    if (from == to || time <= 0.0f)
        return;
    switch (attrib) {
    case BQRFilter::kFrequency:
        m_frequencyFader.lerp(from, to, time, startTime);
        break;
    case BQRFilter::kSampleRate:
        m_sampleRateFader.lerp(from, to, time, startTime);
        break;
    case BQRFilter::kResonance:
        m_sampleRateFader.lerp(from, to, time, startTime);
        break;
    }
}

void BQRFilterInstance::oscFilterParam(int attrib, float from, float to, float time, float startTime) {
    if (from == to || time <= 0.0f)
        return;
    switch (attrib) {
    case BQRFilter::kFrequency:
        m_frequencyFader.lfo(from, to, time, startTime);
        break;
    case BQRFilter::kSampleRate:
        m_sampleRateFader.lfo(from, to, time, startTime);
        break;
    case BQRFilter::kResonance:
        m_resonanceFader.lfo(from, to, time, startTime);
        break;
    }
}

BQRFilterInstance::~BQRFilterInstance() {
    // Empty
}

void BQRFilterInstance::calcParams() {
    const m::vec2 omega = m::sincos((2.0f * m::kPi * m_frequency) / m_sampleRate);
    const float alpha = omega.x / (2.0f * m_resonance);
    const float scalar = 1.0f / (1.0f + alpha);
    switch (m_filterType) {
    case BQRFilter::kNone:
        m_active = false;
        break;
    case BQRFilter::kLowPass:
        m_a.x = 0.5f * (1.0f - omega.y) * scalar;
        m_a.y = (1.0f - omega.y) * scalar;
        m_a.z = m_a.x;
        m_b.x = -2.0f * omega.y * scalar;
        m_b.y = (1.0f - alpha) * scalar;
        m_active = true;
        break;
    case BQRFilter::kHighPass:
        m_a.x = 0.5f * (1.0f + omega.y) * scalar;
        m_a.y = -(1.0f + omega.y) * scalar;
        m_a.z = m_a.x;
        m_b.x = -2.0f * omega.y * scalar;
        m_b.y = (1.0f - alpha) * scalar;
        m_active = true;
        break;
    case BQRFilter::kBandPass:
        m_a.x = alpha * scalar;
        m_a.y = 0.0f;
        m_a.z = -m_a.x;
        m_b.x = -2.0f * omega.y * scalar;
        m_b.y = (1.0f - alpha) * scalar;
        m_active = true;
        break;
    }
}

BQRFilter::BQRFilter()
    : m_filterType(kNone)
    , m_sampleRate(44100.0f)
    , m_frequency(1.0f)
    , m_resonance(0.0f)
{
}

void BQRFilter::setParams(int type, float sampleRate, float frequency, float resonance) {
    m_filterType = type;
    m_sampleRate = sampleRate;
    m_frequency = frequency;
    m_resonance = resonance;
}

BQRFilter::~BQRFilter() {
    // Empty
}

BQRFilterInstance *BQRFilter::create() {
    return new BQRFilterInstance(this);
}

///! DCRemovalFilterInstance
DCRemovalFilterInstance::DCRemovalFilterInstance(DCRemovalFilter *parent)
    : m_offset(0)
    , m_parent(parent)
{
}

void DCRemovalFilterInstance::filter(float *buffer, size_t samples, size_t channels, float sampleRate, float) {
    if (m_buffer.empty()) {
        m_buffer.resize(size_t(m::ceil(m_parent->m_length * sampleRate)) * channels);
        m_totals.resize(channels);
    }
    size_t bufferLength = m_buffer.size() / channels;
    for (size_t i = 0; i < samples; i++) {
        for (size_t j = 0; j < channels; j++) {
            const int c = j * bufferLength;
            const int b = j * samples;
            float n = buffer[i + b];
            m_totals[j] -= m_buffer[m_offset + c];
            m_totals[j] += n;
            m_buffer[m_offset + c] = n;
            n -= m_totals[j] / bufferLength;
            buffer[i + b] += (n - buffer[i + b]) * m_parent->m_length;
        }
        m_offset = (m_offset + 1) % bufferLength;
    }
}

DCRemovalFilterInstance::~DCRemovalFilterInstance() {
    // Empty
}

DCRemovalFilter::DCRemovalFilter()
    : m_length(0.1f)
{
}

void DCRemovalFilter::setParams(float length) {
    m_length = length;
}

filterInstance *DCRemovalFilter::create() {
    return new DCRemovalFilterInstance(this);
}

}
<|endoftext|>


<commit_before>#pragma once
#include <vector>
#include <cstdint>
#include <cassert>

namespace spn {
	//! 複数のバッファ形式を1つに纏める
	template <class T, class Buff=std::vector<T>>
	class AbstBuffer {
		enum class Type {
			ConstPtr,
			Movable,
			Const,
			Invalid
		};
		Type _type;
		union {
			const T*	_pSrc;
			Buff*		_buffM;
			const Buff*	_buffC;
		};
		size_t	_size;
		bool	_bRelease;

		void _invalidate() {
			_pSrc = nullptr;
			_type = Type::Invalid;
			_size = 0;
		}

	public:
		AbstBuffer(const AbstBuffer& ab) {
			_type = ab._type;
			_pSrc = ab._pSrc;
			_size = ab._size;
			_bRelease = false;
		}
		AbstBuffer(AbstBuffer&& ab) {
			_type = ab._type;
			_buffM = ab._buffM;
			_size = ab._size;
			if((_bRelease = ab._bRelease)) {
				ab._bRelease = false;
				ab._buffM = nullptr;
				ab._type = Type::Invalid;
			}
		}
		~AbstBuffer() {
			if(_bRelease)
				delete _buffM;
		}
		//! initialize by const-pointer
		AbstBuffer(const void* src, size_t sz): _type(Type::ConstPtr), _pSrc(reinterpret_cast<const T*>(src)), _size(sz), _bRelease(false) {}
		//! initialize by movable-vector
		AbstBuffer(Buff&& buff): _type(Type::Movable), _buffM(new Buff(std::move(buff))), _size(_buffM->size()), _bRelease(true) {}
		//! initialize by const-vector
		AbstBuffer(const Buff& buff): _type(Type::Const), _buffC(&buff), _size(buff.size()), _bRelease(false) {}

		void setTo(Buff& dst) {
			switch(_type) {
				case Type::ConstPtr:
					dst.assign(_pSrc, _pSrc+_size);
					break;
				case Type::Movable:
					dst = std::move(*_buffM);
					_invalidate();
					break;
				case Type::Const:
					dst = *_buffC;
					break;
				default:
					assert(false);
					break;
			}
		}
		Buff moveTo() {
			switch(_type) {
				case Type::ConstPtr: return Buff(_pSrc, _pSrc+_size);
				case Type::Movable: return std::move(*_buffM);
				case Type::Const: return *_buffC;
				default: assert(false);
			}
		}

		//! データのサイズ (not 文字列長)
		size_t getLength() const {
			return _size;
		}
		//! データの先頭ポインタを取得 (null-terminatedは保証されない)
		const T* getPtr() const {
			if(_type == Type::ConstPtr)
				return _pSrc;
			return &(*_buffC)[0];
		}
	};

	struct StrLen {
		size_t	dataLen,	//!< 単純なバイト長
				strLen;		//!< 多バイト文字を考慮した文字列長
		StrLen() = default;
		StrLen(size_t sz): dataLen(sz), strLen(sz) {}
		StrLen(size_t dLen, size_t sLen): dataLen(dLen), strLen(sLen) {}
	};
	// ---- 文字列バイトの長さが不明な場合に文字数と一緒に計算 ----
	StrLen GetLength(const char* str);
	StrLen GetLength(const char16_t* str);
	StrLen GetLength(const char32_t* str);
	// ---- 文字列バイトの長さが分かっている場合の処理 ----
	StrLen GetLength(const char* str, size_t len);
	StrLen GetLength(const char16_t* str, size_t len);
	StrLen GetLength(const char32_t* str, size_t len);
	// とりあえずバイト長だけ格納しておいて必要に応じて文字列長を計算
	template <class T>
	class AbstString : public AbstBuffer<T, std::basic_string<T>> {
		using base_type = AbstBuffer<T, std::basic_string<T>>;
		using Str = std::basic_string<T>;
		mutable StrLen	_strLenP;
		mutable bool	_bStrLen;	//!< 文字列長を持っている場合はtrue
		mutable bool	_bNonNull;	//!< non null-terminatedでない場合にtrue (バイト長は必ず持っている条件)
		public:
			// 文字数カウント機能を追加
			AbstString(const T* src): base_type(src, (_strLenP=GetLength(src)).dataLen), _bStrLen(true), _bNonNull(false) {}
			// Not NullTerminatedかもしれないのでフラグを立てておく
			AbstString(const T* src, size_t dataLen): base_type(src, dataLen), _bStrLen(false), _bNonNull(true) {}
			AbstString(Str&& str): base_type(std::move(str)), _bStrLen(false), _bNonNull(false) {}
			AbstString(const Str& str): base_type(str), _bStrLen(false), _bNonNull(false) {}
			AbstString(const AbstString& str): base_type(str), _strLenP(str._strLenP), _bStrLen(str._bStrLen), _bNonNull(str._bNonNull) {}
			AbstString(AbstString&& str): base_type(std::move(str)), _strLenP(str._strLenP), _bStrLen(str._bStrLen), _bNonNull(str._bNonNull) {}

			size_t getStringLength() const {
				if(!_bStrLen) {
					_bStrLen = true;
					auto len = GetLength(base_type::getPtr(), base_type::getLength());
					assert(len.dataLen == base_type::getLength());
					_strLenP.strLen = len.strLen;
				}
				return _strLenP.strLen;
			}
			//! 文字列の先頭ポインタを取得 (null-terminated保証付き)
			const T* getStringPtr() const {
				// フラグが立ってない場合はgetPtr()と同義
				if(!_bNonNull) {
					// 1+の領域分コピーして最後をnullにセット
					auto len = base_type::getLength();
					AbstString tmp(base_type::getPtr(), len+1);
					const_cast<T*>(tmp.getPtr())[len] = T(0);
					auto* self = const_cast<AbstString*>(this);
					std::swap(*self, tmp);
				}
				return base_type::getPtr();
			}
	};
	using c8Str = AbstString<char>;
	using c16Str = AbstString<char16_t>;
	using c32Str = AbstString<char32_t>;

	using ByteBuff = std::vector<uint8_t>;
	using U16Buff = std::vector<uint16_t>;
	using FloatBuff = std::vector<float>;
	using AB_Byte = AbstBuffer<uint8_t>;
	using AB_U16 = AbstBuffer<uint16_t>;
	using AB_Float = AbstBuffer<float>;

	struct ToNStr {
		template <class T>
		static AbstString<T> MakeABS(const T* src);
		template <class T>
		static AbstString<T> MakeABS(const T* src, size_t dataLen);
		template <class T>
		static AbstString<T> MakeABS(std::basic_string<T>&& s);
		template <class T>
		static AbstString<T> MakeABS(const std::basic_string<T>& s);
		template <class T>
		static AbstString<T> MakeABS(const AbstString<T>& s);
		template <class T>
		static AbstString<T> MakeABS(AbstString<T>&& s);
	};
	class To32Str : public c32Str {
		public:
			To32Str(c8Str c);
			To32Str(c16Str c);
			To32Str(const c32Str& c);
			To32Str(c32Str&& c);
			template <class... Ts>
			To32Str(Ts&&... ts): To32Str(decltype(ToNStr::MakeABS(std::forward<Ts>(ts)...))(std::forward<Ts>(ts)...)) {}
	};
	class To16Str : public c16Str {
		public:
			To16Str(c32Str c);
			To16Str(c8Str c);
			To16Str(const c16Str& c);
			To16Str(c16Str&& c);
			template <class... Ts>
			To16Str(Ts&&... ts): To16Str(decltype(ToNStr::MakeABS(std::forward<Ts>(ts)...))(std::forward<Ts>(ts)...)) {}
	};
	class To8Str : public c8Str {
		public:
			To8Str(c32Str c);
			To8Str(c16Str c);
			To8Str(const c8Str& c);
			To8Str(c8Str&& c);
			template <class... Ts>
			To8Str(Ts&&... ts): To8Str(decltype(ToNStr::MakeABS(std::forward<Ts>(ts)...))(std::forward<Ts>(ts)...)) {}
	};
}
<commit_msg>abstbuffer: move assign operator<commit_after>#pragma once
#include <vector>
#include <cstdint>
#include <cassert>

namespace spn {
	//! 複数のバッファ形式を1つに纏める
	template <class T, class Buff=std::vector<T>>
	class AbstBuffer {
		enum class Type {
			ConstPtr,
			Movable,
			Const,
			Invalid
		};
		Type _type;
		union {
			const T*	_pSrc;
			Buff*		_buffM;
			const Buff*	_buffC;
		};
		size_t	_size;
		bool	_bRelease;

		void _invalidate() {
			_pSrc = nullptr;
			_type = Type::Invalid;
			_size = 0;
		}

	public:
		AbstBuffer(const AbstBuffer& ab) {
			_type = ab._type;
			_pSrc = ab._pSrc;
			_size = ab._size;
			_bRelease = false;
		}
		AbstBuffer(AbstBuffer&& ab) {
			_type = ab._type;
			_buffM = ab._buffM;
			_size = ab._size;
			if((_bRelease = ab._bRelease))
				ab._invalidate();
		}
		~AbstBuffer() {
			if(_bRelease)
				delete _buffM;
		}
		//! initialize by const-pointer
		AbstBuffer(const void* src, size_t sz): _type(Type::ConstPtr), _pSrc(reinterpret_cast<const T*>(src)), _size(sz), _bRelease(false) {}
		//! initialize by movable-vector
		AbstBuffer(Buff&& buff): _type(Type::Movable), _buffM(new Buff(std::move(buff))), _size(_buffM->size()), _bRelease(true) {}
		//! initialize by const-vector
		AbstBuffer(const Buff& buff): _type(Type::Const), _buffC(&buff), _size(buff.size()), _bRelease(false) {}

		AbstBuffer& operator = (AbstBuffer&& a) {
			_type = a._type;
			_buffM = a._buffM;
			_size = a._size;
			if((_bRelease = a._bRelease))
				a._invalidate();
			return *this;
		}
		void setTo(Buff& dst) {
			switch(_type) {
				case Type::ConstPtr:
					dst.assign(_pSrc, _pSrc+_size);
					break;
				case Type::Movable:
					dst = std::move(*_buffM);
					_invalidate();
					break;
				case Type::Const:
					dst = *_buffC;
					break;
				default:
					assert(false);
					break;
			}
		}
		Buff moveTo() {
			switch(_type) {
				case Type::ConstPtr: return Buff(_pSrc, _pSrc+_size);
				case Type::Movable: return std::move(*_buffM);
				case Type::Const: return *_buffC;
				default: assert(false);
			}
		}

		//! データのサイズ (not 文字列長)
		size_t getLength() const {
			return _size;
		}
		//! データの先頭ポインタを取得 (null-terminatedは保証されない)
		const T* getPtr() const {
			if(_type == Type::ConstPtr)
				return _pSrc;
			return &(*_buffC)[0];
		}
	};

	struct StrLen {
		size_t	dataLen,	//!< 単純なバイト長
				strLen;		//!< 多バイト文字を考慮した文字列長
		StrLen() = default;
		StrLen(size_t sz): dataLen(sz), strLen(sz) {}
		StrLen(size_t dLen, size_t sLen): dataLen(dLen), strLen(sLen) {}
	};
	// ---- 文字列バイトの長さが不明な場合に文字数と一緒に計算 ----
	StrLen GetLength(const char* str);
	StrLen GetLength(const char16_t* str);
	StrLen GetLength(const char32_t* str);
	// ---- 文字列バイトの長さが分かっている場合の処理 ----
	StrLen GetLength(const char* str, size_t len);
	StrLen GetLength(const char16_t* str, size_t len);
	StrLen GetLength(const char32_t* str, size_t len);
	// とりあえずバイト長だけ格納しておいて必要に応じて文字列長を計算
	template <class T>
	class AbstString : public AbstBuffer<T, std::basic_string<T>> {
		using base_type = AbstBuffer<T, std::basic_string<T>>;
		using Str = std::basic_string<T>;
		mutable StrLen	_strLenP;
		mutable bool	_bStrLen;	//!< 文字列長を持っている場合はtrue
		mutable bool	_bNonNull;	//!< non null-terminatedでない場合にtrue (バイト長は必ず持っている条件)
		public:
			// 文字数カウント機能を追加
			AbstString(const T* src): base_type(src, (_strLenP=GetLength(src)).dataLen), _bStrLen(true), _bNonNull(false) {}
			// Not NullTerminatedかもしれないのでフラグを立てておく
			AbstString(const T* src, size_t dataLen): base_type(src, dataLen), _bStrLen(false), _bNonNull(true) {}
			AbstString(Str&& str): base_type(std::move(str)), _bStrLen(false), _bNonNull(false) {}
			AbstString(const Str& str): base_type(str), _bStrLen(false), _bNonNull(false) {}
			AbstString(const AbstString& str): base_type(str), _strLenP(str._strLenP), _bStrLen(str._bStrLen), _bNonNull(str._bNonNull) {}
			AbstString(AbstString&& str): base_type(std::move(str)), _strLenP(str._strLenP), _bStrLen(str._bStrLen), _bNonNull(str._bNonNull) {}

			AbstString& operator = (AbstString&& a) {
				reinterpret_cast<base_type&>(*this) = std::move(reinterpret_cast<base_type&>(a));
				_strLenP = a._strLenP;
				_bStrLen = a._bStrLen;
				_bNonNull = a._bNonNull;
				return *this;
			}

			size_t getStringLength() const {
				if(!_bStrLen) {
					_bStrLen = true;
					auto len = GetLength(base_type::getPtr(), base_type::getLength());
					assert(len.dataLen == base_type::getLength());
					_strLenP.strLen = len.strLen;
				}
				return _strLenP.strLen;
			}
			//! 文字列の先頭ポインタを取得 (null-terminated保証付き)
			const T* getStringPtr() const {
				// フラグが立ってない場合はgetPtr()と同義
				if(!_bNonNull) {
					// 1+の領域分コピーして最後をnullにセット
					auto len = base_type::getLength();
					AbstString tmp(base_type::getPtr(), len+1);
					const_cast<T*>(tmp.getPtr())[len] = T(0);
					auto* self = const_cast<AbstString*>(this);
					std::swap(*self, tmp);
				}
				return base_type::getPtr();
			}
	};
	using c8Str = AbstString<char>;
	using c16Str = AbstString<char16_t>;
	using c32Str = AbstString<char32_t>;

	using ByteBuff = std::vector<uint8_t>;
	using U16Buff = std::vector<uint16_t>;
	using FloatBuff = std::vector<float>;
	using AB_Byte = AbstBuffer<uint8_t>;
	using AB_U16 = AbstBuffer<uint16_t>;
	using AB_Float = AbstBuffer<float>;

	struct ToNStr {
		template <class T>
		static AbstString<T> MakeABS(const T* src);
		template <class T>
		static AbstString<T> MakeABS(const T* src, size_t dataLen);
		template <class T>
		static AbstString<T> MakeABS(std::basic_string<T>&& s);
		template <class T>
		static AbstString<T> MakeABS(const std::basic_string<T>& s);
		template <class T>
		static AbstString<T> MakeABS(const AbstString<T>& s);
		template <class T>
		static AbstString<T> MakeABS(AbstString<T>&& s);
	};
	class To32Str : public c32Str {
		public:
			To32Str(c8Str c);
			To32Str(c16Str c);
			To32Str(const c32Str& c);
			To32Str(c32Str&& c);
			template <class... Ts>
			To32Str(Ts&&... ts): To32Str(decltype(ToNStr::MakeABS(std::forward<Ts>(ts)...))(std::forward<Ts>(ts)...)) {}
	};
	class To16Str : public c16Str {
		public:
			To16Str(c32Str c);
			To16Str(c8Str c);
			To16Str(const c16Str& c);
			To16Str(c16Str&& c);
			template <class... Ts>
			To16Str(Ts&&... ts): To16Str(decltype(ToNStr::MakeABS(std::forward<Ts>(ts)...))(std::forward<Ts>(ts)...)) {}
	};
	class To8Str : public c8Str {
		public:
			To8Str(c32Str c);
			To8Str(c16Str c);
			To8Str(const c8Str& c);
			To8Str(c8Str&& c);
			template <class... Ts>
			To8Str(Ts&&... ts): To8Str(decltype(ToNStr::MakeABS(std::forward<Ts>(ts)...))(std::forward<Ts>(ts)...)) {}
	};
}
<|endoftext|>


<commit_before>//
// Copyright © 2017 Arm Ltd. All rights reserved.
// SPDX-License-Identifier: MIT
//

#pragma once

#include "CpuTensorHandle.hpp"
#include "ITensorHandle.hpp"

#include <armnn/Tensor.hpp>

#include <Half.hpp>
#include <Permute.hpp>
#include <Profiling.hpp>

#include <boost/cast.hpp>

namespace armnn
{
namespace
{

template <typename ArrayType, typename Arg>
void AssignValues(unsigned int num, unsigned int& idx, const ArrayType& array, Arg& arg)
{
    if (idx >= num)
    {
        return;
    }

    arg = array[(num - 1) - idx];
    idx++;
}

template <typename T, typename ArrayType, typename... Args>
void AssignValues(unsigned int num, unsigned int idx, const ArrayType& array, T& assignee, Args&... args)
{
    AssignValues(num, idx, array, assignee);

    AssignValues(num, idx, array, args...);
}

}    // anonymous namespace

template <typename CopyFunc>
void CopyTensorContentsGeneric(const ITensorHandle* srcTensor, ITensorHandle* dstTensor, CopyFunc copy)
{
    // For ease of understanding, names are assigned to the dimensions
    // of the tensor as if NHWC, however this routine works with any 5D tensor
    static_assert(MaxNumOfTensorDimensions == 5, "Please update CopyTensorContents");

    TensorShape srcStrides      = srcTensor->GetStrides();
    const TensorShape& srcShape = srcTensor->GetShape();
    TensorShape dstStrides      = dstTensor->GetStrides();
    const TensorShape& dstShape = dstTensor->GetShape();

    size_t srcDepth    = 1;
    size_t srcBatches  = 1;
    size_t srcHeight   = 1;
    size_t srcWidth    = 1;
    size_t srcChannels = 1;
    AssignValues(srcShape.GetNumDimensions(),
                 0,
                 srcShape,
                 srcChannels,
                 srcWidth,
                 srcHeight,
                 srcBatches,
                 srcDepth);

    size_t srcDepthStride   = 0;
    size_t srcBatchStride   = 0;
    size_t srcHeightStride  = 0;
    size_t srcWidthStride   = 0;
    size_t srcChannelStride = 0;
    AssignValues(srcStrides.GetNumDimensions(),
                 0,
                 srcStrides,
                 srcChannelStride,
                 srcWidthStride,
                 srcHeightStride,
                 srcBatchStride,
                 srcDepthStride);

    size_t dstDepth    = 1;
    size_t dstBatches  = 1;
    size_t dstHeight   = 1;
    size_t dstWidth    = 1;
    size_t dstChannels = 1;
    AssignValues(dstShape.GetNumDimensions(),
                 0,
                 dstShape,
                 dstChannels,
                 dstWidth,
                 dstHeight,
                 dstBatches,
                 dstDepth);

    size_t dstDepthStride   = 0;
    size_t dstBatchStride   = 0;
    size_t dstHeightStride  = 0;
    size_t dstWidthStride   = 0;
    size_t dstChannelStride = 0;
    AssignValues(dstStrides.GetNumDimensions(),
                 0,
                 dstStrides,
                 dstChannelStride,
                 dstWidthStride,
                 dstHeightStride,
                 dstBatchStride,
                 dstDepthStride);

    const unsigned char* srcData;
    unsigned char* dstData;
    {
        ARMNN_SCOPED_PROFILING_EVENT(Compute::Undefined, "Synchronize buffers");
        srcData = static_cast<const uint8_t*>(srcTensor->Map());
        dstData = static_cast<uint8_t*>(dstTensor->Map());
    }

    size_t copyLength  = std::min(srcChannels*srcChannelStride, dstChannels*dstChannelStride);
    size_t copyWidth   = std::min(srcWidth, dstWidth);
    size_t copyHeight  = std::min(srcHeight, dstHeight);
    size_t copyBatches = std::min(srcBatches, dstBatches);
    size_t copyDepth   = std::min(srcDepth, dstDepth);

    for (unsigned int d = 0; d < copyDepth; ++d)
    {
        auto srcPtrDepth = srcData;
        auto dstPtrDepth = dstData;
        for (unsigned int b = 0; b < copyBatches; ++b)
        {
            auto srcPtrBatch = srcData;
            auto dstPtrBatch = dstData;
            for (unsigned int h = 0; h < copyHeight; ++h)
            {
                auto srcPtrChannel = srcData;
                auto dstPtrChannel = dstData;
                for (unsigned int w = 0; w < copyWidth; ++w)
                {
                    copy(dstData, srcData, copyLength);
                    dstData += dstWidthStride;
                    srcData += srcWidthStride;
                }
                dstData += (static_cast<long>(dstHeightStride) - (dstData - dstPtrChannel));
                srcData += (static_cast<long>(srcHeightStride) - (srcData - srcPtrChannel));
            }
            dstData += (static_cast<long>(dstBatchStride) - (dstData - dstPtrBatch));
            srcData += (static_cast<long>(srcBatchStride) - (srcData - srcPtrBatch));
        }
        dstData += (static_cast<long>(dstDepthStride) - (dstData - dstPtrDepth));
        srcData += (static_cast<long>(srcDepthStride) - (srcData - srcPtrDepth));
    }

    srcTensor->Unmap();
    dstTensor->Unmap();
}

template <typename SrcTensorHandleType, typename DstTensorHandleType, typename DescriptorType>
void GatherTensorHandlePairs(const DescriptorType& descriptor,
                             std::vector<std::pair<SrcTensorHandleType*, DstTensorHandleType*>>& tensorHandlePairs)
{
    const unsigned int numInputs = static_cast<unsigned int>(descriptor.m_Inputs.size());
    tensorHandlePairs.reserve(numInputs);

    for (unsigned int i = 0; i < numInputs; ++i)
    {
        SrcTensorHandleType* const srcTensorHandle =
            boost::polymorphic_downcast<SrcTensorHandleType*>(descriptor.m_Inputs[i]);
        DstTensorHandleType* const dstTensorHandle =
            boost::polymorphic_downcast<DstTensorHandleType*>(descriptor.m_Outputs[i]);

        tensorHandlePairs.emplace_back(srcTensorHandle, dstTensorHandle);
    }
}

armnn::ConstTensor PermuteTensor(const ConstCpuTensorHandle* tensor,
                                 const PermutationVector& permutationVector,
                                 void* permuteBuffer);

void ReshapeWeightsForAcl(TensorInfo& weightInfo, DataLayout dataLayout);

TensorInfo ConvertWeightTensorInfoFromArmnnToAcl(const TensorInfo& weightInfo, DataLayout dataLayout);

armnn::ConstTensor ConvertWeightTensorFromArmnnToAcl(const ConstCpuTensorHandle* weightTensor,
                                                     DataLayout dataLayout,
                                                     void* permuteBuffer);

}  //namespace armnn
<commit_msg>In CopyTensorContentsGeneric coalesce inner dimensions where possible<commit_after>//
// Copyright © 2017 Arm Ltd. All rights reserved.
// SPDX-License-Identifier: MIT
//

#pragma once

#include "CpuTensorHandle.hpp"
#include "ITensorHandle.hpp"

#include <armnn/Tensor.hpp>

#include <Half.hpp>
#include <Permute.hpp>
#include <Profiling.hpp>

#include <boost/cast.hpp>

namespace armnn
{
namespace
{

template <typename ArrayType, typename Arg>
void AssignValues(unsigned int num, unsigned int& idx, const ArrayType& array, Arg& arg)
{
    if (idx >= num)
    {
        return;
    }

    arg = array[(num - 1) - idx];
    idx++;
}

template <typename T, typename ArrayType, typename... Args>
void AssignValues(unsigned int num, unsigned int idx, const ArrayType& array, T& assignee, Args&... args)
{
    AssignValues(num, idx, array, assignee);

    AssignValues(num, idx, array, args...);
}

}    // anonymous namespace

template <typename CopyFunc>
void CopyTensorContentsGeneric(const ITensorHandle* srcTensor, ITensorHandle* dstTensor, CopyFunc copy)
{
    // For ease of understanding, names are assigned to the dimensions
    // of the tensor as if NHWC, however this routine works with any 5D tensor
    static_assert(MaxNumOfTensorDimensions == 5, "Please update CopyTensorContents");

    TensorShape srcStrides      = srcTensor->GetStrides();
    const TensorShape& srcShape = srcTensor->GetShape();
    TensorShape dstStrides      = dstTensor->GetStrides();
    const TensorShape& dstShape = dstTensor->GetShape();

    size_t srcDepth    = 1;
    size_t srcBatches  = 1;
    size_t srcHeight   = 1;
    size_t srcWidth    = 1;
    size_t srcChannels = 1;
    AssignValues(srcShape.GetNumDimensions(),
                 0,
                 srcShape,
                 srcChannels,
                 srcWidth,
                 srcHeight,
                 srcBatches,
                 srcDepth);

    size_t srcDepthStride   = 0;
    size_t srcBatchStride   = 0;
    size_t srcHeightStride  = 0;
    size_t srcWidthStride   = 0;
    size_t srcChannelStride = 0;
    AssignValues(srcStrides.GetNumDimensions(),
                 0,
                 srcStrides,
                 srcChannelStride,
                 srcWidthStride,
                 srcHeightStride,
                 srcBatchStride,
                 srcDepthStride);

    size_t dstDepth    = 1;
    size_t dstBatches  = 1;
    size_t dstHeight   = 1;
    size_t dstWidth    = 1;
    size_t dstChannels = 1;
    AssignValues(dstShape.GetNumDimensions(),
                 0,
                 dstShape,
                 dstChannels,
                 dstWidth,
                 dstHeight,
                 dstBatches,
                 dstDepth);

    size_t dstDepthStride   = 0;
    size_t dstBatchStride   = 0;
    size_t dstHeightStride  = 0;
    size_t dstWidthStride   = 0;
    size_t dstChannelStride = 0;
    AssignValues(dstStrides.GetNumDimensions(),
                 0,
                 dstStrides,
                 dstChannelStride,
                 dstWidthStride,
                 dstHeightStride,
                 dstBatchStride,
                 dstDepthStride);

    const unsigned char* srcData;
    unsigned char* dstData;
    {
        ARMNN_SCOPED_PROFILING_EVENT(Compute::Undefined, "Synchronize buffers");
        srcData = static_cast<const uint8_t*>(srcTensor->Map());
        dstData = static_cast<uint8_t*>(dstTensor->Map());
    }

    size_t copyLength  = std::min(srcChannels*srcChannelStride, dstChannels*dstChannelStride);
    size_t copyWidth   = std::min(srcWidth, dstWidth);
    size_t copyHeight  = std::min(srcHeight, dstHeight);
    size_t copyBatches = std::min(srcBatches, dstBatches);
    size_t copyDepth   = std::min(srcDepth, dstDepth);

    // Coalesce inner dimensions where possible
    // to reduce overheard calling copy() and to
    // allow for memory bandwidth optimisations
    if (copyLength == srcWidthStride &&
        copyLength == dstWidthStride)
    {
        // There is no special padding between rows,
        // and sizes are compatible, so copy whole rows
        copyLength *= copyWidth;
        copyWidth = 1;

        if (copyLength == srcHeightStride &&
            copyLength == dstHeightStride)
        {
            // There is no special padding between batches
            // and sizes are compatible so copy whole batches
            copyLength *= copyHeight;
            copyHeight = 1;
        }
    }

    for (unsigned int d = 0; d < copyDepth; ++d)
    {
        auto srcPtrDepth = srcData;
        auto dstPtrDepth = dstData;
        for (unsigned int b = 0; b < copyBatches; ++b)
        {
            auto srcPtrBatch = srcData;
            auto dstPtrBatch = dstData;
            for (unsigned int h = 0; h < copyHeight; ++h)
            {
                auto srcPtrChannel = srcData;
                auto dstPtrChannel = dstData;
                for (unsigned int w = 0; w < copyWidth; ++w)
                {
                    copy(dstData, srcData, copyLength);
                    dstData += dstWidthStride;
                    srcData += srcWidthStride;
                }
                dstData += (static_cast<long>(dstHeightStride) - (dstData - dstPtrChannel));
                srcData += (static_cast<long>(srcHeightStride) - (srcData - srcPtrChannel));
            }
            dstData += (static_cast<long>(dstBatchStride) - (dstData - dstPtrBatch));
            srcData += (static_cast<long>(srcBatchStride) - (srcData - srcPtrBatch));
        }
        dstData += (static_cast<long>(dstDepthStride) - (dstData - dstPtrDepth));
        srcData += (static_cast<long>(srcDepthStride) - (srcData - srcPtrDepth));
    }

    srcTensor->Unmap();
    dstTensor->Unmap();
}

template <typename SrcTensorHandleType, typename DstTensorHandleType, typename DescriptorType>
void GatherTensorHandlePairs(const DescriptorType& descriptor,
                             std::vector<std::pair<SrcTensorHandleType*, DstTensorHandleType*>>& tensorHandlePairs)
{
    const unsigned int numInputs = static_cast<unsigned int>(descriptor.m_Inputs.size());
    tensorHandlePairs.reserve(numInputs);

    for (unsigned int i = 0; i < numInputs; ++i)
    {
        SrcTensorHandleType* const srcTensorHandle =
            boost::polymorphic_downcast<SrcTensorHandleType*>(descriptor.m_Inputs[i]);
        DstTensorHandleType* const dstTensorHandle =
            boost::polymorphic_downcast<DstTensorHandleType*>(descriptor.m_Outputs[i]);

        tensorHandlePairs.emplace_back(srcTensorHandle, dstTensorHandle);
    }
}

armnn::ConstTensor PermuteTensor(const ConstCpuTensorHandle* tensor,
                                 const PermutationVector& permutationVector,
                                 void* permuteBuffer);

void ReshapeWeightsForAcl(TensorInfo& weightInfo, DataLayout dataLayout);

TensorInfo ConvertWeightTensorInfoFromArmnnToAcl(const TensorInfo& weightInfo, DataLayout dataLayout);

armnn::ConstTensor ConvertWeightTensorFromArmnnToAcl(const ConstCpuTensorHandle* weightTensor,
                                                     DataLayout dataLayout,
                                                     void* permuteBuffer);

}  //namespace armnn
<|endoftext|>


<commit_before>////////////////////////////////////////////////////////////////////////////////
// taskwarrior - a command line task list manager.
//
// Copyright 2006 - 2011, Paul Beckingham, Federico Hernandez.
// All rights reserved.
//
// This program is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free Software
// Foundation; either version 2 of the License, or (at your option) any later
// version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
// details.
//
// You should have received a copy of the GNU General Public License along with
// this program; if not, write to the
//
//     Free Software Foundation, Inc.,
//     51 Franklin Street, Fifth Floor,
//     Boston, MA
//     02110-1301
//     USA
//
////////////////////////////////////////////////////////////////////////////////

#define L10N                                           // Localization complete.

#include <sstream>
#include <vector>
#include <stdlib.h>
#include <Context.h>
#include <ViewText.h>
#include <CmdTags.h>
#include <text.h>
#include <i18n.h>

extern Context context;

////////////////////////////////////////////////////////////////////////////////
CmdTags::CmdTags ()
{
  _keyword     = "tags";
  _usage       = "task tags";
  _description = STRING_CMD_TAGS_USAGE;
  _read_only   = true;
  _displays_id = false;
}

////////////////////////////////////////////////////////////////////////////////
int CmdTags::execute (std::string& output)
{
  int rc = 0;
  std::stringstream out;

  // Get all the tasks.
  std::vector <Task> tasks = context.tdb2.pending.get_tasks ();

  if (context.config.getBoolean ("list.all.tags"))
  {
    std::vector <Task> extra = context.tdb2.completed.get_tasks ();
    std::vector <Task>::iterator task;
    for (task = extra.begin (); task != extra.end (); ++task)
      tasks.push_back (*task);
  }

  int quantity = tasks.size ();

  // Apply filter.
  std::vector <Task> filtered;
  filter (tasks, filtered);

  // Scan all the tasks for their project name, building a map using project
  // names as keys.
  std::map <std::string, int> unique;
  std::vector <Task>::iterator task;
  for (task = filtered.begin (); task != filtered.end (); ++task)
  {
    std::vector <std::string> tags;
    task->getTags (tags);

    std::vector <std::string>::iterator tag;
    for (tag = tags.begin (); tag != tags.end (); ++tag)
      if (unique.find (*tag) != unique.end ())
        unique[*tag]++;
      else
        unique[*tag] = 1;
  }

  if (unique.size ())
  {
    // Render a list of tags names from the map.
    ViewText view;
    view.width (context.getWidth ());
    view.add (Column::factory ("string", STRING_COLUMN_LABEL_TAG));
    view.add (Column::factory ("string.right", STRING_COLUMN_LABEL_COUNT));

    Color bold ("bold");
    bool special = false;
    std::map <std::string, int>::iterator i;
    for (i = unique.begin (); i != unique.end (); ++i)
    {
      // Highlight the special tags.
      special = (context.color () &&
                 (i->first == "nocolor" ||
                  i->first == "nonag"   ||
                  i->first == "next")) ? true : false;

      int row = view.addRow ();
      view.set (row, 0, i->first,  special ? bold : Color ());
      view.set (row, 1, i->second, special ? bold : Color ());
    }

    out << optionalBlankLine ()
        << view.render ()
        << optionalBlankLine ();

    if (unique.size () == 1)
      context.footnote (STRING_CMD_TAGS_SINGLE);
    else
      context.footnote (format (STRING_CMD_TAGS_PLURAL, unique.size ()));

    if (quantity == 1)
      context.footnote (STRING_FEEDBACK_TASKS_SINGLE);
    else
      context.footnote (format (STRING_FEEDBACK_TASKS_PLURAL, quantity));

    out << "\n";
  }
  else
  {
    context.footnote (STRING_CMD_TAGS_NO_TAGS);
    rc = 1;
  }

  output = out.str ();
  return rc;
}

////////////////////////////////////////////////////////////////////////////////
CmdCompletionTags::CmdCompletionTags ()
{
  _keyword     = "_tags";
  _usage       = "task _tags";
  _description = STRING_CMD_COMTAGS_USAGE;
  _read_only   = true;
  _displays_id = false;
}

////////////////////////////////////////////////////////////////////////////////
int CmdCompletionTags::execute (std::string& output)
{
  // Get all the tasks.
  std::vector <Task> tasks = context.tdb2.pending.get_tasks ();

  if (context.config.getBoolean ("complete.all.tags"))
  {
    std::vector <Task> extra = context.tdb2.completed.get_tasks ();
    std::vector <Task>::iterator task;
    for (task = extra.begin (); task != extra.end (); ++task)
      tasks.push_back (*task);
  }

  // Apply filter.
  std::vector <Task> filtered;
  filter (tasks, filtered);

  // Scan all the tasks for their tags, building a map using tag
  // names as keys.
  std::map <std::string, int> unique;
  std::vector <Task>::iterator task;
  for (task = filtered.begin (); task != filtered.end (); ++task)
  {
    std::vector <std::string> tags;
    task->getTags (tags);

    std::vector <std::string>::iterator tag;
    for (tag = tags.begin (); tag != tags.end (); ++tag)
      unique[*tag] = 0;
  }

  // add built-in tags to map
  unique["nocolor"] = 0;
  unique["nonag"]   = 0;
  unique["nocal"]   = 0;
  unique["next"]    = 0;
  unique["stall"]   = 0;
  unique["someday"] = 0;

  std::stringstream out;
  std::map <std::string, int>::iterator it;
  for (it = unique.begin (); it != unique.end (); ++it)
    out << it->first << "\n";

  output = out.str ();
  return 0;
}

////////////////////////////////////////////////////////////////////////////////
<commit_msg>Command: tags<commit_after>////////////////////////////////////////////////////////////////////////////////
// taskwarrior - a command line task list manager.
//
// Copyright 2006 - 2011, Paul Beckingham, Federico Hernandez.
// All rights reserved.
//
// This program is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free Software
// Foundation; either version 2 of the License, or (at your option) any later
// version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
// details.
//
// You should have received a copy of the GNU General Public License along with
// this program; if not, write to the
//
//     Free Software Foundation, Inc.,
//     51 Franklin Street, Fifth Floor,
//     Boston, MA
//     02110-1301
//     USA
//
////////////////////////////////////////////////////////////////////////////////

#define L10N                                           // Localization complete.

#include <sstream>
#include <vector>
#include <stdlib.h>
#include <Context.h>
#include <ViewText.h>
#include <CmdTags.h>
#include <text.h>
#include <i18n.h>

extern Context context;

////////////////////////////////////////////////////////////////////////////////
CmdTags::CmdTags ()
{
  _keyword     = "tags";
  _usage       = "task tags";
  _description = STRING_CMD_TAGS_USAGE;
  _read_only   = true;
  _displays_id = false;
}

////////////////////////////////////////////////////////////////////////////////
int CmdTags::execute (std::string& output)
{
  int rc = 0;
  std::stringstream out;

  // Get all the tasks.
  std::vector <Task> tasks = context.tdb2.pending.get_tasks ();

  if (context.config.getBoolean ("list.all.tags"))
  {
    std::vector <Task> extra = context.tdb2.completed.get_tasks ();
    std::vector <Task>::iterator task;
    for (task = extra.begin (); task != extra.end (); ++task)
      tasks.push_back (*task);
  }

  int quantity = tasks.size ();

  // Apply filter.
  std::vector <Task> filtered;
  filter (tasks, filtered);

  // Scan all the tasks for their project name, building a map using project
  // names as keys.
  std::map <std::string, int> unique;
  std::vector <Task>::iterator task;
  for (task = filtered.begin (); task != filtered.end (); ++task)
  {
    std::vector <std::string> tags;
    task->getTags (tags);

    std::vector <std::string>::iterator tag;
    for (tag = tags.begin (); tag != tags.end (); ++tag)
      if (unique.find (*tag) != unique.end ())
        unique[*tag]++;
      else
        unique[*tag] = 1;
  }

  if (unique.size ())
  {
    // Render a list of tags names from the map.
    ViewText view;
    view.width (context.getWidth ());
    view.add (Column::factory ("string", STRING_COLUMN_LABEL_TAG));
    view.add (Column::factory ("string.right", STRING_COLUMN_LABEL_COUNT));

    Color bold ("bold");
    bool special = false;
    std::map <std::string, int>::iterator i;
    for (i = unique.begin (); i != unique.end (); ++i)
    {
      // Highlight the special tags.
      special = (context.color () &&
                 (i->first == "nocolor" ||
                  i->first == "nonag"   ||
                  i->first == "nocal"   ||
                  i->first == "next")) ? true : false;

      int row = view.addRow ();
      view.set (row, 0, i->first,  special ? bold : Color ());
      view.set (row, 1, i->second, special ? bold : Color ());
    }

    out << optionalBlankLine ()
        << view.render ()
        << optionalBlankLine ();

    if (unique.size () == 1)
      context.footnote (STRING_CMD_TAGS_SINGLE);
    else
      context.footnote (format (STRING_CMD_TAGS_PLURAL, unique.size ()));

    if (quantity == 1)
      context.footnote (STRING_FEEDBACK_TASKS_SINGLE);
    else
      context.footnote (format (STRING_FEEDBACK_TASKS_PLURAL, quantity));

    out << "\n";
  }
  else
  {
    context.footnote (STRING_CMD_TAGS_NO_TAGS);
    rc = 1;
  }

  output = out.str ();
  return rc;
}

////////////////////////////////////////////////////////////////////////////////
CmdCompletionTags::CmdCompletionTags ()
{
  _keyword     = "_tags";
  _usage       = "task _tags";
  _description = STRING_CMD_COMTAGS_USAGE;
  _read_only   = true;
  _displays_id = false;
}

////////////////////////////////////////////////////////////////////////////////
int CmdCompletionTags::execute (std::string& output)
{
  // Get all the tasks.
  std::vector <Task> tasks = context.tdb2.pending.get_tasks ();

  if (context.config.getBoolean ("complete.all.tags"))
  {
    std::vector <Task> extra = context.tdb2.completed.get_tasks ();
    std::vector <Task>::iterator task;
    for (task = extra.begin (); task != extra.end (); ++task)
      tasks.push_back (*task);
  }

  // Apply filter.
  std::vector <Task> filtered;
  filter (tasks, filtered);

  // Scan all the tasks for their tags, building a map using tag
  // names as keys.
  std::map <std::string, int> unique;
  std::vector <Task>::iterator task;
  for (task = filtered.begin (); task != filtered.end (); ++task)
  {
    std::vector <std::string> tags;
    task->getTags (tags);

    std::vector <std::string>::iterator tag;
    for (tag = tags.begin (); tag != tags.end (); ++tag)
      unique[*tag] = 0;
  }

  // add built-in tags to map
  unique["nocolor"] = 0;
  unique["nonag"]   = 0;
  unique["nocal"]   = 0;
  unique["next"]    = 0;

  std::stringstream out;
  std::map <std::string, int>::iterator it;
  for (it = unique.begin (); it != unique.end (); ++it)
    out << it->first << "\n";

  output = out.str ();
  return 0;
}

////////////////////////////////////////////////////////////////////////////////
<|endoftext|>


<commit_before>/*
 * Copyright 2014-2015 Dario Manesku. All rights reserved.
 * License: http://www.opensource.org/licenses/BSD-2-Clause
 */

#include "appconfig.h"

#include <stdio.h>                      // fprintf
#include <emmintrin.h>                  // __m128i

#include "globals.h"                    // g_frameNum
#include "tinystl.h"                    // cs::TinyStlAllocator

#include <dm/misc.h>                    // DM_MEGABYTES
#include <dm/datastructures/array.h>    // dm::Array
#include <dm/datastructures/objarray.h> // dm::ObjArray

#include <bx/thread.h>                  // bx::Mutex
#include <bx/uint32_t.h>                // bx::uint32_cntlz

#undef DM_ALLOCATOR_IMPL
#define DM_ALLOCATOR_IMPL 1
#include <dm/allocator/allocator.h>
#undef DM_ALLOCATOR_IMPL

namespace cs
{
    #if DM_ALLOCATOR
        struct DelayedFreeAllocator : public bx::AllocatorI
        {
            virtual ~DelayedFreeAllocator()
            {
            }

            virtual void* alloc(size_t _size, size_t _align, const char* _file, uint32_t _line) BX_OVERRIDE
            {
                BX_UNUSED(_align, _file, _line);

                return DM_ALLOC(dm::mainAlloc, _size);
            }

            virtual void free(void* _ptr, size_t _align, const char* _file, uint32_t _line) BX_OVERRIDE
            {
                BX_UNUSED(_align, _file, _line);

                PostponedFree* free = m_free.addNew();
                free->m_frame = g_frameNum + 2; // Postpone deallocation for two frames.
                free->m_ptr = _ptr;
            }

            void cleanup()
            {
                const uint32_t currFrame = g_frameNum;

                for (uint16_t ii = m_free.count(); ii--; )
                {
                    if (m_free[ii].m_frame <= currFrame)
                    {
                        DM_FREE(dm::mainAlloc, m_free[ii].m_ptr);
                        m_free.removeAt(ii);
                    }
                }
            }

        private:
            struct PostponedFree
            {
                uint32_t m_frame;
                void*    m_ptr;
            };

            dm::ListT<PostponedFree, 512> m_free;
        };
        static DelayedFreeAllocator s_delayedFreeAllocator;

        struct BgfxAllocator : public bx::ReallocatorI
        {
            BgfxAllocator()
            {
                #if CS_ALLOC_PRINT_STATS
                m_alloc   = 0;
                m_realloc = 0;
                m_free    = 0;
                #endif //CS_ALLOC_PRINT_STATS
            }

            virtual ~BgfxAllocator()
            {
            }

            virtual void* alloc(size_t _size, size_t _align, const char* _file, uint32_t _line) BX_OVERRIDE
            {
                BX_UNUSED(_align, _file, _line);

                #if CS_ALLOC_PRINT_STATS
                m_mutex.lock();
                m_alloc++;
                m_mutex.unlock();
                #endif //CS_ALLOC_PRINT_STATS

                CS_PRINT_BGFX("Bgfx alloc: %zuB", _size);

                return DM_ALLOC(dm::mainAlloc, _size);
            }

            virtual void free(void* _ptr, size_t _align, const char* _file, uint32_t _line) BX_OVERRIDE
            {
                BX_UNUSED(_align, _file, _line);

                #if CS_ALLOC_PRINT_STATS
                m_mutex.lock();
                m_free++;
                m_mutex.unlock();
                #endif //CS_ALLOC_PRINT_STATS

                CS_PRINT_BGFX("Bgfx free: %llu.%lluKB - (0x%p)", dm::U_UKB(allocSizeOf(_ptr)), _ptr);

                return DM_FREE(dm::mainAlloc, _ptr);
            }

            virtual void* realloc(void* _ptr, size_t _size, size_t _align, const char* _file, uint32_t _line) BX_OVERRIDE
            {
                BX_UNUSED(_align, _file, _line);

                #if CS_ALLOC_PRINT_STATS
                m_mutex.lock();
                m_realloc++;
                m_mutex.unlock();
                #endif //CS_ALLOC_PRINT_STATS

                CS_PRINT_BGFX("Bgfx realloc: %llu.%lluKB - (0x%p)", dm::U_UKB(allocSizeOf(_ptr)), _ptr);

                return DM_REALLOC(dm::mainAlloc, _ptr, _size);
            }

            #if CS_ALLOC_PRINT_STATS
            void printStats()
            {
                fprintf(stderr
                      , "Bgfx allocator:\n"
                        "\t%d/%d/%d (alloc/realloc/free)\n\n"
                      , m_alloc, m_realloc, m_free
                      );
            }
            #endif //CS_ALLOC_PRINT_STATS

        private:
            #if CS_ALLOC_PRINT_STATS
            uint32_t m_alloc;
            uint32_t m_realloc;
            uint32_t m_free;
            bx::LwMutex m_mutex;
            #endif //CS_ALLOC_PRINT_STATS
        };
        static BgfxAllocator s_bgfxAllocator;

        bx::AllocatorI*   delayedFree = &s_delayedFreeAllocator;
        bx::ReallocatorI* bgfxAlloc   = &s_bgfxAllocator;

        void allocGc()
        {
            s_delayedFreeAllocator.cleanup();
        }
    #else
        struct CrtDelayedFreeAllocator : public bx::AllocatorI
        {
            virtual ~CrtDelayedFreeAllocator()
            {
            }

            virtual void* alloc(size_t _size, size_t _align, const char* _file, uint32_t _line) BX_OVERRIDE
            {
                BX_UNUSED(_align, _file, _line);

                return ::malloc(_size);
            }

            virtual void free(void* _ptr, size_t _align, const char* _file, uint32_t _line) BX_OVERRIDE
            {
                BX_UNUSED(_align, _file, _line);

                PostponedFree* free = m_free.addNew();
                free->m_frame = g_frameNum + 2; // Postpone deallocation for two frames.
                free->m_ptr = _ptr;
            }

            void cleanup()
            {
                const uint32_t currFrame = g_frameNum;

                for (uint16_t ii = m_free.count(); ii--; )
                {
                    if (m_free[ii].m_frame <= currFrame)
                    {
                        ::free(m_free[ii].m_ptr);
                        m_free.removeAt(ii);
                    }
                }
            }

        private:
            struct PostponedFree
            {
                uint32_t m_frame;
                void*    m_ptr;
            };

            dm::ListT<PostponedFree, 512> m_free;
        };
        static CrtDelayedFreeAllocator s_crtDelayedFreeAllocator;

        bx::AllocatorI*   delayedFree = &s_crtDelayedFreeAllocator;
        bx::ReallocatorI* bgfxAlloc   = dm::crtAlloc;

        void allocGc()
        {
            s_crtDelayedFreeAllocator.cleanup();
        }
    #endif // DM_ALLOCATOR

    //TODO
    static bool s_allocatorDestroyed = false;
    void allocDestroy()
    {
        s_allocatorDestroyed = true;
    }
}

// Alloc redirection.
//-----

#if CS_OVERRIDE_NEWDELETE && DM_ALLOCATOR
    void* operator new(size_t _size)
    {
        // Make sure memory is initialized.
        static const bool assertInitialized = dm::allocInit();
        BX_UNUSED(assertInitialized);
        return DM_ALLOC(dm::mainAlloc, _size);
    }

    void* operator new[](size_t _size)
    {
        static const bool assertInitialized = dm::allocInit();
        BX_UNUSED(assertInitialized);
        return DM_ALLOC(dm::mainAlloc, _size);
    }

    void operator delete(void* _ptr)
    {
        static const bool assertInitialized = dm::allocInit();
        BX_UNUSED(assertInitialized);
        if (!cs::s_allocatorDestroyed)
        {
            DM_FREE(dm::mainAlloc, _ptr);
        }
        else if (!dm::allocContains(_ptr))
        {
            ::free(_ptr);
        }
    }

    void operator delete[](void* _ptr)
    {
        static const bool assertInitialized = dm::allocInit();
        BX_UNUSED(assertInitialized);
        if (!cs::s_allocatorDestroyed)
        {
            DM_FREE(dm::mainAlloc, _ptr);
        }
        else if (!dm::allocContains(_ptr))
        {
            ::free(_ptr);
        }
    }
#endif // CS_OVERRIDE_NEWDELETE && CS_OVERRIDE_TINYSTL_ALLOCATOR

#if IMGUI_CONFIG_CUSTOM_ALLOCATOR && DM_ALLOCATOR
    void* imguiMalloc(size_t _size, void* /*_userptr*/)
    {
        static const bool assertInitialized = dm::allocInit();
        BX_UNUSED(assertInitialized);

        return DM_ALLOC(dm::mainAlloc, _size);
    }

    void imguiFree(void* _ptr, void* /*_userptr*/)
    {
        static const bool assertInitialized = dm::allocInit();
        BX_UNUSED(assertInitialized);

        return DM_FREE(dm::mainAlloc, _ptr);
    }
#elif IMGUI_CONFIG_CUSTOM_ALLOCATOR
    void* imguiMalloc(size_t _size, void* /*_userptr*/)
    {
        return ::malloc(_size);
    }

    void imguiFree(void* _ptr, void* /*_userptr*/)
    {
        return ::free(_ptr);
    }
#endif // IMGUI_CONFIG_CUSTOM_ALLOCATOR && DM_ALLOCATOR

#if !ENTRY_CONFIG_IMPLEMENT_DEFAULT_ALLOCATOR
    namespace entry
    {
        bx::ReallocatorI* getDefaultAllocator()
        {
            #if DM_ALLOCATOR
            static const bool assertInitialized = dm::allocInit();
                BX_UNUSED(assertInitialized);

                return dm::mainAlloc;
            #else
                return &dm::s_crtAllocator;
            #endif // DM_ALLOCATOR
        }
    }
#endif // !ENTRY_CONFIG_IMPLEMENT_DEFAULT_ALLOCATOR

namespace cs
{
    #if CS_OVERRIDE_TINYSTL_ALLOCATOR && DM_ALLOCATOR
        void* TinyStlAllocator::static_allocate(size_t _bytes)
        {
            static const bool assertInitialized = dm::allocInit();
            BX_UNUSED(assertInitialized);
            return DM_ALLOC(dm::mainAlloc, _bytes);
        }

        void TinyStlAllocator::static_deallocate(void* _ptr, size_t /*_bytes*/)
        {
            static const bool assertInitialized = dm::allocInit();
            BX_UNUSED(assertInitialized);

            return DM_FREE(dm::mainAlloc, _ptr);
        }
    #elif CS_OVERRIDE_TINYSTL_ALLOCATOR
        void* TinyStlAllocator::static_allocate(size_t _bytes)
        {
            return ::malloc(_bytes);
        }

        void TinyStlAllocator::static_deallocate(void* _ptr, size_t /*_bytes*/)
        {
            return ::free(_ptr);
        }
    #endif // CS_OVERRIDE_TINYSTL_ALLOCATOR && DM_ALLOCATOR
} // namespace cs

/* vim: set sw=4 ts=4 expandtab: */
<commit_msg>Cleanup.<commit_after>/*
 * Copyright 2014-2015 Dario Manesku. All rights reserved.
 * License: http://www.opensource.org/licenses/BSD-2-Clause
 */

#include "appconfig.h"

#include <stdio.h>                      // fprintf
#include "globals.h"                    // g_frameNum
#include "tinystl.h"                    // cs::TinyStlAllocator

#undef DM_ALLOCATOR_IMPL
#define DM_ALLOCATOR_IMPL 1
#include <dm/allocator/allocator.h>
#undef DM_ALLOCATOR_IMPL

namespace cs
{
    #if DM_ALLOCATOR
        struct DelayedFreeAllocator : public bx::AllocatorI
        {
            virtual ~DelayedFreeAllocator()
            {
            }

            virtual void* alloc(size_t _size, size_t _align, const char* _file, uint32_t _line) BX_OVERRIDE
            {
                BX_UNUSED(_align, _file, _line);

                return DM_ALLOC(dm::mainAlloc, _size);
            }

            virtual void free(void* _ptr, size_t _align, const char* _file, uint32_t _line) BX_OVERRIDE
            {
                BX_UNUSED(_align, _file, _line);

                PostponedFree* free = m_free.addNew();
                free->m_frame = g_frameNum + 2; // Postpone deallocation for two frames.
                free->m_ptr = _ptr;
            }

            void cleanup()
            {
                const uint32_t currFrame = g_frameNum;

                for (uint16_t ii = m_free.count(); ii--; )
                {
                    if (m_free[ii].m_frame <= currFrame)
                    {
                        DM_FREE(dm::mainAlloc, m_free[ii].m_ptr);
                        m_free.removeAt(ii);
                    }
                }
            }

        private:
            struct PostponedFree
            {
                uint32_t m_frame;
                void*    m_ptr;
            };

            dm::ListT<PostponedFree, 512> m_free;
        };
        static DelayedFreeAllocator s_delayedFreeAllocator;

        struct BgfxAllocator : public bx::ReallocatorI
        {
            BgfxAllocator()
            {
                #if CS_ALLOC_PRINT_STATS
                m_alloc   = 0;
                m_realloc = 0;
                m_free    = 0;
                #endif //CS_ALLOC_PRINT_STATS
            }

            virtual ~BgfxAllocator()
            {
            }

            virtual void* alloc(size_t _size, size_t _align, const char* _file, uint32_t _line) BX_OVERRIDE
            {
                BX_UNUSED(_align, _file, _line);

                #if CS_ALLOC_PRINT_STATS
                m_mutex.lock();
                m_alloc++;
                m_mutex.unlock();
                #endif //CS_ALLOC_PRINT_STATS

                CS_PRINT_BGFX("Bgfx alloc: %zuB", _size);

                return DM_ALLOC(dm::mainAlloc, _size);
            }

            virtual void free(void* _ptr, size_t _align, const char* _file, uint32_t _line) BX_OVERRIDE
            {
                BX_UNUSED(_align, _file, _line);

                #if CS_ALLOC_PRINT_STATS
                m_mutex.lock();
                m_free++;
                m_mutex.unlock();
                #endif //CS_ALLOC_PRINT_STATS

                CS_PRINT_BGFX("Bgfx free: %llu.%lluKB - (0x%p)", dm::U_UKB(allocSizeOf(_ptr)), _ptr);

                return DM_FREE(dm::mainAlloc, _ptr);
            }

            virtual void* realloc(void* _ptr, size_t _size, size_t _align, const char* _file, uint32_t _line) BX_OVERRIDE
            {
                BX_UNUSED(_align, _file, _line);

                #if CS_ALLOC_PRINT_STATS
                m_mutex.lock();
                m_realloc++;
                m_mutex.unlock();
                #endif //CS_ALLOC_PRINT_STATS

                CS_PRINT_BGFX("Bgfx realloc: %llu.%lluKB - (0x%p)", dm::U_UKB(allocSizeOf(_ptr)), _ptr);

                return DM_REALLOC(dm::mainAlloc, _ptr, _size);
            }

            #if CS_ALLOC_PRINT_STATS
            void printStats()
            {
                fprintf(stderr
                      , "Bgfx allocator:\n"
                        "\t%d/%d/%d (alloc/realloc/free)\n\n"
                      , m_alloc, m_realloc, m_free
                      );
            }
            #endif //CS_ALLOC_PRINT_STATS

        private:
            #if CS_ALLOC_PRINT_STATS
            uint32_t m_alloc;
            uint32_t m_realloc;
            uint32_t m_free;
            bx::LwMutex m_mutex;
            #endif //CS_ALLOC_PRINT_STATS
        };
        static BgfxAllocator s_bgfxAllocator;

        bx::AllocatorI*   delayedFree = &s_delayedFreeAllocator;
        bx::ReallocatorI* bgfxAlloc   = &s_bgfxAllocator;

        void allocGc()
        {
            s_delayedFreeAllocator.cleanup();
        }
    #else
        struct CrtDelayedFreeAllocator : public bx::AllocatorI
        {
            virtual ~CrtDelayedFreeAllocator()
            {
            }

            virtual void* alloc(size_t _size, size_t _align, const char* _file, uint32_t _line) BX_OVERRIDE
            {
                BX_UNUSED(_align, _file, _line);

                return ::malloc(_size);
            }

            virtual void free(void* _ptr, size_t _align, const char* _file, uint32_t _line) BX_OVERRIDE
            {
                BX_UNUSED(_align, _file, _line);

                PostponedFree* free = m_free.addNew();
                free->m_frame = g_frameNum + 2; // Postpone deallocation for two frames.
                free->m_ptr = _ptr;
            }

            void cleanup()
            {
                const uint32_t currFrame = g_frameNum;

                for (uint16_t ii = m_free.count(); ii--; )
                {
                    if (m_free[ii].m_frame <= currFrame)
                    {
                        ::free(m_free[ii].m_ptr);
                        m_free.removeAt(ii);
                    }
                }
            }

        private:
            struct PostponedFree
            {
                uint32_t m_frame;
                void*    m_ptr;
            };

            dm::ListT<PostponedFree, 512> m_free;
        };
        static CrtDelayedFreeAllocator s_crtDelayedFreeAllocator;

        bx::AllocatorI*   delayedFree = &s_crtDelayedFreeAllocator;
        bx::ReallocatorI* bgfxAlloc   = dm::crtAlloc;

        void allocGc()
        {
            s_crtDelayedFreeAllocator.cleanup();
        }
    #endif // DM_ALLOCATOR

    //TODO
    static bool s_allocatorDestroyed = false;
    void allocDestroy()
    {
        s_allocatorDestroyed = true;
    }
}

// Alloc redirection.
//-----

#if CS_OVERRIDE_NEWDELETE && DM_ALLOCATOR
    void* operator new(size_t _size)
    {
        // Make sure memory is initialized.
        static const bool assertInitialized = dm::allocInit();
        BX_UNUSED(assertInitialized);
        return DM_ALLOC(dm::mainAlloc, _size);
    }

    void* operator new[](size_t _size)
    {
        static const bool assertInitialized = dm::allocInit();
        BX_UNUSED(assertInitialized);
        return DM_ALLOC(dm::mainAlloc, _size);
    }

    void operator delete(void* _ptr)
    {
        static const bool assertInitialized = dm::allocInit();
        BX_UNUSED(assertInitialized);
        if (!cs::s_allocatorDestroyed)
        {
            DM_FREE(dm::mainAlloc, _ptr);
        }
        else if (!dm::allocContains(_ptr))
        {
            ::free(_ptr);
        }
    }

    void operator delete[](void* _ptr)
    {
        static const bool assertInitialized = dm::allocInit();
        BX_UNUSED(assertInitialized);
        if (!cs::s_allocatorDestroyed)
        {
            DM_FREE(dm::mainAlloc, _ptr);
        }
        else if (!dm::allocContains(_ptr))
        {
            ::free(_ptr);
        }
    }
#endif // CS_OVERRIDE_NEWDELETE && CS_OVERRIDE_TINYSTL_ALLOCATOR

#if IMGUI_CONFIG_CUSTOM_ALLOCATOR && DM_ALLOCATOR
    void* imguiMalloc(size_t _size, void* /*_userptr*/)
    {
        static const bool assertInitialized = dm::allocInit();
        BX_UNUSED(assertInitialized);

        return DM_ALLOC(dm::mainAlloc, _size);
    }

    void imguiFree(void* _ptr, void* /*_userptr*/)
    {
        static const bool assertInitialized = dm::allocInit();
        BX_UNUSED(assertInitialized);

        return DM_FREE(dm::mainAlloc, _ptr);
    }
#elif IMGUI_CONFIG_CUSTOM_ALLOCATOR
    void* imguiMalloc(size_t _size, void* /*_userptr*/)
    {
        return ::malloc(_size);
    }

    void imguiFree(void* _ptr, void* /*_userptr*/)
    {
        return ::free(_ptr);
    }
#endif // IMGUI_CONFIG_CUSTOM_ALLOCATOR && DM_ALLOCATOR

#if !ENTRY_CONFIG_IMPLEMENT_DEFAULT_ALLOCATOR
    namespace entry
    {
        bx::ReallocatorI* getDefaultAllocator()
        {
            #if DM_ALLOCATOR
            static const bool assertInitialized = dm::allocInit();
                BX_UNUSED(assertInitialized);

                return dm::mainAlloc;
            #else
                return &dm::s_crtAllocator;
            #endif // DM_ALLOCATOR
        }
    }
#endif // !ENTRY_CONFIG_IMPLEMENT_DEFAULT_ALLOCATOR

namespace cs
{
    #if CS_OVERRIDE_TINYSTL_ALLOCATOR && DM_ALLOCATOR
        void* TinyStlAllocator::static_allocate(size_t _bytes)
        {
            static const bool assertInitialized = dm::allocInit();
            BX_UNUSED(assertInitialized);
            return DM_ALLOC(dm::mainAlloc, _bytes);
        }

        void TinyStlAllocator::static_deallocate(void* _ptr, size_t /*_bytes*/)
        {
            static const bool assertInitialized = dm::allocInit();
            BX_UNUSED(assertInitialized);

            return DM_FREE(dm::mainAlloc, _ptr);
        }
    #elif CS_OVERRIDE_TINYSTL_ALLOCATOR
        void* TinyStlAllocator::static_allocate(size_t _bytes)
        {
            return ::malloc(_bytes);
        }

        void TinyStlAllocator::static_deallocate(void* _ptr, size_t /*_bytes*/)
        {
            return ::free(_ptr);
        }
    #endif // CS_OVERRIDE_TINYSTL_ALLOCATOR && DM_ALLOCATOR
} // namespace cs

/* vim: set sw=4 ts=4 expandtab: */
<|endoftext|>


<commit_before>/* bzflag
 * Copyright (c) 1993 - 2005 Tim Riker
 *
 * This package is free software;  you can redistribute it and/or
 * modify it under the terms of the license found in the file
 * named COPYING that should have accompanied this file.
 *
 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

#include "bzfsAPI.h"
#include "PyBZFlag.h"

namespace Python
{

void
TickHandler::process (bz_EventData *eventData)
{
	PyObject *listeners = parent->GetListeners (bz_eTickEvent);

	bz_TickEventData *ted = (bz_TickEventData*) eventData;
	if (listeners == NULL || !PyList_Check (listeners)) {
		// FIXME - throw error
		fprintf (stderr, "tick listeners is not a list!\n");
		return;
	}

	PyObject *arglist = Py_BuildValue("(d)", ted->time);

	// Call out to all of our listeners
	int size = PyList_Size (listeners);
	for (int i = 0; i < size; i++) {
		PyObject *handler = PyList_GetItem (listeners, i);
		if (!PyCallable_Check (handler)) {
			// FIXME - throw error
			fprintf (stderr, "tick listener is not callable\n");
			Py_DECREF (arglist);
			return;
		}
		PyEval_CallObject (handler, arglist);
	}
	Py_DECREF (arglist);
}

void
JoinHandler::process (bz_EventData *eventData)
{
	bz_PlayerJoinPartEventData *pjped = (bz_PlayerJoinPartEventData*) eventData;
	parent->AddPlayer (pjped->playerID);

	PyObject *listeners = parent->GetListeners (bz_ePlayerJoinEvent);
	if (listeners == NULL || !PyList_Check (listeners)) {
		// FIXME - throw error
		fprintf (stderr, "join listeners is not a list!\n");
		return;
	}

	// Call out to all of our listeners
	int size = PyList_Size (listeners);
	for (int i = 0; i < size; i++) {
		PyObject *handler = PyList_GetItem (listeners, i);
		if (!PyCallable_Check (handler)) {
			// FIXME - throw error
			fprintf (stderr, "join listener is not callable\n");
			return;
		}
		PyEval_CallObject (handler, NULL);
	}
}

void
PartHandler::process (bz_EventData *eventData)
{
	bz_PlayerJoinPartEventData *pjped = (bz_PlayerJoinPartEventData*) eventData;
	parent->RemovePlayer (pjped->playerID);

	PyObject *listeners = parent->GetListeners (bz_ePlayerPartEvent);
	if (listeners == NULL || !PyList_Check (listeners)) {
		// FIXME - throw error
		fprintf (stderr, "part listeners is not a list!\n");
		return;
	}

	// Call out to all of our listeners
	int size = PyList_Size (listeners);
	for (int i = 0; i < size; i++) {
		PyObject *handler = PyList_GetItem (listeners, i);
		if (!PyCallable_Check (handler)) {
			// FIXME - throw error
			fprintf (stderr, "part listener is not callable\n");
			return;
		}
		PyEval_CallObject (handler, NULL);
	}
}

static PyObject *SendTextMessage (PyObject *self, PyObject *args, PyObject *keywords);
static PyObject *FireWorldWeapon (PyObject *self, PyObject *args);
static PyObject *GetCurrentTime  (PyObject *self, PyObject *args);

static struct PyMethodDef methods[] =
{
	// FIXME - docstrings
	{"SendTextMessage", (PyCFunction) SendTextMessage, METH_VARARGS | METH_KEYWORDS, NULL},
	{"FireWorldWeapon", (PyCFunction) FireWorldWeapon, METH_VARARGS,                 NULL},
	{"GetCurrentTime",  (PyCFunction) GetCurrentTime,  METH_NOARGS,                  NULL},
	{NULL,              (PyCFunction) NULL,            0,                            NULL},
};

BZFlag *BZFlag::instance = NULL;
int BZFlag::References = 0;

BZFlag *
BZFlag::GetInstance ()
{
	if (instance == NULL)
		instance = new BZFlag ();
	References++;
	return instance;
}

void
BZFlag::DeRef ()
{
	References--;
}

void
CreateHandlerList (PyObject *dict, int event)
{
	PyDict_SetItem (dict, PyInt_FromLong (event), PyList_New (0));
}

BZFlag::BZFlag ()
{
	module = Py_InitModule3 ("BZFlag", methods, NULL);
	Py_INCREF (Py_None);
	Py_INCREF (Py_False);
	Py_INCREF (Py_True);

	// Create and add submodules
	event_sub = new Event ();
	team_sub  = new Team ();

	PyModule_AddObject (module, "Event", event_sub->GetSubModule ());
	PyModule_AddObject (module, "Team",   team_sub->GetSubModule ());

	// Register event handlers
	tick_handler.parent = this;
	join_handler.parent = this;
	part_handler.parent = this;
	bz_registerGeneralEvent (bz_eTickEvent,       &tick_handler);
	bz_registerGeneralEvent (bz_ePlayerJoinEvent, &join_handler);
	bz_registerGeneralEvent (bz_ePlayerPartEvent, &part_handler);

	// Create the dictionary for all the event handlers. Key is the int
	// event ID, value is a list of callables for our callbacks. Marshalling
	// is handled by the individual event handler classes
	event_listeners = PyDict_New ();
	CreateHandlerList (event_listeners, bz_eTickEvent);
	CreateHandlerList (event_listeners, bz_ePlayerJoinEvent);
	CreateHandlerList (event_listeners, bz_ePlayerPartEvent);

	PyModule_AddObject (module, "Events", event_listeners);

	// Create the players list
	players = PyDict_New ();

	PyModule_AddObject (module, "Players", players);
}

PyObject *
BZFlag::GetListeners (int event)
{
	PyObject *o = PyInt_FromLong (event);
	PyObject *ret = PyDict_GetItem (event_listeners, o);
	Py_DECREF (o);

	return ret;
}

bool PlayerExists (std::vector<int> h, int n)
{
	for (std::vector<int>::iterator it = h.begin (); it != h.end (); it++) {
		if (n == *it)
			return true;
	}
	return false;
}

void
BZFlag::AddPlayer (int id)
{
	bz_PlayerRecord record;
	bz_getPlayerByIndex (id, &record);

	//PyObject *pyp = CreatePlayer (record);
	PyDict_SetItem (players, PyInt_FromLong (id), Py_None);
}

void
BZFlag::RemovePlayer (int id)
{
	PyDict_DelItem (players, PyInt_FromLong (id));
}

static PyObject *
SendTextMessage (PyObject *self, PyObject *args, PyObject *keywords)
{
	int to, from;
	char *message;

	static char *kwlist[] = {"to", "from", "message", NULL};

	if (!PyArg_ParseTupleAndKeywords (args, keywords, "iis", kwlist, &to, &from, &message)) {
		fprintf (stderr, "couldn't parse args\n");
		// FIXME - throw error
		return NULL;
	}

	printf ("SendTextMessage (%d, %d, %s)\n", to, from, message);
	bool result = bz_sendTextMessage (to, from, message);
	return Py_None;
}

static PyObject *
FireWorldWeapon (PyObject *self, PyObject *args)
{
	printf ("FireWorldWeapon ()\n");
	char *flag;
	float lifetime;
	int from_player;
	return Py_None;
}

static PyObject *
GetCurrentTime (PyObject *self, PyObject *args)
{
	printf ("GetCurrentTime ()\n");
	return Py_None;
}

};
<commit_msg>yep, getting lots of paid work done today. stub out bindings for the wait time funcs<commit_after>/* bzflag
 * Copyright (c) 1993 - 2005 Tim Riker
 *
 * This package is free software;  you can redistribute it and/or
 * modify it under the terms of the license found in the file
 * named COPYING that should have accompanied this file.
 *
 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

#include "bzfsAPI.h"
#include "PyBZFlag.h"

namespace Python
{

void
TickHandler::process (bz_EventData *eventData)
{
	PyObject *listeners = parent->GetListeners (bz_eTickEvent);

	bz_TickEventData *ted = (bz_TickEventData*) eventData;
	if (listeners == NULL || !PyList_Check (listeners)) {
		// FIXME - throw error
		fprintf (stderr, "tick listeners is not a list!\n");
		return;
	}

	PyObject *arglist = Py_BuildValue("(d)", ted->time);

	// Call out to all of our listeners
	int size = PyList_Size (listeners);
	for (int i = 0; i < size; i++) {
		PyObject *handler = PyList_GetItem (listeners, i);
		if (!PyCallable_Check (handler)) {
			// FIXME - throw error
			fprintf (stderr, "tick listener is not callable\n");
			Py_DECREF (arglist);
			return;
		}
		PyEval_CallObject (handler, arglist);
	}
	Py_DECREF (arglist);
}

void
JoinHandler::process (bz_EventData *eventData)
{
	bz_PlayerJoinPartEventData *pjped = (bz_PlayerJoinPartEventData*) eventData;
	parent->AddPlayer (pjped->playerID);

	PyObject *listeners = parent->GetListeners (bz_ePlayerJoinEvent);
	if (listeners == NULL || !PyList_Check (listeners)) {
		// FIXME - throw error
		fprintf (stderr, "join listeners is not a list!\n");
		return;
	}

	// Call out to all of our listeners
	int size = PyList_Size (listeners);
	for (int i = 0; i < size; i++) {
		PyObject *handler = PyList_GetItem (listeners, i);
		if (!PyCallable_Check (handler)) {
			// FIXME - throw error
			fprintf (stderr, "join listener is not callable\n");
			return;
		}
		PyEval_CallObject (handler, NULL);
	}
}

void
PartHandler::process (bz_EventData *eventData)
{
	bz_PlayerJoinPartEventData *pjped = (bz_PlayerJoinPartEventData*) eventData;
	parent->RemovePlayer (pjped->playerID);

	PyObject *listeners = parent->GetListeners (bz_ePlayerPartEvent);
	if (listeners == NULL || !PyList_Check (listeners)) {
		// FIXME - throw error
		fprintf (stderr, "part listeners is not a list!\n");
		return;
	}

	// Call out to all of our listeners
	int size = PyList_Size (listeners);
	for (int i = 0; i < size; i++) {
		PyObject *handler = PyList_GetItem (listeners, i);
		if (!PyCallable_Check (handler)) {
			// FIXME - throw error
			fprintf (stderr, "part listener is not callable\n");
			return;
		}
		PyEval_CallObject (handler, NULL);
	}
}

static PyObject *FireWorldWeapon (PyObject *self, PyObject *args);
static PyObject *GetCurrentTime  (PyObject *self, PyObject *args);
static PyObject *GetMaxWaitTime  (PyObject *self, PyObject *args);
static PyObject *SendTextMessage (PyObject *self, PyObject *args, PyObject *keywords);
static PyObject *SetMaxWaitTime  (PyObject *self, PyObject *args);

static struct PyMethodDef methods[] =
{
	// FIXME - docstrings
	{"FireWorldWeapon", (PyCFunction) FireWorldWeapon, METH_VARARGS,                 NULL},
	{"GetCurrentTime",  (PyCFunction) GetCurrentTime,  METH_NOARGS,                  NULL},
	{"GetMaxWaitTime",  (PyCFunction) GetMaxWaitTime,  METH_NOARGS,                  NULL},
	{"SendTextMessage", (PyCFunction) SendTextMessage, METH_VARARGS | METH_KEYWORDS, NULL},
	{"SetMaxWaitTime",  (PyCFunction) SetMaxWaitTime,  METH_VARARGS,                 NULL},
	{NULL,              (PyCFunction) NULL,            0,                            NULL},
};

BZFlag *BZFlag::instance = NULL;
int BZFlag::References = 0;

BZFlag *
BZFlag::GetInstance ()
{
	if (instance == NULL)
		instance = new BZFlag ();
	References++;
	return instance;
}

void
BZFlag::DeRef ()
{
	References--;
}

void
CreateHandlerList (PyObject *dict, int event)
{
	PyDict_SetItem (dict, PyInt_FromLong (event), PyList_New (0));
}

BZFlag::BZFlag ()
{
	module = Py_InitModule3 ("BZFlag", methods, NULL);
	Py_INCREF (Py_None);
	Py_INCREF (Py_False);
	Py_INCREF (Py_True);

	// Create and add submodules
	event_sub = new Event ();
	team_sub  = new Team ();

	PyModule_AddObject (module, "Event", event_sub->GetSubModule ());
	PyModule_AddObject (module, "Team",   team_sub->GetSubModule ());

	// Register event handlers
	tick_handler.parent = this;
	join_handler.parent = this;
	part_handler.parent = this;
	bz_registerGeneralEvent (bz_eTickEvent,       &tick_handler);
	bz_registerGeneralEvent (bz_ePlayerJoinEvent, &join_handler);
	bz_registerGeneralEvent (bz_ePlayerPartEvent, &part_handler);

	// Create the dictionary for all the event handlers. Key is the int
	// event ID, value is a list of callables for our callbacks. Marshalling
	// is handled by the individual event handler classes
	event_listeners = PyDict_New ();
	CreateHandlerList (event_listeners, bz_eTickEvent);
	CreateHandlerList (event_listeners, bz_ePlayerJoinEvent);
	CreateHandlerList (event_listeners, bz_ePlayerPartEvent);

	PyModule_AddObject (module, "Events", event_listeners);

	// Create the players list
	players = PyDict_New ();

	PyModule_AddObject (module, "Players", players);
}

PyObject *
BZFlag::GetListeners (int event)
{
	PyObject *o = PyInt_FromLong (event);
	PyObject *ret = PyDict_GetItem (event_listeners, o);
	Py_DECREF (o);

	return ret;
}

bool PlayerExists (std::vector<int> h, int n)
{
	for (std::vector<int>::iterator it = h.begin (); it != h.end (); it++) {
		if (n == *it)
			return true;
	}
	return false;
}

void
BZFlag::AddPlayer (int id)
{
	bz_PlayerRecord record;
	bz_getPlayerByIndex (id, &record);

	//PyObject *pyp = CreatePlayer (record);
	PyDict_SetItem (players, PyInt_FromLong (id), Py_None);
}

void
BZFlag::RemovePlayer (int id)
{
	PyDict_DelItem (players, PyInt_FromLong (id));
}

static PyObject *
FireWorldWeapon (PyObject *self, PyObject *args)
{
	printf ("FireWorldWeapon ()\n");
	char *flag;
	float lifetime;
	int from_player;
	return Py_None;
}

static PyObject *
GetCurrentTime (PyObject *self, PyObject *args)
{
	printf ("GetCurrentTime ()\n");
	return Py_None;
}

static PyObject *
GetMaxWaitTime (PyObject *self, PyObject *args)
{
}

static PyObject *
SendTextMessage (PyObject *self, PyObject *args, PyObject *keywords)
{
	int to, from;
	char *message;

	static char *kwlist[] = {"to", "from", "message", NULL};

	if (!PyArg_ParseTupleAndKeywords (args, keywords, "iis", kwlist, &to, &from, &message)) {
		fprintf (stderr, "couldn't parse args\n");
		// FIXME - throw error
		return NULL;
	}

	printf ("SendTextMessage (%d, %d, %s)\n", to, from, message);
	bool result = bz_sendTextMessage (to, from, message);
	return Py_None;
}

static PyObject *
SetMaxWaitTime (PyObject *self, PyObject *args)
{
}

};
<|endoftext|>