<commit_before>#include "kernel.h"
#include "raster.h"
#include "linerasterizer.h"
#include "pixeliterator.h"

using namespace Ilwis;

bool PixelIterator::isValid() const {
    return _isValid;
}

PixelIterator::PixelIterator() :
    _grid(0),
    _x(0),
    _y(0),
    _z(0),
    _localOffset(0),
    _currentBlock(0),
    _flow(fXYZ),
    _isValid(true),
    _endx(0),
    _endy(0),
    _endz(0),
    _linearposition(0),
    _endposition(0),
    _xChanged(false),
    _yChanged(false),
    _zChanged(false)
{

}

PixelIterator::PixelIterator(const IRasterCoverage &raster, const Box3D<>& box) :
    _raster(raster),
    _box(box),
    _localOffset(0),
    _currentBlock(0),
    _flow(fXYZ),
    _isValid(false)
{
    init();
}

PixelIterator::PixelIterator(PixelIterator&& iter) :
    _raster(std::move(iter._raster)),
    _grid(std::move(iter._grid)),
    _box(std::move(iter._box)),
    _x(iter._x),
    _y(iter._y),
    _z(iter._z),
    _localOffset(iter._localOffset),
    _currentBlock(iter._currentBlock),
    _flow(iter._flow),
    _isValid(iter._isValid),
    _endx(iter._endx),
    _endy(iter._endy),
    _endz(iter._endz),
    _linearposition(iter._linearposition),
    _endposition(iter._endposition),
    _xChanged(iter._xChanged),
    _yChanged(iter._yChanged),
    _zChanged(iter._zChanged)
{
//    _raster = IRasterCoverage();
//    _box = Box3D<>();
//    _localOffset = 0;
//    _currentBlock = 0;
//    _flow = fXYZ;
//    _isValid = false;
}

PixelIterator::PixelIterator(const PixelIterator& iter)  {
    copy(iter);
}

void PixelIterator::copy(const PixelIterator &iter) {
    _raster = iter._raster;
    if ( _raster.isValid()) // TODO beyond end marker(end()) dont have a valid raster, no problem just yet but it maybe needed in the future
        _grid = _raster->_grid.data();
    _box = iter._box;
    _isValid = iter._isValid;
    _flow = iter._flow;
    _x = iter._x;
    _y = iter._y;
    _z = iter._z;
    _endx = iter._endx;
    _endy = iter._endy;
    _endz = iter._endz;
    _linearposition = iter._linearposition;
    _endposition = iter._endposition;
    _localOffset = iter._localOffset;
    _currentBlock = iter._currentBlock;

}

void PixelIterator::init() {
    const Size& sz = _raster->size();
    if ( _box.isNull()) {
        _box = Box3D<>(sz);
    }
    _box.ensure(sz);

    _x = _box.min_corner().x();
    _y = _box.min_corner().y();
    _z = _box.min_corner().z();

    _endx = _box.max_corner().x();
    _endy = _box.max_corner().y();
    _endz = _box.max_corner().z();

    bool inside = contains(Pixel(_x,_y));
    if ( inside) {
        _grid = _raster->grid();
    }
    if ( _grid == 0) {
        _isValid = false;
        ERROR1(ERR_NO_INITIALIZED_1,_raster->name());
        return;
    }

    initPosition();
    _isValid = inside;
    _xChanged = _yChanged = _zChanged = false;
}

inline bool PixelIterator::moveXYZ(int delta) {
    _x += delta;
    _linearposition += delta;
    _localOffset += delta;
    _xChanged = true;
    _yChanged = _zChanged = false;

    if ( _x > _endx) {
        _xChanged = (_x - delta) %  _box.xlength() != 0;
        qint32 tempy = _y + (_x - _box.min_corner().x()) / _box.xlength();
        _x = _box.min_corner().x() + (_x - _box.min_corner().x()) % _box.xlength();
        _yChanged = tempy != _y;
        std::swap(_y,tempy);
        qint32 ylocal = _y % _grid->maxLines();
        quint32 localblock = _y /  _grid->maxLines();
        quint32 bandblocks = _grid->blocksPerBand() * _z;
        _localOffset = _x + ylocal * _grid->size().xsize();
        if ( bandblocks + localblock != _currentBlock) {
            _currentBlock = bandblocks + localblock;;
            _localOffset = _x;
        }
        if ( _y > _endy) {
            quint32 newz = _z + (_y - _box.min_corner().y()) / _box.ylength();
            _currentBlock = newz * _grid->blocksPerBand() + _y / _grid->maxLines();
            _zChanged = newz != _z;
            _z = newz;
            _y = _box.min_corner().y() + (_y - _box.min_corner().y()) % _box.ylength();
            _yChanged = _y != tempy;
            localblock = _y /  _grid->maxLines();
            _localOffset = _y * _grid->size().xsize() + _x - localblock * _grid->maxLines() * _grid->size().xsize();
            if ( _z > _endz) { // done with this iteration block
                _linearposition = _endposition;
                return false;
            }
        }
    }
    return true;
}

inline bool PixelIterator::isAtEnd() const {
    return _x == _box.max_corner().x() &&
           _y == _box.max_corner().y() &&
           _z == _box.max_corner().z();
}

Voxel PixelIterator::position() const
{
    return Voxel(_x, _y, _z);
}

const Box3D<> &PixelIterator::box() const
{
    return _box;
}

quint32 PixelIterator::linearPosition() const
{
   // return sz.xsize() * sz.ysize() * _z + sz.xsize() * _y + _x;
    return _linearposition;
}

bool PixelIterator::move(int n) {

    bool ok;
    if (isAtEnd()) {
        _linearposition = _endposition;
        return false;
    }
    if ( _flow == fXYZ) {
        ok = moveXYZ(n);
    }
    else if ( _flow == fYXZ){
    }

    return ok;
}

PixelIterator& PixelIterator::operator=(const PixelIterator& iter) {
    copy(iter);
    return *this;
}

PixelIterator& PixelIterator::operator=(const PixelIterator&& iter) {
    copy(iter);
    return *this;
}

inline PixelIterator PixelIterator::operator++(int) {
    PixelIterator temp(*this);
    if(!move(1))
        return end();
    return temp;
}
inline PixelIterator PixelIterator::operator--(int) {
    PixelIterator temp(*this);
    move(-1);
    return temp;
}

bool PixelIterator::operator==(const PixelIterator& iter) const{
    return _linearposition == iter._linearposition;
}

bool PixelIterator::operator!=(const PixelIterator& iter) const{
    return ! operator ==(iter);
}

bool PixelIterator::operator<(const PixelIterator &iter) const
{
    return _linearposition < iter._linearposition;
}

bool PixelIterator::operator>(const PixelIterator &iter) const
{
    return _linearposition > iter._linearposition;
}

bool PixelIterator::operator<=(const PixelIterator &iter) const
{
    return _linearposition <= iter._linearposition;
}

bool PixelIterator::operator>=(const PixelIterator &iter) const
{
    return _linearposition >= iter._linearposition;
}

PixelIterator PixelIterator::end() const {
    PixelIterator iter(*this);
    iter += _endposition;
    return iter;
}

void PixelIterator::setFlow(Flow flw) {
    _flow = flw;
}

bool PixelIterator::contains(const Pixel& pix) {
    return pix.x() >= _box.min_corner().x() &&
            pix.x() < _box.max_corner().x()  &&
            pix.y() >= _box.min_corner().y() &&
            pix.y() < _box.max_corner().y();

}

bool PixelIterator::xchanged() const {
    return _xChanged;
}

bool PixelIterator::ychanged() const {
    return _yChanged;
}

bool PixelIterator::zchanged() const {
    return _zChanged;
}

void PixelIterator::initPosition() {
    const Size& sz = _raster->size();
    quint64 linpos = _y * sz.xsize() + _x;
    _currentBlock = _y / _grid->maxLines();
    _localOffset = linpos - _currentBlock * _grid->maxLines() * sz.xsize();
    _currentBlock += _z * _grid->blocksPerBand();
    _linearposition = sz.xsize() * sz.ysize() * _z + linpos;
    _endposition = sz.xsize() * sz.ysize() * sz.zsize();

}

int PixelIterator:: operator-(const PixelIterator& iter) {
    return linearPosition() - iter.linearPosition();
}

<commit_msg>added initialization<commit_after>#include "kernel.h"
#include "raster.h"
#include "linerasterizer.h"
#include "pixeliterator.h"

using namespace Ilwis;

bool PixelIterator::isValid() const {
    return _isValid;
}

PixelIterator::PixelIterator() :
    _grid(0),
    _x(0),
    _y(0),
    _z(0),
    _localOffset(0),
    _currentBlock(0),
    _flow(fXYZ),
    _isValid(true),
    _endx(0),
    _endy(0),
    _endz(0),
    _linearposition(0),
    _endposition(0),
    _xChanged(false),
    _yChanged(false),
    _zChanged(false)
{

}

PixelIterator::PixelIterator(const IRasterCoverage &raster, const Box3D<>& box) :
    _raster(raster),
    _box(box),
    _localOffset(0),
    _currentBlock(0),
    _flow(fXYZ),
    _isValid(false)
{
    init();
}

PixelIterator::PixelIterator(PixelIterator&& iter) :
    _raster(std::move(iter._raster)),
    _grid(std::move(iter._grid)),
    _box(std::move(iter._box)),
    _x(iter._x),
    _y(iter._y),
    _z(iter._z),
    _localOffset(iter._localOffset),
    _currentBlock(iter._currentBlock),
    _flow(iter._flow),
    _isValid(iter._isValid),
    _endx(iter._endx),
    _endy(iter._endy),
    _endz(iter._endz),
    _linearposition(iter._linearposition),
    _endposition(iter._endposition),
    _xChanged(iter._xChanged),
    _yChanged(iter._yChanged),
    _zChanged(iter._zChanged)
{
//    _raster = IRasterCoverage();
//    _box = Box3D<>();
//    _localOffset = 0;
//    _currentBlock = 0;
//    _flow = fXYZ;
//    _isValid = false;
}

PixelIterator::PixelIterator(const PixelIterator& iter)  {
    copy(iter);
}

void PixelIterator::copy(const PixelIterator &iter) {
    _raster = iter._raster;
    if ( _raster.isValid()) // TODO beyond end marker(end()) dont have a valid raster, no problem just yet but it maybe needed in the future
        _grid = _raster->_grid.data();
    _box = iter._box;
    _isValid = iter._isValid;
    _flow = iter._flow;
    _x = iter._x;
    _y = iter._y;
    _z = iter._z;
    _endx = iter._endx;
    _endy = iter._endy;
    _endz = iter._endz;
    _linearposition = iter._linearposition;
    _endposition = iter._endposition;
    _localOffset = iter._localOffset;
    _currentBlock = iter._currentBlock;

}

void PixelIterator::init() {
    const Size& sz = _raster->size();
    if ( _box.isNull()) {
        _box = Box3D<>(sz);
    }
    _box.ensure(sz);

    _x = _box.min_corner().x();
    _y = _box.min_corner().y();
    _z = _box.min_corner().z();

    _endx = _box.max_corner().x();
    _endy = _box.max_corner().y();
    _endz = _box.max_corner().z();

    bool inside = contains(Pixel(_x,_y));
    if ( inside) {
        _grid = _raster->grid();
    }
    if ( _grid == 0) {
        _isValid = false;
        ERROR1(ERR_NO_INITIALIZED_1,_raster->name());
        return;
    }

    initPosition();
    _isValid = inside;
    _xChanged = _yChanged = _zChanged = false;
}

inline bool PixelIterator::moveXYZ(int delta) {
    _x += delta;
    _linearposition += delta;
    _localOffset += delta;
    _xChanged = true;
    _yChanged = _zChanged = false;

    if ( _x > _endx) {
        _xChanged = (_x - delta) %  _box.xlength() != 0;
        qint32 tempy = _y + (_x - _box.min_corner().x()) / _box.xlength();
        _x = _box.min_corner().x() + (_x - _box.min_corner().x()) % _box.xlength();
        _yChanged = tempy != _y;
        std::swap(_y,tempy);
        qint32 ylocal = _y % _grid->maxLines();
        quint32 localblock = _y /  _grid->maxLines();
        quint32 bandblocks = _grid->blocksPerBand() * _z;
        _localOffset = _x + ylocal * _grid->size().xsize();
        if ( bandblocks + localblock != _currentBlock) {
            _currentBlock = bandblocks + localblock;;
            _localOffset = _x;
        }
        if ( _y > _endy) {
            quint32 newz = _z + (_y - _box.min_corner().y()) / _box.ylength();
            _currentBlock = newz * _grid->blocksPerBand() + _y / _grid->maxLines();
            _zChanged = newz != _z;
            _z = newz;
            _y = _box.min_corner().y() + (_y - _box.min_corner().y()) % _box.ylength();
            _yChanged = _y != tempy;
            localblock = _y /  _grid->maxLines();
            _localOffset = _y * _grid->size().xsize() + _x - localblock * _grid->maxLines() * _grid->size().xsize();
            if ( _z > _endz) { // done with this iteration block
                _linearposition = _endposition;
                return false;
            }
        }
    }
    return true;
}

inline bool PixelIterator::isAtEnd() const {
    return _x == _box.max_corner().x() &&
           _y == _box.max_corner().y() &&
           _z == _box.max_corner().z();
}

Voxel PixelIterator::position() const
{
    return Voxel(_x, _y, _z);
}

const Box3D<> &PixelIterator::box() const
{
    return _box;
}

quint32 PixelIterator::linearPosition() const
{
   // return sz.xsize() * sz.ysize() * _z + sz.xsize() * _y + _x;
    return _linearposition;
}

bool PixelIterator::move(int n) {

    bool ok = false;
    if (isAtEnd()) {
        _linearposition = _endposition;
        return false;
    }
    if ( _flow == fXYZ) {
        ok = moveXYZ(n);
    }
    else if ( _flow == fYXZ){
    }

    return ok;
}

PixelIterator& PixelIterator::operator=(const PixelIterator& iter) {
    copy(iter);
    return *this;
}

PixelIterator& PixelIterator::operator=(const PixelIterator&& iter) {
    copy(iter);
    return *this;
}

inline PixelIterator PixelIterator::operator++(int) {
    PixelIterator temp(*this);
    if(!move(1))
        return end();
    return temp;
}
inline PixelIterator PixelIterator::operator--(int) {
    PixelIterator temp(*this);
    move(-1);
    return temp;
}

bool PixelIterator::operator==(const PixelIterator& iter) const{
    return _linearposition == iter._linearposition;
}

bool PixelIterator::operator!=(const PixelIterator& iter) const{
    return ! operator ==(iter);
}

bool PixelIterator::operator<(const PixelIterator &iter) const
{
    return _linearposition < iter._linearposition;
}

bool PixelIterator::operator>(const PixelIterator &iter) const
{
    return _linearposition > iter._linearposition;
}

bool PixelIterator::operator<=(const PixelIterator &iter) const
{
    return _linearposition <= iter._linearposition;
}

bool PixelIterator::operator>=(const PixelIterator &iter) const
{
    return _linearposition >= iter._linearposition;
}

PixelIterator PixelIterator::end() const {
    PixelIterator iter(*this);
    iter += _endposition;
    return iter;
}

void PixelIterator::setFlow(Flow flw) {
    _flow = flw;
}

bool PixelIterator::contains(const Pixel& pix) {
    return pix.x() >= _box.min_corner().x() &&
            pix.x() < _box.max_corner().x()  &&
            pix.y() >= _box.min_corner().y() &&
            pix.y() < _box.max_corner().y();

}

bool PixelIterator::xchanged() const {
    return _xChanged;
}

bool PixelIterator::ychanged() const {
    return _yChanged;
}

bool PixelIterator::zchanged() const {
    return _zChanged;
}

void PixelIterator::initPosition() {
    const Size& sz = _raster->size();
    quint64 linpos = _y * sz.xsize() + _x;
    _currentBlock = _y / _grid->maxLines();
    _localOffset = linpos - _currentBlock * _grid->maxLines() * sz.xsize();
    _currentBlock += _z * _grid->blocksPerBand();
    _linearposition = sz.xsize() * sz.ysize() * _z + linpos;
    _endposition = sz.xsize() * sz.ysize() * sz.zsize();

}

int PixelIterator:: operator-(const PixelIterator& iter) {
    return linearPosition() - iter.linearPosition();
}

<|endoftext|>


<commit_before>// Copyright (c) 2016 ASMlover. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
//  * Redistributions of source code must retain the above copyright
//    notice, this list ofconditions and the following disclaimer.
//
//  * Redistributions in binary form must reproduce the above copyright
//    notice, this list of conditions and the following disclaimer in
//    the documentation and/or other materialsprovided with the
//    distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
// COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
#include <sys/syscall.h>
#include <unistd.h>
#include "../TPlatform.h"

namespace tyr { namespace basic {

pid_t kern_getpid(void) {
  return getpid();
}

int kern_mutex_init(KernMutex* mtx) {
  return pthread_mutex_init(mtx, nullptr);
}

int kern_mutex_destroy(KernMutex* mtx) {
  return pthread_mutex_destroy(mtx);
}

int kern_mutex_lock(KernMutex* mtx) {
  return pthread_mutex_lock(mtx);
}

int kern_mutex_unlock(KernMutex* mtx) {
  return pthread_mutex_unlock(mtx);
}

int kern_cond_init(KernCond* cond) {
  return pthread_cond_init(cond, nullptr);
}

int kern_cond_destroy(KernCond* cond) {
  return pthread_cond_destroy(cond);
}

int kern_cond_signal(KernCond* cond) {
  return pthread_cond_signal(cond);
}

int kern_cond_broadcast(KernCond* cond) {
  return pthread_cond_broadcast(cond);
}

int kern_cond_wait(KernCond* cond, KernMutex* mtx) {
  return pthread_cond_wait(cond, mtx);
}

int kern_cond_timedwait(KernCond* cond, KernMutex* mtx, uint64_t nanosec) {
  struct timespec ts;
  kern_gettime(&ts);
  ts.tv_sec += nanosec / NANOSEC;
  ts.tv_nsec = nanosec % NANOSEC;
  return pthread_cond_timedwait(cond, mtx, &ts);
}

int kern_thread_create(KernThread* thread, void* (*start_routine)(void*), void* arg) {
  return pthread_create(thread, nullptr, start_routine, arg);
}

int kern_thread_join(KernThread thread) {
  return pthread_join(thread, nullptr);
}

int kern_thread_detach(KernThread thread) {
  return pthread_detach(thread);
}

int kern_thread_atfork(void (*prepare)(void), void (*parent)(void), void (*child)(void)) {
  return pthread_atfork(prepare, parent, child);
}

int kern_thread_atfork(void (*prepare)(void), void (*parent)(void), void (*child)(void)) {
  return 0;
}

int kern_threadkey_create(KernThreadKey* key, void (*destructor)(void*)) {
  return pthread_key_create(key, destructor);
}

int kern_threadkey_delete(KernThreadKey key) {
  return pthread_key_delete(key);
}

int kern_setspecific(KernThreadKey key, const void* value) {
  return pthread_setspecific(key, value);
}

void* kern_getspecific(KernThreadKey key) {
  return pthread_getspecific(key);
}

}}
<commit_msg>fix(platform): fixed bug of *_atfork  for posix<commit_after>// Copyright (c) 2016 ASMlover. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
//  * Redistributions of source code must retain the above copyright
//    notice, this list ofconditions and the following disclaimer.
//
//  * Redistributions in binary form must reproduce the above copyright
//    notice, this list of conditions and the following disclaimer in
//    the documentation and/or other materialsprovided with the
//    distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
// COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
#include <sys/syscall.h>
#include <unistd.h>
#include "../TPlatform.h"

namespace tyr { namespace basic {

pid_t kern_getpid(void) {
  return getpid();
}

int kern_mutex_init(KernMutex* mtx) {
  return pthread_mutex_init(mtx, nullptr);
}

int kern_mutex_destroy(KernMutex* mtx) {
  return pthread_mutex_destroy(mtx);
}

int kern_mutex_lock(KernMutex* mtx) {
  return pthread_mutex_lock(mtx);
}

int kern_mutex_unlock(KernMutex* mtx) {
  return pthread_mutex_unlock(mtx);
}

int kern_cond_init(KernCond* cond) {
  return pthread_cond_init(cond, nullptr);
}

int kern_cond_destroy(KernCond* cond) {
  return pthread_cond_destroy(cond);
}

int kern_cond_signal(KernCond* cond) {
  return pthread_cond_signal(cond);
}

int kern_cond_broadcast(KernCond* cond) {
  return pthread_cond_broadcast(cond);
}

int kern_cond_wait(KernCond* cond, KernMutex* mtx) {
  return pthread_cond_wait(cond, mtx);
}

int kern_cond_timedwait(KernCond* cond, KernMutex* mtx, uint64_t nanosec) {
  struct timespec ts;
  kern_gettime(&ts);
  ts.tv_sec += nanosec / NANOSEC;
  ts.tv_nsec = nanosec % NANOSEC;
  return pthread_cond_timedwait(cond, mtx, &ts);
}

int kern_thread_create(KernThread* thread, void* (*start_routine)(void*), void* arg) {
  return pthread_create(thread, nullptr, start_routine, arg);
}

int kern_thread_join(KernThread thread) {
  return pthread_join(thread, nullptr);
}

int kern_thread_detach(KernThread thread) {
  return pthread_detach(thread);
}

int kern_thread_atfork(void (*prepare)(void), void (*parent)(void), void (*child)(void)) {
  return pthread_atfork(prepare, parent, child);
}

int kern_threadkey_create(KernThreadKey* key, void (*destructor)(void*)) {
  return pthread_key_create(key, destructor);
}

int kern_threadkey_delete(KernThreadKey key) {
  return pthread_key_delete(key);
}

int kern_setspecific(KernThreadKey key, const void* value) {
  return pthread_setspecific(key, value);
}

void* kern_getspecific(KernThreadKey key) {
  return pthread_getspecific(key);
}

}}
<|endoftext|>


<commit_before><commit_msg>308. Range Sum Query 2D - Mutable<commit_after><|endoftext|>


<commit_before>/*
   Copyright (C) 2013 Andreas Hartmetz <ahartmetz@gmail.com>

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

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

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

   Alternatively, this file is available under the Mozilla Public License
   Version 1.1.  You may obtain a copy of the License at
   http://www.mozilla.org/MPL/
*/

#include "localsocket.h"

#include <errno.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include "sys/uio.h"
#include <sys/un.h>
#include <unistd.h>

#include <cassert>
#include <climits>
#include <cstdlib>
#include <cstring>

// HACK, put this somewhere else (get the value from original d-bus? or is it infinite?)
static const int maxFds = 12;

using namespace std;

LocalSocket::LocalSocket(const string &socketFilePath)
   : m_fd(-1)
{
    const int fd = socket(PF_UNIX, SOCK_STREAM, 0);
    if (fd < 0) {
        return;
    }
    // don't let forks inherit the file descriptor - that can cause confusion...
    fcntl(fd, F_SETFD, FD_CLOEXEC);

    struct sockaddr_un addr;
    addr.sun_family = PF_UNIX;
    bool ok = socketFilePath.length() < sizeof(addr.sun_path);
    if (ok) {
        memcpy(addr.sun_path, socketFilePath.c_str(), socketFilePath.length());
    }

    ok = ok && (connect(fd, (struct sockaddr *)&addr, sizeof(sa_family_t) + socketFilePath.length()) == 0);

    if (ok) {
        m_fd = fd;
    } else {
        ::close(fd);
    }
}

LocalSocket::LocalSocket(int fd)
   : m_fd(fd)
{
}

LocalSocket::~LocalSocket()
{
    close();
}

void LocalSocket::close()
{
    setEventDispatcher(nullptr);
    if (m_fd >= 0) {
        ::close(m_fd);
    }
    m_fd = -1;
}

int LocalSocket::write(chunk a)
{
    if (m_fd < 0) {
        return 0; // TODO -1?
    }

    // sendmsg  boilerplate
    struct msghdr send_msg;
    struct iovec iov;

    send_msg.msg_name = 0;
    send_msg.msg_namelen = 0;
    send_msg.msg_flags = 0;
    send_msg.msg_iov = &iov;
    send_msg.msg_iovlen = 1;

    iov.iov_base = a.ptr;
    iov.iov_len = a.length;

    // we can only send a fixed number of fds anyway due to the non-flexible size of the control message
    // receive buffer, so we set an arbitrary limit.
    const int numFds = 0; // TODO - how many should we get? do we need to know?
    assert(numFds <= maxFds);

    char cmsgBuf[CMSG_SPACE(sizeof(int) * maxFds)];

    if (numFds) {
        // fill in a control message
        send_msg.msg_control = cmsgBuf;
        send_msg.msg_controllen = CMSG_SPACE(sizeof(int) * numFds);

        struct cmsghdr *c_msg = CMSG_FIRSTHDR(&send_msg);
        c_msg->cmsg_len = CMSG_LEN(sizeof(int) * numFds);
        c_msg->cmsg_level = SOL_SOCKET;
        c_msg->cmsg_type = SCM_RIGHTS;

        // set the control data to pass - this is why we don't use the simpler write()
        for (int i = 0; i < numFds; i++) {
            // TODO
            // reinterpret_cast<int *>(CMSG_DATA(c_msg))[i] = message.m_fileDescriptors[i];
        }
    } else {
        // no file descriptor to send, no control message
        send_msg.msg_control = 0;
        send_msg.msg_controllen = 0;
    }

    while (iov.iov_len > 0) {
        int nbytes = sendmsg(m_fd, &send_msg, MSG_DONTWAIT);
        if (nbytes < 0) {
            if (errno == EINTR) {
                continue;
            }
            // if we were notified for writing, we must have written at least one byte before getting
            // EAGAIN aka EWOULDBLOCK
            if (errno == EAGAIN && iov.iov_len < a.length) {
                break;
            }
            close();
            return false;
        }

        iov.iov_base = static_cast<char *>(iov.iov_base) + nbytes;
        iov.iov_len -= nbytes;
        // sendmsg() should always send the number of bytes asked for or block, so...
        if (nbytes != 0) {
            assert(iov.iov_len == 0);
        }
    }

    return a.length - iov.iov_len; // "- iov.iov_len" is for later, TODO revisit
}

int LocalSocket::availableBytesForReading()
{
    int available = 0;
    if (ioctl(m_fd, FIONREAD, &available) < 0) {
        available = 0;
    }
    return available;
}

chunk LocalSocket::read(byte *buffer, int maxSize)
{
    chunk ret;
    if (maxSize <= 0) {
        return ret;
    }

    // recvmsg-with-control-message boilerplate
    struct msghdr recv_msg;
    char cmsgBuf[CMSG_SPACE(sizeof(int) * maxFds)];
    memset(cmsgBuf, 0, sizeof(cmsgBuf));

    recv_msg.msg_control = cmsgBuf;
    recv_msg.msg_controllen = sizeof(cmsgBuf);
    recv_msg.msg_name = 0;
    recv_msg.msg_namelen = 0;
    recv_msg.msg_flags = 0;

    struct iovec iov;
    recv_msg.msg_iov = &iov;
    recv_msg.msg_iovlen = 1;

    // end boilerplate

    ret.ptr = buffer;
    ret.length = 0;
    iov.iov_base = ret.ptr;
    iov.iov_len = maxSize;
    while (iov.iov_len > 0) {
        int nbytes = recvmsg(m_fd, &recv_msg, MSG_DONTWAIT);
        if (nbytes < 0) {
            if (errno == EINTR) {
                continue;
            }
            // If we were notified for reading directly by the event dispatcher, we must be able to read at
            // least one byte before getting AGAIN aka EWOULDBLOCK - *however* the event loop might notify
            // something that is very eager to read everything (like Message::notifyRead()...) by reading
            // multiple times and in that case, we may be called in an attempt to read more when there is
            // currently no more data.
            // Just return zero bytes and no error in that case.
            if (errno == EAGAIN /* && iov.iov_len < maxSize */) {
                break;
            }
            close();
            return ret;
        }
        ret.length += nbytes;
        iov.iov_base = static_cast<char *>(iov.iov_base) + nbytes;
        iov.iov_len -= nbytes;
    }

    // done reading "regular data", now read any file descriptors passed via control messages

    struct cmsghdr *c_msg = CMSG_FIRSTHDR(&recv_msg);
    if (c_msg && c_msg->cmsg_level == SOL_SOCKET && c_msg->cmsg_type == SCM_RIGHTS) {
        const int len = c_msg->cmsg_len / sizeof(int);
        int *data = reinterpret_cast<int *>(CMSG_DATA(c_msg));
        for (int i = 0; i < len; i++) {
            // TODO
            // message.appendFileDescriptor(data[i]);
        }
    }

    return ret;
}

bool LocalSocket::isOpen()
{
    return m_fd != -1;
}

int LocalSocket::fileDescriptor() const
{
    return m_fd;
}

void LocalSocket::notifyRead()
{
    if (availableBytesForReading()) {
        IConnection::notifyRead();
    } else {
        // This should really only happen in error cases! ### TODO test?
        close();
    }
}
<commit_msg>LocalSocket write: don't fail on short writes.<commit_after>/*
   Copyright (C) 2013 Andreas Hartmetz <ahartmetz@gmail.com>

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

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

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

   Alternatively, this file is available under the Mozilla Public License
   Version 1.1.  You may obtain a copy of the License at
   http://www.mozilla.org/MPL/
*/

#include "localsocket.h"

#include <errno.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include "sys/uio.h"
#include <sys/un.h>
#include <unistd.h>

#include <cassert>
#include <climits>
#include <cstdlib>
#include <cstring>

// HACK, put this somewhere else (get the value from original d-bus? or is it infinite?)
static const int maxFds = 12;

using namespace std;

LocalSocket::LocalSocket(const string &socketFilePath)
   : m_fd(-1)
{
    const int fd = socket(PF_UNIX, SOCK_STREAM, 0);
    if (fd < 0) {
        return;
    }
    // don't let forks inherit the file descriptor - that can cause confusion...
    fcntl(fd, F_SETFD, FD_CLOEXEC);

    struct sockaddr_un addr;
    addr.sun_family = PF_UNIX;
    bool ok = socketFilePath.length() < sizeof(addr.sun_path);
    if (ok) {
        memcpy(addr.sun_path, socketFilePath.c_str(), socketFilePath.length());
    }

    ok = ok && (connect(fd, (struct sockaddr *)&addr, sizeof(sa_family_t) + socketFilePath.length()) == 0);

    if (ok) {
        m_fd = fd;
    } else {
        ::close(fd);
    }
}

LocalSocket::LocalSocket(int fd)
   : m_fd(fd)
{
}

LocalSocket::~LocalSocket()
{
    close();
}

void LocalSocket::close()
{
    setEventDispatcher(nullptr);
    if (m_fd >= 0) {
        ::close(m_fd);
    }
    m_fd = -1;
}

int LocalSocket::write(chunk a)
{
    if (m_fd < 0) {
        return 0; // TODO -1?
    }

    // sendmsg  boilerplate
    struct msghdr send_msg;
    struct iovec iov;

    send_msg.msg_name = 0;
    send_msg.msg_namelen = 0;
    send_msg.msg_flags = 0;
    send_msg.msg_iov = &iov;
    send_msg.msg_iovlen = 1;

    iov.iov_base = a.ptr;
    iov.iov_len = a.length;

    // we can only send a fixed number of fds anyway due to the non-flexible size of the control message
    // receive buffer, so we set an arbitrary limit.
    const int numFds = 0; // TODO - how many should we get? do we need to know?
    assert(numFds <= maxFds);

    char cmsgBuf[CMSG_SPACE(sizeof(int) * maxFds)];

    if (numFds) {
        // fill in a control message
        send_msg.msg_control = cmsgBuf;
        send_msg.msg_controllen = CMSG_SPACE(sizeof(int) * numFds);

        struct cmsghdr *c_msg = CMSG_FIRSTHDR(&send_msg);
        c_msg->cmsg_len = CMSG_LEN(sizeof(int) * numFds);
        c_msg->cmsg_level = SOL_SOCKET;
        c_msg->cmsg_type = SCM_RIGHTS;

        // set the control data to pass - this is why we don't use the simpler write()
        for (int i = 0; i < numFds; i++) {
            // TODO
            // reinterpret_cast<int *>(CMSG_DATA(c_msg))[i] = message.m_fileDescriptors[i];
        }
    } else {
        // no file descriptor to send, no control message
        send_msg.msg_control = 0;
        send_msg.msg_controllen = 0;
    }

    while (iov.iov_len > 0) {
        int nbytes = sendmsg(m_fd, &send_msg, MSG_DONTWAIT);
        if (nbytes < 0) {
            if (errno == EINTR) {
                continue;
            }
            // if we were notified for writing, we must have written at least one byte before getting
            // EAGAIN aka EWOULDBLOCK
            if (errno == EAGAIN && iov.iov_len < a.length) {
                break;
            }
            close();
            return false;
        }

        iov.iov_base = static_cast<char *>(iov.iov_base) + nbytes;
        iov.iov_len -= nbytes;
    }

    return a.length - iov.iov_len;
}

int LocalSocket::availableBytesForReading()
{
    int available = 0;
    if (ioctl(m_fd, FIONREAD, &available) < 0) {
        available = 0;
    }
    return available;
}

chunk LocalSocket::read(byte *buffer, int maxSize)
{
    chunk ret;
    if (maxSize <= 0) {
        return ret;
    }

    // recvmsg-with-control-message boilerplate
    struct msghdr recv_msg;
    char cmsgBuf[CMSG_SPACE(sizeof(int) * maxFds)];
    memset(cmsgBuf, 0, sizeof(cmsgBuf));

    recv_msg.msg_control = cmsgBuf;
    recv_msg.msg_controllen = sizeof(cmsgBuf);
    recv_msg.msg_name = 0;
    recv_msg.msg_namelen = 0;
    recv_msg.msg_flags = 0;

    struct iovec iov;
    recv_msg.msg_iov = &iov;
    recv_msg.msg_iovlen = 1;

    // end boilerplate

    ret.ptr = buffer;
    ret.length = 0;
    iov.iov_base = ret.ptr;
    iov.iov_len = maxSize;
    while (iov.iov_len > 0) {
        int nbytes = recvmsg(m_fd, &recv_msg, MSG_DONTWAIT);
        if (nbytes < 0) {
            if (errno == EINTR) {
                continue;
            }
            // If we were notified for reading directly by the event dispatcher, we must be able to read at
            // least one byte before getting AGAIN aka EWOULDBLOCK - *however* the event loop might notify
            // something that is very eager to read everything (like Message::notifyRead()...) by reading
            // multiple times and in that case, we may be called in an attempt to read more when there is
            // currently no more data.
            // Just return zero bytes and no error in that case.
            if (errno == EAGAIN /* && iov.iov_len < maxSize */) {
                break;
            }
            close();
            return ret;
        }
        ret.length += nbytes;
        iov.iov_base = static_cast<char *>(iov.iov_base) + nbytes;
        iov.iov_len -= nbytes;
    }

    // done reading "regular data", now read any file descriptors passed via control messages

    struct cmsghdr *c_msg = CMSG_FIRSTHDR(&recv_msg);
    if (c_msg && c_msg->cmsg_level == SOL_SOCKET && c_msg->cmsg_type == SCM_RIGHTS) {
        const int len = c_msg->cmsg_len / sizeof(int);
        int *data = reinterpret_cast<int *>(CMSG_DATA(c_msg));
        for (int i = 0; i < len; i++) {
            // TODO
            // message.appendFileDescriptor(data[i]);
        }
    }

    return ret;
}

bool LocalSocket::isOpen()
{
    return m_fd != -1;
}

int LocalSocket::fileDescriptor() const
{
    return m_fd;
}

void LocalSocket::notifyRead()
{
    if (availableBytesForReading()) {
        IConnection::notifyRead();
    } else {
        // This should really only happen in error cases! ### TODO test?
        close();
    }
}
<|endoftext|>


<commit_before>/**
 *  @file
 *  @copyright defined in eos/LICENSE.txt
 */
#pragma once
#include <eoslib/print.h>
#include <eoslib/types.hpp>
#include <eoslib/math.hpp>

namespace eosio {

   static_assert( sizeof(long) == sizeof(int), "unexpected size difference" );

   /**
    *  Prints string
    *  @brief Prints string
    *  @param cstr - a null terminated string
    */
   inline void print( const char* ptr ) {
      prints(ptr);
   }

   /**
    * Prints 64 bit unsigned integer as a 64 bit unsigned integer
    * @brief Prints integer 64 bit unsigned integer
    * @param Value to be printed
    */
   inline void print( uint64_t num ) {
      printi(num);
   }

   /**
    * Prints 32 bit unsigned integer as a 64 bit unsigned integer
    * @brief Prints integer  32 bit unsigned integer
    * @param Value to be printed
    */
   inline void print( uint32_t num ) {
      printi(num);
   }

   /**
    * Prints integer as a 64 bit unsigned integer
    * @brief Prints integer
    * @param Value to be printed
    */
   inline void print( int num ) {
      printi(num);
   }

   /**
    * Prints unsigned integer as a 64 bit unsigned integer
    * @brief Prints unsigned integer
    * @param Value to be printed
    */
   inline void print( unsigned int num ) {
      printi(num);
   }

   /**
    * Prints uint128 struct as 128 bit unsigned integer
    * @brief Prints uint128 struct
    * @param Value to be printed
    */
   inline void print( uint128 num ) {
      printi128((uint128_t*)&num);
   }

   /**
    * Prints 128 bit unsigned integer
    * @brief Prints 128 bit unsigned integer
    * @param Value to be printed
    */
   inline void print( uint128_t num ) {
      printi128((uint128_t*)&num);
   }

   /**
    * Prints a 64 bit names as base32 encoded string
    * @brief Prints a 64 bit names as base32 encoded string
    * @param Value of 64 bit names to be printed
    */
   inline void print( name name ) {
      printn(name.value);
   }

   inline void print( bool val ) {
      prints(val?"true":"false");
   }

   template<typename T>
   inline void print( T&& t ) {
      t.print();
   }

   /**
    *  @defgroup consoleCppapi Console C++ API
    *  @ingroup consoleapi
    *  @brief C++ wrapper for Console C API
    *
    *  This API uses C++ variadic templates and type detection to
    *  make it easy to print any native type. You can even overload
    *  the `print()` method for your own custom types.
    *
    *  **Example:**
    *  ```
    *     print( "hello world, this is a number: ", 5 );
    *  ```
    *
    *  @section override Overriding Print for your Types
    *
    *  There are two ways to overload print:
    *  1. implement void print( const T& )
    *  2. implement T::print()const
    *
    *  @{
    */

    /**
     *  Print out value / list of values (except double)
     *  @brief Print out value  / list of values
     *  @param a    Value to be printed
     *  @param args Other values to be printed
     *
     *  Example:
     *  @code
     *  char *s = "Hello World!";
     *  uint64_t unsigned_64_bit_int = 1e+18;
     *  uint128_t unsigned_128_bit_int (87654323456);
     *  uint64_t string_as_unsigned_64_bit = N(abcde);
     *  print(s , unsigned_64_bit_int, unsigned_128_bit_int, string_as_unsigned_64_bit);
     *  // Ouput: Hello World!100000000000000000087654323456abcde
     *  @endcode
     */
   template<typename Arg, typename... Args>
   void print( Arg a, Args... args ) {
      print(a);
      print(args...);
   }

   /**
    * Simulate C++ style streams
    */
   class iostream {};

   /**
    *  Overload c++ iostream
    *  @brief Overload c++ iostream
    *  @param out  Output strem
    *  @param v    Value to be printed
    *
    *  Example:
    *  @code
    *  const char *s = "Hello World!";
    *  uint64_t unsigned_64_bit_int = 1e+18;
    *  uint128_t unsigned_128_bit_int (87654323456);
    *  uint64_t string_as_unsigned_64_bit = N(abcde);
    *  std::out << s << " " << unsigned_64_bit_int << " "  << unsigned_128_bit_int << " " << string_as_unsigned_64_bit);
    *  // Output: Hello World! 1000000000000000000 87654323456 abcde
    *  @endcode
    */
   template<typename T>
   inline iostream& operator<<( iostream& out, const T& v ) {
      print( v );
      return out;
   }

   static iostream cout;

   /// @} consoleCppapi

}
<commit_msg>Fix for comments. (cherry-picked from fd9582a1a57d557aff5efcfe99b7e72a4ef5ad80)<commit_after>/**
 *  @file
 *  @copyright defined in eos/LICENSE.txt
 */
#pragma once
#include <eoslib/print.h>
#include <eoslib/types.hpp>
#include <eoslib/math.hpp>

namespace eosio {

   static_assert( sizeof(long) == sizeof(int), "unexpected size difference" );

   /**
    *  Prints string
    *  @brief Prints string
    *  @param cstr - a null terminated string
    */
   inline void print( const char* ptr ) {
      prints(ptr);
   }

   /**
    * Prints 64 bit unsigned integer as a 64 bit unsigned integer
    * @brief Prints integer 64 bit unsigned integer
    * @param Value to be printed
    */
   inline void print( uint64_t num ) {
      printi(num);
   }

   /**
    * Prints 32 bit unsigned integer as a 64 bit unsigned integer
    * @brief Prints integer  32 bit unsigned integer
    * @param Value to be printed
    */
   inline void print( uint32_t num ) {
      printi(num);
   }

   /**
    * Prints integer as a 64 bit unsigned integer
    * @brief Prints integer
    * @param Value to be printed
    */
   inline void print( int num ) {
      printi(num);
   }

   /**
    * Prints unsigned integer as a 64 bit unsigned integer
    * @brief Prints unsigned integer
    * @param Value to be printed
    */
   inline void print( unsigned int num ) {
      printi(num);
   }

   /**
    * Prints uint128 struct as 128 bit unsigned integer
    * @brief Prints uint128 struct
    * @param Value to be printed
    */
   inline void print( uint128 num ) {
      printi128((uint128_t*)&num);
   }

   /**
    * Prints 128 bit unsigned integer
    * @brief Prints 128 bit unsigned integer
    * @param Value to be printed
    */
   inline void print( uint128_t num ) {
      printi128((uint128_t*)&num);
   }

   /**
    * Prints a 64 bit names as base32 encoded string
    * @brief Prints a 64 bit names as base32 encoded string
    * @param Value of 64 bit names to be printed
    */
   inline void print( name name ) {
      printn(name.value);
   }

   inline void print( bool val ) {
      prints(val?"true":"false");
   }

   template<typename T>
   inline void print( T&& t ) {
      t.print();
   }

   /**
    *  @defgroup consoleCppapi Console C++ API
    *  @ingroup consoleapi
    *  @brief C++ wrapper for Console C API
    *
    *  This API uses C++ variadic templates and type detection to
    *  make it easy to print any native type. You can even overload
    *  the `print()` method for your own custom types.
    *
    *  **Example:**
    *  ```
    *     print( "hello world, this is a number: ", 5 );
    *  ```
    *
    *  @section override Overriding Print for your Types
    *
    *  There are two ways to overload print:
    *  1. implement void print( const T& )
    *  2. implement T::print()const
    *
    *  @{
    */

    /**
     *  Print out value / list of values (except double)
     *  @brief Print out value  / list of values
     *  @param a    Value to be printed
     *  @param args Other values to be printed
     *
     *  Example:
     *  @code
     *  const char *s = "Hello World!";
     *  uint64_t unsigned_64_bit_int = 1e+18;
     *  uint128_t unsigned_128_bit_int (87654323456);
     *  uint64_t string_as_unsigned_64_bit = N(abcde);
     *  print(s , unsigned_64_bit_int, unsigned_128_bit_int, string_as_unsigned_64_bit);
     *  // Ouput: Hello World!100000000000000000087654323456abcde
     *  @endcode
     */
   template<typename Arg, typename... Args>
   void print( Arg a, Args... args ) {
      print(a);
      print(args...);
   }

   /**
    * Simulate C++ style streams
    */
   class iostream {};

   /**
    *  Overload c++ iostream
    *  @brief Overload c++ iostream
    *  @param out  Output strem
    *  @param v    Value to be printed
    *
    *  Example:
    *  @code
    *  const char *s = "Hello World!";
    *  uint64_t unsigned_64_bit_int = 1e+18;
    *  uint128_t unsigned_128_bit_int (87654323456);
    *  uint64_t string_as_unsigned_64_bit = N(abcde);
    *  std::out << s << " " << unsigned_64_bit_int << " "  << unsigned_128_bit_int << " " << string_as_unsigned_64_bit;
    *  // Output: Hello World! 1000000000000000000 87654323456 abcde
    *  @endcode
    */
   template<typename T>
   inline iostream& operator<<( iostream& out, const T& v ) {
      print( v );
      return out;
   }

   static iostream cout;

   /// @} consoleCppapi

}
<|endoftext|>


<commit_before>/* This file is part of the KDE project
 *
 * Copyright 2004-2007 Torsten Rahn  <tackat@kde.org>
 * Copyright 2007      Inge Wallin   <ingwa@kde.org>
 * Copyright 2007      Thomas Zander <zander@kde.org>
 * Copyright 2010      Bastian Holst <bastianholst@gmx.de>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public License
 * along with this library; see the file COPYING.LIB.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 */

// Self
#include "MarbleControlBox.h"

// Tabs
#include "CurrentLocationWidget.h"
#include "NavigationWidget.h"
#include "FileViewWidget.h"
#include "LegendWidget.h"
#include "MapViewWidget.h"
#include "RoutingWidget.h"

// Marble
#include "global.h"
#include "MarbleWidget.h"
#include "MarbleModel.h"
#include "GeoSceneDocument.h"
#include "GeoSceneHead.h"
#include "HttpDownloadManager.h"
#include "MarbleDebug.h"

namespace Marble
{

class MarbleControlBoxPrivate
{
 public:
    MarbleControlBoxPrivate();
    MarbleWidget  *m_widget;

    NavigationWidget            *m_navigationWidget;
    LegendWidget                *m_legendWidget;
    MapViewWidget               *m_mapViewWidget;

    CurrentLocationWidget       *m_currentLocationWidget;

    FileViewWidget              *m_fileViewWidget;

    RoutingWidget  *m_routingWidget;
};

MarbleControlBoxPrivate::MarbleControlBoxPrivate() : m_routingWidget(0)
{
}

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

MarbleControlBox::MarbleControlBox(QWidget *parent)
    : QToolBox( parent ),
      d( new MarbleControlBoxPrivate )
{
    d->m_widget = 0;

    setFocusPolicy( Qt::NoFocus );
//    setFocusProxy( d->uiWidget.searchLineEdit );

    //  Iterate through all of the Side Widget values  //
    d->m_navigationWidget = new NavigationWidget( this );
    addItem( d->m_navigationWidget, d->m_navigationWidget->windowTitle() );

    d->m_legendWidget = new LegendWidget( this );
    addItem( d->m_legendWidget, d->m_legendWidget->windowTitle() );

    d->m_mapViewWidget = new MapViewWidget( this );
    addItem( d->m_mapViewWidget, d->m_mapViewWidget->windowTitle() );

    d->m_fileViewWidget = new FileViewWidget( this );
    addItem( d->m_fileViewWidget, d->m_fileViewWidget->windowTitle() );

    d->m_currentLocationWidget = new CurrentLocationWidget( this );

    addItem( d->m_currentLocationWidget, d->m_currentLocationWidget->windowTitle() );

    setCurrentIndex(0);

    //default
    setCurrentLocationTabShown( true );
    setFileViewTabShown( false );

    connect( d->m_mapViewWidget, SIGNAL( showMapWizard() ), this, SIGNAL( showMapWizard() ) );
    connect( d->m_mapViewWidget, SIGNAL( showUploadDialog() ), this, SIGNAL( showUploadDialog() ) );
}

MarbleControlBox::~MarbleControlBox()
{
    delete d;
}

void MarbleControlBox::addMarbleWidget(MarbleWidget *widget)
{
    d->m_widget = widget;

    bool const smallScreen = MarbleGlobal::getInstance()->profiles() & MarbleGlobal::SmallScreen;
    if ( !smallScreen ) {
        d->m_routingWidget = new RoutingWidget( widget, this );
        addItem( d->m_routingWidget, tr( "Routing" ) );
    }

    d->m_fileViewWidget->setMarbleWidget( widget );
    d->m_legendWidget->setMarbleWidget( widget );
    d->m_navigationWidget->setMarbleWidget( widget );
    d->m_mapViewWidget->setMarbleWidget( widget );
    d->m_currentLocationWidget->setMarbleWidget( widget );

    connect( d->m_widget, SIGNAL( themeChanged( QString ) ),
             this,        SLOT( selectTheme( QString ) ) );
}

void MarbleControlBox::setWidgetTabShown( QWidget * widget,
                                          int insertIndex, bool show,
                                          QString &text )
{
    int index = indexOf( widget );

    if( show ) {
        if ( !(index >= 0) ){
            if ( insertIndex < count() ) {
                insertItem( insertIndex, widget, text );
            } else {
                insertItem( 3 ,widget, text );
            }
            widget->show();
        }
    } else {
        if ( index >= 0 ) {
            widget->hide();
            removeItem( index );
        }
    }
}

void MarbleControlBox::setNavigationTabShown( bool show )
{
    QString  title = tr( "Navigation" );
    setWidgetTabShown( d->m_navigationWidget, 0, show, title);
}

void MarbleControlBox::setLegendTabShown( bool show )
{
    QString  title = tr( "Legend" );
    setWidgetTabShown( d->m_legendWidget, 1, show, title );
}

void MarbleControlBox::setMapViewTabShown( bool show )
{
    QString  title = tr( "Map View" );
    setWidgetTabShown( d->m_mapViewWidget, 2, show, title );
}

void MarbleControlBox::setFileViewTabShown( bool show )
{
    QString  title = tr( "File View" );
    setWidgetTabShown( d->m_fileViewWidget, 3, show, title );
}

void MarbleControlBox::setCurrentLocationTabShown( bool show )
{
    QString  title = tr( "Current Location" );
    setWidgetTabShown( d->m_currentLocationWidget, 4, show, title );
    if ( d->m_widget && d->m_widget->mapTheme() ) {
        bool enabled = d->m_widget->mapTheme()->head()->target() == "earth";
        int locationIndex = indexOf( d->m_currentLocationWidget );
        if ( locationIndex >= 0 ) {
            setItemEnabled( locationIndex, enabled );
        }

        if ( !enabled ) {
            d->m_widget->setShowGps( false );
        }
    }
}

void MarbleControlBox::setRoutingTabShown( bool show )
{
    if ( d->m_routingWidget ) {
        QString  title = tr( "Routing" );
        setWidgetTabShown( d->m_routingWidget, 5, show, title );
    }
}

void MarbleControlBox::selectTheme( const QString &theme )
{
    Q_UNUSED( theme )

    if ( !d->m_widget )
        return;

    QString selectedId = d->m_widget->mapTheme()->head()->target();
    if ( d->m_routingWidget ) {
        int routingIndex = indexOf( d->m_routingWidget );
        setItemEnabled( routingIndex, selectedId == "earth" );
    }
    int locationIndex = indexOf( d->m_currentLocationWidget );
    if ( locationIndex >= 0 ) {
        setItemEnabled( locationIndex, selectedId == "earth" );
    }
}

void MarbleControlBox::setWorkOffline(bool offline)
{
    HttpDownloadManager * const downloadManager =
        d->m_widget->model()->downloadManager();
    downloadManager->setDownloadEnabled( !offline );
    d->m_navigationWidget->setWorkOffline( offline );
    if ( d->m_routingWidget ) {
        d->m_routingWidget->setWorkOffline( offline );
    }
}

void MarbleControlBox::updateMapThemeView()
{
    d->m_mapViewWidget->updateMapThemeView();
}

}

#include "MarbleControlBox.moc"
<commit_msg>Fix routing manager not always being aware of offline mode on Maemo.<commit_after>/* This file is part of the KDE project
 *
 * Copyright 2004-2007 Torsten Rahn  <tackat@kde.org>
 * Copyright 2007      Inge Wallin   <ingwa@kde.org>
 * Copyright 2007      Thomas Zander <zander@kde.org>
 * Copyright 2010      Bastian Holst <bastianholst@gmx.de>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public License
 * along with this library; see the file COPYING.LIB.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 */

// Self
#include "MarbleControlBox.h"

// Tabs
#include "CurrentLocationWidget.h"
#include "NavigationWidget.h"
#include "FileViewWidget.h"
#include "LegendWidget.h"
#include "MapViewWidget.h"
#include "RoutingWidget.h"

// Marble
#include "global.h"
#include "MarbleWidget.h"
#include "MarbleModel.h"
#include "GeoSceneDocument.h"
#include "GeoSceneHead.h"
#include "HttpDownloadManager.h"
#include "MarbleDebug.h"

namespace Marble
{

class MarbleControlBoxPrivate
{
 public:
    MarbleControlBoxPrivate();
    MarbleWidget  *m_widget;

    NavigationWidget            *m_navigationWidget;
    LegendWidget                *m_legendWidget;
    MapViewWidget               *m_mapViewWidget;

    CurrentLocationWidget       *m_currentLocationWidget;

    FileViewWidget              *m_fileViewWidget;

    RoutingWidget  *m_routingWidget;
};

MarbleControlBoxPrivate::MarbleControlBoxPrivate() : m_routingWidget(0)
{
}

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

MarbleControlBox::MarbleControlBox(QWidget *parent)
    : QToolBox( parent ),
      d( new MarbleControlBoxPrivate )
{
    d->m_widget = 0;

    setFocusPolicy( Qt::NoFocus );
//    setFocusProxy( d->uiWidget.searchLineEdit );

    //  Iterate through all of the Side Widget values  //
    d->m_navigationWidget = new NavigationWidget( this );
    addItem( d->m_navigationWidget, d->m_navigationWidget->windowTitle() );

    d->m_legendWidget = new LegendWidget( this );
    addItem( d->m_legendWidget, d->m_legendWidget->windowTitle() );

    d->m_mapViewWidget = new MapViewWidget( this );
    addItem( d->m_mapViewWidget, d->m_mapViewWidget->windowTitle() );

    d->m_fileViewWidget = new FileViewWidget( this );
    addItem( d->m_fileViewWidget, d->m_fileViewWidget->windowTitle() );

    d->m_currentLocationWidget = new CurrentLocationWidget( this );

    addItem( d->m_currentLocationWidget, d->m_currentLocationWidget->windowTitle() );

    setCurrentIndex(0);

    //default
    setCurrentLocationTabShown( true );
    setFileViewTabShown( false );

    connect( d->m_mapViewWidget, SIGNAL( showMapWizard() ), this, SIGNAL( showMapWizard() ) );
    connect( d->m_mapViewWidget, SIGNAL( showUploadDialog() ), this, SIGNAL( showUploadDialog() ) );
}

MarbleControlBox::~MarbleControlBox()
{
    delete d;
}

void MarbleControlBox::addMarbleWidget(MarbleWidget *widget)
{
    d->m_widget = widget;

    bool const smallScreen = MarbleGlobal::getInstance()->profiles() & MarbleGlobal::SmallScreen;
    if ( !smallScreen ) {
        d->m_routingWidget = new RoutingWidget( widget, this );
        addItem( d->m_routingWidget, tr( "Routing" ) );
    }

    d->m_fileViewWidget->setMarbleWidget( widget );
    d->m_legendWidget->setMarbleWidget( widget );
    d->m_navigationWidget->setMarbleWidget( widget );
    d->m_mapViewWidget->setMarbleWidget( widget );
    d->m_currentLocationWidget->setMarbleWidget( widget );

    connect( d->m_widget, SIGNAL( themeChanged( QString ) ),
             this,        SLOT( selectTheme( QString ) ) );
}

void MarbleControlBox::setWidgetTabShown( QWidget * widget,
                                          int insertIndex, bool show,
                                          QString &text )
{
    int index = indexOf( widget );

    if( show ) {
        if ( !(index >= 0) ){
            if ( insertIndex < count() ) {
                insertItem( insertIndex, widget, text );
            } else {
                insertItem( 3 ,widget, text );
            }
            widget->show();
        }
    } else {
        if ( index >= 0 ) {
            widget->hide();
            removeItem( index );
        }
    }
}

void MarbleControlBox::setNavigationTabShown( bool show )
{
    QString  title = tr( "Navigation" );
    setWidgetTabShown( d->m_navigationWidget, 0, show, title);
}

void MarbleControlBox::setLegendTabShown( bool show )
{
    QString  title = tr( "Legend" );
    setWidgetTabShown( d->m_legendWidget, 1, show, title );
}

void MarbleControlBox::setMapViewTabShown( bool show )
{
    QString  title = tr( "Map View" );
    setWidgetTabShown( d->m_mapViewWidget, 2, show, title );
}

void MarbleControlBox::setFileViewTabShown( bool show )
{
    QString  title = tr( "File View" );
    setWidgetTabShown( d->m_fileViewWidget, 3, show, title );
}

void MarbleControlBox::setCurrentLocationTabShown( bool show )
{
    QString  title = tr( "Current Location" );
    setWidgetTabShown( d->m_currentLocationWidget, 4, show, title );
    if ( d->m_widget && d->m_widget->mapTheme() ) {
        bool enabled = d->m_widget->mapTheme()->head()->target() == "earth";
        int locationIndex = indexOf( d->m_currentLocationWidget );
        if ( locationIndex >= 0 ) {
            setItemEnabled( locationIndex, enabled );
        }

        if ( !enabled ) {
            d->m_widget->setShowGps( false );
        }
    }
}

void MarbleControlBox::setRoutingTabShown( bool show )
{
    if ( d->m_routingWidget ) {
        QString  title = tr( "Routing" );
        setWidgetTabShown( d->m_routingWidget, 5, show, title );
    }
}

void MarbleControlBox::selectTheme( const QString &theme )
{
    Q_UNUSED( theme )

    if ( !d->m_widget )
        return;

    QString selectedId = d->m_widget->mapTheme()->head()->target();
    if ( d->m_routingWidget ) {
        int routingIndex = indexOf( d->m_routingWidget );
        setItemEnabled( routingIndex, selectedId == "earth" );
    }
    int locationIndex = indexOf( d->m_currentLocationWidget );
    if ( locationIndex >= 0 ) {
        setItemEnabled( locationIndex, selectedId == "earth" );
    }
}

void MarbleControlBox::setWorkOffline(bool offline)
{
    HttpDownloadManager * const downloadManager =
        d->m_widget->model()->downloadManager();
    downloadManager->setDownloadEnabled( !offline );
    d->m_navigationWidget->setWorkOffline( offline );
    d->m_widget->model()->routingManager()->setWorkOffline( offline );
    if ( d->m_routingWidget ) {
        d->m_routingWidget->setWorkOffline( offline );
    }
}

void MarbleControlBox::updateMapThemeView()
{
    d->m_mapViewWidget->updateMapThemeView();
}

}

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


<commit_before>/* Begin CVS Header
   $Source: /Volumes/Home/Users/shoops/cvs/copasi_dev/copasi/trajectory/CTrajectoryTask.cpp,v $
   $Revision: 1.74 $
   $Name:  $
   $Author: shoops $
   $Date: 2006/04/27 01:32:17 $
   End CVS Header */

// Copyright  2005 by Pedro Mendes, Virginia Tech Intellectual
// Properties, Inc. and EML Research, gGmbH.
// All rights reserved.

/**
 * CTrajectoryTask class.
 *
 * This class implements a trajectory task which is comprised of a
 * of a problem and a method. Additionally calls to the reporting
 * methods are done when initialized.
 *
 * Created for Copasi by Stefan Hoops 2002
 */

#include <string>

#include "copasi.h"

#include "CTrajectoryTask.h"
#include "CTrajectoryProblem.h"
#include "CTrajectoryMethod.h"
#include "model/CModel.h"
#include "model/CState.h"
#include "report/CKeyFactory.h"
#include "report/CReport.h"
#include "utilities/CProcessReport.h"
#include "utilities/CCopasiException.h"
#include  "CopasiDataModel/CCopasiDataModel.h"

#define XXXX_Reporting

bool fle(const C_FLOAT64 & d1, const C_FLOAT64 & d2)
{return (d1 <= d2);}

bool fl(const C_FLOAT64 & d1, const C_FLOAT64 & d2)
{return (d1 < d2);}

bool ble(const C_FLOAT64 & d1, const C_FLOAT64 & d2)
{return (d1 >= d2);}

bool bl(const C_FLOAT64 & d1, const C_FLOAT64 & d2)
{return (d1 > d2);}

CTrajectoryTask::CTrajectoryTask(const CCopasiContainer * pParent):
    CCopasiTask(CCopasiTask::timeCourse, pParent),
    mTimeSeriesRequested(true),
    mTimeSeries(),
    mpTrajectoryProblem(NULL),
    mpTrajectoryMethod(NULL),
    mpCurrentState(NULL),
    mpCurrentTime(NULL)
{
  mpProblem = new CTrajectoryProblem(this);
  mpMethod =
    CTrajectoryMethod::createTrajectoryMethod(CCopasiMethod::deterministic,
        (CTrajectoryProblem *) mpProblem);
  this->add(mpMethod, true);
  //mpMethod->setObjectParent(this);
}

/*CTrajectoryTask::CTrajectoryTask(const CTrajectoryTask & src,
                                 const CCopasiContainer * pParent):
    CCopasiTask(src, pParent),
    mpCurrentState(src.mpCurrentState),
    mTimeSeriesRequested(src.mTimeSeriesRequested)
{fatalError();}*/

CTrajectoryTask::~CTrajectoryTask()
{
  cleanup();
}

void CTrajectoryTask::cleanup()
{
  pdelete(mpCurrentState);
}

void CTrajectoryTask::load(CReadConfig & configBuffer)
{
  configBuffer.getVariable("Dynamics", "bool", &mScheduled,
                           CReadConfig::LOOP);

  pdelete(mpProblem);
  mpProblem = new CTrajectoryProblem(this);
  ((CTrajectoryProblem *) mpProblem)->load(configBuffer);

  pdelete(mpMethod);
  mpMethod = CTrajectoryMethod::createTrajectoryMethod();
  this->add(mpMethod, true);
  //mpMethod->setObjectParent(this);
  ((CTrajectoryMethod *)mpMethod)->setProblem((CTrajectoryProblem *) mpProblem);
}

bool CTrajectoryTask::initialize(const OutputFlag & of,
                                 std::ostream * pOstream)
{
  assert(mpProblem && mpMethod);

  mpTrajectoryProblem = dynamic_cast<CTrajectoryProblem *>(mpProblem);
  assert(mpTrajectoryProblem);

  mpTrajectoryMethod = dynamic_cast<CTrajectoryMethod *>(mpMethod);
  assert(mpTrajectoryMethod);

  mpTrajectoryMethod->setProblem(mpTrajectoryProblem);

  bool success = mpMethod->isValidProblem(mpProblem);

  pdelete(mpCurrentState);
  mpCurrentState = new CState(mpTrajectoryProblem->getModel()->getState());
  mpCurrentTime = &mpCurrentState->getTime();

  if (!CCopasiTask::initialize(of, pOstream)) success = false;
  mTimeSeriesRequested = mpTrajectoryProblem->timeSeriesRequested();

  return success;
}

bool CTrajectoryTask::process(const bool & useInitialValues)
{
  //*****

  processStart(useInitialValues);

  //*****

  unsigned C_INT32 FailCounter = 0;

  C_FLOAT64 StepSize = mpTrajectoryProblem->getStepSize();
  C_FLOAT64 NextTimeToReport;

  const C_FLOAT64 EndTime = *mpCurrentTime + mpTrajectoryProblem->getDuration();
  const C_FLOAT64 StartTime = *mpCurrentTime;

  C_FLOAT64 StepNumber = (mpTrajectoryProblem->getDuration()) / StepSize;

  bool (*LE)(const C_FLOAT64 &, const C_FLOAT64 &);
  bool (*L)(const C_FLOAT64 &, const C_FLOAT64 &);
  if (StepSize < 0.0)
    {
      LE = &ble;
      L = &bl;
    }
  else
    {
      LE = &fle;
      L = &fl;
    }

  unsigned C_INT32 StepCounter = 1;

  C_FLOAT64 outputStartTime = mpTrajectoryProblem->getOutputStartTime();

  if (StepSize == 0.0 && mpTrajectoryProblem->getDuration() != 0.0)
    {
      CCopasiMessage(CCopasiMessage::ERROR, MCTrajectoryProblem + 1, StepSize);
      return false;
    }

  output(COutputInterface::BEFORE);

  bool flagProceed = true;
  C_FLOAT64 handlerFactor = 100.0 / mpTrajectoryProblem->getDuration();

  C_FLOAT64 Percentage = 0;
  unsigned C_INT32 hProcess;

  if (mpCallBack)
    {
      mpCallBack->setName("performing simulation...");
      C_FLOAT64 hundred = 100;
      hProcess = mpCallBack->addItem("Completion",
                                     CCopasiParameter::DOUBLE,
                                     &Percentage,
                                     &hundred);
    }

  if ((*LE)(outputStartTime, *mpCurrentTime)) output(COutputInterface::DURING);

  try
    {
      do
        {
          // This is numerically more stable then adding
          // mpTrajectoryProblem->getStepSize().
          NextTimeToReport =
            StartTime + (EndTime - StartTime) * StepCounter++ / StepNumber;

          flagProceed &= processStep(NextTimeToReport);

          if (mpCallBack)
            {
              Percentage = (*mpCurrentTime - StartTime) * handlerFactor;
              flagProceed &= mpCallBack->progress(hProcess);
            }

          if ((*LE)(outputStartTime, *mpCurrentTime))
            {
              output(COutputInterface::DURING);
            }
        }
      while ((*L)(*mpCurrentTime, EndTime) && flagProceed);
    }

  catch (CCopasiException Exception)
    {
      mpTrajectoryProblem->getModel()->setState(*mpCurrentState);
      mpTrajectoryProblem->getModel()->refreshConcentrations();

      if ((*LE)(outputStartTime, *mpCurrentTime))
        {
          output(COutputInterface::DURING);
        }

      if (mpCallBack) mpCallBack->finish(hProcess);
      output(COutputInterface::AFTER);

      throw CCopasiException(Exception.getMessage());
    }

  if (mpCallBack) mpCallBack->finish(hProcess);

  output(COutputInterface::AFTER);

  return true;
}

void CTrajectoryTask::processStart(const bool & useInitialValues)
{
  if (useInitialValues)
    mpTrajectoryProblem->getModel()->applyInitialValues();

  *mpCurrentState = mpTrajectoryProblem->getModel()->getState();

  mpTrajectoryMethod->setCurrentState(mpCurrentState);
  mpTrajectoryMethod->start(mpCurrentState);

  return;
}

bool CTrajectoryTask::processStep(const C_FLOAT64 & nextTime)
{
  C_FLOAT64 CompareTime = nextTime - 100 * fabs(nextTime) * DBL_EPSILON;

  if (*mpCurrentTime <= CompareTime)
    {
      do
        {
          mpTrajectoryMethod->step(nextTime - *mpCurrentTime);

          if (*mpCurrentTime > CompareTime) break;

          /* Here we will do conditional event processing */

          /* Currently this is correct since no events are processed. */
          CCopasiMessage(CCopasiMessage::EXCEPTION, MCTrajectoryMethod + 12);
        }
      while (true);

      mpTrajectoryProblem->getModel()->setState(*mpCurrentState);
      mpTrajectoryProblem->getModel()->refreshConcentrations();

      return true;
    }

  CompareTime = nextTime + 100 * fabs(nextTime) * DBL_EPSILON;
  if (*mpCurrentTime >= CompareTime)
    {
      do
        {
          mpTrajectoryMethod->step(nextTime - *mpCurrentTime);

          if (*mpCurrentTime < CompareTime) break;

          /* Here we will do conditional event processing */

          /* Currently this is correct since no events are processed. */
          CCopasiMessage(CCopasiMessage::EXCEPTION, MCTrajectoryMethod + 12);
        }
      while (true);

      mpTrajectoryProblem->getModel()->setState(*mpCurrentState);
      mpTrajectoryProblem->getModel()->refreshConcentrations();

      return true;
    }

  // Current time is approximately nextTime;
  return false;
}

bool CTrajectoryTask::restore()
{
  bool success = CCopasiTask::restore();

  if (mUpdateModel)
    {
      CModel * pModel = mpProblem->getModel();

      pModel->setState(*mpCurrentState);
      pModel->applyAssignments();
      pModel->setInitialState(pModel->getState());
    }

  return success;
}

bool CTrajectoryTask::setMethodType(const int & type)
{
  CCopasiMethod::SubType Type = (CCopasiMethod::SubType) type;

  if (!CTrajectoryMethod::isValidSubType(Type)) return false;
  if (mpMethod->getSubType() == Type) return true;

  pdelete (mpMethod);
  mpMethod =
    CTrajectoryMethod::createTrajectoryMethod(Type,
        (CTrajectoryProblem *) mpProblem);
  this->add(mpMethod, true);
  //mpMethod->setObjectParent(this);

  return true;
}

CState * CTrajectoryTask::getState()
{return mpCurrentState;}

const CTimeSeries & CTrajectoryTask::getTimeSeries() const
  {return mTimeSeries;}

void CTrajectoryTask::output(const COutputInterface::Activity & activity)
{
  CCopasiDataModel::Global->output(activity);

  if (mTimeSeriesRequested && mDoOutput == OUTPUT_COMPLETE)
    switch (activity)
      {
      case COutputInterface::BEFORE:
        mTimeSeries.init(mpTrajectoryProblem->getStepNumber(), mpProblem->getModel());
        break;

      case COutputInterface::DURING:
        mTimeSeries.add();
        break;

      case COutputInterface::AFTER:
        mTimeSeries.finish();
        break;
      }
}
<commit_msg>Fixed output to call CCopasiTask::output instead of the global output handler.<commit_after>/* Begin CVS Header
   $Source: /Volumes/Home/Users/shoops/cvs/copasi_dev/copasi/trajectory/CTrajectoryTask.cpp,v $
   $Revision: 1.75 $
   $Name:  $
   $Author: shoops $
   $Date: 2006/05/02 20:20:22 $
   End CVS Header */

// Copyright  2005 by Pedro Mendes, Virginia Tech Intellectual
// Properties, Inc. and EML Research, gGmbH.
// All rights reserved.

/**
 * CTrajectoryTask class.
 *
 * This class implements a trajectory task which is comprised of a
 * of a problem and a method. Additionally calls to the reporting
 * methods are done when initialized.
 *
 * Created for Copasi by Stefan Hoops 2002
 */

#include <string>

#include "copasi.h"

#include "CTrajectoryTask.h"
#include "CTrajectoryProblem.h"
#include "CTrajectoryMethod.h"
#include "model/CModel.h"
#include "model/CState.h"
#include "report/CKeyFactory.h"
#include "report/CReport.h"
#include "utilities/CProcessReport.h"
#include "utilities/CCopasiException.h"
#include  "CopasiDataModel/CCopasiDataModel.h"

#define XXXX_Reporting

bool fle(const C_FLOAT64 & d1, const C_FLOAT64 & d2)
{return (d1 <= d2);}

bool fl(const C_FLOAT64 & d1, const C_FLOAT64 & d2)
{return (d1 < d2);}

bool ble(const C_FLOAT64 & d1, const C_FLOAT64 & d2)
{return (d1 >= d2);}

bool bl(const C_FLOAT64 & d1, const C_FLOAT64 & d2)
{return (d1 > d2);}

CTrajectoryTask::CTrajectoryTask(const CCopasiContainer * pParent):
    CCopasiTask(CCopasiTask::timeCourse, pParent),
    mTimeSeriesRequested(true),
    mTimeSeries(),
    mpTrajectoryProblem(NULL),
    mpTrajectoryMethod(NULL),
    mpCurrentState(NULL),
    mpCurrentTime(NULL)
{
  mpProblem = new CTrajectoryProblem(this);
  mpMethod =
    CTrajectoryMethod::createTrajectoryMethod(CCopasiMethod::deterministic,
        (CTrajectoryProblem *) mpProblem);
  this->add(mpMethod, true);
  //mpMethod->setObjectParent(this);
}

/*CTrajectoryTask::CTrajectoryTask(const CTrajectoryTask & src,
                                 const CCopasiContainer * pParent):
    CCopasiTask(src, pParent),
    mpCurrentState(src.mpCurrentState),
    mTimeSeriesRequested(src.mTimeSeriesRequested)
{fatalError();}*/

CTrajectoryTask::~CTrajectoryTask()
{
  cleanup();
}

void CTrajectoryTask::cleanup()
{
  pdelete(mpCurrentState);
}

void CTrajectoryTask::load(CReadConfig & configBuffer)
{
  configBuffer.getVariable("Dynamics", "bool", &mScheduled,
                           CReadConfig::LOOP);

  pdelete(mpProblem);
  mpProblem = new CTrajectoryProblem(this);
  ((CTrajectoryProblem *) mpProblem)->load(configBuffer);

  pdelete(mpMethod);
  mpMethod = CTrajectoryMethod::createTrajectoryMethod();
  this->add(mpMethod, true);
  //mpMethod->setObjectParent(this);
  ((CTrajectoryMethod *)mpMethod)->setProblem((CTrajectoryProblem *) mpProblem);
}

bool CTrajectoryTask::initialize(const OutputFlag & of,
                                 std::ostream * pOstream)
{
  assert(mpProblem && mpMethod);

  mpTrajectoryProblem = dynamic_cast<CTrajectoryProblem *>(mpProblem);
  assert(mpTrajectoryProblem);

  mpTrajectoryMethod = dynamic_cast<CTrajectoryMethod *>(mpMethod);
  assert(mpTrajectoryMethod);

  mpTrajectoryMethod->setProblem(mpTrajectoryProblem);

  bool success = mpMethod->isValidProblem(mpProblem);

  pdelete(mpCurrentState);
  mpCurrentState = new CState(mpTrajectoryProblem->getModel()->getState());
  mpCurrentTime = &mpCurrentState->getTime();

  if (!CCopasiTask::initialize(of, pOstream)) success = false;
  mTimeSeriesRequested = mpTrajectoryProblem->timeSeriesRequested();

  return success;
}

bool CTrajectoryTask::process(const bool & useInitialValues)
{
  //*****

  processStart(useInitialValues);

  //*****

  unsigned C_INT32 FailCounter = 0;

  C_FLOAT64 StepSize = mpTrajectoryProblem->getStepSize();
  C_FLOAT64 NextTimeToReport;

  const C_FLOAT64 EndTime = *mpCurrentTime + mpTrajectoryProblem->getDuration();
  const C_FLOAT64 StartTime = *mpCurrentTime;

  C_FLOAT64 StepNumber = (mpTrajectoryProblem->getDuration()) / StepSize;

  bool (*LE)(const C_FLOAT64 &, const C_FLOAT64 &);
  bool (*L)(const C_FLOAT64 &, const C_FLOAT64 &);
  if (StepSize < 0.0)
    {
      LE = &ble;
      L = &bl;
    }
  else
    {
      LE = &fle;
      L = &fl;
    }

  unsigned C_INT32 StepCounter = 1;

  C_FLOAT64 outputStartTime = mpTrajectoryProblem->getOutputStartTime();

  if (StepSize == 0.0 && mpTrajectoryProblem->getDuration() != 0.0)
    {
      CCopasiMessage(CCopasiMessage::ERROR, MCTrajectoryProblem + 1, StepSize);
      return false;
    }

  output(COutputInterface::BEFORE);

  bool flagProceed = true;
  C_FLOAT64 handlerFactor = 100.0 / mpTrajectoryProblem->getDuration();

  C_FLOAT64 Percentage = 0;
  unsigned C_INT32 hProcess;

  if (mpCallBack)
    {
      mpCallBack->setName("performing simulation...");
      C_FLOAT64 hundred = 100;
      hProcess = mpCallBack->addItem("Completion",
                                     CCopasiParameter::DOUBLE,
                                     &Percentage,
                                     &hundred);
    }

  if ((*LE)(outputStartTime, *mpCurrentTime)) output(COutputInterface::DURING);

  try
    {
      do
        {
          // This is numerically more stable then adding
          // mpTrajectoryProblem->getStepSize().
          NextTimeToReport =
            StartTime + (EndTime - StartTime) * StepCounter++ / StepNumber;

          flagProceed &= processStep(NextTimeToReport);

          if (mpCallBack)
            {
              Percentage = (*mpCurrentTime - StartTime) * handlerFactor;
              flagProceed &= mpCallBack->progress(hProcess);
            }

          if ((*LE)(outputStartTime, *mpCurrentTime))
            {
              output(COutputInterface::DURING);
            }
        }
      while ((*L)(*mpCurrentTime, EndTime) && flagProceed);
    }

  catch (CCopasiException Exception)
    {
      mpTrajectoryProblem->getModel()->setState(*mpCurrentState);
      mpTrajectoryProblem->getModel()->refreshConcentrations();

      if ((*LE)(outputStartTime, *mpCurrentTime))
        {
          output(COutputInterface::DURING);
        }

      if (mpCallBack) mpCallBack->finish(hProcess);
      output(COutputInterface::AFTER);

      throw CCopasiException(Exception.getMessage());
    }

  if (mpCallBack) mpCallBack->finish(hProcess);

  output(COutputInterface::AFTER);

  return true;
}

void CTrajectoryTask::processStart(const bool & useInitialValues)
{
  if (useInitialValues)
    mpTrajectoryProblem->getModel()->applyInitialValues();

  *mpCurrentState = mpTrajectoryProblem->getModel()->getState();

  mpTrajectoryMethod->setCurrentState(mpCurrentState);
  mpTrajectoryMethod->start(mpCurrentState);

  return;
}

bool CTrajectoryTask::processStep(const C_FLOAT64 & nextTime)
{
  C_FLOAT64 CompareTime = nextTime - 100 * fabs(nextTime) * DBL_EPSILON;

  if (*mpCurrentTime <= CompareTime)
    {
      do
        {
          mpTrajectoryMethod->step(nextTime - *mpCurrentTime);

          if (*mpCurrentTime > CompareTime) break;

          /* Here we will do conditional event processing */

          /* Currently this is correct since no events are processed. */
          CCopasiMessage(CCopasiMessage::EXCEPTION, MCTrajectoryMethod + 12);
        }
      while (true);

      mpTrajectoryProblem->getModel()->setState(*mpCurrentState);
      mpTrajectoryProblem->getModel()->refreshConcentrations();

      return true;
    }

  CompareTime = nextTime + 100 * fabs(nextTime) * DBL_EPSILON;
  if (*mpCurrentTime >= CompareTime)
    {
      do
        {
          mpTrajectoryMethod->step(nextTime - *mpCurrentTime);

          if (*mpCurrentTime < CompareTime) break;

          /* Here we will do conditional event processing */

          /* Currently this is correct since no events are processed. */
          CCopasiMessage(CCopasiMessage::EXCEPTION, MCTrajectoryMethod + 12);
        }
      while (true);

      mpTrajectoryProblem->getModel()->setState(*mpCurrentState);
      mpTrajectoryProblem->getModel()->refreshConcentrations();

      return true;
    }

  // Current time is approximately nextTime;
  return false;
}

bool CTrajectoryTask::restore()
{
  bool success = CCopasiTask::restore();

  if (mUpdateModel)
    {
      CModel * pModel = mpProblem->getModel();

      pModel->setState(*mpCurrentState);
      pModel->applyAssignments();
      pModel->setInitialState(pModel->getState());
    }

  return success;
}

bool CTrajectoryTask::setMethodType(const int & type)
{
  CCopasiMethod::SubType Type = (CCopasiMethod::SubType) type;

  if (!CTrajectoryMethod::isValidSubType(Type)) return false;
  if (mpMethod->getSubType() == Type) return true;

  pdelete (mpMethod);
  mpMethod =
    CTrajectoryMethod::createTrajectoryMethod(Type,
        (CTrajectoryProblem *) mpProblem);
  this->add(mpMethod, true);
  //mpMethod->setObjectParent(this);

  return true;
}

CState * CTrajectoryTask::getState()
{return mpCurrentState;}

const CTimeSeries & CTrajectoryTask::getTimeSeries() const
  {return mTimeSeries;}

void CTrajectoryTask::output(const COutputInterface::Activity & activity)
{
  CCopasiTask::output(activity);

  if (mTimeSeriesRequested && mDoOutput == OUTPUT_COMPLETE)
    switch (activity)
      {
      case COutputInterface::BEFORE:
        mTimeSeries.init(mpTrajectoryProblem->getStepNumber(), mpProblem->getModel());
        break;

      case COutputInterface::DURING:
        mTimeSeries.add();
        break;

      case COutputInterface::AFTER:
        mTimeSeries.finish();
        break;
      }
}
<|endoftext|>


<commit_before>/*
 * Copyright 2007-2017 Content Management AG
 * All rights reserved.
 *
 * author: Max Kellermann <mk@cm4all.com>
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * - Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *
 * - Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the
 * distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
 * FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 * OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "Glue.hxx"
#include "Client.hxx"
#include "http_response.hxx"
#include "http_address.hxx"
#include "header_writer.hxx"
#include "stock/GetHandler.hxx"
#include "stock/Item.hxx"
#include "strmap.hxx"
#include "lease.hxx"
#include "tcp_stock.hxx"
#include "tcp_balancer.hxx"
#include "abort_close.hxx"
#include "istream/istream.hxx"
#include "istream/istream_hold.hxx"
#include "net/SocketDescriptor.hxx"
#include "net/SocketAddress.hxx"
#include "pool.hxx"
#include "util/Cancellable.hxx"

#include "util/Compiler.h"

#include <string.h>
#include <sys/socket.h>

struct AjpRequest final : public StockGetHandler, Lease {
    struct pool &pool;
    EventLoop &event_loop;

    StockItem *stock_item;

    const char *const protocol;
    const char *const remote_addr;
    const char *const remote_host;
    const char *const server_name;
    const unsigned server_port;
    const bool is_ssl;

    const http_method_t method;
    const char *const uri;
    StringMap headers;
    Istream *body;

    HttpResponseHandler &handler;
    CancellablePointer &cancel_ptr;

    AjpRequest(struct pool &_pool, EventLoop &_event_loop,
               const char *_protocol, const char *_remote_addr,
               const char *_remote_host, const char *_server_name,
               unsigned _server_port, bool _is_ssl,
               http_method_t _method, const char *_uri,
               StringMap &&_headers,
               HttpResponseHandler &_handler,
               CancellablePointer &_cancel_ptr)
        :pool(_pool), event_loop(_event_loop),
         protocol(_protocol),
         remote_addr(_remote_addr), remote_host(_remote_host),
         server_name(_server_name), server_port(_server_port),
         is_ssl(_is_ssl),
         method(_method), uri(_uri),
         headers(std::move(_headers)),
         handler(_handler),
         cancel_ptr(_cancel_ptr) {
    }

    /* virtual methods from class StockGetHandler */
    void OnStockItemReady(StockItem &item) override;
    void OnStockItemError(std::exception_ptr ep) override;

    /* virtual methods from class Lease */
    void ReleaseLease(bool reuse) override {
        stock_item->Put(!reuse);
    }
};

/*
 * stock callback
 *
 */

void
AjpRequest::OnStockItemReady(StockItem &item)
{
    stock_item = &item;

    ajp_client_request(pool, event_loop,
                       tcp_stock_item_get(item),
                       tcp_stock_item_get_domain(item) == AF_LOCAL
                       ? FdType::FD_SOCKET : FdType::FD_TCP,
                       *this,
                       protocol, remote_addr,
                       remote_host, server_name,
                       server_port, is_ssl,
                       method, uri, headers, body,
                       handler, cancel_ptr);
}

void
AjpRequest::OnStockItemError(std::exception_ptr ep)
{
    handler.InvokeError(ep);

    if (body != nullptr)
        body->CloseUnused();
}

/*
 * constructor
 *
 */

void
ajp_stock_request(struct pool &pool, EventLoop &event_loop,
                  TcpBalancer &tcp_balancer,
                  sticky_hash_t session_sticky,
                  const char *protocol, const char *remote_addr,
                  const char *remote_host, const char *server_name,
                  unsigned server_port, bool is_ssl,
                  http_method_t method,
                  const HttpAddress &uwa,
                  StringMap &&headers,
                  Istream *body,
                  HttpResponseHandler &handler,
                  CancellablePointer &_cancel_ptr)
{
    assert(uwa.path != nullptr);
    assert(body == nullptr || !body->HasHandler());

    auto hr = NewFromPool<AjpRequest>(pool, pool, event_loop,
                                      protocol,
                                      remote_addr, remote_host,
                                      server_name, server_port,
                                      is_ssl, method, uwa.path,
                                      std::move(headers),
                                      handler, _cancel_ptr);

    auto *cancel_ptr = &_cancel_ptr;
    if (body != nullptr) {
        hr->body = istream_hold_new(pool, *body);
        cancel_ptr = &async_close_on_abort(pool, *hr->body, *cancel_ptr);
    } else
        hr->body = nullptr;

    tcp_balancer.Get(pool,
                     false, SocketAddress::Null(),
                     session_sticky,
                     uwa.addresses,
                     20,
                     *hr, *cancel_ptr);
}
<commit_msg>ajp/Glue: move code to method BeginConnect()<commit_after>/*
 * Copyright 2007-2017 Content Management AG
 * All rights reserved.
 *
 * author: Max Kellermann <mk@cm4all.com>
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * - Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *
 * - Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the
 * distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
 * FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 * OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "Glue.hxx"
#include "Client.hxx"
#include "http_response.hxx"
#include "http_address.hxx"
#include "header_writer.hxx"
#include "stock/GetHandler.hxx"
#include "stock/Item.hxx"
#include "strmap.hxx"
#include "lease.hxx"
#include "tcp_stock.hxx"
#include "tcp_balancer.hxx"
#include "abort_close.hxx"
#include "istream/istream.hxx"
#include "istream/istream_hold.hxx"
#include "net/SocketDescriptor.hxx"
#include "net/SocketAddress.hxx"
#include "pool.hxx"
#include "util/Cancellable.hxx"

#include "util/Compiler.h"

#include <string.h>
#include <sys/socket.h>

struct AjpRequest final : StockGetHandler, Lease {
    struct pool &pool;
    EventLoop &event_loop;

    StockItem *stock_item;

    const char *const protocol;
    const char *const remote_addr;
    const char *const remote_host;
    const char *const server_name;
    const unsigned server_port;
    const bool is_ssl;

    const http_method_t method;
    const char *const uri;
    StringMap headers;
    Istream *body;

    HttpResponseHandler &handler;
    CancellablePointer &cancel_ptr;

    AjpRequest(struct pool &_pool, EventLoop &_event_loop,
               const char *_protocol, const char *_remote_addr,
               const char *_remote_host, const char *_server_name,
               unsigned _server_port, bool _is_ssl,
               http_method_t _method, const char *_uri,
               StringMap &&_headers,
               HttpResponseHandler &_handler,
               CancellablePointer &_cancel_ptr)
        :pool(_pool), event_loop(_event_loop),
         protocol(_protocol),
         remote_addr(_remote_addr), remote_host(_remote_host),
         server_name(_server_name), server_port(_server_port),
         is_ssl(_is_ssl),
         method(_method), uri(_uri),
         headers(std::move(_headers)),
         handler(_handler),
         cancel_ptr(_cancel_ptr) {
    }

    void BeginConnect(TcpBalancer &tcp_balancer, sticky_hash_t session_sticky,
                      const HttpAddress &address,
                      CancellablePointer &_cancel_ptr) {
        tcp_balancer.Get(pool,
                         false, SocketAddress::Null(),
                         session_sticky,
                         address.addresses,
                         20,
                         *this, _cancel_ptr);
    }

private:
    /* virtual methods from class StockGetHandler */
    void OnStockItemReady(StockItem &item) override;
    void OnStockItemError(std::exception_ptr ep) override;

    /* virtual methods from class Lease */
    void ReleaseLease(bool reuse) override {
        stock_item->Put(!reuse);
    }
};

/*
 * stock callback
 *
 */

void
AjpRequest::OnStockItemReady(StockItem &item)
{
    stock_item = &item;

    ajp_client_request(pool, event_loop,
                       tcp_stock_item_get(item),
                       tcp_stock_item_get_domain(item) == AF_LOCAL
                       ? FdType::FD_SOCKET : FdType::FD_TCP,
                       *this,
                       protocol, remote_addr,
                       remote_host, server_name,
                       server_port, is_ssl,
                       method, uri, headers, body,
                       handler, cancel_ptr);
}

void
AjpRequest::OnStockItemError(std::exception_ptr ep)
{
    handler.InvokeError(ep);

    if (body != nullptr)
        body->CloseUnused();
}

/*
 * constructor
 *
 */

void
ajp_stock_request(struct pool &pool, EventLoop &event_loop,
                  TcpBalancer &tcp_balancer,
                  sticky_hash_t session_sticky,
                  const char *protocol, const char *remote_addr,
                  const char *remote_host, const char *server_name,
                  unsigned server_port, bool is_ssl,
                  http_method_t method,
                  const HttpAddress &uwa,
                  StringMap &&headers,
                  Istream *body,
                  HttpResponseHandler &handler,
                  CancellablePointer &_cancel_ptr)
{
    assert(uwa.path != nullptr);
    assert(body == nullptr || !body->HasHandler());

    auto hr = NewFromPool<AjpRequest>(pool, pool, event_loop,
                                      protocol,
                                      remote_addr, remote_host,
                                      server_name, server_port,
                                      is_ssl, method, uwa.path,
                                      std::move(headers),
                                      handler, _cancel_ptr);

    auto *cancel_ptr = &_cancel_ptr;
    if (body != nullptr) {
        hr->body = istream_hold_new(pool, *body);
        cancel_ptr = &async_close_on_abort(pool, *hr->body, *cancel_ptr);
    } else
        hr->body = nullptr;

    hr->BeginConnect(tcp_balancer, session_sticky, uwa, *cancel_ptr);
}
<|endoftext|>