<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: SchemaRestrictionContext.cxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-09 16:00:52 $
 *
 *  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
 *
 ************************************************************************/

#include "SchemaRestrictionContext.hxx"
#include "xformsapi.hxx"

#include <xmltoken.hxx>
#include <nmspmap.hxx>
#include <xmlnmspe.hxx>
#include <xmltkmap.hxx>
#include <xmluconv.hxx>
#include <xmlimp.hxx>

#include <com/sun/star/beans/XPropertySet.hpp>
#include <com/sun/star/uno/Type.hxx>
#include <com/sun/star/util/Date.hpp>
#include <com/sun/star/util/Time.hpp>
#include <com/sun/star/util/DateTime.hpp>
#include <com/sun/star/xforms/XDataTypeRepository.hpp>
#include <com/sun/star/xsd/DataTypeClass.hpp>
#include <com/sun/star/xsd/WhiteSpaceTreatment.hpp>

#include <tools/debug.hxx>

using rtl::OUString;
using com::sun::star::uno::Reference;
using com::sun::star::uno::Exception;
using com::sun::star::uno::Any;
using com::sun::star::uno::makeAny;
using com::sun::star::uno::UNO_QUERY;
using com::sun::star::util::Date;
using com::sun::star::util::DateTime;
using com::sun::star::xml::sax::XAttributeList;
using com::sun::star::beans::XPropertySet;
using com::sun::star::beans::XPropertySetInfo;
using com::sun::star::xforms::XDataTypeRepository;
using namespace xmloff::token;

static SvXMLTokenMapEntry aAttributes[] =
{
    TOKEN_MAP_ENTRY( NONE, BASE ),
    XML_TOKEN_MAP_END
};

static SvXMLTokenMapEntry aChildren[] =
{
    TOKEN_MAP_ENTRY( XSD, LENGTH         ),
    TOKEN_MAP_ENTRY( XSD, MINLENGTH      ),
    TOKEN_MAP_ENTRY( XSD, MAXLENGTH      ),
    TOKEN_MAP_ENTRY( XSD, MININCLUSIVE   ),
    TOKEN_MAP_ENTRY( XSD, MINEXCLUSIVE   ),
    TOKEN_MAP_ENTRY( XSD, MAXINCLUSIVE   ),
    TOKEN_MAP_ENTRY( XSD, MAXEXCLUSIVE   ),
    TOKEN_MAP_ENTRY( XSD, PATTERN        ),
    // ??? XML_ENUMERATION
    TOKEN_MAP_ENTRY( XSD, WHITESPACE     ),
    TOKEN_MAP_ENTRY( XSD, TOTALDIGITS    ),
    TOKEN_MAP_ENTRY( XSD, FRACTIONDIGITS ),
    XML_TOKEN_MAP_END
};

SchemaRestrictionContext::SchemaRestrictionContext(
    SvXMLImport& rImport,
    USHORT nPrefix,
    const OUString& rLocalName,
    Reference<com::sun::star::xforms::XDataTypeRepository>& rRepository,
    const OUString& sTypeName ) :
        TokenContext( rImport, nPrefix, rLocalName, aAttributes, aChildren ),
        mxRepository( rRepository ),
        msTypeName( sTypeName ),
        msBaseName()
{
    DBG_ASSERT( mxRepository.is(), "need repository" );
}

SchemaRestrictionContext::~SchemaRestrictionContext()
{
}

void SchemaRestrictionContext::CreateDataType()
{
    // only do something if we don't have a data type already
    if( mxDataType.is() )
        return;

    DBG_ASSERT( msBaseName.getLength() > 0, "no base name?" );
    DBG_ASSERT( mxRepository.is(), "no repository?" );

    try
    {
        mxDataType =
            Reference<XPropertySet>(
                mxRepository->cloneDataType(
                    lcl_getBasicTypeName( mxRepository,
                                          GetImport().GetNamespaceMap(),
                                          msBaseName ),
                    msTypeName ),
                UNO_QUERY );
    }
    catch( const Exception& )
    {
        DBG_ERROR( "exception during type creation" );
    }
    DBG_ASSERT( mxDataType.is(), "can't create type" );
}

void SchemaRestrictionContext::HandleAttribute(
    sal_uInt16 nToken,
    const OUString& rValue )
{
    if( nToken == XML_BASE )
    {
        msBaseName = rValue;
    }
}

typedef Any (*convert_t)( const OUString& );

Any lcl_string( const OUString& rValue )
{
    return makeAny( rValue );
}

Any lcl_int32( const OUString& rValue )
{
    sal_Int32 nValue;
    bool bSuccess = SvXMLUnitConverter::convertNumber( nValue, rValue );
    return bSuccess ? makeAny( nValue ) : Any();
}

Any lcl_int16( const OUString& rValue )
{
    sal_Int32 nValue;
    bool bSuccess = SvXMLUnitConverter::convertNumber( nValue, rValue );
    return bSuccess ? makeAny( static_cast<sal_Int16>( nValue ) ) : Any();
}

Any lcl_whitespace( const OUString& rValue )
{
    Any aValue;
    if( IsXMLToken( rValue, XML_PRESERVE ) )
        aValue <<= com::sun::star::xsd::WhiteSpaceTreatment::Preserve;
    else if( IsXMLToken( rValue, XML_REPLACE ) )
        aValue <<= com::sun::star::xsd::WhiteSpaceTreatment::Replace;
    else if( IsXMLToken( rValue, XML_COLLAPSE ) )
        aValue <<= com::sun::star::xsd::WhiteSpaceTreatment::Collapse;
    return aValue;
}

Any lcl_double( const OUString& rValue )
{
    double fValue;
    bool bSuccess = SvXMLUnitConverter::convertDouble( fValue, rValue );
    return bSuccess ? makeAny( fValue ) : Any();
}

Any lcl_date( const OUString& rValue )
{
    Any aAny;

    // parse ISO date
    sal_Int32 nPos1 = rValue.indexOf( sal_Unicode('-') );
    sal_Int32 nPos2 = rValue.indexOf( sal_Unicode('-'), nPos1 + 1 );
    if( nPos1 > 0  &&  nPos2 > 0 )
    {
        Date aDate;
        aDate.Year = static_cast<sal_uInt16>(
                     rValue.copy( 0, nPos1 ).toInt32() );
        aDate.Month = static_cast<sal_uInt16>(
                      rValue.copy( nPos1 + 1, nPos2 - nPos1 - 1 ).toInt32() );
        aDate.Day   = static_cast<sal_uInt16>(
                      rValue.copy( nPos2 + 1 ).toInt32() );
        aAny <<= aDate;
    }
    return aAny;
}

Any lcl_dateTime( const OUString& rValue )
{
    DateTime aDateTime;
    bool bSuccess = SvXMLUnitConverter::convertDateTime( aDateTime, rValue );
    return bSuccess ? makeAny( aDateTime ) : Any();
}

Any lcl_time( const OUString& rValue )
{
    Any aAny;
    DateTime aDateTime;
    if( SvXMLUnitConverter::convertTime( aDateTime, rValue ) )
    {
        com::sun::star::util::Time aTime;
        aTime.Hours = aDateTime.Hours;
        aTime.Minutes = aDateTime.Minutes;
        aTime.Seconds = aDateTime.Seconds;
        aTime.HundredthSeconds = aDateTime.HundredthSeconds;
        aAny <<= aTime;
    }
    return aAny;
}

SvXMLImportContext* SchemaRestrictionContext::HandleChild(
    sal_uInt16 nToken,
    sal_uInt16 nPrefix,
    const OUString& rLocalName,
    const Reference<XAttributeList>& xAttrList )
{
    // find value
    OUString sValue;
    sal_Int16 nLength = xAttrList->getLength();
    for( sal_Int16 n = 0; n < nLength; n++ )
    {
        if( IsXMLToken( xAttrList->getNameByIndex( n ), XML_VALUE ) )
            sValue = xAttrList->getValueByIndex( n );
    }

    // determine property name + suitable converter
    OUString sPropertyName;
    convert_t pConvert = NULL;
    switch( nToken )
    {
    case XML_LENGTH:
        sPropertyName = OUString(RTL_CONSTASCII_USTRINGPARAM("Length"));
        pConvert = &lcl_int32;
        break;
    case XML_MINLENGTH:
        sPropertyName = OUString(RTL_CONSTASCII_USTRINGPARAM("MinLength"));
        pConvert = &lcl_int32;
        break;
    case XML_MAXLENGTH:
        sPropertyName = OUString(RTL_CONSTASCII_USTRINGPARAM("MaxLength"));
        pConvert = &lcl_int32;
        break;
    case XML_TOTALDIGITS:
        sPropertyName = OUString(RTL_CONSTASCII_USTRINGPARAM("TotalDigits"));
        pConvert = &lcl_int32;
        break;
    case XML_FRACTIONDIGITS:
        sPropertyName =OUString(RTL_CONSTASCII_USTRINGPARAM("FractionDigits"));
        pConvert = &lcl_int32;
        break;
    case XML_PATTERN:
        sPropertyName = OUString(RTL_CONSTASCII_USTRINGPARAM("Pattern"));
        pConvert = &lcl_string;
        break;
    case XML_WHITESPACE:
        sPropertyName = OUString(RTL_CONSTASCII_USTRINGPARAM("WhiteSpace"));
        pConvert = &lcl_whitespace;
        break;
    case XML_MININCLUSIVE:
    case XML_MINEXCLUSIVE:
    case XML_MAXINCLUSIVE:
    case XML_MAXEXCLUSIVE:
        {
            // these attributes are mapped to different properties.
            // To determine the property name, we use an attribute
            // dependent prefix and a type dependent suffix. The
            // converter is only type dependent.

            // first, attribute-dependent prefix
            switch( nToken )
            {
            case XML_MININCLUSIVE:
                sPropertyName = OUString(RTL_CONSTASCII_USTRINGPARAM("MinInclusive"));
                break;
            case XML_MINEXCLUSIVE:
                sPropertyName = OUString(RTL_CONSTASCII_USTRINGPARAM("MinExclusive"));
                break;
            case XML_MAXINCLUSIVE:
                sPropertyName = OUString(RTL_CONSTASCII_USTRINGPARAM("MaxInclusive"));
                break;
            case XML_MAXEXCLUSIVE:
                sPropertyName = OUString(RTL_CONSTASCII_USTRINGPARAM("MaxExclusive"));
                break;
            }

            // second, type-dependent suffix + converter
            switch( lcl_getTypeClass( mxRepository,
                                      GetImport().GetNamespaceMap(),
                                      msBaseName ) )
            {
            case com::sun::star::xsd::DataTypeClass::DECIMAL:
            case com::sun::star::xsd::DataTypeClass::DOUBLE:
            case com::sun::star::xsd::DataTypeClass::FLOAT:
                sPropertyName += OUString(RTL_CONSTASCII_USTRINGPARAM("Double"));
                pConvert = &lcl_double;
                break;
            case com::sun::star::xsd::DataTypeClass::DATETIME:
                sPropertyName += OUString(RTL_CONSTASCII_USTRINGPARAM("DateTime"));
                pConvert = &lcl_dateTime;
                break;
            case com::sun::star::xsd::DataTypeClass::DATE:
                sPropertyName += OUString(RTL_CONSTASCII_USTRINGPARAM("Date"));
                pConvert = &lcl_date;
                break;
            case com::sun::star::xsd::DataTypeClass::TIME:
                sPropertyName += OUString(RTL_CONSTASCII_USTRINGPARAM("Time"));
                pConvert = &lcl_time;
                break;
            case com::sun::star::xsd::DataTypeClass::gYear:
            case com::sun::star::xsd::DataTypeClass::gDay:
            case com::sun::star::xsd::DataTypeClass::gMonth:
                sPropertyName += OUString(RTL_CONSTASCII_USTRINGPARAM("Int"));
                pConvert = &lcl_int16;
                break;

            case com::sun::star::xsd::DataTypeClass::STRING:
            case com::sun::star::xsd::DataTypeClass::anyURI:
            case com::sun::star::xsd::DataTypeClass::BOOLEAN:
                // invalid: These shouldn't have min/max-inclusive
                break;

                /* data types not yet supported:
                   case com::sun::star::xsd::DataTypeClass::DURATION:
                   case com::sun::star::xsd::DataTypeClass::gYearMonth:
                   case com::sun::star::xsd::DataTypeClass::gMonthDay:
                   case com::sun::star::xsd::DataTypeClass::hexBinary:
                   case com::sun::star::xsd::DataTypeClass::base64Binary:
                   case com::sun::star::xsd::DataTypeClass::QName:
                   case com::sun::star::xsd::DataTypeClass::NOTATION:
                */
            }
        }
        break;

    default:
        DBG_ERROR( "unknown facet" );
    }

    // finally, set the property
    CreateDataType();
    if( mxDataType.is()
        && sPropertyName.getLength() > 0
        && pConvert != NULL
        && mxDataType->getPropertySetInfo()->hasPropertyByName(sPropertyName) )
    {
        try
        {
            mxDataType->setPropertyValue( sPropertyName, pConvert( sValue ) );
        }
        catch( const Exception& )
        {
            ; // can't set property? Then ignore.
        }
    }

    return new SvXMLImportContext( GetImport(), nPrefix, rLocalName );
}
<commit_msg>INTEGRATION: CWS pchfix02 (1.4.160); FILE MERGED 2006/09/01 18:00:21 kaib 1.4.160.1: #i68856# Added header markers and pch files<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: SchemaRestrictionContext.cxx,v $
 *
 *  $Revision: 1.5 $
 *
 *  last change: $Author: obo $ $Date: 2006-09-17 11:30:15 $
 *
 *  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_xmloff.hxx"

#include "SchemaRestrictionContext.hxx"
#include "xformsapi.hxx"

#include <xmltoken.hxx>
#include <nmspmap.hxx>
#include <xmlnmspe.hxx>
#include <xmltkmap.hxx>
#include <xmluconv.hxx>
#include <xmlimp.hxx>

#include <com/sun/star/beans/XPropertySet.hpp>
#include <com/sun/star/uno/Type.hxx>
#include <com/sun/star/util/Date.hpp>
#include <com/sun/star/util/Time.hpp>
#include <com/sun/star/util/DateTime.hpp>
#include <com/sun/star/xforms/XDataTypeRepository.hpp>
#include <com/sun/star/xsd/DataTypeClass.hpp>
#include <com/sun/star/xsd/WhiteSpaceTreatment.hpp>

#include <tools/debug.hxx>

using rtl::OUString;
using com::sun::star::uno::Reference;
using com::sun::star::uno::Exception;
using com::sun::star::uno::Any;
using com::sun::star::uno::makeAny;
using com::sun::star::uno::UNO_QUERY;
using com::sun::star::util::Date;
using com::sun::star::util::DateTime;
using com::sun::star::xml::sax::XAttributeList;
using com::sun::star::beans::XPropertySet;
using com::sun::star::beans::XPropertySetInfo;
using com::sun::star::xforms::XDataTypeRepository;
using namespace xmloff::token;

static SvXMLTokenMapEntry aAttributes[] =
{
    TOKEN_MAP_ENTRY( NONE, BASE ),
    XML_TOKEN_MAP_END
};

static SvXMLTokenMapEntry aChildren[] =
{
    TOKEN_MAP_ENTRY( XSD, LENGTH         ),
    TOKEN_MAP_ENTRY( XSD, MINLENGTH      ),
    TOKEN_MAP_ENTRY( XSD, MAXLENGTH      ),
    TOKEN_MAP_ENTRY( XSD, MININCLUSIVE   ),
    TOKEN_MAP_ENTRY( XSD, MINEXCLUSIVE   ),
    TOKEN_MAP_ENTRY( XSD, MAXINCLUSIVE   ),
    TOKEN_MAP_ENTRY( XSD, MAXEXCLUSIVE   ),
    TOKEN_MAP_ENTRY( XSD, PATTERN        ),
    // ??? XML_ENUMERATION
    TOKEN_MAP_ENTRY( XSD, WHITESPACE     ),
    TOKEN_MAP_ENTRY( XSD, TOTALDIGITS    ),
    TOKEN_MAP_ENTRY( XSD, FRACTIONDIGITS ),
    XML_TOKEN_MAP_END
};

SchemaRestrictionContext::SchemaRestrictionContext(
    SvXMLImport& rImport,
    USHORT nPrefix,
    const OUString& rLocalName,
    Reference<com::sun::star::xforms::XDataTypeRepository>& rRepository,
    const OUString& sTypeName ) :
        TokenContext( rImport, nPrefix, rLocalName, aAttributes, aChildren ),
        mxRepository( rRepository ),
        msTypeName( sTypeName ),
        msBaseName()
{
    DBG_ASSERT( mxRepository.is(), "need repository" );
}

SchemaRestrictionContext::~SchemaRestrictionContext()
{
}

void SchemaRestrictionContext::CreateDataType()
{
    // only do something if we don't have a data type already
    if( mxDataType.is() )
        return;

    DBG_ASSERT( msBaseName.getLength() > 0, "no base name?" );
    DBG_ASSERT( mxRepository.is(), "no repository?" );

    try
    {
        mxDataType =
            Reference<XPropertySet>(
                mxRepository->cloneDataType(
                    lcl_getBasicTypeName( mxRepository,
                                          GetImport().GetNamespaceMap(),
                                          msBaseName ),
                    msTypeName ),
                UNO_QUERY );
    }
    catch( const Exception& )
    {
        DBG_ERROR( "exception during type creation" );
    }
    DBG_ASSERT( mxDataType.is(), "can't create type" );
}

void SchemaRestrictionContext::HandleAttribute(
    sal_uInt16 nToken,
    const OUString& rValue )
{
    if( nToken == XML_BASE )
    {
        msBaseName = rValue;
    }
}

typedef Any (*convert_t)( const OUString& );

Any lcl_string( const OUString& rValue )
{
    return makeAny( rValue );
}

Any lcl_int32( const OUString& rValue )
{
    sal_Int32 nValue;
    bool bSuccess = SvXMLUnitConverter::convertNumber( nValue, rValue );
    return bSuccess ? makeAny( nValue ) : Any();
}

Any lcl_int16( const OUString& rValue )
{
    sal_Int32 nValue;
    bool bSuccess = SvXMLUnitConverter::convertNumber( nValue, rValue );
    return bSuccess ? makeAny( static_cast<sal_Int16>( nValue ) ) : Any();
}

Any lcl_whitespace( const OUString& rValue )
{
    Any aValue;
    if( IsXMLToken( rValue, XML_PRESERVE ) )
        aValue <<= com::sun::star::xsd::WhiteSpaceTreatment::Preserve;
    else if( IsXMLToken( rValue, XML_REPLACE ) )
        aValue <<= com::sun::star::xsd::WhiteSpaceTreatment::Replace;
    else if( IsXMLToken( rValue, XML_COLLAPSE ) )
        aValue <<= com::sun::star::xsd::WhiteSpaceTreatment::Collapse;
    return aValue;
}

Any lcl_double( const OUString& rValue )
{
    double fValue;
    bool bSuccess = SvXMLUnitConverter::convertDouble( fValue, rValue );
    return bSuccess ? makeAny( fValue ) : Any();
}

Any lcl_date( const OUString& rValue )
{
    Any aAny;

    // parse ISO date
    sal_Int32 nPos1 = rValue.indexOf( sal_Unicode('-') );
    sal_Int32 nPos2 = rValue.indexOf( sal_Unicode('-'), nPos1 + 1 );
    if( nPos1 > 0  &&  nPos2 > 0 )
    {
        Date aDate;
        aDate.Year = static_cast<sal_uInt16>(
                     rValue.copy( 0, nPos1 ).toInt32() );
        aDate.Month = static_cast<sal_uInt16>(
                      rValue.copy( nPos1 + 1, nPos2 - nPos1 - 1 ).toInt32() );
        aDate.Day   = static_cast<sal_uInt16>(
                      rValue.copy( nPos2 + 1 ).toInt32() );
        aAny <<= aDate;
    }
    return aAny;
}

Any lcl_dateTime( const OUString& rValue )
{
    DateTime aDateTime;
    bool bSuccess = SvXMLUnitConverter::convertDateTime( aDateTime, rValue );
    return bSuccess ? makeAny( aDateTime ) : Any();
}

Any lcl_time( const OUString& rValue )
{
    Any aAny;
    DateTime aDateTime;
    if( SvXMLUnitConverter::convertTime( aDateTime, rValue ) )
    {
        com::sun::star::util::Time aTime;
        aTime.Hours = aDateTime.Hours;
        aTime.Minutes = aDateTime.Minutes;
        aTime.Seconds = aDateTime.Seconds;
        aTime.HundredthSeconds = aDateTime.HundredthSeconds;
        aAny <<= aTime;
    }
    return aAny;
}

SvXMLImportContext* SchemaRestrictionContext::HandleChild(
    sal_uInt16 nToken,
    sal_uInt16 nPrefix,
    const OUString& rLocalName,
    const Reference<XAttributeList>& xAttrList )
{
    // find value
    OUString sValue;
    sal_Int16 nLength = xAttrList->getLength();
    for( sal_Int16 n = 0; n < nLength; n++ )
    {
        if( IsXMLToken( xAttrList->getNameByIndex( n ), XML_VALUE ) )
            sValue = xAttrList->getValueByIndex( n );
    }

    // determine property name + suitable converter
    OUString sPropertyName;
    convert_t pConvert = NULL;
    switch( nToken )
    {
    case XML_LENGTH:
        sPropertyName = OUString(RTL_CONSTASCII_USTRINGPARAM("Length"));
        pConvert = &lcl_int32;
        break;
    case XML_MINLENGTH:
        sPropertyName = OUString(RTL_CONSTASCII_USTRINGPARAM("MinLength"));
        pConvert = &lcl_int32;
        break;
    case XML_MAXLENGTH:
        sPropertyName = OUString(RTL_CONSTASCII_USTRINGPARAM("MaxLength"));
        pConvert = &lcl_int32;
        break;
    case XML_TOTALDIGITS:
        sPropertyName = OUString(RTL_CONSTASCII_USTRINGPARAM("TotalDigits"));
        pConvert = &lcl_int32;
        break;
    case XML_FRACTIONDIGITS:
        sPropertyName =OUString(RTL_CONSTASCII_USTRINGPARAM("FractionDigits"));
        pConvert = &lcl_int32;
        break;
    case XML_PATTERN:
        sPropertyName = OUString(RTL_CONSTASCII_USTRINGPARAM("Pattern"));
        pConvert = &lcl_string;
        break;
    case XML_WHITESPACE:
        sPropertyName = OUString(RTL_CONSTASCII_USTRINGPARAM("WhiteSpace"));
        pConvert = &lcl_whitespace;
        break;
    case XML_MININCLUSIVE:
    case XML_MINEXCLUSIVE:
    case XML_MAXINCLUSIVE:
    case XML_MAXEXCLUSIVE:
        {
            // these attributes are mapped to different properties.
            // To determine the property name, we use an attribute
            // dependent prefix and a type dependent suffix. The
            // converter is only type dependent.

            // first, attribute-dependent prefix
            switch( nToken )
            {
            case XML_MININCLUSIVE:
                sPropertyName = OUString(RTL_CONSTASCII_USTRINGPARAM("MinInclusive"));
                break;
            case XML_MINEXCLUSIVE:
                sPropertyName = OUString(RTL_CONSTASCII_USTRINGPARAM("MinExclusive"));
                break;
            case XML_MAXINCLUSIVE:
                sPropertyName = OUString(RTL_CONSTASCII_USTRINGPARAM("MaxInclusive"));
                break;
            case XML_MAXEXCLUSIVE:
                sPropertyName = OUString(RTL_CONSTASCII_USTRINGPARAM("MaxExclusive"));
                break;
            }

            // second, type-dependent suffix + converter
            switch( lcl_getTypeClass( mxRepository,
                                      GetImport().GetNamespaceMap(),
                                      msBaseName ) )
            {
            case com::sun::star::xsd::DataTypeClass::DECIMAL:
            case com::sun::star::xsd::DataTypeClass::DOUBLE:
            case com::sun::star::xsd::DataTypeClass::FLOAT:
                sPropertyName += OUString(RTL_CONSTASCII_USTRINGPARAM("Double"));
                pConvert = &lcl_double;
                break;
            case com::sun::star::xsd::DataTypeClass::DATETIME:
                sPropertyName += OUString(RTL_CONSTASCII_USTRINGPARAM("DateTime"));
                pConvert = &lcl_dateTime;
                break;
            case com::sun::star::xsd::DataTypeClass::DATE:
                sPropertyName += OUString(RTL_CONSTASCII_USTRINGPARAM("Date"));
                pConvert = &lcl_date;
                break;
            case com::sun::star::xsd::DataTypeClass::TIME:
                sPropertyName += OUString(RTL_CONSTASCII_USTRINGPARAM("Time"));
                pConvert = &lcl_time;
                break;
            case com::sun::star::xsd::DataTypeClass::gYear:
            case com::sun::star::xsd::DataTypeClass::gDay:
            case com::sun::star::xsd::DataTypeClass::gMonth:
                sPropertyName += OUString(RTL_CONSTASCII_USTRINGPARAM("Int"));
                pConvert = &lcl_int16;
                break;

            case com::sun::star::xsd::DataTypeClass::STRING:
            case com::sun::star::xsd::DataTypeClass::anyURI:
            case com::sun::star::xsd::DataTypeClass::BOOLEAN:
                // invalid: These shouldn't have min/max-inclusive
                break;

                /* data types not yet supported:
                   case com::sun::star::xsd::DataTypeClass::DURATION:
                   case com::sun::star::xsd::DataTypeClass::gYearMonth:
                   case com::sun::star::xsd::DataTypeClass::gMonthDay:
                   case com::sun::star::xsd::DataTypeClass::hexBinary:
                   case com::sun::star::xsd::DataTypeClass::base64Binary:
                   case com::sun::star::xsd::DataTypeClass::QName:
                   case com::sun::star::xsd::DataTypeClass::NOTATION:
                */
            }
        }
        break;

    default:
        DBG_ERROR( "unknown facet" );
    }

    // finally, set the property
    CreateDataType();
    if( mxDataType.is()
        && sPropertyName.getLength() > 0
        && pConvert != NULL
        && mxDataType->getPropertySetInfo()->hasPropertyByName(sPropertyName) )
    {
        try
        {
            mxDataType->setPropertyValue( sPropertyName, pConvert( sValue ) );
        }
        catch( const Exception& )
        {
            ; // can't set property? Then ignore.
        }
    }

    return new SvXMLImportContext( GetImport(), nPrefix, rLocalName );
}
<|endoftext|>


<commit_before>#include <RESTClient/base/url.hpp>
#include <RESTClient/base/logger.hpp>

#include <string>
#include <cassert>

using namespace std;
using namespace RESTClient;

int main(int , char**)
{
  URL test1("http://somewhere.com");
  using namespace std;
  cout << "Protocol: " << test1.parts().protocol << endl
       << "Hostname: " << test1.parts().hostname << endl;
  //assert(test1.protocol == "http");
  //assert(test1.hostname == "somewhere.com");
  return 0;
}
<commit_msg>Better url testing<commit_after>#include <RESTClient/base/url.hpp>
#include <RESTClient/base/logger.hpp>

#include <string>
#include <cassert>

using namespace std;
using namespace RESTClient;

int main(int , char**)
{
  URL test1("http://somewhere.com");
  using namespace std;
  cout << "Protocol: " << test1.parts().protocol << endl
       << "Hostname: " << test1.parts().hostname << endl;
  assert(test1.parts().protocol == "http");
  assert(test1.parts().hostname == "somewhere.com");
  return 0;
}
<|endoftext|>


<commit_before>
#include "nucleus/Streams/FileInputStream.h"

#include "nucleus/Logging.h"

#include "nucleus/MemoryDebug.h"

namespace nu {

namespace detail {

I64 setFileInputStreamPosition(FileInputStream::HandleType handle, I64 pos);

}  // namespace detail

FileInputStream::FileInputStream(const FilePath& path) : m_path(path) {
  openHandle();
}

FileInputStream::~FileInputStream() {
  closeHandle();
}

bool FileInputStream::openedOk() const {
  return m_status;
}

FileInputStream::SizeType FileInputStream::read(void* destBuffer, SizeType maxBytesToRead) {
  if (!openedOk()) {
    LOG(Warning) << "Trying to read from an invalid stream.";
    NOTREACHED() << "Do not read from an invalid stream.";
    return 0;
  }
  DCHECK(destBuffer != NULL && maxBytesToRead >= 0);

  if (m_needToSeek) {
    if (detail::setFileInputStreamPosition(m_handle, m_currentPosition) < 0)
      return 0;

    m_needToSeek = false;
  }

  USize num = readInternal(destBuffer, static_cast<USize>(maxBytesToRead));
  m_currentPosition += num;

  return static_cast<SizeType>(num);
}

bool FileInputStream::isExhausted() {
  return m_currentPosition >= getLength();
}

FileInputStream::SizeType FileInputStream::getPosition() {
  return m_currentPosition;
}

bool FileInputStream::setPosition(SizeType newPosition) {
  DCHECK(openedOk());

  if (newPosition != m_currentPosition) {
    newPosition = max(newPosition, static_cast<SizeType>(0));
    newPosition = min(newPosition, getLength());

    m_needToSeek |= (m_currentPosition != newPosition);
    m_currentPosition = newPosition;
  }

  return true;
}
}  // namespace nu
<commit_msg>Fix error message<commit_after>
#include "nucleus/Streams/FileInputStream.h"

#include "nucleus/Logging.h"

#include "nucleus/MemoryDebug.h"

namespace nu {

namespace detail {

I64 setFileInputStreamPosition(FileInputStream::HandleType handle, I64 pos);

}  // namespace detail

FileInputStream::FileInputStream(const FilePath& path) : m_path(path) {
  openHandle();
}

FileInputStream::~FileInputStream() {
  closeHandle();
}

bool FileInputStream::openedOk() const {
  return m_status;
}

FileInputStream::SizeType FileInputStream::read(void* destBuffer, SizeType maxBytesToRead) {
  if (!openedOk()) {
    LOG(Fatal) << "Trying to read from an invalid stream.";
    return 0;
  }
  DCHECK(destBuffer != NULL && maxBytesToRead >= 0);

  if (m_needToSeek) {
    if (detail::setFileInputStreamPosition(m_handle, m_currentPosition) < 0)
      return 0;

    m_needToSeek = false;
  }

  USize num = readInternal(destBuffer, static_cast<USize>(maxBytesToRead));
  m_currentPosition += num;

  return static_cast<SizeType>(num);
}

bool FileInputStream::isExhausted() {
  return m_currentPosition >= getLength();
}

FileInputStream::SizeType FileInputStream::getPosition() {
  return m_currentPosition;
}

bool FileInputStream::setPosition(SizeType newPosition) {
  DCHECK(openedOk());

  if (newPosition != m_currentPosition) {
    newPosition = max(newPosition, static_cast<SizeType>(0));
    newPosition = min(newPosition, getLength());

    m_needToSeek |= (m_currentPosition != newPosition);
    m_currentPosition = newPosition;
  }

  return true;
}
}  // namespace nu
<|endoftext|>


<commit_before>// Copyright (c) 2020-2021 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include <banman.h>
#include <fs.h>
#include <netaddress.h>
#include <test/fuzz/FuzzedDataProvider.h>
#include <test/fuzz/fuzz.h>
#include <test/fuzz/util.h>
#include <test/util/setup_common.h>
#include <util/readwritefile.h>
#include <util/system.h>

#include <cassert>
#include <cstdint>
#include <limits>
#include <string>
#include <vector>

namespace {
int64_t ConsumeBanTimeOffset(FuzzedDataProvider& fuzzed_data_provider) noexcept
{
    // Avoid signed integer overflow by capping to int32_t max:
    // banman.cpp:137:73: runtime error: signed integer overflow: 1591700817 + 9223372036854775807 cannot be represented in type 'long'
    return fuzzed_data_provider.ConsumeIntegralInRange<int64_t>(std::numeric_limits<int64_t>::min(), std::numeric_limits<int32_t>::max());
}
} // namespace

void initialize_banman()
{
    static const auto testing_setup = MakeNoLogFileContext<>();
}

static bool operator==(const CBanEntry& lhs, const CBanEntry& rhs)
{
    return lhs.nVersion == rhs.nVersion &&
           lhs.nCreateTime == rhs.nCreateTime &&
           lhs.nBanUntil == rhs.nBanUntil;
}

FUZZ_TARGET_INIT(banman, initialize_banman)
{
    // The complexity is O(N^2), where N is the input size, because each call
    // might call DumpBanlist (or other methods that are at least linear
    // complexity of the input size).
    int limit_max_ops{300};
    FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()};
    SetMockTime(ConsumeTime(fuzzed_data_provider));
    fs::path banlist_file = gArgs.GetDataDirNet() / "fuzzed_banlist";

    const bool start_with_corrupted_banlist{fuzzed_data_provider.ConsumeBool()};
    bool force_read_and_write_to_err{false};
    if (start_with_corrupted_banlist) {
        const std::string sfx{fuzzed_data_provider.ConsumeBool() ? ".dat" : ".json"};
        assert(WriteBinaryFile(banlist_file.string() + sfx,
                               fuzzed_data_provider.ConsumeRandomLengthString()));
    } else {
        force_read_and_write_to_err = fuzzed_data_provider.ConsumeBool();
        if (force_read_and_write_to_err) {
            banlist_file = fs::path{"path"} / "to" / "inaccessible" / "fuzzed_banlist";
        }
    }

    {
        BanMan ban_man{banlist_file, /* client_interface */ nullptr, /* default_ban_time */ ConsumeBanTimeOffset(fuzzed_data_provider)};
        while (--limit_max_ops >= 0 && fuzzed_data_provider.ConsumeBool()) {
            CallOneOf(
                fuzzed_data_provider,
                [&] {
                    ban_man.Ban(ConsumeNetAddr(fuzzed_data_provider),
                                ConsumeBanTimeOffset(fuzzed_data_provider), fuzzed_data_provider.ConsumeBool());
                },
                [&] {
                    ban_man.Ban(ConsumeSubNet(fuzzed_data_provider),
                                ConsumeBanTimeOffset(fuzzed_data_provider), fuzzed_data_provider.ConsumeBool());
                },
                [&] {
                    ban_man.ClearBanned();
                },
                [&] {
                    ban_man.IsBanned(ConsumeNetAddr(fuzzed_data_provider));
                },
                [&] {
                    ban_man.IsBanned(ConsumeSubNet(fuzzed_data_provider));
                },
                [&] {
                    ban_man.Unban(ConsumeNetAddr(fuzzed_data_provider));
                },
                [&] {
                    ban_man.Unban(ConsumeSubNet(fuzzed_data_provider));
                },
                [&] {
                    banmap_t banmap;
                    ban_man.GetBanned(banmap);
                },
                [&] {
                    ban_man.DumpBanlist();
                },
                [&] {
                    ban_man.Discourage(ConsumeNetAddr(fuzzed_data_provider));
                });
        }
        if (!force_read_and_write_to_err) {
            ban_man.DumpBanlist();
            SetMockTime(ConsumeTime(fuzzed_data_provider));
            banmap_t banmap;
            ban_man.GetBanned(banmap);
            BanMan ban_man_read{banlist_file, /* client_interface */ nullptr, /* default_ban_time */ 0};
            banmap_t banmap_read;
            ban_man_read.GetBanned(banmap_read);
            assert(banmap == banmap_read);
        }
    }
    fs::remove(banlist_file.string() + ".dat");
    fs::remove(banlist_file.string() + ".json");
}
<commit_msg>fuzz: Temporarily disable failing assert in banman fuzz test<commit_after>// Copyright (c) 2020-2021 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include <banman.h>
#include <fs.h>
#include <netaddress.h>
#include <test/fuzz/FuzzedDataProvider.h>
#include <test/fuzz/fuzz.h>
#include <test/fuzz/util.h>
#include <test/util/setup_common.h>
#include <util/readwritefile.h>
#include <util/system.h>

#include <cassert>
#include <cstdint>
#include <limits>
#include <string>
#include <vector>

namespace {
int64_t ConsumeBanTimeOffset(FuzzedDataProvider& fuzzed_data_provider) noexcept
{
    // Avoid signed integer overflow by capping to int32_t max:
    // banman.cpp:137:73: runtime error: signed integer overflow: 1591700817 + 9223372036854775807 cannot be represented in type 'long'
    return fuzzed_data_provider.ConsumeIntegralInRange<int64_t>(std::numeric_limits<int64_t>::min(), std::numeric_limits<int32_t>::max());
}
} // namespace

void initialize_banman()
{
    static const auto testing_setup = MakeNoLogFileContext<>();
}

static bool operator==(const CBanEntry& lhs, const CBanEntry& rhs)
{
    return lhs.nVersion == rhs.nVersion &&
           lhs.nCreateTime == rhs.nCreateTime &&
           lhs.nBanUntil == rhs.nBanUntil;
}

FUZZ_TARGET_INIT(banman, initialize_banman)
{
    // The complexity is O(N^2), where N is the input size, because each call
    // might call DumpBanlist (or other methods that are at least linear
    // complexity of the input size).
    int limit_max_ops{300};
    FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()};
    SetMockTime(ConsumeTime(fuzzed_data_provider));
    fs::path banlist_file = gArgs.GetDataDirNet() / "fuzzed_banlist";

    const bool start_with_corrupted_banlist{fuzzed_data_provider.ConsumeBool()};
    bool force_read_and_write_to_err{false};
    if (start_with_corrupted_banlist) {
        const std::string sfx{fuzzed_data_provider.ConsumeBool() ? ".dat" : ".json"};
        assert(WriteBinaryFile(banlist_file.string() + sfx,
                               fuzzed_data_provider.ConsumeRandomLengthString()));
    } else {
        force_read_and_write_to_err = fuzzed_data_provider.ConsumeBool();
        if (force_read_and_write_to_err) {
            banlist_file = fs::path{"path"} / "to" / "inaccessible" / "fuzzed_banlist";
        }
    }

    {
        BanMan ban_man{banlist_file, /* client_interface */ nullptr, /* default_ban_time */ ConsumeBanTimeOffset(fuzzed_data_provider)};
        while (--limit_max_ops >= 0 && fuzzed_data_provider.ConsumeBool()) {
            CallOneOf(
                fuzzed_data_provider,
                [&] {
                    ban_man.Ban(ConsumeNetAddr(fuzzed_data_provider),
                                ConsumeBanTimeOffset(fuzzed_data_provider), fuzzed_data_provider.ConsumeBool());
                },
                [&] {
                    ban_man.Ban(ConsumeSubNet(fuzzed_data_provider),
                                ConsumeBanTimeOffset(fuzzed_data_provider), fuzzed_data_provider.ConsumeBool());
                },
                [&] {
                    ban_man.ClearBanned();
                },
                [&] {
                    ban_man.IsBanned(ConsumeNetAddr(fuzzed_data_provider));
                },
                [&] {
                    ban_man.IsBanned(ConsumeSubNet(fuzzed_data_provider));
                },
                [&] {
                    ban_man.Unban(ConsumeNetAddr(fuzzed_data_provider));
                },
                [&] {
                    ban_man.Unban(ConsumeSubNet(fuzzed_data_provider));
                },
                [&] {
                    banmap_t banmap;
                    ban_man.GetBanned(banmap);
                },
                [&] {
                    ban_man.DumpBanlist();
                },
                [&] {
                    ban_man.Discourage(ConsumeNetAddr(fuzzed_data_provider));
                });
        }
        if (!force_read_and_write_to_err) {
            ban_man.DumpBanlist();
            SetMockTime(ConsumeTime(fuzzed_data_provider));
            banmap_t banmap;
            ban_man.GetBanned(banmap);
            BanMan ban_man_read{banlist_file, /* client_interface */ nullptr, /* default_ban_time */ 0};
            banmap_t banmap_read;
            ban_man_read.GetBanned(banmap_read);
            // Temporarily disabled to allow the remainder of the fuzz test to run while a fix is being worked on:
            // assert(banmap == banmap_read);
        }
    }
    fs::remove(banlist_file.string() + ".dat");
    fs::remove(banlist_file.string() + ".json");
}
<|endoftext|>


<commit_before>#include <cstdlib>
#include <vector>
#include <ctime>
#include <set>
#include <map>
#include "ceres/ceres.h"
#include "trans_solver.h"

using ceres::AutoDiffCostFunction;
using ceres::CostFunction;
using ceres::Problem;
using ceres::Solver;
using ceres::Solve;
using ceres::HuberLoss;

void solve_translations_problem(
        const int* edges,
        const double* poses,
        const double* weights,
        int num_edges,
        double loss_width,
        double* X,
        double function_tolerance,
        double parameter_tolerance,
        int max_iterations
    ) {
    // seed the random number generator
    std::srand( std::time( NULL ) );

    // reindex the edges to be a sequential set
    int *_edges = new int[2*num_edges];
    memcpy(_edges, edges, 2*num_edges*sizeof(int));
    std::vector<int> reindex_lookup;
    reindex_problem(_edges, num_edges, reindex_lookup);
    int num_nodes = reindex_lookup.size();

	// Make a random guess solution
    double *x = new double[3*num_nodes];
    for (int i=0; i<3*num_nodes; ++i)
        x[i] = (double)rand() / RAND_MAX;

	// add the parameter blocks (a 3-vector for each node)
    Problem problem;
    for (int i=0; i<num_nodes; ++i)
        problem.AddParameterBlock(x+3*i, 3);

	// set the residual function (chordal distance for each edge)
    for (int i=0; i<num_edges; ++i) {
        CostFunction* cost_function =
                new AutoDiffCostFunction<ChordFunctor, 3, 3, 3>(
                new ChordFunctor(poses+3*i,weights[i]));

        if (loss_width == 0.0) {
            // No robust loss function
            problem.AddResidualBlock(cost_function, NULL, x+3*_edges[2*i+0], x+3*_edges[2*i+1]);
        } else {
            problem.AddResidualBlock(cost_function, new ceres::HuberLoss(loss_width), x+3*_edges[2*i+0], x+3*_edges[2*i+1]);
        }
    }

	// solve
    Solver::Options options;
    options.num_threads = 16;
    options.num_linear_solver_threads = 16;
    //options.minimizer_progress_to_stdout = true;
    options.max_num_iterations = max_iterations;
    options.function_tolerance = function_tolerance;
    options.parameter_tolerance = parameter_tolerance;
    options.linear_solver_type = ceres::ITERATIVE_SCHUR;
    options.preconditioner_type = ceres::SCHUR_JACOBI;

    Solver::Summary summary;
    Solve(options, &problem, &summary);

    std::cout << summary.FullReport() << "\n";

    // undo the reindexing
    for (int i=0; i<num_nodes; ++i) {
        int j = reindex_lookup[i];
        X[3*j+0] = x[3*i+0];
        X[3*j+1] = x[3*i+1];
        X[3*j+2] = x[3*i+2];
    }

    delete[] _edges;
}

template <typename T>
bool ChordFunctor::operator()(
        const T* const x0,
        const T* const x1,
        T* residual) const {

    // compute ||x1 - x0||_2
    T norm = sqrt((x1[0]-x0[0])*(x1[0]-x0[0]) +
                  (x1[1]-x0[1])*(x1[1]-x0[1]) +
                  (x1[2]-x0[2])*(x1[2]-x0[2]));
    residual[0] = w_*((x1[0]-x0[0]) / norm - T(u_[0]));
    residual[1] = w_*((x1[1]-x0[1]) / norm - T(u_[1]));
    residual[2] = w_*((x1[2]-x0[2]) / norm - T(u_[2]));
    return true;
}

void
reindex_problem(int* edges, int num_edges, std::vector<int> &reindex_lookup) {

    reindex_lookup.clear();

    // get the unique set of notes
    std::set<int> nodes;
    for (int i=0; i<2*num_edges; ++i)
        nodes.insert(edges[i]);

    std::map<int, int> reindexing_key;

    // iterator through them and assign a new name to each vertex
    std::set<int>::const_iterator it;
    int n=0;
    for (it = nodes.begin(); it != nodes.end(); ++it) {
        reindex_lookup.push_back(*it);
        reindexing_key[*it] = n;
        ++n;
    }

    // now renumber the edges
    for (int i=0; i<2*num_edges; ++i)
        edges[i]  = reindexing_key[edges[i]];

}<commit_msg>Update trans_solver.cc<commit_after>#include <cstdlib>
#include <vector>
#include <ctime>
#include <set>
#include <map>
#include "ceres/ceres.h"
#include "trans_solver.h"

using ceres::AutoDiffCostFunction;
using ceres::CostFunction;
using ceres::Problem;
using ceres::Solver;
using ceres::Solve;
using ceres::HuberLoss;

void solve_translations_problem(
        const int* edges,
        const double* poses,
        const double* weights,
        int num_edges,
        double loss_width,
        double* X,
        double function_tolerance,
        double parameter_tolerance,
        int max_iterations
    ) {
    // seed the random number generator
    std::srand( std::time( NULL ) );

    // reindex the edges to be a sequential set
    int *_edges = new int[2*num_edges];
    memcpy(_edges, edges, 2*num_edges*sizeof(int));
    std::vector<int> reindex_lookup;
    reindex_problem(_edges, num_edges, reindex_lookup);
    int num_nodes = reindex_lookup.size();

	// Make a random guess solution
    double *x = new double[3*num_nodes];
    for (int i=0; i<3*num_nodes; ++i)
        x[i] = (double)rand() / RAND_MAX;

	// add the parameter blocks (a 3-vector for each node)
    Problem problem;
    for (int i=0; i<num_nodes; ++i)
        problem.AddParameterBlock(x+3*i, 3);

	// set the residual function (chordal distance for each edge)
    for (int i=0; i<num_edges; ++i) {
        CostFunction* cost_function =
                new AutoDiffCostFunction<ChordFunctor, 3, 3, 3>(
                new ChordFunctor(poses+3*i,weights[i]));

        if (loss_width == 0.0) {
            // No robust loss function
            problem.AddResidualBlock(cost_function, NULL, x+3*_edges[2*i+0], x+3*_edges[2*i+1]);
        } else {
            problem.AddResidualBlock(cost_function, new ceres::HuberLoss(loss_width), x+3*_edges[2*i+0], x+3*_edges[2*i+1]);
        }
    }

	// solve
    Solver::Options options;
    options.num_threads = 16;
    options.num_linear_solver_threads = 16;
    //options.minimizer_progress_to_stdout = true;
    options.max_num_iterations = max_iterations;
    options.function_tolerance = function_tolerance;
    options.parameter_tolerance = parameter_tolerance;
    options.linear_solver_type = ceres::ITERATIVE_SCHUR;
    options.preconditioner_type = ceres::SCHUR_JACOBI;

    Solver::Summary summary;
    Solve(options, &problem, &summary);

    std::cout << summary.FullReport() << "\n";

    // undo the reindexing
    for (int i=0; i<num_nodes; ++i) {
        int j = reindex_lookup[i];
        X[3*j+0] = x[3*i+0];
        X[3*j+1] = x[3*i+1];
        X[3*j+2] = x[3*i+2];
    }

    delete[] _edges;
}

template <typename T>
bool ChordFunctor::operator()(
        const T* const x0,
        const T* const x1,
        T* residual) const {

    // compute ||x1 - x0||_2
    T norm = sqrt((x1[0]-x0[0])*(x1[0]-x0[0]) +
                  (x1[1]-x0[1])*(x1[1]-x0[1]) +
                  (x1[2]-x0[2])*(x1[2]-x0[2]));
    residual[0] = w_*((x1[0]-x0[0]) / norm - T(u_[0]));
    residual[1] = w_*((x1[1]-x0[1]) / norm - T(u_[1]));
    residual[2] = w_*((x1[2]-x0[2]) / norm - T(u_[2]));
    return true;
}

void
reindex_problem(int* edges, int num_edges, std::vector<int> &reindex_lookup) {

    reindex_lookup.clear();

    // get the unique set of nodes
    std::set<int> nodes;
    for (int i=0; i<2*num_edges; ++i)
        nodes.insert(edges[i]);

    std::map<int, int> reindexing_key;

    // iterator through them and assign a new Id to each vertex
    std::set<int>::const_iterator it;
    int n=0;
    for (it = nodes.begin(); it != nodes.end(); ++it) {
        reindex_lookup.push_back(*it);
        reindexing_key[*it] = n;
        ++n;
    }

    // now renumber the edges
    for (int i=0; i<2*num_edges; ++i)
        edges[i]  = reindexing_key[edges[i]];

}
<|endoftext|>


<commit_before><?hh // strict
/**
 * @author Alex Phillips <exonintrendo@gmail.com>
 * Date: 2/5/15
 * Time: 4:45 PM
 */

namespace Titon\Context;

use Closure;
use ArrayAccess;
use Titon\Context\Definition\Definition;
use Titon\Context\Definition\CallableDefinition;
use Titon\Context\Definition\Factory;

class Depository implements ArrayAccess
{
    protected Factory $factory;

    protected Array $items = [];

    protected Array $singletons = [];

    public function __construct()
    {
        $this->factory = new Factory();
        $this->add('Titon\Context\Container', $this);
    }

    public function add(string $alias, $concrete = null, boolean $singleton = false): this
    {
        if (is_null($concrete)) {
            $concrete = $alias;
        }

        if (is_object($concrete) && !($concrete instanceof Closure)) {
            $this->singletons[$alias] = $concrete;
            return null;
        }

        // we need to build a definition
        $definition = $this->factory->create($alias, $concrete, $this);

        $this->items[$alias] = [
            'definition' => $definition,
            'singleton'  => $singleton,
        ];

        return $this;
    }

    public function singleton(string $alias, $concrete): this
    {
        $this->add($alias, $concrete, true);

        return $this;
    }

    public function make(string $alias, ...$arguments)
    {
        if (isset($this->singletons[$alias])) {
            return $this->singletons[$alias];
        }

        if (array_key_exists($alias, $this->items)) {
            return $this->resolveDefinition($alias, $arguments);
        }
    }

    protected function resolveDefinition(string $alias, ...$arguments)
    {
        $retval = $this->items[$alias]['definition'];

        if ($retval instanceof CallableDefinition || $retval instanceof ClassDefinition) {
            $retval = $retval->create($arguments);
        }

        // store as a singleton if needed
        if (isset($this->items[$alias]['singleton']) && $this->items[$alias]['singleton'] === true) {
            $this->singletons[$alias] = $retval;
        }

        return $retval;
    }

    public function offsetExists(mixed $key): bool
    {
        if (!is_null($this->singletons->get($key))) {
            return true;
        }
        if (!is_null($this->items->get($key))) {
            return true;
        }

        return false;
    }

    public function offsetGet($key): mixed
    {
        return $this->make($key);
    }

    public function offsetSet(mixed $key, $value): mixed
    {
        return $this->add($key, $value);
    }

    public function offsetUnset($key)
    {
        $this->singletons->remove($key);
        $this->items->remove($key);
    }
}<commit_msg>added lots of docs, changed factory functionality, corrected all issues with ArrayAccess, modified method names<commit_after><?hh // strict
/**
 * @author Alex Phillips <exonintrendo@gmail.com>
 * Date: 2/5/15
 * Time: 4:45 PM
 */

namespace Titon\Context;

use Closure;
use ArrayAccess;
use ReflectionClass;
use ReflectionException;
use Titon\Context\Definition\CallableDefinition;
use Titon\Context\Definition\ClassDefinition;
use Titon\Context\Definition\Definition;

class Depository implements ArrayAccess
{
    /**
     * Hash of registered item definitions keyed by its alias or class name
     *
     * @var array
     */
    protected array $items = [];

    /**
     * Hash of registered, and already constructed, singletons keyd by its
     * alias or class name
     *
     * @var array
     */
    protected array $singletons = [];

    /**
     * Instantiate a new container object
     */
    public function __construct()
    {
        $this->register('Titon\Context\Container', $this);
    }

    /**
     * Register a new class, callable, or object in the container
     *
     * @param string $alias     The alias (container key) for the registered item
     * @param mixed $concrete   The class name, closure, object to register in
     *                          the container, or null to use the alias as the
     *                          class name
     * @param bool  $singleton  Whether or not the container should register the
     *                          concrete as a singleton or not (only if concrete
     *                          is class name or a closure)
     *
     * @return object|$definition   Either the concrete (if an object is registered)
     *                              or the definition of the registered item
     */
    public function register(string $alias, ?mixed $concrete = null, boolean $singleton = false): mixed
    {
        if (is_null($concrete)) {
            $concrete = $alias;
        }

        if (is_object($concrete) && !($concrete instanceof Closure)) {
            $this->singletons[$alias] = $concrete;

            return $concrete;
        }

        // we need to build a definition
        $definition = Definition::factory($alias, $concrete, $this);

        $this->items[$alias] = [
            'definition' => $definition,
            'singleton'  => $singleton,
        ];

        return $definition;
    }

    public function alias($alias, $binding)
    {
        $this->aliases[$alias] = $binding;
    }

    /**
     * Register a new singleton in the container
     *
     * @param string $alias     The alias (container key) for the registered item
     * @param mixed $concrete   The class name, closure, object to register in
     *                          the container, or null to use the alias as the
     *                          class name
     *
     * @return object|$definition   Either the concrete (if an object is registered)
     *                              or the definition of the registered item
     */
    public function singleton(string $alias, ?mixed $concrete): mixed
    {
        return $this->register($alias, $concrete, true);
    }

    /**
     * Retrieve (and build if necessary) the registered item from the container
     *
     * @param string $alias         The alias that the item was registered as
     * @param mixed ...$arguments   Additional arguments to pass into the object
     *                              during
     *
     * @return mixed
     */
    public function make(string $alias, ...$arguments)
    {
        if (isset($this->singletons[$alias])) {
            return $this->singletons[$alias];
        }

        if (array_key_exists($alias, $this->items)) {
            $definition = $this->items[$alias]['definition'];
            $retval = $definition;

            if ($definition instanceof CallableDefinition || $definition instanceof ClassDefinition) {
                $retval = $definition->create(...$arguments);
            }

            if (isset($this->items[$alias]['singleton']) && $this->items[$alias]['singleton'] === true) {
                unset($this->items[$alias]);
                $this->singletons[$alias] = $retval;
            }

            return $retval;
        }

        $definition = $this->build($alias);
        $this->items[$alias]['definition'] = $definition;

        return $definition->create(...$arguments);
    }

    protected function build($class, ...$parameters)
    {
        if (!class_exists($class)) {
            throw new ReflectionException("Class $class does not exist.");
        }

        $reflector = new ReflectionClass($class);
        if (!$reflector->isInstantiable()) {
            $message = "Target [$class] is not instantiable.";
            throw new ReflectionException($message);
        }

        $definition = Definition::factory($class, $class, $this);
        $constructor = $reflector->getConstructor();

        if (is_null($constructor)) {
            return $definition;
        }

        foreach ($constructor->getParameters() as $param) {
            $dependency = $param->getClass();

            if (is_null($dependency)) {
                if ($param->isDefaultValueAvailable()) {
                    $definition->with($param->getDefaultValue());
                    continue;
                }

                throw new ReflectionException(
                    sprintf('Unable to resolve a non-class dependency of [%s] for [%s]', $param, $class)
                );
            }

            $definition->with($dependency->getName());
        }

        return $definition;
    }

    /**
     * Return whether or not an alias has been registered in the container
     *
     * @param string $alias Registered key or class name
     *
     * @return bool
     */
    public function isRegistered(string $alias): bool
    {
        if (isset($this->singletons[$alias])) {
            return true;
        }

        if (isset($this->items[$alias])) {
            return true;
        }

        return false;
    }

    /**
     * Return whether or not an alias has been registered as a singleton in
     * the container
     *
     * @param string $alias Registered key or class name
     *
     * @return bool
     */
    public function isSingleton(string $alias)
    {
        if (isset($this->singletons[$alias]) || (isset($this->items[$alias]) && $this->items[$alias]['singleton'] === true)) {
            return true;
        }

        return false;
    }

    /**
     * {@inheritdoc}
     */
    public function offsetExists(mixed $key): bool
    {
        return $this->isRegistered($key);
    }

    /**
     * {@inheritdoc}
     */
    public function offsetGet(mixed $key): mixed
    {
        return $this->make($key);
    }

    /**
     * {@inheritdoc}
     */
    public function offsetSet(mixed $key, $value): mixed
    {
        return $this->register($key, $value);
    }

    /**
     * {@inheritdoc}
     */
    public function offsetUnset(mixed $key)
    {
        unset($this->singletons[$key]);
        unset($this->items[$key]);
    }
}<|endoftext|>


<commit_before>// Copyright 2019, The max Contributors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "max/Testing/CoutResultPolicy.hpp"
#include <iostream>

namespace max
{
namespace Testing
{

	void CoutResultPolicy::OnTestSuiteRun( std::string const & TestSuiteName )
	{
		std::cout << "Running test suite " << TestSuiteName << std::endl;
	}

	void CoutResultPolicy::OnTestSuiteSetup( std::string const & TestSuiteName )
	{
		std::cout << "Setting up test suite " << TestSuiteName << "." << std::endl;
	}

	void CoutResultPolicy::OnTestSuiteSetupComplete( std::string const & TestSuiteName )
	{
		std::cout << "Done setting up test suites " << TestSuiteName << "." << std::endl;
	}

	void CoutResultPolicy::OnTestRun( std::string const & TestName )
	{
		std::cout << "Running test " << TestName << "." << std::endl;
	}

	void CoutResultPolicy::OnTestPassed( std::string const & TestName )
	{
		std::cout << "Passed test " << TestName << "." << std::endl;
	}

	void CoutResultPolicy::OnTestFailed( std::string const & TestName )
	{
		std::cout << "Failed test " << TestName << "." << std::endl;
	}

	void CoutResultPolicy::OnAssert( std::string const & FileName,
	                                 int LineNumber,
	                                 char const * const ExpressionString )
	{
		std::cout << L"Assert failed: " << ExpressionString << "\n";
		std::cout << L"\tin file " << FileName << "\n";
		std::cout << L"\ton line " << LineNumber << std::endl;
	}

	void CoutResultPolicy::OnTestSuiteTearDown( std::string const & TestSuiteName )
	{
		std::cout << "Tearing down test suite " << TestSuiteName << "." << std::endl;
	}

	void CoutResultPolicy::OnTestSuiteDone( char const * const TestSuiteName,
	                                        int TestsPassed,
	                                        int TestsFailed )
	{
		std::cout << "Done tearing down test suite " << TestSuiteName << "." << "\n";
		std::cout << "Tests passed: " << TestsPassed << "\n";
		std::cout << "Tests failed: " << TestsFailed << std::endl;
	}

} // namespace Testing
} // namespace max
<commit_msg>Fix build error with CoutResultPolicy.cpp<commit_after>// Copyright 2019, The max Contributors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "max/Testing/CoutResultPolicy.hpp"
#include <iostream>

namespace max
{
namespace Testing
{

	void CoutResultPolicy::OnTestSuiteRun( std::string const & TestSuiteName )
	{
		std::cout << "Running test suite " << TestSuiteName << std::endl;
	}

	void CoutResultPolicy::OnTestSuiteSetup( std::string const & TestSuiteName )
	{
		std::cout << "Setting up test suite " << TestSuiteName << "." << std::endl;
	}

	void CoutResultPolicy::OnTestSuiteSetupComplete( std::string const & TestSuiteName )
	{
		std::cout << "Done setting up test suites " << TestSuiteName << "." << std::endl;
	}

	void CoutResultPolicy::OnTestRun( std::string const & TestName )
	{
		std::cout << "Running test " << TestName << "." << std::endl;
	}

	void CoutResultPolicy::OnTestPassed( std::string const & TestName )
	{
		std::cout << "Passed test " << TestName << "." << std::endl;
	}

	void CoutResultPolicy::OnTestFailed( std::string const & TestName )
	{
		std::cout << "Failed test " << TestName << "." << std::endl;
	}

	void CoutResultPolicy::OnAssert( std::string const & FileName,
	                                 int LineNumber,
	                                 char const * const ExpressionString )
	{
		std::cout << L"Assert failed: " << ExpressionString << "\n";
		std::cout << L"\tin file " << FileName << "\n";
		std::cout << L"\ton line " << LineNumber << std::endl;
	}

	void CoutResultPolicy::OnTestSuiteTearDown( std::string const & TestSuiteName )
	{
		std::cout << "Tearing down test suite " << TestSuiteName << "." << std::endl;
	}

	void CoutResultPolicy::OnTestSuiteDone( std::string const & TestSuiteName,
	                                        int TestsPassed,
	                                        int TestsFailed )
	{
		std::cout << "Done tearing down test suite " << TestSuiteName << "." << "\n";
		std::cout << "Tests passed: " << TestsPassed << "\n";
		std::cout << "Tests failed: " << TestsFailed << std::endl;
	}

} // namespace Testing
} // namespace max
<|endoftext|>


<commit_before>#include "tinfra/platform.h"
#include "tinfra/fmt.h"

#include "tinfra/win32.h"
#include <stdexcept>

#include <windows.h>

namespace tinfra { namespace win32 {

std::string get_error_string(unsigned int error_code)
{
    LPVOID lpMsgBuf;
    if( ::FormatMessage(
	FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
	NULL,
	error_code,
	MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
	(LPTSTR) &lpMsgBuf,
	0,
	NULL
	) < 0 || lpMsgBuf == NULL) {

	return fmt("unknown error: %i") % error_code;
    }
    std::string result((char*)lpMsgBuf);
    ::LocalFree(lpMsgBuf);
    strip_inplace(result);
    return result;
}

template <typename E>
static void throw_system_error2(unsigned int error, const std::string& message)
{
    std::string error_str = get_error_string(error);
    std::string full_message = tinfra::fmt("%s: %s") % message % error_str;
    throw E(full_message);
}

void throw_system_error(unsigned int error, std::string const& message)
{
    switch( error ) {
    case ERROR_FILE_NOT_FOUND:
    case ERROR_PATH_NOT_FOUND:

    case WSAHOST_NOT_FOUND:
    case WSANO_DATA:
    case WSAECONNREFUSED:
        throw_system_error2<std::logic_error>(error, message);

    case WSAEFAULT:
    case ERROR_INVALID_HANDLE:
        throw_system_error2<std::invalid_argument>(error, message);

    default:
        throw_system_error2<std::runtime_error>(error, message);
    }
}
void throw_system_error(std::string const& message)
{
    unsigned int error = ::GetLastError();
    throw_system_error(error, message);
}

void get_available_drives(std::vector<std::string>& result)
{
    TCHAR drives[30];

    if( ::GetLogicalDriveStrings(sizeof(drives), drives) == 0 ) {
        throw_system_error("GetLogicalDriveStrings failed");
    }
    //printf("DDD %s\n", drives);
    TCHAR* p = drives;
    while( *p ) {
        result.push_back(fmt("%c:/") % *p);
        p++;
    }
}

} } // end namespace tinfra::win32
<commit_msg>win32 disk enumeration works<commit_after>#include "tinfra/platform.h"
#include "tinfra/fmt.h"

#include "tinfra/win32.h"
#include <stdexcept>

#include <windows.h>

namespace tinfra { namespace win32 {

std::string get_error_string(unsigned int error_code)
{
    LPVOID lpMsgBuf;
    if( ::FormatMessage(
	FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
	NULL,
	error_code,
	MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
	(LPTSTR) &lpMsgBuf,
	0,
	NULL
	) < 0 || lpMsgBuf == NULL) {

	return fmt("unknown error: %i") % error_code;
    }
    std::string result((char*)lpMsgBuf);
    ::LocalFree(lpMsgBuf);
    strip_inplace(result);
    return result;
}

template <typename E>
static void throw_system_error2(unsigned int error, const std::string& message)
{
    std::string error_str = get_error_string(error);
    std::string full_message = tinfra::fmt("%s: %s") % message % error_str;
    throw E(full_message);
}

void throw_system_error(unsigned int error, std::string const& message)
{
    switch( error ) {
    case ERROR_FILE_NOT_FOUND:
    case ERROR_PATH_NOT_FOUND:

    case WSAHOST_NOT_FOUND:
    case WSANO_DATA:
    case WSAECONNREFUSED:
        throw_system_error2<std::logic_error>(error, message);

    case WSAEFAULT:
    case ERROR_INVALID_HANDLE:
        throw_system_error2<std::invalid_argument>(error, message);

    default:
        throw_system_error2<std::runtime_error>(error, message);
    }
}
void throw_system_error(std::string const& message)
{
    unsigned int error = ::GetLastError();
    throw_system_error(error, message);
}

void get_available_drives(std::vector<std::string>& result)
{
    TCHAR drives[1024];
    DWORD len;
    len = ::GetLogicalDriveStrings(sizeof(drives), drives);

    if( len == 0 || len > sizeof(drives)) {
        throw_system_error("GetLogicalDriveStrings failed");
    }

    TCHAR* p = drives;
    while( *p && len > 0 ) {
        int l2 = strlen(p);
        result.push_back(fmt("%s:/") % p[0]);
        p += l2+1;
        len -= l2;
    }
}

} } // end namespace tinfra::win32
<|endoftext|>


<commit_before>/*
 * Copyright © 2013 Jørgen Lind

 * Permission to use, copy, modify, distribute, and sell this software and its
 * documentation for any purpose is hereby granted without fee, provided that
 * the above copyright notice appear in all copies and that both that copyright
 * notice and this permission notice appear in supporting documentation, and
 * that the name of the copyright holders not be used in advertising or
 * publicity pertaining to distribution of the software without specific,
 * written prior permission.  The copyright holders make no representations
 * about the suitability of this software for any purpose.  It is provided "as
 * is" without express or implied warranty.

 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
 * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
 * OF THIS SOFTWARE.
*/
#include "tree_writer.h"

#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>

TreeWriter::TreeWriter(const std::string &file)
    : m_error(false)
    , m_close_file(true)
{
    mode_t mode = S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH;
    m_file = open(file.c_str(), O_WRONLY|O_CREAT|O_TRUNC|O_CLOEXEC, mode);
    if (m_file < 0) {
        m_error = true;
        fprintf(stderr, "Failed to open file %s : %s\n", file.c_str(), strerror(errno));
        return;
    }
}
TreeWriter::TreeWriter(int file, bool closeFileOnDestruct)
    : m_file(file)
    , m_error(false)
    , m_close_file(closeFileOnDestruct)
{
}

TreeWriter::~TreeWriter()
{
    if (m_close_file)
        close(m_file);
}

bool TreeWriter::error() const { return m_error; }

void TreeWriter::write(JT::ObjectNode *root)
{
    std::function<void(JT::Serializer *)> callback =
        std::bind(&TreeWriter::requestFlush, this, std::placeholders::_1);

    JT::TreeSerializer serializer;
    serializer.registerTokenTransformer(m_transformer);
    JT::SerializerOptions options = serializer.options();
    options.setPretty(true);
    serializer.setOptions(options);
    serializer.addRequestBufferCallback(callback);
    m_error = !serializer.serialize(root);

    if (m_error)
        return;

    if (serializer.buffers().size()) {
        JT::SerializerBuffer serializer_buffer = serializer.buffers().front();
        writeBufferToFile(serializer_buffer);
    }

    if (m_error)
        return;

    if (::write(m_file,"\n",1) != 1) {
        fprintf(stderr, "Failed to write newline to file\n");
        m_error = true;
    }
}

void TreeWriter::setSerializeTransformer(std::function<const JT::Token&(const JT::Token &)> transformer)
{
    m_transformer = transformer;
}

void TreeWriter::writeBufferToFile(const JT::SerializerBuffer &buffer)
{
    if (m_error)
        return;
    size_t written = ::write(m_file,buffer.buffer,buffer.used);
    if (written < buffer.used) {
        fprintf(stderr, "Error while writing to outbuffer: %s\n", strerror(errno));
        m_error = true;
    }
}

void TreeWriter::requestFlush(JT::Serializer *serializer)
{
    if (m_error)
        return;
    if (serializer->buffers().size()) {
        JT::SerializerBuffer serializer_buffer = serializer->buffers().front();
        serializer->clearBuffers();

        writeBufferToFile(serializer_buffer);
    }
    serializer->appendBuffer(m_buffer,sizeof m_buffer);
}
<commit_msg>Add some error messages to tree_writer<commit_after>/*
 * Copyright © 2013 Jørgen Lind

 * Permission to use, copy, modify, distribute, and sell this software and its
 * documentation for any purpose is hereby granted without fee, provided that
 * the above copyright notice appear in all copies and that both that copyright
 * notice and this permission notice appear in supporting documentation, and
 * that the name of the copyright holders not be used in advertising or
 * publicity pertaining to distribution of the software without specific,
 * written prior permission.  The copyright holders make no representations
 * about the suitability of this software for any purpose.  It is provided "as
 * is" without express or implied warranty.

 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
 * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
 * OF THIS SOFTWARE.
*/
#include "tree_writer.h"

#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>

TreeWriter::TreeWriter(const std::string &file)
    : m_error(false)
    , m_close_file(true)
{
    mode_t mode = S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH;
    m_file = open(file.c_str(), O_WRONLY|O_CREAT|O_TRUNC|O_CLOEXEC, mode);
    if (m_file < 0) {
        m_error = true;
        fprintf(stderr, "Failed to open file %s : %s\n", file.c_str(), strerror(errno));
        return;
    }
}
TreeWriter::TreeWriter(int file, bool closeFileOnDestruct)
    : m_file(file)
    , m_error(false)
    , m_close_file(closeFileOnDestruct)
{
}

TreeWriter::~TreeWriter()
{
    if (m_close_file)
        close(m_file);
}

bool TreeWriter::error() const { return m_error; }

void TreeWriter::write(JT::ObjectNode *root)
{
    if (m_error) {
        fprintf(stderr, "Error when writing node to file\n");
        return;
    }

    std::function<void(JT::Serializer *)> callback =
        std::bind(&TreeWriter::requestFlush, this, std::placeholders::_1);

    JT::TreeSerializer serializer;
    serializer.registerTokenTransformer(m_transformer);
    JT::SerializerOptions options = serializer.options();
    options.setPretty(true);
    serializer.setOptions(options);
    serializer.addRequestBufferCallback(callback);
    m_error = !serializer.serialize(root);

    if (m_error) {
        fprintf(stderr, "Failed to serialize token\n");
        return;
    }

    if (serializer.buffers().size()) {
        JT::SerializerBuffer serializer_buffer = serializer.buffers().front();
        writeBufferToFile(serializer_buffer);
    }

    if (m_error) {
        fprintf(stderr, "Failed to serialize token\n");
        return;
    }

    if (::write(m_file,"\n",1) != 1) {
        fprintf(stderr, "Failed to write newline to file\n");
        m_error = true;
    }
}

void TreeWriter::setSerializeTransformer(std::function<const JT::Token&(const JT::Token &)> transformer)
{
    m_transformer = transformer;
}

void TreeWriter::writeBufferToFile(const JT::SerializerBuffer &buffer)
{
    if (m_error)
        return;
    size_t written = ::write(m_file,buffer.buffer,buffer.used);
    if (written < buffer.used) {
        fprintf(stderr, "Error while writing to outbuffer: %s\n", strerror(errno));
        m_error = true;
    }
}

void TreeWriter::requestFlush(JT::Serializer *serializer)
{
    if (m_error)
        return;
    if (serializer->buffers().size()) {
        JT::SerializerBuffer serializer_buffer = serializer->buffers().front();
        serializer->clearBuffers();

        writeBufferToFile(serializer_buffer);
    }
    serializer->appendBuffer(m_buffer,sizeof m_buffer);
}
<|endoftext|>


<commit_before>/*
 * This file is part of the µOS++ distribution.
 *   (https://github.com/micro-os-plus)
 * Copyright (c) 2016 Liviu Ionescu.
 *
 * µOS++ 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, version 3.
 *
 * µOS++ 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 program. If not, see <http://www.gnu.org/licenses/>.
 */

#include <cmsis-plus/rtos/os.h>
#include <cmsis-plus/diag/trace.h>

#include <cmsis-plus/rtos/port/os-decls.h>
#include <cmsis-plus/rtos/port/os-inlines.h>

// ----------------------------------------------------------------------------

#include <cassert>
#include <cerrno>
#include <cstdlib>

// ----------------------------------------------------------------------------

namespace os
{
  /**
   * @details
   * The `os::rtos` namespace groups all RTOS specific declarations,
   * either directly or via nested namespaces.
   */
  namespace rtos
  {

#pragma GCC diagnostic push
// TODO: remove it when fully implemented
#pragma GCC diagnostic ignored "-Wunused-parameter"

    /**
     * @details
     * The `os::rtos::scheduler` namespace groups scheduler types
     * and functions.
     */
    namespace scheduler
    {
      /**
       * @details
       * No further changes allowed, the scheduler cannot be stopped,
       * in can be only locked.
       */
      status_t is_started_ = false;

      /**
       * @details
       * Modified by `lock()` and restored to previous value
       * by `unlock()`.
       */
      status_t is_locked_ = false;

      /**
       * @details
       * Create all RTOS internal objects and be ready to run.
       *
       * @warning Cannot be invoked from Interrupt Service Routines.
       */
      result_t
      initialize (void)
      {
        os_assert_err(!scheduler::in_handler_mode (), EPERM);

        trace::printf ("%s() \n", __func__);

        return port::scheduler::initialize ();
      }

      /**
       *
       * @note Can be invoked from Interrupt Service Routines (obviously).
       */
      bool
      in_handler_mode (void)
      {
        return port::scheduler::in_handler_mode ();
      }

      /**
       * @details
       * The scheduler cannot be stopped, it will run forever, but
       * thread switching can be locked/unlocked.
       *
       * @warning Cannot be invoked from Interrupt Service Routines.
       */
      result_t
      start (void)
      {
        os_assert_err(!scheduler::in_handler_mode (), EPERM);

        trace::printf ("%s() \n", __func__);

        is_started_ = true;
        is_locked_ = false;

        return port::scheduler::start ();
      }

      /**
       * @details
       * Lock the scheduler (prevent it for doing thread switches) and
       * return the previous status, to be restored by `unlock()`.
       *
       * @warning Cannot be invoked from Interrupt Service Routines.
       */
      status_t
      lock (void)
      {
        os_assert_throw(!scheduler::in_handler_mode (), EPERM);

        port::scheduler::lock ();

        status_t tmp = is_locked_;
        is_locked_ = true;

        return tmp;
      }

      /**
       * @details
       * Actually restore the scheduler status based on the given
       * parameter, usually returned by a `lock()`. This allows for
       * embedded critical sections to preserve the locked status
       * until the outer one completes and invokes `unlock()`.
       *
       * @warning Cannot be invoked from Interrupt Service Routines.
       */
      void
      unlock (status_t status)
      {
        os_assert_throw(!scheduler::in_handler_mode (), EPERM);

        port::scheduler::unlock (status);

        is_locked_ = status;
      }

    /**
     * @class Critical_section
     * @details
     * Use this class to define a critical section
     * protected to scheduler switches. The beginning of the
     * critical section is exactly the place where this class is
     * instantiated (the constructor will lock
     * the scheduler). The end of the critical
     * section is the end of the surrounding block (the destructor will
     * unlock the scheduler).
     *
     * @note Can be nested as many times as required without problems,
     * only the outer call will unlock the scheduler.
     *
     * @par Example
     *
     * @code{.cpp}
     * void
     * func(void)
     * {
     *    // Do something
     *
     *    {
     *      scheduler::Critical_section cs;  // Critical section begins here.
     *
     *      // Inside the critical section.
     *      // No scheduler switches will happen here.
     *
     *    } // Critical section ends here.
     *
     *    // Do something else.
     * }
     * @endcode
     */

    /**
     * @var const status_t Critical_section::status_
     * @details
     * The variable is constant, after being set by the constructor no
     * further changes are possible.
     *
     * The variable type usually is a `bool`, but a counter is also
     * possible if the scheduler uses a recursive lock.
     */

    /**
     * @class Lock
     * @details
     * Locker meeting the standard `Lockable` requirements (30.2.5.3).
     */

    /**
     * @var status_t Lock::status_
     * @details
     * The variable type usually is a `bool`, but a counter is also
     * possible if the scheduler uses a recursive lock.
     */

    } /* namespace scheduler */

#if 0
    namespace scheduler
      {

        void
        __register_thread (Thread* thread)
          {
            // TODO
#if defined(TESTING)
            thread->__run_function ();
#endif
          }

        void
        __unregister_thread (Thread* thread)
          {
            return;
          }

      } /* namespace scheduler */
#endif

    /**
     * @details
     * The os::rtos::interrupts namespace groups interrupts related
     *  types and enumerations.
     */
    namespace interrupts
    {
      /**
       * @class Critical_section
       * @details
       * Use this class to define a critical section
       * protected to interrupts service routines. The begining of the
       * critical section is exactly the place where this class is
       * instantiated (the constructor will disable interrupts below
       * the scheduler priority). The end of the critical
       * section is the end of the surrounding block (the destructor will
       * enable the interrupts).
       *
       * @note Can be nested as many times as required without problems,
       * only the outer call will re-enable the interrupts.
       *
       * @par Example
       *
       * @code{.cpp}
       * void
       * func(void)
       * {
       *    // Do something
       *
       *    {
       *      interrupts::Critical_section cs;  // Critical section begins here.
       *
       *      // Inside the critical section.
       *      // No scheduler switches will happen here.
       *
       *    } // Critical section ends here.
       *
       *    // Do something else.
       * }
       * @endcode
       */

      /**
       * @var const status_t Critical_section::status_
       * @details
       * The variable is constant, after being set by the constructor no
       * further changes are possible.
       *
       * The variable type usually is an unsigned integer where
       * the status register is saved.
       */

      // Enter an IRQ critical section
      status_t
      Critical_section::enter (void)
      {
        return port::interrupts::Critical_section::enter ();
      }

      // Exit an IRQ critical section
      void
      Critical_section::exit (status_t status)
      {
        return port::interrupts::Critical_section::exit (status);
      }

    /**
     * @class Lock
     * @details
     * Locker meeting the standard `Lockable` requirements (30.2.5.3).
     */

    /**
     * @var status_t Lock::status_
     * @details
     * The variable type usually is an unsigned integer where
     * the status register is saved.
     */

    } /* namespace interrupts */

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

    /**
     * @details
     * The os::rtos::flags namespace groups event types and enumerations.
     */
    namespace flags
    {

    } /* namespace flags */

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

    /**
     * @class Named_object
     * @details
     * This class serves as a base class for all objects that have a
     * name (most of the RTOS classes do have a name).
     */

    /**
     * @var const char* const Named_object::name_
     * @details
     * To save space, the null terminated string passed to the
     * constructor is not copied locally. Instead, the pointer to
     * the string is copied, so the
     * caller must ensure that the pointer life cycle
     * is at least as long as the object life cycle. A constant
     * string (stored in flash) is preferred.
     */

#if 1
    /**
     * @details
     * To save space, instead of copying the null terminated string
     * locally, the pointer to the string
     * is copied, so the caller must ensure that the pointer
     * life cycle is at least as long as the object life cycle.
     * A constant string (stored in flash) is preferred.
     */
    Named_object::Named_object (const char* name) :
        name_ (name != nullptr ? name : "-")
    {
      ;
    }
#endif

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

#if !defined(__DOXYGEN__)
    namespace port
    {

      Tasks_list::Tasks_list ()
      {
        for (std::size_t i = 0; i < sizeof(array_) / sizeof(array_[0]); ++i)
          {
            array_[i] = nullptr;
          }
        count_ = 0;
      }

      Tasks_list::~Tasks_list ()
      {
        ;
      }

      void
      Tasks_list::add (rtos::Thread* thread)
      {
        assert (thread != nullptr);
        assert (count_ < (sizeof(array_) / sizeof(array_[0]) + 1));

        array_[count_++] = thread;
      }

      void
      Tasks_list::remove (std::size_t pos)
      {
        for (std::size_t i = pos; i < (sizeof(array_) / sizeof(array_[0]) - 2);
            ++i)
          {
            array_[i] = array_[i + 1];
          }
        count_--;
        array_[count_] = nullptr;
      }

      void
      Tasks_list::remove (rtos::Thread* thread)
      {

        for (std::size_t i = 0; i < sizeof(array_) / sizeof(array_[0]); ++i)
          {
            if (array_[i] == thread)
              {
                remove (i);
                return;
              }
          }
      }

#if 1
      rtos::Thread*
      Tasks_list::_top_prio_task (void)
      {
        rtos::Thread* thread = nullptr;
        thread::priority_t prio = thread::priority::none;
        std::size_t pos = 0;

        for (std::size_t i = 0; i < sizeof(array_) / sizeof(array_[0]); ++i)
          {
            if (array_[i]->sched_prio () > prio)
              {
                prio = array_[i]->sched_prio ();
                thread = array_[i];
                pos = i;
              }
          }

        remove (pos);

        return thread;
      }
#endif

      void
      Tasks_list::wakeup_one ()
      {
        _top_prio_task ()->wakeup ();
      }

      void
      Tasks_list::wakeup_all ()
      {
        for (std::size_t i = 0; i < sizeof(array_) / sizeof(array_[0]); ++i)
          {
            array_[i]->wakeup ();
          }
        count_ = 0;
      }

    } /* namespace port */
#endif

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

#pragma GCC diagnostic pop

  } /* namespace rtos */
} /* namespace os */
<commit_msg>os-core.cpp: fix nullptr<commit_after>/*
 * This file is part of the µOS++ distribution.
 *   (https://github.com/micro-os-plus)
 * Copyright (c) 2016 Liviu Ionescu.
 *
 * µOS++ 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, version 3.
 *
 * µOS++ 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 program. If not, see <http://www.gnu.org/licenses/>.
 */

#include <cmsis-plus/rtos/os.h>
#include <cmsis-plus/diag/trace.h>

#include <cmsis-plus/rtos/port/os-decls.h>
#include <cmsis-plus/rtos/port/os-inlines.h>

// ----------------------------------------------------------------------------

#include <cassert>
#include <cerrno>
#include <cstdlib>

// ----------------------------------------------------------------------------

namespace os
{
  /**
   * @details
   * The `os::rtos` namespace groups all RTOS specific declarations,
   * either directly or via nested namespaces.
   */
  namespace rtos
  {

#pragma GCC diagnostic push
// TODO: remove it when fully implemented
#pragma GCC diagnostic ignored "-Wunused-parameter"

    /**
     * @details
     * The `os::rtos::scheduler` namespace groups scheduler types
     * and functions.
     */
    namespace scheduler
    {
      /**
       * @details
       * No further changes allowed, the scheduler cannot be stopped,
       * in can be only locked.
       */
      status_t is_started_ = false;

      /**
       * @details
       * Modified by `lock()` and restored to previous value
       * by `unlock()`.
       */
      status_t is_locked_ = false;

      /**
       * @details
       * Create all RTOS internal objects and be ready to run.
       *
       * @warning Cannot be invoked from Interrupt Service Routines.
       */
      result_t
      initialize (void)
      {
        os_assert_err(!scheduler::in_handler_mode (), EPERM);

        trace::printf ("%s() \n", __func__);

        return port::scheduler::initialize ();
      }

      /**
       *
       * @note Can be invoked from Interrupt Service Routines (obviously).
       */
      bool
      in_handler_mode (void)
      {
        return port::scheduler::in_handler_mode ();
      }

      /**
       * @details
       * The scheduler cannot be stopped, it will run forever, but
       * thread switching can be locked/unlocked.
       *
       * @warning Cannot be invoked from Interrupt Service Routines.
       */
      result_t
      start (void)
      {
        os_assert_err(!scheduler::in_handler_mode (), EPERM);

        trace::printf ("%s() \n", __func__);

        is_started_ = true;
        is_locked_ = false;

        return port::scheduler::start ();
      }

      /**
       * @details
       * Lock the scheduler (prevent it for doing thread switches) and
       * return the previous status, to be restored by `unlock()`.
       *
       * @warning Cannot be invoked from Interrupt Service Routines.
       */
      status_t
      lock (void)
      {
        os_assert_throw(!scheduler::in_handler_mode (), EPERM);

        port::scheduler::lock ();

        status_t tmp = is_locked_;
        is_locked_ = true;

        return tmp;
      }

      /**
       * @details
       * Actually restore the scheduler status based on the given
       * parameter, usually returned by a `lock()`. This allows for
       * embedded critical sections to preserve the locked status
       * until the outer one completes and invokes `unlock()`.
       *
       * @warning Cannot be invoked from Interrupt Service Routines.
       */
      void
      unlock (status_t status)
      {
        os_assert_throw(!scheduler::in_handler_mode (), EPERM);

        port::scheduler::unlock (status);

        is_locked_ = status;
      }

    /**
     * @class Critical_section
     * @details
     * Use this class to define a critical section
     * protected to scheduler switches. The beginning of the
     * critical section is exactly the place where this class is
     * instantiated (the constructor will lock
     * the scheduler). The end of the critical
     * section is the end of the surrounding block (the destructor will
     * unlock the scheduler).
     *
     * @note Can be nested as many times as required without problems,
     * only the outer call will unlock the scheduler.
     *
     * @par Example
     *
     * @code{.cpp}
     * void
     * func(void)
     * {
     *    // Do something
     *
     *    {
     *      scheduler::Critical_section cs;  // Critical section begins here.
     *
     *      // Inside the critical section.
     *      // No scheduler switches will happen here.
     *
     *    } // Critical section ends here.
     *
     *    // Do something else.
     * }
     * @endcode
     */

    /**
     * @var const status_t Critical_section::status_
     * @details
     * The variable is constant, after being set by the constructor no
     * further changes are possible.
     *
     * The variable type usually is a `bool`, but a counter is also
     * possible if the scheduler uses a recursive lock.
     */

    /**
     * @class Lock
     * @details
     * Locker meeting the standard `Lockable` requirements (30.2.5.3).
     */

    /**
     * @var status_t Lock::status_
     * @details
     * The variable type usually is a `bool`, but a counter is also
     * possible if the scheduler uses a recursive lock.
     */

    } /* namespace scheduler */

#if 0
    namespace scheduler
      {

        void
        __register_thread (Thread* thread)
          {
            // TODO
#if defined(TESTING)
            thread->__run_function ();
#endif
          }

        void
        __unregister_thread (Thread* thread)
          {
            return;
          }

      } /* namespace scheduler */
#endif

    /**
     * @details
     * The os::rtos::interrupts namespace groups interrupts related
     *  types and enumerations.
     */
    namespace interrupts
    {
      /**
       * @class Critical_section
       * @details
       * Use this class to define a critical section
       * protected to interrupts service routines. The begining of the
       * critical section is exactly the place where this class is
       * instantiated (the constructor will disable interrupts below
       * the scheduler priority). The end of the critical
       * section is the end of the surrounding block (the destructor will
       * enable the interrupts).
       *
       * @note Can be nested as many times as required without problems,
       * only the outer call will re-enable the interrupts.
       *
       * @par Example
       *
       * @code{.cpp}
       * void
       * func(void)
       * {
       *    // Do something
       *
       *    {
       *      interrupts::Critical_section cs;  // Critical section begins here.
       *
       *      // Inside the critical section.
       *      // No scheduler switches will happen here.
       *
       *    } // Critical section ends here.
       *
       *    // Do something else.
       * }
       * @endcode
       */

      /**
       * @var const status_t Critical_section::status_
       * @details
       * The variable is constant, after being set by the constructor no
       * further changes are possible.
       *
       * The variable type usually is an unsigned integer where
       * the status register is saved.
       */

      // Enter an IRQ critical section
      status_t
      Critical_section::enter (void)
      {
        return port::interrupts::Critical_section::enter ();
      }

      // Exit an IRQ critical section
      void
      Critical_section::exit (status_t status)
      {
        return port::interrupts::Critical_section::exit (status);
      }

    /**
     * @class Lock
     * @details
     * Locker meeting the standard `Lockable` requirements (30.2.5.3).
     */

    /**
     * @var status_t Lock::status_
     * @details
     * The variable type usually is an unsigned integer where
     * the status register is saved.
     */

    } /* namespace interrupts */

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

    /**
     * @details
     * The os::rtos::flags namespace groups event types and enumerations.
     */
    namespace flags
    {

    } /* namespace flags */

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

    /**
     * @class Named_object
     * @details
     * This class serves as a base class for all objects that have a
     * name (most of the RTOS classes do have a name).
     */

    /**
     * @var const char* const Named_object::name_
     * @details
     * To save space, the null terminated string passed to the
     * constructor is not copied locally. Instead, the pointer to
     * the string is copied, so the
     * caller must ensure that the pointer life cycle
     * is at least as long as the object life cycle. A constant
     * string (stored in flash) is preferred.
     */

#if 1
    /**
     * @details
     * To save space, instead of copying the null terminated string
     * locally, the pointer to the string
     * is copied, so the caller must ensure that the pointer
     * life cycle is at least as long as the object life cycle.
     * A constant string (stored in flash) is preferred.
     */
    Named_object::Named_object (const char* name) :
        name_ (name != nullptr ? name : "-")
    {
      ;
    }
#endif

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

#if !defined(__DOXYGEN__)
    namespace port
    {

      Tasks_list::Tasks_list ()
      {
        _init ();
      }

      Tasks_list::~Tasks_list ()
      {
        ;
      }

      void
      Tasks_list::_init (void)
      {
        for (std::size_t i = 0; i < sizeof(array_) / sizeof(array_[0]); ++i)
          {
            array_[i] = nullptr;
          }
        count_ = 0;
      }

      void
      Tasks_list::add (rtos::Thread* thread)
      {
        assert(thread != nullptr);
        assert(count_ < (sizeof(array_) / sizeof(array_[0]) + 1));

        array_[count_++] = thread;
      }

      void
      Tasks_list::remove (std::size_t pos)
      {
        for (std::size_t i = pos; i < (sizeof(array_) / sizeof(array_[0]) - 2);
            ++i)
          {
            array_[i] = array_[i + 1];
          }
        count_--;
        array_[count_] = nullptr;
      }

      void
      Tasks_list::remove (rtos::Thread* thread)
      {

        for (std::size_t i = 0; i < sizeof(array_) / sizeof(array_[0]); ++i)
          {
            if (array_[i] == thread)
              {
                remove (i);
                return;
              }
          }
      }

#if 1
      rtos::Thread*
      Tasks_list::_top_prio_task (void)
      {
        rtos::Thread* thread = nullptr;
        thread::priority_t prio = thread::priority::none;
        std::size_t pos = 0;

        for (std::size_t i = 0; i < sizeof(array_) / sizeof(array_[0]); ++i)
          {
            if ((array_[i] != nullptr) && (array_[i]->sched_prio () > prio))
              {
                prio = array_[i]->sched_prio ();
                thread = array_[i];
                pos = i;
              }
          }

        remove (pos);

        return thread;
      }
#endif

      void
      Tasks_list::wakeup_one ()
      {
        _top_prio_task ()->wakeup ();
      }

      void
      Tasks_list::wakeup_all ()
      {
        for (std::size_t i = 0; i < sizeof(array_) / sizeof(array_[0]); ++i)
          {
            if (array_[i] != nullptr)
              {
                array_[i]->wakeup ();
              }
          }
        count_ = 0;
      }

      void
      Tasks_list::clear ()
      {
        _init ();
      }

    } /* namespace port */
#endif

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

#pragma GCC diagnostic pop

  } /* namespace rtos */
} /* namespace os */
<|endoftext|>