<commit_before>/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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.
 */

/*
 * $Id$
 */

#if !defined(XERCESC_INCLUDE_GUARD_XMLBUFFER_HPP)
#define XERCESC_INCLUDE_GUARD_XMLBUFFER_HPP

#include <xercesc/util/XMemory.hpp>
#include <xercesc/util/PlatformUtils.hpp>
#include <xercesc/framework/MemoryManager.hpp>
#include <string.h>

XERCES_CPP_NAMESPACE_BEGIN

class XMLBufferFullHandler;

/**
 *  XMLBuffer is a lightweight, expandable Unicode text buffer. Since XML is
 *  inherently theoretically unbounded in terms of the sizes of things, we
 *  very often need to have expandable buffers. The primary concern here is
 *  that appends of characters and other buffers or strings be very fast, so
 *  it always maintains the current buffer size.
 *
 *  The buffer is not null terminated until some asks to see the raw buffer
 *  contents. This also avoids overhead during append operations.
 */
class XMLPARSER_EXPORT XMLBuffer : public XMemory
{
public :
    // -----------------------------------------------------------------------
    //  Constructors and Destructor
    // -----------------------------------------------------------------------

    /** @name Constructor */
    //@{
    XMLBuffer(const XMLSize_t capacity = 1023
              , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager) :

        fIndex(0)
        , fCapacity(capacity)
        , fFullSize(0)
        , fUsed(false)
        , fMemoryManager(manager)
        , fFullHandler(0)
        , fBuffer(0)
    {
        // Buffer is one larger than capacity, to allow for zero term
        fBuffer = (XMLCh*) manager->allocate((capacity+1) * sizeof(XMLCh)); //new XMLCh[fCapacity+1];

        // Keep it null terminated
        fBuffer[0] = XMLCh(0);
    }
    //@}

    /** @name Destructor */
    //@{
    ~XMLBuffer()
    {
        fMemoryManager->deallocate(fBuffer); //delete [] fBuffer;
    }
    //@}

    // -----------------------------------------------------------------------
    //  Buffer Full Handler Management
    // -----------------------------------------------------------------------
    void setFullHandler(XMLBufferFullHandler* handler, const XMLSize_t fullSize)
    {
        if (handler && fullSize) {
            fFullHandler = handler;
            fFullSize = fullSize;

            // Need to consider the case that the fullsize is less than the current capacity.
            // For example, say fullSize = 100 and fCapacity is 1023 (the default).
            // If the fIndex is less than the fullSize, then no problem.  We can just carry
            // on by resetting fCapacity to fullsize and proceed business as usual.
            // If the fIndex is already bigger than the fullSize then we call insureCapacity
            // to see if it can handle emptying the current buffer (it will throw an
            // exception if it can't).
            if (fullSize < fCapacity) {
                fCapacity = fullSize;
                if (fIndex >= fullSize) {
                    insureCapacity(0);
                }
            }
        }
        else {
            // reset fFullHandler to zero because setFullHandler had bad input
            fFullHandler = 0;
        }
    }

    // -----------------------------------------------------------------------
    //  Buffer Management
    // -----------------------------------------------------------------------
    void append(const XMLCh toAppend)
    {
        // Put in char and bump the index
        if (fIndex == fCapacity)
            insureCapacity(1);
        fBuffer[fIndex++] = toAppend;
    }

    void append (const XMLCh* const chars, const XMLSize_t count)
    {
        if (count) {
            if (fIndex + count >= fCapacity) {
                insureCapacity(count);
            }
            memcpy(&fBuffer[fIndex], chars, count * sizeof(XMLCh));
            fIndex += count;
        }
        else {
            append(chars);
        }
    }

    void append (const XMLCh* const chars)
    {
        if (chars != 0 && *chars != 0) {
            // get length of chars
            XMLSize_t count = 0;
            for (; *(chars+count); count++ );

            if (fIndex + count >= fCapacity) {
                insureCapacity(count);
            }
            memcpy(&fBuffer[fIndex], chars, count * sizeof(XMLCh));
            fIndex += count;
        }
    }

    void set (const XMLCh* const chars, const XMLSize_t count)
    {
        fIndex = 0;
        append(chars, count);
    }

    void set (const XMLCh* const chars)
    {
        fIndex = 0;
        if (chars != 0 && *chars != 0)
            append(chars);
    }

    const XMLCh* getRawBuffer() const
    {
        fBuffer[fIndex] = 0;
        return fBuffer;
    }

    XMLCh* getRawBuffer()
    {
        fBuffer[fIndex] = 0;
        return fBuffer;
    }

    void reset()
    {
        fIndex = 0;
    }

    // -----------------------------------------------------------------------
    //  Getters
    // -----------------------------------------------------------------------
    bool getInUse() const
    {
        return fUsed;
    }

    XMLSize_t getLen() const
    {
        return fIndex;
    }

    bool isEmpty() const
    {
        return (fIndex == 0);
    }

    // -----------------------------------------------------------------------
    //  Setters
    // -----------------------------------------------------------------------
    void setInUse(const bool newValue)
    {
        fUsed = newValue;
    }

private :
    // -----------------------------------------------------------------------
    //  Unimplemented constructors and operators
    // -----------------------------------------------------------------------
    XMLBuffer(const XMLBuffer&);
    XMLBuffer& operator=(const XMLBuffer&);

    // -----------------------------------------------------------------------
    //  Declare our friends
    // -----------------------------------------------------------------------
    friend class XMLBufBid;

    // -----------------------------------------------------------------------
    //  Private helpers
    // -----------------------------------------------------------------------
    void insureCapacity(const XMLSize_t extraNeeded);

    // -----------------------------------------------------------------------
    //  Private data members
    //
    //  fBuffer
    //      The pointer to the buffer data. Its grown as needed. Its always
    //      one larger than fCapacity, to leave room for the null terminator.
    //
    //  fIndex
    //      The current index into the buffer, as characters are appended
    //      to it. If its zero, then the buffer is empty.
    //
    //  fCapacity
    //      The current capacity of the buffer. Its actually always one
    //      larger, to leave room for the null terminator.
    //
    //  fUsed
    //      Indicates whether this buffer is in use or not.
    //
    //  fFullHandler, fFullSize
    //      If fFullHandler is non-null, the buffer has a maximum size
    //      indicated by fFullSize. If writing to the buffer would exceed the
    //      buffer's maximum size, fFullHandler's bufferFull callback is
    //      invoked, to empty the buffer.
    // -----------------------------------------------------------------------
    XMLSize_t                   fIndex;
    XMLSize_t                   fCapacity;
    XMLSize_t                   fFullSize;
    bool                        fUsed;
    MemoryManager* const        fMemoryManager;
    XMLBufferFullHandler*       fFullHandler;
    XMLCh*                      fBuffer;
};

/**
 *  XMLBufferFullHandler is a callback interface for clients of
 *  XMLBuffers that impose a size restriction (e.g. XMLScanner).
 *  Note that this is intended solely as a mix-in for internal
 *  use, and therefore does not derive from XMemory (to avoid
 *  the ambiguous base class problem).
 */
class XMLPARSER_EXPORT XMLBufferFullHandler
{
public :

    virtual ~XMLBufferFullHandler() {}

    /**
     * Callback method, intended to allow clients of an XMLBuffer which has
     * become full to empty it appropriately.
     * @return true if the handler was able to empty the buffer (either
     * partially or completely), otherwise false to indicate an error.
     */
    virtual bool bufferFull(XMLBuffer&) = 0;

};

XERCES_CPP_NAMESPACE_END

#endif
<commit_msg>Suppress new warnings introduced in g++ 4.3.<commit_after>/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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.
 */

/*
 * $Id$
 */

#if !defined(XERCESC_INCLUDE_GUARD_XMLBUFFER_HPP)
#define XERCESC_INCLUDE_GUARD_XMLBUFFER_HPP

#include <xercesc/util/XMemory.hpp>
#include <xercesc/util/PlatformUtils.hpp>
#include <xercesc/framework/MemoryManager.hpp>
#include <string.h>

XERCES_CPP_NAMESPACE_BEGIN

class XMLBufferFullHandler;

/**
 *  XMLBuffer is a lightweight, expandable Unicode text buffer. Since XML is
 *  inherently theoretically unbounded in terms of the sizes of things, we
 *  very often need to have expandable buffers. The primary concern here is
 *  that appends of characters and other buffers or strings be very fast, so
 *  it always maintains the current buffer size.
 *
 *  The buffer is not null terminated until some asks to see the raw buffer
 *  contents. This also avoids overhead during append operations.
 */
class XMLPARSER_EXPORT XMLBuffer : public XMemory
{
public :
    // -----------------------------------------------------------------------
    //  Constructors and Destructor
    // -----------------------------------------------------------------------

    /** @name Constructor */
    //@{
    XMLBuffer(const XMLSize_t capacity = 1023
              , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager) :

        fIndex(0)
        , fCapacity(capacity)
        , fFullSize(0)
        , fUsed(false)
        , fMemoryManager(manager)
        , fFullHandler(0)
        , fBuffer(0)
    {
        // Buffer is one larger than capacity, to allow for zero term
        fBuffer = (XMLCh*) manager->allocate((capacity+1) * sizeof(XMLCh)); //new XMLCh[fCapacity+1];

        // Keep it null terminated
        fBuffer[0] = XMLCh(0);
    }
    //@}

    /** @name Destructor */
    //@{
    ~XMLBuffer()
    {
        fMemoryManager->deallocate(fBuffer); //delete [] fBuffer;
    }
    //@}

    // -----------------------------------------------------------------------
    //  Buffer Full Handler Management
    // -----------------------------------------------------------------------
    void setFullHandler(XMLBufferFullHandler* handler, const XMLSize_t fullSize)
    {
        if (handler && fullSize) {
            fFullHandler = handler;
            fFullSize = fullSize;

            // Need to consider the case that the fullsize is less than the current capacity.
            // For example, say fullSize = 100 and fCapacity is 1023 (the default).
            // If the fIndex is less than the fullSize, then no problem.  We can just carry
            // on by resetting fCapacity to fullsize and proceed business as usual.
            // If the fIndex is already bigger than the fullSize then we call insureCapacity
            // to see if it can handle emptying the current buffer (it will throw an
            // exception if it can't).
            if (fullSize < fCapacity) {
                fCapacity = fullSize;
                if (fIndex >= fullSize) {
                    insureCapacity(0);
                }
            }
        }
        else {
            // reset fFullHandler to zero because setFullHandler had bad input
            fFullHandler = 0;
        }
    }

    // -----------------------------------------------------------------------
    //  Buffer Management
    // -----------------------------------------------------------------------
    void append(const XMLCh toAppend)
    {
        // Put in char and bump the index
        if (fIndex == fCapacity)
            insureCapacity(1);
        fBuffer[fIndex++] = toAppend;
    }

    void append (const XMLCh* const chars, const XMLSize_t count)
    {
        if (count) {
            if (fIndex + count >= fCapacity) {
                insureCapacity(count);
            }
            memcpy(&fBuffer[fIndex], chars, count * sizeof(XMLCh));
            fIndex += count;
        }
        else {
            append(chars);
        }
    }

    void append (const XMLCh* const chars)
    {
        if (chars != 0 && *chars != 0) {
            // get length of chars
            XMLSize_t count = 0;
            for (; *(chars+count); count++ ) /*noop*/;

            if (fIndex + count >= fCapacity) {
                insureCapacity(count);
            }
            memcpy(&fBuffer[fIndex], chars, count * sizeof(XMLCh));
            fIndex += count;
        }
    }

    void set (const XMLCh* const chars, const XMLSize_t count)
    {
        fIndex = 0;
        append(chars, count);
    }

    void set (const XMLCh* const chars)
    {
        fIndex = 0;
        if (chars != 0 && *chars != 0)
            append(chars);
    }

    const XMLCh* getRawBuffer() const
    {
        fBuffer[fIndex] = 0;
        return fBuffer;
    }

    XMLCh* getRawBuffer()
    {
        fBuffer[fIndex] = 0;
        return fBuffer;
    }

    void reset()
    {
        fIndex = 0;
    }

    // -----------------------------------------------------------------------
    //  Getters
    // -----------------------------------------------------------------------
    bool getInUse() const
    {
        return fUsed;
    }

    XMLSize_t getLen() const
    {
        return fIndex;
    }

    bool isEmpty() const
    {
        return (fIndex == 0);
    }

    // -----------------------------------------------------------------------
    //  Setters
    // -----------------------------------------------------------------------
    void setInUse(const bool newValue)
    {
        fUsed = newValue;
    }

private :
    // -----------------------------------------------------------------------
    //  Unimplemented constructors and operators
    // -----------------------------------------------------------------------
    XMLBuffer(const XMLBuffer&);
    XMLBuffer& operator=(const XMLBuffer&);

    // -----------------------------------------------------------------------
    //  Declare our friends
    // -----------------------------------------------------------------------
    friend class XMLBufBid;

    // -----------------------------------------------------------------------
    //  Private helpers
    // -----------------------------------------------------------------------
    void insureCapacity(const XMLSize_t extraNeeded);

    // -----------------------------------------------------------------------
    //  Private data members
    //
    //  fBuffer
    //      The pointer to the buffer data. Its grown as needed. Its always
    //      one larger than fCapacity, to leave room for the null terminator.
    //
    //  fIndex
    //      The current index into the buffer, as characters are appended
    //      to it. If its zero, then the buffer is empty.
    //
    //  fCapacity
    //      The current capacity of the buffer. Its actually always one
    //      larger, to leave room for the null terminator.
    //
    //  fUsed
    //      Indicates whether this buffer is in use or not.
    //
    //  fFullHandler, fFullSize
    //      If fFullHandler is non-null, the buffer has a maximum size
    //      indicated by fFullSize. If writing to the buffer would exceed the
    //      buffer's maximum size, fFullHandler's bufferFull callback is
    //      invoked, to empty the buffer.
    // -----------------------------------------------------------------------
    XMLSize_t                   fIndex;
    XMLSize_t                   fCapacity;
    XMLSize_t                   fFullSize;
    bool                        fUsed;
    MemoryManager* const        fMemoryManager;
    XMLBufferFullHandler*       fFullHandler;
    XMLCh*                      fBuffer;
};

/**
 *  XMLBufferFullHandler is a callback interface for clients of
 *  XMLBuffers that impose a size restriction (e.g. XMLScanner).
 *  Note that this is intended solely as a mix-in for internal
 *  use, and therefore does not derive from XMemory (to avoid
 *  the ambiguous base class problem).
 */
class XMLPARSER_EXPORT XMLBufferFullHandler
{
public :

    virtual ~XMLBufferFullHandler() {}

    /**
     * Callback method, intended to allow clients of an XMLBuffer which has
     * become full to empty it appropriately.
     * @return true if the handler was able to empty the buffer (either
     * partially or completely), otherwise false to indicate an error.
     */
    virtual bool bufferFull(XMLBuffer&) = 0;

};

XERCES_CPP_NAMESPACE_END

#endif
<|endoftext|>


<commit_before>/*
*******************************************************
        Parallel PLUQ quad recurisve with OpenMP
*******************************************************

g++ -D__FFLASFFPACK_HAVE_CBLAS -Wall -g -fopenmp -O3 -march=native -mavx -I/home/sultan/soft/fflas-ffpack/ -I/usr/local/soft/givaro-3.7.1/include  test-ppluq.C -L/home/pernet/Logiciels/ATLAS_1TH/lib -lcblas -latlas -L/usr/local/soft/givaro-3.7.1/lib -lgivaro -lm -lrt -Wl,-rpath -Wl,/usr/local/soft/givaro-3.7.1/lib  -o test-ppluq
*/

#include <iostream>
#include <fstream>
#include <stdlib.h>
#include <iomanip>
//#include "omp.h"

#define __FFLASFFPACK_USE_OPENMP

#define __FFLAS__TRSM_READONLY
#define __PFTRSM_FOR_PLUQ
#include "fflas-ffpack/utils/Matio.h"
//#include "fflas-ffpack/utils/timer.h"
#include "fflas-ffpack/field/modular-balanced.h"
#include "fflas-ffpack/field/modular-balanced.h"
#include "fflas-ffpack/ffpack/ffpack.h"
#include "fflas-ffpack/fflas-ffpack.h"
#include "fflas-ffpack/fflas/fflas.h"
#include "sys/time.h"

//#define BASECASE_K 256

//#include "fflas-ffpack/ffpack/parallel.h"

using namespace std;
using namespace FFLAS;
using namespace FFPACK;
#ifndef MODULO
#define MODULO 1
#endif

#if(MODULO==1)
typedef FFPACK::Modular<double> Field;
#else
typedef FFPACK::UnparametricField<double> Field;
#endif

#ifndef DEBUG
#define DEBUG 1
#endif

#ifndef SEQ
#define SEQ 1
#endif

void verification_PLUQ(const Field & F, typename Field::Element * B, typename Field::Element * A,
		       size_t * P, size_t * Q, size_t m, size_t n, size_t R)
{

  Field::Element * X = FFLAS::fflas_new<Field::Element>(m*n);
  Field::Element * L, *U;
  L = FFLAS::fflas_new<Field::Element>(m*R);
  U = FFLAS::fflas_new<Field::Element>(R*n);

  for (size_t i=0; i<m*R; ++i)
    F.init(L[i], 0.0);

  for (size_t i=0; i<m*R; ++i)
    F.init(U[i], 0.0);

  for (size_t i=0; i<m*n; ++i)
    F.init(X[i], 0.0);

  Field::Element zero,one;
  F.init(zero,0.0);
  F.init(one,1.0);
  for (size_t i=0; i<R; ++i){
    for (size_t j=0; j<i; ++j)
      F.assign ( *(U + i*n + j), zero);
    for (size_t j=i; j<n; ++j)
      F.assign (*(U + i*n + j), *(A+ i*n+j));
  }
  for ( size_t j=0; j<R; ++j ){
    for (size_t i=0; i<=j; ++i )
      F.assign( *(L+i*R+j), zero);
    F.assign(*(L+j*R+j), one);
    for (size_t i=j+1; i<m; i++)
      F.assign( *(L + i*R+j), *(A+i*n+j));
  }

  FFPACK::applyP( F, FFLAS::FflasLeft, FFLAS::FflasTrans, R,0,m, L, R, P);

  FFPACK::applyP (F, FFLAS::FflasRight, FFLAS::FflasNoTrans, R,0,n, U, n, Q);
  FFLAS::fgemm (F, FFLAS::FflasNoTrans, FFLAS::FflasNoTrans, m,n,R,
		1.0, L,R, U,n, 0.0, X,n);
  bool fail = false;
  for (size_t i=0; i<m; ++i)
    for (size_t j=0; j<n; ++j)
      if (!F.areEqual (*(B+i*n+j), *(X+i*n+j))){
	std::cerr << " B["<<i<<","<<j<<"] = " << (*(B+i*n+j))
		  << " X["<<i<<","<<j<<"] = " << (*(X+i*n+j))
		  << std::endl;
	fail=true;
      }

  if (fail)
    std::cerr<<"FAIL"<<std::endl;

  else
    std::cerr<<"PASS"<<std::endl;
  FFLAS::fflas_delete( U);
  FFLAS::fflas_delete( L);
  FFLAS::fflas_delete( X);
}

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

    int p, n, m, nbf;

	if (argc > 6){
		std::cerr<<"usage : PLUQ-rec-omp <p> <m> <n> <i> <file>"<<std::endl
//		std::cerr<<"usage : PLUQ-rec-omp <m> <n> <p> <r> <i>"<<std::endl
		    <<std::endl;
		exit(-1);
	}

	p = (argc>1 ? atoi( argv[1] ) : 1009);

	m = (argc>2 ? atoi( argv[2] ) : 1024);
	n = (argc>3 ? atoi( argv[3] ) : 1024);
	// r = atoi( argv[4] );
	nbf = (argc>4 ? atoi( argv[4] ) : 1);

	//	size_t lda = n;

		// random seed
	// ifstream f("/dev/urandom");
	// size_t seed1, seed2, seed3,seed4;
	// f.read(reinterpret_cast<char*>(&seed1), sizeof(seed1));
	// f.read(reinterpret_cast<char*>(&seed2), sizeof(seed2));
	// f.read(reinterpret_cast<char*>(&seed3), sizeof(seed3));
	// f.read(reinterpret_cast<char*>(&seed4), sizeof(seed4));

//     seed1=10;seed2=12;
//     seed3=13;seed4=14;

        enum FFLAS::FFLAS_DIAG diag = FFLAS::FflasNonUnit;
        size_t R;

	const Field F((double)p);
	// Field::RandIter G(F, seed1);

	Field::Element alpha, beta;
	F.init(alpha,1.0);
	F.init(beta,0.0);
	// Field::Element * U = FFLAS::fflas_new<Field::Element>(n*n);

	typename Field::Element* Acop;
    if (argc > 5) {
        Acop = read_field(F,argv[5],&m,&n);
    } else {
        Field::RandIter G(F);
        Acop = FFLAS::fflas_new<Field::Element>(m*n);
        PAR_FOR(size_t i=0; i<(size_t)m; ++i)
            for (size_t j=0; j<(size_t)n; ++j)
                G.random (*(Acop+i*n+j));
    }

// FFLAS::fflas_new<Field::Element>(n*m);
	Field::Element* A = FFLAS::fflas_new<Field::Element>(n*m);
#if(DEBUG==1)
	Field::Element* Adebug = FFLAS::fflas_new<Field::Element>(n*m);
#endif
	// std::vector<size_t> Index_P(r);

	// U = construct_U(F,G, n, r, Index_P, seed4, seed3);
	// A = construct_L(F,G, m, r, Index_P, seed2);
	// M_randgen(F, A, U, r, m, n);
	// size_t taille=m*n;
	// for(size_t i=0; i<taille;++i) U[i]=A[i];

	struct timespec t0, t1;// tt0, tt1;
	double delay, avrg;//, avrgg;
	double t_total=0;

    size_t maxP, maxQ;
    maxP = m;
    maxQ = n;

    size_t *P = FFLAS::fflas_new<size_t>(maxP);
    size_t *Q = FFLAS::fflas_new<size_t>(maxQ);

    PAR_FOR(size_t i=0; i<(size_t)m; ++i)
        for (size_t j=0; j<(size_t)n; ++j) {
            *(A+i*n+j) = *(Acop+i*n+j) ;
#if(DEBUG==1)
            *(Adebug+i*n+j) = *(Acop+i*n+j) ;
#endif
        }

    for ( int i=0;i<nbf+1;i++){
        for (size_t j=0;j<maxP;j++)
            P[j]=0;
        for (size_t j=0;j<maxQ;j++)
            Q[j]=0;

        PAR_FOR(size_t i=0; i<(size_t)m; ++i)
            for (size_t j=0; j<(size_t)n; ++j)
                *(A+i*n+j) = *(Acop+i*n+j) ;

	    clock_gettime(CLOCK_REALTIME, &t0);
	    PAR_REGION{
            R = pPLUQ(F, diag, m, n, A, n, P, Q);// Parallel PLUQ
	    }
	    clock_gettime(CLOCK_REALTIME, &t1);
	    delay = (double)(t1.tv_sec-t0.tv_sec)+(double)(t1.tv_nsec-t0.tv_nsec)/1000000000;

	    if(i)
            t_total +=delay;

    }
    avrg = t_total/nbf;
    std::cerr << "MODULO: " << (MODULO?p:0) << std::endl;

    PAR_REGION{
        std::cerr<<"Parallel --- m: "<<m<<" , n: " << n << " , r: " <<R<<" "
                 <<avrg<<" "<<(2.0*n*n*n)/(double(3.0*(1000000000)*avrg))<<" "
                //#ifdef  __FFLASFFPACK_USE_OPENMP
                 <<NUM_THREADS<<endl;
            //#else
    }
        //<<endl;
        //#endi

        //	std::cout<<typeid(A).name()<<endl;
#if(DEBUG==1)
	cout<<"check equality A == PLUQ ?"<<endl;
    verification_PLUQ(F,Adebug,A,P,Q,m,n,R);
    FFLAS::fflas_delete( Adebug);
#endif
#if(SEQ==1)
	struct timespec  tt0, tt1;
	double avrgg;
	//call sequential PLUQ
	size_t * PP = FFLAS::fflas_new<size_t>(maxP);
	size_t * QQ = FFLAS::fflas_new<size_t>(maxQ);
	for (size_t j=0;j<maxP;j++)
	  PP[j]=0;
	for (size_t j=0;j<maxQ;j++)
	  QQ[j]=0;
	clock_gettime(CLOCK_REALTIME, &tt0);
	size_t R2 = PLUQ(F, diag, m, n, Acop, n, PP, QQ);
	clock_gettime(CLOCK_REALTIME, &tt1);
        FFLAS::fflas_delete( Acop);
	avrgg = (double)(tt1.tv_sec-tt0.tv_sec)+(double)(tt1.tv_nsec-tt0.tv_nsec)/1000000000;
	//verification
	std::cerr<<"Sequential : "<<m<<" "<<R2<<" "
                 <<avrgg<<" "<<(2.0*n*n*n)/(double(3.0*(1000000000)*avrgg))<<endl;
#endif

        FFLAS::fflas_delete( A);
	return 0;
}
<commit_msg>PAR_FIOR test<commit_after>/*
*******************************************************
        Parallel PLUQ quad recurisve with OpenMP
*******************************************************

g++ -D__FFLASFFPACK_HAVE_CBLAS -Wall -g -fopenmp -O3 -march=native -mavx -I/home/sultan/soft/fflas-ffpack/ -I/usr/local/soft/givaro-3.7.1/include  test-ppluq.C -L/home/pernet/Logiciels/ATLAS_1TH/lib -lcblas -latlas -L/usr/local/soft/givaro-3.7.1/lib -lgivaro -lm -lrt -Wl,-rpath -Wl,/usr/local/soft/givaro-3.7.1/lib  -o test-ppluq
*/

#include <iostream>
#include <fstream>
#include <stdlib.h>
#include <iomanip>
//#include "omp.h"

#define __FFLASFFPACK_USE_OPENMP

#define __FFLAS__TRSM_READONLY
#define __PFTRSM_FOR_PLUQ
#include "fflas-ffpack/utils/Matio.h"
//#include "fflas-ffpack/utils/timer.h"
#include "fflas-ffpack/field/modular-balanced.h"
#include "fflas-ffpack/field/modular-balanced.h"
#include "fflas-ffpack/ffpack/ffpack.h"
#include "fflas-ffpack/fflas-ffpack.h"
#include "fflas-ffpack/fflas/fflas.h"
#include "sys/time.h"

//#define BASECASE_K 256

//#include "fflas-ffpack/ffpack/parallel.h"

using namespace std;
using namespace FFLAS;
using namespace FFPACK;
#ifndef MODULO
#define MODULO 1
#endif

#if(MODULO==1)
typedef FFPACK::Modular<double> Field;
#else
typedef FFPACK::UnparametricField<double> Field;
#endif

#ifndef DEBUG
#define DEBUG 1
#endif

#ifndef SEQ
#define SEQ 1
#endif

void verification_PLUQ(const Field & F, typename Field::Element * B, typename Field::Element * A,
		       size_t * P, size_t * Q, size_t m, size_t n, size_t R)
{

  Field::Element * X = FFLAS::fflas_new<Field::Element>(m*n);
  Field::Element * L, *U;
  L = FFLAS::fflas_new<Field::Element>(m*R);
  U = FFLAS::fflas_new<Field::Element>(R*n);

  PAR_FOR (size_t i=0; i<m*R; ++i)
    F.init(L[i], 0.0);

  PAR_FOR (size_t i=0; i<m*R; ++i)
    F.init(U[i], 0.0);

  PAR_FOR (size_t i=0; i<m*n; ++i)
    F.init(X[i], 0.0);

  Field::Element zero,one;
  F.init(zero,0.0);
  F.init(one,1.0);
  PAR_FOR (size_t i=0; i<R; ++i){
    for (size_t j=0; j<i; ++j)
      F.assign ( *(U + i*n + j), zero);
    for (size_t j=i; j<n; ++j)
      F.assign (*(U + i*n + j), *(A+ i*n+j));
  }
  PAR_FOR ( size_t j=0; j<R; ++j ){
    for (size_t i=0; i<=j; ++i )
      F.assign( *(L+i*R+j), zero);
    F.assign(*(L+j*R+j), one);
    for (size_t i=j+1; i<m; i++)
      F.assign( *(L + i*R+j), *(A+i*n+j));
  }

  FFPACK::applyP( F, FFLAS::FflasLeft, FFLAS::FflasTrans, R,0,m, L, R, P);

  FFPACK::applyP (F, FFLAS::FflasRight, FFLAS::FflasNoTrans, R,0,n, U, n, Q);
  FFLAS::fgemm (F, FFLAS::FflasNoTrans, FFLAS::FflasNoTrans, m,n,R,
		1.0, L,R, U,n, 0.0, X,n);
  bool fail = false;
  PAR_FOR (size_t i=0; i<m; ++i)
    for (size_t j=0; j<n; ++j)
      if (!F.areEqual (*(B+i*n+j), *(X+i*n+j))){
          std::stringstream errs;
          errs << " B["<<i<<","<<j<<"] = " << (*(B+i*n+j))
                    << " X["<<i<<","<<j<<"] = " << (*(X+i*n+j))
                    << std::endl;
          std::cerr << errs;
          fail=true;
      }

  if (fail)
      std::cerr<<"FAIL"<<std::endl;
  else
      std::cerr<<"PASS"<<std::endl;

  FFLAS::fflas_delete( U);
  FFLAS::fflas_delete( L);
  FFLAS::fflas_delete( X);
}

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

    int p, n, m, nbf;

	if (argc > 6){
		std::cerr<<"usage : PLUQ-rec-omp <p> <m> <n> <i> <file>"<<std::endl
//		std::cerr<<"usage : PLUQ-rec-omp <m> <n> <p> <r> <i>"<<std::endl
		    <<std::endl;
		exit(-1);
	}

	p = (argc>1 ? atoi( argv[1] ) : 1009);

	m = (argc>2 ? atoi( argv[2] ) : 1024);
	n = (argc>3 ? atoi( argv[3] ) : 1024);
	// r = atoi( argv[4] );
	nbf = (argc>4 ? atoi( argv[4] ) : 1);

	//	size_t lda = n;

		// random seed
	// ifstream f("/dev/urandom");
	// size_t seed1, seed2, seed3,seed4;
	// f.read(reinterpret_cast<char*>(&seed1), sizeof(seed1));
	// f.read(reinterpret_cast<char*>(&seed2), sizeof(seed2));
	// f.read(reinterpret_cast<char*>(&seed3), sizeof(seed3));
	// f.read(reinterpret_cast<char*>(&seed4), sizeof(seed4));

//     seed1=10;seed2=12;
//     seed3=13;seed4=14;

        enum FFLAS::FFLAS_DIAG diag = FFLAS::FflasNonUnit;
        size_t R;

	const Field F((double)p);
	// Field::RandIter G(F, seed1);

	Field::Element alpha, beta;
	F.init(alpha,1.0);
	F.init(beta,0.0);
	// Field::Element * U = FFLAS::fflas_new<Field::Element>(n*n);

	typename Field::Element* Acop;
    if (argc > 5) {
        Acop = read_field(F,argv[5],&m,&n);
    } else {
        Field::RandIter G(F);
        Acop = FFLAS::fflas_new<Field::Element>(m*n);
        PAR_FOR(size_t i=0; i<(size_t)m; ++i)
            for (size_t j=0; j<(size_t)n; ++j)
                G.random (*(Acop+i*n+j));
    }

// FFLAS::fflas_new<Field::Element>(n*m);
	Field::Element* A = FFLAS::fflas_new<Field::Element>(n*m);
#if(DEBUG==1)
	Field::Element* Adebug = FFLAS::fflas_new<Field::Element>(n*m);
#endif
	// std::vector<size_t> Index_P(r);

	// U = construct_U(F,G, n, r, Index_P, seed4, seed3);
	// A = construct_L(F,G, m, r, Index_P, seed2);
	// M_randgen(F, A, U, r, m, n);
	// size_t taille=m*n;
	// for(size_t i=0; i<taille;++i) U[i]=A[i];

	struct timespec t0, t1;// tt0, tt1;
	double delay, avrg;//, avrgg;
	double t_total=0;

    size_t maxP, maxQ;
    maxP = m;
    maxQ = n;

    size_t *P = FFLAS::fflas_new<size_t>(maxP);
    size_t *Q = FFLAS::fflas_new<size_t>(maxQ);

    PAR_FOR(size_t i=0; i<(size_t)m; ++i)
        for (size_t j=0; j<(size_t)n; ++j) {
            *(A+i*n+j) = *(Acop+i*n+j) ;
#if(DEBUG==1)
            *(Adebug+i*n+j) = *(Acop+i*n+j) ;
#endif
        }

    for ( int i=0;i<nbf+1;i++){
        for (size_t j=0;j<maxP;j++)
            P[j]=0;
        for (size_t j=0;j<maxQ;j++)
            Q[j]=0;

        PAR_FOR(size_t i=0; i<(size_t)m; ++i)
            for (size_t j=0; j<(size_t)n; ++j)
                *(A+i*n+j) = *(Acop+i*n+j) ;

	    clock_gettime(CLOCK_REALTIME, &t0);
	    PAR_REGION{
            R = pPLUQ(F, diag, m, n, A, n, P, Q);// Parallel PLUQ
	    }
	    clock_gettime(CLOCK_REALTIME, &t1);
	    delay = (double)(t1.tv_sec-t0.tv_sec)+(double)(t1.tv_nsec-t0.tv_nsec)/1000000000;

	    if(i)
            t_total +=delay;

    }
    avrg = t_total/nbf;
    std::cerr << "MODULO: " << (MODULO?p:0) << std::endl;

    PAR_REGION{
        std::cerr<<"Parallel --- m: "<<m<<" , n: " << n << " , r: " <<R<<" "
                 <<avrg<<" "<<(2.0*n*n*n)/(double(3.0*(1000000000)*avrg))<<" "
                //#ifdef  __FFLASFFPACK_USE_OPENMP
                 <<NUM_THREADS<<endl;
            //#else
    }
        //<<endl;
        //#endi

        //	std::cout<<typeid(A).name()<<endl;
#if(DEBUG==1)
	cout<<"check equality A == PLUQ ?"<<endl;
    verification_PLUQ(F,Adebug,A,P,Q,m,n,R);
    FFLAS::fflas_delete( Adebug);
#endif
#if(SEQ==1)
	struct timespec  tt0, tt1;
	double avrgg;
	//call sequential PLUQ
	size_t * PP = FFLAS::fflas_new<size_t>(maxP);
	size_t * QQ = FFLAS::fflas_new<size_t>(maxQ);
	for (size_t j=0;j<maxP;j++)
	  PP[j]=0;
	for (size_t j=0;j<maxQ;j++)
	  QQ[j]=0;
	clock_gettime(CLOCK_REALTIME, &tt0);
	size_t R2 = PLUQ(F, diag, m, n, Acop, n, PP, QQ);
	clock_gettime(CLOCK_REALTIME, &tt1);
        FFLAS::fflas_delete( Acop);
	avrgg = (double)(tt1.tv_sec-tt0.tv_sec)+(double)(tt1.tv_nsec-tt0.tv_nsec)/1000000000;
	//verification
	std::cerr<<"Sequential : "<<m<<" "<<R2<<" "
                 <<avrgg<<" "<<(2.0*n*n*n)/(double(3.0*(1000000000)*avrgg))<<endl;
#endif

        FFLAS::fflas_delete( A);
	return 0;
}
<|endoftext|>


<commit_before>// Copyright (C) 2009, 2010 by Florent Lamiraux, Thomas Moulard, JRL.
//
// This file is part of the hpp-corbaserver.
//
// This software is provided "as is" without warranty of any kind,
// either expressed or implied, including but not limited to the
// implied warranties of fitness for a particular purpose.
//
// See the COPYING file for more information.

#include <errno.h>
#include <pthread.h>
#include <iostream>

#include <kwsPlus/directPath/kwsPlusSteeringMethodFactory.h>
#include <kwsPlus/directPath/kwsPlusDistanceFactory.h>
#include <kwsPlus/roadmap/kwsPlusDiffusionNodePickerFactory.h>
#include <kwsPlus/roadmap/kwsPlusDiffusionShooterFactory.h>

#include <hpp/util/debug.hh>

#include "hpp/corbaserver/server.hh"

#include "server-private.hh"

//FIXME: remove me.
#define HPPCI_CATCH(msg, ret)						\
  catch(CORBA::SystemException&) {					\
    hppDout (error, "hppCorbaChppciServer: CORBA::SystemException: " << msg);	\
    return ret;								\
  }									\
  catch(CORBA::Exception&) {						\
    hppDout (error, "hppCorbaChppciServer: CORBA::Exception: " << msg);	\
    return ret;								\
  }									\
  catch(omniORB::fatalException& fe) {					\
    hppDout (error, "hppCorbaChppciServer: CORBA::fatalException: " << msg);	\
    return ret;								\
  }									\
  catch(...) {								\
    hppDout (error, "hppCorbaChppciServer: unknown exception: " << msg);	\
    return ret;								\
  }

namespace hpp
{
  namespace corbaChppciServer
  {
    using CORBA::Exception;
    using CORBA::Object_var;
    using CORBA::SystemException;
    using CORBA::ORB_init;
    using CORBA::PolicyList;
    using omniORB::fatalException;

    namespace
    {
      /// \brief Forward logging messages to hpp logging mechanism.
      /// If debug is disabled, CORBA logging will be disabled too.
      ///
      /// Tracing has to be enabled in your ``omniORB.cfg'' to use this
      /// feature.
      /// See ``omniORB configuration and API'' > ``Tracing options''
      /// section of omniORB manual for more information.
      void logFunction (const char* msg);

      void logFunction (const char* msg)
      {
	hppDout (info, "omniORB: " << msg);
      }
    } // end of anonymous namespace.

    ChppciServer::ChppciServer(core::Planner *inHppPlanner, int argc, const char *argv[], bool inMultiThread) :
      hppPlanner(inHppPlanner)
    {
      // Register log function.
      omniORB::setLogFunction (&logFunction);

      attPrivate = new impl::ChppciServer;

      initORBandChppciServers (argc, argv, inMultiThread);
      initMapSteeringMethodFactory();
      initMapDistanceFunctionFactory();
      initMapDiffusionNodePickerFactory();
      initMapDiffusionShooterFactory();
    }

    /// \brief Shutdown CORBA server
    ChppciServer::~ChppciServer()
    {
      attPrivate->deactivateAndDestroyChppciServers();
      attPrivate->orb_->shutdown(0);
      delete attPrivate;
      attPrivate = NULL;
      destroySteeringMethodFactory();
      destroyDistanceFunctionFactory();
      destroyDiffusionNodePickerFactory();
      destroyDiffusionShooterFactory();
    }

    /*
      STEERING METHOD FACTORIES
    */

    void ChppciServer::initMapSteeringMethodFactory()
    {
      attMapSteeringMethodFactory["linear"] = new CkwsPlusLinearSteeringMethodFactory;
      attMapSteeringMethodFactory["rs"] = new CkwsPlusRSSteeringMethodFactory(1.0);
      attMapSteeringMethodFactory["flic"] = new CkwsPlusFlicSteeringMethodFactory();
    }

    void ChppciServer::destroySteeringMethodFactory()
    {
      std::map<std::string, CkwsPlusSteeringMethodFactory*>::iterator start
	= attMapSteeringMethodFactory.begin();
      std::map<std::string, CkwsPlusSteeringMethodFactory*>::iterator end
	= attMapSteeringMethodFactory.end();

      for (std::map<std::string, CkwsPlusSteeringMethodFactory*>::iterator it=start;
	   it != end; it++) {
	CkwsPlusSteeringMethodFactory* factory = it->second;
	hppDout (info, "deleting steering method factory" << it->first);
	delete factory;
      }
    }

    bool ChppciServer::steeringMethodFactoryAlreadySet(std::string inName)
    {
      if (attMapSteeringMethodFactory.count(inName) == 1) {
	return true;
      }
      return false;
    }

    bool ChppciServer::addSteeringMethodFactory(std::string inName,
						CkwsPlusSteeringMethodFactory* inSteeringMethodFactory)
    {
      if(steeringMethodFactoryAlreadySet(inName)) {
	return false;
      }
      attMapSteeringMethodFactory[inName] = inSteeringMethodFactory;
      return true;
    }

    CkwsSteeringMethodShPtr ChppciServer::createSteeringMethod(std::string inName,
							       bool inOriented)
    {
      CkwsSteeringMethodShPtr result;

      if (steeringMethodFactoryAlreadySet(inName)) {
	result = attMapSteeringMethodFactory[inName]->makeSteeringMethod(inOriented);
      }
      return result;
    }

    /*
      DISTANCE FUNCTION FACTORIES
    */

    void ChppciServer::initMapDistanceFunctionFactory()
    {
      attMapDistanceFunctionFactory["linear"] = new CkwsPlusLinearDistanceFactory;
      attMapDistanceFunctionFactory["rs"] = new CkwsPlusRSDistanceFactory(1.0);
      attMapDistanceFunctionFactory["flic"] = new CkwsPlusApproxFlicDistanceFactory;
    }

    void ChppciServer::destroyDistanceFunctionFactory()
    {
      std::map<std::string, CkwsPlusDistanceFactory*>::iterator start
	= attMapDistanceFunctionFactory.begin();
      std::map<std::string, CkwsPlusDistanceFactory*>::iterator end
	= attMapDistanceFunctionFactory.end();

      for (std::map<std::string, CkwsPlusDistanceFactory*>::iterator it=start;
	   it != end; it++) {
	CkwsPlusDistanceFactory* factory = it->second;
	hppDout (info, " deleting distance function factory" << it->first);
	delete factory;
      }
    }

    bool ChppciServer::distanceFactoryAlreadySet(std::string inName)
    {
      if (attMapDistanceFunctionFactory.count(inName) == 1) {
	return true;
      }
      return false;
    }

    bool ChppciServer::addDistanceFactory(std::string inName,
					  CkwsPlusDistanceFactory* inDistanceFunctionFactory)
    {
      if(distanceFactoryAlreadySet(inName)) {
	return false;
      }
      attMapDistanceFunctionFactory[inName] = inDistanceFunctionFactory;
      return true;
    }

    CkwsDistanceShPtr ChppciServer::createDistanceFunction(std::string inName,
							   bool inOriented)
    {
      CkwsDistanceShPtr result;

      if (distanceFactoryAlreadySet(inName)) {
	result = attMapDistanceFunctionFactory[inName]->makeDistance(inOriented);
      }
      return result;
    }

    /*
      DIFFUSION NODE PICKER FACTORIES
    */

    void ChppciServer::initMapDiffusionNodePickerFactory()
    {
      attMapDiffusionNodePickerFactory["basic"] = new CkwsPlusBasicDiffusionNodePickerFactory;
      attMapDiffusionNodePickerFactory["smallestTree"] =
	new CkwsPlusSmallestTreeDiffusionNodePickerFactory;
    }

    void ChppciServer::destroyDiffusionNodePickerFactory()
    {
      std::map<std::string, CkwsPlusDiffusionNodePickerFactory*>::iterator start
	= attMapDiffusionNodePickerFactory.begin();
      std::map<std::string, CkwsPlusDiffusionNodePickerFactory*>::iterator end
	= attMapDiffusionNodePickerFactory.end();

      for (std::map<std::string, CkwsPlusDiffusionNodePickerFactory*>::iterator it=start;
	   it != end; it++) {
	CkwsPlusDiffusionNodePickerFactory* factory = it->second;
	hppDout (info, " deleting diffusion node picker factory" << it->first);
	delete factory;
      }
    }

    bool ChppciServer::diffusionNodePickerFactoryAlreadySet(std::string inName)
    {
      if (attMapDiffusionNodePickerFactory.count(inName) == 1) {
	return true;
      }
      return false;
    }

    bool ChppciServer::addDiffusionNodePickerFactory(std::string inName,
						     CkwsPlusDiffusionNodePickerFactory* inDiffusionNodePickerFactory)
    {
      if(diffusionNodePickerFactoryAlreadySet(inName)) {
	return false;
      }
      attMapDiffusionNodePickerFactory[inName] = inDiffusionNodePickerFactory;
      return true;
    }

    CkwsDiffusionNodePickerShPtr ChppciServer::createDiffusionNodePicker(std::string inName)
    {
      CkwsDiffusionNodePickerShPtr result;

      if (diffusionNodePickerFactoryAlreadySet(inName)) {
	result = attMapDiffusionNodePickerFactory[inName]->makeDiffusionNodePicker();
      }
      return result;
    }

    /*
      DIFFUSION SHOOTER FACTORIES
    */

    void ChppciServer::initMapDiffusionShooterFactory()
    {
      attMapDiffusionShooterFactory["config space"] = new CkwsPlusShooterConfigSpaceFactory;
      attMapDiffusionShooterFactory["roadmap box"] = new CkwsPlusShooterRoadmapBoxFactory;
      attMapDiffusionShooterFactory["roadmap node"] = new CkwsPlusShooterRoadmapNodesFactory;
    }

    void ChppciServer::destroyDiffusionShooterFactory()
    {
      std::map<std::string, CkwsPlusDiffusionShooterFactory*>::iterator start
	= attMapDiffusionShooterFactory.begin();
      std::map<std::string, CkwsPlusDiffusionShooterFactory*>::iterator end
	= attMapDiffusionShooterFactory.end();

      for (std::map<std::string, CkwsPlusDiffusionShooterFactory*>::iterator it=start;
	   it != end; it++) {
	CkwsPlusDiffusionShooterFactory* factory = it->second;
	hppDout (info, " deleting diffusion shooter factory" << it->first);
	delete factory;
      }
    }

    bool ChppciServer::diffusionShooterFactoryAlreadySet(std::string inName)
    {
      if (attMapDiffusionShooterFactory.count(inName) == 1) {
	return true;
      }
      return false;
    }

    bool ChppciServer::addDiffusionShooterFactory(std::string inName,
						  CkwsPlusDiffusionShooterFactory* inDiffusionShooterFactory)
    {
      if(diffusionShooterFactoryAlreadySet(inName)) {
	return false;
      }
      attMapDiffusionShooterFactory[inName] = inDiffusionShooterFactory;
      return true;
    }

    CkwsDiffusionShooterShPtr ChppciServer::createDiffusionShooter(std::string inName,
								   double inStandardDeviation)
    {
      CkwsDiffusionShooterShPtr result;

      if (diffusionShooterFactoryAlreadySet(inName)) {
	result = attMapDiffusionShooterFactory[inName]->makeDiffusionShooter(inStandardDeviation);
      }
      return result;
    }

    /*
      CORBA SERVER INITIALIZATION
    */

    ktStatus ChppciServer::initORBandChppciServers(int argc, const char* argv[], bool inMultiThread)
    {
      Object_var obj;
      PortableChppciServer::ThreadPolicy_var threadPolicy;
      PortableChppciServer::POA_var rootPoa;

      /*
	 Fine granularity in exception handling
      */

      /*
	ORB init
      */
      try {
	attPrivate->orb_ = ORB_init (argc, const_cast<char **> (argv)); //FIXME: handle this properly.
	if (is_nil(attPrivate->orb_)) {
	  hppDout (error, "failed to initialize ORB");
	  return KD_ERROR;
	}
      }
      HPPCI_CATCH("failed to initialize ORB", KD_ERROR)

	/*
	  ORB init
	*/

	try {
	  obj = attPrivate->orb_->resolve_initial_references("RootPOA");
	}
      HPPCI_CATCH("failed to resolve initial references", KD_ERROR)

	/*
	  Create thread policy
	*/

	try {
	  //
	  // Make the CORBA object single-threaded to avoid GUI krash
	  //
	  // Create a sigle threaded policy object
	  rootPoa = PortableChppciServer::POA::_narrow(obj);

	  if (inMultiThread) {
	    threadPolicy = rootPoa->create_thread_policy(PortableChppciServer::ORB_CTRL_MODEL);
	  }
	  else {
	    threadPolicy = rootPoa->create_thread_policy(PortableChppciServer::MAIN_THREAD_MODEL);
	  }
	}
      HPPCI_CATCH("failed to create thread policy", KD_ERROR)

	/*
	  Duplicate thread policy
	*/

	try {
	  PolicyList policyList;
	  policyList.length(1);
	  policyList[0] = PortableChppciServer::ThreadPolicy::_duplicate(threadPolicy);

	  attPrivate->poa_ = rootPoa->create_POA("child", PortableChppciServer::POAManager::_nil(),
						policyList);

	}
      HPPCI_CATCH("failed to duplicate thread policy", KD_ERROR)

	/*
	  Destroy thread policy
	*/

	try {
	  // Destroy policy object
	  threadPolicy->destroy();

	}
      HPPCI_CATCH("failed to destroy thread policy", KD_ERROR);

      return attPrivate->createAndActivateChppciServers(this);
    }

    int ChppciServer::startCorbaChppciServer()
    {
      try {
	// Obtain a reference to objects, and register them in
	// the naming service.
	Object_var robotObj = attPrivate->robotServant_->_this();
	Object_var obstacleObj = attPrivate->obstacleServant_->_this();
	Object_var problemObj = attPrivate->problemServant_->_this();

	if (!attPrivate->createHppContext()) {
	  return KD_ERROR;
	}
	// Bind robotObj with name Robot to the hppContext:
	CosNaming::Name objectName;
	objectName.length(1);
	objectName[0].id   = (const char*) "robots";   // string copied
	objectName[0].kind = (const char*) "servant"; // string copied

	if(!attPrivate->bindObjectToName(robotObj, objectName)) {
	  return KD_ERROR;
	}
	attPrivate->robotServant_->_remove_ref();

	// Bind obstacleObj with name Obstacle to the hppContext:
	objectName.length(1);
	objectName[0].id   = (const char*) "obstacles";   // string copied
	objectName[0].kind = (const char*) "servant"; // string copied

	if(!attPrivate->bindObjectToName(obstacleObj, objectName)) {
	  return KD_ERROR;
	}
	attPrivate->obstacleServant_->_remove_ref();

	// Bind problemObj with name Problem to the hppContext:
	objectName.length(1);
	objectName[0].id   = (const char*) "problems";   // string copied
	objectName[0].kind = (const char*) "servant"; // string copied

	if(!attPrivate->bindObjectToName(problemObj, objectName)) {
	  return KD_ERROR;
	}
	attPrivate->problemServant_->_remove_ref();

	PortableChppciServer::POAManager_var pman = attPrivate->poa_->the_POAManager();
	pman->activate();
      }
      HPPCI_CATCH("failed to start CORBA server", KD_ERROR);
      return KD_OK;
    }

    const core::Planner* ChppciServer::planner() const
    {
      return hppPlanner;
    }

    core::Planner* ChppciServer::planner()
    {
      return hppPlanner;
    }

    /// \brief If CORBA requests are pending, process them
    int ChppciServer::processRequest (bool loop)
    {
      if (loop)
	{
	  hppDout (info, "start processing CORBA requests for ever.");
	  attPrivate->orb_->run();
	}
      else
	{
	  if (attPrivate->orb_->work_pending())
	    attPrivate->orb_->perform_work();
	}
      return 0;
    }

  } // end of namespace corbaChppciServer.
} // end of namespace hpp.
<commit_msg>Remove flic steering method to comply with kwsPlus.<commit_after>// Copyright (C) 2009, 2010 by Florent Lamiraux, Thomas Moulard, JRL.
//
// This file is part of the hpp-corbaserver.
//
// This software is provided "as is" without warranty of any kind,
// either expressed or implied, including but not limited to the
// implied warranties of fitness for a particular purpose.
//
// See the COPYING file for more information.

#include <errno.h>
#include <pthread.h>
#include <iostream>

#include <kwsPlus/directPath/kwsPlusSteeringMethodFactory.h>
#include <kwsPlus/directPath/kwsPlusDistanceFactory.h>
#include <kwsPlus/roadmap/kwsPlusDiffusionNodePickerFactory.h>
#include <kwsPlus/roadmap/kwsPlusDiffusionShooterFactory.h>

#include <hpp/util/debug.hh>

#include "hpp/corbaserver/server.hh"

#include "server-private.hh"

//FIXME: remove me.
#define HPPCI_CATCH(msg, ret)						\
  catch(CORBA::SystemException&) {					\
    hppDout (error, "hppCorbaChppciServer: CORBA::SystemException: " << msg);	\
    return ret;								\
  }									\
  catch(CORBA::Exception&) {						\
    hppDout (error, "hppCorbaChppciServer: CORBA::Exception: " << msg);	\
    return ret;								\
  }									\
  catch(omniORB::fatalException& fe) {					\
    hppDout (error, "hppCorbaChppciServer: CORBA::fatalException: " << msg);	\
    return ret;								\
  }									\
  catch(...) {								\
    hppDout (error, "hppCorbaChppciServer: unknown exception: " << msg);	\
    return ret;								\
  }

namespace hpp
{
  namespace corbaChppciServer
  {
    using CORBA::Exception;
    using CORBA::Object_var;
    using CORBA::SystemException;
    using CORBA::ORB_init;
    using CORBA::PolicyList;
    using omniORB::fatalException;

    namespace
    {
      /// \brief Forward logging messages to hpp logging mechanism.
      /// If debug is disabled, CORBA logging will be disabled too.
      ///
      /// Tracing has to be enabled in your ``omniORB.cfg'' to use this
      /// feature.
      /// See ``omniORB configuration and API'' > ``Tracing options''
      /// section of omniORB manual for more information.
      void logFunction (const char* msg);

      void logFunction (const char* msg)
      {
	hppDout (info, "omniORB: " << msg);
      }
    } // end of anonymous namespace.

    ChppciServer::ChppciServer(core::Planner *inHppPlanner, int argc, const char *argv[], bool inMultiThread) :
      hppPlanner(inHppPlanner)
    {
      // Register log function.
      omniORB::setLogFunction (&logFunction);

      attPrivate = new impl::ChppciServer;

      initORBandChppciServers (argc, argv, inMultiThread);
      initMapSteeringMethodFactory();
      initMapDistanceFunctionFactory();
      initMapDiffusionNodePickerFactory();
      initMapDiffusionShooterFactory();
    }

    /// \brief Shutdown CORBA server
    ChppciServer::~ChppciServer()
    {
      attPrivate->deactivateAndDestroyChppciServers();
      attPrivate->orb_->shutdown(0);
      delete attPrivate;
      attPrivate = NULL;
      destroySteeringMethodFactory();
      destroyDistanceFunctionFactory();
      destroyDiffusionNodePickerFactory();
      destroyDiffusionShooterFactory();
    }

    /*
      STEERING METHOD FACTORIES
    */

    void ChppciServer::initMapSteeringMethodFactory()
    {
      attMapSteeringMethodFactory["linear"] = new CkwsPlusLinearSteeringMethodFactory;
      attMapSteeringMethodFactory["rs"] = new CkwsPlusRSSteeringMethodFactory(1.0);
    }

    void ChppciServer::destroySteeringMethodFactory()
    {
      std::map<std::string, CkwsPlusSteeringMethodFactory*>::iterator start
	= attMapSteeringMethodFactory.begin();
      std::map<std::string, CkwsPlusSteeringMethodFactory*>::iterator end
	= attMapSteeringMethodFactory.end();

      for (std::map<std::string, CkwsPlusSteeringMethodFactory*>::iterator it=start;
	   it != end; it++) {
	CkwsPlusSteeringMethodFactory* factory = it->second;
	hppDout (info, "deleting steering method factory" << it->first);
	delete factory;
      }
    }

    bool ChppciServer::steeringMethodFactoryAlreadySet(std::string inName)
    {
      if (attMapSteeringMethodFactory.count(inName) == 1) {
	return true;
      }
      return false;
    }

    bool ChppciServer::addSteeringMethodFactory(std::string inName,
						CkwsPlusSteeringMethodFactory* inSteeringMethodFactory)
    {
      if(steeringMethodFactoryAlreadySet(inName)) {
	return false;
      }
      attMapSteeringMethodFactory[inName] = inSteeringMethodFactory;
      return true;
    }

    CkwsSteeringMethodShPtr ChppciServer::createSteeringMethod(std::string inName,
							       bool inOriented)
    {
      CkwsSteeringMethodShPtr result;

      if (steeringMethodFactoryAlreadySet(inName)) {
	result = attMapSteeringMethodFactory[inName]->makeSteeringMethod(inOriented);
      }
      return result;
    }

    /*
      DISTANCE FUNCTION FACTORIES
    */

    void ChppciServer::initMapDistanceFunctionFactory()
    {
      attMapDistanceFunctionFactory["linear"] = new CkwsPlusLinearDistanceFactory;
      attMapDistanceFunctionFactory["rs"] = new CkwsPlusRSDistanceFactory(1.0);
    }

    void ChppciServer::destroyDistanceFunctionFactory()
    {
      std::map<std::string, CkwsPlusDistanceFactory*>::iterator start
	= attMapDistanceFunctionFactory.begin();
      std::map<std::string, CkwsPlusDistanceFactory*>::iterator end
	= attMapDistanceFunctionFactory.end();

      for (std::map<std::string, CkwsPlusDistanceFactory*>::iterator it=start;
	   it != end; it++) {
	CkwsPlusDistanceFactory* factory = it->second;
	hppDout (info, " deleting distance function factory" << it->first);
	delete factory;
      }
    }

    bool ChppciServer::distanceFactoryAlreadySet(std::string inName)
    {
      if (attMapDistanceFunctionFactory.count(inName) == 1) {
	return true;
      }
      return false;
    }

    bool ChppciServer::addDistanceFactory(std::string inName,
					  CkwsPlusDistanceFactory* inDistanceFunctionFactory)
    {
      if(distanceFactoryAlreadySet(inName)) {
	return false;
      }
      attMapDistanceFunctionFactory[inName] = inDistanceFunctionFactory;
      return true;
    }

    CkwsDistanceShPtr ChppciServer::createDistanceFunction(std::string inName,
							   bool inOriented)
    {
      CkwsDistanceShPtr result;

      if (distanceFactoryAlreadySet(inName)) {
	result = attMapDistanceFunctionFactory[inName]->makeDistance(inOriented);
      }
      return result;
    }

    /*
      DIFFUSION NODE PICKER FACTORIES
    */

    void ChppciServer::initMapDiffusionNodePickerFactory()
    {
      attMapDiffusionNodePickerFactory["basic"] = new CkwsPlusBasicDiffusionNodePickerFactory;
      attMapDiffusionNodePickerFactory["smallestTree"] =
	new CkwsPlusSmallestTreeDiffusionNodePickerFactory;
    }

    void ChppciServer::destroyDiffusionNodePickerFactory()
    {
      std::map<std::string, CkwsPlusDiffusionNodePickerFactory*>::iterator start
	= attMapDiffusionNodePickerFactory.begin();
      std::map<std::string, CkwsPlusDiffusionNodePickerFactory*>::iterator end
	= attMapDiffusionNodePickerFactory.end();

      for (std::map<std::string, CkwsPlusDiffusionNodePickerFactory*>::iterator it=start;
	   it != end; it++) {
	CkwsPlusDiffusionNodePickerFactory* factory = it->second;
	hppDout (info, " deleting diffusion node picker factory" << it->first);
	delete factory;
      }
    }

    bool ChppciServer::diffusionNodePickerFactoryAlreadySet(std::string inName)
    {
      if (attMapDiffusionNodePickerFactory.count(inName) == 1) {
	return true;
      }
      return false;
    }

    bool ChppciServer::addDiffusionNodePickerFactory(std::string inName,
						     CkwsPlusDiffusionNodePickerFactory* inDiffusionNodePickerFactory)
    {
      if(diffusionNodePickerFactoryAlreadySet(inName)) {
	return false;
      }
      attMapDiffusionNodePickerFactory[inName] = inDiffusionNodePickerFactory;
      return true;
    }

    CkwsDiffusionNodePickerShPtr ChppciServer::createDiffusionNodePicker(std::string inName)
    {
      CkwsDiffusionNodePickerShPtr result;

      if (diffusionNodePickerFactoryAlreadySet(inName)) {
	result = attMapDiffusionNodePickerFactory[inName]->makeDiffusionNodePicker();
      }
      return result;
    }

    /*
      DIFFUSION SHOOTER FACTORIES
    */

    void ChppciServer::initMapDiffusionShooterFactory()
    {
      attMapDiffusionShooterFactory["config space"] = new CkwsPlusShooterConfigSpaceFactory;
      attMapDiffusionShooterFactory["roadmap box"] = new CkwsPlusShooterRoadmapBoxFactory;
      attMapDiffusionShooterFactory["roadmap node"] = new CkwsPlusShooterRoadmapNodesFactory;
    }

    void ChppciServer::destroyDiffusionShooterFactory()
    {
      std::map<std::string, CkwsPlusDiffusionShooterFactory*>::iterator start
	= attMapDiffusionShooterFactory.begin();
      std::map<std::string, CkwsPlusDiffusionShooterFactory*>::iterator end
	= attMapDiffusionShooterFactory.end();

      for (std::map<std::string, CkwsPlusDiffusionShooterFactory*>::iterator it=start;
	   it != end; it++) {
	CkwsPlusDiffusionShooterFactory* factory = it->second;
	hppDout (info, " deleting diffusion shooter factory" << it->first);
	delete factory;
      }
    }

    bool ChppciServer::diffusionShooterFactoryAlreadySet(std::string inName)
    {
      if (attMapDiffusionShooterFactory.count(inName) == 1) {
	return true;
      }
      return false;
    }

    bool ChppciServer::addDiffusionShooterFactory(std::string inName,
						  CkwsPlusDiffusionShooterFactory* inDiffusionShooterFactory)
    {
      if(diffusionShooterFactoryAlreadySet(inName)) {
	return false;
      }
      attMapDiffusionShooterFactory[inName] = inDiffusionShooterFactory;
      return true;
    }

    CkwsDiffusionShooterShPtr ChppciServer::createDiffusionShooter(std::string inName,
								   double inStandardDeviation)
    {
      CkwsDiffusionShooterShPtr result;

      if (diffusionShooterFactoryAlreadySet(inName)) {
	result = attMapDiffusionShooterFactory[inName]->makeDiffusionShooter(inStandardDeviation);
      }
      return result;
    }

    /*
      CORBA SERVER INITIALIZATION
    */

    ktStatus ChppciServer::initORBandChppciServers(int argc, const char* argv[], bool inMultiThread)
    {
      Object_var obj;
      PortableChppciServer::ThreadPolicy_var threadPolicy;
      PortableChppciServer::POA_var rootPoa;

      /*
	 Fine granularity in exception handling
      */

      /*
	ORB init
      */
      try {
	attPrivate->orb_ = ORB_init (argc, const_cast<char **> (argv)); //FIXME: handle this properly.
	if (is_nil(attPrivate->orb_)) {
	  hppDout (error, "failed to initialize ORB");
	  return KD_ERROR;
	}
      }
      HPPCI_CATCH("failed to initialize ORB", KD_ERROR)

	/*
	  ORB init
	*/

	try {
	  obj = attPrivate->orb_->resolve_initial_references("RootPOA");
	}
      HPPCI_CATCH("failed to resolve initial references", KD_ERROR)

	/*
	  Create thread policy
	*/

	try {
	  //
	  // Make the CORBA object single-threaded to avoid GUI krash
	  //
	  // Create a sigle threaded policy object
	  rootPoa = PortableChppciServer::POA::_narrow(obj);

	  if (inMultiThread) {
	    threadPolicy = rootPoa->create_thread_policy(PortableChppciServer::ORB_CTRL_MODEL);
	  }
	  else {
	    threadPolicy = rootPoa->create_thread_policy(PortableChppciServer::MAIN_THREAD_MODEL);
	  }
	}
      HPPCI_CATCH("failed to create thread policy", KD_ERROR)

	/*
	  Duplicate thread policy
	*/

	try {
	  PolicyList policyList;
	  policyList.length(1);
	  policyList[0] = PortableChppciServer::ThreadPolicy::_duplicate(threadPolicy);

	  attPrivate->poa_ = rootPoa->create_POA("child", PortableChppciServer::POAManager::_nil(),
						policyList);

	}
      HPPCI_CATCH("failed to duplicate thread policy", KD_ERROR)

	/*
	  Destroy thread policy
	*/

	try {
	  // Destroy policy object
	  threadPolicy->destroy();

	}
      HPPCI_CATCH("failed to destroy thread policy", KD_ERROR);

      return attPrivate->createAndActivateChppciServers(this);
    }

    int ChppciServer::startCorbaChppciServer()
    {
      try {
	// Obtain a reference to objects, and register them in
	// the naming service.
	Object_var robotObj = attPrivate->robotServant_->_this();
	Object_var obstacleObj = attPrivate->obstacleServant_->_this();
	Object_var problemObj = attPrivate->problemServant_->_this();

	if (!attPrivate->createHppContext()) {
	  return KD_ERROR;
	}
	// Bind robotObj with name Robot to the hppContext:
	CosNaming::Name objectName;
	objectName.length(1);
	objectName[0].id   = (const char*) "robots";   // string copied
	objectName[0].kind = (const char*) "servant"; // string copied

	if(!attPrivate->bindObjectToName(robotObj, objectName)) {
	  return KD_ERROR;
	}
	attPrivate->robotServant_->_remove_ref();

	// Bind obstacleObj with name Obstacle to the hppContext:
	objectName.length(1);
	objectName[0].id   = (const char*) "obstacles";   // string copied
	objectName[0].kind = (const char*) "servant"; // string copied

	if(!attPrivate->bindObjectToName(obstacleObj, objectName)) {
	  return KD_ERROR;
	}
	attPrivate->obstacleServant_->_remove_ref();

	// Bind problemObj with name Problem to the hppContext:
	objectName.length(1);
	objectName[0].id   = (const char*) "problems";   // string copied
	objectName[0].kind = (const char*) "servant"; // string copied

	if(!attPrivate->bindObjectToName(problemObj, objectName)) {
	  return KD_ERROR;
	}
	attPrivate->problemServant_->_remove_ref();

	PortableChppciServer::POAManager_var pman = attPrivate->poa_->the_POAManager();
	pman->activate();
      }
      HPPCI_CATCH("failed to start CORBA server", KD_ERROR);
      return KD_OK;
    }

    const core::Planner* ChppciServer::planner() const
    {
      return hppPlanner;
    }

    core::Planner* ChppciServer::planner()
    {
      return hppPlanner;
    }

    /// \brief If CORBA requests are pending, process them
    int ChppciServer::processRequest (bool loop)
    {
      if (loop)
	{
	  hppDout (info, "start processing CORBA requests for ever.");
	  attPrivate->orb_->run();
	}
      else
	{
	  if (attPrivate->orb_->work_pending())
	    attPrivate->orb_->perform_work();
	}
      return 0;
    }

  } // end of namespace corbaChppciServer.
} // end of namespace hpp.
<|endoftext|>


<commit_before>#include "gtest/gtest.h"
#include <ten/json.hh>
#include <array>

#include "ten/logging.hh"
#include "ten/jsonstream.hh"
#include <map>

using namespace std;
using namespace ten;

const char json_text[] =
"{ \"store\": {"
"    \"book\": ["
"      { \"category\": \"reference\","
"        \"author\": \"Nigel Rees\","
"        \"title\": \"Sayings of the Century\","
"        \"price\": 8.95"
"      },"
"      { \"category\": \"fiction\","
"        \"author\": \"Evelyn Waugh\","
"        \"title\": \"Sword of Honour\","
"        \"price\": 12.99"
"      },"
"      { \"category\": \"fiction\","
"        \"author\": \"Herman Melville\","
"        \"title\": \"Moby Dick\","
"        \"isbn\": \"0-553-21311-3\","
"        \"price\": 8.99"
"      },"
"      { \"category\": \"fiction\","
"        \"author\": \"J. R. R. Tolkien\","
"        \"title\": \"The Lord of the Rings\","
"        \"isbn\": \"0-395-19395-8\","
"        \"price\": 22.99"
"      }"
"    ],"
"    \"bicycle\": {"
"      \"color\": \"red\","
"      \"price\": 19.95"
"    }"
"  }"
"}";

TEST(Json, Path1) {
    json o{json::load(json_text)};
    ASSERT_TRUE(o.get());

    static const char a1[] = "[\"Nigel Rees\", \"Evelyn Waugh\", \"Herman Melville\", \"J. R. R. Tolkien\"]";
    json r1{o.path("/store/book/author")};
    EXPECT_EQ(json::load(a1), r1);

    json r2{o.path("//author")};
    EXPECT_EQ(json::load(a1), r2);

    // jansson hashtable uses size_t for hash
    // we think this is causing the buckets to change on 32bit vs. 64bit
#if (__SIZEOF_SIZE_T__ == 4)
    static const char a3[] = "[{\"category\": \"reference\", \"author\": \"Nigel Rees\", \"title\": \"Sayings of the Century\", \"price\": 8.95}, {\"category\": \"fiction\", \"author\": \"Evelyn Waugh\", \"title\": \"Sword of Honour\", \"price\": 12.99}, {\"category\": \"fiction\", \"author\": \"Herman Melville\", \"title\": \"Moby Dick\", \"isbn\": \"0-553-21311-3\", \"price\": 8.99}, {\"category\": \"fiction\", \"author\": \"J. R. R. Tolkien\", \"title\": \"The Lord of the Rings\", \"isbn\": \"0-395-19395-8\", \"price\": 22.99}, {\"color\": \"red\", \"price\": 19.95}]";
#elif (__SIZEOF_SIZE_T__ == 8)
    static const char a3[] = "[{\"color\": \"red\", \"price\": 19.95}, {\"category\": \"reference\", \"author\": \"Nigel Rees\", \"title\": \"Sayings of the Century\", \"price\": 8.95}, {\"category\": \"fiction\", \"author\": \"Evelyn Waugh\", \"title\": \"Sword of Honour\", \"price\": 12.99}, {\"category\": \"fiction\", \"author\": \"Herman Melville\", \"title\": \"Moby Dick\", \"isbn\": \"0-553-21311-3\", \"price\": 8.99}, {\"category\": \"fiction\", \"author\": \"J. R. R. Tolkien\", \"title\": \"The Lord of the Rings\", \"isbn\": \"0-395-19395-8\", \"price\": 22.99}]";
#endif
    json r3{o.path("/store/*")};
    json t3{json::load(a3)};
    EXPECT_EQ(t3, r3);

#if (__SIZEOF_SIZE_T__ == 4)
    static const char a4[] = "[8.95, 12.99, 8.99, 22.99, 19.95]";
#elif (__SIZEOF_SIZE_T__ == 8)
    static const char a4[] = "[19.95, 8.95, 12.99, 8.99, 22.99]";
#endif
    json r4{o.path("/store//price")};
    EXPECT_EQ(json::load(a4), r4);

    static const char a5[] = "{\"category\": \"fiction\", \"author\": \"J. R. R. Tolkien\", \"title\": \"The Lord of the Rings\", \"isbn\": \"0-395-19395-8\", \"price\": 22.99}";
    json r5{o.path("//book[3]")};
    EXPECT_EQ(json::load(a5), r5);

    static const char a6[] = "\"J. R. R. Tolkien\"";
    json r6{o.path("/store/book[3]/author")};
    EXPECT_EQ(json::load(a6), r6);
    EXPECT_TRUE(json::load(a6) == r6);

    static const char a7[] = "[{\"category\": \"fiction\", \"author\": \"Evelyn Waugh\", \"title\": \"Sword of Honour\", \"price\": 12.99}, {\"category\": \"fiction\", \"author\": \"Herman Melville\", \"title\": \"Moby Dick\", \"isbn\": \"0-553-21311-3\", \"price\": 8.99}, {\"category\": \"fiction\", \"author\": \"J. R. R. Tolkien\", \"title\": \"The Lord of the Rings\", \"isbn\": \"0-395-19395-8\", \"price\": 22.99}]";
    json r7{o.path("/store/book[category=\"fiction\"]")};
    EXPECT_EQ(json::load(a7), r7);
}

TEST(Json, Path2) {
    json o{json::load("[{\"type\": 0}, {\"type\": 1}]")};
    EXPECT_EQ(json::load("[{\"type\":1}]"), o.path("/[type=1]"));
}

TEST(Json, FilterKeyExists) {
    json o{json::load(json_text)};
    ASSERT_TRUE(o.get());

    static const char a[] = "["
"      { \"category\": \"fiction\","
"        \"author\": \"Herman Melville\","
"        \"title\": \"Moby Dick\","
"        \"isbn\": \"0-553-21311-3\","
"        \"price\": 8.99"
"      },"
"      { \"category\": \"fiction\","
"        \"author\": \"J. R. R. Tolkien\","
"        \"title\": \"The Lord of the Rings\","
"        \"isbn\": \"0-395-19395-8\","
"        \"price\": 22.99"
"      }]";
    json r{o.path("//book[isbn]")};
    EXPECT_EQ(json::load(a), r);

    json r1{o.path("//book[doesnotexist]")};
    ASSERT_TRUE(r1.is_array());
    EXPECT_EQ(0, r1.asize());
}

TEST(Json, Truth) {
    json o{{}}; // empty init list
    EXPECT_TRUE(o.get("nothing").is_true() == false);
    EXPECT_TRUE(o.get("nothing").is_false() == false);
    EXPECT_TRUE(o.get("nothing").is_null() == false);
    EXPECT_TRUE(!o.get("nothing"));
}

TEST(Json, Path3) {
    json o{json::load(json_text)};
    ASSERT_TRUE(o.get());

    EXPECT_EQ(o, o.path("/"));
    EXPECT_EQ("Sayings of the Century",
        o.path("/store/book[category=\"reference\"]/title"));

    static const char text[] = "["
    "{\"type\":\"a\", \"value\":0},"
    "{\"type\":\"b\", \"value\":1},"
    "{\"type\":\"c\", \"value\":2},"
    "{\"type\":\"c\", \"value\":3}"
    "]";

    EXPECT_EQ(json(1), json::load(text).path("/[type=\"b\"]/value"));
}

TEST(Json, InitList) {
    json meta{
        { "foo", 17 },
        { "bar", 23 },
        { "baz", true },
        { "corge", json::array({ 1, 3.14159 }) },
        { "grault", json::array({ "hello", string("world") }) },
    };
    ASSERT_TRUE(meta);
    ASSERT_TRUE(meta.is_object());
    EXPECT_EQ(meta.osize(), 5);
    EXPECT_EQ(meta["foo"].integer(), 17);
    EXPECT_EQ(meta["corge"][0].integer(), 1);
    EXPECT_EQ(meta["grault"][1].str(), "world");
}

template <class T>
inline void test_conv(T val, json j, json_type t) {
    json j2 = to_json(val);
    EXPECT_EQ((json_type)j2.type(), t);
    EXPECT_EQ(j, j2);
    T val2 = json_cast<T>(j2);
    EXPECT_EQ(val, val2);
}

template <class T, json_type TYPE = JSON_INTEGER>
inline void test_conv_num() {
    typedef numeric_limits<T> lim;
    T range[5] = { lim::min(), T(-1), 0, T(1), lim::max() };
    for (unsigned i = 0; i < 5; ++i)
        test_conv<T>(range[i], json(range[i]), TYPE);
}

TEST(Json, Conversions) {
    test_conv<string>(string("hello"), json::str("hello"), JSON_STRING);
    EXPECT_EQ(to_json("world"), json::str("world"));

    test_conv_num<short>();
    test_conv_num<int>();
    test_conv_num<long>();
    test_conv_num<long long>();
    test_conv_num<unsigned short>();
    test_conv_num<unsigned>();
#if ULONG_MAX < LLONG_MAX
    test_conv_num<unsigned long>();
#endif

    test_conv_num<double, JSON_REAL>();
    test_conv_num<float,  JSON_REAL>();

    test_conv<bool>(true,  json::jtrue(),  JSON_TRUE);
    test_conv<bool>(false, json::jfalse(), JSON_FALSE);
}

TEST(Json, Create) {
    json obj1{{}};
    EXPECT_TRUE(obj1);
    obj1.set("test", "set");
    EXPECT_TRUE(obj1.get("test"));
    json root{
        {"obj1", obj1}
    };
    EXPECT_EQ(root.get("obj1"), obj1);
    obj1.set("this", "that");
    EXPECT_EQ(root.get("obj1").get("this").str(), "that");
    json obj2{ {"answer", 42} };
    obj1.set("obj2", obj2);
    EXPECT_EQ(root.get("obj1").get("obj2"), obj2);
}

TEST(Json, Stream) {
    // TODO: improve these tests or don't. this is a hack anyway
    using namespace jsonstream_manip;
    std::stringstream ss;
    jsonstream s(ss);
    int8_t c = 'C'; // printable
    float fval = -1.28;
    double dval = -1.28;
    s << jsobject
        << "key1" << 1234
        << "key2" << "value"
        << "list" << jsarray << "1" << 2.0f << 3.14e-20 << 4 << 5 << jsend
        << "list2" << jsarray << jsobject << jsend << jsend
        << "max_dbl" << std::numeric_limits<double>::max()
        << "inf" << std::numeric_limits<float>::infinity()
        << "nan" << (1.0 / 0.0)
        << "vec" << std::vector<int>({0, 1, 2, 3})
        << "char" << c
        << "bool" << false
        << jsescape
        << "escape" << "\n\t\""
        << "noescape" << "blahblah"
        << "raw" << jsraw
            << "[]"
        << jsnoraw
        << "lahalha" << 666
        << "fval" << fval
        << "dval" << dval
        //<< "map" << std::map<const char *, int>({{"key", 1}})
    << jsend;
    VLOG(1) << ss.str();
    auto js = json::load(ss.str());
    EXPECT_TRUE((bool)js);
    EXPECT_EQ(js.get("fval"), js.get("dval"));
}

<commit_msg>fix json test to handle explicit bool<commit_after>#include "gtest/gtest.h"
#include <ten/json.hh>
#include <array>

#include "ten/logging.hh"
#include "ten/jsonstream.hh"
#include <map>

using namespace std;
using namespace ten;

const char json_text[] =
"{ \"store\": {"
"    \"book\": ["
"      { \"category\": \"reference\","
"        \"author\": \"Nigel Rees\","
"        \"title\": \"Sayings of the Century\","
"        \"price\": 8.95"
"      },"
"      { \"category\": \"fiction\","
"        \"author\": \"Evelyn Waugh\","
"        \"title\": \"Sword of Honour\","
"        \"price\": 12.99"
"      },"
"      { \"category\": \"fiction\","
"        \"author\": \"Herman Melville\","
"        \"title\": \"Moby Dick\","
"        \"isbn\": \"0-553-21311-3\","
"        \"price\": 8.99"
"      },"
"      { \"category\": \"fiction\","
"        \"author\": \"J. R. R. Tolkien\","
"        \"title\": \"The Lord of the Rings\","
"        \"isbn\": \"0-395-19395-8\","
"        \"price\": 22.99"
"      }"
"    ],"
"    \"bicycle\": {"
"      \"color\": \"red\","
"      \"price\": 19.95"
"    }"
"  }"
"}";

TEST(Json, Path1) {
    json o{json::load(json_text)};
    ASSERT_TRUE(o.get());

    static const char a1[] = "[\"Nigel Rees\", \"Evelyn Waugh\", \"Herman Melville\", \"J. R. R. Tolkien\"]";
    json r1{o.path("/store/book/author")};
    EXPECT_EQ(json::load(a1), r1);

    json r2{o.path("//author")};
    EXPECT_EQ(json::load(a1), r2);

    // jansson hashtable uses size_t for hash
    // we think this is causing the buckets to change on 32bit vs. 64bit
#if (__SIZEOF_SIZE_T__ == 4)
    static const char a3[] = "[{\"category\": \"reference\", \"author\": \"Nigel Rees\", \"title\": \"Sayings of the Century\", \"price\": 8.95}, {\"category\": \"fiction\", \"author\": \"Evelyn Waugh\", \"title\": \"Sword of Honour\", \"price\": 12.99}, {\"category\": \"fiction\", \"author\": \"Herman Melville\", \"title\": \"Moby Dick\", \"isbn\": \"0-553-21311-3\", \"price\": 8.99}, {\"category\": \"fiction\", \"author\": \"J. R. R. Tolkien\", \"title\": \"The Lord of the Rings\", \"isbn\": \"0-395-19395-8\", \"price\": 22.99}, {\"color\": \"red\", \"price\": 19.95}]";
#elif (__SIZEOF_SIZE_T__ == 8)
    static const char a3[] = "[{\"color\": \"red\", \"price\": 19.95}, {\"category\": \"reference\", \"author\": \"Nigel Rees\", \"title\": \"Sayings of the Century\", \"price\": 8.95}, {\"category\": \"fiction\", \"author\": \"Evelyn Waugh\", \"title\": \"Sword of Honour\", \"price\": 12.99}, {\"category\": \"fiction\", \"author\": \"Herman Melville\", \"title\": \"Moby Dick\", \"isbn\": \"0-553-21311-3\", \"price\": 8.99}, {\"category\": \"fiction\", \"author\": \"J. R. R. Tolkien\", \"title\": \"The Lord of the Rings\", \"isbn\": \"0-395-19395-8\", \"price\": 22.99}]";
#endif
    json r3{o.path("/store/*")};
    json t3{json::load(a3)};
    EXPECT_EQ(t3, r3);

#if (__SIZEOF_SIZE_T__ == 4)
    static const char a4[] = "[8.95, 12.99, 8.99, 22.99, 19.95]";
#elif (__SIZEOF_SIZE_T__ == 8)
    static const char a4[] = "[19.95, 8.95, 12.99, 8.99, 22.99]";
#endif
    json r4{o.path("/store//price")};
    EXPECT_EQ(json::load(a4), r4);

    static const char a5[] = "{\"category\": \"fiction\", \"author\": \"J. R. R. Tolkien\", \"title\": \"The Lord of the Rings\", \"isbn\": \"0-395-19395-8\", \"price\": 22.99}";
    json r5{o.path("//book[3]")};
    EXPECT_EQ(json::load(a5), r5);

    static const char a6[] = "\"J. R. R. Tolkien\"";
    json r6{o.path("/store/book[3]/author")};
    EXPECT_EQ(json::load(a6), r6);
    EXPECT_TRUE(json::load(a6) == r6);

    static const char a7[] = "[{\"category\": \"fiction\", \"author\": \"Evelyn Waugh\", \"title\": \"Sword of Honour\", \"price\": 12.99}, {\"category\": \"fiction\", \"author\": \"Herman Melville\", \"title\": \"Moby Dick\", \"isbn\": \"0-553-21311-3\", \"price\": 8.99}, {\"category\": \"fiction\", \"author\": \"J. R. R. Tolkien\", \"title\": \"The Lord of the Rings\", \"isbn\": \"0-395-19395-8\", \"price\": 22.99}]";
    json r7{o.path("/store/book[category=\"fiction\"]")};
    EXPECT_EQ(json::load(a7), r7);
}

TEST(Json, Path2) {
    json o{json::load("[{\"type\": 0}, {\"type\": 1}]")};
    EXPECT_EQ(json::load("[{\"type\":1}]"), o.path("/[type=1]"));
}

TEST(Json, FilterKeyExists) {
    json o{json::load(json_text)};
    ASSERT_TRUE(o.get());

    static const char a[] = "["
"      { \"category\": \"fiction\","
"        \"author\": \"Herman Melville\","
"        \"title\": \"Moby Dick\","
"        \"isbn\": \"0-553-21311-3\","
"        \"price\": 8.99"
"      },"
"      { \"category\": \"fiction\","
"        \"author\": \"J. R. R. Tolkien\","
"        \"title\": \"The Lord of the Rings\","
"        \"isbn\": \"0-395-19395-8\","
"        \"price\": 22.99"
"      }]";
    json r{o.path("//book[isbn]")};
    EXPECT_EQ(json::load(a), r);

    json r1{o.path("//book[doesnotexist]")};
    ASSERT_TRUE(r1.is_array());
    EXPECT_EQ(0, r1.asize());
}

TEST(Json, Truth) {
    json o{{}}; // empty init list
    EXPECT_TRUE(o.get("nothing").is_true() == false);
    EXPECT_TRUE(o.get("nothing").is_false() == false);
    EXPECT_TRUE(o.get("nothing").is_null() == false);
    EXPECT_TRUE(!o.get("nothing"));
}

TEST(Json, Path3) {
    json o{json::load(json_text)};
    ASSERT_TRUE(o.get());

    EXPECT_EQ(o, o.path("/"));
    EXPECT_EQ("Sayings of the Century",
        o.path("/store/book[category=\"reference\"]/title"));

    static const char text[] = "["
    "{\"type\":\"a\", \"value\":0},"
    "{\"type\":\"b\", \"value\":1},"
    "{\"type\":\"c\", \"value\":2},"
    "{\"type\":\"c\", \"value\":3}"
    "]";

    EXPECT_EQ(json(1), json::load(text).path("/[type=\"b\"]/value"));
}

TEST(Json, InitList) {
    json meta{
        { "foo", 17 },
        { "bar", 23 },
        { "baz", true },
        { "corge", json::array({ 1, 3.14159 }) },
        { "grault", json::array({ "hello", string("world") }) },
    };
    ASSERT_TRUE((bool)meta);
    ASSERT_TRUE(meta.is_object());
    EXPECT_EQ(meta.osize(), 5);
    EXPECT_EQ(meta["foo"].integer(), 17);
    EXPECT_EQ(meta["corge"][0].integer(), 1);
    EXPECT_EQ(meta["grault"][1].str(), "world");
}

template <class T>
inline void test_conv(T val, json j, json_type t) {
    json j2 = to_json(val);
    EXPECT_EQ((json_type)j2.type(), t);
    EXPECT_EQ(j, j2);
    T val2 = json_cast<T>(j2);
    EXPECT_EQ(val, val2);
}

template <class T, json_type TYPE = JSON_INTEGER>
inline void test_conv_num() {
    typedef numeric_limits<T> lim;
    T range[5] = { lim::min(), T(-1), 0, T(1), lim::max() };
    for (unsigned i = 0; i < 5; ++i)
        test_conv<T>(range[i], json(range[i]), TYPE);
}

TEST(Json, Conversions) {
    test_conv<string>(string("hello"), json::str("hello"), JSON_STRING);
    EXPECT_EQ(to_json("world"), json::str("world"));

    test_conv_num<short>();
    test_conv_num<int>();
    test_conv_num<long>();
    test_conv_num<long long>();
    test_conv_num<unsigned short>();
    test_conv_num<unsigned>();
#if ULONG_MAX < LLONG_MAX
    test_conv_num<unsigned long>();
#endif

    test_conv_num<double, JSON_REAL>();
    test_conv_num<float,  JSON_REAL>();

    test_conv<bool>(true,  json::jtrue(),  JSON_TRUE);
    test_conv<bool>(false, json::jfalse(), JSON_FALSE);
}

TEST(Json, Create) {
    json obj1{{}};
    EXPECT_TRUE((bool)obj1);
    obj1.set("test", "set");
    EXPECT_TRUE((bool)obj1.get("test"));
    json root{
        {"obj1", obj1}
    };
    EXPECT_EQ(root.get("obj1"), obj1);
    obj1.set("this", "that");
    EXPECT_EQ(root.get("obj1").get("this").str(), "that");
    json obj2{ {"answer", 42} };
    obj1.set("obj2", obj2);
    EXPECT_EQ(root.get("obj1").get("obj2"), obj2);
}

TEST(Json, Stream) {
    // TODO: improve these tests or don't. this is a hack anyway
    using namespace jsonstream_manip;
    std::stringstream ss;
    jsonstream s(ss);
    int8_t c = 'C'; // printable
    float fval = -1.28;
    double dval = -1.28;
    s << jsobject
        << "key1" << 1234
        << "key2" << "value"
        << "list" << jsarray << "1" << 2.0f << 3.14e-20 << 4 << 5 << jsend
        << "list2" << jsarray << jsobject << jsend << jsend
        << "max_dbl" << std::numeric_limits<double>::max()
        << "inf" << std::numeric_limits<float>::infinity()
        << "nan" << (1.0 / 0.0)
        << "vec" << std::vector<int>({0, 1, 2, 3})
        << "char" << c
        << "bool" << false
        << jsescape
        << "escape" << "\n\t\""
        << "noescape" << "blahblah"
        << "raw" << jsraw
            << "[]"
        << jsnoraw
        << "lahalha" << 666
        << "fval" << fval
        << "dval" << dval
        //<< "map" << std::map<const char *, int>({{"key", 1}})
    << jsend;
    VLOG(1) << ss.str();
    auto js = json::load(ss.str());
    EXPECT_TRUE((bool)js);
    EXPECT_EQ(js.get("fval"), js.get("dval"));
}

<|endoftext|>


<commit_before>#include <string>
#include <stdio.h>
#include <id3v2tag.h>
#include <infotag.h>
#include <tbytevectorlist.h>
#include <tpropertymap.h>
#include <wavfile.h>
#include <cppunit/extensions/HelperMacros.h>
#include "utils.h"

using namespace std;
using namespace TagLib;

class TestWAV : public CppUnit::TestFixture
{
  CPPUNIT_TEST_SUITE(TestWAV);
  CPPUNIT_TEST(testPCMProperties);
  CPPUNIT_TEST(testALAWProperties);
  CPPUNIT_TEST(testFloatProperties);
  CPPUNIT_TEST(testZeroSizeDataChunk);
  CPPUNIT_TEST(testID3v2Tag);
  CPPUNIT_TEST(testInfoTag);
  CPPUNIT_TEST(testStripTags);
  CPPUNIT_TEST(testDuplicateTags);
  CPPUNIT_TEST(testFuzzedFile1);
  CPPUNIT_TEST(testFuzzedFile2);
  CPPUNIT_TEST(testStripAndProperties);
  CPPUNIT_TEST_SUITE_END();

public:

  void testPCMProperties()
  {
    RIFF::WAV::File f(TEST_FILE_PATH_C("empty.wav"));
    CPPUNIT_ASSERT(f.audioProperties());
    CPPUNIT_ASSERT_EQUAL(3, f.audioProperties()->length());
    CPPUNIT_ASSERT_EQUAL(3, f.audioProperties()->lengthInSeconds());
    CPPUNIT_ASSERT_EQUAL(3675, f.audioProperties()->lengthInMilliseconds());
    CPPUNIT_ASSERT_EQUAL(32, f.audioProperties()->bitrate());
    CPPUNIT_ASSERT_EQUAL(2, f.audioProperties()->channels());
    CPPUNIT_ASSERT_EQUAL(1000, f.audioProperties()->sampleRate());
    CPPUNIT_ASSERT_EQUAL(16, f.audioProperties()->bitsPerSample());
    CPPUNIT_ASSERT_EQUAL(16, f.audioProperties()->sampleWidth());
    CPPUNIT_ASSERT_EQUAL(3675U, f.audioProperties()->sampleFrames());
    CPPUNIT_ASSERT_EQUAL(1, f.audioProperties()->format());
  }

  void testALAWProperties()
  {
    RIFF::WAV::File f(TEST_FILE_PATH_C("alaw.wav"));
    CPPUNIT_ASSERT(f.audioProperties());
    CPPUNIT_ASSERT_EQUAL(3, f.audioProperties()->length());
    CPPUNIT_ASSERT_EQUAL(3, f.audioProperties()->lengthInSeconds());
    CPPUNIT_ASSERT_EQUAL(3550, f.audioProperties()->lengthInMilliseconds());
    CPPUNIT_ASSERT_EQUAL(128, f.audioProperties()->bitrate());
    CPPUNIT_ASSERT_EQUAL(2, f.audioProperties()->channels());
    CPPUNIT_ASSERT_EQUAL(8000, f.audioProperties()->sampleRate());
    CPPUNIT_ASSERT_EQUAL(8, f.audioProperties()->bitsPerSample());
    CPPUNIT_ASSERT_EQUAL(8, f.audioProperties()->sampleWidth());
    CPPUNIT_ASSERT_EQUAL(28400U, f.audioProperties()->sampleFrames());
    CPPUNIT_ASSERT_EQUAL(6, f.audioProperties()->format());
  }

  void testFloatProperties()
  {
    RIFF::WAV::File f(TEST_FILE_PATH_C("float64.wav"));
    CPPUNIT_ASSERT(f.audioProperties());
    CPPUNIT_ASSERT_EQUAL(0, f.audioProperties()->length());
    CPPUNIT_ASSERT_EQUAL(0, f.audioProperties()->lengthInSeconds());
    CPPUNIT_ASSERT_EQUAL(97, f.audioProperties()->lengthInMilliseconds());
    CPPUNIT_ASSERT_EQUAL(5645, f.audioProperties()->bitrate());
    CPPUNIT_ASSERT_EQUAL(2, f.audioProperties()->channels());
    CPPUNIT_ASSERT_EQUAL(44100, f.audioProperties()->sampleRate());
    CPPUNIT_ASSERT_EQUAL(64, f.audioProperties()->bitsPerSample());
    CPPUNIT_ASSERT_EQUAL(64, f.audioProperties()->sampleWidth());
    CPPUNIT_ASSERT_EQUAL(4281U, f.audioProperties()->sampleFrames());
    CPPUNIT_ASSERT_EQUAL(3, f.audioProperties()->format());
  }

  void testZeroSizeDataChunk()
  {
    RIFF::WAV::File f(TEST_FILE_PATH_C("zero-size-chunk.wav"));
    CPPUNIT_ASSERT(!f.isValid());
  }

  void testID3v2Tag()
  {
    ScopedFileCopy copy("empty", ".wav");
    string filename = copy.fileName();

    {
      RIFF::WAV::File f(filename.c_str());
      CPPUNIT_ASSERT(f.isValid());

      f.ID3v2Tag()->setTitle(L"Title");
      f.ID3v2Tag()->setArtist(L"Artist");
      f.save();
    }

    {
      RIFF::WAV::File f(filename.c_str());
      CPPUNIT_ASSERT(f.isValid());
      CPPUNIT_ASSERT_EQUAL(String(L"Title"),  f.ID3v2Tag()->title());
      CPPUNIT_ASSERT_EQUAL(String(L"Artist"), f.ID3v2Tag()->artist());

      f.ID3v2Tag()->setTitle(L"");
      f.ID3v2Tag()->setArtist(L"");
      f.save();
    }

    {
      RIFF::WAV::File f(filename.c_str());
      CPPUNIT_ASSERT(f.isValid());
      CPPUNIT_ASSERT_EQUAL(String(L""), f.ID3v2Tag()->title());
      CPPUNIT_ASSERT_EQUAL(String(L""), f.ID3v2Tag()->artist());
    }
  }

  void testInfoTag()
  {
    ScopedFileCopy copy("empty", ".wav");
    string filename = copy.fileName();

    {
      RIFF::WAV::File f(filename.c_str());
      CPPUNIT_ASSERT(f.isValid());

      f.InfoTag()->setTitle(L"Title");
      f.InfoTag()->setArtist(L"Artist");
      f.save();
    }

    {
      RIFF::WAV::File f(filename.c_str());
      CPPUNIT_ASSERT(f.isValid());
      CPPUNIT_ASSERT_EQUAL(String(L"Title"),  f.InfoTag()->title());
      CPPUNIT_ASSERT_EQUAL(String(L"Artist"), f.InfoTag()->artist());

      f.InfoTag()->setTitle(L"");
      f.InfoTag()->setArtist(L"");
      f.save();
    }

    {
      RIFF::WAV::File f(filename.c_str());
      CPPUNIT_ASSERT(f.isValid());
      CPPUNIT_ASSERT_EQUAL(String(L""), f.InfoTag()->title());
      CPPUNIT_ASSERT_EQUAL(String(L""), f.InfoTag()->artist());
    }
  }

  void testStripTags()
  {
    ScopedFileCopy copy("empty", ".wav");
    string filename = copy.fileName();

    {
      RIFF::WAV::File f(filename.c_str());
      f.ID3v2Tag()->setTitle("test title");
      f.InfoTag()->setTitle("test title");
      f.save();
    }
    {
      RIFF::WAV::File f(filename.c_str());
      CPPUNIT_ASSERT(f.hasID3v2Tag());
      CPPUNIT_ASSERT(f.hasInfoTag());
      f.save(RIFF::WAV::File::ID3v2, true);
    }
    {
      RIFF::WAV::File f(filename.c_str());
      CPPUNIT_ASSERT(f.hasID3v2Tag());
      CPPUNIT_ASSERT(!f.hasInfoTag());
      f.ID3v2Tag()->setTitle("test title");
      f.InfoTag()->setTitle("test title");
      f.save();
    }
    {
      RIFF::WAV::File f(filename.c_str());
      CPPUNIT_ASSERT(f.hasID3v2Tag());
      CPPUNIT_ASSERT(f.hasInfoTag());
      f.save(RIFF::WAV::File::Info, true);
    }
    {
      RIFF::WAV::File f(filename.c_str());
      CPPUNIT_ASSERT(!f.hasID3v2Tag());
      CPPUNIT_ASSERT(f.hasInfoTag());
    }
  }

  void testDuplicateTags()
  {
    ScopedFileCopy copy("duplicate_tags", ".wav");

    RIFF::WAV::File f(copy.fileName().c_str());
    CPPUNIT_ASSERT_EQUAL(17052L, f.length());

    // duplicate_tags.wav has duplicate ID3v2/INFO tags.
    // title() returns "Title2" if can't skip the second tag.

    CPPUNIT_ASSERT(f.hasID3v2Tag());
    CPPUNIT_ASSERT_EQUAL(String("Title1"), f.ID3v2Tag()->title());

    CPPUNIT_ASSERT(f.hasInfoTag());
    CPPUNIT_ASSERT_EQUAL(String("Title1"), f.InfoTag()->title());

    f.save();
    CPPUNIT_ASSERT_EQUAL(15898L, f.length());
    CPPUNIT_ASSERT_EQUAL(-1L, f.find("Title2"));
  }

  void testFuzzedFile1()
  {
    RIFF::WAV::File f1(TEST_FILE_PATH_C("infloop.wav"));
    CPPUNIT_ASSERT(!f1.isValid());
  }

  void testFuzzedFile2()
  {
    RIFF::WAV::File f2(TEST_FILE_PATH_C("segfault.wav"));
    CPPUNIT_ASSERT(f2.isValid());
  }

  void testStripAndProperties()
  {
    ScopedFileCopy copy("empty", ".wav");

    {
      RIFF::WAV::File f(copy.fileName().c_str());
      f.ID3v2Tag()->setTitle("ID3v2");
      f.InfoTag()->setTitle("INFO");
      f.save();
    }
    {
      RIFF::WAV::File f(copy.fileName().c_str());
      CPPUNIT_ASSERT_EQUAL(String("ID3v2"), f.properties()["TITLE"].front());
      f.strip(RIFF::WAV::File::ID3v2);
      CPPUNIT_ASSERT_EQUAL(String("INFO"), f.properties()["TITLE"].front());
      f.strip(RIFF::WAV::File::Info);
      CPPUNIT_ASSERT(f.properties().isEmpty());
    }
  }

};

CPPUNIT_TEST_SUITE_REGISTRATION(TestWAV);
<commit_msg>Add some tests to check if the internal flags are updated when writing WAV files.<commit_after>#include <string>
#include <stdio.h>
#include <id3v2tag.h>
#include <infotag.h>
#include <tbytevectorlist.h>
#include <tpropertymap.h>
#include <wavfile.h>
#include <cppunit/extensions/HelperMacros.h>
#include "utils.h"

using namespace std;
using namespace TagLib;

class TestWAV : public CppUnit::TestFixture
{
  CPPUNIT_TEST_SUITE(TestWAV);
  CPPUNIT_TEST(testPCMProperties);
  CPPUNIT_TEST(testALAWProperties);
  CPPUNIT_TEST(testFloatProperties);
  CPPUNIT_TEST(testZeroSizeDataChunk);
  CPPUNIT_TEST(testID3v2Tag);
  CPPUNIT_TEST(testInfoTag);
  CPPUNIT_TEST(testStripTags);
  CPPUNIT_TEST(testDuplicateTags);
  CPPUNIT_TEST(testFuzzedFile1);
  CPPUNIT_TEST(testFuzzedFile2);
  CPPUNIT_TEST(testStripAndProperties);
  CPPUNIT_TEST_SUITE_END();

public:

  void testPCMProperties()
  {
    RIFF::WAV::File f(TEST_FILE_PATH_C("empty.wav"));
    CPPUNIT_ASSERT(f.audioProperties());
    CPPUNIT_ASSERT_EQUAL(3, f.audioProperties()->length());
    CPPUNIT_ASSERT_EQUAL(3, f.audioProperties()->lengthInSeconds());
    CPPUNIT_ASSERT_EQUAL(3675, f.audioProperties()->lengthInMilliseconds());
    CPPUNIT_ASSERT_EQUAL(32, f.audioProperties()->bitrate());
    CPPUNIT_ASSERT_EQUAL(2, f.audioProperties()->channels());
    CPPUNIT_ASSERT_EQUAL(1000, f.audioProperties()->sampleRate());
    CPPUNIT_ASSERT_EQUAL(16, f.audioProperties()->bitsPerSample());
    CPPUNIT_ASSERT_EQUAL(16, f.audioProperties()->sampleWidth());
    CPPUNIT_ASSERT_EQUAL(3675U, f.audioProperties()->sampleFrames());
    CPPUNIT_ASSERT_EQUAL(1, f.audioProperties()->format());
  }

  void testALAWProperties()
  {
    RIFF::WAV::File f(TEST_FILE_PATH_C("alaw.wav"));
    CPPUNIT_ASSERT(f.audioProperties());
    CPPUNIT_ASSERT_EQUAL(3, f.audioProperties()->length());
    CPPUNIT_ASSERT_EQUAL(3, f.audioProperties()->lengthInSeconds());
    CPPUNIT_ASSERT_EQUAL(3550, f.audioProperties()->lengthInMilliseconds());
    CPPUNIT_ASSERT_EQUAL(128, f.audioProperties()->bitrate());
    CPPUNIT_ASSERT_EQUAL(2, f.audioProperties()->channels());
    CPPUNIT_ASSERT_EQUAL(8000, f.audioProperties()->sampleRate());
    CPPUNIT_ASSERT_EQUAL(8, f.audioProperties()->bitsPerSample());
    CPPUNIT_ASSERT_EQUAL(8, f.audioProperties()->sampleWidth());
    CPPUNIT_ASSERT_EQUAL(28400U, f.audioProperties()->sampleFrames());
    CPPUNIT_ASSERT_EQUAL(6, f.audioProperties()->format());
  }

  void testFloatProperties()
  {
    RIFF::WAV::File f(TEST_FILE_PATH_C("float64.wav"));
    CPPUNIT_ASSERT(f.audioProperties());
    CPPUNIT_ASSERT_EQUAL(0, f.audioProperties()->length());
    CPPUNIT_ASSERT_EQUAL(0, f.audioProperties()->lengthInSeconds());
    CPPUNIT_ASSERT_EQUAL(97, f.audioProperties()->lengthInMilliseconds());
    CPPUNIT_ASSERT_EQUAL(5645, f.audioProperties()->bitrate());
    CPPUNIT_ASSERT_EQUAL(2, f.audioProperties()->channels());
    CPPUNIT_ASSERT_EQUAL(44100, f.audioProperties()->sampleRate());
    CPPUNIT_ASSERT_EQUAL(64, f.audioProperties()->bitsPerSample());
    CPPUNIT_ASSERT_EQUAL(64, f.audioProperties()->sampleWidth());
    CPPUNIT_ASSERT_EQUAL(4281U, f.audioProperties()->sampleFrames());
    CPPUNIT_ASSERT_EQUAL(3, f.audioProperties()->format());
  }

  void testZeroSizeDataChunk()
  {
    RIFF::WAV::File f(TEST_FILE_PATH_C("zero-size-chunk.wav"));
    CPPUNIT_ASSERT(!f.isValid());
  }

  void testID3v2Tag()
  {
    ScopedFileCopy copy("empty", ".wav");
    string filename = copy.fileName();

    {
      RIFF::WAV::File f(filename.c_str());
      CPPUNIT_ASSERT(f.isValid());
      CPPUNIT_ASSERT(!f.hasID3v2Tag());

      f.ID3v2Tag()->setTitle(L"Title");
      f.ID3v2Tag()->setArtist(L"Artist");
      f.save();
      CPPUNIT_ASSERT(f.hasID3v2Tag());
    }
    {
      RIFF::WAV::File f(filename.c_str());
      CPPUNIT_ASSERT(f.isValid());
      CPPUNIT_ASSERT(f.hasID3v2Tag());
      CPPUNIT_ASSERT_EQUAL(String(L"Title"),  f.ID3v2Tag()->title());
      CPPUNIT_ASSERT_EQUAL(String(L"Artist"), f.ID3v2Tag()->artist());

      f.ID3v2Tag()->setTitle(L"");
      f.ID3v2Tag()->setArtist(L"");
      f.save();
      CPPUNIT_ASSERT(!f.hasID3v2Tag());
    }
    {
      RIFF::WAV::File f(filename.c_str());
      CPPUNIT_ASSERT(f.isValid());
      CPPUNIT_ASSERT(!f.hasID3v2Tag());
      CPPUNIT_ASSERT_EQUAL(String(L""), f.ID3v2Tag()->title());
      CPPUNIT_ASSERT_EQUAL(String(L""), f.ID3v2Tag()->artist());
    }
  }

  void testInfoTag()
  {
    ScopedFileCopy copy("empty", ".wav");
    string filename = copy.fileName();

    {
      RIFF::WAV::File f(filename.c_str());
      CPPUNIT_ASSERT(f.isValid());
      CPPUNIT_ASSERT(!f.hasInfoTag());

      f.InfoTag()->setTitle(L"Title");
      f.InfoTag()->setArtist(L"Artist");
      f.save();
      CPPUNIT_ASSERT(f.hasInfoTag());
    }
    {
      RIFF::WAV::File f(filename.c_str());
      CPPUNIT_ASSERT(f.isValid());
      CPPUNIT_ASSERT(f.hasInfoTag());
      CPPUNIT_ASSERT_EQUAL(String(L"Title"),  f.InfoTag()->title());
      CPPUNIT_ASSERT_EQUAL(String(L"Artist"), f.InfoTag()->artist());

      f.InfoTag()->setTitle(L"");
      f.InfoTag()->setArtist(L"");
      f.save();
      CPPUNIT_ASSERT(!f.hasInfoTag());
    }

    {
      RIFF::WAV::File f(filename.c_str());
      CPPUNIT_ASSERT(f.isValid());
      CPPUNIT_ASSERT(!f.hasInfoTag());
      CPPUNIT_ASSERT_EQUAL(String(L""), f.InfoTag()->title());
      CPPUNIT_ASSERT_EQUAL(String(L""), f.InfoTag()->artist());
    }
  }

  void testStripTags()
  {
    ScopedFileCopy copy("empty", ".wav");
    string filename = copy.fileName();

    {
      RIFF::WAV::File f(filename.c_str());
      f.ID3v2Tag()->setTitle("test title");
      f.InfoTag()->setTitle("test title");
      f.save();
    }
    {
      RIFF::WAV::File f(filename.c_str());
      CPPUNIT_ASSERT(f.hasID3v2Tag());
      CPPUNIT_ASSERT(f.hasInfoTag());
      f.save(RIFF::WAV::File::ID3v2, true);
    }
    {
      RIFF::WAV::File f(filename.c_str());
      CPPUNIT_ASSERT(f.hasID3v2Tag());
      CPPUNIT_ASSERT(!f.hasInfoTag());
      f.ID3v2Tag()->setTitle("test title");
      f.InfoTag()->setTitle("test title");
      f.save();
    }
    {
      RIFF::WAV::File f(filename.c_str());
      CPPUNIT_ASSERT(f.hasID3v2Tag());
      CPPUNIT_ASSERT(f.hasInfoTag());
      f.save(RIFF::WAV::File::Info, true);
    }
    {
      RIFF::WAV::File f(filename.c_str());
      CPPUNIT_ASSERT(!f.hasID3v2Tag());
      CPPUNIT_ASSERT(f.hasInfoTag());
    }
  }

  void testDuplicateTags()
  {
    ScopedFileCopy copy("duplicate_tags", ".wav");

    RIFF::WAV::File f(copy.fileName().c_str());
    CPPUNIT_ASSERT_EQUAL(17052L, f.length());

    // duplicate_tags.wav has duplicate ID3v2/INFO tags.
    // title() returns "Title2" if can't skip the second tag.

    CPPUNIT_ASSERT(f.hasID3v2Tag());
    CPPUNIT_ASSERT_EQUAL(String("Title1"), f.ID3v2Tag()->title());

    CPPUNIT_ASSERT(f.hasInfoTag());
    CPPUNIT_ASSERT_EQUAL(String("Title1"), f.InfoTag()->title());

    f.save();
    CPPUNIT_ASSERT_EQUAL(15898L, f.length());
    CPPUNIT_ASSERT_EQUAL(-1L, f.find("Title2"));
  }

  void testFuzzedFile1()
  {
    RIFF::WAV::File f1(TEST_FILE_PATH_C("infloop.wav"));
    CPPUNIT_ASSERT(!f1.isValid());
  }

  void testFuzzedFile2()
  {
    RIFF::WAV::File f2(TEST_FILE_PATH_C("segfault.wav"));
    CPPUNIT_ASSERT(f2.isValid());
  }

  void testStripAndProperties()
  {
    ScopedFileCopy copy("empty", ".wav");

    {
      RIFF::WAV::File f(copy.fileName().c_str());
      f.ID3v2Tag()->setTitle("ID3v2");
      f.InfoTag()->setTitle("INFO");
      f.save();
    }
    {
      RIFF::WAV::File f(copy.fileName().c_str());
      CPPUNIT_ASSERT_EQUAL(String("ID3v2"), f.properties()["TITLE"].front());
      f.strip(RIFF::WAV::File::ID3v2);
      CPPUNIT_ASSERT_EQUAL(String("INFO"), f.properties()["TITLE"].front());
      f.strip(RIFF::WAV::File::Info);
      CPPUNIT_ASSERT(f.properties().isEmpty());
    }
  }

};

CPPUNIT_TEST_SUITE_REGISTRATION(TestWAV);
<|endoftext|>