<commit_before>#include "behaviour_xsensfollowing.h"
#include <QtGui>
#include <Behaviour_XsensFollowing/xsensfollowingform.h>
#include <Framework/Angles.h>

Behaviour_XsensFollowing::Behaviour_XsensFollowing(QString id, Module_ThrusterControlLoop *tcl, Module_XsensMTi *xsens)
    : RobotBehaviour(id)
{
    this->xsens = xsens;
    this->tcl = tcl;
    turnTimer.moveToThread(this);
    timer.moveToThread(this);

    this->setDefaultValue("timer",30);
    this->setDefaultValue("driveTime",10000);
    this->setDefaultValue("ffSpeed",0.5);
    this->setDefaultValue("kp",0.3);
    this->setDefaultValue("delta",10);
}

bool Behaviour_XsensFollowing::isActive()
{
    return isEnabled();
}

void Behaviour_XsensFollowing::init()
{
    logger->info("Xsens Following init");
    setEnabled(false);
    connect(this,SIGNAL(newAngularSpeed(float)),tcl,SLOT(setAngularSpeed(float)));
    connect(this,SIGNAL(newForwardSpeed(float)),tcl,SLOT(setForwardSpeed(float)));
    connect(&timer,SIGNAL(timeout()),this,SLOT(controlLoop()));
    connect(&turnTimer,SIGNAL(timeout()),this,SLOT(turnNinety()));
    connect(this, SIGNAL(enabled(bool)), this, SLOT(controlEnabledChanged(bool)));
}

void Behaviour_XsensFollowing::startBehaviour()
{
    if (this->isEnabled() == true){
        logger->info("Already enabled/started!");
        return;
    }
    logger->info("Starting Xsens Following");
    this->setEnabled(true);

    targetHeading = xsens->getHeading();

    emit dataChanged(this);

    timer.start(getSettingsValue("timer").toInt());
    turnTimer.start(getSettingsValue("driveTime").toInt());
}

void Behaviour_XsensFollowing::stop()
{
    if(timer.isActive()){
        timer.stop();
    }
    if(turnTimer.isActive()){
        turnTimer.stop();
    }

    if (!isEnabled()) {
        return;
    }

    logger->info("Xsens follow stop");
    this->setEnabled(false);
    setEnabled(false);
    emit newAngularSpeed(0.0);
    emit newForwardSpeed(0.0);
    logger->info("Stop Xsens Following");
    emit finished(this,true);
}

void Behaviour_XsensFollowing::reset()
{
    logger->info("Xsens follow reset");
    if (this->isEnabled() == false){
        logger->info("Not enabled!");
        return;
    }
    timer.stop();
    turnTimer.stop();
    emit newAngularSpeed(0.0);
    emit newForwardSpeed(0.0);
    RobotModule::reset();
    if(xsens->isEnabled()){
        if(xsens->getHealthStatus().isHealthOk()){
            targetHeading = xsens->getHeading();
            emit dataChanged(this);
            this->setHealthToOk();
            timer.start(getSettingsValue("timer").toInt());
            turnTimer.start(getSettingsValue("driveTime").toInt());
        }else{
            this->stopOnXsensError();
        }
    }else{
        this->stop();
    }
}

void Behaviour_XsensFollowing::controlLoop()
{
    if (this->isEnabled() == false){
        logger->info("not enabled - controlloop");
        this->stop();
        return;
    }

    if(!xsens->isEnabled() || !xsens->getHealthStatus().isHealthOk())
    {
        this->stopOnXsensError();
        return;
    }

    double currentHeading = xsens->getHeading();
    double diffHeading = Angles::deg2deg(targetHeading - currentHeading);
    double ctrAngleSpeed = 0.0;

    if(fabs(diffHeading) < getSettingsValue("delta").toDouble())
    {
        ctrAngleSpeed = 0.0;
    } else {
        ctrAngleSpeed = getSettingsValue("kp").toFloat()*diffHeading;
    }

    addData("heading current",currentHeading);
    addData("heading target", targetHeading);
    addData("heading difference", diffHeading);
    emit dataChanged(this);
    emit newAngularSpeed(ctrAngleSpeed);
    emit newForwardSpeed(getSettingsValue("ffSpeed").toFloat());
}

void Behaviour_XsensFollowing::turnNinety()
{
    if (this->isEnabled() == false){
        logger->info("not enabled - 90");
        this->stop();
        return;
    }
    logger->info("Turn 90");
    qDebug()<< "oldTargetHeading" << targetHeading;
    if(getSettingsValue("enableTurn").toBool() == true){
        if(getSettingsValue("turnClockwise").toBool() == true){
            targetHeading = Angles::deg2deg(targetHeading+90);
        } else {
            targetHeading = Angles::deg2deg(targetHeading-90);
        }
    }
    qDebug()<< "newTargetHeading" << targetHeading;
}

void Behaviour_XsensFollowing::refreshHeading()
{
    //logger->debug("Xsens follow refresh heading");
    if (this->isEnabled() == false){
        logger->info("Not enabled!");
        return;
    }
    if(xsens->isEnabled()){

        this->dataLockerMutex.lock();

        targetHeading = this->xsens->getHeading();
        addData("heading target", targetHeading);
        dataChanged( this );
        this->dataLockerMutex.unlock();

    }
}

void Behaviour_XsensFollowing::stopOnXsensError()
{
    if (!isEnabled()) {
        return;
    }

    logger->info("Xsens follow stop error");
    this->setEnabled(false);
    timer.stop();
    turnTimer.stop();
    setHealthToSick("xsens error");
    setEnabled(false);
    emit newAngularSpeed(0.0);
    emit newForwardSpeed(0.0);
    emit finished(this,false);
}

QList<RobotModule*> Behaviour_XsensFollowing::getDependencies()
{
    QList<RobotModule*> ret;
    ret.append(tcl);
    ret.append(xsens);
    return ret;
}

QWidget* Behaviour_XsensFollowing::createView(QWidget* parent)
{
    return new XsensFollowingForm(parent, this);
}

void Behaviour_XsensFollowing::controlEnabledChanged(bool b){
    if(b == false){
        logger->info("No longer enabled!");
        QTimer::singleShot(0, this, SLOT(stop()));
    }
}
<commit_msg>kleiner fehler -> falscher slot name<commit_after>#include "behaviour_xsensfollowing.h"
#include <QtGui>
#include <Behaviour_XsensFollowing/xsensfollowingform.h>
#include <Framework/Angles.h>

Behaviour_XsensFollowing::Behaviour_XsensFollowing(QString id, Module_ThrusterControlLoop *tcl, Module_XsensMTi *xsens)
    : RobotBehaviour(id)
{
    this->xsens = xsens;
    this->tcl = tcl;
    turnTimer.moveToThread(this);
    timer.moveToThread(this);

    this->setDefaultValue("timer",30);
    this->setDefaultValue("driveTime",10000);
    this->setDefaultValue("ffSpeed",0.5);
    this->setDefaultValue("kp",0.3);
    this->setDefaultValue("delta",10);
}

bool Behaviour_XsensFollowing::isActive()
{
    return isEnabled();
}

void Behaviour_XsensFollowing::init()
{
    logger->info("Xsens Following init");
    setEnabled(false);
    connect(this,SIGNAL(newAngularSpeed(float)),tcl,SLOT(setAngularSpeed(float)));
    connect(this,SIGNAL(newForwardSpeed(float)),tcl,SLOT(setForwardSpeed(float)));
    connect(&timer,SIGNAL(timeout()),this,SLOT(controlLoop()));
    connect(&turnTimer,SIGNAL(timeout()),this,SLOT(turnNinety()));
    connect(this, SIGNAL(enabled(bool)), this, SLOT(controlEnabledChanged(bool)));
}

void Behaviour_XsensFollowing::startBehaviour()
{
    if (this->isEnabled() == true){
        logger->info("Already enabled/started!");
        return;
    }
    logger->info("Starting Xsens Following");
    this->setEnabled(true);

    targetHeading = xsens->getHeading();

    emit dataChanged(this);

    timer.start(getSettingsValue("timer").toInt());
    turnTimer.start(getSettingsValue("driveTime").toInt());
}

void Behaviour_XsensFollowing::stop()
{
    if(timer.isActive()){
        timer.stop();
    }
    if(turnTimer.isActive()){
        turnTimer.stop();
    }

    if (!isEnabled()) {
        return;
    }

    logger->info("Xsens follow stop");
    this->setEnabled(false);
    setEnabled(false);
    emit newAngularSpeed(0.0);
    emit newForwardSpeed(0.0);
    logger->info("Stop Xsens Following");
    emit finished(this,true);
}

void Behaviour_XsensFollowing::reset()
{
    logger->info("Xsens follow reset");
    if (this->isEnabled() == false){
        logger->info("Not enabled!");
        return;
    }
    timer.stop();
    turnTimer.stop();
    emit newAngularSpeed(0.0);
    emit newForwardSpeed(0.0);
    RobotModule::reset();
    if(xsens->isEnabled()){
        if(xsens->getHealthStatus().isHealthOk()){
            targetHeading = xsens->getHeading();
            emit dataChanged(this);
            this->setHealthToOk();
            timer.start(getSettingsValue("timer").toInt());
            turnTimer.start(getSettingsValue("driveTime").toInt());
        }else{
            this->stopOnXsensError();
        }
    }else{
        this->stop();
    }
}

void Behaviour_XsensFollowing::controlLoop()
{
    if (this->isEnabled() == false){
        logger->info("not enabled - controlloop");
        this->stop();
        return;
    }

    if(!xsens->isEnabled() || !xsens->getHealthStatus().isHealthOk())
    {
        this->stopOnXsensError();
        return;
    }

    double currentHeading = xsens->getHeading();
    double diffHeading = Angles::deg2deg(targetHeading - currentHeading);
    double ctrAngleSpeed = 0.0;

    if(fabs(diffHeading) < getSettingsValue("delta").toDouble())
    {
        ctrAngleSpeed = 0.0;
    } else {
        ctrAngleSpeed = getSettingsValue("kp").toFloat()*diffHeading;
    }

    addData("heading current",currentHeading);
    addData("heading target", targetHeading);
    addData("heading difference", diffHeading);
    emit dataChanged(this);
    emit newAngularSpeed(ctrAngleSpeed);
    emit newForwardSpeed(getSettingsValue("ffSpeed").toFloat());
}

void Behaviour_XsensFollowing::turnNinety()
{
    if (this->isEnabled() == false){
        logger->info("not enabled - 90");
        this->stop();
        return;
    }
    logger->info("Turn 90");
    if(getSettingsValue("enableTurn").toBool() == true){
        if(getSettingsValue("turnClockwise").toBool() == true){
            targetHeading = Angles::deg2deg(targetHeading+90);
        } else {
            targetHeading = Angles::deg2deg(targetHeading-90);
        }
    }
}

void Behaviour_XsensFollowing::refreshHeading()
{

    //logger->debug("Xsens follow refresh heading");
    if (this->isEnabled() == false){
        logger->info("Not enabled!");
        return;
    }
    if(xsens->isEnabled()){

        this->dataLockerMutex.lock();

        targetHeading = this->xsens->getHeading();
        addData("heading target", targetHeading);
        dataChanged( this );
        this->dataLockerMutex.unlock();

    }
}

void Behaviour_XsensFollowing::stopOnXsensError()
{
    if (!isEnabled()) {
        return;
    }

    logger->info("Xsens follow stop error");
    this->setEnabled(false);
    timer.stop();
    turnTimer.stop();
    setHealthToSick("xsens error");
    setEnabled(false);
    emit newAngularSpeed(0.0);
    emit newForwardSpeed(0.0);
    emit finished(this,false);
}

QList<RobotModule*> Behaviour_XsensFollowing::getDependencies()
{
    QList<RobotModule*> ret;
    ret.append(tcl);
    ret.append(xsens);
    return ret;
}

QWidget* Behaviour_XsensFollowing::createView(QWidget* parent)
{
    return new XsensFollowingForm(parent, this);
}

void Behaviour_XsensFollowing::controlEnabledChanged(bool b){
    if(b == false){
        logger->info("No longer enabled!");
        QTimer::singleShot(0, this, SLOT(stop()));
    }
}
<|endoftext|>


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

#include    <set>

#include    "StroikaConfig.h"

#include    "../Characters/SDKString.h"
#include    "../Characters/Format.h"
#include    "../Characters/String_Constant.h"
#include    "../Execution/Exceptions.h"
#include    "../Execution/StringException.h"

#include    "Locale.h"

using   namespace   Stroika::Foundation;
using   namespace   Stroika::Foundation::Configuration;

using   Characters::String_Constant;

// Comment this in to turn on aggressive noisy DbgTrace in this module
//#define   USE_NOISY_TRACE_IN_THIS_MODULE_       1

/*
********************************************************************************
*********** Configuration::UsePlatformDefaultLocaleAsDefaultLocale *************
********************************************************************************
*/
void    Configuration::UsePlatformDefaultLocaleAsDefaultLocale ()
{
    locale::global (GetPlatformDefaultLocale ());
}

/*
********************************************************************************
************************* Configuration::GetAvailableLocales *******************
********************************************************************************
*/
#if     0
EnumSystemLocales(EnumLocalesProc, LCID_INSTALLED);
// the enumeration callback function
BOOL CALLBACK EnumLocalesProc(LPTSTR lpLocaleString)
{
    LCID uiCurLocale;
    TCHAR szCurNam[STR_LEN];
    if (!lpLocaleString)
        return FALSE;
// This enumeration returns the LCID as a character string while
// we will be using numbers in other NLS calls.
    uiCurLocale = uiConvertStrToInt(lpLocaleString);
// Get the language name associated with this locale ID.
    GetLocaleInfo(uiCurLocale, LOCALE_SLANGUAGE, szCurName, STR_LEN);
    return TRUE;
}
#endif
vector<Characters::String>    Configuration::GetAvailableLocales ()
{
    // horrible!!!! - see TOOD
    vector<Characters::String>  result;
    result.reserve (10);
    IgnoreExceptionsForCall (result.push_back (FindLocaleName (String_Constant { L"en" }, String_Constant { L"us" })));
    return result;
}

/*
********************************************************************************
*************************** Configuration::FindLocaleName **********************
********************************************************************************
*/
Characters::String    Configuration::FindLocaleName (const Characters::String& iso2LetterLanguageCode, const Characters::String& iso2LetterTerritoryCode)
{
    using   Characters::String;
    Require (iso2LetterLanguageCode.length () == 2);
    Require (iso2LetterTerritoryCode.length () == 2);       // may lift this in the future and make it optional

#if     USE_NOISY_TRACE_IN_THIS_MODULE_
    Debug::TraceContextBumper  ctx ("Configuration::FindLocaleName");
    DbgTrace (L"(%s,%s)", iso2LetterLanguageCode.c_str (), iso2LetterTerritoryCode.c_str ());
#endif

    // This is a HORRIBLE way - but I know of no better (especially no better portable way).
    // See todo for planned fixes
    //  --LGP 2013-03-02
    //
    // Could make less heinous with memoizing, but not currently used much, and I plan todo much better impl...
    static  set<String> part1 {
        iso2LetterLanguageCode,
        iso2LetterLanguageCode.ToLowerCase (),
        iso2LetterLanguageCode.ToUpperCase (),
    };
    static  const   set<String> part2 {
        String_Constant { L"-" },
        String_Constant { L"_" },
        String_Constant { L"." },
        String_Constant { L" " },
    };
    static  set<String> part3 {
        iso2LetterTerritoryCode,
        iso2LetterTerritoryCode.ToLowerCase (),
        iso2LetterTerritoryCode.ToUpperCase (),
    };
    static  const   set<String> part4 {
        String_Constant { L"" },
        String_Constant { L".utf8" },
    };
    for (String i1 : part1) {
        for (String i2 : part2) {
            for (String i3 : part3) {
                for (String i4 : part4) {
#if     USE_NOISY_TRACE_IN_THIS_MODULE_
                    DbgTrace (L"***trying locale (i1 + i2 + i3 + i4).AsUTF8 ().c_str ()=%s", (i1 + i2 + i3 + i4).c_str ());
#endif
                    IgnoreExceptionsForCall (return String::FromNarrowSDKString (locale ((i1 + i2 + i3 + i4).AsUTF8 ().c_str ()).name ()));
                }
            }
        }
    }
    Execution::Throw (Execution::StringException (Characters::Format (L"Locale (%s-%s) not found", iso2LetterLanguageCode.c_str (), iso2LetterTerritoryCode.c_str ())));
}

/*
********************************************************************************
*************************** Configuration::FindNamedLocale *********************
********************************************************************************
*/
locale    Configuration::FindNamedLocale (const Characters::String& iso2LetterLanguageCode, const Characters::String& iso2LetterTerritoryCode)
{
    return locale (FindLocaleName (iso2LetterLanguageCode, iso2LetterTerritoryCode).AsNarrowSDKString ().c_str ());
}
<commit_msg>fixed bug with Configuration::FindLocaleName - part1 and part3 cannot be static!<commit_after>/*
 * Copyright(c) Sophist Solutions, Inc. 1990-2016.  All rights reserved
 */
#include    "../StroikaPreComp.h"

#include    <set>

#include    "StroikaConfig.h"

#include    "../Characters/SDKString.h"
#include    "../Characters/Format.h"
#include    "../Characters/String_Constant.h"
#include    "../Execution/Exceptions.h"
#include    "../Execution/StringException.h"

#include    "Locale.h"

using   namespace   Stroika::Foundation;
using   namespace   Stroika::Foundation::Configuration;

using   Characters::String_Constant;

// Comment this in to turn on aggressive noisy DbgTrace in this module
//#define   USE_NOISY_TRACE_IN_THIS_MODULE_       1

/*
********************************************************************************
*********** Configuration::UsePlatformDefaultLocaleAsDefaultLocale *************
********************************************************************************
*/
void    Configuration::UsePlatformDefaultLocaleAsDefaultLocale ()
{
    locale::global (GetPlatformDefaultLocale ());
}

/*
********************************************************************************
************************* Configuration::GetAvailableLocales *******************
********************************************************************************
*/
#if     0
EnumSystemLocales(EnumLocalesProc, LCID_INSTALLED);
// the enumeration callback function
BOOL CALLBACK EnumLocalesProc(LPTSTR lpLocaleString)
{
    LCID uiCurLocale;
    TCHAR szCurNam[STR_LEN];
    if (!lpLocaleString)
        return FALSE;
// This enumeration returns the LCID as a character string while
// we will be using numbers in other NLS calls.
    uiCurLocale = uiConvertStrToInt(lpLocaleString);
// Get the language name associated with this locale ID.
    GetLocaleInfo(uiCurLocale, LOCALE_SLANGUAGE, szCurName, STR_LEN);
    return TRUE;
}
#endif
vector<Characters::String>    Configuration::GetAvailableLocales ()
{
    // horrible!!!! - see TOOD
    vector<Characters::String>  result;
    result.reserve (10);
    IgnoreExceptionsForCall (result.push_back (FindLocaleName (String_Constant { L"en" }, String_Constant { L"us" })));
    return result;
}

/*
********************************************************************************
*************************** Configuration::FindLocaleName **********************
********************************************************************************
*/
Characters::String    Configuration::FindLocaleName (const Characters::String& iso2LetterLanguageCode, const Characters::String& iso2LetterTerritoryCode)
{
    using   Characters::String;
    Require (iso2LetterLanguageCode.length () == 2);
    Require (iso2LetterTerritoryCode.length () == 2);       // may lift this in the future and make it optional

#if     USE_NOISY_TRACE_IN_THIS_MODULE_
    Debug::TraceContextBumper  ctx ("Configuration::FindLocaleName");
    DbgTrace (L"(%s,%s)", iso2LetterLanguageCode.c_str (), iso2LetterTerritoryCode.c_str ());
#endif

    // This is a HORRIBLE way - but I know of no better (especially no better portable way).
    // See todo for planned fixes
    //  --LGP 2013-03-02
    //
    // Could make less heinous with memoizing, but not currently used much, and I plan todo much better impl...
    set<String> part1 {
        iso2LetterLanguageCode,
        iso2LetterLanguageCode.ToLowerCase (),
        iso2LetterLanguageCode.ToUpperCase (),
    };
    static  const   set<String> part2 {
        String_Constant { L"-" },
        String_Constant { L"_" },
        String_Constant { L"." },
        String_Constant { L" " },
    };
    set<String> part3 {
        iso2LetterTerritoryCode,
        iso2LetterTerritoryCode.ToLowerCase (),
        iso2LetterTerritoryCode.ToUpperCase (),
    };
    static  const   set<String> part4 {
        String_Constant { L"" },
        String_Constant { L".utf8" },
    };
    for (String i1 : part1) {
        for (String i2 : part2) {
            for (String i3 : part3) {
                for (String i4 : part4) {
#if     USE_NOISY_TRACE_IN_THIS_MODULE_
                    DbgTrace (L"***trying locale (i1 + i2 + i3 + i4).AsUTF8 ().c_str ()=%s", (i1 + i2 + i3 + i4).c_str ());
#endif
                    IgnoreExceptionsForCall (return String::FromNarrowSDKString (locale ((i1 + i2 + i3 + i4).AsUTF8 ().c_str ()).name ()));
                }
            }
        }
    }
    Execution::Throw (Execution::StringException (Characters::Format (L"Locale (%s-%s) not found", iso2LetterLanguageCode.c_str (), iso2LetterTerritoryCode.c_str ())));
}

/*
********************************************************************************
*************************** Configuration::FindNamedLocale *********************
********************************************************************************
*/
locale    Configuration::FindNamedLocale (const Characters::String& iso2LetterLanguageCode, const Characters::String& iso2LetterTerritoryCode)
{
    return locale (FindLocaleName (iso2LetterLanguageCode, iso2LetterTerritoryCode).AsNarrowSDKString ().c_str ());
}
<|endoftext|>


<commit_before>/*
 * Copyright(c) Sophist Solutions, Inc. 1990-2014.  All rights reserved
 */
#ifndef _Stroika_Foundation_Memory_SharedByValue_inl_
#define _Stroika_Foundation_Memory_SharedByValue_inl_   1

/*
 ********************************************************************************
 ***************************** Implementation Details ***************************
 ********************************************************************************
 */

namespace   Stroika {
    namespace   Foundation {
        namespace   Memory {

            /*
            ********************************************************************************
            ************** SharedByValue_CopyByFunction<T,SHARED_IMLP> *********************
            ********************************************************************************
            */
#if     qCompilerAndStdLib_lambda_default_argument_with_template_param_as_function_cast_Buggy
            template    <typename   T, typename SHARED_IMLP>
            SHARED_IMLP  SharedByValue_CopyByFunction<T, SHARED_IMLP>::DefaultElementCopier_ (const T& t)
            {
                return SHARED_IMLP (new T (t));
            }
#endif
            template    <typename   T, typename SHARED_IMLP>
            inline  SharedByValue_CopyByFunction<T, SHARED_IMLP>::SharedByValue_CopyByFunction (SHARED_IMLP (*copier) (const T&))
                : fCopier (copier)
            {
            }
            template    <typename   T, typename SHARED_IMLP>
            inline  SHARED_IMLP  SharedByValue_CopyByFunction<T, SHARED_IMLP>::Copy (const T& t) const
            {
                return (*fCopier) (t);
            }

            /*
            ********************************************************************************
            *************** SharedByValue_CopyByDefault<T,SHARED_IMLP> *********************
            ********************************************************************************
            */
            template    <typename   T, typename SHARED_IMLP>
            inline  SHARED_IMLP  SharedByValue_CopyByDefault<T, SHARED_IMLP>::Copy (const T& t)
            {
                return SHARED_IMLP (new T (t));
            }

            /*
            ********************************************************************************
            ****************************** SharedByValue<TRAITS> ***************************
            ********************************************************************************
            */
            template    <typename TRAITS>
            inline  SharedByValue<TRAITS>::SharedByValue ()
                : fCopier_ (copier_type ())
                , fSharedImpl_ ()
            {
            }
            template    <typename TRAITS>
            inline  SharedByValue<TRAITS>::SharedByValue (nullptr_t n)
                : fCopier_ (copier_type ())
                , fSharedImpl_ ()
            {
            }
            template    <typename TRAITS>
            inline  SharedByValue<TRAITS>::SharedByValue (const SharedByValue<TRAITS>& from)
                : fCopier_ (from.fCopier_)
                , fSharedImpl_ (from.fSharedImpl_)
            {
            }
            template    <typename TRAITS>
            inline  SharedByValue<TRAITS>::SharedByValue (SharedByValue<TRAITS>&& from)
                : fCopier_ (from.fCopier_)
                , fSharedImpl_ (std::move (from.fSharedImpl_))
            {
            }
            template    <typename TRAITS>
            inline  SharedByValue<TRAITS>::SharedByValue (const shared_ptr_type& from, const copier_type& copier)
                : fCopier_ (copier)
                , fSharedImpl_ (from)
            {
            }
            template    <typename TRAITS>
            inline  SharedByValue<TRAITS>::SharedByValue (shared_ptr_type&& from, const copier_type& copier)
                : fCopier_ (copier)
                , fSharedImpl_ (std::move (from))
            {
            }
            template    <typename TRAITS>
            inline  SharedByValue<TRAITS>::SharedByValue (element_type* from, const copier_type& copier)
                : fCopier_ (copier)
                , fSharedImpl_ (from)
            {
            }
            template    <typename TRAITS>
            inline  SharedByValue<TRAITS>& SharedByValue<TRAITS>::operator= (const SharedByValue<TRAITS>& src)
            {
                if (this != &src) {
                    fCopier_ = src.fCopier_;
                    fSharedImpl_ = src.fSharedImpl_;
                }
                return *this;
            }
            template    <typename TRAITS>
            inline  const typename SharedByValue<TRAITS>::element_type*    SharedByValue<TRAITS>::get () const
            {
                return (fSharedImpl_.get ());
            }
            template    <typename TRAITS>
            typename SharedByValue<TRAITS>::element_type* SharedByValue<TRAITS>::get ()
            {
                element_type*  ptr =   fSharedImpl_.get ();
                /*
                 * For non-const pointing, we must clone ourselves (if there are
                 * extra referneces). If we are a nullptr pointer, nobody could actually
                 * rereference it anyhow, so don't bother with the Assure1Reference()
                 * in that case.
                 */
                if (ptr == nullptr) {
                    return nullptr;
                }
                Assure1Reference ();
                ptr = fSharedImpl_.get ();
                EnsureNotNull (ptr);
                return ptr;
            }
            template    <typename TRAITS>
            inline  const typename SharedByValue<TRAITS>::element_type*    SharedByValue<TRAITS>::operator-> () const
            {
                return (fSharedImpl_.get ());
            }
            template    <typename TRAITS>
            inline  typename SharedByValue<TRAITS>::element_type* SharedByValue<TRAITS>::operator-> ()
            {
                return get ();
            }
            template    <typename TRAITS>
            inline  const typename SharedByValue<TRAITS>::element_type&    SharedByValue<TRAITS>::operator* () const
            {
                const element_type*  ptr =   get ();
                EnsureNotNull (ptr);
                return *ptr;
            }
            template    <typename TRAITS>
            typename SharedByValue<TRAITS>::element_type& SharedByValue<TRAITS>::operator* ()
            {
                /*
                 * For non-const dereferencing, we must clone ourselves (if there are
                 * extra referneces).
                 */
                Assure1Reference ();
                element_type*  ptr =   get ();
                EnsureNotNull (ptr);
                return *ptr;
            }
            template    <typename TRAITS>
            bool SharedByValue<TRAITS>::operator== (const SharedByValue<TRAITS>& rhs) const
            {
                return fSharedImpl_ == rhs.fSharedImpl_;
            }
            template    <typename TRAITS>
            bool SharedByValue<TRAITS>::operator!= (const SharedByValue<TRAITS>& rhs) const
            {
                return fSharedImpl_ != rhs.fSharedImpl_;
            }
            template    <typename TRAITS>
            SharedByValue_State    SharedByValue<TRAITS>::GetSharingState () const
            {
                switch (fSharedImpl_.use_count ()) {
                    case 0:
                        Assert (fSharedImpl_.get () == nullptr);
                        return SharedByValue_State::eNull;
                    case 1:
                        Assert (fSharedImpl_.get () != nullptr);
                        Assert (fSharedImpl_.unique ());
                        return SharedByValue_State::eSolo;
                    default:
                        Assert (fSharedImpl_.get () != nullptr);
                        Assert (not fSharedImpl_.unique ());
                        return SharedByValue_State::eShared;
                }
            }
            template    <typename TRAITS>
            bool    SharedByValue<TRAITS>::unique () const
            {
                return fSharedImpl_.unique ();
            }
            template    <typename TRAITS>
            inline  void    SharedByValue<TRAITS>::Assure1Reference ()
            {
                if (!fSharedImpl_.unique ()) {
                    BreakReferences_ ();
                }
            }
            template    <typename TRAITS>
            void    SharedByValue<TRAITS>::BreakReferences_ ()
            {
                element_type*  ptr =   fSharedImpl_.get ();
                RequireNotNull (ptr);
                /*
                 *      For a valid pointer that is reference counted and multiply shared,
                 *  make a copy of that pointer via our fCloner function, and assign
                 *  that cloned reference to this.
                 *
                 *      Note that by doing so, we remove any references to the current
                 *  item, and end up with our having the sole reference to the new copy of fPtr.
                 *
                 *      Since we will be cloning the given pointer, we assume(assert) that
                 *  it is non-nullptr.
                 */
                //Require (!SHARED_IMLP::unique ());    This is not NECESSARILY so. Another thread could have just released this pointer, in which case
                // the creation of a new object was pointless, but harmless, as the assignemnt should decrement to zero the old
                // value and it should go away.
                *this = SharedByValue<TRAITS> (fCopier_.Copy (*ptr), fCopier_);
                Ensure (fSharedImpl_.unique ());
            }

        }
    }
}
#endif  /*_Stroika_Foundation_Memory_SharedByValue_inl_*/
<commit_msg>Minor tweaks to SharedByValue<TRAITS><commit_after>/*
 * Copyright(c) Sophist Solutions, Inc. 1990-2014.  All rights reserved
 */
#ifndef _Stroika_Foundation_Memory_SharedByValue_inl_
#define _Stroika_Foundation_Memory_SharedByValue_inl_   1

/*
 ********************************************************************************
 ***************************** Implementation Details ***************************
 ********************************************************************************
 */

namespace   Stroika {
    namespace   Foundation {
        namespace   Memory {

            /*
            ********************************************************************************
            ************** SharedByValue_CopyByFunction<T,SHARED_IMLP> *********************
            ********************************************************************************
            */
#if     qCompilerAndStdLib_lambda_default_argument_with_template_param_as_function_cast_Buggy
            template    <typename   T, typename SHARED_IMLP>
            SHARED_IMLP  SharedByValue_CopyByFunction<T, SHARED_IMLP>::DefaultElementCopier_ (const T& t)
            {
                return SHARED_IMLP (new T (t));
            }
#endif
            template    <typename   T, typename SHARED_IMLP>
            inline  SharedByValue_CopyByFunction<T, SHARED_IMLP>::SharedByValue_CopyByFunction (SHARED_IMLP (*copier) (const T&))
                : fCopier (copier)
            {
            }
            template    <typename   T, typename SHARED_IMLP>
            inline  SHARED_IMLP  SharedByValue_CopyByFunction<T, SHARED_IMLP>::Copy (const T& t) const
            {
                return (*fCopier) (t);
            }

            /*
            ********************************************************************************
            *************** SharedByValue_CopyByDefault<T,SHARED_IMLP> *********************
            ********************************************************************************
            */
            template    <typename   T, typename SHARED_IMLP>
            inline  SHARED_IMLP  SharedByValue_CopyByDefault<T, SHARED_IMLP>::Copy (const T& t)
            {
                return SHARED_IMLP (new T (t));
            }

            /*
            ********************************************************************************
            ****************************** SharedByValue<TRAITS> ***************************
            ********************************************************************************
            */
            template    <typename TRAITS>
            inline  SharedByValue<TRAITS>::SharedByValue ()
                : fCopier_ (copier_type ())
                , fSharedImpl_ ()
            {
            }
            template    <typename TRAITS>
            inline  SharedByValue<TRAITS>::SharedByValue (nullptr_t n)
                : fCopier_ (copier_type ())
                , fSharedImpl_ ()
            {
            }
            template    <typename TRAITS>
            inline  SharedByValue<TRAITS>::SharedByValue (const SharedByValue<TRAITS>& from)
                : fCopier_ (from.fCopier_)
                , fSharedImpl_ (from.fSharedImpl_)
            {
            }
            template    <typename TRAITS>
            inline  SharedByValue<TRAITS>::SharedByValue (SharedByValue<TRAITS>&& from)
                : fCopier_ (from.fCopier_)
                , fSharedImpl_ (std::move (from.fSharedImpl_))
            {
            }
            template    <typename TRAITS>
            inline  SharedByValue<TRAITS>::SharedByValue (const shared_ptr_type& from, const copier_type& copier)
                : fCopier_ (copier)
                , fSharedImpl_ (from)
            {
            }
            template    <typename TRAITS>
            inline  SharedByValue<TRAITS>::SharedByValue (shared_ptr_type&& from, const copier_type& copier)
                : fCopier_ (copier)
                , fSharedImpl_ (std::move (from))
            {
            }
            template    <typename TRAITS>
            inline  SharedByValue<TRAITS>::SharedByValue (element_type* from, const copier_type& copier)
                : fCopier_ (copier)
                , fSharedImpl_ (from)
            {
            }
            template    <typename TRAITS>
            inline  SharedByValue<TRAITS>& SharedByValue<TRAITS>::operator= (const SharedByValue<TRAITS>& src)
            {
                if (this != &src) {
                    fCopier_ = src.fCopier_;
                    fSharedImpl_ = src.fSharedImpl_;
                }
                return *this;
            }
            template    <typename TRAITS>
            inline  const typename SharedByValue<TRAITS>::element_type*    SharedByValue<TRAITS>::get () const
            {
                return fSharedImpl_.get ();
            }
            template    <typename TRAITS>
            inline  typename SharedByValue<TRAITS>::element_type* SharedByValue<TRAITS>::get ()
            {
                element_type*  ptr =   fSharedImpl_.get ();
                /*
                 * For non-const pointing, we must clone ourselves (if there are
                 * extra referneces). If we are a nullptr pointer, nobody could actually
                 * rereference it anyhow, so don't bother with the Assure1Reference()
                 * in that case.
                 */
                if (ptr != nullptr) {
                    Assure1Reference ();
                    ptr = fSharedImpl_.get ();
                    EnsureNotNull (ptr);
                }
                return ptr;
            }
            template    <typename TRAITS>
            inline  const typename SharedByValue<TRAITS>::element_type*    SharedByValue<TRAITS>::operator-> () const
            {
                return fSharedImpl_.get ();
            }
            template    <typename TRAITS>
            inline  typename SharedByValue<TRAITS>::element_type* SharedByValue<TRAITS>::operator-> ()
            {
                return get ();
            }
            template    <typename TRAITS>
            inline  const typename SharedByValue<TRAITS>::element_type&    SharedByValue<TRAITS>::operator* () const
            {
                const element_type*  ptr =   get ();
                EnsureNotNull (ptr);
                return *ptr;
            }
            template    <typename TRAITS>
            inline  typename SharedByValue<TRAITS>::element_type&   SharedByValue<TRAITS>::operator* ()
            {
                /*
                 * For non-const dereferencing, we must clone ourselves (if there are
                 * extra referneces).
                 */
                Assure1Reference ();
                element_type*  ptr =   get ();
                EnsureNotNull (ptr);
                return *ptr;
            }
            template    <typename TRAITS>
            inline  bool    SharedByValue<TRAITS>::operator== (const SharedByValue<TRAITS>& rhs) const
            {
                return fSharedImpl_ == rhs.fSharedImpl_;
            }
            template    <typename TRAITS>
            inline  bool    SharedByValue<TRAITS>::operator!= (const SharedByValue<TRAITS>& rhs) const
            {
                return fSharedImpl_ != rhs.fSharedImpl_;
            }
            template    <typename TRAITS>
            inline  SharedByValue_State    SharedByValue<TRAITS>::GetSharingState () const
            {
                switch (fSharedImpl_.use_count ()) {
                    case 0:
                        Assert (fSharedImpl_.get () == nullptr);
                        return SharedByValue_State::eNull;
                    case 1:
                        Assert (fSharedImpl_.get () != nullptr);
                        Assert (fSharedImpl_.unique ());
                        return SharedByValue_State::eSolo;
                    default:
                        Assert (fSharedImpl_.get () != nullptr);
                        Assert (not fSharedImpl_.unique ());
                        return SharedByValue_State::eShared;
                }
            }
            template    <typename TRAITS>
            inline  bool    SharedByValue<TRAITS>::unique () const
            {
                return fSharedImpl_.unique ();
            }
            template    <typename TRAITS>
            inline  void    SharedByValue<TRAITS>::Assure1Reference ()
            {
                if (!fSharedImpl_.unique ()) {
                    BreakReferences_ ();
                }
            }
            template    <typename TRAITS>
            void    SharedByValue<TRAITS>::BreakReferences_ ()
            {
                element_type*  ptr =   fSharedImpl_.get ();
                RequireNotNull (ptr);
                /*
                 *      For a valid pointer that is reference counted and multiply shared,
                 *  make a copy of that pointer via our fCloner function, and assign
                 *  that cloned reference to this.
                 *
                 *      Note that by doing so, we remove any references to the current
                 *  item, and end up with our having the sole reference to the new copy of fPtr.
                 *
                 *      Since we will be cloning the given pointer, we assume(assert) that
                 *  it is non-nullptr.
                 */
                //Require (!SHARED_IMLP::unique ());    This is not NECESSARILY so. Another thread could have just released this pointer, in which case
                // the creation of a new object was pointless, but harmless, as the assignemnt should decrement to zero the old
                // value and it should go away.
                *this = SharedByValue<TRAITS> (fCopier_.Copy (*ptr), fCopier_);
                Ensure (fSharedImpl_.unique ());
            }

        }
    }
}
#endif  /*_Stroika_Foundation_Memory_SharedByValue_inl_*/
<|endoftext|>


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

#include <algorithm>
#include <cstdlib>

#include "../../Foundation/Characters/Format.h"
#include "../../Foundation/Characters/String_Constant.h"
#include "../../Foundation/Characters/ToString.h"
#include "../../Foundation/Containers/Common.h"
#include "../../Foundation/DataExchange/BadFormatException.h"
#include "../../Foundation/Debug/Assertions.h"
#include "../../Foundation/Execution/Exceptions.h"
#include "../../Foundation/IO/Network/HTTP/Headers.h"
#include "../../Foundation/IO/Network/HTTP/MessageStartTextInputStreamBinaryAdapter.h"
#include "../../Foundation/Memory/SmallStackBuffer.h"

#include "ClientErrorException.h"

#include "Connection.h"

using namespace Stroika::Foundation;
using namespace Stroika::Foundation::Characters;
using namespace Stroika::Foundation::Containers;
using namespace Stroika::Foundation::Memory;

using namespace Stroika::Frameworks;
using namespace Stroika::Frameworks::WebServer;

// Comment this in to turn on aggressive noisy DbgTrace in this module
//#define   USE_NOISY_TRACE_IN_THIS_MODULE_       1

/*
 ********************************************************************************
 ***************************** WebServer::Connection ****************************
 ********************************************************************************
 */
#if qCompilerAndStdLib_copy_elision_Warning_too_aggressive_when_not_copyable_Buggy
DISABLE_COMPILER_CLANG_WARNING_START ("clang diagnostic ignored \"-Wpessimizing-move\"");
#endif
Connection::Connection (Socket s, const InterceptorChain& interceptorChain)
    : fInterceptorChain_{interceptorChain}
    , fSocket_ (s)
    , fSocketStream_ (s)
    , fMessage_{
          move (Request (fSocketStream_)),
          move (Response (s, fSocketStream_, DataExchange::PredefinedInternetMediaType::OctetStream_CT ())),
          s.GetPeerAddress ()}
{
}
#if qCompilerAndStdLib_copy_elision_Warning_too_aggressive_when_not_copyable_Buggy
DISABLE_COMPILER_CLANG_WARNING_END ("clang diagnostic ignored \"-Wpessimizing-move\"");
#endif

Connection::~Connection ()
{
    if (fMessage_.PeekResponse ()->GetState () != Response::State::eCompleted) {
        IgnoreExceptionsForCall (fMessage_.PeekResponse ()->Abort ());
    }
    Require (fMessage_.PeekResponse ()->GetState () == Response::State::eCompleted);
}

void Connection::ReadHeaders ()
{
    // @todo - DONT use TextStream::ReadLine - because that asserts SEEKABLE - which may not be true (and probably isn't here anymore)
    // Instead - we need a special variant that looks for CRLF - which doesn't require backtracking...!!!

    Foundation::IO::Network::HTTP::MessageStartTextInputStreamBinaryAdapter inTextStream (fMessage_.PeekRequest ()->GetInputStream ());
    {
        // Read METHOD line
        String           line = inTextStream.ReadLine ();
        Sequence<String> tokens{line.Tokenize (Set<Character>{' '})};
        if (tokens.size () < 3) {
            DbgTrace (L"tokens=%s, line='%s'", Characters::ToString (tokens).c_str (), line.c_str ());
            Execution::Throw (ClientErrorException (Characters::Format (L"Bad METHOD REQUEST HTTP line (%s)", line.c_str ())));
        }
        fMessage_.PeekRequest ()->SetHTTPMethod (tokens[0]);
        if (tokens[1].empty ()) {
            // should check if GET/PUT/DELETE etc...
            DbgTrace (L"tokens=%s, line='%s'", Characters::ToString (tokens).c_str (), line.c_str ());
            Execution::Throw (ClientErrorException (String_Constant (L"Bad HTTP REQUEST line - missing host-relative URL")));
        }
        using IO::Network::URL;
        fMessage_.PeekRequest ()->SetURL (URL::Parse (tokens[1], URL::eAsRelativeURL));
        if (fMessage_.PeekRequest ()->GetHTTPMethod ().empty ()) {
            // should check if GET/PUT/DELETE etc...
            DbgTrace (L"tokens=%s, line='%s'", Characters::ToString (tokens).c_str (), line.c_str ());
            Execution::Throw (ClientErrorException (String_Constant (L"Bad METHOD in REQUEST HTTP line")));
        }
    }
    while (true) {
        String line = inTextStream.ReadLine ();
        if (line == String_Constant (L"\r\n") or line.empty ()) {
            return; // done
        }

        // add subsequent items to the header map
        size_t i = line.find (':');
        if (i == string::npos) {
            DbgTrace (L"line=%s", Characters::ToString (line).c_str ());
            Execution::Throw (ClientErrorException (String_Constant (L"Bad HTTP REQUEST missing colon in headers")));
        }
        else {
            String hdr   = line.SubString (0, i).Trim ();
            String value = line.SubString (i + 1).Trim ();
            fMessage_.PeekRequest ()->AddHeader (hdr, value);
        }
    }
}

void Connection::Close ()
{
    fMessage_.PeekResponse ()->Flush ();
    fSocket_.Close ();
}

bool Connection::ReadAndProcessMessage ()
{
#if USE_NOISY_TRACE_IN_THIS_MODULE_
    Debug::TraceContextBumper ctx (L"Connection::ReadAndProcessMessage");
#endif
    constexpr bool kSupportHTTPKeepAlives_{false}; // @todo - support - now structured so maybe not too hard -- LGP 2016-09-02
    // @todo but be sure REsponse::End () doesnt close socket - just flushes response!

    ReadHeaders (); // bad API. Must rethink...

    if (not kSupportHTTPKeepAlives_) {
        // From https://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html
        //      HTTP/1.1 applications that do not support persistent connections MUST include the "close" connection option in every message.
        GetResponse ().AddHeader (IO::Network::HTTP::HeaderName::kConnection, String_Constant{L"close"});
    }
#if USE_NOISY_TRACE_IN_THIS_MODULE_
    String url = GetRequest ().GetURL ().GetFullURL ();
    DbgTrace (L"Serving page %s", url.c_str ());
#endif
    try {
        fInterceptorChain_.HandleMessage (&fMessage_);
    }
    catch (...) {
        //DbgTrace ("Caught exception halding message");
    }
    GetResponse ().End ();
    return kSupportHTTPKeepAlives_;
}
<commit_msg>Frameworks/WebServer/Connection DbgTrace message on exception<commit_after>/*
 * Copyright(c) Sophist Solutions, Inc. 1990-2017.  All rights reserved
 */
#include "../StroikaPreComp.h"

#include <algorithm>
#include <cstdlib>

#include "../../Foundation/Characters/Format.h"
#include "../../Foundation/Characters/String_Constant.h"
#include "../../Foundation/Characters/ToString.h"
#include "../../Foundation/Containers/Common.h"
#include "../../Foundation/DataExchange/BadFormatException.h"
#include "../../Foundation/Debug/Assertions.h"
#include "../../Foundation/Execution/Exceptions.h"
#include "../../Foundation/IO/Network/HTTP/Headers.h"
#include "../../Foundation/IO/Network/HTTP/MessageStartTextInputStreamBinaryAdapter.h"
#include "../../Foundation/Memory/SmallStackBuffer.h"

#include "ClientErrorException.h"

#include "Connection.h"

using namespace Stroika::Foundation;
using namespace Stroika::Foundation::Characters;
using namespace Stroika::Foundation::Containers;
using namespace Stroika::Foundation::Memory;

using namespace Stroika::Frameworks;
using namespace Stroika::Frameworks::WebServer;

// Comment this in to turn on aggressive noisy DbgTrace in this module
//#define   USE_NOISY_TRACE_IN_THIS_MODULE_       1

/*
 ********************************************************************************
 ***************************** WebServer::Connection ****************************
 ********************************************************************************
 */
#if qCompilerAndStdLib_copy_elision_Warning_too_aggressive_when_not_copyable_Buggy
DISABLE_COMPILER_CLANG_WARNING_START ("clang diagnostic ignored \"-Wpessimizing-move\"");
#endif
Connection::Connection (Socket s, const InterceptorChain& interceptorChain)
    : fInterceptorChain_{interceptorChain}
    , fSocket_ (s)
    , fSocketStream_ (s)
    , fMessage_{
          move (Request (fSocketStream_)),
          move (Response (s, fSocketStream_, DataExchange::PredefinedInternetMediaType::OctetStream_CT ())),
          s.GetPeerAddress ()}
{
}
#if qCompilerAndStdLib_copy_elision_Warning_too_aggressive_when_not_copyable_Buggy
DISABLE_COMPILER_CLANG_WARNING_END ("clang diagnostic ignored \"-Wpessimizing-move\"");
#endif

Connection::~Connection ()
{
    if (fMessage_.PeekResponse ()->GetState () != Response::State::eCompleted) {
        IgnoreExceptionsForCall (fMessage_.PeekResponse ()->Abort ());
    }
    Require (fMessage_.PeekResponse ()->GetState () == Response::State::eCompleted);
}

void Connection::ReadHeaders ()
{
    // @todo - DONT use TextStream::ReadLine - because that asserts SEEKABLE - which may not be true (and probably isn't here anymore)
    // Instead - we need a special variant that looks for CRLF - which doesn't require backtracking...!!!

    Foundation::IO::Network::HTTP::MessageStartTextInputStreamBinaryAdapter inTextStream (fMessage_.PeekRequest ()->GetInputStream ());
    {
        // Read METHOD line
        String           line = inTextStream.ReadLine ();
        Sequence<String> tokens{line.Tokenize (Set<Character>{' '})};
        if (tokens.size () < 3) {
            DbgTrace (L"tokens=%s, line='%s'", Characters::ToString (tokens).c_str (), line.c_str ());
            Execution::Throw (ClientErrorException (Characters::Format (L"Bad METHOD REQUEST HTTP line (%s)", line.c_str ())));
        }
        fMessage_.PeekRequest ()->SetHTTPMethod (tokens[0]);
        if (tokens[1].empty ()) {
            // should check if GET/PUT/DELETE etc...
            DbgTrace (L"tokens=%s, line='%s'", Characters::ToString (tokens).c_str (), line.c_str ());
            Execution::Throw (ClientErrorException (String_Constant (L"Bad HTTP REQUEST line - missing host-relative URL")));
        }
        using IO::Network::URL;
        fMessage_.PeekRequest ()->SetURL (URL::Parse (tokens[1], URL::eAsRelativeURL));
        if (fMessage_.PeekRequest ()->GetHTTPMethod ().empty ()) {
            // should check if GET/PUT/DELETE etc...
            DbgTrace (L"tokens=%s, line='%s'", Characters::ToString (tokens).c_str (), line.c_str ());
            Execution::Throw (ClientErrorException (String_Constant (L"Bad METHOD in REQUEST HTTP line")));
        }
    }
    while (true) {
        String line = inTextStream.ReadLine ();
        if (line == String_Constant (L"\r\n") or line.empty ()) {
            return; // done
        }

        // add subsequent items to the header map
        size_t i = line.find (':');
        if (i == string::npos) {
            DbgTrace (L"line=%s", Characters::ToString (line).c_str ());
            Execution::Throw (ClientErrorException (String_Constant (L"Bad HTTP REQUEST missing colon in headers")));
        }
        else {
            String hdr   = line.SubString (0, i).Trim ();
            String value = line.SubString (i + 1).Trim ();
            fMessage_.PeekRequest ()->AddHeader (hdr, value);
        }
    }
}

void Connection::Close ()
{
    fMessage_.PeekResponse ()->Flush ();
    fSocket_.Close ();
}

bool Connection::ReadAndProcessMessage ()
{
#if USE_NOISY_TRACE_IN_THIS_MODULE_
    Debug::TraceContextBumper ctx (L"Connection::ReadAndProcessMessage");
#endif
    constexpr bool kSupportHTTPKeepAlives_{false}; // @todo - support - now structured so maybe not too hard -- LGP 2016-09-02
    // @todo but be sure REsponse::End () doesnt close socket - just flushes response!

    ReadHeaders (); // bad API. Must rethink...

    if (not kSupportHTTPKeepAlives_) {
        // From https://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html
        //      HTTP/1.1 applications that do not support persistent connections MUST include the "close" connection option in every message.
        GetResponse ().AddHeader (IO::Network::HTTP::HeaderName::kConnection, String_Constant{L"close"});
    }
#if USE_NOISY_TRACE_IN_THIS_MODULE_
    String url = GetRequest ().GetURL ().GetFullURL ();
    DbgTrace (L"Serving page %s", url.c_str ());
#endif
    try {
        fInterceptorChain_.HandleMessage (&fMessage_);
    }
    catch (...) {
#if USE_NOISY_TRACE_IN_THIS_MODULE_
        DbgTrace (L"Interceptor-Chain caught exception handling message: %s", Characters::ToString (current_exception ()).c_str ());
#endif
    }
    GetResponse ().End ();
    return kSupportHTTPKeepAlives_;
}
<|endoftext|>


<commit_before>/*=========================================================================
 *
 *  Copyright Insight Software Consortium
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0.txt
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 *=========================================================================*/
/*=========================================================================
 *
 *  Portions of this file are subject to the VTK Toolkit Version 3 copyright.
 *
 *  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
 *
 *  For complete copyright, license and disclaimer of warranty information
 *  please refer to the NOTICE file at the top of the ITK source tree.
 *
 *=========================================================================*/
#ifndef itkSliceImageFilter_hxx
#define itkSliceImageFilter_hxx

#include "itkSliceImageFilter.h"
#include "itkImageRegionIteratorWithIndex.h"
#include "itkMath.h"
#include "itkContinuousIndex.h"
#include "itkObjectFactory.h"
#include "itkProgressReporter.h"

namespace itk
{

template< class TInputImage, class TOutputImage >
SliceImageFilter< TInputImage, TOutputImage >
::SliceImageFilter()
{
  m_Start.Fill(NumericTraits<IndexValueType>::min());
  m_Stop.Fill(NumericTraits<IndexValueType>::max());
  m_Step.Fill(1);
  this->DynamicMultiThreadingOn();
}

template< class TInputImage, class TOutputImage >
void
SliceImageFilter< TInputImage, TOutputImage >
::PrintSelf(std::ostream & os, Indent indent) const
{
  Superclass::PrintSelf(os, indent);

  os << indent << "Start: " << m_Start << std::endl;
  os << indent << "Stop: " << m_Stop << std::endl;
  os << indent << "Step: " << m_Step << std::endl;

}

template< class TInputImage, class TOutputImage >
void
SliceImageFilter< TInputImage, TOutputImage >
::SetStart( typename TInputImage::IndexType::IndexValueType start)
{
  unsigned int j;

  for ( j = 0; j < ImageDimension; ++j )
    {
    if ( start != m_Start[j] )
      {
      this->Modified();
      m_Start.Fill( start );
      return;
      }
    }
}

template< class TInputImage, class TOutputImage >
void
SliceImageFilter< TInputImage, TOutputImage >
::SetStop(typename TInputImage::IndexType::IndexValueType  stop)
{
  unsigned int j;

  for ( j = 0; j < ImageDimension; ++j )
    {
    if ( stop != m_Stop[j] )
      {
      this->Modified();
      m_Stop.Fill( stop );
      return;
      }
    }
}

template< class TInputImage, class TOutputImage >
void
SliceImageFilter< TInputImage, TOutputImage >
::SetStep(int step)
{
  unsigned int j;

  for ( j = 0; j < ImageDimension; ++j )
    {
    if ( step != m_Step[j] )
      {
      this->Modified();
      m_Step.Fill( step );
      return;
      }
    }

}

template< class TInputImage, class TOutputImage >
void
SliceImageFilter< TInputImage, TOutputImage >
::DynamicThreadedGenerateData(const OutputImageRegionType & outputRegionForThread)
{
  InputImageConstPointer inputPtr = this->GetInput();
  OutputImagePointer     outputPtr = this->GetOutput();

  const typename TInputImage::SizeType &inputSize = inputPtr->GetLargestPossibleRegion().GetSize();
  const typename TInputImage::IndexType &inputIndex = inputPtr->GetLargestPossibleRegion().GetIndex();

  // clamp start
  InputIndexType start;
  for ( unsigned int i = 0; i < TOutputImage::ImageDimension; ++i )
    {
    start[i] = std::max( m_Start[i], inputIndex[i] );
    start[i] = std::min( start[i], static_cast<IndexValueType>(inputIndex[i] + inputSize[i]-1) );
    }

  // Define/declare an iterator that will walk the output region for this thread
  using OutputIterator = ImageRegionIteratorWithIndex< TOutputImage >;
  OutputIterator outIt(outputPtr, outputRegionForThread);

  OutputIndexType destIndex;
  InputIndexType srcIndex;

  while ( !outIt.IsAtEnd() )
    {
    // Determine the index and physical location of the output pixel
    destIndex = outIt.GetIndex();

    for( unsigned int i = 0; i < TOutputImage::ImageDimension; ++i )
      {
      srcIndex[i] = destIndex[i]*m_Step[i] + start[i];
      }

    // Copy the input pixel to the output
    outIt.Set( inputPtr->GetPixel(srcIndex) );
    ++outIt;
    }
}

template< class TInputImage, class TOutputImage >
void
SliceImageFilter< TInputImage, TOutputImage >
::GenerateInputRequestedRegion()
{

  // Get pointers to the input and output
  InputImagePointer  inputPtr = const_cast< TInputImage * >( this->GetInput() );
  OutputImagePointer outputPtr = this->GetOutput();

  const typename TOutputImage::SizeType & outputRequestedRegionSize = outputPtr->GetRequestedRegion().GetSize();
  const typename TOutputImage::IndexType & outputRequestedRegionStartIndex = outputPtr->GetRequestedRegion().GetIndex();

  const typename TInputImage::SizeType  &inputSize = inputPtr->GetLargestPossibleRegion().GetSize();
  const typename TInputImage::IndexType &inputIndex = inputPtr->GetLargestPossibleRegion().GetIndex();

  // clamp start
  InputIndexType start;
  for ( unsigned int i = 0; i < TOutputImage::ImageDimension; ++i )
    {
    // clamp to valid index range and don't include one past end, so
    // that a zero size RR would be valid
    start[i] = std::max( m_Start[i], inputIndex[i] );
    start[i] = std::min( start[i], static_cast<IndexValueType>(inputIndex[i] + inputSize[i] -1) );
    }

  typename TInputImage::SizeType inputRequestedRegionSize;
  inputRequestedRegionSize.Fill(0);
  for ( unsigned int i=0; i < TInputImage::ImageDimension; ++i )
    {
    if ( outputRequestedRegionSize[i] > 0 )
      {
      inputRequestedRegionSize[i] = (outputRequestedRegionSize[i] - 1 ) * itk::Math::abs(m_Step[i]) + 1;
      }
    }

  InputIndexType  inputRequestedRegionIndex;
  for ( unsigned int i=0; i < TOutputImage::ImageDimension; ++i )
    {
    inputRequestedRegionIndex[i] = outputRequestedRegionStartIndex[i] * m_Step[i] + start[i];

    // if reversing, go to the lower ending index - 1
    if (m_Step[i] < 0)
      {
      inputRequestedRegionIndex[i] -= inputRequestedRegionSize[i] - 1;
      }
    }

  typename TInputImage::RegionType inputRequestedRegion;
  inputRequestedRegion.SetIndex(inputRequestedRegionIndex);
  inputRequestedRegion.SetSize(inputRequestedRegionSize);

  // test if input RR is completely inside input largest region
  if ( inputRequestedRegion.GetNumberOfPixels() > 0 &&
       !inputPtr->GetLargestPossibleRegion().IsInside( inputRequestedRegion ) )
    {
    itkExceptionMacro( "Logic Error: incorrect computation of RequestedRegion" );
    }

  inputPtr->SetRequestedRegion(inputRequestedRegion);
  return;

}

template< class TInputImage, class TOutputImage >
void
SliceImageFilter< TInputImage, TOutputImage >
::GenerateOutputInformation()
{
  // Call the superclass' implementation of this method
  Superclass::GenerateOutputInformation();

  // Get pointers to the input and output
  InputImageConstPointer inputPtr  = this->GetInput();
  OutputImagePointer     outputPtr = this->GetOutput();

  // Compute the output spacing, the output image size, and the
  // output image start index
  const typename TInputImage::SpacingType &inputSpacing = inputPtr->GetSpacing();
  const typename TInputImage::SizeType &inputSize = inputPtr->GetLargestPossibleRegion().GetSize();
  const typename TInputImage::IndexType &inputIndex = inputPtr->GetLargestPossibleRegion().GetIndex();
  typename TInputImage::IndexType inputStartIndex;

  typename TOutputImage::SpacingType outputSpacing;
  typename TOutputImage::SizeType outputSize;

  typename TOutputImage::IndexType outputStartIndex;
  outputStartIndex.Fill(0);

  for ( unsigned int i = 0; i < TOutputImage::ImageDimension; ++i )
    {
    outputSpacing[i] = inputSpacing[i] * itk::Math::abs(m_Step[i]);

    // clamp start
    // Based on the sign of the step include 1 after the end.
    IndexValueType start = std::max( m_Start[i], inputIndex[i] - int(m_Step[i]<0));
    start = std::min( start,  static_cast<IndexValueType>(inputIndex[i] + inputSize[i]) - int(m_Step[i]<0) );

    // clamp stop
    // Based on the sign of the step include 1 after the end.
    IndexValueType stop = std::max( m_Stop[i], inputIndex[i] - int(m_Step[i]<0) );
    stop = std::min( stop,  static_cast<IndexValueType>(inputIndex[i] + inputSize[i]) - int(m_Step[i]<0));

    // If both the numerator and the denominator have the same sign,
    // then the range is a valid and non-zero sized. Truncation is the
    // correct rounding for these positive values.
    if ( (m_Step[i] > 0 && stop > start) ||
         ( m_Step[i] < 0 && stop < start ) )
      {
      outputSize[i] = (stop-start)/m_Step[i];
      }
    else
      {
      outputSize[i] = 0u;
      }

    // If the step is negative, then the start is still the index of
    // the output origin
    inputStartIndex[i] = start;

    }

  const typename TInputImage::DirectionType & inputDirection = inputPtr->GetDirection();
  typename TInputImage::DirectionType flipMatrix;

  // Need a matrix to model the reversing of directions, this should
  // maintain the physical location of the pixels
  for ( unsigned int j = 0; j < ImageDimension; ++j )
    {
    flipMatrix[j][j] = itk::Math::sgn0(m_Step[j]);
    }

  outputPtr->SetDirection(inputDirection * flipMatrix);
  outputPtr->SetSpacing(outputSpacing);

  typename TOutputImage::PointType outputOrigin;
  inputPtr->TransformIndexToPhysicalPoint(inputStartIndex, outputOrigin);
  outputPtr->SetOrigin(outputOrigin);

  // Set region
  typename TOutputImage::RegionType outputLargestPossibleRegion;
  outputLargestPossibleRegion.SetSize(outputSize);
  outputLargestPossibleRegion.SetIndex(outputStartIndex);

  outputPtr->SetLargestPossibleRegion(outputLargestPossibleRegion);
}

template< class TInputImage, class TOutputImage >
void
SliceImageFilter< TInputImage, TOutputImage >
::VerifyInputInformation() ITKv5_CONST
{

  Superclass::VerifyInputInformation();

  for ( unsigned int i = 0; i < ImageDimension; ++i )
    {
    if ( m_Step[i] == 0 )
      {
      itkExceptionMacro( "Step size is zero " << m_Step << "!" );
      }
    }

}

} // end namespace itk

#endif
<commit_msg>BUG: Address bug with small size in output of SliceImageFilter<commit_after>/*=========================================================================
 *
 *  Copyright Insight Software Consortium
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0.txt
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 *=========================================================================*/
/*=========================================================================
 *
 *  Portions of this file are subject to the VTK Toolkit Version 3 copyright.
 *
 *  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
 *
 *  For complete copyright, license and disclaimer of warranty information
 *  please refer to the NOTICE file at the top of the ITK source tree.
 *
 *=========================================================================*/
#ifndef itkSliceImageFilter_hxx
#define itkSliceImageFilter_hxx

#include "itkSliceImageFilter.h"
#include "itkImageRegionIteratorWithIndex.h"
#include "itkMath.h"
#include "itkContinuousIndex.h"
#include "itkObjectFactory.h"
#include "itkProgressReporter.h"

namespace itk
{

template< class TInputImage, class TOutputImage >
SliceImageFilter< TInputImage, TOutputImage >
::SliceImageFilter()
{
  m_Start.Fill(NumericTraits<IndexValueType>::min());
  m_Stop.Fill(NumericTraits<IndexValueType>::max());
  m_Step.Fill(1);
  this->DynamicMultiThreadingOn();
}

template< class TInputImage, class TOutputImage >
void
SliceImageFilter< TInputImage, TOutputImage >
::PrintSelf(std::ostream & os, Indent indent) const
{
  Superclass::PrintSelf(os, indent);

  os << indent << "Start: " << m_Start << std::endl;
  os << indent << "Stop: " << m_Stop << std::endl;
  os << indent << "Step: " << m_Step << std::endl;

}

template< class TInputImage, class TOutputImage >
void
SliceImageFilter< TInputImage, TOutputImage >
::SetStart( typename TInputImage::IndexType::IndexValueType start)
{
  unsigned int j;

  for ( j = 0; j < ImageDimension; ++j )
    {
    if ( start != m_Start[j] )
      {
      this->Modified();
      m_Start.Fill( start );
      return;
      }
    }
}

template< class TInputImage, class TOutputImage >
void
SliceImageFilter< TInputImage, TOutputImage >
::SetStop(typename TInputImage::IndexType::IndexValueType  stop)
{
  unsigned int j;

  for ( j = 0; j < ImageDimension; ++j )
    {
    if ( stop != m_Stop[j] )
      {
      this->Modified();
      m_Stop.Fill( stop );
      return;
      }
    }
}

template< class TInputImage, class TOutputImage >
void
SliceImageFilter< TInputImage, TOutputImage >
::SetStep(int step)
{
  unsigned int j;

  for ( j = 0; j < ImageDimension; ++j )
    {
    if ( step != m_Step[j] )
      {
      this->Modified();
      m_Step.Fill( step );
      return;
      }
    }

}

template< class TInputImage, class TOutputImage >
void
SliceImageFilter< TInputImage, TOutputImage >
::DynamicThreadedGenerateData(const OutputImageRegionType & outputRegionForThread)
{
  InputImageConstPointer inputPtr = this->GetInput();
  OutputImagePointer     outputPtr = this->GetOutput();

  const typename TInputImage::SizeType &inputSize = inputPtr->GetLargestPossibleRegion().GetSize();
  const typename TInputImage::IndexType &inputIndex = inputPtr->GetLargestPossibleRegion().GetIndex();

  // clamp start
  InputIndexType start;
  for ( unsigned int i = 0; i < TOutputImage::ImageDimension; ++i )
    {
    start[i] = std::max( m_Start[i], inputIndex[i] );
    start[i] = std::min( start[i], static_cast<IndexValueType>(inputIndex[i] + inputSize[i]-1) );
    }

  // Define/declare an iterator that will walk the output region for this thread
  using OutputIterator = ImageRegionIteratorWithIndex< TOutputImage >;
  OutputIterator outIt(outputPtr, outputRegionForThread);

  OutputIndexType destIndex;
  InputIndexType srcIndex;

  while ( !outIt.IsAtEnd() )
    {
    // Determine the index and physical location of the output pixel
    destIndex = outIt.GetIndex();

    for( unsigned int i = 0; i < TOutputImage::ImageDimension; ++i )
      {
      srcIndex[i] = destIndex[i]*m_Step[i] + start[i];
      }

    // Copy the input pixel to the output
    outIt.Set( inputPtr->GetPixel(srcIndex) );
    ++outIt;
    }
}

template< class TInputImage, class TOutputImage >
void
SliceImageFilter< TInputImage, TOutputImage >
::GenerateInputRequestedRegion()
{

  // Get pointers to the input and output
  InputImagePointer  inputPtr = const_cast< TInputImage * >( this->GetInput() );
  OutputImagePointer outputPtr = this->GetOutput();

  const typename TOutputImage::SizeType & outputRequestedRegionSize = outputPtr->GetRequestedRegion().GetSize();
  const typename TOutputImage::IndexType & outputRequestedRegionStartIndex = outputPtr->GetRequestedRegion().GetIndex();

  const typename TInputImage::SizeType  &inputSize = inputPtr->GetLargestPossibleRegion().GetSize();
  const typename TInputImage::IndexType &inputIndex = inputPtr->GetLargestPossibleRegion().GetIndex();

  // clamp start
  InputIndexType start;
  for ( unsigned int i = 0; i < TOutputImage::ImageDimension; ++i )
    {
    // clamp to valid index range and don't include one past end, so
    // that a zero size RR would be valid
    start[i] = std::max( m_Start[i], inputIndex[i] );
    start[i] = std::min( start[i], static_cast<IndexValueType>(inputIndex[i] + inputSize[i] -1) );
    }

  typename TInputImage::SizeType inputRequestedRegionSize;
  inputRequestedRegionSize.Fill(0);
  for ( unsigned int i=0; i < TInputImage::ImageDimension; ++i )
    {
    if ( outputRequestedRegionSize[i] > 0 )
      {
      inputRequestedRegionSize[i] = (outputRequestedRegionSize[i] - 1 ) * itk::Math::abs(m_Step[i]) + 1;
      }
    }

  InputIndexType  inputRequestedRegionIndex;
  for ( unsigned int i=0; i < TOutputImage::ImageDimension; ++i )
    {
    inputRequestedRegionIndex[i] = outputRequestedRegionStartIndex[i] * m_Step[i] + start[i];

    // if reversing, go to the lower ending index - 1
    if (m_Step[i] < 0)
      {
      inputRequestedRegionIndex[i] -= inputRequestedRegionSize[i] - 1;
      }
    }

  typename TInputImage::RegionType inputRequestedRegion;
  inputRequestedRegion.SetIndex(inputRequestedRegionIndex);
  inputRequestedRegion.SetSize(inputRequestedRegionSize);

  // test if input RR is completely inside input largest region
  if ( inputRequestedRegion.GetNumberOfPixels() > 0 &&
       !inputPtr->GetLargestPossibleRegion().IsInside( inputRequestedRegion ) )
    {
    itkExceptionMacro( "Logic Error: incorrect computation of RequestedRegion" );
    }

  inputPtr->SetRequestedRegion(inputRequestedRegion);
  return;

}

template< class TInputImage, class TOutputImage >
void
SliceImageFilter< TInputImage, TOutputImage >
::GenerateOutputInformation()
{
  // Call the superclass' implementation of this method
  Superclass::GenerateOutputInformation();

  // Get pointers to the input and output
  InputImageConstPointer inputPtr  = this->GetInput();
  OutputImagePointer     outputPtr = this->GetOutput();

  // Compute the output spacing, the output image size, and the
  // output image start index
  const typename TInputImage::SpacingType &inputSpacing = inputPtr->GetSpacing();
  const typename TInputImage::SizeType &inputSize = inputPtr->GetLargestPossibleRegion().GetSize();
  const typename TInputImage::IndexType &inputIndex = inputPtr->GetLargestPossibleRegion().GetIndex();
  typename TInputImage::IndexType inputStartIndex;

  typename TOutputImage::SpacingType outputSpacing;
  typename TOutputImage::SizeType outputSize;

  typename TOutputImage::IndexType outputStartIndex;
  outputStartIndex.Fill(0);

  for ( unsigned int i = 0; i < TOutputImage::ImageDimension; ++i )
    {
    outputSpacing[i] = inputSpacing[i] * itk::Math::abs(m_Step[i]);

    // clamp start
    // Based on the sign of the step include 1 after the end.
    IndexValueType start = std::max( m_Start[i], inputIndex[i] - int(m_Step[i]<0));
    start = std::min( start,  static_cast<IndexValueType>(inputIndex[i] + inputSize[i]) - int(m_Step[i]<0) );

    // clamp stop
    // Based on the sign of the step include 1 after the end.
    IndexValueType stop = std::max( m_Stop[i], inputIndex[i] - int(m_Step[i]<0) );
    stop = std::min( stop,  static_cast<IndexValueType>(inputIndex[i] + inputSize[i]) - int(m_Step[i]<0));

    // If both the numerator and the denominator have the same sign,
    // then the range is a valid and non-zero sized. Truncation is the
    // correct rounding for these positive values.
    if ( (m_Step[i] > 0 && stop > start) ||
         ( m_Step[i] < 0 && stop < start ) )
      {
      outputSize[i] = (stop-start-Math::sgn(m_Step[i]))/m_Step[i];
      outputSize[i] += 1u;
      }
    else
      {
      outputSize[i] = 0u;
      }

    // If the step is negative, then the start is still the index of
    // the output origin
    inputStartIndex[i] = start;

    }

  const typename TInputImage::DirectionType & inputDirection = inputPtr->GetDirection();
  typename TInputImage::DirectionType flipMatrix;

  // Need a matrix to model the reversing of directions, this should
  // maintain the physical location of the pixels
  for ( unsigned int j = 0; j < ImageDimension; ++j )
    {
    flipMatrix[j][j] = itk::Math::sgn0(m_Step[j]);
    }

  outputPtr->SetDirection(inputDirection * flipMatrix);
  outputPtr->SetSpacing(outputSpacing);

  typename TOutputImage::PointType outputOrigin;
  inputPtr->TransformIndexToPhysicalPoint(inputStartIndex, outputOrigin);
  outputPtr->SetOrigin(outputOrigin);

  // Set region
  typename TOutputImage::RegionType outputLargestPossibleRegion;
  outputLargestPossibleRegion.SetSize(outputSize);
  outputLargestPossibleRegion.SetIndex(outputStartIndex);

  outputPtr->SetLargestPossibleRegion(outputLargestPossibleRegion);
}

template< class TInputImage, class TOutputImage >
void
SliceImageFilter< TInputImage, TOutputImage >
::VerifyInputInformation() ITKv5_CONST
{

  Superclass::VerifyInputInformation();

  for ( unsigned int i = 0; i < ImageDimension; ++i )
    {
    if ( m_Step[i] == 0 )
      {
      itkExceptionMacro( "Step size is zero " << m_Step << "!" );
      }
    }

}

} // end namespace itk

#endif
<|endoftext|>