<commit_before>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2000, 2010 Oracle and/or its affiliates.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org 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 version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_svx.hxx"
#include <tools/stream.hxx>
#include <com/sun/star/table/BorderLine.hpp>
#include <com/sun/star/table/CellVertJustify2.hpp>
#include <com/sun/star/table/ShadowLocation.hpp>
#include <com/sun/star/table/TableBorder.hpp>
#include <com/sun/star/table/ShadowFormat.hpp>
#include <com/sun/star/table/CellRangeAddress.hpp>
#include <com/sun/star/table/CellContentType.hpp>
#include <com/sun/star/table/TableOrientation.hpp>
#include <com/sun/star/util/SortField.hpp>
#include <com/sun/star/util/SortFieldType.hpp>
#include <com/sun/star/table/CellOrientation.hpp>
#include <com/sun/star/table/CellAddress.hpp>

#include "rotmodit.hxx"

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

// STATIC DATA -----------------------------------------------------------

TYPEINIT1_FACTORY(SvxRotateModeItem, SfxEnumItem, new SvxRotateModeItem(SVX_ROTATE_MODE_STANDARD, 0));

//-----------------------------------------------------------------------
//  SvxRotateModeItem - Ausrichtung bei gedrehtem Text
//-----------------------------------------------------------------------

SvxRotateModeItem::SvxRotateModeItem( SvxRotateMode eMode, USHORT _nWhich )
    : SfxEnumItem( _nWhich, (USHORT)eMode )
{
}

SvxRotateModeItem::SvxRotateModeItem( const SvxRotateModeItem& rItem )
    : SfxEnumItem( rItem )
{
}

SvxRotateModeItem::~SvxRotateModeItem()
{
}

SfxPoolItem* SvxRotateModeItem::Create( SvStream& rStream, USHORT ) const
{
    USHORT nVal;
    rStream >> nVal;
    return new SvxRotateModeItem( (SvxRotateMode) nVal,Which() );
}

SfxItemPresentation SvxRotateModeItem::GetPresentation(
                                SfxItemPresentation ePres,
                                SfxMapUnit /*eCoreUnit*/, SfxMapUnit /*ePresUnit*/,
                                String& rText, const IntlWrapper * )  const
{
    rText.Erase();

    switch ( ePres )
    {
        case SFX_ITEM_PRESENTATION_COMPLETE:
            rText.AppendAscii("...");
            rText.AppendAscii(": ");
//          break; // DURCHFALLEN!!!

        case SFX_ITEM_PRESENTATION_NAMELESS:
            rText += UniString::CreateFromInt32( GetValue() );
            break;
        default: ;//prevent warning
    }

    return ePres;
}

String SvxRotateModeItem::GetValueText( USHORT nVal ) const
{
    String aText;

    switch ( nVal )
    {
        case SVX_ROTATE_MODE_STANDARD:
        case SVX_ROTATE_MODE_TOP:
        case SVX_ROTATE_MODE_CENTER:
        case SVX_ROTATE_MODE_BOTTOM:
            aText.AppendAscii("...");
            break;
        default:
            DBG_ERROR("SvxRotateModeItem: falscher enum");
            break;
    }
    return aText;
}

USHORT SvxRotateModeItem::GetValueCount() const
{
    return 4;       // STANDARD, TOP, CENTER, BOTTOM
}

SfxPoolItem* SvxRotateModeItem::Clone( SfxItemPool* ) const
{
    return new SvxRotateModeItem( *this );
}

USHORT SvxRotateModeItem::GetVersion( USHORT /*nFileVersion*/ ) const
{
    return 0;
}

bool SvxRotateModeItem::QueryValue( uno::Any& rVal, BYTE /*nMemberId*/ ) const
{
    sal_Int32 nUno = table::CellVertJustify2::STANDARD;
    switch ( (SvxRotateMode)GetValue() )
    {
        case SVX_ROTATE_MODE_STANDARD: nUno = table::CellVertJustify2::STANDARD; break;
        case SVX_ROTATE_MODE_TOP:      nUno = table::CellVertJustify2::TOP;      break;
        case SVX_ROTATE_MODE_CENTER:   nUno = table::CellVertJustify2::CENTER;   break;
        case SVX_ROTATE_MODE_BOTTOM:   nUno = table::CellVertJustify2::BOTTOM;   break;
    }
    rVal <<= nUno;
    return true;
}

bool SvxRotateModeItem::PutValue( const uno::Any& rVal, BYTE /*nMemberId*/ )
{
    sal_Int32 nUno;
    if(!(rVal >>= nUno))
    {
        nUno = table::CellVertJustify2::STANDARD;
    }

    SvxRotateMode eSvx = SVX_ROTATE_MODE_STANDARD;
    switch (nUno)
    {
        case table::CellVertJustify2::STANDARD: eSvx = SVX_ROTATE_MODE_STANDARD; break;
        case table::CellVertJustify2::TOP:      eSvx = SVX_ROTATE_MODE_TOP;      break;
        case table::CellVertJustify2::CENTER:   eSvx = SVX_ROTATE_MODE_CENTER;   break;
        case table::CellVertJustify2::BOTTOM:   eSvx = SVX_ROTATE_MODE_BOTTOM;   break;
        default: ;//prevent warning
    }
    SetValue( (USHORT)eSvx );
    return true;
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<commit_msg>Fix a compile time warning: un-initialized variable.<commit_after>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2000, 2010 Oracle and/or its affiliates.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org 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 version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_svx.hxx"
#include <tools/stream.hxx>
#include <com/sun/star/table/BorderLine.hpp>
#include <com/sun/star/table/CellVertJustify2.hpp>
#include <com/sun/star/table/ShadowLocation.hpp>
#include <com/sun/star/table/TableBorder.hpp>
#include <com/sun/star/table/ShadowFormat.hpp>
#include <com/sun/star/table/CellRangeAddress.hpp>
#include <com/sun/star/table/CellContentType.hpp>
#include <com/sun/star/table/TableOrientation.hpp>
#include <com/sun/star/util/SortField.hpp>
#include <com/sun/star/util/SortFieldType.hpp>
#include <com/sun/star/table/CellOrientation.hpp>
#include <com/sun/star/table/CellAddress.hpp>

#include "rotmodit.hxx"

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

// STATIC DATA -----------------------------------------------------------

TYPEINIT1_FACTORY(SvxRotateModeItem, SfxEnumItem, new SvxRotateModeItem(SVX_ROTATE_MODE_STANDARD, 0));

//-----------------------------------------------------------------------
//  SvxRotateModeItem - Ausrichtung bei gedrehtem Text
//-----------------------------------------------------------------------

SvxRotateModeItem::SvxRotateModeItem( SvxRotateMode eMode, USHORT _nWhich )
    : SfxEnumItem( _nWhich, (USHORT)eMode )
{
}

SvxRotateModeItem::SvxRotateModeItem( const SvxRotateModeItem& rItem )
    : SfxEnumItem( rItem )
{
}

SvxRotateModeItem::~SvxRotateModeItem()
{
}

SfxPoolItem* SvxRotateModeItem::Create( SvStream& rStream, USHORT ) const
{
    USHORT nVal;
    rStream >> nVal;
    return new SvxRotateModeItem( (SvxRotateMode) nVal,Which() );
}

SfxItemPresentation SvxRotateModeItem::GetPresentation(
                                SfxItemPresentation ePres,
                                SfxMapUnit /*eCoreUnit*/, SfxMapUnit /*ePresUnit*/,
                                String& rText, const IntlWrapper * )  const
{
    rText.Erase();

    switch ( ePres )
    {
        case SFX_ITEM_PRESENTATION_COMPLETE:
            rText.AppendAscii("...");
            rText.AppendAscii(": ");
//          break; // DURCHFALLEN!!!

        case SFX_ITEM_PRESENTATION_NAMELESS:
            rText += UniString::CreateFromInt32( GetValue() );
            break;
        default: ;//prevent warning
    }

    return ePres;
}

String SvxRotateModeItem::GetValueText( USHORT nVal ) const
{
    String aText;

    switch ( nVal )
    {
        case SVX_ROTATE_MODE_STANDARD:
        case SVX_ROTATE_MODE_TOP:
        case SVX_ROTATE_MODE_CENTER:
        case SVX_ROTATE_MODE_BOTTOM:
            aText.AppendAscii("...");
            break;
        default:
            DBG_ERROR("SvxRotateModeItem: falscher enum");
            break;
    }
    return aText;
}

USHORT SvxRotateModeItem::GetValueCount() const
{
    return 4;       // STANDARD, TOP, CENTER, BOTTOM
}

SfxPoolItem* SvxRotateModeItem::Clone( SfxItemPool* ) const
{
    return new SvxRotateModeItem( *this );
}

USHORT SvxRotateModeItem::GetVersion( USHORT /*nFileVersion*/ ) const
{
    return 0;
}

bool SvxRotateModeItem::QueryValue( uno::Any& rVal, BYTE /*nMemberId*/ ) const
{
    sal_Int32 nUno = table::CellVertJustify2::STANDARD;
    switch ( (SvxRotateMode)GetValue() )
    {
        case SVX_ROTATE_MODE_STANDARD: nUno = table::CellVertJustify2::STANDARD; break;
        case SVX_ROTATE_MODE_TOP:      nUno = table::CellVertJustify2::TOP;      break;
        case SVX_ROTATE_MODE_CENTER:   nUno = table::CellVertJustify2::CENTER;   break;
        case SVX_ROTATE_MODE_BOTTOM:   nUno = table::CellVertJustify2::BOTTOM;   break;
    }
    rVal <<= nUno;
    return true;
}

bool SvxRotateModeItem::PutValue( const uno::Any& rVal, BYTE /*nMemberId*/ )
{
    sal_Int32 nUno(0);
    if(!(rVal >>= nUno))
    {
        nUno = table::CellVertJustify2::STANDARD;
    }

    SvxRotateMode eSvx = SVX_ROTATE_MODE_STANDARD;
    switch (nUno)
    {
        case table::CellVertJustify2::STANDARD: eSvx = SVX_ROTATE_MODE_STANDARD; break;
        case table::CellVertJustify2::TOP:      eSvx = SVX_ROTATE_MODE_TOP;      break;
        case table::CellVertJustify2::CENTER:   eSvx = SVX_ROTATE_MODE_CENTER;   break;
        case table::CellVertJustify2::BOTTOM:   eSvx = SVX_ROTATE_MODE_BOTTOM;   break;
        default: ;//prevent warning
    }
    SetValue( (USHORT)eSvx );
    return true;
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: xmlcnitm.cxx,v $
 *
 *  $Revision: 1.8 $
 *
 *  last change: $Author: obo $ $Date: 2006-10-12 12:56:25 $
 *
 *  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_svx.hxx"

#ifndef _COM_SUN_STAR_XML_ATTRIBUTEDATA_HPP_
#include <com/sun/star/xml/AttributeData.hpp>
#endif
#ifndef _COM_SUN_STAR_LANG_XUNOTUNNEL_HPP_
#include <com/sun/star/lang/XUnoTunnel.hpp>
#endif

#ifndef _XMLOFF_XMLCNIMP_HXX
#include <xmloff/xmlcnimp.hxx>
#endif
#ifndef _XMLOFF_XMLCNITM_HXX
#include <xmloff/unoatrcn.hxx>
#endif
#include "xmlcnitm.hxx"

using namespace rtl;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::container;
using namespace ::com::sun::star::lang;
using namespace ::com::sun::star::xml;

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

TYPEINIT1(SvXMLAttrContainerItem, SfxPoolItem);

SvXMLAttrContainerItem::SvXMLAttrContainerItem( USHORT _nWhich ) :
    SfxPoolItem( _nWhich )
{
    pImpl = new SvXMLAttrContainerData;
}

SvXMLAttrContainerItem::SvXMLAttrContainerItem(
                                        const SvXMLAttrContainerItem& rItem ) :
    SfxPoolItem( rItem )
{
    pImpl = new SvXMLAttrContainerData( *rItem.pImpl );
}

SvXMLAttrContainerItem::~SvXMLAttrContainerItem()
{
    delete pImpl;
}

int SvXMLAttrContainerItem::operator==( const SfxPoolItem& rItem ) const
{
    DBG_ASSERT( rItem.ISA(SvXMLAttrContainerItem),
               "SvXMLAttrContainerItem::operator ==(): Bad type");
    return *pImpl == *((const SvXMLAttrContainerItem&)rItem).pImpl;
}

int SvXMLAttrContainerItem::Compare( const SfxPoolItem &/*rWith*/ ) const
{
    DBG_ASSERT( !this, "not yet implemented" );

    return 0;
}

SfxItemPresentation SvXMLAttrContainerItem::GetPresentation(
                    SfxItemPresentation /*ePresentation*/,
                    SfxMapUnit /*eCoreMetric*/,
                    SfxMapUnit /*ePresentationMetric*/,
                    XubString &/*rText*/,
                    const IntlWrapper * /*pIntlWrapper*/ ) const
{
    return SFX_ITEM_PRESENTATION_NONE;
}

USHORT SvXMLAttrContainerItem::GetVersion( USHORT /*nFileFormatVersion*/ ) const
{
    // This item should never be stored
    return USHRT_MAX;
}

BOOL  SvXMLAttrContainerItem::QueryValue( com::sun::star::uno::Any& rVal, BYTE /*nMemberId*/ ) const
{
    Reference<XNameContainer> xContainer =
        new SvUnoAttributeContainer( new SvXMLAttrContainerData( *pImpl ) );

    rVal.setValue( &xContainer, ::getCppuType((Reference<XNameContainer>*)0) );
    return TRUE;
}
BOOL SvXMLAttrContainerItem::PutValue( const com::sun::star::uno::Any& rVal, BYTE /*nMemberId*/ )
{
    Reference<XInterface> xRef;
    SvUnoAttributeContainer* pContainer = NULL;

    if( rVal.getValue() != NULL && rVal.getValueType().getTypeClass() == TypeClass_INTERFACE )
    {
        xRef = *(Reference<XInterface>*)rVal.getValue();
        Reference<XUnoTunnel> xTunnel(xRef, UNO_QUERY);
        if( xTunnel.is() )
            pContainer = (SvUnoAttributeContainer*)(ULONG)xTunnel->getSomething(SvUnoAttributeContainer::getUnoTunnelId());
    }

    if( pContainer )
    {
        delete pImpl;
        pImpl = new SvXMLAttrContainerData( * pContainer->GetContainerImpl() );
    }
    else
    {
        SvXMLAttrContainerData* pNewImpl = new SvXMLAttrContainerData;

        try
        {
            Reference<XNameContainer> xContainer( xRef, UNO_QUERY );
            if( !xContainer.is() )
                return FALSE;

            const Sequence< OUString > aNameSequence( xContainer->getElementNames() );
            const OUString* pNames = aNameSequence.getConstArray();
            const INT32 nCount = aNameSequence.getLength();
            Any aAny;
            AttributeData* pData;
            INT32 nAttr;

            for( nAttr = 0; nAttr < nCount; nAttr++ )
            {
                const OUString aName( *pNames++ );

                aAny = xContainer->getByName( aName );
                if( aAny.getValue() == NULL || aAny.getValueType() != ::getCppuType((AttributeData*)0) )
                    return FALSE;

                pData = (AttributeData*)aAny.getValue();
                sal_Int32 pos = aName.indexOf( sal_Unicode(':') );
                if( pos != -1 )
                {
                    const OUString aPrefix( aName.copy( 0, pos ));
                    const OUString aLName( aName.copy( pos+1 ));

                    if( pData->Namespace.getLength() == 0 )
                    {
                        if( !pNewImpl->AddAttr( aPrefix, aLName, pData->Value ) )
                            break;
                    }
                    else
                    {
                        if( !pNewImpl->AddAttr( aPrefix, pData->Namespace, aLName, pData->Value ) )
                            break;
                    }
                }
                else
                {
                    if( !pNewImpl->AddAttr( aName, pData->Value ) )
                        break;
                }
            }

            if( nAttr == nCount )
            {
                delete pImpl;
                pImpl = pNewImpl;
            }
            else
            {
                delete pNewImpl;
                return FALSE;
            }
        }
        catch(...)
        {
            delete pNewImpl;
            return FALSE;
        }
    }
    return TRUE;
}

BOOL SvXMLAttrContainerItem::AddAttr( const OUString& rLName,
                                        const OUString& rValue )
{
    return pImpl->AddAttr( rLName, rValue );
}

BOOL SvXMLAttrContainerItem::AddAttr( const OUString& rPrefix,
          const OUString& rNamespace, const OUString& rLName,
          const OUString& rValue )
{
    return pImpl->AddAttr( rPrefix, rNamespace, rLName, rValue );
}

USHORT SvXMLAttrContainerItem::GetAttrCount() const
{
    return (USHORT)pImpl->GetAttrCount();
}

OUString SvXMLAttrContainerItem::GetAttrNamespace( USHORT i ) const
{
    return pImpl->GetAttrNamespace( i );
}

OUString SvXMLAttrContainerItem::GetAttrPrefix( USHORT i ) const
{
    return pImpl->GetAttrPrefix( i );
}

const OUString& SvXMLAttrContainerItem::GetAttrLName( USHORT i ) const
{
    return pImpl->GetAttrLName( i );
}

const OUString& SvXMLAttrContainerItem::GetAttrValue( USHORT i ) const
{
    return pImpl->GetAttrValue( i );
}

USHORT SvXMLAttrContainerItem::GetFirstNamespaceIndex() const
{
    return pImpl->GetFirstNamespaceIndex();
}

USHORT SvXMLAttrContainerItem::GetNextNamespaceIndex( USHORT nIdx ) const
{
    return pImpl->GetNextNamespaceIndex( nIdx );
}

const OUString& SvXMLAttrContainerItem::GetNamespace( USHORT i ) const
{
    return pImpl->GetNamespace( i );
}

const OUString& SvXMLAttrContainerItem::GetPrefix( USHORT i ) const
{
    return pImpl->GetPrefix( i );
}

<commit_msg>INTEGRATION: CWS changefileheader (1.8.698); FILE MERGED 2008/04/01 15:51:19 thb 1.8.698.3: #i85898# Stripping all external header guards 2008/04/01 12:49:16 thb 1.8.698.2: #i85898# Stripping all external header guards 2008/03/31 14:22:39 rt 1.8.698.1: #i87441# Change license header to LPGL v3.<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: xmlcnitm.cxx,v $
 * $Revision: 1.9 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org 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 version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_svx.hxx"
#include <com/sun/star/xml/AttributeData.hpp>
#include <com/sun/star/lang/XUnoTunnel.hpp>
#include <xmloff/xmlcnimp.hxx>
#ifndef _XMLOFF_XMLCNITM_HXX
#include <xmloff/unoatrcn.hxx>
#endif
#include "xmlcnitm.hxx"

using namespace rtl;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::container;
using namespace ::com::sun::star::lang;
using namespace ::com::sun::star::xml;

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

TYPEINIT1(SvXMLAttrContainerItem, SfxPoolItem);

SvXMLAttrContainerItem::SvXMLAttrContainerItem( USHORT _nWhich ) :
    SfxPoolItem( _nWhich )
{
    pImpl = new SvXMLAttrContainerData;
}

SvXMLAttrContainerItem::SvXMLAttrContainerItem(
                                        const SvXMLAttrContainerItem& rItem ) :
    SfxPoolItem( rItem )
{
    pImpl = new SvXMLAttrContainerData( *rItem.pImpl );
}

SvXMLAttrContainerItem::~SvXMLAttrContainerItem()
{
    delete pImpl;
}

int SvXMLAttrContainerItem::operator==( const SfxPoolItem& rItem ) const
{
    DBG_ASSERT( rItem.ISA(SvXMLAttrContainerItem),
               "SvXMLAttrContainerItem::operator ==(): Bad type");
    return *pImpl == *((const SvXMLAttrContainerItem&)rItem).pImpl;
}

int SvXMLAttrContainerItem::Compare( const SfxPoolItem &/*rWith*/ ) const
{
    DBG_ASSERT( !this, "not yet implemented" );

    return 0;
}

SfxItemPresentation SvXMLAttrContainerItem::GetPresentation(
                    SfxItemPresentation /*ePresentation*/,
                    SfxMapUnit /*eCoreMetric*/,
                    SfxMapUnit /*ePresentationMetric*/,
                    XubString &/*rText*/,
                    const IntlWrapper * /*pIntlWrapper*/ ) const
{
    return SFX_ITEM_PRESENTATION_NONE;
}

USHORT SvXMLAttrContainerItem::GetVersion( USHORT /*nFileFormatVersion*/ ) const
{
    // This item should never be stored
    return USHRT_MAX;
}

BOOL  SvXMLAttrContainerItem::QueryValue( com::sun::star::uno::Any& rVal, BYTE /*nMemberId*/ ) const
{
    Reference<XNameContainer> xContainer =
        new SvUnoAttributeContainer( new SvXMLAttrContainerData( *pImpl ) );

    rVal.setValue( &xContainer, ::getCppuType((Reference<XNameContainer>*)0) );
    return TRUE;
}
BOOL SvXMLAttrContainerItem::PutValue( const com::sun::star::uno::Any& rVal, BYTE /*nMemberId*/ )
{
    Reference<XInterface> xRef;
    SvUnoAttributeContainer* pContainer = NULL;

    if( rVal.getValue() != NULL && rVal.getValueType().getTypeClass() == TypeClass_INTERFACE )
    {
        xRef = *(Reference<XInterface>*)rVal.getValue();
        Reference<XUnoTunnel> xTunnel(xRef, UNO_QUERY);
        if( xTunnel.is() )
            pContainer = (SvUnoAttributeContainer*)(ULONG)xTunnel->getSomething(SvUnoAttributeContainer::getUnoTunnelId());
    }

    if( pContainer )
    {
        delete pImpl;
        pImpl = new SvXMLAttrContainerData( * pContainer->GetContainerImpl() );
    }
    else
    {
        SvXMLAttrContainerData* pNewImpl = new SvXMLAttrContainerData;

        try
        {
            Reference<XNameContainer> xContainer( xRef, UNO_QUERY );
            if( !xContainer.is() )
                return FALSE;

            const Sequence< OUString > aNameSequence( xContainer->getElementNames() );
            const OUString* pNames = aNameSequence.getConstArray();
            const INT32 nCount = aNameSequence.getLength();
            Any aAny;
            AttributeData* pData;
            INT32 nAttr;

            for( nAttr = 0; nAttr < nCount; nAttr++ )
            {
                const OUString aName( *pNames++ );

                aAny = xContainer->getByName( aName );
                if( aAny.getValue() == NULL || aAny.getValueType() != ::getCppuType((AttributeData*)0) )
                    return FALSE;

                pData = (AttributeData*)aAny.getValue();
                sal_Int32 pos = aName.indexOf( sal_Unicode(':') );
                if( pos != -1 )
                {
                    const OUString aPrefix( aName.copy( 0, pos ));
                    const OUString aLName( aName.copy( pos+1 ));

                    if( pData->Namespace.getLength() == 0 )
                    {
                        if( !pNewImpl->AddAttr( aPrefix, aLName, pData->Value ) )
                            break;
                    }
                    else
                    {
                        if( !pNewImpl->AddAttr( aPrefix, pData->Namespace, aLName, pData->Value ) )
                            break;
                    }
                }
                else
                {
                    if( !pNewImpl->AddAttr( aName, pData->Value ) )
                        break;
                }
            }

            if( nAttr == nCount )
            {
                delete pImpl;
                pImpl = pNewImpl;
            }
            else
            {
                delete pNewImpl;
                return FALSE;
            }
        }
        catch(...)
        {
            delete pNewImpl;
            return FALSE;
        }
    }
    return TRUE;
}

BOOL SvXMLAttrContainerItem::AddAttr( const OUString& rLName,
                                        const OUString& rValue )
{
    return pImpl->AddAttr( rLName, rValue );
}

BOOL SvXMLAttrContainerItem::AddAttr( const OUString& rPrefix,
          const OUString& rNamespace, const OUString& rLName,
          const OUString& rValue )
{
    return pImpl->AddAttr( rPrefix, rNamespace, rLName, rValue );
}

USHORT SvXMLAttrContainerItem::GetAttrCount() const
{
    return (USHORT)pImpl->GetAttrCount();
}

OUString SvXMLAttrContainerItem::GetAttrNamespace( USHORT i ) const
{
    return pImpl->GetAttrNamespace( i );
}

OUString SvXMLAttrContainerItem::GetAttrPrefix( USHORT i ) const
{
    return pImpl->GetAttrPrefix( i );
}

const OUString& SvXMLAttrContainerItem::GetAttrLName( USHORT i ) const
{
    return pImpl->GetAttrLName( i );
}

const OUString& SvXMLAttrContainerItem::GetAttrValue( USHORT i ) const
{
    return pImpl->GetAttrValue( i );
}

USHORT SvXMLAttrContainerItem::GetFirstNamespaceIndex() const
{
    return pImpl->GetFirstNamespaceIndex();
}

USHORT SvXMLAttrContainerItem::GetNextNamespaceIndex( USHORT nIdx ) const
{
    return pImpl->GetNextNamespaceIndex( nIdx );
}

const OUString& SvXMLAttrContainerItem::GetNamespace( USHORT i ) const
{
    return pImpl->GetNamespace( i );
}

const OUString& SvXMLAttrContainerItem::GetPrefix( USHORT i ) const
{
    return pImpl->GetPrefix( i );
}

<|endoftext|>


<commit_before>#include <stan/math/prim/scal.hpp>
#include <boost/math/special_functions/fpclassify.hpp>
#include <gtest/gtest.h>

TEST(MathFunctions, falling_factorial) {
  using stan::math::falling_factorial;

  EXPECT_FLOAT_EQ(24, falling_factorial(4.0,3));
  EXPECT_FLOAT_EQ(120, falling_factorial(5.0,4));
  EXPECT_FLOAT_EQ(144.8261, falling_factorial(6.1,3.1));
  EXPECT_THROW(falling_factorial(1, -4), std::domain_error);
}

TEST(MathFunctions, falling_factorial_nan) {
  double nan = std::numeric_limits<double>::quiet_NaN();

  EXPECT_PRED1(boost::math::isnan<double>,
               stan::math::falling_factorial(4.0, nan));

  EXPECT_PRED1(boost::math::isnan<double>,
               stan::math::falling_factorial(nan, 4.0));

  EXPECT_PRED1(boost::math::isnan<double>,
               stan::math::falling_factorial(nan, nan));
}
<commit_msg>Tests using real n, only defined for integer n<commit_after>#include <stan/math/prim/scal.hpp>
#include <boost/math/special_functions/fpclassify.hpp>
#include <gtest/gtest.h>

TEST(MathFunctions, falling_factorial) {
  using stan::math::falling_factorial;

  EXPECT_FLOAT_EQ(24, falling_factorial(4.0,3));
  EXPECT_FLOAT_EQ(120, falling_factorial(5.0,4));
  EXPECT_THROW(falling_factorial(1, -4), std::domain_error);
}

TEST(MathFunctions, falling_factorial_nan) {
  double nan = std::numeric_limits<double>::quiet_NaN();

  EXPECT_PRED1(boost::math::isnan<double>,
               stan::math::falling_factorial(4.0, nan));

  EXPECT_PRED1(boost::math::isnan<double>,
               stan::math::falling_factorial(nan, 4.0));

  EXPECT_PRED1(boost::math::isnan<double>,
               stan::math::falling_factorial(nan, nan));
}
<|endoftext|>


<commit_before>#define GURKE_STEP_NAME_PREFIX TestSteps

#include "gurkenlaeufer/Step.h"
#include "gtest/gtest.h"
#include <iostream>
#include <vector>

struct Calculator {
    std::vector<int> values;
};

STEP(".*have entered (\\d+) into the calculator$")
{
    // This step uses the gurkenlaeufer native API
    auto calc = getFixture<Calculator>();
    calc->values.push_back(getNextParam<int>());
}

STEP(".*press (\\w+)")
{
    std::cout << getNextParam<std::string>() << std::endl;
}

STEP(".*nostep")
{
}

STEP(".*the result should be (\\d+) on the screen$")
{
    // This step uses the cucumber-cpp adaption layer
    auto calc = getFixture<Calculator>();
    int sum = 0;
    for (auto& n : calc->values)
        sum += n;
    auto result = getParam<int>(0u);
    std::cout << "Sum=" << sum << " " << result << std::endl;
    EXPECT_EQ(result, sum);
}

STEP(".*nobody should know")
{
    auto docString = getNextParam<std::string>();
    std::cout << docString << std::endl;
}

BEFORE("@Print")
{
    std::cout << "ctrl + p" << std::endl;
}

AFTER("@Echo")
{
    std::cout << "echo ho ho ho" << std::endl;
}
<commit_msg>Remove misleading comments<commit_after>#define GURKE_STEP_NAME_PREFIX TestSteps

#include "gurkenlaeufer/Step.h"
#include "gtest/gtest.h"
#include <iostream>
#include <vector>

struct Calculator {
    std::vector<int> values;
};

STEP(".*have entered (\\d+) into the calculator$")
{
    auto calc = getFixture<Calculator>();
    calc->values.push_back(getNextParam<int>());
}

STEP(".*press (\\w+)")
{
    std::cout << getNextParam<std::string>() << std::endl;
}

STEP(".*nostep")
{
}

STEP(".*the result should be (\\d+) on the screen$")
{
    auto calc = getFixture<Calculator>();
    int sum = 0;
    for (auto& n : calc->values)
        sum += n;
    auto result = getParam<int>(0u);
    std::cout << "Sum=" << sum << " " << result << std::endl;
    EXPECT_EQ(result, sum);
}

STEP(".*nobody should know")
{
    auto docString = getNextParam<std::string>();
    std::cout << docString << std::endl;
}

BEFORE("@Print")
{
    std::cout << "ctrl + p" << std::endl;
}

AFTER("@Echo")
{
    std::cout << "echo ho ho ho" << std::endl;
}
<|endoftext|>


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

#include "../unittest_enchant_providers.h"
#include <vector>
#include <map>
#include <assert.h>
#include <string.h>

struct DictionaryCheck_TestFixture : Provider_TestFixture
{
    typedef std::multimap<EnchantDict*, std::string> AddedWordsByDict;
    EnchantDict* _dict;
    const char *_provider_name;
    AddedWordsByDict _addedWordsByDict;

    //Setup
    DictionaryCheck_TestFixture():_dict(NULL)
    {
        _dict = GetFirstAvailableDictionary();
        /* FIXME: hspell does not consider non-Hebrew letters to be valid letters */
        if (_dict) {
          _provider_name = _provider->identify(_provider);
          if (strcmp(_provider_name, "hspell") == 0)
            _dict = NULL;
        }
    }

    //Teardown
    ~DictionaryCheck_TestFixture()
    {
        ReleaseDictionary(_dict);
    }

    virtual void ReleaseDictionary(EnchantDict* dict){
        std::pair<AddedWordsByDict::const_iterator,
                  AddedWordsByDict::const_iterator>
                  addedWords = _addedWordsByDict.equal_range(dict);

        AddedWordsByDict::const_iterator it;
        for(it = addedWords.first; it != addedWords.second; ++it)
        {
            if(dict->add_to_exclude)
            {
                (*dict->add_to_exclude)(dict, it->second.c_str(), it->second.length());
            }
        }
        _addedWordsByDict.erase(dict);
        Provider_TestFixture::ReleaseDictionary(dict);
    }

    bool IsWordInDictionary(const std::string& word)
    {
        return IsWordInDictionary(_dict, word);
    }

    static bool IsWordInDictionary(EnchantDict* dict, const std::string& word)
    {
        assert(dict && dict->check); // tests must check this before calling

        return (*dict->check)(dict, word.c_str(), word.length()) == 0; //check returns 0 when successful and 1 when not successful
    }

    bool AddWordToDictionary(const std::string& word)
    {
        return AddWordToDictionary(_dict, word);
    }

    bool AddWordToDictionary(EnchantDict* dict, const std::string& word)
    {
        if(dict == NULL)
        {
            return false;
        }

        if(IsWordInDictionary(word))
        {
            return true;
        }

        // prefer adding it to the session so it will get automatically removed
        if(dict->add_to_session)
        {
            (*dict->add_to_session) (dict, word.c_str(), word.length());
            if(IsWordInDictionary(word))
            {
                return true;
            }
        }

        if(dict->add_to_personal)
        {
            _addedWordsByDict.insert(std::pair<EnchantDict*, std::string>(dict,word));
            (*dict->add_to_personal) (dict, word.c_str(), word.length());
            if(IsWordInDictionary(word))
            {
                return true;
            }
        }

        return false;
    }
};

/////////////////////////////////////////////////////////////////////////////////////////////////
// Unicode normalization
TEST_FIXTURE(DictionaryCheck_TestFixture,
             IsWordInDictionary_AddedComposed_SuccessfulCheckWithComposedAndDecomposed)
{
    if(_dict && _dict->check)
    {
      if(AddWordToDictionary(Convert(L"fianc\x00e9" L"deleteme"))) // u00e9 = Latin small letter e with acute
      {
          CHECK( IsWordInDictionary(Convert(L"fianc\x00e9" L"deleteme")) ); //NFC
// FIXME: This test times out on macOS >= 10.12 with "findMisspelledWordInString timed out"
#if !(defined(__APPLE__) && defined(__MACH__))
          CHECK( IsWordInDictionary(Convert(L"fiance\x0301" L"deleteme")) ); //NFD u0301 = Combining acute accent
#endif
      }
    }
}

TEST_FIXTURE(DictionaryCheck_TestFixture,
             IsWordInDictionary_AddedDecomposed_SuccessfulCheckWithComposedAndDecomposed)
{
    if(_dict && _dict->check)
    {
      if(AddWordToDictionary(Convert(L"fiance\x0301" L"deletethis"))) // u0301 = Combining acute accent
      {
          CHECK( IsWordInDictionary(Convert(L"fianc\x00e9" L"deletethis")) ); //NFC
          CHECK( IsWordInDictionary(Convert(L"fiance\x0301" L"deletethis")) ); //NFD
      }
    }
}

TEST_FIXTURE(DictionaryCheck_TestFixture,
             IsWordInDictionary_SuccessfulCheckWithComposedAndDecomposed)
{
    EnchantDict* dict = GetDictionary("fr_FR");
    if(dict && dict->check)
    {
        CHECK( IsWordInDictionary(dict, Convert(L"Fran\x00e7" L"ais")) ); //NFC latin small letter c with cedilla
        CHECK( IsWordInDictionary(dict, Convert(L"Franc\x0327" L"ais")) ); //NFD combining cedilla
    }
    ReleaseDictionary(dict);
}

/////////////////////////////////////////////////////////////////////////////////////////////////
// Capitalization
TEST_FIXTURE(DictionaryCheck_TestFixture,
             IsWordInDictionary_AddedAllCaps_OnlyAllCapsSuccessful)
{
    if(_dict && _dict->check)
    {
      if(AddWordToDictionary("ZYX"))
      {
          CHECK( IsWordInDictionary("ZYX") );
          CHECK(!IsWordInDictionary("ZYx") );
          CHECK(!IsWordInDictionary("Zyx") );
          CHECK(!IsWordInDictionary("zyx") );
          if (strcmp(_provider_name, "AppleSpell") != 0) /* FIXME: This fails on AppleSpell */
	    CHECK(!IsWordInDictionary("zYx") );
      }
    }
}

TEST_FIXTURE(DictionaryCheck_TestFixture,
             IsWordInDictionary_AddedTitle_lowerCaseAndMixedCaseNotSuccessful)
{
    if(_dict && _dict->check)
    {
      if(AddWordToDictionary("Zxyz"))
      {
          CHECK( IsWordInDictionary("ZXYZ") );
          CHECK(!IsWordInDictionary("ZXyz") );
          CHECK( IsWordInDictionary("Zxyz") );
          CHECK(!IsWordInDictionary("zxyz") );
          CHECK(!IsWordInDictionary("zXyz") );
      }
   }
}

TEST_FIXTURE(DictionaryCheck_TestFixture,
             IsWordInDictionary_Addedlower_MixedCaseNotSuccessful)
{
    if(_dict && _dict->check)
    {
      if(AddWordToDictionary("zyxz"))
      {
          CHECK( IsWordInDictionary("ZYXZ") );
          CHECK(!IsWordInDictionary("ZYxz") );
          CHECK( IsWordInDictionary("Zyxz") );
          CHECK( IsWordInDictionary("zyxz") );
          CHECK(!IsWordInDictionary("zYxz") );
      }
    }
}
<commit_msg>Comment out another test failing on macOS >= 10.12<commit_after>/* Copyright (c) 2008 Eric Scott Albright
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
#include <UnitTest++.h>

#include "../unittest_enchant_providers.h"
#include <vector>
#include <map>
#include <assert.h>
#include <string.h>

struct DictionaryCheck_TestFixture : Provider_TestFixture
{
    typedef std::multimap<EnchantDict*, std::string> AddedWordsByDict;
    EnchantDict* _dict;
    const char *_provider_name;
    AddedWordsByDict _addedWordsByDict;

    //Setup
    DictionaryCheck_TestFixture():_dict(NULL)
    {
        _dict = GetFirstAvailableDictionary();
        /* FIXME: hspell does not consider non-Hebrew letters to be valid letters */
        if (_dict) {
          _provider_name = _provider->identify(_provider);
          if (strcmp(_provider_name, "hspell") == 0)
            _dict = NULL;
        }
    }

    //Teardown
    ~DictionaryCheck_TestFixture()
    {
        ReleaseDictionary(_dict);
    }

    virtual void ReleaseDictionary(EnchantDict* dict){
        std::pair<AddedWordsByDict::const_iterator,
                  AddedWordsByDict::const_iterator>
                  addedWords = _addedWordsByDict.equal_range(dict);

        AddedWordsByDict::const_iterator it;
        for(it = addedWords.first; it != addedWords.second; ++it)
        {
            if(dict->add_to_exclude)
            {
                (*dict->add_to_exclude)(dict, it->second.c_str(), it->second.length());
            }
        }
        _addedWordsByDict.erase(dict);
        Provider_TestFixture::ReleaseDictionary(dict);
    }

    bool IsWordInDictionary(const std::string& word)
    {
        return IsWordInDictionary(_dict, word);
    }

    static bool IsWordInDictionary(EnchantDict* dict, const std::string& word)
    {
        assert(dict && dict->check); // tests must check this before calling

        return (*dict->check)(dict, word.c_str(), word.length()) == 0; //check returns 0 when successful and 1 when not successful
    }

    bool AddWordToDictionary(const std::string& word)
    {
        return AddWordToDictionary(_dict, word);
    }

    bool AddWordToDictionary(EnchantDict* dict, const std::string& word)
    {
        if(dict == NULL)
        {
            return false;
        }

        if(IsWordInDictionary(word))
        {
            return true;
        }

        // prefer adding it to the session so it will get automatically removed
        if(dict->add_to_session)
        {
            (*dict->add_to_session) (dict, word.c_str(), word.length());
            if(IsWordInDictionary(word))
            {
                return true;
            }
        }

        if(dict->add_to_personal)
        {
            _addedWordsByDict.insert(std::pair<EnchantDict*, std::string>(dict,word));
            (*dict->add_to_personal) (dict, word.c_str(), word.length());
            if(IsWordInDictionary(word))
            {
                return true;
            }
        }

        return false;
    }
};

/////////////////////////////////////////////////////////////////////////////////////////////////
// Unicode normalization
TEST_FIXTURE(DictionaryCheck_TestFixture,
             IsWordInDictionary_AddedComposed_SuccessfulCheckWithComposedAndDecomposed)
{
    if(_dict && _dict->check)
    {
      if(AddWordToDictionary(Convert(L"fianc\x00e9" L"deleteme"))) // u00e9 = Latin small letter e with acute
      {
// FIXME: These tests time out on macOS >= 10.12 with "findMisspelledWordInString timed out"
#if !(defined(__APPLE__) && defined(__MACH__))
          CHECK( IsWordInDictionary(Convert(L"fianc\x00e9" L"deleteme")) ); //NFC
          CHECK( IsWordInDictionary(Convert(L"fiance\x0301" L"deleteme")) ); //NFD u0301 = Combining acute accent
#endif
      }
    }
}

TEST_FIXTURE(DictionaryCheck_TestFixture,
             IsWordInDictionary_AddedDecomposed_SuccessfulCheckWithComposedAndDecomposed)
{
    if(_dict && _dict->check)
    {
      if(AddWordToDictionary(Convert(L"fiance\x0301" L"deletethis"))) // u0301 = Combining acute accent
      {
          CHECK( IsWordInDictionary(Convert(L"fianc\x00e9" L"deletethis")) ); //NFC
          CHECK( IsWordInDictionary(Convert(L"fiance\x0301" L"deletethis")) ); //NFD
      }
    }
}

TEST_FIXTURE(DictionaryCheck_TestFixture,
             IsWordInDictionary_SuccessfulCheckWithComposedAndDecomposed)
{
    EnchantDict* dict = GetDictionary("fr_FR");
    if(dict && dict->check)
    {
        CHECK( IsWordInDictionary(dict, Convert(L"Fran\x00e7" L"ais")) ); //NFC latin small letter c with cedilla
        CHECK( IsWordInDictionary(dict, Convert(L"Franc\x0327" L"ais")) ); //NFD combining cedilla
    }
    ReleaseDictionary(dict);
}

/////////////////////////////////////////////////////////////////////////////////////////////////
// Capitalization
TEST_FIXTURE(DictionaryCheck_TestFixture,
             IsWordInDictionary_AddedAllCaps_OnlyAllCapsSuccessful)
{
    if(_dict && _dict->check)
    {
      if(AddWordToDictionary("ZYX"))
      {
          CHECK( IsWordInDictionary("ZYX") );
          CHECK(!IsWordInDictionary("ZYx") );
          CHECK(!IsWordInDictionary("Zyx") );
          CHECK(!IsWordInDictionary("zyx") );
          if (strcmp(_provider_name, "AppleSpell") != 0) /* FIXME: This fails on AppleSpell */
	    CHECK(!IsWordInDictionary("zYx") );
      }
    }
}

TEST_FIXTURE(DictionaryCheck_TestFixture,
             IsWordInDictionary_AddedTitle_lowerCaseAndMixedCaseNotSuccessful)
{
    if(_dict && _dict->check)
    {
      if(AddWordToDictionary("Zxyz"))
      {
          CHECK( IsWordInDictionary("ZXYZ") );
          CHECK(!IsWordInDictionary("ZXyz") );
          CHECK( IsWordInDictionary("Zxyz") );
          CHECK(!IsWordInDictionary("zxyz") );
          CHECK(!IsWordInDictionary("zXyz") );
      }
   }
}

TEST_FIXTURE(DictionaryCheck_TestFixture,
             IsWordInDictionary_Addedlower_MixedCaseNotSuccessful)
{
    if(_dict && _dict->check)
    {
      if(AddWordToDictionary("zyxz"))
      {
          CHECK( IsWordInDictionary("ZYXZ") );
          CHECK(!IsWordInDictionary("ZYxz") );
          CHECK( IsWordInDictionary("Zyxz") );
          CHECK( IsWordInDictionary("zyxz") );
          CHECK(!IsWordInDictionary("zYxz") );
      }
    }
}
<|endoftext|>


<commit_before>/*
  level.cpp

  Contains functions for loading and saving level data.

  This code is released under the terms of the MIT license.
  See COPYING.txt for details.
*/

#include "compress.h"
#include "romfile.h"
#include "level.h"

#include <algorithm>
#include <cstring>
#include <cstdlib>
#include <cstdint>
#include <list>
#include <iostream>
#include <stdexcept>

#include <QMessageBox>
#include <QString>
#include <QCoreApplication>

#define MAP_DATA_SIZE 0xCDA

//Locations of chunk data in ROM (using CPU addressing.)
//currently assumes table locations are constant in all versions,
// may need to change this later to use version arrays like kdceditor
//...
const romaddr_t ptrMapDataL = {0x12, 0x88a6};
const romaddr_t ptrMapDataH = {0x12, 0x875f};
const romaddr_t ptrMapDataB = {0x12, 0x84d1};
const romaddr_t mapTilesets = {0x12, 0x8618};
const romaddr_t ptrSpritesL = {0x12, 0x8d0e};
const romaddr_t ptrSpritesH = {0x12, 0x8bc7};
const romaddr_t ptrSpritesB = {0x12, 0x8a80};
const romaddr_t ptrExitsL   = {0x12, 0x8f82};
const romaddr_t ptrExitsH   = {0x12, 0x90cb};
const uint      ptrExitsB   = 0x12;
const romaddr_t bossExits   = {0x12, 0x9c4a};

/*
  Load a level by number. Returns pointer to the level data as a struct.
  Returns null if a level failed and the user decided not to continue.
*/
leveldata_t* loadLevel (ROMFile& file, uint num) {
    //invalid data should at least be able to decompress fully
    uint8_t  buf[DATA_SIZE] = {0};
    header_t *header  = (header_t*)buf + 0;
    uint8_t  *screens = buf + 8;
    uint8_t  *tiles   = buf + 0xDA;

    size_t result = file.readFromPointer(ptrMapDataL, ptrMapDataH, ptrMapDataB, 0, buf, num);
    // TODO: "error reading level, attempt to continue?"
    if (result == 0) return NULL;

    leveldata_t *level;
    try {
        level = new leveldata_t;
    } catch (std::bad_alloc) {
        QMessageBox::critical(0,
                              "Load ROM",
                              QString("Unable to allocate memory for room %1").arg(num),
                              QMessageBox::Ok);
        return NULL;
    }

    memcpy(&level->header, header, sizeof(header_t));

    // make sure the level size is valid
    if (header->screensH * header->screensV > 16
            || header->screensH == 0
            || header->screensV == 0) {
        QMessageBox::critical(0,
                              "Load ROM",
                              QString("Unable to load room %1 because it has an invalid size.\n\n"
                                      "The ROM may be corrupt.").arg(num),
                              QMessageBox::Ok);

        delete level;
        return NULL;
    }

    // kinda slow, but eh
    for (uint y = 0; y < SCREEN_HEIGHT * header->screensV; y++) {
        for (uint x = 0; x < SCREEN_WIDTH * header->screensH; x++) {
            uint idx = (y / SCREEN_HEIGHT * header->screensH) + (x / SCREEN_WIDTH);
            uint8_t screen = screens[idx];
            level->tiles[y][x] = tiles[(screen * SCREEN_SIZE)
                    + (y % SCREEN_HEIGHT * 16) + (x % SCREEN_WIDTH)];
        }
    }

    // get tileset from table
    level->tileset = file.readByte(mapTilesets + num);

    // get "don't return on death" flag
    // (which is the highest bit of the level pointer's bank byte)
    level->noReturn = file.readByte(ptrMapDataB + num) & 0x80;

    // get sprite data
    romaddr_t spritePtr = file.readPointer(ptrSpritesL, ptrSpritesH, ptrSpritesB, num);
    // true number of screens (this may differ in levels more than 2 screens tall)
    uint sprScreens = file.readByte(spritePtr);

    // last # of sprite on each screen
    romaddr_t spriteCounts = spritePtr + 2;
    uint numSprites = file.readByte(spriteCounts + (sprScreens - 1));
    // position of each sprite
    romaddr_t spritePos    = spriteCounts + sprScreens;
    // type of each sprite
    romaddr_t spriteTypes  = spritePos + numSprites;

    uint sprNum = 0;
    for (uint i = 0; i < sprScreens; i++) {
        // number of sprites on this screen
        numSprites = file.readByte(spriteCounts + i);
        while (sprNum < numSprites) {
            sprite_t *sprite = new sprite_t;

            sprite->type = file.readByte(spriteTypes + sprNum);

            uint8_t pos  = file.readByte(spritePos + sprNum);

            // calculate normal x/y positions
            sprite->x = (i % header->screensH * SCREEN_WIDTH) + (pos >> 4);
            // for some stupid reason, HAL designed the sprite data so that
            // sprite coords / screen positions are based on screens being
            // 16 tiles tall instead of 12. changing this should put sprites
            // in the correct place all the time on vertical levels.
            // (fixes issue #2)
            sprite->y = (i / header->screensH * (SCREEN_HEIGHT + 4)) + (pos & 0xF);

            level->sprites.push_back(sprite);
            sprNum++;
        }
    }

    // get exit data
    romaddr_t exits     = file.readShortPointer(ptrExitsL, ptrExitsH, ptrExitsB, num);
    romaddr_t nextExits = file.readShortPointer(ptrExitsL, ptrExitsH, ptrExitsB, num+1);
    // the game subtracts consecutive pointers to calculate # of exits in current level
    uint numExits = (nextExits.addr - exits.addr) / 5;
    for (uint i = 0; i < numExits; i++) {
        exit_t *exit = new exit_t;
        romaddr_t thisExit = exits + (i * 5);
        uint8_t byte;

        // byte 0: exit type / screen
        byte = file.readByte(thisExit);
        uint screen = byte & 0xF;
        exit->type = byte >> 4;

        // byte 1: coordinates
        byte = file.readByte(thisExit + 1);
        exit->x = (screen % header->screensH * SCREEN_WIDTH) + (byte >> 4);
        exit->y = (screen / header->screensH * SCREEN_HEIGHT) + (byte & 0xF);

        // byte 2: LSB of destination
        exit->dest = file.readByte(thisExit + 2);

        // byte 3: MSB of destination / type / dest screen
        byte = file.readByte(thisExit + 3);
        if (byte & 0x80)
            exit->dest |= 0x100;
        exit->type |= (byte & 0x70);
        exit->destScreen = byte & 0xF;

        // byte 4: dest coordinates
        byte = file.readByte(thisExit + 4);
        exit->destX = byte >> 4;
        exit->destY = byte & 0xF;

        // if this is a "next level/boss" door, get that info too
        if (num < 8 && exit->type == 0x1F) {
            exit->bossLevel = file.readByte(bossExits + (num * 3));

            byte = file.readByte(bossExits + (num * 3) + 1);
            if (byte & 0x80)
                exit->bossLevel |= 0x100;

            exit->bossScreen = byte & 0xF;

            byte = file.readByte(bossExits + (num * 3) + 2);
            exit->bossX = byte >> 4;
            exit->bossY = byte & 0xF;
        } else {
            exit->bossLevel = 0;
            exit->bossScreen = 0;
            exit->bossX = 0;
            exit->bossY = 0;
        }

        level->exits.push_back(exit);
    }

    level->modified = false;

    return level;
}

/*
 * Returns a compressed data chunk based on level data (tile map only).
 * This is inserted into the big list of data chunks and then
 * later passed back to saveLevel in order to save it to the ROM
 * (and add it to the pointer table).
 */
DataChunk packLevel(const leveldata_t *level, uint num) {
    uint8_t buf[MAP_DATA_SIZE] = {0};
    header_t *header  = (header_t*)buf + 0;
    uint8_t  *screens = buf + 8;
    uint8_t  *tiles   = buf + 0xDA;

    *header = level->header;

    uint numScreens = level->header.screensV * level->header.screensH;

    // all current unique screens
    uint8_t uniques[16][SCREEN_SIZE] = {{0}};
    uint unique = 0;

    for (uint i = 0; i < numScreens; i++) {
        // temporary screen
        uint8_t tempScreen[SCREEN_SIZE] = {0};

        // write tile data for screen
        uint h = i % header->screensH;
        uint v = i / header->screensH;
        for (uint y = 0; y < SCREEN_HEIGHT; y++) {
            memcpy(tempScreen + (y * SCREEN_WIDTH),
                   &level->tiles[v * SCREEN_HEIGHT + y][h * SCREEN_WIDTH], SCREEN_WIDTH);
        }

        // does an identical screen already exist?
        bool found = false;
        for (uint s = 0; s < unique; s++) {
            if (!memcmp(uniques[s], tempScreen, SCREEN_SIZE)) {
                // reuse the same screen index
                screens[i] = s;
                found = true;
                break;
            }
        }
        if (found) continue;

        // write the new unique screen
        uint8_t *newScreen = tiles + (SCREEN_SIZE * unique);
        // to the level data
        memcpy(newScreen, tempScreen, SCREEN_SIZE);
        // and to the unique screens
        memcpy(uniques[unique], tempScreen, SCREEN_SIZE);

        // use a new screen index
        screens[i] = unique++;
    }

    // pack and return
    return DataChunk(buf, 0xDA + (SCREEN_SIZE * numScreens),
                     DataChunk::level, num);
}

DataChunk packSprites(const leveldata_t *level, uint num) {
    uint8_t buf[DATA_SIZE] = {0};

    // sort sprites by screen
    std::list<sprite_t> sprites;

    for (std::list<sprite_t*>::const_iterator i = level->sprites.begin();
         i != level->sprites.end(); i++) {

        sprite_t sprite = *(*i);

        // which screen is this sprite on?
        // (treat screens as 16 tiles tall instead of 12 - fixes issue #2)
        sprite.screen = (sprite.y / (SCREEN_HEIGHT + 4) * level->header.screensH)
                      + (sprite.x / SCREEN_WIDTH);

        sprites.push_back(sprite);
    }

    sprites.sort();

    uint numScreens = level->header.screensH * level->header.screensV;
    uint numSprites = sprites.size();

    uint8_t  *screens   = buf + 2;
    uint8_t  *positions = screens + numScreens;
    uint8_t  *types     = positions + numSprites;

    // write screen count bytes
    buf[0] = numScreens;
    buf[1] = level->header.screensV;

    uint sprNum = 0;
    for (std::list<sprite_t>::const_iterator i = sprites.begin(); i != sprites.end(); i++) {
        sprite_t sprite = *i;

        // update sprites-per-screen counts
        for (uint j = sprite.screen; j < numScreens; j++)
            screens[j]++;

        // sprite position and type
        positions[sprNum] = ((sprite.x % SCREEN_WIDTH) << 4) + (sprite.y % (SCREEN_HEIGHT + 4));
        types[sprNum]     = sprite.type;

        sprNum++;
    }

    // pack and return
    return DataChunk(buf, 2 + numScreens + numSprites + numSprites,
                     DataChunk::enemy, num);
}

/*
  Save a level back to the ROM and update the pointer table.
  Takes both a compressed data chunk for the tilemap (used to sort by size beforehand)
  and a pointer to the editor's own level struct for saving exits and other stuff.
*/
void saveLevel(ROMFile& file, const DataChunk &chunk, const leveldata_t *level, romaddr_t addr) {
    // level data banks mapped to A000-BFFF
    addr.addr %= BANK_SIZE;
    addr.addr += 0xA000;
    if (level->noReturn) addr.bank |= 0x80;

    // save compressed data chunk, update pointer table
    uint num = chunk.num;
    file.writeToPointer(ptrMapDataL, ptrMapDataH, ptrMapDataB, addr, chunk.size, chunk.data, num);

    // write tileset number
    file.writeByte(mapTilesets + num, level->tileset);

}

void saveExits(ROMFile& file, const leveldata_t *level, uint num) {
    romaddr_t addr = file.readShortPointer(ptrExitsL, ptrExitsH, ptrExitsB, num);

    for (std::list<exit_t*>::const_iterator i = level->exits.begin(); i != level->exits.end(); i++) {
        exit_t *exit = *i;
        uint8_t bytes[5];

        // byte 0: upper 4 = exit type & 0xF, lower 4 = screen exit is on
        bytes[0] = exit->type << 4;
        // calculate screen number
        bytes[0] |= (exit->y / SCREEN_HEIGHT * level->header.screensH)
                  + (exit->x / SCREEN_WIDTH);

        // byte 1: upper 4 = x, lower 4 = y
        bytes[1] = ((exit->x % SCREEN_WIDTH) << 4) | (exit->y % SCREEN_HEIGHT);

        // byte 2: level number lsb
        bytes[2] = exit->dest & 0xFF;

        // byte 3: upper bit = level number msbit, rest of upper = exit type & 0x70,
        //         lower = destination screen number
        bytes[3] = (exit->type & 0x70) | exit->destScreen;
        if (exit->dest >= 0x100)
            bytes[3] |= 0x80;

        // byte 4: destination x/y
        bytes[4] = (exit->destX << 4) | exit->destY;

        file.writeBytes(addr, 5, bytes);

        addr.addr += 5;

        // if this is a "next level/boss" door, save that info
        if (num < 8 && exit->type == 0x1F) {
            bytes[0] = exit->bossLevel & 0xFF;

            bytes[1] = exit->bossScreen;
            if (exit->bossLevel >= 0x100)
                bytes[1] |= 0x80;

            bytes[2] = (exit->bossX << 4) | exit->bossY;

            file.writeBytes(bossExits + (num * 3), 3, bytes);
        }
    }

    // write pointer for NEXT level
    file.writeByte(ptrExitsL + num + 1, addr.addr & 0xFF);
    file.writeByte(ptrExitsH + num + 1, addr.addr >> 8);
}

void saveSprites(ROMFile& file, const DataChunk& chunk, romaddr_t addr) {
    // level data banks mapped to A000-BFFF
    addr.addr %= BANK_SIZE;
    addr.addr += 0xA000;

    // save compressed data chunk, update pointer table
    uint num = chunk.num;
    file.writeToPointer(ptrSpritesL, ptrSpritesH, ptrSpritesB, addr, chunk.size, chunk.data, num);
}
<commit_msg>only merge identical screens for rot. towers<commit_after>/*
  level.cpp

  Contains functions for loading and saving level data.

  This code is released under the terms of the MIT license.
  See COPYING.txt for details.
*/

#include "compress.h"
#include "romfile.h"
#include "level.h"

#include <algorithm>
#include <cstring>
#include <cstdlib>
#include <cstdint>
#include <list>
#include <iostream>
#include <stdexcept>

#include <QMessageBox>
#include <QString>
#include <QCoreApplication>

#define MAP_DATA_SIZE 0xCDA

//Locations of chunk data in ROM (using CPU addressing.)
//currently assumes table locations are constant in all versions,
// may need to change this later to use version arrays like kdceditor
//...
const romaddr_t ptrMapDataL = {0x12, 0x88a6};
const romaddr_t ptrMapDataH = {0x12, 0x875f};
const romaddr_t ptrMapDataB = {0x12, 0x84d1};
const romaddr_t mapTilesets = {0x12, 0x8618};
const romaddr_t ptrSpritesL = {0x12, 0x8d0e};
const romaddr_t ptrSpritesH = {0x12, 0x8bc7};
const romaddr_t ptrSpritesB = {0x12, 0x8a80};
const romaddr_t ptrExitsL   = {0x12, 0x8f82};
const romaddr_t ptrExitsH   = {0x12, 0x90cb};
const uint      ptrExitsB   = 0x12;
const romaddr_t bossExits   = {0x12, 0x9c4a};

/*
  Load a level by number. Returns pointer to the level data as a struct.
  Returns null if a level failed and the user decided not to continue.
*/
leveldata_t* loadLevel (ROMFile& file, uint num) {
    //invalid data should at least be able to decompress fully
    uint8_t  buf[DATA_SIZE] = {0};
    header_t *header  = (header_t*)buf + 0;
    uint8_t  *screens = buf + 8;
    uint8_t  *tiles   = buf + 0xDA;

    size_t result = file.readFromPointer(ptrMapDataL, ptrMapDataH, ptrMapDataB, 0, buf, num);
    // TODO: "error reading level, attempt to continue?"
    if (result == 0) return NULL;

    leveldata_t *level;
    try {
        level = new leveldata_t;
    } catch (std::bad_alloc) {
        QMessageBox::critical(0,
                              "Load ROM",
                              QString("Unable to allocate memory for room %1").arg(num),
                              QMessageBox::Ok);
        return NULL;
    }

    memcpy(&level->header, header, sizeof(header_t));

    // make sure the level size is valid
    if (header->screensH * header->screensV > 16
            || header->screensH == 0
            || header->screensV == 0) {
        QMessageBox::critical(0,
                              "Load ROM",
                              QString("Unable to load room %1 because it has an invalid size.\n\n"
                                      "The ROM may be corrupt.").arg(num),
                              QMessageBox::Ok);

        delete level;
        return NULL;
    }

    // kinda slow, but eh
    for (uint y = 0; y < SCREEN_HEIGHT * header->screensV; y++) {
        for (uint x = 0; x < SCREEN_WIDTH * header->screensH; x++) {
            uint idx = (y / SCREEN_HEIGHT * header->screensH) + (x / SCREEN_WIDTH);
            uint8_t screen = screens[idx];
            level->tiles[y][x] = tiles[(screen * SCREEN_SIZE)
                    + (y % SCREEN_HEIGHT * 16) + (x % SCREEN_WIDTH)];
        }
    }

    // get tileset from table
    level->tileset = file.readByte(mapTilesets + num);

    // get "don't return on death" flag
    // (which is the highest bit of the level pointer's bank byte)
    level->noReturn = file.readByte(ptrMapDataB + num) & 0x80;

    // get sprite data
    romaddr_t spritePtr = file.readPointer(ptrSpritesL, ptrSpritesH, ptrSpritesB, num);
    // true number of screens (this may differ in levels more than 2 screens tall)
    uint sprScreens = file.readByte(spritePtr);

    // last # of sprite on each screen
    romaddr_t spriteCounts = spritePtr + 2;
    uint numSprites = file.readByte(spriteCounts + (sprScreens - 1));
    // position of each sprite
    romaddr_t spritePos    = spriteCounts + sprScreens;
    // type of each sprite
    romaddr_t spriteTypes  = spritePos + numSprites;

    uint sprNum = 0;
    for (uint i = 0; i < sprScreens; i++) {
        // number of sprites on this screen
        numSprites = file.readByte(spriteCounts + i);
        while (sprNum < numSprites) {
            sprite_t *sprite = new sprite_t;

            sprite->type = file.readByte(spriteTypes + sprNum);

            uint8_t pos  = file.readByte(spritePos + sprNum);

            // calculate normal x/y positions
            sprite->x = (i % header->screensH * SCREEN_WIDTH) + (pos >> 4);
            // for some stupid reason, HAL designed the sprite data so that
            // sprite coords / screen positions are based on screens being
            // 16 tiles tall instead of 12. changing this should put sprites
            // in the correct place all the time on vertical levels.
            // (fixes issue #2)
            sprite->y = (i / header->screensH * (SCREEN_HEIGHT + 4)) + (pos & 0xF);

            level->sprites.push_back(sprite);
            sprNum++;
        }
    }

    // get exit data
    romaddr_t exits     = file.readShortPointer(ptrExitsL, ptrExitsH, ptrExitsB, num);
    romaddr_t nextExits = file.readShortPointer(ptrExitsL, ptrExitsH, ptrExitsB, num+1);
    // the game subtracts consecutive pointers to calculate # of exits in current level
    uint numExits = (nextExits.addr - exits.addr) / 5;
    for (uint i = 0; i < numExits; i++) {
        exit_t *exit = new exit_t;
        romaddr_t thisExit = exits + (i * 5);
        uint8_t byte;

        // byte 0: exit type / screen
        byte = file.readByte(thisExit);
        uint screen = byte & 0xF;
        exit->type = byte >> 4;

        // byte 1: coordinates
        byte = file.readByte(thisExit + 1);
        exit->x = (screen % header->screensH * SCREEN_WIDTH) + (byte >> 4);
        exit->y = (screen / header->screensH * SCREEN_HEIGHT) + (byte & 0xF);

        // byte 2: LSB of destination
        exit->dest = file.readByte(thisExit + 2);

        // byte 3: MSB of destination / type / dest screen
        byte = file.readByte(thisExit + 3);
        if (byte & 0x80)
            exit->dest |= 0x100;
        exit->type |= (byte & 0x70);
        exit->destScreen = byte & 0xF;

        // byte 4: dest coordinates
        byte = file.readByte(thisExit + 4);
        exit->destX = byte >> 4;
        exit->destY = byte & 0xF;

        // if this is a "next level/boss" door, get that info too
        if (num < 8 && exit->type == 0x1F) {
            exit->bossLevel = file.readByte(bossExits + (num * 3));

            byte = file.readByte(bossExits + (num * 3) + 1);
            if (byte & 0x80)
                exit->bossLevel |= 0x100;

            exit->bossScreen = byte & 0xF;

            byte = file.readByte(bossExits + (num * 3) + 2);
            exit->bossX = byte >> 4;
            exit->bossY = byte & 0xF;
        } else {
            exit->bossLevel = 0;
            exit->bossScreen = 0;
            exit->bossX = 0;
            exit->bossY = 0;
        }

        level->exits.push_back(exit);
    }

    level->modified = false;

    return level;
}

/*
 * Returns a compressed data chunk based on level data (tile map only).
 * This is inserted into the big list of data chunks and then
 * later passed back to saveLevel in order to save it to the ROM
 * (and add it to the pointer table).
 */
DataChunk packLevel(const leveldata_t *level, uint num) {
    uint8_t buf[MAP_DATA_SIZE] = {0};
    header_t *header  = (header_t*)buf + 0;
    uint8_t  *screens = buf + 8;
    uint8_t  *tiles   = buf + 0xDA;

    *header = level->header;

    uint numScreens = level->header.screensV * level->header.screensH;

    // all current unique screens
    uint8_t uniques[16][SCREEN_SIZE] = {{0}};
    uint unique = 0;

    for (uint i = 0; i < numScreens; i++) {
        // temporary screen
        uint8_t tempScreen[SCREEN_SIZE] = {0};

        // write tile data for screen
        uint h = i % header->screensH;
        uint v = i / header->screensH;
        for (uint y = 0; y < SCREEN_HEIGHT; y++) {
            memcpy(tempScreen + (y * SCREEN_WIDTH),
                   &level->tiles[v * SCREEN_HEIGHT + y][h * SCREEN_WIDTH], SCREEN_WIDTH);
        }

        // combine unique screens instead of writing multiple copies of them.
        // this is currently only done for rotating tower rooms (0CD, 0D4, 0DF, 0E6)
        // because they require this in order for their exits to work correctly.
        // doing it anywhere else can cause destroyable tiles to inadvertedly
        // affect more than one part of the level at the same time.
        if (num == 0xCD || num == 0xD4 || num == 0xDF || num == 0xE6) {
            // does an identical screen already exist?
            bool found = false;
            for (uint s = 0; !found && s < unique; s++) {
                if (!memcmp(uniques[s], tempScreen, SCREEN_SIZE)) {
                    // reuse the same screen index
                    screens[i] = s;
                    found = true;
                }
            }
            if (found) continue;

            // add this screen to the unique screens
            memcpy(uniques[unique], tempScreen, SCREEN_SIZE);
        }

        // write the new unique screen to the level data
        uint8_t *newScreen = tiles + (SCREEN_SIZE * unique);
        memcpy(newScreen, tempScreen, SCREEN_SIZE);

        // use a new screen index
        screens[i] = unique++;
    }

    // pack and return
    return DataChunk(buf, 0xDA + (SCREEN_SIZE * numScreens),
                     DataChunk::level, num);
}

DataChunk packSprites(const leveldata_t *level, uint num) {
    uint8_t buf[DATA_SIZE] = {0};

    // sort sprites by screen
    std::list<sprite_t> sprites;

    for (std::list<sprite_t*>::const_iterator i = level->sprites.begin();
         i != level->sprites.end(); i++) {

        sprite_t sprite = *(*i);

        // which screen is this sprite on?
        // (treat screens as 16 tiles tall instead of 12 - fixes issue #2)
        sprite.screen = (sprite.y / (SCREEN_HEIGHT + 4) * level->header.screensH)
                      + (sprite.x / SCREEN_WIDTH);

        sprites.push_back(sprite);
    }

    sprites.sort();

    uint numScreens = level->header.screensH * level->header.screensV;
    uint numSprites = sprites.size();

    uint8_t  *screens   = buf + 2;
    uint8_t  *positions = screens + numScreens;
    uint8_t  *types     = positions + numSprites;

    // write screen count bytes
    buf[0] = numScreens;
    buf[1] = level->header.screensV;

    uint sprNum = 0;
    for (std::list<sprite_t>::const_iterator i = sprites.begin(); i != sprites.end(); i++) {
        sprite_t sprite = *i;

        // update sprites-per-screen counts
        for (uint j = sprite.screen; j < numScreens; j++)
            screens[j]++;

        // sprite position and type
        positions[sprNum] = ((sprite.x % SCREEN_WIDTH) << 4) + (sprite.y % (SCREEN_HEIGHT + 4));
        types[sprNum]     = sprite.type;

        sprNum++;
    }

    // pack and return
    return DataChunk(buf, 2 + numScreens + numSprites + numSprites,
                     DataChunk::enemy, num);
}

/*
  Save a level back to the ROM and update the pointer table.
  Takes both a compressed data chunk for the tilemap (used to sort by size beforehand)
  and a pointer to the editor's own level struct for saving exits and other stuff.
*/
void saveLevel(ROMFile& file, const DataChunk &chunk, const leveldata_t *level, romaddr_t addr) {
    // level data banks mapped to A000-BFFF
    addr.addr %= BANK_SIZE;
    addr.addr += 0xA000;
    if (level->noReturn) addr.bank |= 0x80;

    // save compressed data chunk, update pointer table
    uint num = chunk.num;
    file.writeToPointer(ptrMapDataL, ptrMapDataH, ptrMapDataB, addr, chunk.size, chunk.data, num);

    // write tileset number
    file.writeByte(mapTilesets + num, level->tileset);

}

void saveExits(ROMFile& file, const leveldata_t *level, uint num) {
    romaddr_t addr = file.readShortPointer(ptrExitsL, ptrExitsH, ptrExitsB, num);

    for (std::list<exit_t*>::const_iterator i = level->exits.begin(); i != level->exits.end(); i++) {
        exit_t *exit = *i;
        uint8_t bytes[5];

        // byte 0: upper 4 = exit type & 0xF, lower 4 = screen exit is on
        bytes[0] = exit->type << 4;
        // calculate screen number
        bytes[0] |= (exit->y / SCREEN_HEIGHT * level->header.screensH)
                  + (exit->x / SCREEN_WIDTH);

        // byte 1: upper 4 = x, lower 4 = y
        bytes[1] = ((exit->x % SCREEN_WIDTH) << 4) | (exit->y % SCREEN_HEIGHT);

        // byte 2: level number lsb
        bytes[2] = exit->dest & 0xFF;

        // byte 3: upper bit = level number msbit, rest of upper = exit type & 0x70,
        //         lower = destination screen number
        bytes[3] = (exit->type & 0x70) | exit->destScreen;
        if (exit->dest >= 0x100)
            bytes[3] |= 0x80;

        // byte 4: destination x/y
        bytes[4] = (exit->destX << 4) | exit->destY;

        file.writeBytes(addr, 5, bytes);

        addr.addr += 5;

        // if this is a "next level/boss" door, save that info
        if (num < 8 && exit->type == 0x1F) {
            bytes[0] = exit->bossLevel & 0xFF;

            bytes[1] = exit->bossScreen;
            if (exit->bossLevel >= 0x100)
                bytes[1] |= 0x80;

            bytes[2] = (exit->bossX << 4) | exit->bossY;

            file.writeBytes(bossExits + (num * 3), 3, bytes);
        }
    }

    // write pointer for NEXT level
    file.writeByte(ptrExitsL + num + 1, addr.addr & 0xFF);
    file.writeByte(ptrExitsH + num + 1, addr.addr >> 8);
}

void saveSprites(ROMFile& file, const DataChunk& chunk, romaddr_t addr) {
    // level data banks mapped to A000-BFFF
    addr.addr %= BANK_SIZE;
    addr.addr += 0xA000;

    // save compressed data chunk, update pointer table
    uint num = chunk.num;
    file.writeToPointer(ptrSpritesL, ptrSpritesH, ptrSpritesB, addr, chunk.size, chunk.data, num);
}
<|endoftext|>


<commit_before>#include <iostream>
#include <fstream>
#include <string>

// Loriano: let's try Armadillo quick code
#include <armadillo>

#define ENTDIM 8
#define COORDIM (ENTDIM-2)

namespace
{
  int numofline (const char * fname)
  {
    int number_of_lines = 0;
    std::string line;
    std::ifstream myfile(fname);

    while (std::getline(myfile, line))
      ++number_of_lines;

    myfile.close();

    return number_of_lines;
  }
}

int main (int argc, char ** argv)
{
  if (argc != 2)
  {
    std::cerr << "usage: " << argv[0] << " coordinatesfile " << std::endl;
    return 1;
  }

  int num_of_line = numofline(argv[1]);
  std::cout << "file has " << num_of_line << " line " << std::endl;
  int num_of_ent = (num_of_line-1)/ENTDIM;
  std::cout << "  " << num_of_ent << " entries " << std::endl;

  // non perfomante ma easy to go
  double ** param_mtx = new double *[num_of_ent];
  double ** coord_mtx = new double *[num_of_ent];
  for (int i = 0; i < num_of_ent; ++i)
  {
    coord_mtx[i] = new double[3*COORDIM];
    param_mtx[i] = new double[5];
  }

  // leggere file coordinate tracce simulate plus parametri
  std::string line;
  std::ifstream mytfp;
  mytfp.open (argv[1], std::ios::in);

  std::getline (mytfp, line);
  //std::cout << line << std::endl;

  for (int i = 0; i < num_of_ent; ++i)
  {
    int fake1, fake2;
    mytfp >> fake1 >> fake2 ;
#ifdef DEBUG
    std::cout << fake1 << " " << fake2 << std::endl;
#endif
    for (int j = 0; j < COORDIM; ++j)
    {
      int a, b, c;
      mytfp >> coord_mtx[i][j*3] >>
               coord_mtx[i][j*3+1] >>
               coord_mtx[i][j*3+2] >>
               a >> b >> c;
    }
    mytfp >> param_mtx[i][0] >>
             param_mtx[i][1] >>
             param_mtx[i][2] >>
             param_mtx[i][3] >>
             param_mtx[i][4];
  }

  mytfp.close();

#ifdef DEBUG
  for (int i = 0; i < num_of_ent; ++i)
  {
    for (int j = 0; j < COORDIM; ++j)
    {
      std::cout << coord_mtx[i][j*3] << " " <<
                   coord_mtx[i][j*3+1] << " " <<
                   coord_mtx[i][j*3+2] << std::endl;
    }
    std::cout << param_mtx[i][0] << " " <<
                 param_mtx[i][1] << " " <<
                 param_mtx[i][2] << " " <<
                 param_mtx[i][3] << " " <<
                 param_mtx[i][4] << std::endl;
  }
#endif

  double sum = 1.0e0;
  double coordm[3*COORDIM] = {0.0e0};
  double hc[3*COORDIM][3*COORDIM] = {0.0e0};

  for (int l=0; l<num_of_ent; ++l)
  {
    sum += 1.0e0;
    for (int i=0; i<(3*COORDIM); ++i)
      coordm[i] += (coord_mtx[l][i]-coordm[i])/sum;

    for (int i=0; i<(3*COORDIM); ++i)
    {
      for (int j=0; j<(3*COORDIM); ++j)
      {
        hc[i][j] += ((coord_mtx[l][i] - coordm[i])*
                     (coord_mtx[l][j] - coordm[j])-
                     (sum-1.0e0)*hc[i][j]/sum)/(sum-1.0e0);
      }
    }
  }

  for (int i=0; i<(3*COORDIM); ++i)
    for (int j=i+1; j<(3*COORDIM); ++j)
      if (hc[i][j] != hc[j][i])
        std::cout << i << " " << j << " " <<
          hc[i][j] << " ERROR" << std::endl;;

  arma::mat hca = arma::zeros<arma::mat>(3*COORDIM,3*COORDIM);
  for (int i=0; i<(3*COORDIM); ++i)
    for (int j=0; j<(3*COORDIM); ++j)
      hca(i,j) = hc[i][j];

  arma::vec eigval;
  arma::mat eigvec;

  arma::eig_sym(eigval, eigvec, hca);

  double totval = 0.0e0;
  for (int i=0; i<(3*COORDIM); ++i)
    totval += eigval(i);

  int j = 1;
  double totvar = 0.0e0;
  for (int i=(3*COORDIM-1); i>=0; --i)
  {
    if (j <= 5)
      totvar += 100.0e0*(eigval(i)/totval);
    ++j;

    std::cout << i+1 << " ==> " << 100.0e0*(eigval(i)/totval) << std::endl;
  }
  std::cout << "5 eigenvalues: " << totvar << std::endl;

  arma::mat hcai = arma::zeros<arma::mat>(3*COORDIM,3*COORDIM);
  hcai = hca.i();

  std::cout << hca * hcai ;

  // and so on ...

  // documento Annovi
  // calcolo matrice di correlazione traccie HC
  // diagonalizzo HC e determino A, matrice 5 autovettori principali (5 componenti pricipali)
  // A matrice rotazione che mi permette di calcolare la traslazione usando i paamtri di tracce
  // simulate.

  // documento ATLAS
  // calcolare V e data V calcolare inversa V e quindi C, matrice di rotazione
  // data C determinare il vettore di traslazione q
  // c plus q costanti PCA
  // write constants in a file

  for (int i = 0; i < num_of_ent; ++i)
  {
    delete(coord_mtx[i]);
    delete(param_mtx[i]);
  }
  delete(coord_mtx);
  delete(param_mtx);

  return 0;
}
<commit_msg>add covariane between trace and parameter (just a backup cjheck it)<commit_after>#include <iostream>
#include <fstream>
#include <string>

// Loriano: let's try Armadillo quick code
#include <armadillo>

#define ENTDIM 8
#define COORDIM (ENTDIM-2)
#define PARAMDIM 5

namespace
{
  int numofline (const char * fname)
  {
    int number_of_lines = 0;
    std::string line;
    std::ifstream myfile(fname);

    while (std::getline(myfile, line))
      ++number_of_lines;

    myfile.close();

    return number_of_lines;
  }
}

int main (int argc, char ** argv)
{
  if (argc != 2)
  {
    std::cerr << "usage: " << argv[0] << " coordinatesfile " << std::endl;
    return 1;
  }

  int num_of_line = numofline(argv[1]);
  std::cout << "file has " << num_of_line << " line " << std::endl;
  int num_of_ent = (num_of_line-1)/ENTDIM;
  std::cout << "  " << num_of_ent << " entries " << std::endl;

  // non perfomante ma easy to go
  double ** param_mtx = new double *[num_of_ent];
  double ** coord_mtx = new double *[num_of_ent];
  for (int i = 0; i < num_of_ent; ++i)
  {
    coord_mtx[i] = new double[3*COORDIM];
    param_mtx[i] = new double[PARAMDIM];
  }

  // leggere file coordinate tracce simulate plus parametri
  std::string line;
  std::ifstream mytfp;
  mytfp.open (argv[1], std::ios::in);

  std::getline (mytfp, line);
  //std::cout << line << std::endl;

  for (int i = 0; i < num_of_ent; ++i)
  {
    int fake1, fake2;
    mytfp >> fake1 >> fake2 ;
#ifdef DEBUG
    std::cout << fake1 << " " << fake2 << std::endl;
#endif
    for (int j = 0; j < COORDIM; ++j)
    {
      int a, b, c;
      mytfp >> coord_mtx[i][j*3] >>
               coord_mtx[i][j*3+1] >>
               coord_mtx[i][j*3+2] >>
               a >> b >> c;
    }
    mytfp >> param_mtx[i][0] >>
             param_mtx[i][1] >>
             param_mtx[i][2] >>
             param_mtx[i][3] >>
             param_mtx[i][4];
  }

  mytfp.close();

#ifdef DEBUG
  for (int i = 0; i < num_of_ent; ++i)
  {
    for (int j = 0; j < COORDIM; ++j)
    {
      std::cout << coord_mtx[i][j*3] << " " <<
                   coord_mtx[i][j*3+1] << " " <<
                   coord_mtx[i][j*3+2] << std::endl;
    }
    std::cout << param_mtx[i][0] << " " <<
                 param_mtx[i][1] << " " <<
                 param_mtx[i][2] << " " <<
                 param_mtx[i][3] << " " <<
                 param_mtx[i][4] << std::endl;
  }
#endif

  double sum = 1.0e0;
  double coordm[3*COORDIM] = {0.0e0};
  double hc[3*COORDIM][3*COORDIM] = {0.0e0};

  for (int l=0; l<num_of_ent; ++l)
  {
    sum += 1.0e0;
    for (int i=0; i<(3*COORDIM); ++i)
      coordm[i] += (coord_mtx[l][i]-coordm[i])/sum;

    for (int i=0; i<(3*COORDIM); ++i)
    {
      for (int j=0; j<(3*COORDIM); ++j)
      {
        hc[i][j] += ((coord_mtx[l][i] - coordm[i])*
                     (coord_mtx[l][j] - coordm[j])-
                     (sum-1.0e0)*hc[i][j]/sum)/(sum-1.0e0);
      }
    }
  }

  for (int i=0; i<(3*COORDIM); ++i)
    for (int j=i+1; j<(3*COORDIM); ++j)
      if (hc[i][j] != hc[j][i])
        std::cout << i << " " << j << " " <<
          hc[i][j] << " ERROR" << std::endl;;

  arma::mat hca = arma::zeros<arma::mat>(3*COORDIM,3*COORDIM);
  for (int i=0; i<(3*COORDIM); ++i)
    for (int j=0; j<(3*COORDIM); ++j)
      hca(i,j) = hc[i][j];

  arma::vec eigval;
  arma::mat eigvec;

  arma::eig_sym(eigval, eigvec, hca);

  double totval = 0.0e0;
  for (int i=0; i<(3*COORDIM); ++i)
    totval += eigval(i);

  int j = 1;
  double totvar = 0.0e0;
  for (int i=(3*COORDIM-1); i>=0; --i)
  {
    if (j <= PARAMDIM)
      totvar += 100.0e0*(eigval(i)/totval);
    ++j;

    std::cout << i+1 << " ==> " << 100.0e0*(eigval(i)/totval) << std::endl;
  }
  std::cout << "PARAMDIM eigenvalues: " << totvar << std::endl;

  arma::mat hcai = arma::zeros<arma::mat>(3*COORDIM,3*COORDIM);
  hcai = hca.i();

  //std::cout << hca * hcai ;

  // and so on ...
  std::fill(coordm, &(coordm[3*COORDIM]), 0.0e0 );
  double paramm[PARAMDIM] = {0.0e0};
  double hcp[3*COORDIM][PARAMDIM] = {0.0e0};

  for (int l=0; l<num_of_ent; ++l)
  {
    sum += 1.0e0;
    for (int i=0; i<(3*COORDIM); ++i)
      coordm[i] += (coord_mtx[l][i]-coordm[i])/sum;

    for (int i=0; i<(3*COORDIM); ++i)
      paramm[i] += (param_mtx[l][i]-paramm[i])/sum;

    for (int i=0; i<(3*COORDIM); ++i)
    {
      for (int j=0; j<PARAMDIM; ++j)
      {
        hcp[i][j] += ((coord_mtx[l][i] - coordm[i])*
                     (param_mtx[l][j] - paramm[j])-
                     (sum-1.0e0)*hcp[i][j]/sum)/(sum-1.0e0);
      }
    }
  }

  // documento Annovi
  // calcolo matrice di correlazione traccie HC
  // diagonalizzo HC e determino A, matrice 5 autovettori principali (5 componenti pricipali)
  // A matrice rotazione che mi permette di calcolare la traslazione usando i paamtri di tracce
  // simulate.

  // documento ATLAS
  // calcolare V e data V calcolare inversa V e quindi C, matrice di rotazione
  // data C determinare il vettore di traslazione q
  // c plus q costanti PCA
  // write constants in a file

  for (int i = 0; i < num_of_ent; ++i)
  {
    delete(coord_mtx[i]);
    delete(param_mtx[i]);
  }
  delete(coord_mtx);
  delete(param_mtx);

  return 0;
}
<|endoftext|>


<commit_before>#include "lexer.hpp"

#include <cctype>
#include <algorithm>
#include <iterator>
#include <vector>

namespace klang {
namespace {
  using const_iterator = std::string::const_iterator;
}

Token::Token()
  : type_(TokenType::UNKNOWN), str_(), line_(-1)
{}

Token::Token(TokenType type, const std::string& str, int line)
  : type_(type), str_(str), line_(line)
{}

TokenType Token::type() const { return type_; }
std::string Token::str() const { return str_; }
int Token::line() const { return line_; }

bool alphabet(char c) {
  return std::isalpha(c);
}

bool alphabet_or_bar(char c) {
  return (c == '_' || alphabet(c));
}

bool nonzero_digit(char c) {
  return (c >= '1' && c <= '9');
}

bool decimal_digit(char c) {
  return std::isdigit(c);
}

bool identifier(const std::string& str) {
  if (str.empty() || !alphabet_or_bar(str.front())) {
    return false;
  }
  for (char c : str) {
    if (!alphabet_or_bar(c) && !decimal_digit(c)) {
      return false;
    }
  }
  return true;
}

bool decimal_integer(const std::string& str) {
  if (str == "0") return true;
  if (str.empty() || !nonzero_digit(str.front())) {
    return false;
  }
  for (char c : str) {
    if (!decimal_digit(c)) {
      return false;
    }
  }
  return true;
}

bool symbol(const_iterator head, const_iterator tail) {
  using std::begin;
  using std::end;
  std::string const str(head, tail);
  static std::vector<std::string> const symbol_list = {
    "~", "+", "-", "*", "/", "%",
    ":=", ":+=", ":-=", ":*=", ":/=", ":%=",
    "=", "=/", "<", ">", "<=", ">=",
    ";", "(", ")", "{", "}", "->", "~}",
    "and", "or", "not", "int", "def", "var",
    "if", "else", "while", "for", "break", "continue", "return"
  };
  return (std::find(begin(symbol_list), end(symbol_list), str) != end(symbol_list));
}

bool ignore(const std::string& str) {
  if(str.size() != 1) return false;
  return std::isspace(str[0]);
}

bool singleline_comment(const_iterator head, const_iterator tail) {
  using std::begin;
  using std::end;
  if(std::equal(head, std::next(head, 2), "~~")) {
      return std::find(head, tail, '\n') == std::prev(tail);
  }
  return false;
}

bool multiline_comment(const_iterator head, const_iterator tail) {
  using std::begin;
  using std::end;
  if (std::equal(head, std::next(head, 2), "{~")) {
    int nest = 0;
    for(auto it = head; std::next(it) != tail; ++it) {
      std::string tk(it, std::next(it, 2));
      if (tk == "{~") {
        ++nest;
      } else if(tk == "~}") {
        --nest;
      }
    }
    bool closed = nest == 0 && std::equal(std::prev(tail, 2), std::prev(tail), "~}");
    return (nest > 0 || closed);
  }
  return false;
}

bool comment(const_iterator head, const_iterator tail) {
  return (singleline_comment(head, tail) || multiline_comment(head, tail));
}

bool string_token(const std::string& str) {
  using std::begin;
  using std::end;
  if (str.front() == '"') {
    bool escaped = false;
    for(auto it = std::next(begin(str)); it != end(str); ++it) {
      if (*it == '\\') {
        escaped = true;
      } else if (*it == '"' && (!escaped)) {
        return std::next(it) == end(str);
      } else {
        escaped = false;
      }
    }
  }
  return false;
}

TokenType match_type(const_iterator head, const_iterator tail) {
  if (comment(head, tail)) return TokenType::IGNORE;
  if (symbol(head, tail)) return TokenType::SYMBOL;
  if (identifier(head, tail)) return TokenType::IDENTIFIER;
  if (decimal_integer(head, tail)) return TokenType::NUMBER;
  if (string_token(head, tail)) return TokenType::STRING;
  if (ignore(head, tail)) return TokenType::IGNORE;
  return TokenType::UNKNOWN;
}

std::string extract_string(const std::string& str) {
  if (str.front() == '"') {
    bool escaped = false;
    std::string new_str;
    for(auto c : str) {
      if (escaped) {
        if(c == '"') new_str.push_back('"');
        if(c == 'n') new_str.push_back('\n');
        escaped = false;
      } else if (c == '\\') {
        escaped = true;
      } else if (c != '"') {
        new_str.push_back(c);
      }
    }
    return new_str;
  }
  return str;
}

TokenVector tokenize(std::istream& is) {
  using std::begin;
  using std::end;
  std::string const code(std::string{std::istreambuf_iterator<char>(is), std::istreambuf_iterator<char>()} + '\n');
  // ファイルの末尾が改行で終わっているほうが処理しやすい。
  TokenVector tokens;
  TokenType prev = TokenType::UNKNOWN;
  const_iterator head(begin(code));
  int line = 1;
  for (auto it(begin(code)); it != end(code); ++it) {
    TokenType next = match_type(head, std::next(it));
    if (prev != TokenType::UNKNOWN && next == TokenType::UNKNOWN) {
      if (prev != TokenType::IGNORE) {
        tokens.push_back(Token(prev, extract_string(head, it), line));
      }
      head = it;
      prev = match_type(head, std::next(head));
    } else {
      prev = next;
    }
    if (*it == '\n') ++line;
  }
  return tokens;
}

bool operator==(Token const& lhs, Token const& rhs) {
  return lhs.type() == rhs.type()
      && lhs.str()  == rhs.str()
      && lhs.line() == rhs.line();
}
bool operator!=(Token const& lhs, Token const& rhs) {
  return !( lhs == rhs );
}

}  // namespace klang
<commit_msg>identifier を対応<commit_after>#include "lexer.hpp"

#include <cctype>
#include <algorithm>
#include <iterator>
#include <vector>

namespace klang {
namespace {
  using const_iterator = std::string::const_iterator;
}

Token::Token()
  : type_(TokenType::UNKNOWN), str_(), line_(-1)
{}

Token::Token(TokenType type, const std::string& str, int line)
  : type_(type), str_(str), line_(line)
{}

TokenType Token::type() const { return type_; }
std::string Token::str() const { return str_; }
int Token::line() const { return line_; }

bool alphabet(char c) {
  return std::isalpha(c);
}

bool alphabet_or_bar(char c) {
  return (c == '_' || alphabet(c));
}

bool nonzero_digit(char c) {
  return (c >= '1' && c <= '9');
}

bool decimal_digit(char c) {
  return std::isdigit(c);
}

bool identifier(const_iterator head, const_iterator tail) {
  if (head == tail || !alphabet_or_bar(*head)) {
    return false;
  }
  for (auto it(head); it != tail; ++it) {
    if (!alphabet_or_bar(*it) && !decimal_digit(*it)) {
      return false;
    }
  }
  return true;
}

bool decimal_integer(const std::string& str) {
  if (str == "0") return true;
  if (str.empty() || !nonzero_digit(str.front())) {
    return false;
  }
  for (char c : str) {
    if (!decimal_digit(c)) {
      return false;
    }
  }
  return true;
}

bool symbol(const_iterator head, const_iterator tail) {
  using std::begin;
  using std::end;
  std::string const str(head, tail);
  static std::vector<std::string> const symbol_list = {
    "~", "+", "-", "*", "/", "%",
    ":=", ":+=", ":-=", ":*=", ":/=", ":%=",
    "=", "=/", "<", ">", "<=", ">=",
    ";", "(", ")", "{", "}", "->", "~}",
    "and", "or", "not", "int", "def", "var",
    "if", "else", "while", "for", "break", "continue", "return"
  };
  return (std::find(begin(symbol_list), end(symbol_list), str) != end(symbol_list));
}

bool ignore(const std::string& str) {
  if(str.size() != 1) return false;
  return std::isspace(str[0]);
}

bool singleline_comment(const_iterator head, const_iterator tail) {
  using std::begin;
  using std::end;
  if(std::equal(head, std::next(head, 2), "~~")) {
      return std::find(head, tail, '\n') == std::prev(tail);
  }
  return false;
}

bool multiline_comment(const_iterator head, const_iterator tail) {
  using std::begin;
  using std::end;
  if (std::equal(head, std::next(head, 2), "{~")) {
    int nest = 0;
    for(auto it = head; std::next(it) != tail; ++it) {
      std::string tk(it, std::next(it, 2));
      if (tk == "{~") {
        ++nest;
      } else if(tk == "~}") {
        --nest;
      }
    }
    bool closed = nest == 0 && std::equal(std::prev(tail, 2), std::prev(tail), "~}");
    return (nest > 0 || closed);
  }
  return false;
}

bool comment(const_iterator head, const_iterator tail) {
  return (singleline_comment(head, tail) || multiline_comment(head, tail));
}

bool string_token(const std::string& str) {
  using std::begin;
  using std::end;
  if (str.front() == '"') {
    bool escaped = false;
    for(auto it = std::next(begin(str)); it != end(str); ++it) {
      if (*it == '\\') {
        escaped = true;
      } else if (*it == '"' && (!escaped)) {
        return std::next(it) == end(str);
      } else {
        escaped = false;
      }
    }
  }
  return false;
}

TokenType match_type(const_iterator head, const_iterator tail) {
  if (comment(head, tail)) return TokenType::IGNORE;
  if (symbol(head, tail)) return TokenType::SYMBOL;
  if (identifier(head, tail)) return TokenType::IDENTIFIER;
  if (decimal_integer(head, tail)) return TokenType::NUMBER;
  if (string_token(head, tail)) return TokenType::STRING;
  if (ignore(head, tail)) return TokenType::IGNORE;
  return TokenType::UNKNOWN;
}

std::string extract_string(const std::string& str) {
  if (str.front() == '"') {
    bool escaped = false;
    std::string new_str;
    for(auto c : str) {
      if (escaped) {
        if(c == '"') new_str.push_back('"');
        if(c == 'n') new_str.push_back('\n');
        escaped = false;
      } else if (c == '\\') {
        escaped = true;
      } else if (c != '"') {
        new_str.push_back(c);
      }
    }
    return new_str;
  }
  return str;
}

TokenVector tokenize(std::istream& is) {
  using std::begin;
  using std::end;
  std::string const code(std::string{std::istreambuf_iterator<char>(is), std::istreambuf_iterator<char>()} + '\n');
  // ファイルの末尾が改行で終わっているほうが処理しやすい。
  TokenVector tokens;
  TokenType prev = TokenType::UNKNOWN;
  const_iterator head(begin(code));
  int line = 1;
  for (auto it(begin(code)); it != end(code); ++it) {
    TokenType next = match_type(head, std::next(it));
    if (prev != TokenType::UNKNOWN && next == TokenType::UNKNOWN) {
      if (prev != TokenType::IGNORE) {
        tokens.push_back(Token(prev, extract_string(head, it), line));
      }
      head = it;
      prev = match_type(head, std::next(head));
    } else {
      prev = next;
    }
    if (*it == '\n') ++line;
  }
  return tokens;
}

bool operator==(Token const& lhs, Token const& rhs) {
  return lhs.type() == rhs.type()
      && lhs.str()  == rhs.str()
      && lhs.line() == rhs.line();
}
bool operator!=(Token const& lhs, Token const& rhs) {
  return !( lhs == rhs );
}

}  // namespace klang
<|endoftext|>


<commit_before><commit_msg>Use +=<commit_after><|endoftext|>


<commit_before><commit_msg>coverity#1257108 Explicit null dereferenced<commit_after><|endoftext|>