<commit_before>/** \copyright
 * Copyright (c) 2016, Balazs Racz
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are  permitted provided that the following conditions are met:
 *
 *  - Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 *
 *  - Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * \file Uninitialized.hxx
 * Helper class for creating delayed initialized objects in static memory.
 *
 * @author Balazs Racz
 * @date 24 June 2017
 */

#ifndef _UTILS_UNINITIALIZED_HXX_
#define _UTILS_UNINITIALIZED_HXX_

#include <type_traits>

/// Template class that allows allocating storage for an object but not calling
/// its constructor.
///
/// The object shall be constructed before first use by calling emplace(). It
/// is the responsibility of the caller to also call the destructor sometime by
/// invoking reset(), otherwise the object will be leaked.
///
/// Using this class is inherently unsafe, so avoid if possible. After c++17
/// this class will be replaceable by std::optional.
template <class T>
class uninitialized
{
public:
    /// @return pointer to the embedded object
    const T *operator->() const
    {
        return tptr();
    }
    /// @return pointer to the embedded object.
    T *operator->()
    {
        return tptrm();
    }
    /// @return the embedded object
    T &operator*()
    {
        return *tptrm();
    }
    /// @return the embedded object
    const T &operator*() const
    {
        return *tptr();
    }
    /// @return the embedded object
    T &value()
    {
        return *tptrm();
    }
    /// @return the embedded object
    const T &value() const
    {
        return *tptr();
    };

    /// Gets the embedded object pointer in a way that is friendly to
    /// linker-initialization.
    /// NOTE: when switching to std::optional<>, calls to this function need to
    /// be replaced with calls to .operator->().
    /// @return mutable pointer to the embedded object
    constexpr T* get_mutable()
    {
        return tptrm();
    }

    /// Gets the embedded object pointer in a way that is friendly to
    /// linker-initialization.
    /// NOTE: when switching to std::optional<>, calls to this function need to
    /// be replaced with calls to .operator->().
    /// @return const pointer to the embedded object
    constexpr const T* get() const
    {
        return tptr();
    }

    /// Constructs the embedded object.
    template <class... Args> T &emplace(Args &&... args)
    {
        new (this) T(std::forward<Args>(args)...);
        return *tptrm();
    }

    /// Destructs the embedded object.
    void reset()
    {
        tptr()->~T();
    }

    /// Public API to convert the pointer in a linker-initialized way.
    static constexpr T *cast_data(uninitialized<T> *parent)
    {
        return static_cast<T *>((void*)&parent->data);
    }

private:
    typename std::aligned_storage<sizeof(T), alignof(T)>::type data;

    /// @return the embedded object (mutable pointer)
    constexpr T *tptrm()
    {
        return static_cast<T *>((void*)&data);
    }
    /// @return the embedded object
    constexpr const T *tptr() const
    {
        return static_cast<const T *>((void*)&data);
    }
};

#endif // _UTILS_UNINITIALIZED_HXX_
<commit_msg>Fixes LLVM warnings in uninitialized.<commit_after>/** \copyright
 * Copyright (c) 2016, Balazs Racz
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are  permitted provided that the following conditions are met:
 *
 *  - Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 *
 *  - Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * \file Uninitialized.hxx
 * Helper class for creating delayed initialized objects in static memory.
 *
 * @author Balazs Racz
 * @date 24 June 2017
 */

#ifndef _UTILS_UNINITIALIZED_HXX_
#define _UTILS_UNINITIALIZED_HXX_

#include <type_traits>

/// Template class that allows allocating storage for an object but not calling
/// its constructor.
///
/// The object shall be constructed before first use by calling emplace(). It
/// is the responsibility of the caller to also call the destructor sometime by
/// invoking reset(), otherwise the object will be leaked.
///
/// Using this class is inherently unsafe, so avoid if possible. After c++17
/// this class will be replaceable by std::optional.
template <class T>
class uninitialized
{
public:
    /// @return pointer to the embedded object
    const T *operator->() const
    {
        return tptr();
    }
    /// @return pointer to the embedded object.
    T *operator->()
    {
        return tptrm();
    }
    /// @return the embedded object
    T &operator*()
    {
        return *tptrm();
    }
    /// @return the embedded object
    const T &operator*() const
    {
        return *tptr();
    }
    /// @return the embedded object
    T &value()
    {
        return *tptrm();
    }
    /// @return the embedded object
    const T &value() const
    {
        return *tptr();
    };

    /// Gets the embedded object pointer in a way that is friendly to
    /// linker-initialization.
    /// NOTE: when switching to std::optional<>, calls to this function need to
    /// be replaced with calls to .operator->().
    /// @return mutable pointer to the embedded object
    constexpr T* get_mutable() const
    {
        return tptrm();
    }

    /// Gets the embedded object pointer in a way that is friendly to
    /// linker-initialization.
    /// NOTE: when switching to std::optional<>, calls to this function need to
    /// be replaced with calls to .operator->().
    /// @return const pointer to the embedded object
    constexpr const T* get() const
    {
        return tptr();
    }

    /// Constructs the embedded object.
    template <class... Args> T &emplace(Args &&... args)
    {
        new (this) T(std::forward<Args>(args)...);
        return *tptrm();
    }

    /// Destructs the embedded object.
    void reset()
    {
        tptr()->~T();
    }

    /// Public API to convert the pointer in a linker-initialized way.
    static constexpr T *cast_data(uninitialized<T> *parent)
    {
        return static_cast<T *>((void*)&parent->data);
    }

private:
    typename std::aligned_storage<sizeof(T), alignof(T)>::type data;

    /// @return the embedded object (mutable pointer)
    constexpr T *tptrm() const
    {
        return static_cast<T *>((void*)&data);
    }
    /// @return the embedded object
    constexpr const T *tptr() const
    {
        return static_cast<const T *>((void*)&data);
    }
};

#endif // _UTILS_UNINITIALIZED_HXX_
<|endoftext|>


<commit_before>//
//  libavg - Media Playback Engine.
//  Copyright (C) 2003-2008 Ulrich von Zadow
//
//  This library is free software; you can redistribute it and/or
//  modify it under the terms of the GNU Lesser General Public
//  License as published by the Free Software Foundation; either
//  version 2 of the License, or (at your option) any later version.
//
//  This library is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
//  Lesser General Public License for more details.
//
//  You should have received a copy of the GNU Lesser General Public
//  License along with this library; if not, write to the Free Software
//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//
//  Current versions can be found at www.libavg.de
//

#include "FFMpegDemuxer.h"
#include "../base/ScopeTimer.h"
#include "../base/ObjectCounter.h"
#include "../base/Exception.h"

#include <cstring>
#include <iostream>

using namespace std;

namespace avg {

FFMpegDemuxer::FFMpegDemuxer(AVFormatContext * pFormatContext, vector<int> streamIndexes)
    : m_pFormatContext(pFormatContext)
{
    ObjectCounter::get()->incRef(&typeid(*this));
    for (unsigned i = 0; i < streamIndexes.size(); ++i) {
        m_PacketLists[streamIndexes[i]] = PacketList();
    }
}

FFMpegDemuxer::~FFMpegDemuxer()
{
    clearPacketCache();
    ObjectCounter::get()->decRef(&typeid(*this));
}

AVPacket * FFMpegDemuxer::getPacket(int streamIndex)
{
    // Make sure enableStream was called on streamIndex.
    AVG_ASSERT(m_PacketLists.size() > 0);
    AVG_ASSERT(streamIndex > -1 && streamIndex < 10);
    if (m_PacketLists.find(streamIndex) == m_PacketLists.end()) {
        cerr << this << ": getPacket: Stream " << streamIndex << " not found." << endl;
        dump();
        AVG_ASSERT(false);
    }
    PacketList & CurPacketList = m_PacketLists.find(streamIndex)->second;
    AVPacket * pPacket;
    if (!CurPacketList.empty()) {
        pPacket = CurPacketList.front();
        CurPacketList.pop_front();
    } else {
        do {
            pPacket = new AVPacket;
            memset(pPacket, 0, sizeof(AVPacket));
            int err = av_read_frame(m_pFormatContext, pPacket);
            // TODO: Check url_ferror here too.
            if (err < 0) {
                av_free_packet(pPacket);
                delete pPacket;
                pPacket = 0;
                return 0;
            }
            if (pPacket->stream_index != streamIndex) {
                if (m_PacketLists.find(pPacket->stream_index) != m_PacketLists.end()) {
                    av_dup_packet(pPacket);
                    PacketList& OtherPacketList =
                            m_PacketLists.find(pPacket->stream_index)->second;
                    OtherPacketList.push_back(pPacket);
                } else {
                    av_free_packet(pPacket);
                    delete pPacket;
                    pPacket = 0;
                }
            } else {
                av_dup_packet(pPacket);
            }
        } while (!pPacket || pPacket->stream_index != streamIndex);
    }
    return pPacket;
}

void FFMpegDemuxer::seek(double destTime)
{
#if LIBAVFORMAT_BUILD <= 4616
    av_seek_frame(m_pFormatContext, -1, destTime*1000000);
#else
#if LIBAVFORMAT_BUILD < ((49<<16)+(0<<8)+0)
    av_seek_frame(m_pFormatContext, -1, destTime*1000000, 0);
#else
    av_seek_frame(m_pFormatContext, -1, (long long)(destTime)*AV_TIME_BASE, AVSEEK_FLAG_BACKWARD);
#endif
#endif
    clearPacketCache();
    map<int, PacketList>::iterator it;
    for (it = m_PacketLists.begin(); it != m_PacketLists.end(); ++it) {
        int CurStreamIndex = it->first;
        AVStream * pStream = m_pFormatContext->streams[CurStreamIndex];
        avcodec_flush_buffers(pStream->codec);
    }
}

void FFMpegDemuxer::clearPacketCache()
{
    map<int, PacketList>::iterator it;
    for (it = m_PacketLists.begin(); it != m_PacketLists.end(); ++it) {
        PacketList::iterator it2;
        PacketList* thePacketList = &(it->second);
        for (it2 = thePacketList->begin(); it2 != thePacketList->end(); ++it2) {
            av_free_packet(*it2);
            delete *it2;
        }
        thePacketList->clear();
    }
}

void FFMpegDemuxer::dump()
{
    map<int, PacketList>::iterator it;
    cerr << "FFMpegDemuxer " << this << endl;
    cerr << "packetlists.size(): " << int(m_PacketLists.size()) << endl;
    for (it = m_PacketLists.begin(); it != m_PacketLists.end(); ++it) {
        cerr << "  " << it->first << ":  " << int(it->second.size()) << endl;
    }
}

}
<commit_msg>Fixed test failure caused by last checkin.<commit_after>//
//  libavg - Media Playback Engine.
//  Copyright (C) 2003-2008 Ulrich von Zadow
//
//  This library is free software; you can redistribute it and/or
//  modify it under the terms of the GNU Lesser General Public
//  License as published by the Free Software Foundation; either
//  version 2 of the License, or (at your option) any later version.
//
//  This library is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
//  Lesser General Public License for more details.
//
//  You should have received a copy of the GNU Lesser General Public
//  License along with this library; if not, write to the Free Software
//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//
//  Current versions can be found at www.libavg.de
//

#include "FFMpegDemuxer.h"
#include "../base/ScopeTimer.h"
#include "../base/ObjectCounter.h"
#include "../base/Exception.h"

#include <cstring>
#include <iostream>

using namespace std;

namespace avg {

FFMpegDemuxer::FFMpegDemuxer(AVFormatContext * pFormatContext, vector<int> streamIndexes)
    : m_pFormatContext(pFormatContext)
{
    ObjectCounter::get()->incRef(&typeid(*this));
    for (unsigned i = 0; i < streamIndexes.size(); ++i) {
        m_PacketLists[streamIndexes[i]] = PacketList();
    }
}

FFMpegDemuxer::~FFMpegDemuxer()
{
    clearPacketCache();
    ObjectCounter::get()->decRef(&typeid(*this));
}

AVPacket * FFMpegDemuxer::getPacket(int streamIndex)
{
    // Make sure enableStream was called on streamIndex.
    AVG_ASSERT(m_PacketLists.size() > 0);
    AVG_ASSERT(streamIndex > -1 && streamIndex < 10);
    if (m_PacketLists.find(streamIndex) == m_PacketLists.end()) {
        cerr << this << ": getPacket: Stream " << streamIndex << " not found." << endl;
        dump();
        AVG_ASSERT(false);
    }
    PacketList & CurPacketList = m_PacketLists.find(streamIndex)->second;
    AVPacket * pPacket;
    if (!CurPacketList.empty()) {
        pPacket = CurPacketList.front();
        CurPacketList.pop_front();
    } else {
        do {
            pPacket = new AVPacket;
            memset(pPacket, 0, sizeof(AVPacket));
            int err = av_read_frame(m_pFormatContext, pPacket);
            // TODO: Check url_ferror here too.
            if (err < 0) {
                av_free_packet(pPacket);
                delete pPacket;
                pPacket = 0;
                return 0;
            }
            if (pPacket->stream_index != streamIndex) {
                if (m_PacketLists.find(pPacket->stream_index) != m_PacketLists.end()) {
                    av_dup_packet(pPacket);
                    PacketList& OtherPacketList =
                            m_PacketLists.find(pPacket->stream_index)->second;
                    OtherPacketList.push_back(pPacket);
                } else {
                    av_free_packet(pPacket);
                    delete pPacket;
                    pPacket = 0;
                }
            } else {
                av_dup_packet(pPacket);
            }
        } while (!pPacket || pPacket->stream_index != streamIndex);
    }
    return pPacket;
}

void FFMpegDemuxer::seek(double destTime)
{
#if LIBAVFORMAT_BUILD <= 4616
    av_seek_frame(m_pFormatContext, -1, destTime*1000000);
#else
#if LIBAVFORMAT_BUILD < ((49<<16)+(0<<8)+0)
    av_seek_frame(m_pFormatContext, -1, destTime*1000000, 0);
#else
    av_seek_frame(m_pFormatContext, -1, (long long)(destTime*AV_TIME_BASE), AVSEEK_FLAG_BACKWARD);
#endif
#endif
    clearPacketCache();
    map<int, PacketList>::iterator it;
    for (it = m_PacketLists.begin(); it != m_PacketLists.end(); ++it) {
        int CurStreamIndex = it->first;
        AVStream * pStream = m_pFormatContext->streams[CurStreamIndex];
        avcodec_flush_buffers(pStream->codec);
    }
}

void FFMpegDemuxer::clearPacketCache()
{
    map<int, PacketList>::iterator it;
    for (it = m_PacketLists.begin(); it != m_PacketLists.end(); ++it) {
        PacketList::iterator it2;
        PacketList* thePacketList = &(it->second);
        for (it2 = thePacketList->begin(); it2 != thePacketList->end(); ++it2) {
            av_free_packet(*it2);
            delete *it2;
        }
        thePacketList->clear();
    }
}

void FFMpegDemuxer::dump()
{
    map<int, PacketList>::iterator it;
    cerr << "FFMpegDemuxer " << this << endl;
    cerr << "packetlists.size(): " << int(m_PacketLists.size()) << endl;
    for (it = m_PacketLists.begin(); it != m_PacketLists.end(); ++it) {
        cerr << "  " << it->first << ":  " << int(it->second.size()) << endl;
    }
}

}
<|endoftext|>


<commit_before>#include <cmath>
#include <complex>
#include <limits>
#include <fstream>
#include <iterator>
#include <sstream>

#include "Tools/Exception/exception.hpp"

#include "Modem_user.hpp"

namespace aff3ct
{
namespace module
{
/*
 * Constructor / Destructor
 */
template <typename B, typename R, typename Q, tools::proto_max<Q> MAX>
Modem_user<B,R,Q,MAX>
::Modem_user(const int N, const R sigma, const int bits_per_symbol, const std::string const_path,
             const bool disable_sig2, const int n_frames, const std::string name)
: Modem<B,R,Q>(N, (int)(std::ceil((float)N / (float)bits_per_symbol) * 2), sigma, n_frames, name),
  bits_per_symbol(bits_per_symbol),
  nbr_symbols    (1 << bits_per_symbol),
  sqrt_es        (0.0),
  disable_sig2   (disable_sig2),
  constellation  ()
{
	if (const_path.empty())
		throw tools::invalid_argument(__FILE__, __LINE__, __func__, "'const_path' should not be empty.");

	if (bits_per_symbol % 2)
	{
		std::stringstream message;
		message << "'bits_per_symbol' has to be a multiple of 2 ('bits_per_symbol' = " << bits_per_symbol << ").";
		throw tools::invalid_argument(__FILE__, __LINE__, __func__, message.str());
	}

	std::fstream const_file(const_path, std::ios_base::in);

	std::string temp;
	while (std::getline(const_file, temp))
	{
		if (temp[0] == '#') continue;

		std::istringstream buffer(temp);
		std::vector<R> line((std::istream_iterator<R>(buffer)), std::istream_iterator<R>());

		if (line.size() >= 3)
		{
			std::stringstream message;
			message << "'line.size()' has to be smaller than 3 ('line.size()' = " << line.size() << ").";
			throw tools::runtime_error(__FILE__, __LINE__, __func__, message.str());
		}

		if (line.size() == 2)
			constellation.push_back(std::complex<R>(line[0],line[1]));
		else
			constellation.push_back(std::complex<R>(line[0],0.0));
		sqrt_es += std::norm(constellation.back());
	}
	sqrt_es = std::sqrt(sqrt_es/nbr_symbols);

	if ((int)constellation.size() != nbr_symbols)
	{
		std::stringstream message;
		message << "'constellation.size()' has to be equal to 'nbr_symbols' ('constellation.size()' = "
		        << constellation.size() << ", 'nbr_symbols' = " << nbr_symbols << ").";
		throw tools::runtime_error(__FILE__, __LINE__, __func__, message.str());
	}

	for (auto i = 0; i < nbr_symbols; i++)
		constellation[i] /= (std::complex<R>)sqrt_es;

	const_file.close();
}

template <typename B, typename R, typename Q, tools::proto_max<Q> MAX>
Modem_user<B,R,Q,MAX>
::~Modem_user()
{
}

/*
 * Modem
 */
template <typename B,typename R, typename Q, tools::proto_max<Q> MAX>
void Modem_user<B,R,Q,MAX>
::_modulate(const B *X_N1, R *X_N2, const int frame_id)
{
	auto size_in  = this->N;
	auto size_out = this->N_mod;

	auto loop_size = size_in / this->bits_per_symbol;
	for (auto i = 0; i < loop_size; i++)
	{
		unsigned idx = 0;
		for (auto j = 0; j < this->bits_per_symbol; j++)
			idx += unsigned(unsigned(1 << (this->bits_per_symbol -j -1)) * X_N1[i * this->bits_per_symbol +j]);
		auto symbol = this->constellation[idx];

		X_N2[2*i   ] = symbol.real();
		X_N2[2*i +1] = symbol.imag();
	}

	// last elements if "size_in" is not a multiple of the number of bits per symbol
	if (loop_size * this->bits_per_symbol < size_in)
	{
		unsigned idx = 0;
		for (auto j = 0; j < size_in - (loop_size * this->bits_per_symbol); j++)
			idx += unsigned(unsigned(1 << (this->bits_per_symbol -j -1)) * X_N1[loop_size * this->bits_per_symbol +j]);
		auto symbol = this->constellation[idx];

		X_N2[size_out -2] = symbol.real();
		X_N2[size_out -1] = symbol.imag();
	}
}

/*
 * Filter
 */
template <typename B,typename R, typename Q, tools::proto_max<Q> MAX>
void Modem_user<B,R,Q,MAX>
::_filter(const R *Y_N1, R *Y_N2, const int frame_id)
{
	std::copy(Y_N1, Y_N1 + this->N_fil, Y_N2);
}

/*
 * Demodulator
 */
template <typename B,typename R, typename Q, tools::proto_max<Q> MAX>
void Modem_user<B,R,Q,MAX>
::_demodulate(const Q *Y_N1, Q *Y_N2, const int frame_id)
{
	if (typeid(R) != typeid(Q))
		throw tools::invalid_argument(__FILE__, __LINE__, __func__, "Type 'R' and 'Q' have to be the same.");

	if (typeid(Q) != typeid(float) && typeid(Q) != typeid(double))
		throw tools::invalid_argument(__FILE__, __LINE__, __func__, "Type 'Q' has to be float or double.");

	auto size       = this->N;
	auto inv_sigma2 = disable_sig2 ? (Q)1.0 : (Q)(1.0 / (this->sigma * this->sigma));

	for (auto n = 0; n < size; n++) // loop upon the LLRs
	{
		auto L0 = -std::numeric_limits<Q>::infinity();
		auto L1 = -std::numeric_limits<Q>::infinity();

		auto b  = n % this->bits_per_symbol; // bit position in the symbol
		auto k  = n / this->bits_per_symbol; // symbol position

		auto complex_Yk = std::complex<Q>(Y_N1[2*k], Y_N1[2*k+1]);

		for (auto j = 0; j < this->nbr_symbols; j++)
			if ((j &(1 << (this->bits_per_symbol -b -1))) == 0)
				L0 = MAX(L0, -std::norm(complex_Yk - std::complex<Q>((Q)this->constellation[j].real(),
				                                                     (Q)this->constellation[j].imag())) * inv_sigma2);
			else
				L1 = MAX(L1, -std::norm(complex_Yk - std::complex<Q>((Q)this->constellation[j].real(),
				                                                     (Q)this->constellation[j].imag())) * inv_sigma2);

		Y_N2[n] = (L0 - L1);
	}
}

/*
 * Demodulator
 */
template <typename B,typename R, typename Q, tools::proto_max<Q> MAX>
void Modem_user<B,R,Q,MAX>
::_demodulate_with_gains(const Q *Y_N1, const R *H_N, Q *Y_N2, const int frame_id)
{
	if (typeid(R) != typeid(Q))
		throw tools::invalid_argument(__FILE__, __LINE__, __func__, "Type 'R' and 'Q' have to be the same.");

	if (typeid(Q) != typeid(float) && typeid(Q) != typeid(double))
		throw tools::invalid_argument(__FILE__, __LINE__, __func__, "Type 'Q' has to be float or double.");

	auto size       = this->N;
	auto inv_sigma2 = disable_sig2 ? (Q)1.0 : (Q)(1.0 / (this->sigma * this->sigma));

	for (auto n = 0; n < size; n++) // loop upon the LLRs
	{
		auto L0 = -std::numeric_limits<Q>::infinity();
		auto L1 = -std::numeric_limits<Q>::infinity();

		auto b  = n % this->bits_per_symbol; // bit position in the symbol
		auto k  = n / this->bits_per_symbol; // symbol position

		auto complex_Yk = std::complex<Q>(   Y_N1[2*k],    Y_N1[2*k+1]);
		auto complex_Hk = std::complex<Q>((Q)H_N [2*k], (Q)H_N [2*k+1]);

		for (auto j = 0; j < this->nbr_symbols; j++)
			if ((j &(1 << (this->bits_per_symbol -b -1))) == 0)
				L0 = MAX(L0, -std::norm(complex_Yk -
				                        complex_Hk * std::complex<Q>((Q)this->constellation[j].real(),
				                                                     (Q)this->constellation[j].imag())) * inv_sigma2);
			else
				L1 = MAX(L1, -std::norm(complex_Yk -
				                        complex_Hk * std::complex<Q>((Q)this->constellation[j].real(),
				                                                     (Q)this->constellation[j].imag())) * inv_sigma2);

		Y_N2[n] = (L0 - L1);
	}
}

template <typename B, typename R, typename Q, tools::proto_max<Q> MAX>
void Modem_user<B,R,Q,MAX>
::_demodulate(const Q *Y_N1, const Q *Y_N2, Q *Y_N3, const int frame_id)
{
	if (typeid(R) != typeid(Q))
		throw tools::invalid_argument(__FILE__, __LINE__, __func__, "Type 'R' and 'Q' have to be the same.");

	if (typeid(Q) != typeid(float) && typeid(Q) != typeid(double))
		throw tools::invalid_argument(__FILE__, __LINE__, __func__, "Type 'Q' has to be float or double.");

	auto size       = this->N;
	auto inv_sigma2 = disable_sig2 ? (Q)1.0 : (Q)1.0 / (this->sigma * this->sigma);

	for (auto n = 0; n < size; n++) // loop upon the LLRs
	{
		auto L0 = -std::numeric_limits<Q>::infinity();
		auto L1 = -std::numeric_limits<Q>::infinity();
		auto b  = n % this->bits_per_symbol; // bit position in the symbol
		auto k  = n / this->bits_per_symbol; // symbol position

		auto complex_Yk = std::complex<Q>(Y_N1[2*k], Y_N1[2*k+1]);

		for (auto j = 0; j < this->nbr_symbols; j++)
		{
			auto tempL = (Q)(std::norm(complex_Yk - std::complex<Q>((Q)this->constellation[j].real(),
			                                                        (Q)this->constellation[j].imag())) * inv_sigma2);

			for (auto l = 0; l < b; l++)
				tempL += (j & (1 << (this->bits_per_symbol -l -1))) * Y_N2[k * this->bits_per_symbol +l];

			for (auto l = b + 1; l < this->bits_per_symbol; l++)
				tempL += (j & (1 << (this->bits_per_symbol -l -1))) * Y_N2[k * this->bits_per_symbol +l];

			if ((j & (1 << (this->bits_per_symbol-b-1))) == 0)
				L0 = MAX(L0, -tempL);
			else
				L1 = MAX(L1, -tempL);
		}

		Y_N3[n] = (L0 - L1);
	}
}

template <typename B, typename R, typename Q, tools::proto_max<Q> MAX>
void Modem_user<B,R,Q,MAX>
::_demodulate_with_gains(const Q *Y_N1, const R *H_N, const Q *Y_N2, Q *Y_N3, const int frame_id)
{
	if (typeid(R) != typeid(Q))
		throw tools::invalid_argument(__FILE__, __LINE__, __func__, "Type 'R' and 'Q' have to be the same.");

	if (typeid(Q) != typeid(float) && typeid(Q) != typeid(double))
		throw tools::invalid_argument(__FILE__, __LINE__, __func__, "Type 'Q' has to be float or double.");

	auto size       = this->N;
	auto inv_sigma2 = disable_sig2 ? (Q)1.0 : (Q)1.0 / (this->sigma * this->sigma);

	for (auto n = 0; n < size; n++) // loop upon the LLRs
	{
		auto L0 = -std::numeric_limits<Q>::infinity();
		auto L1 = -std::numeric_limits<Q>::infinity();
		auto b  = n % this->bits_per_symbol; // bit position in the symbol
		auto k  = n / this->bits_per_symbol; // symbol position

		auto complex_Yk = std::complex<Q>(   Y_N1[2*k],    Y_N1[2*k+1]);
		auto complex_Hk = std::complex<Q>((Q)H_N [2*k], (Q)H_N [2*k+1]);

		for (auto j = 0; j < this->nbr_symbols; j++)
		{
			auto tempL = (Q)(std::norm(complex_Yk -
			                           complex_Hk * std::complex<Q>((Q)this->constellation[j].real(),
			                                                        (Q)this->constellation[j].imag())) * inv_sigma2);

			for (auto l = 0; l < b; l++)
				tempL += (j & (1 << (this->bits_per_symbol -l -1))) * Y_N2[k * this->bits_per_symbol +l];

			for (auto l = b + 1; l < this->bits_per_symbol; l++)
				tempL += (j & (1 << (this->bits_per_symbol -l -1))) * Y_N2[k * this->bits_per_symbol +l];

			if ((j & (1 << (this->bits_per_symbol-b-1))) == 0)
				L0 = MAX(L0, -tempL);
			else
				L1 = MAX(L1, -tempL);
		}

		Y_N3[n] = (L0 - L1);
	}
}
}
}
<commit_msg>Modification of the modulation energy after normalization.<commit_after>#include <cmath>
#include <complex>
#include <limits>
#include <fstream>
#include <iterator>
#include <sstream>

#include "Tools/Exception/exception.hpp"

#include "Modem_user.hpp"

namespace aff3ct
{
namespace module
{
/*
 * Constructor / Destructor
 */
template <typename B, typename R, typename Q, tools::proto_max<Q> MAX>
Modem_user<B,R,Q,MAX>
::Modem_user(const int N, const R sigma, const int bits_per_symbol, const std::string const_path,
             const bool disable_sig2, const int n_frames, const std::string name)
: Modem<B,R,Q>(N, (int)(std::ceil((float)N / (float)bits_per_symbol) * 2), sigma, n_frames, name),
  bits_per_symbol(bits_per_symbol),
  nbr_symbols    (1 << bits_per_symbol),
  sqrt_es        (0.0),
  disable_sig2   (disable_sig2),
  constellation  ()
{
	if (const_path.empty())
		throw tools::invalid_argument(__FILE__, __LINE__, __func__, "'const_path' should not be empty.");

	if (bits_per_symbol % 2)
	{
		std::stringstream message;
		message << "'bits_per_symbol' has to be a multiple of 2 ('bits_per_symbol' = " << bits_per_symbol << ").";
		throw tools::invalid_argument(__FILE__, __LINE__, __func__, message.str());
	}

	std::fstream const_file(const_path, std::ios_base::in);

	std::string temp;
	while (std::getline(const_file, temp))
	{
		if (temp[0] == '#') continue;

		std::istringstream buffer(temp);
		std::vector<R> line((std::istream_iterator<R>(buffer)), std::istream_iterator<R>());

		if (line.size() >= 3)
		{
			std::stringstream message;
			message << "'line.size()' has to be smaller than 3 ('line.size()' = " << line.size() << ").";
			throw tools::runtime_error(__FILE__, __LINE__, __func__, message.str());
		}

		if (line.size() == 2)
			constellation.push_back(std::complex<R>(line[0],line[1]));
		else
			constellation.push_back(std::complex<R>(line[0],0.0));
		sqrt_es += std::norm(constellation.back());
	}
	sqrt_es = std::sqrt(sqrt_es/nbr_symbols);

	if ((int)constellation.size() != nbr_symbols)
	{
		std::stringstream message;
		message << "'constellation.size()' has to be equal to 'nbr_symbols' ('constellation.size()' = "
		        << constellation.size() << ", 'nbr_symbols' = " << nbr_symbols << ").";
		throw tools::runtime_error(__FILE__, __LINE__, __func__, message.str());
	}

	for (auto i = 0; i < nbr_symbols; i++)
		constellation[i] /= (std::complex<R>)sqrt_es;

	this->sqrt_es = 1.0;
	const_file.close();
}

template <typename B, typename R, typename Q, tools::proto_max<Q> MAX>
Modem_user<B,R,Q,MAX>
::~Modem_user()
{
}

/*
 * Modem
 */
template <typename B,typename R, typename Q, tools::proto_max<Q> MAX>
void Modem_user<B,R,Q,MAX>
::_modulate(const B *X_N1, R *X_N2, const int frame_id)
{
	auto size_in  = this->N;
	auto size_out = this->N_mod;

	auto loop_size = size_in / this->bits_per_symbol;
	for (auto i = 0; i < loop_size; i++)
	{
		unsigned idx = 0;
		for (auto j = 0; j < this->bits_per_symbol; j++)
			idx += unsigned(unsigned(1 << (this->bits_per_symbol -j -1)) * X_N1[i * this->bits_per_symbol +j]);
		auto symbol = this->constellation[idx];

		X_N2[2*i   ] = symbol.real();
		X_N2[2*i +1] = symbol.imag();
	}

	// last elements if "size_in" is not a multiple of the number of bits per symbol
	if (loop_size * this->bits_per_symbol < size_in)
	{
		unsigned idx = 0;
		for (auto j = 0; j < size_in - (loop_size * this->bits_per_symbol); j++)
			idx += unsigned(unsigned(1 << (this->bits_per_symbol -j -1)) * X_N1[loop_size * this->bits_per_symbol +j]);
		auto symbol = this->constellation[idx];

		X_N2[size_out -2] = symbol.real();
		X_N2[size_out -1] = symbol.imag();
	}
}

/*
 * Filter
 */
template <typename B,typename R, typename Q, tools::proto_max<Q> MAX>
void Modem_user<B,R,Q,MAX>
::_filter(const R *Y_N1, R *Y_N2, const int frame_id)
{
	std::copy(Y_N1, Y_N1 + this->N_fil, Y_N2);
}

/*
 * Demodulator
 */
template <typename B,typename R, typename Q, tools::proto_max<Q> MAX>
void Modem_user<B,R,Q,MAX>
::_demodulate(const Q *Y_N1, Q *Y_N2, const int frame_id)
{
	if (typeid(R) != typeid(Q))
		throw tools::invalid_argument(__FILE__, __LINE__, __func__, "Type 'R' and 'Q' have to be the same.");

	if (typeid(Q) != typeid(float) && typeid(Q) != typeid(double))
		throw tools::invalid_argument(__FILE__, __LINE__, __func__, "Type 'Q' has to be float or double.");

	auto size       = this->N;
	auto inv_sigma2 = disable_sig2 ? (Q)1.0 : (Q)(1.0 / (this->sigma * this->sigma));

	for (auto n = 0; n < size; n++) // loop upon the LLRs
	{
		auto L0 = -std::numeric_limits<Q>::infinity();
		auto L1 = -std::numeric_limits<Q>::infinity();

		auto b  = n % this->bits_per_symbol; // bit position in the symbol
		auto k  = n / this->bits_per_symbol; // symbol position

		auto complex_Yk = std::complex<Q>(Y_N1[2*k], Y_N1[2*k+1]);

		for (auto j = 0; j < this->nbr_symbols; j++)
			if ((j &(1 << (this->bits_per_symbol -b -1))) == 0)
				L0 = MAX(L0, -std::norm(complex_Yk - std::complex<Q>((Q)this->constellation[j].real(),
				                                                     (Q)this->constellation[j].imag())) * inv_sigma2);
			else
				L1 = MAX(L1, -std::norm(complex_Yk - std::complex<Q>((Q)this->constellation[j].real(),
				                                                     (Q)this->constellation[j].imag())) * inv_sigma2);

		Y_N2[n] = (L0 - L1);
	}
}

/*
 * Demodulator
 */
template <typename B,typename R, typename Q, tools::proto_max<Q> MAX>
void Modem_user<B,R,Q,MAX>
::_demodulate_with_gains(const Q *Y_N1, const R *H_N, Q *Y_N2, const int frame_id)
{
	if (typeid(R) != typeid(Q))
		throw tools::invalid_argument(__FILE__, __LINE__, __func__, "Type 'R' and 'Q' have to be the same.");

	if (typeid(Q) != typeid(float) && typeid(Q) != typeid(double))
		throw tools::invalid_argument(__FILE__, __LINE__, __func__, "Type 'Q' has to be float or double.");

	auto size       = this->N;
	auto inv_sigma2 = disable_sig2 ? (Q)1.0 : (Q)(1.0 / (this->sigma * this->sigma));

	for (auto n = 0; n < size; n++) // loop upon the LLRs
	{
		auto L0 = -std::numeric_limits<Q>::infinity();
		auto L1 = -std::numeric_limits<Q>::infinity();

		auto b  = n % this->bits_per_symbol; // bit position in the symbol
		auto k  = n / this->bits_per_symbol; // symbol position

		auto complex_Yk = std::complex<Q>(   Y_N1[2*k],    Y_N1[2*k+1]);
		auto complex_Hk = std::complex<Q>((Q)H_N [2*k], (Q)H_N [2*k+1]);

		for (auto j = 0; j < this->nbr_symbols; j++)
			if ((j &(1 << (this->bits_per_symbol -b -1))) == 0)
				L0 = MAX(L0, -std::norm(complex_Yk -
				                        complex_Hk * std::complex<Q>((Q)this->constellation[j].real(),
				                                                     (Q)this->constellation[j].imag())) * inv_sigma2);
			else
				L1 = MAX(L1, -std::norm(complex_Yk -
				                        complex_Hk * std::complex<Q>((Q)this->constellation[j].real(),
				                                                     (Q)this->constellation[j].imag())) * inv_sigma2);

		Y_N2[n] = (L0 - L1);
	}
}

template <typename B, typename R, typename Q, tools::proto_max<Q> MAX>
void Modem_user<B,R,Q,MAX>
::_demodulate(const Q *Y_N1, const Q *Y_N2, Q *Y_N3, const int frame_id)
{
	if (typeid(R) != typeid(Q))
		throw tools::invalid_argument(__FILE__, __LINE__, __func__, "Type 'R' and 'Q' have to be the same.");

	if (typeid(Q) != typeid(float) && typeid(Q) != typeid(double))
		throw tools::invalid_argument(__FILE__, __LINE__, __func__, "Type 'Q' has to be float or double.");

	auto size       = this->N;
	auto inv_sigma2 = disable_sig2 ? (Q)1.0 : (Q)1.0 / (this->sigma * this->sigma);

	for (auto n = 0; n < size; n++) // loop upon the LLRs
	{
		auto L0 = -std::numeric_limits<Q>::infinity();
		auto L1 = -std::numeric_limits<Q>::infinity();
		auto b  = n % this->bits_per_symbol; // bit position in the symbol
		auto k  = n / this->bits_per_symbol; // symbol position

		auto complex_Yk = std::complex<Q>(Y_N1[2*k], Y_N1[2*k+1]);

		for (auto j = 0; j < this->nbr_symbols; j++)
		{
			auto tempL = (Q)(std::norm(complex_Yk - std::complex<Q>((Q)this->constellation[j].real(),
			                                                        (Q)this->constellation[j].imag())) * inv_sigma2);

			for (auto l = 0; l < b; l++)
				tempL += (j & (1 << (this->bits_per_symbol -l -1))) * Y_N2[k * this->bits_per_symbol +l];

			for (auto l = b + 1; l < this->bits_per_symbol; l++)
				tempL += (j & (1 << (this->bits_per_symbol -l -1))) * Y_N2[k * this->bits_per_symbol +l];

			if ((j & (1 << (this->bits_per_symbol-b-1))) == 0)
				L0 = MAX(L0, -tempL);
			else
				L1 = MAX(L1, -tempL);
		}

		Y_N3[n] = (L0 - L1);
	}
}

template <typename B, typename R, typename Q, tools::proto_max<Q> MAX>
void Modem_user<B,R,Q,MAX>
::_demodulate_with_gains(const Q *Y_N1, const R *H_N, const Q *Y_N2, Q *Y_N3, const int frame_id)
{
	if (typeid(R) != typeid(Q))
		throw tools::invalid_argument(__FILE__, __LINE__, __func__, "Type 'R' and 'Q' have to be the same.");

	if (typeid(Q) != typeid(float) && typeid(Q) != typeid(double))
		throw tools::invalid_argument(__FILE__, __LINE__, __func__, "Type 'Q' has to be float or double.");

	auto size       = this->N;
	auto inv_sigma2 = disable_sig2 ? (Q)1.0 : (Q)1.0 / (this->sigma * this->sigma);

	for (auto n = 0; n < size; n++) // loop upon the LLRs
	{
		auto L0 = -std::numeric_limits<Q>::infinity();
		auto L1 = -std::numeric_limits<Q>::infinity();
		auto b  = n % this->bits_per_symbol; // bit position in the symbol
		auto k  = n / this->bits_per_symbol; // symbol position

		auto complex_Yk = std::complex<Q>(   Y_N1[2*k],    Y_N1[2*k+1]);
		auto complex_Hk = std::complex<Q>((Q)H_N [2*k], (Q)H_N [2*k+1]);

		for (auto j = 0; j < this->nbr_symbols; j++)
		{
			auto tempL = (Q)(std::norm(complex_Yk -
			                           complex_Hk * std::complex<Q>((Q)this->constellation[j].real(),
			                                                        (Q)this->constellation[j].imag())) * inv_sigma2);

			for (auto l = 0; l < b; l++)
				tempL += (j & (1 << (this->bits_per_symbol -l -1))) * Y_N2[k * this->bits_per_symbol +l];

			for (auto l = b + 1; l < this->bits_per_symbol; l++)
				tempL += (j & (1 << (this->bits_per_symbol -l -1))) * Y_N2[k * this->bits_per_symbol +l];

			if ((j & (1 << (this->bits_per_symbol-b-1))) == 0)
				L0 = MAX(L0, -tempL);
			else
				L1 = MAX(L1, -tempL);
		}

		Y_N3[n] = (L0 - L1);
	}
}
}
}
<|endoftext|>


<commit_before>// Copyright (C) 2017 Jérôme Leclercq
// This file is part of the "Nazara Engine - Core module"
// For conditions of distribution and use, see copyright notice in Config.hpp

#include <Nazara/Core/Win32/ThreadImpl.hpp>
#include <Nazara/Core/Error.hpp>
#include <Nazara/Core/Functor.hpp>
#include <process.h>
#include <windows.h>
#include <Nazara/Core/Debug.hpp>

namespace Nz
{
	namespace
	{
#pragma pack(push,8)
		struct THREADNAME_INFO
		{
			DWORD dwType;
			LPCSTR szName;
			DWORD dwThreadID;
			DWORD dwFlags;
		};
#pragma pack(pop)
	}

	ThreadImpl::ThreadImpl(Functor* functor)
	{
		unsigned int threadId;
		m_handle = reinterpret_cast<HANDLE>(_beginthreadex(nullptr, 0, &ThreadImpl::ThreadProc, functor, 0, &threadId));
		if (!m_handle)
			NazaraInternalError("Failed to create thread: " + Error::GetLastSystemError());

		m_threadId = threadId;
	}

	void ThreadImpl::Detach()
	{
		// http://stackoverflow.com/questions/418742/is-it-reasonable-to-call-closehandle-on-a-thread-before-it-terminates
		CloseHandle(m_handle);
	}

	void ThreadImpl::Join()
	{
		WaitForSingleObject(m_handle, INFINITE);
		CloseHandle(m_handle);
	}

	void ThreadImpl::SetName(const Nz::String& name)
	{
		SetThreadName(m_threadId, name.GetConstBuffer());
	}

	void ThreadImpl::SetCurrentName(const Nz::String& name)
	{
		SetThreadName(::GetCurrentThreadId(), name.GetConstBuffer());
	}

	void ThreadImpl::Sleep(UInt32 time)
	{
		::Sleep(time);
	}

	void ThreadImpl::SetThreadName(DWORD threadId, const char* threadName)
	{
		// https://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx
		constexpr DWORD MS_VC_EXCEPTION = 0x406D1388;

		THREADNAME_INFO info;
		info.dwType = 0x1000;
		info.szName = threadName;
		info.dwThreadID = threadId;
		info.dwFlags = 0;

#pragma warning(push)
#pragma warning(disable: 6320 6322)
		__try
		{
			RaiseException(MS_VC_EXCEPTION, 0, sizeof(info) / sizeof(ULONG_PTR), reinterpret_cast<ULONG_PTR*>(&info));
		}
		__except (EXCEPTION_EXECUTE_HANDLER)
		{
		}
#pragma warning(pop)
	}

	unsigned int __stdcall ThreadImpl::ThreadProc(void* userdata)
	{
		Functor* func = static_cast<Functor*>(userdata);
		func->Run();
		delete func;

		/*
		En C++, il vaut mieux retourner depuis la fonction que de quitter le thread explicitement
		Source : http://msdn.microsoft.com/en-us/library/windows/desktop/ms682659(v=vs.85).aspx
		*/

		return 0;
	}
}
<commit_msg>Fix compilation with MinGW<commit_after>// Copyright (C) 2017 Jérôme Leclercq
// This file is part of the "Nazara Engine - Core module"
// For conditions of distribution and use, see copyright notice in Config.hpp

#include <Nazara/Core/Win32/ThreadImpl.hpp>
#include <Nazara/Core/Error.hpp>
#include <Nazara/Core/Functor.hpp>
#include <process.h>
#include <windows.h>
#include <Nazara/Core/Debug.hpp>

namespace Nz
{
	namespace
	{
#pragma pack(push,8)
		struct THREADNAME_INFO
		{
			DWORD dwType;
			LPCSTR szName;
			DWORD dwThreadID;
			DWORD dwFlags;
		};
#pragma pack(pop)
	}

	ThreadImpl::ThreadImpl(Functor* functor)
	{
		unsigned int threadId;
		m_handle = reinterpret_cast<HANDLE>(_beginthreadex(nullptr, 0, &ThreadImpl::ThreadProc, functor, 0, &threadId));
		if (!m_handle)
			NazaraInternalError("Failed to create thread: " + Error::GetLastSystemError());

		m_threadId = threadId;
	}

	void ThreadImpl::Detach()
	{
		// http://stackoverflow.com/questions/418742/is-it-reasonable-to-call-closehandle-on-a-thread-before-it-terminates
		CloseHandle(m_handle);
	}

	void ThreadImpl::Join()
	{
		WaitForSingleObject(m_handle, INFINITE);
		CloseHandle(m_handle);
	}

	void ThreadImpl::SetName(const Nz::String& name)
	{
		SetThreadName(m_threadId, name.GetConstBuffer());
	}

	void ThreadImpl::SetCurrentName(const Nz::String& name)
	{
		SetThreadName(::GetCurrentThreadId(), name.GetConstBuffer());
	}

	void ThreadImpl::Sleep(UInt32 time)
	{
		::Sleep(time);
	}

	void ThreadImpl::SetThreadName(DWORD threadId, const char* threadName)
	{
		#ifdef NAZARA_COMPILER_MSVC
		// https://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx
		constexpr DWORD MS_VC_EXCEPTION = 0x406D1388;

		THREADNAME_INFO info;
		info.dwType = 0x1000;
		info.szName = threadName;
		info.dwThreadID = threadId;
		info.dwFlags = 0;

		#pragma warning(push)
		#pragma warning(disable: 6320 6322)
		__try
		{
			RaiseException(MS_VC_EXCEPTION, 0, sizeof(info) / sizeof(ULONG_PTR), reinterpret_cast<ULONG_PTR*>(&info));
		}
		__except (EXCEPTION_EXECUTE_HANDLER)
		{
		}
		#pragma warning(pop)
		#else
		NazaraWarning("SetThreadName on Windows is only supported with MSVC for now");
		#endif
	}

	unsigned int __stdcall ThreadImpl::ThreadProc(void* userdata)
	{
		Functor* func = static_cast<Functor*>(userdata);
		func->Run();
		delete func;

		/*
		En C++, il vaut mieux retourner depuis la fonction que de quitter le thread explicitement
		Source : http://msdn.microsoft.com/en-us/library/windows/desktop/ms682659(v=vs.85).aspx
		*/

		return 0;
	}
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
 */

#include <string>
#include <vector>
#include <base/logging.h>
#include <base/lifetime.h>
#include <base/misc_utils.h>
#include <io/event_manager.h>
#include <ifmap/ifmap_link.h>

#include <vnc_cfg_types.h>
#include <cmn/agent_cmn.h>
#include <cmn/agent_stats.h>

#include <init/agent_param.h>
#include <init/agent_init.h>
#include <cfg/cfg_init.h>
#include <cfg/cfg_mirror.h>
#include <cfg/discovery_agent.h>

#include <oper/operdb_init.h>
#include <oper/interface_common.h>
#include <oper/multicast.h>
#include <oper/nexthop.h>
#include <oper/mirror_table.h>

#include <ksync/ksync_init.h>
#include <services/services_init.h>
#include <pkt/pkt_init.h>
#include <pkt/flow_table.h>
#include <pkt/pkt_types.h>
#include <pkt/proto.h>
#include <pkt/proto_handler.h>
#include <uve/flow_stats_collector.h>
#include <uve/agent_uve.h>
#include <uve/agent_uve_test.h>
#include <vgw/vgw.h>

#include <diag/diag.h>

const std::string Agent::null_str_ = "";
const std::string Agent::fabric_vn_name_ =
    "default-domain:default-project:ip-fabric";
const std::string Agent::fabric_vrf_name_ =
    "default-domain:default-project:ip-fabric:__default__";
const std::string Agent::link_local_vn_name_ =
    "default-domain:default-project:__link_local__";
const std::string Agent::link_local_vrf_name_ =
    "default-domain:default-project:__link_local__:__link_local__";
const std::string Agent::vrrp_mac_ = "00:00:5E:00:01:00";
const std::string Agent::bcast_mac_ = "FF:FF:FF:FF:FF:FF";

Agent *Agent::singleton_;

const string &Agent::GetHostInterfaceName() {
    // There is single host interface.  Its addressed by type and not name
    return Agent::null_str_;
};

const string &Agent::vhost_interface_name() const {
    return vhost_interface_name_;
};

const string &Agent::GetHostName() {
    return host_name_;
};

bool Agent::isXenMode() {
    return params_->isXenMode();
}

static void SetTaskPolicyOne(const char *task, const char *exclude_list[],
                             int count) {
    TaskScheduler *scheduler = TaskScheduler::GetInstance();
    TaskPolicy policy;
    for (int i = 0; i < count; ++i) {
        int task_id = scheduler->GetTaskId(exclude_list[i]);
        policy.push_back(TaskExclusion(task_id));
    }
    scheduler->SetPolicy(scheduler->GetTaskId(task), policy);
}

void Agent::SetAgentTaskPolicy() {
    const char *db_exclude_list[] = {
        "Agent::FlowHandler",
        "Agent::Services",
        "Agent::StatsCollector",
        "sandesh::RecvQueue",
        "io::ReaderTask",
        "Agent::Uve",
        "Agent::KSync",
        "Agent::PktFlowResponder"
    };
    SetTaskPolicyOne("db::DBTable", db_exclude_list,
                     sizeof(db_exclude_list) / sizeof(char *));

    const char *flow_exclude_list[] = {
        "Agent::StatsCollector",
        "io::ReaderTask",
        "Agent::PktFlowResponder"
    };
    SetTaskPolicyOne("Agent::FlowHandler", flow_exclude_list,
                     sizeof(flow_exclude_list) / sizeof(char *));

    const char *sandesh_exclude_list[] = {
        "db::DBTable",
        "Agent::FlowHandler",
        "Agent::Services",
        "Agent::StatsCollector",
        "io::ReaderTask",
        "Agent::PktFlowResponder"
    };
    SetTaskPolicyOne("sandesh::RecvQueue", sandesh_exclude_list,
                     sizeof(sandesh_exclude_list) / sizeof(char *));

    const char *xmpp_config_exclude_list[] = {
        "Agent::FlowHandler",
        "Agent::Services",
        "Agent::StatsCollector",
        "sandesh::RecvQueue",
        "io::ReaderTask",
        "xmpp::StateMachine",
        "db::DBTable"
    };
    SetTaskPolicyOne("bgp::Config", xmpp_config_exclude_list,
                     sizeof(xmpp_config_exclude_list) / sizeof(char *));

    const char *xmpp_state_machine_exclude_list[] = {
        "io::ReaderTask",
        "db::DBTable"
    };
    SetTaskPolicyOne("xmpp::StateMachine", xmpp_state_machine_exclude_list,
                     sizeof(xmpp_state_machine_exclude_list) / sizeof(char *));

    const char *ksync_exclude_list[] = {
        "Agent::FlowHandler",
        "Agent::StatsCollector",
        "db::DBTable",
        "Agent::PktFlowResponder"
    };
    SetTaskPolicyOne("Agent::KSync", ksync_exclude_list,
                     sizeof(ksync_exclude_list) / sizeof(char *));
}

void Agent::CreateLifetimeManager() {
    lifetime_manager_ = new LifetimeManager(
            TaskScheduler::GetInstance()->GetTaskId("db::DBTable"));
}

void Agent::ShutdownLifetimeManager() {
    delete lifetime_manager_;
    lifetime_manager_ = NULL;
}

// Get configuration from AgentParam into Agent
void Agent::GetConfig() {
    int count = 0;
    int dns_count = 0;

    if (params_->xmpp_server_1().to_ulong()) {
        SetAgentMcastLabelRange(count);
        xs_addr_[count++] = params_->xmpp_server_1().to_string();
    }

    if (params_->xmpp_server_2().to_ulong()) {
        SetAgentMcastLabelRange(count);
        xs_addr_[count++] = params_->xmpp_server_2().to_string();
    }

    if (params_->dns_server_1().to_ulong()) {
        xs_dns_addr_[dns_count++] = params_->dns_server_1().to_string();
    }

    if (params_->dns_server_2().to_ulong()) {
        xs_dns_addr_[dns_count++] = params_->dns_server_2().to_string();
    }

    if (params_->discovery_server().to_ulong()) {
        dss_addr_ = params_->discovery_server().to_string();
        dss_xs_instances_ = params_->xmpp_instance_count();
    }

    vhost_interface_name_ = params_->vhost_name();
    ip_fabric_intf_name_ = params_->eth_port();
    host_name_ = params_->host_name();
    prog_name_ = params_->program_name();
    sandesh_port_ = params_->http_server_port();
    prefix_len_ = params_->vhost_plen();
    gateway_id_ = params_->vhost_gw();
    router_id_ = params_->vhost_addr();
    if (router_id_.to_ulong()) {
        router_id_configured_ = false;
    }

    if (params_->tunnel_type() == "MPLSoUDP")
        TunnelType::SetDefaultType(TunnelType::MPLS_UDP);
    else if (params_->tunnel_type() == "VXLAN")
        TunnelType::SetDefaultType(TunnelType::VXLAN);
    else
        TunnelType::SetDefaultType(TunnelType::MPLS_GRE);
}

DiscoveryAgentClient *Agent::discovery_client() const {
    return cfg_.get()->discovery_client();
}

CfgListener *Agent::cfg_listener() const {
    return cfg_.get()->cfg_listener();
}

void Agent::CreateModules() {
    Sandesh::SetLoggingParams(params_->log_local(),
                              params_->log_category(),
                              params_->log_level());
    if (dss_addr_.empty()) {
        Module::type module = Module::VROUTER_AGENT;
        NodeType::type node_type =
            g_vns_constants.Module2NodeType.find(module)->second;
        Sandesh::InitGenerator(
            g_vns_constants.ModuleNames.find(module)->second,
            params_->host_name(),
            g_vns_constants.NodeTypeNames.find(node_type)->second,
            g_vns_constants.INSTANCE_ID_DEFAULT,
            GetEventManager(),
            params_->http_server_port());

        if (params_->collector_port() != 0 &&
            !params_->collector().to_ulong() != 0) {
            Sandesh::ConnectToCollector(params_->collector().to_string(),
                                        params_->collector_port());
        }
    }

    cfg_ = std::auto_ptr<AgentConfig>(new AgentConfig(this));
    stats_ = std::auto_ptr<AgentStats>(new AgentStats(this));
    oper_db_ = std::auto_ptr<OperDB>(new OperDB(this));
    if (IsTestMode()) {
        uve_ = std::auto_ptr<AgentUve>(new AgentUveTest(
                    this, AgentUve::kBandwidthInterval));
    } else {
        uve_ = std::auto_ptr<AgentUve>(new AgentUve(
                    this, AgentUve::kBandwidthInterval));
    }
    ksync_ = std::auto_ptr<KSync>(new KSync(this));

    if (init_->packet_enable()) {
        pkt_ = std::auto_ptr<PktModule>(new PktModule(this));
    }

    if (init_->services_enable()) {
        services_ = std::auto_ptr<ServicesModule>(new ServicesModule(
                    this, params_->metadata_shared_secret()));
    }

    if (init_->vgw_enable()) {
        vgw_ = std::auto_ptr<VirtualGateway>(new VirtualGateway(this));
    }
}

void Agent::CreateDBTables() {
    cfg_.get()->CreateDBTables(db_);
    oper_db_.get()->CreateDBTables(db_);
}

void Agent::CreateDBClients() {
    cfg_.get()->RegisterDBClients(db_);
    oper_db_.get()->CreateDBClients();
    uve_.get()->RegisterDBClients();
    if (!test_mode_) {
        ksync_.get()->RegisterDBClients(db_);
    } else {
        ksync_.get()->RegisterDBClientsTest(db_);
    }

    if (vgw_.get()) {
        vgw_.get()->RegisterDBClients();
    }

}

void Agent::InitModules() {
    // Create peer entries
    local_peer_.reset(new Peer(Peer::LOCAL_PEER, LOCAL_PEER_NAME));
    local_vm_peer_.reset(new Peer(Peer::LOCAL_VM_PEER, LOCAL_VM_PEER_NAME));
    linklocal_peer_.reset(new Peer(Peer::LINKLOCAL_PEER, LINKLOCAL_PEER_NAME));
    ecmp_peer_.reset(new Peer(Peer::ECMP_PEER, ECMP_PEER_NAME));

    if (!test_mode_) {
        ksync_.get()->NetlinkInit();
        ksync_.get()->VRouterInterfaceSnapshot();
        ksync_.get()->InitFlowMem();
        ksync_.get()->ResetVRouter();
        if (init_->create_vhost()) {
            ksync_.get()->CreateVhostIntf();
        }
        ksync_.get()->Init();
    } else {
        ksync_.get()->InitTest();
        ksync_.get()->NetlinkInitTest(ksync_sync_mode_);
    }

    if (pkt_.get()) {
        pkt_.get()->Init(init_->ksync_enable());
    }

    if (services_.get()) {
        services_.get()->Init(init_->ksync_enable());
    }

    cfg_.get()->Init();
    oper_db_.get()->Init();
    uve_.get()->Init();
}

void Agent::CreateVrf() {
    // Create the default VRF
    init_->CreateDefaultVrf();

    // Create VRF for VGw
    if (vgw_.get()) {
        vgw_.get()->CreateVrf();
    }
}

void Agent::CreateNextHops() {
    init_->CreateDefaultNextHops();
}

void Agent::CreateInterfaces() {
    if (pkt_.get()) {
        pkt_.get()->CreateInterfaces();
    }

    init_->CreateInterfaces(db_);
    cfg_.get()->CreateInterfaces();

    // Create VRF for VGw
    if (vgw_.get()) {
        vgw_.get()->CreateInterfaces();
    }

}

void Agent::InitDone() {
    //Open up mirror socket
    mirror_table_->MirrorSockInit();

    if (services_.get()) {
        services_.get()->ConfigInit();
    }

    // Diag module needs PktModule
    if (pkt_.get()) {
        diag_table_ = std::auto_ptr<DiagTable>(new DiagTable(this));
    }

    if (init_->create_vhost()) {
        //Update mac address of vhost interface with
        //that of ethernet interface
        ksync_.get()->UpdateVhostMac();
    }

    if (init_->ksync_enable()) {
        ksync_.get()->VnswInterfaceListenerInit();
    }

    if (init_->router_id_dep_enable() && GetRouterIdConfigured()) {
        RouterIdDepInit();
    } else {
        LOG(DEBUG,
            "Router ID Dependent modules (Nova & BGP) not initialized");
    }

    cfg_.get()->InitDone();
}

void Agent::Init(AgentParam *param, AgentInit *init) {
    params_ = param;
    init_ = init;
    GetConfig();
    // Start initialization state-machine
    init_->Start();
}

Agent::Agent() :
    params_(NULL), init_(NULL), event_mgr_(NULL), agent_xmpp_channel_(),
    ifmap_channel_(), xmpp_client_(), xmpp_init_(), dns_xmpp_channel_(),
    dns_xmpp_client_(), dns_xmpp_init_(), agent_stale_cleaner_(NULL),
    cn_mcast_builder_(NULL), ds_client_(NULL), host_name_(""),
    prog_name_(""), sandesh_port_(0), db_(NULL), intf_table_(NULL),
    nh_table_(NULL), uc_rt_table_(NULL), mc_rt_table_(NULL), vrf_table_(NULL),
    vm_table_(NULL), vn_table_(NULL), sg_table_(NULL), addr_table_(NULL),
    mpls_table_(NULL), acl_table_(NULL), mirror_table_(NULL),
    vrf_assign_table_(NULL), mirror_cfg_table_(NULL),
    intf_mirror_cfg_table_(NULL), intf_cfg_table_(NULL),
    domain_config_table_(NULL), router_id_(0), prefix_len_(0),
    gateway_id_(0), xs_cfg_addr_(""), xs_idx_(0), xs_addr_(), xs_port_(),
    xs_stime_(), xs_dns_idx_(0), xs_dns_addr_(), xs_dns_port_(),
    dss_addr_(""), dss_port_(0), dss_xs_instances_(0), label_range_(),
    ip_fabric_intf_name_(""), vhost_interface_name_(""),
    pkt_interface_name_("pkt0"), cfg_listener_(NULL), arp_proto_(NULL),
    dhcp_proto_(NULL), dns_proto_(NULL), icmp_proto_(NULL), flow_proto_(NULL),
    local_peer_(NULL), local_vm_peer_(NULL), linklocal_peer_(NULL),
    ifmap_parser_(NULL), router_id_configured_(false),
    mirror_src_udp_port_(0), lifetime_manager_(NULL), test_mode_(false),
    ksync_sync_mode_(true), mgmt_ip_(""),
    vxlan_network_identifier_mode_(AUTOMATIC) {

    assert(singleton_ == NULL);
    singleton_ = this;
    db_ = new DB();
    assert(db_);

    event_mgr_ = new EventManager();
    assert(event_mgr_);

    SetAgentTaskPolicy();
    CreateLifetimeManager();
}

Agent::~Agent() {
    delete event_mgr_;
    event_mgr_ = NULL;

    ShutdownLifetimeManager();

    delete db_;
    db_ = NULL;
}

<commit_msg>Adding task exclusion between stats_collector and PktFlowResponder to ensure synchronized access<commit_after>/*
 * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
 */

#include <string>
#include <vector>
#include <base/logging.h>
#include <base/lifetime.h>
#include <base/misc_utils.h>
#include <io/event_manager.h>
#include <ifmap/ifmap_link.h>

#include <vnc_cfg_types.h>
#include <cmn/agent_cmn.h>
#include <cmn/agent_stats.h>

#include <init/agent_param.h>
#include <init/agent_init.h>
#include <cfg/cfg_init.h>
#include <cfg/cfg_mirror.h>
#include <cfg/discovery_agent.h>

#include <oper/operdb_init.h>
#include <oper/interface_common.h>
#include <oper/multicast.h>
#include <oper/nexthop.h>
#include <oper/mirror_table.h>

#include <ksync/ksync_init.h>
#include <services/services_init.h>
#include <pkt/pkt_init.h>
#include <pkt/flow_table.h>
#include <pkt/pkt_types.h>
#include <pkt/proto.h>
#include <pkt/proto_handler.h>
#include <uve/flow_stats_collector.h>
#include <uve/agent_uve.h>
#include <uve/agent_uve_test.h>
#include <vgw/vgw.h>

#include <diag/diag.h>

const std::string Agent::null_str_ = "";
const std::string Agent::fabric_vn_name_ =
    "default-domain:default-project:ip-fabric";
const std::string Agent::fabric_vrf_name_ =
    "default-domain:default-project:ip-fabric:__default__";
const std::string Agent::link_local_vn_name_ =
    "default-domain:default-project:__link_local__";
const std::string Agent::link_local_vrf_name_ =
    "default-domain:default-project:__link_local__:__link_local__";
const std::string Agent::vrrp_mac_ = "00:00:5E:00:01:00";
const std::string Agent::bcast_mac_ = "FF:FF:FF:FF:FF:FF";

Agent *Agent::singleton_;

const string &Agent::GetHostInterfaceName() {
    // There is single host interface.  Its addressed by type and not name
    return Agent::null_str_;
};

const string &Agent::vhost_interface_name() const {
    return vhost_interface_name_;
};

const string &Agent::GetHostName() {
    return host_name_;
};

bool Agent::isXenMode() {
    return params_->isXenMode();
}

static void SetTaskPolicyOne(const char *task, const char *exclude_list[],
                             int count) {
    TaskScheduler *scheduler = TaskScheduler::GetInstance();
    TaskPolicy policy;
    for (int i = 0; i < count; ++i) {
        int task_id = scheduler->GetTaskId(exclude_list[i]);
        policy.push_back(TaskExclusion(task_id));
    }
    scheduler->SetPolicy(scheduler->GetTaskId(task), policy);
}

void Agent::SetAgentTaskPolicy() {
    const char *db_exclude_list[] = {
        "Agent::FlowHandler",
        "Agent::Services",
        "Agent::StatsCollector",
        "sandesh::RecvQueue",
        "io::ReaderTask",
        "Agent::Uve",
        "Agent::KSync",
        "Agent::PktFlowResponder"
    };
    SetTaskPolicyOne("db::DBTable", db_exclude_list,
                     sizeof(db_exclude_list) / sizeof(char *));

    const char *flow_exclude_list[] = {
        "Agent::StatsCollector",
        "io::ReaderTask",
        "Agent::PktFlowResponder"
    };
    SetTaskPolicyOne("Agent::FlowHandler", flow_exclude_list,
                     sizeof(flow_exclude_list) / sizeof(char *));

    const char *sandesh_exclude_list[] = {
        "db::DBTable",
        "Agent::FlowHandler",
        "Agent::Services",
        "Agent::StatsCollector",
        "io::ReaderTask",
        "Agent::PktFlowResponder"
    };
    SetTaskPolicyOne("sandesh::RecvQueue", sandesh_exclude_list,
                     sizeof(sandesh_exclude_list) / sizeof(char *));

    const char *xmpp_config_exclude_list[] = {
        "Agent::FlowHandler",
        "Agent::Services",
        "Agent::StatsCollector",
        "sandesh::RecvQueue",
        "io::ReaderTask",
        "xmpp::StateMachine",
        "db::DBTable"
    };
    SetTaskPolicyOne("bgp::Config", xmpp_config_exclude_list,
                     sizeof(xmpp_config_exclude_list) / sizeof(char *));

    const char *xmpp_state_machine_exclude_list[] = {
        "io::ReaderTask",
        "db::DBTable"
    };
    SetTaskPolicyOne("xmpp::StateMachine", xmpp_state_machine_exclude_list,
                     sizeof(xmpp_state_machine_exclude_list) / sizeof(char *));

    const char *ksync_exclude_list[] = {
        "Agent::FlowHandler",
        "Agent::StatsCollector",
        "db::DBTable",
        "Agent::PktFlowResponder"
    };
    SetTaskPolicyOne("Agent::KSync", ksync_exclude_list,
                     sizeof(ksync_exclude_list) / sizeof(char *));

    const char *stats_collector_exclude_list[] = {
        "Agent::PktFlowResponder"
    };
    SetTaskPolicyOne("Agent::StatsCollector", stats_collector_exclude_list,
                     sizeof(stats_collector_exclude_list) / sizeof(char *));
}

void Agent::CreateLifetimeManager() {
    lifetime_manager_ = new LifetimeManager(
            TaskScheduler::GetInstance()->GetTaskId("db::DBTable"));
}

void Agent::ShutdownLifetimeManager() {
    delete lifetime_manager_;
    lifetime_manager_ = NULL;
}

// Get configuration from AgentParam into Agent
void Agent::GetConfig() {
    int count = 0;
    int dns_count = 0;

    if (params_->xmpp_server_1().to_ulong()) {
        SetAgentMcastLabelRange(count);
        xs_addr_[count++] = params_->xmpp_server_1().to_string();
    }

    if (params_->xmpp_server_2().to_ulong()) {
        SetAgentMcastLabelRange(count);
        xs_addr_[count++] = params_->xmpp_server_2().to_string();
    }

    if (params_->dns_server_1().to_ulong()) {
        xs_dns_addr_[dns_count++] = params_->dns_server_1().to_string();
    }

    if (params_->dns_server_2().to_ulong()) {
        xs_dns_addr_[dns_count++] = params_->dns_server_2().to_string();
    }

    if (params_->discovery_server().to_ulong()) {
        dss_addr_ = params_->discovery_server().to_string();
        dss_xs_instances_ = params_->xmpp_instance_count();
    }

    vhost_interface_name_ = params_->vhost_name();
    ip_fabric_intf_name_ = params_->eth_port();
    host_name_ = params_->host_name();
    prog_name_ = params_->program_name();
    sandesh_port_ = params_->http_server_port();
    prefix_len_ = params_->vhost_plen();
    gateway_id_ = params_->vhost_gw();
    router_id_ = params_->vhost_addr();
    if (router_id_.to_ulong()) {
        router_id_configured_ = false;
    }

    if (params_->tunnel_type() == "MPLSoUDP")
        TunnelType::SetDefaultType(TunnelType::MPLS_UDP);
    else if (params_->tunnel_type() == "VXLAN")
        TunnelType::SetDefaultType(TunnelType::VXLAN);
    else
        TunnelType::SetDefaultType(TunnelType::MPLS_GRE);
}

DiscoveryAgentClient *Agent::discovery_client() const {
    return cfg_.get()->discovery_client();
}

CfgListener *Agent::cfg_listener() const {
    return cfg_.get()->cfg_listener();
}

void Agent::CreateModules() {
    Sandesh::SetLoggingParams(params_->log_local(),
                              params_->log_category(),
                              params_->log_level());
    if (dss_addr_.empty()) {
        Module::type module = Module::VROUTER_AGENT;
        NodeType::type node_type =
            g_vns_constants.Module2NodeType.find(module)->second;
        Sandesh::InitGenerator(
            g_vns_constants.ModuleNames.find(module)->second,
            params_->host_name(),
            g_vns_constants.NodeTypeNames.find(node_type)->second,
            g_vns_constants.INSTANCE_ID_DEFAULT,
            GetEventManager(),
            params_->http_server_port());

        if (params_->collector_port() != 0 &&
            !params_->collector().to_ulong() != 0) {
            Sandesh::ConnectToCollector(params_->collector().to_string(),
                                        params_->collector_port());
        }
    }

    cfg_ = std::auto_ptr<AgentConfig>(new AgentConfig(this));
    stats_ = std::auto_ptr<AgentStats>(new AgentStats(this));
    oper_db_ = std::auto_ptr<OperDB>(new OperDB(this));
    if (IsTestMode()) {
        uve_ = std::auto_ptr<AgentUve>(new AgentUveTest(
                    this, AgentUve::kBandwidthInterval));
    } else {
        uve_ = std::auto_ptr<AgentUve>(new AgentUve(
                    this, AgentUve::kBandwidthInterval));
    }
    ksync_ = std::auto_ptr<KSync>(new KSync(this));

    if (init_->packet_enable()) {
        pkt_ = std::auto_ptr<PktModule>(new PktModule(this));
    }

    if (init_->services_enable()) {
        services_ = std::auto_ptr<ServicesModule>(new ServicesModule(
                    this, params_->metadata_shared_secret()));
    }

    if (init_->vgw_enable()) {
        vgw_ = std::auto_ptr<VirtualGateway>(new VirtualGateway(this));
    }
}

void Agent::CreateDBTables() {
    cfg_.get()->CreateDBTables(db_);
    oper_db_.get()->CreateDBTables(db_);
}

void Agent::CreateDBClients() {
    cfg_.get()->RegisterDBClients(db_);
    oper_db_.get()->CreateDBClients();
    uve_.get()->RegisterDBClients();
    if (!test_mode_) {
        ksync_.get()->RegisterDBClients(db_);
    } else {
        ksync_.get()->RegisterDBClientsTest(db_);
    }

    if (vgw_.get()) {
        vgw_.get()->RegisterDBClients();
    }

}

void Agent::InitModules() {
    // Create peer entries
    local_peer_.reset(new Peer(Peer::LOCAL_PEER, LOCAL_PEER_NAME));
    local_vm_peer_.reset(new Peer(Peer::LOCAL_VM_PEER, LOCAL_VM_PEER_NAME));
    linklocal_peer_.reset(new Peer(Peer::LINKLOCAL_PEER, LINKLOCAL_PEER_NAME));
    ecmp_peer_.reset(new Peer(Peer::ECMP_PEER, ECMP_PEER_NAME));

    if (!test_mode_) {
        ksync_.get()->NetlinkInit();
        ksync_.get()->VRouterInterfaceSnapshot();
        ksync_.get()->InitFlowMem();
        ksync_.get()->ResetVRouter();
        if (init_->create_vhost()) {
            ksync_.get()->CreateVhostIntf();
        }
        ksync_.get()->Init();
    } else {
        ksync_.get()->InitTest();
        ksync_.get()->NetlinkInitTest(ksync_sync_mode_);
    }

    if (pkt_.get()) {
        pkt_.get()->Init(init_->ksync_enable());
    }

    if (services_.get()) {
        services_.get()->Init(init_->ksync_enable());
    }

    cfg_.get()->Init();
    oper_db_.get()->Init();
    uve_.get()->Init();
}

void Agent::CreateVrf() {
    // Create the default VRF
    init_->CreateDefaultVrf();

    // Create VRF for VGw
    if (vgw_.get()) {
        vgw_.get()->CreateVrf();
    }
}

void Agent::CreateNextHops() {
    init_->CreateDefaultNextHops();
}

void Agent::CreateInterfaces() {
    if (pkt_.get()) {
        pkt_.get()->CreateInterfaces();
    }

    init_->CreateInterfaces(db_);
    cfg_.get()->CreateInterfaces();

    // Create VRF for VGw
    if (vgw_.get()) {
        vgw_.get()->CreateInterfaces();
    }

}

void Agent::InitDone() {
    //Open up mirror socket
    mirror_table_->MirrorSockInit();

    if (services_.get()) {
        services_.get()->ConfigInit();
    }

    // Diag module needs PktModule
    if (pkt_.get()) {
        diag_table_ = std::auto_ptr<DiagTable>(new DiagTable(this));
    }

    if (init_->create_vhost()) {
        //Update mac address of vhost interface with
        //that of ethernet interface
        ksync_.get()->UpdateVhostMac();
    }

    if (init_->ksync_enable()) {
        ksync_.get()->VnswInterfaceListenerInit();
    }

    if (init_->router_id_dep_enable() && GetRouterIdConfigured()) {
        RouterIdDepInit();
    } else {
        LOG(DEBUG,
            "Router ID Dependent modules (Nova & BGP) not initialized");
    }

    cfg_.get()->InitDone();
}

void Agent::Init(AgentParam *param, AgentInit *init) {
    params_ = param;
    init_ = init;
    GetConfig();
    // Start initialization state-machine
    init_->Start();
}

Agent::Agent() :
    params_(NULL), init_(NULL), event_mgr_(NULL), agent_xmpp_channel_(),
    ifmap_channel_(), xmpp_client_(), xmpp_init_(), dns_xmpp_channel_(),
    dns_xmpp_client_(), dns_xmpp_init_(), agent_stale_cleaner_(NULL),
    cn_mcast_builder_(NULL), ds_client_(NULL), host_name_(""),
    prog_name_(""), sandesh_port_(0), db_(NULL), intf_table_(NULL),
    nh_table_(NULL), uc_rt_table_(NULL), mc_rt_table_(NULL), vrf_table_(NULL),
    vm_table_(NULL), vn_table_(NULL), sg_table_(NULL), addr_table_(NULL),
    mpls_table_(NULL), acl_table_(NULL), mirror_table_(NULL),
    vrf_assign_table_(NULL), mirror_cfg_table_(NULL),
    intf_mirror_cfg_table_(NULL), intf_cfg_table_(NULL),
    domain_config_table_(NULL), router_id_(0), prefix_len_(0),
    gateway_id_(0), xs_cfg_addr_(""), xs_idx_(0), xs_addr_(), xs_port_(),
    xs_stime_(), xs_dns_idx_(0), xs_dns_addr_(), xs_dns_port_(),
    dss_addr_(""), dss_port_(0), dss_xs_instances_(0), label_range_(),
    ip_fabric_intf_name_(""), vhost_interface_name_(""),
    pkt_interface_name_("pkt0"), cfg_listener_(NULL), arp_proto_(NULL),
    dhcp_proto_(NULL), dns_proto_(NULL), icmp_proto_(NULL), flow_proto_(NULL),
    local_peer_(NULL), local_vm_peer_(NULL), linklocal_peer_(NULL),
    ifmap_parser_(NULL), router_id_configured_(false),
    mirror_src_udp_port_(0), lifetime_manager_(NULL), test_mode_(false),
    ksync_sync_mode_(true), mgmt_ip_(""),
    vxlan_network_identifier_mode_(AUTOMATIC) {

    assert(singleton_ == NULL);
    singleton_ = this;
    db_ = new DB();
    assert(db_);

    event_mgr_ = new EventManager();
    assert(event_mgr_);

    SetAgentTaskPolicy();
    CreateLifetimeManager();
}

Agent::~Agent() {
    delete event_mgr_;
    event_mgr_ = NULL;

    ShutdownLifetimeManager();

    delete db_;
    db_ = NULL;
}

<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: xbmread.cxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: hr $ $Date: 2006-06-19 21:06:50 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#define XBMMINREAD 512

#define _XBMPRIVATE
#include <ctype.h>
#include "xbmread.hxx"

// -------------
// - XBMReader -
// -------------

XBMReader::XBMReader( SvStream& rStm, void* ) :
            rIStm           ( rStm ),
            pAcc1           ( NULL ),
            nLastPos        ( rStm.Tell() ),
            nWidth          ( 0 ),
            nHeight         ( 0 ),
            bStatus         ( TRUE )
{
    pHexTable = new short[ 256 ];
    maUpperName = String::CreateFromAscii( "SVIXBM", 6 );
    InitTable();
}

// ------------------------------------------------------------------------

XBMReader::~XBMReader()
{
    delete[] pHexTable;

    if( pAcc1 )
        aBmp1.ReleaseAccess( pAcc1 );
}

// ------------------------------------------------------------------------

void XBMReader::InitTable()
{
    memset( pHexTable, 0, sizeof( short ) );

    pHexTable['0'] = 0;
    pHexTable['1'] = 1;
    pHexTable['2'] = 2;
    pHexTable['3'] = 3;
    pHexTable['4'] = 4;
    pHexTable['5'] = 5;
    pHexTable['6'] = 6;
    pHexTable['7'] = 7;
    pHexTable['8'] = 8;
    pHexTable['9'] = 9;
    pHexTable['A'] = 10;
    pHexTable['B'] = 11;
    pHexTable['C'] = 12;
    pHexTable['D'] = 13;
    pHexTable['E'] = 14;
    pHexTable['F'] = 15;
    pHexTable['X'] = 0;
    pHexTable['a'] = 10;
    pHexTable['b'] = 11;
    pHexTable['c'] = 12;
    pHexTable['d'] = 13;
    pHexTable['e'] = 14;
    pHexTable['f'] = 15;
    pHexTable['x'] = 0;
    pHexTable[' '] =     -1;
    pHexTable[','] = -1;
    pHexTable['}'] = -1;
    pHexTable['\n'] = -1;
    pHexTable['\t'] = -1;
    pHexTable['\0'] = -1;
}

// ------------------------------------------------------------------------

ByteString XBMReader::FindTokenLine( SvStream* pInStm, const char* pTok1,
                                 const char* pTok2, const char* pTok3 )
{
    ByteString  aRet;
    long        nPos1;
    long        nPos2;
    long        nPos3;

    bStatus = FALSE;

    do
    {
        if( !pInStm->ReadLine( aRet ) )
            break;

        if( pTok1 )
        {
            if( ( nPos1 = aRet.Search( pTok1 ) ) != STRING_NOTFOUND )
            {
                bStatus = TRUE;

                if( pTok2 )
                {
                    bStatus = FALSE;

                    if( ( ( nPos2 = aRet.Search( pTok2 ) ) != STRING_NOTFOUND ) &&
                         ( nPos2 > nPos1 ) )
                    {
                        bStatus = TRUE;

                        if( pTok3 )
                        {
                            bStatus = FALSE;

                            if( ( ( nPos3 = aRet.Search( pTok3 ) ) != STRING_NOTFOUND ) && ( nPos3 > nPos2 ) )
                                bStatus = TRUE;
                        }
                    }
                }
            }
        }
    }
    while( !bStatus );

    return aRet;
}

// ------------------------------------------------------------------------

long XBMReader::ParseDefine( const sal_Char* pDefine )
{
    long    nRet = 0;
    char*   pTmp = (char*) pDefine;
    char    cTmp;

    // bis zum Ende gehen
    pTmp += ( strlen( pDefine ) - 1 );
    cTmp = *pTmp--;

    // letzte Ziffer suchen
    while( pHexTable[ cTmp ] == -1 )
        cTmp = *pTmp--;

    // bis vor die Zahl laufen
    while( pHexTable[ cTmp ] != -1 )
        cTmp = *pTmp--;

    // auf Anfang der Zahl gehen
    pTmp += 2;

    // Hex lesen
    if( ( pTmp[0] == '0' ) && ( ( pTmp[1] == 'X' ) || ( pTmp[1] == 'x' ) ) )
    {
        pTmp += 2;
        cTmp = *pTmp++;

        while ( pHexTable[ cTmp ] != -1 )
        {
            nRet = ( nRet << 4 ) + pHexTable[ cTmp ];
            cTmp = *pTmp++;
        }
    }
    // Dezimal lesen
    else
    {
        cTmp = *pTmp++;
        while( ( cTmp >= '0' ) && ( cTmp <= '9' ) )
        {
            nRet = nRet * 10 + ( cTmp - '0' );
            cTmp = *pTmp++;
        }
    }

    return nRet;
}

// ------------------------------------------------------------------------

BOOL XBMReader::ParseData( SvStream* pInStm, const ByteString& aLastLine, XBMFormat eFormat )
{
    ByteString      aLine;
    long            nRow = 0;
    long            nCol = 0;
    long            nBits = ( eFormat == XBM10 ) ? 16 : 8;
    long            nBit;
    USHORT          nValue;
    USHORT          nDigits;
    BOOL            bFirstLine = TRUE;

    while( nRow < nHeight )
    {
        if( bFirstLine )
        {
            long nPos;

            // einfuehrende geschweifte Klammer loeschen
            if( (nPos = ( aLine = aLastLine ).Search( '{' ) ) != STRING_NOTFOUND )
                aLine.Erase( 0, nPos + 1 );

            bFirstLine = FALSE;
        }
        else if( !pInStm->ReadLine( aLine ) )
            break;

        if( aLine.Len() )
        {
            const USHORT nCount = aLine.GetTokenCount( ',' );

            for( USHORT i = 0; ( i < nCount ) && ( nRow < nHeight ); i++ )
            {
                const ByteString    aToken( aLine.GetToken( i, ',' ) );
                const ULONG         nLen = aToken.Len();
                BOOL                bProcessed = FALSE;

                nBit = nDigits = nValue = 0;

                for( ULONG n = 0UL; n < nLen; n++ )
                {
                    const unsigned char cChar = aToken.GetChar( n );
                    const short         nTable = pHexTable[ cChar ];

                    if( isxdigit( cChar ) || !nTable )
                    {
                        nValue = ( nValue << 4 ) + nTable;
                        nDigits++;
                        bProcessed = TRUE;
                    }
                    else if( ( nTable < 0 ) && nDigits )
                    {
                        bProcessed = TRUE;
                        break;
                    }
                }

                if( bProcessed )
                {
                    while( ( nCol < nWidth ) && ( nBit < nBits ) )
                        pAcc1->SetPixel( nRow, nCol++, ( nValue & ( 1 << nBit++ ) ) ? aBlack : aWhite );

                    if( nCol == nWidth )
                        nCol = 0, nRow++;
                }
            }
        }
    }

    return TRUE;
}

// ------------------------------------------------------------------------

ReadState XBMReader::ReadXBM( Graphic& rGraphic )
{
    ReadState   eReadState;
    BYTE        cDummy;

    // sehen, ob wir _alles_ lesen koennen
    rIStm.Seek( STREAM_SEEK_TO_END );
    rIStm >> cDummy;

    // falls wir nicht alles lesen koennen
    // kehren wir zurueck und warten auf neue Daten
    if ( rIStm.GetError() != ERRCODE_IO_PENDING )
    {
        ByteString  aLine;
        int         nValue;

        rIStm.Seek( nLastPos );
        bStatus = FALSE;
        aLine = FindTokenLine( &rIStm, "#define", "_width" );

        if ( bStatus )
        {
            if ( ( nValue = (int) ParseDefine( aLine.GetBuffer() ) ) > 0 )
            {
                nWidth = nValue;
                aLine = FindTokenLine( &rIStm, "#define", "_height" );

                // Falls die Hoehe nicht folgt, suchen wir noch
                // einmal vom Anfang der Datei an
                if ( !bStatus )
                {
                    rIStm.Seek( nLastPos );
                    aLine = FindTokenLine( &rIStm, "#define", "_height" );
                }
            }
            else
                bStatus = FALSE;

            if ( bStatus )
            {
                if ( ( nValue = (int) ParseDefine( aLine.GetBuffer() ) ) > 0 )
                {
                    nHeight = nValue;
                    aLine = FindTokenLine( &rIStm, "static", "_bits" );

                    if ( bStatus )
                    {
                        XBMFormat eFormat = XBM10;

                        if ( aLine.Search( "short" ) != STRING_NOTFOUND )
                            eFormat = XBM10;
                        else if ( aLine.Search( "char" ) != STRING_NOTFOUND )
                            eFormat = XBM11;
                        else
                            bStatus = FALSE;

                        if ( bStatus && nWidth && nHeight )
                        {
                            aBmp1 = Bitmap( Size( nWidth, nHeight ), 1 );
                            pAcc1 = aBmp1.AcquireWriteAccess();

                            if( pAcc1 )
                            {
                                aWhite = pAcc1->GetBestMatchingColor( Color( COL_WHITE ) );
                                aBlack = pAcc1->GetBestMatchingColor( Color( COL_BLACK ) );
                                bStatus = ParseData( &rIStm, aLine, eFormat );
                            }
                            else
                                bStatus = FALSE;
                        }
                    }
                }
            }
        }

        if( bStatus )
        {
            Bitmap aBlackBmp( Size( pAcc1->Width(), pAcc1->Height() ), 1 );

            aBmp1.ReleaseAccess( pAcc1 ), pAcc1 = NULL;
            aBlackBmp.Erase( Color( COL_BLACK ) );
            rGraphic = BitmapEx( aBlackBmp, aBmp1 );
            eReadState = XBMREAD_OK;
        }
        else
            eReadState = XBMREAD_ERROR;
    }
    else
    {
        rIStm.ResetError();
        eReadState = XBMREAD_NEED_MORE;
    }

    return eReadState;
}

// -------------
// - ImportXBM -
// -------------

BOOL ImportXBM( SvStream& rStm, Graphic& rGraphic, void* pCallerData )
{
    XBMReader*  pXBMReader = (XBMReader*) rGraphic.GetContext();
    ReadState   eReadState;
    BOOL        bRet = TRUE;

    if( !pXBMReader )
        pXBMReader = new XBMReader( rStm, pCallerData );

    rGraphic.SetContext( NULL );
    eReadState = pXBMReader->ReadXBM( rGraphic );

    if( eReadState == XBMREAD_ERROR )
    {
        bRet = FALSE;
        delete pXBMReader;
    }
    else if( eReadState == XBMREAD_OK )
        delete pXBMReader;
    else
        rGraphic.SetContext( pXBMReader );

    return bRet;
}
<commit_msg>INTEGRATION: CWS pchfix02 (1.4.90); FILE MERGED 2006/09/01 17:43:08 kaib 1.4.90.1: #i68856# Added header markers and pch files<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: xbmread.cxx,v $
 *
 *  $Revision: 1.5 $
 *
 *  last change: $Author: obo $ $Date: 2006-09-17 14:54:16 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_svtools.hxx"

#define XBMMINREAD 512

#define _XBMPRIVATE
#include <ctype.h>
#include "xbmread.hxx"

// -------------
// - XBMReader -
// -------------

XBMReader::XBMReader( SvStream& rStm, void* ) :
            rIStm           ( rStm ),
            pAcc1           ( NULL ),
            nLastPos        ( rStm.Tell() ),
            nWidth          ( 0 ),
            nHeight         ( 0 ),
            bStatus         ( TRUE )
{
    pHexTable = new short[ 256 ];
    maUpperName = String::CreateFromAscii( "SVIXBM", 6 );
    InitTable();
}

// ------------------------------------------------------------------------

XBMReader::~XBMReader()
{
    delete[] pHexTable;

    if( pAcc1 )
        aBmp1.ReleaseAccess( pAcc1 );
}

// ------------------------------------------------------------------------

void XBMReader::InitTable()
{
    memset( pHexTable, 0, sizeof( short ) );

    pHexTable['0'] = 0;
    pHexTable['1'] = 1;
    pHexTable['2'] = 2;
    pHexTable['3'] = 3;
    pHexTable['4'] = 4;
    pHexTable['5'] = 5;
    pHexTable['6'] = 6;
    pHexTable['7'] = 7;
    pHexTable['8'] = 8;
    pHexTable['9'] = 9;
    pHexTable['A'] = 10;
    pHexTable['B'] = 11;
    pHexTable['C'] = 12;
    pHexTable['D'] = 13;
    pHexTable['E'] = 14;
    pHexTable['F'] = 15;
    pHexTable['X'] = 0;
    pHexTable['a'] = 10;
    pHexTable['b'] = 11;
    pHexTable['c'] = 12;
    pHexTable['d'] = 13;
    pHexTable['e'] = 14;
    pHexTable['f'] = 15;
    pHexTable['x'] = 0;
    pHexTable[' '] =     -1;
    pHexTable[','] = -1;
    pHexTable['}'] = -1;
    pHexTable['\n'] = -1;
    pHexTable['\t'] = -1;
    pHexTable['\0'] = -1;
}

// ------------------------------------------------------------------------

ByteString XBMReader::FindTokenLine( SvStream* pInStm, const char* pTok1,
                                 const char* pTok2, const char* pTok3 )
{
    ByteString  aRet;
    long        nPos1;
    long        nPos2;
    long        nPos3;

    bStatus = FALSE;

    do
    {
        if( !pInStm->ReadLine( aRet ) )
            break;

        if( pTok1 )
        {
            if( ( nPos1 = aRet.Search( pTok1 ) ) != STRING_NOTFOUND )
            {
                bStatus = TRUE;

                if( pTok2 )
                {
                    bStatus = FALSE;

                    if( ( ( nPos2 = aRet.Search( pTok2 ) ) != STRING_NOTFOUND ) &&
                         ( nPos2 > nPos1 ) )
                    {
                        bStatus = TRUE;

                        if( pTok3 )
                        {
                            bStatus = FALSE;

                            if( ( ( nPos3 = aRet.Search( pTok3 ) ) != STRING_NOTFOUND ) && ( nPos3 > nPos2 ) )
                                bStatus = TRUE;
                        }
                    }
                }
            }
        }
    }
    while( !bStatus );

    return aRet;
}

// ------------------------------------------------------------------------

long XBMReader::ParseDefine( const sal_Char* pDefine )
{
    long    nRet = 0;
    char*   pTmp = (char*) pDefine;
    char    cTmp;

    // bis zum Ende gehen
    pTmp += ( strlen( pDefine ) - 1 );
    cTmp = *pTmp--;

    // letzte Ziffer suchen
    while( pHexTable[ cTmp ] == -1 )
        cTmp = *pTmp--;

    // bis vor die Zahl laufen
    while( pHexTable[ cTmp ] != -1 )
        cTmp = *pTmp--;

    // auf Anfang der Zahl gehen
    pTmp += 2;

    // Hex lesen
    if( ( pTmp[0] == '0' ) && ( ( pTmp[1] == 'X' ) || ( pTmp[1] == 'x' ) ) )
    {
        pTmp += 2;
        cTmp = *pTmp++;

        while ( pHexTable[ cTmp ] != -1 )
        {
            nRet = ( nRet << 4 ) + pHexTable[ cTmp ];
            cTmp = *pTmp++;
        }
    }
    // Dezimal lesen
    else
    {
        cTmp = *pTmp++;
        while( ( cTmp >= '0' ) && ( cTmp <= '9' ) )
        {
            nRet = nRet * 10 + ( cTmp - '0' );
            cTmp = *pTmp++;
        }
    }

    return nRet;
}

// ------------------------------------------------------------------------

BOOL XBMReader::ParseData( SvStream* pInStm, const ByteString& aLastLine, XBMFormat eFormat )
{
    ByteString      aLine;
    long            nRow = 0;
    long            nCol = 0;
    long            nBits = ( eFormat == XBM10 ) ? 16 : 8;
    long            nBit;
    USHORT          nValue;
    USHORT          nDigits;
    BOOL            bFirstLine = TRUE;

    while( nRow < nHeight )
    {
        if( bFirstLine )
        {
            long nPos;

            // einfuehrende geschweifte Klammer loeschen
            if( (nPos = ( aLine = aLastLine ).Search( '{' ) ) != STRING_NOTFOUND )
                aLine.Erase( 0, nPos + 1 );

            bFirstLine = FALSE;
        }
        else if( !pInStm->ReadLine( aLine ) )
            break;

        if( aLine.Len() )
        {
            const USHORT nCount = aLine.GetTokenCount( ',' );

            for( USHORT i = 0; ( i < nCount ) && ( nRow < nHeight ); i++ )
            {
                const ByteString    aToken( aLine.GetToken( i, ',' ) );
                const ULONG         nLen = aToken.Len();
                BOOL                bProcessed = FALSE;

                nBit = nDigits = nValue = 0;

                for( ULONG n = 0UL; n < nLen; n++ )
                {
                    const unsigned char cChar = aToken.GetChar( n );
                    const short         nTable = pHexTable[ cChar ];

                    if( isxdigit( cChar ) || !nTable )
                    {
                        nValue = ( nValue << 4 ) + nTable;
                        nDigits++;
                        bProcessed = TRUE;
                    }
                    else if( ( nTable < 0 ) && nDigits )
                    {
                        bProcessed = TRUE;
                        break;
                    }
                }

                if( bProcessed )
                {
                    while( ( nCol < nWidth ) && ( nBit < nBits ) )
                        pAcc1->SetPixel( nRow, nCol++, ( nValue & ( 1 << nBit++ ) ) ? aBlack : aWhite );

                    if( nCol == nWidth )
                        nCol = 0, nRow++;
                }
            }
        }
    }

    return TRUE;
}

// ------------------------------------------------------------------------

ReadState XBMReader::ReadXBM( Graphic& rGraphic )
{
    ReadState   eReadState;
    BYTE        cDummy;

    // sehen, ob wir _alles_ lesen koennen
    rIStm.Seek( STREAM_SEEK_TO_END );
    rIStm >> cDummy;

    // falls wir nicht alles lesen koennen
    // kehren wir zurueck und warten auf neue Daten
    if ( rIStm.GetError() != ERRCODE_IO_PENDING )
    {
        ByteString  aLine;
        int         nValue;

        rIStm.Seek( nLastPos );
        bStatus = FALSE;
        aLine = FindTokenLine( &rIStm, "#define", "_width" );

        if ( bStatus )
        {
            if ( ( nValue = (int) ParseDefine( aLine.GetBuffer() ) ) > 0 )
            {
                nWidth = nValue;
                aLine = FindTokenLine( &rIStm, "#define", "_height" );

                // Falls die Hoehe nicht folgt, suchen wir noch
                // einmal vom Anfang der Datei an
                if ( !bStatus )
                {
                    rIStm.Seek( nLastPos );
                    aLine = FindTokenLine( &rIStm, "#define", "_height" );
                }
            }
            else
                bStatus = FALSE;

            if ( bStatus )
            {
                if ( ( nValue = (int) ParseDefine( aLine.GetBuffer() ) ) > 0 )
                {
                    nHeight = nValue;
                    aLine = FindTokenLine( &rIStm, "static", "_bits" );

                    if ( bStatus )
                    {
                        XBMFormat eFormat = XBM10;

                        if ( aLine.Search( "short" ) != STRING_NOTFOUND )
                            eFormat = XBM10;
                        else if ( aLine.Search( "char" ) != STRING_NOTFOUND )
                            eFormat = XBM11;
                        else
                            bStatus = FALSE;

                        if ( bStatus && nWidth && nHeight )
                        {
                            aBmp1 = Bitmap( Size( nWidth, nHeight ), 1 );
                            pAcc1 = aBmp1.AcquireWriteAccess();

                            if( pAcc1 )
                            {
                                aWhite = pAcc1->GetBestMatchingColor( Color( COL_WHITE ) );
                                aBlack = pAcc1->GetBestMatchingColor( Color( COL_BLACK ) );
                                bStatus = ParseData( &rIStm, aLine, eFormat );
                            }
                            else
                                bStatus = FALSE;
                        }
                    }
                }
            }
        }

        if( bStatus )
        {
            Bitmap aBlackBmp( Size( pAcc1->Width(), pAcc1->Height() ), 1 );

            aBmp1.ReleaseAccess( pAcc1 ), pAcc1 = NULL;
            aBlackBmp.Erase( Color( COL_BLACK ) );
            rGraphic = BitmapEx( aBlackBmp, aBmp1 );
            eReadState = XBMREAD_OK;
        }
        else
            eReadState = XBMREAD_ERROR;
    }
    else
    {
        rIStm.ResetError();
        eReadState = XBMREAD_NEED_MORE;
    }

    return eReadState;
}

// -------------
// - ImportXBM -
// -------------

BOOL ImportXBM( SvStream& rStm, Graphic& rGraphic, void* pCallerData )
{
    XBMReader*  pXBMReader = (XBMReader*) rGraphic.GetContext();
    ReadState   eReadState;
    BOOL        bRet = TRUE;

    if( !pXBMReader )
        pXBMReader = new XBMReader( rStm, pCallerData );

    rGraphic.SetContext( NULL );
    eReadState = pXBMReader->ReadXBM( rGraphic );

    if( eReadState == XBMREAD_ERROR )
    {
        bRet = FALSE;
        delete pXBMReader;
    }
    else if( eReadState == XBMREAD_OK )
        delete pXBMReader;
    else
        rGraphic.SetContext( pXBMReader );

    return bRet;
}
<|endoftext|>


<commit_before><commit_msg>Do not map virtual keycodes (VK_0 - VK_9) to characters when accelerators in the UI.  If we do that, the result is the layout-dependent. For instance, in fr-FR layout, we get 'a with grave' in place of '0' for Ctrl+0 (normal in Zoom menu). Besides, in Slovak lazout, we get 'e with accent'<commit_after><|endoftext|>