<commit_before>// Copyright (c) 2009-2017 The Regents of the University of Michigan
// This file is part of the HOOMD-blue project, released under the BSD 3-Clause License.

// Maintainer: joaander

#include "IntegrationMethodTwoStep.h"
#include "hoomd/VectorMath.h"
#include "QuaternionMath.h"
#include "hoomd/HOOMDMath.h"

#include "hoomd/Saru.h"

namespace py = pybind11;

#ifdef ENABLE_MPI
#include "hoomd/Communicator.h"
#endif

using namespace std;

/*! \file IntegrationMethodTwoStep.h
    \brief Contains code for the IntegrationMethodTwoStep class
*/

/*! \param sysdef SystemDefinition this method will act on. Must not be NULL.
    \param group The group of particles this integration method is to work on
    \post The method is constructed with the given particle data and a NULL profiler.
*/
IntegrationMethodTwoStep::IntegrationMethodTwoStep(std::shared_ptr<SystemDefinition> sysdef,
                                                   std::shared_ptr<ParticleGroup> group)
    : m_sysdef(sysdef), m_group(group), m_pdata(m_sysdef->getParticleData()), m_exec_conf(m_pdata->getExecConf()),
      m_aniso(false), m_deltaT(Scalar(0.0)), m_valid_restart(false)
    {
    // sanity check
    assert(m_sysdef);
    assert(m_pdata);
    assert(m_group);

    m_integrator_id = m_sysdef->getIntegratorData()->registerIntegrator();
    }

/*! It is useful for the user to know where computation time is spent, so all integration methods
    should profile themselves. This method sets the profiler for them to use.
    This method does not need to be called, as Computes will not profile themselves
    on a NULL profiler
    \param prof Pointer to a profiler for the compute to use. Set to NULL
        (std::shared_ptr<Profiler>()) to stop the
        analyzer from profiling itself.
    \note Derived classes MUST check if m_prof is set before calling any profiler methods.
*/
void IntegrationMethodTwoStep::setProfiler(std::shared_ptr<Profiler> prof)
    {
    m_prof = prof;
    }

/*! \param deltaT New time step to set
*/
void IntegrationMethodTwoStep::setDeltaT(Scalar deltaT)
    {
    m_deltaT = deltaT;
    }

/*! \param v is the restart variables for the current integrator
    \param type is the type of expected integrator type
    \param nvariables is the expected number of variables

    If the either the integrator type or number of variables does not match the
    expected values, this function throws the appropriate warning and returns
    "false."  Otherwise, the function returns true.
*/
bool IntegrationMethodTwoStep::restartInfoTestValid(const IntegratorVariables& v, std::string type, unsigned int nvariables)
    {
    bool good = true;
    if (v.type == "")
        good = false;
    else if (v.type != type && v.type != "")
        {
        m_exec_conf->msg->warning() << "Integrator #"<<  m_integrator_id <<" type "<< type <<" does not match type ";
        m_exec_conf->msg->warning() << v.type << " found in restart file. " << endl;
        m_exec_conf->msg->warning() << "Ensure that the integrator order is consistent for restarted simulations. " << endl;
        m_exec_conf->msg->warning() << "Continuing while ignoring restart information..." << endl;
        good = false;
        }
    else if (v.type == type)
        {
        if (v.variable.size() != nvariables)
            {
            m_exec_conf->msg->warning() << "Integrator #"<< m_integrator_id <<" type "<< type << endl;
            m_exec_conf->msg->warning() << "appears to contain bad or incomplete restart information. " << endl;
            m_exec_conf->msg->warning() << "Continuing while ignoring restart information..." << endl;
            good = false;
            }
        }
    return good;
    }

/*! \param query_group Group over which to count (translational) degrees of freedom.
    A majority of the integration methods add D degrees of freedom per particle in \a query_group that is also in the
    group assigned to the method. Hence, the base class IntegrationMethodTwoStep will implement that counting.
    Derived classes can ovveride if needed.
*/
unsigned int IntegrationMethodTwoStep::getNDOF(std::shared_ptr<ParticleGroup> query_group)
    {
    // get the size of the intersecion between query_group and m_group
    unsigned int intersect_size = ParticleGroup::groupIntersection(query_group, m_group)->getNumMembersGlobal();

    return m_sysdef->getNDimensions() * intersect_size;
    }

unsigned int IntegrationMethodTwoStep::getRotationalNDOF(std::shared_ptr<ParticleGroup> query_group)
    {
    // get the size of the intersecion between query_group and m_group
    std::shared_ptr<ParticleGroup> intersect = ParticleGroup::groupIntersection(query_group, m_group);

    unsigned int local_group_size = intersect->getNumMembers();

    unsigned int query_group_dof = 0;
    unsigned int dimension = m_sysdef->getNDimensions();
    unsigned int dof_one;
    ArrayHandle<Scalar3> h_moment_inertia(m_pdata->getMomentsOfInertiaArray(), access_location::host, access_mode::read);

    for (unsigned int group_idx = 0; group_idx < local_group_size; group_idx++)
        {
        unsigned int j = intersect->getMemberIndex(group_idx);
        if (dimension == 3)
            {
            dof_one = 3;
            if (fabs(h_moment_inertia.data[j].x) < EPSILON)
                dof_one--;

            if (fabs(h_moment_inertia.data[j].y) < EPSILON)
                dof_one--;

            if (fabs(h_moment_inertia.data[j].z) < EPSILON)
                dof_one--;
            }
        else
            {
            dof_one = 1;
            if (fabs(h_moment_inertia.data[j].z) < EPSILON)
                dof_one--;
            }

        query_group_dof += dof_one;
        }

    #ifdef ENABLE_MPI
    if (m_pdata->getDomainDecomposition())
        {
        MPI_Allreduce(MPI_IN_PLACE, &query_group_dof, 1, MPI_UNSIGNED, MPI_SUM, m_exec_conf->getMPICommunicator());
        }
    #endif

    return query_group_dof;
    }

/*! Checks that every particle in the group is valid. This method may be called by anyone wishing to make this
    error check.

    The base class does nothing
*/
void IntegrationMethodTwoStep::validateGroup()
    {
    for (unsigned int gidx = 0; gidx < m_group->getNumMembersGlobal(); gidx++)
        {
        unsigned int tag = m_group->getMemberTag(gidx);
        if (m_pdata->isParticleLocal(tag))
            {
            ArrayHandle<unsigned int> h_body(m_pdata->getBodies(), access_location::host, access_mode::read);
            ArrayHandle<unsigned int> h_rtag(m_pdata->getRTags(), access_location::host, access_mode::read);
            ArrayHandle<unsigned int> h_tag(m_pdata->getTags(), access_location::host, access_mode::read);

            unsigned int body = h_body.data[h_rtag.data[tag]];

            if (body != NO_BODY && body != tag)
                {
                m_exec_conf->msg->error() << "Particle " << tag << " belongs to a rigid body, but is not its center particle. "
                    << std::endl << "This integration method does not operate on constituent particles."
                    << std::endl << std::endl;
                throw std::runtime_error("Error initializing integration method");
                }
            }
        }

    }

/*!
   Randomizes linear velocities and angular momenta by sampling the
   Maxwell-Boltzmann (MB) distribution.
   The user provides three arguments:
   - The particle group
   - Temperature
   - Seed for initializing the random number generator used for this purpose
   These variables are member variables of the class.
*/
void IntegrationMethodTwoStep::randomizeVelocities(unsigned int timestep)
    {
    if (m_shouldRandomize == false)
        {
        return;
        }

    /* Get the number of particles in the group */
    unsigned int group_size = m_group->getNumMembers();

    /* Grab some variables */
    const unsigned int D = Scalar(m_sysdef->getNDimensions());

    ArrayHandle<Scalar4> h_vel(m_pdata->getVelocities(),
                               access_location::host,
                               access_mode::readwrite);

    ArrayHandle<Scalar4> h_orientation(m_pdata->getOrientationArray(),
                                       access_location::host,
                                       access_mode::read);

    ArrayHandle<Scalar4> h_angmom(m_pdata->getAngularMomentumArray(),
                                  access_location::host,
                                  access_mode::readwrite);

    ArrayHandle<Scalar3> h_inertia(m_pdata->getMomentsOfInertiaArray(),
                                   access_location::host,
                                   access_mode::read);

    ArrayHandle<unsigned int> h_tag(m_pdata->getTags(),
                                    access_location::host,
                                    access_mode::read);

    /* Total momentum */
    vec3<Scalar> tot_momentum(0,0,0);

    /* Loop over all the particles in the group */
    for (unsigned int group_idx = 0; group_idx < group_size; group_idx++)
        {
        unsigned int j = m_group->getMemberIndex(group_idx);
        unsigned int ptag = h_tag.data[j];

        /* Initialize the random number generator */
        hoomd::detail::Saru saru(ptag, timestep, m_seed_randomize);

        /* Generate a new random linear velocity for particle j */
        Scalar mass =  h_vel.data[j].w;
        Scalar sigma = fast::sqrt(m_T_randomize/mass);
        h_vel.data[j].x = gaussian_rng(saru, sigma);
        h_vel.data[j].y = gaussian_rng(saru, sigma);
        if (D > 2)
            h_vel.data[j].z = gaussian_rng(saru, sigma);
        else
            h_vel.data[j].z = 0; // For 2D systems

        tot_momentum += mass * vec3<Scalar>(h_vel.data[j]);

        /* Generate a new random angular momentum if the particle is a rigid
         * body and anisotropy flag gets set.
         * There may be some issues for 2D systems */
        if (m_aniso)
            {
            vec3<Scalar> p_vec(0,0,0);
            quat<Scalar> q(h_orientation.data[j]);
            vec3<Scalar> I(h_inertia.data[j]);

            /* Generate a new random angular momentum for particle j in
             * body frame */
            if (I.x >= EPSILON)
                p_vec.x = gaussian_rng(saru, fast::sqrt(m_T_randomize * I.x));
            if (I.y >= EPSILON)
                p_vec.y = gaussian_rng(saru, fast::sqrt(m_T_randomize * I.y));
            if (I.z >= EPSILON)
                p_vec.z = gaussian_rng(saru, fast::sqrt(m_T_randomize * I.z));

            /* Store the angular momentum quaternion */
            quat<Scalar> p = Scalar(2.0) * q * p_vec;
            h_angmom.data[j] = quat_to_scalar4(p);
            }
        }

    /* Remove the drift i.e. remove the center of mass velocity */
    #ifdef ENABLE_MPI
    vec3<Scalar> reduced_tot_momentum(0,0,0);
    if(m_comm)
       {
       MPI_Reduce(&tot_momentum, &reduced_tot_momentum, 3, MPI_FLOAT,
                  MPI_SUM, 0, m_exec_conf->getMPICommunicator());
       }
    else
       {
       reduced_tot_momentum = tot_momentum;
       }
    #else
    vec3<Scalar> reduced_tot_momentum = tot_momentum;
    #endif
    vec3<Scalar> com_momentum(0,0,0);
    com_momentum.x = reduced_tot_momentum.x / m_group->getNumMembersGlobal();
    com_momentum.y = reduced_tot_momentum.y / m_group->getNumMembersGlobal();
    com_momentum.z = reduced_tot_momentum.z / m_group->getNumMembersGlobal();
    for (unsigned int group_idx = 0; group_idx < group_size; group_idx++)
        {
        unsigned int j = m_group->getMemberIndex(group_idx);
        h_vel.data[j].x = h_vel.data[j].x - com_momentum.x;
        h_vel.data[j].y = h_vel.data[j].y - com_momentum.y;
        if (D > 2)
            h_vel.data[j].z = h_vel.data[j].z - com_momentum.z;
        else
            h_vel.data[j].z = 0; // For 2D systems
        }

    /* Done randomizing velocities */

    /* Reset the flag */
    m_shouldRandomize = false;
    }

void export_IntegrationMethodTwoStep(py::module& m)
    {
    py::class_<IntegrationMethodTwoStep, std::shared_ptr<IntegrationMethodTwoStep> >(m, "IntegrationMethodTwoStep")
        .def(py::init< std::shared_ptr<SystemDefinition>, std::shared_ptr<ParticleGroup> >())
        .def("validateGroup", &IntegrationMethodTwoStep::validateGroup)
#ifdef ENABLE_MPI
        .def("setCommunicator", &IntegrationMethodTwoStep::setCommunicator)
#endif
        .def("setRandomizeVelocitiesParams", &IntegrationMethodTwoStep::setRandomizeVelocitiesParams)
        ;
    }
<commit_msg>Fixed bug in drift subtraction (must account for particle mass).<commit_after>// Copyright (c) 2009-2017 The Regents of the University of Michigan
// This file is part of the HOOMD-blue project, released under the BSD 3-Clause License.

// Maintainer: joaander

#include "IntegrationMethodTwoStep.h"
#include "hoomd/VectorMath.h"
#include "QuaternionMath.h"
#include "hoomd/HOOMDMath.h"

#include "hoomd/Saru.h"

namespace py = pybind11;

#ifdef ENABLE_MPI
#include "hoomd/Communicator.h"
#endif

using namespace std;

/*! \file IntegrationMethodTwoStep.h
    \brief Contains code for the IntegrationMethodTwoStep class
*/

/*! \param sysdef SystemDefinition this method will act on. Must not be NULL.
    \param group The group of particles this integration method is to work on
    \post The method is constructed with the given particle data and a NULL profiler.
*/
IntegrationMethodTwoStep::IntegrationMethodTwoStep(std::shared_ptr<SystemDefinition> sysdef,
                                                   std::shared_ptr<ParticleGroup> group)
    : m_sysdef(sysdef), m_group(group), m_pdata(m_sysdef->getParticleData()), m_exec_conf(m_pdata->getExecConf()),
      m_aniso(false), m_deltaT(Scalar(0.0)), m_valid_restart(false)
    {
    // sanity check
    assert(m_sysdef);
    assert(m_pdata);
    assert(m_group);

    m_integrator_id = m_sysdef->getIntegratorData()->registerIntegrator();
    }

/*! It is useful for the user to know where computation time is spent, so all integration methods
    should profile themselves. This method sets the profiler for them to use.
    This method does not need to be called, as Computes will not profile themselves
    on a NULL profiler
    \param prof Pointer to a profiler for the compute to use. Set to NULL
        (std::shared_ptr<Profiler>()) to stop the
        analyzer from profiling itself.
    \note Derived classes MUST check if m_prof is set before calling any profiler methods.
*/
void IntegrationMethodTwoStep::setProfiler(std::shared_ptr<Profiler> prof)
    {
    m_prof = prof;
    }

/*! \param deltaT New time step to set
*/
void IntegrationMethodTwoStep::setDeltaT(Scalar deltaT)
    {
    m_deltaT = deltaT;
    }

/*! \param v is the restart variables for the current integrator
    \param type is the type of expected integrator type
    \param nvariables is the expected number of variables

    If the either the integrator type or number of variables does not match the
    expected values, this function throws the appropriate warning and returns
    "false."  Otherwise, the function returns true.
*/
bool IntegrationMethodTwoStep::restartInfoTestValid(const IntegratorVariables& v, std::string type, unsigned int nvariables)
    {
    bool good = true;
    if (v.type == "")
        good = false;
    else if (v.type != type && v.type != "")
        {
        m_exec_conf->msg->warning() << "Integrator #"<<  m_integrator_id <<" type "<< type <<" does not match type ";
        m_exec_conf->msg->warning() << v.type << " found in restart file. " << endl;
        m_exec_conf->msg->warning() << "Ensure that the integrator order is consistent for restarted simulations. " << endl;
        m_exec_conf->msg->warning() << "Continuing while ignoring restart information..." << endl;
        good = false;
        }
    else if (v.type == type)
        {
        if (v.variable.size() != nvariables)
            {
            m_exec_conf->msg->warning() << "Integrator #"<< m_integrator_id <<" type "<< type << endl;
            m_exec_conf->msg->warning() << "appears to contain bad or incomplete restart information. " << endl;
            m_exec_conf->msg->warning() << "Continuing while ignoring restart information..." << endl;
            good = false;
            }
        }
    return good;
    }

/*! \param query_group Group over which to count (translational) degrees of freedom.
    A majority of the integration methods add D degrees of freedom per particle in \a query_group that is also in the
    group assigned to the method. Hence, the base class IntegrationMethodTwoStep will implement that counting.
    Derived classes can ovveride if needed.
*/
unsigned int IntegrationMethodTwoStep::getNDOF(std::shared_ptr<ParticleGroup> query_group)
    {
    // get the size of the intersecion between query_group and m_group
    unsigned int intersect_size = ParticleGroup::groupIntersection(query_group, m_group)->getNumMembersGlobal();

    return m_sysdef->getNDimensions() * intersect_size;
    }

unsigned int IntegrationMethodTwoStep::getRotationalNDOF(std::shared_ptr<ParticleGroup> query_group)
    {
    // get the size of the intersecion between query_group and m_group
    std::shared_ptr<ParticleGroup> intersect = ParticleGroup::groupIntersection(query_group, m_group);

    unsigned int local_group_size = intersect->getNumMembers();

    unsigned int query_group_dof = 0;
    unsigned int dimension = m_sysdef->getNDimensions();
    unsigned int dof_one;
    ArrayHandle<Scalar3> h_moment_inertia(m_pdata->getMomentsOfInertiaArray(), access_location::host, access_mode::read);

    for (unsigned int group_idx = 0; group_idx < local_group_size; group_idx++)
        {
        unsigned int j = intersect->getMemberIndex(group_idx);
        if (dimension == 3)
            {
            dof_one = 3;
            if (fabs(h_moment_inertia.data[j].x) < EPSILON)
                dof_one--;

            if (fabs(h_moment_inertia.data[j].y) < EPSILON)
                dof_one--;

            if (fabs(h_moment_inertia.data[j].z) < EPSILON)
                dof_one--;
            }
        else
            {
            dof_one = 1;
            if (fabs(h_moment_inertia.data[j].z) < EPSILON)
                dof_one--;
            }

        query_group_dof += dof_one;
        }

    #ifdef ENABLE_MPI
    if (m_pdata->getDomainDecomposition())
        {
        MPI_Allreduce(MPI_IN_PLACE, &query_group_dof, 1, MPI_UNSIGNED, MPI_SUM, m_exec_conf->getMPICommunicator());
        }
    #endif

    return query_group_dof;
    }

/*! Checks that every particle in the group is valid. This method may be called by anyone wishing to make this
    error check.

    The base class does nothing
*/
void IntegrationMethodTwoStep::validateGroup()
    {
    for (unsigned int gidx = 0; gidx < m_group->getNumMembersGlobal(); gidx++)
        {
        unsigned int tag = m_group->getMemberTag(gidx);
        if (m_pdata->isParticleLocal(tag))
            {
            ArrayHandle<unsigned int> h_body(m_pdata->getBodies(), access_location::host, access_mode::read);
            ArrayHandle<unsigned int> h_rtag(m_pdata->getRTags(), access_location::host, access_mode::read);
            ArrayHandle<unsigned int> h_tag(m_pdata->getTags(), access_location::host, access_mode::read);

            unsigned int body = h_body.data[h_rtag.data[tag]];

            if (body != NO_BODY && body != tag)
                {
                m_exec_conf->msg->error() << "Particle " << tag << " belongs to a rigid body, but is not its center particle. "
                    << std::endl << "This integration method does not operate on constituent particles."
                    << std::endl << std::endl;
                throw std::runtime_error("Error initializing integration method");
                }
            }
        }

    }

/*!
   Randomizes linear velocities and angular momenta by sampling the
   Maxwell-Boltzmann (MB) distribution.
   The user provides three arguments:
   - The particle group
   - Temperature
   - Seed for initializing the random number generator used for this purpose
   These variables are member variables of the class.
*/
void IntegrationMethodTwoStep::randomizeVelocities(unsigned int timestep)
    {
    if (m_shouldRandomize == false)
        {
        return;
        }

    /* Get the number of particles in the group */
    unsigned int group_size = m_group->getNumMembers();

    /* Grab some variables */
    const unsigned int D = Scalar(m_sysdef->getNDimensions());

    ArrayHandle<Scalar4> h_vel(m_pdata->getVelocities(),
                               access_location::host,
                               access_mode::readwrite);

    ArrayHandle<Scalar4> h_orientation(m_pdata->getOrientationArray(),
                                       access_location::host,
                                       access_mode::read);

    ArrayHandle<Scalar4> h_angmom(m_pdata->getAngularMomentumArray(),
                                  access_location::host,
                                  access_mode::readwrite);

    ArrayHandle<Scalar3> h_inertia(m_pdata->getMomentsOfInertiaArray(),
                                   access_location::host,
                                   access_mode::read);

    ArrayHandle<unsigned int> h_tag(m_pdata->getTags(),
                                    access_location::host,
                                    access_mode::read);

    /* Total momentum */
    vec3<Scalar> tot_momentum(0,0,0);

    /* Loop over all the particles in the group */
    for (unsigned int group_idx = 0; group_idx < group_size; group_idx++)
        {
        unsigned int j = m_group->getMemberIndex(group_idx);
        unsigned int ptag = h_tag.data[j];

        /* Initialize the random number generator */
        hoomd::detail::Saru saru(ptag, timestep, m_seed_randomize);

        /* Generate a new random linear velocity for particle j */
        Scalar mass =  h_vel.data[j].w;
        Scalar sigma = fast::sqrt(m_T_randomize/mass);
        h_vel.data[j].x = gaussian_rng(saru, sigma);
        h_vel.data[j].y = gaussian_rng(saru, sigma);
        if (D > 2)
            h_vel.data[j].z = gaussian_rng(saru, sigma);
        else
            h_vel.data[j].z = 0; // For 2D systems

        tot_momentum += mass * vec3<Scalar>(h_vel.data[j]);

        /* Generate a new random angular momentum if the particle is a rigid
         * body and anisotropy flag gets set.
         * There may be some issues for 2D systems */
        if (m_aniso)
            {
            vec3<Scalar> p_vec(0,0,0);
            quat<Scalar> q(h_orientation.data[j]);
            vec3<Scalar> I(h_inertia.data[j]);

            /* Generate a new random angular momentum for particle j in
             * body frame */
            if (I.x >= EPSILON)
                p_vec.x = gaussian_rng(saru, fast::sqrt(m_T_randomize * I.x));
            if (I.y >= EPSILON)
                p_vec.y = gaussian_rng(saru, fast::sqrt(m_T_randomize * I.y));
            if (I.z >= EPSILON)
                p_vec.z = gaussian_rng(saru, fast::sqrt(m_T_randomize * I.z));

            /* Store the angular momentum quaternion */
            quat<Scalar> p = Scalar(2.0) * q * p_vec;
            h_angmom.data[j] = quat_to_scalar4(p);
            }
        }

    /* Remove the drift i.e. remove the center of mass velocity */
    #ifdef ENABLE_MPI
    vec3<Scalar> reduced_tot_momentum(0,0,0);
    if(m_comm)
       {
       MPI_Reduce(&tot_momentum, &reduced_tot_momentum, 3, MPI_FLOAT,
                  MPI_SUM, 0, m_exec_conf->getMPICommunicator());
       }
    else
       {
       reduced_tot_momentum = tot_momentum;
       }
    #else
    vec3<Scalar> reduced_tot_momentum = tot_momentum;
    #endif
    vec3<Scalar> com_momentum(0,0,0);
    com_momentum.x = reduced_tot_momentum.x / m_group->getNumMembersGlobal();
    com_momentum.y = reduced_tot_momentum.y / m_group->getNumMembersGlobal();
    com_momentum.z = reduced_tot_momentum.z / m_group->getNumMembersGlobal();
    for (unsigned int group_idx = 0; group_idx < group_size; group_idx++)
        {
        unsigned int j = m_group->getMemberIndex(group_idx);
        Scalar mass =  h_vel.data[j].w;
        h_vel.data[j].x = h_vel.data[j].x - com_momentum.x / mass;
        h_vel.data[j].y = h_vel.data[j].y - com_momentum.y / mass;
        if (D > 2)
            h_vel.data[j].z = h_vel.data[j].z - com_momentum.z / mass;
        else
            h_vel.data[j].z = 0; // For 2D systems
        }

    /* Done randomizing velocities */

    /* Reset the flag */
    m_shouldRandomize = false;
    }

void export_IntegrationMethodTwoStep(py::module& m)
    {
    py::class_<IntegrationMethodTwoStep, std::shared_ptr<IntegrationMethodTwoStep> >(m, "IntegrationMethodTwoStep")
        .def(py::init< std::shared_ptr<SystemDefinition>, std::shared_ptr<ParticleGroup> >())
        .def("validateGroup", &IntegrationMethodTwoStep::validateGroup)
#ifdef ENABLE_MPI
        .def("setCommunicator", &IntegrationMethodTwoStep::setCommunicator)
#endif
        .def("setRandomizeVelocitiesParams", &IntegrationMethodTwoStep::setRandomizeVelocitiesParams)
        ;
    }
<|endoftext|>


<commit_before>/*
 *Date: 13-09-10

*/

#include <assert.h>
#include <math.h>
#include "point.h"

Point::Point(const Point& point)
  : x(point.x), y(point.y)
{
}

Point::Point(double _x, double _y)
  : x(_x), y(_y)
{
}

double Point::distance(const Point& point) const {
   double carreX=pow((point.x-x),2);
   double carreY=pow((point.y-y),2);
   double dist=sqrt(carreX+carreY);
   return dist;
}

std::ostream& operator << (std::ostream& os, const Point& point) {
  os << "(" << point.x << "," << point.y << ")";
  return os;
}

std::istream& operator >> (std::istream& is, Point& point) {
  char po, vir, pf;
  is >> po;
  if(is){
    is >> point.x >> vir >> point.y >> pf;
    assert(po=='(');
    assert(vir==',');
    assert(pf==')');
  }
  return is;
}

<commit_msg>Update point.cpp<commit_after>#include <assert.h>
#include <math.h>
#include "point.h"

Point::Point(double _x, double _y)
  : x(_x), y(_y)
{
}

Point::Point(const Point& point)
  : x(point.x), y(point.y)
{
}

double Point::distance(const Point& point) const {
    return sqrt(pow((x-point.x), 2) + pow((y-point.y),2));
}

ostream& operator << (ostream& os, const Point& point) {
    os << "(" << point.x << "," << point.y << ")";
    return os;
}

istream& operator >> (istream& is, Point& point) {
    char po, vir, pf;
    is >> po;
    if(is){
        is >> point.x >> vir >> point.y >> pf;
        assert(po=='(');
        assert(vir==',');
        assert(pf==')');
    }
    return is;
}
<|endoftext|>


<commit_before>#include <map>
#include <vector>
#include <string>
#include <time.h>
#include "NFComm/NFPluginModule/NFIPluginManager.h"
#include "NFComm/NFCore/NFQueue.h"
#include "NFComm/RapidXML/rapidxml.hpp"
#include "NFComm/RapidXML/rapidxml_iterators.hpp"
#include "NFComm/RapidXML/rapidxml_print.hpp"
#include "NFComm/RapidXML/rapidxml_utils.hpp"
#include "NFComm/NFPluginModule/NFPlatform.h"

#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <errno.h>

#if NF_PLATFORM == NF_PLATFORM_WIN
#include <io.h>
#include <windows.h>
#include <conio.h>
#else
#include <iconv.h>
#include <unistd.h>
#include <cstdio>
#include <dirent.h>
#include <sys/stat.h>
#endif

bool GetPluginNameList(std::string& strPlugin, std::vector<std::string>& pluginList, std::string& configPath)
{
	rapidxml::file<> fdoc(strPlugin.c_str());
	rapidxml::xml_document<>  doc;
	doc.parse<0>(fdoc.data());

	rapidxml::xml_node<>* pRoot = doc.first_node();
	for (rapidxml::xml_node<>* pPluginNode = pRoot->first_node("Plugin"); pPluginNode; pPluginNode = pPluginNode->next_sibling("Plugin"))
	{
		const char* strPluginName = pPluginNode->first_attribute("Name")->value();
		const char* strMain = pPluginNode->first_attribute("Main")->value();
		pluginList.push_back(std::string(strPluginName));
	}

	rapidxml::xml_node<>* pPluginAppNode = pRoot->first_node("APPID");
	if (!pPluginAppNode)
	{
		//NFASSERT(0, "There are no App ID", __FILE__, __FUNCTION__);
		return false;
	}

	const char* strAppID = pPluginAppNode->first_attribute("Name")->value();
	if (!strAppID)
	{
		//NFASSERT(0, "There are no App ID", __FILE__, __FUNCTION__);
		return false;
	}

	rapidxml::xml_node<>* pPluginConfigPathNode = pRoot->first_node("ConfigPath");
	if (!pPluginConfigPathNode)
	{
		//NFASSERT(0, "There are no ConfigPath", __FILE__, __FUNCTION__);
		return false;
	}

	if (NULL == pPluginConfigPathNode->first_attribute("Name"))
	{
		//NFASSERT(0, "There are no ConfigPath.Name", __FILE__, __FUNCTION__);
		return false;
	}

	configPath = pPluginConfigPathNode->first_attribute("Name")->value();

	return true;
}

int CopyFile(std::string& SourceFile, std::string& NewFile)
{
	ifstream in;
	ofstream out;
	in.open(SourceFile.c_str(), ios::binary);//Դļ
	if (in.fail())//Դļʧ
	{
		cout << "Error 1: Fail to open the source file." << endl;
		in.close();
		out.close();
		return 0;
	}
	out.open(NewFile.c_str(), ios::binary);//Ŀļ
	if (out.fail())//ļʧ
	{
		cout << "Error 2: Fail to create the new file." << endl;
		out.close();
		in.close();
		return 0;
	}
	else//ļ
	{
		out << in.rdbuf();
		out.close();
		in.close();
		return 1;
	}
}

std::vector<std::string> GetFileListInFolder(std::string folderPath, int depth)
{
	std::vector<std::string> result;
#if NF_PLATFORM == NF_PLATFORM_WIN
	_finddata_t FileInfo;
	std::string strfind = folderPath + "\\*";
	long long Handle = _findfirst(strfind.c_str(), &FileInfo);

	if (Handle == -1L)
	{
		std::cerr << "can not match the folder path" << std::endl;
		exit(-1);
	}
	do {
		//жǷĿ¼
		if (FileInfo.attrib & _A_SUBDIR)
		{
			//Ҫ
			if ((strcmp(FileInfo.name, ".") != 0) && (strcmp(FileInfo.name, "..") != 0))
			{
				std::string newPath = folderPath + "\\" + FileInfo.name;
				//dfsFolder(newPath, depth);
				auto newResult = GetFileListInFolder(newPath, depth);
				result.insert(result.begin(), newResult.begin(), newResult.end());
			}
		}
		else
		{

			std::string filename = (folderPath + "\\" + FileInfo.name);
			result.push_back(filename);
		}
	} while (_findnext(Handle, &FileInfo) == 0);

	_findclose(Handle);
#else
	DIR *pDir;
	struct dirent *ent;
	char childpath[512];
	char absolutepath[512];
	pDir = opendir(folderPath.c_str());
	memset(childpath, 0, sizeof(childpath));
	while ((ent = readdir(pDir)) != NULL)
	{
		if (ent->d_type & DT_DIR)
		{
			if (strcmp(ent->d_name, ".") == 0 || strcmp(ent->d_name, "..") == 0)
			{
				continue;
			}
			std::string childpath = folderPath + "/" + ent->d_name;
			auto newResult = GetFileListInFolder(childpath, depth);
			result.insert(result.begin(), newResult.begin(), newResult.end());
		}
		else
		{
			sprintf(absolutepath, "%s/%s", folderPath.c_str(), ent->d_name);
			result.push_back(absolutepath);
		}
	}

	sort(result.begin(), result.end());//
#endif
	return result;
}

void StringReplace(std::string &strBig, const std::string &strsrc, const std::string &strdst)
{
	std::string::size_type pos = 0;
	std::string::size_type srclen = strsrc.size();
	std::string::size_type dstlen = strdst.size();

	while ((pos = strBig.find(strsrc, pos)) != std::string::npos)
	{
		strBig.replace(pos, srclen, strdst);
		pos += dstlen;
	}
}

void printResult(int result, std::string& strName)
{
	if (result == 1)
	{
		printf("Copy file: %s success!\n", strName.c_str());
	}
	else
	{
		printf("Copy file: %s failed!\n", strName.c_str());
	}
}

int main()
{
	std::vector<std::string> fileList;
#ifdef NF_DEBUG_MODE
	fileList = GetFileListInFolder("../../Debug", 10);
#else
	fileList = GetFileListInFolder("../../Release", 10);
#endif
	for (auto fileName : fileList)
	{
		if (fileName.find("Plugin.xml") != std::string::npos)
		{
			StringReplace(fileName, "\\", "/");
			StringReplace(fileName, "//", "/");
			printf("Reading xml file: %s\n", fileName.c_str());

			std::vector<std::string> pluginList;
			std::string configPath = "";
			GetPluginNameList(fileName, pluginList, configPath);
			if (pluginList.size() > 0 && configPath != "")
			{
#if NF_PLATFORM == NF_PLATFORM_WIN
				pluginList.push_back("libprotobuf");
				pluginList.push_back("NFMessageDefine");
#else
				pluginList.push_back("NFMessageDefine");
#endif
				pluginList.push_back("NFPluginLoader");
				configPath = "../" + configPath;
				configPath = fileName.substr(0, fileName.find_last_of("/")) + "/" + configPath;

				for (std::string name : pluginList)
				{
					int result = 0;
					if (name == "NFPluginLoader")
					{
#if NF_PLATFORM == NF_PLATFORM_WIN

#ifdef NF_DEBUG_MODE
						std::string src = configPath + "Comm/Debug/" + name;
						std::string des = fileName.substr(0, fileName.find_last_of("/")) + "/" + name;
						auto strSrc = src + "_d.exe";
						auto strDes = des + "_d.exe";
						auto strSrcPDB = src + "_d.pdb";
						auto strDesPDB = des + "_d.pdb";
						printResult(CopyFile(strSrc, strDes), strSrc);
						printResult(CopyFile(strSrcPDB, strDesPDB), strSrcPDB);
#else
						std::string src = configPath + "Comm/Release/" + name;
						std::string des = fileName.substr(0, fileName.find_last_of("/")) + "/" + name;
						auto strSrc = src + ".exe";
						auto strDes = des + ".exe";
						printResult(CopyFile(strSrc, strDes), strSrc);
#endif

#else
						std::string src = configPath + "Comm/" + name;
						std::string des = fileName.substr(0, fileName.find_last_of("/")) + "/" + name;
						auto strSrc = src + "_d";
						auto strDes = des + "_d";
						printResult(CopyFile(strSrc, strDes), strSrc);
#endif

					}
					else
					{
#if NF_PLATFORM == NF_PLATFORM_WIN

#ifdef NF_DEBUG_MODE
						std::string src = configPath + "Comm/Debug/" + name;
						std::string des = fileName.substr(0, fileName.find_last_of("/")) + "/" + name;
						auto strSrc = src + "_d.dll";
						auto strDes = des + "_d.dll";
						auto strSrcPDB = src + "_d.pdb";
						auto strDesPDB = des + "_d.pdb";
						printResult(CopyFile(strSrc, strDes), strSrc);
						printResult(CopyFile(strSrcPDB, strDesPDB), strSrcPDB);
#else
						std::string src = configPath + "Comm/Release/" + name;
						std::string des = fileName.substr(0, fileName.find_last_of("/")) + "/" + name;
						auto strSrc = src + ".dll";
						auto strDes = des + ".dll";
						printResult(CopyFile(strSrc, strDes), strSrc);
#endif

#else
						std::string src = configPath + "Comm/lib" + name;
						std::string des = fileName.substr(0, fileName.find_last_of("/")) + "/" + name;
						auto strSrc = src + "_d.so";
						auto strDes = des + "_d.so";
						printResult(CopyFile(strSrc, strDes), strSrc);
#endif
					}
				}
			}
		}
	}
#if NF_PLATFORM == NF_PLATFORM_WIN
	getch();
#else

#endif
	return 0;
}<commit_msg>optimized NFAutoCopyDll to show errors<commit_after>#include <map>
#include <vector>
#include <string>
#include <time.h>
#include "NFComm/NFPluginModule/NFIPluginManager.h"
#include "NFComm/NFCore/NFQueue.h"
#include "NFComm/RapidXML/rapidxml.hpp"
#include "NFComm/RapidXML/rapidxml_iterators.hpp"
#include "NFComm/RapidXML/rapidxml_print.hpp"
#include "NFComm/RapidXML/rapidxml_utils.hpp"
#include "NFComm/NFPluginModule/NFPlatform.h"

#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <errno.h>

#if NF_PLATFORM == NF_PLATFORM_WIN
#include <io.h>
#include <windows.h>
#include <conio.h>
#else
#include <iconv.h>
#include <unistd.h>
#include <cstdio>
#include <dirent.h>
#include <sys/stat.h>
#endif

bool GetPluginNameList(std::string& strPlugin, std::vector<std::string>& pluginList, std::string& configPath)
{
	rapidxml::file<> fdoc(strPlugin.c_str());
	rapidxml::xml_document<>  doc;
	doc.parse<0>(fdoc.data());

	rapidxml::xml_node<>* pRoot = doc.first_node();
	for (rapidxml::xml_node<>* pPluginNode = pRoot->first_node("Plugin"); pPluginNode; pPluginNode = pPluginNode->next_sibling("Plugin"))
	{
		const char* strPluginName = pPluginNode->first_attribute("Name")->value();
		const char* strMain = pPluginNode->first_attribute("Main")->value();
		pluginList.push_back(std::string(strPluginName));
	}

	rapidxml::xml_node<>* pPluginAppNode = pRoot->first_node("APPID");
	if (!pPluginAppNode)
	{
		//NFASSERT(0, "There are no App ID", __FILE__, __FUNCTION__);
		return false;
	}

	const char* strAppID = pPluginAppNode->first_attribute("Name")->value();
	if (!strAppID)
	{
		//NFASSERT(0, "There are no App ID", __FILE__, __FUNCTION__);
		return false;
	}

	rapidxml::xml_node<>* pPluginConfigPathNode = pRoot->first_node("ConfigPath");
	if (!pPluginConfigPathNode)
	{
		//NFASSERT(0, "There are no ConfigPath", __FILE__, __FUNCTION__);
		return false;
	}

	if (NULL == pPluginConfigPathNode->first_attribute("Name"))
	{
		//NFASSERT(0, "There are no ConfigPath.Name", __FILE__, __FUNCTION__);
		return false;
	}

	configPath = pPluginConfigPathNode->first_attribute("Name")->value();

	return true;
}

int CopyFile(std::string& SourceFile, std::string& NewFile)
{
	ifstream in;
	ofstream out;
	in.open(SourceFile.c_str(), ios::binary);//Դļ
	if (in.fail())//Դļʧ
	{
		cout << "Error 1: Fail to open the source file." << endl;
		in.close();
		out.close();
		return 0;
	}
	out.open(NewFile.c_str(), ios::binary);//Ŀļ
	if (out.fail())//ļʧ
	{
		cout << "Error 2: Fail to create the new file." << endl;
		out.close();
		in.close();
		return 0;
	}
	else//ļ
	{
		out << in.rdbuf();
		out.close();
		in.close();
		return 1;
	}
}

std::vector<std::string> GetFileListInFolder(std::string folderPath, int depth)
{
	std::vector<std::string> result;
#if NF_PLATFORM == NF_PLATFORM_WIN
	_finddata_t FileInfo;
	std::string strfind = folderPath + "\\*";
	long long Handle = _findfirst(strfind.c_str(), &FileInfo);

	if (Handle == -1L)
	{
		std::cerr << "can not match the folder path" << std::endl;
		exit(-1);
	}
	do {
		//жǷĿ¼
		if (FileInfo.attrib & _A_SUBDIR)
		{
			//Ҫ
			if ((strcmp(FileInfo.name, ".") != 0) && (strcmp(FileInfo.name, "..") != 0))
			{
				std::string newPath = folderPath + "\\" + FileInfo.name;
				//dfsFolder(newPath, depth);
				auto newResult = GetFileListInFolder(newPath, depth);
				result.insert(result.begin(), newResult.begin(), newResult.end());
			}
		}
		else
		{

			std::string filename = (folderPath + "\\" + FileInfo.name);
			result.push_back(filename);
		}
	} while (_findnext(Handle, &FileInfo) == 0);

	_findclose(Handle);
#else
	DIR *pDir;
	struct dirent *ent;
	char childpath[512];
	char absolutepath[512];
	pDir = opendir(folderPath.c_str());
	memset(childpath, 0, sizeof(childpath));
	while ((ent = readdir(pDir)) != NULL)
	{
		if (ent->d_type & DT_DIR)
		{
			if (strcmp(ent->d_name, ".") == 0 || strcmp(ent->d_name, "..") == 0)
			{
				continue;
			}
			std::string childpath = folderPath + "/" + ent->d_name;
			auto newResult = GetFileListInFolder(childpath, depth);
			result.insert(result.begin(), newResult.begin(), newResult.end());
		}
		else
		{
			sprintf(absolutepath, "%s/%s", folderPath.c_str(), ent->d_name);
			result.push_back(absolutepath);
		}
	}

	sort(result.begin(), result.end());//
#endif
	return result;
}

void StringReplace(std::string &strBig, const std::string &strsrc, const std::string &strdst)
{
	std::string::size_type pos = 0;
	std::string::size_type srclen = strsrc.size();
	std::string::size_type dstlen = strdst.size();

	while ((pos = strBig.find(strsrc, pos)) != std::string::npos)
	{
		strBig.replace(pos, srclen, strdst);
		pos += dstlen;
	}
}

void printResult(int result, std::string& strName)
{
	if (result == 1)
	{
		printf("Copy file: %s success!\n", strName.c_str());
	}
	else
	{
		printf("Copy file: %s failed!\n", strName.c_str());
	}
}

int main()
{
	std::vector<std::string> fileList;
	std::vector<std::string> errorFileList;
#ifdef NF_DEBUG_MODE
	fileList = GetFileListInFolder("../../Debug", 10);
#else
	fileList = GetFileListInFolder("../../Release", 10);
#endif

	for (auto fileName : fileList)
	{
		if (fileName.find("Plugin.xml") != std::string::npos)
		{
			StringReplace(fileName, "\\", "/");
			StringReplace(fileName, "//", "/");
			printf("Reading xml file: %s\n", fileName.c_str());

			std::vector<std::string> pluginList;
			std::string configPath = "";
			GetPluginNameList(fileName, pluginList, configPath);
			if (pluginList.size() > 0 && configPath != "")
			{
#if NF_PLATFORM == NF_PLATFORM_WIN
				pluginList.push_back("libprotobuf");
				pluginList.push_back("NFMessageDefine");
#else
				pluginList.push_back("NFMessageDefine");
#endif
				pluginList.push_back("NFPluginLoader");
				configPath = "../" + configPath;
				configPath = fileName.substr(0, fileName.find_last_of("/")) + "/" + configPath;

				for (std::string name : pluginList)
				{
					int result = 0;
					if (name == "NFPluginLoader")
					{
						int result = 0;
#if NF_PLATFORM == NF_PLATFORM_WIN

#ifdef NF_DEBUG_MODE
						std::string src = configPath + "Comm/Debug/" + name;
						std::string des = fileName.substr(0, fileName.find_last_of("/")) + "/" + name;
						auto strSrc = src + "_d.exe";
						auto strDes = des + "_d.exe";
						auto strSrcPDB = src + "_d.pdb";
						auto strDesPDB = des + "_d.pdb";

						result = CopyFile(strSrc, strDes);
						if (result != 1)
						{
							errorFileList.push_back(strSrc);
						}
						printResult(result, strSrc);

						result = CopyFile(strSrcPDB, strDesPDB);
						if (result != 1)
						{
							errorFileList.push_back(strSrcPDB);
						}
						printResult(result, strSrcPDB);
#else
						std::string src = configPath + "Comm/Release/" + name;
						std::string des = fileName.substr(0, fileName.find_last_of("/")) + "/" + name;
						auto strSrc = src + ".exe";
						auto strDes = des + ".exe";
						int result = 0;
						result = CopyFile(strSrc, strDes);
						if (result != 1)
						{
							errorFileList.push_back(strSrc);
						}
						printResult(result, strSrc);
#endif

#else
						std::string src = configPath + "Comm/" + name;
						std::string des = fileName.substr(0, fileName.find_last_of("/")) + "/" + name;
						auto strSrc = src + "_d";
						auto strDes = des + "_d";
						result = CopyFile(strSrc, strDes);
						if (result != 1)
						{
							errorFileList.push_back(strSrc);
						}
						printResult(result, strSrc);
#endif

					}
					else
					{
#if NF_PLATFORM == NF_PLATFORM_WIN

#ifdef NF_DEBUG_MODE
						std::string src = configPath + "Comm/Debug/" + name;
						std::string des = fileName.substr(0, fileName.find_last_of("/")) + "/" + name;
						auto strSrc = src + "_d.dll";
						auto strDes = des + "_d.dll";
						auto strSrcPDB = src + "_d.pdb";
						auto strDesPDB = des + "_d.pdb";
						result = CopyFile(strSrc, strDes);
						if (result != 1)
						{
							errorFileList.push_back(strSrc);
						}
						printResult(result, strSrc);

						result = CopyFile(strSrcPDB, strDesPDB);
						if (result != 1)
						{
							errorFileList.push_back(strSrcPDB);
						}
						printResult(result, strSrcPDB);
#else
						std::string src = configPath + "Comm/Release/" + name;
						std::string des = fileName.substr(0, fileName.find_last_of("/")) + "/" + name;
						auto strSrc = src + ".dll";
						auto strDes = des + ".dll";
						result = CopyFile(strSrc, strDes);
						if (result != 1)
						{
							errorFileList.push_back(strSrc);
						}
						printResult(result, strSrc);
#endif

#else
						std::string src = configPath + "Comm/lib" + name;
						std::string des = fileName.substr(0, fileName.find_last_of("/")) + "/" + name;
						auto strSrc = src + "_d.so";
						auto strDes = des + "_d.so";
						result = CopyFile(strSrc, strDes);
						if (result != 1)
						{
							errorFileList.push_back(strSrc);
						}
						printResult(result, strSrc);
#endif
					}
				}
			}
		}
	}
	if (errorFileList.size() <= 0)
	{
		printf("File Copy Done with NO ERROR!\n");
	}
	else
	{
		printf("File Copy Done with %d errors as follow:\n", (int)errorFileList.size());
		for (auto errFile : errorFileList)
		{
			printf("\t%s\n", errFile.c_str());
		}
	}
#if NF_PLATFORM == NF_PLATFORM_WIN
	printf("Press any Key to Exit!");
	getch();
#else

#endif
	return 0;
}<|endoftext|>


<commit_before>/*
	Copyright (c) 2016 Xavier Leclercq

	Permission is hereby granted, free of charge, to any person obtaining a
	copy of this software and associated documentation files (the "Software"),
	to deal in the Software without restriction, including without limitation
	the rights to use, copy, modify, merge, publish, distribute, sublicense,
	and/or sell copies of the Software, and to permit persons to whom the
	Software is furnished to do so, subject to the following conditions:

	The above copyright notice and this permission notice shall be included in
	all copies or substantial portions of the Software.

	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
	IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
	FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
	THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
	LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
	FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
	IN THE SOFTWARE.
*/

/*
	Part of this file were copied from the Chart.js project (http://chartjs.org/)
	and translated into C++.

	The files of the Chart.js project have the following copyright and license.

	Copyright (c) 2013-2016 Nick Downie
	Released under the MIT license
	https://github.com/nnnick/Chart.js/blob/master/LICENSE.md
*/

#include "wxchartgrid.h"
#include "wxchartutilities.h"

wxChartGrid::wxChartGrid(const wxSize &size,
						 const wxVector<wxString> &labels,
						 wxDouble minValue,
						 wxDouble maxValue,
						 const wxChartGridOptions& options)
	: m_options(options), m_mapping(size, labels.size()),
	m_XAxis(labels), m_needsFit(true)
{
	wxDouble graphMinValue;
	wxDouble graphMaxValue;
	wxDouble valueRange = 0;
	wxChartUtilities::CalculateGridRange(minValue, maxValue,
		graphMinValue, graphMaxValue, valueRange, m_steps, m_stepValue);
	m_mapping.SetMinValue(graphMinValue);
	m_mapping.SetMaxValue(graphMaxValue);

	m_YAxis.BuildYLabels(m_mapping.GetMinValue(), m_steps, m_stepValue);
}

bool wxChartGrid::HitTest(const wxPoint &point) const
{
	return false;
}

void wxChartGrid::Draw(wxGraphicsContext &gc)
{
	Fit(m_steps, gc);

	wxDouble yLabelGap = (m_mapping.GetEndPoint() - m_mapping.GetStartPoint()) / m_steps;
	wxDouble xStart = m_mapping.GetLeftPadding();

	m_XAxis.UpdateLabelPositions2();
	m_YAxis.UpdateLabelPositions1();

	if (m_options.ShowHorizontalLines())
	{
		for (size_t i = 1; i < m_YAxis.GetLabels().size(); ++i)
		{
			wxDouble yLabelCenter = m_mapping.GetEndPoint() - (yLabelGap * i);
			wxDouble linePositionY = yLabelCenter;

			wxGraphicsPath path = gc.CreatePath();
			path.MoveToPoint(xStart, linePositionY);
			path.AddLineToPoint(m_mapping.GetSize().GetWidth(), linePositionY);
			path.CloseSubpath();

			wxPen pen1(m_options.GetGridLineColor(), m_options.GetGridLineWidth());
			gc.SetPen(pen1);
			gc.StrokePath(path);

			wxGraphicsPath path2 = gc.CreatePath();
			path2.MoveToPoint(xStart - 5, linePositionY);
			path2.AddLineToPoint(xStart, linePositionY);
			path2.CloseSubpath();

			wxPen pen(m_options.GetXAxisOptions().GetLineColor(),
				m_options.GetXAxisOptions().GetLineWidth());
			gc.SetPen(pen);
			gc.StrokePath(path2);
		}
	}

	if (m_options.ShowVerticalLines())
	{
		for (size_t i = 1; i < m_XAxis.GetLabels().size(); ++i)
		{
			wxPoint2DDouble s;
			wxPoint2DDouble t;
			m_mapping.GetVerticalLinePositions(i, s, t);
			wxDouble linePosition = s.m_x;

			wxGraphicsPath path = gc.CreatePath();
			path.MoveToPoint(linePosition, m_mapping.GetEndPoint());
			path.AddLineToPoint(linePosition, m_mapping.GetStartPoint() - 3);
			path.CloseSubpath();

			wxPen pen1(m_options.GetGridLineColor(), m_options.GetGridLineWidth());
			gc.SetPen(pen1);
			gc.StrokePath(path);

			// Small lines at the bottom of the base grid line
			wxGraphicsPath path2 = gc.CreatePath();
			path2.MoveToPoint(linePosition, m_mapping.GetEndPoint());
			path2.AddLineToPoint(linePosition, m_mapping.GetEndPoint() + 5);
			path2.CloseSubpath();

			wxPen pen(m_options.GetYAxisOptions().GetLineColor(),
				m_options.GetYAxisOptions().GetLineWidth());
			gc.SetPen(pen);
			gc.StrokePath(path2);
		}
	}

	m_XAxis.Draw(gc);
	m_YAxis.Draw(gc);

	// Draw the Y-axis
	if (m_XAxis.GetLabels().size() > 0)
	{
		wxPoint2DDouble s;
		wxPoint2DDouble t;
		m_mapping.GetVerticalLinePositions(0, s, t);
		wxDouble linePosition = s.m_x;

		wxGraphicsPath path = gc.CreatePath();
		path.MoveToPoint(linePosition, m_mapping.GetEndPoint());
		path.AddLineToPoint(linePosition, m_mapping.GetStartPoint() - 3);
		path.CloseSubpath();

		wxPen pen(m_options.GetYAxisOptions().GetLineColor(),
			m_options.GetYAxisOptions().GetLineWidth());
		gc.SetPen(pen);
		gc.StrokePath(path);
	}

	if (m_XAxis.GetLabels().size() > 0)
	{
		wxPoint2DDouble s;
		wxPoint2DDouble t;
		m_mapping.GetVerticalLinePositions(0, s, t);
		wxDouble linePosition = s.m_x;

		// Small lines at the bottom of the base grid line
		wxGraphicsPath path2 = gc.CreatePath();
		path2.MoveToPoint(linePosition, m_mapping.GetEndPoint());
		path2.AddLineToPoint(linePosition, m_mapping.GetEndPoint() + 5);
		path2.CloseSubpath();

		wxPen pen(m_options.GetYAxisOptions().GetLineColor(),
			m_options.GetYAxisOptions().GetLineWidth());
		gc.SetPen(pen);
		gc.StrokePath(path2);
	}

	// Draw the X-axis
	if (m_YAxis.GetLabels().size() > 0)
	{
		wxDouble yLabelCenter = m_mapping.GetEndPoint();
		wxDouble linePositionY = yLabelCenter;

		wxGraphicsPath path = gc.CreatePath();
		path.MoveToPoint(xStart, linePositionY);
		path.AddLineToPoint(m_mapping.GetSize().GetWidth(), linePositionY);
		path.CloseSubpath();

		wxPen pen(m_options.GetXAxisOptions().GetLineColor(),
			m_options.GetXAxisOptions().GetLineWidth());
		gc.SetPen(pen);
		gc.StrokePath(path);

		wxGraphicsPath path2 = gc.CreatePath();
		path2.MoveToPoint(xStart - 5, linePositionY);
		path2.AddLineToPoint(xStart, linePositionY);
		path2.CloseSubpath();

		gc.SetPen(pen);
		gc.StrokePath(path2);
	}
}

void wxChartGrid::Resize(const wxSize &size)
{
	m_mapping.SetSize(size);
	m_needsFit = true;
}

const wxChartGridMapping& wxChartGrid::GetMapping() const
{
	return m_mapping;
}

void wxChartGrid::Fit(size_t steps,
					  wxGraphicsContext &gc)
{
	if (!m_needsFit)
	{
		return;
	}

	wxDouble startPoint = m_options.GetYAxisOptions().GetFontSize();
	wxDouble endPoint = m_mapping.GetSize().GetHeight() - (m_options.GetYAxisOptions().GetFontSize() + 15) - 5; // -5 to pad labels

	// Apply padding settings to the start and end point.
	//this.startPoint += this.padding;
	//this.endPoint -= this.padding;

	m_YAxis.UpdateLabelSizes(gc);

	m_XAxis.UpdateLabelSizes(gc);
	wxDouble leftPadding = CalculateLeftPadding(m_XAxis.GetLabels(), m_YAxis.GetLabelMaxWidth());
	m_XAxis.Fit(leftPadding, 0, endPoint, m_mapping.GetSize().GetWidth() - leftPadding);
	m_YAxis.Fit(leftPadding, startPoint, endPoint, 0);

	m_mapping.Fit(leftPadding, startPoint, endPoint);

	m_needsFit = false;
}

wxDouble wxChartGrid::CalculateLeftPadding(const wxVector<wxChartLabel> &xLabels,
										   wxDouble yLabelMaxWidth)
{
	// Either the first x label or any of the y labels can be the widest
	// so they are all taken into account to compute the left padding
	wxDouble leftPadding = yLabelMaxWidth;
	if ((xLabels.size() > 0) && ((xLabels[0].GetSize().GetWidth() / 2) > leftPadding))
	{
		leftPadding = (xLabels[0].GetSize().GetWidth() / 2);
	}
	return leftPadding;
}
<commit_msg>Refactoring<commit_after>/*
	Copyright (c) 2016 Xavier Leclercq

	Permission is hereby granted, free of charge, to any person obtaining a
	copy of this software and associated documentation files (the "Software"),
	to deal in the Software without restriction, including without limitation
	the rights to use, copy, modify, merge, publish, distribute, sublicense,
	and/or sell copies of the Software, and to permit persons to whom the
	Software is furnished to do so, subject to the following conditions:

	The above copyright notice and this permission notice shall be included in
	all copies or substantial portions of the Software.

	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
	IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
	FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
	THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
	LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
	FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
	IN THE SOFTWARE.
*/

/*
	Part of this file were copied from the Chart.js project (http://chartjs.org/)
	and translated into C++.

	The files of the Chart.js project have the following copyright and license.

	Copyright (c) 2013-2016 Nick Downie
	Released under the MIT license
	https://github.com/nnnick/Chart.js/blob/master/LICENSE.md
*/

#include "wxchartgrid.h"
#include "wxchartutilities.h"

wxChartGrid::wxChartGrid(const wxSize &size,
						 const wxVector<wxString> &labels,
						 wxDouble minValue,
						 wxDouble maxValue,
						 const wxChartGridOptions& options)
	: m_options(options), m_mapping(size, labels.size()),
	m_XAxis(labels), m_needsFit(true)
{
	wxDouble graphMinValue;
	wxDouble graphMaxValue;
	wxDouble valueRange = 0;
	wxChartUtilities::CalculateGridRange(minValue, maxValue,
		graphMinValue, graphMaxValue, valueRange, m_steps, m_stepValue);
	m_mapping.SetMinValue(graphMinValue);
	m_mapping.SetMaxValue(graphMaxValue);

	m_YAxis.BuildYLabels(m_mapping.GetMinValue(), m_steps, m_stepValue);
}

bool wxChartGrid::HitTest(const wxPoint &point) const
{
	return false;
}

void wxChartGrid::Draw(wxGraphicsContext &gc)
{
	Fit(m_steps, gc);

	wxDouble yLabelGap = (m_mapping.GetEndPoint() - m_mapping.GetStartPoint()) / m_steps;
	wxDouble xStart = m_mapping.GetLeftPadding();

	m_XAxis.UpdateLabelPositions2();
	m_YAxis.UpdateLabelPositions1();

	if (m_options.ShowHorizontalLines())
	{
		for (size_t i = 1; i < m_YAxis.GetLabels().size(); ++i)
		{
			wxDouble yLabelCenter = m_mapping.GetEndPoint() - (yLabelGap * i);
			wxDouble linePositionY = yLabelCenter;

			wxGraphicsPath path = gc.CreatePath();
			path.MoveToPoint(xStart, linePositionY);
			path.AddLineToPoint(m_mapping.GetSize().GetWidth(), linePositionY);
			path.CloseSubpath();

			wxPen pen1(m_options.GetGridLineColor(), m_options.GetGridLineWidth());
			gc.SetPen(pen1);
			gc.StrokePath(path);

			wxGraphicsPath path2 = gc.CreatePath();
			path2.MoveToPoint(xStart - 5, linePositionY);
			path2.AddLineToPoint(xStart, linePositionY);
			path2.CloseSubpath();

			wxPen pen(m_options.GetXAxisOptions().GetLineColor(),
				m_options.GetXAxisOptions().GetLineWidth());
			gc.SetPen(pen);
			gc.StrokePath(path2);
		}
	}

	if (m_options.ShowVerticalLines())
	{
		for (size_t i = 1; i < m_XAxis.GetLabels().size(); ++i)
		{
			wxPoint2DDouble s;
			wxPoint2DDouble t;
			m_mapping.GetVerticalLinePositions(i, s, t);
			wxDouble linePosition = s.m_x;

			wxGraphicsPath path = gc.CreatePath();
			path.MoveToPoint(linePosition, m_mapping.GetEndPoint());
			path.AddLineToPoint(linePosition, m_mapping.GetStartPoint() - 3);
			path.CloseSubpath();

			wxPen pen1(m_options.GetGridLineColor(), m_options.GetGridLineWidth());
			gc.SetPen(pen1);
			gc.StrokePath(path);

			// Small lines at the bottom of the base grid line
			wxGraphicsPath path2 = gc.CreatePath();
			path2.MoveToPoint(linePosition, m_mapping.GetEndPoint());
			path2.AddLineToPoint(linePosition, m_mapping.GetEndPoint() + 5);
			path2.CloseSubpath();

			wxPen pen(m_options.GetYAxisOptions().GetLineColor(),
				m_options.GetYAxisOptions().GetLineWidth());
			gc.SetPen(pen);
			gc.StrokePath(path2);
		}
	}

	m_XAxis.Draw(gc);
	m_YAxis.Draw(gc);

	// Draw the Y-axis
	if (m_XAxis.GetLabels().size() > 0)
	{
		wxPoint2DDouble s;
		wxPoint2DDouble t;
		m_mapping.GetVerticalLinePositions(0, s, t);
		wxDouble linePosition = s.m_x;

		wxGraphicsPath path = gc.CreatePath();
		path.MoveToPoint(linePosition, m_mapping.GetEndPoint());
		path.AddLineToPoint(linePosition, m_mapping.GetStartPoint() - 3);
		path.CloseSubpath();

		wxPen pen(m_options.GetYAxisOptions().GetLineColor(),
			m_options.GetYAxisOptions().GetLineWidth());
		gc.SetPen(pen);
		gc.StrokePath(path);
	}

	if (m_XAxis.GetLabels().size() > 0)
	{
		wxPoint2DDouble s;
		wxPoint2DDouble t;
		m_mapping.GetVerticalLinePositions(0, s, t);
		wxDouble linePosition = s.m_x;

		// Small lines at the bottom of the base grid line
		wxGraphicsPath path2 = gc.CreatePath();
		path2.MoveToPoint(linePosition, m_mapping.GetEndPoint());
		path2.AddLineToPoint(linePosition, m_mapping.GetEndPoint() + 5);
		path2.CloseSubpath();

		wxPen pen(m_options.GetYAxisOptions().GetLineColor(),
			m_options.GetYAxisOptions().GetLineWidth());
		gc.SetPen(pen);
		gc.StrokePath(path2);
	}

	// Draw the X-axis
	if (m_YAxis.GetLabels().size() > 0)
	{
		wxDouble yLabelCenter = m_mapping.GetEndPoint();
		wxDouble linePositionY = yLabelCenter;

		wxGraphicsPath path = gc.CreatePath();
		path.MoveToPoint(xStart, linePositionY);
		path.AddLineToPoint(m_mapping.GetSize().GetWidth(), linePositionY);
		path.CloseSubpath();

		wxPen pen(m_options.GetXAxisOptions().GetLineColor(),
			m_options.GetXAxisOptions().GetLineWidth());
		gc.SetPen(pen);
		gc.StrokePath(path);
	}

	if (m_YAxis.GetLabels().size() > 0)
	{
		wxDouble yLabelCenter = m_mapping.GetEndPoint();
		wxDouble linePositionY = yLabelCenter;

		wxGraphicsPath path2 = gc.CreatePath();
		path2.MoveToPoint(xStart - 5, linePositionY);
		path2.AddLineToPoint(xStart, linePositionY);
		path2.CloseSubpath();

		wxPen pen(m_options.GetXAxisOptions().GetLineColor(),
			m_options.GetXAxisOptions().GetLineWidth());
		gc.SetPen(pen);
		gc.StrokePath(path2);
	}
}

void wxChartGrid::Resize(const wxSize &size)
{
	m_mapping.SetSize(size);
	m_needsFit = true;
}

const wxChartGridMapping& wxChartGrid::GetMapping() const
{
	return m_mapping;
}

void wxChartGrid::Fit(size_t steps,
					  wxGraphicsContext &gc)
{
	if (!m_needsFit)
	{
		return;
	}

	wxDouble startPoint = m_options.GetYAxisOptions().GetFontSize();
	wxDouble endPoint = m_mapping.GetSize().GetHeight() - (m_options.GetYAxisOptions().GetFontSize() + 15) - 5; // -5 to pad labels

	// Apply padding settings to the start and end point.
	//this.startPoint += this.padding;
	//this.endPoint -= this.padding;

	m_YAxis.UpdateLabelSizes(gc);

	m_XAxis.UpdateLabelSizes(gc);
	wxDouble leftPadding = CalculateLeftPadding(m_XAxis.GetLabels(), m_YAxis.GetLabelMaxWidth());
	m_XAxis.Fit(leftPadding, 0, endPoint, m_mapping.GetSize().GetWidth() - leftPadding);
	m_YAxis.Fit(leftPadding, startPoint, endPoint, 0);

	m_mapping.Fit(leftPadding, startPoint, endPoint);

	m_needsFit = false;
}

wxDouble wxChartGrid::CalculateLeftPadding(const wxVector<wxChartLabel> &xLabels,
										   wxDouble yLabelMaxWidth)
{
	// Either the first x label or any of the y labels can be the widest
	// so they are all taken into account to compute the left padding
	wxDouble leftPadding = yLabelMaxWidth;
	if ((xLabels.size() > 0) && ((xLabels[0].GetSize().GetWidth() / 2) > leftPadding))
	{
		leftPadding = (xLabels[0].GetSize().GetWidth() / 2);
	}
	return leftPadding;
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: streamsection.hxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: vg $ $Date: 2005-02-16 16:02:22 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (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.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef _COMPHELPER_STREAMSECTION_HXX_
#define _COMPHELPER_STREAMSECTION_HXX_

#ifndef _COM_SUN_STAR_IO_XMARKABLESTREAM_HPP_
#include <com/sun/star/io/XMarkableStream.hpp>
#endif
#ifndef _COM_SUN_STAR_IO_XDATAINPUTSTREAM_HPP_
#include <com/sun/star/io/XDataInputStream.hpp>
#endif
#ifndef _COM_SUN_STAR_IO_XDATAOUTPUTSTREAM_HPP_
#include <com/sun/star/io/XDataOutputStream.hpp>
#endif

#ifndef INCLUDED_COMPHELPERDLLAPI_H
#include "comphelper/comphelperdllapi.h"
#endif

namespace comphelper
{

    namespace stario    = ::com::sun::star::io;
    namespace staruno   = ::com::sun::star::uno;

/** implements handling for compatibly reading/writing data from/into an input/output stream.
    data written in a block secured by this class should be readable by older versions which
    use the same mechanism.

    @author Frank Schoenheit
    @since  00/26/05
*/

class COMPHELPER_DLLPUBLIC OStreamSection
{
    staruno::Reference< stario::XMarkableStream >       m_xMarkStream;
    staruno::Reference< stario::XDataInputStream >      m_xInStream;
    staruno::Reference< stario::XDataOutputStream >     m_xOutStream;

    sal_Int32   m_nBlockStart;
    sal_Int32   m_nBlockLen;

public:
    /** starts reading of a "skippable" section of data within the given input stream

        @param      _rxInput    the stream to read from. Must support the
                                <type scope="com::sun::star::io">XMarkableStream</type> interface
    */
    OStreamSection(const staruno::Reference< stario::XDataInputStream >& _rxInput);

    /** starts writing of a "skippable" section of data into the given output stream
        @param      _rxOutput           the stream the stream to write to. Must support the
                                        <type scope="com::sun::star::io">XMarkableStream</type> interface
        @param      _nPresumedLength    estimation for the length of the upcoming section. If greater 0, this
                                        value will be written as section length and corrected (in the dtor) only if
                                        needed. If you know how much bytes you are about to write, you may
                                        want to use this param, saving some stream operations this way.
    */
    OStreamSection(const staruno::Reference< stario::XDataOutputStream >& _rxOutput, sal_Int32 _nPresumedLength = 0);

    /** dtor.
If constructed for writing, the section "opened" by this object will be "closed".

        If constructed for reading, any remaining bytes 'til the end of the section will be skipped.
    */
    ~OStreamSection();
    /**
        return the number of bytes which are still available
    */
    sal_Int32 available();
};

}   // namespace comphelper

#endif // _COMPHELPER_STREAMSECTION_HXX_
<commit_msg>INTEGRATION: CWS ooo19126 (1.3.56); FILE MERGED 2005/09/05 15:23:49 rt 1.3.56.1: #i54170# Change license header: remove SISSL<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: streamsection.hxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-08 02:40:28 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef _COMPHELPER_STREAMSECTION_HXX_
#define _COMPHELPER_STREAMSECTION_HXX_

#ifndef _COM_SUN_STAR_IO_XMARKABLESTREAM_HPP_
#include <com/sun/star/io/XMarkableStream.hpp>
#endif
#ifndef _COM_SUN_STAR_IO_XDATAINPUTSTREAM_HPP_
#include <com/sun/star/io/XDataInputStream.hpp>
#endif
#ifndef _COM_SUN_STAR_IO_XDATAOUTPUTSTREAM_HPP_
#include <com/sun/star/io/XDataOutputStream.hpp>
#endif

#ifndef INCLUDED_COMPHELPERDLLAPI_H
#include "comphelper/comphelperdllapi.h"
#endif

namespace comphelper
{

    namespace stario    = ::com::sun::star::io;
    namespace staruno   = ::com::sun::star::uno;

/** implements handling for compatibly reading/writing data from/into an input/output stream.
    data written in a block secured by this class should be readable by older versions which
    use the same mechanism.

    @author Frank Schoenheit
    @since  00/26/05
*/

class COMPHELPER_DLLPUBLIC OStreamSection
{
    staruno::Reference< stario::XMarkableStream >       m_xMarkStream;
    staruno::Reference< stario::XDataInputStream >      m_xInStream;
    staruno::Reference< stario::XDataOutputStream >     m_xOutStream;

    sal_Int32   m_nBlockStart;
    sal_Int32   m_nBlockLen;

public:
    /** starts reading of a "skippable" section of data within the given input stream

        @param      _rxInput    the stream to read from. Must support the
                                <type scope="com::sun::star::io">XMarkableStream</type> interface
    */
    OStreamSection(const staruno::Reference< stario::XDataInputStream >& _rxInput);

    /** starts writing of a "skippable" section of data into the given output stream
        @param      _rxOutput           the stream the stream to write to. Must support the
                                        <type scope="com::sun::star::io">XMarkableStream</type> interface
        @param      _nPresumedLength    estimation for the length of the upcoming section. If greater 0, this
                                        value will be written as section length and corrected (in the dtor) only if
                                        needed. If you know how much bytes you are about to write, you may
                                        want to use this param, saving some stream operations this way.
    */
    OStreamSection(const staruno::Reference< stario::XDataOutputStream >& _rxOutput, sal_Int32 _nPresumedLength = 0);

    /** dtor.
If constructed for writing, the section "opened" by this object will be "closed".

        If constructed for reading, any remaining bytes 'til the end of the section will be skipped.
    */
    ~OStreamSection();
    /**
        return the number of bytes which are still available
    */
    sal_Int32 available();
};

}   // namespace comphelper

#endif // _COMPHELPER_STREAMSECTION_HXX_
<|endoftext|>


<commit_before>/*****************************************************************************
 * Timestamp.cxx
 *****************************************************************************
 * Implementation for class Timestamp.
 *****************************************************************************/

// System includes.
#if defined(PLAT_WIN32)
  #if defined(HAS_WINDOWS_H)
    #include <windows.h>
  #endif
#elif defined(PLAT_POSIX)
  #if defined(HAS_SYS_TIME_H)
    #include <sys/time.h>
  #endif
  #if defined(HAS_TIME_H)
    #include <time.h>
  #endif
#endif

// Class include.
#include "Timestamp.hxx"

// Namespaces used.
using namespace std;

// Namespace wrapper.
namespace DAC {

  /***************************************************************************
   * Class Timestamp::I_Month.
   ***************************************************************************/

  /***************************************************************************/
  // Function members.

  // Get the number of days in this month.
  Timestamp::I_Day Timestamp::I_Month::daysInMonth (I_Year const& year) const {

    // Work area.
    Timestamp::I_Day days;

    // Easy.
    try {
      switch (Value<int>()) {

        case 1:
        case 3:
        case 5:
        case 7:
        case 8:
        case 10:
        case 12:
          days = 31;
        break;

        case 2:
          days = ((year % I_Year(4)) && (!(year % I_Year(100)) || (year % I_Year(400)))) ? 29 : 28;
        break;

        case 4:
        case 6:
        case 9:
        case 11:
          days = 30;
        break;

        default:
          days = 0;
        break;

      }
    } catch (ArbIntErrors::ScalarOverflow) {
      days = 0;
    }

    // We done.
    return days;

  }

  /***************************************************************************
   * Class Timestamp.
   ***************************************************************************/

  /***************************************************************************/
  // Static data members.

  // True when class has been initialized.
  bool Timestamp::s_initialized = false;

  // Default list of leap seconds.
  ReferencePointer<Timestamp::LeapSecondList> Timestamp::s_defaultleapseconds;

  /***************************************************************************/
  // Function members.

  // Default constructor.
  Timestamp::Timestamp () {

    // Call common init.
    _init();

  }

  // Copy constructor.
  Timestamp::Timestamp (Timestamp const& ts) {

    // Call common init.
    _init();

    // Set the timestamp.
    copy(ts);

  }

  // Set this timestamp.
  Timestamp& Timestamp::set (Interval const& time) {

    // Work area.
    Timestamp newtime(*this);

    // Verify that the new time is a valid time.
    if (!time.isSet_Second()      ||
        !time.isSet_Minute()      ||
        !time.isSet_Hour()        ||
        !time.isSet_Day()         ||
        !time.isSet_Month()       ||
        !time.isSet_Year()        ||
        !time.Year().isInteger()        || !time.Year()                      ||
        !time.Month().isInteger()       || (time.Month()       < TimeVal(1)) || (time.Month()       > TimeVal(12))                                                      ||
        !time.Day().isInteger()         || (time.Day()         < TimeVal(1)) || (time.Day()         > time.Month().daysInMonth(time.Year()))                            ||
        !time.Hour().isInteger()        || (time.Hour()        < TimeVal(0)) || (time.Hour()        > TimeVal(23))                                                      ||
        !time.Minute().isInteger()      || (time.Minute()      < TimeVal(0)) || (time.Minute()      > TimeVal(59))                                                      ||
        !time.Second().isInteger()      || (time.Second()      < TimeVal(0)) || (time.Second()      > TimeVal(59) + _leapSecond(time.Year(), time.Month(), time.Day())) ||
        !time.Millisecond().isInteger() || (time.Millisecond() < TimeVal(0)) || (time.Millisecond() > TimeVal(999))
    ) {
      throw TimestampErrors::InvalidTime();
    }

    // Set the julian date.
    TimeVal a   = ((TimeVal(14) - time.Month()) / TimeVal(12)).floor();
    TimeVal y   = time.Year() + TimeVal(time.Year().isPositive() ? 0 : 1) + TimeVal(4800) - a;
    cout << "y: " << y << endl;
    TimeVal m   = time.Month() + TimeVal(12) * a - TimeVal(3);
    TimeVal jdn = ((time.Year() >  _lastjulian.Year) || (
                   (time.Year() == _lastjulian.Year) && ((time.Month() >  _lastjulian.Month) || (
                                                         (time.Month() == _lastjulian.Month) && (time.Day() > _lastjulian.Day)
                                                        ))
                  )) ?
                    time.Day() + ((TimeVal(153) * m + TimeVal(2)) / TimeVal(5)).floor() + TimeVal(365) * y + (y / TimeVal(4)).floor() - (y / TimeVal(100)).floor() + (y / TimeVal(400)).floor() - TimeVal(32045)
                  :
                    time.Day() + ((TimeVal(153) * m + TimeVal(2)) / TimeVal(5)).floor() + TimeVal(365) * y + (y / TimeVal(4)).floor() - TimeVal(32083);
    newtime._jd = jdn + (time.Hour() - TimeVal(12)) / TimeVal(24) + time.Minute() / TimeVal(1440) + time.Second() / TimeVal(86400);

    // We done, return.
    _jd = newtime._jd;
    return *this;

  }

  // Get the current system time.
  Timestamp& Timestamp::getSystemTime () {

    // Verify that we are on a supported platform.
  #if !defined(PLAT_WIN32) && \
      !defined(PLAT_POSIX)
    throw TimestampErrors::UnknownPlatform();
  #endif

    // Verify that we have the necessary system support to get the system
    // time.
  #if   defined(PLAT_WIN32)
    #if !defined(HAS__SYSTEMTIME)
    throw TimestampErrors::MissingSysSupport();
    #endif
  #elif defined(PLAT_POSIX)
    #if (!defined(HAS_GMTIME_R) && !defined(HAS_GMTIME)) || \
        !defined(HAS_TIME_T) || !defined(HAS_TM)
    throw TimestampErrors::MissingSysSupport();
    #endif
    #if !defined(HAS_GETTIMEOFDAY) || !defined(HAS_TIMEVAL) || !defined(HAS_TIMEZONE)
      #define USE_TIME
      #if !defined(HAS_TIME)
    throw TimestampErrors::MissingSysSupport();
      #endif
    #endif
  #endif

    // Work area.
    Timestamp       newtime(*this);
    Interval        interval;
  #if   defined(PLAT_WIN32)
    _SYSTEMTIME     systime = { 0, 0, 0, 0, 0, 0, 0, 0 };
  #elif defined(PLAT_POSIX)
    #if !defined(USE_TIME)
    struct timezone tz      = { 0, 0 };
    struct timeval  tv      = { 0, 0 };
    #endif
    time_t          t       = 0;
    struct tm       systime = { 0, 0, 0, 0, 0, 0, 0, 0, 0 };
    struct tm*      stp     = &systime;
  #endif

    // Set the interval.
  #if   defined(PLAT_WIN32)
    GetSystemTime(&systime);
    interval.Millisecond(systime.wMilliseconds)
            .Second(systime.wSecond)
            .Minute(systime.wMinute)
            .Hour(systime.wHour)
            .Day(systime.wDay)
            .Month(systime.wMonth)
            .Year(systime.wYear);
  #elif defined(PLAT_POSIX)
    TimeVal ms;
    #if defined(USE_TIME)
    if (!time(&t)) {
      throw TimestampErrors::SysCallError();
    }
    #else
    if (gettimeofday(&tv, &tz)) {
      throw TimestampErrors::SysCallError();
    }
    t  = tv.tv_sec;
    ms = tv.tv_usec / 1000;
    #endif
    #if defined(HAS_GMTIME_R)
    if ((!gmtime_r(&t, &systime)) && (!(stp = gmtime(&t)))) {
      throw TimestampErrors::SysCallError();
    }
    #else
    if ((!stp = gmtime(&t))) {
      throw TimestampErrors::SysCallError();
    }
    #endif
    interval.Millisecond(ms)
            .Second(stp->tm_sec)
            .Minute(stp->tm_min)
            .Hour(stp->tm_hour)
            .Day(stp->tm_mday)
            .Month(TimeVal(1) + TimeVal(stp->tm_mon))
            .Year(TimeVal(1900) + TimeVal(stp->tm_year));
  #endif

    // Set the new time.
    newtime.set(interval);

    // We done, return.
    _jd = newtime._jd;
    return *this;

  }

  // Reset to just-constructed state.
  Timestamp& Timestamp::clear () {

    // Make a new jd.
    TimeVal tmp_jd;
    tmp_jd.PropCopy(false).Base(10).PointPos(5).Fixed(true);

    // Make a new lastjulian.
    YMD new_lastjulian(1582, 10, 4);
    _lastjulian = new_lastjulian;

    // Set the leap second list to the default.
    _leapseconds = s_defaultleapseconds;

    // Clear the jd.
    _jd = tmp_jd;

    // We done.
    return *this;

  }

  // Copy another timestamp.
  Timestamp& Timestamp::copy (Timestamp const& ts) {

    // Set the last julian date.
    _lastjulian = ts._lastjulian;

    // Set the leap second list.
    _leapseconds = ts._leapseconds;

    // Set the jd.
    _jd = ts._jd;

    // We done.
    return *this;

  }

  // Convert this timestamp to a string.
  string Timestamp::toString () const {

    // This is the string we will be returning.
    string retval;

    // We done, return the string.
    return retval;

  }

  // Common initialization tasks.
  void Timestamp::_init () {

    // Perform class initialization.
    if (!s_initialized) {
      s_classInit();
    }

    // Construct this object fully.
    clear();

  }

  // Return the leap seconds of a given day.
  Timestamp::I_Second Timestamp::_leapSecond (I_Year const& year, I_Month const& month, I_Day const& day) {

    // List should be very short, just iterate through it and determine if this is a leap second.
    for (LeapSecondList::iterator i = _leapseconds->begin(); i != _leapseconds->end(); ++i) {
      if ((i->Year == year) && (i->Month == month) && (i->Day == day)) {
        return i->Leap;
      }
    }

    // No leap second found.
    return I_Second(0);

  }

  // Class initialization.
  void Timestamp::s_classInit () {

    // Set the default leap seconds.
    s_defaultleapseconds = new LeapSecondList;
    s_defaultleapseconds->push_back(LeapSecondDay(YMD(1972,  6, 30), 1));
    s_defaultleapseconds->push_back(LeapSecondDay(YMD(1972, 12, 31), 1));
    s_defaultleapseconds->push_back(LeapSecondDay(YMD(1973, 12, 31), 1));
    s_defaultleapseconds->push_back(LeapSecondDay(YMD(1974, 12, 31), 1));
    s_defaultleapseconds->push_back(LeapSecondDay(YMD(1975, 12, 31), 1));
    s_defaultleapseconds->push_back(LeapSecondDay(YMD(1976, 12, 31), 1));
    s_defaultleapseconds->push_back(LeapSecondDay(YMD(1977, 12, 31), 1));
    s_defaultleapseconds->push_back(LeapSecondDay(YMD(1978, 12, 31), 1));
    s_defaultleapseconds->push_back(LeapSecondDay(YMD(1979, 12, 31), 1));
    s_defaultleapseconds->push_back(LeapSecondDay(YMD(1981,  6, 30), 1));
    s_defaultleapseconds->push_back(LeapSecondDay(YMD(1982,  6, 30), 1));
    s_defaultleapseconds->push_back(LeapSecondDay(YMD(1983,  6, 30), 1));
    s_defaultleapseconds->push_back(LeapSecondDay(YMD(1985,  6, 30), 1));
    s_defaultleapseconds->push_back(LeapSecondDay(YMD(1987, 12, 31), 1));
    s_defaultleapseconds->push_back(LeapSecondDay(YMD(1989, 12, 31), 1));
    s_defaultleapseconds->push_back(LeapSecondDay(YMD(1990, 12, 31), 1));
    s_defaultleapseconds->push_back(LeapSecondDay(YMD(1992,  6, 30), 1));
    s_defaultleapseconds->push_back(LeapSecondDay(YMD(1993,  6, 30), 1));
    s_defaultleapseconds->push_back(LeapSecondDay(YMD(1994,  6, 30), 1));
    s_defaultleapseconds->push_back(LeapSecondDay(YMD(1995, 12, 31), 1));
    s_defaultleapseconds->push_back(LeapSecondDay(YMD(1997,  6, 30), 1));
    s_defaultleapseconds->push_back(LeapSecondDay(YMD(1998, 12, 31), 1));

    // Class has been successfully initialized.
    s_initialized = true;

  }

};
<commit_msg>Added millisecond precision to the JD.<commit_after>/*****************************************************************************
 * Timestamp.cxx
 *****************************************************************************
 * Implementation for class Timestamp.
 *****************************************************************************/

// System includes.
#if defined(PLAT_WIN32)
  #if defined(HAS_WINDOWS_H)
    #include <windows.h>
  #endif
#elif defined(PLAT_POSIX)
  #if defined(HAS_SYS_TIME_H)
    #include <sys/time.h>
  #endif
  #if defined(HAS_TIME_H)
    #include <time.h>
  #endif
#endif

// Class include.
#include "Timestamp.hxx"

// Namespaces used.
using namespace std;

// Namespace wrapper.
namespace DAC {

  /***************************************************************************
   * Class Timestamp::I_Month.
   ***************************************************************************/

  /***************************************************************************/
  // Function members.

  // Get the number of days in this month.
  Timestamp::I_Day Timestamp::I_Month::daysInMonth (I_Year const& year) const {

    // Work area.
    Timestamp::I_Day days;

    // Easy.
    try {
      switch (Value<int>()) {

        case 1:
        case 3:
        case 5:
        case 7:
        case 8:
        case 10:
        case 12:
          days = 31;
        break;

        case 2:
          days = ((year % I_Year(4)) && (!(year % I_Year(100)) || (year % I_Year(400)))) ? 29 : 28;
        break;

        case 4:
        case 6:
        case 9:
        case 11:
          days = 30;
        break;

        default:
          days = 0;
        break;

      }
    } catch (ArbIntErrors::ScalarOverflow) {
      days = 0;
    }

    // We done.
    return days;

  }

  /***************************************************************************
   * Class Timestamp.
   ***************************************************************************/

  /***************************************************************************/
  // Static data members.

  // True when class has been initialized.
  bool Timestamp::s_initialized = false;

  // Default list of leap seconds.
  ReferencePointer<Timestamp::LeapSecondList> Timestamp::s_defaultleapseconds;

  /***************************************************************************/
  // Function members.

  // Default constructor.
  Timestamp::Timestamp () {

    // Call common init.
    _init();

  }

  // Copy constructor.
  Timestamp::Timestamp (Timestamp const& ts) {

    // Call common init.
    _init();

    // Set the timestamp.
    copy(ts);

  }

  // Set this timestamp.
  Timestamp& Timestamp::set (Interval const& time) {

    // Work area.
    Timestamp newtime(*this);

    // Verify that the new time is a valid time.
    if (!time.isSet_Second()      ||
        !time.isSet_Minute()      ||
        !time.isSet_Hour()        ||
        !time.isSet_Day()         ||
        !time.isSet_Month()       ||
        !time.isSet_Year()        ||
        !time.Year().isInteger()        || !time.Year()                      ||
        !time.Month().isInteger()       || (time.Month()       < TimeVal(1)) || (time.Month()       > TimeVal(12))                                                      ||
        !time.Day().isInteger()         || (time.Day()         < TimeVal(1)) || (time.Day()         > time.Month().daysInMonth(time.Year()))                            ||
        !time.Hour().isInteger()        || (time.Hour()        < TimeVal(0)) || (time.Hour()        > TimeVal(23))                                                      ||
        !time.Minute().isInteger()      || (time.Minute()      < TimeVal(0)) || (time.Minute()      > TimeVal(59))                                                      ||
        !time.Second().isInteger()      || (time.Second()      < TimeVal(0)) || (time.Second()      > TimeVal(59) + _leapSecond(time.Year(), time.Month(), time.Day())) ||
        !time.Millisecond().isInteger() || (time.Millisecond() < TimeVal(0)) || (time.Millisecond() > TimeVal(999))
    ) {
      throw TimestampErrors::InvalidTime();
    }

    // Set the julian date.
    TimeVal a   = ((TimeVal(14) - time.Month()) / TimeVal(12)).floor();
    TimeVal y   = time.Year() + TimeVal(time.Year().isPositive() ? 0 : 1) + TimeVal(4800) - a;
    TimeVal m   = time.Month() + TimeVal(12) * a - TimeVal(3);
    TimeVal jdn = ((time.Year() >  _lastjulian.Year) || (
                   (time.Year() == _lastjulian.Year) && ((time.Month() >  _lastjulian.Month) || (
                                                         (time.Month() == _lastjulian.Month) && (time.Day() > _lastjulian.Day)
                                                        ))
                  )) ?
                    time.Day() + ((TimeVal(153) * m + TimeVal(2)) / TimeVal(5)).floor() + TimeVal(365) * y + (y / TimeVal(4)).floor() - (y / TimeVal(100)).floor() + (y / TimeVal(400)).floor() - TimeVal(32045)
                  :
                    time.Day() + ((TimeVal(153) * m + TimeVal(2)) / TimeVal(5)).floor() + TimeVal(365) * y + (y / TimeVal(4)).floor() - TimeVal(32083);
    //newtime._jd = jdn + (time.Hour() - TimeVal(12)) / TimeVal(24) + time.Minute() / TimeVal(1440) + time.Second() / TimeVal(86400);
    newtime._jd = jdn + ((time.Hour() - TimeVal(12)) + (time.Minute() + (time.Second() + (time.Millisecond() / TimeVal(1000))) / TimeVal(60)) / TimeVal(60)) / TimeVal(24);

    // We done, return.
    _jd = newtime._jd;
    return *this;

  }

  // Get the current system time.
  Timestamp& Timestamp::getSystemTime () {

    // Verify that we are on a supported platform.
  #if !defined(PLAT_WIN32) && \
      !defined(PLAT_POSIX)
    throw TimestampErrors::UnknownPlatform();
  #endif

    // Verify that we have the necessary system support to get the system
    // time.
  #if   defined(PLAT_WIN32)
    #if !defined(HAS__SYSTEMTIME)
    throw TimestampErrors::MissingSysSupport();
    #endif
  #elif defined(PLAT_POSIX)
    #if (!defined(HAS_GMTIME_R) && !defined(HAS_GMTIME)) || \
        !defined(HAS_TIME_T) || !defined(HAS_TM)
    throw TimestampErrors::MissingSysSupport();
    #endif
    #if !defined(HAS_GETTIMEOFDAY) || !defined(HAS_TIMEVAL) || !defined(HAS_TIMEZONE)
      #define USE_TIME
      #if !defined(HAS_TIME)
    throw TimestampErrors::MissingSysSupport();
      #endif
    #endif
  #endif

    // Work area.
    Timestamp       newtime(*this);
    Interval        interval;
  #if   defined(PLAT_WIN32)
    _SYSTEMTIME     systime = { 0, 0, 0, 0, 0, 0, 0, 0 };
  #elif defined(PLAT_POSIX)
    #if !defined(USE_TIME)
    struct timezone tz      = { 0, 0 };
    struct timeval  tv      = { 0, 0 };
    #endif
    time_t          t       = 0;
    struct tm       systime = { 0, 0, 0, 0, 0, 0, 0, 0, 0 };
    struct tm*      stp     = &systime;
  #endif

    // Set the interval.
  #if   defined(PLAT_WIN32)
    GetSystemTime(&systime);
    interval.Millisecond(systime.wMilliseconds)
            .Second(systime.wSecond)
            .Minute(systime.wMinute)
            .Hour(systime.wHour)
            .Day(systime.wDay)
            .Month(systime.wMonth)
            .Year(systime.wYear);
  #elif defined(PLAT_POSIX)
    TimeVal ms;
    #if defined(USE_TIME)
    if (!time(&t)) {
      throw TimestampErrors::SysCallError();
    }
    #else
    if (gettimeofday(&tv, &tz)) {
      throw TimestampErrors::SysCallError();
    }
    t  = tv.tv_sec;
    ms = tv.tv_usec / 1000;
    #endif
    #if defined(HAS_GMTIME_R)
    if ((!gmtime_r(&t, &systime)) && (!(stp = gmtime(&t)))) {
      throw TimestampErrors::SysCallError();
    }
    #else
    if ((!stp = gmtime(&t))) {
      throw TimestampErrors::SysCallError();
    }
    #endif
    interval.Millisecond(ms)
            .Second(stp->tm_sec)
            .Minute(stp->tm_min)
            .Hour(stp->tm_hour)
            .Day(stp->tm_mday)
            .Month(TimeVal(1) + TimeVal(stp->tm_mon))
            .Year(TimeVal(1900) + TimeVal(stp->tm_year));
  #endif

    // Set the new time.
    newtime.set(interval);

    // We done, return.
    _jd = newtime._jd;
    return *this;

  }

  // Reset to just-constructed state.
  Timestamp& Timestamp::clear () {

    // Make a new jd.
    TimeVal tmp_jd;
    tmp_jd.PropCopy(false).Base(10).PointPos(8).Fixed(true);

    // Make a new lastjulian.
    YMD new_lastjulian(1582, 10, 4);
    _lastjulian = new_lastjulian;

    // Set the leap second list to the default.
    _leapseconds = s_defaultleapseconds;

    // Clear the jd.
    _jd = tmp_jd;

    // We done.
    return *this;

  }

  // Copy another timestamp.
  Timestamp& Timestamp::copy (Timestamp const& ts) {

    // Set the last julian date.
    _lastjulian = ts._lastjulian;

    // Set the leap second list.
    _leapseconds = ts._leapseconds;

    // Set the jd.
    _jd = ts._jd;

    // We done.
    return *this;

  }

  // Convert this timestamp to a string.
  string Timestamp::toString () const {

    // This is the string we will be returning.
    string retval;

    // We done, return the string.
    return retval;

  }

  // Common initialization tasks.
  void Timestamp::_init () {

    // Perform class initialization.
    if (!s_initialized) {
      s_classInit();
    }

    // Construct this object fully.
    clear();

  }

  // Return the leap seconds of a given day.
  Timestamp::I_Second Timestamp::_leapSecond (I_Year const& year, I_Month const& month, I_Day const& day) {

    // List should be very short, just iterate through it and determine if this is a leap second.
    for (LeapSecondList::iterator i = _leapseconds->begin(); i != _leapseconds->end(); ++i) {
      if ((i->Year == year) && (i->Month == month) && (i->Day == day)) {
        return i->Leap;
      }
    }

    // No leap second found.
    return I_Second(0);

  }

  // Class initialization.
  void Timestamp::s_classInit () {

    // Set the default leap seconds.
    s_defaultleapseconds = new LeapSecondList;
    s_defaultleapseconds->push_back(LeapSecondDay(YMD(1972,  6, 30), 1));
    s_defaultleapseconds->push_back(LeapSecondDay(YMD(1972, 12, 31), 1));
    s_defaultleapseconds->push_back(LeapSecondDay(YMD(1973, 12, 31), 1));
    s_defaultleapseconds->push_back(LeapSecondDay(YMD(1974, 12, 31), 1));
    s_defaultleapseconds->push_back(LeapSecondDay(YMD(1975, 12, 31), 1));
    s_defaultleapseconds->push_back(LeapSecondDay(YMD(1976, 12, 31), 1));
    s_defaultleapseconds->push_back(LeapSecondDay(YMD(1977, 12, 31), 1));
    s_defaultleapseconds->push_back(LeapSecondDay(YMD(1978, 12, 31), 1));
    s_defaultleapseconds->push_back(LeapSecondDay(YMD(1979, 12, 31), 1));
    s_defaultleapseconds->push_back(LeapSecondDay(YMD(1981,  6, 30), 1));
    s_defaultleapseconds->push_back(LeapSecondDay(YMD(1982,  6, 30), 1));
    s_defaultleapseconds->push_back(LeapSecondDay(YMD(1983,  6, 30), 1));
    s_defaultleapseconds->push_back(LeapSecondDay(YMD(1985,  6, 30), 1));
    s_defaultleapseconds->push_back(LeapSecondDay(YMD(1987, 12, 31), 1));
    s_defaultleapseconds->push_back(LeapSecondDay(YMD(1989, 12, 31), 1));
    s_defaultleapseconds->push_back(LeapSecondDay(YMD(1990, 12, 31), 1));
    s_defaultleapseconds->push_back(LeapSecondDay(YMD(1992,  6, 30), 1));
    s_defaultleapseconds->push_back(LeapSecondDay(YMD(1993,  6, 30), 1));
    s_defaultleapseconds->push_back(LeapSecondDay(YMD(1994,  6, 30), 1));
    s_defaultleapseconds->push_back(LeapSecondDay(YMD(1995, 12, 31), 1));
    s_defaultleapseconds->push_back(LeapSecondDay(YMD(1997,  6, 30), 1));
    s_defaultleapseconds->push_back(LeapSecondDay(YMD(1998, 12, 31), 1));

    // Class has been successfully initialized.
    s_initialized = true;

  }

};
<|endoftext|>