<commit_before>#include <fstream>
#include <iostream> // temp!!

#include "filepage.h"

#define PAGE_MAGIC		"LFBX01E"	/* Magic checkup */

#define PAGE_FLAG_NIL	0x0
#define PAGE_FLAG_INV	0x2
#define PAGE_FLAG_GZIP	0x8
#define PAGE_FLAG_FULL	0x12

struct pageHeader {
	char magic[8];// = PAGE_MAGIC;
	unsigned short elements = 0;
	unsigned int allocated = 0;
	unsigned int first_free = 0;
	int flags = PAGE_FLAG_NIL;
};

struct pageIndex {
	char name[40];
	int item = 0;
};

size_t Filepage::size() {
	return m_Elements;
}

void Filepage::create(unsigned int alloc) {
	m_pFile = fopen(m_File.c_str(), "w+");

	pageHeader header;
	strcpy(header.magic, PAGE_MAGIC);
	header.allocated = alloc;
	header.first_free = sizeof(pageHeader) + (sizeof(pageIndex) * header.allocated);
	fwrite((const char *)&header, sizeof(pageHeader), 1, m_pFile);

	/* Allocate page on disk */
	fseek(m_pFile, sizeof(pageHeader) + (sizeof(pageIndex) * header.allocated) + (ITEM_SIZE * header.allocated), SEEK_CUR);
	fwrite("\0", 1, 1, m_pFile);

	fflush(m_pFile);

	m_Elements = header.elements;
	m_Allocated = header.allocated;
	m_FirstFree = header.first_free;
}

void Filepage::open() {
	m_pFile = fopen(m_File.c_str(), "r+");

	pageHeader header;
	fread((char *)&header, sizeof(pageHeader), 1, m_pFile);

	if (strcmp((const char *)header.magic, PAGE_MAGIC)) {
		puts("Magic error 1"); // throw error
		return;
	}

	if (header.elements > header.allocated) {
		puts("Overflow error"); // throw error
		return;
	}

	m_Elements = header.elements;
	m_Allocated = header.allocated;
	m_FirstFree = header.first_free;
}

void Filepage::writeHeader() {
	fseek(m_pFile, 0, SEEK_SET);

	pageHeader header;
	strcpy(header.magic, PAGE_MAGIC);
	header.elements = m_Elements;
	header.allocated = m_Allocated;
	header.first_free = m_FirstFree;

	fwrite((const char *)&header, sizeof(pageHeader), 1, m_pFile);

	fflush(m_pFile);
}

void Filepage::storeItem(std::string name, std::string data) {
	if (name.size() > 40) {
		puts("Name overflows index");
		return;
	}

	std::cout << "Current allocation size: " << (m_Allocated * ITEM_SIZE) << std::endl;
	std::cout << "Elements: " << m_Elements << std::endl;
	std::cout << "Free offset: " << m_FirstFree << std::endl;
	std::cout << "New data size: " << data.size() << std::endl;

	if (m_FirstFree + data.size() > (m_Allocated * ITEM_SIZE)) {
		puts("Should grow");
		return;
	}

	if (m_Elements == m_Allocated) {
		puts("Should grow certainly, fullhouse");
		return;
	}

	{
		size_t namepos = sizeof(pageHeader) + (sizeof(pageIndex) * m_Elements);
		std::cout << "Position for new name: " << namepos << std::endl;

		fseek(m_pFile, namepos, SEEK_CUR);

		pageIndex index;
		strcpy(index.name, name.c_str());
		index.item = m_FirstFree;

		fwrite((const char *)&index, sizeof(pageIndex), 1, m_pFile);
	}

	{
		std::cout << "Position for new data: " << m_FirstFree << std::endl;
		fseek(m_pFile, m_FirstFree, SEEK_CUR);

		fwrite(data.c_str(), 1, data.size(), m_pFile);

		m_FirstFree += data.size();
	}

	m_Elements++;

	writeHeader();

	fflush(m_pFile);
}
<commit_msg>Grow page<commit_after>#include <fstream>
#include <iostream> // temp!!

#include "filepage.h"

#define PAGE_MAGIC		"LFBX01E"	/* Magic checkup */

#define PAGE_FLAG_NIL	0x0
#define PAGE_FLAG_INV	0x2
#define PAGE_FLAG_GZIP	0x8
#define PAGE_FLAG_FULL	0x12

#define INDEX_FLAG_NIL	0x0
#define INDEX_FLAG_DEL	0x2

struct pageHeader {
	char magic[8];
	unsigned short elements = 0;
	unsigned int allocated = 0;
	unsigned int first_free = 0;
	int flags = PAGE_FLAG_NIL;
};

struct pageIndex {
	char name[40];
	unsigned int item = 0;
	char flags = INDEX_FLAG_NIL;
};

size_t Filepage::size() {
	return m_Elements;
}

void Filepage::create(unsigned int alloc) {
	m_pFile = fopen(m_File.c_str(), "w+");

	pageHeader header;
	strcpy(header.magic, PAGE_MAGIC);
	header.allocated = alloc;
	header.first_free = sizeof(pageHeader) + (sizeof(pageIndex) * header.allocated);
	fwrite((const char *)&header, sizeof(pageHeader), 1, m_pFile);

	/* Allocate page on disk */
	fseek(m_pFile, sizeof(pageHeader) + header.first_free + (ITEM_SIZE * header.allocated), SEEK_CUR);
	fwrite("\0", 1, 1, m_pFile);

	fflush(m_pFile);

	m_Elements = header.elements;
	m_Allocated = header.allocated;
	m_FirstFree = header.first_free;
}

void Filepage::open() {
	m_pFile = fopen(m_File.c_str(), "r+");

	pageHeader header;
	fread((char *)&header, sizeof(pageHeader), 1, m_pFile);

	if (strcmp((const char *)header.magic, PAGE_MAGIC)) {
		puts("Magic error 1"); // throw error
		return;
	}

	if (header.elements > header.allocated) {
		puts("Overflow error"); // throw error
		return;
	}

	m_Elements = header.elements;
	m_Allocated = header.allocated;
	m_FirstFree = header.first_free;
}

void Filepage::writeHeader() {
	fseek(m_pFile, 0, SEEK_SET);

	pageHeader header;
	strcpy(header.magic, PAGE_MAGIC);
	header.elements = m_Elements;
	header.allocated = m_Allocated;
	header.first_free = m_FirstFree;

	fwrite((const char *)&header, sizeof(pageHeader), 1, m_pFile);

	fflush(m_pFile);
}

void Filepage::grow() {
	m_Allocated *= 2;

	m_FirstFree += (sizeof(pageIndex) * (m_Allocated / 2));

	/* Allocate page on disk */
	fseek(m_pFile, m_FirstFree + (ITEM_SIZE * m_Allocated), SEEK_CUR);
	fwrite("\0", 1, 1, m_pFile);

	writeHeader();
}

void Filepage::storeItem(std::string name, std::string data) {
	if (name.size() > 40) {
		puts("Name overflows index");
		return;
	}

	std::cout << "Current allocation size: " << (m_Allocated * ITEM_SIZE) << std::endl;
	std::cout << "Elements: " << m_Elements << std::endl;
	std::cout << "Free offset: " << m_FirstFree << std::endl;
	std::cout << "New data size: " << data.size() << std::endl;

	if (m_FirstFree + data.size() > (m_Allocated * ITEM_SIZE)) {
		puts("Should grow");
		return;
	}

	if (m_Elements == m_Allocated) {
		puts("Should grow certainly, fullhouse");
		grow();
		return;
	}

	{
		size_t namepos = sizeof(pageHeader) + (sizeof(pageIndex) * m_Elements);
		std::cout << "Position for new name: " << namepos << std::endl;

		fseek(m_pFile, namepos, SEEK_CUR);

		pageIndex index;
		strcpy(index.name, name.c_str());
		index.item = m_FirstFree;

		fwrite((const char *)&index, sizeof(pageIndex), 1, m_pFile);
	}

	{
		std::cout << "Position for new data: " << m_FirstFree << std::endl;
		fseek(m_pFile, m_FirstFree, SEEK_CUR);

		fwrite(data.c_str(), 1, data.size(), m_pFile);

		m_FirstFree += data.size();
	}

	m_Elements++;

	writeHeader();

	fflush(m_pFile);
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: GridProperties.cxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: rt $ $Date: 2007-07-25 08:50:24 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_chart2.hxx"

#include "GridProperties.hxx"
#include "LineProperties.hxx"
#include "UserDefinedProperties.hxx"
#include "PropertyHelper.hxx"
#include "macros.hxx"
#include "ContainerHelper.hxx"

#ifndef _COM_SUN_STAR_STYLE_XSTYLE_HPP_
#include <com/sun/star/style/XStyle.hpp>
#endif
#ifndef _COM_SUN_STAR_BEANS_PROPERTYATTRIBUTE_HPP_
#include <com/sun/star/beans/PropertyAttribute.hpp>
#endif
#ifndef _COM_SUN_STAR_BEANS_XPROPERTYSET_HPP_
#include <com/sun/star/beans/XPropertySet.hpp>
#endif

#ifndef _COM_SUN_STAR_UNO_SEQUENCE_HXX_
#include <com/sun/star/uno/Sequence.hxx>
#endif

using namespace ::com::sun::star;

using ::com::sun::star::uno::Reference;
using ::com::sun::star::uno::Sequence;
using ::com::sun::star::beans::Property;
using ::osl::MutexGuard;
using ::rtl::OUString;

// ____________________________________________________________

namespace
{

static const ::rtl::OUString lcl_aServiceName(
    RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.chart2.GridProperties" ));

enum
{
    PROP_GRID_SHOW
};

void lcl_AddPropertiesToVector(
    ::std::vector< Property > & rOutProperties )
{
    rOutProperties.push_back(
        Property( C2U( "Show" ),
                  PROP_GRID_SHOW,
                  ::getBooleanCppuType(),
                  beans::PropertyAttribute::BOUND
                  | beans::PropertyAttribute::MAYBEDEFAULT ));
}

void lcl_addDefaultsToMap( ::chart::tPropertyValueMap & rOutMap )
{
    ::chart::LineProperties::AddDefaultsToMap( rOutMap );

    OSL_ASSERT( rOutMap.end() == rOutMap.find( PROP_GRID_SHOW ));
    rOutMap[ PROP_GRID_SHOW ] = uno::makeAny( sal_False );

    // override other defaults
    rOutMap[ ::chart::LineProperties::PROP_LINE_COLOR ] =
        uno::makeAny( static_cast< sal_Int32 >( 0xb3b3b3 ) );  // gray30
}

const Sequence< Property > & lcl_getPropertySequence()
{
    static Sequence< Property > aPropSeq;

    // /--
    MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() );
    if( 0 == aPropSeq.getLength() )
    {
        // get properties
        ::std::vector< Property > aProperties;
        lcl_AddPropertiesToVector( aProperties );
        ::chart::LineProperties::AddPropertiesToVector( aProperties );
        ::chart::UserDefinedProperties::AddPropertiesToVector( aProperties );

        // and sort them for access via bsearch
        ::std::sort( aProperties.begin(), aProperties.end(),
                     ::chart::PropertyNameLess() );

        // transfer result to static Sequence
        aPropSeq = ::chart::ContainerHelper::ContainerToSequence( aProperties );
    }

    return aPropSeq;
}

::cppu::IPropertyArrayHelper & lcl_getInfoHelper()
{
    static ::cppu::OPropertyArrayHelper aArrayHelper(
        lcl_getPropertySequence(),
        /* bSorted = */ sal_True );

    return aArrayHelper;
}

} // anonymous namespace

// ____________________________________________________________

namespace chart
{

GridProperties::GridProperties( Reference< uno::XComponentContext > const & /* xContext */ ) :
        ::property::OPropertySet( m_aMutex ),
    m_xModifyEventForwarder( new ModifyListenerHelper::ModifyEventForwarder( m_aMutex ))
{
}

GridProperties::GridProperties() :
        ::property::OPropertySet( m_aMutex ),
    m_xModifyEventForwarder( new ModifyListenerHelper::ModifyEventForwarder( m_aMutex ))
{}

GridProperties::GridProperties( const GridProperties & rOther ) :
        MutexContainer(),
        impl::GridProperties_Base(),
        ::property::OPropertySet( rOther, m_aMutex ),
    m_xModifyEventForwarder( new ModifyListenerHelper::ModifyEventForwarder( m_aMutex ))
{
}

GridProperties::~GridProperties()
{}

// ____ OPropertySet ____
uno::Any GridProperties::GetDefaultValue( sal_Int32 nHandle ) const
    throw(beans::UnknownPropertyException)
{
    static tPropertyValueMap aStaticDefaults;

    // /--
    ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() );
    if( 0 == aStaticDefaults.size() )
        lcl_addDefaultsToMap( aStaticDefaults );

    tPropertyValueMap::const_iterator aFound(
        aStaticDefaults.find( nHandle ));

    if( aFound == aStaticDefaults.end())
        return uno::Any();

    return (*aFound).second;
    // \--
}

::cppu::IPropertyArrayHelper & SAL_CALL GridProperties::getInfoHelper()
{
    return lcl_getInfoHelper();
}

// ____ XPropertySet ____
Reference< beans::XPropertySetInfo > SAL_CALL
    GridProperties::getPropertySetInfo()
    throw (uno::RuntimeException)
{
    static Reference< beans::XPropertySetInfo > xInfo;

    // /--
    ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() );
    if( !xInfo.is())
    {
        xInfo = ::cppu::OPropertySetHelper::createPropertySetInfo(
            lcl_getInfoHelper());
    }

    return xInfo;
    // \--
}

::osl::Mutex & GridProperties::GetMutex()
{
    return m_aMutex;
}

// ____ XCloneable ____
uno::Reference< util::XCloneable > SAL_CALL GridProperties::createClone()
    throw (uno::RuntimeException)
{
    return uno::Reference< util::XCloneable >( new GridProperties( *this ));
}

// ____ XModifyBroadcaster ____
void SAL_CALL GridProperties::addModifyListener( const Reference< util::XModifyListener >& aListener )
    throw (uno::RuntimeException)
{
    try
    {
        Reference< util::XModifyBroadcaster > xBroadcaster( m_xModifyEventForwarder, uno::UNO_QUERY_THROW );
        xBroadcaster->addModifyListener( aListener );
    }
    catch( const uno::Exception & ex )
    {
        ASSERT_EXCEPTION( ex );
    }
}

void SAL_CALL GridProperties::removeModifyListener( const Reference< util::XModifyListener >& aListener )
    throw (uno::RuntimeException)
{
    try
    {
        Reference< util::XModifyBroadcaster > xBroadcaster( m_xModifyEventForwarder, uno::UNO_QUERY_THROW );
        xBroadcaster->removeModifyListener( aListener );
    }
    catch( const uno::Exception & ex )
    {
        ASSERT_EXCEPTION( ex );
    }
}

// ____ XModifyListener ____
void SAL_CALL GridProperties::modified( const lang::EventObject& aEvent )
    throw (uno::RuntimeException)
{
    m_xModifyEventForwarder->modified( aEvent );
}

// ____ XEventListener (base of XModifyListener) ____
void SAL_CALL GridProperties::disposing( const lang::EventObject& /* Source */ )
    throw (uno::RuntimeException)
{
    // nothing
}

// ____ OPropertySet ____
void GridProperties::firePropertyChangeEvent()
{
    fireModifyEvent();
}

void GridProperties::fireModifyEvent()
{
    m_xModifyEventForwarder->modified( lang::EventObject( static_cast< uno::XWeak* >( this )));
}

// ================================================================================

Sequence< OUString > GridProperties::getSupportedServiceNames_Static()
{
    Sequence< OUString > aServices( 2 );
    aServices[ 0 ] = C2U( "com.sun.star.chart2.GridProperties" );
    aServices[ 1 ] = C2U( "com.sun.star.beans.PropertySet" );
    return aServices;
}

// implement XServiceInfo methods basing upon getSupportedServiceNames_Static
APPHELPER_XSERVICEINFO_IMPL( GridProperties, lcl_aServiceName );

// needed by MSC compiler
using impl::GridProperties_Base;

IMPLEMENT_FORWARD_XINTERFACE2( GridProperties, GridProperties_Base, ::property::OPropertySet )
IMPLEMENT_FORWARD_XTYPEPROVIDER2( GridProperties, GridProperties_Base, ::property::OPropertySet )

} //  namespace chart
<commit_msg>INTEGRATION: CWS chart11 (1.4.2); FILE MERGED 2007/07/31 22:19:25 bm 1.4.2.2: #i79522# warnings on Solaris removed 2007/07/31 12:56:45 bm 1.4.2.1: #i80084# avoid usage of map operator[] with enums as keys, simplify initialization of default property values<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: GridProperties.cxx,v $
 *
 *  $Revision: 1.5 $
 *
 *  last change: $Author: vg $ $Date: 2007-09-18 15:01:41 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_chart2.hxx"

#include "GridProperties.hxx"
#include "LineProperties.hxx"
#include "UserDefinedProperties.hxx"
#include "PropertyHelper.hxx"
#include "macros.hxx"
#include "ContainerHelper.hxx"

#ifndef _COM_SUN_STAR_STYLE_XSTYLE_HPP_
#include <com/sun/star/style/XStyle.hpp>
#endif
#ifndef _COM_SUN_STAR_BEANS_PROPERTYATTRIBUTE_HPP_
#include <com/sun/star/beans/PropertyAttribute.hpp>
#endif
#ifndef _COM_SUN_STAR_BEANS_XPROPERTYSET_HPP_
#include <com/sun/star/beans/XPropertySet.hpp>
#endif

#ifndef _COM_SUN_STAR_UNO_SEQUENCE_HXX_
#include <com/sun/star/uno/Sequence.hxx>
#endif

using namespace ::com::sun::star;

using ::com::sun::star::uno::Reference;
using ::com::sun::star::uno::Sequence;
using ::com::sun::star::beans::Property;
using ::osl::MutexGuard;
using ::rtl::OUString;

// ____________________________________________________________

namespace
{

static const ::rtl::OUString lcl_aServiceName(
    RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.chart2.GridProperties" ));

enum
{
    PROP_GRID_SHOW
};

void lcl_AddPropertiesToVector(
    ::std::vector< Property > & rOutProperties )
{
    rOutProperties.push_back(
        Property( C2U( "Show" ),
                  PROP_GRID_SHOW,
                  ::getBooleanCppuType(),
                  beans::PropertyAttribute::BOUND
                  | beans::PropertyAttribute::MAYBEDEFAULT ));
}

void lcl_addDefaultsToMap( ::chart::tPropertyValueMap & rOutMap )
{
    ::chart::LineProperties::AddDefaultsToMap( rOutMap );

    ::chart::PropertyHelper::setPropertyValueDefault( rOutMap, PROP_GRID_SHOW, false );

    // override other defaults
    ::chart::PropertyHelper::setPropertyValue< sal_Int32 >(
        rOutMap, ::chart::LineProperties::PROP_LINE_COLOR, 0xb3b3b3 );  // gray30
}

const Sequence< Property > & lcl_getPropertySequence()
{
    static Sequence< Property > aPropSeq;

    // /--
    MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() );
    if( 0 == aPropSeq.getLength() )
    {
        // get properties
        ::std::vector< Property > aProperties;
        lcl_AddPropertiesToVector( aProperties );
        ::chart::LineProperties::AddPropertiesToVector( aProperties );
        ::chart::UserDefinedProperties::AddPropertiesToVector( aProperties );

        // and sort them for access via bsearch
        ::std::sort( aProperties.begin(), aProperties.end(),
                     ::chart::PropertyNameLess() );

        // transfer result to static Sequence
        aPropSeq = ::chart::ContainerHelper::ContainerToSequence( aProperties );
    }

    return aPropSeq;
}

::cppu::IPropertyArrayHelper & lcl_getInfoHelper()
{
    static ::cppu::OPropertyArrayHelper aArrayHelper(
        lcl_getPropertySequence(),
        /* bSorted = */ sal_True );

    return aArrayHelper;
}

} // anonymous namespace

// ____________________________________________________________

namespace chart
{

GridProperties::GridProperties( Reference< uno::XComponentContext > const & /* xContext */ ) :
        ::property::OPropertySet( m_aMutex ),
    m_xModifyEventForwarder( new ModifyListenerHelper::ModifyEventForwarder( m_aMutex ))
{
}

GridProperties::GridProperties() :
        ::property::OPropertySet( m_aMutex ),
    m_xModifyEventForwarder( new ModifyListenerHelper::ModifyEventForwarder( m_aMutex ))
{}

GridProperties::GridProperties( const GridProperties & rOther ) :
        MutexContainer(),
        impl::GridProperties_Base(),
        ::property::OPropertySet( rOther, m_aMutex ),
    m_xModifyEventForwarder( new ModifyListenerHelper::ModifyEventForwarder( m_aMutex ))
{
}

GridProperties::~GridProperties()
{}

// ____ OPropertySet ____
uno::Any GridProperties::GetDefaultValue( sal_Int32 nHandle ) const
    throw(beans::UnknownPropertyException)
{
    static tPropertyValueMap aStaticDefaults;

    // /--
    ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() );
    if( 0 == aStaticDefaults.size() )
        lcl_addDefaultsToMap( aStaticDefaults );

    tPropertyValueMap::const_iterator aFound(
        aStaticDefaults.find( nHandle ));

    if( aFound == aStaticDefaults.end())
        return uno::Any();

    return (*aFound).second;
    // \--
}

::cppu::IPropertyArrayHelper & SAL_CALL GridProperties::getInfoHelper()
{
    return lcl_getInfoHelper();
}

// ____ XPropertySet ____
Reference< beans::XPropertySetInfo > SAL_CALL
    GridProperties::getPropertySetInfo()
    throw (uno::RuntimeException)
{
    static Reference< beans::XPropertySetInfo > xInfo;

    // /--
    ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() );
    if( !xInfo.is())
    {
        xInfo = ::cppu::OPropertySetHelper::createPropertySetInfo(
            lcl_getInfoHelper());
    }

    return xInfo;
    // \--
}

// ____ XCloneable ____
uno::Reference< util::XCloneable > SAL_CALL GridProperties::createClone()
    throw (uno::RuntimeException)
{
    return uno::Reference< util::XCloneable >( new GridProperties( *this ));
}

// ____ XModifyBroadcaster ____
void SAL_CALL GridProperties::addModifyListener( const Reference< util::XModifyListener >& aListener )
    throw (uno::RuntimeException)
{
    try
    {
        Reference< util::XModifyBroadcaster > xBroadcaster( m_xModifyEventForwarder, uno::UNO_QUERY_THROW );
        xBroadcaster->addModifyListener( aListener );
    }
    catch( const uno::Exception & ex )
    {
        ASSERT_EXCEPTION( ex );
    }
}

void SAL_CALL GridProperties::removeModifyListener( const Reference< util::XModifyListener >& aListener )
    throw (uno::RuntimeException)
{
    try
    {
        Reference< util::XModifyBroadcaster > xBroadcaster( m_xModifyEventForwarder, uno::UNO_QUERY_THROW );
        xBroadcaster->removeModifyListener( aListener );
    }
    catch( const uno::Exception & ex )
    {
        ASSERT_EXCEPTION( ex );
    }
}

// ____ XModifyListener ____
void SAL_CALL GridProperties::modified( const lang::EventObject& aEvent )
    throw (uno::RuntimeException)
{
    m_xModifyEventForwarder->modified( aEvent );
}

// ____ XEventListener (base of XModifyListener) ____
void SAL_CALL GridProperties::disposing( const lang::EventObject& /* Source */ )
    throw (uno::RuntimeException)
{
    // nothing
}

// ____ OPropertySet ____
void GridProperties::firePropertyChangeEvent()
{
    fireModifyEvent();
}

void GridProperties::fireModifyEvent()
{
    m_xModifyEventForwarder->modified( lang::EventObject( static_cast< uno::XWeak* >( this )));
}

// ================================================================================

Sequence< OUString > GridProperties::getSupportedServiceNames_Static()
{
    Sequence< OUString > aServices( 2 );
    aServices[ 0 ] = C2U( "com.sun.star.chart2.GridProperties" );
    aServices[ 1 ] = C2U( "com.sun.star.beans.PropertySet" );
    return aServices;
}

// implement XServiceInfo methods basing upon getSupportedServiceNames_Static
APPHELPER_XSERVICEINFO_IMPL( GridProperties, lcl_aServiceName );

// needed by MSC compiler
using impl::GridProperties_Base;

IMPLEMENT_FORWARD_XINTERFACE2( GridProperties, GridProperties_Base, ::property::OPropertySet )
IMPLEMENT_FORWARD_XTYPEPROVIDER2( GridProperties, GridProperties_Base, ::property::OPropertySet )

} //  namespace chart
<|endoftext|>


<commit_before>/**
 * @file tc.hxx
 * @author Muhammad A. Awad (mawad@ucdavis.edu)
 * @brief Triangle Counting algorithm.
 * @version 0.1
 * @date 2022-08-06
 *
 * @copyright Copyright (c) 2022
 *
 */
#pragma once

#include <gunrock/algorithms/algorithms.hxx>
#include <gunrock/util/timer.hxx>

namespace gunrock {
namespace tc {

template <typename vertex_t>
struct param_t {
  bool reduce_all_triangles;
  param_t(bool _reduce_all_triangles)
      : reduce_all_triangles(_reduce_all_triangles) {}
};

template <typename vertex_t>
struct result_t {
  vertex_t* vertex_triangles_count;
  std::size_t* total_triangles_count;
  result_t(vertex_t* _vertex_triangles_count, uint64_t* _total_triangles_count)
      : vertex_triangles_count(_vertex_triangles_count),
        total_triangles_count(_total_triangles_count) {}
};

template <typename graph_t, typename param_type, typename result_type>
struct problem_t : gunrock::problem_t<graph_t> {
  param_type param;
  result_type result;

  problem_t(graph_t& G,
            param_type& _param,
            result_type& _result,
            std::shared_ptr<gcuda::multi_context_t> _context)
      : gunrock::problem_t<graph_t>(G, _context),
        param(_param),
        result(_result) {}

  using vertex_t = typename graph_t::vertex_type;
  using edge_t = typename graph_t::edge_type;

  void init() override {}

  void reset() override {}
};

template <typename problem_t>
struct enactor_t : gunrock::enactor_t<problem_t> {
  enactor_t(problem_t* _problem,
            std::shared_ptr<gcuda::multi_context_t> _context,
            enactor_properties_t _properties)
      : gunrock::enactor_t<problem_t>(_problem, _context, _properties) {}

  using vertex_t = typename problem_t::vertex_t;
  using edge_t = typename problem_t::edge_t;
  using weight_t = typename problem_t::weight_t;
  using frontier_t = typename enactor_t<problem_t>::frontier_t;

  void loop(gcuda::multi_context_t& context) override {
    // Data slice
    auto E = this->get_enactor();
    auto P = this->get_problem();
    auto G = P->get_graph();

    auto vertex_triangles_count = P->result.vertex_triangles_count;

    auto intersect = [G, vertex_triangles_count] __host__ __device__(
                         vertex_t const& source,    // ... source
                         vertex_t const& neighbor,  // neighbor
                         edge_t const& edge,        // edge
                         weight_t const& weight     // weight (tuple).
                         ) -> bool {
      if (neighbor > source) {
        auto src_vertex_triangles_count = G.get_intersection_count(
            source, neighbor,
            [vertex_triangles_count](auto intersection_vertex) {
              math::atomic::add(&(vertex_triangles_count[intersection_vertex]),
                                vertex_t{1});
            });
      }
      return false;
    };

    // Execute advance operator on the provided lambda
    operators::advance::execute<operators::load_balance_t::block_mapped,
                                operators::advance_direction_t::forward,
                                operators::advance_io_type_t::graph,
                                operators::advance_io_type_t::none>(
        G, E, intersect, context);
  }

  virtual bool is_converged(gcuda::multi_context_t& context) {
    if (this->iteration == 1)
      return true;
    return false;
  }

  float post_process() {
    util::timer_t timer;
    timer.begin();
    auto P = this->get_problem();
    auto G = P->get_graph();

    if (P->param.reduce_all_triangles) {
      auto policy = this->context->get_context(0)->execution_policy();
      *P->result.total_triangles_count = thrust::transform_reduce(
          policy, P->result.vertex_triangles_count,
          P->result.vertex_triangles_count + G.get_number_of_vertices(),
          [] __device__(const vertex_t& vertex_triangles) {
            return static_cast<std::size_t>(vertex_triangles);
          },
          std::size_t{0}, thrust::plus<std::size_t>());
    }
    return timer.end();
  }
};  // struct enactor_t

template <typename graph_t>
float run(graph_t& G,
          bool reduce_all_triangles,
          typename graph_t::vertex_type* vertex_triangles_count,  // Output
          std::size_t* total_triangles_count,                     // Output
          std::shared_ptr<gcuda::multi_context_t> context =
              std::shared_ptr<gcuda::multi_context_t>(
                  new gcuda::multi_context_t(0))  // Context
) {
  // <user-defined>
  using vertex_t = typename graph_t::vertex_type;
  using weight_t = typename graph_t::weight_type;

  using param_type = param_t<vertex_t>;
  using result_type = result_t<vertex_t>;

  param_type param(reduce_all_triangles);
  result_type result(vertex_triangles_count, total_triangles_count);
  // </user-defined>

  using problem_type = problem_t<graph_t, param_type, result_type>;
  using enactor_type = enactor_t<problem_type>;

  problem_type problem(G, param, result, context);
  problem.init();
  problem.reset();

  // Disable internal-frontiers:
  enactor_properties_t props;
  props.self_manage_frontiers = true;
  enactor_type enactor(&problem, context, props);
  auto time = enactor.enact();
  time += enactor.post_process();

  // </boiler-plate>
  return time;
}

}  // namespace tc
}  // namespace gunrock<commit_msg>Handle self loops in intersection lambda<commit_after>/**
 * @file tc.hxx
 * @author Muhammad A. Awad (mawad@ucdavis.edu)
 * @brief Triangle Counting algorithm.
 * @version 0.1
 * @date 2022-08-06
 *
 * @copyright Copyright (c) 2022
 *
 */
#pragma once

#include <gunrock/algorithms/algorithms.hxx>
#include <gunrock/util/timer.hxx>

namespace gunrock {
namespace tc {

template <typename vertex_t>
struct param_t {
  bool reduce_all_triangles;
  param_t(bool _reduce_all_triangles)
      : reduce_all_triangles(_reduce_all_triangles) {}
};

template <typename vertex_t>
struct result_t {
  vertex_t* vertex_triangles_count;
  std::size_t* total_triangles_count;
  result_t(vertex_t* _vertex_triangles_count, uint64_t* _total_triangles_count)
      : vertex_triangles_count(_vertex_triangles_count),
        total_triangles_count(_total_triangles_count) {}
};

template <typename graph_t, typename param_type, typename result_type>
struct problem_t : gunrock::problem_t<graph_t> {
  param_type param;
  result_type result;

  problem_t(graph_t& G,
            param_type& _param,
            result_type& _result,
            std::shared_ptr<gcuda::multi_context_t> _context)
      : gunrock::problem_t<graph_t>(G, _context),
        param(_param),
        result(_result) {}

  using vertex_t = typename graph_t::vertex_type;
  using edge_t = typename graph_t::edge_type;

  void init() override {}

  void reset() override {}
};

template <typename problem_t>
struct enactor_t : gunrock::enactor_t<problem_t> {
  enactor_t(problem_t* _problem,
            std::shared_ptr<gcuda::multi_context_t> _context,
            enactor_properties_t _properties)
      : gunrock::enactor_t<problem_t>(_problem, _context, _properties) {}

  using vertex_t = typename problem_t::vertex_t;
  using edge_t = typename problem_t::edge_t;
  using weight_t = typename problem_t::weight_t;
  using frontier_t = typename enactor_t<problem_t>::frontier_t;

  void loop(gcuda::multi_context_t& context) override {
    // Data slice
    auto E = this->get_enactor();
    auto P = this->get_problem();
    auto G = P->get_graph();

    auto vertex_triangles_count = P->result.vertex_triangles_count;

    auto intersect = [G, vertex_triangles_count] __host__ __device__(
                         vertex_t const& source,    // ... source
                         vertex_t const& neighbor,  // neighbor
                         edge_t const& edge,        // edge
                         weight_t const& weight     // weight (tuple).
                         ) -> bool {
      if (neighbor > source) {
        auto src_vertex_triangles_count = G.get_intersection_count(
            source, neighbor,
            [vertex_triangles_count, source,
             neighbor](auto intersection_vertex) {
              if (source != intersection_vertex &&
                  neighbor != intersection_vertex) {
                math::atomic::add(
                    &(vertex_triangles_count[intersection_vertex]),
                    vertex_t{1});
              }
            });
      }
      return false;
    };

    // Execute advance operator on the provided lambda
    operators::advance::execute<operators::load_balance_t::block_mapped,
                                operators::advance_direction_t::forward,
                                operators::advance_io_type_t::graph,
                                operators::advance_io_type_t::none>(
        G, E, intersect, context);
  }

  virtual bool is_converged(gcuda::multi_context_t& context) {
    if (this->iteration == 1)
      return true;
    return false;
  }

  float post_process() {
    util::timer_t timer;
    timer.begin();
    auto P = this->get_problem();
    auto G = P->get_graph();

    if (P->param.reduce_all_triangles) {
      auto policy = this->context->get_context(0)->execution_policy();
      *P->result.total_triangles_count = thrust::transform_reduce(
          policy, P->result.vertex_triangles_count,
          P->result.vertex_triangles_count + G.get_number_of_vertices(),
          [] __device__(const vertex_t& vertex_triangles) {
            return static_cast<std::size_t>(vertex_triangles);
          },
          std::size_t{0}, thrust::plus<std::size_t>());
    }
    return timer.end();
  }
};  // struct enactor_t

template <typename graph_t>
float run(graph_t& G,
          bool reduce_all_triangles,
          typename graph_t::vertex_type* vertex_triangles_count,  // Output
          std::size_t* total_triangles_count,                     // Output
          std::shared_ptr<gcuda::multi_context_t> context =
              std::shared_ptr<gcuda::multi_context_t>(
                  new gcuda::multi_context_t(0))  // Context
) {
  // <user-defined>
  using vertex_t = typename graph_t::vertex_type;
  using weight_t = typename graph_t::weight_type;

  using param_type = param_t<vertex_t>;
  using result_type = result_t<vertex_t>;

  param_type param(reduce_all_triangles);
  result_type result(vertex_triangles_count, total_triangles_count);
  // </user-defined>

  using problem_type = problem_t<graph_t, param_type, result_type>;
  using enactor_type = enactor_t<problem_type>;

  problem_type problem(G, param, result, context);
  problem.init();
  problem.reset();

  // Disable internal-frontiers:
  enactor_properties_t props;
  props.self_manage_frontiers = true;
  enactor_type enactor(&problem, context, props);
  auto time = enactor.enact();
  time += enactor.post_process();

  // </boiler-plate>
  return time;
}

}  // namespace tc
}  // namespace gunrock<|endoftext|>


<commit_before>/*
   +----------------------------------------------------------------------+
   | HipHop for PHP                                                       |
   +----------------------------------------------------------------------+
   | Copyright (c) 2015 Alexandre Kalendarev                              |
   +----------------------------------------------------------------------+
   | This source file is subject to version 3.01 of the PHP license,      |
   | that is bundled with this package in the file LICENSE, and is        |
   | available through the world-wide-web at the following url:           |
   | http://www.php.net/license/3_01.txt                                  |
   | If you did not receive a copy of the PHP license and are unable to   |
   | obtain it through the world-wide-web, please send a note to          |
   | license@php.net so we can mail you a copy immediately.               |
   +----------------------------------------------------------------------+

	 part this code was derived from tarantool/msgpuck, author Roman Tsisyk

	 for HHVM version 3.13
*/

/*
  KindOfUninit          = 0x00,  //  00000000    0
  KindOfNull            = 0x01,  //  00000001    1
  KindOfBoolean         = 0x09,  //  00001001    9
  KindOfInt64           = 0x11,  //  00010001   17
  KindOfDouble          = 0x19,  //  00011001   25
  KindOfPersistentString = 0x1b, //  00011011   27
  KindOfPersistentArray = 0x1d,  //  00011101   29
  KindOfString          = 0x22,  //  00100010   34
  KindOfArray           = 0x34,  //  00110100   52
  KindOfObject          = 0x40,  //  01000000   64
  KindOfResource        = 0x50,  //  01010000
  KindOfRef             = 0x60,  //  01100000
*/

#include "hphp/runtime/ext/extension.h"
#include "hphp/runtime/base/execution-context.h"  // g_context

#define MP_SOURCE 1
#include "msgpuck.h"
#include "msgpack.h"

namespace HPHP {

static void printVariant(const Variant& data);
static void packVariant(const Variant& el);

static int sizeof_pack( const Array& data ) {

	int size = 0;

	for (int i=0; i < data.length(); i++) {
		Variant el(data[i]);
		switch(el.getType()) {

			case KindOfInt64 : {
				size += mp_sizeof_int( el.toInt64() );
				break;
			}

			case KindOfNull : {
				size += mp_sizeof_nil();
				break;
			}

			case KindOfPersistentString:
			case KindOfString : {
				size += mp_sizeof_str( el.toString().length());
				break;
			}

			case KindOfPersistentArray:
			case KindOfArray : {
				size += mp_sizeof_array( el.toArray().size() );
				int arr_size = sizeof_pack( el.toArray() );
				size += arr_size;
				break;
			}

			case KindOfDouble :
				size += mp_sizeof_float(el.toDouble());
				break;

			case KindOfBoolean :
				size += mp_sizeof_bool(el.toBoolean());
				break;

			default : g_context->write( "wrong\n");
		}
	}

	return size;
}

static void arrayIteration(ArrayData* data, void  (arrayIterationCb) (const Variant& , const Variant&)) {

	for (ssize_t pos = data->iter_begin(); pos != data->iter_end();
	       pos = data->iter_advance(pos)) {
	       const Variant key = data->getKey(pos);
	   	   const Variant val = data->getValue(pos);
	   	   arrayIterationCb(key, val);
	}
}

static void encodeArrayElement(const Variant& key, const Variant& val) {
	packVariant(key);
	packVariant(val);
}

static void packVariant(const Variant& el) {

	switch(el.getType()) {
		case KindOfInt64 : {
			int64_t int_val = el.toInt64();
			if (int_val >= 0)
				MsgpackExtension::BufferPtr = mp_encode_uint(MsgpackExtension::BufferPtr,  int_val );
			else
				MsgpackExtension::BufferPtr = mp_encode_int(MsgpackExtension::BufferPtr,  int_val );
			break; }

		case KindOfNull : {
			MsgpackExtension::BufferPtr = mp_encode_nil(MsgpackExtension::BufferPtr);
			break; }

		case KindOfBoolean : {
			MsgpackExtension::BufferPtr = mp_encode_bool(MsgpackExtension::BufferPtr, el.toBoolean());
			break;
		}

		case KindOfPersistentString:
		case KindOfString : {
			MsgpackExtension::BufferPtr = mp_encode_str(MsgpackExtension::BufferPtr, el.toString().c_str(), el.toString().length());
			break;
		}

		case KindOfPersistentArray:
		case KindOfArray : {

				MsgpackExtension::BufferPtr = mp_encode_map(MsgpackExtension::BufferPtr, el.toArray().length());
				ArrayData* ad = el.toArray().get();
				arrayIteration(ad, encodeArrayElement);
				break;
			}

		case KindOfDouble : {
			MsgpackExtension::BufferPtr = mp_encode_double(MsgpackExtension::BufferPtr, el.toDouble());
			break;
	 	}

		default : raise_warning("error type of data element");
	}
};

void unpackElement( char **p, Variant* pout) {

	const char c = (**p);
	char * pos = *p;
	mp_type type = mp_typeof(c);

	switch(type) {

		case MP_NIL : {
			pout->setNull();
			(*p)++;
			break;
		}

		case MP_UINT : {
			int64_t intval = mp_decode_uint(const_cast<const char**>(&pos));

			*pout = intval;
			*p = pos;
			break;
		}

		case MP_INT : {
			int64_t intval = mp_decode_int(const_cast<const char**>(&pos));

			*pout = intval;
			*p = pos;
			break;
		}

		case MP_STR : {
			uint32_t len = 0;
			const char * res = mp_decode_str(const_cast<const char**>(&pos), &len);
			*p = pos;
			*pout = String(StringData::Make( res, len, CopyString ));
			break;
		}

		case MP_BOOL : {
			const bool res = mp_decode_bool(const_cast<const char**>(&pos));
			*p = pos;
			*pout =  res ? true : false;
			break;

		}

		case MP_DOUBLE : {
			double dbl_val = mp_decode_double(const_cast<const char**>(&pos));
			*pout = dbl_val;
			*p = pos;
			break;
		}

		case MP_ARRAY : {
			int count = mp_decode_array(const_cast<const char**>(&pos));
			Array ret = Array::Create();
			for(int i = 0; i < count; ++i) {
				Variant val;
				unpackElement( &pos, &val);
				ret.add(i,val);
			}

			*pout = ret;
			*p = pos;
			break;
		}

		case MP_MAP : {
			int count = mp_decode_map(const_cast<const char**>(&pos));

			Array ret = Array::Create();
			for(int i = 0; i < count; ++i) {
				Variant key, val;
				unpackElement( &pos, &key);
				unpackElement( &pos, &val);

				ret.add(key,val,true);
			}

			*pout = ret;
			*p = pos;
			break;
		}

		default :
			raise_warning("unpack error data element");
			pout->setNull();
			mp_next(const_cast<const char**>(p));
	}

}

//////////////////////////////////////////////////////////////////////////////////////////////

void MsgpackExtension::moduleInit() {

	HHVM_FE(msgpack_pack);
	HHVM_FE(msgpack_unpack);

	loadSystemlib();

	MsgpackExtension::BufferSize = BUFFSIZE;
	MsgpackExtension::Buffer = malloc(BUFFSIZE);

}

void MsgpackExtension::moduleShutdown() {

	free(MsgpackExtension::Buffer);
	// printf("moduleShutdown size=%d\n", MsgpackExtension::BufferSize);
}

//////////////////    static    /////////////////////////
int MsgpackExtension::BufferSize = 0;
int MsgpackExtension::Level = 0;
void* MsgpackExtension::Buffer = NULL;
char* MsgpackExtension::BufferPtr = NULL;

static MsgpackExtension s_msgpack_extension;

//////////////////    HHVM_FUNCTION     //////////////////

static String HHVM_FUNCTION(msgpack_pack, const Array& data) {

	MsgpackExtension::Level = 0;
	MsgpackExtension::BufferPtr = static_cast<char*>(MsgpackExtension::Buffer);
	MsgpackExtension::BufferPtr = mp_encode_array( MsgpackExtension::BufferPtr, data.length());

	for (int i = 0; i < data.length(); ++i)	{
		packVariant(data[i]);
	}
	size_t len = reinterpret_cast<uint64_t>(MsgpackExtension::BufferPtr) - reinterpret_cast<uint64_t>(MsgpackExtension::Buffer);

	StringData* str =  StringData::Make(reinterpret_cast<const char*>(MsgpackExtension::Buffer), len, CopyString);

	return  String(str);
}

static Array HHVM_FUNCTION(msgpack_unpack, const String& data) {
	Array ret = Array::Create();

	char * p = const_cast<char *>(data.c_str());
	char c = *p;

	if ( mp_typeof(c) != MP_ARRAY ) {
 		raise_warning("the root element must be array");
		return ret;
	}
	int count = mp_decode_array( const_cast<const char**>(&p));

	printf("elements %d\n", count);

	for (int i =0; i < count; i++) {
		Variant el;
		unpackElement(&p, &el);
		ret.set(i, el);
	}

	return  ret;
}

HHVM_GET_MODULE(msgpack);

} // namespace HPHP<commit_msg>remove comments<commit_after>/*
   +----------------------------------------------------------------------+
   | HipHop for PHP                                                       |
   +----------------------------------------------------------------------+
   | Copyright (c) 2015 Alexandre Kalendarev                              |
   +----------------------------------------------------------------------+
   | This source file is subject to version 3.01 of the PHP license,      |
   | that is bundled with this package in the file LICENSE, and is        |
   | available through the world-wide-web at the following url:           |
   | http://www.php.net/license/3_01.txt                                  |
   | If you did not receive a copy of the PHP license and are unable to   |
   | obtain it through the world-wide-web, please send a note to          |
   | license@php.net so we can mail you a copy immediately.               |
   +----------------------------------------------------------------------+

	 part this code was derived from tarantool/msgpuck, author Roman Tsisyk

	 for HHVM version 3.13
*/

#include "hphp/runtime/ext/extension.h"
#include "hphp/runtime/base/execution-context.h"  // g_context

#define MP_SOURCE 1
#include "msgpuck.h"
#include "msgpack.h"

namespace HPHP {

static void printVariant(const Variant& data);
static void packVariant(const Variant& el);

static int sizeof_pack( const Array& data ) {

	int size = 0;

	for (int i=0; i < data.length(); i++) {
		Variant el(data[i]);
		switch(el.getType()) {

			case KindOfInt64 : {
				size += mp_sizeof_int( el.toInt64() );
				break;
			}

			case KindOfNull : {
				size += mp_sizeof_nil();
				break;
			}

			case KindOfPersistentString:
			case KindOfString : {
				size += mp_sizeof_str( el.toString().length());
				break;
			}

			case KindOfPersistentArray:
			case KindOfArray : {
				size += mp_sizeof_array( el.toArray().size() );
				int arr_size = sizeof_pack( el.toArray() );
				size += arr_size;
				break;
			}

			case KindOfDouble :
				size += mp_sizeof_float(el.toDouble());
				break;

			case KindOfBoolean :
				size += mp_sizeof_bool(el.toBoolean());
				break;

			default : g_context->write( "wrong\n");
		}
	}

	return size;
}

static void arrayIteration(ArrayData* data, void  (arrayIterationCb) (const Variant& , const Variant&)) {

	for (ssize_t pos = data->iter_begin(); pos != data->iter_end();
	       pos = data->iter_advance(pos)) {
	       const Variant key = data->getKey(pos);
	   	   const Variant val = data->getValue(pos);
	   	   arrayIterationCb(key, val);
	}
}

static void encodeArrayElement(const Variant& key, const Variant& val) {
	packVariant(key);
	packVariant(val);
}

static void packVariant(const Variant& el) {

	switch(el.getType()) {
		case KindOfInt64 : {
			int64_t int_val = el.toInt64();
			if (int_val >= 0)
				MsgpackExtension::BufferPtr = mp_encode_uint(MsgpackExtension::BufferPtr,  int_val );
			else
				MsgpackExtension::BufferPtr = mp_encode_int(MsgpackExtension::BufferPtr,  int_val );
			break; }

		case KindOfNull : {
			MsgpackExtension::BufferPtr = mp_encode_nil(MsgpackExtension::BufferPtr);
			break; }

		case KindOfBoolean : {
			MsgpackExtension::BufferPtr = mp_encode_bool(MsgpackExtension::BufferPtr, el.toBoolean());
			break;
		}

		case KindOfPersistentString:
		case KindOfString : {
			MsgpackExtension::BufferPtr = mp_encode_str(MsgpackExtension::BufferPtr, el.toString().c_str(), el.toString().length());
			break;
		}

		case KindOfPersistentArray:
		case KindOfArray : {

				MsgpackExtension::BufferPtr = mp_encode_map(MsgpackExtension::BufferPtr, el.toArray().length());
				ArrayData* ad = el.toArray().get();
				arrayIteration(ad, encodeArrayElement);
				break;
			}

		case KindOfDouble : {
			MsgpackExtension::BufferPtr = mp_encode_double(MsgpackExtension::BufferPtr, el.toDouble());
			break;
	 	}

		default : raise_warning("error type of data element");
	}
};

void unpackElement( char **p, Variant* pout) {

	const char c = (**p);
	char * pos = *p;
	mp_type type = mp_typeof(c);

	switch(type) {

		case MP_NIL : {
			pout->setNull();
			(*p)++;
			break;
		}

		case MP_UINT : {
			int64_t intval = mp_decode_uint(const_cast<const char**>(&pos));

			*pout = intval;
			*p = pos;
			break;
		}

		case MP_INT : {
			int64_t intval = mp_decode_int(const_cast<const char**>(&pos));

			*pout = intval;
			*p = pos;
			break;
		}

		case MP_STR : {
			uint32_t len = 0;
			const char * res = mp_decode_str(const_cast<const char**>(&pos), &len);
			*p = pos;
			*pout = String(StringData::Make( res, len, CopyString ));
			break;
		}

		case MP_BOOL : {
			const bool res = mp_decode_bool(const_cast<const char**>(&pos));
			*p = pos;
			*pout =  res ? true : false;
			break;

		}

		case MP_DOUBLE : {
			double dbl_val = mp_decode_double(const_cast<const char**>(&pos));
			*pout = dbl_val;
			*p = pos;
			break;
		}

		case MP_ARRAY : {
			int count = mp_decode_array(const_cast<const char**>(&pos));
			Array ret = Array::Create();
			for(int i = 0; i < count; ++i) {
				Variant val;
				unpackElement( &pos, &val);
				ret.add(i,val);
			}

			*pout = ret;
			*p = pos;
			break;
		}

		case MP_MAP : {
			int count = mp_decode_map(const_cast<const char**>(&pos));

			Array ret = Array::Create();
			for(int i = 0; i < count; ++i) {
				Variant key, val;
				unpackElement( &pos, &key);
				unpackElement( &pos, &val);

				ret.add(key,val,true);
			}

			*pout = ret;
			*p = pos;
			break;
		}

		default :
			raise_warning("unpack error data element");
			pout->setNull();
			mp_next(const_cast<const char**>(p));
	}

}

//////////////////////////////////////////////////////////////////////////////////////////////

void MsgpackExtension::moduleInit() {

	HHVM_FE(msgpack_pack);
	HHVM_FE(msgpack_unpack);

	loadSystemlib();

	MsgpackExtension::BufferSize = BUFFSIZE;
	MsgpackExtension::Buffer = malloc(BUFFSIZE);

}

void MsgpackExtension::moduleShutdown() {

	free(MsgpackExtension::Buffer);
	// printf("moduleShutdown size=%d\n", MsgpackExtension::BufferSize);
}

//////////////////    static    /////////////////////////
int MsgpackExtension::BufferSize = 0;
int MsgpackExtension::Level = 0;
void* MsgpackExtension::Buffer = NULL;
char* MsgpackExtension::BufferPtr = NULL;

static MsgpackExtension s_msgpack_extension;

//////////////////    HHVM_FUNCTION     //////////////////

static String HHVM_FUNCTION(msgpack_pack, const Array& data) {

	MsgpackExtension::Level = 0;
	MsgpackExtension::BufferPtr = static_cast<char*>(MsgpackExtension::Buffer);
	MsgpackExtension::BufferPtr = mp_encode_array( MsgpackExtension::BufferPtr, data.length());

	for (int i = 0; i < data.length(); ++i)	{
		packVariant(data[i]);
	}
	size_t len = reinterpret_cast<uint64_t>(MsgpackExtension::BufferPtr) - reinterpret_cast<uint64_t>(MsgpackExtension::Buffer);

	StringData* str =  StringData::Make(reinterpret_cast<const char*>(MsgpackExtension::Buffer), len, CopyString);

	return  String(str);
}

static Array HHVM_FUNCTION(msgpack_unpack, const String& data) {
	Array ret = Array::Create();

	char * p = const_cast<char *>(data.c_str());
	char c = *p;

	if ( mp_typeof(c) != MP_ARRAY ) {
 		raise_warning("the root element must be array");
		return ret;
	}
	int count = mp_decode_array( const_cast<const char**>(&p));

	printf("elements %d\n", count);

	for (int i =0; i < count; i++) {
		Variant el;
		unpackElement(&p, &el);
		ret.set(i, el);
	}

	return  ret;
}

HHVM_GET_MODULE(msgpack);

} // namespace HPHP<|endoftext|>


<commit_before>// Copyright (c) 2015 Giorgio Marcias
//
// This file is part of distance_transform, a C++11 implementation of the
// algorithm in "Distance Transforms of Sampled Functions"
// Pedro F. Felzenszwalb, Daniel P. Huttenlocher
// Theory of Computing, Vol. 8, No. 19, September 2012
//
// This source code is subject to Apache 2.0 License.
//
// Author: Giorgio Marcias
// email: marcias.giorgio@gmail.com

#ifndef multiple_array_hpp
#define multiple_array_hpp

#include <cstddef>
#include <cstring>
#include <memory>
#include <type_traits>
#include <exception>
#include <sstream>
#include <utility>

template < typename T, std::size_t D >
class MArray {
public:
    MArray() : _array(nullptr), _accumulatedOffset(0)
    {
        for (std::size_t i = 0; i < D; ++i) {
            _size[i] = 0;
            _offset[i] = 0;
        }
    }

    MArray(const T *array, const std::size_t accumulatedOffset, const std::size_t size[D])
        : _array(const_cast<T*>(array))
        , _accumulatedOffset(_array ? accumulatedOffset : 0)
    {
        for (std::size_t i = 0; i < D; ++i)
            _size[i] = _array ? size[i] : 0;
        _offset[D-1] = 1;
        for (std::size_t j = D-1; j > 0; --j)
            _offset[j-1] = _size[j-1] * _offset[j];
    }

    MArray(const T *array, const std::size_t accumulatedOffset, const std::size_t size[D], const std::size_t offset[D])
        : _array(const_cast<T*>(array))
        , _accumulatedOffset(_array ? accumulatedOffset : 0)
    {
        for (std::size_t i = 0; i < D; ++i) {
            _size[i] = _array ? size[i] : 0;
            _offset[i] = _array ? offset[i] : 0;
        }
    }

    MArray(const MArray &ma)
        : _array(ma._array)
        , _accumulatedOffset(ma._accumulatedOffset)
    {
        for (std::size_t i = 0; i < D; ++i)
            _size[i] = ma._size[i];
        _offset[D-1] = 1;
        for (std::size_t j = D-1; j > 0; --j)
            _offset[j-1] = _size[j-1] * _offset[j];
    }

    MArray(MArray &&ma)
        : _array(ma._array)
        , _accumulatedOffset(ma._accumulatedOffset)
    {
        ma._array = nullptr;
        for (std::size_t i = 0; i < D; ++i) {
            _size[i] = ma._size[i];
            ma._size[i] = 0;
            _offset[i] = ma._offset[i];
            ma._offset[i] = 0;
        }
    }

    inline MArray & operator=(const MArray &ma)
    {
        if (&ma != this) {
            _array = ma._array;
            _accumulatedOffset = ma._accumulatedOffset;
            for (std::size_t i = 0; i < D; ++i) {
                _size[i] = ma._size[i];
                _offset[i] = ma._offset[i];
            }
        }
        return *this;
    }

    inline MArray & operator=(MArray &&ma)
    {
        if (&ma != this) {
            _array = ma._array;
            ma._array = nullptr;
            _accumulatedOffset = ma._accumulatedOffset;
            ma._accumulatedOffset = 0;
            for (std::size_t i = 0; i < D; ++i) {
                _size[i] = ma._size[i];
                ma._size[i] = 0;
                _offset[i] = ma._offset[i];
                ma._offset[i] = 0;
            }
        }
        return *this;
    }

    inline MArray<T, D-1> operator[](const std::size_t i) const
    {
        if (i >= _size[0]) {
            std::stringstream stream;
            stream << "Index " << i << " is out of range [0, " << _size[0]-1 << ']';
            throw std::out_of_range(stream.str());
        }
        return MArray<T, D-1>(_array + _offset[0] * i, accumulatedOffset(i), _size + 1, _offset + 1);
    }

    inline MArray<T, D-1> slice(const std::size_t d, const std::size_t i) const
    {
        if (d >= D) {
            std::stringstream stream;
            stream << "Index " << d << " is out of range [0, " << D-1 << ']';
            throw std::out_of_range(stream.str());
        }
        if (i >= _size[d]) {
            std::stringstream stream;
            stream << "Index " << i << " is out of range [0, " << _size[d]-1 << ']';
            throw std::out_of_range(stream.str());
        }
        std::size_t size[D-1];
        std::size_t offset[D-1];
        std::size_t k = 0;
        for (std::size_t j = 0; j < d; ++j, ++k) {
            size[k] = _size[j];
            offset[k] = _offset[j];
        }
        for (std::size_t j = d+1; j < D; ++j, ++k) {
            size[k] = _size[j];
            offset[k] = _offset[j];
        }
        return MArray<T, D-1>(_array + _offset[d] * i, accumulatedOffset(i, d), size, offset);
    }

    inline std::size_t size(const std::size_t d = 0) const
    {
        return _size[d];
    }

    inline void size(std::size_t s[D]) const
    {
        for (std::size_t i = 0; i < D; ++i)
            s[i] = _size[i];
    }

    inline std::size_t totalSize() const
    {
        std::size_t total = _size[0];
        for (std::size_t i = 1; i < D; ++i)
            total *= _size[i];
        return total;
    }

    inline std::size_t accumulatedOffset(const std::size_t i, const std::size_t d = 0) const
    {
        if (d >= D) {
            std::stringstream stream;
            stream << "Index " << d << " is out of range [0, " << D-1 << ']';
            throw std::out_of_range(stream.str());
        }
        if (i >= _size[0]) {
            std::stringstream stream;
            stream << "Index " << i << " is out of range [0, " << _size[d]-1 << ']';
            throw std::out_of_range(stream.str());
        }
        return  _accumulatedOffset + _offset[d] * i;
    }

private:
    T                  *_array;
    std::size_t         _accumulatedOffset;

protected:
    std::size_t         _size[D];

private:
    std::size_t         _offset[D];
};

template < typename T >
class MArray<T, 1> {
public:
    MArray()
        : _array(nullptr)
        , _accumulatedOffset(0)
        , _size(0)
        , _offset(0)
    { }

    MArray(const T *array, const std::size_t accumulatedOffset, const std::size_t size)
        : _array(array)
        , _accumulatedOffset(_array ? accumulatedOffset : 0)
        , _size(_array ? size : 0)
        , _offset(0)
    { }

    MArray(const T *array, const std::size_t accumulatedOffset, const std::size_t size, const std::size_t offset)
        : _array(array)
        , _accumulatedOffset(_array ? accumulatedOffset : 0)
        , _size(_array ? size : 0)
        , _offset(_array ? offset : 0)
    { }

    MArray(const T *array, const std::size_t accumulatedOffset, const std::size_t size[1])
        : _array(const_cast<T*>(array))
        , _accumulatedOffset(_array ? accumulatedOffset : 0)
        , _size(_array ? size[0] : 0)
        , _offset(0)
    { }

    MArray(const T *array, const std::size_t accumulatedOffset, const std::size_t size[1], const std::size_t offset[1])
        : _array(const_cast<T*>(array))
        , _accumulatedOffset(_array ? accumulatedOffset : 0)
        , _size(_array ? size[0] : 0)
        , _offset(_array ? offset[0] : 0)
    { }

    MArray(const MArray &ma)
        : _array(ma._array)
        , _accumulatedOffset(ma._accumulatedOffset)
        , _size(ma._size)
        , _offset(ma._offset)
    { }

    MArray(MArray &&ma)
        : _array(ma._array)
        , _accumulatedOffset(ma._accumulatedOffset)
        , _size(ma._size)
        , _offset(ma._offset)
    {
        ma._array = nullptr;
        ma._accumulatedOffset = 0;
        ma._size = 0;
        ma._offset = 0;
    }

    MArray & operator=(const MArray &ma)
    {
        if (&ma != this) {
            _array = ma._array;
            _size = ma._size;
            _offset = ma._offset;
        }
        return *this;
    }

    MArray & operator=(MArray &&ma)
    {
        if (&ma != this) {
            _array = ma._array;
            _size = ma._size;
            _offset = ma._offset;
            ma._array = nullptr;
            ma._size = 0;
            ma._offset = 0;
        }
        return *this;
    }

    inline const T & operator[](const std::size_t i) const
    {
        if (i >= _size) {
            std::stringstream stream;
            stream << "Index " << i << " is out of range [0, " << _size-1 << ']';
            throw std::out_of_range(stream.str());
        }
        return *(_array + i * _offset);
    }

    inline T & operator[](const std::size_t i)
    {
        if (i >= _size) {
            std::stringstream stream;
            stream << "Index " << i << " is out of range [0, " << _size-1 << ']';
            throw std::out_of_range(stream.str());
        }
        return *(_array + i * _offset);
    }

    inline const T & slice(const std::size_t i) const
    {
        return *this[i];
    }

    inline T & slice(const std::size_t i)
    {
        return *this[i];
    }

    inline std::size_t size() const
    {
        return _size;
    }

    inline std::size_t accumulatedOffset(const std::size_t i = 0) const
    {
        if (i >= _size) {
            std::stringstream stream;
            stream << "Index " << i << " is out of range [0, " << _size-1 << ']';
            throw std::out_of_range(stream.str());
        }
        return _accumulatedOffset + _offset * i;
    }

private:
    T                  *_array;
    std::size_t         _accumulatedOffset;

protected:
    std::size_t         _size;

private:
    std::size_t         _offset;
};

template < typename T, std::size_t D >
class MMArray : public MArray<T, D> {
public:
    MMArray()
        : MArray<T, D>()
        , _array(nullptr)
    { }

    MMArray(const std::size_t size[D])
    {
        std::size_t total = size[0];
        for (std::size_t i = 1; i < D; ++i)
            total *= size[i];
        _array.reset(new T[total]);
        MArray<T, D>::operator=(MArray<T, D>(_array.get(), 0, size));
    }

    MMArray(const MMArray<T, D> &mma)
    {
        *this = mma;
    }

    MMArray(MMArray &&mma)
        : MArray<T, D>(std::forward<MMArray<T, D>>(mma))
        , _array(std::move(mma._array))
    { }

    MMArray & operator=(const MMArray &mma)
    {
        if (&mma != this) {
            _array.reset(new T[mma.totalSize()]);
            std::memcpy(_array.get(), mma._array.get(), mma.totalSize() * sizeof(T));
            std::size_t size[D];
            mma.size(size);
            MArray<T, D>::operator=(MArray<T, D>(_array.get(), 0, size));
        }
        return *this;
    }

    MMArray & operator=(MMArray &&mma)
    {
        if (&mma != this) {
            MArray<T, D>::operator=(std::forward<MMArray<T, D>>(mma));
            _array = std::move(mma._array);
        }
        return *this;
    }

private:
    std::unique_ptr<T[]>    _array;
};

#endif /* multiple_array_hpp */
<commit_msg>Added array resizing<commit_after>// Copyright (c) 2015 Giorgio Marcias
//
// This file is part of distance_transform, a C++11 implementation of the
// algorithm in "Distance Transforms of Sampled Functions"
// Pedro F. Felzenszwalb, Daniel P. Huttenlocher
// Theory of Computing, Vol. 8, No. 19, September 2012
//
// This source code is subject to Apache 2.0 License.
//
// Author: Giorgio Marcias
// email: marcias.giorgio@gmail.com

#ifndef multiple_array_hpp
#define multiple_array_hpp

#include <cstddef>
#include <cstring>
#include <memory>
#include <type_traits>
#include <exception>
#include <sstream>
#include <utility>

template < typename T, std::size_t D >
class MArray {
public:
    MArray() : _array(nullptr), _accumulatedOffset(0)
    {
        for (std::size_t i = 0; i < D; ++i) {
            _size[i] = 0;
            _offset[i] = 0;
        }
    }

    MArray(const T *array, const std::size_t accumulatedOffset, const std::size_t size[D])
        : _array(const_cast<T*>(array))
        , _accumulatedOffset(_array ? accumulatedOffset : 0)
    {
        for (std::size_t i = 0; i < D; ++i)
            _size[i] = _array ? size[i] : 0;
        _offset[D-1] = 1;
        for (std::size_t j = D-1; j > 0; --j)
            _offset[j-1] = _size[j-1] * _offset[j];
    }

    MArray(const T *array, const std::size_t accumulatedOffset, const std::size_t size[D], const std::size_t offset[D])
        : _array(const_cast<T*>(array))
        , _accumulatedOffset(_array ? accumulatedOffset : 0)
    {
        for (std::size_t i = 0; i < D; ++i) {
            _size[i] = _array ? size[i] : 0;
            _offset[i] = _array ? offset[i] : 0;
        }
    }

    MArray(const MArray &ma)
        : _array(ma._array)
        , _accumulatedOffset(ma._accumulatedOffset)
    {
        for (std::size_t i = 0; i < D; ++i)
            _size[i] = ma._size[i];
        _offset[D-1] = 1;
        for (std::size_t j = D-1; j > 0; --j)
            _offset[j-1] = _size[j-1] * _offset[j];
    }

    MArray(MArray &&ma)
        : _array(ma._array)
        , _accumulatedOffset(ma._accumulatedOffset)
    {
        ma._array = nullptr;
        for (std::size_t i = 0; i < D; ++i) {
            _size[i] = ma._size[i];
            ma._size[i] = 0;
            _offset[i] = ma._offset[i];
            ma._offset[i] = 0;
        }
    }

    inline MArray & operator=(const MArray &ma)
    {
        if (&ma != this) {
            _array = ma._array;
            _accumulatedOffset = ma._accumulatedOffset;
            for (std::size_t i = 0; i < D; ++i) {
                _size[i] = ma._size[i];
                _offset[i] = ma._offset[i];
            }
        }
        return *this;
    }

    inline MArray & operator=(MArray &&ma)
    {
        if (&ma != this) {
            _array = ma._array;
            ma._array = nullptr;
            _accumulatedOffset = ma._accumulatedOffset;
            ma._accumulatedOffset = 0;
            for (std::size_t i = 0; i < D; ++i) {
                _size[i] = ma._size[i];
                ma._size[i] = 0;
                _offset[i] = ma._offset[i];
                ma._offset[i] = 0;
            }
        }
        return *this;
    }

    inline MArray<T, D-1> operator[](const std::size_t i) const
    {
        if (i >= _size[0]) {
            std::stringstream stream;
            stream << "Index " << i << " is out of range [0, " << _size[0]-1 << ']';
            throw std::out_of_range(stream.str());
        }
        return MArray<T, D-1>(_array + _offset[0] * i, accumulatedOffset(i), _size + 1, _offset + 1);
    }

    inline MArray<T, D-1> slice(const std::size_t d, const std::size_t i) const
    {
        if (d >= D) {
            std::stringstream stream;
            stream << "Index " << d << " is out of range [0, " << D-1 << ']';
            throw std::out_of_range(stream.str());
        }
        if (i >= _size[d]) {
            std::stringstream stream;
            stream << "Index " << i << " is out of range [0, " << _size[d]-1 << ']';
            throw std::out_of_range(stream.str());
        }
        std::size_t size[D-1];
        std::size_t offset[D-1];
        std::size_t k = 0;
        for (std::size_t j = 0; j < d; ++j, ++k) {
            size[k] = _size[j];
            offset[k] = _offset[j];
        }
        for (std::size_t j = d+1; j < D; ++j, ++k) {
            size[k] = _size[j];
            offset[k] = _offset[j];
        }
        return MArray<T, D-1>(_array + _offset[d] * i, accumulatedOffset(i, d), size, offset);
    }

    inline std::size_t size(const std::size_t d = 0) const
    {
        return _size[d];
    }

    inline void size(std::size_t s[D]) const
    {
        for (std::size_t i = 0; i < D; ++i)
            s[i] = _size[i];
    }

    inline std::size_t totalSize() const
    {
        std::size_t total = _size[0];
        for (std::size_t i = 1; i < D; ++i)
            total *= _size[i];
        return total;
    }

    inline std::size_t accumulatedOffset(const std::size_t i, const std::size_t d = 0) const
    {
        if (d >= D) {
            std::stringstream stream;
            stream << "Index " << d << " is out of range [0, " << D-1 << ']';
            throw std::out_of_range(stream.str());
        }
        if (i >= _size[0]) {
            std::stringstream stream;
            stream << "Index " << i << " is out of range [0, " << _size[d]-1 << ']';
            throw std::out_of_range(stream.str());
        }
        return  _accumulatedOffset + _offset[d] * i;
    }

private:
    T                  *_array;
    std::size_t         _accumulatedOffset;

protected:
    std::size_t         _size[D];

private:
    std::size_t         _offset[D];
};

template < typename T >
class MArray<T, 1> {
public:
    MArray()
        : _array(nullptr)
        , _accumulatedOffset(0)
        , _size(0)
        , _offset(0)
    { }

    MArray(const T *array, const std::size_t accumulatedOffset, const std::size_t size)
        : _array(array)
        , _accumulatedOffset(_array ? accumulatedOffset : 0)
        , _size(_array ? size : 0)
        , _offset(0)
    { }

    MArray(const T *array, const std::size_t accumulatedOffset, const std::size_t size, const std::size_t offset)
        : _array(array)
        , _accumulatedOffset(_array ? accumulatedOffset : 0)
        , _size(_array ? size : 0)
        , _offset(_array ? offset : 0)
    { }

    MArray(const T *array, const std::size_t accumulatedOffset, const std::size_t size[1])
        : _array(const_cast<T*>(array))
        , _accumulatedOffset(_array ? accumulatedOffset : 0)
        , _size(_array ? size[0] : 0)
        , _offset(0)
    { }

    MArray(const T *array, const std::size_t accumulatedOffset, const std::size_t size[1], const std::size_t offset[1])
        : _array(const_cast<T*>(array))
        , _accumulatedOffset(_array ? accumulatedOffset : 0)
        , _size(_array ? size[0] : 0)
        , _offset(_array ? offset[0] : 0)
    { }

    MArray(const MArray &ma)
        : _array(ma._array)
        , _accumulatedOffset(ma._accumulatedOffset)
        , _size(ma._size)
        , _offset(ma._offset)
    { }

    MArray(MArray &&ma)
        : _array(ma._array)
        , _accumulatedOffset(ma._accumulatedOffset)
        , _size(ma._size)
        , _offset(ma._offset)
    {
        ma._array = nullptr;
        ma._accumulatedOffset = 0;
        ma._size = 0;
        ma._offset = 0;
    }

    MArray & operator=(const MArray &ma)
    {
        if (&ma != this) {
            _array = ma._array;
            _size = ma._size;
            _offset = ma._offset;
        }
        return *this;
    }

    MArray & operator=(MArray &&ma)
    {
        if (&ma != this) {
            _array = ma._array;
            _size = ma._size;
            _offset = ma._offset;
            ma._array = nullptr;
            ma._size = 0;
            ma._offset = 0;
        }
        return *this;
    }

    inline const T & operator[](const std::size_t i) const
    {
        if (i >= _size) {
            std::stringstream stream;
            stream << "Index " << i << " is out of range [0, " << _size-1 << ']';
            throw std::out_of_range(stream.str());
        }
        return *(_array + i * _offset);
    }

    inline T & operator[](const std::size_t i)
    {
        if (i >= _size) {
            std::stringstream stream;
            stream << "Index " << i << " is out of range [0, " << _size-1 << ']';
            throw std::out_of_range(stream.str());
        }
        return *(_array + i * _offset);
    }

    inline const T & slice(const std::size_t i) const
    {
        return *this[i];
    }

    inline T & slice(const std::size_t i)
    {
        return *this[i];
    }

    inline std::size_t size() const
    {
        return _size;
    }

    inline std::size_t accumulatedOffset(const std::size_t i = 0) const
    {
        if (i >= _size) {
            std::stringstream stream;
            stream << "Index " << i << " is out of range [0, " << _size-1 << ']';
            throw std::out_of_range(stream.str());
        }
        return _accumulatedOffset + _offset * i;
    }

private:
    T                  *_array;
    std::size_t         _accumulatedOffset;

protected:
    std::size_t         _size;

private:
    std::size_t         _offset;
};

template < typename T, std::size_t D >
class MMArray : public MArray<T, D> {
public:
    MMArray()
        : MArray<T, D>()
        , _array(nullptr)
    { }

    MMArray(const std::size_t size[D])
    {
        resize(size);
    }

    MMArray(const MMArray<T, D> &mma)
    {
        *this = mma;
    }

    MMArray(MMArray &&mma)
        : MArray<T, D>(std::forward<MMArray<T, D>>(mma))
        , _array(std::move(mma._array))
    { }

    MMArray & operator=(const MMArray &mma)
    {
        if (&mma != this) {
            _array.reset(new T[mma.totalSize()]);
            std::memcpy(_array.get(), mma._array.get(), mma.totalSize() * sizeof(T));
            std::size_t size[D];
            mma.size(size);
            MArray<T, D>::operator=(MArray<T, D>(_array.get(), 0, size));
        }
        return *this;
    }

    MMArray & operator=(MMArray &&mma)
    {
        if (&mma != this) {
            MArray<T, D>::operator=(std::forward<MMArray<T, D>>(mma));
            _array = std::move(mma._array);
        }
        return *this;
    }

    inline void resize(const std::size_t size[D])
    {
        std::size_t total = size[0];
        for (std::size_t i = 1; i < D; ++i)
            total *= size[i];
        _array.reset(new T[total]);                                     // Be aware: data is LOST!
        MArray<T, D>::operator=(MArray<T, D>(_array.get(), 0, size));
    }

private:
    std::unique_ptr<T[]>    _array;
};

#endif /* multiple_array_hpp */
<|endoftext|>


<commit_before>#ifndef IMQUE_QUEUE_IMPL_HH
#define IMQUE_QUEUE_IMPL_HH

#include "../ipc/shared_memory.hh" // XXX: 最終的には無くす
#include "../block_allocator.hh"
#include "../atomic/atomic.hh"

#include <inttypes.h>
#include <string.h>

namespace imque {
  class QueueImpl {
    struct Entry {
      uint32_t state:2;
      uint32_t value:30;

      enum STATE {
        FREE = 0,
        USED = 1
      };
    }__attribute__((__packed__));

    struct Stat {
      uint32_t overflowed_count;
    };

    struct Header {
      uint32_t version; // XXX: name
      volatile uint32_t read_pos;
      volatile uint32_t write_pos;
      Stat stat;
      uint32_t entry_count;
      Entry entries[0];

      uint32_t next_read_pos() const { return (read_pos+1)%entry_count; }
      uint32_t next_write_pos() const { return (write_pos+1)%entry_count; }
    };

  public:
    QueueImpl(size_t entry_count, SharedMemory& shm)
      : que_(shm.ptr<Header>()),
        alc_(shm.ptr<void>(que_size(entry_count)), shm.size()-que_size(entry_count)) {
      if(shm) {
        que_->entry_count = entry_count;
      }
    }

    operator bool() const { return alc_; }

    void init() {
      alc_.init();

      que_->version = 0;
      que_->read_pos  = 0;
      que_->write_pos = 0;
      que_->stat.overflowed_count = 0;
      memset(que_->entries, 0, sizeof(Entry)*que_->entry_count);
    }

    bool enq(const void* data, size_t size) {
      if(isFull()) {
        atomic::add_and_fetch(&que_->stat.overflowed_count, 1);
        return false;
      }

      uint32_t alloc_id = alc_.allocate(sizeof(size_t) + size);
      if(alloc_id == 0) {
        atomic::add_and_fetch(&que_->stat.overflowed_count, 1);
        return false;
      }

      alc_.ptr<size_t>(alloc_id)[0] = size;
      memcpy(alc_.ptr<void>(alloc_id, sizeof(size_t)), data, size);

      if(enq_impl(alloc_id) == false) {
        atomic::add_and_fetch(&que_->stat.overflowed_count, 1);
        alc_.release(alloc_id);
        return false;
      }

      return true;
    }

    bool deq(std::string& buf) {
      if(isEmpty()) {
        return false;
      }

      uint32_t alloc_id = deq_impl();
      if(alloc_id == 0) {
        return false;
      }

      size_t size = alc_.ptr<size_t>(alloc_id)[0];
      char*  data = alc_.ptr<char>(alloc_id, sizeof(size_t));
      buf.assign(data, size);

      assert(alc_.release(alloc_id));

      return true;
    }

    bool isEmpty() const { return que_->read_pos == que_->write_pos; }
    bool isFull()  const { return que_->read_pos == que_->next_write_pos(); }

    static size_t calc_need_byte_size(size_t entry_count, size_t data_size) {
      return que_size(entry_count) + dat_size(data_size);
    }

    size_t overflowedCount() const { return que_->stat.overflowed_count; }
    void resetOverflowedCount() { que_->stat.overflowed_count = 0; }

  private:
    bool enq_impl(uint32_t value) {
      uint32_t curr_read  = que_->read_pos;
      uint32_t curr_write = que_->write_pos;
      uint32_t next_write = (curr_write+1) % que_->entry_count;

      if(curr_read == next_write) {
        atomic::add_and_fetch(&que_->stat.overflowed_count, 1);
        return false;
      }

      Entry* pe = &que_->entries[curr_write];
      Entry  e = *pe;
      if(e.state != Entry::FREE) {
        atomic::compare_and_swap(&que_->write_pos, curr_write, next_write);
        return enq_impl(value);
      }

      Entry new_e = {Entry::USED, value};
      if(atomic::compare_and_swap(pe, e, new_e) == false) {
        return enq_impl(value);
      }

      atomic::compare_and_swap(&que_->write_pos, curr_write, next_write);
      return true;
    }

    uint32_t deq_impl() {
      uint32_t curr_read  = que_->read_pos;
      uint32_t curr_write = que_->write_pos;
      uint32_t next_read = (curr_read+1) % que_->entry_count;

      if(curr_read == curr_write) {
        return 0;
      }

      Entry* pe = &que_->entries[curr_read];
      Entry   e = *pe;
      if(e.state == Entry::FREE) {
        atomic::compare_and_swap(&que_->read_pos, curr_read, next_read);
        return deq_impl();
      }

      uint32_t new_version = atomic::fetch_and_add(&que_->version, 1);
      Entry new_e = {Entry::FREE, new_version};
      if(atomic::compare_and_swap(pe, e, new_e) == false) {
        return deq_impl();
      }

      atomic::compare_and_swap(&que_->read_pos, curr_read, next_read);
      return e.value;
    }

    static size_t que_size(size_t entry_count) {
      return sizeof(Header) + sizeof(Entry)*entry_count;
    }

    static size_t dat_size(size_t data_size) {
      return Allocator::calc_need_byte_size(data_size);
    }

  private:
    Header*   que_;
    BlockAllocator alc_;
  };
}

#endif
<commit_msg>volatile対応<commit_after>#ifndef IMQUE_QUEUE_IMPL_HH
#define IMQUE_QUEUE_IMPL_HH

#include "../ipc/shared_memory.hh" // XXX: 最終的には無くす
#include "../block_allocator.hh"
#include "../atomic/atomic.hh"

#include <inttypes.h>
#include <string.h>

namespace imque {
  class QueueImpl {
    struct Entry {
      uint32_t state:2;
      uint32_t value:30;

      enum STATE {
        FREE = 0,
        USED = 1
      };
    }__attribute__((__packed__));

    struct Stat {
      uint32_t overflowed_count;
    };

    struct Header {
      volatile uint32_t version; // XXX: name
      volatile uint32_t read_pos;
      volatile uint32_t write_pos;
      Stat stat;
      uint32_t entry_count;
      Entry entries[0];

      uint32_t next_read_pos() const { return (read_pos+1)%entry_count; }
      uint32_t next_write_pos() const { return (write_pos+1)%entry_count; }
    };

  public:
    QueueImpl(size_t entry_count, SharedMemory& shm)
      : que_(shm.ptr<Header>()),
        alc_(shm.ptr<void>(que_size(entry_count)), shm.size()-que_size(entry_count)) {
      if(shm) {
        que_->entry_count = entry_count;
      }
    }

    operator bool() const { return alc_; }

    void init() {
      alc_.init();

      que_->version = 0;
      que_->read_pos  = 0;
      que_->write_pos = 0;
      que_->stat.overflowed_count = 0;
      memset(que_->entries, 0, sizeof(Entry)*que_->entry_count);
    }

    bool enq(const void* data, size_t size) {
      if(isFull()) {
        atomic::add_and_fetch(&que_->stat.overflowed_count, 1);
        return false;
      }

      uint32_t alloc_id = alc_.allocate(sizeof(size_t) + size);
      if(alloc_id == 0) {
        atomic::add_and_fetch(&que_->stat.overflowed_count, 1);
        return false;
      }

      alc_.ptr<size_t>(alloc_id)[0] = size;
      memcpy(alc_.ptr<void>(alloc_id, sizeof(size_t)), data, size);

      if(enq_impl(alloc_id) == false) {
        atomic::add_and_fetch(&que_->stat.overflowed_count, 1);
        alc_.release(alloc_id);
        return false;
      }

      return true;
    }

    bool deq(std::string& buf) {
      if(isEmpty()) {
        return false;
      }

      uint32_t alloc_id = deq_impl();
      if(alloc_id == 0) {
        return false;
      }

      size_t size = alc_.ptr<size_t>(alloc_id)[0];
      char*  data = alc_.ptr<char>(alloc_id, sizeof(size_t));
      buf.assign(data, size);

      assert(alc_.release(alloc_id));

      return true;
    }

    bool isEmpty() const { return que_->read_pos == que_->write_pos; }
    bool isFull()  const { return que_->read_pos == que_->next_write_pos(); }

    static size_t calc_need_byte_size(size_t entry_count, size_t data_size) {
      return que_size(entry_count) + dat_size(data_size);
    }

    size_t overflowedCount() const { return que_->stat.overflowed_count; }
    void resetOverflowedCount() { que_->stat.overflowed_count = 0; }

  private:
    bool enq_impl(uint32_t value) {
      uint32_t curr_read  = que_->read_pos;
      uint32_t curr_write = que_->write_pos;
      uint32_t next_write = (curr_write+1) % que_->entry_count;

      if(curr_read == next_write) {
        atomic::add_and_fetch(&que_->stat.overflowed_count, 1);
        return false;
      }

      Entry* pe = &que_->entries[curr_write];
      Entry  e = *pe;
      if(e.state != Entry::FREE) {
        atomic::compare_and_swap(&que_->write_pos, curr_write, next_write);
        return enq_impl(value);
      }

      Entry new_e = {Entry::USED, value};
      if(atomic::compare_and_swap(pe, e, new_e) == false) {
        return enq_impl(value);
      }

      atomic::compare_and_swap(&que_->write_pos, curr_write, next_write);
      return true;
    }

    uint32_t deq_impl() {
      uint32_t curr_read  = que_->read_pos;
      uint32_t curr_write = que_->write_pos;
      uint32_t next_read = (curr_read+1) % que_->entry_count;

      if(curr_read == curr_write) {
        return 0;
      }

      Entry* pe = &que_->entries[curr_read];
      Entry   e = *pe;
      if(e.state == Entry::FREE) {
        atomic::compare_and_swap(&que_->read_pos, curr_read, next_read);
        return deq_impl();
      }

      uint32_t new_version = atomic::fetch_and_add(&que_->version, 1);
      Entry new_e = {Entry::FREE, new_version};
      if(atomic::compare_and_swap(pe, e, new_e) == false) {
        return deq_impl();
      }

      atomic::compare_and_swap(&que_->read_pos, curr_read, next_read);
      return e.value;
    }

    static size_t que_size(size_t entry_count) {
      return sizeof(Header) + sizeof(Entry)*entry_count;
    }

    static size_t dat_size(size_t data_size) {
      return Allocator::calc_need_byte_size(data_size);
    }

  private:
    Header*   que_;
    BlockAllocator alc_;
  };
}

#endif
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2004  Justin Karneges
 * Copyright (C) 2004  Brad Hards <bradh@frogmouth.net>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 */
#include "qcaprovider.h"
#include <qstringlist.h>
#include <gcrypt.h>
#include <iostream>

void check_error( gcry_error_t err )
{
    if ( GPG_ERR_NO_ERROR != err ) {
	std::cout << "Failure: " ;
		std::cout << gcry_strsource(err) << "/";
		std::cout << gcry_strerror(err) << std::endl;
    }
}

class gcryHashContext : public QCA::HashContext
{
public:
    gcryHashContext(QCA::Provider *p, const QString &type) : QCA::HashContext(p, type) {};

    void clear()
    {
	gcry_md_reset( context );
    }

    void update(const QSecureArray &a)
    {
	gcry_md_write( context, a.data(), a.size() );
    }

    QSecureArray final()
    {
	unsigned char *md;
	QSecureArray a( gcry_md_get_algo_dlen( hashAlgorithm ) );
	md = gcry_md_read( context, hashAlgorithm );
	memcpy( a.data(), md, a.size() );
	return a;
    }

protected:
    gcry_md_hd_t context;
    gcry_error_t err;
    int hashAlgorithm;
};

class SHA1Context : public gcryHashContext
{
public:
	SHA1Context(QCA::Provider *p) : gcryHashContext(p, "sha1")
	{
		gcry_check_version("GCRYPT_VERSION");
		hashAlgorithm = GCRY_MD_SHA1;
		err =  gcry_md_open( &context, hashAlgorithm, 0 );
		if ( GPG_ERR_NO_ERROR != err ) {
			std::cout << "Failure: " ;
			std::cout << gcry_strsource(err) << "/";
			std::cout << gcry_strerror(err) << std::endl;
		}
	}

	~SHA1Context()
	{
		gcry_md_close( context );
	}

	Context *clone() const
	{
		return new SHA1Context(*this);
	}
};

class SHA256Context : public gcryHashContext
{
public:
    SHA256Context(QCA::Provider *p) : gcryHashContext(p, "sha256")
    {
	gcry_check_version("GCRYPT_VERSION");
	hashAlgorithm = GCRY_MD_SHA256;
	err =  gcry_md_open( &context, hashAlgorithm, 0 );
	if ( GPG_ERR_NO_ERROR != err ) {
	    std::cout << "Failure: " ;
	    std::cout << gcry_strsource(err) << "/";
	    std::cout << gcry_strerror(err) << std::endl;
	}
    }

    ~SHA256Context()
    {
	gcry_md_close( context );
    }

    Context *clone() const
    {
	return new SHA256Context(*this);
    }
};

class SHA384Context : public gcryHashContext
{
public:
	SHA384Context(QCA::Provider *p) : gcryHashContext(p, "sha384")
	{
		gcry_check_version("GCRYPT_VERSION");
		hashAlgorithm = GCRY_MD_SHA384;
		err =  gcry_md_open( &context, hashAlgorithm, 0 );
		if ( GPG_ERR_NO_ERROR != err ) {
			std::cout << "Failure: " ;
			std::cout << gcry_strsource(err) << "/";
			std::cout << gcry_strerror(err) << std::endl;
		}
	}

	~SHA384Context()
	{
		gcry_md_close( context );
	}

	Context *clone() const
	{
		return new SHA384Context(*this);
	}
};

class SHA512Context : public gcryHashContext
{
public:
	SHA512Context(QCA::Provider *p) : gcryHashContext(p, "sha512")
	{
		gcry_check_version("GCRYPT_VERSION");
		hashAlgorithm = GCRY_MD_SHA512;
		err =  gcry_md_open( &context, hashAlgorithm, 0 );
		if ( GPG_ERR_NO_ERROR != err ) {
			std::cout << "Failure: " ;
			std::cout << gcry_strsource(err) << "/";
			std::cout << gcry_strerror(err) << std::endl;
		}
	}

	~SHA512Context()
	{
		gcry_md_close( context );
	}

	Context *clone() const
	{
		return new SHA512Context(*this);
	}
};

static int gcry_mode( QCA::CipherContext::Mode mode )
{
    int retmode;
    switch (mode)
    {
    case QCA::CipherContext::ECB :
	retmode = GCRY_CIPHER_MODE_ECB;
	break;
    case QCA::CipherContext::CBC :
	retmode = GCRY_CIPHER_MODE_CBC;
	break;
    case QCA::CipherContext::CFB :
	retmode = GCRY_CIPHER_MODE_CFB;
	break;
    default:
	retmode = GCRY_CIPHER_MODE_NONE;
    }
    return retmode;
};

class gcryCipherContext : public QCA::CipherContext
{
public:
    gcryCipherContext(QCA::Provider *p, const QString &type) : QCA::CipherContext(p, type) {}

    void setup(const QCA::SymmetricKey &key,
	       QCA::CipherContext::Mode m,
	       QCA::Direction dir,
	       const QCA::InitializationVector &iv)
    {
	m_direction = dir;
	err =  gcry_cipher_open( &context, cryptoAlgorithm, gcry_mode(m), 0 );
	check_error( err );
	err = gcry_cipher_setkey( context, key.data(), key.size() );
	check_error( err );
	err = gcry_cipher_setiv( context, iv.data(), iv.size() );
	check_error( err );
    }

    int blockSize() const
    {
	int blockSize;
	gcry_cipher_algo_info( cryptoAlgorithm, GCRYCTL_GET_BLKLEN, 0, (size_t*)&blockSize );
	return blockSize;
    }

    bool update(const QSecureArray &in, QSecureArray *out)
    {
	QSecureArray result( in.size() );
	if (QCA::Encode == m_direction) {
	    err = gcry_cipher_encrypt( context, (unsigned char*)result.data(), result.size(), (unsigned char*)in.data(), in.size() );
	} else {
	    err = gcry_cipher_decrypt( context, (unsigned char*)result.data(), result.size(), (unsigned char*)in.data(), in.size() );
	}
	check_error(err );
	result.resize( in.size() );
	*out = result;
	return true;
    }

    bool final(QSecureArray *out)
    {
	*out = QSecureArray();
	return true;
    }

protected:
    gcry_cipher_hd_t context;
    gcry_error_t err;
    int cryptoAlgorithm;
    QCA::Direction m_direction;
};

class AES128Context : public gcryCipherContext
{
public:
    AES128Context(QCA::Provider *p) : gcryCipherContext( p, "aes128" )
    {
	gcry_check_version("GCRYPT_VERSION");
	cryptoAlgorithm = GCRY_CIPHER_AES128;
    }

    Context *clone() const
    {
	return new AES128Context( *this );
    }

    QCA::KeyLength keyLength() const
    {
	// Must be 128 bits
	return QCA::KeyLength( 16, 16, 1);
    }

};

class AES192Context : public gcryCipherContext
{
public:
    AES192Context(QCA::Provider *p) : gcryCipherContext( p, "aes192" )
    {
	gcry_check_version("GCRYPT_VERSION");
	cryptoAlgorithm = GCRY_CIPHER_AES192;
    }

    Context *clone() const
    {
	return new AES192Context( *this );
    }

    QCA::KeyLength keyLength() const
    {
	// Must be 192 bits
	return QCA::KeyLength( 24, 24, 1);
    }
};

class AES256Context : public gcryCipherContext
{
public:
    AES256Context(QCA::Provider *p) : gcryCipherContext( p, "aes256" )
    {
	gcry_check_version("GCRYPT_VERSION");
	cryptoAlgorithm = GCRY_CIPHER_AES256;
    }

    Context *clone() const
    {
	return new AES256Context( *this );
    }

    QCA::KeyLength keyLength() const
    {
	// Must be 256 bits
	return QCA::KeyLength( 32, 32, 1);
    }
};

class BlowFishContext : public gcryCipherContext
{
public:
    BlowFishContext(QCA::Provider *p) : gcryCipherContext( p, "blowfish" )
    {
	gcry_check_version("GCRYPT_VERSION");
	cryptoAlgorithm = GCRY_CIPHER_BLOWFISH;
    }

    Context *clone() const
    {
	return new BlowFishContext( *this );
    }

    QCA::KeyLength keyLength() const
    {
	// Don't know - TODO
	return QCA::KeyLength( 1, 32, 1);
    }
};

class TripleDESContext : public gcryCipherContext
{
public:
    TripleDESContext(QCA::Provider *p) : gcryCipherContext( p, "tripledes" )
    {
	gcry_check_version("GCRYPT_VERSION");
	cryptoAlgorithm = GCRY_CIPHER_3DES;
    }

    Context *clone() const
    {
	return new TripleDESContext( *this );
    }

    QCA::KeyLength keyLength() const
    {
	return QCA::KeyLength( 24, 24, 1);
    }
};

class gcryptProvider : public QCA::Provider
{
public:
	void init()
	{
	}

	QString name() const
	{
		return "qca-gcrypt";
	}

	QStringList features() const
	{
		QStringList list;
		list += "sha1";
		list += "sha256";
		list += "sha384";
		list += "sha512";
		list += "aes128";
		list += "aes192";
		list += "aes256";
		list += "blowfish";
		list += "tripledes";
		return list;
	}

	Context *createContext(const QString &type)
	{
		if ( type == "sha1" )
			return new SHA1Context( this );
		else if ( type == "sha256" )
			return new SHA256Context( this );
		else if ( type == "sha384" )
			return new SHA384Context( this );
		else if ( type == "sha512" )
			return new SHA512Context( this );
		else if ( type == "aes128" )
			return new AES128Context( this );
		else if ( type == "aes192" )
			return new AES192Context( this );
		else if ( type == "aes256" )
			return new AES256Context( this );
		else if ( type == "blowfish" )
			return new BlowFishContext( this );
		else if ( type == "tripledes" )
			return new TripleDESContext( this );
		else
			return 0;
	}
};

QCA_EXPORT_PLUGIN(gcryptProvider);
<commit_msg>DES provider<commit_after>/*
 * Copyright (C) 2004  Justin Karneges
 * Copyright (C) 2004  Brad Hards <bradh@frogmouth.net>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 */
#include "qcaprovider.h"
#include <qstringlist.h>
#include <gcrypt.h>
#include <iostream>

void check_error( gcry_error_t err )
{
    if ( GPG_ERR_NO_ERROR != err ) {
	std::cout << "Failure: " ;
		std::cout << gcry_strsource(err) << "/";
		std::cout << gcry_strerror(err) << std::endl;
    }
}

class gcryHashContext : public QCA::HashContext
{
public:
    gcryHashContext(QCA::Provider *p, const QString &type) : QCA::HashContext(p, type) {};

    void clear()
    {
	gcry_md_reset( context );
    }

    void update(const QSecureArray &a)
    {
	gcry_md_write( context, a.data(), a.size() );
    }

    QSecureArray final()
    {
	unsigned char *md;
	QSecureArray a( gcry_md_get_algo_dlen( hashAlgorithm ) );
	md = gcry_md_read( context, hashAlgorithm );
	memcpy( a.data(), md, a.size() );
	return a;
    }

protected:
    gcry_md_hd_t context;
    gcry_error_t err;
    int hashAlgorithm;
};

class SHA1Context : public gcryHashContext
{
public:
	SHA1Context(QCA::Provider *p) : gcryHashContext(p, "sha1")
	{
		gcry_check_version("GCRYPT_VERSION");
		hashAlgorithm = GCRY_MD_SHA1;
		err =  gcry_md_open( &context, hashAlgorithm, 0 );
		if ( GPG_ERR_NO_ERROR != err ) {
			std::cout << "Failure: " ;
			std::cout << gcry_strsource(err) << "/";
			std::cout << gcry_strerror(err) << std::endl;
		}
	}

	~SHA1Context()
	{
		gcry_md_close( context );
	}

	Context *clone() const
	{
		return new SHA1Context(*this);
	}
};

class SHA256Context : public gcryHashContext
{
public:
    SHA256Context(QCA::Provider *p) : gcryHashContext(p, "sha256")
    {
	gcry_check_version("GCRYPT_VERSION");
	hashAlgorithm = GCRY_MD_SHA256;
	err =  gcry_md_open( &context, hashAlgorithm, 0 );
	if ( GPG_ERR_NO_ERROR != err ) {
	    std::cout << "Failure: " ;
	    std::cout << gcry_strsource(err) << "/";
	    std::cout << gcry_strerror(err) << std::endl;
	}
    }

    ~SHA256Context()
    {
	gcry_md_close( context );
    }

    Context *clone() const
    {
	return new SHA256Context(*this);
    }
};

class SHA384Context : public gcryHashContext
{
public:
	SHA384Context(QCA::Provider *p) : gcryHashContext(p, "sha384")
	{
		gcry_check_version("GCRYPT_VERSION");
		hashAlgorithm = GCRY_MD_SHA384;
		err =  gcry_md_open( &context, hashAlgorithm, 0 );
		if ( GPG_ERR_NO_ERROR != err ) {
			std::cout << "Failure: " ;
			std::cout << gcry_strsource(err) << "/";
			std::cout << gcry_strerror(err) << std::endl;
		}
	}

	~SHA384Context()
	{
		gcry_md_close( context );
	}

	Context *clone() const
	{
		return new SHA384Context(*this);
	}
};

class SHA512Context : public gcryHashContext
{
public:
	SHA512Context(QCA::Provider *p) : gcryHashContext(p, "sha512")
	{
		gcry_check_version("GCRYPT_VERSION");
		hashAlgorithm = GCRY_MD_SHA512;
		err =  gcry_md_open( &context, hashAlgorithm, 0 );
		if ( GPG_ERR_NO_ERROR != err ) {
			std::cout << "Failure: " ;
			std::cout << gcry_strsource(err) << "/";
			std::cout << gcry_strerror(err) << std::endl;
		}
	}

	~SHA512Context()
	{
		gcry_md_close( context );
	}

	Context *clone() const
	{
		return new SHA512Context(*this);
	}
};

static int gcry_mode( QCA::CipherContext::Mode mode )
{
    int retmode;
    switch (mode)
    {
    case QCA::CipherContext::ECB :
	retmode = GCRY_CIPHER_MODE_ECB;
	break;
    case QCA::CipherContext::CBC :
	retmode = GCRY_CIPHER_MODE_CBC;
	break;
    case QCA::CipherContext::CFB :
	retmode = GCRY_CIPHER_MODE_CFB;
	break;
    default:
	retmode = GCRY_CIPHER_MODE_NONE;
    }
    return retmode;
};

class gcryCipherContext : public QCA::CipherContext
{
public:
    gcryCipherContext(QCA::Provider *p, const QString &type) : QCA::CipherContext(p, type) {}

    void setup(const QCA::SymmetricKey &key,
	       QCA::CipherContext::Mode m,
	       QCA::Direction dir,
	       const QCA::InitializationVector &iv)
    {
	m_direction = dir;
	err =  gcry_cipher_open( &context, cryptoAlgorithm, gcry_mode(m), 0 );
	check_error( err );
	err = gcry_cipher_setkey( context, key.data(), key.size() );
	check_error( err );
	err = gcry_cipher_setiv( context, iv.data(), iv.size() );
	check_error( err );
    }

    unsigned int blockSize() const
    {
	unsigned int blockSize;
	gcry_cipher_algo_info( cryptoAlgorithm, GCRYCTL_GET_BLKLEN, 0, (size_t*)&blockSize );
	return blockSize;
    }

    bool update(const QSecureArray &in, QSecureArray *out)
    {
	QSecureArray result( in.size() );
	if (QCA::Encode == m_direction) {
	    err = gcry_cipher_encrypt( context, (unsigned char*)result.data(), result.size(), (unsigned char*)in.data(), in.size() );
	} else {
	    err = gcry_cipher_decrypt( context, (unsigned char*)result.data(), result.size(), (unsigned char*)in.data(), in.size() );
	}
	check_error(err );
	result.resize( in.size() );
	*out = result;
	return true;
    }

    bool final(QSecureArray *out)
    {
	*out = QSecureArray();
	return true;
    }

protected:
    gcry_cipher_hd_t context;
    gcry_error_t err;
    int cryptoAlgorithm;
    QCA::Direction m_direction;
};

class AES128Context : public gcryCipherContext
{
public:
    AES128Context(QCA::Provider *p) : gcryCipherContext( p, "aes128" )
    {
	gcry_check_version("GCRYPT_VERSION");
	cryptoAlgorithm = GCRY_CIPHER_AES128;
    }

    Context *clone() const
    {
	return new AES128Context( *this );
    }

    QCA::KeyLength keyLength() const
    {
	// Must be 128 bits
	return QCA::KeyLength( 16, 16, 1);
    }

};

class AES192Context : public gcryCipherContext
{
public:
    AES192Context(QCA::Provider *p) : gcryCipherContext( p, "aes192" )
    {
	gcry_check_version("GCRYPT_VERSION");
	cryptoAlgorithm = GCRY_CIPHER_AES192;
    }

    Context *clone() const
    {
	return new AES192Context( *this );
    }

    QCA::KeyLength keyLength() const
    {
	// Must be 192 bits
	return QCA::KeyLength( 24, 24, 1);
    }
};

class AES256Context : public gcryCipherContext
{
public:
    AES256Context(QCA::Provider *p) : gcryCipherContext( p, "aes256" )
    {
	gcry_check_version("GCRYPT_VERSION");
	cryptoAlgorithm = GCRY_CIPHER_AES256;
    }

    Context *clone() const
    {
	return new AES256Context( *this );
    }

    QCA::KeyLength keyLength() const
    {
	// Must be 256 bits
	return QCA::KeyLength( 32, 32, 1);
    }
};

class BlowFishContext : public gcryCipherContext
{
public:
    BlowFishContext(QCA::Provider *p) : gcryCipherContext( p, "blowfish" )
    {
	gcry_check_version("GCRYPT_VERSION");
	cryptoAlgorithm = GCRY_CIPHER_BLOWFISH;
    }

    Context *clone() const
    {
	return new BlowFishContext( *this );
    }

    QCA::KeyLength keyLength() const
    {
	// Don't know - TODO
	return QCA::KeyLength( 1, 32, 1);
    }
};

class TripleDESContext : public gcryCipherContext
{
public:
    TripleDESContext(QCA::Provider *p) : gcryCipherContext( p, "tripledes" )
    {
	gcry_check_version("GCRYPT_VERSION");
	cryptoAlgorithm = GCRY_CIPHER_3DES;
    }

    Context *clone() const
    {
	return new TripleDESContext( *this );
    }

    QCA::KeyLength keyLength() const
    {
	return QCA::KeyLength( 24, 24, 1);
    }
};

class DESContext : public gcryCipherContext
{
public:
    DESContext(QCA::Provider *p) : gcryCipherContext( p, "des" )
    {
	gcry_check_version("GCRYPT_VERSION");
	cryptoAlgorithm = GCRY_CIPHER_DES;
    }

    Context *clone() const
    {
	return new DESContext( *this );
    }

    QCA::KeyLength keyLength() const
    {
	return QCA::KeyLength( 8, 8, 1);
    }
};

class gcryptProvider : public QCA::Provider
{
public:
	void init()
	{
	}

	QString name() const
	{
		return "qca-gcrypt";
	}

	QStringList features() const
	{
		QStringList list;
		list += "sha1";
		list += "sha256";
		list += "sha384";
		list += "sha512";
		list += "aes128";
		list += "aes192";
		list += "aes256";
		list += "blowfish";
		list += "tripledes";
		list += "des";
		return list;
	}

	Context *createContext(const QString &type)
	{
		if ( type == "sha1" )
			return new SHA1Context( this );
		else if ( type == "sha256" )
			return new SHA256Context( this );
		else if ( type == "sha384" )
			return new SHA384Context( this );
		else if ( type == "sha512" )
			return new SHA512Context( this );
		else if ( type == "aes128" )
			return new AES128Context( this );
		else if ( type == "aes192" )
			return new AES192Context( this );
		else if ( type == "aes256" )
			return new AES256Context( this );
		else if ( type == "blowfish" )
			return new BlowFishContext( this );
		else if ( type == "tripledes" )
			return new TripleDESContext( this );
		else if ( type == "des" )
			return new DESContext( this );
		else
			return 0;
	}
};

QCA_EXPORT_PLUGIN(gcryptProvider);
<|endoftext|>