<commit_before>#include <iostream>

#include "occa.hpp"

int main(int argc, char **argv){

  int entries = 5;

  float *a  = new float[entries];
  float *b  = new float[entries];
  float *ab = new float[entries];

  for(int i = 0; i < entries; ++i){
    a[i]  = (float) i;
    b[i]  = (float) (1 - i);
    ab[i] = 0;
  }

  int int_size = sizeof(int);
  int pointer_size = sizeof(void*);
  int size_t_size = sizeof(size_t);
  int long_size = sizeof(long);
  std::cout << "Hello from addVectors: "
      << " integer size: " << int_size
	  << " long size: " << long_size
      << " pointer size: " << pointer_size
	  << " size_t size: " << size_t_size << std::endl;

  // occa::availableDevices<occa::OpenCL>();

  std::string mode = "OpenMP";

<<<<<<< HEAD
  std::string mode = "OpenMP";
=======
>>>>>>> 4faa48ec859b34cebcf89c9c3d1df76f8c94cd5b
  int platformID = 0;
  int deviceID   = 0;

  occa::device device;
  occa::kernel addVectors;
  occa::memory o_a, o_b, o_ab;

  device.setup(mode, platformID, deviceID);

  o_a  = device.malloc(entries*sizeof(float));
  o_b  = device.malloc(entries*sizeof(float));
  o_ab = device.malloc(entries*sizeof(float));

  char *occaDir_ = getenv("OCCA_DIR");
  std::string addVectors_occa("addVectors.occa");
  if(occaDir_ != NULL) {
	  std::string occaDir(occaDir_);
	  addVectors_occa = occaDir + "/examples/addVectors/" + addVectors_occa;
  }

  addVectors = device.buildKernelFromSource(addVectors_occa.c_str(),
                                            "addVectors");

  int dims = 1;
  int itemsPerGroup(2);
  int groups((entries + itemsPerGroup - 1)/itemsPerGroup);

  addVectors.setWorkingDims(dims, itemsPerGroup, groups);

  o_a.copyFrom(a);
  o_b.copyFrom(b);

  addVectors(entries, o_a, o_b, o_ab);

  o_ab.copyTo(ab);

  for(int i = 0; i < 5; ++i)
    std::cout << i << ": " << ab[i] << '\n';

  delete [] a;
  delete [] b;
  delete [] ab;

  addVectors.free();
  o_a.free();
  o_b.free();
  o_ab.free();
  device.free();

}
<commit_msg>b4 merge<commit_after>#include <iostream>

#include "occa.hpp"

int main(int argc, char **argv){

  int entries = 5;

  float *a  = new float[entries];
  float *b  = new float[entries];
  float *ab = new float[entries];

  for(int i = 0; i < entries; ++i){
    a[i]  = (float) i;
    b[i]  = (float) (1 - i);
    ab[i] = 0;
  }

  int int_size = sizeof(int);
  int pointer_size = sizeof(void*);
  int size_t_size = sizeof(size_t);
  int long_size = sizeof(long);
  std::cout << "Hello from addVectors: "
      << " integer size: " << int_size
	  << " long size: " << long_size
      << " pointer size: " << pointer_size
	  << " size_t size: " << size_t_size << std::endl;

  // occa::availableDevices<occa::OpenCL>();

  std::string mode = "OpenMP";
  int platformID = 0;
  int deviceID   = 0;

  occa::device device;
  occa::kernel addVectors;
  occa::memory o_a, o_b, o_ab;

  device.setup(mode, platformID, deviceID);

  o_a  = device.malloc(entries*sizeof(float));
  o_b  = device.malloc(entries*sizeof(float));
  o_ab = device.malloc(entries*sizeof(float));

  char *occaDir_ = getenv("OCCA_DIR");
  std::string addVectors_occa("addVectors.occa");
  if(occaDir_ != NULL) {
	  std::string occaDir(occaDir_);
	  addVectors_occa = occaDir + "/examples/addVectors/" + addVectors_occa;
  }

  //device.setCompilerEnvScript(

  addVectors = device.buildKernelFromSource(addVectors_occa.c_str(),
                                            "addVectors");

  int dims = 1;
  int itemsPerGroup(2);
  int groups((entries + itemsPerGroup - 1)/itemsPerGroup);

  addVectors.setWorkingDims(dims, itemsPerGroup, groups);

  o_a.copyFrom(a);
  o_b.copyFrom(b);

  addVectors(entries, o_a, o_b, o_ab);

  o_ab.copyTo(ab);

  for(int i = 0; i < 5; ++i)
    std::cout << i << ": " << ab[i] << '\n';

  delete [] a;
  delete [] b;
  delete [] ab;

  addVectors.free();
  o_a.free();
  o_b.free();
  o_ab.free();
  device.free();

}
<|endoftext|>


<commit_before>#pragma once
// blas_utils.hpp :  include file containing templated utilities to work with vectors and matrices
//
// Copyright (C) 2017-2018 Stillwater Supercomputing, Inc.
//
// This file is part of the universal numbers project, which is released under an MIT Open Source license.
#include <random>

// initialize a vector
template<typename Vector, typename Scalar>
void init(Vector& x, const Scalar& value) {
	for (size_t i = 0; i < x.size(); ++i) x[i] = value;
}

// These functions print matrices and vectors in a nice format
template<typename Ty>
void printMatrix(std::ostream& ostr, const std::string& name, const std::vector<Ty>& m) {
	size_t d = size_t(std::sqrt(m.size()));
	ostr << "Matrix: " << name << " is " << d << "x" << d << std::endl;
	std::streamsize prec = ostr.precision();
	ostr << std::setprecision(17);
	for (size_t i = 0; i<d; ++i) {
		for (size_t j = 0; j<d; ++j) std::cout << std::setw(20) << m[i*d + j] << " ";
		ostr << std::endl;
	}
	ostr << std::setprecision(prec);
}

template<typename Ty>
void printVector(std::ostream& ostr, const std::string& name, const std::vector<Ty>& v) {
	size_t d = v.size();
	ostr << "Vector: " << name << " is of size " << d << " elements" << std::endl;
	std::streamsize prec = ostr.precision();
	ostr << std::setprecision(17);
	for (size_t j = 0; j<d; ++j) std::cout << std::setw(20) << v[j] << " ";
	ostr << std::setprecision(prec) << std::endl;
}

// print a vector
template<typename vector_T>
void print(std::ostream& ostr, size_t n, vector_T& x, size_t incx = 1) {
	size_t cnt, ix;
	for (cnt = 0, ix = 0; cnt < n && ix < x.size(); ++cnt, ix += incx) {
		cnt == 0 ? ostr << "[" << x[ix] : ostr << ", " << x[ix];
	}
	ostr << "]";
}

// generate a vector of random permutations around 1.0
// contraction is a right shift of the mantissa causing smaller fluctuations
template<typename element_T>
void randomVectorFillAroundOneEPS(size_t n, std::vector<element_T>& vec, size_t contraction = 6) {
	// Use random_device to generate a seed for Mersenne twister engine.
	std::random_device rd{};
	// Use Mersenne twister engine to generate pseudo-random numbers.
	std::mt19937 engine{ rd() };
	// "Filter" MT engine's output to generate pseudo-random double values,
	// **uniformly distributed** on the closed interval [0, 1].
	// (Note that the range is [inclusive, inclusive].)
	std::uniform_real_distribution<double> dist{ 0.0, 1.0 };
	// Pattern to generate pseudo-random number.
	// double rnd_value = dist(engine);

	double scale = std::pow(2, double(0.0-contraction));
	for (size_t i = 0; i < n; ++i) {
		// generate random value between [-0.5, 0.5], and contract
		double eps = (dist(engine) - 0.5) * scale;
		double v = 1.0 + eps;
		vec[i] = (element_T)v;
	}
}

// generate a vector of random permutations around 1.0
// contraction is a right shift of the mantissa causing smaller fluctuations
template<typename element_T>
void randomVectorFillAroundZeroEPS(size_t n, std::vector<element_T>& vec, size_t contraction = 6) {
	// Use random_device to generate a seed for Mersenne twister engine.
	std::random_device rd{};
	// Use Mersenne twister engine to generate pseudo-random numbers.
	std::mt19937 engine{ rd() };
	// "Filter" MT engine's output to generate pseudo-random double values,
	// **uniformly distributed** on the closed interval [0, 1].
	// (Note that the range is [inclusive, inclusive].)
	std::uniform_real_distribution<double> dist{ 0.0, 1.0 };
	// Pattern to generate pseudo-random number.
	// double rnd_value = dist(engine);

	double scale = std::pow(2, double(0.0 - contraction));
	for (size_t i = 0; i < n; ++i) {
		// generate random value between [-0.5, 0.5], and contract
		double eps = (dist(engine) - 0.5) * scale;
		double v = 0.0 + eps;
		vec[i] = (element_T)v;
	}
}

// print a sampling of the provided vector
// if samples is set to 0, all elements of the vector are printed
template<typename element_T>
void sampleVector(std::string vec_name, std::vector<element_T>& vec, uint32_t start = 0, uint32_t incr = 1, uint32_t nrSamples = 0) {
	std::cout << "Vector sample is: " << '\n';
	std::streamsize prec = std::cout.precision();
	if (nrSamples) {
		uint32_t printed = 0;
		for (uint32_t i = start; i < vec.size(); i += incr) {
			if (printed < nrSamples) {
				printed++;
				std::cout << vec_name << "[" << std::setw(3) << i << "] = " << std::setprecision(15) << vec[i] << '\n';
			}
		}
	}
	else {
		for (uint32_t i = start; i < vec.size(); i += incr) {
			std::cout << vec_name << "[" << std::setw(3) << i << "] = " << std::setprecision(15) << vec[i] << '\n';
		}
	}
	std::cout << std::setprecision(prec) << std::endl;
}

template<typename Scalar>
void GenerateHilbertMatrix(int N, std::vector<Scalar>& m) {
	assert(N*N == m.size());
	for (int i = 1; i <= N; ++i) {
		for (int j = 1; j <= N; ++j) {
			m[(i-1)*N + (j-1)] = Scalar(1.0) / Scalar(i + j - 1);
		}
	}
}

uint64_t factorial(uint64_t n) {
	return (n == 0 || n == 1) ? 1 : factorial(n - 1) * n;
}

// (n over k) = n! / k!(n-k)!
template<typename Scalar>
Scalar BinomialCoefficient(uint64_t n, uint64_t k) {
	Scalar numerator = Scalar(factorial(n));
	Scalar denominator = Scalar(factorial(k)*factorial(n - k));
	Scalar coef = numerator / denominator;
//	std::cout << numerator << " / " << denominator << " = " << coef << std::endl;
	if (coef * denominator != numerator) std::cout << "FAIL: (" << n << " over " << k << ")" << std::endl;
	return coef;
}

template<typename Scalar>
void GenerateHilbertMatrixInverse(int N, std::vector<Scalar>& m) {
	assert(N*N == m.size());
	for (int i = 1; i <= N; ++i) {
		for (int j = 1; j <= N; ++j) {
			Scalar sign = ((i + j) % 2) ? Scalar(-1) : Scalar(1);
			Scalar factor1 = Scalar(i + j - 1);
			Scalar factor2 = BinomialCoefficient<Scalar>(N + i - 1, N - j);
			Scalar factor3 = BinomialCoefficient<Scalar>(N + j - 1, N - i);
			Scalar factor4 = BinomialCoefficient<Scalar>(i + j - 2, i - 1);
			m[(i - 1)*N + (j - 1)] = Scalar(sign * factor1 * factor2 * factor3 * factor4 * factor4);
		}
	}
}<commit_msg>Scaling the Hilbert matrix to make the presentation easier to judge<commit_after>#pragma once
// blas_utils.hpp :  include file containing templated utilities to work with vectors and matrices
//
// Copyright (C) 2017-2018 Stillwater Supercomputing, Inc.
//
// This file is part of the universal numbers project, which is released under an MIT Open Source license.
#include <random>

// initialize a vector
template<typename Vector, typename Scalar>
void init(Vector& x, const Scalar& value) {
	for (size_t i = 0; i < x.size(); ++i) x[i] = value;
}

// These functions print matrices and vectors in a nice format
template<typename Ty>
void printMatrix(std::ostream& ostr, const std::string& name, const std::vector<Ty>& m) {
	size_t d = size_t(std::sqrt(m.size()));
	ostr << "Matrix: " << name << " is " << d << "x" << d << std::endl;
	std::streamsize prec = ostr.precision();
	ostr << std::setprecision(17);
	for (size_t i = 0; i<d; ++i) {
		for (size_t j = 0; j<d; ++j) std::cout << std::setw(20) << m[i*d + j] << " ";
		ostr << std::endl;
	}
	ostr << std::setprecision(prec);
}

template<typename Ty>
void printVector(std::ostream& ostr, const std::string& name, const std::vector<Ty>& v) {
	size_t d = v.size();
	ostr << "Vector: " << name << " is of size " << d << " elements" << std::endl;
	std::streamsize prec = ostr.precision();
	ostr << std::setprecision(17);
	for (size_t j = 0; j<d; ++j) std::cout << std::setw(20) << v[j] << " ";
	ostr << std::setprecision(prec) << std::endl;
}

// print a vector
template<typename vector_T>
void print(std::ostream& ostr, size_t n, vector_T& x, size_t incx = 1) {
	size_t cnt, ix;
	for (cnt = 0, ix = 0; cnt < n && ix < x.size(); ++cnt, ix += incx) {
		cnt == 0 ? ostr << "[" << x[ix] : ostr << ", " << x[ix];
	}
	ostr << "]";
}

// generate a vector of random permutations around 1.0
// contraction is a right shift of the mantissa causing smaller fluctuations
template<typename element_T>
void randomVectorFillAroundOneEPS(size_t n, std::vector<element_T>& vec, size_t contraction = 6) {
	// Use random_device to generate a seed for Mersenne twister engine.
	std::random_device rd{};
	// Use Mersenne twister engine to generate pseudo-random numbers.
	std::mt19937 engine{ rd() };
	// "Filter" MT engine's output to generate pseudo-random double values,
	// **uniformly distributed** on the closed interval [0, 1].
	// (Note that the range is [inclusive, inclusive].)
	std::uniform_real_distribution<double> dist{ 0.0, 1.0 };
	// Pattern to generate pseudo-random number.
	// double rnd_value = dist(engine);

	double scale = std::pow(2, double(0.0-contraction));
	for (size_t i = 0; i < n; ++i) {
		// generate random value between [-0.5, 0.5], and contract
		double eps = (dist(engine) - 0.5) * scale;
		double v = 1.0 + eps;
		vec[i] = (element_T)v;
	}
}

// generate a vector of random permutations around 1.0
// contraction is a right shift of the mantissa causing smaller fluctuations
template<typename element_T>
void randomVectorFillAroundZeroEPS(size_t n, std::vector<element_T>& vec, size_t contraction = 6) {
	// Use random_device to generate a seed for Mersenne twister engine.
	std::random_device rd{};
	// Use Mersenne twister engine to generate pseudo-random numbers.
	std::mt19937 engine{ rd() };
	// "Filter" MT engine's output to generate pseudo-random double values,
	// **uniformly distributed** on the closed interval [0, 1].
	// (Note that the range is [inclusive, inclusive].)
	std::uniform_real_distribution<double> dist{ 0.0, 1.0 };
	// Pattern to generate pseudo-random number.
	// double rnd_value = dist(engine);

	double scale = std::pow(2, double(0.0 - contraction));
	for (size_t i = 0; i < n; ++i) {
		// generate random value between [-0.5, 0.5], and contract
		double eps = (dist(engine) - 0.5) * scale;
		double v = 0.0 + eps;
		vec[i] = (element_T)v;
	}
}

// print a sampling of the provided vector
// if samples is set to 0, all elements of the vector are printed
template<typename element_T>
void sampleVector(std::string vec_name, std::vector<element_T>& vec, uint32_t start = 0, uint32_t incr = 1, uint32_t nrSamples = 0) {
	std::cout << "Vector sample is: " << '\n';
	std::streamsize prec = std::cout.precision();
	if (nrSamples) {
		uint32_t printed = 0;
		for (uint32_t i = start; i < vec.size(); i += incr) {
			if (printed < nrSamples) {
				printed++;
				std::cout << vec_name << "[" << std::setw(3) << i << "] = " << std::setprecision(15) << vec[i] << '\n';
			}
		}
	}
	else {
		for (uint32_t i = start; i < vec.size(); i += incr) {
			std::cout << vec_name << "[" << std::setw(3) << i << "] = " << std::setprecision(15) << vec[i] << '\n';
		}
	}
	std::cout << std::setprecision(prec) << std::endl;
}

template<typename Scalar>
void GenerateHilbertMatrix(int N, std::vector<Scalar>& m) {
	assert(N*N == m.size());
	for (int i = 1; i <= N; ++i) {
		for (int j = 1; j <= N; ++j) {
			m[(i-1)*N + (j-1)] = Scalar(5*7*9) / Scalar(i + j - 1);
		}
	}
}

uint64_t factorial(uint64_t n) {
	return (n == 0 || n == 1) ? 1 : factorial(n - 1) * n;
}

// (n over k) = n! / k!(n-k)!
template<typename Scalar>
Scalar BinomialCoefficient(uint64_t n, uint64_t k) {
	Scalar numerator = Scalar(factorial(n));
	Scalar denominator = Scalar(factorial(k)*factorial(n - k));
	Scalar coef = numerator / denominator;
//	std::cout << numerator << " / " << denominator << " = " << coef << std::endl;
	if (coef * denominator != numerator) std::cout << "FAIL: (" << n << " over " << k << ")" << std::endl;
	return coef;
}

template<typename Scalar>
void GenerateHilbertMatrixInverse(int N, std::vector<Scalar>& m) {
	assert(N*N == m.size());
	for (int i = 1; i <= N; ++i) {
		for (int j = 1; j <= N; ++j) {
			Scalar sign = ((i + j) % 2) ? Scalar(-1) : Scalar(1);
			Scalar factor1 = Scalar(i + j - 1);
			Scalar factor2 = BinomialCoefficient<Scalar>(N + i - 1, N - j);
			Scalar factor3 = BinomialCoefficient<Scalar>(N + j - 1, N - i);
			Scalar factor4 = BinomialCoefficient<Scalar>(i + j - 2, i - 1);
			m[(i - 1)*N + (j - 1)] = Scalar(sign * factor1 * factor2 * factor3 * factor4 * factor4);
		}
	}
}<|endoftext|>


<commit_before>//
// Created by tag on 03/01/17.
//

#include "networktools.h"

/* A simple server in the internet domain using TCP
   The port number is passed as an argument */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>

void error(const char *msg)
{
    perror(msg);
    exit(1);
}

int sockfd=-1, newsockfd=-1, portno;
socklen_t clilen;
char buffer[256];
struct sockaddr_in serv_addr, cli_addr;
int n;
int tour=0;

int init_connection( char *port)
{

     if (argc < 2) {
         fprintf(stderr,"ERROR, no port provided\n");
         exit(1);
     }
     portno = atoi(port);

	 sockfd = socket(AF_INET, SOCK_STREAM, 0);
     if (sockfd < 0)
         error("ERROR opening\n");

     //if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (int *)0 +1, sizeof(int)) < 0)
     //	error("setsockopt(SO_REUSEADDR) failed");
     bzero((char *) &serv_addr, sizeof(serv_addr));

     serv_addr.sin_family = AF_INET;
     serv_addr.sin_addr.s_addr = INADDR_ANY;
     serv_addr.sin_port = htons(portno);
	 if (bind(sockfd, (struct sockaddr *) &serv_addr,
              sizeof(serv_addr)) < 0)
              	error("ERROR on binding\n");

     return 0;
}

char* wait_connection(char *reponse, int longueur){
     tour++;
     usleep(20000);

     listen(sockfd,5);
     clilen = sizeof(cli_addr);
     newsockfd = accept(sockfd,
             (struct sockaddr *) &cli_addr,
             &clilen);
     if (newsockfd < 0){
         printf("ERROR on accept\n");
         return NULL;
     }

     bzero(buffer,256);
     n = read(newsockfd,buffer,255);

     //printf("Here is the message: %s\n",buffer);
     //sprintf(reponse, "I got your message %d",tour);
     n = write(newsockfd,reponse,longueur);

     close(newsockfd);

     return buffer;
}

void close_connection(){
     close(sockfd);
}
<commit_msg>correction d'un bug<commit_after>//
// Created by tag on 03/01/17.
//

#include "networktools.h"

/* A simple server in the internet domain using TCP
   The port number is passed as an argument */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>

void error(const char *msg)
{
    perror(msg);
    exit(1);
}

int sockfd=-1, newsockfd=-1, portno;
socklen_t clilen;
char buffer[256];
struct sockaddr_in serv_addr, cli_addr;
int n;
int tour=0;

int init_connection( char *port)
{

     portno = atoi(port);

	 sockfd = socket(AF_INET, SOCK_STREAM, 0);
     if (sockfd < 0)
         error("ERROR opening\n");

     //if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (int *)0 +1, sizeof(int)) < 0)
     //	error("setsockopt(SO_REUSEADDR) failed");
     bzero((char *) &serv_addr, sizeof(serv_addr));

     serv_addr.sin_family = AF_INET;
     serv_addr.sin_addr.s_addr = INADDR_ANY;
     serv_addr.sin_port = htons(portno);
	 if (bind(sockfd, (struct sockaddr *) &serv_addr,
              sizeof(serv_addr)) < 0)
              	error("ERROR on binding\n");

     return 0;
}

char* wait_connection(char *reponse, int longueur){
     tour++;
     usleep(20000);

     listen(sockfd,5);
     clilen = sizeof(cli_addr);
     newsockfd = accept(sockfd,
             (struct sockaddr *) &cli_addr,
             &clilen);
     if (newsockfd < 0){
         printf("ERROR on accept\n");
         return NULL;
     }

     bzero(buffer,256);
     n = read(newsockfd,buffer,255);

     //printf("Here is the message: %s\n",buffer);
     //sprintf(reponse, "I got your message %d",tour);
     n = write(newsockfd,reponse,longueur);

     close(newsockfd);

     return buffer;
}

void close_connection(){
     close(sockfd);
}
<|endoftext|>


<commit_before>#pragma once

#include <agency/detail/config.hpp>
#include <agency/detail/factory.hpp>
#include <agency/detail/optional.hpp>
#include <agency/detail/index_cast.hpp>
#include <agency/detail/shape_cast.hpp>
#include <utility>
#include <type_traits>

namespace agency
{
namespace detail
{

template<class Index, class Function, class Shape>
struct project_index_and_invoke
{
  using index_type = Index;
  using shape_type = Shape;

  using projected_index_type = decltype(
    detail::project_index(std::declval<index_type>(), std::declval<shape_type>())
  );

  using projected_shape_type  = decltype(
    project_shape(std::declval<shape_type>())
  );

  Function             f_;
  shape_type           shape_;
  projected_shape_type projected_shape_;

  __AGENCY_ANNOTATION
  project_index_and_invoke(const Function& f, shape_type shape, projected_shape_type projected_shape)
    : f_(f),
      shape_(shape),
      projected_shape_(projected_shape)
  {}

  // this type stores the result of f_(index)
  template<class T>
  struct value_and_index
  {
    T value;
    projected_index_type index;
  };

  template<class T>
  __AGENCY_ANNOTATION
  value_and_index<typename std::decay<T>::type> make_value_and_index(T&& value, projected_index_type idx)
  {
    return value_and_index<typename std::decay<T>::type>{std::forward<T>(value), idx};
  }

  // this is the type of result returned by f_
  template<class... Args>
  using result_of_function_t = typename std::result_of<Function(projected_index_type,Args...)>::type;

  template<class T>
  using void_or_optionally_value_and_index_t = typename std::conditional<
    std::is_void<T>::value,
    void,
    optional<value_and_index<T>>
  >::type;

  // this is the type of result returned by this functor
  template<class... Args>
  using result_t = void_or_optionally_value_and_index_t<result_of_function_t<Args...>>;

  // when f_(idx) has no result, we just return void
  template<class... Args,
           class = typename std::enable_if<
             std::is_void<
               result_of_function_t<Args&&...>
             >::value
           >::type
          >
  __AGENCY_ANNOTATION
  void impl(const Index& idx, Args&&... args)
  {
    auto projected_idx = detail::project_index(idx, shape_);

    if(projected_idx < projected_shape_)
    {
      f_(projected_idx, std::forward<Args>(args)...);
    }
  }

  // when f_(idx) has a result, we optionally return f_'s result and the index,
  // but only at points where f_(idx) is defined
  template<class... Args,
           class = typename std::enable_if<
             !std::is_void<
               result_of_function_t<Args&&...>
             >::value
           >::type
          >
  __AGENCY_ANNOTATION
  result_t<Args&&...>
    impl(const Index& idx, Args&&... args)
  {
    auto projected_idx = detail::project_index(idx, shape_);

    if(projected_idx < projected_shape_)
    {
      return make_value_and_index(f_(projected_idx, std::forward<Args>(args)...), projected_idx);
    }

    return nullopt;
  }

  // this overload implements the functor for then_execute() when the dependency future is void
  template<class T>
  __AGENCY_ANNOTATION
  result_t<T&>
    operator()(const Index& idx, T& outer_shared_parameter, unit)
  {
    return impl(idx, outer_shared_parameter);
  }

  // this overload implements the functor for then_execute() when the dependency future is not void
  template<class T1, class T2>
  __AGENCY_ANNOTATION
  result_t<T1&,T2&>
    operator()(const Index& idx, T1& past_parameter, T2& outer_shared_parameter, unit)
  {
    return impl(idx, past_parameter, outer_shared_parameter);
  }
};

template<class Index, class Function, class Shape>
__AGENCY_ANNOTATION
project_index_and_invoke<Index,Function,Shape>
  make_project_index_and_invoke(Function f,
                                Shape higher_dimensional_shape,
                                typename project_index_and_invoke<Index,Function,Shape>::projected_shape_type lower_dimensional_shape)
{
  return project_index_and_invoke<Index,Function,Shape>{f,higher_dimensional_shape,lower_dimensional_shape};
}

} // end detail
} // end agency

<commit_msg>Make project_index_and_invoke's member functions const<commit_after>#pragma once

#include <agency/detail/config.hpp>
#include <agency/detail/factory.hpp>
#include <agency/detail/optional.hpp>
#include <agency/detail/index_cast.hpp>
#include <agency/detail/shape_cast.hpp>
#include <utility>
#include <type_traits>

namespace agency
{
namespace detail
{

template<class Index, class Function, class Shape>
struct project_index_and_invoke
{
  using index_type = Index;
  using shape_type = Shape;

  using projected_index_type = decltype(
    detail::project_index(std::declval<index_type>(), std::declval<shape_type>())
  );

  using projected_shape_type  = decltype(
    project_shape(std::declval<shape_type>())
  );

  mutable Function     f_;
  shape_type           shape_;
  projected_shape_type projected_shape_;

  __AGENCY_ANNOTATION
  project_index_and_invoke(const Function& f, shape_type shape, projected_shape_type projected_shape)
    : f_(f),
      shape_(shape),
      projected_shape_(projected_shape)
  {}

  // this type stores the result of f_(index)
  template<class T>
  struct value_and_index
  {
    T value;
    projected_index_type index;
  };

  template<class T>
  __AGENCY_ANNOTATION
  value_and_index<typename std::decay<T>::type> make_value_and_index(T&& value, projected_index_type idx) const
  {
    return value_and_index<typename std::decay<T>::type>{std::forward<T>(value), idx};
  }

  // this is the type of result returned by f_
  template<class... Args>
  using result_of_function_t = typename std::result_of<Function(projected_index_type,Args...)>::type;

  template<class T>
  using void_or_optionally_value_and_index_t = typename std::conditional<
    std::is_void<T>::value,
    void,
    optional<value_and_index<T>>
  >::type;

  // this is the type of result returned by this functor
  template<class... Args>
  using result_t = void_or_optionally_value_and_index_t<result_of_function_t<Args...>>;

  // when f_(idx) has no result, we just return void
  template<class... Args,
           class = typename std::enable_if<
             std::is_void<
               result_of_function_t<Args&&...>
             >::value
           >::type
          >
  __AGENCY_ANNOTATION
  void impl(const Index& idx, Args&&... args) const
  {
    auto projected_idx = detail::project_index(idx, shape_);

    if(projected_idx < projected_shape_)
    {
      f_(projected_idx, std::forward<Args>(args)...);
    }
  }

  // when f_(idx) has a result, we optionally return f_'s result and the index,
  // but only at points where f_(idx) is defined
  template<class... Args,
           class = typename std::enable_if<
             !std::is_void<
               result_of_function_t<Args&&...>
             >::value
           >::type
          >
  __AGENCY_ANNOTATION
  result_t<Args&&...>
    impl(const Index& idx, Args&&... args) const
  {
    auto projected_idx = detail::project_index(idx, shape_);

    if(projected_idx < projected_shape_)
    {
      return make_value_and_index(f_(projected_idx, std::forward<Args>(args)...), projected_idx);
    }

    return nullopt;
  }

  // this overload implements the functor for then_execute() when the dependency future is void
  template<class T>
  __AGENCY_ANNOTATION
  result_t<T&>
    operator()(const Index& idx, T& outer_shared_parameter, unit) const
  {
    return impl(idx, outer_shared_parameter);
  }

  // this overload implements the functor for then_execute() when the dependency future is not void
  template<class T1, class T2>
  __AGENCY_ANNOTATION
  result_t<T1&,T2&>
    operator()(const Index& idx, T1& past_parameter, T2& outer_shared_parameter, unit) const
  {
    return impl(idx, past_parameter, outer_shared_parameter);
  }
};

template<class Index, class Function, class Shape>
__AGENCY_ANNOTATION
project_index_and_invoke<Index,Function,Shape>
  make_project_index_and_invoke(Function f,
                                Shape higher_dimensional_shape,
                                typename project_index_and_invoke<Index,Function,Shape>::projected_shape_type lower_dimensional_shape)
{
  return project_index_and_invoke<Index,Function,Shape>{f,higher_dimensional_shape,lower_dimensional_shape};
}

} // end detail
} // end agency

<|endoftext|>


<commit_before>/* ==================================================================================================
# Copyright 2014 vpon, Inc.
# --------------------------------------------------------------------------------------------------
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this work except in compliance with the License.
# You may obtain a copy of the License in the LICENSE file, or 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 <unistd.h>
#include <stdio.h>
#include <string>
#include <vector>
#include <fstream>
#include "producer/capture.h"
#include "agent/els.h"
#include "public/daemonize.h"
#include "err/err.h"
#include "log/log.h"

using std::string;
using std::vector;
using std::ofstream;
using log2esd::producer::Capture;
using log2esd::agent::ELS;
using log2esd::pub::Daemon;
using log2esd::log::FileHandle;
using log2esd::ERR_ELS_PUSH_DOC_NO_RESPONSE;

struct AppConfig {
  string host_;
  string log_home_;
  string level_;
  string daemon_log_;
  string pid_file_;
  string written_file_;
  string rm_;
  string index_prefix_;
  int lines_;
  int line_size_;
  int interval_;
  int divisor_;
  AppConfig() : host_("localhost:9200"), log_home_("./log"), level_("INFO"), daemon_log_("/data/logs/log2esd/"), pid_file_(""), written_file_(".written_file.txt"), rm_("yes"), index_prefix_(""), lines_(2), line_size_(2048), interval_(10), divisor_(2) {}
};

void Help(char ** argv) {
  printf("##########################################\n\n");
  printf("Usage: %s -p <file.ini>"
         "\n"
         "Options:\n"
         "-h <192.168.0.1:9200> els service (default: localhost:9200)\n"
         "-s <app_logs> directory of app's logs (default: ./log)\n"
         "-x <index_prefix> index prefix (default: empty)\n"
         "-v <index_divisor> index divisor, must be (2,3,4,6,8,12,24) (default: 2)\n"
         "-n <lines> lines of read once (default: 2)\n"
         "-b <line_size> size of line (default: 2048)\n"
         "-i <interval> waiting interval (default: 10)\n"
         "-w <daemon log> directory of daemon logs (default: /data/logs/log2esd)\n"
         "-l <level> level of daemon logs (default: INFO)\n"
         "-r <yes/no> remove log file after send all datas (default yes)\n"
         "-d <pid_file> daemonize log2esd\n"
         "-H Show this help\n"
         "\n",
         argv[0]
         );
  printf("##########################################\n\n");
}

void GetParam(AppConfig * conf, int argc, char ** argv) {
  char opt;
  while (-1 != (opt = ::getopt(argc, argv, "h:s:x:v:d:n:b:i:w:l:r:H"))) {
    switch (opt) {
    case 'h':
      if (NULL != optarg) {
        conf->host_ = optarg;
      }
      break;

    case 's':
      if (NULL != optarg) {
        conf->log_home_ = optarg;
      }
      break;

    case 'x':
      if (NULL != optarg) {
        conf->index_prefix_ = optarg;
      }
      break;

    case 'v':
      if (NULL != optarg) {
        conf->divisor_ = ::atoi(optarg);
      }
      break;

    case 'd':
      if (NULL != optarg) {
        conf->pid_file_ = optarg;
      }
      break;

    case 'n':
      if (NULL != optarg) {
        conf->lines_ = ::atoi(optarg);
      }
      break;

    case 'b':
      if (NULL != optarg) {
        conf->line_size_ = ::atoi(optarg);
      }
      break;

    case 'i':
      if (NULL != optarg) {
        conf->interval_ = ::atoi(optarg);
      }
      break;

    case 'w':
      if (NULL != optarg) {
        conf->daemon_log_ = optarg;
      }
      break;

    case 'l':
      if (NULL != optarg) {
        conf->level_ = optarg;
      }
      break;

    case 'r':
      if (NULL != optarg) {
        conf->rm_ = optarg;
      }
      break;

    case 'H':
    default:
      Help(argv);
      ::_exit(0);
      break;
    }
  }

  printf("###########################################\n");
  printf("host:%s\n", conf->host_.c_str());
  printf("log home:%s\n", conf->log_home_.c_str());
  printf("index prefix:%s\n", conf->index_prefix_.c_str());
  printf("index divisor:%d\n", conf->divisor_);
  printf("read lines:%d\n", conf->lines_);
  printf("line size:%d\n", conf->line_size_);
  printf("waiting interval:%d\n", conf->interval_);
  printf("deamon log:%s\n", conf->daemon_log_.c_str());
  printf("log level:%s\n", conf->level_.c_str());
  printf("pid file:%s\n", conf->pid_file_.c_str());
  printf("remove log file: %s\n", conf->rm_.c_str());
  printf("###########################################\n");

  return;
}

int ReadLines(Capture & capture, int lines, char * block, int max_size) {
  int used = 0;
  while (lines) {
    int unused = max_size - used;
    int cmd_size = capture.EncodeCmd(block + used, unused);
    if (0 >= cmd_size) {
      break;
    }
    used += cmd_size;
    unused = max_size - used;
    int size = capture.GetLine(block + used, unused);
    if (0 < size) {
      used += size;
      unused = max_size - used;

      lines--;
    } else {
      used -= cmd_size;

      break;
    }
  }

  return used;
}

int PushToELS(ELS & els, const string & data) {
  return els.PushDocs(data);
}

int RetryPush(ELS & els, const string & data, int times, int interval) {
  while (times) {
    if (0 == PushToELS(els, data)) {
      return 0;
    }

    --times;

    LOG_WARN("retry push to els times " << times);

    ::sleep(interval);
  }

  return -1;
}

void LogToErrDoc(const string & log_home, const string & json) {
  uint now = ::time(NULL);
  ::srand(now);
  int random = ::rand()%1000;
  char file[1024] = {0};
  ::snprintf(file, sizeof(file) - 1, ".written_error_%u_%d.json", now, random);
  const string path = log_home + "/" + file;
  int result = ::access(path.c_str(), F_OK);
  if (0 == result) {
    LOG_WARN("agent log to err doc file name is exists");
  }

  ofstream os(path.c_str());
  if (os.is_open()) {
    os << json;
    os.flush();
    os.close();
  }
}

int main(int argc, char ** argv) {
  if (1 >= argc) {
    Help(argv);
    ::_exit(0);
  }

  AppConfig conf;
  GetParam(&conf, argc, argv);
  if (0 == conf.divisor_ || 0 != 24 % conf.divisor_) {
    Help(argv);
    printf("\nindex divisor is invalid\n");
    ::_exit(0);
  }

  int block_size = conf.lines_*conf.line_size_;

  FileHandle * logger = FileHandle::Instance(conf.daemon_log_, FileHandle::GetLevel(conf.level_));
  if (NULL == logger) {
    printf("log2esd initial log failed");
    return -1;
  }
  LOG_DEBUG("log2esd initial log successed");

  if (conf.pid_file_.length()) {
    if (0 != Daemon::Daemonize(1, 1, false, conf.pid_file_.c_str())) {
      printf("log2esd daemonize failed");
      ::_exit(-1);
    }
  }
  LOG_DEBUG("log2esd daemonize successed");

  vector<char> mem(block_size);
  char * block = &mem.front();

  bool rm = true;
  if (0 == ::strncasecmp("no", conf.rm_.c_str(), 2)) {
    rm = false;
  }
  Capture capture(conf.log_home_, conf.index_prefix_, conf.divisor_, conf.written_file_, rm);
  LOG_DEBUG("log2esd initial capture successed");

  capture.FindLogs();
  LOG_DEBUG("log2esd search log files successed");

  ELS els(conf.host_);
  LOG_DEBUG("log2esd initial els successed");

  while (true) {
    int size = 0;
    if (0 >= (size = ReadLines(capture, conf.lines_, block, block_size))) {
      ::sleep(conf.interval_);
      continue;
    }

    block[size] = 0x00;

    if (5 > conf.lines_) {
      LOG_DEBUG("send to els:" << block);
    }
    int result = PushToELS(els, block);
    if (0 == result) {
      capture.Flush();
    } else if (ERR_ELS_PUSH_DOC_NO_RESPONSE == result) {
      if (0 != RetryPush(els, block, 3*600 , 2)) {
        LogToErrDoc(conf.log_home_, block);
      }
    } else {
      LOG_WARN("log to els failed data size:" << size);

      LogToErrDoc(conf.log_home_, block);

      ::sleep(60);
    }
  }

  vector<char>().swap(mem);

  delete logger;

  return 0;
}
<commit_msg>add help info<commit_after>/* ==================================================================================================
# Copyright 2014 vpon, Inc.
# --------------------------------------------------------------------------------------------------
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this work except in compliance with the License.
# You may obtain a copy of the License in the LICENSE file, or 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 <unistd.h>
#include <stdio.h>
#include <string>
#include <vector>
#include <fstream>
#include "producer/capture.h"
#include "agent/els.h"
#include "public/daemonize.h"
#include "err/err.h"
#include "log/log.h"

using std::string;
using std::vector;
using std::ofstream;
using log2esd::producer::Capture;
using log2esd::agent::ELS;
using log2esd::pub::Daemon;
using log2esd::log::FileHandle;
using log2esd::ERR_ELS_PUSH_DOC_NO_RESPONSE;

struct AppConfig {
  string host_;
  string log_home_;
  string level_;
  string daemon_log_;
  string pid_file_;
  string written_file_;
  string rm_;
  string index_prefix_;
  int lines_;
  int line_size_;
  int interval_;
  int divisor_;
  AppConfig() : host_("localhost:9200"), log_home_("./log"), level_("INFO"), daemon_log_("/data/logs/log2esd/"), pid_file_(""), written_file_(".written_file.txt"), rm_("yes"), index_prefix_(""), lines_(2), line_size_(2048), interval_(10), divisor_(2) {}
};

void Help(char ** argv) {
  printf("##########################################\n\n");
  printf("Usage: %s -p <file.ini>"
         "\n"
         "Options:\n"
         "-h <192.168.0.1:9200> els service (default: localhost:9200)\n"
         "-s <app_logs> directory of app's logs (default: ./log)\n"
         "-x <index_prefix> index prefix (default: empty)\n"
         "-v <index_divisor> index divisor, must be (2,3,4,6,8,12,24) (default: 2)\n"
         "-n <lines> lines of read once (default: 2)\n"
         "-b <line_size> size of line (default: 2048)\n"
         "-i <interval> waiting interval (default: 10)\n"
         "-w <daemon log> directory of daemon logs (default: /data/logs/log2esd)\n"
         "-l <level> level of daemon logs (default: INFO)\n"
         "-r <yes/no> remove log file after send all datas (default yes)\n"
         "-d <pid_file> daemonize log2esd\n"
         "-H Show this help\n"
         "\n",
         argv[0]
         );
  printf("##########################################\n\n");
}

void GetParam(AppConfig * conf, int argc, char ** argv) {
  char opt;
  while (-1 != (opt = ::getopt(argc, argv, "h:s:x:v:d:n:b:i:w:l:r:H"))) {
    switch (opt) {
    case 'h':
      if (NULL != optarg) {
        conf->host_ = optarg;
      }
      break;

    case 's':
      if (NULL != optarg) {
        conf->log_home_ = optarg;
      }
      break;

    case 'x':
      if (NULL != optarg) {
        conf->index_prefix_ = optarg;
      }
      break;

    case 'v':
      if (NULL != optarg) {
        conf->divisor_ = ::atoi(optarg);
      }
      break;

    case 'd':
      if (NULL != optarg) {
        conf->pid_file_ = optarg;
      }
      break;

    case 'n':
      if (NULL != optarg) {
        conf->lines_ = ::atoi(optarg);
      }
      break;

    case 'b':
      if (NULL != optarg) {
        conf->line_size_ = ::atoi(optarg);
      }
      break;

    case 'i':
      if (NULL != optarg) {
        conf->interval_ = ::atoi(optarg);
      }
      break;

    case 'w':
      if (NULL != optarg) {
        conf->daemon_log_ = optarg;
      }
      break;

    case 'l':
      if (NULL != optarg) {
        conf->level_ = optarg;
      }
      break;

    case 'r':
      if (NULL != optarg) {
        conf->rm_ = optarg;
      }
      break;

    case 'H':
    default:
      Help(argv);
      ::_exit(0);
      break;
    }
  }

  printf("###########################################\n");
  printf("host:%s\n", conf->host_.c_str());
  printf("log home:%s\n", conf->log_home_.c_str());
  printf("index prefix:%s\n", conf->index_prefix_.c_str());
  printf("index divisor:%d\n", conf->divisor_);
  printf("read lines:%d\n", conf->lines_);
  printf("line size:%d\n", conf->line_size_);
  printf("waiting interval:%d\n", conf->interval_);
  printf("deamon log:%s\n", conf->daemon_log_.c_str());
  printf("log level:%s\n", conf->level_.c_str());
  printf("pid file:%s\n", conf->pid_file_.c_str());
  printf("remove log file: %s\n", conf->rm_.c_str());
  printf("###########################################\n");

  return;
}

int ReadLines(Capture & capture, int lines, char * block, int max_size) {
  int used = 0;
  while (lines) {
    int unused = max_size - used;
    int cmd_size = capture.EncodeCmd(block + used, unused);
    if (0 >= cmd_size) {
      break;
    }
    used += cmd_size;
    unused = max_size - used;
    int size = capture.GetLine(block + used, unused);
    if (0 < size) {
      used += size;
      unused = max_size - used;

      lines--;
    } else {
      used -= cmd_size;

      break;
    }
  }

  return used;
}

int PushToELS(ELS & els, const string & data) {
  return els.PushDocs(data);
}

int RetryPush(ELS & els, const string & data, int times, int interval) {
  while (times) {
    if (0 == PushToELS(els, data)) {
      return 0;
    }

    --times;

    LOG_WARN("retry push to els times " << times);

    ::sleep(interval);
  }

  return -1;
}

void LogToErrDoc(const string & log_home, const string & json) {
  uint now = ::time(NULL);
  ::srand(now);
  int random = ::rand()%1000;
  char file[1024] = {0};
  ::snprintf(file, sizeof(file) - 1, ".written_error_%u_%d.json", now, random);
  const string path = log_home + "/" + file;
  int result = ::access(path.c_str(), F_OK);
  if (0 == result) {
    LOG_WARN("agent log to err doc file name is exists");
  }

  ofstream os(path.c_str());
  if (os.is_open()) {
    os << json;
    os.flush();
    os.close();
  }
}

int main(int argc, char ** argv) {
  if (1 >= argc) {
    Help(argv);
    ::_exit(0);
  }

  AppConfig conf;
  GetParam(&conf, argc, argv);
  if (0 >= conf.divisor_ || 24 < conf.divisor_ || 0 != 24 % conf.divisor_) {
    Help(argv);
    printf("\nindex divisor is invalid\n");
    ::_exit(0);
  }

  int block_size = conf.lines_*conf.line_size_;

  FileHandle * logger = FileHandle::Instance(conf.daemon_log_, FileHandle::GetLevel(conf.level_));
  if (NULL == logger) {
    printf("log2esd initial log failed");
    return -1;
  }
  LOG_DEBUG("log2esd initial log successed");

  if (conf.pid_file_.length()) {
    if (0 != Daemon::Daemonize(1, 1, false, conf.pid_file_.c_str())) {
      printf("log2esd daemonize failed");
      ::_exit(-1);
    }
  }
  LOG_DEBUG("log2esd daemonize successed");

  vector<char> mem(block_size);
  char * block = &mem.front();

  bool rm = true;
  if (0 == ::strncasecmp("no", conf.rm_.c_str(), 2)) {
    rm = false;
  }
  Capture capture(conf.log_home_, conf.index_prefix_, conf.divisor_, conf.written_file_, rm);
  LOG_DEBUG("log2esd initial capture successed");

  capture.FindLogs();
  LOG_DEBUG("log2esd search log files successed");

  ELS els(conf.host_);
  LOG_DEBUG("log2esd initial els successed");

  while (true) {
    int size = 0;
    if (0 >= (size = ReadLines(capture, conf.lines_, block, block_size))) {
      ::sleep(conf.interval_);
      continue;
    }

    block[size] = 0x00;

    if (5 > conf.lines_) {
      LOG_DEBUG("send to els:" << block);
    }
    int result = PushToELS(els, block);
    if (0 == result) {
      capture.Flush();
    } else if (ERR_ELS_PUSH_DOC_NO_RESPONSE == result) {
      if (0 != RetryPush(els, block, 3*600 , 2)) {
        LogToErrDoc(conf.log_home_, block);
      }
    } else {
      LOG_WARN("log to els failed data size:" << size);

      LogToErrDoc(conf.log_home_, block);

      ::sleep(60);
    }
  }

  vector<char>().swap(mem);

  delete logger;

  return 0;
}
<|endoftext|>


<commit_before>/*******************************************************************************
  Copyright (c) 2016, Manuel Freiberger
  All rights reserved.

  Redistribution and use in source and binary forms, with or without
  modification, are permitted provided that the following conditions are met:

  * Redistributions of source code must retain the above copyright notice, this
    list of conditions and the following disclaimer.

  * Redistributions in binary form must reproduce the above copyright notice,
    this list of conditions and the following disclaimer in the documentation
    and/or other materials provided with the distribution.

  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*******************************************************************************/

#include "logger.hpp"
#include "sink.hpp"

#include <cstdint>
#include <cstring>

#ifdef LOG11_USE_WEOS
#include <weos/thread.hpp>
#else
#include <thread>
#endif // LOG11_USE_WEOS

using namespace std;

namespace log11
{
using namespace log11_detail;

// ----=====================================================================----
//     Converter
// ----=====================================================================----

class Converter : public Visitor
{
public:
    Converter(Logger& logger)
        : m_logger(logger)
    {
    }

    virtual void visit(bool value)
    {
        if (value)
            m_logger.m_sink.load()->putString("true", 4);
        else
            m_logger.m_sink.load()->putString("false", 5);
    }

    virtual void visit(char value)
    {
        m_logger.m_sink.load()->putChar(value);
    }

    virtual void visit(signed char value)
    {
        auto length = snprintf(m_logger.m_conversionBuffer, sizeof(m_logger.m_conversionBuffer),
                               "%d", value);
        m_logger.m_sink.load()->putString(m_logger.m_conversionBuffer, length);
    }

    virtual void visit(unsigned char value)
    {
        auto length = snprintf(m_logger.m_conversionBuffer, sizeof(m_logger.m_conversionBuffer),
                               "%u", value);
        m_logger.m_sink.load()->putString(m_logger.m_conversionBuffer, length);
    }

    virtual void visit(short value)
    {
        auto length = snprintf(m_logger.m_conversionBuffer, sizeof(m_logger.m_conversionBuffer),
                               "%d", value);
        m_logger.m_sink.load()->putString(m_logger.m_conversionBuffer, length);
    }

    virtual void visit(unsigned short value)
    {
        auto length = snprintf(m_logger.m_conversionBuffer, sizeof(m_logger.m_conversionBuffer),
                               "%u", value);
        m_logger.m_sink.load()->putString(m_logger.m_conversionBuffer, length);
    }

    virtual void visit(int value)
    {
        auto length = snprintf(m_logger.m_conversionBuffer, sizeof(m_logger.m_conversionBuffer),
                               "%d", value);
        m_logger.m_sink.load()->putString(m_logger.m_conversionBuffer, length);
    }

    virtual void visit(unsigned value)
    {
        auto length = snprintf(m_logger.m_conversionBuffer, sizeof(m_logger.m_conversionBuffer),
                               "%u", value);
        m_logger.m_sink.load()->putString(m_logger.m_conversionBuffer, length);
    }

    virtual void visit(long value)
    {
        auto length = snprintf(m_logger.m_conversionBuffer, sizeof(m_logger.m_conversionBuffer),
                               "%ld", value);
        m_logger.m_sink.load()->putString(m_logger.m_conversionBuffer, length);
    }

    virtual void visit(unsigned long value)
    {
        auto length = snprintf(m_logger.m_conversionBuffer, sizeof(m_logger.m_conversionBuffer),
                               "%lu", value);
        m_logger.m_sink.load()->putString(m_logger.m_conversionBuffer, length);
    }

    virtual void visit(long long value)
    {
        auto length = snprintf(m_logger.m_conversionBuffer, sizeof(m_logger.m_conversionBuffer),
                               "%lld", value);
        m_logger.m_sink.load()->putString(m_logger.m_conversionBuffer, length);
    }

    virtual void visit(unsigned long long value)
    {
        auto length = snprintf(m_logger.m_conversionBuffer, sizeof(m_logger.m_conversionBuffer),
                               "%llu", value);
        m_logger.m_sink.load()->putString(m_logger.m_conversionBuffer, length);
    }

    virtual void visit(float value)
    {
        auto length = snprintf(m_logger.m_conversionBuffer, sizeof(m_logger.m_conversionBuffer),
                               "%f", value);
        m_logger.m_sink.load()->putString(m_logger.m_conversionBuffer, length);
    }

    virtual void visit(double value)
    {
        auto length = snprintf(m_logger.m_conversionBuffer, sizeof(m_logger.m_conversionBuffer),
                               "%f", value);
        m_logger.m_sink.load()->putString(m_logger.m_conversionBuffer, length);
    }

    virtual void visit(long double value)
    {
        auto length = snprintf(m_logger.m_conversionBuffer, sizeof(m_logger.m_conversionBuffer),
                               "%Lf", value);
        m_logger.m_sink.load()->putString(m_logger.m_conversionBuffer, length);
    }

    virtual void visit(const void* value) override
    {
        auto length = snprintf(m_logger.m_conversionBuffer, sizeof(m_logger.m_conversionBuffer),
                               "0x%08lx", uintptr_t(value));
        m_logger.m_sink.load()->putString(m_logger.m_conversionBuffer, length);
    }

    virtual void visit(const char* value) override
    {
        m_logger.m_sink.load()->putString(value, std::strlen(value));
    }

    virtual void visit(const StringRef& s1, const StringRef& s2)
    {
        Sink* sink = m_logger.m_sink;
        if (s1.size())
            sink->putString(s1.data(), s1.size());
        if (s2.size())
            sink->putString(s2.data(), s2.size());
    }

    virtual void outOfBounds()
    {
        m_logger.m_sink.load()->putString("?!", 2);
    }

private:
    Logger& m_logger;
};

// ----=====================================================================----
//     LogStatement
// ----=====================================================================----

LogStatement::LogStatement(Severity severity, const char* msg)
    : m_timeStamp(LOG11_STD::chrono::high_resolution_clock::now().time_since_epoch().count()),
      m_message(msg),
      m_extensionSize(0),
      m_extensionType(0),
      m_severity(static_cast<int>(severity))
{
}

// ----=====================================================================----
//     Logger
// ----=====================================================================----

#ifdef LOG11_USE_WEOS
Logger::Logger(const weos::thread_attributes& attrs, std::size_t bufferSize)
#else
Logger::Logger(std::size_t bufferSize)
#endif // LOG11_USE_WEOS
    : m_messageFifo(sizeof(LogStatement), bufferSize),
      m_flags(AppendNewLine),
      m_sink{nullptr},
      m_severityThreshold{Severity::Info}
{
#ifdef LOG11_USE_WEOS
    weos::thread(attrs, &Logger::consumeFifoEntries, this).detach();
#else
    std::thread(&Logger::consumeFifoEntries, this).detach();
#endif // LOG11_USE_WEOS
}

Logger::~Logger()
{
    m_flags |= StopRequest;
    // Signal the consumer thread.
    auto claimed = m_messageFifo.claim(1);
    new (m_messageFifo[claimed.begin]) LogStatement(Severity::Debug, nullptr);
    m_messageFifo.publish(claimed);
}

void Logger::setSeverityThreshold(Severity severity) noexcept
{
    m_severityThreshold = severity;
}

void Logger::setAutomaticNewLine(bool enable) noexcept
{
    if (enable)
    {
        int flag = m_flags;
        while (!m_flags.compare_exchange_weak(flag, flag | AppendNewLine));
    }
    else
    {
        int flag = m_flags;
        while (!m_flags.compare_exchange_weak(flag, flag & ~AppendNewLine));
    }
}

void Logger::setSink(Sink* sink) noexcept
{
    m_sink = sink;
}

void Logger::doLog(ClaimPolicy policy, Severity severity, const char* message)
{
    if (severity < m_severityThreshold)
        return;

    auto claimed = policy == Block ? m_messageFifo.claim(1)
                                   : m_messageFifo.tryClaim(1, policy == Truncate);
    if (claimed.length == 0)
        return;

    new (m_messageFifo[claimed.begin]) LogStatement(severity, message);

    if (policy == Block)
        m_messageFifo.publish(claimed);
    else
        m_messageFifo.tryPublish(claimed);
}

void Logger::consumeFifoEntries()
{
    Converter converter(*this);

    while ((m_flags & StopRequest) == 0)
    {
        auto available = m_messageFifo.available();
        while ((m_flags & StopRequest) == 0 && available.length)
        {
            // If no sink is attached to the logger, consume all FIFO entries.
            Sink* sink = m_sink;
            if (!sink)
            {
                m_messageFifo.consume(available.length);
                break;
            }

            auto stmt = static_cast<LogStatement*>(m_messageFifo[available.begin]);
            if (!stmt->m_message)
                return;

            sink->beginLogEntry(static_cast<Severity>(stmt->m_severity));
            printHeader(stmt);

            if (stmt->m_extensionType == 0)
            {
                sink->putString(stmt->m_message, std::strlen(stmt->m_message));

                ++available.begin;
                --available.length;
                m_messageFifo.consume(1);
            }
            else
            {
                SerdesBase* serdes
                        = stmt->m_extensionSize
                          ? *static_cast<SerdesBase**>(m_messageFifo[available.begin + 1])
                          : nullptr;
                auto byteRange = m_messageFifo.byteRange(
                                     RingBuffer::Range(available.begin + 1,
                                                       stmt->m_extensionSize));

                // Interpret the format string.
                unsigned argCounter = 0;
                const char* beginPos = stmt->m_message;
                const char* iter = beginPos;
                for (; *iter; ++iter)
                {
                    if (*iter == '{')
                    {
                        if (iter != beginPos)
                            sink->putString(beginPos, iter - beginPos);

                        // Loop to the end of the format specifier (or the end of the string).
                        beginPos = ++iter;
                        while (*iter && *iter != '}')
                            ++iter;
                        if (!*iter)
                        {
                            beginPos = iter;
                            break;
                        }
                        ++argCounter;
                        if (serdes)
                            serdes->apply(m_messageFifo, byteRange, argCounter, converter);
                        else
                            converter.outOfBounds();

                        beginPos = iter + 1;
                    }
                }
                if (iter != beginPos)
                    sink->putString(beginPos, iter - beginPos);

                available.begin += 1 + stmt->m_extensionSize;
                available.length -= 1 + stmt->m_extensionSize;
                m_messageFifo.consume(1 + stmt->m_extensionSize);
            }

            if (m_flags & AppendNewLine)
                sink->putChar('\n');
            sink->endLogEntry();
        }
    }
}

int numDecimalDigits(uint64_t x)
{
    unsigned digits = 1;
    while (true)
    {
        if (x < 10)
            return digits;
        if (x < 100)
            return digits + 1;
        if (x < 1000)
            return digits + 2;
        if (x < 10000)
            return digits + 3;
        x /= 10000;
        digits += 4;
    }
}

template <typename T>
void printDecimal(T x, char* buffer, unsigned numDigits)
{
    buffer += numDigits;
    while (numDigits--)
    {
        *--buffer = static_cast<char>('0' + (x % 10));
        x /= 10;
    }
}

void Logger::printHeader(LogStatement* stmt)
{
    static const char* severity_texts[] = {
        "TRACE",
        "DEBUG",
        "INFO ",
        "WARN ",
        "ERROR"
    };

    using namespace LOG11_STD::chrono;

    Sink* sink = m_sink;
    if (!sink)
        return;

    auto t = duration_cast<microseconds>(
                 high_resolution_clock::duration(stmt->m_timeStamp)).count();

    auto secs = t / 1000000;
    auto mins = secs / 60;
    auto hours = mins / 60;
    unsigned days = (hours / 24) % 10000;

    memset(m_conversionBuffer, ' ', 29);
    m_conversionBuffer[0] = '[';
    m_conversionBuffer[27] = ']';
    m_conversionBuffer[8] = ':';
    m_conversionBuffer[11] = ':';
    m_conversionBuffer[14] = '.';
    auto digits = numDecimalDigits(days);
    printDecimal(days, m_conversionBuffer + 5 - digits, digits);
    printDecimal(unsigned(hours % 24), m_conversionBuffer + 6, 2);
    printDecimal(unsigned(mins % 60), m_conversionBuffer + 9, 2);
    printDecimal(unsigned(secs % 60), m_conversionBuffer + 12, 2);
    printDecimal(unsigned(t % 1000000), m_conversionBuffer + 15, 6);
    memcpy(m_conversionBuffer + 22, severity_texts[stmt->m_severity], 5);

    sink->putString(m_conversionBuffer, 29);
}

} // namespace log11
<commit_msg>Better output for nullptr.<commit_after>/*******************************************************************************
  Copyright (c) 2016, Manuel Freiberger
  All rights reserved.

  Redistribution and use in source and binary forms, with or without
  modification, are permitted provided that the following conditions are met:

  * Redistributions of source code must retain the above copyright notice, this
    list of conditions and the following disclaimer.

  * Redistributions in binary form must reproduce the above copyright notice,
    this list of conditions and the following disclaimer in the documentation
    and/or other materials provided with the distribution.

  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*******************************************************************************/

#include "logger.hpp"
#include "sink.hpp"

#include <cstdint>
#include <cstring>

#ifdef LOG11_USE_WEOS
#include <weos/thread.hpp>
#else
#include <thread>
#endif // LOG11_USE_WEOS

using namespace std;

namespace log11
{
using namespace log11_detail;

// ----=====================================================================----
//     Converter
// ----=====================================================================----

class Converter : public Visitor
{
public:
    Converter(Logger& logger)
        : m_logger(logger)
    {
    }

    virtual void visit(bool value)
    {
        if (value)
            m_logger.m_sink.load()->putString("true", 4);
        else
            m_logger.m_sink.load()->putString("false", 5);
    }

    virtual void visit(char value)
    {
        m_logger.m_sink.load()->putChar(value);
    }

    virtual void visit(signed char value)
    {
        auto length = snprintf(m_logger.m_conversionBuffer, sizeof(m_logger.m_conversionBuffer),
                               "%d", value);
        m_logger.m_sink.load()->putString(m_logger.m_conversionBuffer, length);
    }

    virtual void visit(unsigned char value)
    {
        auto length = snprintf(m_logger.m_conversionBuffer, sizeof(m_logger.m_conversionBuffer),
                               "%u", value);
        m_logger.m_sink.load()->putString(m_logger.m_conversionBuffer, length);
    }

    virtual void visit(short value)
    {
        auto length = snprintf(m_logger.m_conversionBuffer, sizeof(m_logger.m_conversionBuffer),
                               "%d", value);
        m_logger.m_sink.load()->putString(m_logger.m_conversionBuffer, length);
    }

    virtual void visit(unsigned short value)
    {
        auto length = snprintf(m_logger.m_conversionBuffer, sizeof(m_logger.m_conversionBuffer),
                               "%u", value);
        m_logger.m_sink.load()->putString(m_logger.m_conversionBuffer, length);
    }

    virtual void visit(int value)
    {
        auto length = snprintf(m_logger.m_conversionBuffer, sizeof(m_logger.m_conversionBuffer),
                               "%d", value);
        m_logger.m_sink.load()->putString(m_logger.m_conversionBuffer, length);
    }

    virtual void visit(unsigned value)
    {
        auto length = snprintf(m_logger.m_conversionBuffer, sizeof(m_logger.m_conversionBuffer),
                               "%u", value);
        m_logger.m_sink.load()->putString(m_logger.m_conversionBuffer, length);
    }

    virtual void visit(long value)
    {
        auto length = snprintf(m_logger.m_conversionBuffer, sizeof(m_logger.m_conversionBuffer),
                               "%ld", value);
        m_logger.m_sink.load()->putString(m_logger.m_conversionBuffer, length);
    }

    virtual void visit(unsigned long value)
    {
        auto length = snprintf(m_logger.m_conversionBuffer, sizeof(m_logger.m_conversionBuffer),
                               "%lu", value);
        m_logger.m_sink.load()->putString(m_logger.m_conversionBuffer, length);
    }

    virtual void visit(long long value)
    {
        auto length = snprintf(m_logger.m_conversionBuffer, sizeof(m_logger.m_conversionBuffer),
                               "%lld", value);
        m_logger.m_sink.load()->putString(m_logger.m_conversionBuffer, length);
    }

    virtual void visit(unsigned long long value)
    {
        auto length = snprintf(m_logger.m_conversionBuffer, sizeof(m_logger.m_conversionBuffer),
                               "%llu", value);
        m_logger.m_sink.load()->putString(m_logger.m_conversionBuffer, length);
    }

    virtual void visit(float value)
    {
        auto length = snprintf(m_logger.m_conversionBuffer, sizeof(m_logger.m_conversionBuffer),
                               "%f", value);
        m_logger.m_sink.load()->putString(m_logger.m_conversionBuffer, length);
    }

    virtual void visit(double value)
    {
        auto length = snprintf(m_logger.m_conversionBuffer, sizeof(m_logger.m_conversionBuffer),
                               "%f", value);
        m_logger.m_sink.load()->putString(m_logger.m_conversionBuffer, length);
    }

    virtual void visit(long double value)
    {
        auto length = snprintf(m_logger.m_conversionBuffer, sizeof(m_logger.m_conversionBuffer),
                               "%Lf", value);
        m_logger.m_sink.load()->putString(m_logger.m_conversionBuffer, length);
    }

    virtual void visit(const void* value) override
    {
        if (value)
        {
            auto length = snprintf(m_logger.m_conversionBuffer, sizeof(m_logger.m_conversionBuffer),
                                   "0x%08lx", uintptr_t(value));
            m_logger.m_sink.load()->putString(m_logger.m_conversionBuffer, length);
        }
        else
        {
            m_logger.m_sink.load()->putString("<null>", 6);
        }
    }

    virtual void visit(const char* value) override
    {
        if (value)
        {
            m_logger.m_sink.load()->putString(value, std::strlen(value));
        }
        else
        {
            m_logger.m_sink.load()->putString("<null>", 6);
        }
    }

    virtual void visit(const StringRef& s1, const StringRef& s2)
    {
        Sink* sink = m_logger.m_sink;
        if (s1.size())
            sink->putString(s1.data(), s1.size());
        if (s2.size())
            sink->putString(s2.data(), s2.size());
    }

    virtual void outOfBounds()
    {
        m_logger.m_sink.load()->putString("?!", 2);
    }

private:
    Logger& m_logger;
};

// ----=====================================================================----
//     LogStatement
// ----=====================================================================----

LogStatement::LogStatement(Severity severity, const char* msg)
    : m_timeStamp(LOG11_STD::chrono::high_resolution_clock::now().time_since_epoch().count()),
      m_message(msg),
      m_extensionSize(0),
      m_extensionType(0),
      m_severity(static_cast<int>(severity))
{
}

// ----=====================================================================----
//     Logger
// ----=====================================================================----

#ifdef LOG11_USE_WEOS
Logger::Logger(const weos::thread_attributes& attrs, std::size_t bufferSize)
#else
Logger::Logger(std::size_t bufferSize)
#endif // LOG11_USE_WEOS
    : m_messageFifo(sizeof(LogStatement), bufferSize),
      m_flags(AppendNewLine),
      m_sink{nullptr},
      m_severityThreshold{Severity::Info}
{
#ifdef LOG11_USE_WEOS
    weos::thread(attrs, &Logger::consumeFifoEntries, this).detach();
#else
    std::thread(&Logger::consumeFifoEntries, this).detach();
#endif // LOG11_USE_WEOS
}

Logger::~Logger()
{
    m_flags |= StopRequest;
    // Signal the consumer thread.
    auto claimed = m_messageFifo.claim(1);
    new (m_messageFifo[claimed.begin]) LogStatement(Severity::Debug, nullptr);
    m_messageFifo.publish(claimed);
}

void Logger::setSeverityThreshold(Severity severity) noexcept
{
    m_severityThreshold = severity;
}

void Logger::setAutomaticNewLine(bool enable) noexcept
{
    if (enable)
    {
        int flag = m_flags;
        while (!m_flags.compare_exchange_weak(flag, flag | AppendNewLine));
    }
    else
    {
        int flag = m_flags;
        while (!m_flags.compare_exchange_weak(flag, flag & ~AppendNewLine));
    }
}

void Logger::setSink(Sink* sink) noexcept
{
    m_sink = sink;
}

void Logger::doLog(ClaimPolicy policy, Severity severity, const char* message)
{
    if (severity < m_severityThreshold)
        return;

    auto claimed = policy == Block ? m_messageFifo.claim(1)
                                   : m_messageFifo.tryClaim(1, policy == Truncate);
    if (claimed.length == 0)
        return;

    new (m_messageFifo[claimed.begin]) LogStatement(severity, message);

    if (policy == Block)
        m_messageFifo.publish(claimed);
    else
        m_messageFifo.tryPublish(claimed);
}

void Logger::consumeFifoEntries()
{
    Converter converter(*this);

    while ((m_flags & StopRequest) == 0)
    {
        auto available = m_messageFifo.available();
        while ((m_flags & StopRequest) == 0 && available.length)
        {
            // If no sink is attached to the logger, consume all FIFO entries.
            Sink* sink = m_sink;
            if (!sink)
            {
                m_messageFifo.consume(available.length);
                break;
            }

            auto stmt = static_cast<LogStatement*>(m_messageFifo[available.begin]);
            if (!stmt->m_message)
                return;

            sink->beginLogEntry(static_cast<Severity>(stmt->m_severity));
            printHeader(stmt);

            if (stmt->m_extensionType == 0)
            {
                sink->putString(stmt->m_message, std::strlen(stmt->m_message));

                ++available.begin;
                --available.length;
                m_messageFifo.consume(1);
            }
            else
            {
                SerdesBase* serdes
                        = stmt->m_extensionSize
                          ? *static_cast<SerdesBase**>(m_messageFifo[available.begin + 1])
                          : nullptr;
                auto byteRange = m_messageFifo.byteRange(
                                     RingBuffer::Range(available.begin + 1,
                                                       stmt->m_extensionSize));

                // Interpret the format string.
                unsigned argCounter = 0;
                const char* beginPos = stmt->m_message;
                const char* iter = beginPos;
                for (; *iter; ++iter)
                {
                    if (*iter == '{')
                    {
                        if (iter != beginPos)
                            sink->putString(beginPos, iter - beginPos);

                        // Loop to the end of the format specifier (or the end of the string).
                        beginPos = ++iter;
                        while (*iter && *iter != '}')
                            ++iter;
                        if (!*iter)
                        {
                            beginPos = iter;
                            break;
                        }
                        ++argCounter;
                        if (serdes)
                            serdes->apply(m_messageFifo, byteRange, argCounter, converter);
                        else
                            converter.outOfBounds();

                        beginPos = iter + 1;
                    }
                }
                if (iter != beginPos)
                    sink->putString(beginPos, iter - beginPos);

                available.begin += 1 + stmt->m_extensionSize;
                available.length -= 1 + stmt->m_extensionSize;
                m_messageFifo.consume(1 + stmt->m_extensionSize);
            }

            if (m_flags & AppendNewLine)
                sink->putChar('\n');
            sink->endLogEntry();
        }
    }
}

int numDecimalDigits(uint64_t x)
{
    unsigned digits = 1;
    while (true)
    {
        if (x < 10)
            return digits;
        if (x < 100)
            return digits + 1;
        if (x < 1000)
            return digits + 2;
        if (x < 10000)
            return digits + 3;
        x /= 10000;
        digits += 4;
    }
}

template <typename T>
void printDecimal(T x, char* buffer, unsigned numDigits)
{
    buffer += numDigits;
    while (numDigits--)
    {
        *--buffer = static_cast<char>('0' + (x % 10));
        x /= 10;
    }
}

void Logger::printHeader(LogStatement* stmt)
{
    static const char* severity_texts[] = {
        "TRACE",
        "DEBUG",
        "INFO ",
        "WARN ",
        "ERROR"
    };

    using namespace LOG11_STD::chrono;

    Sink* sink = m_sink;
    if (!sink)
        return;

    auto t = duration_cast<microseconds>(
                 high_resolution_clock::duration(stmt->m_timeStamp)).count();

    auto secs = t / 1000000;
    auto mins = secs / 60;
    auto hours = mins / 60;
    unsigned days = (hours / 24) % 10000;

    memset(m_conversionBuffer, ' ', 29);
    m_conversionBuffer[0] = '[';
    m_conversionBuffer[27] = ']';
    m_conversionBuffer[8] = ':';
    m_conversionBuffer[11] = ':';
    m_conversionBuffer[14] = '.';
    auto digits = numDecimalDigits(days);
    printDecimal(days, m_conversionBuffer + 5 - digits, digits);
    printDecimal(unsigned(hours % 24), m_conversionBuffer + 6, 2);
    printDecimal(unsigned(mins % 60), m_conversionBuffer + 9, 2);
    printDecimal(unsigned(secs % 60), m_conversionBuffer + 12, 2);
    printDecimal(unsigned(t % 1000000), m_conversionBuffer + 15, 6);
    memcpy(m_conversionBuffer + 22, severity_texts[stmt->m_severity], 5);

    sink->putString(m_conversionBuffer, 29);
}

} // namespace log11
<|endoftext|>


<commit_before>/*
 * PolygonParser.cpp
 *
 *  Created on: 22 Aug 2015
 *      Author: makrai
 */

#include "PolygonParser.h"

#include <fstream>
#include <stdlib.h>
#include <cmath>

#ifdef _DEBUG_
#include <iostream>
using namespace std;
#endif

void PolygonParser::parse(const char* fileName, unsigned char* buffer, int bufferSize, PolygonStore* polygonStore) {
	FILE* source = fopen(fileName, "r");

	int state = 0;

	int var1 = 0;
	int var2 = 0;

	char XChar[32];
	char YChar[32];

	double ax;
	double ay;
	double bx;
	double by;
	double cx;
	double cy;

	while (!feof(source)) {
		int readedBytes = fread(buffer, 1, bufferSize, source);
		for (int i = 0; i < readedBytes; ++i) {
			if (state == 0 && buffer[i] != ':') {
				state =1;
			} else if (state == 1 && buffer[i] == '>') {
				state = 2;
			} else if (state == 2 && buffer[i] == '>') {
				state = 3;
			} else if (state == 3 && buffer[i] == '>') {
				state = 4;
			} else if (state == 4 && buffer[i] == '>') {
				state = 5;
			} else if (state == 5 && buffer[i] != ',') {
				XChar[var1] = buffer[i];
				++var1;
			} else if (state == 5) {
				XChar[var1] = 0;
				state = 6;
				var1 = 0;
			} else if (state == 6 && buffer[i] != ' ' && buffer[i] != '<') {
				YChar[var1] = buffer[i];
				++var1;
			} else if (state == 6) {
				YChar[var1] = 0;
				var1 = 0;
				state = 5;

				if (var2 == 0) {
					ax = atof(XChar);
					ay = atof(YChar);
					var2 = 1;
				} else if (var2 == 1) {
					bx = atof(XChar);
					by = atof(YChar);
					var2 = 2;
				} else {
					cx = atof(XChar);
					cy = atof(YChar);

					if (fabs(ax - cx) + fabs(ay - cy) > 0.000001) {
						polygonStore->addPolygon(ax, ay, bx, by, cx, cy);
	#ifdef _PDEBUG_
						cout << "add polygon: ax:" << ax << ",ay:" << ay << ",bx:" << bx << ",by:" << by << ",cx:" << cx << ",cy:" << cy << endl;
						bx = cx;
						by = cy;
	#endif

					}
				}
				if (buffer[i] == '<') {
					state = 10;
				}
			} else if (state == 10 && buffer[i] == 10) {
				var1 = 0;
				var2 = 0;
				state = 0;
			}
		}
	}

	fclose(source);

}

<commit_msg>initialising some variables in PolygonParser<commit_after>/*
 * PolygonParser.cpp
 *
 *  Created on: 22 Aug 2015
 *      Author: makrai
 */

#include "PolygonParser.h"

#include <fstream>
#include <stdlib.h>
#include <cmath>

#ifdef _DEBUG_
#include <iostream>
using namespace std;
#endif

void PolygonParser::parse(const char* fileName, unsigned char* buffer, int bufferSize, PolygonStore* polygonStore) {
	FILE* source = fopen(fileName, "r");

	int state = 0;

	int var1 = 0;
	int var2 = 0;

	char XChar[32];
	char YChar[32];

	double ax = 0.0;
	double ay = 0.0;
	double bx = 0.0;
	double by = 0.0;
	double cx = 0.0;
	double cy = 0.0;

	while (!feof(source)) {
		int readedBytes = fread(buffer, 1, bufferSize, source);
		for (int i = 0; i < readedBytes; ++i) {
			if (state == 0 && buffer[i] != ':') {
				state =1;
			} else if (state == 1 && buffer[i] == '>') {
				state = 2;
			} else if (state == 2 && buffer[i] == '>') {
				state = 3;
			} else if (state == 3 && buffer[i] == '>') {
				state = 4;
			} else if (state == 4 && buffer[i] == '>') {
				state = 5;
			} else if (state == 5 && buffer[i] != ',') {
				XChar[var1] = buffer[i];
				++var1;
			} else if (state == 5) {
				XChar[var1] = 0;
				state = 6;
				var1 = 0;
			} else if (state == 6 && buffer[i] != ' ' && buffer[i] != '<') {
				YChar[var1] = buffer[i];
				++var1;
			} else if (state == 6) {
				YChar[var1] = 0;
				var1 = 0;
				state = 5;

				if (var2 == 0) {
					ax = atof(XChar);
					ay = atof(YChar);
					var2 = 1;
				} else if (var2 == 1) {
					bx = atof(XChar);
					by = atof(YChar);
					var2 = 2;
				} else {
					cx = atof(XChar);
					cy = atof(YChar);

					if (fabs(ax - cx) + fabs(ay - cy) > 0.000001) {
						polygonStore->addPolygon(ax, ay, bx, by, cx, cy);
	#ifdef _PDEBUG_
						cout << "add polygon: ax:" << ax << ",ay:" << ay << ",bx:" << bx << ",by:" << by << ",cx:" << cx << ",cy:" << cy << endl;
						bx = cx;
						by = cy;
	#endif

					}
				}
				if (buffer[i] == '<') {
					state = 10;
				}
			} else if (state == 10 && buffer[i] == 10) {
				var1 = 0;
				var2 = 0;
				state = 0;
			}
		}
	}

	fclose(source);

}

<|endoftext|>


<commit_before>//=============================================================================
//File Name: ITG3200_ADXL345.cpp
//Description: Implements a Kalman filter with the I2C IMU with the ITG3200
//             3-axis gyro and the ADXL345 3-axis accelerometer
//Author: FRC Team 3512, Spartatroniks
//=============================================================================

#include "ITG3200_ADXL345.hpp"

#include <DigitalModule.h>
#include <I2C.h>

ITG3200_ADXL345::ITG3200_ADXL345( UINT32 slot , UINT32 gyroAddress , UINT32 accelAddress )
: m_gyro( NULL ) , m_accel( NULL ) {
    DigitalModule* module = DigitalModule::GetInstance( slot );

    if ( module != NULL ) {
        m_gyro = module->GetI2C( gyroAddress );
        m_accel = module->GetI2C( accelAddress );
    }

    if ( m_gyro != NULL ) {
        m_gyro->Write( 0x16 , 0x1A ); // Sets gyro at +-2000deg/sec  and 98Hz Low pass filter
        m_gyro->Write( 0x15 , 0x09 ); // Sets gyro at 100Hz sample rate
    }

    if ( m_accel != NULL ) {
        m_accel->Write( 0x31 , 0x09 ); // Full resolution mode
        m_accel->Write( 0x2D , 0x08 ); // Setup ADXL345 for constant measurement mode
    }
}

ITG3200_ADXL345::~ITG3200_ADXL345() {
    delete m_gyro;
    delete m_accel;
}

// Actually measures y-axis of gyro for consistency with accelerometer
int ITG3200_ADXL345::readGyroX() {
    uint8_t* data = NULL;

    m_gyro->Read( 0x1F , 2 , data );

    return (data[0] << 8) | data[1];
}

// Actually measures x-axis of gyro for consistency with accelerometer
int ITG3200_ADXL345::readGyroY() {
    uint8_t* data = NULL;

    m_gyro->Read( 0x1D , 2 , data );

    return (data[0] << 8) | data[1];
}

int ITG3200_ADXL345::readGyroZ() {
    uint8_t* data = NULL;

    m_gyro->Read( 0x21 , 2 , data );

    return (data[0] << 8) | data[1];
}

int ITG3200_ADXL345::readAccelX() {
    uint8_t* data = NULL;

    m_accel->Read( 0x32 , 2 , data );

    return data[0] | (data[1] << 8);
}

int ITG3200_ADXL345::readAccelY() {
    uint8_t* data = NULL;

    m_accel->Read( 0x34 , 2 , data );

    return data[0] | (data[1] << 8);
}

int ITG3200_ADXL345::readAccelZ() {
    uint8_t* data = NULL;

    m_accel->Read( 0x36 , 2 , data );

    return data[0] | (data[1] << 8);
}

double ITG3200_ADXL345::getGyroXzero() {
    return 52.3;
}

double ITG3200_ADXL345::getGyroYzero() {
    return -18.5;
}

double ITG3200_ADXL345::getGyroZzero() {
    return 0.0; // TODO Find gyro's real z-axis zero
}

double ITG3200_ADXL345::getAccelXzero() {
    return -200;
}

double ITG3200_ADXL345::getAccelYzero() {
    return 44;
}

double ITG3200_ADXL345::getAccelZzero() {
    return 660;
}

double ITG3200_ADXL345::getGyroLSBsPerUnit() {
    return 14.375;
}

void ITG3200_ADXL345::callCalcAngle() {
    calcAngle( getAccelXangle() , getGyroXrate() );
}
<commit_msg>Removed null dereferences in I2C reads<commit_after>//=============================================================================
//File Name: ITG3200_ADXL345.cpp
//Description: Implements a Kalman filter with the I2C IMU with the ITG3200
//             3-axis gyro and the ADXL345 3-axis accelerometer
//Author: FRC Team 3512, Spartatroniks
//=============================================================================

#include "ITG3200_ADXL345.hpp"

#include <DigitalModule.h>
#include <I2C.h>

ITG3200_ADXL345::ITG3200_ADXL345( UINT32 slot , UINT32 gyroAddress , UINT32 accelAddress )
: m_gyro( NULL ) , m_accel( NULL ) {
    DigitalModule* module = DigitalModule::GetInstance( slot );

    if ( module != NULL ) {
        m_gyro = module->GetI2C( gyroAddress );
        m_accel = module->GetI2C( accelAddress );
    }

    if ( m_gyro != NULL ) {
        m_gyro->Write( 0x16 , 0x1A ); // Sets gyro at +-2000deg/sec  and 98Hz Low pass filter
        m_gyro->Write( 0x15 , 0x09 ); // Sets gyro at 100Hz sample rate
    }

    if ( m_accel != NULL ) {
        m_accel->Write( 0x31 , 0x09 ); // Full resolution mode
        m_accel->Write( 0x2D , 0x08 ); // Setup ADXL345 for constant measurement mode
    }
}

ITG3200_ADXL345::~ITG3200_ADXL345() {
    delete m_gyro;
    delete m_accel;
}

// Actually measures y-axis of gyro for consistency with accelerometer
int ITG3200_ADXL345::readGyroX() {
    uint8_t data[2];

    if ( m_gyro != NULL ) {
        m_gyro->Read( 0x1F , 2 , data );
        return (data[0] << 8) | data[1];
    }
    else {
        return 0;
    }
}

// Actually measures x-axis of gyro for consistency with accelerometer
int ITG3200_ADXL345::readGyroY() {
    uint8_t data[2];

    if ( m_gyro != NULL ) {
        m_gyro->Read( 0x1D , 2 , data );
        return (data[0] << 8) | data[1];
    }
    else {
        return 0;
    }
}

int ITG3200_ADXL345::readGyroZ() {
    uint8_t data[2];

    if ( m_gyro != NULL ) {
        m_gyro->Read( 0x21 , 2 , data );
        return (data[0] << 8) | data[1];
    }
    else {
        return 0;
    }
}

int ITG3200_ADXL345::readAccelX() {
    uint8_t data[2];

    if ( m_accel != NULL ) {
        m_accel->Read( 0x32 , 2 , data );
        return (data[0] << 8) | data[1];
    }
    else {
        return 0;
    }
}

int ITG3200_ADXL345::readAccelY() {
    uint8_t data[2];

    if ( m_accel != NULL ) {
        m_accel->Read( 0x34 , 2 , data );
        return data[0] | (data[1] << 8);
    }
    else {
        return 0;
    }
}

int ITG3200_ADXL345::readAccelZ() {
    uint8_t data[2];

    if ( m_accel != NULL ) {
        m_accel->Read( 0x36 , 2 , data );
        return (data[0] << 8) | data[1];
    }
    else {
        return 0;
    }
}

double ITG3200_ADXL345::getGyroXzero() {
    return 52.3;
}

double ITG3200_ADXL345::getGyroYzero() {
    return -18.5;
}

double ITG3200_ADXL345::getGyroZzero() {
    return 0.0; // TODO Find gyro's real z-axis zero
}

double ITG3200_ADXL345::getAccelXzero() {
    return -200;
}

double ITG3200_ADXL345::getAccelYzero() {
    return 44;
}

double ITG3200_ADXL345::getAccelZzero() {
    return 660;
}

double ITG3200_ADXL345::getGyroLSBsPerUnit() {
    return 14.375;
}

void ITG3200_ADXL345::callCalcAngle() {
    calcAngle( getAccelXangle() , getGyroXrate() );
}
<|endoftext|>