<commit_before>//
// This file is part of the Marble Virtual Globe.
//
// This program is free software licensed under the GNU LGPL. You can
// find a copy of this license in LICENSE.txt in the top directory of
// the source code.
//
// Copyright 2012       Thibaut Gridel <tgridel@free.fr>
// Copyright 2012,2013  Bernhard Beschow <bbeschow@cs.tu-berlin.de>
//

#include <QtTest/QtTest>
#include "TestUtils.h"

#include "ViewportParams.h"

#include "AbstractProjection.h"
#include "GeoDataCoordinates.h"
#include "GeoDataLineString.h"

namespace Marble
{

class ViewportParamsTest : public QObject
{
    Q_OBJECT

 private slots:
    void constructorDefaultValues();

    void constructorValues_data();
    void constructorValues();

    void screenCoordinates_GeoDataLineString_data();
    void screenCoordinates_GeoDataLineString();

    void setInvalidRadius();

    void setFocusPoint();
};

void ViewportParamsTest::constructorDefaultValues()
{
    const ViewportParams viewport;

    QCOMPARE( viewport.projection(), Spherical );
    QCOMPARE( viewport.size(), QSize( 100, 100 ) );
    QCOMPARE( viewport.width(), 100 );
    QCOMPARE( viewport.height(), 100 );
    QCOMPARE( viewport.centerLongitude(), 0. );
    QCOMPARE( viewport.centerLatitude(), 0. );
    QCOMPARE( viewport.polarity(), 1 );
    QCOMPARE( viewport.radius(), 2000 );
    QCOMPARE( viewport.mapCoversViewport(), true );
    QCOMPARE( viewport.focusPoint(), GeoDataCoordinates( 0., 0., 0. ) );

    // invariants:
    QVERIFY( viewport.radius() > 0 ); // avoids divisions by zero
    QVERIFY( viewport.viewLatLonAltBox() == viewport.latLonAltBox( QRect( 0, 0, 100, 100 ) ) );
    // FIXME QCOMPARE( viewport.viewLatLonAltBox().center().longitude(), viewport.centerLongitude() );
    // FIXME QCOMPARE( viewport.viewLatLonAltBox().center().latitude(), viewport.centerLatitude() );
}

void ViewportParamsTest::constructorValues_data()
{
    QTest::addColumn<Marble::Projection>( "projection" );
    QTest::addColumn<qreal>( "lon" );
    QTest::addColumn<qreal>( "lat" );
    QTest::addColumn<int>( "radius" );
    QTest::addColumn<QSize>( "size" );

    ViewportParams viewport;

    viewport.setProjection( Spherical );
    const AbstractProjection *const spherical = viewport.currentProjection();

    viewport.setProjection( Mercator);
    const AbstractProjection *const mercator = viewport.currentProjection();

    viewport.setProjection( Equirectangular );
    const AbstractProjection *const equirectangular = viewport.currentProjection();

    addRow() << Spherical << 0. << 0. << 2000 << QSize( 100, 100 );
    addRow() << Mercator << 0. << 0. << 2000 << QSize( 100, 100 );
    addRow() << Equirectangular << 0. << 0. << 2000 << QSize( 100, 100 );

    addRow() << Spherical << 205. * DEG2RAD << spherical->maxValidLat() + 1.0 << 2000 << QSize( 100, 100 );
    addRow() << Mercator << 205. * DEG2RAD << mercator->maxValidLat() + 1.0 << 2000 << QSize( 100, 100 );
    addRow() << Equirectangular << 205. * DEG2RAD << equirectangular->maxValidLat() + 1.0 << 2000 << QSize( 100, 100 );
}

void ViewportParamsTest::constructorValues()
{
    QFETCH( Projection, projection );
    QFETCH( qreal, lon );
    QFETCH( qreal, lat );
    QFETCH( int, radius );
    QFETCH( QSize, size );

    const ViewportParams byConstructor( projection, lon, lat, radius, size );

    ViewportParams bySetters;
    bySetters.setProjection( projection );
    bySetters.centerOn( lon, lat );
    bySetters.setRadius( radius );
    bySetters.setSize( size );

    QCOMPARE( byConstructor.projection(), bySetters.projection() );
    QCOMPARE( byConstructor.currentProjection(), bySetters.currentProjection() );
    QCOMPARE( byConstructor.centerLongitude(), bySetters.centerLongitude() );
    QCOMPARE( byConstructor.centerLatitude(), bySetters.centerLatitude() );
    QCOMPARE( byConstructor.planetAxis(), bySetters.planetAxis() );
    QCOMPARE( byConstructor.angularResolution(), bySetters.angularResolution() );
    QCOMPARE( byConstructor.radius(), bySetters.radius() );
    QCOMPARE( byConstructor.size(), bySetters.size() );
}

void ViewportParamsTest::screenCoordinates_GeoDataLineString_data()
{
    QTest::addColumn<Marble::Projection>( "projection" );
    QTest::addColumn<Marble::TessellationFlags>( "tessellation" );
    QTest::addColumn<GeoDataLineString>( "line" );
    QTest::addColumn<int>( "size" );

    GeoDataCoordinates::Unit deg = GeoDataCoordinates::Degree;

    GeoDataLineString longitudeLine;
    longitudeLine << GeoDataCoordinates(185, 5, 0, deg )
                  << GeoDataCoordinates(185, 15, 0, deg );

    GeoDataLineString diagonalLine;
    diagonalLine << GeoDataCoordinates(-185, 5, 0, deg )
                 << GeoDataCoordinates(185, 15, 0, deg );

    GeoDataLineString latitudeLine;
    latitudeLine << GeoDataCoordinates(-185, 5, 0, deg )
                 << GeoDataCoordinates(185, 5, 0, deg );

    Projection projection = Mercator;

    TessellationFlags flags = NoTessellation;
    QTest::newRow("Mercator NoTesselation Longitude")
            << projection << flags << longitudeLine << 2;

    QTest::newRow("Mercator NoTesselation Diagonal IDL")
            << projection << flags << diagonalLine << 2;

    QTest::newRow("Mercator NoTesselation Latitude IDL")
            << projection << flags << latitudeLine << 2;

    flags = Tessellate;
    QTest::newRow("Mercator Tesselate Longitude")
            << projection << flags << longitudeLine << 2;

    QTest::newRow("Mercator Tesselate Diagonal IDL")
            << projection << flags << diagonalLine << 4;

    QTest::newRow("Mercator Tesselate Latitude IDL")
            << projection << flags << latitudeLine << 4;

    flags = Tessellate | RespectLatitudeCircle;
    QTest::newRow("Mercator LatitudeCircle Longitude")
            << projection << flags << longitudeLine << 2;

    QTest::newRow("Mercator LatitudeCircle Diagonal IDL")
            << projection << flags << diagonalLine << 4;

    QTest::newRow("Mercator LatitudeCircle Latitude IDL")
            << projection << flags << latitudeLine << 2;

    projection = Spherical;

    flags = NoTessellation;
    QTest::newRow("Spherical NoTesselation Longitude")
            << projection << flags << longitudeLine << 1;

    QTest::newRow("Spherical NoTesselation Diagonal IDL")
            << projection << flags << diagonalLine << 1;

    QTest::newRow("Spherical NoTesselation Latitude IDL")
            << projection << flags << latitudeLine << 1;

    flags = Tessellate;
    QTest::newRow("Spherical Tesselate Longitude")
            << projection << flags << longitudeLine << 1;

    QTest::newRow("Spherical Tesselate Diagonal IDL")
            << projection << flags << diagonalLine << 1;

    QTest::newRow("Spherical Tesselate Latitude IDL")
            << projection << flags << latitudeLine << 1;

    flags = Tessellate | RespectLatitudeCircle;
    QTest::newRow("Spherical LatitudeCircle Longitude")
            << projection << flags << longitudeLine << 1;

    QTest::newRow("Spherical LatitudeCircle Diagonal IDL")
            << projection << flags << diagonalLine << 1;

    QTest::newRow("Spherical LatitudeCircle Latitude IDL")
            << projection << flags << latitudeLine << 1;

}

void ViewportParamsTest::screenCoordinates_GeoDataLineString()
{
    QFETCH( Marble::Projection, projection );
    QFETCH( Marble::TessellationFlags, tessellation );
    QFETCH( GeoDataLineString, line );
    QFETCH( int, size );

    ViewportParams viewport;
    viewport.setProjection( projection );
    viewport.setRadius( 360 / 4 ); // for easy mapping of lon <-> x
    viewport.centerOn(185 * DEG2RAD, 0);

    line.setTessellationFlags( tessellation );
    QVector<QPolygonF*> polys;
    viewport.screenCoordinates(line, polys);

    foreach (QPolygonF* poly, polys) {
        // at least 2 points in one poly
        QVERIFY( poly->size() > 1 );
        QPointF oldCoord = poly->first();
        poly->pop_front();

        foreach(const QPointF &coord, *poly) {
            // no 2 same points
            QVERIFY( (coord-oldCoord) != QPointF() );

            // no 2 consecutive points should be more than 90° apart
            QVERIFY( (coord-oldCoord).manhattanLength() < viewport.radius() );
            oldCoord = coord;
        }
    }

    // check the provided number of polys
    QCOMPARE( polys.size(), size );
}

void ViewportParamsTest::setInvalidRadius()
{
    ViewportParams viewport;

    // QVERIFY( viewport.radius() > 0 ); already verified above

    const int radius = viewport.radius();
    viewport.setRadius( 0 );

    QCOMPARE( viewport.radius(), radius );
}

void ViewportParamsTest::setFocusPoint()
{
    const GeoDataCoordinates focusPoint1( 10, 13, 0, GeoDataCoordinates::Degree );
    const GeoDataCoordinates focusPoint2( 14.3, 20.5, 0, GeoDataCoordinates::Degree );

    ViewportParams viewport;

    const GeoDataCoordinates center = viewport.focusPoint();

    QVERIFY( center != focusPoint1 );
    QVERIFY( center != focusPoint2 );

    viewport.setFocusPoint( focusPoint1 );
    QCOMPARE( viewport.focusPoint(), focusPoint1 );

    viewport.resetFocusPoint();
    QCOMPARE( viewport.focusPoint(), center );

    viewport.setFocusPoint( focusPoint2 );
    QCOMPARE( viewport.focusPoint(), focusPoint2 );

    viewport.setFocusPoint( focusPoint1 );
    QCOMPARE( viewport.focusPoint(), focusPoint1 );

    viewport.resetFocusPoint();
    QCOMPARE( viewport.focusPoint(), center );
}

}

Q_DECLARE_METATYPE( Marble::Projection )
Q_DECLARE_METATYPE( Marble::TessellationFlag )
Q_DECLARE_METATYPE( Marble::TessellationFlags )
QTEST_MAIN( Marble::ViewportParamsTest )

#include "ViewportParamsTest.moc"
<commit_msg>ViewportParamsTest: hunting the IDL bugs<commit_after>//
// This file is part of the Marble Virtual Globe.
//
// This program is free software licensed under the GNU LGPL. You can
// find a copy of this license in LICENSE.txt in the top directory of
// the source code.
//
// Copyright 2012       Thibaut Gridel <tgridel@free.fr>
// Copyright 2012,2013  Bernhard Beschow <bbeschow@cs.tu-berlin.de>
//

#include <QtTest/QtTest>
#include "TestUtils.h"

#include "ViewportParams.h"

#include "AbstractProjection.h"
#include "GeoDataCoordinates.h"
#include "GeoDataLineString.h"
#include "GeoDataLinearRing.h"

namespace Marble
{

class ViewportParamsTest : public QObject
{
    Q_OBJECT

 private slots:
    void constructorDefaultValues();

    void constructorValues_data();
    void constructorValues();

    void screenCoordinates_GeoDataLineString_data();
    void screenCoordinates_GeoDataLineString();

    void geoDataLinearRing_data();
    void geoDataLinearRing();

    void setInvalidRadius();

    void setFocusPoint();
};

void ViewportParamsTest::constructorDefaultValues()
{
    const ViewportParams viewport;

    QCOMPARE( viewport.projection(), Spherical );
    QCOMPARE( viewport.size(), QSize( 100, 100 ) );
    QCOMPARE( viewport.width(), 100 );
    QCOMPARE( viewport.height(), 100 );
    QCOMPARE( viewport.centerLongitude(), 0. );
    QCOMPARE( viewport.centerLatitude(), 0. );
    QCOMPARE( viewport.polarity(), 1 );
    QCOMPARE( viewport.radius(), 2000 );
    QCOMPARE( viewport.mapCoversViewport(), true );
    QCOMPARE( viewport.focusPoint(), GeoDataCoordinates( 0., 0., 0. ) );

    // invariants:
    QVERIFY( viewport.radius() > 0 ); // avoids divisions by zero
    QVERIFY( viewport.viewLatLonAltBox() == viewport.latLonAltBox( QRect( 0, 0, 100, 100 ) ) );
    // FIXME QCOMPARE( viewport.viewLatLonAltBox().center().longitude(), viewport.centerLongitude() );
    // FIXME QCOMPARE( viewport.viewLatLonAltBox().center().latitude(), viewport.centerLatitude() );
}

void ViewportParamsTest::constructorValues_data()
{
    QTest::addColumn<Marble::Projection>( "projection" );
    QTest::addColumn<qreal>( "lon" );
    QTest::addColumn<qreal>( "lat" );
    QTest::addColumn<int>( "radius" );
    QTest::addColumn<QSize>( "size" );

    ViewportParams viewport;

    viewport.setProjection( Spherical );
    const AbstractProjection *const spherical = viewport.currentProjection();

    viewport.setProjection( Mercator);
    const AbstractProjection *const mercator = viewport.currentProjection();

    viewport.setProjection( Equirectangular );
    const AbstractProjection *const equirectangular = viewport.currentProjection();

    addRow() << Spherical << 0. << 0. << 2000 << QSize( 100, 100 );
    addRow() << Mercator << 0. << 0. << 2000 << QSize( 100, 100 );
    addRow() << Equirectangular << 0. << 0. << 2000 << QSize( 100, 100 );

    addRow() << Spherical << 205. * DEG2RAD << spherical->maxValidLat() + 1.0 << 2000 << QSize( 100, 100 );
    addRow() << Mercator << 205. * DEG2RAD << mercator->maxValidLat() + 1.0 << 2000 << QSize( 100, 100 );
    addRow() << Equirectangular << 205. * DEG2RAD << equirectangular->maxValidLat() + 1.0 << 2000 << QSize( 100, 100 );
}

void ViewportParamsTest::constructorValues()
{
    QFETCH( Projection, projection );
    QFETCH( qreal, lon );
    QFETCH( qreal, lat );
    QFETCH( int, radius );
    QFETCH( QSize, size );

    const ViewportParams byConstructor( projection, lon, lat, radius, size );

    ViewportParams bySetters;
    bySetters.setProjection( projection );
    bySetters.centerOn( lon, lat );
    bySetters.setRadius( radius );
    bySetters.setSize( size );

    QCOMPARE( byConstructor.projection(), bySetters.projection() );
    QCOMPARE( byConstructor.currentProjection(), bySetters.currentProjection() );
    QCOMPARE( byConstructor.centerLongitude(), bySetters.centerLongitude() );
    QCOMPARE( byConstructor.centerLatitude(), bySetters.centerLatitude() );
    QCOMPARE( byConstructor.planetAxis(), bySetters.planetAxis() );
    QCOMPARE( byConstructor.angularResolution(), bySetters.angularResolution() );
    QCOMPARE( byConstructor.radius(), bySetters.radius() );
    QCOMPARE( byConstructor.size(), bySetters.size() );
}

void ViewportParamsTest::screenCoordinates_GeoDataLineString_data()
{
    QTest::addColumn<Marble::Projection>( "projection" );
    QTest::addColumn<Marble::TessellationFlags>( "tessellation" );
    QTest::addColumn<GeoDataLineString>( "line" );
    QTest::addColumn<int>( "size" );

    GeoDataCoordinates::Unit deg = GeoDataCoordinates::Degree;

    GeoDataLineString longitudeLine;
    longitudeLine << GeoDataCoordinates(185, 5, 0, deg )
                  << GeoDataCoordinates(185, 15, 0, deg );

    GeoDataLineString diagonalLine;
    diagonalLine << GeoDataCoordinates(-185, 5, 0, deg )
                 << GeoDataCoordinates(185, 15, 0, deg );

    GeoDataLineString latitudeLine;
    latitudeLine << GeoDataCoordinates(-185, 5, 0, deg )
                 << GeoDataCoordinates(185, 5, 0, deg );

    Projection projection = Mercator;

    TessellationFlags flags = NoTessellation;
    QTest::newRow("Mercator NoTesselation Longitude")
            << projection << flags << longitudeLine << 2;

    QTest::newRow("Mercator NoTesselation Diagonal IDL")
            << projection << flags << diagonalLine << 2;

    QTest::newRow("Mercator NoTesselation Latitude IDL")
            << projection << flags << latitudeLine << 2;

    flags = Tessellate;
    QTest::newRow("Mercator Tesselate Longitude")
            << projection << flags << longitudeLine << 2;

    QTest::newRow("Mercator Tesselate Diagonal IDL")
            << projection << flags << diagonalLine << 4;

    QTest::newRow("Mercator Tesselate Latitude IDL")
            << projection << flags << latitudeLine << 4;

    flags = Tessellate | RespectLatitudeCircle;
    QTest::newRow("Mercator LatitudeCircle Longitude")
            << projection << flags << longitudeLine << 2;

    QTest::newRow("Mercator LatitudeCircle Diagonal IDL")
            << projection << flags << diagonalLine << 4;

    QTest::newRow("Mercator LatitudeCircle Latitude IDL")
            << projection << flags << latitudeLine << 2;

    projection = Spherical;

    flags = NoTessellation;
    QTest::newRow("Spherical NoTesselation Longitude")
            << projection << flags << longitudeLine << 1;

    QTest::newRow("Spherical NoTesselation Diagonal IDL")
            << projection << flags << diagonalLine << 1;

    QTest::newRow("Spherical NoTesselation Latitude IDL")
            << projection << flags << latitudeLine << 1;

    flags = Tessellate;
    QTest::newRow("Spherical Tesselate Longitude")
            << projection << flags << longitudeLine << 1;

    QTest::newRow("Spherical Tesselate Diagonal IDL")
            << projection << flags << diagonalLine << 1;

    QTest::newRow("Spherical Tesselate Latitude IDL")
            << projection << flags << latitudeLine << 1;

    flags = Tessellate | RespectLatitudeCircle;
    QTest::newRow("Spherical LatitudeCircle Longitude")
            << projection << flags << longitudeLine << 1;

    QTest::newRow("Spherical LatitudeCircle Diagonal IDL")
            << projection << flags << diagonalLine << 1;

    QTest::newRow("Spherical LatitudeCircle Latitude IDL")
            << projection << flags << latitudeLine << 1;

}

void ViewportParamsTest::screenCoordinates_GeoDataLineString()
{
    QFETCH( Marble::Projection, projection );
    QFETCH( Marble::TessellationFlags, tessellation );
    QFETCH( GeoDataLineString, line );
    QFETCH( int, size );

    ViewportParams viewport;
    viewport.setProjection( projection );
    viewport.setRadius( 360 / 4 ); // for easy mapping of lon <-> x
    viewport.centerOn(185 * DEG2RAD, 0);

    line.setTessellationFlags( tessellation );
    QVector<QPolygonF*> polys;
    viewport.screenCoordinates(line, polys);

    foreach (QPolygonF* poly, polys) {
        // at least 2 points in one poly
        QVERIFY( poly->size() > 1 );
        QPointF oldCoord = poly->first();
        poly->pop_front();

        foreach(const QPointF &coord, *poly) {
            // no 2 same points
            QVERIFY( (coord-oldCoord) != QPointF() );

            // no 2 consecutive points should be more than 90° apart
            QVERIFY( (coord-oldCoord).manhattanLength() < viewport.radius() );
            oldCoord = coord;
        }
    }

    // check the provided number of polys
    QCOMPARE( polys.size(), size );
}

void ViewportParamsTest::geoDataLinearRing_data()
{
    QTest::addColumn<Marble::Projection>( "projection" );
    QTest::addColumn<Marble::TessellationFlags>( "tessellation" );
    QTest::addColumn<GeoDataLinearRing>( "ring" );
    QTest::addColumn<int>( "size" );

    GeoDataCoordinates::Unit deg = GeoDataCoordinates::Degree;

    GeoDataLinearRing normalRing;
    normalRing << GeoDataCoordinates(175, 5, 0, deg )
               << GeoDataCoordinates(175, 15, 0, deg )
               << GeoDataCoordinates(170, 15, 0, deg );

    GeoDataLinearRing acrossIDLRing;
    acrossIDLRing << GeoDataCoordinates(-175, 5, 0, deg )
                  << GeoDataCoordinates(175, 5, 0, deg )
                  << GeoDataCoordinates(175, 15, 0, deg );

    GeoDataLinearRing aroundSPoleRing;
    aroundSPoleRing << GeoDataCoordinates(-175, -65, 0, deg )
                 << GeoDataCoordinates(115, -70, 0, deg )
                    << GeoDataCoordinates(105, -75, 0, deg );

    Projection projection = Mercator;

    TessellationFlags flags = NoTessellation;
    QTest::newRow("Mercator NoTesselation normalRing")
            << projection << flags << normalRing << 2;

    QTest::newRow("Mercator NoTesselation acrossIDLRing")
            << projection << flags << acrossIDLRing << 2;

    QTest::newRow("Mercator NoTesselation aroundSPoleRing")
            << projection << flags << aroundSPoleRing << 2;

//    flags = Tessellate;
//    QTest::newRow("Mercator Tesselate normalRing")
//            << projection << flags << normalRing << 2;

//    QTest::newRow("Mercator Tesselate acrossIDLRing")
//            << projection << flags << acrossIDLRing << 2;

//    QTest::newRow("Mercator Tesselate aroundSPoleRing")
//            << projection << flags << aroundSPoleRing << 2;

//    flags = Tessellate | RespectLatitudeCircle;
//    QTest::newRow("Mercator LatitudeCircle normalRing")
//            << projection << flags << normalRing << 1;

//    QTest::newRow("Mercator LatitudeCircle acrossIDLRing")
//            << projection << flags << acrossIDLRing << 1;

//    QTest::newRow("Mercator LatitudeCircle aroundSPoleRing")
//            << projection << flags << aroundSPoleRing << 1;

    projection = Spherical;

    flags = NoTessellation;
    QTest::newRow("Spherical NoTesselation normalRing")
            << projection << flags << normalRing << 1;

    QTest::newRow("Spherical NoTesselation acrossIDLRing")
            << projection << flags << acrossIDLRing << 1;

    QTest::newRow("Spherical NoTesselation aroundSPoleRing")
            << projection << flags << aroundSPoleRing << 1;

//    flags = Tessellate;
//    QTest::newRow("Spherical Tesselate normalRing")
//            << projection << flags << normalRing << 1;

//    QTest::newRow("Spherical Tesselate acrossIDLRing")
//            << projection << flags << acrossIDLRing << 1;

//    QTest::newRow("Spherical Tesselate aroundSPoleRing")
//            << projection << flags << aroundSPoleRing << 1;

//    flags = Tessellate | RespectLatitudeCircle;
//    QTest::newRow("Spherical LatitudeCircle normalRing")
//            << projection << flags << normalRing << 1;

//    QTest::newRow("Spherical LatitudeCircle acrossIDLRing")
//            << projection << flags << acrossIDLRing << 1;

//    QTest::newRow("Spherical LatitudeCircle aroundSPoleRing")
//            << projection << flags << aroundSPoleRing << 1;

}

void ViewportParamsTest::geoDataLinearRing()
{
    QFETCH( Marble::Projection, projection );
    QFETCH( Marble::TessellationFlags, tessellation );
    QFETCH( GeoDataLinearRing, ring );
    QFETCH( int, size );

    ViewportParams viewport;
    viewport.setProjection( projection );
    viewport.setRadius( 360 / 4 ); // for easy mapping of lon <-> x
    viewport.centerOn(175 * DEG2RAD, 0);

    ring.setTessellationFlags( tessellation );
    QVector<QPolygonF*> polys;
    viewport.screenCoordinates(ring, polys);

    foreach (QPolygonF* poly, polys) {
        // at least 3 points in one poly
        QVERIFY( poly->size() > 2 );
        QPointF oldCoord = poly->first();
        poly->pop_front();

        foreach(const QPointF &coord, *poly) {
            // no 2 same points
            QVERIFY( (coord-oldCoord) != QPointF() );

            // no 2 consecutive points should be more than 90° apart
//            QVERIFY( (coord-oldCoord).manhattanLength() < viewport.radius() );
            oldCoord = coord;
        }
    }

    // check the provided number of polys
    QCOMPARE( polys.size(), size );
}

void ViewportParamsTest::setInvalidRadius()
{
    ViewportParams viewport;

    // QVERIFY( viewport.radius() > 0 ); already verified above

    const int radius = viewport.radius();
    viewport.setRadius( 0 );

    QCOMPARE( viewport.radius(), radius );
}

void ViewportParamsTest::setFocusPoint()
{
    const GeoDataCoordinates focusPoint1( 10, 13, 0, GeoDataCoordinates::Degree );
    const GeoDataCoordinates focusPoint2( 14.3, 20.5, 0, GeoDataCoordinates::Degree );

    ViewportParams viewport;

    const GeoDataCoordinates center = viewport.focusPoint();

    QVERIFY( center != focusPoint1 );
    QVERIFY( center != focusPoint2 );

    viewport.setFocusPoint( focusPoint1 );
    QCOMPARE( viewport.focusPoint(), focusPoint1 );

    viewport.resetFocusPoint();
    QCOMPARE( viewport.focusPoint(), center );

    viewport.setFocusPoint( focusPoint2 );
    QCOMPARE( viewport.focusPoint(), focusPoint2 );

    viewport.setFocusPoint( focusPoint1 );
    QCOMPARE( viewport.focusPoint(), focusPoint1 );

    viewport.resetFocusPoint();
    QCOMPARE( viewport.focusPoint(), center );
}

}

Q_DECLARE_METATYPE( Marble::GeoDataLinearRing )
Q_DECLARE_METATYPE( Marble::Projection )
Q_DECLARE_METATYPE( Marble::TessellationFlag )
Q_DECLARE_METATYPE( Marble::TessellationFlags )
QTEST_MAIN( Marble::ViewportParamsTest )

#include "ViewportParamsTest.moc"
<|endoftext|>


<commit_before>//
// keyvi - A key value store.
//
// Copyright 2015 Hendrik Muhs<hendrik.muhs@gmail.com>
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

/*
 * memory_map_flags_test.cpp
 *
 *  Created on: May 17, 2016
 *      Author: hendrik
 */

#include <boost/test/unit_test.hpp>
#include <boost/interprocess/mapped_region.hpp>
#include "dictionary/fsa/internal/memory_map_flags.h"

namespace keyvi {
namespace dictionary {
namespace fsa {
namespace internal {

// The name of the suite must be a different name to your class
BOOST_AUTO_TEST_SUITE( MemoryMapFlagsTests )

BOOST_AUTO_TEST_CASE( MemoryMapFlagsTestLazy ) {
  loading_strategy_types strategy = loading_strategy_types::lazy;
  int key_flags = MemoryMapFlags::FSAGetMemoryMapOptions(strategy);
  int value_flags = MemoryMapFlags::ValuesGetMemoryMapOptions(strategy);
  auto key_advise_flags = MemoryMapFlags::FSAGetMemoryMapAdvices(strategy);
  auto value_advise_flags = MemoryMapFlags::ValuesGetMemoryMapAdvices(strategy);

  // no map populate
  BOOST_CHECK((key_flags & MAP_POPULATE) == 0);
  BOOST_CHECK((value_flags & MAP_POPULATE) == 0);

  BOOST_CHECK(key_advise_flags == boost::interprocess::mapped_region::advice_types::advice_normal);
  BOOST_CHECK(value_advise_flags == boost::interprocess::mapped_region::advice_types::advice_normal);
}

BOOST_AUTO_TEST_CASE( MemoryMapFlagsTestPopulate ) {
  loading_strategy_types strategy = loading_strategy_types::populate;
  int key_flags = MemoryMapFlags::FSAGetMemoryMapOptions(strategy);
  int value_flags = MemoryMapFlags::ValuesGetMemoryMapOptions(strategy);
  auto key_advise_flags = MemoryMapFlags::FSAGetMemoryMapAdvices(strategy);
  auto value_advise_flags = MemoryMapFlags::ValuesGetMemoryMapAdvices(strategy);

  // map populate
  BOOST_CHECK((key_flags & MAP_POPULATE));
  BOOST_CHECK((value_flags & MAP_POPULATE));

  BOOST_CHECK(key_advise_flags == boost::interprocess::mapped_region::advice_types::advice_normal);
  BOOST_CHECK(value_advise_flags == boost::interprocess::mapped_region::advice_types::advice_normal);
}

BOOST_AUTO_TEST_CASE( MemoryMapFlagsTestPopulate_key_part ) {
  loading_strategy_types strategy = loading_strategy_types::populate_key_part;
  int key_flags = MemoryMapFlags::FSAGetMemoryMapOptions(strategy);
  int value_flags = MemoryMapFlags::ValuesGetMemoryMapOptions(strategy);
  auto key_advise_flags = MemoryMapFlags::FSAGetMemoryMapAdvices(strategy);
  auto value_advise_flags = MemoryMapFlags::ValuesGetMemoryMapAdvices(strategy);

  // no map populate
  BOOST_CHECK((key_flags & MAP_POPULATE));
  BOOST_CHECK((value_flags & MAP_POPULATE) == 0);

  BOOST_CHECK(key_advise_flags == boost::interprocess::mapped_region::advice_types::advice_normal);
  BOOST_CHECK(value_advise_flags == boost::interprocess::mapped_region::advice_types::advice_normal);
}

BOOST_AUTO_TEST_CASE( MemoryMapFlagsTestPopulate_lazy ) {
  loading_strategy_types strategy = loading_strategy_types::populate_lazy;
  int key_flags = MemoryMapFlags::FSAGetMemoryMapOptions(strategy);
  int value_flags = MemoryMapFlags::ValuesGetMemoryMapOptions(strategy);
  auto key_advise_flags = MemoryMapFlags::FSAGetMemoryMapAdvices(strategy);
  auto value_advise_flags = MemoryMapFlags::ValuesGetMemoryMapAdvices(strategy);

  // no map populate
  BOOST_CHECK((key_flags & MAP_POPULATE) == 0);
  BOOST_CHECK((value_flags & MAP_POPULATE) == 0);

  BOOST_CHECK(key_advise_flags == boost::interprocess::mapped_region::advice_types::advice_willneed);
  BOOST_CHECK(value_advise_flags == boost::interprocess::mapped_region::advice_types::advice_willneed);
}

BOOST_AUTO_TEST_CASE( MemoryMapFlagsTestlazy_no_readahead ) {
  loading_strategy_types strategy = loading_strategy_types::lazy_no_readahead;
  int key_flags = MemoryMapFlags::FSAGetMemoryMapOptions(strategy);
  int value_flags = MemoryMapFlags::ValuesGetMemoryMapOptions(strategy);
  auto key_advise_flags = MemoryMapFlags::FSAGetMemoryMapAdvices(strategy);
  auto value_advise_flags = MemoryMapFlags::ValuesGetMemoryMapAdvices(strategy);

  // no map populate
  BOOST_CHECK((key_flags & MAP_POPULATE) == 0);
  BOOST_CHECK((value_flags & MAP_POPULATE) == 0);

  BOOST_CHECK(key_advise_flags == boost::interprocess::mapped_region::advice_types::advice_random);
  BOOST_CHECK(value_advise_flags == boost::interprocess::mapped_region::advice_types::advice_random);
}

BOOST_AUTO_TEST_CASE( MemoryMapFlagsTestlazy_no_readahead_value_part ) {
  loading_strategy_types strategy = loading_strategy_types::lazy_no_readahead_value_part;
  int key_flags = MemoryMapFlags::FSAGetMemoryMapOptions(strategy);
  int value_flags = MemoryMapFlags::ValuesGetMemoryMapOptions(strategy);
  auto key_advise_flags = MemoryMapFlags::FSAGetMemoryMapAdvices(strategy);
  auto value_advise_flags = MemoryMapFlags::ValuesGetMemoryMapAdvices(strategy);

  // no map populate
  BOOST_CHECK((key_flags & MAP_POPULATE) == 0);
  BOOST_CHECK((value_flags & MAP_POPULATE) == 0);

  BOOST_CHECK(key_advise_flags == boost::interprocess::mapped_region::advice_types::advice_normal);
  BOOST_CHECK(value_advise_flags == boost::interprocess::mapped_region::advice_types::advice_random);
}

BOOST_AUTO_TEST_CASE( MemoryMapFlagsTestpopulate_key_part_no_readahead_value_part ) {
  loading_strategy_types strategy = loading_strategy_types::populate_key_part_no_readahead_value_part;
  int key_flags = MemoryMapFlags::FSAGetMemoryMapOptions(strategy);
  int value_flags = MemoryMapFlags::ValuesGetMemoryMapOptions(strategy);
  auto key_advise_flags = MemoryMapFlags::FSAGetMemoryMapAdvices(strategy);
  auto value_advise_flags = MemoryMapFlags::ValuesGetMemoryMapAdvices(strategy);

  // no map populate
  BOOST_CHECK((key_flags & MAP_POPULATE));
  BOOST_CHECK((value_flags & MAP_POPULATE) == 0);

  BOOST_CHECK(key_advise_flags == boost::interprocess::mapped_region::advice_types::advice_normal);
  BOOST_CHECK(value_advise_flags == boost::interprocess::mapped_region::advice_types::advice_random);
}

BOOST_AUTO_TEST_SUITE_END()

} /* namespace internal */
} /* namespace fsa */
} /* namespace dictionary */
} /* namespace keyvi */

<commit_msg>no map populate tests on OSX, as OSX doesn't support map populate<commit_after>//
// keyvi - A key value store.
//
// Copyright 2015 Hendrik Muhs<hendrik.muhs@gmail.com>
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

/*
 * memory_map_flags_test.cpp
 *
 *  Created on: May 17, 2016
 *      Author: hendrik
 */

#include <boost/test/unit_test.hpp>
#include <boost/interprocess/mapped_region.hpp>
#include "dictionary/fsa/internal/memory_map_flags.h"

namespace keyvi {
namespace dictionary {
namespace fsa {
namespace internal {

// The name of the suite must be a different name to your class
BOOST_AUTO_TEST_SUITE( MemoryMapFlagsTests )

BOOST_AUTO_TEST_CASE( MemoryMapFlagsTestLazy ) {
  loading_strategy_types strategy = loading_strategy_types::lazy;
  int key_flags = MemoryMapFlags::FSAGetMemoryMapOptions(strategy);
  int value_flags = MemoryMapFlags::ValuesGetMemoryMapOptions(strategy);
  auto key_advise_flags = MemoryMapFlags::FSAGetMemoryMapAdvices(strategy);
  auto value_advise_flags = MemoryMapFlags::ValuesGetMemoryMapAdvices(strategy);

#if not defined(OS_MACOSX)
  // no map populate
  BOOST_CHECK((key_flags & MAP_POPULATE) == 0);
  BOOST_CHECK((value_flags & MAP_POPULATE) == 0);
#endif

  BOOST_CHECK(key_advise_flags == boost::interprocess::mapped_region::advice_types::advice_normal);
  BOOST_CHECK(value_advise_flags == boost::interprocess::mapped_region::advice_types::advice_normal);
}

BOOST_AUTO_TEST_CASE( MemoryMapFlagsTestPopulate ) {
  loading_strategy_types strategy = loading_strategy_types::populate;
  int key_flags = MemoryMapFlags::FSAGetMemoryMapOptions(strategy);
  int value_flags = MemoryMapFlags::ValuesGetMemoryMapOptions(strategy);
  auto key_advise_flags = MemoryMapFlags::FSAGetMemoryMapAdvices(strategy);
  auto value_advise_flags = MemoryMapFlags::ValuesGetMemoryMapAdvices(strategy);

#if not defined(OS_MACOSX)
  // map populate
  BOOST_CHECK((key_flags & MAP_POPULATE));
  BOOST_CHECK((value_flags & MAP_POPULATE));
#endif

  BOOST_CHECK(key_advise_flags == boost::interprocess::mapped_region::advice_types::advice_normal);
  BOOST_CHECK(value_advise_flags == boost::interprocess::mapped_region::advice_types::advice_normal);
}

BOOST_AUTO_TEST_CASE( MemoryMapFlagsTestPopulate_key_part ) {
  loading_strategy_types strategy = loading_strategy_types::populate_key_part;
  int key_flags = MemoryMapFlags::FSAGetMemoryMapOptions(strategy);
  int value_flags = MemoryMapFlags::ValuesGetMemoryMapOptions(strategy);
  auto key_advise_flags = MemoryMapFlags::FSAGetMemoryMapAdvices(strategy);
  auto value_advise_flags = MemoryMapFlags::ValuesGetMemoryMapAdvices(strategy);

#if not defined(OS_MACOSX)
  // no map populate
  BOOST_CHECK((key_flags & MAP_POPULATE));
  BOOST_CHECK((value_flags & MAP_POPULATE) == 0);
#endif

  BOOST_CHECK(key_advise_flags == boost::interprocess::mapped_region::advice_types::advice_normal);
  BOOST_CHECK(value_advise_flags == boost::interprocess::mapped_region::advice_types::advice_normal);
}

BOOST_AUTO_TEST_CASE( MemoryMapFlagsTestPopulate_lazy ) {
  loading_strategy_types strategy = loading_strategy_types::populate_lazy;
  int key_flags = MemoryMapFlags::FSAGetMemoryMapOptions(strategy);
  int value_flags = MemoryMapFlags::ValuesGetMemoryMapOptions(strategy);
  auto key_advise_flags = MemoryMapFlags::FSAGetMemoryMapAdvices(strategy);
  auto value_advise_flags = MemoryMapFlags::ValuesGetMemoryMapAdvices(strategy);

#if not defined(OS_MACOSX)
  // no map populate
  BOOST_CHECK((key_flags & MAP_POPULATE) == 0);
  BOOST_CHECK((value_flags & MAP_POPULATE) == 0);
#endif

  BOOST_CHECK(key_advise_flags == boost::interprocess::mapped_region::advice_types::advice_willneed);
  BOOST_CHECK(value_advise_flags == boost::interprocess::mapped_region::advice_types::advice_willneed);
}

BOOST_AUTO_TEST_CASE( MemoryMapFlagsTestlazy_no_readahead ) {
  loading_strategy_types strategy = loading_strategy_types::lazy_no_readahead;
  int key_flags = MemoryMapFlags::FSAGetMemoryMapOptions(strategy);
  int value_flags = MemoryMapFlags::ValuesGetMemoryMapOptions(strategy);
  auto key_advise_flags = MemoryMapFlags::FSAGetMemoryMapAdvices(strategy);
  auto value_advise_flags = MemoryMapFlags::ValuesGetMemoryMapAdvices(strategy);

#if not defined(OS_MACOSX)
  // no map populate
  BOOST_CHECK((key_flags & MAP_POPULATE) == 0);
  BOOST_CHECK((value_flags & MAP_POPULATE) == 0);
#endif

  BOOST_CHECK(key_advise_flags == boost::interprocess::mapped_region::advice_types::advice_random);
  BOOST_CHECK(value_advise_flags == boost::interprocess::mapped_region::advice_types::advice_random);
}

BOOST_AUTO_TEST_CASE( MemoryMapFlagsTestlazy_no_readahead_value_part ) {
  loading_strategy_types strategy = loading_strategy_types::lazy_no_readahead_value_part;
  int key_flags = MemoryMapFlags::FSAGetMemoryMapOptions(strategy);
  int value_flags = MemoryMapFlags::ValuesGetMemoryMapOptions(strategy);
  auto key_advise_flags = MemoryMapFlags::FSAGetMemoryMapAdvices(strategy);
  auto value_advise_flags = MemoryMapFlags::ValuesGetMemoryMapAdvices(strategy);

#if not defined(OS_MACOSX)
  // no map populate
  BOOST_CHECK((key_flags & MAP_POPULATE) == 0);
  BOOST_CHECK((value_flags & MAP_POPULATE) == 0);
#endif

  BOOST_CHECK(key_advise_flags == boost::interprocess::mapped_region::advice_types::advice_normal);
  BOOST_CHECK(value_advise_flags == boost::interprocess::mapped_region::advice_types::advice_random);
}

BOOST_AUTO_TEST_CASE( MemoryMapFlagsTestpopulate_key_part_no_readahead_value_part ) {
  loading_strategy_types strategy = loading_strategy_types::populate_key_part_no_readahead_value_part;
  int key_flags = MemoryMapFlags::FSAGetMemoryMapOptions(strategy);
  int value_flags = MemoryMapFlags::ValuesGetMemoryMapOptions(strategy);
  auto key_advise_flags = MemoryMapFlags::FSAGetMemoryMapAdvices(strategy);
  auto value_advise_flags = MemoryMapFlags::ValuesGetMemoryMapAdvices(strategy);

#if not defined(OS_MACOSX)
  // no map populate
  BOOST_CHECK((key_flags & MAP_POPULATE));
  BOOST_CHECK((value_flags & MAP_POPULATE) == 0);
#endif

  BOOST_CHECK(key_advise_flags == boost::interprocess::mapped_region::advice_types::advice_normal);
  BOOST_CHECK(value_advise_flags == boost::interprocess::mapped_region::advice_types::advice_random);
}

BOOST_AUTO_TEST_SUITE_END()

} /* namespace internal */
} /* namespace fsa */
} /* namespace dictionary */
} /* namespace keyvi */

<|endoftext|>


<commit_before>//
// Created by xzl on 2018/9/20.
//

#include "HttpRequestSplitter.h"
#include "Util/logger.h"
#include "Util/util.h"
using namespace ZL::Util;

void HttpRequestSplitter::input(const char *data,uint64_t len) {
    const char *ptr = data;
    if(!_remain_data.empty()){
        _remain_data.append(data,len);
        data = ptr = _remain_data.data();
        len = _remain_data.size();
    }

splitPacket:

    //数据按照请求头处理
    char *index = nullptr;
    while (_content_len == 0 && (index = strstr(ptr,"\r\n\r\n")) != nullptr) {
        //_content_len == 0，这是请求头
        _content_len = onRecvHeader(ptr, index - ptr + 4);
        ptr = index + 4;
    }

    uint64_t remain = len - (ptr - data);
    if(remain <= 0){
        //没有剩余数据，清空缓存
        _remain_data.clear();
        return;
    }

    if(_content_len == 0){
        //尚未找到http头，缓存定位到剩余数据部分
        _remain_data.assign(ptr,remain);
        return;
    }

    //已经找到http头了
    if(_content_len > 0){
        //数据按照固定长度content处理
        if(remain < _content_len){
            //数据不够，缓存定位到剩余数据部分
            _remain_data.assign(ptr,remain);
            return;
        }
        //收到content数据，并且接受content完毕
        onRecvContent(ptr,_content_len);

        remain -= _content_len;
        ptr += _content_len;
        //content处理完毕,后面数据当做请求头处理
        _content_len = 0;

        if(remain > 0){
            //还有数据没有处理完毕
            _remain_data.assign(ptr,remain);

            data = ptr = (char *)_remain_data.data();
            len = _remain_data.size();
            goto splitPacket;
        }
        return;
    }

    //_content_len < 0;数据按照不固定长度content处理
    onRecvContent(ptr,remain);//消费掉所有剩余数据
    _remain_data.clear();
}

void HttpRequestSplitter::setContentLen(int64_t content_len) {
    _content_len = content_len;
}
<commit_msg>修复编译问题<commit_after>//
// Created by xzl on 2018/9/20.
//

#include "HttpRequestSplitter.h"
#include "Util/logger.h"
#include "Util/util.h"
using namespace ZL::Util;

void HttpRequestSplitter::input(const char *data,uint64_t len) {
    const char *ptr = data;
    if(!_remain_data.empty()){
        _remain_data.append(data,len);
        data = ptr = _remain_data.data();
        len = _remain_data.size();
    }

splitPacket:

    //数据按照请求头处理
    const char *index = nullptr;
    while (_content_len == 0 && (index = strstr(ptr,"\r\n\r\n")) != nullptr) {
        //_content_len == 0，这是请求头
        _content_len = onRecvHeader(ptr, index - ptr + 4);
        ptr = index + 4;
    }

    uint64_t remain = len - (ptr - data);
    if(remain <= 0){
        //没有剩余数据，清空缓存
        _remain_data.clear();
        return;
    }

    if(_content_len == 0){
        //尚未找到http头，缓存定位到剩余数据部分
        _remain_data.assign(ptr,remain);
        return;
    }

    //已经找到http头了
    if(_content_len > 0){
        //数据按照固定长度content处理
        if(remain < _content_len){
            //数据不够，缓存定位到剩余数据部分
            _remain_data.assign(ptr,remain);
            return;
        }
        //收到content数据，并且接受content完毕
        onRecvContent(ptr,_content_len);

        remain -= _content_len;
        ptr += _content_len;
        //content处理完毕,后面数据当做请求头处理
        _content_len = 0;

        if(remain > 0){
            //还有数据没有处理完毕
            _remain_data.assign(ptr,remain);

            data = ptr = (char *)_remain_data.data();
            len = _remain_data.size();
            goto splitPacket;
        }
        return;
    }

    //_content_len < 0;数据按照不固定长度content处理
    onRecvContent(ptr,remain);//消费掉所有剩余数据
    _remain_data.clear();
}

void HttpRequestSplitter::setContentLen(int64_t content_len) {
    _content_len = content_len;
}
<|endoftext|>


<commit_before>/*
	Multi-precision real number class. C++ wrapper fo MPFR library.
	Project homepage: http://www.holoborodko.com/pavel/
	Contact e-mail:   pavel@holoborodko.com

	Copyright (c) 2008-2010 Pavel Holoborodko

	This library is free software; you can redistribute it and/or
	modify it under the terms of the GNU Lesser General Public
	License as published by the Free Software Foundation; either
	version 2.1 of the License, or (at your option) any later version.

	This library is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
	Lesser General Public License for more details.

	You should have received a copy of the GNU Lesser General Public
	License along with this library; if not, write to the Free Software
	Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

	Contributors:
	Brian Gladman, Helmut Jarausch, Fokko Beekhof, Ulrich Mutze,
	Heinz van Saanen, Pere Constans, Dmitriy Gubanov
*/

#include <cstring>
#include "mpreal.h"

using std::ws;
using std::cerr;
using std::endl;
using std::string;
using std::ostream;
using std::istream;

namespace mpfr{

mp_rnd_t   mpreal::default_rnd  = mpfr_get_default_rounding_mode();
mp_prec_t  mpreal::default_prec = mpfr_get_default_prec();
int		   mpreal::default_base = 10;
int        mpreal::double_bits = -1;

// Default constructor: creates mp number and initializes it to 0.
mpreal::mpreal()
{
	mpfr_init2(mp,default_prec);
	mpfr_set_ui(mp,0,default_rnd);
}

mpreal::mpreal(const mpreal& u)
{
	mpfr_init2(mp,mpfr_get_prec(u.mp));
	mpfr_set(mp,u.mp,default_rnd);
}

mpreal::mpreal(const mpfr_t u)
{
	mpfr_init2(mp,mpfr_get_prec(u));
	mpfr_set(mp,u,default_rnd);
}

mpreal::mpreal(const mpf_t u)
{
	mpfr_init2(mp,mpf_get_prec(u));
	mpfr_set_f(mp,u,default_rnd);
}

mpreal::mpreal(const mpz_t u, mp_prec_t prec, mp_rnd_t mode)
{
	mpfr_init2(mp,prec);
	mpfr_set_z(mp,u,mode);
}

mpreal::mpreal(const mpq_t u, mp_prec_t prec, mp_rnd_t mode)
{
	mpfr_init2(mp,prec);
	mpfr_set_q(mp,u,mode);
}

mpreal::mpreal(const double u, mp_prec_t prec, mp_rnd_t mode)
{
    if(double_bits == -1 || fits_in_bits(u, double_bits))
    {
    	mpfr_init2(mp,prec);
	    mpfr_set_d(mp,u,mode);
    }
    else
        throw conversion_overflow();
}

mpreal::mpreal(const long double u, mp_prec_t prec, mp_rnd_t mode)
{
    mpfr_init2(mp,prec);
	mpfr_set_ld(mp,u,mode);
}

mpreal::mpreal(const unsigned long int u, mp_prec_t prec, mp_rnd_t mode)
{
	mpfr_init2(mp,prec);
	mpfr_set_ui(mp,u,mode);
}

mpreal::mpreal(const unsigned int u, mp_prec_t prec, mp_rnd_t mode)
{
	mpfr_init2(mp,prec);
	mpfr_set_ui(mp,u,mode);
}

mpreal::mpreal(const long int u, mp_prec_t prec, mp_rnd_t mode)
{
	mpfr_init2(mp,prec);
	mpfr_set_si(mp,u,mode);
}

mpreal::mpreal(const int u, mp_prec_t prec, mp_rnd_t mode)
{
	mpfr_init2(mp,prec);
	mpfr_set_si(mp,u,mode);
}

mpreal::mpreal(const char* s, mp_prec_t prec, int base, mp_rnd_t mode)
{
	mpfr_init2(mp,prec);
	mpfr_set_str(mp, s, base, mode);
}

mpreal::~mpreal()
{
	mpfr_clear(mp);
}

// Operators - Assignment
mpreal& mpreal::operator=(const char* s)
{
	mpfr_t t;
	if(0==mpfr_init_set_str(t,s,default_base,default_rnd))
	{
		mpfr_set(mp,t,mpreal::default_rnd);
		mpfr_clear(t);
	}else{
		mpfr_clear(t);
		// cerr<<"fail to convert string"<<endl;
	}

	return *this;
}

const mpreal fma (const mpreal& v1, const mpreal& v2, const mpreal& v3, mp_rnd_t rnd_mode)
{
	mpreal a;
	mp_prec_t p1, p2, p3;

	p1 = v1.get_prec();
	p2 = v2.get_prec();
	p3 = v3.get_prec();

	a.set_prec(p3>p2?(p3>p1?p3:p1):(p2>p1?p2:p1));

	mpfr_fma(a.mp,v1.mp,v2.mp,v3.mp,rnd_mode);
	return a;
}

const mpreal fms (const mpreal& v1, const mpreal& v2, const mpreal& v3, mp_rnd_t rnd_mode)
{
	mpreal a;
	mp_prec_t p1, p2, p3;

	p1 = v1.get_prec();
	p2 = v2.get_prec();
	p3 = v3.get_prec();

	a.set_prec(p3>p2?(p3>p1?p3:p1):(p2>p1?p2:p1));

	mpfr_fms(a.mp,v1.mp,v2.mp,v3.mp,rnd_mode);
	return a;
}

const mpreal agm (const mpreal& v1, const mpreal& v2, mp_rnd_t rnd_mode)
{
	mpreal a;
	mp_prec_t p1, p2;

	p1 = v1.get_prec();
	p2 = v2.get_prec();

	a.set_prec(p1>p2?p1:p2);

	mpfr_agm(a.mp, v1.mp, v2.mp, rnd_mode);

	return a;
}

const mpreal hypot (const mpreal& x, const mpreal& y, mp_rnd_t rnd_mode)
{
	mpreal a;
	mp_prec_t yp, xp;

	yp = y.get_prec();
	xp = x.get_prec();

	a.set_prec(yp>xp?yp:xp);

	mpfr_hypot(a.mp, x.mp, y.mp, rnd_mode);

	return a;
}

const mpreal sum (const mpreal tab[], unsigned long int n, mp_rnd_t rnd_mode)
{
	mpreal x;
	mpfr_ptr* t;
	unsigned long int i;

	t = new mpfr_ptr[n];
	for (i=0;i<n;i++) t[i] = (mpfr_ptr)tab[i].mp;
	mpfr_sum(x.mp,t,n,rnd_mode);
	delete[] t;
	return x;
}

const mpreal remainder (const mpreal& x, const mpreal& y, mp_rnd_t rnd_mode)
{
	mpreal a;
	mp_prec_t yp, xp;

	yp = y.get_prec();
	xp = x.get_prec();

	a.set_prec(yp>xp?yp:xp);

	mpfr_remainder(a.mp, x.mp, y.mp, rnd_mode);

	return a;
}

const mpreal remquo (long* q, const mpreal& x, const mpreal& y, mp_rnd_t rnd_mode)
{
	mpreal a;
	mp_prec_t yp, xp;

	yp = y.get_prec();
	xp = x.get_prec();

	a.set_prec(yp>xp?yp:xp);

	mpfr_remquo(a.mp,q, x.mp, y.mp, rnd_mode);

	return a;
}

template <class T>
std::string to_string(T t, std::ios_base & (*f)(std::ios_base&))
{
	std::ostringstream oss;
	oss << f << t;
	return oss.str();
}

mpreal::operator std::string() const
{
	return to_string();
}

string mpreal::to_string(size_t n, int b, mp_rnd_t mode) const
{
	char *s, *ns = NULL;
	size_t slen, nslen;
	mp_exp_t exp;
	string out;

	if(mpfr_inf_p(mp))
	{
		if(mpfr_sgn(mp)>0) return "+@Inf@";
		else			   return "-@Inf@";
	}

	if(mpfr_zero_p(mp)) return "0";
	if(mpfr_nan_p(mp))  return "@NaN@";

	s  = mpfr_get_str(NULL,&exp,b,0,mp,mode);
	ns = mpfr_get_str(NULL,&exp,b,n,mp,mode);

	if(s!=NULL && ns!=NULL)
	{
		slen  = strlen(s);
		nslen = strlen(ns);
		if(nslen<=slen)
		{
			mpfr_free_str(s);
			s = ns;
			slen = nslen;
		}
		else {
			mpfr_free_str(ns);
		}

		// Make human eye-friendly formatting if possible
		if (exp>0 && static_cast<size_t>(exp)<slen)
		{
			if(s[0]=='-')
			{
				// Remove zeros starting from right end
				char* ptr = s+slen-1;
				while (*ptr=='0' && ptr>s+exp) ptr--;

				if(ptr==s+exp) out = string(s,exp+1);
				else		   out = string(s,exp+1)+'.'+string(s+exp+1,ptr-(s+exp+1)+1);

				//out = string(s,exp+1)+'.'+string(s+exp+1);
			}
			else
			{
				// Remove zeros starting from right end
				char* ptr = s+slen-1;
				while (*ptr=='0' && ptr>s+exp-1) ptr--;

				if(ptr==s+exp-1) out = string(s,exp);
				else		     out = string(s,exp)+'.'+string(s+exp,ptr-(s+exp)+1);

				//out = string(s,exp)+'.'+string(s+exp);
			}

		}else{ // exp<0 || exp>slen
			if(s[0]=='-')
			{
				// Remove zeros starting from right end
				char* ptr = s+slen-1;
				while (*ptr=='0' && ptr>s+1) ptr--;

				if(ptr==s+1) out = string(s,2);
				else		 out = string(s,2)+'.'+string(s+2,ptr-(s+2)+1);

				//out = string(s,2)+'.'+string(s+2);
			}
			else
			{
				// Remove zeros starting from right end
				char* ptr = s+slen-1;
				while (*ptr=='0' && ptr>s) ptr--;

				if(ptr==s) out = string(s,1);
				else	   out = string(s,1)+'.'+string(s+1,ptr-(s+1)+1);

				//out = string(s,1)+'.'+string(s+1);
			}

			// Make final string
			if(--exp)
			{
				if(exp>0) out += "e+"+mpfr::to_string<mp_exp_t>(exp,std::dec);
				else 	  out += "e"+mpfr::to_string<mp_exp_t>(exp,std::dec);
			}
		}

		mpfr_free_str(s);
		return out;
	}else{
		return "conversion error!";
	}
}

//////////////////////////////////////////////////////////////////////////
// I/O
ostream& operator<<(ostream& os, const mpreal& v)
{
	return os<<v.to_string(os.precision());
}

istream& operator>>(istream &is, mpreal& v)
{
	char c;
	string s = "";
	mpfr_t t;

	if(is.good())
	{
		is>>ws;
		while ((c = is.get())!=EOF)
		{
			if(c ==' ' || c == '\t' || c == '\n' || c == '\r')
			{
				is.putback(c);
				break;
			}
			s += c;
		}

		if(s.size() != 0)
		{
			// Protect current value from alternation in case of input error
			// so some error handling(roll back) procedure can be used
			if(0==mpfr_init_set_str(t,s.c_str(),mpreal::default_base,mpreal::default_rnd))
			{
				mpfr_set(v.mp,t,mpreal::default_rnd);
				mpfr_clear(t);

			}else{
				mpfr_clear(t);
				cerr<<"error reading from istream"<<endl;
				// throw an exception
			}
		}
	}
	return is;
}
}
<commit_msg>dos2unix<commit_after>/*
	Multi-precision real number class. C++ wrapper fo MPFR library.
	Project homepage: http://www.holoborodko.com/pavel/
	Contact e-mail:   pavel@holoborodko.com

	Copyright (c) 2008-2010 Pavel Holoborodko

	This library is free software; you can redistribute it and/or
	modify it under the terms of the GNU Lesser General Public
	License as published by the Free Software Foundation; either
	version 2.1 of the License, or (at your option) any later version.

	This library is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
	Lesser General Public License for more details.

	You should have received a copy of the GNU Lesser General Public
	License along with this library; if not, write to the Free Software
	Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

	Contributors:
	Brian Gladman, Helmut Jarausch, Fokko Beekhof, Ulrich Mutze,
	Heinz van Saanen, Pere Constans, Dmitriy Gubanov
*/

#include <cstring>
#include "mpreal.h"

using std::ws;
using std::cerr;
using std::endl;
using std::string;
using std::ostream;
using std::istream;

namespace mpfr{

mp_rnd_t   mpreal::default_rnd  = mpfr_get_default_rounding_mode();
mp_prec_t  mpreal::default_prec = mpfr_get_default_prec();
int		   mpreal::default_base = 10;
int        mpreal::double_bits = -1;

// Default constructor: creates mp number and initializes it to 0.
mpreal::mpreal()
{
	mpfr_init2(mp,default_prec);
	mpfr_set_ui(mp,0,default_rnd);
}

mpreal::mpreal(const mpreal& u)
{
	mpfr_init2(mp,mpfr_get_prec(u.mp));
	mpfr_set(mp,u.mp,default_rnd);
}

mpreal::mpreal(const mpfr_t u)
{
	mpfr_init2(mp,mpfr_get_prec(u));
	mpfr_set(mp,u,default_rnd);
}

mpreal::mpreal(const mpf_t u)
{
	mpfr_init2(mp,mpf_get_prec(u));
	mpfr_set_f(mp,u,default_rnd);
}

mpreal::mpreal(const mpz_t u, mp_prec_t prec, mp_rnd_t mode)
{
	mpfr_init2(mp,prec);
	mpfr_set_z(mp,u,mode);
}

mpreal::mpreal(const mpq_t u, mp_prec_t prec, mp_rnd_t mode)
{
	mpfr_init2(mp,prec);
	mpfr_set_q(mp,u,mode);
}

mpreal::mpreal(const double u, mp_prec_t prec, mp_rnd_t mode)
{
    if(double_bits == -1 || fits_in_bits(u, double_bits))
    {
    	mpfr_init2(mp,prec);
	    mpfr_set_d(mp,u,mode);
    }
    else
        throw conversion_overflow();
}

mpreal::mpreal(const long double u, mp_prec_t prec, mp_rnd_t mode)
{
    mpfr_init2(mp,prec);
	mpfr_set_ld(mp,u,mode);
}

mpreal::mpreal(const unsigned long int u, mp_prec_t prec, mp_rnd_t mode)
{
	mpfr_init2(mp,prec);
	mpfr_set_ui(mp,u,mode);
}

mpreal::mpreal(const unsigned int u, mp_prec_t prec, mp_rnd_t mode)
{
	mpfr_init2(mp,prec);
	mpfr_set_ui(mp,u,mode);
}

mpreal::mpreal(const long int u, mp_prec_t prec, mp_rnd_t mode)
{
	mpfr_init2(mp,prec);
	mpfr_set_si(mp,u,mode);
}

mpreal::mpreal(const int u, mp_prec_t prec, mp_rnd_t mode)
{
	mpfr_init2(mp,prec);
	mpfr_set_si(mp,u,mode);
}

mpreal::mpreal(const char* s, mp_prec_t prec, int base, mp_rnd_t mode)
{
	mpfr_init2(mp,prec);
	mpfr_set_str(mp, s, base, mode);
}

mpreal::~mpreal()
{
	mpfr_clear(mp);
}

// Operators - Assignment
mpreal& mpreal::operator=(const char* s)
{
	mpfr_t t;
	if(0==mpfr_init_set_str(t,s,default_base,default_rnd))
	{
		mpfr_set(mp,t,mpreal::default_rnd);
		mpfr_clear(t);
	}else{
		mpfr_clear(t);
		// cerr<<"fail to convert string"<<endl;
	}

	return *this;
}

const mpreal fma (const mpreal& v1, const mpreal& v2, const mpreal& v3, mp_rnd_t rnd_mode)
{
	mpreal a;
	mp_prec_t p1, p2, p3;

	p1 = v1.get_prec();
	p2 = v2.get_prec();
	p3 = v3.get_prec();

	a.set_prec(p3>p2?(p3>p1?p3:p1):(p2>p1?p2:p1));

	mpfr_fma(a.mp,v1.mp,v2.mp,v3.mp,rnd_mode);
	return a;
}

const mpreal fms (const mpreal& v1, const mpreal& v2, const mpreal& v3, mp_rnd_t rnd_mode)
{
	mpreal a;
	mp_prec_t p1, p2, p3;

	p1 = v1.get_prec();
	p2 = v2.get_prec();
	p3 = v3.get_prec();

	a.set_prec(p3>p2?(p3>p1?p3:p1):(p2>p1?p2:p1));

	mpfr_fms(a.mp,v1.mp,v2.mp,v3.mp,rnd_mode);
	return a;
}

const mpreal agm (const mpreal& v1, const mpreal& v2, mp_rnd_t rnd_mode)
{
	mpreal a;
	mp_prec_t p1, p2;

	p1 = v1.get_prec();
	p2 = v2.get_prec();

	a.set_prec(p1>p2?p1:p2);

	mpfr_agm(a.mp, v1.mp, v2.mp, rnd_mode);

	return a;
}

const mpreal hypot (const mpreal& x, const mpreal& y, mp_rnd_t rnd_mode)
{
	mpreal a;
	mp_prec_t yp, xp;

	yp = y.get_prec();
	xp = x.get_prec();

	a.set_prec(yp>xp?yp:xp);

	mpfr_hypot(a.mp, x.mp, y.mp, rnd_mode);

	return a;
}

const mpreal sum (const mpreal tab[], unsigned long int n, mp_rnd_t rnd_mode)
{
	mpreal x;
	mpfr_ptr* t;
	unsigned long int i;

	t = new mpfr_ptr[n];
	for (i=0;i<n;i++) t[i] = (mpfr_ptr)tab[i].mp;
	mpfr_sum(x.mp,t,n,rnd_mode);
	delete[] t;
	return x;
}

const mpreal remainder (const mpreal& x, const mpreal& y, mp_rnd_t rnd_mode)
{
	mpreal a;
	mp_prec_t yp, xp;

	yp = y.get_prec();
	xp = x.get_prec();

	a.set_prec(yp>xp?yp:xp);

	mpfr_remainder(a.mp, x.mp, y.mp, rnd_mode);

	return a;
}

const mpreal remquo (long* q, const mpreal& x, const mpreal& y, mp_rnd_t rnd_mode)
{
	mpreal a;
	mp_prec_t yp, xp;

	yp = y.get_prec();
	xp = x.get_prec();

	a.set_prec(yp>xp?yp:xp);

	mpfr_remquo(a.mp,q, x.mp, y.mp, rnd_mode);

	return a;
}

template <class T>
std::string to_string(T t, std::ios_base & (*f)(std::ios_base&))
{
	std::ostringstream oss;
	oss << f << t;
	return oss.str();
}

mpreal::operator std::string() const
{
	return to_string();
}

string mpreal::to_string(size_t n, int b, mp_rnd_t mode) const
{
	char *s, *ns = NULL;
	size_t slen, nslen;
	mp_exp_t exp;
	string out;

	if(mpfr_inf_p(mp))
	{
		if(mpfr_sgn(mp)>0) return "+@Inf@";
		else			   return "-@Inf@";
	}

	if(mpfr_zero_p(mp)) return "0";
	if(mpfr_nan_p(mp))  return "@NaN@";

	s  = mpfr_get_str(NULL,&exp,b,0,mp,mode);
	ns = mpfr_get_str(NULL,&exp,b,n,mp,mode);

	if(s!=NULL && ns!=NULL)
	{
		slen  = strlen(s);
		nslen = strlen(ns);
		if(nslen<=slen)
		{
			mpfr_free_str(s);
			s = ns;
			slen = nslen;
		}
		else {
			mpfr_free_str(ns);
		}

		// Make human eye-friendly formatting if possible
		if (exp>0 && static_cast<size_t>(exp)<slen)
		{
			if(s[0]=='-')
			{
				// Remove zeros starting from right end
				char* ptr = s+slen-1;
				while (*ptr=='0' && ptr>s+exp) ptr--;

				if(ptr==s+exp) out = string(s,exp+1);
				else		   out = string(s,exp+1)+'.'+string(s+exp+1,ptr-(s+exp+1)+1);

				//out = string(s,exp+1)+'.'+string(s+exp+1);
			}
			else
			{
				// Remove zeros starting from right end
				char* ptr = s+slen-1;
				while (*ptr=='0' && ptr>s+exp-1) ptr--;

				if(ptr==s+exp-1) out = string(s,exp);
				else		     out = string(s,exp)+'.'+string(s+exp,ptr-(s+exp)+1);

				//out = string(s,exp)+'.'+string(s+exp);
			}

		}else{ // exp<0 || exp>slen
			if(s[0]=='-')
			{
				// Remove zeros starting from right end
				char* ptr = s+slen-1;
				while (*ptr=='0' && ptr>s+1) ptr--;

				if(ptr==s+1) out = string(s,2);
				else		 out = string(s,2)+'.'+string(s+2,ptr-(s+2)+1);

				//out = string(s,2)+'.'+string(s+2);
			}
			else
			{
				// Remove zeros starting from right end
				char* ptr = s+slen-1;
				while (*ptr=='0' && ptr>s) ptr--;

				if(ptr==s) out = string(s,1);
				else	   out = string(s,1)+'.'+string(s+1,ptr-(s+1)+1);

				//out = string(s,1)+'.'+string(s+1);
			}

			// Make final string
			if(--exp)
			{
				if(exp>0) out += "e+"+mpfr::to_string<mp_exp_t>(exp,std::dec);
				else 	  out += "e"+mpfr::to_string<mp_exp_t>(exp,std::dec);
			}
		}

		mpfr_free_str(s);
		return out;
	}else{
		return "conversion error!";
	}
}

//////////////////////////////////////////////////////////////////////////
// I/O
ostream& operator<<(ostream& os, const mpreal& v)
{
	return os<<v.to_string(os.precision());
}

istream& operator>>(istream &is, mpreal& v)
{
	char c;
	string s = "";
	mpfr_t t;

	if(is.good())
	{
		is>>ws;
		while ((c = is.get())!=EOF)
		{
			if(c ==' ' || c == '\t' || c == '\n' || c == '\r')
			{
				is.putback(c);
				break;
			}
			s += c;
		}

		if(s.size() != 0)
		{
			// Protect current value from alternation in case of input error
			// so some error handling(roll back) procedure can be used
			if(0==mpfr_init_set_str(t,s.c_str(),mpreal::default_base,mpreal::default_rnd))
			{
				mpfr_set(v.mp,t,mpreal::default_rnd);
				mpfr_clear(t);

			}else{
				mpfr_clear(t);
				cerr<<"error reading from istream"<<endl;
				// throw an exception
			}
		}
	}
	return is;
}
}
<|endoftext|>


<commit_before>//
//  CSSubtitlesLoader.cpp
//  Chilli Source
//
//  Created by Ian Copland 21/02/2013.
//  Copyright 2013 Tag Games. All rights reserved.
//

#include <ChilliSource/Video/Base/CSSubtitlesLoader.h>

#include <ChilliSource/Core/Base/Application.h>
#include <ChilliSource/Core/Base/Utils.h>
#include <ChilliSource/Core/File/FileStream.h>
#include <ChilliSource/Core/JSON/json.h>
#include <ChilliSource/Core/String/StringParser.h>
#include <ChilliSource/Core/Threading/TaskScheduler.h>
#include <ChilliSource/Video/Base/Subtitles.h>

namespace ChilliSource
{
	namespace Video
	{
        //----------------------------------------------------------------
        // Constants
        //----------------------------------------------------------------
		const std::string k_CSSubtitlesExtension("mosubtitles");
		const std::string k_tagVersionNumber = "VersionNumber";
        const std::string k_tagStyles = "Styles";
        const std::string k_tagSubtitles = "Subtitles";
        const std::string k_tagStyleName = "Name";
        const std::string k_tagStyleFont = "Font";
        const std::string k_tagStyleFontSize = "FontSize";
        const std::string k_tagStyleFontColour = "FontColour";
        const std::string k_tagStyleFadeTime = "FadeTime";
        const std::string k_tagStyleAlignment = "Alignment";
        const std::string k_tagStyleBounds = "Bounds";
        const std::string k_tagStyleBoundsTop = "Top";
        const std::string k_tagStyleBoundsBottom = "Bottom";
        const std::string k_tagStyleBoundsLeft = "Left";
        const std::string k_tagStyleBoundsRight = "Right";
        const std::string k_tagSubtitlestyle = "Style";
        const std::string k_tagSubtitlestartTime = "StartTime";
        const std::string k_tagSubtitleEndTime = "EndTime";
        const std::string k_tagSubtitleTextID = "TextID";
        const std::string k_defaultFont = "Arial";
        const std::string k_defaultColour = "1.0 1.0 1.0 1.0";
        const std::string k_defaultAlignment = "MiddleCentre";
        const u32 k_defaultFontSize = 18;
        const TimeIntervalMs k_defaultFadeTimeMS = 250;
        const f32 k_defaultTop = 0.0f;
        const f32 k_defaultLeft = 0.0f;
        const f32 k_defaultRight = 1.0f;
        const f32 k_defaultBottom = 1.0f;

		//----------------------------------------------------------------
		//----------------------------------------------------------------
		bool CSSubtitlesLoader::IsA(Core::InterfaceIDType in_interfaceID) const
		{
			return in_interfaceID == ResourceProvider::InterfaceID || in_interfaceID == CSSubtitlesLoader::InterfaceID;
		}
		//----------------------------------------------------------------
		//----------------------------------------------------------------
		bool CSSubtitlesLoader::CanCreateResourceOfKind(Core::InterfaceIDType in_interfaceID) const
		{
			return (in_interfaceID == Subtitles::InterfaceID);
		}
		//----------------------------------------------------------------
		//----------------------------------------------------------------
		bool CSSubtitlesLoader::CanCreateResourceFromFileWithExtension(const std::string & in_extension) const
		{
			return (in_extension == k_CSSubtitlesExtension);
		}
		//--------------------------------------------------------------
		//--------------------------------------------------------------
		bool CSSubtitlesLoader::CreateResourceFromFile(Core::StorageLocation in_storageLocation, const std::string& in_filePath, Core::ResourceSPtr& out_resource)
		{
            SubtitlesSPtr pSubtitles = std::static_pointer_cast<Subtitles>(out_resource);

            LoadSubtitles(in_storageLocation, in_filePath, pSubtitles);

            return out_resource->IsLoaded();
		}
		//--------------------------------------------------------------
		// Async Create Resource From File
		//--------------------------------------------------------------
		bool CSSubtitlesLoader::AsyncCreateResourceFromFile(Core::StorageLocation in_storageLocation, const std::string& in_filePath, Core::ResourceSPtr& out_resource)
		{
			SubtitlesSPtr pSubtitles = std::static_pointer_cast<Subtitles>(out_resource);

			//Load model as task
            Core::Task<Core::StorageLocation, const std::string&, SubtitlesSPtr&> task(this, &CSSubtitlesLoader::LoadSubtitles, in_storageLocation, in_filePath, pSubtitles);
			Core::TaskScheduler::ScheduleTask(task);

			return true;
		}
        //--------------------------------------------------------------
        //--------------------------------------------------------------
        void CSSubtitlesLoader::LoadSubtitles(Core::StorageLocation in_storageLocation, const std::string& in_filePath, SubtitlesSPtr& out_resource) const
        {
            //read the JSON
            Json::Value root;
            ChilliSource::Core::Utils::ReadJson(in_storageLocation, in_filePath, &root);

            //get the version number
            u32 udwVersionNumber = root.get(k_tagVersionNumber, 0).asUInt();
            if (udwVersionNumber != 1)
            {
                CS_LOG_ERROR("MoSubtitles file '" + in_filePath + "' has version number '" + Core::ToString(udwVersionNumber) + "'. Only version 1 is supported.");
                out_resource->SetLoaded(false);
                return;
            }

            //get the styles
            if (root.isMember(k_tagStyles) == true)
            {
                for (Json::ValueIterator it = root[k_tagStyles].begin(); it != root[k_tagStyles].end(); ++it)
                {
                    Subtitles::StylePtr pStyle = LoadStyle((*it));
                    if (pStyle != nullptr)
                    {
                        out_resource->AddStyle(pStyle);
                    }
                    else
                    {
                        CS_LOG_ERROR("MoSubtitles file '" + in_filePath + "' failed to load.");
                        out_resource->SetLoaded(false);
                        return;
                    }
                }
            }
            else
            {
                CS_LOG_ERROR("MoSubtitles file '" + in_filePath + "' does not have styles.");
                out_resource->SetLoaded(false);
                return;
            }

            //get the subtitles
            if (root.isMember(k_tagSubtitles) == true)
            {
                for (Json::ValueIterator it = root[k_tagSubtitles].begin(); it != root[k_tagSubtitles].end(); ++it)
                {
                    Subtitles::SubtitlePtr pSubtitle = LoadSubtitle((*it));
                    if (pSubtitle != nullptr)
                    {
                        out_resource->AddSubtitle(pSubtitle);
                    }
                    else
                    {
                        CS_LOG_ERROR("MoSubtitles file '" + in_filePath + "' failed to load.");
                        out_resource->SetLoaded(false);
                        return;
                    }
                }
            }
            else
            {
                CS_LOG_ERROR("MoSubtitles file '" + in_filePath + "' does not have subtitles.");
                out_resource->SetLoaded(false);
                return;
            }

            out_resource->SetLoaded(true);
        }
        //-------------------------------------------------------------------------
        // Load Style
        //-------------------------------------------------------------------------
        Subtitles::StylePtr CSSubtitlesLoader::LoadStyle(const Json::Value& in_styleJSON) const
        {
            Subtitles::StylePtr pStyle(new Subtitles::Style());

            //name
            pStyle->strName = in_styleJSON.get(k_tagStyleName,"").asString();
            if(pStyle->strName == "")
            {
                CS_LOG_ERROR("Subtitle style must have a name.");
                return Subtitles::StylePtr();
            }

            pStyle->strFontName = in_styleJSON.get(k_tagStyleFont, k_defaultFont).asString();
            pStyle->udwFontSize = in_styleJSON.get(k_tagStyleFontSize, k_defaultFontSize).asUInt();
            pStyle->Colour = Core::ParseColour(in_styleJSON.get(k_tagStyleFontColour, k_defaultColour).asString());
            pStyle->FadeTimeMS = ParseTime(in_styleJSON.get(k_tagStyleFadeTime, (s32)k_defaultFadeTimeMS).asString());
            pStyle->eAlignment = Rendering::AlignmentAnchorFromString(in_styleJSON.get(k_tagStyleAlignment, k_defaultAlignment).asString());
            pStyle->Bounds = LoadBounds(in_styleJSON.get(k_tagStyleBounds, ""));

            return pStyle;
        }
        //-------------------------------------------------------------------------
        //-------------------------------------------------------------------------
        Subtitles::SubtitlePtr CSSubtitlesLoader::LoadSubtitle(const Json::Value& in_subtitleJSON) const
        {
            Subtitles::SubtitlePtr pSubtitle(new Subtitles::Subtitle());

            //style
            pSubtitle->strStyleName = in_subtitleJSON.get(k_tagSubtitlestyle, "").asString();
            if (pSubtitle->strStyleName == "")
            {
            	CS_LOG_ERROR("Subtitle must have a style.");
            	return Subtitles::SubtitlePtr();
            }

            //text id
            pSubtitle->strTextID = in_subtitleJSON.get(k_tagSubtitleTextID, "").asString();
            if (pSubtitle->strTextID == "")
            {
                CS_LOG_ERROR("Subtitle must have a text ID.");
                return Subtitles::SubtitlePtr();
            }

            pSubtitle->StartTimeMS = ParseTime(in_subtitleJSON.get(k_tagSubtitlestartTime, "0").asString());
            pSubtitle->EndTimeMS = ParseTime(in_subtitleJSON.get(k_tagSubtitleEndTime, "0").asString());

            return pSubtitle;
        }
        //-------------------------------------------------------------------------
        //-------------------------------------------------------------------------
        Core::Rectangle CSSubtitlesLoader::LoadBounds(const Json::Value& in_boundsJSON) const
        {
        	f32 fTop = (f32)in_boundsJSON.get(k_tagStyleBoundsTop, k_defaultTop).asDouble();
        	f32 fBottom = (f32)in_boundsJSON.get(k_tagStyleBoundsBottom, k_defaultBottom).asDouble();
        	f32 fLeft = (f32)in_boundsJSON.get(k_tagStyleBoundsLeft, k_defaultLeft).asDouble();
        	f32 fRight = (f32)in_boundsJSON.get(k_tagStyleBoundsRight, k_defaultRight).asDouble();

            return Core::Rectangle(ChilliSource::Core::Vector2(fLeft, fTop), ChilliSource::Core::Vector2(fRight - fLeft, fBottom - fTop));
        }
        //-------------------------------------------------------------------------
        //-------------------------------------------------------------------------
        TimeIntervalMs CSSubtitlesLoader::ParseTime(const std::string& in_time) const
        {
            u32 udwHours, udwMinutes, udwSeconds, udwMilliseconds;

            CS_SSCANF(in_time.c_str(), "%d:%d:%d:%d", &udwHours, &udwMinutes, &udwSeconds, &udwMilliseconds);

            TimeIntervalMs outputMS = ((TimeIntervalMs)udwHours) * 60 * 60 * 1000 + ((TimeIntervalMs)udwMinutes) * 60 * 1000 + ((TimeIntervalMs)udwSeconds) * 1000 + ((TimeIntervalMs)udwMilliseconds);
            return outputMS;
        }
	}
}
<commit_msg>Forgot to remove CPP comment in subtitles<commit_after>//
//  CSSubtitlesLoader.cpp
//  Chilli Source
//
//  Created by Ian Copland 21/02/2013.
//  Copyright 2013 Tag Games. All rights reserved.
//

#include <ChilliSource/Video/Base/CSSubtitlesLoader.h>

#include <ChilliSource/Core/Base/Application.h>
#include <ChilliSource/Core/Base/Utils.h>
#include <ChilliSource/Core/File/FileStream.h>
#include <ChilliSource/Core/JSON/json.h>
#include <ChilliSource/Core/String/StringParser.h>
#include <ChilliSource/Core/Threading/TaskScheduler.h>
#include <ChilliSource/Video/Base/Subtitles.h>

namespace ChilliSource
{
	namespace Video
	{
        //----------------------------------------------------------------
        // Constants
        //----------------------------------------------------------------
		const std::string k_CSSubtitlesExtension("mosubtitles");
		const std::string k_tagVersionNumber = "VersionNumber";
        const std::string k_tagStyles = "Styles";
        const std::string k_tagSubtitles = "Subtitles";
        const std::string k_tagStyleName = "Name";
        const std::string k_tagStyleFont = "Font";
        const std::string k_tagStyleFontSize = "FontSize";
        const std::string k_tagStyleFontColour = "FontColour";
        const std::string k_tagStyleFadeTime = "FadeTime";
        const std::string k_tagStyleAlignment = "Alignment";
        const std::string k_tagStyleBounds = "Bounds";
        const std::string k_tagStyleBoundsTop = "Top";
        const std::string k_tagStyleBoundsBottom = "Bottom";
        const std::string k_tagStyleBoundsLeft = "Left";
        const std::string k_tagStyleBoundsRight = "Right";
        const std::string k_tagSubtitlestyle = "Style";
        const std::string k_tagSubtitlestartTime = "StartTime";
        const std::string k_tagSubtitleEndTime = "EndTime";
        const std::string k_tagSubtitleTextID = "TextID";
        const std::string k_defaultFont = "Arial";
        const std::string k_defaultColour = "1.0 1.0 1.0 1.0";
        const std::string k_defaultAlignment = "MiddleCentre";
        const u32 k_defaultFontSize = 18;
        const TimeIntervalMs k_defaultFadeTimeMS = 250;
        const f32 k_defaultTop = 0.0f;
        const f32 k_defaultLeft = 0.0f;
        const f32 k_defaultRight = 1.0f;
        const f32 k_defaultBottom = 1.0f;

		//----------------------------------------------------------------
		//----------------------------------------------------------------
		bool CSSubtitlesLoader::IsA(Core::InterfaceIDType in_interfaceID) const
		{
			return in_interfaceID == ResourceProvider::InterfaceID || in_interfaceID == CSSubtitlesLoader::InterfaceID;
		}
		//----------------------------------------------------------------
		//----------------------------------------------------------------
		bool CSSubtitlesLoader::CanCreateResourceOfKind(Core::InterfaceIDType in_interfaceID) const
		{
			return (in_interfaceID == Subtitles::InterfaceID);
		}
		//----------------------------------------------------------------
		//----------------------------------------------------------------
		bool CSSubtitlesLoader::CanCreateResourceFromFileWithExtension(const std::string & in_extension) const
		{
			return (in_extension == k_CSSubtitlesExtension);
		}
		//--------------------------------------------------------------
		//--------------------------------------------------------------
		bool CSSubtitlesLoader::CreateResourceFromFile(Core::StorageLocation in_storageLocation, const std::string& in_filePath, Core::ResourceSPtr& out_resource)
		{
            SubtitlesSPtr pSubtitles = std::static_pointer_cast<Subtitles>(out_resource);

            LoadSubtitles(in_storageLocation, in_filePath, pSubtitles);

            return out_resource->IsLoaded();
		}
		//--------------------------------------------------------------
		//--------------------------------------------------------------
		bool CSSubtitlesLoader::AsyncCreateResourceFromFile(Core::StorageLocation in_storageLocation, const std::string& in_filePath, Core::ResourceSPtr& out_resource)
		{
			SubtitlesSPtr pSubtitles = std::static_pointer_cast<Subtitles>(out_resource);

			//Load model as task
            Core::Task<Core::StorageLocation, const std::string&, SubtitlesSPtr&> task(this, &CSSubtitlesLoader::LoadSubtitles, in_storageLocation, in_filePath, pSubtitles);
			Core::TaskScheduler::ScheduleTask(task);

			return true;
		}
        //--------------------------------------------------------------
        //--------------------------------------------------------------
        void CSSubtitlesLoader::LoadSubtitles(Core::StorageLocation in_storageLocation, const std::string& in_filePath, SubtitlesSPtr& out_resource) const
        {
            //read the JSON
            Json::Value root;
            ChilliSource::Core::Utils::ReadJson(in_storageLocation, in_filePath, &root);

            //get the version number
            u32 udwVersionNumber = root.get(k_tagVersionNumber, 0).asUInt();
            if (udwVersionNumber != 1)
            {
                CS_LOG_ERROR("MoSubtitles file '" + in_filePath + "' has version number '" + Core::ToString(udwVersionNumber) + "'. Only version 1 is supported.");
                out_resource->SetLoaded(false);
                return;
            }

            //get the styles
            if (root.isMember(k_tagStyles) == true)
            {
                for (Json::ValueIterator it = root[k_tagStyles].begin(); it != root[k_tagStyles].end(); ++it)
                {
                    Subtitles::StylePtr pStyle = LoadStyle((*it));
                    if (pStyle != nullptr)
                    {
                        out_resource->AddStyle(pStyle);
                    }
                    else
                    {
                        CS_LOG_ERROR("MoSubtitles file '" + in_filePath + "' failed to load.");
                        out_resource->SetLoaded(false);
                        return;
                    }
                }
            }
            else
            {
                CS_LOG_ERROR("MoSubtitles file '" + in_filePath + "' does not have styles.");
                out_resource->SetLoaded(false);
                return;
            }

            //get the subtitles
            if (root.isMember(k_tagSubtitles) == true)
            {
                for (Json::ValueIterator it = root[k_tagSubtitles].begin(); it != root[k_tagSubtitles].end(); ++it)
                {
                    Subtitles::SubtitlePtr pSubtitle = LoadSubtitle((*it));
                    if (pSubtitle != nullptr)
                    {
                        out_resource->AddSubtitle(pSubtitle);
                    }
                    else
                    {
                        CS_LOG_ERROR("MoSubtitles file '" + in_filePath + "' failed to load.");
                        out_resource->SetLoaded(false);
                        return;
                    }
                }
            }
            else
            {
                CS_LOG_ERROR("MoSubtitles file '" + in_filePath + "' does not have subtitles.");
                out_resource->SetLoaded(false);
                return;
            }

            out_resource->SetLoaded(true);
        }
        //-------------------------------------------------------------------------
        // Load Style
        //-------------------------------------------------------------------------
        Subtitles::StylePtr CSSubtitlesLoader::LoadStyle(const Json::Value& in_styleJSON) const
        {
            Subtitles::StylePtr pStyle(new Subtitles::Style());

            //name
            pStyle->strName = in_styleJSON.get(k_tagStyleName,"").asString();
            if(pStyle->strName == "")
            {
                CS_LOG_ERROR("Subtitle style must have a name.");
                return Subtitles::StylePtr();
            }

            pStyle->strFontName = in_styleJSON.get(k_tagStyleFont, k_defaultFont).asString();
            pStyle->udwFontSize = in_styleJSON.get(k_tagStyleFontSize, k_defaultFontSize).asUInt();
            pStyle->Colour = Core::ParseColour(in_styleJSON.get(k_tagStyleFontColour, k_defaultColour).asString());
            pStyle->FadeTimeMS = ParseTime(in_styleJSON.get(k_tagStyleFadeTime, (s32)k_defaultFadeTimeMS).asString());
            pStyle->eAlignment = Rendering::AlignmentAnchorFromString(in_styleJSON.get(k_tagStyleAlignment, k_defaultAlignment).asString());
            pStyle->Bounds = LoadBounds(in_styleJSON.get(k_tagStyleBounds, ""));

            return pStyle;
        }
        //-------------------------------------------------------------------------
        //-------------------------------------------------------------------------
        Subtitles::SubtitlePtr CSSubtitlesLoader::LoadSubtitle(const Json::Value& in_subtitleJSON) const
        {
            Subtitles::SubtitlePtr pSubtitle(new Subtitles::Subtitle());

            //style
            pSubtitle->strStyleName = in_subtitleJSON.get(k_tagSubtitlestyle, "").asString();
            if (pSubtitle->strStyleName == "")
            {
            	CS_LOG_ERROR("Subtitle must have a style.");
            	return Subtitles::SubtitlePtr();
            }

            //text id
            pSubtitle->strTextID = in_subtitleJSON.get(k_tagSubtitleTextID, "").asString();
            if (pSubtitle->strTextID == "")
            {
                CS_LOG_ERROR("Subtitle must have a text ID.");
                return Subtitles::SubtitlePtr();
            }

            pSubtitle->StartTimeMS = ParseTime(in_subtitleJSON.get(k_tagSubtitlestartTime, "0").asString());
            pSubtitle->EndTimeMS = ParseTime(in_subtitleJSON.get(k_tagSubtitleEndTime, "0").asString());

            return pSubtitle;
        }
        //-------------------------------------------------------------------------
        //-------------------------------------------------------------------------
        Core::Rectangle CSSubtitlesLoader::LoadBounds(const Json::Value& in_boundsJSON) const
        {
        	f32 fTop = (f32)in_boundsJSON.get(k_tagStyleBoundsTop, k_defaultTop).asDouble();
        	f32 fBottom = (f32)in_boundsJSON.get(k_tagStyleBoundsBottom, k_defaultBottom).asDouble();
        	f32 fLeft = (f32)in_boundsJSON.get(k_tagStyleBoundsLeft, k_defaultLeft).asDouble();
        	f32 fRight = (f32)in_boundsJSON.get(k_tagStyleBoundsRight, k_defaultRight).asDouble();

            return Core::Rectangle(ChilliSource::Core::Vector2(fLeft, fTop), ChilliSource::Core::Vector2(fRight - fLeft, fBottom - fTop));
        }
        //-------------------------------------------------------------------------
        //-------------------------------------------------------------------------
        TimeIntervalMs CSSubtitlesLoader::ParseTime(const std::string& in_time) const
        {
            u32 udwHours, udwMinutes, udwSeconds, udwMilliseconds;

            CS_SSCANF(in_time.c_str(), "%d:%d:%d:%d", &udwHours, &udwMinutes, &udwSeconds, &udwMilliseconds);

            TimeIntervalMs outputMS = ((TimeIntervalMs)udwHours) * 60 * 60 * 1000 + ((TimeIntervalMs)udwMinutes) * 60 * 1000 + ((TimeIntervalMs)udwSeconds) * 1000 + ((TimeIntervalMs)udwMilliseconds);
            return outputMS;
        }
	}
}
<|endoftext|>


<commit_before>#pragma once
//=====================================================================//
/*!	@file
	@brief	BMP280 デジタル圧力センサー・ドライバー @n
			Bosch Sensotec / Digital Pressure Sensor @n
			https://www.bosch-sensortec.com/bst/products/all_products/bmp280 @n
			Copyright 2016 Kunihito Hiramatsu
	@author	平松邦仁 (hira@rvf-rc45.net)
*/
//=====================================================================//
#include <cstdint>
#include <cmath>
#include "common/iica_io.hpp"
#include "common/delay.hpp"

namespace chip {

	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	/*!
		@brief  BMP280 テンプレートクラス
		@param[in]	I2C_IO	i2c I/O クラス
	*/
	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	template <class I2C_IO>
	class BMP280 {

		// R/W ビットを含まない７ビット値
		// ※ SDO:L ---> 0x76, SDO:H ---> 0x77
		static const uint8_t BMP280_ADR_ = 0x77;

		I2C_IO& i2c_;

		enum class REG : uint8_t {
      		DIG_T1        = 0x88,
      		DIG_T2        = 0x8A,
      		DIG_T3        = 0x8C,

      		DIG_P1        = 0x8E,
      		DIG_P2        = 0x90,
      		DIG_P3        = 0x92,
      		DIG_P4        = 0x94,
      		DIG_P5        = 0x96,
      		DIG_P6        = 0x98,
      		DIG_P7        = 0x9A,
      		DIG_P8        = 0x9C,
      		DIG_P9        = 0x9E,

      		CHIPID        = 0xD0,
      		VERSION       = 0xD1,
      		SOFTRESET     = 0xE0,

      		CAL26         = 0xE1,  // R calibration stored in 0xE1-0xF0

      		CONTROL       = 0xF4,
      		CONFIG        = 0xF5,
      		PRESSUREDATA  = 0xF7,
      		TEMPDATA      = 0xFA,
			HUMIDDATA     = 0xFD,
		};

    	struct calib_t {
			uint16_t	dig_T1;
			int16_t		dig_T2;
			int16_t		dig_T3;

			uint16_t	dig_P1;
			int16_t		dig_P2;
			int16_t		dig_P3;
			int16_t		dig_P4;
			int16_t		dig_P5;
			int16_t		dig_P6;
			int16_t		dig_P7;
			int16_t		dig_P8;
			int16_t		dig_P9;

			uint8_t		dig_H1;
			int16_t		dig_H2;
			uint8_t		dig_H3;
			int16_t		dig_H4;
			int16_t		dig_H5;
			int8_t		dig_H6;
		};

		calib_t		calib_;

		int32_t		t_fine_;

		uint8_t read8_(REG adr) {
			uint8_t reg[1];
			reg[0] = static_cast<uint8_t>(adr);
			i2c_.send(BMP280_ADR_, reg, 1);
			i2c_.recv(BMP280_ADR_, reg, 1);
			return reg[0];
		}

		uint16_t read16_(REG adr) {
			uint8_t reg[2];
			reg[0] = static_cast<uint8_t>(adr);
			i2c_.send(BMP280_ADR_, reg, 1);
			i2c_.recv(BMP280_ADR_, reg, 2);
			return (reg[0] << 8) | reg[1];
		}

		uint32_t read24_(REG adr) {
			uint8_t reg[3];
			reg[0] = static_cast<uint8_t>(adr);
			i2c_.send(BMP280_ADR_, reg, 1);
			i2c_.recv(BMP280_ADR_, reg, 3);
			return (static_cast<uint32_t>(reg[0]) << 16) | (static_cast<uint32_t>(reg[1]) << 8) | reg[2];
		}

		uint16_t read16le_(REG adr) {
			uint8_t reg[2];
			reg[0] = static_cast<uint8_t>(adr);
			i2c_.send(BMP280_ADR_, reg, 1);
			i2c_.recv(BMP280_ADR_, reg, 2);
			return (reg[1] << 8) | reg[0];
		}

		void write8_(REG a, uint8_t data) {
			uint8_t reg[2];
			reg[0] = static_cast<uint8_t>(a);
			reg[1] = data;
			i2c_.send(BMP280_ADR_, reg, 2);
		}

		void get_coefficients_() {
			calib_.dig_T1 = read16le_(REG::DIG_T1);
			calib_.dig_T2 = read16le_(REG::DIG_T2);
			calib_.dig_T3 = read16le_(REG::DIG_T3);

			calib_.dig_P1 = read16le_(REG::DIG_P1);
			calib_.dig_P2 = read16le_(REG::DIG_P2);
			calib_.dig_P3 = read16le_(REG::DIG_P3);
			calib_.dig_P4 = read16le_(REG::DIG_P4);
			calib_.dig_P5 = read16le_(REG::DIG_P5);
			calib_.dig_P6 = read16le_(REG::DIG_P6);
			calib_.dig_P7 = read16le_(REG::DIG_P7);
			calib_.dig_P8 = read16le_(REG::DIG_P8);
			calib_.dig_P9 = read16le_(REG::DIG_P9);
		}

	public:
		//-----------------------------------------------------------------//
		/*!
			@brief	コンストラクター
			@param[in]	i2c	iica_io クラスを参照で渡す
		 */
		//-----------------------------------------------------------------//
		BMP280(I2C_IO& i2c) : i2c_(i2c), calib_(), t_fine_(0) { }

		//-----------------------------------------------------------------//
		/*!
			@brief	開始
			@param[in]	addr	オプションの I2C アドレス
			@return エラーなら「false」を返す
		 */
		//-----------------------------------------------------------------//
		bool start(uint8_t addr = BMP280_ADR_) {

			if(read8_(REG::CHIPID) != 0x58) {
				return false;
			}

			get_coefficients_();

			write8_(REG::CONTROL, 0x3F);

			return true;
		}

		//-----------------------------------------------------------------//
		/*!
			@brief	温度を返す（100 * ℃）
			@return 温度
		 */
		//-----------------------------------------------------------------//
		int32_t get_temperature() {
			int32_t adc_T = read24_(REG::TEMPDATA);
			adc_T >>= 4;

  			int32_t var1  = ((((adc_T>>3) - (static_cast<int32_t>(calib_.dig_T1) << 1))) *
				(static_cast<int32_t>(calib_.dig_T2))) >> 11;

			int32_t var2  = (((((adc_T>>4) - (static_cast<int32_t>(calib_.dig_T1))) *
				((adc_T>>4) - (static_cast<int32_t>(calib_.dig_T1)))) >> 12) *
				(static_cast<int32_t>(calib_.dig_T3))) >> 14;

			t_fine_ = var1 + var2;

			return (t_fine_ * 5 + 128) >> 8;
		}

		//-----------------------------------------------------------------//
		/*!
			@brief	湿度を返す（％）(for BME280)
			@return 湿度
		 */
		//-----------------------------------------------------------------//
		float get_humidity() {

			get_temperature(); // must be done first to get t_fine

			int32_t adc_H = read16_(REG::HUMIDDATA);

			int32_t v_x1_u32r = (t_fine_ - (static_cast<int32_t>(76800)));

			v_x1_u32r = (((((adc_H << 14) - ((static_cast<int32_t>(calib_.dig_H4)) << 20) -
				((static_cast<int32_t>(calib_.dig_H5)) * v_x1_u32r)) + (static_cast<int32_t>(16384))) >> 15) *
				(((((((v_x1_u32r * (static_cast<int32_t>(calib_.dig_H6))) >> 10) *
				(((v_x1_u32r * (static_cast<int32_t>(calib_.dig_H3))) >> 11) +
				(static_cast<int32_t>(32768)))) >> 10) +
				(static_cast<int32_t>(2097152))) * (static_cast<int32_t>(calib_.dig_H2)) + 8192) >> 14));

			v_x1_u32r = (v_x1_u32r - (((((v_x1_u32r >> 15) * (v_x1_u32r >> 15)) >> 7) *
				(static_cast<int32_t>(calib_.dig_H1))) >> 4));

			v_x1_u32r = (v_x1_u32r < 0) ? 0 : v_x1_u32r;
			v_x1_u32r = (v_x1_u32r > 419430400) ? 419430400 : v_x1_u32r;
			float h = (v_x1_u32r>>12);
			return  h / 1024.0f;
		}

		//-----------------------------------------------------------------//
		/*!
			@brief	圧力を返す（hPa * 100)
			@return 圧力
		 */
		//-----------------------------------------------------------------//
		int32_t get_pressure_int25600() {
			// Must be done first to get the t_fine variable set up
			get_temperature();

			int32_t adc_P = read24_(REG::PRESSUREDATA);
			adc_P >>= 4;

			int64_t var1 = (static_cast<int64_t>(t_fine_)) - 128000;
			int64_t var2 = var1 * var1 * static_cast<int64_t>(calib_.dig_P6);
			var2 = var2 + ((var1 * static_cast<int64_t>(calib_.dig_P5)) << 17);
			var2 = var2 + ((static_cast<int64_t>(calib_.dig_P4)) << 35);
			var1 = ((var1 * var1 * static_cast<int64_t>(calib_.dig_P3)) >> 8) +
				((var1 * static_cast<int64_t>(calib_.dig_P2)) << 12);
			var1 = ((((static_cast<int64_t>(1)) << 47) + var1)) * (static_cast<int64_t>(calib_.dig_P1)) >> 33;

			if(var1 == 0) {
				return 0.0f;  // avoid exception caused by division by zero
			}

			int64_t p = 1048576 - adc_P;
			p = (((p << 31) - var2) * 3125) / var1;
			var1 = ((static_cast<int64_t>(calib_.dig_P9)) * (p >> 13) * (p >> 13)) >> 25;
			var2 = ((static_cast<int64_t>(calib_.dig_P8)) * p) >> 19;

			p = ((p + var1 + var2) >> 8) + ((static_cast<int64_t>(calib_.dig_P7)) << 4);
			return p;
		}

		//-----------------------------------------------------------------//
		/*!
			@brief	圧力を返す [hPa]
			@return 圧力 [hPa]
		 */
		//-----------------------------------------------------------------//
		float get_pressure() {
			return static_cast<float>(get_pressure_int25600()) / 25600.0f;
		}

		//-----------------------------------------------------------------//
		/*!
			@brief	高度を返す
			@param[in]	seaLevelhPa 海面ヘクトパスカル
			@return 高度
		 */
		//-----------------------------------------------------------------//
		float get_altitude(float seaLevelhPa = 1013.25f) {
			float pressure = get_pressure();
			float altitude = 44330.0f * (1.0f - std::pow(pressure / seaLevelhPa, 0.1903f));
			return altitude;
		}

	};
}
<commit_msg>update comment<commit_after>#pragma once
//=====================================================================//
/*!	@file
	@brief	BMP280 デジタル圧力センサー・ドライバー @n
			Bosch Sensotec / Digital Pressure Sensor @n
			https://www.bosch-sensortec.com/bst/products/all_products/bmp280 @n
			Copyright 2016 Kunihito Hiramatsu
	@author	平松邦仁 (hira@rvf-rc45.net)
*/
//=====================================================================//
#include <cstdint>
#include <cmath>
#include "common/iica_io.hpp"
#include "common/delay.hpp"

namespace chip {

	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	/*!
		@brief  BMP280 テンプレートクラス
		@param[in]	I2C_IO	i2c I/O クラス
	*/
	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	template <class I2C_IO>
	class BMP280 {

		// R/W ビットを含まない７ビット値
		// ※ SDO:L ---> 0x76, SDO:H ---> 0x77
		static const uint8_t BMP280_ADR_ = 0x77;

		I2C_IO& i2c_;

		enum class REG : uint8_t {
      		DIG_T1        = 0x88,
      		DIG_T2        = 0x8A,
      		DIG_T3        = 0x8C,

      		DIG_P1        = 0x8E,
      		DIG_P2        = 0x90,
      		DIG_P3        = 0x92,
      		DIG_P4        = 0x94,
      		DIG_P5        = 0x96,
      		DIG_P6        = 0x98,
      		DIG_P7        = 0x9A,
      		DIG_P8        = 0x9C,
      		DIG_P9        = 0x9E,

      		CHIPID        = 0xD0,
      		VERSION       = 0xD1,
      		SOFTRESET     = 0xE0,

      		CAL26         = 0xE1,  // R calibration stored in 0xE1-0xF0

      		CONTROL       = 0xF4,
      		CONFIG        = 0xF5,
      		PRESSUREDATA  = 0xF7,
      		TEMPDATA      = 0xFA,
			HUMIDDATA     = 0xFD,
		};

    	struct calib_t {
			uint16_t	dig_T1;
			int16_t		dig_T2;
			int16_t		dig_T3;

			uint16_t	dig_P1;
			int16_t		dig_P2;
			int16_t		dig_P3;
			int16_t		dig_P4;
			int16_t		dig_P5;
			int16_t		dig_P6;
			int16_t		dig_P7;
			int16_t		dig_P8;
			int16_t		dig_P9;

			uint8_t		dig_H1;
			int16_t		dig_H2;
			uint8_t		dig_H3;
			int16_t		dig_H4;
			int16_t		dig_H5;
			int8_t		dig_H6;
		};

		calib_t		calib_;

		int32_t		t_fine_;

		uint8_t read8_(REG adr) {
			uint8_t reg[1];
			reg[0] = static_cast<uint8_t>(adr);
			i2c_.send(BMP280_ADR_, reg, 1);
			i2c_.recv(BMP280_ADR_, reg, 1);
			return reg[0];
		}

		uint16_t read16_(REG adr) {
			uint8_t reg[2];
			reg[0] = static_cast<uint8_t>(adr);
			i2c_.send(BMP280_ADR_, reg, 1);
			i2c_.recv(BMP280_ADR_, reg, 2);
			return (reg[0] << 8) | reg[1];
		}

		uint32_t read24_(REG adr) {
			uint8_t reg[3];
			reg[0] = static_cast<uint8_t>(adr);
			i2c_.send(BMP280_ADR_, reg, 1);
			i2c_.recv(BMP280_ADR_, reg, 3);
			return (static_cast<uint32_t>(reg[0]) << 16) | (static_cast<uint32_t>(reg[1]) << 8) | reg[2];
		}

		uint16_t read16le_(REG adr) {
			uint8_t reg[2];
			reg[0] = static_cast<uint8_t>(adr);
			i2c_.send(BMP280_ADR_, reg, 1);
			i2c_.recv(BMP280_ADR_, reg, 2);
			return (reg[1] << 8) | reg[0];
		}

		void write8_(REG a, uint8_t data) {
			uint8_t reg[2];
			reg[0] = static_cast<uint8_t>(a);
			reg[1] = data;
			i2c_.send(BMP280_ADR_, reg, 2);
		}

		void get_coefficients_() {
			calib_.dig_T1 = read16le_(REG::DIG_T1);
			calib_.dig_T2 = read16le_(REG::DIG_T2);
			calib_.dig_T3 = read16le_(REG::DIG_T3);

			calib_.dig_P1 = read16le_(REG::DIG_P1);
			calib_.dig_P2 = read16le_(REG::DIG_P2);
			calib_.dig_P3 = read16le_(REG::DIG_P3);
			calib_.dig_P4 = read16le_(REG::DIG_P4);
			calib_.dig_P5 = read16le_(REG::DIG_P5);
			calib_.dig_P6 = read16le_(REG::DIG_P6);
			calib_.dig_P7 = read16le_(REG::DIG_P7);
			calib_.dig_P8 = read16le_(REG::DIG_P8);
			calib_.dig_P9 = read16le_(REG::DIG_P9);
		}

	public:
		//-----------------------------------------------------------------//
		/*!
			@brief	コンストラクター
			@param[in]	i2c	iica_io クラスを参照で渡す
		 */
		//-----------------------------------------------------------------//
		BMP280(I2C_IO& i2c) : i2c_(i2c), calib_(), t_fine_(0) { }

		//-----------------------------------------------------------------//
		/*!
			@brief	開始
			@param[in]	addr	オプションの I2C アドレス
			@return エラーなら「false」を返す
		 */
		//-----------------------------------------------------------------//
		bool start(uint8_t addr = BMP280_ADR_) {

			if(read8_(REG::CHIPID) != 0x58) {
				return false;
			}

			get_coefficients_();

			write8_(REG::CONTROL, 0x3F);

			return true;
		}

		//-----------------------------------------------------------------//
		/*!
			@brief	温度を返す（100 * ℃）
			@return 温度
		 */
		//-----------------------------------------------------------------//
		int32_t get_temperature() {
			int32_t adc_T = read24_(REG::TEMPDATA);
			adc_T >>= 4;

  			int32_t var1  = ((((adc_T>>3) - (static_cast<int32_t>(calib_.dig_T1) << 1))) *
				(static_cast<int32_t>(calib_.dig_T2))) >> 11;

			int32_t var2  = (((((adc_T>>4) - (static_cast<int32_t>(calib_.dig_T1))) *
				((adc_T>>4) - (static_cast<int32_t>(calib_.dig_T1)))) >> 12) *
				(static_cast<int32_t>(calib_.dig_T3))) >> 14;

			t_fine_ = var1 + var2;

			return (t_fine_ * 5 + 128) >> 8;
		}

		//-----------------------------------------------------------------//
		/*!
			@brief	湿度を返す（％）(for BME280)
			@return 湿度
		 */
		//-----------------------------------------------------------------//
		float get_humidity() {

			get_temperature(); // must be done first to get t_fine

			int32_t adc_H = read16_(REG::HUMIDDATA);

			int32_t v_x1_u32r = (t_fine_ - (static_cast<int32_t>(76800)));

			v_x1_u32r = (((((adc_H << 14) - ((static_cast<int32_t>(calib_.dig_H4)) << 20) -
				((static_cast<int32_t>(calib_.dig_H5)) * v_x1_u32r)) + (static_cast<int32_t>(16384))) >> 15) *
				(((((((v_x1_u32r * (static_cast<int32_t>(calib_.dig_H6))) >> 10) *
				(((v_x1_u32r * (static_cast<int32_t>(calib_.dig_H3))) >> 11) +
				(static_cast<int32_t>(32768)))) >> 10) +
				(static_cast<int32_t>(2097152))) * (static_cast<int32_t>(calib_.dig_H2)) + 8192) >> 14));

			v_x1_u32r = (v_x1_u32r - (((((v_x1_u32r >> 15) * (v_x1_u32r >> 15)) >> 7) *
				(static_cast<int32_t>(calib_.dig_H1))) >> 4));

			v_x1_u32r = (v_x1_u32r < 0) ? 0 : v_x1_u32r;
			v_x1_u32r = (v_x1_u32r > 419430400) ? 419430400 : v_x1_u32r;
			float h = (v_x1_u32r>>12);
			return  h / 1024.0f;
		}

		//-----------------------------------------------------------------//
		/*!
			@brief	整数圧力を返す（hPa * 100 * 256)
			@return 圧力
		 */
		//-----------------------------------------------------------------//
		int32_t get_pressure_int25600() {
			// Must be done first to get the t_fine variable set up
			get_temperature();

			int32_t adc_P = read24_(REG::PRESSUREDATA);
			adc_P >>= 4;

			int64_t var1 = (static_cast<int64_t>(t_fine_)) - 128000;
			int64_t var2 = var1 * var1 * static_cast<int64_t>(calib_.dig_P6);
			var2 = var2 + ((var1 * static_cast<int64_t>(calib_.dig_P5)) << 17);
			var2 = var2 + ((static_cast<int64_t>(calib_.dig_P4)) << 35);
			var1 = ((var1 * var1 * static_cast<int64_t>(calib_.dig_P3)) >> 8) +
				((var1 * static_cast<int64_t>(calib_.dig_P2)) << 12);
			var1 = ((((static_cast<int64_t>(1)) << 47) + var1)) * (static_cast<int64_t>(calib_.dig_P1)) >> 33;

			if(var1 == 0) {
				return 0.0f;  // avoid exception caused by division by zero
			}

			int64_t p = 1048576 - adc_P;
			p = (((p << 31) - var2) * 3125) / var1;
			var1 = ((static_cast<int64_t>(calib_.dig_P9)) * (p >> 13) * (p >> 13)) >> 25;
			var2 = ((static_cast<int64_t>(calib_.dig_P8)) * p) >> 19;

			p = ((p + var1 + var2) >> 8) + ((static_cast<int64_t>(calib_.dig_P7)) << 4);
			return p;
		}

		//-----------------------------------------------------------------//
		/*!
			@brief	圧力を返す [hPa]
			@return 圧力 [hPa]
		 */
		//-----------------------------------------------------------------//
		float get_pressure() {
			return static_cast<float>(get_pressure_int25600()) / 25600.0f;
		}

		//-----------------------------------------------------------------//
		/*!
			@brief	高度を返す
			@param[in]	seaLevelhPa 海面ヘクトパスカル
			@return 高度
		 */
		//-----------------------------------------------------------------//
		float get_altitude(float seaLevelhPa = 1013.25f) {
			float pressure = get_pressure();
			float altitude = 44330.0f * (1.0f - std::pow(pressure / seaLevelhPa, 0.1903f));
			return altitude;
		}

	};
}
<|endoftext|>