<commit_before>/*
 *  Copyright 2007-2015 The OpenMx Project
 *
 *  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 <ctype.h>
#define R_NO_REMAP
#include <R.h>
#include <Rinternals.h>

#include "omxState.h"
#include "omxNPSOLSpecific.h"
#include "omxMatrix.h"
#include "glue.h"
#include "omxImportFrontendState.h"
#include "Compute.h"
#include "npsolswitch.h"
#include "omxBuffer.h"

template <typename T1>
void GradientOptimizerContext::allConstraintsFun(Eigen::MatrixBase<T1> &constraintOut)
{
	omxState *globalState = fc->state;
	int l=0;
	for(int j = 0; j < (int) globalState->conList.size(); j++) {
		omxConstraint &cs = *globalState->conList[j];
		cs.refreshAndGrab(fc, omxConstraint::LESS_THAN, &constraintOut(l));
		l += cs.size;
	}
}

#ifdef  __cplusplus
extern "C" {
#endif

/* NPSOL-related functions */
extern void F77_SUB(npsol)(int *n, int *nclin, int *ncnln, int *ldA, int *ldJ, int *ldR, double *A,
                            double *bl, double *bu, void* funcon, void* funobj, int *inform, int *iter,
                            int *istate, double *c, double *cJac, double *clambda, double *f, double *g, double *R,
                            double *x, int *iw, int *leniw, double *w, int *lenw);
extern void F77_SUB(npoptn)(char* string, int Rf_length);

#ifdef  __cplusplus
}
#endif

#if HAS_NPSOL

static struct GradientOptimizerContext *NPSOL_GOpt;

void F77_SUB(npsolObjectiveFunction)(int* mode, int* n, double* x,
				     double* f, double* g, int* nstate)
{
	if (x != NPSOL_GOpt->fc->est) return;  // this is strange but necessary
	double fit = NPSOL_GOpt->recordFit(x, mode);
	*f = fit;
}

/* (Non)Linear Constraint Functions */
void F77_SUB(npsolConstraintFunction)
	(	int *mode, int *ncnln, int *n,
		int *ldJ, int *needc, double *x,
		double *c, double *cJac, int *nstate)
{
	if(*mode==1) return;

	// "Note that if there are any nonlinear constraints then the
	// first call to CONFUN will precede the first call to
	// OBJFUN." Hence, we must copyParamToModel here.

	NPSOL_GOpt->fc->copyParamToModel();

	Eigen::Map< Eigen::VectorXd > cE(c, *ncnln);
	NPSOL_GOpt->allConstraintsFun(cE);
}

void omxNPSOL(double *est, GradientOptimizerContext &rf)
{
	rf.optName = "NPSOL";
	rf.setupAllBounds();
	if (std::isfinite(rf.ControlTolerance)) {
		std::string opt = string_snprintf("Optimality tolerance %.8g", rf.ControlTolerance);
		F77_CALL(npoptn)((char*) opt.c_str(), opt.size());
	}
	if (rf.warmStart) {
		std::string opt = string_snprintf("Warm start");
		F77_CALL(npoptn)((char*) opt.c_str(), opt.size());
	} else {
		std::string opt = string_snprintf("Cold start");
		F77_CALL(npoptn)((char*) opt.c_str(), opt.size());
	}

	// Will fail if we re-enter after an exception
	//if (NPSOL_fitMatrix) Rf_error("NPSOL is not reentrant");
	FitContext *fc = rf.fc;
	NPSOL_GOpt = &rf;

    omxState *globalState = fc->state;
    int nclin = 0;
    int nlinwid = std::max(1, nclin);
    int equality, inequality;
    globalState->countNonlinearConstraints(equality, inequality);
    int ncnln = equality + inequality;
    int nlnwid = std::max(1, ncnln);

	if (ncnln == 0) {
		// ensure we never move to a worse point
		int mode = 0;
		double fit = rf.recordFit(fc->est, &mode);
		if (!std::isfinite(fit)) {
			rf.informOut = INFORM_STARTING_VALUES_INFEASIBLE;
			NPSOL_GOpt = NULL;
			return;
		}
		if (mode == -1) {
			NPSOL_GOpt = NULL;
			return;
		}
	}

	fc->grad.resize(fc->numParam); // ensure memory is allocated
	int n = int(fc->numParam);

        int nctotl = n + nlinwid + nlnwid;

        int leniw = 3 * n + nclin + 2 * ncnln;
        int lenw = 2 * n * n + n * nclin + 2 * n * ncnln + 20 * n + 11 * nclin + 21 * ncnln;

        int ldA = nlinwid;          // NPSOL specifies this should be either 1 or nclin, whichever is greater
        int ldJ = nlnwid;           // NPSOL specifies this should be either 1 or nclin, whichever is greater
        int ldR = n;                // TODO: Test alternative versions of the size of R to see what's best.

    /* Allocate arrays */
	Eigen::ArrayXXd A(ldA, n);  // maybe transposed?
	Eigen::VectorXd c(nlnwid);
	Eigen::MatrixXd cJac(ldJ, n); // maybe transposed?
	Eigen::VectorXd clambda(nctotl);
	Eigen::VectorXd w(lenw);
	Eigen::VectorXi istate(nctotl);
	Eigen::VectorXi iw(leniw);

	if (rf.warmStart) {
		istate.setZero();
		clambda.setZero();
	}

    /*  F77_CALL(npsol)
        (   int *n,                 -- Number of variables
            int *nclin,             -- Number of linear constraints
            int *ncnln,             -- Number of nonlinear constraints
            int *ldA,               -- Row dimension of A (Linear Constraints)
            int *ldJ,               -- Row dimension of cJac (Jacobian)
            int *ldR,               -- Row dimension of R (Hessian)
            double *A,              -- Linear Constraints Array A (in Column-major order)
            double *bl,             -- Lower Bounds Array (at least n + nclin + ncnln long)
            double *bu,             -- Upper Bounds Array (at least n + nclin + ncnln long)
            function funcon,        -- Nonlinear constraint function
            function funobj,        -- Objective function
            int *inform,            -- Used to report state.  Need not be initialized.
            int *iter,              -- Used to report number of major iterations performed.  Need not be initialized.
            int *istate,            -- Initial State.  Need not be initialized unless using Warm Start.
            double *c,              -- Array of length ncnln.  Need not be initialized.  Reports nonlinear constraints at final iteration.
            double *cJac,           -- Array of Row-length ldJ.  Unused if ncnln = 0. Generally need not be initialized.
            double *clambda,        -- Array of length n+nclin+ncnln.  Need not be initialized unless using Warm Start. Reports final QP multipliers.
            double *f,              -- Used to report final objective value.  Need not be initialized.
            double *g,              -- Array of length n. Used to report final objective gradient.  Need not be initialized.
            double *R,              -- Array of length ldR.  Need not be intialized unless using Warm Start.
            double *x,              -- Array of length n.  Contains initial solution estimate.
            int *iw,                -- Array of length leniw. Need not be initialized.  Provides workspace.
            int *leniw,             -- Length of iw.  Must be at least 3n + nclin + ncnln.
            double *w,              -- Array of length lenw. Need not be initialized.  Provides workspace.
            int *lenw               -- Length of w.  Must be at least 2n^2 + n*nclin + 2*n*ncnln + 20*n + 11*nclin +21*ncnln
        )

        bl, bu, istate, and clambda are all length n+nclin+ncnln.
            First n elements refer to the vars, in order.
            Next nclin elements refer to bounds on Ax
            Last ncnln elements refer to bounds on c(x)

        All arrays must be in column-major order.
        */

	fc->grad.resize(n);
	rf.hessOut.resize(n, n);
	double fit; // do not pass in &fc->fit
	int iter_out; // ignored
	F77_CALL(npsol)(&n, &nclin, &ncnln, &ldA, &ldJ, &ldR, A.data(),
			rf.solLB.data(), rf.solUB.data(), (void*)F77_SUB(npsolConstraintFunction),
			(void*) F77_SUB(npsolObjectiveFunction), &rf.informOut, &iter_out,
			istate.data(), c.data(), cJac.data(),
			clambda.data(), &fit, fc->grad.data(), rf.hessOut.data(), fc->est, iw.data(), &leniw, w.data(), &lenw);

	// NPSOL can return the wrong fit and estimates, but hard to
	// know what to do if there are constraints.
	if (rf.bestEst.size() && ncnln == 0) {
		fc->fit = rf.bestFit;
		memcpy(fc->est, rf.bestEst.data(), sizeof(double) * fc->numParam);
	}

    NPSOL_GOpt = NULL;
}

void omxSetNPSOLOpts(SEXP options)
{
    omxManageProtectInsanity mpi;

    static const char *whitelist[] = {
        "Central Difference Interval",
        "Crash Tolerance",
        "Derivative level",
        "Difference interval",
        "Feasibility tolerance",
        "Function precision",
        "Hessian",
        "Infinite bound size",
        "Infinite step size",
        "Iteration limit",
        "Iters",
        "Line search tolerance",
        "Major iteration limit",
        "Major iterations",
        "Print level",
        "Print file",
        "Minor iteration limit",
        "Minor print level",
        "Nolist",
        "Optimality tolerance",
        "Step limit",
        "Summary file",
        "Verify level",
        0
    };

    const int opBufLen = 250;
    char optionCharArray[opBufLen];
    int numOptions = Rf_length(options);
    SEXP optionNames;
    Rf_protect(optionNames = Rf_getAttrib(options, R_NamesSymbol));
    for(int i = 0; i < numOptions; i++) {
        const char *nextOptionName = CHAR(STRING_ELT(optionNames, i));
        const char *nextOptionValue = CHAR(Rf_asChar(VECTOR_ELT(options, i)));
        bool ok=false;
        for (int wx=0; whitelist[wx]; ++wx) {
            if (matchCaseInsensitive(nextOptionName, whitelist[wx])) {
                ok=true;
                break;
            }
        }
        if (!ok) continue;
        snprintf(optionCharArray, opBufLen, "%s %s", nextOptionName, nextOptionValue);
        F77_CALL(npoptn)(optionCharArray, strlen(optionCharArray));
        if(OMX_DEBUG) { mxLog("Option %s ", optionCharArray);}
    }
}
#endif
<commit_msg>Remove redundent vector resize<commit_after>/*
 *  Copyright 2007-2015 The OpenMx Project
 *
 *  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 <ctype.h>
#define R_NO_REMAP
#include <R.h>
#include <Rinternals.h>

#include "omxState.h"
#include "omxNPSOLSpecific.h"
#include "omxMatrix.h"
#include "glue.h"
#include "omxImportFrontendState.h"
#include "Compute.h"
#include "npsolswitch.h"
#include "omxBuffer.h"

template <typename T1>
void GradientOptimizerContext::allConstraintsFun(Eigen::MatrixBase<T1> &constraintOut)
{
	omxState *globalState = fc->state;
	int l=0;
	for(int j = 0; j < (int) globalState->conList.size(); j++) {
		omxConstraint &cs = *globalState->conList[j];
		cs.refreshAndGrab(fc, omxConstraint::LESS_THAN, &constraintOut(l));
		l += cs.size;
	}
}

#ifdef  __cplusplus
extern "C" {
#endif

/* NPSOL-related functions */
extern void F77_SUB(npsol)(int *n, int *nclin, int *ncnln, int *ldA, int *ldJ, int *ldR, double *A,
                            double *bl, double *bu, void* funcon, void* funobj, int *inform, int *iter,
                            int *istate, double *c, double *cJac, double *clambda, double *f, double *g, double *R,
                            double *x, int *iw, int *leniw, double *w, int *lenw);
extern void F77_SUB(npoptn)(char* string, int Rf_length);

#ifdef  __cplusplus
}
#endif

#if HAS_NPSOL

static struct GradientOptimizerContext *NPSOL_GOpt;

void F77_SUB(npsolObjectiveFunction)(int* mode, int* n, double* x,
				     double* f, double* g, int* nstate)
{
	if (x != NPSOL_GOpt->fc->est) return;  // this is strange but necessary
	double fit = NPSOL_GOpt->recordFit(x, mode);
	*f = fit;
}

/* (Non)Linear Constraint Functions */
void F77_SUB(npsolConstraintFunction)
	(	int *mode, int *ncnln, int *n,
		int *ldJ, int *needc, double *x,
		double *c, double *cJac, int *nstate)
{
	if(*mode==1) return;

	// "Note that if there are any nonlinear constraints then the
	// first call to CONFUN will precede the first call to
	// OBJFUN." Hence, we must copyParamToModel here.

	NPSOL_GOpt->fc->copyParamToModel();

	Eigen::Map< Eigen::VectorXd > cE(c, *ncnln);
	NPSOL_GOpt->allConstraintsFun(cE);
}

void omxNPSOL(double *est, GradientOptimizerContext &rf)
{
	rf.optName = "NPSOL";
	rf.setupAllBounds();
	if (std::isfinite(rf.ControlTolerance)) {
		std::string opt = string_snprintf("Optimality tolerance %.8g", rf.ControlTolerance);
		F77_CALL(npoptn)((char*) opt.c_str(), opt.size());
	}
	if (rf.warmStart) {
		std::string opt = string_snprintf("Warm start");
		F77_CALL(npoptn)((char*) opt.c_str(), opt.size());
	} else {
		std::string opt = string_snprintf("Cold start");
		F77_CALL(npoptn)((char*) opt.c_str(), opt.size());
	}

	// Will fail if we re-enter after an exception
	//if (NPSOL_fitMatrix) Rf_error("NPSOL is not reentrant");
	FitContext *fc = rf.fc;
	NPSOL_GOpt = &rf;

    omxState *globalState = fc->state;
    int nclin = 0;
    int nlinwid = std::max(1, nclin);
    int equality, inequality;
    globalState->countNonlinearConstraints(equality, inequality);
    int ncnln = equality + inequality;
    int nlnwid = std::max(1, ncnln);

	if (ncnln == 0) {
		// ensure we never move to a worse point
		int mode = 0;
		double fit = rf.recordFit(fc->est, &mode);
		if (!std::isfinite(fit)) {
			rf.informOut = INFORM_STARTING_VALUES_INFEASIBLE;
			NPSOL_GOpt = NULL;
			return;
		}
		if (mode == -1) {
			NPSOL_GOpt = NULL;
			return;
		}
	}

	int n = int(fc->numParam);

        int nctotl = n + nlinwid + nlnwid;

        int leniw = 3 * n + nclin + 2 * ncnln;
        int lenw = 2 * n * n + n * nclin + 2 * n * ncnln + 20 * n + 11 * nclin + 21 * ncnln;

        int ldA = nlinwid;          // NPSOL specifies this should be either 1 or nclin, whichever is greater
        int ldJ = nlnwid;           // NPSOL specifies this should be either 1 or nclin, whichever is greater
        int ldR = n;                // TODO: Test alternative versions of the size of R to see what's best.

    /* Allocate arrays */
	Eigen::ArrayXXd A(ldA, n);  // maybe transposed?
	Eigen::VectorXd c(nlnwid);
	Eigen::MatrixXd cJac(ldJ, n); // maybe transposed?
	Eigen::VectorXd clambda(nctotl);
	Eigen::VectorXd w(lenw);
	Eigen::VectorXi istate(nctotl);
	Eigen::VectorXi iw(leniw);

	if (rf.warmStart) {
		istate.setZero();
		clambda.setZero();
	}

    /*  F77_CALL(npsol)
        (   int *n,                 -- Number of variables
            int *nclin,             -- Number of linear constraints
            int *ncnln,             -- Number of nonlinear constraints
            int *ldA,               -- Row dimension of A (Linear Constraints)
            int *ldJ,               -- Row dimension of cJac (Jacobian)
            int *ldR,               -- Row dimension of R (Hessian)
            double *A,              -- Linear Constraints Array A (in Column-major order)
            double *bl,             -- Lower Bounds Array (at least n + nclin + ncnln long)
            double *bu,             -- Upper Bounds Array (at least n + nclin + ncnln long)
            function funcon,        -- Nonlinear constraint function
            function funobj,        -- Objective function
            int *inform,            -- Used to report state.  Need not be initialized.
            int *iter,              -- Used to report number of major iterations performed.  Need not be initialized.
            int *istate,            -- Initial State.  Need not be initialized unless using Warm Start.
            double *c,              -- Array of length ncnln.  Need not be initialized.  Reports nonlinear constraints at final iteration.
            double *cJac,           -- Array of Row-length ldJ.  Unused if ncnln = 0. Generally need not be initialized.
            double *clambda,        -- Array of length n+nclin+ncnln.  Need not be initialized unless using Warm Start. Reports final QP multipliers.
            double *f,              -- Used to report final objective value.  Need not be initialized.
            double *g,              -- Array of length n. Used to report final objective gradient.  Need not be initialized.
            double *R,              -- Array of length ldR.  Need not be intialized unless using Warm Start.
            double *x,              -- Array of length n.  Contains initial solution estimate.
            int *iw,                -- Array of length leniw. Need not be initialized.  Provides workspace.
            int *leniw,             -- Length of iw.  Must be at least 3n + nclin + ncnln.
            double *w,              -- Array of length lenw. Need not be initialized.  Provides workspace.
            int *lenw               -- Length of w.  Must be at least 2n^2 + n*nclin + 2*n*ncnln + 20*n + 11*nclin +21*ncnln
        )

        bl, bu, istate, and clambda are all length n+nclin+ncnln.
            First n elements refer to the vars, in order.
            Next nclin elements refer to bounds on Ax
            Last ncnln elements refer to bounds on c(x)

        All arrays must be in column-major order.
        */

	fc->grad.resize(n);
	rf.hessOut.resize(n, n);
	double fit; // do not pass in &fc->fit
	int iter_out; // ignored
	F77_CALL(npsol)(&n, &nclin, &ncnln, &ldA, &ldJ, &ldR, A.data(),
			rf.solLB.data(), rf.solUB.data(), (void*)F77_SUB(npsolConstraintFunction),
			(void*) F77_SUB(npsolObjectiveFunction), &rf.informOut, &iter_out,
			istate.data(), c.data(), cJac.data(),
			clambda.data(), &fit, fc->grad.data(), rf.hessOut.data(), fc->est, iw.data(), &leniw, w.data(), &lenw);

	// NPSOL can return the wrong fit and estimates, but hard to
	// know what to do if there are constraints.
	if (rf.bestEst.size() && ncnln == 0) {
		fc->fit = rf.bestFit;
		memcpy(fc->est, rf.bestEst.data(), sizeof(double) * fc->numParam);
	}

    NPSOL_GOpt = NULL;
}

void omxSetNPSOLOpts(SEXP options)
{
    omxManageProtectInsanity mpi;

    static const char *whitelist[] = {
        "Central Difference Interval",
        "Crash Tolerance",
        "Derivative level",
        "Difference interval",
        "Feasibility tolerance",
        "Function precision",
        "Hessian",
        "Infinite bound size",
        "Infinite step size",
        "Iteration limit",
        "Iters",
        "Line search tolerance",
        "Major iteration limit",
        "Major iterations",
        "Print level",
        "Print file",
        "Minor iteration limit",
        "Minor print level",
        "Nolist",
        "Optimality tolerance",
        "Step limit",
        "Summary file",
        "Verify level",
        0
    };

    const int opBufLen = 250;
    char optionCharArray[opBufLen];
    int numOptions = Rf_length(options);
    SEXP optionNames;
    Rf_protect(optionNames = Rf_getAttrib(options, R_NamesSymbol));
    for(int i = 0; i < numOptions; i++) {
        const char *nextOptionName = CHAR(STRING_ELT(optionNames, i));
        const char *nextOptionValue = CHAR(Rf_asChar(VECTOR_ELT(options, i)));
        bool ok=false;
        for (int wx=0; whitelist[wx]; ++wx) {
            if (matchCaseInsensitive(nextOptionName, whitelist[wx])) {
                ok=true;
                break;
            }
        }
        if (!ok) continue;
        snprintf(optionCharArray, opBufLen, "%s %s", nextOptionName, nextOptionValue);
        F77_CALL(npoptn)(optionCharArray, strlen(optionCharArray));
        if(OMX_DEBUG) { mxLog("Option %s ", optionCharArray);}
    }
}
#endif
<|endoftext|>


<commit_before>/**
 * This file is part of the CernVM File System.
 */

#include "gtest/gtest.h"

#include "../../cvmfs/compression.h"
#include "../../cvmfs/util.h"

// TODO(jblomer): typed tests

namespace zlib {

// Test fixture that creates data structures necessary to test Compressor
class T_Compressor : public ::testing::Test {
 protected:
  virtual void SetUp() {
    // Compress a known String
    test_string = strdup("Hello World!");
    ptr_test_string = test_string;

    // Include the null character
    size_input = strlen(test_string) + 1;

    // Create a buffer to hold the output
    buf = new unsigned char[100];
    buf_size = 100;

    long_size = 1024 * 1024 * 20;  // 20 MB
    long_string = new unsigned char[long_size];
  }

  virtual void TearDown() {
    delete long_string;
    delete buf;
    free(test_string);
  }

  char *test_string, *ptr_test_string;
  UniquePtr<Compressor> compressor;
  unsigned char *buf;
  size_t buf_size;
  size_t size_input;

  unsigned char *long_string;
  size_t long_size;
};

TEST_F(T_Compressor, Compression) {
  compressor = zlib::Compressor::Construct(zlib::kZlibDefault);

  // Compress the output
  unsigned char *input = reinterpret_cast<unsigned char *>(ptr_test_string);
  bool deflate_finished =
    compressor->Deflate(true, &input, &size_input, &buf, &buf_size);

  ASSERT_TRUE(deflate_finished);
  ASSERT_GT(buf_size, 0U);
  ASSERT_EQ(0U, size_input);

  // Decompress it, check if it's still the same
  char *decompress_buf;
  uint64_t decompress_size;
  DecompressMem2Mem(buf, buf_size,
    reinterpret_cast<void **>(&decompress_buf), &decompress_size);

  // Check if the string is the same as the beginning
  ASSERT_EQ(0, strcmp(decompress_buf, test_string));

  free(decompress_buf);
}

TEST_F(T_Compressor, CompressionLong) {
  compressor = zlib::Compressor::Construct(zlib::kZlibDefault);
  unsigned char *compress_buf =
    new unsigned char[compressor->DeflateBound(long_size)];
  unsigned compress_pos = 0;
  bool deflate_finished = false;
  unsigned char *input = long_string;
  size_t remaining = long_size;
  unsigned rounds = 0;

  while (!deflate_finished) {
    // Compress the output in multiple stages
    deflate_finished =
      compressor->Deflate(true, &input, &remaining, &buf, &buf_size);
    memcpy(compress_buf + compress_pos, buf, buf_size);
    compress_pos += buf_size;
    rounds++;
  }

  EXPECT_GT(rounds, 1U);
  EXPECT_GT(compress_pos, 0U);
  ASSERT_EQ(0U, remaining);

  // Decompress it, check if it's still the same
  char *decompress_buf;
  uint64_t decompress_size;
  bool retval = DecompressMem2Mem(compress_buf, compress_pos,
    reinterpret_cast<void **>(&decompress_buf), &decompress_size);
  EXPECT_EQ(true, retval);
  EXPECT_EQ(decompress_size, static_cast<uint64_t>(long_size));
  EXPECT_EQ(0, memcmp(decompress_buf, long_string, long_size));

  delete compress_buf;
  free(decompress_buf);
}

TEST_F(T_Compressor, EchoCompression) {
  compressor = zlib::Compressor::Construct(zlib::kNoCompression);

  unsigned char *input = reinterpret_cast<unsigned char *>(ptr_test_string);
  bool deflate_finished =
    compressor->Deflate(true, &input, &size_input, &buf, &buf_size);

  ASSERT_TRUE(deflate_finished);
  ASSERT_GT(buf_size, 0U);
  ASSERT_EQ(size_input, (size_t)0);

  // Make sure the compressed data is exactly the same as the
  // input.
  ASSERT_EQ(0, strcmp(reinterpret_cast<char *>(buf), test_string));
}

TEST_F(T_Compressor, EchoCompressionLong) {
  compressor = zlib::Compressor::Construct(zlib::kNoCompression);
  unsigned char *compress_buf =
    new unsigned char[compressor->DeflateBound(long_size)];
  unsigned compress_pos = 0;
  bool deflate_finished = false;
  unsigned char *input = long_string;
  size_t remaining = long_size;
  unsigned rounds = 0;

  while (!deflate_finished) {
    // Compress the output in multiple stages
    deflate_finished =
      compressor->Deflate(true, &input, &remaining, &buf, &buf_size);
    memcpy(compress_buf + compress_pos, buf, buf_size);
    compress_pos += buf_size;
    rounds++;
  }

  EXPECT_GT(rounds, 1U);
  EXPECT_GT(compress_pos, 0U);
  ASSERT_EQ(0U, remaining);

  EXPECT_EQ(compress_pos, long_size);
  EXPECT_EQ(0, memcmp(compress_buf, long_string, long_size));

  delete compress_buf;
}

}  // end namespace zlib
<commit_msg>FIX: coverity 63530<commit_after>/**
 * This file is part of the CernVM File System.
 */

#include "gtest/gtest.h"

#include "../../cvmfs/compression.h"
#include "../../cvmfs/util.h"

// TODO(jblomer): typed tests

namespace zlib {

// Test fixture that creates data structures necessary to test Compressor
class T_Compressor : public ::testing::Test {
 protected:
  virtual void SetUp() {
    // Compress a known String
    test_string = strdup("Hello World!");
    ptr_test_string = test_string;

    // Include the null character
    size_input = strlen(test_string) + 1;

    // Create a buffer to hold the output
    buf = new unsigned char[100];
    buf_size = 100;

    long_size = 1024 * 1024 * 20;  // 20 MB
    long_string = new unsigned char[long_size];
  }

  virtual void TearDown() {
    delete long_string;
    delete buf;
    free(test_string);
  }

  char *test_string, *ptr_test_string;
  UniquePtr<Compressor> compressor;
  unsigned char *buf;
  size_t buf_size;
  size_t size_input;

  unsigned char *long_string;
  size_t long_size;
};

TEST_F(T_Compressor, Compression) {
  compressor = zlib::Compressor::Construct(zlib::kZlibDefault);

  // Compress the output
  unsigned char *input = reinterpret_cast<unsigned char *>(ptr_test_string);
  bool deflate_finished =
    compressor->Deflate(true, &input, &size_input, &buf, &buf_size);

  ASSERT_TRUE(deflate_finished);
  ASSERT_GT(buf_size, 0U);
  ASSERT_EQ(0U, size_input);

  // Decompress it, check if it's still the same
  char *decompress_buf;
  uint64_t decompress_size;
  DecompressMem2Mem(buf, buf_size,
    reinterpret_cast<void **>(&decompress_buf), &decompress_size);

  // Check if the string is the same as the beginning
  ASSERT_EQ(0, strcmp(decompress_buf, test_string));

  free(decompress_buf);
}

TEST_F(T_Compressor, CompressionLong) {
  compressor = zlib::Compressor::Construct(zlib::kZlibDefault);
  unsigned char *compress_buf =
    new unsigned char[compressor->DeflateBound(long_size)];
  unsigned compress_pos = 0;
  bool deflate_finished = false;
  unsigned char *input = long_string;
  size_t remaining = long_size;
  unsigned rounds = 0;

  while (!deflate_finished) {
    // Compress the output in multiple stages
    deflate_finished =
      compressor->Deflate(true, &input, &remaining, &buf, &buf_size);
    memcpy(compress_buf + compress_pos, buf, buf_size);
    compress_pos += buf_size;
    rounds++;
  }

  EXPECT_GT(rounds, 1U);
  EXPECT_GT(compress_pos, 0U);
  ASSERT_EQ(0U, remaining);

  // Decompress it, check if it's still the same
  char *decompress_buf;
  uint64_t decompress_size;
  bool retval = DecompressMem2Mem(compress_buf, compress_pos,
    reinterpret_cast<void **>(&decompress_buf), &decompress_size);
  EXPECT_EQ(true, retval);
  EXPECT_EQ(decompress_size, static_cast<uint64_t>(long_size));
  EXPECT_EQ(0, memcmp(decompress_buf, long_string, long_size));

  delete[] compress_buf;
  free(decompress_buf);
}

TEST_F(T_Compressor, EchoCompression) {
  compressor = zlib::Compressor::Construct(zlib::kNoCompression);

  unsigned char *input = reinterpret_cast<unsigned char *>(ptr_test_string);
  bool deflate_finished =
    compressor->Deflate(true, &input, &size_input, &buf, &buf_size);

  ASSERT_TRUE(deflate_finished);
  ASSERT_GT(buf_size, 0U);
  ASSERT_EQ(size_input, (size_t)0);

  // Make sure the compressed data is exactly the same as the
  // input.
  ASSERT_EQ(0, strcmp(reinterpret_cast<char *>(buf), test_string));
}

TEST_F(T_Compressor, EchoCompressionLong) {
  compressor = zlib::Compressor::Construct(zlib::kNoCompression);
  unsigned char *compress_buf =
    new unsigned char[compressor->DeflateBound(long_size)];
  unsigned compress_pos = 0;
  bool deflate_finished = false;
  unsigned char *input = long_string;
  size_t remaining = long_size;
  unsigned rounds = 0;

  while (!deflate_finished) {
    // Compress the output in multiple stages
    deflate_finished =
      compressor->Deflate(true, &input, &remaining, &buf, &buf_size);
    memcpy(compress_buf + compress_pos, buf, buf_size);
    compress_pos += buf_size;
    rounds++;
  }

  EXPECT_GT(rounds, 1U);
  EXPECT_GT(compress_pos, 0U);
  ASSERT_EQ(0U, remaining);

  EXPECT_EQ(compress_pos, long_size);
  EXPECT_EQ(0, memcmp(compress_buf, long_string, long_size));

  delete compress_buf;
}

}  // end namespace zlib
<|endoftext|>


<commit_before>#ifndef MJOLNIR_TEST_MAKE_EMPTY_INPUT_HPP
#define MJOLNIR_TEST_MAKE_EMPTY_INPUT_HPP
#include <extlib/toml/toml.hpp>
#include <mjolnir/util/string.hpp>

namespace mjolnir
{
namespace test
{

// make a minimal input file that contains no particle, no forcefield.
// It contains only parameters that are needed to pass read_input() functions.
inline toml::Table make_empty_input()
{
    using namespace mjolnir::literals::string_literals;

    toml::Table files;
    files["output_prefix"] = "nothing"_s;
    files["output_path"]   = "./"_s;

    toml::Table units;
    units["length"] = "angstrom"_s;
    units["energy"] = "kcal/mol"_s;

    // Mjolnir does not consider running simulation without simulator
    // (that does not make sense!) . Here, temporary set MD simulator with
    // Newtonian dynamics.
    toml::Table simulator;
    simulator["type"]          = "Molecular Dynamics"_s;
    simulator["scheme"]        = "Newtonian"_s;
    simulator["precision"]     = "double"_s;
    simulator["boundary_type"] = "Unlimited"_s;
    simulator["total_step"]    = 1;
    simulator["save_step"]     = 1;
    simulator["delta_t"]       = 0.1;

    // Mjolnir requires a system to simulate, even if it has no particle.
    toml::Table system;
    system["attributes"]     = toml::Table{{"temperature"_s, toml::value(300.0)}};
    system["boundary_shape"] = toml::Table(); // no boundary
    system["particles"]      = toml::Array(); // no particle
    toml::Array systems(1, std::move(system));

    // "empty forcefields" completely make sense because essentially any kind of
    // forcefields are a sum of several potential terms. Forcefield that has
    // zero term means an ideal system having no interaction.
    toml::Array forcefields(1, toml::Table(/* nothing! */));

    toml::Table input;
    input["files"]       = std::move(files);
    input["units"]       = std::move(units);
    input["simulator"]   = std::move(simulator);
    input["systems"]     = std::move(systems);
    input["forcefields"] = std::move(forcefields);

    return input;
}

} // test
} // mjolnir
#endif// MJOLNIR_TEST_MAKE_EMPTY_INPUT_HPP
<commit_msg>update test/make_empty_input<commit_after>#ifndef MJOLNIR_TEST_MAKE_EMPTY_INPUT_HPP
#define MJOLNIR_TEST_MAKE_EMPTY_INPUT_HPP
#include <extlib/toml/toml.hpp>
#include <mjolnir/util/string.hpp>

namespace mjolnir
{
namespace test
{

// make a minimal input file that contains no particle, no forcefield.
// It contains only parameters that are needed to pass read_input() functions.
inline toml::Table make_empty_input()
{
    using namespace mjolnir::literals::string_literals;

    toml::Table output;
    output["prefix"] = "nothing"_s;
    output["path"]   = "./"_s;

    toml::Table files;
    files["output"]  = std::move(output);

    toml::Table units;
    units["length"] = "angstrom"_s;
    units["energy"] = "kcal/mol"_s;

    // Mjolnir does not consider running simulation without simulator
    // (that does not make sense!) . Here, temporary set MD simulator with
    // Newtonian dynamics.
    toml::Table simulator;
    simulator["type"]          = "Molecular Dynamics"_s;
    simulator["scheme"]        = "Newtonian"_s;
    simulator["precision"]     = "double"_s;
    simulator["boundary_type"] = "Unlimited"_s;
    simulator["total_step"]    = 1;
    simulator["save_step"]     = 1;
    simulator["delta_t"]       = 0.1;

    // Mjolnir requires a system to simulate, even if it has no particle.
    toml::Table system;
    system["attributes"]     = toml::Table{{"temperature"_s, toml::value(300.0)}};
    system["boundary_shape"] = toml::Table(); // no boundary
    system["particles"]      = toml::Array(); // no particle
    toml::Array systems(1, std::move(system));

    // "empty forcefields" completely make sense because essentially any kind of
    // forcefields are a sum of several potential terms. Forcefield that has
    // zero term means an ideal system having no interaction.
    toml::Array forcefields(1, toml::Table(/* nothing! */));

    toml::Table input;
    input["files"]       = std::move(files);
    input["units"]       = std::move(units);
    input["simulator"]   = std::move(simulator);
    input["systems"]     = std::move(systems);
    input["forcefields"] = std::move(forcefields);

    return input;
}

} // test
} // mjolnir
#endif// MJOLNIR_TEST_MAKE_EMPTY_INPUT_HPP
<|endoftext|>


<commit_before>#include "vm_manager.h"
#include "simulator.h"
#include <boost/lexical_cast.hpp>

#include "log.h"

VMManager *VMManager::m_singleton = NULL;

void VMManager::allocate()
{
   assert (m_singleton == NULL);
   m_singleton = new VMManager();
}

void VMManager::release()
{
   delete m_singleton;
   m_singleton = NULL;
}

VMManager *VMManager::getSingleton()
{
   return m_singleton;
}

VMManager::VMManager()
{
   // FIXME: Figure out a way to get the end of the static data
   m_start_data_segment = (IntPtr) sbrk(0);
   m_end_data_segment = m_start_data_segment;

   UInt32 total_cores = Sim()->getConfig()->getTotalCores();

   UInt32 stack_size_per_core;
   try
   {
      m_start_stack_segment = (IntPtr) boost::lexical_cast <unsigned long int> (Sim()->getCfg()->get("stack/stack_base"));
      stack_size_per_core = (UInt32) boost::lexical_cast <unsigned long int> (Sim()->getCfg()->get("stack/stack_size_per_core"));
   }
   catch (boost::bad_lexical_cast &)
   {
      LOG_PRINT_ERROR("Error reading stack parameters from the config file");
      return;
   }

   // FIXME: MCP does not have a stack. Do something about this
   m_end_stack_segment = m_start_stack_segment + total_cores * stack_size_per_core;

   LOG_ASSERT_ERROR(m_end_stack_segment > m_start_stack_segment,
       "Problem with Application Stack: start_stack_segment(0x%x), end_stack_segment(0x%x)",
       m_start_stack_segment, m_end_stack_segment);

   LOG_ASSERT_ERROR(m_start_stack_segment > m_start_data_segment,
       "Problem with Application Stack: start_data_segment(0x%x), start_stack_segment(0x%x)",
       m_start_data_segment, m_start_stack_segment);

#ifdef TARGET_IA32
   m_start_dynamic_segment = 0xb0000000;
#endif

#ifdef TARGET_X86_64
   m_start_dynamic_segment = 0xf0000000;
#endif

   m_end_dynamic_segment = m_start_dynamic_segment;

   LOG_ASSERT_ERROR(m_start_dynamic_segment > m_end_stack_segment,
       "Problem with Application Stack: end_stack_segment(0x%x), start_dynamic_segment(0x%x)",
       m_end_stack_segment, m_start_dynamic_segment);
}

VMManager::~VMManager()
{
}

void *VMManager::brk(void *end_data_segment)
{
   LOG_PRINT("VMManager: brk(%p)", end_data_segment);

   if (end_data_segment == (void*) 0)
   {
      LOG_PRINT ("VMManager: brk(%p) returned %p", end_data_segment, m_end_data_segment);
      return (void*) m_end_data_segment;
   }

   LOG_ASSERT_ERROR(m_start_data_segment < ((IntPtr) end_data_segment),
       "Problem with brk() system call: start_data_segment(0x%x), end_data_segment(0x%x)",
       m_start_data_segment, (IntPtr) end_data_segment);

   LOG_ASSERT_ERROR(m_start_stack_segment > ((IntPtr) end_data_segment),
       "Problem with brk() system call: No more memory to allocate! end_data_segment(0x%x), start_stack_segment(0x%x)",
       (IntPtr) end_data_segment, m_start_stack_segment);

   m_end_data_segment = (IntPtr) end_data_segment;

   LOG_PRINT("VMManager: brk(%p) returned %p", end_data_segment, m_end_data_segment);
   return ((void*) m_end_data_segment);
}

void *VMManager::mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset)
{
   LOG_PRINT("VMManager: mmap(start = %p, length = 0x%x, flags = 0x%x, fd = %i, offset = %u)",
         start, length, flags, fd, flags);

   LOG_ASSERT_ERROR(fd == -1,
         "Mmap() system call, received valid file descriptor. Not currently supported");
   LOG_ASSERT_ERROR((flags & MAP_ANONYMOUS) == MAP_ANONYMOUS,
         "Mmap() system call, MAP_ANONYMOUS should be set in flags");
   LOG_ASSERT_ERROR((flags & MAP_FIXED) == 0,
         "Mmap() system call, MAP_FIXED should NOT be set in flags");
   LOG_ASSERT_ERROR((flags & MAP_PRIVATE) == MAP_PRIVATE,
         "Mmap() system call, MAP_PRIVATE should be set in flags");

   LOG_ASSERT_ERROR(m_end_stack_segment < (m_start_dynamic_segment - length),
         "Mmap() system call: No more memory to allocate! end_stack_segment(0x%x), start_dynamic_segment(0x%x)",
         m_end_stack_segment, m_start_dynamic_segment - length);

   m_start_dynamic_segment -= length;

   LOG_PRINT("VMManager: mmap() returned %p", (void*) m_start_dynamic_segment);
   return ((void*) m_start_dynamic_segment);
}

#ifdef TARGET_IA32
void *VMManager::mmap2(void *start, size_t length, int prot, int flags, int fd, off_t offset)
{
   LOG_PRINT("VMManager: mmap2(start = %p, length = 0x%x, flags = 0x%x)",
         start, length, (unsigned) flags);

   LOG_ASSERT_ERROR(fd == -1,
         "Mmap2() system call, received valid file descriptor. Not currently supported");
   LOG_ASSERT_ERROR((flags & MAP_ANONYMOUS) == MAP_ANONYMOUS,
         "Mmap2() system call, MAP_ANONYMOUS should be set in flags");
   LOG_ASSERT_ERROR((flags & MAP_FIXED) == 0,
         "Mmap2() system call, MAP_FIXED should NOT be set in flags");
   LOG_ASSERT_ERROR((flags & MAP_PRIVATE) == MAP_PRIVATE,
         "Mmap2() system call, MAP_PRIVATE should be set in flags");

   LOG_ASSERT_ERROR(m_end_stack_segment < (m_start_dynamic_segment - length),
         "Mmap2() system call: No more memory to allocate! end_stack_segment(0x%x), start_dynamic_segment(0x%x)",
         m_end_stack_segment, m_start_dynamic_segment - length);

   m_start_dynamic_segment -= length;

   LOG_PRINT("VMManager: mmap2() returned %p", (void*) m_start_dynamic_segment);
   return ((void*) m_start_dynamic_segment);
}
#endif

int VMManager::munmap(void *start, size_t length)
{
   LOG_PRINT("VMManager: munmap(start = %p, length = 0x%x",
         start, length);

   // Ignore for now
   LOG_ASSERT_ERROR(m_start_dynamic_segment <= ((IntPtr) start),
         "Munmap() system call, start(0x%x), start_dynamic_segment(0x%x)",
         (IntPtr) start, m_start_dynamic_segment);

   LOG_PRINT("VMManager: munmap() returned 0");
   return 0;
}
<commit_msg>[vm_manager] Changed m_start_dynamic_segment<commit_after>#include "vm_manager.h"
#include "simulator.h"
#include <boost/lexical_cast.hpp>

#include "log.h"

VMManager *VMManager::m_singleton = NULL;

void VMManager::allocate()
{
   assert (m_singleton == NULL);
   m_singleton = new VMManager();
}

void VMManager::release()
{
   delete m_singleton;
   m_singleton = NULL;
}

VMManager *VMManager::getSingleton()
{
   return m_singleton;
}

VMManager::VMManager()
{
   // FIXME: Figure out a way to get the end of the static data
   m_start_data_segment = (IntPtr) sbrk(0);
   m_end_data_segment = m_start_data_segment;

   UInt32 total_cores = Sim()->getConfig()->getTotalCores();

   UInt32 stack_size_per_core;
   try
   {
      m_start_stack_segment = (IntPtr) boost::lexical_cast <unsigned long int> (Sim()->getCfg()->get("stack/stack_base"));
      stack_size_per_core = (UInt32) boost::lexical_cast <unsigned long int> (Sim()->getCfg()->get("stack/stack_size_per_core"));
   }
   catch (boost::bad_lexical_cast &)
   {
      LOG_PRINT_ERROR("Error reading stack parameters from the config file");
      return;
   }

   // FIXME: MCP does not have a stack. Do something about this
   m_end_stack_segment = m_start_stack_segment + total_cores * stack_size_per_core;

   LOG_ASSERT_ERROR(m_end_stack_segment > m_start_stack_segment,
       "Problem with Application Stack: start_stack_segment(0x%x), end_stack_segment(0x%x)",
       m_start_stack_segment, m_end_stack_segment);

   LOG_ASSERT_ERROR(m_start_stack_segment > m_start_data_segment,
       "Problem with Application Stack: start_data_segment(0x%x), start_stack_segment(0x%x)",
       m_start_data_segment, m_start_stack_segment);

#ifdef TARGET_IA32
   m_start_dynamic_segment = 0xb0000000;
#endif

#ifdef TARGET_X86_64
   m_start_dynamic_segment = 0xf000000000;
#endif

   m_end_dynamic_segment = m_start_dynamic_segment;

   LOG_ASSERT_ERROR(m_start_dynamic_segment > m_end_stack_segment,
       "Problem with Application Stack: end_stack_segment(0x%x), start_dynamic_segment(0x%x)",
       m_end_stack_segment, m_start_dynamic_segment);
}

VMManager::~VMManager()
{
}

void *VMManager::brk(void *end_data_segment)
{
   LOG_PRINT("VMManager: brk(%p)", end_data_segment);

   if (end_data_segment == (void*) 0)
   {
      LOG_PRINT ("VMManager: brk(%p) returned %p", end_data_segment, m_end_data_segment);
      return (void*) m_end_data_segment;
   }

   LOG_ASSERT_ERROR(m_start_data_segment < ((IntPtr) end_data_segment),
       "Problem with brk() system call: start_data_segment(0x%x), end_data_segment(0x%x)",
       m_start_data_segment, (IntPtr) end_data_segment);

   LOG_ASSERT_ERROR(m_start_stack_segment > ((IntPtr) end_data_segment),
       "Problem with brk() system call: No more memory to allocate! end_data_segment(0x%x), start_stack_segment(0x%x)",
       (IntPtr) end_data_segment, m_start_stack_segment);

   m_end_data_segment = (IntPtr) end_data_segment;

   LOG_PRINT("VMManager: brk(%p) returned %p", end_data_segment, m_end_data_segment);
   return ((void*) m_end_data_segment);
}

void *VMManager::mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset)
{
   LOG_PRINT("VMManager: mmap(start = %p, length = 0x%x, flags = 0x%x, fd = %i, offset = %u)",
         start, length, flags, fd, flags);

   LOG_ASSERT_ERROR(fd == -1,
         "Mmap() system call, received valid file descriptor. Not currently supported");
   LOG_ASSERT_ERROR((flags & MAP_ANONYMOUS) == MAP_ANONYMOUS,
         "Mmap() system call, MAP_ANONYMOUS should be set in flags");
   LOG_ASSERT_ERROR((flags & MAP_FIXED) == 0,
         "Mmap() system call, MAP_FIXED should NOT be set in flags");
   LOG_ASSERT_ERROR((flags & MAP_PRIVATE) == MAP_PRIVATE,
         "Mmap() system call, MAP_PRIVATE should be set in flags");

   LOG_ASSERT_ERROR(m_end_stack_segment < (m_start_dynamic_segment - length),
         "Mmap() system call: No more memory to allocate! end_stack_segment(0x%x), start_dynamic_segment(0x%x)",
         m_end_stack_segment, m_start_dynamic_segment - length);

   m_start_dynamic_segment -= length;

   LOG_PRINT("VMManager: mmap() returned %p", (void*) m_start_dynamic_segment);
   return ((void*) m_start_dynamic_segment);
}

#ifdef TARGET_IA32
void *VMManager::mmap2(void *start, size_t length, int prot, int flags, int fd, off_t offset)
{
   LOG_PRINT("VMManager: mmap2(start = %p, length = 0x%x, flags = 0x%x)",
         start, length, (unsigned) flags);

   LOG_ASSERT_ERROR(fd == -1,
         "Mmap2() system call, received valid file descriptor. Not currently supported");
   LOG_ASSERT_ERROR((flags & MAP_ANONYMOUS) == MAP_ANONYMOUS,
         "Mmap2() system call, MAP_ANONYMOUS should be set in flags");
   LOG_ASSERT_ERROR((flags & MAP_FIXED) == 0,
         "Mmap2() system call, MAP_FIXED should NOT be set in flags");
   LOG_ASSERT_ERROR((flags & MAP_PRIVATE) == MAP_PRIVATE,
         "Mmap2() system call, MAP_PRIVATE should be set in flags");

   LOG_ASSERT_ERROR(m_end_stack_segment < (m_start_dynamic_segment - length),
         "Mmap2() system call: No more memory to allocate! end_stack_segment(0x%x), start_dynamic_segment(0x%x)",
         m_end_stack_segment, m_start_dynamic_segment - length);

   m_start_dynamic_segment -= length;

   LOG_PRINT("VMManager: mmap2() returned %p", (void*) m_start_dynamic_segment);
   return ((void*) m_start_dynamic_segment);
}
#endif

int VMManager::munmap(void *start, size_t length)
{
   LOG_PRINT("VMManager: munmap(start = %p, length = 0x%x",
         start, length);

   // Ignore for now
   LOG_ASSERT_ERROR(m_start_dynamic_segment <= ((IntPtr) start),
         "Munmap() system call, start(0x%x), start_dynamic_segment(0x%x)",
         (IntPtr) start, m_start_dynamic_segment);

   LOG_PRINT("VMManager: munmap() returned 0");
   return 0;
}
<|endoftext|>


<commit_before>/*
 * Software License Agreement (BSD License)
 *
 *  Copyright (c) 2010, Willow Garage, Inc.
 *  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.
 *   * Neither the name of Willow Garage, Inc. nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 *  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 OWNER 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.
 *
 * $Id$
 *
 */

#include <gtest/gtest.h>
#include <pcl/common/common.h>
#include <pcl/common/distances.h>
#include <pcl/common/eigen.h>
#include <pcl/point_types.h>
#include <pcl/point_cloud.h>

using namespace pcl;

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
TEST (PCL, PointXYZRGB)
{
  PointXYZRGB p;

  uint8_t r = 127, g = 64, b = 254;
  uint32_t rgb = ((uint32_t)r << 16 | (uint32_t)g << 8 | (uint32_t)b);
  p.rgb = *reinterpret_cast<float*>(&rgb);

  rgb = *reinterpret_cast<int*>(&p.rgb);
  uint8_t rr = (rgb >> 16) & 0x0000ff;
  uint8_t gg = (rgb >> 8)  & 0x0000ff;
  uint8_t bb = (rgb)       & 0x0000ff;

  EXPECT_EQ (r, rr);
  EXPECT_EQ (g, gg);
  EXPECT_EQ (b, bb);
  EXPECT_EQ (rr, 127);
  EXPECT_EQ (gg, 64);
  EXPECT_EQ (bb, 254);

  p.r = 0; p.g = 127; p.b = 0;
  rgb = *reinterpret_cast<int*>(&p.rgb);
  rr = (rgb >> 16) & 0x0000ff;
  gg = (rgb >> 8)  & 0x0000ff;
  bb = (rgb)       & 0x0000ff;

  EXPECT_EQ (rr, 0);
  EXPECT_EQ (gg, 127);
  EXPECT_EQ (bb, 0);
}

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
TEST (PCL, PointXYZRGBNormal)
{
  PointXYZRGBNormal p;

  uint8_t r = 127, g = 64, b = 254;
  uint32_t rgb = ((uint32_t)r << 16 | (uint32_t)g << 8 | (uint32_t)b);
  p.rgb = *reinterpret_cast<float*>(&rgb);

  rgb = *reinterpret_cast<int*>(&p.rgb);
  uint8_t rr = (rgb >> 16) & 0x0000ff;
  uint8_t gg = (rgb >> 8)  & 0x0000ff;
  uint8_t bb = (rgb)       & 0x0000ff;

  EXPECT_EQ (r, rr);
  EXPECT_EQ (g, gg);
  EXPECT_EQ (b, bb);
  EXPECT_EQ (rr, 127);
  EXPECT_EQ (gg, 64);
  EXPECT_EQ (bb, 254);

  p.r = 0; p.g = 127; p.b = 0;
  rgb = *reinterpret_cast<int*>(&p.rgb);
  rr = (rgb >> 16) & 0x0000ff;
  gg = (rgb >> 8)  & 0x0000ff;
  bb = (rgb)       & 0x0000ff;

  EXPECT_EQ (rr, 0);
  EXPECT_EQ (gg, 127);
  EXPECT_EQ (bb, 0);
}

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
TEST (PCL, Common)
{
  PointXYZ p1, p2, p3;
  p1.x = 1; p1.y = p1.z = 0;
  p2.y = 1; p2.x = p2.z = 0;
  p3.z = 1; p3.x = p3.y = 0;
  double radius = getCircumcircleRadius (p1, p2, p3);
  EXPECT_NEAR (radius, 0.816497, 1e-4);

  Eigen::Vector4f pt (1,0,0,0), line_pt (0,0,0,0), line_dir (1,1,0,0);
  double point2line_disance = sqrt (sqrPointToLineDistance (pt, line_pt, line_dir));
  EXPECT_NEAR (point2line_disance, sqrt(2.0)/2, 1e-4);
}

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
TEST (PCL, Eigen)
{
  Eigen::Matrix3f mat, vec;
  mat << 0.000536227, -1.56178e-05, -9.47391e-05, -1.56178e-05, 0.000297322, -0.000148785, -9.47391e-05, -0.000148785, 9.7827e-05;
  Eigen::Vector3f val;

  eigen33 (mat, vec, val);

  EXPECT_NEAR (fabs (vec (0, 0)), 0.168841, 1e-4); EXPECT_NEAR (fabs (vec (0, 1)), 0.161623, 1e-4); EXPECT_NEAR (fabs (vec (0, 2)), 0.972302, 1e-4);
  EXPECT_NEAR (fabs (vec (1, 0)), 0.451632, 1e-4); EXPECT_NEAR (fabs (vec (1, 1)), 0.889498, 1e-4); EXPECT_NEAR (fabs (vec (1, 2)), 0.0694328, 1e-4);
  EXPECT_NEAR (fabs (vec (2, 0)), 0.876082, 1e-4); EXPECT_NEAR (fabs (vec (2, 1)), 0.4274,   1e-4); EXPECT_NEAR (fabs (vec (2, 2)), 0.223178, 1e-4);

  EXPECT_NEAR (val (0), 2.86806e-06, 1e-4); EXPECT_NEAR (val (1), 0.00037165, 1e-4); EXPECT_NEAR (val (2), 0.000556858, 1e-4);

  Eigen::SelfAdjointEigenSolver<Eigen::Matrix3f> eig (mat);

  EXPECT_NEAR (eig.eigenvectors () (0, 0), -0.168841, 1e-4); EXPECT_NEAR (eig.eigenvectors () (0, 1),  0.161623, 1e-4); EXPECT_NEAR (eig.eigenvectors () (0, 2),  0.972302, 1e-4);
  EXPECT_NEAR (eig.eigenvectors () (1, 0), -0.451632, 1e-4); EXPECT_NEAR (eig.eigenvectors () (1, 1), -0.889498, 1e-4); EXPECT_NEAR (eig.eigenvectors () (1, 2),  0.0694328, 1e-4);
  EXPECT_NEAR (eig.eigenvectors () (2, 0), -0.876083, 1e-4); EXPECT_NEAR (eig.eigenvectors () (2, 1),  0.4274,   1e-4); EXPECT_NEAR (eig.eigenvectors () (2, 2), -0.223178, 1e-4);

  EXPECT_NEAR (eig.eigenvalues () (0), 2.86806e-06, 1e-4); EXPECT_NEAR (eig.eigenvalues () (1), 0.00037165, 1e-4); EXPECT_NEAR (eig.eigenvalues () (2), 0.000556858, 1e-4);

  Eigen::Vector3f eivals = mat.selfadjointView<Eigen::Lower>().eigenvalues ();

  EXPECT_NEAR (eivals (0), 2.86806e-06, 1e-4); EXPECT_NEAR (eivals (1), 0.00037165, 1e-4); EXPECT_NEAR (eivals (2), 0.000556858, 1e-4);

}

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
TEST (PCL, PointCloud)
{
  PointCloud<PointXYZ> cloud;
  cloud.width = 640;
  cloud.height = 480;

  EXPECT_EQ (cloud.isOrganized (), true);

  cloud.height = 1;
  EXPECT_EQ (cloud.isOrganized (), false);

  cloud.width = 10;
  for (uint32_t i = 0; i < cloud.width*cloud.height; ++i)
    cloud.points.push_back (PointXYZ (3*i+0,3*i+1,3*i+2));

  Eigen::MatrixXf mat_xyz1 = cloud.getMatrixXfMap();
  EXPECT_EQ (mat_xyz1.rows (), 4);
  EXPECT_EQ (mat_xyz1.cols (), cloud.width);
  EXPECT_EQ (mat_xyz1 (0,0), 0);
  EXPECT_EQ (mat_xyz1 (2,cloud.width-1), 3*cloud.width-1);

  Eigen::MatrixXf mat_xyz = cloud.getMatrixXfMap(3,4,0);
  EXPECT_EQ (mat_xyz.rows (), 3);
  EXPECT_EQ (mat_xyz.cols (), cloud.width);
  EXPECT_EQ (mat_xyz (0,0), 0);
  EXPECT_EQ (mat_xyz (2,cloud.width-1), 3*cloud.width-1);

#ifdef NDEBUG
  Eigen::MatrixXf mat_yz = cloud.getMatrixXfMap(2,4,1);
  EXPECT_EQ (mat_yz.rows (), 2);
  EXPECT_EQ (mat_yz.cols (), cloud.width);
  EXPECT_EQ (mat_yz (0,0), 1);
  EXPECT_EQ (mat_yz (1,cloud.width-1), 3*cloud.width-1);
#endif

  cloud.clear ();
  EXPECT_EQ (cloud.width, 0);
  EXPECT_EQ (cloud.height, 0);

  cloud.width = 640;
  cloud.height = 480;

  cloud.insert (cloud.end (), PointXYZ (1, 1, 1));
  EXPECT_EQ (cloud.isOrganized (), false);
  EXPECT_EQ (cloud.width, 1);

  cloud.insert (cloud.end (), 5, PointXYZ (1, 1, 1));
  EXPECT_EQ (cloud.isOrganized (), false);
  EXPECT_EQ (cloud.width, 6);

  cloud.erase (cloud.end ());
  EXPECT_EQ (cloud.isOrganized (), false);
  EXPECT_EQ (cloud.width, 5);

  cloud.erase (cloud.begin (), cloud.end ());
  EXPECT_EQ (cloud.isOrganized (), false);
  EXPECT_EQ (cloud.width, 0);
}

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
TEST (PCL, PointTypes)
{
  EXPECT_EQ (sizeof (PointXYZ), 16);
  EXPECT_EQ (__alignof (PointXYZ), 16);
  EXPECT_EQ (sizeof (PointXYZI), 32);
  EXPECT_EQ (__alignof (PointXYZI), 16);
  EXPECT_EQ (sizeof (PointXYZRGB), 32);
  EXPECT_EQ (__alignof (PointXYZRGB), 16);
  EXPECT_EQ (sizeof (PointXYZRGBA), 32);
  EXPECT_EQ (__alignof (PointXYZRGBA), 16);
  EXPECT_EQ (sizeof (Normal), 32);
  EXPECT_EQ (__alignof (Normal), 16);
  EXPECT_EQ (sizeof (PointNormal), 48);
  EXPECT_EQ (__alignof (PointNormal), 16);
  EXPECT_EQ (sizeof (PointXYZRGBNormal), 48);
  EXPECT_EQ (__alignof (PointXYZRGBNormal), 16);
}

/* ---[ */
int
main (int argc, char** argv)
{
  testing::InitGoogleTest (&argc, argv);
  return (RUN_ALL_TESTS ());
}
/* ]--- */
<commit_msg>erase the last item<commit_after>/*
 * Software License Agreement (BSD License)
 *
 *  Copyright (c) 2010, Willow Garage, Inc.
 *  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.
 *   * Neither the name of Willow Garage, Inc. nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 *  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 OWNER 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.
 *
 * $Id$
 *
 */

#include <gtest/gtest.h>
#include <pcl/common/common.h>
#include <pcl/common/distances.h>
#include <pcl/common/eigen.h>
#include <pcl/point_types.h>
#include <pcl/point_cloud.h>

using namespace pcl;

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
TEST (PCL, PointXYZRGB)
{
  PointXYZRGB p;

  uint8_t r = 127, g = 64, b = 254;
  uint32_t rgb = ((uint32_t)r << 16 | (uint32_t)g << 8 | (uint32_t)b);
  p.rgb = *reinterpret_cast<float*>(&rgb);

  rgb = *reinterpret_cast<int*>(&p.rgb);
  uint8_t rr = (rgb >> 16) & 0x0000ff;
  uint8_t gg = (rgb >> 8)  & 0x0000ff;
  uint8_t bb = (rgb)       & 0x0000ff;

  EXPECT_EQ (r, rr);
  EXPECT_EQ (g, gg);
  EXPECT_EQ (b, bb);
  EXPECT_EQ (rr, 127);
  EXPECT_EQ (gg, 64);
  EXPECT_EQ (bb, 254);

  p.r = 0; p.g = 127; p.b = 0;
  rgb = *reinterpret_cast<int*>(&p.rgb);
  rr = (rgb >> 16) & 0x0000ff;
  gg = (rgb >> 8)  & 0x0000ff;
  bb = (rgb)       & 0x0000ff;

  EXPECT_EQ (rr, 0);
  EXPECT_EQ (gg, 127);
  EXPECT_EQ (bb, 0);
}

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
TEST (PCL, PointXYZRGBNormal)
{
  PointXYZRGBNormal p;

  uint8_t r = 127, g = 64, b = 254;
  uint32_t rgb = ((uint32_t)r << 16 | (uint32_t)g << 8 | (uint32_t)b);
  p.rgb = *reinterpret_cast<float*>(&rgb);

  rgb = *reinterpret_cast<int*>(&p.rgb);
  uint8_t rr = (rgb >> 16) & 0x0000ff;
  uint8_t gg = (rgb >> 8)  & 0x0000ff;
  uint8_t bb = (rgb)       & 0x0000ff;

  EXPECT_EQ (r, rr);
  EXPECT_EQ (g, gg);
  EXPECT_EQ (b, bb);
  EXPECT_EQ (rr, 127);
  EXPECT_EQ (gg, 64);
  EXPECT_EQ (bb, 254);

  p.r = 0; p.g = 127; p.b = 0;
  rgb = *reinterpret_cast<int*>(&p.rgb);
  rr = (rgb >> 16) & 0x0000ff;
  gg = (rgb >> 8)  & 0x0000ff;
  bb = (rgb)       & 0x0000ff;

  EXPECT_EQ (rr, 0);
  EXPECT_EQ (gg, 127);
  EXPECT_EQ (bb, 0);
}

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
TEST (PCL, Common)
{
  PointXYZ p1, p2, p3;
  p1.x = 1; p1.y = p1.z = 0;
  p2.y = 1; p2.x = p2.z = 0;
  p3.z = 1; p3.x = p3.y = 0;
  double radius = getCircumcircleRadius (p1, p2, p3);
  EXPECT_NEAR (radius, 0.816497, 1e-4);

  Eigen::Vector4f pt (1,0,0,0), line_pt (0,0,0,0), line_dir (1,1,0,0);
  double point2line_disance = sqrt (sqrPointToLineDistance (pt, line_pt, line_dir));
  EXPECT_NEAR (point2line_disance, sqrt(2.0)/2, 1e-4);
}

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
TEST (PCL, Eigen)
{
  Eigen::Matrix3f mat, vec;
  mat << 0.000536227, -1.56178e-05, -9.47391e-05, -1.56178e-05, 0.000297322, -0.000148785, -9.47391e-05, -0.000148785, 9.7827e-05;
  Eigen::Vector3f val;

  eigen33 (mat, vec, val);

  EXPECT_NEAR (fabs (vec (0, 0)), 0.168841, 1e-4); EXPECT_NEAR (fabs (vec (0, 1)), 0.161623, 1e-4); EXPECT_NEAR (fabs (vec (0, 2)), 0.972302, 1e-4);
  EXPECT_NEAR (fabs (vec (1, 0)), 0.451632, 1e-4); EXPECT_NEAR (fabs (vec (1, 1)), 0.889498, 1e-4); EXPECT_NEAR (fabs (vec (1, 2)), 0.0694328, 1e-4);
  EXPECT_NEAR (fabs (vec (2, 0)), 0.876082, 1e-4); EXPECT_NEAR (fabs (vec (2, 1)), 0.4274,   1e-4); EXPECT_NEAR (fabs (vec (2, 2)), 0.223178, 1e-4);

  EXPECT_NEAR (val (0), 2.86806e-06, 1e-4); EXPECT_NEAR (val (1), 0.00037165, 1e-4); EXPECT_NEAR (val (2), 0.000556858, 1e-4);

  Eigen::SelfAdjointEigenSolver<Eigen::Matrix3f> eig (mat);

  EXPECT_NEAR (eig.eigenvectors () (0, 0), -0.168841, 1e-4); EXPECT_NEAR (eig.eigenvectors () (0, 1),  0.161623, 1e-4); EXPECT_NEAR (eig.eigenvectors () (0, 2),  0.972302, 1e-4);
  EXPECT_NEAR (eig.eigenvectors () (1, 0), -0.451632, 1e-4); EXPECT_NEAR (eig.eigenvectors () (1, 1), -0.889498, 1e-4); EXPECT_NEAR (eig.eigenvectors () (1, 2),  0.0694328, 1e-4);
  EXPECT_NEAR (eig.eigenvectors () (2, 0), -0.876083, 1e-4); EXPECT_NEAR (eig.eigenvectors () (2, 1),  0.4274,   1e-4); EXPECT_NEAR (eig.eigenvectors () (2, 2), -0.223178, 1e-4);

  EXPECT_NEAR (eig.eigenvalues () (0), 2.86806e-06, 1e-4); EXPECT_NEAR (eig.eigenvalues () (1), 0.00037165, 1e-4); EXPECT_NEAR (eig.eigenvalues () (2), 0.000556858, 1e-4);

  Eigen::Vector3f eivals = mat.selfadjointView<Eigen::Lower>().eigenvalues ();

  EXPECT_NEAR (eivals (0), 2.86806e-06, 1e-4); EXPECT_NEAR (eivals (1), 0.00037165, 1e-4); EXPECT_NEAR (eivals (2), 0.000556858, 1e-4);

}

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
TEST (PCL, PointCloud)
{
  PointCloud<PointXYZ> cloud;
  cloud.width = 640;
  cloud.height = 480;

  EXPECT_EQ (cloud.isOrganized (), true);

  cloud.height = 1;
  EXPECT_EQ (cloud.isOrganized (), false);

  cloud.width = 10;
  for (uint32_t i = 0; i < cloud.width*cloud.height; ++i)
    cloud.points.push_back (PointXYZ (3*i+0,3*i+1,3*i+2));

  Eigen::MatrixXf mat_xyz1 = cloud.getMatrixXfMap();
  EXPECT_EQ (mat_xyz1.rows (), 4);
  EXPECT_EQ (mat_xyz1.cols (), cloud.width);
  EXPECT_EQ (mat_xyz1 (0,0), 0);
  EXPECT_EQ (mat_xyz1 (2,cloud.width-1), 3*cloud.width-1);

  Eigen::MatrixXf mat_xyz = cloud.getMatrixXfMap(3,4,0);
  EXPECT_EQ (mat_xyz.rows (), 3);
  EXPECT_EQ (mat_xyz.cols (), cloud.width);
  EXPECT_EQ (mat_xyz (0,0), 0);
  EXPECT_EQ (mat_xyz (2,cloud.width-1), 3*cloud.width-1);

#ifdef NDEBUG
  Eigen::MatrixXf mat_yz = cloud.getMatrixXfMap(2,4,1);
  EXPECT_EQ (mat_yz.rows (), 2);
  EXPECT_EQ (mat_yz.cols (), cloud.width);
  EXPECT_EQ (mat_yz (0,0), 1);
  EXPECT_EQ (mat_yz (1,cloud.width-1), 3*cloud.width-1);
#endif

  cloud.clear ();
  EXPECT_EQ (cloud.width, 0);
  EXPECT_EQ (cloud.height, 0);

  cloud.width = 640;
  cloud.height = 480;

  cloud.insert (cloud.end (), PointXYZ (1, 1, 1));
  EXPECT_EQ (cloud.isOrganized (), false);
  EXPECT_EQ (cloud.width, 1);

  cloud.insert (cloud.end (), 5, PointXYZ (1, 1, 1));
  EXPECT_EQ (cloud.isOrganized (), false);
  EXPECT_EQ (cloud.width, 6);

  cloud.erase (cloud.end () - 1);
  EXPECT_EQ (cloud.isOrganized (), false);
  EXPECT_EQ (cloud.width, 5);

  cloud.erase (cloud.begin (), cloud.end ());
  EXPECT_EQ (cloud.isOrganized (), false);
  EXPECT_EQ (cloud.width, 0);
}

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
TEST (PCL, PointTypes)
{
  EXPECT_EQ (sizeof (PointXYZ), 16);
  EXPECT_EQ (__alignof (PointXYZ), 16);
  EXPECT_EQ (sizeof (PointXYZI), 32);
  EXPECT_EQ (__alignof (PointXYZI), 16);
  EXPECT_EQ (sizeof (PointXYZRGB), 32);
  EXPECT_EQ (__alignof (PointXYZRGB), 16);
  EXPECT_EQ (sizeof (PointXYZRGBA), 32);
  EXPECT_EQ (__alignof (PointXYZRGBA), 16);
  EXPECT_EQ (sizeof (Normal), 32);
  EXPECT_EQ (__alignof (Normal), 16);
  EXPECT_EQ (sizeof (PointNormal), 48);
  EXPECT_EQ (__alignof (PointNormal), 16);
  EXPECT_EQ (sizeof (PointXYZRGBNormal), 48);
  EXPECT_EQ (__alignof (PointXYZRGBNormal), 16);
}

/* ---[ */
int
main (int argc, char** argv)
{
  testing::InitGoogleTest (&argc, argv);
  return (RUN_ALL_TESTS ());
}
/* ]--- */
<|endoftext|>


<commit_before>/*
**
** Copyright (C) 2012 Aldebaran Robotics
*/

#pragma once
#ifndef _QIMESSAGING_SIGNAL_HPP_
#define _QIMESSAGING_SIGNAL_HPP_

#include <qimessaging/metafunction.hpp>
#include <qimessaging/event_loop.hpp>
#include <qimessaging/signature.hpp>

namespace qi {

  class GenericObject;
  class SignalBasePrivate;
  struct SignalSubscriber;

  class QIMESSAGING_API SignalBase
  {
  public:
    explicit SignalBase(const std::string& signature);
    ~SignalBase();

    typedef unsigned int Link;

    template<typename FUNCTION_TYPE> Link connect(FUNCTION_TYPE f,
      EventLoop* ctx = getDefaultObjectEventLoop());

    template<typename OBJECT_TYPE, typename FUNCTION_TYPE>
    Link connect(OBJECT_TYPE c, FUNCTION_TYPE f, EventLoop* ctx = getDefaultObjectEventLoop());

    Link connect(qi::GenericObject target, unsigned int slot);
    Link connect(GenericFunction callback, EventLoop* ctx = getDefaultObjectEventLoop());
    Link connect(MetaCallable callback, EventLoop* ctx = getDefaultObjectEventLoop());
    Link connect(const SignalSubscriber& s);
    bool disconnect(const Link& link);

    void trigger(const MetaFunctionParameters& params);
    void operator()(
      qi::AutoGenericValue p1 = qi::AutoGenericValue(),
      qi::AutoGenericValue p2 = qi::AutoGenericValue(),
      qi::AutoGenericValue p3 = qi::AutoGenericValue(),
      qi::AutoGenericValue p4 = qi::AutoGenericValue(),
      qi::AutoGenericValue p5 = qi::AutoGenericValue(),
      qi::AutoGenericValue p6 = qi::AutoGenericValue(),
      qi::AutoGenericValue p7 = qi::AutoGenericValue(),
      qi::AutoGenericValue p8 = qi::AutoGenericValue());

    std::vector<SignalSubscriber> subscribers();

  public:
    boost::shared_ptr<SignalBasePrivate> _p;
  };

  template<typename FUNCTION_TYPE>
  inline SignalBase::Link SignalBase::connect(FUNCTION_TYPE  callback, EventLoop* ctx)
  {
    return connect(makeGenericFunction(callback), ctx);
  }

  template<typename OBJECT_TYPE, typename FUNCTION_TYPE>
  inline SignalBase::Link SignalBase::connect(OBJECT_TYPE inst, FUNCTION_TYPE fun, EventLoop* ctx)
  {
    return connect(makeGenericFunction(inst, fun), ctx);
  }

  template<typename T>
  class Signal: public SignalBase, public boost::function<T>
  {
  public:
    Signal();
    using boost::function<T>::operator();
    inline SignalBase::Link connect(boost::function<T> f, EventLoop* ctx=getDefaultObjectEventLoop())
    {
      return SignalBase::connect(f, ctx);
    }

    template<typename OBJECT_TYPE, typename FUNCTION_TYPE>
    inline SignalBase::Link connect(OBJECT_TYPE inst, FUNCTION_TYPE fun, EventLoop* ctx=getDefaultObjectEventLoop())
    {
      return SignalBase::connect(inst, fun, ctx);
    }
  };

}

#include <qimessaging/details/signal.hxx>

QI_NO_TYPE(qi::SignalBase)

#endif
<commit_msg>Signal: Remove ambiguous overloads for connect.<commit_after>/*
**
** Copyright (C) 2012 Aldebaran Robotics
*/

#pragma once
#ifndef _QIMESSAGING_SIGNAL_HPP_
#define _QIMESSAGING_SIGNAL_HPP_

#include <qimessaging/metafunction.hpp>
#include <qimessaging/event_loop.hpp>
#include <qimessaging/signature.hpp>

namespace qi {

  class GenericObject;
  class SignalBasePrivate;
  struct SignalSubscriber;

  class QIMESSAGING_API SignalBase
  {
  public:
    explicit SignalBase(const std::string& signature);
    ~SignalBase();

    typedef unsigned int Link;

    template<typename FUNCTION_TYPE>
    Link connect(FUNCTION_TYPE f, EventLoop* ctx = getDefaultObjectEventLoop());

    Link connect(qi::GenericObject target, unsigned int slot);
    Link connect(GenericFunction callback, EventLoop* ctx = getDefaultObjectEventLoop());
    Link connect(MetaCallable callback, EventLoop* ctx = getDefaultObjectEventLoop());
    Link connect(const SignalSubscriber& s);
    bool disconnect(const Link& link);

    void trigger(const MetaFunctionParameters& params);
    void operator()(
      qi::AutoGenericValue p1 = qi::AutoGenericValue(),
      qi::AutoGenericValue p2 = qi::AutoGenericValue(),
      qi::AutoGenericValue p3 = qi::AutoGenericValue(),
      qi::AutoGenericValue p4 = qi::AutoGenericValue(),
      qi::AutoGenericValue p5 = qi::AutoGenericValue(),
      qi::AutoGenericValue p6 = qi::AutoGenericValue(),
      qi::AutoGenericValue p7 = qi::AutoGenericValue(),
      qi::AutoGenericValue p8 = qi::AutoGenericValue());

    std::vector<SignalSubscriber> subscribers();

  public:
    boost::shared_ptr<SignalBasePrivate> _p;
  };

  template<typename FUNCTION_TYPE>
  inline SignalBase::Link SignalBase::connect(FUNCTION_TYPE  callback, EventLoop* ctx)
  {
    return connect(makeGenericFunction(callback), ctx);
  }

  template<typename T>
  class Signal: public SignalBase, public boost::function<T>
  {
  public:
    Signal();
    using boost::function<T>::operator();
    inline SignalBase::Link connect(boost::function<T> f, EventLoop* ctx=getDefaultObjectEventLoop())
    {
      return SignalBase::connect(f, ctx);
    }
    inline SignalBase::Link connect(GenericFunction f, EventLoop* ctx=getDefaultObjectEventLoop())
    {
      return SignalBase::connect(f, ctx);
    }
  };

}

#include <qimessaging/details/signal.hxx>

QI_NO_TYPE(qi::SignalBase)

#endif
<|endoftext|>


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

#include <boost/algorithm/string/join.hpp>
#include <fc/log/logger.hpp>

namespace graphene { namespace utilities {

bool SendBulk(CURL *curl, std::vector<std::string>& bulk, std::string elasticsearch_url, bool do_logs, std::string logs_index)
{
  // curl buffers to read
  std::string readBuffer;
  std::string readBuffer_logs;

  std::string bulking = "";

  bulking = boost::algorithm::join(bulk, "\n");
  bulking = bulking + "\n";
  bulk.clear();

  struct curl_slist *headers = NULL;
  headers = curl_slist_append(headers, "Content-Type: application/json");
  std::string url = elasticsearch_url + "_bulk";
  curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
  curl_easy_setopt(curl, CURLOPT_POST, true);
  curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
  curl_easy_setopt(curl, CURLOPT_POSTFIELDS, bulking.c_str());
  curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
  curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&readBuffer);
  curl_easy_setopt(curl, CURLOPT_USERAGENT, "libcrp/0.1");
  //curl_easy_setopt(curl, CURLOPT_VERBOSE, true);
  curl_easy_perform(curl);

  long http_code = 0;
  curl_easy_getinfo (curl, CURLINFO_RESPONSE_CODE, &http_code);
   if(http_code == 200) {
      // all good, do nothing
   }
   else if(http_code == 413) {
      elog("413 error: Can be low space disk");
      return 0;
   }
   else {
      elog(std::to_string(http_code) + "error: Unknown error");
      return 0;
   }

  if(do_logs) {
    auto logs = readBuffer;
    // do logs
    std::string url_logs = elasticsearch_url + logs_index + "/data/";
    curl_easy_setopt(curl, CURLOPT_URL, url_logs.c_str());
    curl_easy_setopt(curl, CURLOPT_POST, true);
    curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
    curl_easy_setopt(curl, CURLOPT_POSTFIELDS, logs.c_str());
    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
    curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *) &readBuffer_logs);
    curl_easy_setopt(curl, CURLOPT_USERAGENT, "libcrp/0.1");
    curl_easy_perform(curl);

    http_code = 0;
    curl_easy_getinfo (curl, CURLINFO_RESPONSE_CODE, &http_code);
    if(http_code == 200) {
      // all good, do nothing
       return 1;
    }
    else if(http_code == 201) {
       // 201 is ok
       return 1;
    }
    else if(http_code == 409) {
       // 409 for record already exist is ok
       return 1;
    }
    else if(http_code == 413) {
       elog("413 error: Can be low space disk");
       return 0;
    }
    else {
       elog(std::to_string(http_code) + "error: Unknown error");
       return 0;
    }
  }
  return 0;
}

std::vector<std::string> createBulk(std::string index_name, std::string data, std::string id, bool onlycreate)
{
   std::vector<std::string> bulk;
   std::string create_string = "";
   if(!onlycreate)
      create_string = ",\"_id\" : "+id;

   bulk.push_back("{ \"index\" : { \"_index\" : \""+index_name+"\", \"_type\" : \"data\" "+create_string+" } }");
   bulk.push_back(data);

   return bulk;
}

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

#include <boost/algorithm/string/join.hpp>
#include <fc/log/logger.hpp>

namespace graphene { namespace utilities {

bool SendBulk(CURL *curl, std::vector<std::string>& bulk, std::string elasticsearch_url, bool do_logs, std::string logs_index)
{
  // curl buffers to read
  std::string readBuffer;
  std::string readBuffer_logs;

  std::string bulking = "";

  bulking = boost::algorithm::join(bulk, "\n");
  bulking = bulking + "\n";
  bulk.clear();

  struct curl_slist *headers = NULL;
  headers = curl_slist_append(headers, "Content-Type: application/json");
  std::string url = elasticsearch_url + "_bulk";
  curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
  curl_easy_setopt(curl, CURLOPT_POST, true);
  curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
  curl_easy_setopt(curl, CURLOPT_POSTFIELDS, bulking.c_str());
  curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
  curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&readBuffer);
  curl_easy_setopt(curl, CURLOPT_USERAGENT, "libcrp/0.1");
  //curl_easy_setopt(curl, CURLOPT_VERBOSE, true);
  curl_easy_perform(curl);

  long http_code = 0;
  curl_easy_getinfo (curl, CURLINFO_RESPONSE_CODE, &http_code);
   if(http_code == 200) {
      // all good, do nothing
   }
   else if(http_code == 413) {
      elog("413 error: Can be low space disk");
      return 0;
   }
   else {
      elog(std::to_string(http_code) + " error: Unknown error");
      return 0;
   }

  if(do_logs) {
    auto logs = readBuffer;
    // do logs
    std::string url_logs = elasticsearch_url + logs_index + "/data/";
    curl_easy_setopt(curl, CURLOPT_URL, url_logs.c_str());
    curl_easy_setopt(curl, CURLOPT_POST, true);
    curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
    curl_easy_setopt(curl, CURLOPT_POSTFIELDS, logs.c_str());
    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
    curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *) &readBuffer_logs);
    curl_easy_setopt(curl, CURLOPT_USERAGENT, "libcrp/0.1");
    curl_easy_perform(curl);

    http_code = 0;
    curl_easy_getinfo (curl, CURLINFO_RESPONSE_CODE, &http_code);
    if(http_code == 200) {
      // all good, do nothing
       return 1;
    }
    else if(http_code == 201) {
       // 201 is ok
       return 1;
    }
    else if(http_code == 409) {
       // 409 for record already exist is ok
       return 1;
    }
    else if(http_code == 413) {
       elog("413 error: Can be low space disk");
       return 0;
    }
    else {
       elog(std::to_string(http_code) + " error: Unknown error");
       return 0;
    }
  }
  return 0;
}

std::vector<std::string> createBulk(std::string index_name, std::string data, std::string id, bool onlycreate)
{
   std::vector<std::string> bulk;
   std::string create_string = "";
   if(!onlycreate)
      create_string = ",\"_id\" : "+id;

   bulk.push_back("{ \"index\" : { \"_index\" : \""+index_name+"\", \"_type\" : \"data\" "+create_string+" } }");
   bulk.push_back(data);

   return bulk;
}

} } // end namespace graphene::utilities
<|endoftext|>


<commit_before>/********************************************************************************
    LibVideoGfx - video processing library
    Copyright (C) 2002  Dirk Farin

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

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

    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 ********************************************************************************/

#include "config.h"

#include <time.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>

#include <iostream>
#include <iomanip>
using namespace std;

#include <X11/Xlib.h>
#include <X11/extensions/XShm.h>
#include <X11/Xutil.h>

#if HAVE_XV
#include <X11/extensions/Xvlib.h>
#endif

#include "libvideogfx/init.hh"

#include "server.hh"
#include "imgwin.hh"

namespace videogfx {

  struct X11SpecificData
  {
    Display*  d_display;
    Window    d_win;
  };

  ImageWindow_X11::ImageWindow_X11()
    : d_initialized(false),
      d_server(NULL),
      d_xpos(-1),d_ypos(-1)
  {
    d_x11data = new X11SpecificData;
  }

  ImageWindow_X11::~ImageWindow_X11()
  {
    //printf("ImageWindow_X11::~ImageWindow_X11()\n");
    Close();

    if (d_x11data) { delete d_x11data; d_x11data=NULL; }
    if (d_server) delete d_server;
  }

  void ImageWindow_X11::Close()
  {
    if (!d_initialized)
      return;

    XUnmapWindow(d_x11data->d_display , d_x11data->d_win);
    XFlush(d_x11data->d_display);
    d_initialized=false;
  }

  Window   ImageWindow_X11::AskWindow()  { assert(d_initialized); return d_x11data->d_win; }
  Display* ImageWindow_X11::AskDisplay() { return d_x11data->d_display; }

  void ImageWindow_X11::Create(int w,int h,const char* title,X11Server* server,Window parent)
  {
    assert(!d_initialized);

    // Get X11 server.

    if (d_server) delete d_server;

    if (server)
      d_server = new X11ServerConnection(server);
    else
      d_server = new X11ServerConnection;

    d_x11data->d_display = d_server->AskDisplay();

    int screen = DefaultScreen(d_x11data->d_display);
    Window rootwin = RootWindow(d_x11data->d_display,screen);

    // Choose VisualInfo

    XVisualInfo vinfo;
    //bool use_cmap8=false;

    if (XMatchVisualInfo(d_x11data->d_display, screen, 16, TrueColor, &vinfo))
      {
      }
    else
      if (XMatchVisualInfo(d_x11data->d_display, screen, 15, TrueColor, &vinfo))
	{
	}
      else
	if (XMatchVisualInfo(d_x11data->d_display, screen, 24, TrueColor, &vinfo))
	  {
	  }
	else
	  if (XMatchVisualInfo(d_x11data->d_display, screen, 32, TrueColor, &vinfo))
	    {
	    }
	  else
	    if (XMatchVisualInfo(d_x11data->d_display, screen,  8, PseudoColor, &vinfo))
	      {
		// use_cmap8=true;
	      }
	    else
	      if (XMatchVisualInfo(d_x11data->d_display, screen,  4, StaticGray, &vinfo))
		{
		}
#if 0
	      else
		if (XMatchVisualInfo(d_x11data->d_display, screen,  8, GrayScale, &vinfo))
		  {
		  }
#endif
		else
		  {
		    // TODO
		    cerr << "no matching visual found\n";
		    exit(10);
		    // throw Excpt_Base(ErrSev_Error,"I'm sorry, no matching visual info found.");
		  }

    //cout << "VISUAL-ID used for window: 0x" << hex << vinfo.visualid << dec << endl;

    // Create window

    Colormap theCmap = XCreateColormap(d_x11data->d_display, rootwin, vinfo.visual, AllocNone);

    XSetWindowAttributes attr;
    attr.colormap = theCmap;
    attr.background_pixel = 0;
    attr.border_pixel     = 1;

    Window parent_window;

#if 1
    if (parent)
      parent_window = parent;
    else
#endif
      parent_window = RootWindow(d_x11data->d_display,screen);

    //printf("WINID: %d %p\n",parent,parent);

    d_x11data->d_win = XCreateWindow(d_x11data->d_display, parent_window,
				     d_xpos,d_ypos,w,h, 2, vinfo.depth, InputOutput, vinfo.visual,
				     CWBackPixel|CWBorderPixel|CWColormap,&attr);

    XSizeHints* sizeh;
    if (!(sizeh = XAllocSizeHints()))
      { fprintf(stderr,"cannot allocate XSizeHints structure\n"); exit(0); }

    XWMHints* wm_hints;
    if (!(wm_hints = XAllocWMHints()))
      { fprintf(stderr,"cannot allocate XWMHints structure\n"); exit(0); }

    XClassHint* classhint;
    if (!(classhint = XAllocClassHint()))
      { fprintf(stderr,"cannot allocate XClassHint structure\n"); exit(0); }

    sizeh->flags |= PPosition|PSize|PMinSize|PMaxSize;
    sizeh->width  = w;
    sizeh->height = h;
    sizeh->min_width  = w;
    sizeh->min_height = h;
    sizeh->max_width  = w;
    sizeh->max_height = h;

    XTextProperty windowName, iconName;

    if (XStringListToTextProperty((char**)&title,1,&windowName)==0)
      { fprintf(stderr,"cannot allocate structure for windowName\n"); exit(0); }

    if (XStringListToTextProperty((char**)&title,1,&iconName)==0)
      { fprintf(stderr,"cannot allocate structure for iconName\n"); exit(0); }

    wm_hints->initial_state = NormalState;
    wm_hints->input = True;
    wm_hints->flags = StateHint | InputHint;

    classhint->res_name  = NULL;
    classhint->res_class = "Libvideogfx";

    XSetWMProperties(d_x11data->d_display, d_x11data->d_win, &windowName, &iconName,
		     glob_argv,glob_argc, sizeh, wm_hints, classhint);

    XSelectInput(d_x11data->d_display, d_x11data->d_win, ExposureMask|KeyPressMask|PointerMotionMask);
    XMapWindow(d_x11data->d_display,d_x11data->d_win);
    XFlush(d_x11data->d_display);

    while (1)
      {
	XEvent xev;
	XNextEvent(d_x11data->d_display,&xev);

	if (xev.type == Expose)
	  break;
      }

    // Set Colormap

    // TODO

    d_initialized = true;
  }

  ImageWindow_Autorefresh_X11::ImageWindow_Autorefresh_X11(bool useXv)
    : d_dispimg(NULL),
      d_rgbtransform(NULL)
  {
    d_dispimg = new DisplayImage_X11;
    d_dispimg->UseXv(useXv);

    if (!useXv)
      d_rgbtransform = new Image2RawRGB;
    else
      d_rgbtransform = NULL;
  }

  ImageWindow_Autorefresh_X11::~ImageWindow_Autorefresh_X11()
  {
    delete d_dispimg;
    if (d_rgbtransform) delete d_rgbtransform;
  }

  void ImageWindow_Autorefresh_X11::Create(int w,int h,const char*title,X11Server* server,Window win)
  {
    ImageWindow_X11::Create(w,h,title,server,win);

    d_dispimg->Create(w,h,AskWindow(),server);

    // set output specs for RGB transformation

    if (d_rgbtransform)
      {
	XImage& ximg = d_dispimg->AskXImage();

	RawRGBImageSpec spec;
	spec.bytes_per_line = ximg.bytes_per_line;
	spec.bits_per_pixel = ximg.bits_per_pixel;
	spec.little_endian  = (ximg.byte_order==LSBFirst);
	spec.SetRGBMasks(ximg.red_mask,ximg.green_mask,ximg.blue_mask);

	d_rgbtransform->SetOutputSpec(spec);
      }
  }

  void ImageWindow_Autorefresh_X11::Close()
  {
    ImageWindow_X11::Close();
  }

  void ImageWindow_Autorefresh_X11::Display(const Image<Pixel>& img)
  {
#if HAVE_XV
    if (d_dispimg->UsesXv())
      {
	Assert(img.AskParam().colorspace == Colorspace_YUV);

	XvImage* xvimg = (XvImage*)d_dispimg->AskXvImage();

	const Pixel*const* yp = img.AskFrameY();
	const Pixel*const* up = img.AskFrameU();
	const Pixel*const* vp = img.AskFrameV();

	int w = img.AskWidth();
	int h = img.AskHeight();
	int rw = (w+15) & ~0xF;

	ImageParam param = img.AskParam();

	int cw,ch;
	param.AskChromaSizes(cw,ch);
	int rcw = (cw+7) & ~0x7;

	for (int y=0;y<h;y++)
	  memcpy(&xvimg->data[rw*y],yp[y],w);

	for (int y=0;y<ch;y++)
	  memcpy(&xvimg->data[rw*h+rcw*y],vp[y],cw);

	for (int y=0;y<ch;y++)
	  memcpy(&xvimg->data[rw*h+rcw*ch+rcw*y],up[y],cw);

	d_dispimg->PutImage();
      }
    else
#endif
      {
	d_rgbtransform->Transform(img,(uint8*)(d_dispimg->AskXImage().data));
	d_dispimg->PutImage();
      }
  }

  void ImageWindow_Autorefresh_X11::CheckForRedraw()
  {
    XEvent event;
    while (XCheckWindowEvent(AskDisplay(),AskWindow(),ExposureMask,&event))
      {
	Redraw(event.xexpose);
      }
  }

  void ImageWindow_Autorefresh_X11::RedrawForever()
  {
    XEvent event;
    for (;;)
      {
	XWindowEvent(AskDisplay(),AskWindow(),ExposureMask,&event);
	Redraw(event.xexpose);
      }
  }

  bool ImageWindow_Autorefresh_X11::CheckForMouseMove(int& x,int& y)
  {
    XEvent event;
    if (XCheckWindowEvent(AskDisplay(),AskWindow(),PointerMotionMask,&event))
      {
	x = event.xmotion.x;
	y = event.xmotion.y;
	return true;
      }
    else
      return false;
  }

  char ImageWindow_Autorefresh_X11::CheckForKeypress()
  {
    XEvent event;
    if (XCheckWindowEvent(AskDisplay(),AskWindow(),KeyPressMask,&event))
      {
	char buf;

	if (XLookupString(&event.xkey,&buf,1,NULL,NULL) > 0)
	  return buf;
	else
	  return 0;
      }
    else
      return 0;
  }

  char ImageWindow_Autorefresh_X11::WaitForKeypress()
  {
    XEvent event;

    for (;;)
      {
	XWindowEvent(AskDisplay(),AskWindow(),KeyPressMask|ExposureMask,&event);

	if (event.type == Expose)
	  {
	    Redraw(event.xexpose);
	  }
	else
	  {
	    char buf;

	    if (XLookupString(&event.xkey,&buf,1,NULL,NULL) > 0)
	      return buf;
	    else
	      return 0;
	  }
      }
  }

  void ImageWindow_Autorefresh_X11::Redraw(XExposeEvent& ev)
  {
    d_dispimg->PutImage(ev.x     , ev.y,
			ev.width , ev.height,
			ev.x     , ev.y);
  }

  /* All windows have to be on the same X-server.
   */
  int MultiWindowRefresh(ImageWindow_Autorefresh_X11*const* windows,int nWindows)
  {
    XEvent ev;
    bool refresh_occured=false;

    while (!refresh_occured)
      {
	XMaskEvent(windows[0]->AskDisplay(),ExposureMask|KeyPressMask,&ev);
	for (int i=0;i<nWindows;i++)
	  {
	    if (ev.xany.window == windows[i]->AskWindow())
	      {
		if (ev.type == Expose)
		  {
		    windows[i]->Redraw(ev.xexpose);
		    refresh_occured=true;
		  }
		else if (ev.type == KeyPress)
		  return i;
	      }
	  }
      }

    return -1;
  }

  void DisplayX11(const Image<Pixel>& img, int wait_usecs)
  {
    int w=img.AskWidth(), h=img.AskHeight();
    ImageWindow_Autorefresh_X11 win;
    win.Create(w,h,"libvideogfx (c) Dirk Farin");
    win.Display(img);
    if (wait_usecs) usleep(wait_usecs); else win.WaitForKeypress();
  }
}
<commit_msg>only quit if 'q' is pressed<commit_after>/********************************************************************************
    LibVideoGfx - video processing library
    Copyright (C) 2002  Dirk Farin

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

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

    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 ********************************************************************************/

#include "config.h"

#include <time.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>

#include <iostream>
#include <iomanip>
using namespace std;

#include <X11/Xlib.h>
#include <X11/extensions/XShm.h>
#include <X11/Xutil.h>

#if HAVE_XV
#include <X11/extensions/Xvlib.h>
#endif

#include "libvideogfx/init.hh"

#include "server.hh"
#include "imgwin.hh"

namespace videogfx {

  struct X11SpecificData
  {
    Display*  d_display;
    Window    d_win;
  };

  ImageWindow_X11::ImageWindow_X11()
    : d_initialized(false),
      d_server(NULL),
      d_xpos(-1),d_ypos(-1)
  {
    d_x11data = new X11SpecificData;
  }

  ImageWindow_X11::~ImageWindow_X11()
  {
    //printf("ImageWindow_X11::~ImageWindow_X11()\n");
    Close();

    if (d_x11data) { delete d_x11data; d_x11data=NULL; }
    if (d_server) delete d_server;
  }

  void ImageWindow_X11::Close()
  {
    if (!d_initialized)
      return;

    XUnmapWindow(d_x11data->d_display , d_x11data->d_win);
    XFlush(d_x11data->d_display);
    d_initialized=false;
  }

  Window   ImageWindow_X11::AskWindow()  { assert(d_initialized); return d_x11data->d_win; }
  Display* ImageWindow_X11::AskDisplay() { return d_x11data->d_display; }

  void ImageWindow_X11::Create(int w,int h,const char* title,X11Server* server,Window parent)
  {
    assert(!d_initialized);

    // Get X11 server.

    if (d_server) delete d_server;

    if (server)
      d_server = new X11ServerConnection(server);
    else
      d_server = new X11ServerConnection;

    d_x11data->d_display = d_server->AskDisplay();

    int screen = DefaultScreen(d_x11data->d_display);
    Window rootwin = RootWindow(d_x11data->d_display,screen);

    // Choose VisualInfo

    XVisualInfo vinfo;
    //bool use_cmap8=false;

    if (XMatchVisualInfo(d_x11data->d_display, screen, 16, TrueColor, &vinfo))
      {
      }
    else
      if (XMatchVisualInfo(d_x11data->d_display, screen, 15, TrueColor, &vinfo))
	{
	}
      else
	if (XMatchVisualInfo(d_x11data->d_display, screen, 24, TrueColor, &vinfo))
	  {
	  }
	else
	  if (XMatchVisualInfo(d_x11data->d_display, screen, 32, TrueColor, &vinfo))
	    {
	    }
	  else
	    if (XMatchVisualInfo(d_x11data->d_display, screen,  8, PseudoColor, &vinfo))
	      {
		// use_cmap8=true;
	      }
	    else
	      if (XMatchVisualInfo(d_x11data->d_display, screen,  4, StaticGray, &vinfo))
		{
		}
#if 0
	      else
		if (XMatchVisualInfo(d_x11data->d_display, screen,  8, GrayScale, &vinfo))
		  {
		  }
#endif
		else
		  {
		    // TODO
		    cerr << "no matching visual found\n";
		    exit(10);
		    // throw Excpt_Base(ErrSev_Error,"I'm sorry, no matching visual info found.");
		  }

    //cout << "VISUAL-ID used for window: 0x" << hex << vinfo.visualid << dec << endl;

    // Create window

    Colormap theCmap = XCreateColormap(d_x11data->d_display, rootwin, vinfo.visual, AllocNone);

    XSetWindowAttributes attr;
    attr.colormap = theCmap;
    attr.background_pixel = 0;
    attr.border_pixel     = 1;

    Window parent_window;

#if 1
    if (parent)
      parent_window = parent;
    else
#endif
      parent_window = RootWindow(d_x11data->d_display,screen);

    //printf("WINID: %d %p\n",parent,parent);

    d_x11data->d_win = XCreateWindow(d_x11data->d_display, parent_window,
				     d_xpos,d_ypos,w,h, 2, vinfo.depth, InputOutput, vinfo.visual,
				     CWBackPixel|CWBorderPixel|CWColormap,&attr);

    XSizeHints* sizeh;
    if (!(sizeh = XAllocSizeHints()))
      { fprintf(stderr,"cannot allocate XSizeHints structure\n"); exit(0); }

    XWMHints* wm_hints;
    if (!(wm_hints = XAllocWMHints()))
      { fprintf(stderr,"cannot allocate XWMHints structure\n"); exit(0); }

    XClassHint* classhint;
    if (!(classhint = XAllocClassHint()))
      { fprintf(stderr,"cannot allocate XClassHint structure\n"); exit(0); }

    sizeh->flags |= PPosition|PSize|PMinSize|PMaxSize;
    sizeh->width  = w;
    sizeh->height = h;
    sizeh->min_width  = w;
    sizeh->min_height = h;
    sizeh->max_width  = w;
    sizeh->max_height = h;

    XTextProperty windowName, iconName;

    if (XStringListToTextProperty((char**)&title,1,&windowName)==0)
      { fprintf(stderr,"cannot allocate structure for windowName\n"); exit(0); }

    if (XStringListToTextProperty((char**)&title,1,&iconName)==0)
      { fprintf(stderr,"cannot allocate structure for iconName\n"); exit(0); }

    wm_hints->initial_state = NormalState;
    wm_hints->input = True;
    wm_hints->flags = StateHint | InputHint;

    classhint->res_name  = NULL;
    classhint->res_class = "Libvideogfx";

    XSetWMProperties(d_x11data->d_display, d_x11data->d_win, &windowName, &iconName,
		     glob_argv,glob_argc, sizeh, wm_hints, classhint);

    XSelectInput(d_x11data->d_display, d_x11data->d_win, ExposureMask|KeyPressMask|PointerMotionMask);
    XMapWindow(d_x11data->d_display,d_x11data->d_win);
    XFlush(d_x11data->d_display);

    while (1)
      {
	XEvent xev;
	XNextEvent(d_x11data->d_display,&xev);

	if (xev.type == Expose)
	  break;
      }

    // Set Colormap

    // TODO

    d_initialized = true;
  }

  ImageWindow_Autorefresh_X11::ImageWindow_Autorefresh_X11(bool useXv)
    : d_dispimg(NULL),
      d_rgbtransform(NULL)
  {
    d_dispimg = new DisplayImage_X11;
    d_dispimg->UseXv(useXv);

    if (!useXv)
      d_rgbtransform = new Image2RawRGB;
    else
      d_rgbtransform = NULL;
  }

  ImageWindow_Autorefresh_X11::~ImageWindow_Autorefresh_X11()
  {
    delete d_dispimg;
    if (d_rgbtransform) delete d_rgbtransform;
  }

  void ImageWindow_Autorefresh_X11::Create(int w,int h,const char*title,X11Server* server,Window win)
  {
    ImageWindow_X11::Create(w,h,title,server,win);

    d_dispimg->Create(w,h,AskWindow(),server);

    // set output specs for RGB transformation

    if (d_rgbtransform)
      {
	XImage& ximg = d_dispimg->AskXImage();

	RawRGBImageSpec spec;
	spec.bytes_per_line = ximg.bytes_per_line;
	spec.bits_per_pixel = ximg.bits_per_pixel;
	spec.little_endian  = (ximg.byte_order==LSBFirst);
	spec.SetRGBMasks(ximg.red_mask,ximg.green_mask,ximg.blue_mask);

	d_rgbtransform->SetOutputSpec(spec);
      }
  }

  void ImageWindow_Autorefresh_X11::Close()
  {
    ImageWindow_X11::Close();
  }

  void ImageWindow_Autorefresh_X11::Display(const Image<Pixel>& img)
  {
#if HAVE_XV
    if (d_dispimg->UsesXv())
      {
	Assert(img.AskParam().colorspace == Colorspace_YUV);

	XvImage* xvimg = (XvImage*)d_dispimg->AskXvImage();

	const Pixel*const* yp = img.AskFrameY();
	const Pixel*const* up = img.AskFrameU();
	const Pixel*const* vp = img.AskFrameV();

	int w = img.AskWidth();
	int h = img.AskHeight();
	int rw = (w+15) & ~0xF;

	ImageParam param = img.AskParam();

	int cw,ch;
	param.AskChromaSizes(cw,ch);
	int rcw = (cw+7) & ~0x7;

	for (int y=0;y<h;y++)
	  memcpy(&xvimg->data[rw*y],yp[y],w);

	for (int y=0;y<ch;y++)
	  memcpy(&xvimg->data[rw*h+rcw*y],vp[y],cw);

	for (int y=0;y<ch;y++)
	  memcpy(&xvimg->data[rw*h+rcw*ch+rcw*y],up[y],cw);

	d_dispimg->PutImage();
      }
    else
#endif
      {
	d_rgbtransform->Transform(img,(uint8*)(d_dispimg->AskXImage().data));
	d_dispimg->PutImage();
      }
  }

  void ImageWindow_Autorefresh_X11::CheckForRedraw()
  {
    XEvent event;
    while (XCheckWindowEvent(AskDisplay(),AskWindow(),ExposureMask,&event))
      {
	Redraw(event.xexpose);
      }
  }

  void ImageWindow_Autorefresh_X11::RedrawForever()
  {
    XEvent event;
    for (;;)
      {
	XWindowEvent(AskDisplay(),AskWindow(),ExposureMask,&event);
	Redraw(event.xexpose);
      }
  }

  bool ImageWindow_Autorefresh_X11::CheckForMouseMove(int& x,int& y)
  {
    XEvent event;
    if (XCheckWindowEvent(AskDisplay(),AskWindow(),PointerMotionMask,&event))
      {
	x = event.xmotion.x;
	y = event.xmotion.y;
	return true;
      }
    else
      return false;
  }

  char ImageWindow_Autorefresh_X11::CheckForKeypress()
  {
    XEvent event;
    if (XCheckWindowEvent(AskDisplay(),AskWindow(),KeyPressMask,&event))
      {
	char buf;

	if (XLookupString(&event.xkey,&buf,1,NULL,NULL) > 0)
	  return buf;
	else
	  return 0;
      }
    else
      return 0;
  }

  char ImageWindow_Autorefresh_X11::WaitForKeypress()
  {
    XEvent event;

    for (;;)
      {
	XWindowEvent(AskDisplay(),AskWindow(),KeyPressMask|ExposureMask,&event);

	if (event.type == Expose)
	  {
	    Redraw(event.xexpose);
	  }
	else
	  {
	    char buf;

	    if (XLookupString(&event.xkey,&buf,1,NULL,NULL) > 0)
	      return buf;
	    else
	      return 0;
	  }
      }
  }

  void ImageWindow_Autorefresh_X11::Redraw(XExposeEvent& ev)
  {
    d_dispimg->PutImage(ev.x     , ev.y,
			ev.width , ev.height,
			ev.x     , ev.y);
  }

  /* All windows have to be on the same X-server.
   */
  int MultiWindowRefresh(ImageWindow_Autorefresh_X11*const* windows,int nWindows)
  {
    XEvent ev;
    bool refresh_occured=false;

    while (!refresh_occured)
      {
	XMaskEvent(windows[0]->AskDisplay(),ExposureMask|KeyPressMask,&ev);
	for (int i=0;i<nWindows;i++)
	  {
	    if (ev.xany.window == windows[i]->AskWindow())
	      {
		if (ev.type == Expose)
		  {
		    windows[i]->Redraw(ev.xexpose);
		    refresh_occured=true;
		  }
		else if (ev.type == KeyPress)
		  return i;
	      }
	  }
      }

    return -1;
  }

  void DisplayX11(const Image<Pixel>& img, int wait_usecs)
  {
    int w=img.AskWidth(), h=img.AskHeight();
    ImageWindow_Autorefresh_X11 win;
    win.Create(w,h,"libvideogfx (c) Dirk Farin");
    win.Display(img);
    if (wait_usecs) usleep(wait_usecs); else while (win.WaitForKeypress() != 'q') { }
  }
}
<|endoftext|>