<commit_before>/*
	This file is part of the Sound library.
	Copyright (C) 2008-2012 Benjamin Eikel <benjamin@eikel.org>
	Copyright (C) 2008-2012 Claudius Jähn <claudius@uni-paderborn.de>
	Copyright (C) 2008-2012 Ralf Petring <ralf@petring.net>

	This library is subject to the terms of the Mozilla Public License, v. 2.0.
	You should have received a copy of the MPL along with this library; see the
	file LICENSE. If not, you can obtain one at http://mozilla.org/MPL/2.0/.
*/
#include "Sound.h"
#include "Buffer.h"
#include "Listener.h"
#include "Source.h"
#include "SoundInternals.h"

#include <SDL.h>

#include <Util/Macros.h>
#include <Util/References.h>

#include <algorithm>
#include <cstddef>
#include <iostream>
#include <cstdint>
#include <vector>

namespace Sound {

static ALCdevice *myDevice=nullptr;
static ALCcontext * myContext=nullptr;
//    if (alcIsExtensionPresent(nullptr, "ALC_ENUMERATION_EXT") != AL_TRUE) {
//        std::cout << "Enumeration not available!";
//        return;
//    }

//    // defaultDeviceName contains the name of the default
//    // device
//    const ALCchar *defaultDeviceName;
//    defaultDeviceName = alcGetString(nullptr, ALC_DEFAULT_DEVICE_SPECIFIER);
//    std::cout << "\nDevice:"<< defaultDeviceName ;

//! [static]
std::string getDeviceName(){
	const ALCchar *actualDeviceName;
	actualDeviceName = alcGetString(myDevice, ALC_DEVICE_SPECIFIER);
	return std::string(actualDeviceName);
}

//! [static]
bool checkErrorStatus(const char * file, int line, const std::string & msg) {
	const ALenum error = alGetError();
	if (error == AL_NO_ERROR) {
		return true;
	}
	std::cerr << "AL ERROR (";
	const ALchar * errorString = alGetString(error);
	if(errorString != nullptr) {
		std::cerr << errorString;
	} else {
		std::cerr << error;
	}
	std::cerr << "): " << msg << " at " << file << ":" << line << std::endl;
	return false;
}

static void checkALCErrorStatus(const char * file, int line, ALCdevice * device) {
	const ALCenum error = alcGetError(device);
	if(error == ALC_NO_ERROR) {
		return;
	}
	std::cerr << "ALC ERROR (";
	const ALchar * errorString = alcGetString(device, error);
	if(errorString != nullptr) {
		std::cerr << errorString;
	} else {
		std::cerr << error;
	}
	std::cerr << ") at " << file << ":" << line << std::endl;
}

//! [static]
bool initSoundSystem(){
	if(myContext != nullptr) { // already initialized?
		return true;
	}

	// Open the default device
	myDevice = alcOpenDevice(nullptr);
	checkALCErrorStatus(__FILE__, __LINE__, myDevice);
	if(myDevice == nullptr) {
		return false;
	}

	// Create Context
	myContext = alcCreateContext(myDevice, nullptr);
	checkALCErrorStatus(__FILE__, __LINE__, myDevice);
	if(myContext == nullptr) {
		return false;
	}

	alcMakeContextCurrent(myContext);
	checkALCErrorStatus(__FILE__, __LINE__, myDevice);

	if(!checkErrorStatus(__FILE__, __LINE__, "initSoundSystem()")){
		shutDownSoundSystem();
		return false;
	}
	return true;
}

//! [static]
void shutDownSoundSystem(){
	alcMakeContextCurrent(nullptr);
	alcDestroyContext(myContext);
	alcCloseDevice(myDevice);
	myContext = nullptr;
	myDevice = nullptr;
}

//! [static]
Listener * getListener()	{
	return Listener::getInstance();
}

//! [static]
Source * createSource(){
	return Source::create();
}

//! [static] factory
Buffer * createNoise(unsigned int freq, unsigned int size) {
	Util::Reference<Buffer> b(Buffer::create());
	if(b.isNull())
		return nullptr;

	std::vector<uint8_t> noise;
	noise.reserve(size);
	unsigned int j = 1;
	for (unsigned int i = 0; i < size; ++i) {
		j = (j * 1234393 + i) % 0xffffff;
		noise.push_back(static_cast<uint8_t>(j) % 256);
	}
	b->setData(AL_FORMAT_MONO8, noise.data(), noise.size(),freq);

	return checkErrorStatus(__FILE__, __LINE__) ? b.detachAndDecrease() : nullptr;
}

//! [static] factory
Buffer * createRectangleSound(unsigned int width, unsigned int freq, unsigned int size) {
	Util::Reference<Buffer> b(Buffer::create());
	if(b.isNull())
		return nullptr;

	std::vector<uint8_t> noise;
	noise.reserve(size);
	uint8_t value = 0;
	for (unsigned int i = 0; i < size; ++i) {
		if(i % width == 0) {
			value = 255 - value;
		}
		noise.push_back(value);
	}
	b->setData(AL_FORMAT_MONO8, noise.data(), noise.size(), freq);

	return checkErrorStatus(__FILE__, __LINE__) ? b.detachAndDecrease() : nullptr;
}

//! [static] factory
Buffer * createSilence(unsigned int freq,unsigned int size) {
	Util::Reference<Buffer> b(Buffer::create());
	if(b.isNull())
		return nullptr;

	const std::vector<uint8_t> data(size, 128);
	b->setData(AL_FORMAT_MONO8, data.data(), data.size(), freq);

	return checkErrorStatus(__FILE__, __LINE__) ? b.detachAndDecrease() : nullptr;
}

//! [static] factory
Buffer * loadWAV(const std::string & filename) {
	Util::Reference<Buffer> b(Buffer::create());
	if(b.isNull())
		return nullptr;

	SDL_AudioSpec wav_spec;
	Uint32 wav_length;
	Uint8 *wav_buffer;

	if ( SDL_LoadWAV(filename.c_str(), &wav_spec, &wav_buffer, &wav_length) == nullptr ) {
		WARN("Could not open : "+ filename+ std::string( SDL_GetError()) );
		return nullptr;
	}

	unsigned int format=0;
	unsigned int freq = static_cast<unsigned int>(wav_spec.freq);
	if (wav_spec.format == AUDIO_U8 ) {
		if (wav_spec.channels==1)
			format=AL_FORMAT_MONO8;
		else
			format=AL_FORMAT_STEREO8;
	} else if (wav_spec.format == AUDIO_S16SYS ) {
		if (wav_spec.channels==1)
			format=AL_FORMAT_MONO16;
		else
			format=AL_FORMAT_STEREO16;
	}
	if (format==0) {
		WARN("Uninplemented WAV-format. Please add conversion routine ;).");
		return nullptr;
	} else
		b->setData(format,wav_buffer,wav_length,freq);

//    b->setData(AL_FORMAT_MONO8,noise,size,freq);
	SDL_FreeWAV(wav_buffer);

	return checkErrorStatus(__FILE__, __LINE__) ? b.detachAndDecrease() : nullptr;
}

}
<commit_msg>Remove compiler warnings.<commit_after>/*
	This file is part of the Sound library.
	Copyright (C) 2008-2012 Benjamin Eikel <benjamin@eikel.org>
	Copyright (C) 2008-2012 Claudius Jähn <claudius@uni-paderborn.de>
	Copyright (C) 2008-2012 Ralf Petring <ralf@petring.net>

	This library is subject to the terms of the Mozilla Public License, v. 2.0.
	You should have received a copy of the MPL along with this library; see the
	file LICENSE. If not, you can obtain one at http://mozilla.org/MPL/2.0/.
*/
#include "Sound.h"
#include "Buffer.h"
#include "Listener.h"
#include "Source.h"
#include "SoundInternals.h"

#include <Util/Macros.h>
COMPILER_WARN_PUSH
COMPILER_WARN_OFF_CLANG(-W#warnings)
COMPILER_WARN_OFF_GCC(-Wswitch-default)
#include <SDL.h>
COMPILER_WARN_POP
#include <Util/References.h>

#include <algorithm>
#include <cstddef>
#include <iostream>
#include <cstdint>
#include <vector>

namespace Sound {

static ALCdevice *myDevice=nullptr;
static ALCcontext * myContext=nullptr;
//    if (alcIsExtensionPresent(nullptr, "ALC_ENUMERATION_EXT") != AL_TRUE) {
//        std::cout << "Enumeration not available!";
//        return;
//    }

//    // defaultDeviceName contains the name of the default
//    // device
//    const ALCchar *defaultDeviceName;
//    defaultDeviceName = alcGetString(nullptr, ALC_DEFAULT_DEVICE_SPECIFIER);
//    std::cout << "\nDevice:"<< defaultDeviceName ;

//! [static]
std::string getDeviceName(){
	const ALCchar *actualDeviceName;
	actualDeviceName = alcGetString(myDevice, ALC_DEVICE_SPECIFIER);
	return std::string(actualDeviceName);
}

//! [static]
bool checkErrorStatus(const char * file, int line, const std::string & msg) {
	const ALenum error = alGetError();
	if (error == AL_NO_ERROR) {
		return true;
	}
	std::cerr << "AL ERROR (";
	const ALchar * errorString = alGetString(error);
	if(errorString != nullptr) {
		std::cerr << errorString;
	} else {
		std::cerr << error;
	}
	std::cerr << "): " << msg << " at " << file << ":" << line << std::endl;
	return false;
}

static void checkALCErrorStatus(const char * file, int line, ALCdevice * device) {
	const ALCenum error = alcGetError(device);
	if(error == ALC_NO_ERROR) {
		return;
	}
	std::cerr << "ALC ERROR (";
	const ALchar * errorString = alcGetString(device, error);
	if(errorString != nullptr) {
		std::cerr << errorString;
	} else {
		std::cerr << error;
	}
	std::cerr << ") at " << file << ":" << line << std::endl;
}

//! [static]
bool initSoundSystem(){
	if(myContext != nullptr) { // already initialized?
		return true;
	}

	// Open the default device
	myDevice = alcOpenDevice(nullptr);
	checkALCErrorStatus(__FILE__, __LINE__, myDevice);
	if(myDevice == nullptr) {
		return false;
	}

	// Create Context
	myContext = alcCreateContext(myDevice, nullptr);
	checkALCErrorStatus(__FILE__, __LINE__, myDevice);
	if(myContext == nullptr) {
		return false;
	}

	alcMakeContextCurrent(myContext);
	checkALCErrorStatus(__FILE__, __LINE__, myDevice);

	if(!checkErrorStatus(__FILE__, __LINE__, "initSoundSystem()")){
		shutDownSoundSystem();
		return false;
	}
	return true;
}

//! [static]
void shutDownSoundSystem(){
	alcMakeContextCurrent(nullptr);
	alcDestroyContext(myContext);
	alcCloseDevice(myDevice);
	myContext = nullptr;
	myDevice = nullptr;
}

//! [static]
Listener * getListener()	{
	return Listener::getInstance();
}

//! [static]
Source * createSource(){
	return Source::create();
}

//! [static] factory
Buffer * createNoise(unsigned int freq, unsigned int size) {
	Util::Reference<Buffer> b(Buffer::create());
	if(b.isNull())
		return nullptr;

	std::vector<uint8_t> noise;
	noise.reserve(size);
	unsigned int j = 1;
	for (unsigned int i = 0; i < size; ++i) {
		j = (j * 1234393 + i) % 0xffffff;
		noise.push_back(static_cast<uint8_t>(j) % 256);
	}
	b->setData(AL_FORMAT_MONO8, noise.data(), noise.size(),freq);

	return checkErrorStatus(__FILE__, __LINE__) ? b.detachAndDecrease() : nullptr;
}

//! [static] factory
Buffer * createRectangleSound(unsigned int width, unsigned int freq, unsigned int size) {
	Util::Reference<Buffer> b(Buffer::create());
	if(b.isNull())
		return nullptr;

	std::vector<uint8_t> noise;
	noise.reserve(size);
	uint8_t value = 0;
	for (unsigned int i = 0; i < size; ++i) {
		if(i % width == 0) {
			value = 255 - value;
		}
		noise.push_back(value);
	}
	b->setData(AL_FORMAT_MONO8, noise.data(), noise.size(), freq);

	return checkErrorStatus(__FILE__, __LINE__) ? b.detachAndDecrease() : nullptr;
}

//! [static] factory
Buffer * createSilence(unsigned int freq,unsigned int size) {
	Util::Reference<Buffer> b(Buffer::create());
	if(b.isNull())
		return nullptr;

	const std::vector<uint8_t> data(size, 128);
	b->setData(AL_FORMAT_MONO8, data.data(), data.size(), freq);

	return checkErrorStatus(__FILE__, __LINE__) ? b.detachAndDecrease() : nullptr;
}

//! [static] factory
Buffer * loadWAV(const std::string & filename) {
	Util::Reference<Buffer> b(Buffer::create());
	if(b.isNull())
		return nullptr;

	SDL_AudioSpec wav_spec;
	Uint32 wav_length;
	Uint8 *wav_buffer;

	if ( SDL_LoadWAV(filename.c_str(), &wav_spec, &wav_buffer, &wav_length) == nullptr ) {
		WARN("Could not open : "+ filename+ std::string( SDL_GetError()) );
		return nullptr;
	}

	unsigned int format=0;
	unsigned int freq = static_cast<unsigned int>(wav_spec.freq);
	if (wav_spec.format == AUDIO_U8 ) {
		if (wav_spec.channels==1)
			format=AL_FORMAT_MONO8;
		else
			format=AL_FORMAT_STEREO8;
	} else if (wav_spec.format == AUDIO_S16SYS ) {
		if (wav_spec.channels==1)
			format=AL_FORMAT_MONO16;
		else
			format=AL_FORMAT_STEREO16;
	}
	if (format==0) {
		WARN("Uninplemented WAV-format. Please add conversion routine ;).");
		return nullptr;
	} else
		b->setData(format,wav_buffer,wav_length,freq);

//    b->setData(AL_FORMAT_MONO8,noise,size,freq);
	SDL_FreeWAV(wav_buffer);

	return checkErrorStatus(__FILE__, __LINE__) ? b.detachAndDecrease() : nullptr;
}

}
<|endoftext|>


<commit_before>//=======================================================================
// Copyright (c) 2014-2016 Baptiste Wicht
// Distributed under the terms of the MIT License.
// (See accompanying file LICENSE or copy at
//  http://opensource.org/licenses/MIT)
//=======================================================================

#pragma once

namespace etl {

namespace impl {

namespace vec {

namespace detail {

template <typename V, typename I, typename K, typename C>
void conv2_valid_flipped(const I& input, const K& kernel, C&& conv) {
    using T = value_t<I>;
    using vec_type = V;

    static constexpr size_t vec_size = vec_type::template traits<T>::size;

    const auto n1 = etl::dim<0>(input);
    const auto n2 = etl::dim<1>(input);

    const auto k1 = etl::dim<0>(kernel);
    const auto k2 = etl::dim<1>(kernel);

    const auto c1 = etl::dim<0>(conv);
    const auto c2 = etl::dim<1>(conv);

    const auto R = std::min(k1, c1); // Max number of kernels per line of input

    conv = T(0);

    // Primary steps
    for(size_t i = 0; i < k1 - 1; ++i){
        const auto M = std::min(i + 1, R);

        for(size_t j = 0; j < c2;  ++j){
            for(size_t m = 0; m < M; ++m){
                const auto k_i = i - m;

                auto r1 = vec_type::template zero<T>();

                size_t k = 0;
                for(; k + vec_size - 1 < k2; k += vec_size){
                    auto a1 = input.loadu(i * n2 + j + k);
                    auto b1 = kernel.loadu(k_i * k2 + k);

                    auto t1 = vec_type::template mul<false>(a1, b1);
                    r1 = vec_type::add(r1, t1);
                }

                T value = vec_type::hadd(r1);

                for(; k < k2; ++k){
                    value += input(i, j + k) * kernel(k_i, k);
                }

                conv(m,j) += value;
            }
        }
    }

    // Main steps
    for(size_t i = k1 - 1; i < c1; ++i){
        const auto M = R;

        for(size_t j = 0; j < c2;  ++j){
            for(size_t m = 0; m < M; ++m){
                const auto c_i = i - m;

                auto r1 = vec_type::template zero<T>();

                size_t k = 0;
                for(; k + vec_size - 1 < k2; k += vec_size){
                    auto a1 = input.loadu(i * n2 + j + k);
                    auto b1 = kernel.loadu(m * k2 + k);

                    auto t1 = vec_type::template mul<false>(a1, b1);
                    r1 = vec_type::add(r1, t1);
                }

                T value = vec_type::hadd(r1);

                for(; k < k2; ++k){
                    value += input(i, j + k) * kernel(m, k);
                }

                conv(c_i, j) += value;
            }
        }
    }

    // Secondary steps
    for(size_t i = c1; i < n1; ++i){
        auto M = std::min(n1 - i, R);

        for(size_t j = 0; j < c2;  ++j){
            for(size_t m = 0; m < M; ++m){
                const auto c_i = m + i - k1 + 1;
                const auto k_i = M - m - c1 + i;

                auto r1 = vec_type::template zero<T>();

                size_t k = 0;
                for(; k + vec_size - 1 < k2; k += vec_size){
                    auto a1 = input.loadu(i * n2 + j + k);
                    auto b1 = kernel.loadu(k_i * k2 + k);

                    auto t1 = vec_type::template mul<false>(a1, b1);
                    r1 = vec_type::add(r1, t1);
                }

                T value = vec_type::hadd(r1);

                for(; k < k2; ++k){
                    value += input(i, j + k) * kernel(k_i, k);
                }

                conv(c_i, j) += value;
            }
        }
    }
}

} // end of namespace detail

/*!
 * \brief Standard implementation of a 2D 'valid' convolution C = I * K
 * \param input The input matrix
 * \param kernel The kernel matrix
 * \param conv The output matrix
 */
template <typename I, typename K, typename C>
void conv2_valid_flipped(const I& input, const K& kernel, C&& conv, size_t s1, size_t s2, size_t p1, size_t p2) {
    using T = value_t<I>;

    const auto n1 = etl::dim<0>(input);
    const auto n2 = etl::dim<1>(input);

    const auto k1 = etl::dim<0>(kernel);
    const auto k2 = etl::dim<1>(kernel);

    const auto c1 = etl::dim<0>(conv);
    const auto c2 = etl::dim<1>(conv);

    if(cpp_unlikely(p1 || p2)){
        const auto o1 = n1 + 2 * p1;
        const auto o2 = n2 + 2 * p2;

        etl::dyn_matrix<T> padded_matrix(o1, o2);
        padded_matrix = T(0);

        for (size_t i = 0; i < n1; ++i) {
            for(size_t j = 0; j < n2; ++j){
                padded_matrix[(i + p1) * o2 + p2 + j] = input(i, j);
            }
        }

        conv2_valid_flipped(padded_matrix, kernel, conv, s1, s2, 0, 0);

        return;
    }

    if(cpp_unlikely(s1 > 1 || s2 > 1)){
        etl::dyn_matrix<T> tmp_result(n1 - k1 + 1, n2 - k2 + 1);

        conv2_valid_flipped(input, kernel, tmp_result, 1, 1, 0, 0);

        // Strided copy of the large result into the small result
        for (std::size_t i = 0; i < c1; ++i) {
            for (std::size_t j = 0; j < c2; ++j) {
                conv(i, j) = tmp_result(i * s1, j * s2);
            }
        }

        return;
    }

    detail::conv2_valid_flipped<default_vec>(input, kernel, conv);
}

} //end of namespace vec
} //end of namespace impl
} //end of namespace etl
<commit_msg>Continue locality conv<commit_after>//=======================================================================
// Copyright (c) 2014-2016 Baptiste Wicht
// Distributed under the terms of the MIT License.
// (See accompanying file LICENSE or copy at
//  http://opensource.org/licenses/MIT)
//=======================================================================

#pragma once

namespace etl {

namespace impl {

namespace vec {

namespace detail {

template <typename V, typename I, typename K, typename C>
void conv2_valid_flipped(const I& input, const K& kernel, C&& conv) {
    using T = value_t<I>;
    using vec_type = V;

    static constexpr size_t vec_size = vec_type::template traits<T>::size;

    const auto n1 = etl::dim<0>(input);
    const auto n2 = etl::dim<1>(input);

    const auto k1 = etl::dim<0>(kernel);
    const auto k2 = etl::dim<1>(kernel);

    const auto c1 = etl::dim<0>(conv);
    const auto c2 = etl::dim<1>(conv);

    const auto R = std::min(k1, c1); // Max number of kernels per line of input

    conv = T(0);

    // Primary steps
    for(size_t i = 0; i < k1 - 1; ++i){
        const auto M = std::min(i + 1, R);

        for(size_t j = 0; j < c2;  ++j){
            for(size_t m = 0; m < M; ++m){
                const auto k_i = i - m;

                auto r1 = vec_type::template zero<T>();

                size_t k = 0;
                for(; k + vec_size - 1 < k2; k += vec_size){
                    auto a1 = input.template loadu<vec_type>(i * n2 + j + k);
                    auto b1 = kernel.template loadu<vec_type>(k_i * k2 + k);

                    auto t1 = vec_type::template mul<false>(a1, b1);
                    r1 = vec_type::add(r1, t1);
                }

                T value = vec_type::hadd(r1);

                for(; k < k2; ++k){
                    value += input(i, j + k) * kernel(k_i, k);
                }

                conv(m,j) += value;
            }
        }
    }

    // Main steps
    for(size_t i = k1 - 1; i < c1; ++i){
        const auto M = R;

        for(size_t m = 0; m < M; ++m){
            const auto c_i = i - m;

            size_t j = 0;

            for(; j + 7 < c2; j += 8){
                auto r1 = vec_type::template zero<T>();
                auto r2 = vec_type::template zero<T>();
                auto r3 = vec_type::template zero<T>();
                auto r4 = vec_type::template zero<T>();
                auto r5 = vec_type::template zero<T>();
                auto r6 = vec_type::template zero<T>();
                auto r7 = vec_type::template zero<T>();
                auto r8 = vec_type::template zero<T>();

                size_t k = 0;
                for(; k + vec_size - 1 < k2; k += vec_size){
                    auto b1 = kernel.template loadu<vec_type>(m * k2 + k);

                    auto a1 = input.template loadu<vec_type>(i * n2 + (j + 0) + k);
                    auto a2 = input.template loadu<vec_type>(i * n2 + (j + 1) + k);
                    auto a3 = input.template loadu<vec_type>(i * n2 + (j + 2) + k);
                    auto a4 = input.template loadu<vec_type>(i * n2 + (j + 3) + k);
                    auto a5 = input.template loadu<vec_type>(i * n2 + (j + 4) + k);
                    auto a6 = input.template loadu<vec_type>(i * n2 + (j + 5) + k);
                    auto a7 = input.template loadu<vec_type>(i * n2 + (j + 6) + k);
                    auto a8 = input.template loadu<vec_type>(i * n2 + (j + 7) + k);

                    auto t1 = vec_type::template mul<false>(a1, b1);
                    auto t2 = vec_type::template mul<false>(a2, b1);
                    auto t3 = vec_type::template mul<false>(a3, b1);
                    auto t4 = vec_type::template mul<false>(a4, b1);
                    auto t5 = vec_type::template mul<false>(a5, b1);
                    auto t6 = vec_type::template mul<false>(a6, b1);
                    auto t7 = vec_type::template mul<false>(a7, b1);
                    auto t8 = vec_type::template mul<false>(a8, b1);

                    r1 = vec_type::add(r1, t1);
                    r2 = vec_type::add(r2, t2);
                    r3 = vec_type::add(r3, t3);
                    r4 = vec_type::add(r4, t4);
                    r5 = vec_type::add(r5, t5);
                    r6 = vec_type::add(r6, t6);
                    r7 = vec_type::add(r7, t7);
                    r8 = vec_type::add(r8, t8);
                }

                T v1 = vec_type::hadd(r1);
                T v2 = vec_type::hadd(r2);
                T v3 = vec_type::hadd(r3);
                T v4 = vec_type::hadd(r4);
                T v5 = vec_type::hadd(r5);
                T v6 = vec_type::hadd(r6);
                T v7 = vec_type::hadd(r7);
                T v8 = vec_type::hadd(r8);

                for(; k < k2; ++k){
                    v1 += input(i, (j + 0) + k) * kernel(m, k);
                    v2 += input(i, (j + 1) + k) * kernel(m, k);
                    v3 += input(i, (j + 2) + k) * kernel(m, k);
                    v4 += input(i, (j + 3) + k) * kernel(m, k);
                    v5 += input(i, (j + 4) + k) * kernel(m, k);
                    v6 += input(i, (j + 5) + k) * kernel(m, k);
                    v7 += input(i, (j + 6) + k) * kernel(m, k);
                    v8 += input(i, (j + 7) + k) * kernel(m, k);
                }

                conv(c_i, j+0) += v1;
                conv(c_i, j+1) += v2;
                conv(c_i, j+2) += v3;
                conv(c_i, j+3) += v4;
                conv(c_i, j+4) += v5;
                conv(c_i, j+5) += v6;
                conv(c_i, j+6) += v7;
                conv(c_i, j+7) += v8;
            }

            for(; j < c2; ++j){
                auto r1 = vec_type::template zero<T>();

                size_t k = 0;
                for(; k + vec_size - 1 < k2; k += vec_size){
                    auto a1 = input.template loadu<vec_type>(i * n2 + j + k);
                    auto b1 = kernel.template loadu<vec_type>(m * k2 + k);

                    auto t1 = vec_type::template mul<false>(a1, b1);
                    r1 = vec_type::add(r1, t1);
                }

                T value = vec_type::hadd(r1);

                for(; k < k2; ++k){
                    value += input(i, j + k) * kernel(m, k);
                }

                conv(c_i, j) += value;
            }
        }
    }

    // Secondary steps
    for(size_t i = c1; i < n1; ++i){
        auto M = std::min(n1 - i, R);

        for(size_t j = 0; j < c2;  ++j){
            for(size_t m = 0; m < M; ++m){
                const auto c_i = m + i - k1 + 1;
                const auto k_i = M - m - c1 + i;

                auto r1 = vec_type::template zero<T>();

                size_t k = 0;
                for(; k + vec_size - 1 < k2; k += vec_size){
                    auto a1 = input.template loadu<vec_type>(i * n2 + j + k);
                    auto b1 = kernel.template loadu<vec_type>(k_i * k2 + k);

                    auto t1 = vec_type::template mul<false>(a1, b1);
                    r1 = vec_type::add(r1, t1);
                }

                T value = vec_type::hadd(r1);

                for(; k < k2; ++k){
                    value += input(i, j + k) * kernel(k_i, k);
                }

                conv(c_i, j) += value;
            }
        }
    }
}

template<typename T>
constexpr bool prefer_sse(const size_t n){
    return
          std::is_same<T, float>::value
        ? (n % 4 < n % 8)
        : (n % 2 < n % 4);
}

} // end of namespace detail

/*!
 * \brief Standard implementation of a 2D 'valid' convolution C = I * K
 * \param input The input matrix
 * \param kernel The kernel matrix
 * \param conv The output matrix
 */
template <typename I, typename K, typename C>
void conv2_valid_flipped(const I& input, const K& kernel, C&& conv, size_t s1, size_t s2, size_t p1, size_t p2) {
    using T = value_t<I>;

    const auto n1 = etl::dim<0>(input);
    const auto n2 = etl::dim<1>(input);

    const auto k1 = etl::dim<0>(kernel);
    const auto k2 = etl::dim<1>(kernel);

    const auto c1 = etl::dim<0>(conv);
    const auto c2 = etl::dim<1>(conv);

    if(cpp_unlikely(p1 || p2)){
        const auto o1 = n1 + 2 * p1;
        const auto o2 = n2 + 2 * p2;

        etl::dyn_matrix<T> padded_matrix(o1, o2);
        padded_matrix = T(0);

        for (size_t i = 0; i < n1; ++i) {
            for(size_t j = 0; j < n2; ++j){
                padded_matrix[(i + p1) * o2 + p2 + j] = input(i, j);
            }
        }

        conv2_valid_flipped(padded_matrix, kernel, conv, s1, s2, 0, 0);

        return;
    }

    if(cpp_unlikely(s1 > 1 || s2 > 1)){
        etl::dyn_matrix<T> tmp_result(n1 - k1 + 1, n2 - k2 + 1);

        conv2_valid_flipped(input, kernel, tmp_result, 1, 1, 0, 0);

        // Strided copy of the large result into the small result
        for (std::size_t i = 0; i < c1; ++i) {
            for (std::size_t j = 0; j < c2; ++j) {
                conv(i, j) = tmp_result(i * s1, j * s2);
            }
        }

        return;
    }

    if(detail::prefer_sse<T>(k2)){
        detail::conv2_valid_flipped<sse_vec>(input, kernel, conv);
    } else {
        detail::conv2_valid_flipped<avx_vec>(input, kernel, conv);
    }
}

} //end of namespace vec
} //end of namespace impl
} //end of namespace etl
<|endoftext|>


<commit_before>//
//  catalog.cpp
//  MiniSQL
//
//  Created by scn3 on 15/10/30.
//  Copyright © 2015年 scn3. All rights reserved.
//

#include "catalog.h"
#include "../buffer/buffer.h"

bool Catalog::loadSchema(string tableName) {
    if (schema.tableName == tableName)
        return true;
    else clearSchema();

    string fileName = tableName + ".catalog";
    //    if (Buffer::exists(fileName))
    //        return false;
    //    if (access(fileName.c_str(), 0) == -1)
    //        return false;
    Block *block = Buffer::access(fileName, 0);
    const char *data = block->constData();
    if (data[0] == 0)
        return false;
    schema.tableName = tableName;
    string str = "";
    infoType curInfoType = ATTRNAME;
    AttrDetail *curAttr;
    int zeroCount = 0;  // 连续的0的个数，一个0表示字符串结束，两个0表示attr结束（包括其index），三个0表示table结束；

    int blockIndex = 0;
    int fromOffset;
    while (true) {
        if (blockIndex == 0)
            fromOffset = 1;
        else fromOffset = 0;
        Block *block = Buffer::access(fileName, blockIndex++);
        const char *data = block->constData();
        for (int i = fromOffset; i < block->size(); i++) {
            char ch = data[i];
            if (ch == 0) {
                if (++zeroCount == 1)
                    switch (curInfoType) {
                        case ATTRNAME: {
                            curAttr = new AttrDetail;
                            curAttr->attrName = str;
                            break;
                        }
                        case ATTRTYPE: {
                            if (str == "0")
                                curAttr->attrType = INTTYPE;
                            else if (str == "1")
                                curAttr->attrType = CHARTYPE;
                            else if (str == "2")
                                curAttr->attrType = FLOATTYPE;
                            else return false;
                            break;
                        }
                        case ATTRLEN: {
                            curAttr->length = str.at(0);
                            break;
                        }
                        case ATTRUNIQUE: {
                            curAttr->unique = str == "1";
                            break;
                        }
                        case ATTRPRIMARY: {
                            curAttr->primary = str == "1";
                            break;
                        }
                        case INDEXNAME: {
                            curAttr->indexList.push_back(str);
                        }
                        default:
                            break;
                    }
                if (zeroCount > 2) {
                    schema.attrDetailList.push_back(*curAttr);
                    return true;
                }
                str.clear();
            }
            else {
                if (zeroCount == 2) {   // 一个Attr结束，到一个新的attr，则第一个信息类型是Attr名
                    curInfoType = ATTRNAME;
                    schema.attrDetailList.push_back(*curAttr);
                }
                else if (zeroCount == 1) {
                    if (curInfoType < INDEXNAME)    // 如果当前信息不是索引名信息，则切换到下一信息类型
                        curInfoType++;
                }
                zeroCount = 0;
                str += ch;
            }
        }
    }

    return true;
}

bool Catalog::storeSchema() {
    if (schema.tableName.empty())
        return false;

    string fileName = schema.tableName + ".catalog";
    int blockIndex = 0;
    int offset = 1;
    Block *block = Buffer::access(fileName, 0);
    char *data = block->data();
    data[0] = 1;

    for (vector<AttrDetail>::iterator itr = schema.attrDetailList.begin(); itr != schema.attrDetailList.end(); itr++) {
        save(itr->attrName, blockIndex, offset);
        save('\0', blockIndex, offset);
        if (itr->attrType == INTTYPE)
            save('0', blockIndex, offset);
        else if (itr->attrType == CHARTYPE)
            save('1', blockIndex, offset);
        else save('2', blockIndex, offset);
        save('\0', blockIndex, offset);
        char ch = itr->length;
        string str = "";
        str += ch;
        save(str, blockIndex, offset);
        save('\0', blockIndex, offset);
        if (itr->unique)
            save('1', blockIndex, offset);
        else save('0', blockIndex, offset);
        save('\0', blockIndex, offset);
        if (itr->primary)
            save('1', blockIndex, offset);
        else save('0', blockIndex, offset);
        save('\0', blockIndex, offset);
        for (strings::iterator itr2 = itr->indexList.begin(); itr2 != itr->indexList.end(); itr2++) {
            save(*itr2, blockIndex, offset);
            save('\0', blockIndex, offset);
        }
        save('\0', blockIndex, offset);
    }
    save('\0', blockIndex, offset);
    return true;
}

void Catalog::save(string str, int &blockIndex, int &offset) {
    for (int i = 0; i < str.size(); i++)
        save(str.at(i), blockIndex, offset);
}

void Catalog::save(char ch, int &blockIndex, int &offset) {
    if (offset == defaultBlockSize) {
        offset = 0;
        blockIndex++;
    }
    Block *block = Buffer::access(schema.tableName + ".catalog", blockIndex);
    char *data = block->data();
    data[offset++] = ch;
}

void Catalog::save2(string str, int &blockIndex, int &offset) {
    for (int i = 0; i < str.size(); i++)
        save2(str.at(i), blockIndex, offset);
}

void Catalog::save2(char ch, int &blockIndex, int &offset) {
    if (offset == defaultBlockSize) {
        offset = 0;
        blockIndex++;
    }
    Block *block = Buffer::access("index.cat", blockIndex);
    char *data = block->data();
    data[offset++] = ch;
}

string Catalog::loadStr(int &blockIndex, int &offset) {
    Block *block = Buffer::access("index.cat", blockIndex);
    char *data = block->data();
    string str = "";
    for (; data[offset] != '\0'; ) {
        str += data[offset++];
        if (offset == defaultBlockSize) {
            offset = 0;
            blockIndex++;
            block = Buffer::access("index.cat", offset);
            data = block->data();
        }
    }
    offset++;
    if (offset == defaultBlockSize) {
        blockIndex++;
        offset = 0;
    }
    return str;
}

void Catalog::clearSchema() {
    schema.tableName.clear();
    for (vector<AttrDetail>::iterator itr = schema.attrDetailList.begin(); itr != schema.attrDetailList.end(); itr++) {
        vector<string> ().swap(itr->indexList);
    }
    vector<AttrDetail> ().swap(schema.attrDetailList);
}

bool Catalog::checkTableExist(string tableName) {
    if (schema.tableName == tableName)
        return true;
    return loadSchema(tableName);
}

int Catalog::checkAttributeExist(string tableName, string attributeName) {
    if (!loadSchema(tableName))
        return -1;
    for (vector<AttrDetail>::iterator itr = schema.attrDetailList.begin(); itr != schema.attrDetailList.end(); itr++) {
        if (itr->attrName == attributeName)
            return itr - schema.attrDetailList.begin();
    }
    return -1;
}

bool Catalog::checkIndexExist(string indexName) {
    Block *block = Buffer::access("index.cat", 0);
    char *data = block->data();
    int blockIndex = data[0] * 256 + data[1];
    int offset = data[2] * 256 + data[3];
    if (offset == 0)
        offset = 4;
    int curBlockIndex = 0;
    int curOffset = 4;
    while (true) {
        if (curBlockIndex > blockIndex)
            return false;
        else if (curBlockIndex == blockIndex && curOffset > offset)
            return false;
        bool valid = data[curOffset++] == 1;
        if (curOffset == defaultBlockSize) {
            blockIndex++;
            curOffset = 0;
        }
        string iName = loadStr(curBlockIndex, curOffset);
        string tName = loadStr(curBlockIndex, curOffset);
        if (iName == indexName && valid)
            return true;
    }
    return false;
}

bool Catalog::checkIndexExist(string tableName, string indexName) {
    if (!loadSchema(tableName))
        return false;
    for (vector<AttrDetail>::iterator aitr = schema.attrDetailList.begin(); aitr != schema.attrDetailList.end(); aitr++) {
        vector<string> curIndexList = aitr->indexList;
        for (vector<string>::iterator sitr = curIndexList.begin(); sitr != curIndexList.end(); sitr++) {
            if (*sitr == indexName)
                return true;
        }
    }
    return false;
}

bool Catalog::getIndexList(string tableName, string attributeName, Strings indexList) {
    indexList.clear();
    clearSchema();
    if (!loadSchema(tableName))
        return false;
    for (vector<AttrDetail>::iterator aitr = schema.attrDetailList.begin(); aitr != schema.attrDetailList.end(); aitr++)
        if (aitr->attrName == attributeName) {
            indexList = aitr->indexList;
            return true;
        }
    return false;
}

bool Catalog::createTable(string tableName, vector<AttributeDetail> &attributeList) {
    clearSchema();
    if (checkTableExist(tableName))
        return false;
    schema.tableName = tableName;
    for (vector<AttributeDetail>::iterator itr = attributeList.begin(); itr != attributeList.end(); itr++) {
        AttrDetail attrDetail;
        attrDetail.attrName = itr->name;
        attrDetail.attrType = itr->type;
        if (itr->type == INTTYPE || itr->type == FLOATTYPE)
            attrDetail.length = 4;
        else attrDetail.length = itr->length;
        attrDetail.unique = itr->unique;
        attrDetail.primary = itr->primary;
        schema.attrDetailList.push_back(attrDetail);
    }
    storeSchema();
    return true;
}

bool Catalog::createIndex(string tableName, string attributeName, string indexName) {
    if (!loadSchema(tableName))
        return false;
    if (checkAttributeExist(tableName, attributeName) == -1)
        return false;
    if (checkIndexExist(tableName, indexName))
        return false;
    for (vector<AttrDetail>::iterator itr = schema.attrDetailList.begin(); itr != schema.attrDetailList.end(); itr++)
        if (itr->attrName == attributeName)
            itr->indexList.push_back(indexName);
    storeSchema();

    Block *block = Buffer::access("index.cat", 0);
    char *data = block->data();
    int blockIndex = data[0] * 256 + data[1];
    int offset = data[2] * 256 + data[3];
    if (offset == 0)
        offset = 4;
    block = Buffer::access("index.cat", blockIndex);
    data = block->data();
    save2('\1', blockIndex, offset);
    save2(indexName, blockIndex, offset);
    save2('\0', blockIndex, offset);
    save2(tableName, blockIndex, offset);
    save2('\0', blockIndex, offset);
    data[0] = blockIndex / 256;
    data[1] = blockIndex % 256;
    data[2] = offset / 256;
    data[3] = offset % 256;

    return true;
}

bool Catalog::dropTable(string tableName) {
    if (!checkTableExist(tableName))
        return false;
    Block *block = Buffer::access(tableName + ".catalog", 0);
    char *data = block->data();
    data[0] = 0;
    tableName = "";
    clearSchema();
    return true;
}

bool Catalog::dropIndex(string tableName, string indexName) {
    if (!loadSchema(tableName))
        return false;
    if (!checkIndexExist(tableName, indexName))
        return false;
    bool find = false;
    for (vector<AttrDetail>::iterator aitr = schema.attrDetailList.begin(); aitr != schema.attrDetailList.end(); aitr++) {
        for (vector<string>::iterator sitr = aitr->indexList.begin(); sitr != aitr->indexList.end();) {
            if (*sitr == indexName) {
                aitr->indexList.erase(sitr++);
                find = true;
                break;
            }
            else sitr++;
            if (find)
                break;
        }
    }

    if (!find)
        return false;

    Block *block = Buffer::access("index.cat", 0);
    char *data = block->data();
    int blockIndex = data[0] * 256 + data[1];
    int offset = data[2] * 256 + data[3];
    if (offset == 0)
        offset = 4;
    int curBlockIndex = 0;
    int curOffset = 4;
    while (true) {
        if (curBlockIndex > blockIndex)
            break;
        else if (curBlockIndex == blockIndex && curOffset > offset)
            break;
        int tmpBlockIndex = curBlockIndex;
        int tmpOffset = curOffset;
        bool valid = data[curOffset++] == 1;
        if (curOffset == defaultBlockSize) {
            blockIndex++;
            curOffset = 0;
        }
        string iName = loadStr(curBlockIndex, curOffset);
        string tName = loadStr(curBlockIndex, curOffset);
        if (iName == indexName && valid) {
            block = Buffer::access("index.cat", tmpBlockIndex);
            data = block->data();
            data[tmpOffset] = 0;
        }
    }

    return storeSchema();
}

bool Catalog::dropIndex(string indexName) {
    Block *block = Buffer::access("index.cat", 0);
    char *data = block->data();
    int blockIndex = data[0] * 256 + data[1];
    int offset = data[2] * 256 + data[3];
    if (offset == 0)
        offset = 4;
    int curBlockIndex = 0;
    int curOffset = 4;
    while (true) {
        if (curBlockIndex > blockIndex)
            break;
        else if (curBlockIndex == blockIndex && curOffset > offset)
            break;
        bool valid = data[curOffset++] == 1;
        if (curOffset == defaultBlockSize) {
            blockIndex++;
            curOffset = 0;
        }
        string iName = loadStr(curBlockIndex, curOffset);
        string tName = loadStr(curBlockIndex, curOffset);
        if (iName == indexName && valid)
            dropIndex(tName, indexName);
    }
    return storeSchema();
}

int Catalog::getAttributeSize(string tableName, string attributeName) {
    loadSchema(tableName);
    for (vector<AttrDetail>::iterator itr = schema.attrDetailList.begin(); itr != schema.attrDetailList.end(); itr++)
        if (itr->attrName == attributeName)
            return itr->length;
    return 4;
}

int Catalog::getAttributesTotalSize(string tableName) {
    int sum = 0;
    loadSchema(tableName);
    for (vector<AttrDetail>::iterator itr = schema.attrDetailList.begin(); itr != schema.attrDetailList.end(); itr++)
        sum += itr->length;
    return sum;
}

vector<attributeType> Catalog::getAttributeType(string tableName, string queryName) {
    vector<attributeType> res;
    loadSchema(tableName);
    for (vector<AttrDetail>::iterator itr = schema.attrDetailList.begin(); itr != schema.attrDetailList.end(); itr++) {
        if (queryName == "") {
            res.push_back(itr->attrType);
        } else if (itr->attrName == queryName) {
            res.push_back(itr->attrType);
        }
    }
    return res;
}
vector<int> Catalog::getPrimaryOrUniquePosition(string tableName) {
    vector<int> res;
    loadSchema(tableName);
    for (vector<AttrDetail>::iterator itr = schema.attrDetailList.begin(); itr != schema.attrDetailList.end(); itr++) {
      if (itr->unique || itr->primary) {
          res.push_back(itr - schema.attrDetailList.begin());
      }
    }
    return res;
}
<commit_msg>fix the bug about dropIndex in class Catalog<commit_after>//
//  catalog.cpp
//  MiniSQL
//
//  Created by scn3 on 15/10/30.
//  Copyright © 2015年 scn3. All rights reserved.
//

#include "catalog.h"
#include "../buffer/buffer.h"

bool Catalog::loadSchema(string tableName) {
    if (schema.tableName == tableName)
        return true;
    else clearSchema();

    string fileName = tableName + ".catalog";
    //    if (Buffer::exists(fileName))
    //        return false;
    //    if (access(fileName.c_str(), 0) == -1)
    //        return false;
    Block *block = Buffer::access(fileName, 0);
    const char *data = block->constData();
    if (data[0] == 0)
        return false;
    schema.tableName = tableName;
    string str = "";
    infoType curInfoType = ATTRNAME;
    AttrDetail *curAttr;
    int zeroCount = 0;  // 连续的0的个数，一个0表示字符串结束，两个0表示attr结束（包括其index），三个0表示table结束；

    int blockIndex = 0;
    int fromOffset;
    while (true) {
        if (blockIndex == 0)
            fromOffset = 1;
        else fromOffset = 0;
        Block *block = Buffer::access(fileName, blockIndex++);
        const char *data = block->constData();
        for (int i = fromOffset; i < block->size(); i++) {
            char ch = data[i];
            if (ch == 0) {
                if (++zeroCount == 1)
                    switch (curInfoType) {
                        case ATTRNAME: {
                            curAttr = new AttrDetail;
                            curAttr->attrName = str;
                            break;
                        }
                        case ATTRTYPE: {
                            if (str == "0")
                                curAttr->attrType = INTTYPE;
                            else if (str == "1")
                                curAttr->attrType = CHARTYPE;
                            else if (str == "2")
                                curAttr->attrType = FLOATTYPE;
                            else return false;
                            break;
                        }
                        case ATTRLEN: {
                            curAttr->length = str.at(0);
                            break;
                        }
                        case ATTRUNIQUE: {
                            curAttr->unique = str == "1";
                            break;
                        }
                        case ATTRPRIMARY: {
                            curAttr->primary = str == "1";
                            break;
                        }
                        case INDEXNAME: {
                            curAttr->indexList.push_back(str);
                        }
                        default:
                            break;
                    }
                if (zeroCount > 2) {
                    schema.attrDetailList.push_back(*curAttr);
                    return true;
                }
                str.clear();
            }
            else {
                if (zeroCount == 2) {   // 一个Attr结束，到一个新的attr，则第一个信息类型是Attr名
                    curInfoType = ATTRNAME;
                    schema.attrDetailList.push_back(*curAttr);
                }
                else if (zeroCount == 1) {
                    if (curInfoType < INDEXNAME)    // 如果当前信息不是索引名信息，则切换到下一信息类型
                        curInfoType++;
                }
                zeroCount = 0;
                str += ch;
            }
        }
    }

    return true;
}

bool Catalog::storeSchema() {
    if (schema.tableName.empty())
        return false;

    string fileName = schema.tableName + ".catalog";
    int blockIndex = 0;
    int offset = 1;
    Block *block = Buffer::access(fileName, 0);
    char *data = block->data();
    data[0] = 1;

    for (vector<AttrDetail>::iterator itr = schema.attrDetailList.begin(); itr != schema.attrDetailList.end(); itr++) {
        save(itr->attrName, blockIndex, offset);
        save('\0', blockIndex, offset);
        if (itr->attrType == INTTYPE)
            save('0', blockIndex, offset);
        else if (itr->attrType == CHARTYPE)
            save('1', blockIndex, offset);
        else save('2', blockIndex, offset);
        save('\0', blockIndex, offset);
        char ch = itr->length;
        string str = "";
        str += ch;
        save(str, blockIndex, offset);
        save('\0', blockIndex, offset);
        if (itr->unique)
            save('1', blockIndex, offset);
        else save('0', blockIndex, offset);
        save('\0', blockIndex, offset);
        if (itr->primary)
            save('1', blockIndex, offset);
        else save('0', blockIndex, offset);
        save('\0', blockIndex, offset);
        for (strings::iterator itr2 = itr->indexList.begin(); itr2 != itr->indexList.end(); itr2++) {
            save(*itr2, blockIndex, offset);
            save('\0', blockIndex, offset);
        }
        save('\0', blockIndex, offset);
    }
    save('\0', blockIndex, offset);
    return true;
}

void Catalog::save(string str, int &blockIndex, int &offset) {
    for (int i = 0; i < str.size(); i++)
        save(str.at(i), blockIndex, offset);
}

void Catalog::save(char ch, int &blockIndex, int &offset) {
    if (offset == defaultBlockSize) {
        offset = 0;
        blockIndex++;
    }
    Block *block = Buffer::access(schema.tableName + ".catalog", blockIndex);
    char *data = block->data();
    data[offset++] = ch;
}

void Catalog::save2(string str, int &blockIndex, int &offset) {
    for (int i = 0; i < str.size(); i++)
        save2(str.at(i), blockIndex, offset);
}

void Catalog::save2(char ch, int &blockIndex, int &offset) {
    if (offset == defaultBlockSize) {
        offset = 0;
        blockIndex++;
    }
    Block *block = Buffer::access("index.cat", blockIndex);
    char *data = block->data();
    data[offset++] = ch;
}

string Catalog::loadStr(int &blockIndex, int &offset) {
    Block *block = Buffer::access("index.cat", blockIndex);
    char *data = block->data();
    string str = "";
    for (; data[offset] != '\0'; ) {
        str += data[offset++];
        if (offset == defaultBlockSize) {
            offset = 0;
            blockIndex++;
            block = Buffer::access("index.cat", offset);
            data = block->data();
        }
    }
    offset++;
    if (offset == defaultBlockSize) {
        blockIndex++;
        offset = 0;
    }
    return str;
}

void Catalog::clearSchema() {
    schema.tableName.clear();
    for (vector<AttrDetail>::iterator itr = schema.attrDetailList.begin(); itr != schema.attrDetailList.end(); itr++) {
        vector<string> ().swap(itr->indexList);
    }
    vector<AttrDetail> ().swap(schema.attrDetailList);
}

bool Catalog::checkTableExist(string tableName) {
    if (schema.tableName == tableName)
        return true;
    return loadSchema(tableName);
}

int Catalog::checkAttributeExist(string tableName, string attributeName) {
    if (!loadSchema(tableName))
        return -1;
    for (vector<AttrDetail>::iterator itr = schema.attrDetailList.begin(); itr != schema.attrDetailList.end(); itr++) {
        if (itr->attrName == attributeName)
            return itr - schema.attrDetailList.begin();
    }
    return -1;
}

bool Catalog::checkIndexExist(string indexName) {
    Block *block = Buffer::access("index.cat", 0);
    char *data = block->data();
    int blockIndex = data[0] * 256 + data[1];
    int offset = data[2] * 256 + data[3];
    if (offset == 0)
        offset = 4;
    int curBlockIndex = 0;
    int curOffset = 4;
    while (true) {
        if (curBlockIndex > blockIndex)
            return false;
        else if (curBlockIndex == blockIndex && curOffset > offset)
            return false;
        bool valid = data[curOffset++] == 1;
        if (curOffset == defaultBlockSize) {
            blockIndex++;
            curOffset = 0;
        }
        string iName = loadStr(curBlockIndex, curOffset);
        string tName = loadStr(curBlockIndex, curOffset);
        if (iName == indexName && valid)
            return true;
    }
    return false;
}

bool Catalog::checkIndexExist(string tableName, string indexName) {
    if (!loadSchema(tableName))
        return false;
    for (vector<AttrDetail>::iterator aitr = schema.attrDetailList.begin(); aitr != schema.attrDetailList.end(); aitr++) {
        vector<string> curIndexList = aitr->indexList;
        for (vector<string>::iterator sitr = curIndexList.begin(); sitr != curIndexList.end(); sitr++) {
            if (*sitr == indexName)
                return true;
        }
    }
    return false;
}

bool Catalog::getIndexList(string tableName, string attributeName, Strings indexList) {
    indexList.clear();
    clearSchema();
    if (!loadSchema(tableName))
        return false;
    for (vector<AttrDetail>::iterator aitr = schema.attrDetailList.begin(); aitr != schema.attrDetailList.end(); aitr++)
        if (aitr->attrName == attributeName) {
            indexList = aitr->indexList;
            return true;
        }
    return false;
}

bool Catalog::createTable(string tableName, vector<AttributeDetail> &attributeList) {
    clearSchema();
    if (checkTableExist(tableName))
        return false;
    schema.tableName = tableName;
    for (vector<AttributeDetail>::iterator itr = attributeList.begin(); itr != attributeList.end(); itr++) {
        AttrDetail attrDetail;
        attrDetail.attrName = itr->name;
        attrDetail.attrType = itr->type;
        if (itr->type == INTTYPE || itr->type == FLOATTYPE)
            attrDetail.length = 4;
        else attrDetail.length = itr->length;
        attrDetail.unique = itr->unique;
        attrDetail.primary = itr->primary;
        schema.attrDetailList.push_back(attrDetail);
    }
    storeSchema();
    return true;
}

bool Catalog::createIndex(string tableName, string attributeName, string indexName) {
    if (!loadSchema(tableName))
        return false;
    if (checkAttributeExist(tableName, attributeName) == -1)
        return false;
    if (checkIndexExist(tableName, indexName))
        return false;
    for (vector<AttrDetail>::iterator itr = schema.attrDetailList.begin(); itr != schema.attrDetailList.end(); itr++)
        if (itr->attrName == attributeName)
            itr->indexList.push_back(indexName);
    storeSchema();

    Block *block = Buffer::access("index.cat", 0);
    char *data = block->data();
    int blockIndex = data[0] * 256 + data[1];
    int offset = data[2] * 256 + data[3];
    if (offset == 0)
        offset = 4;
    block = Buffer::access("index.cat", blockIndex);
    data = block->data();
    save2('\1', blockIndex, offset);
    save2(indexName, blockIndex, offset);
    save2('\0', blockIndex, offset);
    save2(tableName, blockIndex, offset);
    save2('\0', blockIndex, offset);
    data[0] = blockIndex / 256;
    data[1] = blockIndex % 256;
    data[2] = offset / 256;
    data[3] = offset % 256;

    return true;
}

bool Catalog::dropTable(string tableName) {
    if (!checkTableExist(tableName))
        return false;
    Block *block = Buffer::access(tableName + ".catalog", 0);
    char *data = block->data();
    data[0] = 0;
    tableName = "";
    clearSchema();
    return true;
}

bool Catalog::dropIndex(string tableName, string indexName) {
    if (!loadSchema(tableName))
        return false;
    if (!checkIndexExist(tableName, indexName))
        return false;
    bool find = false;
    for (vector<AttrDetail>::iterator aitr = schema.attrDetailList.begin(); aitr != schema.attrDetailList.end(); aitr++) {
        for (vector<string>::iterator sitr = aitr->indexList.begin(); sitr != aitr->indexList.end();) {
            if (*sitr == indexName) {
                aitr->indexList.erase(sitr++);
                find = true;
                break;
            }
            else sitr++;
            if (find)
                break;
        }
    }

    if (!find)
        return false;

    Block *block = Buffer::access("index.cat", 0);
    char *data = block->data();
    int blockIndex = data[0] * 256 + data[1];
    int offset = data[2] * 256 + data[3];
    if (offset == 0)
        offset = 4;
    int curBlockIndex = 0;
    int curOffset = 4;
    while (true) {
        if (curBlockIndex > blockIndex)
            break;
        else if (curBlockIndex == blockIndex && curOffset > offset)
            break;
        int tmpBlockIndex = curBlockIndex;
        int tmpOffset = curOffset;
        bool valid = data[curOffset++] == 1;
        if (curOffset == defaultBlockSize) {
            blockIndex++;
            curOffset = 0;
        }
        string iName = loadStr(curBlockIndex, curOffset);
        string tName = loadStr(curBlockIndex, curOffset);
        if (iName == indexName && valid) {
            block = Buffer::access("index.cat", tmpBlockIndex);
            data = block->data();
            data[tmpOffset] = 0;
        }
    }

    return storeSchema();
}

bool Catalog::dropIndex(string indexName) {
    Block *block = Buffer::access("index.cat", 0);
    char *data = block->data();
    int blockIndex = data[0] * 256 + data[1];
    int offset = data[2] * 256 + data[3];
    if (offset == 0)
        offset = 4;
    int curBlockIndex = 0;
    int curOffset = 4;
    while (true) {
        if (curBlockIndex > blockIndex)
            break;
        else if (curBlockIndex == blockIndex && curOffset > offset)
            break;
        bool valid = data[curOffset++] == 1;
        if (curOffset == defaultBlockSize) {
            blockIndex++;
            curOffset = 0;
        }
        string iName = loadStr(curBlockIndex, curOffset);
        string tName = loadStr(curBlockIndex, curOffset);
        if (iName == indexName && valid)
            return dropIndex(tName, indexName);
    }
    return false;
}

int Catalog::getAttributeSize(string tableName, string attributeName) {
    loadSchema(tableName);
    for (vector<AttrDetail>::iterator itr = schema.attrDetailList.begin(); itr != schema.attrDetailList.end(); itr++)
        if (itr->attrName == attributeName)
            return itr->length;
    return 4;
}

int Catalog::getAttributesTotalSize(string tableName) {
    int sum = 0;
    loadSchema(tableName);
    for (vector<AttrDetail>::iterator itr = schema.attrDetailList.begin(); itr != schema.attrDetailList.end(); itr++)
        sum += itr->length;
    return sum;
}

vector<attributeType> Catalog::getAttributeType(string tableName, string queryName) {
    vector<attributeType> res;
    loadSchema(tableName);
    for (vector<AttrDetail>::iterator itr = schema.attrDetailList.begin(); itr != schema.attrDetailList.end(); itr++) {
        if (queryName == "") {
            res.push_back(itr->attrType);
        } else if (itr->attrName == queryName) {
            res.push_back(itr->attrType);
        }
    }
    return res;
}
vector<int> Catalog::getPrimaryOrUniquePosition(string tableName) {
    vector<int> res;
    loadSchema(tableName);
    for (vector<AttrDetail>::iterator itr = schema.attrDetailList.begin(); itr != schema.attrDetailList.end(); itr++) {
      if (itr->unique || itr->primary) {
          res.push_back(itr - schema.attrDetailList.begin());
      }
    }
    return res;
}
<|endoftext|>


<commit_before>/*=========================================================================

Program:   Visualization Toolkit
Module:    TestCubeAxesWithGridlines.cxx

Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
All rights reserved.
See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE.  See the above copyright notice for more information.

=========================================================================*/
// .SECTION Thanks
// This test was written by Philippe Pebay, Kitware SAS 2011

#include "vtkActor.h"
#include "vtkAxisActor.h"
#include "vtkCamera.h"
#include "vtkCoordinate.h"
#include "vtkCubeAxesActor.h"
#include "vtkPlaneSource.h"
#include "vtkPolyDataMapper.h"
#include "vtkProperty.h"
#include "vtkProperty2D.h"
#include "vtkRegressionTestImage.h"
#include "vtkRenderer.h"
#include "vtkRenderWindow.h"
#include "vtkRenderWindowInteractor.h"
#include "vtkSmartPointer.h"
#include "vtkStructuredGrid.h"
#include "vtkTextProperty.h"

#include "vtkCubeAxesActor.h"

int TestCubeAxes2DMode( int argc, char * argv [] )
{
  // Create plane source
  vtkSmartPointer<vtkPlaneSource> plane
    = vtkSmartPointer<vtkPlaneSource>::New();
  plane->SetXResolution( 10 );
  plane->SetYResolution( 10 );

  // Create plane mapper
  vtkSmartPointer<vtkPolyDataMapper> planeMapper
    = vtkSmartPointer<vtkPolyDataMapper>::New();
  planeMapper->SetInputConnection( plane->GetOutputPort() );
  planeMapper->SetResolveCoincidentTopologyPolygonOffsetParameters( 0, 1 );
  planeMapper->SetResolveCoincidentTopologyToPolygonOffset();

  // Create plane actor
  vtkSmartPointer<vtkActor> planeActor
    = vtkSmartPointer<vtkActor>::New();
  planeActor->SetMapper( planeMapper );
  planeActor->GetProperty()->SetColor( .5, .5, .5 );

  // Create edge mapper and actor
  vtkSmartPointer<vtkPolyDataMapper> edgeMapper
    = vtkSmartPointer<vtkPolyDataMapper>::New();
  edgeMapper->SetInputConnection( plane->GetOutputPort() );
  edgeMapper->SetResolveCoincidentTopologyPolygonOffsetParameters( 1, 1 );
  edgeMapper->SetResolveCoincidentTopologyToPolygonOffset();

  // Create edge actor
  vtkSmartPointer<vtkActor> edgeActor
    = vtkSmartPointer<vtkActor>::New();
  edgeActor->SetMapper( edgeMapper );
  edgeActor->GetProperty()->SetColor( .0, .0, .0 );
  edgeActor->GetProperty()->SetRepresentationToWireframe();

  // Create renderer
  vtkSmartPointer<vtkRenderer> renderer
    = vtkSmartPointer<vtkRenderer>::New();
  renderer->SetBackground( 1., 1., 1. );
  renderer->GetActiveCamera()->SetFocalPoint( .0, .0, .0 );
  renderer->GetActiveCamera()->SetPosition( .0, .0, 2.5 );

  // Create cube axes actor
  vtkSmartPointer<vtkCubeAxesActor> axes = vtkSmartPointer<vtkCubeAxesActor>::New();
  axes->SetCamera ( renderer->GetActiveCamera() );
  axes->SetBounds( -.5, .5, -.5, .5, 0., 0. );
  axes->SetCornerOffset( .0 );
  axes->SetXAxisVisibility( 1 );
  axes->SetYAxisVisibility( 1 );
  axes->SetZAxisVisibility( 0 );
  axes->SetUse2DMode( 1 );

  // Desactivate LOD for all axes
  axes->SetEnableDistanceLOD( 0 );
  axes->SetEnableViewAngleLOD( 0 );

  // Use red color for X axis
  axes->GetXAxesLinesProperty()->SetColor( 1., 0., 0.);
  axes->GetTitleTextProperty( 0 )->SetColor( 1., 0., 0.);
  axes->GetLabelTextProperty( 0 )->SetColor( 1., 0., 0.);

  // Use green color for Y axis
  axes->GetYAxesLinesProperty()->SetColor( 0., 1., 0. );
  axes->GetTitleTextProperty( 1 )->SetColor( 0., 1., 0. );
  axes->GetLabelTextProperty( 1 )->SetColor( 0., 1., 0. );

  // Add all actors to renderer
  renderer->AddActor( planeActor );
  renderer->AddActor( edgeActor );
  renderer->AddActor( axes );

  // Create render window and interactor
  vtkSmartPointer<vtkRenderWindow> renderWindow
    = vtkSmartPointer<vtkRenderWindow>::New();
  renderWindow->AddRenderer( renderer );
  renderWindow->SetSize( 800, 600 );
  renderWindow->SetMultiSamples( 0 )
  vtkSmartPointer<vtkRenderWindowInteractor> interactor
    = vtkSmartPointer<vtkRenderWindowInteractor>::New();
  interactor->SetRenderWindow( renderWindow );

  // Render and possibly interact
  renderWindow->Render();
  int retVal = vtkRegressionTestImage( renderWindow );
  if ( retVal == vtkRegressionTester::DO_INTERACTOR)
    {
    interactor->Start();
    }

  return !retVal;
}
<commit_msg>Typo (missing ;)<commit_after>/*=========================================================================

Program:   Visualization Toolkit
Module:    TestCubeAxesWithGridlines.cxx

Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
All rights reserved.
See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE.  See the above copyright notice for more information.

=========================================================================*/
// .SECTION Thanks
// This test was written by Philippe Pebay, Kitware SAS 2011

#include "vtkActor.h"
#include "vtkAxisActor.h"
#include "vtkCamera.h"
#include "vtkCoordinate.h"
#include "vtkCubeAxesActor.h"
#include "vtkPlaneSource.h"
#include "vtkPolyDataMapper.h"
#include "vtkProperty.h"
#include "vtkProperty2D.h"
#include "vtkRegressionTestImage.h"
#include "vtkRenderer.h"
#include "vtkRenderWindow.h"
#include "vtkRenderWindowInteractor.h"
#include "vtkSmartPointer.h"
#include "vtkStructuredGrid.h"
#include "vtkTextProperty.h"

#include "vtkCubeAxesActor.h"

int TestCubeAxes2DMode( int argc, char * argv [] )
{
  // Create plane source
  vtkSmartPointer<vtkPlaneSource> plane
    = vtkSmartPointer<vtkPlaneSource>::New();
  plane->SetXResolution( 10 );
  plane->SetYResolution( 10 );

  // Create plane mapper
  vtkSmartPointer<vtkPolyDataMapper> planeMapper
    = vtkSmartPointer<vtkPolyDataMapper>::New();
  planeMapper->SetInputConnection( plane->GetOutputPort() );
  planeMapper->SetResolveCoincidentTopologyPolygonOffsetParameters( 0, 1 );
  planeMapper->SetResolveCoincidentTopologyToPolygonOffset();

  // Create plane actor
  vtkSmartPointer<vtkActor> planeActor
    = vtkSmartPointer<vtkActor>::New();
  planeActor->SetMapper( planeMapper );
  planeActor->GetProperty()->SetColor( .5, .5, .5 );

  // Create edge mapper and actor
  vtkSmartPointer<vtkPolyDataMapper> edgeMapper
    = vtkSmartPointer<vtkPolyDataMapper>::New();
  edgeMapper->SetInputConnection( plane->GetOutputPort() );
  edgeMapper->SetResolveCoincidentTopologyPolygonOffsetParameters( 1, 1 );
  edgeMapper->SetResolveCoincidentTopologyToPolygonOffset();

  // Create edge actor
  vtkSmartPointer<vtkActor> edgeActor
    = vtkSmartPointer<vtkActor>::New();
  edgeActor->SetMapper( edgeMapper );
  edgeActor->GetProperty()->SetColor( .0, .0, .0 );
  edgeActor->GetProperty()->SetRepresentationToWireframe();

  // Create renderer
  vtkSmartPointer<vtkRenderer> renderer
    = vtkSmartPointer<vtkRenderer>::New();
  renderer->SetBackground( 1., 1., 1. );
  renderer->GetActiveCamera()->SetFocalPoint( .0, .0, .0 );
  renderer->GetActiveCamera()->SetPosition( .0, .0, 2.5 );

  // Create cube axes actor
  vtkSmartPointer<vtkCubeAxesActor> axes = vtkSmartPointer<vtkCubeAxesActor>::New();
  axes->SetCamera ( renderer->GetActiveCamera() );
  axes->SetBounds( -.5, .5, -.5, .5, 0., 0. );
  axes->SetCornerOffset( .0 );
  axes->SetXAxisVisibility( 1 );
  axes->SetYAxisVisibility( 1 );
  axes->SetZAxisVisibility( 0 );
  axes->SetUse2DMode( 1 );

  // Desactivate LOD for all axes
  axes->SetEnableDistanceLOD( 0 );
  axes->SetEnableViewAngleLOD( 0 );

  // Use red color for X axis
  axes->GetXAxesLinesProperty()->SetColor( 1., 0., 0.);
  axes->GetTitleTextProperty( 0 )->SetColor( 1., 0., 0.);
  axes->GetLabelTextProperty( 0 )->SetColor( 1., 0., 0.);

  // Use green color for Y axis
  axes->GetYAxesLinesProperty()->SetColor( 0., 1., 0. );
  axes->GetTitleTextProperty( 1 )->SetColor( 0., 1., 0. );
  axes->GetLabelTextProperty( 1 )->SetColor( 0., 1., 0. );

  // Add all actors to renderer
  renderer->AddActor( planeActor );
  renderer->AddActor( edgeActor );
  renderer->AddActor( axes );

  // Create render window and interactor
  vtkSmartPointer<vtkRenderWindow> renderWindow
    = vtkSmartPointer<vtkRenderWindow>::New();
  renderWindow->AddRenderer( renderer );
  renderWindow->SetSize( 800, 600 );
  renderWindow->SetMultiSamples( 0 );
  vtkSmartPointer<vtkRenderWindowInteractor> interactor
    = vtkSmartPointer<vtkRenderWindowInteractor>::New();
  interactor->SetRenderWindow( renderWindow );

  // Render and possibly interact
  renderWindow->Render();
  int retVal = vtkRegressionTestImage( renderWindow );
  if ( retVal == vtkRegressionTester::DO_INTERACTOR)
    {
    interactor->Start();
    }

  return !retVal;
}
<|endoftext|>


<commit_before>#pragma once

#include "detail/function_traits.hpp"
#include "detail/utils.hpp"
#include "detail/container_service.hpp"

#include <unordered_map>
#include <memory>
#include <type_traits>
#include <tuple>
#include <algorithm>
#include <vector>

namespace kgr {
enum test { brsb};
struct Container {
private:
	template<typename Condition, typename T = int> using enable_if = detail::enable_if_t<Condition::value, T>;
	template<typename Condition, typename T = int> using disable_if = detail::enable_if_t<!Condition::value, T>;
	template<typename T> using decay = typename std::decay<T>::type;
	template<typename T> using is_single = std::is_base_of<Single, decay<T>>;
	template<typename T> using is_container_service = std::is_same<T, ContainerService>;
	template<typename T> using is_base_of_container_service = std::is_base_of<detail::ContainerServiceBase, T>;
	template<typename T> using parent_types = typename decay<T>::ParentTypes;
	template<int S, typename T> using parent_element = typename std::tuple_element<S, parent_types<T>>::type;
	template<typename Tuple, int n> using tuple_seq_minus = typename detail::seq_gen<std::tuple_size<Tuple>::value - n>::type;
	template<typename T> using instance_ptr = std::unique_ptr<T, void(*)(void*)>;
	template<template<typename> class Map, typename T> using service_map_t = typename Map<T>::Service;

	template<typename T>
	static void deleter(void* i) {
		delete static_cast<T*>(i);
	}

	template<typename T, typename... Args, enable_if<std::is_constructible<T, Args...>> = 0>
	static instance_ptr<T> makeInstancePtr(Args&&... args) {
		return instance_ptr<T>{new T(std::forward<Args>(args)...), &Container::deleter<T>};
	}

	template<typename T, typename... Args, disable_if<std::is_constructible<T, Args...>> = 0>
	static instance_ptr<T> makeInstancePtr(Args&&... args) {
		return instance_ptr<T>{new T{std::forward<Args>(args)...}, &Container::deleter<T>};
	}

public:
	Container() = default;
	Container(const Container &) = delete;
	Container& operator =(const Container &) = delete;
	Container(Container&& other) = default;
	Container& operator=(Container&& other) = default;
	virtual ~Container() = default;

	template<typename T, enable_if<is_single<decay<T>>> = 0>
	void instance(T&& service) {
		save_instance(std::forward<T>(service));
	}

	template<typename T, typename... Args, enable_if<is_single<T>> = 0>
	void instance(Args&& ...args) {
		save_new_instance<T>(std::forward<Args>(args)...);
	}

	template<typename T, typename... Args>
	ServiceType<T> service(Args&& ...args) {
		return get_service<T>(std::forward<Args>(args)...).forward();
	}

	template<template<typename> class Map, typename U, typename ...Args>
	detail::function_result_t<decay<U>> invoke(U&& function, Args&&... args) {
		return invoke_helper<Map>(tuple_seq_minus<detail::function_arguments_t<decay<U>>, sizeof...(Args)>{}, std::forward<U>(function), std::forward<Args>(args)...);
	}

	inline void clear() {
		_services.clear();
	}

private:
	template<typename U, typename ...Args>
	detail::function_result_t<decay<U>> invoke(U&& function, Args&&... args) {
		return invoke_helper(tuple_seq_minus<detail::function_arguments_t<decay<U>>, sizeof...(Args)>{}, std::forward<U>(function), std::forward<Args>(args)...);
	}

	template<typename T, typename... Args, enable_if<is_single<T>> = 0, disable_if<std::is_abstract<T>> = 0>
	void save_new_instance(Args&&... args) {
		save_instance(make_service_instance<T>(std::forward<Args>(args)...));
	}

	template<typename T, typename... Args, enable_if<is_single<T>> = 0, enable_if<std::is_abstract<T>> = 0>
	void save_new_instance(Args&&... args) {
		throw std::out_of_range{"No instance found for the requested abstract service"};
	}

	// save instance functions
	template<typename T, enable_if<detail::has_overrides<decay<T>>> = 0>
	void save_instance(T&& service) {
		save_instance(std::forward<T>(service), detail::tuple_seq<parent_types<T>>{});
	}

	template<typename T, disable_if<detail::has_overrides<decay<T>>> = 0>
	void save_instance(T&& service) {
		using U = decay<T>;
		save_instance_helper<U>(makeInstancePtr<U>(std::move(service)));
	}

	template<typename T, int... S>
	void save_instance(T&& service, detail::seq<S...>) {
		using U = decay<T>;
		save_instance_helper<U, parent_element<S, U>...>(makeInstancePtr<U>(std::move(service)));
	}

	template<typename T>
	void save_instance_helper(instance_ptr<T> service) {
		_services[detail::type_id<T>].emplace_back(std::move(service));
	}

	template<typename T, typename Override, typename... Others>
	void save_instance_helper(instance_ptr<T> service) {
		using ServiceOverride = detail::ServiceOverride<T, Override>;

		_services[detail::type_id<Override>].emplace_back(static_cast<instance_ptr<Override>>(makeInstancePtr<ServiceOverride>(*service)));
		save_instance_helper<T, Others...>(std::move(service));
	}

	// get service functions
	template<typename T, typename... Args, disable_if<is_single<T>> = 0, disable_if<is_base_of_container_service<T>> = 0>
	T get_service(Args&&... args) {
		return make_service_instance<T>(std::forward<Args>(args)...);
	}

	template<typename T, enable_if<is_container_service<T>> = 0>
	T get_service() {
		return T{*this};
	}

	template<typename T, enable_if<is_base_of_container_service<T>> = 0, disable_if<is_container_service<T>> = 0>
	T get_service() {
		return T{*dynamic_cast<typename T::Type*>(this)};
	}

	template<typename T, enable_if<is_single<T>> = 0, disable_if<is_base_of_container_service<T>> = 0>
	T& get_service() {
		auto&& list = _services[detail::type_id<T>];

		if (!list.size()) {
			save_new_instance<T>();
		}

		return *static_cast<T*>(list.back().get());
	}

	// make instance
	template<typename T, typename... Args>
	T make_service_instance(Args&&... args) {
		T service = invoke(&T::construct, std::forward<Args>(args)...);
		invoke_service(service);
		return service;
	}

	// invoke
	template<typename U, typename ...Args, int... S>
	detail::function_result_t<decay<U>> invoke_helper(detail::seq<S...>, U&& function, Args&&... args) {
		return std::forward<U>(function)(get_service<decay<detail::function_argument_t<S, decay<U>>>>()..., std::forward<Args>(args)...);
	}

	template<template<typename> class Map, typename U, typename ...Args, int... S>
	detail::function_result_t<decay<U>> invoke_helper(detail::seq<S...>, U&& function, Args&&... args) {
		return std::forward<U>(function)(service<service_map_t<Map, detail::function_argument_t<S, decay<U>>>>()..., std::forward<Args>(args)...);
	}

	template<typename T, int... S, enable_if<detail::has_invoke<decay<T>>> = 0>
	void invoke_service(T&& service) {
		using U = decay<T>;
		invoke_service_helper<typename U::invoke::Next>(std::forward<T>(service), U::invoke::method);
	}

	template<typename Method, typename T, typename F, enable_if<detail::has_next<Method>> = 0>
	void invoke_service_helper(T&& service, F&& function) {
		do_invoke_service(detail::tuple_seq<detail::function_arguments_t<decay<F>>>{}, std::forward<T>(service), std::forward<F>(function));
		invoke_service_helper<typename Method::Next>(std::forward<T>(service), Method::method);
	}

	template<typename Method, typename T, typename F, disable_if<detail::has_next<Method>> = 0>
	void invoke_service_helper(T&& service, F&& function) {
		do_invoke_service(detail::tuple_seq<detail::function_arguments_t<decay<F>>>{}, std::forward<T>(service), std::forward<F>(function));
	}

	template<typename T, typename F, int... S>
	void do_invoke_service(detail::seq<S...>, T&& service, F&& function) {
		invoke([&service, &function](detail::function_argument_t<S, decay<F>>... args){
			(std::forward<T>(service).*std::forward<F>(function))(std::forward<detail::function_argument_t<S, decay<F>>>(args)...);
		});
	}

	template<typename T, disable_if<detail::has_invoke<decay<T>>> = 0>
	void invoke_service(T&&) {}

	std::unordered_map<detail::type_id_t, std::vector<instance_ptr<void>>> _services;
};

}  // namespace kgr
<commit_msg>removed garbage<commit_after>#pragma once

#include "detail/function_traits.hpp"
#include "detail/utils.hpp"
#include "detail/container_service.hpp"

#include <unordered_map>
#include <memory>
#include <type_traits>
#include <tuple>
#include <algorithm>
#include <vector>

namespace kgr {

struct Container {
private:
	template<typename Condition, typename T = int> using enable_if = detail::enable_if_t<Condition::value, T>;
	template<typename Condition, typename T = int> using disable_if = detail::enable_if_t<!Condition::value, T>;
	template<typename T> using decay = typename std::decay<T>::type;
	template<typename T> using is_single = std::is_base_of<Single, decay<T>>;
	template<typename T> using is_container_service = std::is_same<T, ContainerService>;
	template<typename T> using is_base_of_container_service = std::is_base_of<detail::ContainerServiceBase, T>;
	template<typename T> using parent_types = typename decay<T>::ParentTypes;
	template<int S, typename T> using parent_element = typename std::tuple_element<S, parent_types<T>>::type;
	template<typename Tuple, int n> using tuple_seq_minus = typename detail::seq_gen<std::tuple_size<Tuple>::value - n>::type;
	template<typename T> using instance_ptr = std::unique_ptr<T, void(*)(void*)>;
	template<template<typename> class Map, typename T> using service_map_t = typename Map<T>::Service;

	template<typename T>
	static void deleter(void* i) {
		delete static_cast<T*>(i);
	}

	template<typename T, typename... Args, enable_if<std::is_constructible<T, Args...>> = 0>
	static instance_ptr<T> makeInstancePtr(Args&&... args) {
		return instance_ptr<T>{new T(std::forward<Args>(args)...), &Container::deleter<T>};
	}

	template<typename T, typename... Args, disable_if<std::is_constructible<T, Args...>> = 0>
	static instance_ptr<T> makeInstancePtr(Args&&... args) {
		return instance_ptr<T>{new T{std::forward<Args>(args)...}, &Container::deleter<T>};
	}

public:
	Container() = default;
	Container(const Container &) = delete;
	Container& operator =(const Container &) = delete;
	Container(Container&& other) = default;
	Container& operator=(Container&& other) = default;
	virtual ~Container() = default;

	template<typename T, enable_if<is_single<decay<T>>> = 0>
	void instance(T&& service) {
		save_instance(std::forward<T>(service));
	}

	template<typename T, typename... Args, enable_if<is_single<T>> = 0>
	void instance(Args&& ...args) {
		save_new_instance<T>(std::forward<Args>(args)...);
	}

	template<typename T, typename... Args>
	ServiceType<T> service(Args&& ...args) {
		return get_service<T>(std::forward<Args>(args)...).forward();
	}

	template<template<typename> class Map, typename U, typename ...Args>
	detail::function_result_t<decay<U>> invoke(U&& function, Args&&... args) {
		return invoke_helper<Map>(tuple_seq_minus<detail::function_arguments_t<decay<U>>, sizeof...(Args)>{}, std::forward<U>(function), std::forward<Args>(args)...);
	}

	inline void clear() {
		_services.clear();
	}

private:
	template<typename U, typename ...Args>
	detail::function_result_t<decay<U>> invoke(U&& function, Args&&... args) {
		return invoke_helper(tuple_seq_minus<detail::function_arguments_t<decay<U>>, sizeof...(Args)>{}, std::forward<U>(function), std::forward<Args>(args)...);
	}

	template<typename T, typename... Args, enable_if<is_single<T>> = 0, disable_if<std::is_abstract<T>> = 0>
	void save_new_instance(Args&&... args) {
		save_instance(make_service_instance<T>(std::forward<Args>(args)...));
	}

	template<typename T, typename... Args, enable_if<is_single<T>> = 0, enable_if<std::is_abstract<T>> = 0>
	void save_new_instance(Args&&...) {
		throw std::out_of_range{"No instance found for the requested abstract service"};
	}

	// save instance functions
	template<typename T, enable_if<detail::has_overrides<decay<T>>> = 0>
	void save_instance(T&& service) {
		save_instance(std::forward<T>(service), detail::tuple_seq<parent_types<T>>{});
	}

	template<typename T, disable_if<detail::has_overrides<decay<T>>> = 0>
	void save_instance(T&& service) {
		using U = decay<T>;
		save_instance_helper<U>(makeInstancePtr<U>(std::move(service)));
	}

	template<typename T, int... S>
	void save_instance(T&& service, detail::seq<S...>) {
		using U = decay<T>;
		save_instance_helper<U, parent_element<S, U>...>(makeInstancePtr<U>(std::move(service)));
	}

	template<typename T>
	void save_instance_helper(instance_ptr<T> service) {
		_services[detail::type_id<T>].emplace_back(std::move(service));
	}

	template<typename T, typename Override, typename... Others>
	void save_instance_helper(instance_ptr<T> service) {
		using ServiceOverride = detail::ServiceOverride<T, Override>;

		_services[detail::type_id<Override>].emplace_back(static_cast<instance_ptr<Override>>(makeInstancePtr<ServiceOverride>(*service)));
		save_instance_helper<T, Others...>(std::move(service));
	}

	// get service functions
	template<typename T, typename... Args, disable_if<is_single<T>> = 0, disable_if<is_base_of_container_service<T>> = 0>
	T get_service(Args&&... args) {
		return make_service_instance<T>(std::forward<Args>(args)...);
	}

	template<typename T, enable_if<is_container_service<T>> = 0>
	T get_service() {
		return T{*this};
	}

	template<typename T, enable_if<is_base_of_container_service<T>> = 0, disable_if<is_container_service<T>> = 0>
	T get_service() {
		return T{*dynamic_cast<typename T::Type*>(this)};
	}

	template<typename T, enable_if<is_single<T>> = 0, disable_if<is_base_of_container_service<T>> = 0>
	T& get_service() {
		auto&& list = _services[detail::type_id<T>];

		if (!list.size()) {
			save_new_instance<T>();
		}

		return *static_cast<T*>(list.back().get());
	}

	// make instance
	template<typename T, typename... Args>
	T make_service_instance(Args&&... args) {
		T service = invoke(&T::construct, std::forward<Args>(args)...);
		invoke_service(service);
		return service;
	}

	// invoke
	template<typename U, typename ...Args, int... S>
	detail::function_result_t<decay<U>> invoke_helper(detail::seq<S...>, U&& function, Args&&... args) {
		return std::forward<U>(function)(get_service<decay<detail::function_argument_t<S, decay<U>>>>()..., std::forward<Args>(args)...);
	}

	template<template<typename> class Map, typename U, typename ...Args, int... S>
	detail::function_result_t<decay<U>> invoke_helper(detail::seq<S...>, U&& function, Args&&... args) {
		return std::forward<U>(function)(service<service_map_t<Map, detail::function_argument_t<S, decay<U>>>>()..., std::forward<Args>(args)...);
	}

	template<typename T, int... S, enable_if<detail::has_invoke<decay<T>>> = 0>
	void invoke_service(T&& service) {
		using U = decay<T>;
		invoke_service_helper<typename U::invoke::Next>(std::forward<T>(service), U::invoke::method);
	}

	template<typename Method, typename T, typename F, enable_if<detail::has_next<Method>> = 0>
	void invoke_service_helper(T&& service, F&& function) {
		do_invoke_service(detail::tuple_seq<detail::function_arguments_t<decay<F>>>{}, std::forward<T>(service), std::forward<F>(function));
		invoke_service_helper<typename Method::Next>(std::forward<T>(service), Method::method);
	}

	template<typename Method, typename T, typename F, disable_if<detail::has_next<Method>> = 0>
	void invoke_service_helper(T&& service, F&& function) {
		do_invoke_service(detail::tuple_seq<detail::function_arguments_t<decay<F>>>{}, std::forward<T>(service), std::forward<F>(function));
	}

	template<typename T, typename F, int... S>
	void do_invoke_service(detail::seq<S...>, T&& service, F&& function) {
		invoke([&service, &function](detail::function_argument_t<S, decay<F>>... args){
			(std::forward<T>(service).*std::forward<F>(function))(std::forward<detail::function_argument_t<S, decay<F>>>(args)...);
		});
	}

	template<typename T, disable_if<detail::has_invoke<decay<T>>> = 0>
	void invoke_service(T&&) {}

	std::unordered_map<detail::type_id_t, std::vector<instance_ptr<void>>> _services;
};

}  // namespace kgr
<|endoftext|>


<commit_before>#include "Mailer.h"
#include "../Interface/Server.h"
#include "../Interface/Database.h"
#include "database.h"
#include "../urlplugin/IUrlFactory.h"
#include "ClientMain.h"
#include <math.h>

IMutex* Mailer::mutex = NULL;
ICondition* Mailer::cond = NULL;
bool Mailer::queue_limit = false;
bool Mailer::queued_mail = false;
extern IUrlFactory *url_fak;

bool Mailer::sendMail(const std::string & send_to, const std::string & subject, const std::string & message)
{
	IScopedLock lock(mutex);
	if (queue_limit)
		return false;

	lock.relock(NULL);

	IDatabase* db = Server->getDatabase(Server->getThreadID(), URBACKUPDB_SERVER);
	IQuery* q = db->Prepare("INSERT INTO mail_queue (send_to, subject, message) VALUES (?,?,?)", false);
	q->Bind(send_to);
	q->Bind(subject);
	q->Bind(message);
	bool b = q->Write();

	if (b)
	{
		lock.relock(mutex);
		cond->notify_all();
		queued_mail = true;
	}

	db->destroyQuery(q);

	return b;
}

void Mailer::init()
{
	mutex = Server->createMutex();
	cond = Server->createCondition();
	Server->createThread(new Mailer, "mail queue");
}

void Mailer::operator()()
{
	if (url_fak == NULL)
		return;

	bool has_mail_server;
	{
		MailServer mail_server = ClientMain::getMailServerSettings();
		has_mail_server = !mail_server.servername.empty();
	}

	if (!has_mail_server)
	{
		queue_limit = true;
	}

	IDatabase* db = Server->getDatabase(Server->getThreadID(), URBACKUPDB_SERVER);
	IQuery* q_get_mail = db->Prepare("SELECT id, send_to, subject, message, next_try, retry_count FROM mail_queue WHERE next_try IS NULL or next_try>=?");
	IQuery* q_set_retry = db->Prepare("UPDATE mail_queue SET next_try=?, retry_count=? WHERE id=?");
	IQuery* q_remove_mail = db->Prepare("DELETE FROM mail_queue WHERE id=?");

	db->Write("UPDATE mail_queue SET next_try=NULL");

	while (true)
	{
		{
			IScopedLock lock(mutex);
			if (!queued_mail)
			{
				cond->wait(&lock, 5 * 60 * 1000);
				queued_mail = false;
			}
		}

		q_get_mail->Bind(Server->getTimeMS());
		db_results res = q_get_mail->Read();
		q_get_mail->Reset();

		if (res.size() > 1000)
		{
			IScopedLock lock(mutex);
			queue_limit = true;
		}
		else if (queue_limit
			&& has_mail_server)
		{
			IScopedLock lock(mutex);
			queue_limit = false;
		}

		MailServer mail_server;

		if (!res.empty() || !has_mail_server)
		{
			mail_server = ClientMain::getMailServerSettings();
		}

		if (mail_server.servername.empty())
		{
			has_mail_server = false;
			continue;
		}
		else
		{
			has_mail_server = true;
		}

		for (size_t i = 0; i < res.size(); ++i)
		{
			std::vector<std::string> addrs;
			Tokenize(res[i]["send_to"], addrs, ";,");

			std::string errmsg;
			if (!url_fak->sendMail(mail_server, addrs, res[i]["subject"], res[i]["message"], &errmsg))
			{
				int n = watoi(res[i]["retry_count"]);
				unsigned int waittime = (std::min)(static_cast<unsigned int>(1000.*pow(2., static_cast<double>(n))), (unsigned int)30 * 60 * 1000); //30min
				if (n>20)
				{
					waittime = (unsigned int)30 * 60 * 1000;
				}

				Server->Log("Error sending mail to \"" + res[i]["send_to"] + "\". " + errmsg + ". Retrying in " + PrettyPrintTime(waittime), LL_WARNING);

				q_set_retry->Bind(Server->getTimeMS()+waittime);
				q_set_retry->Bind(n + 1);
				q_set_retry->Bind(res[i]["id"]);
				q_set_retry->Write();
				q_set_retry->Reset();
			}
			else
			{
				q_remove_mail->Bind(res[i]["id"]);
				q_remove_mail->Write();
				q_remove_mail->Reset();
			}
		}
	}
}
<commit_msg>Make mail queueing synchonous<commit_after>#include "Mailer.h"
#include "../Interface/Server.h"
#include "../Interface/Database.h"
#include "database.h"
#include "../urlplugin/IUrlFactory.h"
#include "ClientMain.h"
#include <math.h>

IMutex* Mailer::mutex = NULL;
ICondition* Mailer::cond = NULL;
bool Mailer::queue_limit = false;
bool Mailer::queued_mail = false;
extern IUrlFactory *url_fak;

bool Mailer::sendMail(const std::string & send_to, const std::string & subject, const std::string & message)
{
	IScopedLock lock(mutex);
	if (queue_limit)
		return false;

	lock.relock(NULL);

	IDatabase* db = Server->getDatabase(Server->getThreadID(), URBACKUPDB_SERVER);
	DBScopedSynchronous db_synchronous(db);
	IQuery* q = db->Prepare("INSERT INTO mail_queue (send_to, subject, message) VALUES (?,?,?)", false);
	q->Bind(send_to);
	q->Bind(subject);
	q->Bind(message);
	bool b = q->Write();

	if (b)
	{
		lock.relock(mutex);
		cond->notify_all();
		queued_mail = true;
	}

	db->destroyQuery(q);

	return b;
}

void Mailer::init()
{
	mutex = Server->createMutex();
	cond = Server->createCondition();
	Server->createThread(new Mailer, "mail queue");
}

void Mailer::operator()()
{
	if (url_fak == NULL)
		return;

	bool has_mail_server;
	{
		MailServer mail_server = ClientMain::getMailServerSettings();
		has_mail_server = !mail_server.servername.empty();
	}

	if (!has_mail_server)
	{
		queue_limit = true;
	}

	IDatabase* db = Server->getDatabase(Server->getThreadID(), URBACKUPDB_SERVER);
	IQuery* q_get_mail = db->Prepare("SELECT id, send_to, subject, message, next_try, retry_count FROM mail_queue WHERE next_try IS NULL or next_try>=?");
	IQuery* q_set_retry = db->Prepare("UPDATE mail_queue SET next_try=?, retry_count=? WHERE id=?");
	IQuery* q_remove_mail = db->Prepare("DELETE FROM mail_queue WHERE id=?");

	db->Write("UPDATE mail_queue SET next_try=NULL");

	while (true)
	{
		{
			IScopedLock lock(mutex);
			if (!queued_mail)
			{
				cond->wait(&lock, 5 * 60 * 1000);
				queued_mail = false;
			}
		}

		q_get_mail->Bind(Server->getTimeMS());
		db_results res = q_get_mail->Read();
		q_get_mail->Reset();

		if (res.size() > 1000)
		{
			IScopedLock lock(mutex);
			queue_limit = true;
		}
		else if (queue_limit
			&& has_mail_server)
		{
			IScopedLock lock(mutex);
			queue_limit = false;
		}

		MailServer mail_server;

		if (!res.empty() || !has_mail_server)
		{
			mail_server = ClientMain::getMailServerSettings();
		}

		if (mail_server.servername.empty())
		{
			has_mail_server = false;
			continue;
		}
		else
		{
			has_mail_server = true;
		}

		for (size_t i = 0; i < res.size(); ++i)
		{
			std::vector<std::string> addrs;
			Tokenize(res[i]["send_to"], addrs, ";,");

			std::string errmsg;
			if (!url_fak->sendMail(mail_server, addrs, res[i]["subject"], res[i]["message"], &errmsg))
			{
				int n = watoi(res[i]["retry_count"]);
				unsigned int waittime = (std::min)(static_cast<unsigned int>(1000.*pow(2., static_cast<double>(n))), (unsigned int)30 * 60 * 1000); //30min
				if (n>20)
				{
					waittime = (unsigned int)30 * 60 * 1000;
				}

				Server->Log("Error sending mail to \"" + res[i]["send_to"] + "\". " + errmsg + ". Retrying in " + PrettyPrintTime(waittime), LL_WARNING);

				q_set_retry->Bind(Server->getTimeMS()+waittime);
				q_set_retry->Bind(n + 1);
				q_set_retry->Bind(res[i]["id"]);
				q_set_retry->Write();
				q_set_retry->Reset();
			}
			else
			{
				q_remove_mail->Bind(res[i]["id"]);
				q_remove_mail->Write();
				q_remove_mail->Reset();
			}
		}
	}
}
<|endoftext|>