<commit_before>// ---------------------------------------------------------------------
//
// Copyright (C) 2005 - 2014 by the deal.II authors
//
// This file is part of the deal.II library.
//
// The deal.II library is free software; you can use it, 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.
// The full text of the license can be found in the file LICENSE at
// the top level of the deal.II distribution.
//
// ---------------------------------------------------------------------

#include <deal.II/lac/tridiagonal_matrix.h>
#include <deal.II/lac/vector.h>
#include <deal.II/lac/lapack_templates.h>

DEAL_II_NAMESPACE_OPEN

using namespace LAPACKSupport;

template <typename number>
TridiagonalMatrix<number>::TridiagonalMatrix(
  size_type size,
  bool symmetric)
  :
  diagonal(size, 0.),
  left((symmetric ? 0 : size), 0.),
  right(size, 0.),
  is_symmetric(symmetric),
  state(matrix)
{}

template <typename number>
void
TridiagonalMatrix<number>::reinit(
  size_type size,
  bool symmetric)
{
  is_symmetric = symmetric;
  diagonal.resize(size);
  right.resize(size);
  left.resize(symmetric ? 0 : size);
  state = matrix;
}

template <typename number>
bool
TridiagonalMatrix<number>::all_zero() const
{
  Assert(state == matrix, ExcState(state));

  typename std::vector<number>::const_iterator i;
  typename std::vector<number>::const_iterator e;

  e = diagonal.end();
  for (i=diagonal.begin() ; i != e ; ++i)
    if (*i != 0.) return false;

  e = left.end();
  for (i=left.begin() ; i != e ; ++i)
    if (*i != 0.) return false;

  e = right.end();
  for (i=right.begin() ; i != e ; ++i)
    if (*i != 0.) return false;
  return true;
}

template <typename number>
void
TridiagonalMatrix<number>::vmult (
  Vector<number>       &w,
  const Vector<number> &v,
  const bool            adding) const
{
  Assert(state == matrix, ExcState(state));

  Assert(w.size() == n(), ExcDimensionMismatch(w.size(), n()));
  Assert(v.size() == n(), ExcDimensionMismatch(v.size(), n()));

  if (n()==0) return;

  // The actual loop skips the first
  // and last row
  const size_type e=n()-1;
  // Let iterators point to the first
  // entry of each diagonal
  typename std::vector<number>::const_iterator d = diagonal.begin();
  typename std::vector<number>::const_iterator r = right.begin();
  // The left diagonal starts one
  // later or is equal to the right
  // one for symmetric storage
  typename std::vector<number>::const_iterator l = left.begin();
  if (is_symmetric)
    l = r;
  else
    ++l;

  if (adding)
    {
      // Treat first row separately
      w(0) += (*d) * v(0) + (*r) * v(1);
      ++d;
      ++r;
      // All rows with three entries
      for (size_type i=1; i<e; ++i,++d,++r,++l)
        w(i) += (*l) * v(i-1) + (*d) * v(i) + (*r) * v(i+1);
      // Last row is special again
      w(e) += (*l) * v(e-1) + (*d) * v(e);
    }
  else
    {
      w(0) = (*d) * v(0) + (*r) * v(1);
      ++d;
      ++r;
      for (size_type i=1; i<e; ++i,++d,++r,++l)
        w(i) = (*l) * v(i-1) + (*d) * v(i) + (*r) * v(i+1);
      w(e) = (*l) * v(e-1) + (*d) * v(e);
    }
}

template <typename number>
void
TridiagonalMatrix<number>::vmult_add (
  Vector<number>       &w,
  const Vector<number> &v) const
{
  vmult(w, v, true);
}

template <typename number>
void
TridiagonalMatrix<number>::Tvmult (
  Vector<number>       &w,
  const Vector<number> &v,
  const bool            adding) const
{
  Assert(state == matrix, ExcState(state));

  Assert(w.size() == n(), ExcDimensionMismatch(w.size(), n()));
  Assert(v.size() == n(), ExcDimensionMismatch(v.size(), n()));

  if (n()==0) return;

  const size_type e=n()-1;
  typename std::vector<number>::const_iterator d = diagonal.begin();
  typename std::vector<number>::const_iterator r = right.begin();
  typename std::vector<number>::const_iterator l = left.begin();
  if (is_symmetric)
    l = r;
  else
    ++l;

  if (adding)
    {
      w(0) += (*d) * v(0) + (*l) * v(1);
      ++d;
      ++l;
      for (size_type i=1; i<e; ++i,++d,++r,++l)
        w(i) += (*l) * v(i+1) + (*d) * v(i) + (*r) * v(i-1);
      w(e) += (*d) * v(e) + (*r) * v(e-1);
    }
  else
    {
      w(0) = (*d) * v(0) + (*l) * v(1);
      ++d;
      ++l;
      for (size_type i=1; i<e; ++i,++d,++r,++l)
        w(i) = (*l) * v(i+1) + (*d) * v(i) + (*r) * v(i-1);
      w(e) = (*d) * v(e) + (*r) * v(e-1);
    }
}

template <typename number>
void
TridiagonalMatrix<number>::Tvmult_add (
  Vector<number>       &w,
  const Vector<number> &v) const
{
  Tvmult(w, v, true);
}

template <typename number>
number
TridiagonalMatrix<number>::matrix_scalar_product(
  const Vector<number> &w,
  const Vector<number> &v) const
{
  Assert(state == matrix, ExcState(state));

  const size_type e=n()-1;
  typename std::vector<number>::const_iterator d = diagonal.begin();
  typename std::vector<number>::const_iterator r = right.begin();
  typename std::vector<number>::const_iterator l = left.begin();
  if (is_symmetric)
    l = r;
  else
    ++l;

  number result = w(0) * ((*d) * v(0) + (*r) * v(1));
  ++d;
  ++r;
  for (size_type i=1; i<e; ++i,++d,++r,++l)
    result += w(i) * ((*l) * v(i-1)+ (*d) * v(i)+ (*r) * v(i+1));
  result += w(e) * ((*l) * v(e-1) + (*d) * v(e));
  return result;
}

template <typename number>
number
TridiagonalMatrix<number>::matrix_norm_square(
  const Vector<number> &v) const
{
  return matrix_scalar_product(v,v);
}

template <>
void
TridiagonalMatrix<double>::compute_eigenvalues()
{
#ifdef DEAL_II_WITH_LAPACK
  Assert(state == matrix, ExcState(state));
  Assert(is_symmetric, ExcNotImplemented());

  const int nn = n();
  int info;
  stev (&N, &nn, &*diagonal.begin(), &*right.begin(), nullptr, &one, nullptr, &info);
  Assert(info == 0, ExcInternalError());

  state = LAPACKSupport::eigenvalues;
#else
  Assert(false, ExcNeedsLAPACK());
#endif
}

template <typename number>
number
TridiagonalMatrix<number>::eigenvalue(const size_type i) const
{
  Assert(state == LAPACKSupport::eigenvalues, ExcState(state));
  Assert(i<n(), ExcIndexRange(i,0,n()));
  return diagonal[i];
}

/*
template <typename number>
TridiagonalMatrix<number>::
{
}

*/

template class TridiagonalMatrix<float>;
template class TridiagonalMatrix<double>;

DEAL_II_NAMESPACE_CLOSE
<commit_msg>Fix undefined behavior in TridiagonalMatrix<commit_after>// ---------------------------------------------------------------------
//
// Copyright (C) 2005 - 2014 by the deal.II authors
//
// This file is part of the deal.II library.
//
// The deal.II library is free software; you can use it, 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.
// The full text of the license can be found in the file LICENSE at
// the top level of the deal.II distribution.
//
// ---------------------------------------------------------------------

#include <deal.II/lac/tridiagonal_matrix.h>
#include <deal.II/lac/vector.h>
#include <deal.II/lac/lapack_templates.h>

DEAL_II_NAMESPACE_OPEN

using namespace LAPACKSupport;

template <typename number>
TridiagonalMatrix<number>::TridiagonalMatrix(
  size_type size,
  bool symmetric)
  :
  diagonal(size, 0.),
  left((symmetric ? 0 : size), 0.),
  right(size, 0.),
  is_symmetric(symmetric),
  state(matrix)
{}

template <typename number>
void
TridiagonalMatrix<number>::reinit(
  size_type size,
  bool symmetric)
{
  is_symmetric = symmetric;
  diagonal.resize(size);
  right.resize(size);
  left.resize(symmetric ? 0 : size);
  state = matrix;
}

template <typename number>
bool
TridiagonalMatrix<number>::all_zero() const
{
  Assert(state == matrix, ExcState(state));

  typename std::vector<number>::const_iterator i;
  typename std::vector<number>::const_iterator e;

  e = diagonal.end();
  for (i=diagonal.begin() ; i != e ; ++i)
    if (*i != 0.) return false;

  e = left.end();
  for (i=left.begin() ; i != e ; ++i)
    if (*i != 0.) return false;

  e = right.end();
  for (i=right.begin() ; i != e ; ++i)
    if (*i != 0.) return false;
  return true;
}

template <typename number>
void
TridiagonalMatrix<number>::vmult (
  Vector<number>       &w,
  const Vector<number> &v,
  const bool            adding) const
{
  Assert(state == matrix, ExcState(state));

  Assert(w.size() == n(), ExcDimensionMismatch(w.size(), n()));
  Assert(v.size() == n(), ExcDimensionMismatch(v.size(), n()));

  if (n()==0) return;

  // The actual loop skips the first
  // and last row
  const size_type e=n()-1;
  // Let iterators point to the first
  // entry of each diagonal
  typename std::vector<number>::const_iterator d = diagonal.begin();
  typename std::vector<number>::const_iterator r = right.begin();
  // The left diagonal starts one
  // later or is equal to the right
  // one for symmetric storage
  typename std::vector<number>::const_iterator l = left.begin();
  if (is_symmetric)
    l = r;
  else
    ++l;

  if (adding)
    {
      // Treat first row separately
      w(0) += (*d) * v(0) + (*r) * v(1);
      ++d;
      ++r;
      // All rows with three entries
      for (size_type i=1; i<e; ++i,++d,++r,++l)
        w(i) += (*l) * v(i-1) + (*d) * v(i) + (*r) * v(i+1);
      // Last row is special again
      w(e) += (*l) * v(e-1) + (*d) * v(e);
    }
  else
    {
      w(0) = (*d) * v(0) + (*r) * v(1);
      ++d;
      ++r;
      for (size_type i=1; i<e; ++i,++d,++r,++l)
        w(i) = (*l) * v(i-1) + (*d) * v(i) + (*r) * v(i+1);
      w(e) = (*l) * v(e-1) + (*d) * v(e);
    }
}

template <typename number>
void
TridiagonalMatrix<number>::vmult_add (
  Vector<number>       &w,
  const Vector<number> &v) const
{
  vmult(w, v, true);
}

template <typename number>
void
TridiagonalMatrix<number>::Tvmult (
  Vector<number>       &w,
  const Vector<number> &v,
  const bool            adding) const
{
  Assert(state == matrix, ExcState(state));

  Assert(w.size() == n(), ExcDimensionMismatch(w.size(), n()));
  Assert(v.size() == n(), ExcDimensionMismatch(v.size(), n()));

  if (n()==0) return;

  const size_type e=n()-1;
  typename std::vector<number>::const_iterator d = diagonal.begin();
  typename std::vector<number>::const_iterator r = right.begin();
  typename std::vector<number>::const_iterator l = left.begin();
  if (is_symmetric)
    l = r;
  else
    ++l;

  if (adding)
    {
      w(0) += (*d) * v(0) + (*l) * v(1);
      ++d;
      ++l;
      for (size_type i=1; i<e; ++i,++d,++r,++l)
        w(i) += (*l) * v(i+1) + (*d) * v(i) + (*r) * v(i-1);
      w(e) += (*d) * v(e) + (*r) * v(e-1);
    }
  else
    {
      w(0) = (*d) * v(0) + (*l) * v(1);
      ++d;
      ++l;
      for (size_type i=1; i<e; ++i,++d,++r,++l)
        w(i) = (*l) * v(i+1) + (*d) * v(i) + (*r) * v(i-1);
      w(e) = (*d) * v(e) + (*r) * v(e-1);
    }
}

template <typename number>
void
TridiagonalMatrix<number>::Tvmult_add (
  Vector<number>       &w,
  const Vector<number> &v) const
{
  Tvmult(w, v, true);
}

template <typename number>
number
TridiagonalMatrix<number>::matrix_scalar_product(
  const Vector<number> &w,
  const Vector<number> &v) const
{
  Assert(state == matrix, ExcState(state));

  const size_type e=n()-1;
  typename std::vector<number>::const_iterator d = diagonal.begin();
  typename std::vector<number>::const_iterator r = right.begin();
  typename std::vector<number>::const_iterator l = left.begin();
  if (is_symmetric)
    l = r;
  else
    ++l;

  number result = w(0) * ((*d) * v(0) + (*r) * v(1));
  ++d;
  ++r;
  for (size_type i=1; i<e; ++i,++d,++r,++l)
    result += w(i) * ((*l) * v(i-1)+ (*d) * v(i)+ (*r) * v(i+1));
  result += w(e) * ((*l) * v(e-1) + (*d) * v(e));
  return result;
}

template <typename number>
number
TridiagonalMatrix<number>::matrix_norm_square(
  const Vector<number> &v) const
{
  return matrix_scalar_product(v,v);
}

template <>
void
TridiagonalMatrix<double>::compute_eigenvalues()
{
#ifdef DEAL_II_WITH_LAPACK
  Assert(state == matrix, ExcState(state));
  Assert(is_symmetric, ExcNotImplemented());

  const int nn = n();
  int info;
  stev (&N, &nn, diagonal.data(), right.data(), nullptr, &one, nullptr, &info);
  Assert(info == 0, ExcInternalError());

  state = LAPACKSupport::eigenvalues;
#else
  Assert(false, ExcNeedsLAPACK());
#endif
}

template <typename number>
number
TridiagonalMatrix<number>::eigenvalue(const size_type i) const
{
  Assert(state == LAPACKSupport::eigenvalues, ExcState(state));
  Assert(i<n(), ExcIndexRange(i,0,n()));
  return diagonal[i];
}

/*
template <typename number>
TridiagonalMatrix<number>::
{
}

*/

template class TridiagonalMatrix<float>;
template class TridiagonalMatrix<double>;

DEAL_II_NAMESPACE_CLOSE
<|endoftext|>


<commit_before>////////////////////////////////////////////////////////////////////////
// This file is part of Grappa, a system for scaling irregular
// applications on commodity clusters.

// Copyright (C) 2010-2014 University of Washington and Battelle
// Memorial Institute. University of Washington authorizes use of this
// Grappa software.

// Grappa is free software: you can redistribute it and/or modify it
// under the terms of the Affero General Public License as published
// by Affero, Inc., either version 1 of the License, or (at your
// option) any later version.

// Grappa 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
// Affero General Public License for more details.

// You should have received a copy of the Affero General Public
// License along with this program. If not, you may obtain one from
// http://www.affero.org/oagpl.html.
////////////////////////////////////////////////////////////////////////

/// useful utilities

#ifndef __COMMON_HPP__
#define __COMMON_HPP__

#include <stdint.h>
#include <iostream>
#include <glog/logging.h>
#include <memory>
#include <algorithm>

using std::unique_ptr;

/// Construct unique_ptr more easily. (to be included in C++1y)
///
/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/// auto m = make_unique<MyClass>(a,5);
/// // equivalent to:
/// auto m = std::unique_ptr<MyClass>(new MyClass(a,5));
/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
template<typename T, typename... Args>
std::unique_ptr<T> make_unique(Args&&... args) {
  return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
}

#include <cstddef>
using std::nullptr_t;

#if defined(__MTA__)
#include <sys/mta_task.h>
#include <machine/runtime.h>
#elif defined(__MACH__)
#include <mach/mach_time.h>
#else
#include <time.h>
#endif

#define BILLION 1000000000
#define MILLION 1000000

/// Use to deprecate old APIs
#define GRAPPA_DEPRECATED __attribute__((deprecated))

namespace Grappa {

  /// Specify whether tasks are bound to the core they're spawned on, or if they can be load-balanced (via work-stealing).
  enum class TaskMode { Bound /*default*/, Unbound };

  /// Specify whether an operation blocks until complete, or returns "immediately".
  enum class SyncMode { Blocking /*default*/, Async };

/// "Universal" wallclock time (works at least for Mac, MTA, and most Linux)
inline double walltime(void) {
#if defined(__MTA__)
	return((double)mta_get_clock(0) / mta_clock_freq());
#elif defined(__MACH__)
	static mach_timebase_info_data_t info;
	mach_timebase_info(&info);
	uint64_t now = mach_absolute_time();
	now *= info.numer;
	now /= info.denom;
	return 1.0e-9 * (double)now;
#else
	struct timespec tp;
#if defined(CLOCK_PROCESS_CPUTIME_ID)
#define CLKID CLOCK_PROCESS_CPUTIME_ID
#elif  defined(CLOCK_REALTIME_ID)
#define CLKID CLOCK_REALTIME_ID
#endif
	clock_gettime(CLOCK_MONOTONIC, &tp);
	return (double)tp.tv_sec + (double)tp.tv_nsec / BILLION;
#endif
}

} // namespace Grappa

 #define GRAPPA_TIME(var, block) \
      do { \
     double _tmptime = Grappa::walltime(); \
     block \
     var = Grappa::walltime()-_tmptime; \
   } while(0)

#define GRAPPA_TIMER(var) \
    for (double _tmpstart = Grappa::walltime(), _tmptime = -1; \
         _tmptime < 0; \
         var = _tmptime = Grappa::walltime() - _tmpstart)

#define GRAPPA_TIME_LOG(name) \
    for (double _tmpstart = Grappa::walltime(), _tmptime = -1; _tmptime < 0; \
         LOG(INFO) << name << ": " << (Grappa::walltime()-_tmpstart), _tmptime = 1)

#define GRAPPA_TIME_REGION(var) \
    for (double _tmpstart = Grappa::walltime(), _tmptime = -1; _tmptime < 0; \
         var += (Grappa::walltime()-_tmpstart), _tmptime = 1)

/// Compute ratio of doubles, returning 0 when divisor is 0
template< typename T, typename U >
static inline double nanless_double_ratio( T x, U y ) {
  return y == 0 ? 0.0 : static_cast<double>(x) / static_cast<double>(y);
}

/// Disable copy constructor and assignment operator.
/// Put this in your class' private declarations.
/// (from google public C++ coding standards)
#define DISALLOW_COPY_AND_ASSIGN( Name )	\
  Name( const Name & );				\
  void operator=( const Name & )

/// Sign extension.
/// From Stanford bit-twiddling hacks.
template <typename T, unsigned B>
inline T signextend(const T x)
{
  struct {T x:B;} s;
  return s.x = x;
}

/// Base 2 log of 32-bit number.
/// Modified from Stanford bit twiddling hacks.
inline unsigned int log2( unsigned int v ) {
  unsigned int r; // result of log2(v) will go here
  unsigned int shift;

  r =     (v > 0xFFFF) << 4; v >>= r;
  shift = (v > 0xFF  ) << 3; v >>= shift; r |= shift;
  shift = (v > 0xF   ) << 2; v >>= shift; r |= shift;
  shift = (v > 0x3   ) << 1; v >>= shift; r |= shift;
  r |= (v >> 1);

  return r;
}

/// Read 64-bit timestamp counter.
#define rdtscll(val) do {					\
    unsigned int __a,__d;					\
    asm volatile("rdtsc" : "=a" (__a), "=d" (__d));		\
    (val) = ((unsigned long)__a) | (((unsigned long)__d)<<32);	\
  } while(0)

/// Read 64-bit timestamp counter.
static inline unsigned long long rdtsc() {
  unsigned long long val;
  rdtscll(val);
  return val;
}

/// OMGWTFBBQ Grappa magic identity function
/// Use this to get a pointer to a template function inside a template function, etc.
template< typename T >
T * Grappa_magic_identity_function(T * t) {
  return t;
}

/// range for block distribution
struct range_t { int64_t start, end; };

inline std::ostream& operator<<(std::ostream& o, const range_t& r) {
  o << "<" << r.start << "," << r.end << ">";
  return o;
}

inline range_t blockDist(int64_t start, int64_t end, int64_t rank, int64_t numBlocks) {
	int64_t numElems = end-start;
	int64_t each     = numElems / numBlocks;
  int64_t remain   = numElems % numBlocks;
	int64_t mynum    = (rank < remain) ? each+1 : each;
	int64_t mystart  = start + ((rank < remain) ? (each+1)*rank : (each+1)*remain + (rank-remain)*each);
	range_t r = { mystart, mystart+mynum };
  return r;
}

struct block_offset_t { int64_t block, offset; };

inline block_offset_t indexToBlock(int64_t index, int64_t numElements, int64_t numBlocks) {
  block_offset_t result;
	int64_t each   = numElements / numBlocks,
          remain = numElements % numBlocks;
	if (index < (each+1)*remain) {
		result = { index / (each+1), index % (each+1) };
	} else {
		index -= (each+1)*remain;
		result = { remain + index/each, index % each };
	}
  // VLOG(1) << "result.block = " << result.block << ", remain = " << remain << ", index = " << index << ", each = " << each;
  return result;
}

#define GET_TYPE(member) BOOST_PP_TUPLE_ELEM(2,0,member)

#define GET_NAME(member) BOOST_PP_TUPLE_ELEM(2,1,member)

#define CAT_EACH(r, data, elem) BOOST_PP_CAT(elem, data)

#define AUTO_CONSTRUCTOR_DETAIL_PARAM(r, data, member) \
GET_TYPE(member) GET_NAME(member)

#define DECL_W_TYPE(r, data, member) \
GET_TYPE(member) GET_NAME(member);

#define AUTO_CONSTRUCTOR_DETAIL_INIT(r, data, member) \
GET_NAME(member) ( GET_NAME(member) )

#define AUTO_CONSTRUCTOR_DETAIL(className, members) \
className(BOOST_PP_SEQ_ENUM(BOOST_PP_SEQ_TRANSFORM( \
AUTO_CONSTRUCTOR_DETAIL_PARAM, BOOST_PP_EMPTY, members))) : \
BOOST_PP_SEQ_ENUM(BOOST_PP_SEQ_TRANSFORM( \
AUTO_CONSTRUCTOR_DETAIL_INIT, BOOST_PP_EMPTY, members)) \
{}

#define AUTO_CONSTRUCTOR(className, members) \
AUTO_CONSTRUCTOR_DETAIL(className, members)

#define AUTO_DECLS(members) \
BOOST_PP_SEQ_FOR_EACH(CAT_EACH, ,BOOST_PP_SEQ_TRANSFORM(DECL_W_TYPE, BOOST_PP_EMPTY, members))

struct Functor {
  void operator()();
};

#define FUNCTOR(name, members) \
struct name : public Functor { \
AUTO_DECLS(members) \
AUTO_CONSTRUCTOR( name, members ) \
name() {} /* default constructor */\
inline void operator()() const; \
}; \
inline void name::operator()() const

// fast pseudo-random number generator 0 to 32768
// http://software.intel.com/en-us/articles/fast-random-number-generator-on-the-intel-pentiumr-4-processor/
static unsigned int g_seed;
inline void fast_srand( int seed ) {
  g_seed = seed;
}
inline int fast_rand() {
  g_seed = (214013*g_seed+2531011);
  return (g_seed>>16)&0x7FFF;
}

namespace Grappa {

  /// @addtogroup Utility
  /// @{

  /// Get string containing name of type.
  template< typename T >
  const char * typename_of( ) {
    // how big is the name of the type of this function?
    static const int size = sizeof(__PRETTY_FUNCTION__);

    // make a modifiable copy that's that big
    static char fn_name[ size ] = { '\0' };

    // copy the name into the modifiable copy
    static const char * strcpy_retval = strncpy( fn_name, __PRETTY_FUNCTION__, size );

    // find the start of the type name
    static const char with[] = "[with T = ";
    static const char * name = strstr( fn_name, with ) + sizeof( with ) - 1;

    // erase the bracket at the end of the string
    static const char erase_bracket = fn_name[size-2] = '\0';

    // whew. return the string we built.
    return name;
  }

  /// Get string containing name of type
  template< typename T >
  const char * typename_of( const T& unused ) {
    return typename_of<T>();
  }

  namespace impl {
    // A small helper for Google logging CHECK_NULL().
    template <typename T>
    inline T* CheckNull(const char *file, int line, const char *names, T* t) {
      if (t != NULL) {
        google::LogMessageFatal(file, line, new std::string(names));
      }
      return t;
    }
  }

#define CHECK_NULL(val)                                              \
  Grappa::impl::CheckNull(__FILE__, __LINE__, "'" #val "' Must be non NULL", (val))

#ifdef NDEBUG
#define DCHECK_NULL(val)                                              \
  Grappa::impl::CheckNull(__FILE__, __LINE__, "'" #val "' Must be non NULL", (val))
#else
#define DCHECK_NULL(val)                        \
  ;
#endif

#define MPI_CHECK( mpi_call )                                           \
  do {                                                                  \
    int retval;                                                         \
    if( (retval = (mpi_call)) != 0 ) {                                  \
      char error_string[MPI_MAX_ERROR_STRING];                          \
      int length;                                                       \
      MPI_Error_string( retval, error_string, &length);                 \
      LOG(FATAL) << "MPI call failed: " #mpi_call ": "                  \
                 << error_string;                                       \
    }                                                                   \
  } while(0)

  /// @}

}

#endif
<commit_msg>add 'min_element' helpers<commit_after>////////////////////////////////////////////////////////////////////////
// This file is part of Grappa, a system for scaling irregular
// applications on commodity clusters.

// Copyright (C) 2010-2014 University of Washington and Battelle
// Memorial Institute. University of Washington authorizes use of this
// Grappa software.

// Grappa is free software: you can redistribute it and/or modify it
// under the terms of the Affero General Public License as published
// by Affero, Inc., either version 1 of the License, or (at your
// option) any later version.

// Grappa 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
// Affero General Public License for more details.

// You should have received a copy of the Affero General Public
// License along with this program. If not, you may obtain one from
// http://www.affero.org/oagpl.html.
////////////////////////////////////////////////////////////////////////

/// useful utilities

#ifndef __COMMON_HPP__
#define __COMMON_HPP__

#include <stdint.h>
#include <iostream>
#include <glog/logging.h>
#include <memory>
#include <algorithm>

using std::unique_ptr;

/// Construct unique_ptr more easily. (to be included in C++1y)
///
/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/// auto m = make_unique<MyClass>(a,5);
/// // equivalent to:
/// auto m = std::unique_ptr<MyClass>(new MyClass(a,5));
/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
template<typename T, typename... Args>
std::unique_ptr<T> make_unique(Args&&... args) {
  return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
}

#include <cstddef>
using std::nullptr_t;

#if defined(__MTA__)
#include <sys/mta_task.h>
#include <machine/runtime.h>
#elif defined(__MACH__)
#include <mach/mach_time.h>
#else
#include <time.h>
#endif

#define BILLION 1000000000
#define MILLION 1000000

/// Use to deprecate old APIs
#define GRAPPA_DEPRECATED __attribute__((deprecated))

namespace Grappa {

  /// Specify whether tasks are bound to the core they're spawned on, or if they can be load-balanced (via work-stealing).
  enum class TaskMode { Bound /*default*/, Unbound };

  /// Specify whether an operation blocks until complete, or returns "immediately".
  enum class SyncMode { Blocking /*default*/, Async };

/// "Universal" wallclock time (works at least for Mac, MTA, and most Linux)
inline double walltime(void) {
#if defined(__MTA__)
	return((double)mta_get_clock(0) / mta_clock_freq());
#elif defined(__MACH__)
	static mach_timebase_info_data_t info;
	mach_timebase_info(&info);
	uint64_t now = mach_absolute_time();
	now *= info.numer;
	now /= info.denom;
	return 1.0e-9 * (double)now;
#else
	struct timespec tp;
#if defined(CLOCK_PROCESS_CPUTIME_ID)
#define CLKID CLOCK_PROCESS_CPUTIME_ID
#elif  defined(CLOCK_REALTIME_ID)
#define CLKID CLOCK_REALTIME_ID
#endif
	clock_gettime(CLOCK_MONOTONIC, &tp);
	return (double)tp.tv_sec + (double)tp.tv_nsec / BILLION;
#endif
}

} // namespace Grappa

 #define GRAPPA_TIME(var, block) \
      do { \
     double _tmptime = Grappa::walltime(); \
     block \
     var = Grappa::walltime()-_tmptime; \
   } while(0)

#define GRAPPA_TIMER(var) \
    for (double _tmpstart = Grappa::walltime(), _tmptime = -1; \
         _tmptime < 0; \
         var = _tmptime = Grappa::walltime() - _tmpstart)

#define GRAPPA_TIME_LOG(name) \
    for (double _tmpstart = Grappa::walltime(), _tmptime = -1; _tmptime < 0; \
         LOG(INFO) << name << ": " << (Grappa::walltime()-_tmpstart), _tmptime = 1)

#define GRAPPA_TIME_REGION(var) \
    for (double _tmpstart = Grappa::walltime(), _tmptime = -1; _tmptime < 0; \
         var += (Grappa::walltime()-_tmpstart), _tmptime = 1)

/// Compute ratio of doubles, returning 0 when divisor is 0
template< typename T, typename U >
static inline double nanless_double_ratio( T x, U y ) {
  return y == 0 ? 0.0 : static_cast<double>(x) / static_cast<double>(y);
}

/// Disable copy constructor and assignment operator.
/// Put this in your class' private declarations.
/// (from google public C++ coding standards)
#define DISALLOW_COPY_AND_ASSIGN( Name )	\
  Name( const Name & );				\
  void operator=( const Name & )

/// Sign extension.
/// From Stanford bit-twiddling hacks.
template <typename T, unsigned B>
inline T signextend(const T x)
{
  struct {T x:B;} s;
  return s.x = x;
}

/// Base 2 log of 32-bit number.
/// Modified from Stanford bit twiddling hacks.
inline unsigned int log2( unsigned int v ) {
  unsigned int r; // result of log2(v) will go here
  unsigned int shift;

  r =     (v > 0xFFFF) << 4; v >>= r;
  shift = (v > 0xFF  ) << 3; v >>= shift; r |= shift;
  shift = (v > 0xF   ) << 2; v >>= shift; r |= shift;
  shift = (v > 0x3   ) << 1; v >>= shift; r |= shift;
  r |= (v >> 1);

  return r;
}

/// Read 64-bit timestamp counter.
#define rdtscll(val) do {					\
    unsigned int __a,__d;					\
    asm volatile("rdtsc" : "=a" (__a), "=d" (__d));		\
    (val) = ((unsigned long)__a) | (((unsigned long)__d)<<32);	\
  } while(0)

/// Read 64-bit timestamp counter.
static inline unsigned long long rdtsc() {
  unsigned long long val;
  rdtscll(val);
  return val;
}

/// OMGWTFBBQ Grappa magic identity function
/// Use this to get a pointer to a template function inside a template function, etc.
template< typename T >
T * Grappa_magic_identity_function(T * t) {
  return t;
}

/// Helper for invoking 'std::min_element' on containers.
template< typename Container, typename Comparator >
auto min_element(const Container& c, Comparator cmp) -> decltype(*c.begin()) {
  return *std::min_element(c.begin(), c.end(), cmp);
}

/// Helper for invoking 'std::min_element' on containers.
template< typename Container, typename Comparator >
auto min_element(const Container& c0, const Container& c1, Comparator cmp) -> decltype(*c0.begin()) {
   auto m0 = min_element(c0, cmp);
   auto m1 = min_element(c1, cmp);
   return cmp(m0,m1) ? m0 : m1;
}

/// Range type that represents the values `[start,end)`.
/// Only valid for types that define `<`, `==`, and `++`.
template< typename T >
struct Range { T start, end; };

/// Helper for invoking 'std::min_element' on a Range.
template< typename T, typename Comparator >
T min_element(Range<T> r, Comparator cmp) {
  T best = r.start;
  for (T e = r.start; e < r.end; e++) {
    if (cmp(e,best)) {
      best = e;
    }
  }
  return best;
}

/// range for block distribution
using range_t = Range<int64_t>;

inline std::ostream& operator<<(std::ostream& o, const range_t& r) {
  o << "<" << r.start << "," << r.end << ">";
  return o;
}

inline range_t blockDist(int64_t start, int64_t end, int64_t rank, int64_t numBlocks) {
	int64_t numElems = end-start;
	int64_t each     = numElems / numBlocks;
  int64_t remain   = numElems % numBlocks;
	int64_t mynum    = (rank < remain) ? each+1 : each;
	int64_t mystart  = start + ((rank < remain) ? (each+1)*rank : (each+1)*remain + (rank-remain)*each);
	range_t r = { mystart, mystart+mynum };
  return r;
}

struct block_offset_t { int64_t block, offset; };

inline block_offset_t indexToBlock(int64_t index, int64_t numElements, int64_t numBlocks) {
  block_offset_t result;
	int64_t each   = numElements / numBlocks,
          remain = numElements % numBlocks;
	if (index < (each+1)*remain) {
		result = { index / (each+1), index % (each+1) };
	} else {
		index -= (each+1)*remain;
		result = { remain + index/each, index % each };
	}
  // VLOG(1) << "result.block = " << result.block << ", remain = " << remain << ", index = " << index << ", each = " << each;
  return result;
}

#define GET_TYPE(member) BOOST_PP_TUPLE_ELEM(2,0,member)

#define GET_NAME(member) BOOST_PP_TUPLE_ELEM(2,1,member)

#define CAT_EACH(r, data, elem) BOOST_PP_CAT(elem, data)

#define AUTO_CONSTRUCTOR_DETAIL_PARAM(r, data, member) \
GET_TYPE(member) GET_NAME(member)

#define DECL_W_TYPE(r, data, member) \
GET_TYPE(member) GET_NAME(member);

#define AUTO_CONSTRUCTOR_DETAIL_INIT(r, data, member) \
GET_NAME(member) ( GET_NAME(member) )

#define AUTO_CONSTRUCTOR_DETAIL(className, members) \
className(BOOST_PP_SEQ_ENUM(BOOST_PP_SEQ_TRANSFORM( \
AUTO_CONSTRUCTOR_DETAIL_PARAM, BOOST_PP_EMPTY, members))) : \
BOOST_PP_SEQ_ENUM(BOOST_PP_SEQ_TRANSFORM( \
AUTO_CONSTRUCTOR_DETAIL_INIT, BOOST_PP_EMPTY, members)) \
{}

#define AUTO_CONSTRUCTOR(className, members) \
AUTO_CONSTRUCTOR_DETAIL(className, members)

#define AUTO_DECLS(members) \
BOOST_PP_SEQ_FOR_EACH(CAT_EACH, ,BOOST_PP_SEQ_TRANSFORM(DECL_W_TYPE, BOOST_PP_EMPTY, members))

struct Functor {
  void operator()();
};

#define FUNCTOR(name, members) \
struct name : public Functor { \
AUTO_DECLS(members) \
AUTO_CONSTRUCTOR( name, members ) \
name() {} /* default constructor */\
inline void operator()() const; \
}; \
inline void name::operator()() const

// fast pseudo-random number generator 0 to 32768
// http://software.intel.com/en-us/articles/fast-random-number-generator-on-the-intel-pentiumr-4-processor/
static unsigned int g_seed;
inline void fast_srand( int seed ) {
  g_seed = seed;
}
inline int fast_rand() {
  g_seed = (214013*g_seed+2531011);
  return (g_seed>>16)&0x7FFF;
}

namespace Grappa {

  /// @addtogroup Utility
  /// @{

  /// Get string containing name of type.
  template< typename T >
  const char * typename_of( ) {
    // how big is the name of the type of this function?
    static const int size = sizeof(__PRETTY_FUNCTION__);

    // make a modifiable copy that's that big
    static char fn_name[ size ] = { '\0' };

    // copy the name into the modifiable copy
    static const char * strcpy_retval = strncpy( fn_name, __PRETTY_FUNCTION__, size );

    // find the start of the type name
    static const char with[] = "[with T = ";
    static const char * name = strstr( fn_name, with ) + sizeof( with ) - 1;

    // erase the bracket at the end of the string
    static const char erase_bracket = fn_name[size-2] = '\0';

    // whew. return the string we built.
    return name;
  }

  /// Get string containing name of type
  template< typename T >
  const char * typename_of( const T& unused ) {
    return typename_of<T>();
  }

  namespace impl {
    // A small helper for Google logging CHECK_NULL().
    template <typename T>
    inline T* CheckNull(const char *file, int line, const char *names, T* t) {
      if (t != NULL) {
        google::LogMessageFatal(file, line, new std::string(names));
      }
      return t;
    }
  }

#define CHECK_NULL(val)                                              \
  Grappa::impl::CheckNull(__FILE__, __LINE__, "'" #val "' Must be non NULL", (val))

#ifdef NDEBUG
#define DCHECK_NULL(val)                                              \
  Grappa::impl::CheckNull(__FILE__, __LINE__, "'" #val "' Must be non NULL", (val))
#else
#define DCHECK_NULL(val)                        \
  ;
#endif

#define MPI_CHECK( mpi_call )                                           \
  do {                                                                  \
    int retval;                                                         \
    if( (retval = (mpi_call)) != 0 ) {                                  \
      char error_string[MPI_MAX_ERROR_STRING];                          \
      int length;                                                       \
      MPI_Error_string( retval, error_string, &length);                 \
      LOG(FATAL) << "MPI call failed: " #mpi_call ": "                  \
                 << error_string;                                       \
    }                                                                   \
  } while(0)

  /// @}

}

#endif
<|endoftext|>


<commit_before><commit_msg>ruler: translate or clear comments in ruler.cxx<commit_after><|endoftext|>


<commit_before><commit_msg>WaE: implicit conversion of literal of type 'int' to 'bool'<commit_after><|endoftext|>


<commit_before><commit_msg>tdf#91840: Default to transparent text background<commit_after><|endoftext|>


<commit_before><commit_msg>fix picture jumping to incorrect X position after dragging<commit_after><|endoftext|>


<commit_before><commit_msg>rendercontext: Don't direct paint the SHOW_IDLE when double-buffering.<commit_after><|endoftext|>


<commit_before>/*
** Copyright 2011-2015 Merethis
**
** This file is part of Centreon Broker.
**
** Centreon Broker is free software: you can redistribute it and/or
** modify it under the terms of the GNU General Public License version 2
** as published by the Free Software Foundation.
**
** Centreon Broker 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 Centreon Broker. If not, see
** <http://www.gnu.org/licenses/>.
*/

#include <cstdlib>
#include <QMutexLocker>
#include <QWaitCondition>
#include "com/centreon/broker/exceptions/msg.hh"
#include "com/centreon/broker/io/events.hh"
#include "com/centreon/broker/io/exceptions/shutdown.hh"
#include "com/centreon/broker/io/raw.hh"
#include "com/centreon/broker/logging/logging.hh"
#include "com/centreon/broker/tcp/stream.hh"

using namespace com::centreon::broker;
using namespace com::centreon::broker::tcp;

/**************************************
*                                     *
*           Public Methods            *
*                                     *
**************************************/

/**
 *  Constructor.
 *
 *  @param[in] sock Socket used by this stream.
 */
stream::stream(misc::shared_ptr<QTcpSocket> sock)
  : _mutex(new QMutex),
    _read_timeout(-1),
    _socket(sock),
    _write_timeout(-1) {}

/**
 *  Constructor.
 *
 *  @param[in] sock  Socket used by this stream.
 *  @param[in] mutex Mutex used by this stream.
 */
stream::stream(
          misc::shared_ptr<QTcpSocket> sock,
          misc::shared_ptr<QMutex> mutex)
  : _mutex(mutex),
    _read_timeout(-1),
    _socket(sock),
    _write_timeout(-1) {}

/**
 *  Destructor.
 */
stream::~stream() {
  QMutexLocker lock(&*_mutex);
  if (!_socket.isNull())
    _socket->close();
}

/**
 *  Read data with timeout.
 *
 *  @param[out] d         Received event if any.
 *  @param[in]  deadline  Timeout in seconds.
 *
 *  @return Respects io::stream::read()'s return value.
 */
bool stream::read(
               misc::shared_ptr<io::data>& d,
               time_t deadline) {
  d.clear();
  QMutexLocker lock(&*_mutex);

  // If data is already available, skip the waitForReadyRead() loop.
  if (_socket->bytesAvailable() <= 0) {
    while (1) {
      if ((deadline != (time_t)-1)
          && (time(NULL) >= deadline)) {
        return (false);
      }
      bool ret;
      if (!(ret = _socket->waitForReadyRead(200))
          // Disconnected socket with no data.
          && (_socket->state()
              == QAbstractSocket::UnconnectedState)
          && (_socket->bytesAvailable() <= 0))
        throw (exceptions::msg() << "TCP stream is disconnected");
      if (ret
          || (_socket->error() != QAbstractSocket::SocketTimeoutError)
          || (_socket->bytesAvailable() > 0))
        break ;
      else {
        QWaitCondition cv;
        cv.wait(&*_mutex, 1);
      }
    }
  }

  char buffer[2048];
  qint64 rb(_socket->read(buffer, sizeof(buffer)));
  if (rb < 0)
    throw (exceptions::msg() << "TCP: error while reading: "
           << _socket->errorString());
  misc::shared_ptr<io::raw> data(new io::raw);
#if QT_VERSION >= 0x040500
  data->append(buffer, rb);
#else
  data->append(QByteArray(buffer, rb));
#endif // Qt version
  d = data;
  return (true);
}

/**
 *  Set read timeout.
 *
 *  @param[in] secs  Timeout in seconds.
 */
void stream::set_read_timeout(int secs) {
  _read_timeout = secs;
  return ;
}

/**
 *  Set write timeout.
 *
 *  @param[in] secs  Write timeout in seconds.
 */
void stream::set_write_timeout(int secs) {
  _write_timeout = secs;
  return ;
}

/**
 *  Write data to the socket.
 *
 *  @param[in] d Data to write.
 *
 *  @return Number of events acknowledged.
 */
unsigned int stream::write(misc::shared_ptr<io::data> const& d) {
  // Check that data exists and should be processed.
  if (d.isNull())
    return (1);

  if (d->type() == io::raw::static_type()) {
    misc::shared_ptr<io::raw> r(d.staticCast<io::raw>());
    logging::debug(logging::low) << "TCP: write request of "
      << r->size() << " bytes";
    QMutexLocker lock(&*_mutex);
    qint64 wb(_socket->write(static_cast<char*>(r->QByteArray::data()),
                             r->size()));
    if ((wb < 0) || (_socket->state() == QAbstractSocket::UnconnectedState))
      throw (exceptions::msg() << "TCP: error while writing: "
             << _socket->errorString());
    if (_socket->waitForBytesWritten(_write_timeout * 1000) == false)
      throw (exceptions::msg() << "TCP: error while sending data: "
             << _socket->errorString());
  }
  return (1);
}
<commit_msg>TCP: fix stream read method.<commit_after>/*
** Copyright 2011-2015 Merethis
**
** This file is part of Centreon Broker.
**
** Centreon Broker is free software: you can redistribute it and/or
** modify it under the terms of the GNU General Public License version 2
** as published by the Free Software Foundation.
**
** Centreon Broker 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 Centreon Broker. If not, see
** <http://www.gnu.org/licenses/>.
*/

#include <cstdlib>
#include <QMutexLocker>
#include <QWaitCondition>
#include "com/centreon/broker/exceptions/msg.hh"
#include "com/centreon/broker/io/events.hh"
#include "com/centreon/broker/io/exceptions/shutdown.hh"
#include "com/centreon/broker/io/raw.hh"
#include "com/centreon/broker/logging/logging.hh"
#include "com/centreon/broker/tcp/stream.hh"

using namespace com::centreon::broker;
using namespace com::centreon::broker::tcp;

/**************************************
*                                     *
*           Public Methods            *
*                                     *
**************************************/

/**
 *  Constructor.
 *
 *  @param[in] sock Socket used by this stream.
 */
stream::stream(misc::shared_ptr<QTcpSocket> sock)
  : _mutex(new QMutex),
    _read_timeout(-1),
    _socket(sock),
    _write_timeout(-1) {}

/**
 *  Constructor.
 *
 *  @param[in] sock  Socket used by this stream.
 *  @param[in] mutex Mutex used by this stream.
 */
stream::stream(
          misc::shared_ptr<QTcpSocket> sock,
          misc::shared_ptr<QMutex> mutex)
  : _mutex(mutex),
    _read_timeout(-1),
    _socket(sock),
    _write_timeout(-1) {}

/**
 *  Destructor.
 */
stream::~stream() {
  QMutexLocker lock(&*_mutex);
  if (!_socket.isNull())
    _socket->close();
}

/**
 *  Read data with timeout.
 *
 *  @param[out] d         Received event if any.
 *  @param[in]  deadline  Timeout in seconds.
 *
 *  @return Respects io::stream::read()'s return value.
 */
bool stream::read(
               misc::shared_ptr<io::data>& d,
               time_t deadline) {
  d.clear();
  QMutexLocker lock(&*_mutex);

  // If data is already available, skip the waitForReadyRead() loop.
  if (_socket->bytesAvailable() <= 0) {
    bool ret(_socket->waitForReadyRead(0));
    while (_socket->bytesAvailable() <= 0) {
      // Request timeout.
      if ((deadline != (time_t)-1)
          && (time(NULL) >= deadline)) {
        return (false);
      }
      // Disconnected socket with no data.
      else if (!ret
          && (_socket->state() == QAbstractSocket::UnconnectedState)
          && (_socket->bytesAvailable() <= 0))
        throw (exceptions::msg() << "TCP stream is disconnected");
      // Got data.
      else if (ret
          || (_socket->error() != QAbstractSocket::SocketTimeoutError)
          || (_socket->bytesAvailable() > 0))
        break ;
      // Wait very little on mutex to allow socket shutdown.
      else {
        QWaitCondition cv;
        cv.wait(&*_mutex, 1);
      }

      // Wait for data.
      _socket->waitForReadyRead(200);
    }
  }

  char buffer[2048];
  qint64 rb(_socket->read(buffer, sizeof(buffer)));
  if (rb < 0)
    throw (exceptions::msg() << "TCP: error while reading: "
           << _socket->errorString());
  misc::shared_ptr<io::raw> data(new io::raw);
#if QT_VERSION >= 0x040500
  data->append(buffer, rb);
#else
  data->append(QByteArray(buffer, rb));
#endif // Qt version
  d = data;
  return (true);
}

/**
 *  Set read timeout.
 *
 *  @param[in] secs  Timeout in seconds.
 */
void stream::set_read_timeout(int secs) {
  _read_timeout = secs;
  return ;
}

/**
 *  Set write timeout.
 *
 *  @param[in] secs  Write timeout in seconds.
 */
void stream::set_write_timeout(int secs) {
  _write_timeout = secs;
  return ;
}

/**
 *  Write data to the socket.
 *
 *  @param[in] d Data to write.
 *
 *  @return Number of events acknowledged.
 */
unsigned int stream::write(misc::shared_ptr<io::data> const& d) {
  // Check that data exists and should be processed.
  if (d.isNull())
    return (1);

  if (d->type() == io::raw::static_type()) {
    misc::shared_ptr<io::raw> r(d.staticCast<io::raw>());
    logging::debug(logging::low) << "TCP: write request of "
      << r->size() << " bytes";
    QMutexLocker lock(&*_mutex);
    qint64 wb(_socket->write(static_cast<char*>(r->QByteArray::data()),
                             r->size()));
    if ((wb < 0) || (_socket->state() == QAbstractSocket::UnconnectedState))
      throw (exceptions::msg() << "TCP: error while writing: "
             << _socket->errorString());
    if (_socket->waitForBytesWritten(_write_timeout * 1000) == false)
      throw (exceptions::msg() << "TCP: error while sending data: "
             << _socket->errorString());
  }
  return (1);
}
<|endoftext|>


<commit_before>#ifndef ALEPH_FUNCTION_HH__
#define ALEPH_FUNCTION_HH__

#include "BoundaryMatrix.hh"

#include <algorithm>
#include <fstream>
#include <iterator>
#include <numeric>
#include <string>
#include <vector>

namespace aleph
{

namespace io
{

template <
  class Index,
  class DataType
> void loadFunction( const std::string& filename,
                     BoundaryMatrix<Index>& boundaryMatrix,
                     std::vector<DataType>& functionValues )
{
  using BoundaryMatrix = BoundaryMatrix<Index>;

  std::ifstream in( filename );

  if( !in )
    throw std::runtime_error( "Unable to open input filename" );

  functionValues.clear();
  functionValues.shrink_to_fit();

  std::copy( std::istream_iterator<DataType>( in ),
             std::istream_iterator<DataType>(),
             std::back_inserter( functionValues ) );

  if( functionValues.empty() )
    throw std::runtime_error( "Unable to load any function values" );

  std::vector<Index> indices( 2*functionValues.size() - 1 );
  std::iota( indices.begin(), indices.end(), Index(0) );

  std::stable_sort( indices.begin(), indices.end(),
             [&functionValues] ( Index i, Index j )
             {
               auto weight = [&] ( Index i )
               {
                 if( i < functionValues.size() )
                   return functionValues.at(i);
                 else
                 {
                   auto l = functionValues.at( i - functionValues.size()     );
                   auto r = functionValues.at( i - functionValues.size() + 1 );

                   return std::max( l, r );
                 }
               };

               return weight(i) < weight(j);
             } );

  std::vector<Index> vertexIndices( functionValues.size() );

  std::iota( vertexIndices.begin(), vertexIndices.end(),
             Index(0) );

  std::sort( vertexIndices.begin(), vertexIndices.end(),
             [&functionValues] ( Index i, Index j )
             {
              return functionValues.at(i) < functionValues.at(j);
             } );

  std::vector<Index> edgeIndices( functionValues.size() - 1 );

  std::iota( edgeIndices.begin(),
             edgeIndices.end(),
             static_cast<Index>( functionValues.size() ) );

  std::sort( edgeIndices.begin(), edgeIndices.end(),
             [&functionValues] ( Index i, Index j )
             {
              auto k = i - functionValues.size();
              auto l = j - functionValues.size();

              return functionValues.at(k) < functionValues.at(l);
             } );

  boundaryMatrix.setNumColumns( 2 * functionValues.size() - 1 );

  for( Index j = 0; j < static_cast<Index>( functionValues.size() ); j++ )
    boundaryMatrix.clearColumn( j );
}

}

}

#endif
<commit_msg>Filling boundary matrix for 1D function loading<commit_after>#ifndef ALEPH_FUNCTION_HH__
#define ALEPH_FUNCTION_HH__

#include "BoundaryMatrix.hh"

#include <algorithm>
#include <fstream>
#include <iterator>
#include <numeric>
#include <string>
#include <vector>

namespace aleph
{

namespace io
{

template <
  class Index,
  class DataType
> void loadFunction( const std::string& filename,
                     BoundaryMatrix<Index>& boundaryMatrix,
                     std::vector<DataType>& functionValues )
{
  using BoundaryMatrix = BoundaryMatrix<Index>;

  std::ifstream in( filename );

  if( !in )
    throw std::runtime_error( "Unable to open input filename" );

  functionValues.clear();
  functionValues.shrink_to_fit();

  std::copy( std::istream_iterator<DataType>( in ),
             std::istream_iterator<DataType>(),
             std::back_inserter( functionValues ) );

  if( functionValues.empty() )
    throw std::runtime_error( "Unable to load any function values" );

  std::vector<Index> indices( 2*functionValues.size() - 1 );
  std::iota( indices.begin(), indices.end(), Index(0) );

  std::stable_sort( indices.begin(), indices.end(),
             [&functionValues] ( Index i, Index j )
             {
               auto weight = [&] ( Index i )
               {
                 if( i < functionValues.size() )
                   return functionValues.at(i);
                 else
                 {
                   auto l = functionValues.at( i - functionValues.size()     );
                   auto r = functionValues.at( i - functionValues.size() + 1 );

                   return std::max( l, r );
                 }
               };

               return weight(i) < weight(j);
             } );

  for( Index j = 0; j < static_cast<Index>( indices.size() ); j++ )
  {
    auto&& index = indices.at(j);

    if( index < functionValues.size() )
      boundaryMatrix.clearColumn( j );
    else
    {
      std::vector<Index> vertexIndices = { index, index + 1 };

      boundaryMatrix.setColumn(j,
                               vertexIndices.begin(), vertexIndices.end() );
    }
  }
}

}

}

#endif
<|endoftext|>


<commit_before><commit_msg>Drop unused declaration<commit_after><|endoftext|>


<commit_before>/*
** Copyright 2011-2012 Merethis
**
** This file is part of Centreon Broker.
**
** Centreon Broker is free software: you can redistribute it and/or
** modify it under the terms of the GNU General Public License version 2
** as published by the Free Software Foundation.
**
** Centreon Broker 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 Centreon Broker. If not, see
** <http://www.gnu.org/licenses/>.
*/

#include <cassert>
#include <cstdlib>
#include <QMutexLocker>
#include <QWaitCondition>
#include "com/centreon/broker/exceptions/msg.hh"
#include "com/centreon/broker/io/exceptions/shutdown.hh"
#include "com/centreon/broker/io/raw.hh"
#include "com/centreon/broker/tcp/stream.hh"

using namespace com::centreon::broker;
using namespace com::centreon::broker::tcp;

/**************************************
*                                     *
*           Public Methods            *
*                                     *
**************************************/

/**
 *  Constructor.
 *
 *  @param[in] sock Socket used by this stream.
 */
stream::stream(misc::shared_ptr<QTcpSocket> sock)
  : _mutex(new QMutex),
    _process_in(true),
    _process_out(true),
    _socket(sock),
    _timeout(-1) {}

/**
 *  Constructor.
 *
 *  @param[in] sock  Socket used by this stream.
 *  @param[in] mutex Mutex used by this stream.
 */
stream::stream(
          misc::shared_ptr<QTcpSocket> sock,
          misc::shared_ptr<QMutex> mutex)
  : _mutex(mutex),
    _process_in(true),
    _process_out(true),
    _socket(sock),
    _timeout(-1) {}

/**
 *  Destructor.
 */
stream::~stream() {
  QMutexLocker lock(&*_mutex);
  if (!_socket.isNull())
    _socket->close();
}

/**
 *  Enable or disable event processing.
 *
 *  @param[in] in  Set to true to enable input event processing.
 *  @param[in] out Set to true to enable output event processing.
 */
void stream::process(bool in, bool out) {
  _process_in = in;
  _process_out = out;
  return ;
}

/**
 *  Read data from the socket.
 *
 *  @param[out] d Data read.
 */
void stream::read(misc::shared_ptr<io::data>& d) {
  d.clear();
  QMutexLocker lock(&*_mutex);
  bool ret;
  while (1) {
    if (!_process_in)
      throw (io::exceptions::shutdown(!_process_in, !_process_out)
               << "TCP stream is shutdown");
    if (!(ret = _socket->waitForReadyRead(
                  (_timeout == -1)
                  ? 200
                  : _timeout))
            // Standalone socket.
        && ((_timeout != -1)
            // Disconnected socket with no data.
            || ((_socket->state()
                 == QAbstractSocket::UnconnectedState)
                && (_socket->bytesAvailable() <= 0))))
      throw (exceptions::msg() << "TCP stream is disconnected");
    if (ret
        || (_socket->error() != QAbstractSocket::SocketTimeoutError)
        || (_socket->bytesAvailable() > 0))
      break ;
    else {
      QWaitCondition cv;
      cv.wait(&*_mutex, 1);
    }
  }

  char buffer[2048];
  qint64 rb(_socket->read(buffer, sizeof(buffer)));
  if (rb < 0)
    throw (exceptions::msg() << "TCP: error while reading: "
             << _socket->errorString());
  misc::shared_ptr<io::raw> data(new io::raw);
#if QT_VERSION >= 0x040500
  data->append(buffer, rb);
#else
  data->append(QByteArray(buffer, rb));
#endif // Qt version
  d = data.staticCast<io::data>();
  return ;
}

/**
 *  Set connection timeout.
 *
 *  @param[in] msecs Timeout in ms.
 */
void stream::set_timeout(int msecs) {
  _timeout = msecs;
  return ;
}

/**
 *  Write data to the socket.
 *
 *  @param[in] d Data to write.
 */
void stream::write(misc::shared_ptr<io::data> const& d) {
  // Raw type.
  static QString const raw_type("com::centreon::broker::io::raw");

  // Check that data exists and should be processed.
  if (!_process_out)
    throw (io::exceptions::shutdown(!_process_in, !_process_out)
             << "TCP stream is shutdown");
  if (d.isNull())
    return ;

  if (d->type() == raw_type) {
    misc::shared_ptr<io::raw> r(d.staticCast<io::raw>());
    QMutexLocker lock(&*_mutex);
    qint64 wb(_socket->write(static_cast<char*>(r->QByteArray::data()),
                             r->size()));
    if ((wb < 0) || (_socket->state() != QAbstractSocket::UnconnectedState))
      throw (exceptions::msg() << "TCP: error while writing: "
               << _socket->errorString());
    _socket->waitForBytesWritten(-1);
  }
  return ;
}

/**************************************
*                                     *
*           Private Methods           *
*                                     *
**************************************/

/**
 *  @brief Copy constructor.
 *
 *  Any call to this constructor will result in a call to abort().
 *
 *  @param[in] s Object to copy.
 */
stream::stream(stream const& s) : io::stream(s) {
  assert(!"TCP stream is not copyable");
  abort();
}

/**
 *  @brief Assignment operator.
 *
 *  Any call to this method will result in a call to abort().
 *
 *  @param[in] s Object to copy.
 *
 *  @return This object.
 */
stream& stream::operator=(stream const& s) {
  (void)s;
  assert(!"TCP stream is not copyable");
  abort();
  return (*this);
}
<commit_msg>Handle TLS connection failures.<commit_after>/*
** Copyright 2011-2012 Merethis
**
** This file is part of Centreon Broker.
**
** Centreon Broker is free software: you can redistribute it and/or
** modify it under the terms of the GNU General Public License version 2
** as published by the Free Software Foundation.
**
** Centreon Broker 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 Centreon Broker. If not, see
** <http://www.gnu.org/licenses/>.
*/

#include <cassert>
#include <cstdlib>
#include <QMutexLocker>
#include <QWaitCondition>
#include "com/centreon/broker/exceptions/msg.hh"
#include "com/centreon/broker/io/exceptions/shutdown.hh"
#include "com/centreon/broker/io/raw.hh"
#include "com/centreon/broker/tcp/stream.hh"

using namespace com::centreon::broker;
using namespace com::centreon::broker::tcp;

/**************************************
*                                     *
*           Public Methods            *
*                                     *
**************************************/

/**
 *  Constructor.
 *
 *  @param[in] sock Socket used by this stream.
 */
stream::stream(misc::shared_ptr<QTcpSocket> sock)
  : _mutex(new QMutex),
    _process_in(true),
    _process_out(true),
    _socket(sock),
    _timeout(-1) {}

/**
 *  Constructor.
 *
 *  @param[in] sock  Socket used by this stream.
 *  @param[in] mutex Mutex used by this stream.
 */
stream::stream(
          misc::shared_ptr<QTcpSocket> sock,
          misc::shared_ptr<QMutex> mutex)
  : _mutex(mutex),
    _process_in(true),
    _process_out(true),
    _socket(sock),
    _timeout(-1) {}

/**
 *  Destructor.
 */
stream::~stream() {
  QMutexLocker lock(&*_mutex);
  if (!_socket.isNull())
    _socket->close();
}

/**
 *  Enable or disable event processing.
 *
 *  @param[in] in  Set to true to enable input event processing.
 *  @param[in] out Set to true to enable output event processing.
 */
void stream::process(bool in, bool out) {
  _process_in = in;
  _process_out = out;
  return ;
}

/**
 *  Read data from the socket.
 *
 *  @param[out] d Data read.
 */
void stream::read(misc::shared_ptr<io::data>& d) {
  d.clear();
  QMutexLocker lock(&*_mutex);
  bool ret;
  while (1) {
    if (!_process_in)
      throw (io::exceptions::shutdown(!_process_in, !_process_out)
               << "TCP stream is shutdown");
    if (!(ret = _socket->waitForReadyRead(
                  (_timeout == -1)
                  ? 200
                  : _timeout))
            // Standalone socket.
        && ((_timeout != -1)
            // Disconnected socket with no data.
            || ((_socket->state()
                 == QAbstractSocket::UnconnectedState)
                && (_socket->bytesAvailable() <= 0))))
      throw (exceptions::msg() << "TCP stream is disconnected");
    if (ret
        || (_socket->error() != QAbstractSocket::SocketTimeoutError)
        || (_socket->bytesAvailable() > 0))
      break ;
    else {
      QWaitCondition cv;
      cv.wait(&*_mutex, 1);
    }
  }

  char buffer[2048];
  qint64 rb(_socket->read(buffer, sizeof(buffer)));
  if (rb < 0)
    throw (exceptions::msg() << "TCP: error while reading: "
             << _socket->errorString());
  misc::shared_ptr<io::raw> data(new io::raw);
#if QT_VERSION >= 0x040500
  data->append(buffer, rb);
#else
  data->append(QByteArray(buffer, rb));
#endif // Qt version
  d = data.staticCast<io::data>();
  return ;
}

/**
 *  Set connection timeout.
 *
 *  @param[in] msecs Timeout in ms.
 */
void stream::set_timeout(int msecs) {
  _timeout = msecs;
  return ;
}

/**
 *  Write data to the socket.
 *
 *  @param[in] d Data to write.
 */
void stream::write(misc::shared_ptr<io::data> const& d) {
  // Raw type.
  static QString const raw_type("com::centreon::broker::io::raw");

  // Check that data exists and should be processed.
  if (!_process_out)
    throw (io::exceptions::shutdown(!_process_in, !_process_out)
             << "TCP stream is shutdown");
  if (d.isNull())
    return ;

  if (d->type() == raw_type) {
    misc::shared_ptr<io::raw> r(d.staticCast<io::raw>());
    QMutexLocker lock(&*_mutex);
    qint64 wb(_socket->write(static_cast<char*>(r->QByteArray::data()),
                             r->size()));
    if ((wb < 0) || (_socket->state() == QAbstractSocket::UnconnectedState))
      throw (exceptions::msg() << "TCP: error while writing: "
             << _socket->errorString());
    _socket->waitForBytesWritten(-1);
  }
  return ;
}

/**************************************
*                                     *
*           Private Methods           *
*                                     *
**************************************/

/**
 *  @brief Copy constructor.
 *
 *  Any call to this constructor will result in a call to abort().
 *
 *  @param[in] s Object to copy.
 */
stream::stream(stream const& s) : io::stream(s) {
  assert(!"TCP stream is not copyable");
  abort();
}

/**
 *  @brief Assignment operator.
 *
 *  Any call to this method will result in a call to abort().
 *
 *  @param[in] s Object to copy.
 *
 *  @return This object.
 */
stream& stream::operator=(stream const& s) {
  (void)s;
  assert(!"TCP stream is not copyable");
  abort();
  return (*this);
}
<|endoftext|>


<commit_before><commit_msg>avoid out-of-bounds access<commit_after><|endoftext|>


<commit_before>// Copyright (c) 2012 Roman Neuhauser
// Distributed under the MIT license (see LICENSE file)
// vim: sw=2 sts=2 ts=2 fdm=marker cms=\ //\ %s

// shared_ptr
#include <memory>

#include <iostream>
#include <istream>
#include <ostream>
#include <fstream>
#include <string>
#include <vector>

#define EX_OK           0       /* successful termination */
#define EX_USAGE        64      /* command line usage error */
#define EX_DATAERR      65      /* data format error */
#define EX_NOINPUT      66      /* cannot open input */

#include "boost/ref.hpp"
#include "boost/foreach.hpp"
#include "boost/format.hpp"
#include "boost/date_time/gregorian/gregorian.hpp"
#include "boost/regex.hpp"

#include "iniphile/input.hpp"
#include "iniphile/ast.hpp"
#include "iniphile/output.hpp"

#define foreach BOOST_FOREACH

using std::shared_ptr;

using std::cin;
using std::cerr;
using std::endl;
using std::ios;
using std::getline;
using std::ostream;
using std::ifstream;
using std::ofstream;
using std::string;
using std::vector;

using boost::cref;
using boost::format;
using namespace boost::gregorian;
using boost::regex;
using boost::smatch;

namespace
{

struct expand_sink // {{{
{
  expand_sink(string const &prefix, date const &today)
  : prefix(prefix)
  , today(today)
  {}
private:
  string const &prefix;
  date const &today;
public:
  string
  operator()(smatch const &expando) const
  {
    auto sexpando = expando.str();
    if (sexpando == "%D") return to_iso_extended_string(today);
    if (sexpando == "%P") return prefix;
    return "LOGDEMUX-BUG";
  }
}; // }}}

class rule
{
public:
  rule(string const &prefix, string const &match, string const &sink, bool final, ostream &diag) // {{{
  : sink(sink)
  , prefix(prefix)
  , final(final)
  , pat(match, regex::perl)
  , opened_on()
  , os()
  , diag(diag)
  {
  } // }}}
  bool
  handle(date const &today, string const &line) // {{{
  {
    if (!regex_search(line, pat))
      return false;
    if (opened_on != today)
      reopen(today);
    os << line << endl;
    return final;
  } // }}}
private:
  string const sink;
  string const prefix;
  bool final;
  regex pat;
  date opened_on;
  ofstream os;
  ostream &diag;

  void
  reopen(date const &today) // {{{
  {
    if (os.is_open()) os.close();
    os.clear();
    auto fname = expand(sink, today);
    os.open(fname.c_str(), ios::app | ios::binary);
    if (os.fail())
      diag << "failed to open " << fname << endl;
    opened_on = today;
  } // }}}
  string
  expand(string const &fmt, date const &d) const // {{{
  {
    return regex_replace(
      fmt
    , regex("%[DP]\\>")
    , cref(expand_sink(prefix, d))
    );
  } // }}}
};

class ruleset
{
public:
  ruleset(iniphile::ast::node const &ini, string const &prefix, ostream &diag)
  {
    foreach (auto const &rname, iniphile::get(ini, "rules.order", vector<string>()))
      rules.push_back(shared_ptr<rule>(new rule(
        prefix
      , iniphile::get(ini, rname + ".match", string(""))
      , iniphile::get(ini, rname + ".sink", string(""))
      , iniphile::get(ini, rname + ".final", false)
      , diag
      )));
  }
  void
  handle(date const &now, string const &line) // {{{
  {
    foreach (auto &r, rules)
      if (r->handle(now, line))
        break;
  } // }}}
private:
  vector<shared_ptr<rule>> rules;
};

date
today() // {{{
{
  return day_clock::local_day();
} // }}}

template<class Fmt>
int
complain(int exitcode, Fmt msg)
{
  cerr << msg << endl;
  return exitcode;
}

}

int
main(int argc, char **argv)
{
  string self = argc > 0 ? argv[0] : "logdemux";
  string bself = regex_replace(
    self
  , regex("^(.*/)?([^/]+)(.exe)?$", regex::perl)
  , "$2"
  );

  if (argc < 3)
    return complain(
      EX_USAGE
    , format("usage: %1% rules prefix") % bself
    );

  string ini = argv[1];
  string prefix = argv[2];
  ifstream sini;
  sini.open(ini);
  if (sini.fail())
    return complain(
      EX_NOINPUT
    , format("%1%: rules file '%2%' missing") % bself % ini
    );

  auto cfg = iniphile::parse(sini, cerr);
  sini.close();
  if (!cfg)
    return complain(
      EX_DATAERR
    , format("%1%: rules file '%2%' broken") % bself % ini
    );

  auto afg(iniphile::normalize(*cfg));

  if (iniphile::get(afg, "rules.order", string("")) == "")
    return complain(
      EX_DATAERR
    , format("%1%: no rules.order in '%2%'") % bself % ini
    );

  ruleset rules(afg, prefix, cerr);

  string line;
  while (cin.good()) {
    while (getline(cin, line)) {
      rules.handle(today(), line);
    }
  }

  return EX_OK;
}
<commit_msg>logdemux.cpp needed more foldmarkers<commit_after>// Copyright (c) 2012 Roman Neuhauser
// Distributed under the MIT license (see LICENSE file)
// vim: sw=2 sts=2 ts=2 fdm=marker cms=\ //\ %s

// shared_ptr
#include <memory>

#include <iostream>
#include <istream>
#include <ostream>
#include <fstream>
#include <string>
#include <vector>

#define EX_OK           0       /* successful termination */
#define EX_USAGE        64      /* command line usage error */
#define EX_DATAERR      65      /* data format error */
#define EX_NOINPUT      66      /* cannot open input */

#include "boost/ref.hpp"
#include "boost/foreach.hpp"
#include "boost/format.hpp"
#include "boost/date_time/gregorian/gregorian.hpp"
#include "boost/regex.hpp"

#include "iniphile/input.hpp"
#include "iniphile/ast.hpp"
#include "iniphile/output.hpp"

#define foreach BOOST_FOREACH

using std::shared_ptr;

using std::cin;
using std::cerr;
using std::endl;
using std::ios;
using std::getline;
using std::ostream;
using std::ifstream;
using std::ofstream;
using std::string;
using std::vector;

using boost::cref;
using boost::format;
using namespace boost::gregorian;
using boost::regex;
using boost::smatch;

namespace
{

struct expand_sink // {{{
{
  expand_sink(string const &prefix, date const &today)
  : prefix(prefix)
  , today(today)
  {}
private:
  string const &prefix;
  date const &today;
public:
  string
  operator()(smatch const &expando) const
  {
    auto sexpando = expando.str();
    if (sexpando == "%D") return to_iso_extended_string(today);
    if (sexpando == "%P") return prefix;
    return "LOGDEMUX-BUG";
  }
}; // }}}

class rule
// {{{
{
public:
  rule(string const &prefix, string const &match, string const &sink, bool final, ostream &diag) // {{{
  : sink(sink)
  , prefix(prefix)
  , final(final)
  , pat(match, regex::perl)
  , opened_on()
  , os()
  , diag(diag)
  {
  } // }}}
  bool
  handle(date const &today, string const &line) // {{{
  {
    if (!regex_search(line, pat))
      return false;
    if (opened_on != today)
      reopen(today);
    os << line << endl;
    return final;
  } // }}}
private:
  string const sink;
  string const prefix;
  bool final;
  regex pat;
  date opened_on;
  ofstream os;
  ostream &diag;

  void
  reopen(date const &today) // {{{
  {
    if (os.is_open()) os.close();
    os.clear();
    auto fname = expand(sink, today);
    os.open(fname.c_str(), ios::app | ios::binary);
    if (os.fail())
      diag << "failed to open " << fname << endl;
    opened_on = today;
  } // }}}
  string
  expand(string const &fmt, date const &d) const // {{{
  {
    return regex_replace(
      fmt
    , regex("%[DP]\\>")
    , cref(expand_sink(prefix, d))
    );
  } // }}}
}; // }}}

class ruleset
// {{{
{
public:
  ruleset(iniphile::ast::node const &ini, string const &prefix, ostream &diag) // {{{
  {
    foreach (auto const &rname, iniphile::get(ini, "rules.order", vector<string>()))
      rules.push_back(shared_ptr<rule>(new rule(
        prefix
      , iniphile::get(ini, rname + ".match", string(""))
      , iniphile::get(ini, rname + ".sink", string(""))
      , iniphile::get(ini, rname + ".final", false)
      , diag
      )));
  } // }}}
  void
  handle(date const &now, string const &line) // {{{
  {
    foreach (auto &r, rules)
      if (r->handle(now, line))
        break;
  } // }}}
private:
  vector<shared_ptr<rule>> rules;
}; // }}}

date
today() // {{{
{
  return day_clock::local_day();
} // }}}

template<class Fmt>
int
complain(int exitcode, Fmt msg) // {{{
{
  cerr << msg << endl;
  return exitcode;
} // }}}

}

int
main(int argc, char **argv)
{
  string self = argc > 0 ? argv[0] : "logdemux";
  string bself = regex_replace(
    self
  , regex("^(.*/)?([^/]+)(.exe)?$", regex::perl)
  , "$2"
  );

  if (argc < 3)
    return complain(
      EX_USAGE
    , format("usage: %1% rules prefix") % bself
    );

  string ini = argv[1];
  string prefix = argv[2];
  ifstream sini;
  sini.open(ini);
  if (sini.fail())
    return complain(
      EX_NOINPUT
    , format("%1%: rules file '%2%' missing") % bself % ini
    );

  auto cfg = iniphile::parse(sini, cerr);
  sini.close();
  if (!cfg)
    return complain(
      EX_DATAERR
    , format("%1%: rules file '%2%' broken") % bself % ini
    );

  auto afg(iniphile::normalize(*cfg));

  if (iniphile::get(afg, "rules.order", string("")) == "")
    return complain(
      EX_DATAERR
    , format("%1%: no rules.order in '%2%'") % bself % ini
    );

  ruleset rules(afg, prefix, cerr);

  string line;
  while (cin.good()) {
    while (getline(cin, line)) {
      rules.handle(today(), line);
    }
  }

  return EX_OK;
}
<|endoftext|>


<commit_before>// Copyright 2017 Jose M. Arbos
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <experimental/filesystem>
#include <fstream>
#include <iostream>

#include "config.h"
#include "yaml-cpp/yaml.h"

using namespace std;
using namespace std::experimental::filesystem::v1;

static const char* nwn2_dirs[] = {
    "C:\\Program Files\\Atari\\Neverwinter Nights 2",
    "C:\\Program Files (x86)\\Atari\\Neverwinter Nights 2",
    "C:\\GOG Games\\Neverwinter Nights 2 Complete"};

static void create_config_file(const char *filename)
{
	ofstream out(filename);
	out << "# (Optional) Directory where NWN2 is installed.\n";
	out << "# nwn2_home: C:\\Program Files\\Atari\\Neverwinter Nights 2\n";
}

static void find_nwn2_home(Config& config, YAML::Node& config_file)
{
	if (config_file["nwn2_home"]) {
		auto nwn2_home = config_file["nwn2_home"].as<string>("");
		if (exists(nwn2_home))
			config.nwn2_home = nwn2_home;
		else
			cout << "ERROR: The NWN2 installation directory specified in config.yml doesn't exist: \"" << nwn2_home << "\"\n";
	}
	else {
		for (unsigned i = 0; i < sizeof(nwn2_dirs) / sizeof(char*); ++i)
			if (exists(nwn2_dirs[i]))
				config.nwn2_home = nwn2_dirs[i];
	}
}

Config::Config(const char *filename)
{
	if (!exists(filename))
		create_config_file(filename);

	try {
		auto config_file = YAML::LoadFile(filename);
		if (!config_file) {
			cout << "ERROR: Cannot open " << filename << endl;
			return;
		}

		find_nwn2_home(*this, config_file);
	}
	catch (...) {
		cout << "ERROR: Cannot open " << filename << ": It's ill-formed." << endl;
		return;
	}

	if (nwn2_home.empty()) {
		cout << "Cannot find a NWN2 installation directory. Edit the "
			"config.yml file and put the directory where NWN2 is "
			"installed.\n";
	}
}<commit_msg>Search NWN2 install dir in Windows registry<commit_after>// Copyright 2017 Jose M. Arbos
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <experimental/filesystem>
#include <fstream>
#include <iostream>

#ifdef _WIN32
#include <windows.h>
#endif

#include "config.h"
#include "yaml-cpp/yaml.h"

using namespace std;
using namespace std::experimental::filesystem::v1;

static void create_config_file(const char *filename)
{
	ofstream out(filename);
	out << "# (Optional) Directory where NWN2 is installed.\n";
	out << "# nwn2_home: C:\\Program Files\\Atari\\Neverwinter Nights 2\n";
}

static bool find_nwn2_home_in_config(Config& config, YAML::Node& config_file)
{
	if (config_file["nwn2_home"]) {
		auto nwn2_home = config_file["nwn2_home"].as<string>("");

		if (exists(nwn2_home))
			config.nwn2_home = nwn2_home;
		else
			cout << "ERROR: The NWN2 installation directory specified in config.yml doesn't exist: \"" << nwn2_home << "\"\n";

		return true;
	}

	return false;
}

static bool find_nwn2_home_in_list(Config& config)
{
	static const char* nwn2_dirs[] = {
		"C:\\Program Files\\Atari\\Neverwinter Nights 2",
		"C:\\Program Files (x86)\\Atari\\Neverwinter Nights 2",
		"C:\\GOG Games\\Neverwinter Nights 2 Complete" };

	for (size_t i = 0; i < size(nwn2_dirs); ++i) {
		if (exists(nwn2_dirs[i])) {
			config.nwn2_home = nwn2_dirs[i];
			return true;
		}
	}

	return false;
}

static bool find_nwn2_home_in_registry(Config& config)
{
#ifdef _WIN32
	HKEY key;

	LSTATUS status = RegOpenKeyExA(HKEY_LOCAL_MACHINE,
		"SOFTWARE\\Obsidian\\NWN 2\\Neverwinter",
		REG_OPTION_RESERVED,
#ifdef _WIN64
		KEY_QUERY_VALUE | KEY_WOW64_32KEY,
#else
		KEY_QUERY_VALUE,
#endif
		&key);

	if (status != NO_ERROR)
		return false;

	char path[MAX_PATH + 1];
	DWORD path_size = MAX_PATH;

	static const char* names[] = {
		"Location", // Steam & GOG NWN2
		"Path" // Retail NWN2
	};

	for (size_t i = 0; i < size(names); ++i) {
		status = RegQueryValueExA(
			key, names[i], NULL, NULL,
			reinterpret_cast<LPBYTE>(path), &path_size);

		if (status == NO_ERROR) {
			// A registry value may not have been stored with the proper
			// terminating null character. Ensure the path is null-terminated.
			if (path_size == 0 || path[path_size - 1] != '\0')
				path[path_size] = '\0';

			if (exists(path)) {
				RegCloseKey(key);
				config.nwn2_home = path;
				return true;
			}
		}
	}

	RegCloseKey(key);
#endif

	return false;
}

static void find_nwn2_home(Config& config, YAML::Node& config_file)
{
	if (find_nwn2_home_in_config(config, config_file))
		return;
	else if (find_nwn2_home_in_registry(config))
		return;
	else if (find_nwn2_home_in_list(config))
		return;

	cout << "ERROR: Cannot find a NWN2 installation directory. Edit the "
		"config.yml file and put the directory where NWN2 is "
		"installed.\n";
}

Config::Config(const char *filename)
{
	if (!exists(filename))
		create_config_file(filename);

	try {
		auto config_file = YAML::LoadFile(filename);
		if (!config_file) {
			cout << "ERROR: Cannot open " << filename << endl;
			return;
		}

		find_nwn2_home(*this, config_file);
	}
	catch (...) {
		cout << "ERROR: Cannot open " << filename << ": It's ill-formed." << endl;
		return;
	}
}<|endoftext|>