<commit_before>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#include "columniterator.hxx"
#include "column.hxx"
#include "document.hxx"
#include "table.hxx"

ScColumnTextWidthIterator::ScColumnTextWidthIterator(ScColumn& rCol, SCROW nStartRow, SCROW nEndRow) :
    mrCellTextAttrs(rCol.maCellTextAttrs),
    mnEnd(static_cast<size_t>(nEndRow)),
    mnCurPos(0),
    miBlockCur(mrCellTextAttrs.begin()),
    miBlockEnd(mrCellTextAttrs.end())
{
    init(nStartRow, nEndRow);
}

ScColumnTextWidthIterator::ScColumnTextWidthIterator(ScDocument& rDoc, const ScAddress& rStartPos, SCROW nEndRow) :
    mrCellTextAttrs(rDoc.maTabs[rStartPos.Tab()]->aCol[rStartPos.Col()].maCellTextAttrs),
    mnEnd(static_cast<size_t>(nEndRow)),
    mnCurPos(0),
    miBlockCur(mrCellTextAttrs.begin()),
    miBlockEnd(mrCellTextAttrs.end())
{
    init(rStartPos.Row(), nEndRow);
}

void ScColumnTextWidthIterator::next()
{
    ++miDataCur;
    ++mnCurPos;

    if (miDataCur != miDataEnd)
    {
        // Stil in the same block. We're good.
        checkEndRow();
        return;
    }

    // Move to the next block.
    for (++miBlockCur; miBlockCur != miBlockEnd; ++miBlockCur)
    {
        if (miBlockCur->type != sc::element_type_celltextattr)
        {
            // We don't iterator over this block.
            mnCurPos += miBlockCur->size;
            continue;
        }

        getDataIterators(0);
        checkEndRow();
        return;
    }

    // Reached the end.
    OSL_ASSERT(miBlockCur == miBlockEnd);
}

bool ScColumnTextWidthIterator::hasCell() const
{
    return miBlockCur != miBlockEnd;
}

SCROW ScColumnTextWidthIterator::getPos() const
{
    OSL_ASSERT(miBlockCur != miBlockEnd && miDataCur != miDataEnd);
    return static_cast<SCROW>(mnCurPos);
}

sal_uInt16 ScColumnTextWidthIterator::getValue() const
{
    OSL_ASSERT(miBlockCur != miBlockEnd && miDataCur != miDataEnd);
    return miDataCur->mnTextWidth;
}

void ScColumnTextWidthIterator::setValue(sal_uInt16 nVal)
{
    OSL_ASSERT(miBlockCur != miBlockEnd && miDataCur != miDataEnd);
    miDataCur->mnTextWidth = nVal;
}

void ScColumnTextWidthIterator::init(SCROW nStartRow, SCROW nEndRow)
{
    if (!ValidRow(nStartRow) || !ValidRow(nEndRow))
        miBlockCur = miBlockEnd;

    size_t nStart = static_cast<size_t>(nStartRow);

    // Locate the start row position.
    size_t nBlockStart = 0, nBlockEnd = 0;
    for (; miBlockCur != miBlockEnd; ++miBlockCur, nBlockStart = nBlockEnd)
    {
        nBlockEnd = nBlockStart + miBlockCur->size; // non-inclusive end point.
        if (nBlockStart <= nStart && nStart < nBlockEnd)
        {
            // Initial block is found!
            break;
        }
    }

    if (miBlockCur == miBlockEnd)
        // Initial block not found for whatever reason... Bail out.
        return;

    // Locate the initial row position within this block.
    if (miBlockCur->type == sc::element_type_celltextattr)
    {
        // This block stores text widths for non-empty cells.
        size_t nOffsetInBlock = nStart - nBlockStart;
        mnCurPos = nStart;
        getDataIterators(nOffsetInBlock);
        checkEndRow();
        return;
    }

    // Current block is not of ushort type.  Skip to the next block.
    nBlockStart = nBlockEnd;
    ++miBlockCur;

    // Look for the first ushort block.
    for (; miBlockCur != miBlockEnd; ++miBlockCur, nBlockStart = nBlockEnd)
    {
        nBlockEnd = nBlockStart + miBlockCur->size; // non-inclusive end point.
        if (miBlockCur->type != sc::element_type_celltextattr)
            continue;

        // Found!
        mnCurPos = nBlockStart;
        getDataIterators(0);
        checkEndRow();
        return;
    }

    // Not found.
    OSL_ASSERT(miBlockCur == miBlockEnd);
}

void ScColumnTextWidthIterator::getDataIterators(size_t nOffsetInBlock)
{
    OSL_ENSURE(miBlockCur != miBlockEnd, "block is at end position");
    OSL_ENSURE(miBlockCur->type == sc::custom_celltextattr_block,
               "wrong block type - unsigned short block expected.");

    miDataCur = sc::custom_celltextattr_block::begin(*miBlockCur->data);
    miDataEnd = sc::custom_celltextattr_block::end(*miBlockCur->data);

    std::advance(miDataCur, nOffsetInBlock);
}

void ScColumnTextWidthIterator::checkEndRow()
{
    if (mnCurPos <= mnEnd)
        // We're still good.
        return;

    // We're below the end position. End the iteration.
    miBlockCur = miBlockEnd;
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<commit_msg>Bypass for now an OSL_ENSURE that doesn't compile<commit_after>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#include "columniterator.hxx"
#include "column.hxx"
#include "document.hxx"
#include "table.hxx"

ScColumnTextWidthIterator::ScColumnTextWidthIterator(ScColumn& rCol, SCROW nStartRow, SCROW nEndRow) :
    mrCellTextAttrs(rCol.maCellTextAttrs),
    mnEnd(static_cast<size_t>(nEndRow)),
    mnCurPos(0),
    miBlockCur(mrCellTextAttrs.begin()),
    miBlockEnd(mrCellTextAttrs.end())
{
    init(nStartRow, nEndRow);
}

ScColumnTextWidthIterator::ScColumnTextWidthIterator(ScDocument& rDoc, const ScAddress& rStartPos, SCROW nEndRow) :
    mrCellTextAttrs(rDoc.maTabs[rStartPos.Tab()]->aCol[rStartPos.Col()].maCellTextAttrs),
    mnEnd(static_cast<size_t>(nEndRow)),
    mnCurPos(0),
    miBlockCur(mrCellTextAttrs.begin()),
    miBlockEnd(mrCellTextAttrs.end())
{
    init(rStartPos.Row(), nEndRow);
}

void ScColumnTextWidthIterator::next()
{
    ++miDataCur;
    ++mnCurPos;

    if (miDataCur != miDataEnd)
    {
        // Stil in the same block. We're good.
        checkEndRow();
        return;
    }

    // Move to the next block.
    for (++miBlockCur; miBlockCur != miBlockEnd; ++miBlockCur)
    {
        if (miBlockCur->type != sc::element_type_celltextattr)
        {
            // We don't iterator over this block.
            mnCurPos += miBlockCur->size;
            continue;
        }

        getDataIterators(0);
        checkEndRow();
        return;
    }

    // Reached the end.
    OSL_ASSERT(miBlockCur == miBlockEnd);
}

bool ScColumnTextWidthIterator::hasCell() const
{
    return miBlockCur != miBlockEnd;
}

SCROW ScColumnTextWidthIterator::getPos() const
{
    OSL_ASSERT(miBlockCur != miBlockEnd && miDataCur != miDataEnd);
    return static_cast<SCROW>(mnCurPos);
}

sal_uInt16 ScColumnTextWidthIterator::getValue() const
{
    OSL_ASSERT(miBlockCur != miBlockEnd && miDataCur != miDataEnd);
    return miDataCur->mnTextWidth;
}

void ScColumnTextWidthIterator::setValue(sal_uInt16 nVal)
{
    OSL_ASSERT(miBlockCur != miBlockEnd && miDataCur != miDataEnd);
    miDataCur->mnTextWidth = nVal;
}

void ScColumnTextWidthIterator::init(SCROW nStartRow, SCROW nEndRow)
{
    if (!ValidRow(nStartRow) || !ValidRow(nEndRow))
        miBlockCur = miBlockEnd;

    size_t nStart = static_cast<size_t>(nStartRow);

    // Locate the start row position.
    size_t nBlockStart = 0, nBlockEnd = 0;
    for (; miBlockCur != miBlockEnd; ++miBlockCur, nBlockStart = nBlockEnd)
    {
        nBlockEnd = nBlockStart + miBlockCur->size; // non-inclusive end point.
        if (nBlockStart <= nStart && nStart < nBlockEnd)
        {
            // Initial block is found!
            break;
        }
    }

    if (miBlockCur == miBlockEnd)
        // Initial block not found for whatever reason... Bail out.
        return;

    // Locate the initial row position within this block.
    if (miBlockCur->type == sc::element_type_celltextattr)
    {
        // This block stores text widths for non-empty cells.
        size_t nOffsetInBlock = nStart - nBlockStart;
        mnCurPos = nStart;
        getDataIterators(nOffsetInBlock);
        checkEndRow();
        return;
    }

    // Current block is not of ushort type.  Skip to the next block.
    nBlockStart = nBlockEnd;
    ++miBlockCur;

    // Look for the first ushort block.
    for (; miBlockCur != miBlockEnd; ++miBlockCur, nBlockStart = nBlockEnd)
    {
        nBlockEnd = nBlockStart + miBlockCur->size; // non-inclusive end point.
        if (miBlockCur->type != sc::element_type_celltextattr)
            continue;

        // Found!
        mnCurPos = nBlockStart;
        getDataIterators(0);
        checkEndRow();
        return;
    }

    // Not found.
    OSL_ASSERT(miBlockCur == miBlockEnd);
}

void ScColumnTextWidthIterator::getDataIterators(size_t nOffsetInBlock)
{
    OSL_ENSURE(miBlockCur != miBlockEnd, "block is at end position");
#if 0
    // Does not compile
    OSL_ENSURE(miBlockCur->type == sc::custom_celltextattr_block,
               "wrong block type - unsigned short block expected.");
#endif
    miDataCur = sc::custom_celltextattr_block::begin(*miBlockCur->data);
    miDataEnd = sc::custom_celltextattr_block::end(*miBlockCur->data);

    std::advance(miDataCur, nOffsetInBlock);
}

void ScColumnTextWidthIterator::checkEndRow()
{
    if (mnCurPos <= mnEnd)
        // We're still good.
        return;

    // We're below the end position. End the iteration.
    miBlockCur = miBlockEnd;
}

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


<commit_before>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you under the Apache
 *   License, Version 2.0 (the "License"); you may not use this file
 *   except in compliance with the License. You may obtain a copy of
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
 */

#include "unitconverter.hxx"

#include <com/sun/star/awt/DeviceInfo.hpp>
#include <com/sun/star/awt/FontDescriptor.hpp>
#include <com/sun/star/awt/XDevice.hpp>
#include <com/sun/star/awt/XFont.hpp>
#include <com/sun/star/util/Date.hpp>
#include <com/sun/star/util/DateTime.hpp>
#include <rtl/math.hxx>
#include "oox/core/filterbase.hxx"
#include "oox/helper/propertyset.hxx"
#include "oox/token/properties.hxx"
#include "stylesbuffer.hxx"

namespace oox {
namespace xls {

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

using namespace ::com::sun::star::awt;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::util;

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

namespace {

const double MM100_PER_INCH         = 2540.0;
const double MM100_PER_POINT        = MM100_PER_INCH / 72.0;
const double MM100_PER_TWIP         = MM100_PER_POINT / 20.0;
const double MM100_PER_EMU          = 1.0 / 360.0;

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

/** Returns true, if the passed year is a leap year. */
inline sal_Int32 lclIsLeapYear( sal_Int32 nYear )
{
    return ((nYear % 4) == 0) && (((nYear % 100) != 0) || ((nYear % 400) == 0));
}

void lclSkipYearBlock( sal_Int32& ornDays, sal_Int16& ornYear, sal_Int32 nDaysInBlock, sal_Int32 nYearsPerBlock, sal_Int32 nMaxBlocks )
{
    sal_Int32 nBlocks = ::std::min< sal_Int32 >( ornDays / nDaysInBlock, nMaxBlocks );
    ornYear = static_cast< sal_Int16 >( ornYear + nYearsPerBlock * nBlocks );
    ornDays -= nBlocks * nDaysInBlock;
}

/** Returns the number of days before the passed date, starting from the null
    date 0000-Jan-01, using standard leap year conventions. */
sal_Int32 lclGetDays( const Date& rDate )
{
    // number of days in all full years before passed date including all leap days
    sal_Int32 nDays = rDate.Year * 365 + ((rDate.Year + 3) / 4) - ((rDate.Year + 99) / 100) + ((rDate.Year + 399) / 400);
    OSL_ENSURE( (1 <= rDate.Month) && (rDate.Month <= 12), "lclGetDays - invalid month" );
    OSL_ENSURE( (1 <= rDate.Day) && (rDate.Day <= 31), "lclGetDays - invalid day" );    // yes, this is weak...
    if( (1 <= rDate.Month) && (rDate.Month <= 12) )
    {
        // number of days at start of month   jan feb mar apr  may  jun  jul  aug  sep  oct  nov  dec
        static const sal_Int32 spnCumDays[] = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 };
        // add number of days in full months before passed date
        nDays += spnCumDays[ rDate.Month - 1 ];
        // add number of days from passed date (this adds one day too much)
        nDays += rDate.Day;
        /*  Remove the one day added too much if there is no leap day before
            the passed day in the passed year. This means: remove the day, if
            we are in january or february (leap day not reached if existing),
            or if the passed year is not a leap year. */
        if( (rDate.Month < 3) || !lclIsLeapYear( rDate.Year ) )
            --nDays;
    }
    return nDays;
}

} // namespace

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

UnitConverter::UnitConverter( const WorkbookHelper& rHelper ) :
    WorkbookHelper( rHelper ),
    maCoeffs( UNIT_ENUM_SIZE, 1.0 ),
    mnNullDate( lclGetDays( Date( 30, 12, 1899 ) ) )
{
    // initialize constant and default coefficients
    const DeviceInfo& rDeviceInfo = getBaseFilter().getGraphicHelper().getDeviceInfo();
    maCoeffs[ UNIT_INCH ]    = MM100_PER_INCH;
    maCoeffs[ UNIT_POINT ]   = MM100_PER_POINT;
    maCoeffs[ UNIT_TWIP ]    = MM100_PER_TWIP;
    maCoeffs[ UNIT_EMU ]     = MM100_PER_EMU;
    maCoeffs[ UNIT_SCREENX ] = (rDeviceInfo.PixelPerMeterX > 0) ? (100000.0 / rDeviceInfo.PixelPerMeterX) : 50.0;
    maCoeffs[ UNIT_SCREENY ] = (rDeviceInfo.PixelPerMeterY > 0) ? (100000.0 / rDeviceInfo.PixelPerMeterY) : 50.0;
    maCoeffs[ UNIT_REFDEVX ] = 12.5;                 // default: 1 px = 0.125 mm
    maCoeffs[ UNIT_REFDEVY ] = 12.5;                 // default: 1 px = 0.125 mm
    maCoeffs[ UNIT_DIGIT ]   = 200.0;                // default: 1 digit = 2 mm
    maCoeffs[ UNIT_SPACE ]   = 100.0;                // default  1 space = 1 mm

    // error code maps
    addErrorCode( BIFF_ERR_NULL,  "#NULL!" );
    addErrorCode( BIFF_ERR_DIV0,  "#DIV/0!" );
    addErrorCode( BIFF_ERR_VALUE, "#VALUE!" );
    addErrorCode( BIFF_ERR_REF,   "#REF!" );
    addErrorCode( BIFF_ERR_NAME,  "#NAME?" );
    addErrorCode( BIFF_ERR_NUM,   "#NUM!" );
    addErrorCode( BIFF_ERR_NA,    "#NA" );
}

void UnitConverter::finalizeImport()
{
    PropertySet aDocProps( getDocument() );
    Reference< XDevice > xDevice( aDocProps.getAnyProperty( PROP_ReferenceDevice ), UNO_QUERY );
    if( xDevice.is() )
    {
        // get reference device metric first, needed to get character widths below
        DeviceInfo aInfo = xDevice->getInfo();
        maCoeffs[ UNIT_REFDEVX ] = 100000.0 / aInfo.PixelPerMeterX;
        maCoeffs[ UNIT_REFDEVY ] = 100000.0 / aInfo.PixelPerMeterY;

        // get character widths from default font
        if( const Font* pDefFont = getStyles().getDefaultFont().get() )
        {
            // XDevice expects pixels in font descriptor, but font contains twips
            FontDescriptor aDesc = pDefFont->getFontDescriptor();
            Reference< XFont > xFont = xDevice->getFont( aDesc );
            if( xFont.is() )
            {
                // get maximum width of all digits
                sal_Int32 nDigitWidth = 0;
                for( sal_Unicode cChar = '0'; cChar <= '9'; ++cChar )
                    nDigitWidth = ::std::max( nDigitWidth, scaleToMm100( xFont->getCharWidth( cChar ), UNIT_TWIP ) );
                if( nDigitWidth > 0 )
                    maCoeffs[ UNIT_DIGIT ] = nDigitWidth;
                // get width of space character
                sal_Int32 nSpaceWidth = scaleToMm100( xFont->getCharWidth( ' ' ), UNIT_TWIP );
                if( nSpaceWidth > 0 )
                    maCoeffs[ UNIT_SPACE ] = nSpaceWidth;
            }
        }
    }
}

void UnitConverter::finalizeNullDate( const Date& rNullDate )
{
    // convert the nulldate to number of days since 0000-Jan-01
    mnNullDate = lclGetDays( rNullDate );
}

// conversion -----------------------------------------------------------------

double UnitConverter::scaleValue( double fValue, Unit eFromUnit, Unit eToUnit ) const
{
    return (eFromUnit == eToUnit) ? fValue : (fValue * getCoefficient( eFromUnit ) / getCoefficient( eToUnit ));
}

sal_Int32 UnitConverter::scaleToMm100( double fValue, Unit eUnit ) const
{
    return static_cast< sal_Int32 >( fValue * getCoefficient( eUnit ) + 0.5 );
}

double UnitConverter::scaleFromMm100( sal_Int32 nMm100, Unit eUnit ) const
{
    return static_cast< double >( nMm100 ) / getCoefficient( eUnit );
}

double UnitConverter::calcSerialFromDateTime( const DateTime& rDateTime ) const
{
    sal_Int32 nDays = lclGetDays( Date( rDateTime.Day, rDateTime.Month, rDateTime.Year ) ) - mnNullDate;
    OSL_ENSURE( nDays >= 0, "UnitConverter::calcDateTimeSerial - invalid date" );
    OSL_ENSURE( (rDateTime.Hours <= 23) && (rDateTime.Minutes <= 59) && (rDateTime.Seconds <= 59), "UnitConverter::calcDateTimeSerial - invalid time" );
    return nDays + rDateTime.Hours / 24.0 + rDateTime.Minutes / 1440.0 + rDateTime.Seconds / 86400.0;
}

DateTime UnitConverter::calcDateTimeFromSerial( double fSerial ) const
{
    DateTime aDateTime( 0, 0, 0, 0, 1, 1, 0, false );
    double fDays = 0.0;
    double fTime = modf( fSerial, &fDays );

    // calculate date from number of days with O(1) complexity
    sal_Int32 nDays = getLimitedValue< sal_Int32, double >( fDays + mnNullDate, 0, 3652424 );
    // skip year 0, assumed to be a leap year. By starting at year 1, leap years can be handled easily
    if( nDays >= 366 ) { ++aDateTime.Year; nDays -= 366; }
    // skip full blocks of 400, 100, 4 years, and remaining full years
    lclSkipYearBlock( nDays, aDateTime.Year, 400 * 365 + 97, 400, 24 );
    lclSkipYearBlock( nDays, aDateTime.Year, 100 * 365 + 24, 100, 3 );
    lclSkipYearBlock( nDays, aDateTime.Year, 4 * 365 + 1, 4, 24 );
    lclSkipYearBlock( nDays, aDateTime.Year, 365, 1, 3 );
    // skip full months of current year
    static const sal_Int32 spnDaysInMonth[] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
    if( (nDays >= 59) && !lclIsLeapYear( aDateTime.Year ) ) ++nDays;
    const sal_Int32* pnDaysInMonth = spnDaysInMonth;
    while( *pnDaysInMonth >= nDays ) { ++aDateTime.Month; nDays -= *pnDaysInMonth; ++pnDaysInMonth; }
    aDateTime.Day = static_cast< sal_uInt16 >( nDays + 1 );

    // calculate time from fractional part of serial
    sal_Int32 nTime = getLimitedValue< sal_Int32, double >( fTime * 86400, 0, 86399 );
    aDateTime.Seconds = static_cast< sal_uInt16 >( nTime % 60 );
    nTime /= 60;
    aDateTime.Minutes = static_cast< sal_uInt16 >( nTime % 60 );
    aDateTime.Hours = static_cast< sal_uInt16 >( nTime / 60 );

    return aDateTime;
}

sal_uInt8 UnitConverter::calcBiffErrorCode( const OUString& rErrorCode ) const
{
    OoxErrorCodeMap::const_iterator aIt = maOoxErrCodes.find( rErrorCode );
    return (aIt == maOoxErrCodes.end()) ? BIFF_ERR_NA : aIt->second;
}

void UnitConverter::addErrorCode( sal_uInt8 nErrorCode, const OUString& rErrorCode )
{
    maOoxErrCodes[ rErrorCode ]  = nErrorCode;
}

double UnitConverter::getCoefficient( Unit eUnit ) const
{
    OSL_ENSURE( static_cast< size_t >( eUnit ) < UNIT_ENUM_SIZE, "UnitConverter::getCoefficient - invalid unit" );
    return maCoeffs[ static_cast< size_t >( eUnit ) ];
}

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

} // namespace xls
} // namespace oox

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<commit_msg>sc: fix Date/DateTime ambiguity<commit_after>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you under the Apache
 *   License, Version 2.0 (the "License"); you may not use this file
 *   except in compliance with the License. You may obtain a copy of
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
 */

#include "unitconverter.hxx"

#include <com/sun/star/awt/DeviceInfo.hpp>
#include <com/sun/star/awt/FontDescriptor.hpp>
#include <com/sun/star/awt/XDevice.hpp>
#include <com/sun/star/awt/XFont.hpp>
#include <com/sun/star/util/Date.hpp>
#include <com/sun/star/util/DateTime.hpp>
#include <rtl/math.hxx>
#include "oox/core/filterbase.hxx"
#include "oox/helper/propertyset.hxx"
#include "oox/token/properties.hxx"
#include "stylesbuffer.hxx"

namespace oox {
namespace xls {

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

using namespace ::com::sun::star;
using namespace ::com::sun::star::awt;
using namespace ::com::sun::star::uno;

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

namespace {

const double MM100_PER_INCH         = 2540.0;
const double MM100_PER_POINT        = MM100_PER_INCH / 72.0;
const double MM100_PER_TWIP         = MM100_PER_POINT / 20.0;
const double MM100_PER_EMU          = 1.0 / 360.0;

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

/** Returns true, if the passed year is a leap year. */
inline sal_Int32 lclIsLeapYear( sal_Int32 nYear )
{
    return ((nYear % 4) == 0) && (((nYear % 100) != 0) || ((nYear % 400) == 0));
}

void lclSkipYearBlock( sal_Int32& ornDays, sal_Int16& ornYear, sal_Int32 nDaysInBlock, sal_Int32 nYearsPerBlock, sal_Int32 nMaxBlocks )
{
    sal_Int32 nBlocks = ::std::min< sal_Int32 >( ornDays / nDaysInBlock, nMaxBlocks );
    ornYear = static_cast< sal_Int16 >( ornYear + nYearsPerBlock * nBlocks );
    ornDays -= nBlocks * nDaysInBlock;
}

/** Returns the number of days before the passed date, starting from the null
    date 0000-Jan-01, using standard leap year conventions. */
sal_Int32 lclGetDays( const util::Date& rDate )
{
    // number of days in all full years before passed date including all leap days
    sal_Int32 nDays = rDate.Year * 365 + ((rDate.Year + 3) / 4) - ((rDate.Year + 99) / 100) + ((rDate.Year + 399) / 400);
    OSL_ENSURE( (1 <= rDate.Month) && (rDate.Month <= 12), "lclGetDays - invalid month" );
    OSL_ENSURE( (1 <= rDate.Day) && (rDate.Day <= 31), "lclGetDays - invalid day" );    // yes, this is weak...
    if( (1 <= rDate.Month) && (rDate.Month <= 12) )
    {
        // number of days at start of month   jan feb mar apr  may  jun  jul  aug  sep  oct  nov  dec
        static const sal_Int32 spnCumDays[] = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 };
        // add number of days in full months before passed date
        nDays += spnCumDays[ rDate.Month - 1 ];
        // add number of days from passed date (this adds one day too much)
        nDays += rDate.Day;
        /*  Remove the one day added too much if there is no leap day before
            the passed day in the passed year. This means: remove the day, if
            we are in january or february (leap day not reached if existing),
            or if the passed year is not a leap year. */
        if( (rDate.Month < 3) || !lclIsLeapYear( rDate.Year ) )
            --nDays;
    }
    return nDays;
}

} // namespace

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

UnitConverter::UnitConverter( const WorkbookHelper& rHelper ) :
    WorkbookHelper( rHelper ),
    maCoeffs( UNIT_ENUM_SIZE, 1.0 ),
    mnNullDate( lclGetDays( util::Date( 30, 12, 1899 ) ) )
{
    // initialize constant and default coefficients
    const DeviceInfo& rDeviceInfo = getBaseFilter().getGraphicHelper().getDeviceInfo();
    maCoeffs[ UNIT_INCH ]    = MM100_PER_INCH;
    maCoeffs[ UNIT_POINT ]   = MM100_PER_POINT;
    maCoeffs[ UNIT_TWIP ]    = MM100_PER_TWIP;
    maCoeffs[ UNIT_EMU ]     = MM100_PER_EMU;
    maCoeffs[ UNIT_SCREENX ] = (rDeviceInfo.PixelPerMeterX > 0) ? (100000.0 / rDeviceInfo.PixelPerMeterX) : 50.0;
    maCoeffs[ UNIT_SCREENY ] = (rDeviceInfo.PixelPerMeterY > 0) ? (100000.0 / rDeviceInfo.PixelPerMeterY) : 50.0;
    maCoeffs[ UNIT_REFDEVX ] = 12.5;                 // default: 1 px = 0.125 mm
    maCoeffs[ UNIT_REFDEVY ] = 12.5;                 // default: 1 px = 0.125 mm
    maCoeffs[ UNIT_DIGIT ]   = 200.0;                // default: 1 digit = 2 mm
    maCoeffs[ UNIT_SPACE ]   = 100.0;                // default  1 space = 1 mm

    // error code maps
    addErrorCode( BIFF_ERR_NULL,  "#NULL!" );
    addErrorCode( BIFF_ERR_DIV0,  "#DIV/0!" );
    addErrorCode( BIFF_ERR_VALUE, "#VALUE!" );
    addErrorCode( BIFF_ERR_REF,   "#REF!" );
    addErrorCode( BIFF_ERR_NAME,  "#NAME?" );
    addErrorCode( BIFF_ERR_NUM,   "#NUM!" );
    addErrorCode( BIFF_ERR_NA,    "#NA" );
}

void UnitConverter::finalizeImport()
{
    PropertySet aDocProps( getDocument() );
    Reference< XDevice > xDevice( aDocProps.getAnyProperty( PROP_ReferenceDevice ), UNO_QUERY );
    if( xDevice.is() )
    {
        // get reference device metric first, needed to get character widths below
        DeviceInfo aInfo = xDevice->getInfo();
        maCoeffs[ UNIT_REFDEVX ] = 100000.0 / aInfo.PixelPerMeterX;
        maCoeffs[ UNIT_REFDEVY ] = 100000.0 / aInfo.PixelPerMeterY;

        // get character widths from default font
        if( const Font* pDefFont = getStyles().getDefaultFont().get() )
        {
            // XDevice expects pixels in font descriptor, but font contains twips
            FontDescriptor aDesc = pDefFont->getFontDescriptor();
            Reference< XFont > xFont = xDevice->getFont( aDesc );
            if( xFont.is() )
            {
                // get maximum width of all digits
                sal_Int32 nDigitWidth = 0;
                for( sal_Unicode cChar = '0'; cChar <= '9'; ++cChar )
                    nDigitWidth = ::std::max( nDigitWidth, scaleToMm100( xFont->getCharWidth( cChar ), UNIT_TWIP ) );
                if( nDigitWidth > 0 )
                    maCoeffs[ UNIT_DIGIT ] = nDigitWidth;
                // get width of space character
                sal_Int32 nSpaceWidth = scaleToMm100( xFont->getCharWidth( ' ' ), UNIT_TWIP );
                if( nSpaceWidth > 0 )
                    maCoeffs[ UNIT_SPACE ] = nSpaceWidth;
            }
        }
    }
}

void UnitConverter::finalizeNullDate( const util::Date& rNullDate )
{
    // convert the nulldate to number of days since 0000-Jan-01
    mnNullDate = lclGetDays( rNullDate );
}

// conversion -----------------------------------------------------------------

double UnitConverter::scaleValue( double fValue, Unit eFromUnit, Unit eToUnit ) const
{
    return (eFromUnit == eToUnit) ? fValue : (fValue * getCoefficient( eFromUnit ) / getCoefficient( eToUnit ));
}

sal_Int32 UnitConverter::scaleToMm100( double fValue, Unit eUnit ) const
{
    return static_cast< sal_Int32 >( fValue * getCoefficient( eUnit ) + 0.5 );
}

double UnitConverter::scaleFromMm100( sal_Int32 nMm100, Unit eUnit ) const
{
    return static_cast< double >( nMm100 ) / getCoefficient( eUnit );
}

double UnitConverter::calcSerialFromDateTime( const util::DateTime& rDateTime ) const
{
    sal_Int32 nDays = lclGetDays( util::Date( rDateTime.Day, rDateTime.Month, rDateTime.Year ) ) - mnNullDate;
    OSL_ENSURE( nDays >= 0, "UnitConverter::calcDateTimeSerial - invalid date" );
    OSL_ENSURE( (rDateTime.Hours <= 23) && (rDateTime.Minutes <= 59) && (rDateTime.Seconds <= 59), "UnitConverter::calcDateTimeSerial - invalid time" );
    return nDays + rDateTime.Hours / 24.0 + rDateTime.Minutes / 1440.0 + rDateTime.Seconds / 86400.0;
}

util::DateTime UnitConverter::calcDateTimeFromSerial( double fSerial ) const
{
    util::DateTime aDateTime( 0, 0, 0, 0, 1, 1, 0, false );
    double fDays = 0.0;
    double fTime = modf( fSerial, &fDays );

    // calculate date from number of days with O(1) complexity
    sal_Int32 nDays = getLimitedValue< sal_Int32, double >( fDays + mnNullDate, 0, 3652424 );
    // skip year 0, assumed to be a leap year. By starting at year 1, leap years can be handled easily
    if( nDays >= 366 ) { ++aDateTime.Year; nDays -= 366; }
    // skip full blocks of 400, 100, 4 years, and remaining full years
    lclSkipYearBlock( nDays, aDateTime.Year, 400 * 365 + 97, 400, 24 );
    lclSkipYearBlock( nDays, aDateTime.Year, 100 * 365 + 24, 100, 3 );
    lclSkipYearBlock( nDays, aDateTime.Year, 4 * 365 + 1, 4, 24 );
    lclSkipYearBlock( nDays, aDateTime.Year, 365, 1, 3 );
    // skip full months of current year
    static const sal_Int32 spnDaysInMonth[] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
    if( (nDays >= 59) && !lclIsLeapYear( aDateTime.Year ) ) ++nDays;
    const sal_Int32* pnDaysInMonth = spnDaysInMonth;
    while( *pnDaysInMonth >= nDays ) { ++aDateTime.Month; nDays -= *pnDaysInMonth; ++pnDaysInMonth; }
    aDateTime.Day = static_cast< sal_uInt16 >( nDays + 1 );

    // calculate time from fractional part of serial
    sal_Int32 nTime = getLimitedValue< sal_Int32, double >( fTime * 86400, 0, 86399 );
    aDateTime.Seconds = static_cast< sal_uInt16 >( nTime % 60 );
    nTime /= 60;
    aDateTime.Minutes = static_cast< sal_uInt16 >( nTime % 60 );
    aDateTime.Hours = static_cast< sal_uInt16 >( nTime / 60 );

    return aDateTime;
}

sal_uInt8 UnitConverter::calcBiffErrorCode( const OUString& rErrorCode ) const
{
    OoxErrorCodeMap::const_iterator aIt = maOoxErrCodes.find( rErrorCode );
    return (aIt == maOoxErrCodes.end()) ? BIFF_ERR_NA : aIt->second;
}

void UnitConverter::addErrorCode( sal_uInt8 nErrorCode, const OUString& rErrorCode )
{
    maOoxErrCodes[ rErrorCode ]  = nErrorCode;
}

double UnitConverter::getCoefficient( Unit eUnit ) const
{
    OSL_ENSURE( static_cast< size_t >( eUnit ) < UNIT_ENUM_SIZE, "UnitConverter::getCoefficient - invalid unit" );
    return maCoeffs[ static_cast< size_t >( eUnit ) ];
}

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

} // namespace xls
} // namespace oox

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


<commit_before>/*
 * Copyright(c) Sophist Solutions, Inc. 1990-2013.  All rights reserved
 */
#include    "../../../StroikaPreComp.h"

#if     qHasFeature_libcurl
#include    <curl/curl.h>
#endif

#include    "../../../Characters/Format.h"
#include    "../../../Execution/Exceptions.h"

#include    "Client_libcurl.h"

using   namespace   Stroika::Foundation;
using   namespace   Stroika::Foundation::Characters;
using   namespace   Stroika::Foundation::Execution;
using   namespace   Stroika::Foundation::IO;
using   namespace   Stroika::Foundation::IO::Network;
using   namespace   Stroika::Foundation::IO::Network::Transfer;

#if     qHasFeature_libcurl
namespace   {
    struct  ModuleInit_ {
        ModuleInit_ () {
            ::curl_global_init (CURL_GLOBAL_ALL);
        }
    };
    ModuleInit_ sIniter_;
}
#endif

#if     qHasFeature_libcurl
class   Connection_LibCurl::Rep_ : public _IRep {
private:
    NO_COPY_CONSTRUCTOR (Rep_);
    NO_ASSIGNMENT_OPERATOR (Rep_);
public:
    Rep_ ();
    virtual ~Rep_ ();

public:
    virtual DurationSecondsType GetTimeout () const override;
    virtual void                SetTimeout (DurationSecondsType timeout) override;
    virtual URL                 GetURL () const override;
    virtual void                SetURL (const URL& url) override;
    virtual void                Close ()    override;
    virtual Response            SendAndRequest (const Request& request) override;

private:
    nonvirtual  void    MakeHandleIfNeeded_ ();

private:
    static      size_t  s_ResponseWriteHandler_ (void* ptr, size_t size, size_t nmemb, void* userP);
    nonvirtual  size_t  ResponseWriteHandler_ (const Byte* ptr, size_t nBytes);

private:
    static      size_t  s_ResponseHeaderWriteHandler_ (void* ptr, size_t size, size_t nmemb, void* userP);
    nonvirtual  size_t  ResponseHeaderWriteHandler_ (const Byte* ptr, size_t nBytes);

private:
    void*               fCurlHandle_;
    string              fCURLCache_URL_;    // cuz of quirky memory management policies of libcurl
    vector<Byte>        fResponseData_;
    map<String, String> fResponseHeaders_;
    curl_slist*         fSavedHeaders_;
};
#endif

#if     qHasFeature_libcurl
namespace   {
    wstring mkExceptMsg_ (LibCurlException::CURLcode ccode)
    {
        return String::FromUTF8 (curl_easy_strerror (static_cast<CURLcode> (ccode))).As<wstring> ();
    }
}

/*
 ********************************************************************************
 ************************ Transfer::LibCurlException ****************************
 ********************************************************************************
 */
LibCurlException::LibCurlException (CURLcode ccode)
    : StringException (mkExceptMsg_ (ccode))
    , fCurlCode_ (ccode)
{
}

void    LibCurlException::DoThrowIfError (CURLcode status)
{
    if (status != CURLE_OK) {
        Execution::DoThrow (LibCurlException (status));
    }
}
#endif

#if     qHasFeature_libcurl
/*
 ********************************************************************************
 ****************** Transfer::Connection_LibCurl::Rep_ **************************
 ********************************************************************************
 */
Connection_LibCurl::Rep_::Rep_ ()
    : fCurlHandle_ (nullptr)
    , fCURLCache_URL_ ()
    , fResponseData_ ()
    , fSavedHeaders_ (nullptr)
{
}

Connection_LibCurl::Rep_::~Rep_ ()
{
    if (fCurlHandle_ != nullptr) {
        curl_easy_cleanup (fCurlHandle_);
    }
    if (fSavedHeaders_ != nullptr) {
        curl_slist_free_all (fSavedHeaders_);
        fSavedHeaders_ = nullptr;
    }
}

DurationSecondsType Connection_LibCurl::Rep_::GetTimeout () const override
{
    AssertNotImplemented ();
    return 0;
}

void    Connection_LibCurl::Rep_::SetTimeout (DurationSecondsType timeout) override
{
    MakeHandleIfNeeded_ ();
    LibCurlException::DoThrowIfError (::curl_easy_setopt (fCurlHandle_, CURLOPT_TIMEOUT_MS, static_cast<int> (timeout * 1000)));
    LibCurlException::DoThrowIfError (::curl_easy_setopt (fCurlHandle_, CURLOPT_CONNECTTIMEOUT_MS, static_cast<int> (timeout * 1000)));
}

URL     Connection_LibCurl::Rep_::GetURL () const override
{
    // needs work... - not sure this is safe - may need to cache orig... instead of reparsing...
    return URL (String::FromUTF8 (fCURLCache_URL_).As<wstring> ());
}

void    Connection_LibCurl::Rep_::SetURL (const URL& url) override
{
    MakeHandleIfNeeded_ ();
    fCURLCache_URL_ = String (url.GetURL ()).AsUTF8 ();
    LibCurlException::DoThrowIfError (::curl_easy_setopt (fCurlHandle_, CURLOPT_URL, fCURLCache_URL_.c_str ()));
}

void    Connection_LibCurl::Rep_::Close ()  override
{
    if (fCurlHandle_ != nullptr) {
        ::curl_easy_cleanup (fCurlHandle_);
        fCurlHandle_ = nullptr;
    }
}

size_t  Connection_LibCurl::Rep_::s_ResponseWriteHandler_ (void* ptr, size_t size, size_t nmemb, void* userP)
{
    return reinterpret_cast<Rep_*> (userP)->ResponseWriteHandler_ (reinterpret_cast<const Byte*> (ptr), size * nmemb);
}

size_t  Connection_LibCurl::Rep_::ResponseWriteHandler_ (const Byte* ptr, size_t nBytes)
{
    fResponseData_.insert (fResponseData_.end (), ptr, ptr + nBytes);
    return nBytes;
}

size_t  Connection_LibCurl::Rep_::s_ResponseHeaderWriteHandler_ (void* ptr, size_t size, size_t nmemb, void* userP)
{
    return reinterpret_cast<Rep_*> (userP)->ResponseHeaderWriteHandler_ (reinterpret_cast<const Byte*> (ptr), size * nmemb);
}

size_t  Connection_LibCurl::Rep_::ResponseHeaderWriteHandler_ (const Byte* ptr, size_t nBytes)
{
    String  from    =   String::FromUTF8 (reinterpret_cast<const char*> (ptr), reinterpret_cast<const char*> (ptr) + nBytes);
    String  to;
    sized_t i       =   from.find (':');
    if (i != string::npos) {
        to = from.SubString (i + 1);
        from = from.SubString (0, i);
    }
    from = from.Trim ();
    to = to.Trim ();
    fResponseHeaders_[from] = to;
    return nBytes;
}

Response    Connection_LibCurl::Rep_::SendAndRequest (const Request& request)   override
{
    MakeHandleIfNeeded_ ();
    fResponseData_.clear ();
    fResponseHeaders_.clear ();

    //grab useragent from request headers...
    //curl_easy_setopt (fCurlHandle_, CURLOPT_USERAGENT, "libcurl-agent/1.0");

    // grab initial headers and do POST/etc based on args in request...
    curl_slist* tmpH    =   nullptr;
    for (auto i = request.fOverrideHeaders.begin (); i != request.fOverrideHeaders.end (); ++i) {
        tmpH = curl_slist_append (tmpH, (i->first + L": " + i->second).AsUTF8 ().c_str ());
    }
    AssertNotNull (fCurlHandle_);
    LibCurlException::DoThrowIfError (::curl_easy_setopt (fCurlHandle_, CURLOPT_HTTPHEADER, tmpH));
    if (fSavedHeaders_ != nullptr) {
        curl_slist_free_all (fSavedHeaders_);
        fSavedHeaders_ = nullptr;
    }
    fSavedHeaders_ = tmpH;

    LibCurlException::DoThrowIfError (:: curl_easy_perform (fCurlHandle_));

    Response    response;
    response.fData = fResponseData_;

    long    resultCode  =   0;
    LibCurlException::DoThrowIfError (::curl_easy_getinfo (fCurlHandle_, CURLINFO_RESPONSE_CODE, &resultCode));
    response.fStatus = resultCode;
    response.fHeaders = fResponseHeaders_;
    response.fData = fResponseData_;
    return response;
}

void    Connection_LibCurl::Rep_::MakeHandleIfNeeded_ ()
{
    if (fCurlHandle_ == nullptr) {
        ThrowIfNull (fCurlHandle_ = ::curl_easy_init ());

        /*
         * Now setup COMMON options we ALWAYS set.
         */
        LibCurlException::DoThrowIfError (::curl_easy_setopt (fCurlHandle_, CURLOPT_URL, fCURLCache_URL_.c_str ()));

        LibCurlException::DoThrowIfError (::curl_easy_setopt (fCurlHandle_, CURLOPT_WRITEFUNCTION, s_ResponseWriteHandler_));
        LibCurlException::DoThrowIfError (::curl_easy_setopt (fCurlHandle_, CURLOPT_WRITEDATA, this));
        LibCurlException::DoThrowIfError (::curl_easy_setopt (fCurlHandle_, CURLOPT_HEADERFUNCTION, s_ResponseHeaderWriteHandler_));
        LibCurlException::DoThrowIfError (::curl_easy_setopt (fCurlHandle_, CURLOPT_WRITEHEADER, this));
    }
}
#endif

#if     qHasFeature_libcurl
/*
 ********************************************************************************
 ********************** Transfer::Connection_LibCurl ****************************
 ********************************************************************************
 */
Connection_LibCurl::Connection_LibCurl ()
    : Connection (shared_ptr<_IRep> (DEBUG_NEW Rep_ ()))
{
}
#endif
<commit_msg>fix regression in libcurl stuff (from my earlier string changes)<commit_after>/*
 * Copyright(c) Sophist Solutions, Inc. 1990-2013.  All rights reserved
 */
#include    "../../../StroikaPreComp.h"

#if     qHasFeature_libcurl
#include    <curl/curl.h>
#endif

#include    "../../../Characters/Format.h"
#include    "../../../Execution/Exceptions.h"

#include    "Client_libcurl.h"

using   namespace   Stroika::Foundation;
using   namespace   Stroika::Foundation::Characters;
using   namespace   Stroika::Foundation::Execution;
using   namespace   Stroika::Foundation::IO;
using   namespace   Stroika::Foundation::IO::Network;
using   namespace   Stroika::Foundation::IO::Network::Transfer;

#if     qHasFeature_libcurl
namespace   {
    struct  ModuleInit_ {
        ModuleInit_ () {
            ::curl_global_init (CURL_GLOBAL_ALL);
        }
    };
    ModuleInit_ sIniter_;
}
#endif

#if     qHasFeature_libcurl
class   Connection_LibCurl::Rep_ : public _IRep {
private:
    NO_COPY_CONSTRUCTOR (Rep_);
    NO_ASSIGNMENT_OPERATOR (Rep_);
public:
    Rep_ ();
    virtual ~Rep_ ();

public:
    virtual DurationSecondsType GetTimeout () const override;
    virtual void                SetTimeout (DurationSecondsType timeout) override;
    virtual URL                 GetURL () const override;
    virtual void                SetURL (const URL& url) override;
    virtual void                Close ()    override;
    virtual Response            SendAndRequest (const Request& request) override;

private:
    nonvirtual  void    MakeHandleIfNeeded_ ();

private:
    static      size_t  s_ResponseWriteHandler_ (void* ptr, size_t size, size_t nmemb, void* userP);
    nonvirtual  size_t  ResponseWriteHandler_ (const Byte* ptr, size_t nBytes);

private:
    static      size_t  s_ResponseHeaderWriteHandler_ (void* ptr, size_t size, size_t nmemb, void* userP);
    nonvirtual  size_t  ResponseHeaderWriteHandler_ (const Byte* ptr, size_t nBytes);

private:
    void*               fCurlHandle_;
    string              fCURLCache_URL_;    // cuz of quirky memory management policies of libcurl
    vector<Byte>        fResponseData_;
    map<String, String> fResponseHeaders_;
    curl_slist*         fSavedHeaders_;
};
#endif

#if     qHasFeature_libcurl
namespace   {
    wstring mkExceptMsg_ (LibCurlException::CURLcode ccode)
    {
        return String::FromUTF8 (curl_easy_strerror (static_cast<CURLcode> (ccode))).As<wstring> ();
    }
}

/*
 ********************************************************************************
 ************************ Transfer::LibCurlException ****************************
 ********************************************************************************
 */
LibCurlException::LibCurlException (CURLcode ccode)
    : StringException (mkExceptMsg_ (ccode))
    , fCurlCode_ (ccode)
{
}

void    LibCurlException::DoThrowIfError (CURLcode status)
{
    if (status != CURLE_OK) {
        Execution::DoThrow (LibCurlException (status));
    }
}
#endif

#if     qHasFeature_libcurl
/*
 ********************************************************************************
 ****************** Transfer::Connection_LibCurl::Rep_ **************************
 ********************************************************************************
 */
Connection_LibCurl::Rep_::Rep_ ()
    : fCurlHandle_ (nullptr)
    , fCURLCache_URL_ ()
    , fResponseData_ ()
    , fSavedHeaders_ (nullptr)
{
}

Connection_LibCurl::Rep_::~Rep_ ()
{
    if (fCurlHandle_ != nullptr) {
        curl_easy_cleanup (fCurlHandle_);
    }
    if (fSavedHeaders_ != nullptr) {
        curl_slist_free_all (fSavedHeaders_);
        fSavedHeaders_ = nullptr;
    }
}

DurationSecondsType Connection_LibCurl::Rep_::GetTimeout () const override
{
    AssertNotImplemented ();
    return 0;
}

void    Connection_LibCurl::Rep_::SetTimeout (DurationSecondsType timeout) override
{
    MakeHandleIfNeeded_ ();
    LibCurlException::DoThrowIfError (::curl_easy_setopt (fCurlHandle_, CURLOPT_TIMEOUT_MS, static_cast<int> (timeout * 1000)));
    LibCurlException::DoThrowIfError (::curl_easy_setopt (fCurlHandle_, CURLOPT_CONNECTTIMEOUT_MS, static_cast<int> (timeout * 1000)));
}

URL     Connection_LibCurl::Rep_::GetURL () const override
{
    // needs work... - not sure this is safe - may need to cache orig... instead of reparsing...
    return URL (String::FromUTF8 (fCURLCache_URL_).As<wstring> ());
}

void    Connection_LibCurl::Rep_::SetURL (const URL& url) override
{
    MakeHandleIfNeeded_ ();
    fCURLCache_URL_ = String (url.GetURL ()).AsUTF8 ();
    LibCurlException::DoThrowIfError (::curl_easy_setopt (fCurlHandle_, CURLOPT_URL, fCURLCache_URL_.c_str ()));
}

void    Connection_LibCurl::Rep_::Close ()  override
{
    if (fCurlHandle_ != nullptr) {
        ::curl_easy_cleanup (fCurlHandle_);
        fCurlHandle_ = nullptr;
    }
}

size_t  Connection_LibCurl::Rep_::s_ResponseWriteHandler_ (void* ptr, size_t size, size_t nmemb, void* userP)
{
    return reinterpret_cast<Rep_*> (userP)->ResponseWriteHandler_ (reinterpret_cast<const Byte*> (ptr), size * nmemb);
}

size_t  Connection_LibCurl::Rep_::ResponseWriteHandler_ (const Byte* ptr, size_t nBytes)
{
    fResponseData_.insert (fResponseData_.end (), ptr, ptr + nBytes);
    return nBytes;
}

size_t  Connection_LibCurl::Rep_::s_ResponseHeaderWriteHandler_ (void* ptr, size_t size, size_t nmemb, void* userP)
{
    return reinterpret_cast<Rep_*> (userP)->ResponseHeaderWriteHandler_ (reinterpret_cast<const Byte*> (ptr), size * nmemb);
}

size_t  Connection_LibCurl::Rep_::ResponseHeaderWriteHandler_ (const Byte* ptr, size_t nBytes)
{
    String  from    =   String::FromUTF8 (reinterpret_cast<const char*> (ptr), reinterpret_cast<const char*> (ptr) + nBytes);
    String  to;
    size_t	i       =   from.find (':');
    if (i != string::npos) {
        to = from.SubString (i + 1);
        from = from.SubString (0, i);
    }
    from = from.Trim ();
    to = to.Trim ();
    fResponseHeaders_[from] = to;
    return nBytes;
}

Response    Connection_LibCurl::Rep_::SendAndRequest (const Request& request)   override
{
    MakeHandleIfNeeded_ ();
    fResponseData_.clear ();
    fResponseHeaders_.clear ();

    //grab useragent from request headers...
    //curl_easy_setopt (fCurlHandle_, CURLOPT_USERAGENT, "libcurl-agent/1.0");

    // grab initial headers and do POST/etc based on args in request...
    curl_slist* tmpH    =   nullptr;
    for (auto i = request.fOverrideHeaders.begin (); i != request.fOverrideHeaders.end (); ++i) {
        tmpH = curl_slist_append (tmpH, (i->first + L": " + i->second).AsUTF8 ().c_str ());
    }
    AssertNotNull (fCurlHandle_);
    LibCurlException::DoThrowIfError (::curl_easy_setopt (fCurlHandle_, CURLOPT_HTTPHEADER, tmpH));
    if (fSavedHeaders_ != nullptr) {
        curl_slist_free_all (fSavedHeaders_);
        fSavedHeaders_ = nullptr;
    }
    fSavedHeaders_ = tmpH;

    LibCurlException::DoThrowIfError (:: curl_easy_perform (fCurlHandle_));

    Response    response;
    response.fData = fResponseData_;

    long    resultCode  =   0;
    LibCurlException::DoThrowIfError (::curl_easy_getinfo (fCurlHandle_, CURLINFO_RESPONSE_CODE, &resultCode));
    response.fStatus = resultCode;
    response.fHeaders = fResponseHeaders_;
    response.fData = fResponseData_;
    return response;
}

void    Connection_LibCurl::Rep_::MakeHandleIfNeeded_ ()
{
    if (fCurlHandle_ == nullptr) {
        ThrowIfNull (fCurlHandle_ = ::curl_easy_init ());

        /*
         * Now setup COMMON options we ALWAYS set.
         */
        LibCurlException::DoThrowIfError (::curl_easy_setopt (fCurlHandle_, CURLOPT_URL, fCURLCache_URL_.c_str ()));

        LibCurlException::DoThrowIfError (::curl_easy_setopt (fCurlHandle_, CURLOPT_WRITEFUNCTION, s_ResponseWriteHandler_));
        LibCurlException::DoThrowIfError (::curl_easy_setopt (fCurlHandle_, CURLOPT_WRITEDATA, this));
        LibCurlException::DoThrowIfError (::curl_easy_setopt (fCurlHandle_, CURLOPT_HEADERFUNCTION, s_ResponseHeaderWriteHandler_));
        LibCurlException::DoThrowIfError (::curl_easy_setopt (fCurlHandle_, CURLOPT_WRITEHEADER, this));
    }
}
#endif

#if     qHasFeature_libcurl
/*
 ********************************************************************************
 ********************** Transfer::Connection_LibCurl ****************************
 ********************************************************************************
 */
Connection_LibCurl::Connection_LibCurl ()
    : Connection (shared_ptr<_IRep> (DEBUG_NEW Rep_ ()))
{
}
#endif
<|endoftext|>


<commit_before><commit_msg>copyObject should return the clone of the passed object for recursive copies, not an arbitrary object<commit_after><|endoftext|>


<commit_before>/**
 *
 * @file compiled_plugin_base.cpp
 *
 * @date Jan 15, 2013
 * @author partio
 */

#include "compiled_plugin_base.h"
#include <boost/thread.hpp>
#include "plugin_factory.h"

#define HIMAN_AUXILIARY_INCLUDE

#include "neons.h"
#include "writer.h"
#include "pcuda.h"

#undef HIMAN_AUXILIARY_INCLUDE

using namespace std;
using namespace himan::plugin;

const short MAX_THREADS = 12; //<! Max number of threads we allow
const double kInterpolatedValueEpsilon = 0.00001; //<! Max difference between two grid points (if smaller, points are considered the same)

mutex itsAdjustDimensionMutex;

short compiled_plugin_base::ThreadCount(short userThreadCount) const
{
	short coreCount = static_cast<short> (boost::thread::hardware_concurrency()); // Number of cores

	short threadCount = MAX_THREADS;

	if (userThreadCount > 0)
	{
		threadCount = userThreadCount;
	}
	else if (MAX_THREADS > coreCount)
	{
		threadCount = coreCount;
	}

	return threadCount;
}

bool compiled_plugin_base::InterpolateToPoint(shared_ptr<const NFmiGrid> targetGrid, shared_ptr<NFmiGrid> sourceGrid, bool gridsAreEqual, double& value)
{

	/*
	 * Logic of interpolating values:
	 *
	 * 1) If source and target grids are equal, meaning that the grid AND the area
	 *	properties are effectively the same, do not interpolate. Instead return
	 *	the value of the source grid point that matches the ordering number of the
	 *	target grid point (ie. target grid point #1 --> source grid point #1 etc).
	 *
	 * 2) If actual interpolation is needed, first get the *grid* coordinates of the
	 *	latlon target point. Then check if those grid coordinates are very close
	 *	to a grid point -- if so, return the value of the grid point. This serves two
	 *	purposes:
	 *	- We don't need to interpolate if the distance between requested grid point
	 *	  and actual grid point is small enough, saving some CPU cycles
	 *	- Sometimes when the requested grid point is close to grid edge, floating
	 *	  point inaccuracies might move it outside the grid. If this happens, the
	 *	  interpolation fails even though initially the grid point is valid.
	 *
	 * 3) If requested source grid point is not near and actual grid point, interpolate
	 *	the value of the point.
	 */

	// Step 1)

	if (gridsAreEqual)
	{
		value = sourceGrid->FloatValue(targetGrid->GridPoint());
		return true;
	}

	const NFmiPoint targetLatLonPoint = targetGrid->LatLon();
	const NFmiPoint sourceGridPoint = targetGrid->LatLonToGrid(targetLatLonPoint.X(), targetLatLonPoint.Y());

	// Step 2)

	bool noInterpolation = (fabs(sourceGridPoint.X() - round(sourceGridPoint.X())) < kInterpolatedValueEpsilon &&
		 fabs(sourceGridPoint.Y() - round(sourceGridPoint.Y())) < kInterpolatedValueEpsilon);

	if (noInterpolation)
	{
		value = sourceGrid->FloatValue(sourceGridPoint);
		return true;
	}

	// Step 3)

	return sourceGrid->InterpolateToLatLonPoint(targetLatLonPoint, value);

}

bool compiled_plugin_base::AdjustLeadingDimension(shared_ptr<info> myTargetInfo)
{

	lock_guard<mutex> lock(itsAdjustDimensionMutex);

	// Leading dimension can be: time or level

	if (itsLeadingDimension == kTimeDimension)
	{
		if (!itsFeederInfo->NextTime())
		{
			return false;
		}

		myTargetInfo->Time(itsFeederInfo->Time());
	}
	else if (itsLeadingDimension == kLevelDimension)
	{
		if (!itsFeederInfo->NextLevel())
		{
			return false;
		}

		myTargetInfo->Level(itsFeederInfo->Level());
	}
	else
	{
		throw runtime_error(ClassName() + ": Invalid dimension type: " + boost::lexical_cast<string> (itsLeadingDimension));
	}

	return true;
}

bool compiled_plugin_base::AdjustNonLeadingDimension(shared_ptr<info> myTargetInfo)
{
	if (itsLeadingDimension == kTimeDimension)
	{
		return myTargetInfo->NextLevel();
	}
	else if (itsLeadingDimension == kLevelDimension)
	{
		return myTargetInfo->NextTime();
	}
	else
	{
		throw runtime_error(ClassName() + ": unsupported leading dimension: " + boost::lexical_cast<string> (itsLeadingDimension));
	}
}

void compiled_plugin_base::ResetNonLeadingDimension(shared_ptr<info> myTargetInfo)
{
	if (itsLeadingDimension == kTimeDimension)
	{
		myTargetInfo->ResetLevel();
	}
	else if (itsLeadingDimension == kLevelDimension)
	{
		myTargetInfo->ResetTime();
	}
	else
	{
		throw runtime_error(ClassName() + ": unsupported leading dimension: " + boost::lexical_cast<string> (itsLeadingDimension));
	}
}

himan::level compiled_plugin_base::LevelTransform(const himan::producer& sourceProducer,
													const himan::param& targetParam,
													const himan::level& targetLevel) const
{

	level sourceLevel = targetLevel;

	string levelName = HPLevelTypeToString.at(targetLevel.Type());
	string key = boost::lexical_cast<string> (sourceProducer.Id()) + "_" + levelName + "_" + targetParam.Name();

	// Return value from cache if present

	try
	{
		sourceLevel.Type(itsLevelTransformMap.at(key));

		sourceLevel.Name(levelName);

		if (sourceLevel.Type() == kGround)
		{
			sourceLevel.Value(0);
		}

		return sourceLevel;

	}
	catch (...)
	{

	}

	if (sourceProducer.TableVersion() != kHPMissingInt)
	{
		shared_ptr<neons> n = dynamic_pointer_cast <neons> (plugin_factory::Instance()->Plugin("neons"));

		string lvlName = n->NeonsDB().GetGridLevelName(targetParam.Name(), targetLevel.Type(), 204, sourceProducer.TableVersion());

		HPLevelType lvlType = kUnknownLevel;

		double lvlValue = targetLevel.Value();

		if (lvlName == "GROUND")
		{
			lvlType = kGround;
			lvlValue = 0;
		}
		else if (lvlName == "PRESSURE")
		{
			lvlType = kPressure;
		}
		else if (lvlName == "HYBRID")
		{
			lvlType = kHybrid;
		}
		else if (lvlName == "HEIGHT")
		{
			lvlType = kHeight;
		}
		else
		{
			throw runtime_error(ClassName() + ": Unknown level type: " + lvlName);
		}

		sourceLevel = level(lvlType, lvlValue, lvlName);
	}
	else
	{
		sourceLevel = targetLevel;
	}

	itsLevelTransformMap[key] = sourceLevel.Type();

	return sourceLevel;
}

bool compiled_plugin_base::SetAB(shared_ptr<info> myTargetInfo, shared_ptr<info> sourceInfo)
{
	if (myTargetInfo->Level().Type() == kHybrid)
	{
		size_t index = myTargetInfo->ParamIndex();

		myTargetInfo->Grid()->AB(sourceInfo->Grid()->AB());

		myTargetInfo->ParamIndex(index);
	}

	return true;
}

bool compiled_plugin_base::SwapTo(shared_ptr<info> myTargetInfo, HPScanningMode targetScanningMode)
{

	if (myTargetInfo->Grid()->ScanningMode() != targetScanningMode)
	{
		HPScanningMode originalMode = myTargetInfo->Grid()->ScanningMode();

		myTargetInfo->Grid()->ScanningMode(targetScanningMode);

		myTargetInfo->Grid()->Swap(originalMode);
	}

	return true;
}

void compiled_plugin_base::StoreGrib1ParameterDefinitions(vector<param> params, long table2Version)
{
	shared_ptr<neons> n = dynamic_pointer_cast<neons> (plugin_factory::Instance()->Plugin("neons"));

	for (unsigned int i = 0; i < params.size(); i++)
	{
		long parm_id = n->NeonsDB().GetGridParameterId(table2Version, params[i].Name());
		params[i].GribIndicatorOfParameter(parm_id);
		params[i].GribTableVersion(table2Version);
	}
}

void compiled_plugin_base::WriteToFile(shared_ptr<const plugin_configuration> conf, shared_ptr<const info> targetInfo)
{
	shared_ptr<writer> aWriter = dynamic_pointer_cast <writer> (plugin_factory::Instance()->Plugin("writer"));

	// writing might modify iterator positions --> create a copy

	shared_ptr<info> tempInfo(new info(*targetInfo));

	if (conf->FileWriteOption() == kNeons || conf->FileWriteOption() == kMultipleFiles)
	{
		// if info holds multiple parameters, we must loop over them all

		tempInfo->ResetParam();

		while (tempInfo->NextParam())
		{
			aWriter->ToFile(tempInfo, conf);
		}
	}
	else if (conf->FileWriteOption() == kSingleFile)
	{
		aWriter->ToFile(tempInfo, conf, conf->ConfigurationFile());
	}

	tempInfo.reset();
}

bool compiled_plugin_base::GetAndSetCuda(shared_ptr<const configuration> conf, int threadIndex)
{
	bool ret = conf->UseCuda() && threadIndex <= conf->CudaDeviceCount();

	if (ret)
	{
		shared_ptr<pcuda> p = dynamic_pointer_cast <pcuda> (plugin_factory::Instance()->Plugin("pcuda"));

		ret = p->SetDevice(threadIndex-1);
		if (!ret)
		{
			// Setting device failed -- probably it is already in use by another process

			conf->UseCuda(false);
		}
	}

	return ret;
}

void compiled_plugin_base::ResetCuda() const
{
	shared_ptr<pcuda> p = dynamic_pointer_cast <pcuda> (plugin_factory::Instance()->Plugin("pcuda"));
	p->Reset();
}

int compiled_plugin_base::CudaDeviceId() const
{
	shared_ptr<pcuda> p = dynamic_pointer_cast <pcuda> (plugin_factory::Instance()->Plugin("pcuda"));
	return p->GetDevice();
}
<commit_msg>Not setting UseCuda to false since conf is const. Returning false should be adequate enough<commit_after>/**
 *
 * @file compiled_plugin_base.cpp
 *
 * @date Jan 15, 2013
 * @author partio
 */

#include "compiled_plugin_base.h"
#include <boost/thread.hpp>
#include "plugin_factory.h"

#define HIMAN_AUXILIARY_INCLUDE

#include "neons.h"
#include "writer.h"
#include "pcuda.h"

#undef HIMAN_AUXILIARY_INCLUDE

using namespace std;
using namespace himan::plugin;

const short MAX_THREADS = 12; //<! Max number of threads we allow
const double kInterpolatedValueEpsilon = 0.00001; //<! Max difference between two grid points (if smaller, points are considered the same)

mutex itsAdjustDimensionMutex;

short compiled_plugin_base::ThreadCount(short userThreadCount) const
{
	short coreCount = static_cast<short> (boost::thread::hardware_concurrency()); // Number of cores

	short threadCount = MAX_THREADS;

	if (userThreadCount > 0)
	{
		threadCount = userThreadCount;
	}
	else if (MAX_THREADS > coreCount)
	{
		threadCount = coreCount;
	}

	return threadCount;
}

bool compiled_plugin_base::InterpolateToPoint(shared_ptr<const NFmiGrid> targetGrid, shared_ptr<NFmiGrid> sourceGrid, bool gridsAreEqual, double& value)
{

	/*
	 * Logic of interpolating values:
	 *
	 * 1) If source and target grids are equal, meaning that the grid AND the area
	 *	properties are effectively the same, do not interpolate. Instead return
	 *	the value of the source grid point that matches the ordering number of the
	 *	target grid point (ie. target grid point #1 --> source grid point #1 etc).
	 *
	 * 2) If actual interpolation is needed, first get the *grid* coordinates of the
	 *	latlon target point. Then check if those grid coordinates are very close
	 *	to a grid point -- if so, return the value of the grid point. This serves two
	 *	purposes:
	 *	- We don't need to interpolate if the distance between requested grid point
	 *	  and actual grid point is small enough, saving some CPU cycles
	 *	- Sometimes when the requested grid point is close to grid edge, floating
	 *	  point inaccuracies might move it outside the grid. If this happens, the
	 *	  interpolation fails even though initially the grid point is valid.
	 *
	 * 3) If requested source grid point is not near and actual grid point, interpolate
	 *	the value of the point.
	 */

	// Step 1)

	if (gridsAreEqual)
	{
		value = sourceGrid->FloatValue(targetGrid->GridPoint());
		return true;
	}

	const NFmiPoint targetLatLonPoint = targetGrid->LatLon();
	const NFmiPoint sourceGridPoint = targetGrid->LatLonToGrid(targetLatLonPoint.X(), targetLatLonPoint.Y());

	// Step 2)

	bool noInterpolation = (fabs(sourceGridPoint.X() - round(sourceGridPoint.X())) < kInterpolatedValueEpsilon &&
		 fabs(sourceGridPoint.Y() - round(sourceGridPoint.Y())) < kInterpolatedValueEpsilon);

	if (noInterpolation)
	{
		value = sourceGrid->FloatValue(sourceGridPoint);
		return true;
	}

	// Step 3)

	return sourceGrid->InterpolateToLatLonPoint(targetLatLonPoint, value);

}

bool compiled_plugin_base::AdjustLeadingDimension(shared_ptr<info> myTargetInfo)
{

	lock_guard<mutex> lock(itsAdjustDimensionMutex);

	// Leading dimension can be: time or level

	if (itsLeadingDimension == kTimeDimension)
	{
		if (!itsFeederInfo->NextTime())
		{
			return false;
		}

		myTargetInfo->Time(itsFeederInfo->Time());
	}
	else if (itsLeadingDimension == kLevelDimension)
	{
		if (!itsFeederInfo->NextLevel())
		{
			return false;
		}

		myTargetInfo->Level(itsFeederInfo->Level());
	}
	else
	{
		throw runtime_error(ClassName() + ": Invalid dimension type: " + boost::lexical_cast<string> (itsLeadingDimension));
	}

	return true;
}

bool compiled_plugin_base::AdjustNonLeadingDimension(shared_ptr<info> myTargetInfo)
{
	if (itsLeadingDimension == kTimeDimension)
	{
		return myTargetInfo->NextLevel();
	}
	else if (itsLeadingDimension == kLevelDimension)
	{
		return myTargetInfo->NextTime();
	}
	else
	{
		throw runtime_error(ClassName() + ": unsupported leading dimension: " + boost::lexical_cast<string> (itsLeadingDimension));
	}
}

void compiled_plugin_base::ResetNonLeadingDimension(shared_ptr<info> myTargetInfo)
{
	if (itsLeadingDimension == kTimeDimension)
	{
		myTargetInfo->ResetLevel();
	}
	else if (itsLeadingDimension == kLevelDimension)
	{
		myTargetInfo->ResetTime();
	}
	else
	{
		throw runtime_error(ClassName() + ": unsupported leading dimension: " + boost::lexical_cast<string> (itsLeadingDimension));
	}
}

himan::level compiled_plugin_base::LevelTransform(const himan::producer& sourceProducer,
													const himan::param& targetParam,
													const himan::level& targetLevel) const
{

	level sourceLevel = targetLevel;

	string levelName = HPLevelTypeToString.at(targetLevel.Type());
	string key = boost::lexical_cast<string> (sourceProducer.Id()) + "_" + levelName + "_" + targetParam.Name();

	// Return value from cache if present

	try
	{
		sourceLevel.Type(itsLevelTransformMap.at(key));

		sourceLevel.Name(levelName);

		if (sourceLevel.Type() == kGround)
		{
			sourceLevel.Value(0);
		}

		return sourceLevel;

	}
	catch (...)
	{

	}

	if (sourceProducer.TableVersion() != kHPMissingInt)
	{
		shared_ptr<neons> n = dynamic_pointer_cast <neons> (plugin_factory::Instance()->Plugin("neons"));

		string lvlName = n->NeonsDB().GetGridLevelName(targetParam.Name(), targetLevel.Type(), 204, sourceProducer.TableVersion());

		HPLevelType lvlType = kUnknownLevel;

		double lvlValue = targetLevel.Value();

		if (lvlName == "GROUND")
		{
			lvlType = kGround;
			lvlValue = 0;
		}
		else if (lvlName == "PRESSURE")
		{
			lvlType = kPressure;
		}
		else if (lvlName == "HYBRID")
		{
			lvlType = kHybrid;
		}
		else if (lvlName == "HEIGHT")
		{
			lvlType = kHeight;
		}
		else
		{
			throw runtime_error(ClassName() + ": Unknown level type: " + lvlName);
		}

		sourceLevel = level(lvlType, lvlValue, lvlName);
	}
	else
	{
		sourceLevel = targetLevel;
	}

	itsLevelTransformMap[key] = sourceLevel.Type();

	return sourceLevel;
}

bool compiled_plugin_base::SetAB(shared_ptr<info> myTargetInfo, shared_ptr<info> sourceInfo)
{
	if (myTargetInfo->Level().Type() == kHybrid)
	{
		size_t index = myTargetInfo->ParamIndex();

		myTargetInfo->Grid()->AB(sourceInfo->Grid()->AB());

		myTargetInfo->ParamIndex(index);
	}

	return true;
}

bool compiled_plugin_base::SwapTo(shared_ptr<info> myTargetInfo, HPScanningMode targetScanningMode)
{

	if (myTargetInfo->Grid()->ScanningMode() != targetScanningMode)
	{
		HPScanningMode originalMode = myTargetInfo->Grid()->ScanningMode();

		myTargetInfo->Grid()->ScanningMode(targetScanningMode);

		myTargetInfo->Grid()->Swap(originalMode);
	}

	return true;
}

void compiled_plugin_base::StoreGrib1ParameterDefinitions(vector<param> params, long table2Version)
{
	shared_ptr<neons> n = dynamic_pointer_cast<neons> (plugin_factory::Instance()->Plugin("neons"));

	for (unsigned int i = 0; i < params.size(); i++)
	{
		long parm_id = n->NeonsDB().GetGridParameterId(table2Version, params[i].Name());
		params[i].GribIndicatorOfParameter(parm_id);
		params[i].GribTableVersion(table2Version);
	}
}

void compiled_plugin_base::WriteToFile(shared_ptr<const plugin_configuration> conf, shared_ptr<const info> targetInfo)
{
	shared_ptr<writer> aWriter = dynamic_pointer_cast <writer> (plugin_factory::Instance()->Plugin("writer"));

	// writing might modify iterator positions --> create a copy

	shared_ptr<info> tempInfo(new info(*targetInfo));

	if (conf->FileWriteOption() == kNeons || conf->FileWriteOption() == kMultipleFiles)
	{
		// if info holds multiple parameters, we must loop over them all

		tempInfo->ResetParam();

		while (tempInfo->NextParam())
		{
			aWriter->ToFile(tempInfo, conf);
		}
	}
	else if (conf->FileWriteOption() == kSingleFile)
	{
		aWriter->ToFile(tempInfo, conf, conf->ConfigurationFile());
	}

	tempInfo.reset();
}

bool compiled_plugin_base::GetAndSetCuda(shared_ptr<const configuration> conf, int threadIndex)
{
	bool ret = conf->UseCuda() && threadIndex <= conf->CudaDeviceCount();

	if (ret)
	{
		shared_ptr<pcuda> p = dynamic_pointer_cast <pcuda> (plugin_factory::Instance()->Plugin("pcuda"));

		ret = p->SetDevice(threadIndex-1);
	}

	return ret;
}

void compiled_plugin_base::ResetCuda() const
{
	shared_ptr<pcuda> p = dynamic_pointer_cast <pcuda> (plugin_factory::Instance()->Plugin("pcuda"));
	p->Reset();
}

int compiled_plugin_base::CudaDeviceId() const
{
	shared_ptr<pcuda> p = dynamic_pointer_cast <pcuda> (plugin_factory::Instance()->Plugin("pcuda"));
	return p->GetDevice();
}
<|endoftext|>


<commit_before><commit_msg>Typo.<commit_after><|endoftext|>


<commit_before>/* Copyright (c) 2016 Tobias Koelsch
 *
 * 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 "sergut/JavaClassGenerator.h"
#include "sergut/detail/JavaClassGeneratorBuilder.h"

#include "TestSupportClasses.h"

#include <catch.hpp>

#include <sstream>

////////////////////////////////////////////////////////////////////////////////
// Test basic datatypes
////////////////////////////////////////////////////////////////////////////////
struct AllBasicTypes {
  bool _bool;
  char _char;
  signed char _signed_char;
  unsigned char _unsigned_char;
  signed short _signed_short;
  unsigned short _unsigned_short;
  signed int _signed_int;
  unsigned int _unsigned_int;
  signed long _signed_long;
  unsigned long _unsigned_long;
  signed long long _signed_long_long;
  unsigned long long _unsigned_long_long;
  float _float;
  double _double;
  const char* _char_ptr;
  std::string _str;
};
SERGUT_FUNCTION(AllBasicTypes, data, ar) {
  ar
      & SERGUT_MMEMBER(data, _bool)
      & SERGUT_MMEMBER(data, _char)
      & SERGUT_MMEMBER(data, _signed_short)
      & SERGUT_MMEMBER(data, _unsigned_short)
      & SERGUT_MMEMBER(data, _signed_int)
      & SERGUT_MMEMBER(data, _unsigned_int)
      & SERGUT_MMEMBER(data, _signed_long)
      & SERGUT_MMEMBER(data, _unsigned_long)
      & SERGUT_MMEMBER(data, _signed_long_long)
      & SERGUT_MMEMBER(data, _unsigned_long_long)
      & SERGUT_MMEMBER(data, _float)
      & SERGUT_MMEMBER(data, _double)
      & SERGUT_MMEMBER(data, _char_ptr)
      & SERGUT_MMEMBER(data, _str);
}

TEST_CASE("Generate Java Class with all basic types", "[JavaGen]")
{
  SECTION("Simple Class") {
    const sergut::JavaClassGenerator cls = sergut::JavaClassGenerator::generate<AllBasicTypes>();
    std::ostringstream ostr;
    ostr << cls;
    CHECK(ostr.str() == std::string());
  }
}

////////////////////////////////////////////////////////////////////////////////
// Check for correct sizes of basic datatypes
////////////////////////////////////////////////////////////////////////////////
struct AllBasicTypeSizes {
  bool _bool;
  char _char;
  int8_t _int8;
  uint8_t _uint8;
  int16_t _int16;
  uint16_t _uint16;
  int32_t _int32;
  uint32_t _uint32;
  int64_t _int64;
  uint64_t _uint64;
  float _float;
  double _double;
  const char* _char_ptr;
  std::string _str;
};
SERGUT_FUNCTION(AllBasicTypeSizes, data, ar) {
  ar
      & SERGUT_MMEMBER(data, _bool)
      & SERGUT_MMEMBER(data, _char)
      & SERGUT_MMEMBER(data, _int8)
      & SERGUT_MMEMBER(data, _uint8)
      & SERGUT_MMEMBER(data, _int16)
      & SERGUT_MMEMBER(data, _uint16)
      & SERGUT_MMEMBER(data, _int32)
      & SERGUT_MMEMBER(data, _uint32)
      & SERGUT_MMEMBER(data, _int64)
      & SERGUT_MMEMBER(data, _uint64)
      & SERGUT_MMEMBER(data, _float)
      & SERGUT_MMEMBER(data, _double)
      & SERGUT_MMEMBER(data, _char_ptr)
      & SERGUT_MMEMBER(data, _str);
}

TEST_CASE("Generate Java Class and check basic type sizes", "[JavaGen]")
{
  SECTION("Simple Class") {
    const sergut::JavaClassGenerator cls = sergut::JavaClassGenerator::generate<AllBasicTypeSizes>();
    std::ostringstream ostr;
    ostr << cls;
    CHECK(ostr.str() == std::string());
  }
}

////////////////////////////////////////////////////////////////////////////////
//
////////////////////////////////////////////////////////////////////////////////
struct C1 {
  std::uint8_t uint8_1;
};
SERGUT_FUNCTION(C1, data, ar) {
  ar
      & SERGUT_MMEMBER(data, uint8_1);
}

namespace ns1 {
namespace ns2 {
struct C1 {
  std::uint8_t uint8_1;
};
SERGUT_FUNCTION(ns1::ns2::C1, data, ar) {
  ar
      & SERGUT_MMEMBER(data, uint8_1);
}

namespace ns3 {
struct C1 {
  std::uint8_t uint8_1;
};
SERGUT_FUNCTION(ns1::ns2::ns3::C1, data, ar) {
  ar
      & SERGUT_MMEMBER(data, uint8_1);
}

struct C1231 {
  std::string str;
  C1 c1;
};
SERGUT_FUNCTION(ns1::ns2::ns3::C1231, data, ar) {
  ar
      & SERGUT_MMEMBER(data, str)
      & sergut::children
      & SERGUT_MMEMBER(data, c1);
}

struct C1232 {
  std::string str;
  C1231 c1231;
};
SERGUT_FUNCTION(ns1::ns2::ns3::C1232, data, ar) {
  ar
      & SERGUT_MMEMBER(data, str)
      & sergut::children
      & SERGUT_MMEMBER(data, c1231);
}

struct C1233 {
  ns1::ns2::ns3::C1 ns1_ns2_ns3_C1;
  ns1::ns2::C1 ns1_ns2_C1;
  C1 globalNs_C1;
};
SERGUT_FUNCTION(ns1::ns2::ns3::C1233, data, ar) {
  ar
      & SERGUT_MMEMBER(data, ns1_ns2_ns3_C1)
      & SERGUT_MMEMBER(data, ns1_ns2_C1)
      & sergut::children
      & SERGUT_MMEMBER(data, globalNs_C1);
}

}
struct C121 {
  ns3::C1231 c1231_1;
  ns3::C1232 c1232;
  ns3::C1231 c1231_2;
};
SERGUT_FUNCTION(ns1::ns2::C121, data, ar) {
  ar
      & SERGUT_MMEMBER(data, c1231_1)
      & SERGUT_MMEMBER(data, c1232)
      & sergut::children
      & SERGUT_MMEMBER(data, c1231_2);
}

}
}

struct C02 {
  ns1::ns2::ns3::C1232 c1232;
};
SERGUT_FUNCTION(C02, data, ar) {
  ar
      & SERGUT_MMEMBER(data, c1232);
}

////////////////////////////////////////////////////////////////////////////////
//
////////////////////////////////////////////////////////////////////////////////
TEST_CASE("Generate Java Class", "[JavaGen]")
{
  SECTION("Simple Class") {
    const sergut::JavaClassGenerator cls = sergut::JavaClassGenerator::generate<SomeTestData>();
    CHECK(cls.getPath() == std::string("SomeTestData.java"));
    std::ostringstream ostr;
    ostr << cls;
    CHECK(ostr.str() == std::string(""));
  }
  SECTION("More complex Class") {
    const sergut::JavaClassGenerator cls = sergut::JavaClassGenerator::generate<SomeMoreComplexTestData>();
    CHECK(cls.getPath() == "SomeMoreComplexTestData.java");
    std::ostringstream ostr;
    ostr << cls;
    CHECK(ostr.str() == std::string(""));
  }
}

TEST_CASE("Generate Java Class with NameSpaces", "[JavaGen]")
{
  SECTION("With Package and Members without Package") {
    const sergut::JavaClassGenerator cls = sergut::JavaClassGenerator::generate<ns1::ns2::ns3::C1231>();
    CHECK(cls.getPath() == "ns1/ns2/ns3/C1231.java");
    std::ostringstream ostr;
    ostr << cls;
    CHECK(ostr.str() == std::string(""));
  }
  SECTION("With Package and Members from same Package") {
    const sergut::JavaClassGenerator cls = sergut::JavaClassGenerator::generate<ns1::ns2::ns3::C1232>();
    CHECK(cls.getPath() == "ns1/ns2/ns3/C1232.java");
    std::ostringstream ostr;
    ostr << cls;
    CHECK(ostr.str() == std::string(""));
  }
  SECTION("With Package and Members from different Packages") {
    const sergut::JavaClassGenerator cls = sergut::JavaClassGenerator::generate<ns1::ns2::ns3::C1233>();
    CHECK(cls.getPath() == "ns1/ns2/ns3/C1233.java");
    std::ostringstream ostr;
    ostr << cls;
    CHECK(ostr.str() == std::string(""));
  }
}

////////////////////////////////////////////////////////////////////////////////
// Tests with collections
/////////////////////////////////////////////////////////////////////////////////
struct ArrayList {
  int32_t someInt32;
};
SERGUT_FUNCTION(ArrayList, data, ar) {
  ar & SERGUT_MMEMBER(data, someInt32);
}
namespace myNameSpace {
struct ArrayList {
  int32_t someInt32;
};
SERGUT_FUNCTION(myNameSpace::ArrayList, data, ar) {
  ar & SERGUT_MMEMBER(data, someInt32);
}

struct TestClassWithCollection {
  std::vector<ns1::ns2::C1> arrayOf__ns1_ns2_C1;

};
SERGUT_FUNCTION(myNameSpace::TestClassWithCollection, data, ar) {
  ar & SERGUT_MMEMBER(data, arrayOf__ns1_ns2_C1);
}

struct TestClassWithCollectionNameSpaceClash {
  std::vector<ns1::ns2::C1> arrayOf__ns1_ns2_C1;
  myNameSpace::ArrayList memberOfClass__myNameSpace_ArrayList;

};
SERGUT_FUNCTION(myNameSpace::TestClassWithCollectionNameSpaceClash, data, ar) {
  ar
      & SERGUT_MMEMBER(data, arrayOf__ns1_ns2_C1)
      & SERGUT_MMEMBER(data, memberOfClass__myNameSpace_ArrayList);
}

struct TestClassWithCollectionNameSpaceClashGlobal {
  std::vector<ns1::ns2::C1> arrayOf__ns1_ns2_C1;
  ::ArrayList memberOfClass__ArrayList;
};
SERGUT_FUNCTION(myNameSpace::TestClassWithCollectionNameSpaceClashGlobal, data, ar) {
  ar
      & SERGUT_MMEMBER(data, arrayOf__ns1_ns2_C1)
      & SERGUT_MMEMBER(data, memberOfClass__ArrayList);
}

struct TestClassWithCollectionNameSpaceClashAndVectorElementNameSpaceClash {
  std::vector<ns1::ns2::C1> arrayOf__ns1_ns2_C1;
  ns1::ns2::ns3::C1 ns1_ns2_ns3_C1;
  myNameSpace::ArrayList memberOfClass__myNameSpace_ArrayList;

};
SERGUT_FUNCTION(myNameSpace::TestClassWithCollectionNameSpaceClashAndVectorElementNameSpaceClash, data, ar) {
  ar
      & SERGUT_MMEMBER(data, arrayOf__ns1_ns2_C1)
      & SERGUT_MMEMBER(data, ns1_ns2_ns3_C1)
      & SERGUT_MMEMBER(data, memberOfClass__myNameSpace_ArrayList);
}

struct TestClassWithCollectionNameSpaceClash2AndVectorElementNameSpaceClash {
  std::vector<ns1::ns2::C1> arrayOf__ns1_ns2_C1;
  ns1::ns2::ns3::C1 ns1_ns2_ns3_C1;
  myNameSpace::ArrayList memberOfClass__myNameSpace_ArrayList;
  ::ArrayList memberOfClass__ArrayList;

};
SERGUT_FUNCTION(myNameSpace::TestClassWithCollectionNameSpaceClash2AndVectorElementNameSpaceClash, data, ar) {
  ar
      & SERGUT_MMEMBER(data, arrayOf__ns1_ns2_C1)
      & SERGUT_MMEMBER(data, ns1_ns2_ns3_C1)
      & SERGUT_MMEMBER(data, memberOfClass__myNameSpace_ArrayList)
      & SERGUT_MMEMBER(data, memberOfClass__ArrayList);
}

}

TEST_CASE("Generate Java Class with collection", "[JavaGen]")
{
  SECTION("Simple Class with vector") {
    std::ostringstream ostr;
    ostr << sergut::JavaClassGenerator::generate<myNameSpace::TestClassWithCollection>();
    CHECK(ostr.str() == std::string(""));
  }
  SECTION("Class with vector and vector namespace clash") {
    std::ostringstream ostr;
    ostr << sergut::JavaClassGenerator::generate<myNameSpace::TestClassWithCollectionNameSpaceClash>();
    CHECK(ostr.str() == std::string(""));
  }
  SECTION("Class with vector and vector namespace clash from global namespace") {
    std::ostringstream ostr;
    ostr << sergut::JavaClassGenerator::generate<myNameSpace::TestClassWithCollectionNameSpaceClashGlobal>();
    CHECK(ostr.str() == std::string(""));
  }
  SECTION("Class with vector and vector namespace clash and vector element namespace clash") {
    std::ostringstream ostr;
    ostr << sergut::JavaClassGenerator::generate<myNameSpace::TestClassWithCollectionNameSpaceClashAndVectorElementNameSpaceClash>();
    CHECK(ostr.str() == std::string(""));
  }
  SECTION("Class with vector and two vector namespace clashes and vector element namespace clash") {
    std::ostringstream ostr;
    ostr << sergut::JavaClassGenerator::generate<myNameSpace::TestClassWithCollectionNameSpaceClash2AndVectorElementNameSpaceClash>();
    CHECK(ostr.str() == std::string(""));
  }
}

////////////////////////////////////////////////////////////////////////////////
// Tests with type mapping
/////////////////////////////////////////////////////////////////////////////////
struct TestClassWithTime {
  int8_t int8_1;
  Time time;
  uint8_t uint8_2;
};
SERGUT_FUNCTION(TestClassWithTime, data, ar) {
  ar
      & SERGUT_MMEMBER(data, int8_1)
      & SERGUT_MMEMBER(data, time)
      & SERGUT_MMEMBER(data, uint8_2);
}

class MyJavaClassGenerator: public sergut::detail::JavaClassGeneratorBuilder<MyJavaClassGenerator> {
public:
  sergut::detail::TypeName getTypeMapping(const std::string& cppTypeName,
                                          const sergut::detail::TypeName::CollectionType collectionType) const override
  {
    if(cppTypeName == "Time") {
      return sergut::detail::TypeName("java::lang::DateTime", collectionType);
    }
    return sergut::detail::JavaClassGeneratorBase::getTypeMapping(cppTypeName, collectionType);
  }
};

TEST_CASE("Generate Java Class overriding a datatype", "[JavaGen]")
{
  SECTION("Override Time") {
    std::ostringstream ostr;
    ostr << MyJavaClassGenerator::generate<TestClassWithTime>();
    CHECK(ostr.str() == std::string(""));
  }
}
<commit_msg>disable java class generator tests<commit_after>/* Copyright (c) 2016 Tobias Koelsch
 *
 * 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.
 */

#if 0

#include "sergut/JavaClassGenerator.h"
#include "sergut/detail/JavaClassGeneratorBuilder.h"

#include "TestSupportClasses.h"

#include <catch.hpp>

#include <sstream>

////////////////////////////////////////////////////////////////////////////////
// Test basic datatypes
////////////////////////////////////////////////////////////////////////////////
struct AllBasicTypes {
  bool _bool;
  char _char;
  signed char _signed_char;
  unsigned char _unsigned_char;
  signed short _signed_short;
  unsigned short _unsigned_short;
  signed int _signed_int;
  unsigned int _unsigned_int;
  signed long _signed_long;
  unsigned long _unsigned_long;
  signed long long _signed_long_long;
  unsigned long long _unsigned_long_long;
  float _float;
  double _double;
  const char* _char_ptr;
  std::string _str;
};
SERGUT_FUNCTION(AllBasicTypes, data, ar) {
  ar
      & SERGUT_MMEMBER(data, _bool)
      & SERGUT_MMEMBER(data, _char)
      & SERGUT_MMEMBER(data, _signed_short)
      & SERGUT_MMEMBER(data, _unsigned_short)
      & SERGUT_MMEMBER(data, _signed_int)
      & SERGUT_MMEMBER(data, _unsigned_int)
      & SERGUT_MMEMBER(data, _signed_long)
      & SERGUT_MMEMBER(data, _unsigned_long)
      & SERGUT_MMEMBER(data, _signed_long_long)
      & SERGUT_MMEMBER(data, _unsigned_long_long)
      & SERGUT_MMEMBER(data, _float)
      & SERGUT_MMEMBER(data, _double)
      & SERGUT_MMEMBER(data, _char_ptr)
      & SERGUT_MMEMBER(data, _str);
}

TEST_CASE("Generate Java Class with all basic types", "[JavaGen]")
{
  SECTION("Simple Class") {
    const sergut::JavaClassGenerator cls = sergut::JavaClassGenerator::generate<AllBasicTypes>();
    std::ostringstream ostr;
    ostr << cls;
    CHECK(ostr.str() == std::string());
  }
}

////////////////////////////////////////////////////////////////////////////////
// Check for correct sizes of basic datatypes
////////////////////////////////////////////////////////////////////////////////
struct AllBasicTypeSizes {
  bool _bool;
  char _char;
  int8_t _int8;
  uint8_t _uint8;
  int16_t _int16;
  uint16_t _uint16;
  int32_t _int32;
  uint32_t _uint32;
  int64_t _int64;
  uint64_t _uint64;
  float _float;
  double _double;
  const char* _char_ptr;
  std::string _str;
};
SERGUT_FUNCTION(AllBasicTypeSizes, data, ar) {
  ar
      & SERGUT_MMEMBER(data, _bool)
      & SERGUT_MMEMBER(data, _char)
      & SERGUT_MMEMBER(data, _int8)
      & SERGUT_MMEMBER(data, _uint8)
      & SERGUT_MMEMBER(data, _int16)
      & SERGUT_MMEMBER(data, _uint16)
      & SERGUT_MMEMBER(data, _int32)
      & SERGUT_MMEMBER(data, _uint32)
      & SERGUT_MMEMBER(data, _int64)
      & SERGUT_MMEMBER(data, _uint64)
      & SERGUT_MMEMBER(data, _float)
      & SERGUT_MMEMBER(data, _double)
      & SERGUT_MMEMBER(data, _char_ptr)
      & SERGUT_MMEMBER(data, _str);
}

TEST_CASE("Generate Java Class and check basic type sizes", "[JavaGen]")
{
  SECTION("Simple Class") {
    const sergut::JavaClassGenerator cls = sergut::JavaClassGenerator::generate<AllBasicTypeSizes>();
    std::ostringstream ostr;
    ostr << cls;
    CHECK(ostr.str() == std::string());
  }
}

////////////////////////////////////////////////////////////////////////////////
//
////////////////////////////////////////////////////////////////////////////////
struct C1 {
  std::uint8_t uint8_1;
};
SERGUT_FUNCTION(C1, data, ar) {
  ar
      & SERGUT_MMEMBER(data, uint8_1);
}

namespace ns1 {
namespace ns2 {
struct C1 {
  std::uint8_t uint8_1;
};
SERGUT_FUNCTION(ns1::ns2::C1, data, ar) {
  ar
      & SERGUT_MMEMBER(data, uint8_1);
}

namespace ns3 {
struct C1 {
  std::uint8_t uint8_1;
};
SERGUT_FUNCTION(ns1::ns2::ns3::C1, data, ar) {
  ar
      & SERGUT_MMEMBER(data, uint8_1);
}

struct C1231 {
  std::string str;
  C1 c1;
};
SERGUT_FUNCTION(ns1::ns2::ns3::C1231, data, ar) {
  ar
      & SERGUT_MMEMBER(data, str)
      & sergut::children
      & SERGUT_MMEMBER(data, c1);
}

struct C1232 {
  std::string str;
  C1231 c1231;
};
SERGUT_FUNCTION(ns1::ns2::ns3::C1232, data, ar) {
  ar
      & SERGUT_MMEMBER(data, str)
      & sergut::children
      & SERGUT_MMEMBER(data, c1231);
}

struct C1233 {
  ns1::ns2::ns3::C1 ns1_ns2_ns3_C1;
  ns1::ns2::C1 ns1_ns2_C1;
  C1 globalNs_C1;
};
SERGUT_FUNCTION(ns1::ns2::ns3::C1233, data, ar) {
  ar
      & SERGUT_MMEMBER(data, ns1_ns2_ns3_C1)
      & SERGUT_MMEMBER(data, ns1_ns2_C1)
      & sergut::children
      & SERGUT_MMEMBER(data, globalNs_C1);
}

}
struct C121 {
  ns3::C1231 c1231_1;
  ns3::C1232 c1232;
  ns3::C1231 c1231_2;
};
SERGUT_FUNCTION(ns1::ns2::C121, data, ar) {
  ar
      & SERGUT_MMEMBER(data, c1231_1)
      & SERGUT_MMEMBER(data, c1232)
      & sergut::children
      & SERGUT_MMEMBER(data, c1231_2);
}

}
}

struct C02 {
  ns1::ns2::ns3::C1232 c1232;
};
SERGUT_FUNCTION(C02, data, ar) {
  ar
      & SERGUT_MMEMBER(data, c1232);
}

////////////////////////////////////////////////////////////////////////////////
//
////////////////////////////////////////////////////////////////////////////////
TEST_CASE("Generate Java Class", "[JavaGen]")
{
  SECTION("Simple Class") {
    const sergut::JavaClassGenerator cls = sergut::JavaClassGenerator::generate<SomeTestData>();
    CHECK(cls.getPath() == std::string("SomeTestData.java"));
    std::ostringstream ostr;
    ostr << cls;
    CHECK(ostr.str() == std::string(""));
  }
  SECTION("More complex Class") {
    const sergut::JavaClassGenerator cls = sergut::JavaClassGenerator::generate<SomeMoreComplexTestData>();
    CHECK(cls.getPath() == "SomeMoreComplexTestData.java");
    std::ostringstream ostr;
    ostr << cls;
    CHECK(ostr.str() == std::string(""));
  }
}

TEST_CASE("Generate Java Class with NameSpaces", "[JavaGen]")
{
  SECTION("With Package and Members without Package") {
    const sergut::JavaClassGenerator cls = sergut::JavaClassGenerator::generate<ns1::ns2::ns3::C1231>();
    CHECK(cls.getPath() == "ns1/ns2/ns3/C1231.java");
    std::ostringstream ostr;
    ostr << cls;
    CHECK(ostr.str() == std::string(""));
  }
  SECTION("With Package and Members from same Package") {
    const sergut::JavaClassGenerator cls = sergut::JavaClassGenerator::generate<ns1::ns2::ns3::C1232>();
    CHECK(cls.getPath() == "ns1/ns2/ns3/C1232.java");
    std::ostringstream ostr;
    ostr << cls;
    CHECK(ostr.str() == std::string(""));
  }
  SECTION("With Package and Members from different Packages") {
    const sergut::JavaClassGenerator cls = sergut::JavaClassGenerator::generate<ns1::ns2::ns3::C1233>();
    CHECK(cls.getPath() == "ns1/ns2/ns3/C1233.java");
    std::ostringstream ostr;
    ostr << cls;
    CHECK(ostr.str() == std::string(""));
  }
}

////////////////////////////////////////////////////////////////////////////////
// Tests with collections
/////////////////////////////////////////////////////////////////////////////////
struct ArrayList {
  int32_t someInt32;
};
SERGUT_FUNCTION(ArrayList, data, ar) {
  ar & SERGUT_MMEMBER(data, someInt32);
}
namespace myNameSpace {
struct ArrayList {
  int32_t someInt32;
};
SERGUT_FUNCTION(myNameSpace::ArrayList, data, ar) {
  ar & SERGUT_MMEMBER(data, someInt32);
}

struct TestClassWithCollection {
  std::vector<ns1::ns2::C1> arrayOf__ns1_ns2_C1;

};
SERGUT_FUNCTION(myNameSpace::TestClassWithCollection, data, ar) {
  ar & SERGUT_MMEMBER(data, arrayOf__ns1_ns2_C1);
}

struct TestClassWithCollectionNameSpaceClash {
  std::vector<ns1::ns2::C1> arrayOf__ns1_ns2_C1;
  myNameSpace::ArrayList memberOfClass__myNameSpace_ArrayList;

};
SERGUT_FUNCTION(myNameSpace::TestClassWithCollectionNameSpaceClash, data, ar) {
  ar
      & SERGUT_MMEMBER(data, arrayOf__ns1_ns2_C1)
      & SERGUT_MMEMBER(data, memberOfClass__myNameSpace_ArrayList);
}

struct TestClassWithCollectionNameSpaceClashGlobal {
  std::vector<ns1::ns2::C1> arrayOf__ns1_ns2_C1;
  ::ArrayList memberOfClass__ArrayList;
};
SERGUT_FUNCTION(myNameSpace::TestClassWithCollectionNameSpaceClashGlobal, data, ar) {
  ar
      & SERGUT_MMEMBER(data, arrayOf__ns1_ns2_C1)
      & SERGUT_MMEMBER(data, memberOfClass__ArrayList);
}

struct TestClassWithCollectionNameSpaceClashAndVectorElementNameSpaceClash {
  std::vector<ns1::ns2::C1> arrayOf__ns1_ns2_C1;
  ns1::ns2::ns3::C1 ns1_ns2_ns3_C1;
  myNameSpace::ArrayList memberOfClass__myNameSpace_ArrayList;

};
SERGUT_FUNCTION(myNameSpace::TestClassWithCollectionNameSpaceClashAndVectorElementNameSpaceClash, data, ar) {
  ar
      & SERGUT_MMEMBER(data, arrayOf__ns1_ns2_C1)
      & SERGUT_MMEMBER(data, ns1_ns2_ns3_C1)
      & SERGUT_MMEMBER(data, memberOfClass__myNameSpace_ArrayList);
}

struct TestClassWithCollectionNameSpaceClash2AndVectorElementNameSpaceClash {
  std::vector<ns1::ns2::C1> arrayOf__ns1_ns2_C1;
  ns1::ns2::ns3::C1 ns1_ns2_ns3_C1;
  myNameSpace::ArrayList memberOfClass__myNameSpace_ArrayList;
  ::ArrayList memberOfClass__ArrayList;

};
SERGUT_FUNCTION(myNameSpace::TestClassWithCollectionNameSpaceClash2AndVectorElementNameSpaceClash, data, ar) {
  ar
      & SERGUT_MMEMBER(data, arrayOf__ns1_ns2_C1)
      & SERGUT_MMEMBER(data, ns1_ns2_ns3_C1)
      & SERGUT_MMEMBER(data, memberOfClass__myNameSpace_ArrayList)
      & SERGUT_MMEMBER(data, memberOfClass__ArrayList);
}

}

TEST_CASE("Generate Java Class with collection", "[JavaGen]")
{
  SECTION("Simple Class with vector") {
    std::ostringstream ostr;
    ostr << sergut::JavaClassGenerator::generate<myNameSpace::TestClassWithCollection>();
    CHECK(ostr.str() == std::string(""));
  }
  SECTION("Class with vector and vector namespace clash") {
    std::ostringstream ostr;
    ostr << sergut::JavaClassGenerator::generate<myNameSpace::TestClassWithCollectionNameSpaceClash>();
    CHECK(ostr.str() == std::string(""));
  }
  SECTION("Class with vector and vector namespace clash from global namespace") {
    std::ostringstream ostr;
    ostr << sergut::JavaClassGenerator::generate<myNameSpace::TestClassWithCollectionNameSpaceClashGlobal>();
    CHECK(ostr.str() == std::string(""));
  }
  SECTION("Class with vector and vector namespace clash and vector element namespace clash") {
    std::ostringstream ostr;
    ostr << sergut::JavaClassGenerator::generate<myNameSpace::TestClassWithCollectionNameSpaceClashAndVectorElementNameSpaceClash>();
    CHECK(ostr.str() == std::string(""));
  }
  SECTION("Class with vector and two vector namespace clashes and vector element namespace clash") {
    std::ostringstream ostr;
    ostr << sergut::JavaClassGenerator::generate<myNameSpace::TestClassWithCollectionNameSpaceClash2AndVectorElementNameSpaceClash>();
    CHECK(ostr.str() == std::string(""));
  }
}

////////////////////////////////////////////////////////////////////////////////
// Tests with type mapping
/////////////////////////////////////////////////////////////////////////////////
struct TestClassWithTime {
  int8_t int8_1;
  Time time;
  uint8_t uint8_2;
};
SERGUT_FUNCTION(TestClassWithTime, data, ar) {
  ar
      & SERGUT_MMEMBER(data, int8_1)
      & SERGUT_MMEMBER(data, time)
      & SERGUT_MMEMBER(data, uint8_2);
}

class MyJavaClassGenerator: public sergut::detail::JavaClassGeneratorBuilder<MyJavaClassGenerator> {
public:
  sergut::detail::TypeName getTypeMapping(const std::string& cppTypeName,
                                          const sergut::detail::TypeName::CollectionType collectionType) const override
  {
    if(cppTypeName == "Time") {
      return sergut::detail::TypeName("java::lang::DateTime", collectionType);
    }
    return sergut::detail::JavaClassGeneratorBase::getTypeMapping(cppTypeName, collectionType);
  }
};

TEST_CASE("Generate Java Class overriding a datatype", "[JavaGen]")
{
  SECTION("Override Time") {
    std::ostringstream ostr;
    ostr << MyJavaClassGenerator::generate<TestClassWithTime>();
    CHECK(ostr.str() == std::string(""));
  }
}

#endif
<|endoftext|>