<commit_before>// LICENSE/*{{{*/
/*
  sxc - Simple Xmpp Client
  Copyright (C) 2008 Dennis Felsing, Andreas Waidler

  This program is free software: you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation, either version 3 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, see <http://www.gnu.org/licenses/>.
 */
/*}}}*/

#ifndef CONTROL_COMMAND_COMMAND_HXX
#define CONTROL_COMMAND_COMMAND_HXX

// INCLUDES/*{{{*/

#include <string>

#include <CommandParser/AbcCommandParser.hxx>

/*}}}*/

namespace Control
{
    namespace Command
    {
        class Command : CommandParser::AbcCommandParser
        {
            public:
                // Command(const std::string &command);/*{{{*/

                /**
                 * @brief Default constructor, calls parent constructor.
                 *
                 * @param command A command to be parsed.
                 */
                Command(const std::string &command);

/*}}}*/
                // ~Command();/*{{{*/

                /// Destructor, does no work currently.
                ~Command();

/*}}}*/
                // void execute();/*{{{*/

                /**
                 * @brief Executes the passed command.
                 *
                 * Calls @ref parse() and @ref getParsed(). Some parameters may
                 * be checked by this method. Usually the parameters are passed
                 * on without being checked. The associated method will be
                 * called and may throw an exception.
                 *
                 * @note Exception handling has to be done by the caller.
                 *
                 * @exception InputException(InvalidCommand) If a check fails.
                 * @exception libsxc::Exception::Exception Childs of this basic
                 *            exception may be thrown by invoked method.
                 */
                void execute();

/*}}}*/

            protected:

            private:
                // commandMap _createCommands() const;/*{{{*/

                /**
                 * @brief Creates a container holding all possible commands.
                 *
                 * @return All valid commands and the specification of their
                 *         parameters
                 */
                CommandParser::commandMap _createCommands() const;

/*}}}*/
        };
    }
}

#endif // CONTROL_COMMAND_COMMAND_HXX

// Use no tabs at all; four spaces indentation; max. eighty chars per line.
// vim: et ts=4 sw=4 tw=80 fo+=c fdm=marker
<commit_msg>Control::Command::Command : Updated docblocks.<commit_after>// LICENSE/*{{{*/
/*
  sxc - Simple Xmpp Client
  Copyright (C) 2008 Dennis Felsing, Andreas Waidler

  This program is free software: you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation, either version 3 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, see <http://www.gnu.org/licenses/>.
 */
/*}}}*/

#ifndef CONTROL_COMMAND_COMMAND_HXX
#define CONTROL_COMMAND_COMMAND_HXX

// INCLUDES/*{{{*/

#include <string>

#include <CommandParser/AbcCommandParser.hxx>

/*}}}*/

namespace Control
{
    namespace Command
    {
        class Command : CommandParser::AbcCommandParser
        {
            public:
                // Command(const std::string &command);/*{{{*/

                /**
                 * @brief Default constructor, calls parent constructor.
                 *
                 * @param command A command to be parsed.
                 */
                Command(const std::string &command);

/*}}}*/
                // ~Command();/*{{{*/

                /// Destructor, has nothing to do currently.
                ~Command();

/*}}}*/
                // void execute();/*{{{*/

                /**
                 * @brief Executes the passed command.
                 *
                 * Calls @ref parse() and @ref getParsed(). Some parameters may
                 * be checked by this method. Usually the parameters are passed
                 * on without being checked. The associated method will be
                 * called and may throw an exception.
                 *
                 * @note Exception handling has to be done by the caller.
                 *
                 * @exception InputException(InvalidCommand) A check failed.
                 * @exception libsxc::Exception::Exception Childs of this basic
                 *            exception may be thrown by invoked methods.
                 * @exception std::out_of_range Accessing an element of returned
                 *            by @ref getParsed() that does not exist. This
                 *            would be a bug in this class (or its parent).
                 * @exception std::exception This should usually not happen.
                 */
                void execute();

/*}}}*/

            protected:

            private:
                // commandMap _createCommands() const;/*{{{*/

                /**
                 * @brief Creates a container holding all possible commands.
                 *
                 * @return All valid commands and the specification of their
                 *         parameters.
                 */
                CommandParser::commandMap _createCommands() const;

/*}}}*/
        };
    }
}

#endif // CONTROL_COMMAND_COMMAND_HXX

// Use no tabs at all; four spaces indentation; max. eighty chars per line.
// vim: et ts=4 sw=4 tw=80 fo+=c fdm=marker
<|endoftext|>


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

#include "NewmarkMaterial.h"

template<>
InputParameters validParams<NewmarkMaterial>()
{
  InputParameters params = validParams<Material>();

  params.addParam<Real>("gamma", 0.5, "Newmark integration gamma parameter (default: 0.5)");
  params.addParam<Real>("beta", 0.25, "Newmark integration beta parameter (default: 0.25)");
  params.addCoupledVar("disp", "Displacement component");
  //params.set<bool>("use_displaced_mesh") = true;

  return params;
}

NewmarkMaterial::NewmarkMaterial(const std::string & name,
                                 InputParameters parameters) :
    Material(name, parameters),
    _comp_name((getVar("disp", 0))->name()),  // we use the name that was supplied as disp parameter to ensure unique naming and finally correctly correspondence in SecondDerivativeNewmark.C
    _acc(declareProperty<Real>(       "newmark_acceleration-" + _comp_name)),
    _acc_old(declarePropertyOld<Real>("newmark_acceleration-" + _comp_name)),
    _vel(declareProperty<Real>(       "newmark_velocity-"     + _comp_name)),
    _vel_old(declarePropertyOld<Real>("newmark_velocity-"     + _comp_name)),
    _gamma(declareProperty<Real>(     "newmark_gamma-"        + _comp_name)),
    _beta( declareProperty<Real>(     "newmark_beta-"         + _comp_name)),
    // coupled variables
    _disp(coupledValue("disp")),
    _disp_old(coupledValueOld("disp")),
    // parameters
    __gamma(getParam<Real>("gamma")),
    __beta(getParam<Real>("beta"))
{}

void
NewmarkMaterial::initQpStatefulProperties()
{
  // init the stateful properties (these will become _bla_old before/in the first call of computeProperties)
  _acc[_qp] = 0;
  _vel[_qp] = 0;
}

void
NewmarkMaterial::computeQpProperties()
{
  // this looks strange but this is exactly as ConstantPropertyMaterial.C does it
  _gamma[_qp] = __gamma;
  _beta[_qp]  = __beta;

  // FIXME, actually this kernel should only be called at the end of every timestep
  _acc[_qp] = ( _disp[_qp]/(_dt*_dt) - _vel_old[_qp]/_dt - (0.5-_beta[_qp])*_acc_old[_qp] ) / _beta[_qp];
  _vel[_qp] = _vel_old[_qp] + _dt*( (1-_gamma[_qp])*_acc_old[_qp] + _gamma[_qp]*_acc[_qp] );
}
<commit_msg>fixed typo in comment<commit_after>/****************************************************************/
/*                                                              */
/*                                                              */
/****************************************************************/

#include "NewmarkMaterial.h"

template<>
InputParameters validParams<NewmarkMaterial>()
{
  InputParameters params = validParams<Material>();

  params.addParam<Real>("gamma", 0.5, "Newmark integration gamma parameter (default: 0.5)");
  params.addParam<Real>("beta", 0.25, "Newmark integration beta parameter (default: 0.25)");
  params.addCoupledVar("disp", "Displacement component");
  //params.set<bool>("use_displaced_mesh") = true;

  return params;
}

NewmarkMaterial::NewmarkMaterial(const std::string & name,
                                 InputParameters parameters) :
    Material(name, parameters),
    _comp_name((getVar("disp", 0))->name()),  // we use the name that was supplied as disp parameter to ensure unique naming and finally correct correspondence in SecondDerivativeNewmark.C
    _acc(declareProperty<Real>(       "newmark_acceleration-" + _comp_name)),
    _acc_old(declarePropertyOld<Real>("newmark_acceleration-" + _comp_name)),
    _vel(declareProperty<Real>(       "newmark_velocity-"     + _comp_name)),
    _vel_old(declarePropertyOld<Real>("newmark_velocity-"     + _comp_name)),
    _gamma(declareProperty<Real>(     "newmark_gamma-"        + _comp_name)),
    _beta( declareProperty<Real>(     "newmark_beta-"         + _comp_name)),
    // coupled variables
    _disp(coupledValue("disp")),
    _disp_old(coupledValueOld("disp")),
    // parameters
    __gamma(getParam<Real>("gamma")),
    __beta(getParam<Real>("beta"))
{}

void
NewmarkMaterial::initQpStatefulProperties()
{
  // init the stateful properties (these will become _bla_old before/in the first call of computeProperties)
  _acc[_qp] = 0;
  _vel[_qp] = 0;
}

void
NewmarkMaterial::computeQpProperties()
{
  // this looks strange but this is exactly as ConstantPropertyMaterial.C does it
  _gamma[_qp] = __gamma;
  _beta[_qp]  = __beta;

  // FIXME, actually this kernel should only be called at the end of every timestep
  _acc[_qp] = ( _disp[_qp]/(_dt*_dt) - _vel_old[_qp]/_dt - (0.5-_beta[_qp])*_acc_old[_qp] ) / _beta[_qp];
  _vel[_qp] = _vel_old[_qp] + _dt*( (1-_gamma[_qp])*_acc_old[_qp] + _gamma[_qp]*_acc[_qp] );
}
<|endoftext|>


<commit_before>#include <iostream>
#include <string>
#include <tinyxml2.h>
#include "args.h"
#include "load_scene.h"
#include "render/render_target.h"
#include "render/camera.h"
#include "geometry/sphere.h"
#include "geometry/geometry_cache.h"

/*
 * Run intersection tests on all the children of the node
 * returns true if any child was hit
 */
bool intersect_children(Node &node, Ray &ray);

int main(int argc, char **argv){
	if (!flag(argv, argv + argc, "-f")){
		std::cerr << "Error: No scene file passed\n";
		return 1;
	}
	if (!flag(argv, argv + argc, "-o")){
		std::cerr << "Error: No output filename passed\n";
		return 1;
	}
	std::string scene_file = get_param<std::string>(argv, argv + argc, "-f");
	std::string out_file = get_param<std::string>(argv, argv + argc, "-o");
	std::cout << "scene file: " << scene_file << ", output: " << out_file << std::endl;
	Scene scene = load_scene(scene_file);

	Node &root = scene.get_root();
	RenderTarget &target = scene.get_render_target();
	Camera &camera = scene.get_camera();

	for (size_t y = 0; y < target.get_height(); ++y){
		for (size_t x = 0; x < target.get_width(); ++x){
			Ray ray = camera.generate_ray(x + 0.5, y + 0.5);
			if (intersect_children(root, ray)){
				target.write_pixel(x, y, Color{255, 255, 255});
				target.write_depth(x, y, ray.max_t);
			}
		}
	}

	target.save_image(out_file + ".ppm");
	target.save_depth(out_file + ".pgm");
	return 0;
}
bool intersect_children(Node &node, Ray &ray){
	bool hit = false;
	//Transform the ray into this nodes space
	Ray node_space = ray;
	node.get_transform().inverse()(ray, node_space);
	for (auto &c : node.get_children()){
		hit = intersect_children(*c, node_space) || hit;
	}
	//Now test this node
	if (node.get_geometry()){
		hit = node.get_geometry()->intersect(node_space) || hit;
	}
	ray.max_t = node_space.max_t;
	return hit;
}

<commit_msg>Working on computing dimensions needed for subrects<commit_after>#include <iostream>
#include <string>
#include <tinyxml2.h>
#include "args.h"
#include "load_scene.h"
#include "render/render_target.h"
#include "render/camera.h"
#include "geometry/sphere.h"
#include "geometry/geometry_cache.h"

/*
 * Run intersection tests on all the children of the node
 * returns true if any child was hit
 */
bool intersect_children(Node &node, Ray &ray);

int main(int argc, char **argv){
	if (!flag(argv, argv + argc, "-f")){
		std::cerr << "Error: No scene file passed\n";
		return 1;
	}
	if (!flag(argv, argv + argc, "-o")){
		std::cerr << "Error: No output filename passed\n";
		return 1;
	}
	int n_threads = 1;
	if (flag(argv, argv + argc, "-n")){
		n_threads = get_param<int>(argv, argv + argc, "-n");
		if (n_threads > 1 && n_threads % 2 != 0){
			std::cerr << "Warning: num threads not even, increasing thread count by 1\n";
			++n_threads;
		}
	}
	std::string scene_file = get_param<std::string>(argv, argv + argc, "-f");
	std::string out_file = get_param<std::string>(argv, argv + argc, "-o");
	std::cout << "scene file: " << scene_file << ", output: " << out_file << std::endl;
	Scene scene = load_scene(scene_file);

	Node &root = scene.get_root();
	RenderTarget &target = scene.get_render_target();
	Camera &camera = scene.get_camera();

	//Compute the number of columns and rows to partition the image into so
	//we can assign disjoint portions of it to each thread
	//Should warn if the cols & rows don't evenly divide the space,
	//eg if rect dimensions aren't integers
	int n_cols = std::ceil(std::sqrt(n_threads));
	int n_rows = std::ceil(n_threads / static_cast<float>(n_cols));
	std::cout << "cols: " << n_cols << " rows: " << n_rows
		<< "\nEach rect is " << target.get_width() / static_cast<float>(n_cols)
		<< " x " << target.get_height() / static_cast<float>(n_rows)
		<< std::endl;

	for (size_t y = 0; y < target.get_height(); ++y){
		for (size_t x = 0; x < target.get_width(); ++x){
			Ray ray = camera.generate_ray(x + 0.5, y + 0.5);
			if (intersect_children(root, ray)){
				target.write_pixel(x, y, Color{255, 255, 255});
				target.write_depth(x, y, ray.max_t);
			}
		}
	}

	target.save_image(out_file + ".ppm");
	target.save_depth(out_file + ".pgm");
	return 0;
}
bool intersect_children(Node &node, Ray &ray){
	bool hit = false;
	//Transform the ray into this nodes space
	Ray node_space = ray;
	node.get_transform().inverse()(ray, node_space);
	for (auto &c : node.get_children()){
		hit = intersect_children(*c, node_space) || hit;
	}
	//Now test this node
	if (node.get_geometry()){
		hit = node.get_geometry()->intersect(node_space) || hit;
	}
	ray.max_t = node_space.max_t;
	return hit;
}

<|endoftext|>


<commit_before>// This file is part of the dune-pymor project:
//   https://github.com/pyMor/dune-pymor
// Copyright Holders: Felix Albrecht, Stephan Rave
// License: BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)

#ifdef HAVE_CMAKE_CONFIG
  #include "cmake_config.h"
#elif defined (HAVE_CONFIG_H)
  #include <config.h>
#endif // HAVE_CMAKE_CONFIG

#include <utility>

#include <dune/stuff/test/test_common.hh>

#if HAVE_EIGEN
#include <dune/pymor/operators/eigen.hh>
#include <dune/pymor/common/exceptions.hh>
#include <dune/common/float_cmp.hh>

using namespace Dune;
using namespace Dune::Pymor;

typedef testing::Types< std::pair< Dune::Pymor::Operators::EigenDenseMatrix,
                                   Dune::Pymor::LA::EigenDenseVector >
                      , std::pair< Dune::Pymor::Operators::EigenRowMajorSparseMatrix,
                                   Dune::Pymor::LA::EigenDenseVector >
                      > LinearOperatorTypes;

template< class T >
T* createIdentityMatrix(const T&);

Dune::Pymor::Operators::EigenDenseMatrix* createIdentityMatrix(const Dune::Pymor::Operators::EigenDenseMatrix&,
                                                               const size_t dim)
{
  Dune::Pymor::Operators::EigenDenseMatrix* ret = new Dune::Pymor::Operators::EigenDenseMatrix(dim, dim);
  for (size_t ii = 0; ii < dim; ++ii)
    ret->set(ii, ii, 1.0);
  return ret;
}

Dune::Pymor::Operators::EigenRowMajorSparseMatrix* createIdentityMatrix(const Dune::Pymor::Operators::EigenRowMajorSparseMatrix&,
                                                                        const size_t dim)
{
  return new Dune::Pymor::Operators::EigenRowMajorSparseMatrix(*(Dune::Stuff::LA::createIdentityEigenRowMajorSparseMatrix(dim)));
}

template< class TypePair >
struct LinearOperatorTest
  : public ::testing::Test
{
  void check() const
  {
    typedef typename TypePair::first_type   OperatorType;
    typedef typename TypePair::second_type  VectorType;
    const size_t dim = 2;
    VectorType* U = new VectorType(dim, 1.0);
    VectorType* V = new VectorType(dim, 1.0);
    OperatorType* op = createIdentityMatrix(OperatorType(), dim);
    if (!op->linear()) DUNE_PYMOR_THROW(PymorException, "");
    if (op->parametric()) DUNE_PYMOR_THROW(PymorException, "");
    if (op->dim_source() != dim) DUNE_PYMOR_THROW(PymorException, "");
    if (op->dim_range() != dim) DUNE_PYMOR_THROW(PymorException, "");
    if (op->type_source() != U->type()) DUNE_PYMOR_THROW(PymorException, "");
    if (op->type_range() != U->type()) DUNE_PYMOR_THROW(PymorException, "");
    op->apply(U, V);
    if (V->dim() != op->dim_range()) DUNE_PYMOR_THROW(PymorException, "");
    if (!Dune::FloatCmp::eq(V->get(0), 1.0) || !Dune::FloatCmp::eq(V->get(1), 1.0))
      DUNE_PYMOR_THROW(PymorException, "");
    const double res = op->apply2(U, V);
    if (!Dune::FloatCmp::eq(res, 2.0)) DUNE_PYMOR_THROW(PymorException, "");
    delete V;
    delete op;
    delete U;
  }
}; // struct LinearOperatorTest

TYPED_TEST_CASE(LinearOperatorTest, LinearOperatorTypes);
TYPED_TEST(LinearOperatorTest, OPERATORS) {
  this->check();
}

int main(int argc, char** argv)
{
//  try {
    test_init(argc, argv);
    return RUN_ALL_TESTS();
//  } catch (Dune::PymorException &e) {
//    std::cerr << Dune::Stuff::Common::colorStringRed("dune-pymor reported: ") << e << std::endl;
//  } catch (Dune::Exception &e) {
//    std::cerr << Dune::Stuff::Common::colorStringRed("Dune reported error: ") << e << std::endl;
//  } catch (...) {
//    std::cerr << Dune::Stuff::Common::colorStringRed("Unknown exception thrown!") << std::endl;
//  }
}

#else // HAVE_EIGEN

int main(int /*argc*/, char** /*argv*/)
{
  return 0;
}

#endif // HAVE_EIGEN
<commit_msg>[test.operators] added AffineparametricOperatorTest<commit_after>// This file is part of the dune-pymor project:
//   https://github.com/pyMor/dune-pymor
// Copyright Holders: Felix Albrecht, Stephan Rave
// License: BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)

#ifdef HAVE_CMAKE_CONFIG
  #include "cmake_config.h"
#elif defined (HAVE_CONFIG_H)
  #include <config.h>
#endif // HAVE_CMAKE_CONFIG

#include <utility>

#include <dune/stuff/test/test_common.hh>

#if HAVE_EIGEN
#include <dune/common/float_cmp.hh>

#include <dune/pymor/common/exceptions.hh>
#include <dune/pymor/operators/eigen.hh>
#include <dune/pymor/operators/default.hh>
#include <dune/pymor/parameters/base.hh>
#include <dune/pymor/parameters/functional.hh>

using namespace Dune;
using namespace Dune::Pymor;

typedef testing::Types< std::pair< Dune::Pymor::Operators::EigenDenseMatrix,
                                   Dune::Pymor::LA::EigenDenseVector >
                      , std::pair< Dune::Pymor::Operators::EigenRowMajorSparseMatrix,
                                   Dune::Pymor::LA::EigenDenseVector >
                      > LinearOperatorTypes;

template< class T >
T* createIdentityMatrix(const T&);

Dune::Pymor::Operators::EigenDenseMatrix* createIdentityMatrix(const Dune::Pymor::Operators::EigenDenseMatrix&,
                                                               const size_t dim)
{
  Dune::Pymor::Operators::EigenDenseMatrix* ret = new Dune::Pymor::Operators::EigenDenseMatrix(dim, dim);
  for (size_t ii = 0; ii < dim; ++ii)
    ret->set(ii, ii, 1.0);
  return ret;
}

Dune::Pymor::Operators::EigenRowMajorSparseMatrix* createIdentityMatrix(const Dune::Pymor::Operators::EigenRowMajorSparseMatrix&,
                                                                        const size_t dim)
{
  return new Dune::Pymor::Operators::EigenRowMajorSparseMatrix(*(Dune::Stuff::LA::createIdentityEigenRowMajorSparseMatrix(dim)));
}

template< class TypePair >
struct LinearOperatorTest
  : public ::testing::Test
{
  void check() const
  {
    typedef typename TypePair::first_type   OperatorType;
    typedef typename TypePair::second_type  VectorType;
    const size_t dim = 2;
    VectorType* U = new VectorType(dim, 1.0);
    VectorType* V = new VectorType(dim, 1.0);
    OperatorType* op = createIdentityMatrix(OperatorType(), dim);
    if (!op->linear()) DUNE_PYMOR_THROW(PymorException, "");
    if (op->parametric()) DUNE_PYMOR_THROW(PymorException, "");
    if (op->parameter_type() != Parameter().type()) DUNE_PYMOR_THROW(PymorException, "");
    if (op->dim_source() != dim) DUNE_PYMOR_THROW(PymorException, "");
    if (op->dim_range() != dim) DUNE_PYMOR_THROW(PymorException, "");
    if (op->type_source() != U->type()) DUNE_PYMOR_THROW(PymorException, "");
    if (op->type_range() != U->type()) DUNE_PYMOR_THROW(PymorException, "");
    op->apply(U, V);
    if (V->dim() != op->dim_range()) DUNE_PYMOR_THROW(PymorException, "");
    if (!Dune::FloatCmp::eq(V->get(0), 1.0) || !Dune::FloatCmp::eq(V->get(1), 1.0))
      DUNE_PYMOR_THROW(PymorException, "");
    const double res = op->apply2(U, V);
    if (!Dune::FloatCmp::eq(res, 2.0)) DUNE_PYMOR_THROW(PymorException, "");
    delete V;
    delete op;
    delete U;
  }
}; // struct LinearOperatorTest

TYPED_TEST_CASE(LinearOperatorTest, LinearOperatorTypes);
TYPED_TEST(LinearOperatorTest, OPERATORS) {
  this->check();
}

template< class TypePair >
struct AffineparametricOperatorTest
  : public ::testing::Test
{
  void check() const
  {
    typedef typename TypePair::first_type   OperatorType;
    typedef typename TypePair::second_type  VectorType;
    typedef Operators::AffinelyDecomposedDefault< OperatorType > AffineparametricOperatorType;
    const Parameter mu = {"diffusion", {1.0, 1.0}};
    AffineparametricOperatorType op(mu.type());
    const size_t dim = 2;
    op.register_component(createIdentityMatrix(OperatorType(), dim));
    op.register_component(createIdentityMatrix(OperatorType(), dim),
                          new ParameterFunctional(mu.type(), "diffusion[0]"));
    op.register_component(createIdentityMatrix(OperatorType(), dim),
                          new ParameterFunctional(mu.type(), "diffusion[1]"));
    VectorType* U = new VectorType(dim, 1.0);
    VectorType* V = new VectorType(dim, 1.0);
    if (!op.linear()) DUNE_PYMOR_THROW(PymorException, "");
    if (!op.parametric()) DUNE_PYMOR_THROW(PymorException, "");
    if (op.parameter_type() != mu.type()) DUNE_PYMOR_THROW(PymorException, "");
    if (op.dim_source() != dim) DUNE_PYMOR_THROW(PymorException, "");
    if (op.dim_range() != dim) DUNE_PYMOR_THROW(PymorException, "");
    if (op.type_source() != U->type()) DUNE_PYMOR_THROW(PymorException, "");
    if (op.type_range() != U->type()) DUNE_PYMOR_THROW(PymorException, "");
    op.apply(U, V, mu);
    if (V->dim() != op.dim_range()) DUNE_PYMOR_THROW(PymorException, "");
    if (!Dune::FloatCmp::eq(V->get(0), 3.0) || !Dune::FloatCmp::eq(V->get(1), 3.0))
      DUNE_PYMOR_THROW(PymorException, "");
    const double res = op.apply2(U, V, mu);
    if (!Dune::FloatCmp::eq(res, 18.0)) DUNE_PYMOR_THROW(PymorException, "");
    delete V;
    delete U;
  }
}; // struct AffineparametricOperatorTest

TYPED_TEST_CASE(AffineparametricOperatorTest, LinearOperatorTypes);
TYPED_TEST(AffineparametricOperatorTest, OPERATORS) {
  this->check();
}

int main(int argc, char** argv)
{
//  try {
    test_init(argc, argv);
    return RUN_ALL_TESTS();
//  } catch (Dune::PymorException &e) {
//    std::cerr << Dune::Stuff::Common::colorStringRed("dune-pymor reported: ") << e << std::endl;
//  } catch (Dune::Exception &e) {
//    std::cerr << Dune::Stuff::Common::colorStringRed("Dune reported error: ") << e << std::endl;
//  } catch (...) {
//    std::cerr << Dune::Stuff::Common::colorStringRed("Unknown exception thrown!") << std::endl;
//  }
}

#else // HAVE_EIGEN

int main(int /*argc*/, char** /*argv*/)
{
  return 0;
}

#endif // HAVE_EIGEN
<|endoftext|>


<commit_before>#include "node_map.hpp"
#include "node_file_source.hpp"

#include <mbgl/platform/default/headless_display.hpp>
#include <mbgl/map/still_image.hpp>
#include <mbgl/util/exception.hpp>

#include <unistd.h>

namespace node_mbgl {

struct NodeMap::RenderOptions {
    double zoom = 0;
    double bearing = 0;
    double latitude = 0;
    double longitude = 0;
    unsigned int width = 512;
    unsigned int height = 512;
    float ratio = 1.0f;
    std::vector<std::string> classes;
};

////////////////////////////////////////////////////////////////////////////////////////////////
// Static Node Methods

v8::Persistent<v8::FunctionTemplate> NodeMap::constructorTemplate;

static std::shared_ptr<mbgl::HeadlessDisplay> sharedDisplay() {
    static auto display = std::make_shared<mbgl::HeadlessDisplay>();
    return display;
}

const static char* releasedMessage() {
    return "Map resources have already been released";
}

void NodeMap::Init(v8::Handle<v8::Object> target) {
    NanScope();

    v8::Local<v8::FunctionTemplate> t = NanNew<v8::FunctionTemplate>(New);

    t->InstanceTemplate()->SetInternalFieldCount(1);
    t->SetClassName(NanNew("Map"));

    NODE_SET_PROTOTYPE_METHOD(t, "load", Load);
    NODE_SET_PROTOTYPE_METHOD(t, "render", Render);
    NODE_SET_PROTOTYPE_METHOD(t, "release", Release);

    NanAssignPersistent(constructorTemplate, t);

    target->Set(NanNew("Map"), t->GetFunction());

    // Initialize display connection on module load.
    sharedDisplay();
}

NAN_METHOD(NodeMap::New) {
    NanScope();

    if (!args.IsConstructCall()) {
        return NanThrowTypeError("Use the new operator to create new Map objects");
    }

    if (args.Length() < 1 || !NanHasInstance(NodeFileSource::constructorTemplate, args[0])) {
        return NanThrowTypeError("Requires a FileSource as first argument");
    }

    auto source = args[0]->ToObject();

    // Check that request() and cancel() are defined.
    if (!source->Has(NanNew("request")) || !source->Get(NanNew("request"))->IsFunction()) {
        return NanThrowError("FileSource must have a request member function");
    }
    if (!source->Has(NanNew("cancel")) || !source->Get(NanNew("cancel"))->IsFunction()) {
        return NanThrowError("FileSource must have a cancel member function");
    }

    try {
        auto nodeMap = new NodeMap(source);
        nodeMap->Wrap(args.This());
    } catch(std::exception &ex) {
        return NanThrowError(ex.what());
    }

    NanReturnValue(args.This());
}

const std::string StringifyStyle(v8::Handle<v8::Value> styleHandle) {
    NanScope();

    auto JSON = NanGetCurrentContext()->Global()->Get(NanNew("JSON"))->ToObject();
    auto stringify = v8::Handle<v8::Function>::Cast(JSON->Get(NanNew("stringify")));

    return *NanUtf8String(stringify->Call(JSON, 1, &styleHandle));
}

NAN_METHOD(NodeMap::Load) {
    NanScope();

    auto nodeMap = node::ObjectWrap::Unwrap<NodeMap>(args.Holder());

    if (!nodeMap->isValid()) return NanThrowError(releasedMessage());

    if (args.Length() < 1) {
        return NanThrowError("Requires a map style as first argument");
    }

    std::string style;

    if (args[0]->IsObject()) {
        style = StringifyStyle(args[0]);
    } else if (args[0]->IsString()) {
        style = *NanUtf8String(args[0]);
    } else {
        return NanThrowTypeError("First argument must be a string or object");
    }

    try {
        nodeMap->map->setStyleJSON(style, ".");
    } catch (const std::exception &ex) {
        return NanThrowError(ex.what());
    }

    NanReturnUndefined();
}

std::unique_ptr<NodeMap::RenderOptions> NodeMap::ParseOptions(v8::Local<v8::Object> obj) {
    NanScope();

    auto options = std::make_unique<RenderOptions>();

    if (obj->Has(NanNew("zoom"))) { options->zoom = obj->Get(NanNew("zoom"))->NumberValue(); }
    if (obj->Has(NanNew("bearing"))) { options->bearing = obj->Get(NanNew("bearing"))->NumberValue(); }
    if (obj->Has(NanNew("center"))) {
        auto center = obj->Get(NanNew("center")).As<v8::Array>();
        if (center->Length() > 0) { options->latitude = center->Get(0)->NumberValue(); }
        if (center->Length() > 1) { options->longitude = center->Get(1)->NumberValue(); }
    }
    if (obj->Has(NanNew("width"))) { options->width = obj->Get(NanNew("width"))->IntegerValue(); }
    if (obj->Has(NanNew("height"))) { options->height = obj->Get(NanNew("height"))->IntegerValue(); }
    if (obj->Has(NanNew("ratio"))) { options->ratio = obj->Get(NanNew("ratio"))->IntegerValue(); }

    if (obj->Has(NanNew("classes"))) {
        auto classes = obj->Get(NanNew("classes"))->ToObject().As<v8::Array>();
        const int length = classes->Length();
        options->classes.reserve(length);
        for (int i = 0; i < length; i++) {
            options->classes.push_back(std::string { *NanUtf8String(classes->Get(i)->ToString()) });
        }
    }

    return options;
}

NAN_METHOD(NodeMap::Render) {
    NanScope();

    auto nodeMap = node::ObjectWrap::Unwrap<NodeMap>(args.Holder());

    if (!nodeMap->isValid()) return NanThrowError(releasedMessage());

    if (args.Length() <= 0 || !args[0]->IsObject()) {
        return NanThrowTypeError("First argument must be an options object");
    }

    if (args.Length() <= 1 || !args[1]->IsFunction()) {
        return NanThrowTypeError("Second argument must be a callback function");
    }

    auto options = ParseOptions(args[0]->ToObject());

    assert(!nodeMap->callback);
    assert(!nodeMap->image);
    nodeMap->callback = std::unique_ptr<NanCallback>(new NanCallback(args[1].As<v8::Function>()));

    try {
        nodeMap->startRender(std::move(options));
    } catch (mbgl::util::Exception &ex) {
        return NanThrowError(ex.what());
    }

    NanReturnUndefined();
}

void NodeMap::startRender(std::unique_ptr<NodeMap::RenderOptions> options) {
    map->resize(options->width, options->height, options->ratio);
    map->setClasses(options->classes);
    map->setLatLngZoom(mbgl::LatLng(options->latitude, options->longitude), options->zoom);
    map->setBearing(options->bearing);

    map->renderStill([this](const std::exception_ptr eptr, std::unique_ptr<const mbgl::StillImage> result) {
        if (eptr) {
            error = std::move(eptr);
            uv_async_send(async);
        } else {
            assert(!image);
            image = std::move(result);
            uv_async_send(async);
        }
    });

    // Retain this object, otherwise it might get destructed before we are finished rendering the
    // still image.
    Ref();

    // Similarly, we're now waiting for the async to be called, so we need to make sure that it
    // keeps the loop alive.
    uv_ref(reinterpret_cast<uv_handle_t *>(async));
}

void NodeMap::renderFinished() {
    NanScope();

    // We're done with this render call, so we're unrefing so that the loop could close.
    uv_unref(reinterpret_cast<uv_handle_t *>(async));

    // There is no render pending anymore, we the GC could now delete this object if it went out
    // of scope.
    Unref();

    // Move the callback and image out of the way so that the callback can start a new render call.
    auto cb = std::move(callback);
    auto img = std::move(image);
    assert(cb);

    // These have to be empty to be prepared for the next render call.
    assert(!callback);
    assert(!image);

    if (error) {
        // This must be empty to be prepared for the next render call.
        error = nullptr;
        assert(!error);

        v8::Local<v8::Value> argv[] = {
            NanError("Error rendering image")
        };
        cb->Call(1, argv);
    } else if (img) {
        auto result = NanNew<v8::Object>();
        result->Set(NanNew("width"), NanNew(img->width));
        result->Set(NanNew("height"), NanNew(img->height));

        v8::Local<v8::Object> pixels = NanNewBufferHandle(
            reinterpret_cast<char *>(img->pixels.get()),
            size_t(img->width) * size_t(img->height) * sizeof(mbgl::StillImage::Pixel),

            // Retain the StillImage object until the buffer is deleted.
            [](char *, void *hint) {
                delete reinterpret_cast<const mbgl::StillImage *>(hint);
            },
            const_cast<mbgl::StillImage *>(img.get())
        );
        img.release();

        result->Set(NanNew("pixels"), pixels);

        v8::Local<v8::Value> argv[] = {
            NanNull(),
            result,
        };
        cb->Call(2, argv);
    } else {
        v8::Local<v8::Value> argv[] = {
            NanError("Didn't get an image")
        };
        cb->Call(1, argv);
    }
}

NAN_METHOD(NodeMap::Release) {
    NanScope();

    auto nodeMap = node::ObjectWrap::Unwrap<NodeMap>(args.Holder());

    if (!nodeMap->isValid()) return NanThrowError(releasedMessage());

    try {
        nodeMap->release();
    } catch (const std::exception &ex) {
        return NanThrowError(ex.what());
    }

    NanReturnUndefined();
}

void NodeMap::release() {
    if (!isValid()) throw mbgl::util::Exception(releasedMessage());

    valid = false;

    NanDisposePersistent(source);

    uv_close(reinterpret_cast<uv_handle_t *>(async), [] (uv_handle_t *handle) {
        delete reinterpret_cast<uv_async_t *>(handle);
    });

    map.reset(nullptr);
}

////////////////////////////////////////////////////////////////////////////////////////////////
// Instance

NodeMap::NodeMap(v8::Handle<v8::Object> source_) :
    view(sharedDisplay()),
    fs(*ObjectWrap::Unwrap<NodeFileSource>(source_)),
    map(std::make_unique<mbgl::Map>(view, fs, mbgl::MapMode::Still)),
    async(new uv_async_t) {

    NanAssignPersistent(source, source_);

    async->data = this;
#if UV_VERSION_MAJOR == 0 && UV_VERSION_MINOR <= 10
    uv_async_init(uv_default_loop(), async, [](uv_async_t *as, int) {
#else
    uv_async_init(uv_default_loop(), async, [](uv_async_t *as) {
#endif
        reinterpret_cast<NodeMap *>(as->data)->renderFinished();
    });

    // Make sure the async handle doesn't keep the loop alive.
    uv_unref(reinterpret_cast<uv_handle_t *>(async));
}

NodeMap::~NodeMap() {
    if (valid) release();
}

}
<commit_msg>Better error messages<commit_after>#include "node_map.hpp"
#include "node_file_source.hpp"

#include <mbgl/platform/default/headless_display.hpp>
#include <mbgl/map/still_image.hpp>
#include <mbgl/util/exception.hpp>

#include <unistd.h>

namespace node_mbgl {

struct NodeMap::RenderOptions {
    double zoom = 0;
    double bearing = 0;
    double latitude = 0;
    double longitude = 0;
    unsigned int width = 512;
    unsigned int height = 512;
    float ratio = 1.0f;
    std::vector<std::string> classes;
};

////////////////////////////////////////////////////////////////////////////////////////////////
// Static Node Methods

v8::Persistent<v8::FunctionTemplate> NodeMap::constructorTemplate;

static std::shared_ptr<mbgl::HeadlessDisplay> sharedDisplay() {
    static auto display = std::make_shared<mbgl::HeadlessDisplay>();
    return display;
}

const static char* releasedMessage() {
    return "Map resources have already been released";
}

void NodeMap::Init(v8::Handle<v8::Object> target) {
    NanScope();

    v8::Local<v8::FunctionTemplate> t = NanNew<v8::FunctionTemplate>(New);

    t->InstanceTemplate()->SetInternalFieldCount(1);
    t->SetClassName(NanNew("Map"));

    NODE_SET_PROTOTYPE_METHOD(t, "load", Load);
    NODE_SET_PROTOTYPE_METHOD(t, "render", Render);
    NODE_SET_PROTOTYPE_METHOD(t, "release", Release);

    NanAssignPersistent(constructorTemplate, t);

    target->Set(NanNew("Map"), t->GetFunction());

    // Initialize display connection on module load.
    sharedDisplay();
}

NAN_METHOD(NodeMap::New) {
    NanScope();

    if (!args.IsConstructCall()) {
        return NanThrowTypeError("Use the new operator to create new Map objects");
    }

    if (args.Length() < 1 || !NanHasInstance(NodeFileSource::constructorTemplate, args[0])) {
        return NanThrowTypeError("Requires a FileSource as first argument");
    }

    auto source = args[0]->ToObject();

    // Check that request() and cancel() are defined.
    if (!source->Has(NanNew("request")) || !source->Get(NanNew("request"))->IsFunction()) {
        return NanThrowError("FileSource must have a request member function");
    }
    if (!source->Has(NanNew("cancel")) || !source->Get(NanNew("cancel"))->IsFunction()) {
        return NanThrowError("FileSource must have a cancel member function");
    }

    try {
        auto nodeMap = new NodeMap(source);
        nodeMap->Wrap(args.This());
    } catch(std::exception &ex) {
        return NanThrowError(ex.what());
    }

    NanReturnValue(args.This());
}

const std::string StringifyStyle(v8::Handle<v8::Value> styleHandle) {
    NanScope();

    auto JSON = NanGetCurrentContext()->Global()->Get(NanNew("JSON"))->ToObject();
    auto stringify = v8::Handle<v8::Function>::Cast(JSON->Get(NanNew("stringify")));

    return *NanUtf8String(stringify->Call(JSON, 1, &styleHandle));
}

NAN_METHOD(NodeMap::Load) {
    NanScope();

    auto nodeMap = node::ObjectWrap::Unwrap<NodeMap>(args.Holder());

    if (!nodeMap->isValid()) return NanThrowError(releasedMessage());

    if (args.Length() < 1) {
        return NanThrowError("Requires a map style as first argument");
    }

    std::string style;

    if (args[0]->IsObject()) {
        style = StringifyStyle(args[0]);
    } else if (args[0]->IsString()) {
        style = *NanUtf8String(args[0]);
    } else {
        return NanThrowTypeError("First argument must be a string or object");
    }

    try {
        nodeMap->map->setStyleJSON(style, ".");
    } catch (const std::exception &ex) {
        return NanThrowError(ex.what());
    }

    NanReturnUndefined();
}

std::unique_ptr<NodeMap::RenderOptions> NodeMap::ParseOptions(v8::Local<v8::Object> obj) {
    NanScope();

    auto options = std::make_unique<RenderOptions>();

    if (obj->Has(NanNew("zoom"))) { options->zoom = obj->Get(NanNew("zoom"))->NumberValue(); }
    if (obj->Has(NanNew("bearing"))) { options->bearing = obj->Get(NanNew("bearing"))->NumberValue(); }
    if (obj->Has(NanNew("center"))) {
        auto center = obj->Get(NanNew("center")).As<v8::Array>();
        if (center->Length() > 0) { options->latitude = center->Get(0)->NumberValue(); }
        if (center->Length() > 1) { options->longitude = center->Get(1)->NumberValue(); }
    }
    if (obj->Has(NanNew("width"))) { options->width = obj->Get(NanNew("width"))->IntegerValue(); }
    if (obj->Has(NanNew("height"))) { options->height = obj->Get(NanNew("height"))->IntegerValue(); }
    if (obj->Has(NanNew("ratio"))) { options->ratio = obj->Get(NanNew("ratio"))->IntegerValue(); }

    if (obj->Has(NanNew("classes"))) {
        auto classes = obj->Get(NanNew("classes"))->ToObject().As<v8::Array>();
        const int length = classes->Length();
        options->classes.reserve(length);
        for (int i = 0; i < length; i++) {
            options->classes.push_back(std::string { *NanUtf8String(classes->Get(i)->ToString()) });
        }
    }

    return options;
}

NAN_METHOD(NodeMap::Render) {
    NanScope();

    auto nodeMap = node::ObjectWrap::Unwrap<NodeMap>(args.Holder());

    if (!nodeMap->isValid()) return NanThrowError(releasedMessage());

    if (args.Length() <= 0 || !args[0]->IsObject()) {
        return NanThrowTypeError("First argument must be an options object");
    }

    if (args.Length() <= 1 || !args[1]->IsFunction()) {
        return NanThrowTypeError("Second argument must be a callback function");
    }

    auto options = ParseOptions(args[0]->ToObject());

    assert(!nodeMap->callback);
    assert(!nodeMap->image);
    nodeMap->callback = std::unique_ptr<NanCallback>(new NanCallback(args[1].As<v8::Function>()));

    try {
        nodeMap->startRender(std::move(options));
    } catch (mbgl::util::Exception &ex) {
        return NanThrowError(ex.what());
    }

    NanReturnUndefined();
}

void NodeMap::startRender(std::unique_ptr<NodeMap::RenderOptions> options) {
    map->resize(options->width, options->height, options->ratio);
    map->setClasses(options->classes);
    map->setLatLngZoom(mbgl::LatLng(options->latitude, options->longitude), options->zoom);
    map->setBearing(options->bearing);

    map->renderStill([this](const std::exception_ptr eptr, std::unique_ptr<const mbgl::StillImage> result) {
        if (eptr) {
            error = std::move(eptr);
            uv_async_send(async);
        } else {
            assert(!image);
            image = std::move(result);
            uv_async_send(async);
        }
    });

    // Retain this object, otherwise it might get destructed before we are finished rendering the
    // still image.
    Ref();

    // Similarly, we're now waiting for the async to be called, so we need to make sure that it
    // keeps the loop alive.
    uv_ref(reinterpret_cast<uv_handle_t *>(async));
}

void NodeMap::renderFinished() {
    NanScope();

    // We're done with this render call, so we're unrefing so that the loop could close.
    uv_unref(reinterpret_cast<uv_handle_t *>(async));

    // There is no render pending anymore, we the GC could now delete this object if it went out
    // of scope.
    Unref();

    // Move the callback and image out of the way so that the callback can start a new render call.
    auto cb = std::move(callback);
    auto img = std::move(image);
    assert(cb);

    // These have to be empty to be prepared for the next render call.
    assert(!callback);
    assert(!image);

    if (error) {
        std::string errorMessage;

        try {
            std::rethrow_exception(error);
        } catch (const std::exception& ex) {
            errorMessage = ex.what();
        }

        v8::Local<v8::Value> argv[] = {
            NanError(errorMessage.c_str())
        };

        // This must be empty to be prepared for the next render call.
        error = nullptr;
        assert(!error);

        cb->Call(1, argv);
    } else if (img) {
        auto result = NanNew<v8::Object>();
        result->Set(NanNew("width"), NanNew(img->width));
        result->Set(NanNew("height"), NanNew(img->height));

        v8::Local<v8::Object> pixels = NanNewBufferHandle(
            reinterpret_cast<char *>(img->pixels.get()),
            size_t(img->width) * size_t(img->height) * sizeof(mbgl::StillImage::Pixel),

            // Retain the StillImage object until the buffer is deleted.
            [](char *, void *hint) {
                delete reinterpret_cast<const mbgl::StillImage *>(hint);
            },
            const_cast<mbgl::StillImage *>(img.get())
        );
        img.release();

        result->Set(NanNew("pixels"), pixels);

        v8::Local<v8::Value> argv[] = {
            NanNull(),
            result,
        };
        cb->Call(2, argv);
    } else {
        v8::Local<v8::Value> argv[] = {
            NanError("Didn't get an image")
        };
        cb->Call(1, argv);
    }
}

NAN_METHOD(NodeMap::Release) {
    NanScope();

    auto nodeMap = node::ObjectWrap::Unwrap<NodeMap>(args.Holder());

    if (!nodeMap->isValid()) return NanThrowError(releasedMessage());

    try {
        nodeMap->release();
    } catch (const std::exception &ex) {
        return NanThrowError(ex.what());
    }

    NanReturnUndefined();
}

void NodeMap::release() {
    if (!isValid()) throw mbgl::util::Exception(releasedMessage());

    valid = false;

    NanDisposePersistent(source);

    uv_close(reinterpret_cast<uv_handle_t *>(async), [] (uv_handle_t *handle) {
        delete reinterpret_cast<uv_async_t *>(handle);
    });

    map.reset(nullptr);
}

////////////////////////////////////////////////////////////////////////////////////////////////
// Instance

NodeMap::NodeMap(v8::Handle<v8::Object> source_) :
    view(sharedDisplay()),
    fs(*ObjectWrap::Unwrap<NodeFileSource>(source_)),
    map(std::make_unique<mbgl::Map>(view, fs, mbgl::MapMode::Still)),
    async(new uv_async_t) {

    NanAssignPersistent(source, source_);

    async->data = this;
#if UV_VERSION_MAJOR == 0 && UV_VERSION_MINOR <= 10
    uv_async_init(uv_default_loop(), async, [](uv_async_t *as, int) {
#else
    uv_async_init(uv_default_loop(), async, [](uv_async_t *as) {
#endif
        reinterpret_cast<NodeMap *>(as->data)->renderFinished();
    });

    // Make sure the async handle doesn't keep the loop alive.
    uv_unref(reinterpret_cast<uv_handle_t *>(async));
}

NodeMap::~NodeMap() {
    if (valid) release();
}

}
<|endoftext|>


<commit_before>/**
 * @file   LogXmlNode.hpp
 * @brief  LogXmlNode class prototype.
 * @author zer0
 * @date   2017-04-25
 */

#ifndef __INCLUDE_LIBTBAG__LIBTBAG_LOG_NODE_LOGXMLNODE_HPP__
#define __INCLUDE_LIBTBAG__LIBTBAG_LOG_NODE_LOGXMLNODE_HPP__

// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
#pragma once
#endif

#include <libtbag/config.h>
#include <libtbag/predef.hpp>
#include <libtbag/dom/xml/XmlModel.hpp>
#include <libtbag/log/level/Severity.hpp>
#include <libtbag/log/msg/PacketGenerator.hpp>
#include <libtbag/log/mgr/Logger.hpp>
#include <libtbag/string/Environments.hpp>

#include <vector>

// -------------------
NAMESPACE_LIBTBAG_OPEN
// -------------------

namespace log  {
namespace node {

/**
 * LogXmlNode class prototype.
 *
 * @author zer0
 * @date   2017-04-25
 */
class TBAG_API LogXmlNode : public dom::xml::XmlModel::NodeInterface
{
public:
    using Severity = log::level::Severity;
    using MakeType = log::msg::PacketGenerator::MakeType;
    using Logger   = log::mgr::Logger;
    using Element  = dom::xml::XmlModel::Element;

    using Environments = string::Environments;
    using EnvFlag      = Environments::Flag;

    using StringVector = std::vector<std::string>;

public:
    TBAG_CONSTEXPR static char const * const XML_ELEMENT_TLOG_NAME   = "tlog";
    TBAG_CONSTEXPR static char const * const XML_ELEMENT_LOGGER_NAME = "logger";

    TBAG_CONSTEXPR static char const * const XML_ELEMENT_NAME           = "name";
    TBAG_CONSTEXPR static char const * const XML_ELEMENT_SINK           = "sink";
    TBAG_CONSTEXPR static char const * const XML_ELEMENT_DESTINATION    = "destination";
    TBAG_CONSTEXPR static char const * const XML_ELEMENT_MAX_SIZE       = "max_size";
    TBAG_CONSTEXPR static char const * const XML_ELEMENT_MAX_FILE_COUNT = "max_file_count";
    TBAG_CONSTEXPR static char const * const XML_ELEMENT_MULTITHREAD    = "multithread";
    TBAG_CONSTEXPR static char const * const XML_ELEMENT_MUTEX          = "mutex";
    TBAG_CONSTEXPR static char const * const XML_ELEMENT_GENERATOR      = "generator";
    TBAG_CONSTEXPR static char const * const XML_ELEMENT_SEVERITY       = "severity";
    TBAG_CONSTEXPR static char const * const XML_ELEMENT_AUTO_FLUSH     = "auto_flush";

public:
    TBAG_CONSTEXPR static char const * const AUTO_FLUSH_ON  = "true";
    TBAG_CONSTEXPR static char const * const AUTO_FLUSH_OFF = "false";

    TBAG_CONSTEXPR static char const * const MULTITHREAD_ON  = "true";
    TBAG_CONSTEXPR static char const * const MULTITHREAD_OFF = "false";

    TBAG_CONSTEXPR static char const * const MUTEX_ON  = "true";
    TBAG_CONSTEXPR static char const * const MUTEX_OFF = "false";

    TBAG_CONSTEXPR static char const * const GENERATOR_DEFAULT       = "default";
    TBAG_CONSTEXPR static char const * const GENERATOR_DEFAULT_COLOR = "default_color";
    TBAG_CONSTEXPR static char const * const GENERATOR_RAW           = "raw";

    TBAG_CONSTEXPR static char const * const SINK_COUT        = "cout";
    TBAG_CONSTEXPR static char const * const SINK_CONSOLE     = "console";
    TBAG_CONSTEXPR static char const * const SINK_STDOUT      = "stdout";
    TBAG_CONSTEXPR static char const * const SINK_FILE        = "file";
    TBAG_CONSTEXPR static char const * const SINK_ROTATE_FILE = "rotate_file";

public:
    TBAG_CONSTEXPR static char const * const ENVS_EXE_PATH = "EXE_PATH";
    TBAG_CONSTEXPR static char const * const ENVS_EXE_DIR  = "EXE_DIR";
    TBAG_CONSTEXPR static char const * const ENVS_WORK_DIR = "WORK_DIR";
    TBAG_CONSTEXPR static char const * const ENVS_HOME_DIR = "HOME_DIR";

public:
    struct LogInfo
    {
        std::string name;
        std::string sink;
        std::string destination;
        std::size_t max_size;
        std::size_t max_file_count;
        bool auto_flush;
        bool multithread;
        bool mutex;
        Severity severity;
        MakeType generator;
    };

    using LogInfoVector = std::vector<LogInfo>;

private:
    LogInfoVector _infos;
    Environments  _envs;

public:
    LogXmlNode();
    virtual ~LogXmlNode();

public:
    // @formatter:off
    inline LogInfoVector       & atInfos()       TBAG_NOEXCEPT { return _infos; }
    inline LogInfoVector const & atInfos() const TBAG_NOEXCEPT { return _infos; }
    inline Environments        & atEnvs ()       TBAG_NOEXCEPT { return _envs;  }
    inline Environments  const & atEnvs () const TBAG_NOEXCEPT { return _envs;  }
    // @formatter:on

protected:
    virtual std::string name() const override;

    virtual void setup() override;
    virtual void teardown() override;

    virtual void load(Element const & element) override;
    virtual void save(Element & element) const override;

public:
    /**
     * Create loggers.
     *
     * @return The number of created loggers.
     */
    int createLoggers();
    int createLoggers(std::string & preview_message);

    /**
     * Remove loggers.
     *
     * @return The number of deleted loggers.
     */
    int removeLoggers();

public:
    StringVector getNames() const;

public:
    // @formatter:off
    static std::size_t parseSize         (std::string const & value);
    static bool        parseAutoFlush    (std::string const & value);
    static bool        parseMultiThread  (std::string const & value);
    static bool        parseMutex        (std::string const & value);
    static Severity    parseSeverity     (std::string const & value);
    static MakeType    parseGeneratorType(std::string const & value);
    // @formatter:on

public:
    static std::string getElementText(Element const * element);

public:
    static LogInfo getLogInfo(std::string const & name,
                              std::string const & sink,
                              std::string const & destination,
                              std::string const & max_size,
                              std::string const & max_file_count,
                              std::string const & auto_flush,
                              std::string const & multithread,
                              std::string const & mutex,
                              std::string const & severity,
                              std::string const & generator);
    static LogInfo getLogInfo(Element const & element);

public:
    static LogInfoVector loadLogInfo(Element const & element);

public:
    static bool insertName          (Element & parent, std::string const & name);
    static bool insertSink          (Element & parent, std::string const & sink);
    static bool insertDestination   (Element & parent, std::string const & destination);
    static bool insertMaxSize       (Element & parent, std::size_t max_size);
    static bool insertMaxFileCount  (Element & parent, std::size_t max_file_count);
    static bool insertAutoFlush     (Element & parent, bool auto_flush);
    static bool insertMultiThread   (Element & parent, bool multithread);
    static bool insertMutex         (Element & parent, bool mutex);
    static bool insertSeverity      (Element & parent, Severity severity);
    static bool insertGeneratorType (Element & parent, MakeType type);

public:
    static bool saveLogInfo(Element & parent, LogInfo const & info);
    static bool saveLogInfo(Element & parent, LogInfoVector const & infos);

public:
    static Logger * createLogger(LogInfo const & info, bool recreate_if_exists = true);
    static Logger * createLogger(LogInfo const & info, Environments const & envs, bool recreate_if_exists = true);

public:
    static Environments createDefaultEnvironments();
};

TBAG_API int createLoggerWithXmlConfigPath(std::string const & path);
TBAG_API int createLoggerWithXmlString(std::string const & xml);
TBAG_API int createLoggerWithXmlElement(tinyxml2::XMLElement const & parent);
TBAG_API int createLoggerWithXmlLoggerElement(tinyxml2::XMLElement const & element);

} // namespace node
} // namespace log

// --------------------
NAMESPACE_LIBTBAG_CLOSE
// --------------------

#endif // __INCLUDE_LIBTBAG__LIBTBAG_LOG_NODE_LOGXMLNODE_HPP__

<commit_msg>Update LOG/NODE/XML documentation.<commit_after>/**
 * @file   LogXmlNode.hpp
 * @brief  LogXmlNode class prototype.
 * @author zer0
 * @date   2017-04-25
 */

#ifndef __INCLUDE_LIBTBAG__LIBTBAG_LOG_NODE_LOGXMLNODE_HPP__
#define __INCLUDE_LIBTBAG__LIBTBAG_LOG_NODE_LOGXMLNODE_HPP__

// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
#pragma once
#endif

#include <libtbag/config.h>
#include <libtbag/predef.hpp>
#include <libtbag/dom/xml/XmlModel.hpp>
#include <libtbag/log/level/Severity.hpp>
#include <libtbag/log/msg/PacketGenerator.hpp>
#include <libtbag/log/mgr/Logger.hpp>
#include <libtbag/string/Environments.hpp>

#include <vector>

// -------------------
NAMESPACE_LIBTBAG_OPEN
// -------------------

namespace log  {
namespace node {

/**
 * LogXmlNode class prototype.
 *
 * @author zer0
 * @date   2017-04-25
 *
 * @remarks
 *  XML format:
 *  @code{.xml}
 *   <tlog>
 *     <!-- insert your logger -->
 *     <logger>
 *       <!-- Log name -->
 *       <name>your_logger_name</name>
 *
 *       <!-- Select the sink to which you want to send log messages -->
 *       <!--  cout         (Console/Standard output)                -->
 *       <!--  stdout       (== cout)                                -->
 *       <!--  console      (Console output                          -->
 *       <!--  file         (File output                             -->
 *       <!--  rotate_file  (Rotate file output                      -->
 *       <sink>file</sink>
 *
 *       <!-- Specify the detailed path of the sink                 -->
 *       <!--  <sink: cout>        case: Not used                   -->
 *       <!--  <sink: stdout>      case: Not used                   -->
 *       <!--  <sink: console>     case: 'stdout' or 'stderr', if not exists use the 'stdout' [CURRENTLY NOT SUPPORTED] -->
 *       <!--  <sink: file>        case: log file location path     -->
 *       <!--  <sink: rotate_file> case: log file location prefix   -->
 *       <!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
 *       <!-- Special exchange variable:          -->
 *       <!-- ${EXE_PATH} : EXE file path         -->
 *       <!-- ${EXE_DIR}  : EXE directory         -->
 *       <!-- ${WORK_DIR} : Working directory     -->
 *       <!-- ${HOME_DIR} : User's HOME directory -->
 *       <destination>${EXE_DIR}/tbag-logger-test.log</destination>
 *
 *       <!-- File size limit           -->
 *       <!-- [CURRENTLY NOT SUPPORTED] -->
 *       <max_size>1024MByte</max_size>
 *
 *       <!-- Destination size limit    -->
 *       <!-- [CURRENTLY NOT SUPPORTED] -->
 *       <max_file_count>10</max_file_count>
 *
 *       <!-- Multi-thread logger       -->
 *       <!-- [CURRENTLY NOT SUPPORTED] -->
 *       <multithread>false</multithread>
 *
 *       <!-- Use the mutex locking: 'true' or 'false' -->
 *       <mutex>true</mutex>
 *
 *       <!-- Log message generator                                 -->
 *       <!--  default        (Default log message)                 -->
 *       <!--  default_color  (Default+TCES coloring log message)   -->
 *       <!--  raw            (Raw log message)                     -->
 *       <generator>default</generator>
 *
 *       <!-- Log level: 'true' or 'false'                           -->
 *       <!--  level 0: off       (Hide all messages)                -->
 *       <!--  level 1: emergency (System is unusable)               -->
 *       <!--  level 2: alert     (Action must be taken immediately) -->
 *       <!--  level 3: critical  (Critical conditions)              -->
 *       <!--  level 4: error     (Error conditions)                 -->
 *       <!--  level 5: warning   (Warning conditions)               -->
 *       <!--  level 6: notice    (Normal but significant condition) -->
 *       <!--  level 7: info      (Informational messages)           -->
 *       <!--  level 8: debug     (Debug-level messages)             -->
 *       <!--  level 9: unknown   (Unknown level)                    -->
 *       <severity>critical</severity>
 *
 *       <!-- Auto flush flag: 'true' or 'false' -->
 *       <auto_flush>true</auto_flush>
 *     </logger>
 *
 *     <!-- More logger information ... -->
 *   </tlog>
 *  @endcode
 */
class TBAG_API LogXmlNode : public dom::xml::XmlModel::NodeInterface
{
public:
    using Severity = log::level::Severity;
    using MakeType = log::msg::PacketGenerator::MakeType;
    using Logger   = log::mgr::Logger;
    using Element  = dom::xml::XmlModel::Element;

    using Environments = string::Environments;
    using EnvFlag      = Environments::Flag;

    using StringVector = std::vector<std::string>;

public:
    TBAG_CONSTEXPR static char const * const XML_ELEMENT_TLOG_NAME   = "tlog";
    TBAG_CONSTEXPR static char const * const XML_ELEMENT_LOGGER_NAME = "logger";

    TBAG_CONSTEXPR static char const * const XML_ELEMENT_NAME           = "name";
    TBAG_CONSTEXPR static char const * const XML_ELEMENT_SINK           = "sink";
    TBAG_CONSTEXPR static char const * const XML_ELEMENT_DESTINATION    = "destination";
    TBAG_CONSTEXPR static char const * const XML_ELEMENT_MAX_SIZE       = "max_size";
    TBAG_CONSTEXPR static char const * const XML_ELEMENT_MAX_FILE_COUNT = "max_file_count";
    TBAG_CONSTEXPR static char const * const XML_ELEMENT_MULTITHREAD    = "multithread";
    TBAG_CONSTEXPR static char const * const XML_ELEMENT_MUTEX          = "mutex";
    TBAG_CONSTEXPR static char const * const XML_ELEMENT_GENERATOR      = "generator";
    TBAG_CONSTEXPR static char const * const XML_ELEMENT_SEVERITY       = "severity";
    TBAG_CONSTEXPR static char const * const XML_ELEMENT_AUTO_FLUSH     = "auto_flush";

public:
    TBAG_CONSTEXPR static char const * const AUTO_FLUSH_ON  = "true";
    TBAG_CONSTEXPR static char const * const AUTO_FLUSH_OFF = "false";

    TBAG_CONSTEXPR static char const * const MULTITHREAD_ON  = "true";
    TBAG_CONSTEXPR static char const * const MULTITHREAD_OFF = "false";

    TBAG_CONSTEXPR static char const * const MUTEX_ON  = "true";
    TBAG_CONSTEXPR static char const * const MUTEX_OFF = "false";

    TBAG_CONSTEXPR static char const * const GENERATOR_DEFAULT       = "default";
    TBAG_CONSTEXPR static char const * const GENERATOR_DEFAULT_COLOR = "default_color";
    TBAG_CONSTEXPR static char const * const GENERATOR_RAW           = "raw";

    TBAG_CONSTEXPR static char const * const SINK_COUT        = "cout";
    TBAG_CONSTEXPR static char const * const SINK_CONSOLE     = "console";
    TBAG_CONSTEXPR static char const * const SINK_STDOUT      = "stdout";
    TBAG_CONSTEXPR static char const * const SINK_FILE        = "file";
    TBAG_CONSTEXPR static char const * const SINK_ROTATE_FILE = "rotate_file";

public:
    TBAG_CONSTEXPR static char const * const ENVS_EXE_PATH = "EXE_PATH";
    TBAG_CONSTEXPR static char const * const ENVS_EXE_DIR  = "EXE_DIR";
    TBAG_CONSTEXPR static char const * const ENVS_WORK_DIR = "WORK_DIR";
    TBAG_CONSTEXPR static char const * const ENVS_HOME_DIR = "HOME_DIR";

public:
    struct LogInfo
    {
        std::string name;
        std::string sink;
        std::string destination;
        std::size_t max_size;
        std::size_t max_file_count;
        bool auto_flush;
        bool multithread;
        bool mutex;
        Severity severity;
        MakeType generator;
    };

    using LogInfoVector = std::vector<LogInfo>;

private:
    LogInfoVector _infos;
    Environments  _envs;

public:
    LogXmlNode();
    virtual ~LogXmlNode();

public:
    // @formatter:off
    inline LogInfoVector       & atInfos()       TBAG_NOEXCEPT { return _infos; }
    inline LogInfoVector const & atInfos() const TBAG_NOEXCEPT { return _infos; }
    inline Environments        & atEnvs ()       TBAG_NOEXCEPT { return _envs;  }
    inline Environments  const & atEnvs () const TBAG_NOEXCEPT { return _envs;  }
    // @formatter:on

protected:
    virtual std::string name() const override;

    virtual void setup() override;
    virtual void teardown() override;

    virtual void load(Element const & element) override;
    virtual void save(Element & element) const override;

public:
    /**
     * Create loggers.
     *
     * @return The number of created loggers.
     */
    int createLoggers();
    int createLoggers(std::string & preview_message);

    /**
     * Remove loggers.
     *
     * @return The number of deleted loggers.
     */
    int removeLoggers();

public:
    StringVector getNames() const;

public:
    // @formatter:off
    static std::size_t parseSize         (std::string const & value);
    static bool        parseAutoFlush    (std::string const & value);
    static bool        parseMultiThread  (std::string const & value);
    static bool        parseMutex        (std::string const & value);
    static Severity    parseSeverity     (std::string const & value);
    static MakeType    parseGeneratorType(std::string const & value);
    // @formatter:on

public:
    static std::string getElementText(Element const * element);

public:
    static LogInfo getLogInfo(std::string const & name,
                              std::string const & sink,
                              std::string const & destination,
                              std::string const & max_size,
                              std::string const & max_file_count,
                              std::string const & auto_flush,
                              std::string const & multithread,
                              std::string const & mutex,
                              std::string const & severity,
                              std::string const & generator);
    static LogInfo getLogInfo(Element const & element);

public:
    static LogInfoVector loadLogInfo(Element const & element);

public:
    static bool insertName          (Element & parent, std::string const & name);
    static bool insertSink          (Element & parent, std::string const & sink);
    static bool insertDestination   (Element & parent, std::string const & destination);
    static bool insertMaxSize       (Element & parent, std::size_t max_size);
    static bool insertMaxFileCount  (Element & parent, std::size_t max_file_count);
    static bool insertAutoFlush     (Element & parent, bool auto_flush);
    static bool insertMultiThread   (Element & parent, bool multithread);
    static bool insertMutex         (Element & parent, bool mutex);
    static bool insertSeverity      (Element & parent, Severity severity);
    static bool insertGeneratorType (Element & parent, MakeType type);

public:
    static bool saveLogInfo(Element & parent, LogInfo const & info);
    static bool saveLogInfo(Element & parent, LogInfoVector const & infos);

public:
    static Logger * createLogger(LogInfo const & info, bool recreate_if_exists = true);
    static Logger * createLogger(LogInfo const & info, Environments const & envs, bool recreate_if_exists = true);

public:
    static Environments createDefaultEnvironments();
};

TBAG_API int createLoggerWithXmlConfigPath(std::string const & path);
TBAG_API int createLoggerWithXmlString(std::string const & xml);
TBAG_API int createLoggerWithXmlElement(tinyxml2::XMLElement const & parent);
TBAG_API int createLoggerWithXmlLoggerElement(tinyxml2::XMLElement const & element);

} // namespace node
} // namespace log

// --------------------
NAMESPACE_LIBTBAG_CLOSE
// --------------------

#endif // __INCLUDE_LIBTBAG__LIBTBAG_LOG_NODE_LOGXMLNODE_HPP__

<|endoftext|>


<commit_before>// The MIT License (MIT)

// Copyright (c) 2013 lailongwei<lailongwei@126.com>
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

#include "llbc/common/Export.h"
#include "llbc/common/BeforeIncl.h"
#include "llbc/core/file/File.h"
#include "llbc/core/thread/FastLock.h"
#include "llbc/core/os/OS_Console.h"

__LLBC_INTERNAL_NS_BEGIN
static LLBC_NS LLBC_FastLock __g_consoleLock[ 2 ];
__LLBC_INTERNAL_NS_END

#if LLBC_TARGET_PLATFORM_NON_WIN32
__LLBC_INTERNAL_NS_BEGIN
static int __g_consoleColor[ 2 ];
const static char* __g_consoleColorBeginFmt = "\033[";
const static char* __g_consoleHighColorBeginFmt = "\033[1;";
const static char* __g_consoleColorEndFmt = "\033[0m";

static const int __g_consoleFgColorNum = 8;
static const int __g_consoleBgColorNum = 8;
static const char* __g_ConsoleFgColorCode[ __g_consoleFgColorNum ] = { "30", "31", "32", "34", "33", "35", "36", "37" };
static const char* __g_ConsoleBgColorCode[ __g_consoleBgColorNum ] = { "40", "41", "42", "44", "43", "45", "46", "47" };

void __GetConsoleColorCode(int color, const char*& begFmt, const char*& fgColorCode, const char*& bgColorCode, const char*& endFmt)
{
    if (LIKELY(color <= 0))
        return;

	int fgColor = color & ((1 << __g_consoleFgColorNum) - 1);
    int bgColor = (color >> __g_consoleFgColorNum) & ((1 << __g_consoleBgColorNum) - 1);
    int highColor = (color >> __g_consoleFgColorNum) >> __g_consoleBgColorNum;
    if (LIKELY(fgColor > 0))
	{
        int idx = -1;
        while (++idx, fgColor = fgColor >> 1, fgColor > 0 && idx < __g_consoleFgColorNum);
        fgColorCode = __g_ConsoleFgColorCode[ idx ];
	}

    if (LIKELY(bgColor > 0))
    {
		int idx = -1;
        while (++idx, bgColor = bgColor >> 1, bgColor > 0 && idx < __g_consoleBgColorNum);
        bgColorCode = __g_ConsoleBgColorCode[ idx ];
    }

	begFmt = (highColor > 0) ? __g_consoleHighColorBeginFmt : __g_consoleColorBeginFmt;
    endFmt = __g_consoleColorEndFmt;
}

__LLBC_INTERNAL_NS_END
#endif // LLBC_TARGET_PLATFORM_NON_WIN32

__LLBC_NS_BEGIN

int LLBC_GetConsoleColor(FILE *file)
{
	const int fileNo = LLBC_File::GetFileNo(file);
    if (UNLIKELY(fileNo == -1))
    {
        return LLBC_FAILED;
    }
    else if (UNLIKELY(fileNo != 1 && fileNo != 2))
    {
        LLBC_SetLastError(LLBC_ERROR_INVALID);
        return LLBC_FAILED;
    }

#if LLBC_TARGET_PLATFORM_NON_WIN32
    LLBC_INTERNAL_NS __g_consoleLock[ (fileNo == 1 || fileNo == 2 ? 0 : 1) ].Lock();
    const int color = LLBC_INTERNAL_NS __g_consoleColor[ (fileNo == 1 || fileNo == 2 ? 0 : 1) ];
    LLBC_INTERNAL_NS __g_consoleLock[ (fileNo == 1 || fileNo == 2 ? 0 : 1) ].Unlock();
    return color;
#else

    LLBC_INTERNAL_NS __g_consoleLock[ (fileNo == 1 || fileNo == 2 ? 0 : 1) ].Lock();

    HANDLE handle = (fileNo == 1 ?
        ::GetStdHandle(STD_OUTPUT_HANDLE) : GetStdHandle(STD_ERROR_HANDLE));
    CONSOLE_SCREEN_BUFFER_INFO info;
    if (::GetConsoleScreenBufferInfo(handle, &info) == 0)
    {
        LLBC_INTERNAL_NS __g_consoleLock[(fileNo == 1 || fileNo == 2 ? 0 : 1)].Unlock();
        LLBC_SetLastError(LLBC_ERROR_OSAPI);
        return LLBC_FAILED;
    }

    LLBC_INTERNAL_NS __g_consoleLock[(fileNo == 1 || fileNo == 2 ? 0 : 1)].Unlock();

    return info.wAttributes;
#endif
}

int LLBC_SetConsoleColor(FILE *file, int color)
{
    const int fileNo = LLBC_File::GetFileNo(file);
    if (UNLIKELY(fileNo == -1))
    {
        return LLBC_FAILED;
    }
    else if (UNLIKELY(fileNo != 1 && fileNo != 2))
    {
        LLBC_SetLastError(LLBC_ERROR_INVALID);
        return LLBC_FAILED;
    }

#if LLBC_TARGET_PLATFORM_NON_WIN32
    LLBC_INTERNAL_NS __g_consoleLock[ (fileNo == 1 || fileNo == 2 ? 0 : 1) ].Lock();
    LLBC_INTERNAL_NS __g_consoleColor[ (fileNo == 1 || fileNo == 2 ? 0 : 1) ] = color;
    LLBC_INTERNAL_NS __g_consoleLock[ (fileNo == 1 || fileNo == 2 ? 0 : 1) ].Unlock();
    return LLBC_OK;
#else

    LLBC_INTERNAL_NS __g_consoleLock[ (fileNo == 1 || fileNo == 2 ? 0 : 1) ].Lock();

    HANDLE handle = (fileNo == 1 ?
        ::GetStdHandle(STD_OUTPUT_HANDLE) : GetStdHandle(STD_ERROR_HANDLE));
    if (::SetConsoleTextAttribute(handle, color) == 0)
    {
        LLBC_INTERNAL_NS __g_consoleLock[(fileNo == 1 || fileNo == 2 ? 0 : 1)].Unlock();
        LLBC_SetLastError(LLBC_ERROR_OSAPI);
        return LLBC_FAILED;
    }

    LLBC_INTERNAL_NS __g_consoleLock[(fileNo == 1 || fileNo == 2 ? 0 : 1)].Unlock();
    return LLBC_OK;
#endif
}

int __LLBC_FilePrint(bool newline, FILE *file, const char *fmt, ...)
{
    const int fileNo = LLBC_File::GetFileNo(file);
    if (UNLIKELY(fileNo == -1))
    {
        return LLBC_FAILED;
    }

    char *buf; int len;
    LLBC_FormatArg(fmt, buf, len);

#if LLBC_TARGET_PLATFORM_NON_WIN32
    flockfile(file);
	if (LIKELY(file == stdout || file == stderr))
	{
        const char* colorBegFmt = NULL;
        const char* colorEndFmt = NULL;
        const char* fgColorCode = NULL;
        const char* bgColorCode = NULL;
        LLBC_INTERNAL_NS __GetConsoleColorCode(LLBC_GetConsoleColor(file), colorBegFmt, fgColorCode, bgColorCode, colorEndFmt);
        if (LIKELY(fgColorCode != NULL && bgColorCode != NULL))
        {
            fprintf(file, (newline ? "%s%s;%sm%s%s\n" : "%s%s;%sm%s%s"), colorBegFmt, fgColorCode, bgColorCode, buf, colorEndFmt);
        }
        else if (LIKELY(fgColorCode != NULL || bgColorCode != NULL))
        {
            fprintf(file, (newline ? "%s%sm%s%s\n" : "%s%sm%s%s"), colorBegFmt, (fgColorCode != NULL ? fgColorCode : bgColorCode), buf, colorEndFmt);
        }
        else
        {
            fprintf(file, (newline ? "%s\n" : "%s"), buf);
        }
	}
	else
	{
        fprintf(file, (newline ? "%s\n" : "%s"), buf);

	}
    fflush(file);
    funlockfile(file);
#else
    LLBC_INTERNAL_NS __g_consoleLock[(fileNo == 1 || fileNo == 2 ? 0 : 1)].Lock();
    fprintf(file, newline?"%s\n":"%s", buf);
    fflush(file);
    LLBC_INTERNAL_NS __g_consoleLock[(fileNo == 1 || fileNo == 2 ? 0 : 1)].Unlock();
#endif

    LLBC_Free(buf);

    return LLBC_OK;
}

int LLBC_FlushFile(FILE *file)
{
    if (UNLIKELY(!file))
    {
        LLBC_SetLastError(LLBC_ERROR_INVALID);
        return LLBC_FAILED;
    }

#if LLBC_TARGET_PLATFORM_NON_WIN32
    flockfile(file);
    if (UNLIKELY(::fflush(file) != 0))
    {
        funlockfile(file);
        LLBC_SetLastError(LLBC_ERROR_CLIB);
        return LLBC_FAILED;
    }

    funlockfile(file);
    return LLBC_OK;
#else // Win32
    const int fileNo = LLBC_File::GetFileNo(file);
    LLBC_INTERNAL_NS __g_consoleLock[(fileNo == 1 || fileNo == 2 ? 0 : 1)].Lock();
    if (UNLIKELY(::fflush(file) != 0))
    {
        LLBC_INTERNAL_NS __g_consoleLock[(fileNo == 1 || fileNo == 2 ? 0 : 1)].Unlock();
        LLBC_SetLastError(LLBC_ERROR_CLIB);
        return LLBC_FAILED;
    }

    LLBC_INTERNAL_NS __g_consoleLock[(fileNo == 1 || fileNo == 2 ? 0 : 1)].Unlock();
    return LLBC_OK;
#endif
}

__LLBC_NS_END

#include "llbc/common/AfterIncl.h"
<commit_msg>add linux console colors<commit_after>// The MIT License (MIT)

// Copyright (c) 2013 lailongwei<lailongwei@126.com>
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

#include "llbc/common/Export.h"
#include "llbc/common/BeforeIncl.h"
#include "llbc/core/file/File.h"
#include "llbc/core/thread/FastLock.h"
#include "llbc/core/os/OS_Console.h"

__LLBC_INTERNAL_NS_BEGIN
static LLBC_NS LLBC_FastLock __g_consoleLock[ 2 ];
__LLBC_INTERNAL_NS_END

#if LLBC_TARGET_PLATFORM_NON_WIN32
__LLBC_INTERNAL_NS_BEGIN
static int __g_consoleColor[ 2 ];
const static char* __g_consoleColorBeginFmt = "\033[";
const static char* __g_consoleHighColorBeginFmt = "\033[1;";
const static char* __g_consoleColorEndFmt = "\033[0m";

static const int __g_consoleFgColorNum = 8;
static const int __g_consoleBgColorNum = 8;
static const char* __g_ConsoleFgColorCode[ __g_consoleFgColorNum ] = { "30", "31", "32", "34", "33", "35", "36", "37" };
static const char* __g_ConsoleBgColorCode[ __g_consoleBgColorNum ] = { "40", "41", "42", "44", "43", "45", "46", "47" };

void __GetConsoleColorCode(int color, const char*& begFmt, const char*& fgColorCode, const char*& bgColorCode, const char*& endFmt)
{
    if (LIKELY(color <= 0))
        return;

    int fgColor = color & ((1 << __g_consoleFgColorNum) - 1);
    int bgColor = (color >> __g_consoleFgColorNum) & ((1 << __g_consoleBgColorNum) - 1);
    int highColor = (color >> __g_consoleFgColorNum) >> __g_consoleBgColorNum;
    if (LIKELY(fgColor > 0))
    {
        int idx = -1;
        while (++idx, fgColor = fgColor >> 1, fgColor > 0 && idx < __g_consoleFgColorNum);
        fgColorCode = __g_ConsoleFgColorCode[ idx ];
    }

    if (LIKELY(bgColor > 0))
    {
        int idx = -1;
        while (++idx, bgColor = bgColor >> 1, bgColor > 0 && idx < __g_consoleBgColorNum);
        bgColorCode = __g_ConsoleBgColorCode[ idx ];
    }

    begFmt = (highColor > 0) ? __g_consoleHighColorBeginFmt : __g_consoleColorBeginFmt;
    endFmt = __g_consoleColorEndFmt;
}

__LLBC_INTERNAL_NS_END
#endif // LLBC_TARGET_PLATFORM_NON_WIN32

__LLBC_NS_BEGIN

int LLBC_GetConsoleColor(FILE *file)
{
	const int fileNo = LLBC_File::GetFileNo(file);
    if (UNLIKELY(fileNo == -1))
    {
        return LLBC_FAILED;
    }
    else if (UNLIKELY(fileNo != 1 && fileNo != 2))
    {
        LLBC_SetLastError(LLBC_ERROR_INVALID);
        return LLBC_FAILED;
    }

#if LLBC_TARGET_PLATFORM_NON_WIN32
    LLBC_INTERNAL_NS __g_consoleLock[ (fileNo == 1 || fileNo == 2 ? 0 : 1) ].Lock();
    const int color = LLBC_INTERNAL_NS __g_consoleColor[ (fileNo == 1 || fileNo == 2 ? 0 : 1) ];
    LLBC_INTERNAL_NS __g_consoleLock[ (fileNo == 1 || fileNo == 2 ? 0 : 1) ].Unlock();
    return color;
#else

    LLBC_INTERNAL_NS __g_consoleLock[ (fileNo == 1 || fileNo == 2 ? 0 : 1) ].Lock();

    HANDLE handle = (fileNo == 1 ?
        ::GetStdHandle(STD_OUTPUT_HANDLE) : GetStdHandle(STD_ERROR_HANDLE));
    CONSOLE_SCREEN_BUFFER_INFO info;
    if (::GetConsoleScreenBufferInfo(handle, &info) == 0)
    {
        LLBC_INTERNAL_NS __g_consoleLock[(fileNo == 1 || fileNo == 2 ? 0 : 1)].Unlock();
        LLBC_SetLastError(LLBC_ERROR_OSAPI);
        return LLBC_FAILED;
    }

    LLBC_INTERNAL_NS __g_consoleLock[(fileNo == 1 || fileNo == 2 ? 0 : 1)].Unlock();

    return info.wAttributes;
#endif
}

int LLBC_SetConsoleColor(FILE *file, int color)
{
    const int fileNo = LLBC_File::GetFileNo(file);
    if (UNLIKELY(fileNo == -1))
    {
        return LLBC_FAILED;
    }
    else if (UNLIKELY(fileNo != 1 && fileNo != 2))
    {
        LLBC_SetLastError(LLBC_ERROR_INVALID);
        return LLBC_FAILED;
    }

#if LLBC_TARGET_PLATFORM_NON_WIN32
    LLBC_INTERNAL_NS __g_consoleLock[ (fileNo == 1 || fileNo == 2 ? 0 : 1) ].Lock();
    LLBC_INTERNAL_NS __g_consoleColor[ (fileNo == 1 || fileNo == 2 ? 0 : 1) ] = color;
    LLBC_INTERNAL_NS __g_consoleLock[ (fileNo == 1 || fileNo == 2 ? 0 : 1) ].Unlock();
    return LLBC_OK;
#else

    LLBC_INTERNAL_NS __g_consoleLock[ (fileNo == 1 || fileNo == 2 ? 0 : 1) ].Lock();

    HANDLE handle = (fileNo == 1 ?
        ::GetStdHandle(STD_OUTPUT_HANDLE) : GetStdHandle(STD_ERROR_HANDLE));
    if (::SetConsoleTextAttribute(handle, color) == 0)
    {
        LLBC_INTERNAL_NS __g_consoleLock[(fileNo == 1 || fileNo == 2 ? 0 : 1)].Unlock();
        LLBC_SetLastError(LLBC_ERROR_OSAPI);
        return LLBC_FAILED;
    }

    LLBC_INTERNAL_NS __g_consoleLock[(fileNo == 1 || fileNo == 2 ? 0 : 1)].Unlock();
    return LLBC_OK;
#endif
}

int __LLBC_FilePrint(bool newline, FILE *file, const char *fmt, ...)
{
    const int fileNo = LLBC_File::GetFileNo(file);
    if (UNLIKELY(fileNo == -1))
    {
        return LLBC_FAILED;
    }

    char *buf; int len;
    LLBC_FormatArg(fmt, buf, len);

#if LLBC_TARGET_PLATFORM_NON_WIN32
    flockfile(file);
	if (LIKELY(file == stdout || file == stderr))
	{
        const char* colorBegFmt = NULL;
        const char* colorEndFmt = NULL;
        const char* fgColorCode = NULL;
        const char* bgColorCode = NULL;
        LLBC_INTERNAL_NS __GetConsoleColorCode(LLBC_GetConsoleColor(file), colorBegFmt, fgColorCode, bgColorCode, colorEndFmt);
        if (LIKELY(fgColorCode != NULL && bgColorCode != NULL))
        {
            fprintf(file, (newline ? "%s%s;%sm%s%s\n" : "%s%s;%sm%s%s"), colorBegFmt, fgColorCode, bgColorCode, buf, colorEndFmt);
        }
        else if (LIKELY(fgColorCode != NULL || bgColorCode != NULL))
        {
            fprintf(file, (newline ? "%s%sm%s%s\n" : "%s%sm%s%s"), colorBegFmt, (fgColorCode != NULL ? fgColorCode : bgColorCode), buf, colorEndFmt);
        }
        else
        {
            fprintf(file, (newline ? "%s\n" : "%s"), buf);
        }
	}
	else
	{
        fprintf(file, (newline ? "%s\n" : "%s"), buf);

	}
    fflush(file);
    funlockfile(file);
#else
    LLBC_INTERNAL_NS __g_consoleLock[(fileNo == 1 || fileNo == 2 ? 0 : 1)].Lock();
    fprintf(file, newline?"%s\n":"%s", buf);
    fflush(file);
    LLBC_INTERNAL_NS __g_consoleLock[(fileNo == 1 || fileNo == 2 ? 0 : 1)].Unlock();
#endif

    LLBC_Free(buf);

    return LLBC_OK;
}

int LLBC_FlushFile(FILE *file)
{
    if (UNLIKELY(!file))
    {
        LLBC_SetLastError(LLBC_ERROR_INVALID);
        return LLBC_FAILED;
    }

#if LLBC_TARGET_PLATFORM_NON_WIN32
    flockfile(file);
    if (UNLIKELY(::fflush(file) != 0))
    {
        funlockfile(file);
        LLBC_SetLastError(LLBC_ERROR_CLIB);
        return LLBC_FAILED;
    }

    funlockfile(file);
    return LLBC_OK;
#else // Win32
    const int fileNo = LLBC_File::GetFileNo(file);
    LLBC_INTERNAL_NS __g_consoleLock[(fileNo == 1 || fileNo == 2 ? 0 : 1)].Lock();
    if (UNLIKELY(::fflush(file) != 0))
    {
        LLBC_INTERNAL_NS __g_consoleLock[(fileNo == 1 || fileNo == 2 ? 0 : 1)].Unlock();
        LLBC_SetLastError(LLBC_ERROR_CLIB);
        return LLBC_FAILED;
    }

    LLBC_INTERNAL_NS __g_consoleLock[(fileNo == 1 || fileNo == 2 ? 0 : 1)].Unlock();
    return LLBC_OK;
#endif
}

__LLBC_NS_END

#include "llbc/common/AfterIncl.h"
<|endoftext|>