<commit_before>#include <Halide.h>
#include <tiramisu/tiramisu.h>
#include <iostream>
#include "generated_sger.o.h"
#include "benchmarks.h"
#include <tiramisu/utils.h>

#define M_DIM M
#define N_DIM N

int sger_ref(int n, int m, double alpha, double * A, double* x, double * y)
{
    for (int i = 0; i < n; ++i)
		for (int j = 0; j < m; j++)
    	A[i * m + j] +=  alpha * x[i] * y[j];

    return 0;
}

int main(int argc, char** argv)
{
    std::vector<std::chrono::duration<double, std::milli>> duration_vector_1, duration_vector_2;

    bool run_ref = false, run_tiramisu = false;

    const char* env_ref = std::getenv("RUN_REF");
    if (env_ref != NULL && env_ref[0] == '1')
        run_ref = true;

    const char* env_tiramisu = std::getenv("RUN_TIRAMISU");
    if (env_tiramisu != NULL && env_tiramisu[0] == '1')
        run_tiramisu = true;

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

    double alpha = 2.0;

    Halide::Buffer<double> b_alpha(1);
    b_alpha(0) = alpha;

    Halide::Buffer<double> b_X(N_DIM), b_Y(M_DIM), b_A(N_DIM, M_DIM), b_A_ref(N_DIM, M_DIM);

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

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

            init_buffer(b_A_ref, (double) 1);
	    init_buffer(b_X, (double) 2);
	init_buffer(b_Y, (double) 3);
            auto start = std::chrono::high_resolution_clock::now();

            if (run_ref)
	    	sger_ref(N_DIM, M_DIM, alpha, b_A_ref.data(), b_X.data(), b_Y.data() );

            auto end = std::chrono::high_resolution_clock::now();
            duration_vector_1.push_back(end - start);
        }
    }

    {
        for (int i = 0; i < NB_TESTS; ++i)
        {
            init_buffer(b_A, (double)1);
	    init_buffer(b_X, (double) 2);
	    init_buffer(b_Y, (double)3);

            auto start = std::chrono::high_resolution_clock::now();

            if (run_tiramisu)
	    	sger(b_A.raw_buffer(), b_X.raw_buffer(), b_Y.raw_buffer(), b_alpha.raw_buffer());

            auto end = std::chrono::high_resolution_clock::now();
            duration_vector_2.push_back(end - start);
        }
    }

    print_time("performance_cpu.csv", "sger",
	       {"Ref", "Tiramisu"},
	       {median(duration_vector_1), median(duration_vector_2)});

    if (CHECK_CORRECTNESS && run_ref && run_tiramisu)
        compare_buffers("sger", b_A_ref, b_A);

    if (PRINT_OUTPUT)
    {
        std::cout << "Tiramisu " << std::endl;
        print_buffer(b_A);

        std::cout << "Reference " << std::endl;
        print_buffer(b_A_ref);
    }

    return 0;
}
<commit_msg>Update SGER files<commit_after>#include "generated_sger.o.h"

#include <Halide.h>
#include <tiramisu/tiramisu.h>
#include <tiramisu/utils.h>

#include <iostream>
#include "benchmarks.h"

#define M_DIM M
#define N_DIM N

int sger_ref(int n, int m, double alpha, double * A, double* x, double * y)
{
    for (int i = 0; i < n; ++i)
        for (int j = 0; j < m; ++j)
            A[i * m + j] +=  alpha * x[i] * y[j];

    return 0;
}

int main(int argc, char** argv)
{
    std::vector<std::chrono::duration<double, std::milli>> duration_vector_1, duration_vector_2;

    bool run_ref = false, run_tiramisu = false;

    const char* env_ref = std::getenv("RUN_REF");
    if (env_ref != NULL && env_ref[0] == '1')
        run_ref = true;

    const char* env_tiramisu = std::getenv("RUN_TIRAMISU");
    if (env_tiramisu != NULL && env_tiramisu[0] == '1')
        run_tiramisu = true;

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

    double alpha = 2.0;

    Halide::Buffer<double> b_alpha(1);
    b_alpha(0) = alpha;

    // b_A and b_A_ref needs to be initialized in each iteration test
    Halide::Buffer<double> b_A(N_DIM, M_DIM), b_A_ref(N_DIM, M_DIM);

    Halide::Buffer<double> b_X(N_DIM);
    init_buffer(b_X, (double) 2);

    Halide::Buffer<double> b_Y(M_DIM);
    init_buffer(b_Y, (double) 3);

    /**
    * We have :
    *
    * alpha : equals 2
    * b_X : size N_DIM vector with all values set to 2
    * b_Y : size M_DIM vector with all values set to 3
    * b_A : N_DIM by M_DIM matrix with all values set to 1 (initialized in each loop)
    * b_A_ref : N_DIM by M_DIM matrix with all values set to 1 (initialized in each loop)
    *
    * The result must be a N_DIM by M_DIM with all values equal to 13
    */

    {
        for (int i = 0; i < NB_TESTS; ++i)
        {
            // b_A_ref initialized with 1
            init_buffer(b_A_ref, (double) 1);
            auto start = std::chrono::high_resolution_clock::now();

            if (run_ref)
	    	sger_ref(N_DIM, M_DIM, alpha, b_A_ref.data(), b_X.data(), b_Y.data() );

            auto end = std::chrono::high_resolution_clock::now();
            duration_vector_1.push_back(end - start);
        }
    }

    {
        for (int i = 0; i < NB_TESTS; ++i)
        {
            // b_A initialized with 1
            init_buffer(b_A, (double) 1);

            auto start = std::chrono::high_resolution_clock::now();

            if (run_tiramisu)
	    	sger(b_A.raw_buffer(), b_X.raw_buffer(), b_Y.raw_buffer(), b_alpha.raw_buffer());

            auto end = std::chrono::high_resolution_clock::now();
            duration_vector_2.push_back(end - start);
        }
    }

    print_time("performance_cpu.csv", "sger",
	       {"Ref", "Tiramisu"},
	       {median(duration_vector_1), median(duration_vector_2)});

    if (CHECK_CORRECTNESS && run_ref && run_tiramisu)
        compare_buffers("sger", b_A_ref, b_A);

    if (PRINT_OUTPUT)
    {
        std::cout << "Tiramisu " << std::endl;
        print_buffer(b_A);

        std::cout << "Reference " << std::endl;
        print_buffer(b_A_ref);
    }

    return 0;
}
<|endoftext|>


<commit_before>/*
 * simple 3x3 XO game.
 * Object Oriented version.
 * source available at (Github repo - MIT licence):
 * http://dstjrd.ir/s/cppx
 * https://github.com/mohsend/cpp-examples
*/

#include <iostream>

#ifndef SEVENSEGMENT_HPP
#define SEVENSEGMENT_HPP	1

using namespace std;

class xoGame
{
	public:
		xoGame();
		void play();
	private:
		char A[3][3];
		char * const ptr = &A[0][0];
		void show();
		bool check();
		void get(int round);
		bool result(int sum);
};

xoGame::xoGame()
{
	for (int i = 0; i < 9; i++)
	{
		*(ptr + i) = ' ';
	}
}

void xoGame::show()
{
	cout << "    1   2   3\n"; // table head
	for (int i = 0; i < 3; i++)
	{
		cout << i + 1 << " |";
		for (int j = 0; j < 3; j++)
		{
			cout << ' ' << A[i][j] << " |";
		}
		cout << "\n  -------------" << endl;
	}
}

bool xoGame::check()
{
	int sum;
	bool res = false;

	// check horisontal (-) lines
	for (int i = 0; i < 3; i++)
	{
		sum = A[i][0] + A[i][1] + A[i][2];
		res += result(sum);
	}

	// check vertical (|) lines
	for (int j = 0; j < 3; j++)
	{
		sum = A[0][j] + A[1][j] + A[2][j];
		res += result(sum);
	}

	// check left-to-right crossed (\) lines
	sum = A[0][0] + A[1][1] + A[2][2];
	res += result(sum);

	// check right-to-left crossed (/) lines
	sum = A[0][2] + A[1][1] + A[2][0];
	res += result(sum);

	// check if game ended as a draw
	sum = -1;
	for (int i = 0; i < 9; i++)
	{
		sum += (*(ptr + i) == ' ');
	}
	res += result(sum);

	return res;
}

bool xoGame::result(int sum)
{
	char ch = sum / 3;

	if ( (ch == 'X') || (ch == 'O') )
	{
		cout << "\n\t" << ch << " Won!" << endl;
		return true;
	}
	else if (sum == -1)
	{
		cout << "\n\tit's a Draw!" << endl;
		return true;
	}

	return false;
}

void xoGame::get(int round)
{
	int i, j;
	char ch = (round % 2) ? 'X' : 'O';

	cout << ch << "'s turn, Place " << ch << " on:" << endl;
	cout << "i) "; cin >> j;
	cout << "j) "; cin >> i;

	if ( (i > 3) || (i < 1) || (j > 3) || (j < 1) )
	{
		cout << "1,2 and 3 are the only acceptable values for i and j." << endl;
		get(round);
	}
	else if (A[i-1][j-1] != ' ')
	{
		cout << "Already set. try another:" << endl;
		get(round);
	}
	else
	{
		A[i-1][j-1] = ch;
	}
}

void xoGame::play()
{
	int round = 0;

	show();
	while (!check())
	{
		get(round++);
		show();
	}
}

#endif
<commit_msg>fixed typo in macro<commit_after>/*
 * simple 3x3 XO game.
 * Object Oriented version.
 * source available at (Github repo - MIT licence):
 * http://dstjrd.ir/s/cppx
 * https://github.com/mohsend/cpp-examples
*/

#include <iostream>

#ifndef XOGAME_HPP
#define XOGAME_HPP	1

using namespace std;

class xoGame
{
	public:
		xoGame();
		void play();
	private:
		char A[3][3];
		char * const ptr = &A[0][0];
		void show();
		bool check();
		void get(int round);
		bool result(int sum);
};

xoGame::xoGame()
{
	for (int i = 0; i < 9; i++)
	{
		*(ptr + i) = ' ';
	}
}

void xoGame::show()
{
	cout << "    1   2   3\n"; // table head
	for (int i = 0; i < 3; i++)
	{
		cout << i + 1 << " |";
		for (int j = 0; j < 3; j++)
		{
			cout << ' ' << A[i][j] << " |";
		}
		cout << "\n  -------------" << endl;
	}
}

bool xoGame::check()
{
	int sum;
	bool res = false;

	// check horisontal (-) lines
	for (int i = 0; i < 3; i++)
	{
		sum = A[i][0] + A[i][1] + A[i][2];
		res += result(sum);
	}

	// check vertical (|) lines
	for (int j = 0; j < 3; j++)
	{
		sum = A[0][j] + A[1][j] + A[2][j];
		res += result(sum);
	}

	// check left-to-right crossed (\) lines
	sum = A[0][0] + A[1][1] + A[2][2];
	res += result(sum);

	// check right-to-left crossed (/) lines
	sum = A[0][2] + A[1][1] + A[2][0];
	res += result(sum);

	// check if game ended as a draw
	sum = -1;
	for (int i = 0; i < 9; i++)
	{
		sum += (*(ptr + i) == ' ');
	}
	res += result(sum);

	return res;
}

bool xoGame::result(int sum)
{
	char ch = sum / 3;

	if ( (ch == 'X') || (ch == 'O') )
	{
		cout << "\n\t" << ch << " Won!" << endl;
		return true;
	}
	else if (sum == -1)
	{
		cout << "\n\tit's a Draw!" << endl;
		return true;
	}

	return false;
}

void xoGame::get(int round)
{
	int i, j;
	char ch = (round % 2) ? 'X' : 'O';

	cout << ch << "'s turn, Place " << ch << " on:" << endl;
	cout << "i) "; cin >> j;
	cout << "j) "; cin >> i;

	if ( (i > 3) || (i < 1) || (j > 3) || (j < 1) )
	{
		cout << "1,2 and 3 are the only acceptable values for i and j." << endl;
		get(round);
	}
	else if (A[i-1][j-1] != ' ')
	{
		cout << "Already set. try another:" << endl;
		get(round);
	}
	else
	{
		A[i-1][j-1] = ch;
	}
}

void xoGame::play()
{
	int round = 0;

	show();
	while (!check())
	{
		get(round++);
		show();
	}
}

#endif
<|endoftext|>


<commit_before>/* -*- coding: utf-8; mode: c++; tab-width: 3; indent-tabs-mode: nil -*-

Copyright 2010, 2011, 2012, 2013, 2014, 2015
Raffaello D. Di Napoli

This file is part of Abaclade.

Abaclade is free software: you can redistribute it and/or modify it under the terms of the GNU
General Public License as published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.

Abaclade is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
Public License for more details.

You should have received a copy of the GNU General Public License along with Abaclade. If not, see
<http://www.gnu.org/licenses/>.
--------------------------------------------------------------------------------------------------*/

#include <abaclade.hxx>

#if ABC_HOST_API_POSIX
   #include <cstdlib> // std::getenv()
#endif

////////////////////////////////////////////////////////////////////////////////////////////////////

namespace abc { namespace io { namespace text {

_std::shared_ptr<writer> stderr;
_std::shared_ptr<reader> stdin;
_std::shared_ptr<writer> stdout;

/*! Instantiates a text::base specialization appropriate for the specified binary I/O object,
returning a shared pointer to it. If the binary I/O object does not implement buffering, a buffered
I/O wrapper is instanciated as well.

pbb
   Pointer to a binary I/O object.
return
   Shared pointer to the newly created object.
*/
static _std::shared_ptr<binbuf_base> _construct(
   _std::shared_ptr<binary::base> pbb, abc::text::encoding enc
) {
   ABC_TRACE_FUNC(pbb, enc);

   // Choose what type of text I/O object to create based on what type of binary I/O object we got.

   // Check if it’s a buffered I/O object.
   auto pbbr(_std::dynamic_pointer_cast<binary::buffered_reader>(pbb));
   auto pbbw(_std::dynamic_pointer_cast<binary::buffered_writer>(pbb));
   if (!pbbr && !pbbw) {
      // Not a buffered I/O object? Get one then, and try again with the casts.
      auto pbbb(binary::buffer(pbb));
      pbbr = _std::dynamic_pointer_cast<binary::buffered_reader>(pbbb);
      pbbw = _std::dynamic_pointer_cast<binary::buffered_writer>(pbbb);
   }

   // Now we must have a buffered reader or writer, or pbb is not something we can use.
   if (pbbr) {
      return _std::make_shared<binbuf_reader>(_std::move(pbbr), enc);
   }
   if (pbbw) {
      return _std::make_shared<binbuf_writer>(_std::move(pbbw), enc);
   }
   // TODO: use a better exception class.
   ABC_THROW(argument_error, ());
}

/*! Detects the encoding to use for a standard text I/O file, with the help of an optional
environment variable.

TODO: document this behavior and the related enviroment variables.

TODO: change to use a global “environment” map object instead of this ad-hoc code.

TODO: make the below code only pick up variables meant for this PID. This should eventually be made
more general, as a way for an Abaclade-based parent process to communicate with an Abaclade-based
child process. Thought maybe a better way is to pass a command-line argument that triggers Abaclade-
specific behavior, so that it’s inherently PID-specific.

pszEnvVarName
   Environment variable name that, if set, specifies the encoding to be used.
return
   Encoding appropriate for the requested standard I/O file.
*/
static _std::shared_ptr<binbuf_base> _construct_stdio(
   _std::shared_ptr<binary::base> pbb, char_t const * pszEnvVarName
) {
   ABC_TRACE_FUNC(pbb, pszEnvVarName);

   abc::text::encoding enc;
   if (_std::dynamic_pointer_cast<binary::console_file_base>(pbb)) {
      /* Console files can only perform I/O in the host platform’s encoding, so force the correct
      encoding here. */
      enc = abc::text::encoding::host;
   } else {
      // In all other cases, allow selecting the encoding via environment variable.
#if ABC_HOST_API_POSIX
      str sEnc;
      if (char_t const * pszEnvVarValue = std::getenv(pszEnvVarName)) {
         sEnc = str(external_buffer, pszEnvVarValue);
      }
#elif ABC_HOST_API_WIN32 //if ABC_HOST_API_POSIX
      sstr<64> sEnc;
      sEnc.set_from([pszEnvVarName] (char_t * pch, std::size_t cchMax) -> std::size_t {
         /* ::GetEnvironmentVariable() returns < cchMax (length without NUL) if the buffer was large
         enough, or the required size (length including NUL) otherwise. */
         return ::GetEnvironmentVariable(pszEnvVarName, pch, static_cast< ::DWORD>(cchMax));
      });
#else //if ABC_HOST_API_POSIX … elif ABC_HOST_API_WIN32
   #error "TODO: HOST_API"
#endif //if ABC_HOST_API_POSIX … elif ABC_HOST_API_WIN32 … else
      enc = abc::text::encoding::unknown;
      if (sEnc) {
         try {
            enc = abc::text::encoding(sEnc.str());
         } catch (domain_error const &) {
            // Ignore this invalid encoding setting, and default to auto-detection.
            // TODO: display a warning about ABC_STD*_ENCODING being ignored.
         }
      }
   }
   return _construct(_std::move(pbb), enc);
}

_std::shared_ptr<reader> make_reader(
   _std::shared_ptr<binary::reader> pbr, abc::text::encoding enc /*= abc::text::encoding::unknown*/
) {
   ABC_TRACE_FUNC(pbr, enc);

   return _std::make_shared<binbuf_reader>(
      _std::make_shared<binary::default_buffered_reader>(_std::move(pbr)), enc
   );
}

_std::shared_ptr<writer> make_writer(
   _std::shared_ptr<binary::writer> pbw, abc::text::encoding enc /*= abc::text::encoding::unknown*/
) {
   ABC_TRACE_FUNC(pbw, enc);

   return _std::make_shared<binbuf_writer>(
      _std::make_shared<binary::default_buffered_writer>(_std::move(pbw)), enc
   );
}

_std::shared_ptr<binbuf_base> open(
   os::path const & op, access_mode am, abc::text::encoding enc /*= abc::text::encoding::unknown*/
) {
   ABC_TRACE_FUNC(op, am, enc);

   return _construct(binary::open(op, am), enc);
}

}}} //namespace abc::io::text

namespace abc { namespace io { namespace text { namespace detail {

_std::shared_ptr<writer> make_stderr() {
   ABC_TRACE_FUNC();

   return _std::dynamic_pointer_cast<writer>(
      _construct_stdio(binary::stderr, ABC_SL("ABC_STDERR_ENCODING"))
   );
}

_std::shared_ptr<reader> make_stdin() {
   ABC_TRACE_FUNC();

   return _std::dynamic_pointer_cast<reader>(
      _construct_stdio(binary::stdin, ABC_SL("ABC_STDIN_ENCODING"))
   );
}

_std::shared_ptr<writer> make_stdout() {
   ABC_TRACE_FUNC();

   return _std::dynamic_pointer_cast<writer>(
      _construct_stdio(binary::stdout, ABC_SL("ABC_STDOUT_ENCODING"))
   );
}

}}}} //namespace abc::io::text::detail

////////////////////////////////////////////////////////////////////////////////////////////////////

namespace abc { namespace io { namespace text {

base::base() :
   m_lterm(abc::text::line_terminator::convert_any_to_lf) {
}

/*virtual*/ base::~base() {
}

}}} //namespace abc::io::text

////////////////////////////////////////////////////////////////////////////////////////////////////

namespace abc { namespace io { namespace text {

reader::reader() :
   base() {
}

str reader::read_all() {
   ABC_TRACE_FUNC(this);

   str sDst;
   read_line_or_all(&sDst, false);
   return _std::move(sDst);
}
void reader::read_all(str * psDst) {
   ABC_TRACE_FUNC(this, psDst);

   psDst->clear();
   read_line_or_all(psDst, false);
}

bool reader::read_line(str * psDst) {
   ABC_TRACE_FUNC(this, psDst);

   psDst->clear();
   return read_line_or_all(psDst, true);
}

}}} //namespace abc::io::text

////////////////////////////////////////////////////////////////////////////////////////////////////

namespace abc { namespace io { namespace text {

writer::writer() :
   base() {
}

void writer::write_line(str const & s) {
   ABC_TRACE_FUNC(this, s);

   to_str_backend<str> tsb;
   tsb.write(s, this);
   abc::text::line_terminator lterm;
   // If no line terminator sequence has been explicitly set, use the platform’s default.
   if (m_lterm == abc::text::line_terminator::any) {
      lterm = abc::text::line_terminator::host;
   } else {
      lterm = m_lterm;
   }
   tsb.write(get_line_terminator_str(lterm), this);
}

}}} //namespace abc::io::text

////////////////////////////////////////////////////////////////////////////////////////////////////

namespace abc { namespace io { namespace text { namespace detail {

writer_print_helper_impl::writer_print_helper_impl(writer * ptw, str const & sFormat) :
   m_ptw(ptw),
   // write_format_up_to_next_repl() will increment this to 0 or set it to a non-negative number.
   m_iSubstArg(static_cast<unsigned>(-1)),
   m_sFormat(sFormat),
   m_itFormatToWriteBegin(sFormat.cbegin()) {
}

void writer_print_helper_impl::run() {
   /* Since this specialization has no replacements, verify that the format string doesn’t specify
   any either. */
   if (write_format_up_to_next_repl()) {
      ABC_THROW(index_error, (static_cast<std::ptrdiff_t>(m_iSubstArg)));
   }
}

void writer_print_helper_impl::throw_index_error() {
   ABC_THROW(index_error, (static_cast<std::ptrdiff_t>(m_iSubstArg)));
}

bool writer_print_helper_impl::write_format_up_to_next_repl() {
   ABC_TRACE_FUNC(this);

   // Search for the next replacement, if any.
   str::const_iterator it(m_itFormatToWriteBegin), itReplFieldBegin, itEnd(m_sFormat.cend());
   char32_t ch;
   for (;;) {
      if (it >= itEnd) {
         // The format string is over; write any characters not yet written.
         write_format_up_to(itEnd);
         // Report that no more replacement fields were found.
         return false;
      }
      ch = *it++;
      if (ch == '{' || ch == '}') {
         if (ch == '{') {
            // Mark the beginning of the replacement field.
            itReplFieldBegin = it - 1;
            if (it >= itEnd) {
               throw_syntax_error(ABC_SL("unmatched '{' in format string"), itReplFieldBegin);
            }
            ch = *it;
            if (ch != '{') {
               // We found the beginning of a replacement field.
               break;
            }
         } else if (ch == '}') {
            if (it >= itEnd || *it != '}') {
               throw_syntax_error(ABC_SL("single '}' encountered in format string"), it - 1);
            }
         }
         // Convert “{{” into “{” or “}}” into “}”.
         // Write up to and including the first brace.
         write_format_up_to(it);
         // The next call to write_format_up_to() will skip the second brace.
         m_itFormatToWriteBegin = ++it;
      }
   }

   // Check if we have an argument index.
   if (ch >= '0' && ch <= '9') {
      // Consume as many digits as there are, and convert them into the argument index.
      unsigned iArg(0);
      for (;;) {
         iArg += static_cast<unsigned>(ch - '0');
         if (++it >= itEnd) {
            throw_syntax_error(ABC_SL("unmatched '{' in format string"), itReplFieldBegin);
         }
         ch = *it;
         if (ch < '0' || ch > '9') {
            break;
         }
         iArg *= 10;
      }
      // Save this index as the last used one.
      m_iSubstArg = iArg;
   } else {
      // The argument index is missing, so just use the next one.
      ++m_iSubstArg;
   }

   // Check for a format specification.
   if (ch == ':') {
      if (++it >= itEnd) {
         throw_syntax_error(ABC_SL("expected format specification"), it);
      }
      m_pchReplFormatSpecBegin = it.ptr();
      // Find the end of the replacement field.
      it = m_sFormat.find('}', it);
      if (it == itEnd) {
         throw_syntax_error(ABC_SL("unmatched '{' in format string"), itReplFieldBegin);
      }
      m_pchReplFormatSpecEnd = it.ptr();
   } else {
      // If there’s no format specification, it must be the end of the replacement field.
      if (ch != '}') {
         throw_syntax_error(ABC_SL("unmatched '{' in format string"), itReplFieldBegin);
      }
      // Set the format specification to nothing.
      m_pchReplFormatSpecBegin = nullptr;
      m_pchReplFormatSpecEnd = nullptr;
   }

   // Write the format string characters up to the beginning of the replacement.
   write_format_up_to(itReplFieldBegin);
   // Update this, so the next call to write_format_up_to() will skip over this replacement field.
   m_itFormatToWriteBegin = it + 1 /*'}'*/;
   // Report that a substitution must be written.
   return true;
}

void writer_print_helper_impl::throw_syntax_error(
   str const & sDescription, str::const_iterator it
) const {
   // +1 because the first character is 1, to human beings.
   ABC_THROW(
      syntax_error, (sDescription, m_sFormat, static_cast<unsigned>(it - m_sFormat.cbegin() + 1))
   );
}

void writer_print_helper_impl::write_format_up_to(str::const_iterator itUpTo) {
   ABC_TRACE_FUNC(this, itUpTo);

   if (itUpTo > m_itFormatToWriteBegin) {
      m_ptw->write_binary(
         m_itFormatToWriteBegin.ptr(),
         sizeof(char_t) * (itUpTo.index() - m_itFormatToWriteBegin.index()),
         abc::text::encoding::host
      );
      m_itFormatToWriteBegin = itUpTo;
   }
}

}}}} //namespace abc::io::text::detail
<commit_msg>Remove incompatible difference between POSIX and Win32 code<commit_after>/* -*- coding: utf-8; mode: c++; tab-width: 3; indent-tabs-mode: nil -*-

Copyright 2010, 2011, 2012, 2013, 2014, 2015
Raffaello D. Di Napoli

This file is part of Abaclade.

Abaclade is free software: you can redistribute it and/or modify it under the terms of the GNU
General Public License as published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.

Abaclade is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
Public License for more details.

You should have received a copy of the GNU General Public License along with Abaclade. If not, see
<http://www.gnu.org/licenses/>.
--------------------------------------------------------------------------------------------------*/

#include <abaclade.hxx>

#if ABC_HOST_API_POSIX
   #include <cstdlib> // std::getenv()
#endif

////////////////////////////////////////////////////////////////////////////////////////////////////

namespace abc { namespace io { namespace text {

_std::shared_ptr<writer> stderr;
_std::shared_ptr<reader> stdin;
_std::shared_ptr<writer> stdout;

/*! Instantiates a text::base specialization appropriate for the specified binary I/O object,
returning a shared pointer to it. If the binary I/O object does not implement buffering, a buffered
I/O wrapper is instanciated as well.

pbb
   Pointer to a binary I/O object.
return
   Shared pointer to the newly created object.
*/
static _std::shared_ptr<binbuf_base> _construct(
   _std::shared_ptr<binary::base> pbb, abc::text::encoding enc
) {
   ABC_TRACE_FUNC(pbb, enc);

   // Choose what type of text I/O object to create based on what type of binary I/O object we got.

   // Check if it’s a buffered I/O object.
   auto pbbr(_std::dynamic_pointer_cast<binary::buffered_reader>(pbb));
   auto pbbw(_std::dynamic_pointer_cast<binary::buffered_writer>(pbb));
   if (!pbbr && !pbbw) {
      // Not a buffered I/O object? Get one then, and try again with the casts.
      auto pbbb(binary::buffer(pbb));
      pbbr = _std::dynamic_pointer_cast<binary::buffered_reader>(pbbb);
      pbbw = _std::dynamic_pointer_cast<binary::buffered_writer>(pbbb);
   }

   // Now we must have a buffered reader or writer, or pbb is not something we can use.
   if (pbbr) {
      return _std::make_shared<binbuf_reader>(_std::move(pbbr), enc);
   }
   if (pbbw) {
      return _std::make_shared<binbuf_writer>(_std::move(pbbw), enc);
   }
   // TODO: use a better exception class.
   ABC_THROW(argument_error, ());
}

/*! Detects the encoding to use for a standard text I/O file, with the help of an optional
environment variable.

TODO: document this behavior and the related enviroment variables.

TODO: change to use a global “environment” map object instead of this ad-hoc code.

TODO: make the below code only pick up variables meant for this PID. This should eventually be made
more general, as a way for an Abaclade-based parent process to communicate with an Abaclade-based
child process. Thought maybe a better way is to pass a command-line argument that triggers Abaclade-
specific behavior, so that it’s inherently PID-specific.

pszEnvVarName
   Environment variable name that, if set, specifies the encoding to be used.
return
   Encoding appropriate for the requested standard I/O file.
*/
static _std::shared_ptr<binbuf_base> _construct_stdio(
   _std::shared_ptr<binary::base> pbb, char_t const * pszEnvVarName
) {
   ABC_TRACE_FUNC(pbb, pszEnvVarName);

   abc::text::encoding enc;
   if (_std::dynamic_pointer_cast<binary::console_file_base>(pbb)) {
      /* Console files can only perform I/O in the host platform’s encoding, so force the correct
      encoding here. */
      enc = abc::text::encoding::host;
   } else {
      // In all other cases, allow selecting the encoding via environment variable.
      sstr<64> sEnc;
#if ABC_HOST_API_POSIX
      if (char_t const * pszEnvVarValue = std::getenv(pszEnvVarName)) {
         sEnc = str(external_buffer, pszEnvVarValue);
      }
#elif ABC_HOST_API_WIN32 //if ABC_HOST_API_POSIX
      sEnc.set_from([pszEnvVarName] (char_t * pch, std::size_t cchMax) -> std::size_t {
         /* ::GetEnvironmentVariable() returns < cchMax (length without NUL) if the buffer was large
         enough, or the required size (length including NUL) otherwise. */
         return ::GetEnvironmentVariable(pszEnvVarName, pch, static_cast< ::DWORD>(cchMax));
      });
#else //if ABC_HOST_API_POSIX … elif ABC_HOST_API_WIN32
   #error "TODO: HOST_API"
#endif //if ABC_HOST_API_POSIX … elif ABC_HOST_API_WIN32 … else
      enc = abc::text::encoding::unknown;
      if (sEnc) {
         try {
            enc = abc::text::encoding(sEnc.str());
         } catch (domain_error const &) {
            // Ignore this invalid encoding setting, and default to auto-detection.
            // TODO: display a warning about ABC_STD*_ENCODING being ignored.
         }
      }
   }
   return _construct(_std::move(pbb), enc);
}

_std::shared_ptr<reader> make_reader(
   _std::shared_ptr<binary::reader> pbr, abc::text::encoding enc /*= abc::text::encoding::unknown*/
) {
   ABC_TRACE_FUNC(pbr, enc);

   return _std::make_shared<binbuf_reader>(
      _std::make_shared<binary::default_buffered_reader>(_std::move(pbr)), enc
   );
}

_std::shared_ptr<writer> make_writer(
   _std::shared_ptr<binary::writer> pbw, abc::text::encoding enc /*= abc::text::encoding::unknown*/
) {
   ABC_TRACE_FUNC(pbw, enc);

   return _std::make_shared<binbuf_writer>(
      _std::make_shared<binary::default_buffered_writer>(_std::move(pbw)), enc
   );
}

_std::shared_ptr<binbuf_base> open(
   os::path const & op, access_mode am, abc::text::encoding enc /*= abc::text::encoding::unknown*/
) {
   ABC_TRACE_FUNC(op, am, enc);

   return _construct(binary::open(op, am), enc);
}

}}} //namespace abc::io::text

namespace abc { namespace io { namespace text { namespace detail {

_std::shared_ptr<writer> make_stderr() {
   ABC_TRACE_FUNC();

   return _std::dynamic_pointer_cast<writer>(
      _construct_stdio(binary::stderr, ABC_SL("ABC_STDERR_ENCODING"))
   );
}

_std::shared_ptr<reader> make_stdin() {
   ABC_TRACE_FUNC();

   return _std::dynamic_pointer_cast<reader>(
      _construct_stdio(binary::stdin, ABC_SL("ABC_STDIN_ENCODING"))
   );
}

_std::shared_ptr<writer> make_stdout() {
   ABC_TRACE_FUNC();

   return _std::dynamic_pointer_cast<writer>(
      _construct_stdio(binary::stdout, ABC_SL("ABC_STDOUT_ENCODING"))
   );
}

}}}} //namespace abc::io::text::detail

////////////////////////////////////////////////////////////////////////////////////////////////////

namespace abc { namespace io { namespace text {

base::base() :
   m_lterm(abc::text::line_terminator::convert_any_to_lf) {
}

/*virtual*/ base::~base() {
}

}}} //namespace abc::io::text

////////////////////////////////////////////////////////////////////////////////////////////////////

namespace abc { namespace io { namespace text {

reader::reader() :
   base() {
}

str reader::read_all() {
   ABC_TRACE_FUNC(this);

   str sDst;
   read_line_or_all(&sDst, false);
   return _std::move(sDst);
}
void reader::read_all(str * psDst) {
   ABC_TRACE_FUNC(this, psDst);

   psDst->clear();
   read_line_or_all(psDst, false);
}

bool reader::read_line(str * psDst) {
   ABC_TRACE_FUNC(this, psDst);

   psDst->clear();
   return read_line_or_all(psDst, true);
}

}}} //namespace abc::io::text

////////////////////////////////////////////////////////////////////////////////////////////////////

namespace abc { namespace io { namespace text {

writer::writer() :
   base() {
}

void writer::write_line(str const & s) {
   ABC_TRACE_FUNC(this, s);

   to_str_backend<str> tsb;
   tsb.write(s, this);
   abc::text::line_terminator lterm;
   // If no line terminator sequence has been explicitly set, use the platform’s default.
   if (m_lterm == abc::text::line_terminator::any) {
      lterm = abc::text::line_terminator::host;
   } else {
      lterm = m_lterm;
   }
   tsb.write(get_line_terminator_str(lterm), this);
}

}}} //namespace abc::io::text

////////////////////////////////////////////////////////////////////////////////////////////////////

namespace abc { namespace io { namespace text { namespace detail {

writer_print_helper_impl::writer_print_helper_impl(writer * ptw, str const & sFormat) :
   m_ptw(ptw),
   // write_format_up_to_next_repl() will increment this to 0 or set it to a non-negative number.
   m_iSubstArg(static_cast<unsigned>(-1)),
   m_sFormat(sFormat),
   m_itFormatToWriteBegin(sFormat.cbegin()) {
}

void writer_print_helper_impl::run() {
   /* Since this specialization has no replacements, verify that the format string doesn’t specify
   any either. */
   if (write_format_up_to_next_repl()) {
      ABC_THROW(index_error, (static_cast<std::ptrdiff_t>(m_iSubstArg)));
   }
}

void writer_print_helper_impl::throw_index_error() {
   ABC_THROW(index_error, (static_cast<std::ptrdiff_t>(m_iSubstArg)));
}

bool writer_print_helper_impl::write_format_up_to_next_repl() {
   ABC_TRACE_FUNC(this);

   // Search for the next replacement, if any.
   str::const_iterator it(m_itFormatToWriteBegin), itReplFieldBegin, itEnd(m_sFormat.cend());
   char32_t ch;
   for (;;) {
      if (it >= itEnd) {
         // The format string is over; write any characters not yet written.
         write_format_up_to(itEnd);
         // Report that no more replacement fields were found.
         return false;
      }
      ch = *it++;
      if (ch == '{' || ch == '}') {
         if (ch == '{') {
            // Mark the beginning of the replacement field.
            itReplFieldBegin = it - 1;
            if (it >= itEnd) {
               throw_syntax_error(ABC_SL("unmatched '{' in format string"), itReplFieldBegin);
            }
            ch = *it;
            if (ch != '{') {
               // We found the beginning of a replacement field.
               break;
            }
         } else if (ch == '}') {
            if (it >= itEnd || *it != '}') {
               throw_syntax_error(ABC_SL("single '}' encountered in format string"), it - 1);
            }
         }
         // Convert “{{” into “{” or “}}” into “}”.
         // Write up to and including the first brace.
         write_format_up_to(it);
         // The next call to write_format_up_to() will skip the second brace.
         m_itFormatToWriteBegin = ++it;
      }
   }

   // Check if we have an argument index.
   if (ch >= '0' && ch <= '9') {
      // Consume as many digits as there are, and convert them into the argument index.
      unsigned iArg(0);
      for (;;) {
         iArg += static_cast<unsigned>(ch - '0');
         if (++it >= itEnd) {
            throw_syntax_error(ABC_SL("unmatched '{' in format string"), itReplFieldBegin);
         }
         ch = *it;
         if (ch < '0' || ch > '9') {
            break;
         }
         iArg *= 10;
      }
      // Save this index as the last used one.
      m_iSubstArg = iArg;
   } else {
      // The argument index is missing, so just use the next one.
      ++m_iSubstArg;
   }

   // Check for a format specification.
   if (ch == ':') {
      if (++it >= itEnd) {
         throw_syntax_error(ABC_SL("expected format specification"), it);
      }
      m_pchReplFormatSpecBegin = it.ptr();
      // Find the end of the replacement field.
      it = m_sFormat.find('}', it);
      if (it == itEnd) {
         throw_syntax_error(ABC_SL("unmatched '{' in format string"), itReplFieldBegin);
      }
      m_pchReplFormatSpecEnd = it.ptr();
   } else {
      // If there’s no format specification, it must be the end of the replacement field.
      if (ch != '}') {
         throw_syntax_error(ABC_SL("unmatched '{' in format string"), itReplFieldBegin);
      }
      // Set the format specification to nothing.
      m_pchReplFormatSpecBegin = nullptr;
      m_pchReplFormatSpecEnd = nullptr;
   }

   // Write the format string characters up to the beginning of the replacement.
   write_format_up_to(itReplFieldBegin);
   // Update this, so the next call to write_format_up_to() will skip over this replacement field.
   m_itFormatToWriteBegin = it + 1 /*'}'*/;
   // Report that a substitution must be written.
   return true;
}

void writer_print_helper_impl::throw_syntax_error(
   str const & sDescription, str::const_iterator it
) const {
   // +1 because the first character is 1, to human beings.
   ABC_THROW(
      syntax_error, (sDescription, m_sFormat, static_cast<unsigned>(it - m_sFormat.cbegin() + 1))
   );
}

void writer_print_helper_impl::write_format_up_to(str::const_iterator itUpTo) {
   ABC_TRACE_FUNC(this, itUpTo);

   if (itUpTo > m_itFormatToWriteBegin) {
      m_ptw->write_binary(
         m_itFormatToWriteBegin.ptr(),
         sizeof(char_t) * (itUpTo.index() - m_itFormatToWriteBegin.index()),
         abc::text::encoding::host
      );
      m_itFormatToWriteBegin = itUpTo;
   }
}

}}}} //namespace abc::io::text::detail
<|endoftext|>


<commit_before>#ifndef BFC_SOURCELOC_HPP
#define BFC_SOURCELOC_HPP

#include <memory>
#include <ostream>
#include <string>

namespace bfc {

struct source_pos {
  unsigned long off;
  unsigned long row;
  unsigned long col;
};

static std::ostream &
operator<<(std::ostream &out, source_pos pos)
{
  return out << pos.row << ',' << pos.col;
}

class source_loc {

public:

  source_loc(source_pos begin, source_pos end, std::string name) noexcept :
    source_loc{begin, end, std::make_shared<std::string>(std::move(name))}
  {}

  source_loc(source_pos begin, source_pos end,
             std::shared_ptr<std::string> name) noexcept :
    begin_pos{begin}, end_pos{end}, source_name{name}
  {}

  source_pos begin(void) const noexcept
  {
    return begin_pos;
  }

  source_pos end(void) const noexcept
  {
    return end_pos;
  }

  const std::string &name(void) const noexcept
  {
    return *source_name;
  }

  source_loc with_pos(source_pos begin, source_pos end) const noexcept
  {
    return source_loc{begin, end, source_name};
  }

  void print(std::ostream &out) const
  {
    out << *source_name << ':' << begin_pos << '-' << end_pos;
  }

private:

  std::shared_ptr<std::string> source_name;
  source_pos begin_pos;
  source_pos end_pos;

};

static std::ostream &
operator<<(std::ostream &out, const source_loc &loc)
{
  loc.print(out);
  return out;
}

}

#endif /* !BFC_SOURCELOC_HPP */
<commit_msg>Add default constructor to source_loc because I'm an idiot.<commit_after>#ifndef BFC_SOURCELOC_HPP
#define BFC_SOURCELOC_HPP

#include <memory>
#include <ostream>
#include <string>

namespace bfc {

struct source_pos {
  unsigned long off;
  unsigned long row;
  unsigned long col;
};

static std::ostream &
operator<<(std::ostream &out, source_pos pos)
{
  return out << pos.row << ',' << pos.col;
}

class source_loc {

public:

  source_loc(void) :
    source_loc{{0,0,0}, {0,0,0}, std::make_shared<std::string>("(unknown)")}
  {}

  source_loc(source_pos begin, source_pos end, std::string name) noexcept :
    source_loc{begin, end, std::make_shared<std::string>(std::move(name))}
  {}

  source_loc(source_pos begin, source_pos end,
             std::shared_ptr<std::string> name) noexcept :
    begin_pos{begin}, end_pos{end}, source_name{name}
  {}

  source_pos begin(void) const noexcept
  {
    return begin_pos;
  }

  source_pos end(void) const noexcept
  {
    return end_pos;
  }

  const std::string &name(void) const noexcept
  {
    return *source_name;
  }

  source_loc with_pos(source_pos begin, source_pos end) const noexcept
  {
    return source_loc{begin, end, source_name};
  }

  void print(std::ostream &out) const
  {
    out << *source_name << ':' << begin_pos << '-' << end_pos;
  }

private:

  std::shared_ptr<std::string> source_name;
  source_pos begin_pos;
  source_pos end_pos;

};

static std::ostream &
operator<<(std::ostream &out, const source_loc &loc)
{
  loc.print(out);
  return out;
}

}

#endif /* !BFC_SOURCELOC_HPP */
<|endoftext|>


<commit_before>// $Id$

/**************************************************************************
 * This file is property of and copyright by the ALICE HLT Project        *
 * ALICE Experiment at CERN, All rights reserved.                         *
 *                                                                        *
 * Primary Authors: Matthias Richter <Matthias.Richter@ift.uib.no>        *
 *                  for The ALICE HLT Project.                            *
 *                                                                        *
 * Permission to use, copy, modify and distribute this software and its   *
 * documentation strictly for non-commercial purposes is hereby granted   *
 * without fee, provided that the above copyright notice appears in all   *
 * copies and that both the copyright notice and this permission notice   *
 * appear in the supporting documentation. The authors make no claims     *
 * about the suitability of this software for any purpose. It is          *
 * provided "as is" without express or implied warranty.                  *
 **************************************************************************/

/** @file   AliHLTOUT.cxx
    @author Matthias Richter
    @date
    @brief  The control class for HLTOUT data.                            */

// see header file for class documentation
// or
// refer to README to build package
// or
// visit http://web.ift.uib.no/~kjeks/doc/alice-hlt

#include <cerrno>
#include <cassert>
#include "AliHLTOUT.h"

/** ROOT macro for the implementation of ROOT specific class methods */
ClassImp(AliHLTOUT)

AliHLTOUT::AliHLTOUT()
  :
  fSearchDataType(kAliHLTVoidDataType),
  fSearchSpecification(kAliHLTVoidDataSpec),
  fFlags(0),
  fBlockDescList(),
  fCurrent(fBlockDescList.begin()),
  fpBuffer(NULL),
  fDataHandlers()
{
  // see header file for class documentation
  // or
  // refer to README to build package
  // or
  // visit http://web.ift.uib.no/~kjeks/doc/alice-hlt
}

// definitions from ALICE internal note ALICE-INT-2002-010
const unsigned char AliHLTOUT::fgkCDHStatusWord=4;
const unsigned char AliHLTOUT::fgkCDHStatusFlagsOffset=12;

// definitions from ALICE internal note ALICE-INT-2006-XXX
const unsigned char AliHLTOUT::fgkCDHFlagsHLTDecision=6;
const unsigned char AliHLTOUT::fgkCDHFlagsHLTPayload=7;

AliHLTOUT::~AliHLTOUT()
{
  // see header file for class documentation
}

int AliHLTOUT::Init()
{
  // see header file for class documentation
  int iResult=0;
  if ((iResult=GenerateIndex())>=0) {
    if ((iResult=InitHandlers())>=0) {
    }
  }
  return iResult;
}

int AliHLTOUT::GetNofDataBlocks()
{
  // see header file for class documentation
  return fBlockDescList.size();
}

int AliHLTOUT::SelectFirstDataBlock(AliHLTComponentDataType dt, AliHLTUInt32_t spec,
				    AliHLTModuleAgent::AliHLTOUTHandlerType handlerType)
{
  // see header file for class documentation
  if (CheckStatusFlag(kLocked)) return -EPERM;
  fCurrent=fBlockDescList.begin();
  fSearchDataType=dt;
  fSearchSpecification=spec;
  //fSearchHandlerType=handlerType;
  return FindAndSelectDataBlock();
}

int AliHLTOUT::SelectNextDataBlock()
{
  // see header file for class documentation
  if (CheckStatusFlag(kLocked)) return -EPERM;
  fCurrent++;
  return FindAndSelectDataBlock();
}

int AliHLTOUT::FindAndSelectDataBlock()
{
  // see header file for class documentation
  if (CheckStatusFlag(kLocked)) return -EPERM;
  int iResult=-ENOENT;
  while (fCurrent!=fBlockDescList.end() && iResult==-ENOENT) {
    if ((fSearchDataType==kAliHLTAnyDataType || (*fCurrent)==fSearchDataType) &&
	fSearchSpecification==kAliHLTVoidDataSpec || (*fCurrent)==fSearchSpecification &&
	1/*fSearchHandlerType==AliHLTModuleAgent::kUnknownOutput*/) {
      iResult=0;
      // TODO: check the byte order on the current system and the byte order of the
      // data block, print warning when missmatch and user did not check
      //AliHLTOUTByteOrder_t blockBO=CheckByteOrder();
      CheckByteOrder();
      /*
	if (blockBO!=fByteOrder) {
	SetStatusFlag(kByteOrderWarning);

	}
       */
      ClearStatusFlag(kByteOrderChecked);

      // TODO: check the alignment on the current system and the alignment of the
      // data block, print warning when missmatch and user did not check
      ClearStatusFlag(kAlignmentChecked);
    }
    fCurrent++;
  }
  return iResult;
}

int AliHLTOUT::GetDataBlockDescription(AliHLTComponentDataType& dt, AliHLTUInt32_t& spec)
{
  // see header file for class documentation
  int iResult=-ENOENT;
  if (fCurrent!=fBlockDescList.end()) {
    iResult=0;
    dt=(*fCurrent);
    spec=(*fCurrent);
  }
  return iResult;
}

AliHLTUInt32_t AliHLTOUT::GetDataBlockIndex()
{
  // see header file for class documentation
  assert(0); // not implemented
  return AliHLTOUTInvalidIndex;
}

int AliHLTOUT::GetDataBuffer(const AliHLTUInt8_t* &pBuffer, AliHLTUInt32_t& size)
{
  // see header file for class documentation
  int iResult=-ENOENT;
  pBuffer=NULL;
  size=0;
  if (fCurrent!=fBlockDescList.end()) {
    if ((iResult=GetDataBuffer((*fCurrent).GetIndex(), pBuffer, size))>=0) {
      fpBuffer=pBuffer;
    }
  }
  return iResult;
}

int AliHLTOUT::ReleaseDataBuffer(const AliHLTUInt8_t* pBuffer)
{
  // see header file for class documentation
  int iResult=0;
  if (pBuffer==fpBuffer) {
    fpBuffer=NULL;
  } else {
    HLTWarning("buffer %p does not match the provided one %p", pBuffer, fpBuffer);
  }
  return iResult;
}

int AliHLTOUT::AddBlockDescriptor(const AliHLTOUTBlockDescriptor desc)
{
  // see header file for class documentation
  if (!CheckStatusFlag(kCollecting)) return -EPERM;
  int iResult=0;
  fBlockDescList.push_back(desc);
  return iResult;
}

AliHLTOUT::AliHLTOUTByteOrder_t AliHLTOUT::CheckByteOrder()
{
  // see header file for class documentation
  if (fCurrent!=fBlockDescList.end()) {
    SetStatusFlag(kByteOrderChecked);
    AliHLTOUT::AliHLTOUTByteOrder_t order=CheckBlockByteOrder((*fCurrent).GetIndex());
    return order;
  }
  return kInvalidByteOrder;
}

int AliHLTOUT::CheckAlignment(AliHLTOUT::AliHLTOUTDataType_t type)
{
  // see header file for class documentation
  if (fCurrent!=fBlockDescList.end()) {
    SetStatusFlag(kAlignmentChecked);
    int alignment=CheckBlockAlignment((*fCurrent).GetIndex(), type);
    return alignment;
  }
  return -ENOENT;
}

int AliHLTOUT::InitHandlers()
{
  // see header file for class documentation
  int iResult=0;
  AliHLTOUTIndexList remnants;
  for (iResult=SelectFirstDataBlock(kAliHLTAnyDataType, kAliHLTVoidDataSpec); iResult>0; iResult=SelectNextDataBlock()) {
    remnants.push_back(GetDataBlockIndex());
    AliHLTComponentDataType dt=kAliHLTVoidDataType;
    AliHLTUInt32_t spec=kAliHLTVoidDataSpec;
    if ((iResult=GetDataBlockDescription(dt, spec))<0) break;
    for (AliHLTModuleAgent* pAgent=AliHLTModuleAgent::GetFirstAgent(); pAgent && iResult>=0; pAgent=AliHLTModuleAgent::GetNextAgent()) {
      AliHLTModuleAgent::AliHLTOUTHandlerDesc handlerDesc;
      if (pAgent->GetHandlerDescription(dt, spec, &handlerDesc)>0) {
	AliHLTOUTHandlerListEntry entry(pAgent->GetOutputHandler(dt, spec), handlerDesc, pAgent, GetDataBlockIndex());
	iResult=InsertHandler(entry);
	remnants.pop_back();
	break;
      }
    }
  }
  if (remnants.size()>0) {
    HLTWarning("no handlers found for %d data blocks out of %d", remnants.size(), GetNofDataBlocks());
    vector<AliHLTOUTBlockDescriptor>::iterator block=fBlockDescList.begin();
    for (AliHLTOUTIndexList::iterator element=remnants.begin(); element!=remnants.end(); element++) {
      for (int trials=0; trials<2; trials++) {
	do {
	  // we start searching the index from the current position in the block list
	  if ((*block).GetIndex()==*element) break;
	} while ((++block)!=fBlockDescList.end());
	if (block==fBlockDescList.end()) {
	  // rewind and try again
	  block=fBlockDescList.begin();
	}
      }
      assert(block!=fBlockDescList.end());
      if (block!=fBlockDescList.end()) {
	HLTDebug("   %s", AliHLTComponent::DataType2Text((AliHLTComponentDataType)*block).c_str());
      }
    }
  }
  return iResult;
}

int AliHLTOUT::InsertHandler(const AliHLTOUTHandlerListEntry &entry)
{
  // see header file for class documentation
  int iResult=0;
  vector<AliHLTOUTHandlerListEntry>::iterator element=fDataHandlers.begin();
  while (element!=fDataHandlers.end()) {
    if (entry==(*element)) break;
    element++;
  }
  if (element==fDataHandlers.end()) {
    fDataHandlers.push_back(entry);
  } else {

  }
  return iResult;
}

AliHLTOUT::AliHLTOUTHandlerListEntry::AliHLTOUTHandlerListEntry(AliHLTOUTHandler* pHandler,
								AliHLTModuleAgent::AliHLTOUTHandlerDesc& handlerDesc,
								AliHLTModuleAgent* pAgent,
								AliHLTUInt32_t index)
  :
  fpHandler(pHandler),
  fHandlerDesc(handlerDesc),
  fpAgent(pAgent),
  fBlocks()
{
  // see header file for class documentation
  fBlocks.push_back(index);
}

AliHLTOUT::AliHLTOUTHandlerListEntry::AliHLTOUTHandlerListEntry(const AliHLTOUTHandlerListEntry& src)
  :
  fpHandler(src.fpHandler),
  fHandlerDesc(src.fHandlerDesc),
  fpAgent(src.fpAgent),
  fBlocks()
{
  // see header file for class documentation
  fBlocks.assign(src.fBlocks.begin(), src.fBlocks.end());
}

AliHLTOUT::AliHLTOUTHandlerListEntry& AliHLTOUT::AliHLTOUTHandlerListEntry::operator=(const AliHLTOUTHandlerListEntry& src)
{
  // see header file for class documentation
  fpHandler=src.fpHandler;
  fHandlerDesc=src.fHandlerDesc;
  fpAgent=src.fpAgent;
  fBlocks.assign(src.fBlocks.begin(), src.fBlocks.end());
  return *this;
}

AliHLTUInt32_t AliHLTOUT::AliHLTOUTHandlerListEntry::operator[](int i) const {
  return fBlocks.size()>i?fBlocks[i]:AliHLTOUTInvalidIndex;
}

void AliHLTOUT::AliHLTOUTHandlerListEntry::AddIndex(AliHLTUInt32_t index) {
  fBlocks.push_back(index);
}
<commit_msg>Copy constructor and asignment operator (Matthias)<commit_after>// $Id$

/**************************************************************************
 * This file is property of and copyright by the ALICE HLT Project        *
 * ALICE Experiment at CERN, All rights reserved.                         *
 *                                                                        *
 * Primary Authors: Matthias Richter <Matthias.Richter@ift.uib.no>        *
 *                  for The ALICE HLT Project.                            *
 *                                                                        *
 * Permission to use, copy, modify and distribute this software and its   *
 * documentation strictly for non-commercial purposes is hereby granted   *
 * without fee, provided that the above copyright notice appears in all   *
 * copies and that both the copyright notice and this permission notice   *
 * appear in the supporting documentation. The authors make no claims     *
 * about the suitability of this software for any purpose. It is          *
 * provided "as is" without express or implied warranty.                  *
 **************************************************************************/

/** @file   AliHLTOUT.cxx
    @author Matthias Richter
    @date
    @brief  The control class for HLTOUT data.                            */

// see header file for class documentation
// or
// refer to README to build package
// or
// visit http://web.ift.uib.no/~kjeks/doc/alice-hlt

#include <cerrno>
#include <cassert>
#include "AliHLTOUT.h"

/** ROOT macro for the implementation of ROOT specific class methods */
ClassImp(AliHLTOUT)

AliHLTOUT::AliHLTOUT()
  :
  fSearchDataType(kAliHLTVoidDataType),
  fSearchSpecification(kAliHLTVoidDataSpec),
  fFlags(0),
  fBlockDescList(),
  fCurrent(fBlockDescList.begin()),
  fpBuffer(NULL),
  fDataHandlers()
{
  // see header file for class documentation
  // or
  // refer to README to build package
  // or
  // visit http://web.ift.uib.no/~kjeks/doc/alice-hlt
}

// definitions from ALICE internal note ALICE-INT-2002-010
const unsigned char AliHLTOUT::fgkCDHStatusWord=4;
const unsigned char AliHLTOUT::fgkCDHStatusFlagsOffset=12;

// definitions from ALICE internal note ALICE-INT-2006-XXX
const unsigned char AliHLTOUT::fgkCDHFlagsHLTDecision=6;
const unsigned char AliHLTOUT::fgkCDHFlagsHLTPayload=7;

AliHLTOUT::~AliHLTOUT()
{
  // see header file for class documentation
}

int AliHLTOUT::Init()
{
  // see header file for class documentation
  int iResult=0;
  if ((iResult=GenerateIndex())>=0) {
    if ((iResult=InitHandlers())>=0) {
    }
  }
  return iResult;
}

int AliHLTOUT::GetNofDataBlocks()
{
  // see header file for class documentation
  return fBlockDescList.size();
}

int AliHLTOUT::SelectFirstDataBlock(AliHLTComponentDataType dt, AliHLTUInt32_t spec,
				    AliHLTModuleAgent::AliHLTOUTHandlerType handlerType)
{
  // see header file for class documentation
  if (CheckStatusFlag(kLocked)) return -EPERM;
  fCurrent=fBlockDescList.begin();
  fSearchDataType=dt;
  fSearchSpecification=spec;
  //fSearchHandlerType=handlerType;
  return FindAndSelectDataBlock();
}

int AliHLTOUT::SelectNextDataBlock()
{
  // see header file for class documentation
  if (CheckStatusFlag(kLocked)) return -EPERM;
  fCurrent++;
  return FindAndSelectDataBlock();
}

int AliHLTOUT::FindAndSelectDataBlock()
{
  // see header file for class documentation
  if (CheckStatusFlag(kLocked)) return -EPERM;
  int iResult=-ENOENT;
  while (fCurrent!=fBlockDescList.end() && iResult==-ENOENT) {
    if ((fSearchDataType==kAliHLTAnyDataType || (*fCurrent)==fSearchDataType) &&
	fSearchSpecification==kAliHLTVoidDataSpec || (*fCurrent)==fSearchSpecification &&
	1/*fSearchHandlerType==AliHLTModuleAgent::kUnknownOutput*/) {
      iResult=0;
      // TODO: check the byte order on the current system and the byte order of the
      // data block, print warning when missmatch and user did not check
      //AliHLTOUTByteOrder_t blockBO=CheckByteOrder();
      CheckByteOrder();
      /*
	if (blockBO!=fByteOrder) {
	SetStatusFlag(kByteOrderWarning);

	}
       */
      ClearStatusFlag(kByteOrderChecked);

      // TODO: check the alignment on the current system and the alignment of the
      // data block, print warning when missmatch and user did not check
      ClearStatusFlag(kAlignmentChecked);
    }
    fCurrent++;
  }
  return iResult;
}

int AliHLTOUT::GetDataBlockDescription(AliHLTComponentDataType& dt, AliHLTUInt32_t& spec)
{
  // see header file for class documentation
  int iResult=-ENOENT;
  if (fCurrent!=fBlockDescList.end()) {
    iResult=0;
    dt=(*fCurrent);
    spec=(*fCurrent);
  }
  return iResult;
}

AliHLTUInt32_t AliHLTOUT::GetDataBlockIndex()
{
  // see header file for class documentation
  assert(0); // not implemented
  return AliHLTOUTInvalidIndex;
}

int AliHLTOUT::GetDataBuffer(const AliHLTUInt8_t* &pBuffer, AliHLTUInt32_t& size)
{
  // see header file for class documentation
  int iResult=-ENOENT;
  pBuffer=NULL;
  size=0;
  if (fCurrent!=fBlockDescList.end()) {
    if ((iResult=GetDataBuffer((*fCurrent).GetIndex(), pBuffer, size))>=0) {
      fpBuffer=pBuffer;
    }
  }
  return iResult;
}

int AliHLTOUT::ReleaseDataBuffer(const AliHLTUInt8_t* pBuffer)
{
  // see header file for class documentation
  int iResult=0;
  if (pBuffer==fpBuffer) {
    fpBuffer=NULL;
  } else {
    HLTWarning("buffer %p does not match the provided one %p", pBuffer, fpBuffer);
  }
  return iResult;
}

int AliHLTOUT::AddBlockDescriptor(const AliHLTOUTBlockDescriptor desc)
{
  // see header file for class documentation
  if (!CheckStatusFlag(kCollecting)) return -EPERM;
  int iResult=0;
  fBlockDescList.push_back(desc);
  return iResult;
}

AliHLTOUT::AliHLTOUTByteOrder_t AliHLTOUT::CheckByteOrder()
{
  // see header file for class documentation
  if (fCurrent!=fBlockDescList.end()) {
    SetStatusFlag(kByteOrderChecked);
    AliHLTOUT::AliHLTOUTByteOrder_t order=CheckBlockByteOrder((*fCurrent).GetIndex());
    return order;
  }
  return kInvalidByteOrder;
}

int AliHLTOUT::CheckAlignment(AliHLTOUT::AliHLTOUTDataType_t type)
{
  // see header file for class documentation
  if (fCurrent!=fBlockDescList.end()) {
    SetStatusFlag(kAlignmentChecked);
    int alignment=CheckBlockAlignment((*fCurrent).GetIndex(), type);
    return alignment;
  }
  return -ENOENT;
}

int AliHLTOUT::InitHandlers()
{
  // see header file for class documentation
  int iResult=0;
  AliHLTOUTIndexList remnants;
  for (iResult=SelectFirstDataBlock(kAliHLTAnyDataType, kAliHLTVoidDataSpec); iResult>0; iResult=SelectNextDataBlock()) {
    remnants.push_back(GetDataBlockIndex());
    AliHLTComponentDataType dt=kAliHLTVoidDataType;
    AliHLTUInt32_t spec=kAliHLTVoidDataSpec;
    if ((iResult=GetDataBlockDescription(dt, spec))<0) break;
    for (AliHLTModuleAgent* pAgent=AliHLTModuleAgent::GetFirstAgent(); pAgent && iResult>=0; pAgent=AliHLTModuleAgent::GetNextAgent()) {
      AliHLTModuleAgent::AliHLTOUTHandlerDesc handlerDesc;
      if (pAgent->GetHandlerDescription(dt, spec, &handlerDesc)>0) {
	AliHLTOUTHandlerListEntry entry(pAgent->GetOutputHandler(dt, spec), handlerDesc, pAgent, GetDataBlockIndex());
	iResult=InsertHandler(entry);
	remnants.pop_back();
	break;
      }
    }
  }
  if (remnants.size()>0) {
    HLTWarning("no handlers found for %d data blocks out of %d", remnants.size(), GetNofDataBlocks());
    vector<AliHLTOUTBlockDescriptor>::iterator block=fBlockDescList.begin();
    for (AliHLTOUTIndexList::iterator element=remnants.begin(); element!=remnants.end(); element++) {
      for (int trials=0; trials<2; trials++) {
	do {
	  // we start searching the index from the current position in the block list
	  if ((*block).GetIndex()==*element) break;
	} while ((++block)!=fBlockDescList.end());
	if (block==fBlockDescList.end()) {
	  // rewind and try again
	  block=fBlockDescList.begin();
	}
      }
      assert(block!=fBlockDescList.end());
      if (block!=fBlockDescList.end()) {
	HLTDebug("   %s", AliHLTComponent::DataType2Text((AliHLTComponentDataType)*block).c_str());
      }
    }
  }
  return iResult;
}

int AliHLTOUT::InsertHandler(const AliHLTOUTHandlerListEntry &entry)
{
  // see header file for class documentation
  int iResult=0;
  vector<AliHLTOUTHandlerListEntry>::iterator element=fDataHandlers.begin();
  while (element!=fDataHandlers.end()) {
    if (entry==(*element)) break;
    element++;
  }
  if (element==fDataHandlers.end()) {
    fDataHandlers.push_back(entry);
  } else {

  }
  return iResult;
}

AliHLTOUT::AliHLTOUTHandlerListEntry::AliHLTOUTHandlerListEntry(AliHLTOUTHandler* pHandler,
								AliHLTModuleAgent::AliHLTOUTHandlerDesc& handlerDesc,
								AliHLTModuleAgent* pAgent,
								AliHLTUInt32_t index)
  :
  fpHandler(pHandler),
  fHandlerDesc(handlerDesc),
  fpAgent(pAgent),
  fBlocks()
{
  // see header file for class documentation
  fBlocks.push_back(index);
}

AliHLTOUT::AliHLTOUTHandlerListEntry::AliHLTOUTHandlerListEntry(const AliHLTOUTHandlerListEntry& src)
  :
  fpHandler(src.fpHandler),
  fHandlerDesc(src.fHandlerDesc),
  fpAgent(src.fpAgent),
  fBlocks()
{
  // see header file for class documentation
  fBlocks.assign(src.fBlocks.begin(), src.fBlocks.end());
}

AliHLTOUT::AliHLTOUTHandlerListEntry::~AliHLTOUTHandlerListEntry()
{
  // see header file for class documentation
}

AliHLTOUT::AliHLTOUTHandlerListEntry& AliHLTOUT::AliHLTOUTHandlerListEntry::operator=(const AliHLTOUTHandlerListEntry& src)
{
  // see header file for class documentation
  fpHandler=src.fpHandler;
  fHandlerDesc=src.fHandlerDesc;
  fpAgent=src.fpAgent;
  fBlocks.assign(src.fBlocks.begin(), src.fBlocks.end());
  return *this;
}

AliHLTUInt32_t AliHLTOUT::AliHLTOUTHandlerListEntry::operator[](int i) const {
  return fBlocks.size()>i?fBlocks[i]:AliHLTOUTInvalidIndex;
}

bool AliHLTOUT::AliHLTOUTHandlerListEntry::operator==(const AliHLTOUTHandlerListEntry& entry) const
{
  return false;
}

void AliHLTOUT::AliHLTOUTHandlerListEntry::AddIndex(AliHLTUInt32_t index) {
  fBlocks.push_back(index);
}
<|endoftext|>


<commit_before>// Author: Daisuke Kanaizumi
// Affiliation: Department of Applied Mathematics, Waseda University
// Email: daisuke15@asagi.waseda.jp

// verification program for q-Bessel functions
// March 9th, 2017

#ifndef QBESSEL_HPP
#define QBESSEL_HPP

#include <kv/interval.hpp>
#include <kv/rdouble.hpp>

namespace kv{
template <class T> interval<T>Jackson1(const interval<T>& z,const interval<T>& nu,const interval<T>& q){
// verification program for Jackson`s 1st q-Bessel function
interval<T>res,a,b,c,series;
int j,K;
T rad;
if(abs(z)>=2){
throw std::domain_error("Jackson`s 1st q-Bessel function is not defined");
}
if(abs(q)>=1){
throw std::domain_error("absolute value of q must be under 1");
}
 if(z<0){
   throw std::domain_error("z must be positive");
 }
 if (pow(q,nu)<1){
j=1;
K=500;
a=1.;
b=1.;
c=1.;
// Leibniz criterion
 for (int k=1; k<=K; k++){
    j = -1*j;
    b=b*(1-pow(q,k));
    c=c*(1-pow(q,k+nu));
    a = a+j*pow(z/2,2*k)/(b*c);
  }
b=b*(1-pow(q,K+1));
c=c*(1-pow(q,K+nu+1));

rad=abs(pow(z/2,2*K+2)/(b*c)).upper();
series=a+rad*interval<T>(-1.,1.);
res=pow(z/2,nu)*series/Karpelevich(interval<T>(pow(q,nu+1)),interval<T>(q));
}
 else{
res=pow(z/2,nu)*infinite_qPochhammer(interval<T>(pow(q,nu+1)),interval<T>(q))*
  Heine(interval<T>(0),interval<T>(0),interval<T>(pow(q,nu+1)),interval<T>(q),interval<T>(-z*z/4))/Euler(interval<T>(q));
}
 return res;
}
template <class T> complex<interval<T> >Jackson1(const complex<interval<T> >& z,const complex<interval<T> >& nu,const interval<T>& q){
complex<interval<T> >res;
if(abs(q)>=1){
throw std::domain_error("absolute value of q must be under 1");
}
 res=pow(z/2,nu)*infinite_qPochhammer(complex<interval<T> >(pow(q,nu+1)),interval<T>(q))*
  Heine(complex<interval<T> >(0),complex<interval<T> >(0),complex<interval<T> >(pow(q,nu+1)),interval<T>(q),complex<interval<T> >(-z*z/4))/Euler(interval<T>(q));
 return res;
}

template <class T> complex<interval<T> >modified_qBessel1(const complex<interval<T> >& z,const complex<interval<T> >& nu,const interval<T>& q){
  // verification program for 1st modified q-Bessel
complex<interval<T> >res;
if(abs(q)>=1){
throw std::domain_error("absolute value of q must be under 1");
}
 res=pow(z/2,nu)*infinite_qPochhammer(complex<interval<T> >(pow(q,nu+1)),interval<T>(q))*
  Heine(complex<interval<T> >(0),complex<interval<T> >(0),complex<interval<T> >(pow(q,nu+1)),interval<T>(q),complex<interval<T> >(z*z/4))/Euler(interval<T>(q));
 return res;
}

template <class T> interval<T>Jackson2(const interval<T>& z,const interval<T>& nu,const interval<T>& q){
// verification program for Jackson`s 2nd q-Bessel function
interval<T>res,a,b,c,series;
int j,K;
T rad;
if(abs(q)>=1){
throw std::domain_error("absolute value of q must be under 1");
}
 if (pow(q,nu)<1 && abs(z)>pow(q,nu)&&z<500){
   // this method will not converge when z>500
j=1;
K=500;
a=1.;
b=1.;
c=1.;
// Leibniz criterion
 for (int k=1; k<=K; k++){
    j = -1*j;
    b=b*(1-pow(q,k));
    c=c*(1-pow(q,k+nu));
    a = a+j*pow(q,k*(k-1))*pow(pow(q,nu+1)*z*z/4,k)/(b*c);
  }
  b=b*(1-pow(q,K+1));
  c=c*(1-pow(q,K+nu+1));

 rad=abs(pow(q,K*(K+1))*pow(pow(q,nu+1)*z*z/4,K+1)/(b*c)).upper();
 series=a+rad*interval<T>(-1.,1.);
 res=pow(z/2,nu)*series/Karpelevich(interval<T>(pow(q,nu+1)),interval<T>(q));
}
 else{
   res=pow(z/2,nu)*infinite_qPochhammer(interval<T>(pow(q,nu+1)),interval<T>(q))*
     _0phi_1(interval<T>(pow(q,nu+1)),interval<T>(q),interval<T>(-z*z*pow(q,nu+1)/4))/Euler(interval<T>(q));
 }
  return res;
}
template <class T> complex<interval<T> >Jackson2(const complex<interval<T> >& z,const complex<interval<T> >& nu,const interval<T>& q){
  complex<interval<T> >res,pq;
if(abs(q)>=1){
throw std::domain_error("absolute value of q must be under 1");
}
 pq=pow(q,nu+1);
 res=pow(z/2,nu)*infinite_qPochhammer(complex<interval<T> >(pq),interval<T>(q))*
   _0phi_1(complex<interval<T> >(pq),interval<T>(q),complex<interval<T> >(-z*z*pq/4))/Euler(interval<T>(q));
 return res;
}
template <class T> complex<interval<T> >modified_qBessel2(const complex<interval<T> >& z,const complex<interval<T> >& nu,const interval<T>& q){
  //verification program for 2nd modified q-Bessel function
  complex<interval<T> >res,pq;
if(abs(q)>=1){
throw std::domain_error("absolute value of q must be under 1");
}
 pq=pow(q,nu+1);
 res=pow(z/2,nu)*infinite_qPochhammer(complex<interval<T> >(pq),interval<T>(q))*
   _0phi_1(complex<interval<T> >(pq),interval<T>(q),complex<interval<T> >(z*z*pq/4))/Euler(interval<T>(q));
 return res;
}

template <class T> complex<interval<T> >Hahn_Exton(const complex<interval<T> >& z,const complex<interval<T> >& nu,const interval<T>& q){
  // verification program for Hahn-Exton q-Bessel function
  complex<interval<T> >res,pq;
if(abs(q)>=1){
throw std::domain_error("absolute value of q must be under 1");
}
 pq=pow(q,nu+1);
 res=pow(z,nu)*infinite_qPochhammer(complex<interval<T> >(pq),interval<T>(q))*
   _1phi_1(complex<interval<T> >(0),complex<interval<T> >(pq),interval<T>(q),complex<interval<T> >(z*z*q))/Euler(interval<T>(q));
 return res;
}

}

#endif
<commit_msg>Delete qBessel.hpp<commit_after><|endoftext|>


<commit_before>// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/renderer_host/render_widget_host_view_gtk.h"

#include <gtk/gtk.h>
#include <gdk/gdk.h>
#include <cairo/cairo.h>

#include "base/logging.h"
#include "base/string_util.h"
#include "chrome/common/native_web_keyboard_event.h"
#include "chrome/common/x11_util.h"
#include "chrome/browser/renderer_host/backing_store.h"
#include "chrome/browser/renderer_host/render_widget_host.h"
#include "skia/ext/bitmap_platform_device_linux.h"
#include "skia/ext/platform_device_linux.h"
#include "webkit/glue/webinputevent.h"

namespace {

// This class is a simple convenience wrapper for Gtk functions. It has only
// static methods.
class RenderWidgetHostViewGtkWidget {
 public:
  static GtkWidget* CreateNewWidget(RenderWidgetHostViewGtk* host_view) {
    GtkWidget* widget = gtk_drawing_area_new();
    gtk_widget_set_double_buffered(widget, FALSE);

    gtk_widget_add_events(widget, GDK_EXPOSURE_MASK |
                                  GDK_POINTER_MOTION_MASK |
                                  GDK_BUTTON_PRESS_MASK |
                                  GDK_BUTTON_RELEASE_MASK |
                                  GDK_KEY_PRESS_MASK |
                                  GDK_KEY_RELEASE_MASK);
    GTK_WIDGET_SET_FLAGS(widget, GTK_CAN_FOCUS);

    g_signal_connect(widget, "configure-event",
                     G_CALLBACK(ConfigureEvent), host_view);
    g_signal_connect(widget, "expose-event",
                     G_CALLBACK(ExposeEvent), host_view);
    g_signal_connect(widget, "key-press-event",
                     G_CALLBACK(KeyPressReleaseEvent), host_view);
    g_signal_connect(widget, "key-release-event",
                     G_CALLBACK(KeyPressReleaseEvent), host_view);
    g_signal_connect(widget, "focus-in-event",
                     G_CALLBACK(FocusIn), host_view);
    g_signal_connect(widget, "focus-out-event",
                     G_CALLBACK(FocusOut), host_view);
    g_signal_connect(widget, "button-press-event",
                     G_CALLBACK(ButtonPressReleaseEvent), host_view);
    g_signal_connect(widget, "button-release-event",
                     G_CALLBACK(ButtonPressReleaseEvent), host_view);
    g_signal_connect(widget, "motion-notify-event",
                     G_CALLBACK(MouseMoveEvent), host_view);
    g_signal_connect(widget, "scroll-event",
                     G_CALLBACK(MouseScrollEvent), host_view);

    return widget;
  }

 private:
  static gboolean ConfigureEvent(GtkWidget* widget, GdkEventConfigure* config,
                                 RenderWidgetHostViewGtk* host_view) {
    host_view->GetRenderWidgetHost()->WasResized();
    return FALSE;
  }

  static gboolean ExposeEvent(GtkWidget* widget, GdkEventExpose* expose,
                              RenderWidgetHostViewGtk* host_view) {
    const gfx::Rect damage_rect(expose->area);
    host_view->Paint(damage_rect);
    return FALSE;
  }

  static gboolean KeyPressReleaseEvent(GtkWidget* widget, GdkEventKey* event,
                                       RenderWidgetHostViewGtk* host_view) {
    NativeWebKeyboardEvent wke(event);
    host_view->GetRenderWidgetHost()->ForwardKeyboardEvent(wke);
    return FALSE;
  }

  static gboolean FocusIn(GtkWidget* widget, GdkEventFocus* focus,
                          RenderWidgetHostViewGtk* host_view) {
    host_view->GetRenderWidgetHost()->Focus();
    return FALSE;
  }

  static gboolean FocusOut(GtkWidget* widget, GdkEventFocus* focus,
                           RenderWidgetHostViewGtk* host_view) {
    host_view->GetRenderWidgetHost()->Blur();
    return FALSE;
  }

  static gboolean ButtonPressReleaseEvent(
      GtkWidget* widget, GdkEventButton* event,
      RenderWidgetHostViewGtk* host_view) {
    WebMouseEvent wme(event);
    host_view->GetRenderWidgetHost()->ForwardMouseEvent(wme);

    // TODO(evanm): why is this necessary here but not in test shell?
    // This logic is the same as GtkButton.
    if (event->type == GDK_BUTTON_PRESS && !GTK_WIDGET_HAS_FOCUS(widget))
      gtk_widget_grab_focus(widget);

    return FALSE;
  }

  static gboolean MouseMoveEvent(GtkWidget* widget, GdkEventMotion* event,
                                 RenderWidgetHostViewGtk* host_view) {
    WebMouseEvent wme(event);
    host_view->GetRenderWidgetHost()->ForwardMouseEvent(wme);
    return FALSE;
  }

  static gboolean MouseScrollEvent(GtkWidget* widget, GdkEventScroll* event,
                                   RenderWidgetHostViewGtk* host_view) {
    WebMouseWheelEvent wmwe(event);
    host_view->GetRenderWidgetHost()->ForwardWheelEvent(wmwe);
    return FALSE;
  }

  DISALLOW_IMPLICIT_CONSTRUCTORS(RenderWidgetHostViewGtkWidget);
};

}  // namespace

// static
RenderWidgetHostView* RenderWidgetHostView::CreateViewForWidget(
    RenderWidgetHost* widget) {
  return new RenderWidgetHostViewGtk(widget);
}

RenderWidgetHostViewGtk::RenderWidgetHostViewGtk(RenderWidgetHost* widget_host)
    : host_(widget_host) {
  host_->set_view(this);
  view_ = RenderWidgetHostViewGtkWidget::CreateNewWidget(this);
}

RenderWidgetHostViewGtk::~RenderWidgetHostViewGtk() {
}

void RenderWidgetHostViewGtk::DidBecomeSelected() {
  NOTIMPLEMENTED();
}

void RenderWidgetHostViewGtk::WasHidden() {
  NOTIMPLEMENTED();
}

void RenderWidgetHostViewGtk::SetSize(const gfx::Size& size) {
  NOTIMPLEMENTED();
}

gfx::NativeView RenderWidgetHostViewGtk::GetPluginNativeView() {
  // TODO(port): We need to pass some widget pointer out here because the
  // renderer echos it back to us when it asks for GetScreenInfo. However, we
  // should probably be passing the top-level window or some such instead.
  return view_;
}

void RenderWidgetHostViewGtk::MovePluginWindows(
    const std::vector<WebPluginGeometry>& plugin_window_moves) {
  if (plugin_window_moves.empty())
    return;

  NOTIMPLEMENTED();
}

void RenderWidgetHostViewGtk::Focus() {
  NOTIMPLEMENTED();
}

void RenderWidgetHostViewGtk::Blur() {
  NOTIMPLEMENTED();
}

bool RenderWidgetHostViewGtk::HasFocus() {
  NOTIMPLEMENTED();
  return false;
}

void RenderWidgetHostViewGtk::Show() {
  NOTIMPLEMENTED();
}

void RenderWidgetHostViewGtk::Hide() {
  NOTIMPLEMENTED();
}

gfx::Rect RenderWidgetHostViewGtk::GetViewBounds() const {
  return gfx::Rect(view_->allocation.x, view_->allocation.y,
                   view_->allocation.width, view_->allocation.height);
}

void RenderWidgetHostViewGtk::UpdateCursor(const WebCursor& cursor) {
  // TODO(port): some of this logic may need moving to UpdateCursorIfOverSelf at
  // some point.
  GdkCursorType current_cursor_type = current_cursor_.GetCursorType();
  GdkCursorType new_cursor_type = cursor.GetCursorType();
  current_cursor_ = cursor;
  GdkCursor* gdk_cursor;
  if (new_cursor_type == GDK_CURSOR_IS_PIXMAP) {
    // TODO(port): WebKit bug https://bugs.webkit.org/show_bug.cgi?id=16388 is
    // that calling gdk_window_set_cursor repeatedly is expensive.  We should
    // avoid it here where possible.
    gdk_cursor = current_cursor_.GetCustomCursor();
  } else {
    // Optimize the common case, where the cursor hasn't changed.
    // However, we can switch between different pixmaps, so only on the
    // non-pixmap branch.
    if (new_cursor_type == current_cursor_type)
      return;
    gdk_cursor = gdk_cursor_new(new_cursor_type);
  }
  gdk_window_set_cursor(view_->window, gdk_cursor);
  // The window now owns the cursor.
  gdk_cursor_unref(gdk_cursor);
}

void RenderWidgetHostViewGtk::UpdateCursorIfOverSelf() {
  // Windows uses this to show the resizer arrow if the mouse is over the
  // bottom-right corner.
  NOTIMPLEMENTED();
}

void RenderWidgetHostViewGtk::SetIsLoading(bool is_loading) {
  // Windows tracks loading whether it's loading to switch the cursor
  // out for the arrow+hourglass one.  We don't have such a cursor, so we just
  // ignore this.
}

void RenderWidgetHostViewGtk::IMEUpdateStatus(int control,
                                              const gfx::Rect& caret_rect) {
  NOTIMPLEMENTED();
}

void RenderWidgetHostViewGtk::DidPaintRect(const gfx::Rect& rect) {
  Paint(rect);
}

void RenderWidgetHostViewGtk::DidScrollRect(const gfx::Rect& rect, int dx,
                                            int dy) {
  Paint(rect);
}

void RenderWidgetHostViewGtk::RenderViewGone() {
  NOTIMPLEMENTED();
}

void RenderWidgetHostViewGtk::Destroy() {
  // We need to disconnect ourselves from our parent widget at this time; this
  // does the right thing, automatically removing ourselves from our parent
  // container.
  gtk_widget_destroy(view_);
  view_ = NULL;
}

void RenderWidgetHostViewGtk::SetTooltipText(const std::wstring& tooltip_text) {
  if (tooltip_text.empty()) {
    gtk_widget_set_has_tooltip(view_, FALSE);
  } else {
    gtk_widget_set_tooltip_text(view_, WideToUTF8(tooltip_text).c_str());
  }
}

BackingStore* RenderWidgetHostViewGtk::AllocBackingStore(
    const gfx::Size& size) {
  Display* display = x11_util::GetXDisplay();
  void* visual = x11_util::GetVisualFromGtkWidget(view_);
  XID root_window = x11_util::GetX11RootWindow();
  bool use_render = x11_util::QueryRenderSupport(display);
  bool use_shared_memory = x11_util::QuerySharedMemorySupport(display);
  int depth = gtk_widget_get_visual(view_)->depth;

  return new BackingStore(size, display, depth, visual, root_window,
                          use_render, use_shared_memory);
}

void RenderWidgetHostViewGtk::Paint(const gfx::Rect& damage_rect) {
  BackingStore* backing_store = host_->GetBackingStore();

  if (backing_store) {
    // Only render the widget if it is attached to a window; there's a short
    // period where this object isn't attached to a window but hasn't been
    // Destroy()ed yet and it receives paint messages...
    GdkWindow* window = view_->window;
    if (window) {
      backing_store->ShowRect(
          damage_rect, x11_util::GetX11WindowFromGtkWidget(view_));
    }
  } else {
    NOTIMPLEMENTED();
  }
}
<commit_msg>Have RenderWidgetHostViewGtk take ownership of its widget.<commit_after>// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/renderer_host/render_widget_host_view_gtk.h"

#include <gtk/gtk.h>
#include <gdk/gdk.h>
#include <cairo/cairo.h>

#include "base/logging.h"
#include "base/string_util.h"
#include "chrome/common/native_web_keyboard_event.h"
#include "chrome/common/x11_util.h"
#include "chrome/browser/renderer_host/backing_store.h"
#include "chrome/browser/renderer_host/render_widget_host.h"
#include "skia/ext/bitmap_platform_device_linux.h"
#include "skia/ext/platform_device_linux.h"
#include "webkit/glue/webinputevent.h"

namespace {

// This class is a simple convenience wrapper for Gtk functions. It has only
// static methods.
class RenderWidgetHostViewGtkWidget {
 public:
  static GtkWidget* CreateNewWidget(RenderWidgetHostViewGtk* host_view) {
    GtkWidget* widget = gtk_drawing_area_new();
    gtk_widget_set_double_buffered(widget, FALSE);

    gtk_widget_add_events(widget, GDK_EXPOSURE_MASK |
                                  GDK_POINTER_MOTION_MASK |
                                  GDK_BUTTON_PRESS_MASK |
                                  GDK_BUTTON_RELEASE_MASK |
                                  GDK_KEY_PRESS_MASK |
                                  GDK_KEY_RELEASE_MASK);
    GTK_WIDGET_SET_FLAGS(widget, GTK_CAN_FOCUS);

    g_signal_connect(widget, "configure-event",
                     G_CALLBACK(ConfigureEvent), host_view);
    g_signal_connect(widget, "expose-event",
                     G_CALLBACK(ExposeEvent), host_view);
    g_signal_connect(widget, "key-press-event",
                     G_CALLBACK(KeyPressReleaseEvent), host_view);
    g_signal_connect(widget, "key-release-event",
                     G_CALLBACK(KeyPressReleaseEvent), host_view);
    g_signal_connect(widget, "focus-in-event",
                     G_CALLBACK(FocusIn), host_view);
    g_signal_connect(widget, "focus-out-event",
                     G_CALLBACK(FocusOut), host_view);
    g_signal_connect(widget, "button-press-event",
                     G_CALLBACK(ButtonPressReleaseEvent), host_view);
    g_signal_connect(widget, "button-release-event",
                     G_CALLBACK(ButtonPressReleaseEvent), host_view);
    g_signal_connect(widget, "motion-notify-event",
                     G_CALLBACK(MouseMoveEvent), host_view);
    g_signal_connect(widget, "scroll-event",
                     G_CALLBACK(MouseScrollEvent), host_view);

    return widget;
  }

 private:
  static gboolean ConfigureEvent(GtkWidget* widget, GdkEventConfigure* config,
                                 RenderWidgetHostViewGtk* host_view) {
    host_view->GetRenderWidgetHost()->WasResized();
    return FALSE;
  }

  static gboolean ExposeEvent(GtkWidget* widget, GdkEventExpose* expose,
                              RenderWidgetHostViewGtk* host_view) {
    const gfx::Rect damage_rect(expose->area);
    host_view->Paint(damage_rect);
    return FALSE;
  }

  static gboolean KeyPressReleaseEvent(GtkWidget* widget, GdkEventKey* event,
                                       RenderWidgetHostViewGtk* host_view) {
    NativeWebKeyboardEvent wke(event);
    host_view->GetRenderWidgetHost()->ForwardKeyboardEvent(wke);
    return FALSE;
  }

  static gboolean FocusIn(GtkWidget* widget, GdkEventFocus* focus,
                          RenderWidgetHostViewGtk* host_view) {
    host_view->GetRenderWidgetHost()->Focus();
    return FALSE;
  }

  static gboolean FocusOut(GtkWidget* widget, GdkEventFocus* focus,
                           RenderWidgetHostViewGtk* host_view) {
    host_view->GetRenderWidgetHost()->Blur();
    return FALSE;
  }

  static gboolean ButtonPressReleaseEvent(
      GtkWidget* widget, GdkEventButton* event,
      RenderWidgetHostViewGtk* host_view) {
    WebMouseEvent wme(event);
    host_view->GetRenderWidgetHost()->ForwardMouseEvent(wme);

    // TODO(evanm): why is this necessary here but not in test shell?
    // This logic is the same as GtkButton.
    if (event->type == GDK_BUTTON_PRESS && !GTK_WIDGET_HAS_FOCUS(widget))
      gtk_widget_grab_focus(widget);

    return FALSE;
  }

  static gboolean MouseMoveEvent(GtkWidget* widget, GdkEventMotion* event,
                                 RenderWidgetHostViewGtk* host_view) {
    WebMouseEvent wme(event);
    host_view->GetRenderWidgetHost()->ForwardMouseEvent(wme);
    return FALSE;
  }

  static gboolean MouseScrollEvent(GtkWidget* widget, GdkEventScroll* event,
                                   RenderWidgetHostViewGtk* host_view) {
    WebMouseWheelEvent wmwe(event);
    host_view->GetRenderWidgetHost()->ForwardWheelEvent(wmwe);
    return FALSE;
  }

  DISALLOW_IMPLICIT_CONSTRUCTORS(RenderWidgetHostViewGtkWidget);
};

}  // namespace

// static
RenderWidgetHostView* RenderWidgetHostView::CreateViewForWidget(
    RenderWidgetHost* widget) {
  return new RenderWidgetHostViewGtk(widget);
}

RenderWidgetHostViewGtk::RenderWidgetHostViewGtk(RenderWidgetHost* widget_host)
    : host_(widget_host) {
  host_->set_view(this);
  view_ = RenderWidgetHostViewGtkWidget::CreateNewWidget(this);
  // BUG 8707: We will live in some container (in this case in WebContents).
  // We want to destroy during Destroy(), independent of how we are managed in
  // any containers.  We need to sink the reference here to "own" the widget so
  // it can be added and removed from containers without being destroyed.
  g_object_ref_sink(view_);
}

RenderWidgetHostViewGtk::~RenderWidgetHostViewGtk() {
}

void RenderWidgetHostViewGtk::DidBecomeSelected() {
  NOTIMPLEMENTED();
}

void RenderWidgetHostViewGtk::WasHidden() {
  NOTIMPLEMENTED();
}

void RenderWidgetHostViewGtk::SetSize(const gfx::Size& size) {
  NOTIMPLEMENTED();
}

gfx::NativeView RenderWidgetHostViewGtk::GetPluginNativeView() {
  // TODO(port): We need to pass some widget pointer out here because the
  // renderer echos it back to us when it asks for GetScreenInfo. However, we
  // should probably be passing the top-level window or some such instead.
  return view_;
}

void RenderWidgetHostViewGtk::MovePluginWindows(
    const std::vector<WebPluginGeometry>& plugin_window_moves) {
  if (plugin_window_moves.empty())
    return;

  NOTIMPLEMENTED();
}

void RenderWidgetHostViewGtk::Focus() {
  NOTIMPLEMENTED();
}

void RenderWidgetHostViewGtk::Blur() {
  NOTIMPLEMENTED();
}

bool RenderWidgetHostViewGtk::HasFocus() {
  NOTIMPLEMENTED();
  return false;
}

void RenderWidgetHostViewGtk::Show() {
  NOTIMPLEMENTED();
}

void RenderWidgetHostViewGtk::Hide() {
  NOTIMPLEMENTED();
}

gfx::Rect RenderWidgetHostViewGtk::GetViewBounds() const {
  return gfx::Rect(view_->allocation.x, view_->allocation.y,
                   view_->allocation.width, view_->allocation.height);
}

void RenderWidgetHostViewGtk::UpdateCursor(const WebCursor& cursor) {
  // TODO(port): some of this logic may need moving to UpdateCursorIfOverSelf at
  // some point.
  GdkCursorType current_cursor_type = current_cursor_.GetCursorType();
  GdkCursorType new_cursor_type = cursor.GetCursorType();
  current_cursor_ = cursor;
  GdkCursor* gdk_cursor;
  if (new_cursor_type == GDK_CURSOR_IS_PIXMAP) {
    // TODO(port): WebKit bug https://bugs.webkit.org/show_bug.cgi?id=16388 is
    // that calling gdk_window_set_cursor repeatedly is expensive.  We should
    // avoid it here where possible.
    gdk_cursor = current_cursor_.GetCustomCursor();
  } else {
    // Optimize the common case, where the cursor hasn't changed.
    // However, we can switch between different pixmaps, so only on the
    // non-pixmap branch.
    if (new_cursor_type == current_cursor_type)
      return;
    gdk_cursor = gdk_cursor_new(new_cursor_type);
  }
  gdk_window_set_cursor(view_->window, gdk_cursor);
  // The window now owns the cursor.
  gdk_cursor_unref(gdk_cursor);
}

void RenderWidgetHostViewGtk::UpdateCursorIfOverSelf() {
  // Windows uses this to show the resizer arrow if the mouse is over the
  // bottom-right corner.
  NOTIMPLEMENTED();
}

void RenderWidgetHostViewGtk::SetIsLoading(bool is_loading) {
  // Windows tracks loading whether it's loading to switch the cursor
  // out for the arrow+hourglass one.  We don't have such a cursor, so we just
  // ignore this.
}

void RenderWidgetHostViewGtk::IMEUpdateStatus(int control,
                                              const gfx::Rect& caret_rect) {
  NOTIMPLEMENTED();
}

void RenderWidgetHostViewGtk::DidPaintRect(const gfx::Rect& rect) {
  Paint(rect);
}

void RenderWidgetHostViewGtk::DidScrollRect(const gfx::Rect& rect, int dx,
                                            int dy) {
  Paint(rect);
}

void RenderWidgetHostViewGtk::RenderViewGone() {
  NOTIMPLEMENTED();
}

void RenderWidgetHostViewGtk::Destroy() {
  // We need to disconnect ourselves from our parent widget at this time; this
  // does the right thing, automatically removing ourselves from our parent
  // container.
  gtk_widget_destroy(view_);
  view_ = NULL;
}

void RenderWidgetHostViewGtk::SetTooltipText(const std::wstring& tooltip_text) {
  if (tooltip_text.empty()) {
    gtk_widget_set_has_tooltip(view_, FALSE);
  } else {
    gtk_widget_set_tooltip_text(view_, WideToUTF8(tooltip_text).c_str());
  }
}

BackingStore* RenderWidgetHostViewGtk::AllocBackingStore(
    const gfx::Size& size) {
  Display* display = x11_util::GetXDisplay();
  void* visual = x11_util::GetVisualFromGtkWidget(view_);
  XID root_window = x11_util::GetX11RootWindow();
  bool use_render = x11_util::QueryRenderSupport(display);
  bool use_shared_memory = x11_util::QuerySharedMemorySupport(display);
  int depth = gtk_widget_get_visual(view_)->depth;

  return new BackingStore(size, display, depth, visual, root_window,
                          use_render, use_shared_memory);
}

void RenderWidgetHostViewGtk::Paint(const gfx::Rect& damage_rect) {
  BackingStore* backing_store = host_->GetBackingStore();

  if (backing_store) {
    // Only render the widget if it is attached to a window; there's a short
    // period where this object isn't attached to a window but hasn't been
    // Destroy()ed yet and it receives paint messages...
    GdkWindow* window = view_->window;
    if (window) {
      backing_store->ShowRect(
          damage_rect, x11_util::GetX11WindowFromGtkWidget(view_));
    }
  } else {
    NOTIMPLEMENTED();
  }
}
<|endoftext|>


<commit_before>/*
 * STLL Simple Text Layouting Library
 *
 * STLL is the legal property of its developers, whose
 * names are listed in the COPYRIGHT file, which is included
 * within the source distribution.
 *
 * This program 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.1
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */
#include <stll/hyphendictionaries.h>
#include "hyphendictionaries_internal.h"

#include "hyphen/hyphen.h"

#include <map>
#include <memory>

namespace STLL {

static std::map<std::string, std::shared_ptr<internal::HyphenDict<char32_t>>> dictionaries;

void addHyphenDictionary(const std::vector<std::string> & langs, std::istream & str)
{
  auto dict = std::make_shared<internal::HyphenDict<char32_t>>(str);
  for (auto & l : langs) dictionaries[l] = dict;
}

void addHyphenDictionary(const std::vector<std::string> & langs, std::istream && str)
{
  auto dict = std::make_shared<internal::HyphenDict<char32_t>>(str);
  for (auto & l : langs) dictionaries[l] = dict;
}

namespace internal {

const HyphenDict<char32_t> * getHyphenDict(const std::string & lang)
{
  auto d = dictionaries.find(lang);

  if (d != dictionaries.end())
  {
    return d->second.get();
  }

  auto p = lang.find_last_of('_');

  if (p != lang.npos)
  {
    std::string lang2 = lang.substr(0, p);

    auto d2 = dictionaries.find(lang2);

    if (d2 != dictionaries.end())
    {
      return d2->second.get();
    }
  }

  return nullptr;
}

} }
<commit_msg>use dash as language field separator, peel away in a loop<commit_after>/*
 * STLL Simple Text Layouting Library
 *
 * STLL is the legal property of its developers, whose
 * names are listed in the COPYRIGHT file, which is included
 * within the source distribution.
 *
 * This program 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.1
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */
#include <stll/hyphendictionaries.h>
#include "hyphendictionaries_internal.h"

#include "hyphen/hyphen.h"

#include <map>
#include <memory>

namespace STLL {

static std::map<std::string, std::shared_ptr<internal::HyphenDict<char32_t>>> dictionaries;

void addHyphenDictionary(const std::vector<std::string> & langs, std::istream & str)
{
  auto dict = std::make_shared<internal::HyphenDict<char32_t>>(str);
  for (auto & l : langs) dictionaries[l] = dict;
}

void addHyphenDictionary(const std::vector<std::string> & langs, std::istream && str)
{
  auto dict = std::make_shared<internal::HyphenDict<char32_t>>(str);
  for (auto & l : langs) dictionaries[l] = dict;
}

namespace internal {

const HyphenDict<char32_t> * getHyphenDict(const std::string & lang)
{
  std::string l = lang;

  while (!l.empty())
  {
    auto d = dictionaries.find(l);

    if (d != dictionaries.end())
    {
      return d->second.get();
    }

    auto p = lang.find_last_of('-');

    if (p != lang.npos)
    {
      l = l.substr(0, p);
    }
    else
    {
      l = "";
    }
  }

  return nullptr;
}

} }
<|endoftext|>