<commit_before>/*
Copyright (c) 2016 Bastien Durix

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

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

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

/**
 *  \brief Provides tests for skeleton library
 *  \author Bastien Durix
 */

#include <iostream>
#include <math.h>

#include <cstdlib>

#include <skeleton/GraphCurveSkeleton.h>
#include <skeleton/model/Classic.h>
#include <mathtools/geometry/euclidian/HyperSphere.h>

using namespace mathtools::affine;
using namespace mathtools::geometry::euclidian;

int main()
{
	unsigned int return_value = 0;

	// frame creation
	Frame<2>::Ptr frame = Frame<2>::CreateFrame(Eigen::Vector2d(1.0,0.0),Eigen::Vector2d(2.0,1.0),Eigen::Vector2d(1.0,0.0));

	// model creation
	skeleton::model::Classic<2>::Ptr modclass(new skeleton::model::Classic<2>{frame});

	// creating a random node
	Eigen::Vector3d vec3((double)(rand()%201)/10.0-1.0,
						 (double)(rand()%201)/10.0-1.0,
						 (double)(rand()%201)/10.0);

	// skeleton creation
	skeleton::GraphCurveSkeleton<skeleton::model::Classic<2> > skel(modclass);

	std::cout << "Adding Node test... ";

	// adding a node
	unsigned int ind = skel.addNode(vec3);

	// getting the node (vector form)
	Eigen::Vector3d vec3_2 = skel.getNode(ind);

	if(vec3_2.isApprox(vec3,std::numeric_limits<double>::epsilon()))
	{
		std::cout << "Success!" << std::endl;
	}
	else
	{
		return_value = -1;
		std::cout << "Fail!" << std::endl;
	}

	std::cout << "Getter test... ";

	// getting the node (center form)
	Point<2> pt = skel.getNode<Point<2> >(ind);

	if(pt.getCoords().isApprox(frame->getBasis()->getMatrix()*vec3.block<2,1>(0,0)+frame->getOrigin()))
	{
		std::cout << "Success!" << std::endl;
	}
	else
	{
		return_value = -1;
		std::cout << "Fail!" << std::endl;
	}

	// hypersphere creation
	HyperSphere<2> sph(Point<2>(1.0,0.0),5.0,frame);

	std::cout << "Adding Sphere test... ";

	// adding a node
	unsigned int ind2 = skel.addNode<HyperSphere<2> >(sph);

	// get the vector associated to the node
	Eigen::Vector3d vecsph = skel.getNode(ind2);

	// convert the node to a sphere
	HyperSphere<2> sphcpy = skel.getModel()->toObj<HyperSphere<2> >(vecsph);

	if(sphcpy.getCenter().getCoords().isApprox(sph.getCenter().getCoords(),std::numeric_limits<double>::epsilon() &&
	   sphcpy.getRadius() == sph.getRadius() &&
	   sphcpy.getFrame()->getBasis()->getMatrix().isApprox(sph.getFrame()->getBasis()->getMatrix(),std::numeric_limits<double>::epsilon())) &&
	   ind != ind2)
	{
		std::cout << "Success!" << std::endl;
	}
	else
	{
		return_value = -1;
		std::cout << "Fail!" << std::endl;
	}

	// get all indices
	std::list<unsigned int> listnod;

	std::cout << "Get all nodes... ";
	skel.getAllNodes(listnod);

	listnod.unique();

	if(listnod.size() == 2 &&
	   std::find(listnod.begin(),listnod.end(),ind) != listnod.end() &&
	   std::find(listnod.begin(),listnod.end(),ind2) != listnod.end())
	{
		std::cout << "Success!" << std::endl;
	}
	else
	{
		return_value = -1;
		std::cout << "Fail!" << std::endl;
	}

	return return_value;
}
<commit_msg>Added test to neighbor access in skeleton<commit_after>/*
Copyright (c) 2016 Bastien Durix

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

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

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

/**
 *  \brief Provides tests for skeleton library
 *  \author Bastien Durix
 */

#include <iostream>
#include <math.h>

#include <cstdlib>

#include <skeleton/GraphCurveSkeleton.h>
#include <skeleton/model/Classic.h>
#include <mathtools/geometry/euclidian/HyperSphere.h>

using namespace mathtools::affine;
using namespace mathtools::geometry::euclidian;

int main()
{
	unsigned int return_value = 0;

	// frame creation
	Frame<2>::Ptr frame = Frame<2>::CreateFrame(Eigen::Vector2d(1.0,0.0),Eigen::Vector2d(2.0,1.0),Eigen::Vector2d(1.0,0.0));

	// model creation
	skeleton::model::Classic<2>::Ptr modclass(new skeleton::model::Classic<2>{frame});

	// creating a random node
	Eigen::Vector3d vec3((double)(rand()%201)/10.0-1.0,
						 (double)(rand()%201)/10.0-1.0,
						 (double)(rand()%201)/10.0);

	// skeleton creation
	skeleton::GraphCurveSkeleton<skeleton::model::Classic<2> > skel(modclass);

	std::cout << "Adding Node test... ";

	// adding a node
	unsigned int ind = skel.addNode(vec3);

	// getting the node (vector form)
	Eigen::Vector3d vec3_2 = skel.getNode(ind);

	if(vec3_2.isApprox(vec3,std::numeric_limits<double>::epsilon()))
	{
		std::cout << "Success!" << std::endl;
	}
	else
	{
		return_value = -1;
		std::cout << "Fail!" << std::endl;
	}

	std::cout << "Getter test... ";

	// getting the node (center form)
	Point<2> pt = skel.getNode<Point<2> >(ind);

	if(pt.getCoords().isApprox(frame->getBasis()->getMatrix()*vec3.block<2,1>(0,0)+frame->getOrigin()))
	{
		std::cout << "Success!" << std::endl;
	}
	else
	{
		return_value = -1;
		std::cout << "Fail!" << std::endl;
	}

	// hypersphere creation
	HyperSphere<2> sph(Point<2>(1.0,0.0),5.0,frame);

	std::cout << "Adding Sphere test... ";

	// adding a node
	unsigned int ind2 = skel.addNode<HyperSphere<2> >(sph);

	// get the vector associated to the node
	Eigen::Vector3d vecsph = skel.getNode(ind2);

	// convert the node to a sphere
	HyperSphere<2> sphcpy = skel.getModel()->toObj<HyperSphere<2> >(vecsph);

	if(sphcpy.getCenter().getCoords().isApprox(sph.getCenter().getCoords(),std::numeric_limits<double>::epsilon() &&
	   sphcpy.getRadius() == sph.getRadius() &&
	   sphcpy.getFrame()->getBasis()->getMatrix().isApprox(sph.getFrame()->getBasis()->getMatrix(),std::numeric_limits<double>::epsilon())) &&
	   ind != ind2)
	{
		std::cout << "Success!" << std::endl;
	}
	else
	{
		return_value = -1;
		std::cout << "Fail!" << std::endl;
	}

	// get all indices
	std::list<unsigned int> listnod;

	std::cout << "Get all nodes... ";
	skel.getAllNodes(listnod);

	listnod.unique();

	if(listnod.size() == 2 &&
	   std::find(listnod.begin(),listnod.end(),ind) != listnod.end() &&
	   std::find(listnod.begin(),listnod.end(),ind2) != listnod.end())
	{
		std::cout << "Success!" << std::endl;
	}
	else
	{
		return_value = -1;
		std::cout << "Fail!" << std::endl;
	}

	std::cout << "Adding edge test... ";

	// adding an edge
	skel.addEdge(ind, ind2);

	std::list<unsigned int> neigh;
	skel.getNeighbors(ind,neigh);

	if(neigh.size() == 1 && *(neigh.begin()) == ind2)
	{
		std::cout << "Success!" << std::endl;
	}
	else
	{
		return_value = -1;
		std::cout << "Fail!" << std::endl;
	}

	std::cout << "Removing edge test... ";

	// removing an edge
	skel.remEdge(ind, ind2);

	neigh.erase(neigh.begin(),neigh.end());
	skel.getNeighbors(ind,neigh);

	if(neigh.size() == 0)
	{
		std::cout << "Success!" << std::endl;
	}
	else
	{
		return_value = -1;
		std::cout << "Fail!" << std::endl;
	}

	return return_value;
}
<|endoftext|>


<commit_before>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/usr/diag/attn/runtime/attn_rt.C $                         */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2014,2016                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* Licensed under the Apache License, Version 2.0 (the "License");        */
/* you may not use this file except in compliance with the License.       */
/* You may obtain a copy of the License at                                */
/*                                                                        */
/*     http://www.apache.org/licenses/LICENSE-2.0                         */
/*                                                                        */
/* Unless required by applicable law or agreed to in writing, software    */
/* distributed under the License is distributed on an "AS IS" BASIS,      */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or        */
/* implied. See the License for the specific language governing           */
/* permissions and limitations under the License.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */

#include "runtime/attnsvc.H"
#include "common/attntrace.H"
#include "common/attnmem.H"
#include <runtime/interface.h>
#include <runtime/rt_targeting.H>
#include <targeting/common/target.H>
#include <targeting/common/targetservice.H>
#include <targeting/common/utilFilter.H>
#include <errl/errlentry.H>
#include <errl/errlmanager.H>
#include <errno.h>

using namespace std;
using namespace TARGETING;
using namespace ATTN;
using namespace PRDF;

namespace ATTN_RT
{
    /** Enable chip attentions
     *
     *  @return 0 on success else return code
     */
    int enableAttns(void)
    {
        ATTN_SLOW(ENTER_MRK"ATTN_RT::enableAttns");

        int rc = 0;
        errlHndl_t err = NULL;
        err = Singleton<Service>::instance().enableAttns();
        if(err)
        {
            errlCommit(err, ATTN_COMP_ID);
            rc = -1;
        }

        ATTN_SLOW(EXIT_MRK"ATTN_RT::enableAttns rc: %d", rc);

        return rc;
    }

    /** Disable chip attentions
     *
     *  @return 0 on success else return code
     */
    int disableAttns(void)
    {
        ATTN_SLOW(ENTER_MRK"ATTN_RT::disableAttns");

        int rc = 0;
        errlHndl_t err = NULL;
        err = Singleton<Service>::instance().disableAttns();
        if(err)
        {
            errlCommit(err, ATTN_COMP_ID);
            rc = -1;
        }

        ATTN_SLOW(EXIT_MRK"ATTN_RT::disableAttns rc: %d", rc);

        return rc;
    }

    /** brief handle chip attentions
     *
     *  @param[in] i_proc - processor chip id at attention
     *                      XSCOM chip id based on devtree defn
     *  @param[in] i_ipollStatus - processor chip Ipoll status
     *  @param[in] i_ipollMask   - processor chip Ipoll mask
     *  @return 0 on success else return code
     */
    int handleAttns(uint64_t i_proc,
                    uint64_t i_ipollStatus,
                    uint64_t i_ipollMask)
    {
        ATTN_SLOW(ENTER_MRK"ATTN_RT::handleAttns RtProc: %llx"
                  ", ipollMask: %llx, ipollStatus: %llx",
                  i_proc, i_ipollMask, i_ipollStatus);

        int rc = 0;
        errlHndl_t err = NULL;
        AttentionList attentions;
        MemOps & memOps = getMemOps();

        do
        {
            // Convert chipIds to HB targets
            TargetHandle_t proc = NULL;
            err = RT_TARG::getHbTarget(i_proc, proc);
            if(err)
            {
                ATTN_ERR("ATTN_RT::handleAttns getHbTarget "
                   "returned error for RtProc: %llx", i_proc);
                rc = EINVAL;
                break;
            }

            err = Singleton<Service>::instance().handleAttentions(proc);
            if(err)
            {
                ATTN_ERR("ATTN_RT::handleAttns service::handleAttentions "
                   "returned error for RtProc: %llx", i_proc);
                break;
            }

            // On P8,
            // For host attentions, clear gpio interrupt type register.
            // If we do not clear gpio register, ipoll status will again
            // get set and we will end up in infinite loop.

            // For P9,
            // Host attentions should be coming thru the
            // normal (IPOLL) Error status reg. Hence, we shouldn't
            // have to play with the IPR (interrupt presentation register)
            // which was involved with the gpio/gpin register where
            // centaur routed its attentions.

        } while(0);

        if(err)
        {
            errlCommit( err, ATTN_COMP_ID );
            if(0 == rc)
            {
                rc = -1;
            }
        }

        attentions.clear();
        ATTN_SLOW(EXIT_MRK"ATTN_RT::handleAttns rc: %d", rc);

        return rc;
    }

    // register runtimeInterfaces
    struct registerAttn
    {
        registerAttn()
        {
            runtimeInterfaces_t * rt_intf = getRuntimeInterfaces();
            if (NULL == rt_intf)
            {
                return;
            }

            rt_intf->enable_attns  = &enableAttns;
            rt_intf->disable_attns = &disableAttns;
            rt_intf->handle_attns  = &handleAttns;
        }
    };

    registerAttn g_registerAttn;
}

<commit_msg>Remove unused variable in attn_rt.C<commit_after>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/usr/diag/attn/runtime/attn_rt.C $                         */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2014,2016                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* Licensed under the Apache License, Version 2.0 (the "License");        */
/* you may not use this file except in compliance with the License.       */
/* You may obtain a copy of the License at                                */
/*                                                                        */
/*     http://www.apache.org/licenses/LICENSE-2.0                         */
/*                                                                        */
/* Unless required by applicable law or agreed to in writing, software    */
/* distributed under the License is distributed on an "AS IS" BASIS,      */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or        */
/* implied. See the License for the specific language governing           */
/* permissions and limitations under the License.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */

#include "runtime/attnsvc.H"
#include "common/attntrace.H"
#include "common/attnmem.H"
#include <runtime/interface.h>
#include <runtime/rt_targeting.H>
#include <targeting/common/target.H>
#include <targeting/common/targetservice.H>
#include <targeting/common/utilFilter.H>
#include <errl/errlentry.H>
#include <errl/errlmanager.H>
#include <errno.h>

using namespace std;
using namespace TARGETING;
using namespace ATTN;
using namespace PRDF;

namespace ATTN_RT
{
    /** Enable chip attentions
     *
     *  @return 0 on success else return code
     */
    int enableAttns(void)
    {
        ATTN_SLOW(ENTER_MRK"ATTN_RT::enableAttns");

        int rc = 0;
        errlHndl_t err = NULL;
        err = Singleton<Service>::instance().enableAttns();
        if(err)
        {
            errlCommit(err, ATTN_COMP_ID);
            rc = -1;
        }

        ATTN_SLOW(EXIT_MRK"ATTN_RT::enableAttns rc: %d", rc);

        return rc;
    }

    /** Disable chip attentions
     *
     *  @return 0 on success else return code
     */
    int disableAttns(void)
    {
        ATTN_SLOW(ENTER_MRK"ATTN_RT::disableAttns");

        int rc = 0;
        errlHndl_t err = NULL;
        err = Singleton<Service>::instance().disableAttns();
        if(err)
        {
            errlCommit(err, ATTN_COMP_ID);
            rc = -1;
        }

        ATTN_SLOW(EXIT_MRK"ATTN_RT::disableAttns rc: %d", rc);

        return rc;
    }

    /** brief handle chip attentions
     *
     *  @param[in] i_proc - processor chip id at attention
     *                      XSCOM chip id based on devtree defn
     *  @param[in] i_ipollStatus - processor chip Ipoll status
     *  @param[in] i_ipollMask   - processor chip Ipoll mask
     *  @return 0 on success else return code
     */
    int handleAttns(uint64_t i_proc,
                    uint64_t i_ipollStatus,
                    uint64_t i_ipollMask)
    {
        ATTN_SLOW(ENTER_MRK"ATTN_RT::handleAttns RtProc: %llx"
                  ", ipollMask: %llx, ipollStatus: %llx",
                  i_proc, i_ipollMask, i_ipollStatus);

        int rc = 0;
        errlHndl_t err = NULL;
        AttentionList attentions;

        do
        {
            // Convert chipIds to HB targets
            TargetHandle_t proc = NULL;
            err = RT_TARG::getHbTarget(i_proc, proc);
            if(err)
            {
                ATTN_ERR("ATTN_RT::handleAttns getHbTarget "
                   "returned error for RtProc: %llx", i_proc);
                rc = EINVAL;
                break;
            }

            err = Singleton<Service>::instance().handleAttentions(proc);
            if(err)
            {
                ATTN_ERR("ATTN_RT::handleAttns service::handleAttentions "
                   "returned error for RtProc: %llx", i_proc);
                break;
            }

            // On P8,
            // For host attentions, clear gpio interrupt type register.
            // If we do not clear gpio register, ipoll status will again
            // get set and we will end up in infinite loop.

            // For P9,
            // Host attentions should be coming thru the
            // normal (IPOLL) Error status reg. Hence, we shouldn't
            // have to play with the IPR (interrupt presentation register)
            // which was involved with the gpio/gpin register where
            // centaur routed its attentions.

        } while(0);

        if(err)
        {
            errlCommit( err, ATTN_COMP_ID );
            if(0 == rc)
            {
                rc = -1;
            }
        }

        attentions.clear();
        ATTN_SLOW(EXIT_MRK"ATTN_RT::handleAttns rc: %d", rc);

        return rc;
    }

    // register runtimeInterfaces
    struct registerAttn
    {
        registerAttn()
        {
            runtimeInterfaces_t * rt_intf = getRuntimeInterfaces();
            if (NULL == rt_intf)
            {
                return;
            }

            rt_intf->enable_attns  = &enableAttns;
            rt_intf->disable_attns = &disableAttns;
            rt_intf->handle_attns  = &handleAttns;
        }
    };

    registerAttn g_registerAttn;
}

<|endoftext|>


<commit_before>/*
 * httpfileupload.cpp - HTTP File upload
 * Copyright (C) 2017-2019  Aleksey Andreev, Sergey Ilinykh
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 *
 */

#include <QList>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QNetworkRequest>
#include <QRegExp>

#include "httpfileupload.h"
#include "xmpp_tasks.h"
#include "xmpp_xmlcommon.h"
#include "xmpp_serverinfomanager.h"

using namespace XMPP;

static QLatin1String xmlns_v0_2_5("urn:xmpp:http:upload");
static QLatin1String xmlns_v0_3_1("urn:xmpp:http:upload:0");

//----------------------------------------------------------------------------
// HttpFileUpload
//----------------------------------------------------------------------------
class HttpFileUpload::Private
{
public:
    HttpFileUpload::State state = State::None;
    XMPP::Client *client = nullptr;
    QIODevice *sourceDevice = nullptr;
    QPointer<QNetworkAccessManager> qnam = nullptr;
    quint64 fileSize = 0;
    QString fileName;
    QString mediaType;
    QList<HttpHost> httpHosts;

    struct {
        HttpFileUpload::ErrorCode statusCode = HttpFileUpload::ErrorCode::NoError;
        QString statusString;
        QString getUrl;
        QString putUrl;
        XEP0363::HttpHeaders putHeaders;
        quint64 sizeLimit = 0;
    } result;
};

HttpFileUpload::HttpFileUpload(XMPP::Client *client, QIODevice *source, size_t fsize, const QString &dstFilename,
                               const QString &mType) :
    QObject(client),
    d(new Private)
{
    d->client = client;
    d->sourceDevice = source;
    d->fileName = dstFilename;
    d->fileSize = fsize;
    d->mediaType = mType;
}

HttpFileUpload::~HttpFileUpload()
{
    qDebug("destroying");
}

void HttpFileUpload::setNetworkAccessManager(QNetworkAccessManager *qnam)
{
    d->qnam = qnam;
}

void HttpFileUpload::start()
{
    if (d->state != State::None) // Attempt to start twice?
        return;

    setState(State::GettingSlot);

    d->result.statusCode = HttpFileUpload::ErrorCode::NoError;
    static QList<QSet<QString>> featureOptions;
    if (featureOptions.isEmpty()) {
        featureOptions << (QSet<QString>() << xmlns_v0_2_5) << (QSet<QString>() << xmlns_v0_3_1);
    }
    d->client->serverInfoManager()->queryServiceInfo(
                QLatin1String("store"), QLatin1String("file"),
                featureOptions, QRegExp("^(upload|http|stor|file|dis|drive).*"), ServerInfoManager::SQ_CheckAllOnNoMatch,
                [this](const QList<DiscoItem> &items)
    {
        d->httpHosts.clear();
        for (const auto &item: items) {
            const QStringList &l = item.features().list();
            XEP0363::version ver = XEP0363::vUnknown;
            QString xmlns;
            quint64 sizeLimit = 0;
            if (l.contains(xmlns_v0_3_1)) {
                ver = XEP0363::v0_3_1;
                xmlns = xmlns_v0_3_1;
            } else if (l.contains(xmlns_v0_2_5)) {
                ver = XEP0363::v0_2_5;
                xmlns = xmlns_v0_2_5;
            }
            if (ver != XEP0363::vUnknown) {
                QList<std::pair<HttpHost,int>> hosts;
                const XData::Field field = item.registeredExtension(xmlns).getField(QLatin1String("max-file-size"));
                if (field.isValid() && field.type() == XData::Field::Field_TextSingle)
                    sizeLimit = field.value().at(0).toULongLong();
                HttpHost host;
                host.ver = ver;
                host.jid = item.jid();
                host.sizeLimit = sizeLimit;
                QVariant metaProps(d->client->serverInfoManager()->serviceMeta(host.jid, "httpprops"));
                if (metaProps.isValid()) {
                    host.props = HostProps(metaProps.value<int>());
                } else {
                    host.props = SecureGet | SecurePut;
                    if (ver == XEP0363::v0_3_1)
                        host.props |= NewestVer;
                }
                int value = 0;
                if (host.props & SecureGet) value += 5;
                if (host.props & SecurePut) value += 5;
                if (host.props & NewestVer) value += 3;
                if (host.props & Failure) value -= 15;
                if (!sizeLimit || d->fileSize < sizeLimit)
                    hosts.append({host,value});

                // no sorting in preference order. most preferred go first
                std::sort(hosts.begin(), hosts.end(), [](const auto &a, const auto &b){
                    return a.second > b.second;
                });
                for (auto &hp: hosts) {
                    d->httpHosts.append(hp.first);
                }
            }
        }
        //d->currentHost = d->httpHosts.begin();
        if (d->httpHosts.isEmpty()) { // if empty as the last resort check all services
            d->result.statusCode   = HttpFileUpload::ErrorCode::NoUploadService;
            d->result.statusString = "No suitable http upload services were found";
            done(State::Error);
        } else {
            tryNextServer();
        }
    });
}

void HttpFileUpload::tryNextServer()
{
    if (d->httpHosts.isEmpty()) { // if empty as the last resort check all services
        d->result.statusCode   = HttpFileUpload::ErrorCode::NoUploadService;
        d->result.statusString = "All http services are either non compliant or returned errors";
        done(State::Error);
        return;
    }
    HttpHost host = std::move(d->httpHosts.takeFirst());
    d->result.sizeLimit = host.sizeLimit;
    auto jt = new JT_HTTPFileUpload(d->client->rootTask());
    connect(jt, &JT_HTTPFileUpload::finished, this, [this, jt, host]() mutable {
        if (!jt->success()) {
            host.props |= Failure;
            int code = jt->statusCode();
            if (code < 300) {
                code++; // ErrDisc and ErrTimeout. but 0 code is already occupated
            }
            d->result.statusCode   = static_cast<ErrorCode>(jt->statusCode());
            d->result.statusString = jt->statusString();
            d->client->serverInfoManager()->setServiceMeta(host.jid, QLatin1String("httpprops"), int(host.props));
            if (d->httpHosts.isEmpty())
                done(State::Error);
            else
                tryNextServer();
            return;
        }

        d->result.getUrl = jt->url(JT_HTTPFileUpload::GetUrl);
        d->result.putUrl = jt->url(JT_HTTPFileUpload::PutUrl);
        d->result.putHeaders = jt->headers();
        if (d->result.getUrl.startsWith("https://"))
            host.props |= SecureGet;
        else
            host.props &= ~SecureGet;
        if (d->result.putUrl.startsWith("https://"))
            host.props |= SecurePut;
        else
            host.props &= ~SecurePut;
        host.props &= ~Failure;

        d->client->serverInfoManager()->setServiceMeta(host.jid, QLatin1String("httpprops"), int(host.props));

        if (!d->qnam) { // w/o network access manager, it's not more than getting slots
            done(State::Success);
            return;
        }

        setState(State::HttpRequest);
        // time for a http request
        QNetworkRequest req(d->result.putUrl);
        for (auto &h: d->result.putHeaders) {
            req.setRawHeader(h.name.toLatin1(), h.value.toLatin1());
        }
        auto reply = d->qnam->put(req, d->sourceDevice);
        connect(reply, &QNetworkReply::finished, this, [this, reply](){
            if (reply->error() == QNetworkReply::NoError) {
                done(State::Success);
            } else {
                d->result.statusCode   = ErrorCode::HttpFailed;
                d->result.statusString = reply->errorString();
                if (d->httpHosts.isEmpty())
                    done(State::Error);
                else
                    tryNextServer();
            }
            reply->deleteLater();
        });

    }, Qt::QueuedConnection);
    jt->request(host.jid, d->fileName, d->fileSize, d->mediaType, host.ver);
    jt->go(true);
}

bool HttpFileUpload::success() const
{
    return d->state == State::Success;
}

HttpFileUpload::ErrorCode HttpFileUpload::statusCode() const
{
    return d->result.statusCode;
}

const QString & HttpFileUpload::statusString() const
{
    return d->result.statusString;
}

HttpFileUpload::HttpSlot HttpFileUpload::getHttpSlot()
{
    HttpSlot slot;
    if (d->state == State::Success) {
        slot.get.url = d->result.getUrl;
        slot.put.url = d->result.putUrl;
        slot.put.headers = d->result.putHeaders;
        slot.limits.fileSize = d->result.sizeLimit;
    }
    return slot;
}

void HttpFileUpload::setState(State state)
{
    d->state = state;
    if (state == Success) {
        d->result.statusCode = ErrorCode::NoError;
        d->result.statusString.clear();
    }
    emit stateChanged();
}

void HttpFileUpload::done(State state)
{
    setState(state);
    emit finished();
}

//----------------------------------------------------------------------------
// JT_HTTPFileUpload
//----------------------------------------------------------------------------
class JT_HTTPFileUpload::Private
{
public:
    Jid to;
    QDomElement iq;
    QStringList urls;
    XEP0363::version ver;
    XEP0363::HttpHeaders headers;
};

JT_HTTPFileUpload::JT_HTTPFileUpload(Task *parent)
    : Task(parent)
{
    d = new Private;
    d->ver = XEP0363::vUnknown;
    d->urls << QString() << QString();
}

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

void JT_HTTPFileUpload::request(const Jid &to, const QString &fname,
                                quint64 fsize, const QString &ftype, XEP0363::version ver)
{
    d->to = to;
    d->ver = ver;
    d->iq = createIQ(doc(), "get", to.full(), id());
    QDomElement req = doc()->createElement("request");
    switch (ver)
    {
    case XEP0363::v0_2_5:
        req.setAttribute("xmlns", xmlns_v0_2_5);
        req.appendChild(textTag(doc(), "filename", fname));
        req.appendChild(textTag(doc(), "size", QString::number(fsize)));
        if (!ftype.isEmpty()) {
            req.appendChild(textTag(doc(), "content-type", ftype));
        }
        break;
    case XEP0363::v0_3_1:
        req.setAttribute("xmlns", xmlns_v0_3_1);
        req.setAttribute("filename", fname);
        req.setAttribute("size", fsize);
        if (!ftype.isEmpty())
            req.setAttribute("content-type", ftype);
        break;
    default:
        d->ver = XEP0363::vUnknown;
        break;
    }
    d->iq.appendChild(req);
}

QString JT_HTTPFileUpload::url(UrlType t) const
{
    return d->urls.value(t);
}

XEP0363::HttpHeaders JT_HTTPFileUpload::headers() const
{
    return d->headers;
}

void JT_HTTPFileUpload::onGo()
{
    if (d->ver != XEP0363::vUnknown)
        send(d->iq);
}

bool JT_HTTPFileUpload::take(const QDomElement &e)
{
    if (!iqVerify(e, d->to, id()))
        return false;

    if (e.attribute("type") != "result") {
        setError(e);
        return true;
    }

    bool correct_xmlns = false;
    QString getUrl, putUrl;
    XEP0363::HttpHeaders headers;
    const QDomElement &slot = e.firstChildElement("slot");
    if (!slot.isNull()) {
        const QDomElement &get = slot.firstChildElement("get");
        const QDomElement &put = slot.firstChildElement("put");
        switch (d->ver)
        {
        case XEP0363::v0_2_5:
            correct_xmlns = slot.attribute("xmlns") == xmlns_v0_2_5;
            getUrl = tagContent(get);
            putUrl = tagContent(put);
            break;
        case XEP0363::v0_3_1:
            correct_xmlns = slot.attribute("xmlns") == xmlns_v0_3_1;
            getUrl = get.attribute("url");
            if (!put.isNull()) {
                putUrl = put.attribute("url");
                QDomElement he = put.firstChildElement("header");
                while (!he.isNull()) {
                    // only next are allowed: Authorization, Cookie, Expires
                    QString header = he.attribute("name").trimmed().remove(QLatin1Char('\n'));
                    QString value = he.text().trimmed().remove(QLatin1Char('\n'));
                    if (!value.isEmpty() &&
                            (header.compare(QLatin1String("Authorization"), Qt::CaseInsensitive) == 0 ||
                            header.compare(QLatin1String("Cookie"), Qt::CaseInsensitive) == 0 ||
                            header.compare(QLatin1String("Expires"), Qt::CaseInsensitive) == 0))
                    {
                        headers.append(XEP0363::HttpHeader{header, value});
                    }
                    he = he.nextSiblingElement("header");
                }
            }
            break;
        default:
            break;
        }
    }
    if (!correct_xmlns) {
        setError(ErrInvalidResponse);
        return true;
    }
    if (!getUrl.isEmpty() && !putUrl.isEmpty()) {
        d->urls[GetUrl] = getUrl;
        d->urls[PutUrl] = putUrl;
        d->headers      = headers;
        setSuccess();
    }
    else
        setError(ErrInvalidResponse, "Either `put` or `get` URL is missing in the server's reply.");
    return true;
}

class HttpFileUploadManager::Private {
public:
    Client *client = nullptr;
    QPointer<QNetworkAccessManager> qnam;
    QLinkedList<HttpFileUpload::HttpHost> hosts;
};

HttpFileUploadManager::HttpFileUploadManager(Client *parent) :
    QObject(parent),
    d(new Private)
{
    d->client = parent;
}

void HttpFileUploadManager::setNetworkAccessManager(QNetworkAccessManager *qnam)
{
    d->qnam = qnam;
}

HttpFileUpload* HttpFileUploadManager::upload(const QString &srcFilename, const QString &dstFilename, const QString &mType)
{
    auto f = new QFile(srcFilename);
    f->open(QIODevice::ReadOnly);
    auto hfu = upload(f, f->size(), dstFilename, mType);
    f->setParent(hfu);
    return hfu;
}

HttpFileUpload* HttpFileUploadManager::upload(QIODevice *source, size_t fsize, const QString &dstFilename, const QString &mType)
{
    auto hfu = new HttpFileUpload(d->client, source, fsize, dstFilename, mType);
    hfu->setNetworkAccessManager(d->qnam);
    QMetaObject::invokeMethod(hfu, "start", Qt::QueuedConnection);
    return hfu;
}
<commit_msg>Fix clang warning:<commit_after>/*
 * httpfileupload.cpp - HTTP File upload
 * Copyright (C) 2017-2019  Aleksey Andreev, Sergey Ilinykh
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 *
 */

#include <QList>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QNetworkRequest>
#include <QRegExp>

#include "httpfileupload.h"
#include "xmpp_tasks.h"
#include "xmpp_xmlcommon.h"
#include "xmpp_serverinfomanager.h"

using namespace XMPP;

static QLatin1String xmlns_v0_2_5("urn:xmpp:http:upload");
static QLatin1String xmlns_v0_3_1("urn:xmpp:http:upload:0");

//----------------------------------------------------------------------------
// HttpFileUpload
//----------------------------------------------------------------------------
class HttpFileUpload::Private
{
public:
    HttpFileUpload::State state = State::None;
    XMPP::Client *client = nullptr;
    QIODevice *sourceDevice = nullptr;
    QPointer<QNetworkAccessManager> qnam = nullptr;
    quint64 fileSize = 0;
    QString fileName;
    QString mediaType;
    QList<HttpHost> httpHosts;

    struct {
        HttpFileUpload::ErrorCode statusCode = HttpFileUpload::ErrorCode::NoError;
        QString statusString;
        QString getUrl;
        QString putUrl;
        XEP0363::HttpHeaders putHeaders;
        quint64 sizeLimit = 0;
    } result;
};

HttpFileUpload::HttpFileUpload(XMPP::Client *client, QIODevice *source, size_t fsize, const QString &dstFilename,
                               const QString &mType) :
    QObject(client),
    d(new Private)
{
    d->client = client;
    d->sourceDevice = source;
    d->fileName = dstFilename;
    d->fileSize = fsize;
    d->mediaType = mType;
}

HttpFileUpload::~HttpFileUpload()
{
    qDebug("destroying");
}

void HttpFileUpload::setNetworkAccessManager(QNetworkAccessManager *qnam)
{
    d->qnam = qnam;
}

void HttpFileUpload::start()
{
    if (d->state != State::None) // Attempt to start twice?
        return;

    setState(State::GettingSlot);

    d->result.statusCode = HttpFileUpload::ErrorCode::NoError;
    static QList<QSet<QString>> featureOptions;
    if (featureOptions.isEmpty()) {
        featureOptions << (QSet<QString>() << xmlns_v0_2_5) << (QSet<QString>() << xmlns_v0_3_1);
    }
    d->client->serverInfoManager()->queryServiceInfo(
                QLatin1String("store"), QLatin1String("file"),
                featureOptions, QRegExp("^(upload|http|stor|file|dis|drive).*"), ServerInfoManager::SQ_CheckAllOnNoMatch,
                [this](const QList<DiscoItem> &items)
    {
        d->httpHosts.clear();
        for (const auto &item: items) {
            const QStringList &l = item.features().list();
            XEP0363::version ver = XEP0363::vUnknown;
            QString xmlns;
            quint64 sizeLimit = 0;
            if (l.contains(xmlns_v0_3_1)) {
                ver = XEP0363::v0_3_1;
                xmlns = xmlns_v0_3_1;
            } else if (l.contains(xmlns_v0_2_5)) {
                ver = XEP0363::v0_2_5;
                xmlns = xmlns_v0_2_5;
            }
            if (ver != XEP0363::vUnknown) {
                QList<std::pair<HttpHost,int>> hosts;
                const XData::Field field = item.registeredExtension(xmlns).getField(QLatin1String("max-file-size"));
                if (field.isValid() && field.type() == XData::Field::Field_TextSingle)
                    sizeLimit = field.value().at(0).toULongLong();
                HttpHost host;
                host.ver = ver;
                host.jid = item.jid();
                host.sizeLimit = sizeLimit;
                QVariant metaProps(d->client->serverInfoManager()->serviceMeta(host.jid, "httpprops"));
                if (metaProps.isValid()) {
                    host.props = HostProps(metaProps.value<int>());
                } else {
                    host.props = SecureGet | SecurePut;
                    if (ver == XEP0363::v0_3_1)
                        host.props |= NewestVer;
                }
                int value = 0;
                if (host.props & SecureGet) value += 5;
                if (host.props & SecurePut) value += 5;
                if (host.props & NewestVer) value += 3;
                if (host.props & Failure) value -= 15;
                if (!sizeLimit || d->fileSize < sizeLimit)
                    hosts.append({host,value});

                // no sorting in preference order. most preferred go first
                std::sort(hosts.begin(), hosts.end(), [](const auto &a, const auto &b){
                    return a.second > b.second;
                });
                for (auto &hp: hosts) {
                    d->httpHosts.append(hp.first);
                }
            }
        }
        //d->currentHost = d->httpHosts.begin();
        if (d->httpHosts.isEmpty()) { // if empty as the last resort check all services
            d->result.statusCode   = HttpFileUpload::ErrorCode::NoUploadService;
            d->result.statusString = "No suitable http upload services were found";
            done(State::Error);
        } else {
            tryNextServer();
        }
    });
}

void HttpFileUpload::tryNextServer()
{
    if (d->httpHosts.isEmpty()) { // if empty as the last resort check all services
        d->result.statusCode   = HttpFileUpload::ErrorCode::NoUploadService;
        d->result.statusString = "All http services are either non compliant or returned errors";
        done(State::Error);
        return;
    }
    HttpHost host = d->httpHosts.takeFirst();
    d->result.sizeLimit = host.sizeLimit;
    auto jt = new JT_HTTPFileUpload(d->client->rootTask());
    connect(jt, &JT_HTTPFileUpload::finished, this, [this, jt, host]() mutable {
        if (!jt->success()) {
            host.props |= Failure;
            int code = jt->statusCode();
            if (code < 300) {
                code++; // ErrDisc and ErrTimeout. but 0 code is already occupated
            }
            d->result.statusCode   = static_cast<ErrorCode>(jt->statusCode());
            d->result.statusString = jt->statusString();
            d->client->serverInfoManager()->setServiceMeta(host.jid, QLatin1String("httpprops"), int(host.props));
            if (d->httpHosts.isEmpty())
                done(State::Error);
            else
                tryNextServer();
            return;
        }

        d->result.getUrl = jt->url(JT_HTTPFileUpload::GetUrl);
        d->result.putUrl = jt->url(JT_HTTPFileUpload::PutUrl);
        d->result.putHeaders = jt->headers();
        if (d->result.getUrl.startsWith("https://"))
            host.props |= SecureGet;
        else
            host.props &= ~SecureGet;
        if (d->result.putUrl.startsWith("https://"))
            host.props |= SecurePut;
        else
            host.props &= ~SecurePut;
        host.props &= ~Failure;

        d->client->serverInfoManager()->setServiceMeta(host.jid, QLatin1String("httpprops"), int(host.props));

        if (!d->qnam) { // w/o network access manager, it's not more than getting slots
            done(State::Success);
            return;
        }

        setState(State::HttpRequest);
        // time for a http request
        QNetworkRequest req(d->result.putUrl);
        for (auto &h: d->result.putHeaders) {
            req.setRawHeader(h.name.toLatin1(), h.value.toLatin1());
        }
        auto reply = d->qnam->put(req, d->sourceDevice);
        connect(reply, &QNetworkReply::finished, this, [this, reply](){
            if (reply->error() == QNetworkReply::NoError) {
                done(State::Success);
            } else {
                d->result.statusCode   = ErrorCode::HttpFailed;
                d->result.statusString = reply->errorString();
                if (d->httpHosts.isEmpty())
                    done(State::Error);
                else
                    tryNextServer();
            }
            reply->deleteLater();
        });

    }, Qt::QueuedConnection);
    jt->request(host.jid, d->fileName, d->fileSize, d->mediaType, host.ver);
    jt->go(true);
}

bool HttpFileUpload::success() const
{
    return d->state == State::Success;
}

HttpFileUpload::ErrorCode HttpFileUpload::statusCode() const
{
    return d->result.statusCode;
}

const QString & HttpFileUpload::statusString() const
{
    return d->result.statusString;
}

HttpFileUpload::HttpSlot HttpFileUpload::getHttpSlot()
{
    HttpSlot slot;
    if (d->state == State::Success) {
        slot.get.url = d->result.getUrl;
        slot.put.url = d->result.putUrl;
        slot.put.headers = d->result.putHeaders;
        slot.limits.fileSize = d->result.sizeLimit;
    }
    return slot;
}

void HttpFileUpload::setState(State state)
{
    d->state = state;
    if (state == Success) {
        d->result.statusCode = ErrorCode::NoError;
        d->result.statusString.clear();
    }
    emit stateChanged();
}

void HttpFileUpload::done(State state)
{
    setState(state);
    emit finished();
}

//----------------------------------------------------------------------------
// JT_HTTPFileUpload
//----------------------------------------------------------------------------
class JT_HTTPFileUpload::Private
{
public:
    Jid to;
    QDomElement iq;
    QStringList urls;
    XEP0363::version ver;
    XEP0363::HttpHeaders headers;
};

JT_HTTPFileUpload::JT_HTTPFileUpload(Task *parent)
    : Task(parent)
{
    d = new Private;
    d->ver = XEP0363::vUnknown;
    d->urls << QString() << QString();
}

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

void JT_HTTPFileUpload::request(const Jid &to, const QString &fname,
                                quint64 fsize, const QString &ftype, XEP0363::version ver)
{
    d->to = to;
    d->ver = ver;
    d->iq = createIQ(doc(), "get", to.full(), id());
    QDomElement req = doc()->createElement("request");
    switch (ver)
    {
    case XEP0363::v0_2_5:
        req.setAttribute("xmlns", xmlns_v0_2_5);
        req.appendChild(textTag(doc(), "filename", fname));
        req.appendChild(textTag(doc(), "size", QString::number(fsize)));
        if (!ftype.isEmpty()) {
            req.appendChild(textTag(doc(), "content-type", ftype));
        }
        break;
    case XEP0363::v0_3_1:
        req.setAttribute("xmlns", xmlns_v0_3_1);
        req.setAttribute("filename", fname);
        req.setAttribute("size", fsize);
        if (!ftype.isEmpty())
            req.setAttribute("content-type", ftype);
        break;
    default:
        d->ver = XEP0363::vUnknown;
        break;
    }
    d->iq.appendChild(req);
}

QString JT_HTTPFileUpload::url(UrlType t) const
{
    return d->urls.value(t);
}

XEP0363::HttpHeaders JT_HTTPFileUpload::headers() const
{
    return d->headers;
}

void JT_HTTPFileUpload::onGo()
{
    if (d->ver != XEP0363::vUnknown)
        send(d->iq);
}

bool JT_HTTPFileUpload::take(const QDomElement &e)
{
    if (!iqVerify(e, d->to, id()))
        return false;

    if (e.attribute("type") != "result") {
        setError(e);
        return true;
    }

    bool correct_xmlns = false;
    QString getUrl, putUrl;
    XEP0363::HttpHeaders headers;
    const QDomElement &slot = e.firstChildElement("slot");
    if (!slot.isNull()) {
        const QDomElement &get = slot.firstChildElement("get");
        const QDomElement &put = slot.firstChildElement("put");
        switch (d->ver)
        {
        case XEP0363::v0_2_5:
            correct_xmlns = slot.attribute("xmlns") == xmlns_v0_2_5;
            getUrl = tagContent(get);
            putUrl = tagContent(put);
            break;
        case XEP0363::v0_3_1:
            correct_xmlns = slot.attribute("xmlns") == xmlns_v0_3_1;
            getUrl = get.attribute("url");
            if (!put.isNull()) {
                putUrl = put.attribute("url");
                QDomElement he = put.firstChildElement("header");
                while (!he.isNull()) {
                    // only next are allowed: Authorization, Cookie, Expires
                    QString header = he.attribute("name").trimmed().remove(QLatin1Char('\n'));
                    QString value = he.text().trimmed().remove(QLatin1Char('\n'));
                    if (!value.isEmpty() &&
                            (header.compare(QLatin1String("Authorization"), Qt::CaseInsensitive) == 0 ||
                            header.compare(QLatin1String("Cookie"), Qt::CaseInsensitive) == 0 ||
                            header.compare(QLatin1String("Expires"), Qt::CaseInsensitive) == 0))
                    {
                        headers.append(XEP0363::HttpHeader{header, value});
                    }
                    he = he.nextSiblingElement("header");
                }
            }
            break;
        default:
            break;
        }
    }
    if (!correct_xmlns) {
        setError(ErrInvalidResponse);
        return true;
    }
    if (!getUrl.isEmpty() && !putUrl.isEmpty()) {
        d->urls[GetUrl] = getUrl;
        d->urls[PutUrl] = putUrl;
        d->headers      = headers;
        setSuccess();
    }
    else
        setError(ErrInvalidResponse, "Either `put` or `get` URL is missing in the server's reply.");
    return true;
}

class HttpFileUploadManager::Private {
public:
    Client *client = nullptr;
    QPointer<QNetworkAccessManager> qnam;
    QLinkedList<HttpFileUpload::HttpHost> hosts;
};

HttpFileUploadManager::HttpFileUploadManager(Client *parent) :
    QObject(parent),
    d(new Private)
{
    d->client = parent;
}

void HttpFileUploadManager::setNetworkAccessManager(QNetworkAccessManager *qnam)
{
    d->qnam = qnam;
}

HttpFileUpload* HttpFileUploadManager::upload(const QString &srcFilename, const QString &dstFilename, const QString &mType)
{
    auto f = new QFile(srcFilename);
    f->open(QIODevice::ReadOnly);
    auto hfu = upload(f, f->size(), dstFilename, mType);
    f->setParent(hfu);
    return hfu;
}

HttpFileUpload* HttpFileUploadManager::upload(QIODevice *source, size_t fsize, const QString &dstFilename, const QString &mType)
{
    auto hfu = new HttpFileUpload(d->client, source, fsize, dstFilename, mType);
    hfu->setNetworkAccessManager(d->qnam);
    QMetaObject::invokeMethod(hfu, "start", Qt::QueuedConnection);
    return hfu;
}
<|endoftext|>


<commit_before>#ifndef STAN_MATH_PRIM_MAT_FUN_PROMOTER_HPP
#define STAN_MATH_PRIM_MAT_FUN_PROMOTER_HPP

#include <stan/math/prim/arr/fun/promoter.hpp>
#include <stan/math/prim/mat/fun/Eigen.hpp>

namespace stan {
  namespace math {
    /**
     * Struct which holds static function for element-wise type promotion.
     * This specialization promotes Eigen matrix elements of different types.
     *
     * @tparam F type of input element
     * @tparam T type of output element
     */
    template <typename F, typename T>
    struct promoter<Eigen::Matrix<F, Eigen::Dynamic, Eigen::Dynamic>,
                    Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> > {
      inline static void promote(const Eigen::Matrix<F,
                                 Eigen::Dynamic, Eigen::Dynamic>& u,
                                 Eigen::Matrix<T,
                                 Eigen::Dynamic, Eigen::Dynamic>& t) {
        t.resize(u.rows(), u.cols());
        for (int i = 0; i < u.size(); ++i)
          promoter<F, T>::promote(u(i), t(i));
      }
      inline static Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic>
      promote_to(const Eigen::Matrix<F, Eigen::Dynamic, Eigen::Dynamic>& u) {
        Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> t;
        promoter<Eigen::Matrix<F, Eigen::Dynamic, Eigen::Dynamic>,
                 Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic>
                 >::promote(u, t);
        return t;
      }
    };

    /**
     * Struct which holds static function for element-wise type promotion.
     * This specialization promotes Eigen matrix elements of same type.
     *
     * @tparam T type of matrix element
     */
    template <typename T>
    struct promoter<Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic>,
                    Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> > {
      inline static void promote(const Eigen::Matrix<T,
                                 Eigen::Dynamic, Eigen::Dynamic>& u,
                          Eigen::Matrix<T,
                                 Eigen::Dynamic, Eigen::Dynamic>& t) {
        t = u;
      }
      inline static Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic>
      promote_to(const Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic>& u) {
        return u;
      }
    };

  }
}

#endif
<commit_msg>promoter needs matrix specialization, called from promote_to<commit_after>#ifndef STAN_MATH_PRIM_MAT_FUN_PROMOTER_HPP
#define STAN_MATH_PRIM_MAT_FUN_PROMOTER_HPP

#include <stan/math/prim/arr/fun/promoter.hpp>
#include <stan/math/prim/mat/fun/Eigen.hpp>

namespace stan {
  namespace math {
    /**
     * Struct which holds static function for element-wise type promotion.
     * This specialization promotes Eigen matrix elements of different types.
     *
     * @tparam F type of input element
     * @tparam T type of output element
     * @tparam R number of rows
     * @tparam C number of columns
     */
    template <typename F, typename T, int R, int C>
    struct promoter<Eigen::Matrix<F, R, C>,
                    Eigen::Matrix<T, R, C> > {
      inline static void promote(const Eigen::Matrix<F,
                                 R, C>& u,
                                 Eigen::Matrix<T,
                                 R, C>& t) {
        t.resize(u.rows(), u.cols());
        for (int i = 0; i < u.size(); ++i)
          promoter<F, T>::promote(u(i), t(i));
      }
      inline static Eigen::Matrix<T, R, C>
      promote_to(const Eigen::Matrix<F, R, C>& u) {
        Eigen::Matrix<T, R, C> t;
        promoter<Eigen::Matrix<F, R, C>,
                 Eigen::Matrix<T, R, C>
                 >::promote(u, t);
        return t;
      }
    };

    /**
     * Struct which holds static function for element-wise type promotion.
     * This specialization promotes Eigen matrix elements of same type.
     *
     * @tparam T type of matrix element
     * @tparam R number of rows
     * @tparam C number of columns
     */
    template <typename T, int R, int C>
    struct promoter<Eigen::Matrix<T, R, C>,
                    Eigen::Matrix<T, R, C> > {
      inline static void promote(const Eigen::Matrix<T,
                                 R, C>& u,
                          Eigen::Matrix<T,
                                 R, C>& t) {
        t = u;
      }
      inline static Eigen::Matrix<T, R, C>
      promote_to(const Eigen::Matrix<T, R, C>& u) {
        return u;
      }
    };

  }
}

#endif
<|endoftext|>


<commit_before>#ifndef STAN_MATH_PRIM_PROB_NORMAL_LPDF_HPP
#define STAN_MATH_PRIM_PROB_NORMAL_LPDF_HPP

#include <stan/math/prim/meta.hpp>
#include <stan/math/prim/err.hpp>
#include <stan/math/prim/fun/as_column_vector_or_scalar.hpp>
#include <stan/math/prim/fun/as_array_or_scalar.hpp>
#include <stan/math/prim/fun/as_value_column_array_or_scalar.hpp>
#include <stan/math/prim/fun/constants.hpp>
#include <stan/math/prim/fun/log.hpp>
#include <stan/math/prim/fun/max_size.hpp>
#include <stan/math/prim/fun/size.hpp>
#include <stan/math/prim/fun/size_zero.hpp>
#include <stan/math/prim/fun/to_ref.hpp>
#include <stan/math/prim/fun/value_of.hpp>
#include <stan/math/prim/functor/operands_and_partials.hpp>
#include <cmath>

namespace stan {
namespace math {

/** \ingroup prob_dists
 * The log of the normal density for the specified scalar(s) given
 * the specified mean(s) and deviation(s). y, mu, or sigma can
 * each be either a scalar or a vector. Any vector inputs
 * must be the same length.
 *
 *
The result log probability is defined to be the sum of the
 * log probabilities for each observation/mean/deviation triple.
 *
 * @tparam T_y type of scalar
 * @tparam T_loc type of location parameter
 * @tparam T_scale type of scale parameter
 * @param y (Sequence of) scalar(s).
 * @param mu (Sequence of) location parameter(s)
 * for the normal distribution.
 * @param sigma (Sequence of) scale parameters for the normal distribution.
 * @return The log of the product of the densities.
 * @throw std::domain_error if the scale is not positive.
 */
template <bool propto, typename T_y, typename T_loc, typename T_scale,
          require_all_not_nonscalar_prim_or_rev_kernel_expression_t<
              T_y, T_loc, T_scale>* = nullptr>
inline return_type_t<T_y, T_loc, T_scale> normal_lpdf(const T_y& y,
                                                      const T_loc& mu,
                                                      const T_scale& sigma) {
  using T_partials_return = partials_return_t<T_y, T_loc, T_scale>;
  using T_y_ref = ref_type_if_t<!is_constant<T_y>::value, T_y>;
  using T_mu_ref = ref_type_if_t<!is_constant<T_loc>::value, T_loc>;
  using T_sigma_ref = ref_type_if_t<!is_constant<T_scale>::value, T_scale>;
  static const char* function = "normal_lpdf";
  check_consistent_sizes(function, "Random variable", y, "Location parameter",
                         mu, "Scale parameter", sigma);
  T_y_ref y_ref = y;
  T_mu_ref mu_ref = mu;
  T_sigma_ref sigma_ref = sigma;

  decltype(auto) y_val = to_ref(as_value_column_array_or_scalar(y_ref));
  decltype(auto) mu_val = to_ref(as_value_column_array_or_scalar(mu_ref));
  decltype(auto) sigma_val = to_ref(as_value_column_array_or_scalar(sigma_ref));

  check_not_nan(function, "Random variable", y_val);
  check_finite(function, "Location parameter", mu_val);
  check_positive(function, "Scale parameter", sigma_val);

  if (size_zero(y, mu, sigma)) {
    return 0.0;
  }
  if (!include_summand<propto, T_y, T_loc, T_scale>::value) {
    return 0.0;
  }

  operands_and_partials<T_y_ref, T_mu_ref, T_sigma_ref> ops_partials(
      y_ref, mu_ref, sigma_ref);

  const auto& inv_sigma
      = to_ref_if<!is_constant_all<T_y, T_scale, T_loc>::value>(inv(sigma_val));
  const auto& y_scaled = to_ref((y_val - mu_val) * inv_sigma);
  const auto& y_scaled_sq
      = to_ref_if<!is_constant_all<T_scale>::value>(y_scaled * y_scaled);

  size_t N = max_size(y, mu, sigma);
  T_partials_return logp = -0.5 * sum(y_scaled_sq);
  if (include_summand<propto>::value) {
    logp += NEG_LOG_SQRT_TWO_PI * N;
  }
  if (include_summand<propto, T_scale>::value) {
    logp -= sum(log(sigma_val)) * N / size(sigma);
  }

  if (!is_constant_all<T_y, T_scale, T_loc>::value) {
    auto scaled_diff = to_ref_if<!is_constant_all<T_y>::value
                                     + !is_constant_all<T_scale>::value
                                     + !is_constant_all<T_loc>::value
                                 >= 2>(inv_sigma * y_scaled);
    if (!is_constant_all<T_y>::value) {
      ops_partials.edge1_.partials_ = -scaled_diff;
    }
    if (!is_constant_all<T_scale>::value) {
      ops_partials.edge3_.partials_ = inv_sigma * y_scaled_sq - inv_sigma;
    }
    if (!is_constant_all<T_loc>::value) {
      ops_partials.edge2_.partials_ = std::move(scaled_diff);
    }
  }
  return ops_partials.build(logp);
}

template <typename T_y, typename T_loc, typename T_scale>
inline return_type_t<T_y, T_loc, T_scale> normal_lpdf(const T_y& y,
                                                      const T_loc& mu,
                                                      const T_scale& sigma) {
  return normal_lpdf<false>(y, mu, sigma);
}

}  // namespace math
}  // namespace stan
#endif
<commit_msg>Added some couts. All tests passed.<commit_after>#ifndef STAN_MATH_PRIM_PROB_NORMAL_LPDF_HPP
#define STAN_MATH_PRIM_PROB_NORMAL_LPDF_HPP

#include <stan/math/prim/meta.hpp>
#include <stan/math/prim/err.hpp>
#include <stan/math/prim/fun/as_column_vector_or_scalar.hpp>
#include <stan/math/prim/fun/as_array_or_scalar.hpp>
#include <stan/math/prim/fun/as_value_column_array_or_scalar.hpp>
#include <stan/math/prim/fun/constants.hpp>
#include <stan/math/prim/fun/log.hpp>
#include <stan/math/prim/fun/max_size.hpp>
#include <stan/math/prim/fun/size.hpp>
#include <stan/math/prim/fun/size_zero.hpp>
#include <stan/math/prim/fun/to_ref.hpp>
#include <stan/math/prim/fun/value_of.hpp>
#include <stan/math/prim/functor/operands_and_partials.hpp>
#include <cmath>

namespace stan {
namespace math {

/** \ingroup prob_dists
 * The log of the normal density for the specified scalar(s) given
 * the specified mean(s) and deviation(s). y, mu, or sigma can
 * each be either a scalar or a vector. Any vector inputs
 * must be the same length.
 *
 *
The result log probability is defined to be the sum of the
 * log probabilities for each observation/mean/deviation triple.
 *
 * @tparam T_y type of scalar
 * @tparam T_loc type of location parameter
 * @tparam T_scale type of scale parameter
 * @param y (Sequence of) scalar(s).
 * @param mu (Sequence of) location parameter(s)
 * for the normal distribution.
 * @param sigma (Sequence of) scale parameters for the normal distribution.
 * @return The log of the product of the densities.
 * @throw std::domain_error if the scale is not positive.
 */
template <bool propto, typename T_y, typename T_loc, typename T_scale,
          require_all_not_nonscalar_prim_or_rev_kernel_expression_t<
              T_y, T_loc, T_scale>* = nullptr>
inline return_type_t<T_y, T_loc, T_scale> normal_lpdf(const T_y& y,
                                                      const T_loc& mu,
                                                      const T_scale& sigma) {
  using T_partials_return = partials_return_t<T_y, T_loc, T_scale>;
  using T_y_ref = ref_type_if_t<!is_constant<T_y>::value, T_y>;
  using T_mu_ref = ref_type_if_t<!is_constant<T_loc>::value, T_loc>;
  using T_sigma_ref = ref_type_if_t<!is_constant<T_scale>::value, T_scale>;
  static const char* function = "normal_lpdf";
  check_consistent_sizes(function, "Random variable", y, "Location parameter",
                         mu, "Scale parameter", sigma);
  T_y_ref y_ref = y;
  T_mu_ref mu_ref = mu;
  T_sigma_ref sigma_ref = sigma;

  decltype(auto) y_val = to_ref(as_value_column_array_or_scalar(y_ref));
  decltype(auto) mu_val = to_ref(as_value_column_array_or_scalar(mu_ref));
  decltype(auto) sigma_val = to_ref(as_value_column_array_or_scalar(sigma_ref));

  check_not_nan(function, "Random variable", y_val);
  check_finite(function, "Location parameter", mu_val);
  check_positive(function, "Scale parameter", sigma_val);

  if (size_zero(y, mu, sigma)) {
    return 0.0;
  }
  if (!include_summand<propto, T_y, T_loc, T_scale>::value) {
    return 0.0;
  }

  operands_and_partials<T_y_ref, T_mu_ref, T_sigma_ref> ops_partials(
      y_ref, mu_ref, sigma_ref);

  const auto& inv_sigma
      = to_ref_if<!is_constant_all<T_y, T_scale, T_loc>::value>(inv(sigma_val));
  const auto& y_scaled = to_ref((y_val - mu_val) * inv_sigma);
  const auto& y_scaled_sq
      = to_ref_if<!is_constant_all<T_scale>::value>(y_scaled * y_scaled);

  size_t N = max_size(y, mu, sigma);
  T_partials_return logp = -0.5 * sum(y_scaled_sq);
  if (include_summand<propto>::value) {
    logp += NEG_LOG_SQRT_TWO_PI * N;
  }
  if (include_summand<propto, T_scale>::value) {
    logp -= sum(log(sigma_val)) * N / size(sigma);
  }

  if (!is_constant_all<T_y, T_scale, T_loc>::value) {
    auto scaled_diff = to_ref_if<!is_constant_all<T_y>::value
                                     + !is_constant_all<T_scale>::value
                                     + !is_constant_all<T_loc>::value
                                 >= 2>(inv_sigma * y_scaled);
    if (!is_constant_all<T_y>::value) {
      std::cout << "y partial: " << -scaled_diff << std::endl;
      ops_partials.edge1_.partials_ = -scaled_diff;
    }
    if (!is_constant_all<T_scale>::value) {
      std::cout << "mu partial: " << inv_sigma * y_scaled_sq - inv_sigma << std::endl;
      ops_partials.edge3_.partials_ = inv_sigma * y_scaled_sq - inv_sigma;
    }
    if (!is_constant_all<T_loc>::value) {
      std::cout << "mu partial: " << scaled_diff << std::endl;
      ops_partials.edge2_.partials_ = std::move(scaled_diff);
    }
  }
  return ops_partials.build(logp);
}

template <typename T_y, typename T_loc, typename T_scale>
inline return_type_t<T_y, T_loc, T_scale> normal_lpdf(const T_y& y,
                                                      const T_loc& mu,
                                                      const T_scale& sigma) {
  return normal_lpdf<false>(y, mu, sigma);
}

}  // namespace math
}  // namespace stan
#endif
<|endoftext|>


<commit_before>/*-----------------------------------------------------------------------------
 This source file is part of Hopsan NG

 Copyright (c) 2011
    Mikael Axin, Robert Braun, Alessandro Dell'Amico, Björn Eriksson,
    Peter Nordin, Karl Pettersson, Petter Krus, Ingo Staack

 This file is provided "as is", with no guarantee or warranty for the
 functionality or reliability of the contents. All contents in this file is
 the original work of the copyright holders at the Division of Fluid and
 Mechatronic Systems (Flumes) at Linköping University. Modifying, using or
 redistributing any part of this file is prohibited without explicit
 permission from the copyright holders.
-----------------------------------------------------------------------------*/

//!
//! @file   HydraulicCylinderQ.hpp
//! @author Robert Braun <robert.braun@liu.se>
//! @date   2010-01-21
//!
//! @brief Contains a Hydraulic Cylinder of Q type with mass load
//!
//$Id$

////////////////////////////////////////////////////////////////////////////////////
//                                                                                //
//   <--------------Stroke--------------->                                        //
//                                                                                //
//   XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX                XXXXXXXX                //
//   X       Area1  X  X  Area2          X               X        X               //
//   X              X  XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX        X               //
//   X x1,v1,f1 <---O  X                                 X  Mass  O---> x2,v2,f2  //
//   X              X  XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX        X               //
//   X              X  X                 X               X        X               //
//   XXOXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXOXX                XXXXXXXX                //
//     |                               |                                          //
//     |                               |                                          //
//     V p1,q1                         V p2,q2                                    //
//                                                                                //
////////////////////////////////////////////////////////////////////////////////////

#ifndef HYDRAULICCYLINDERQ_HPP_INCLUDED
#define HYDRAULICCYLINDERQ_HPP_INCLUDED

#include <iostream>
#include "../../ComponentEssentials.h"
#include "../../ComponentUtilities.h"

namespace hopsan {

    //!
    //! @brief
    //! @ingroup HydraulicComponents
    //!
    class HydraulicCylinderQ : public ComponentQ
    {
    private:
        double mArea1;
        double mArea2;
        double mStroke;
        double mMass;
        double mBp;
        double mBl;
        double mKl;
        double mTao;
        SecondOrderFilter mPositionFilter;
        SecondOrderFilter mVelocityFilter;
        double posnum[3], posden[3], velnum[3], velden[3];
        double p1, q1, c1, Zc1, p2, q2, c2, Zc2, v1, cx1, Zx1, f2, x2, v2, cx2, Zx2;
        double *mpND_p1, *mpND_q1, *mpND_c1, *mpND_Zc1, *mpND_p2, *mpND_q2, *mpND_c2, *mpND_Zc2, *mpND_f2, *mpND_x2, *mpND_v2, *cmpND_x2, *mpND_Zx2;
        Port *mpP1, *mpP2, *mpP3;

    public:
        static Component *Creator()
        {
            return new HydraulicCylinderQ("CylinderQ");
        }

        HydraulicCylinderQ(const std::string name) : ComponentQ(name)
        {
            mArea1  = 0.0001;
            mArea2  = 0.0001;
            mStroke = 0.01;
            mMass   = 0.05;
            mBp     = 0.0;
            mBl     = 0;
            mKl     = 1000;
            mTao    = 3.0/2.0*mTimestep;        //Velocity filter time constant, should be in initialize?

            mpP1 = addPowerPort("P1", "NodeHydraulic");
            mpP2 = addPowerPort("P2", "NodeHydraulic");
            mpP3 = addPowerPort("P3", "NodeMechanic");

            registerParameter("A_1", "Piston Area 1", "[m^2]", mArea1);
            registerParameter("A_2", "Piston Area 2", "[m^2]", mArea2);
            registerParameter("s_l", "Stroke", "[m]", mStroke);
            registerParameter("B_p", "Viscous Friction Coefficient of Piston", "[Ns/m]", mBp);
            registerParameter("m_l", "Inertia Load", "[kg]", mMass);
            registerParameter("B_l", "Viscous Friction of Load", "[Ns/m]", mBl);
            registerParameter("k_l", "Stiffness of Load", "[N/m]", mKl);
        }

        void initialize()
        {
            //Assign node data pointers
            mpND_p1 = getSafeNodeDataPtr(mpP1, NodeHydraulic::PRESSURE);
            mpND_q1 = getSafeNodeDataPtr(mpP1, NodeHydraulic::FLOW);
            mpND_c1 = getSafeNodeDataPtr(mpP1, NodeHydraulic::WAVEVARIABLE);
            mpND_Zc1 = getSafeNodeDataPtr(mpP1, NodeHydraulic::CHARIMP);
            mpND_p2 = getSafeNodeDataPtr(mpP1, NodeHydraulic::PRESSURE);
            mpND_q2 = getSafeNodeDataPtr(mpP1, NodeHydraulic::FLOW);
            mpND_c2 = getSafeNodeDataPtr(mpP1, NodeHydraulic::WAVEVARIABLE);
            mpND_Zc2 = getSafeNodeDataPtr(mpP1, NodeHydraulic::CHARIMP);
            mpND_f2 = getSafeNodeDataPtr(mpP1, NodeMechanic::FORCE);
            mpND_x2 = getSafeNodeDataPtr(mpP1, NodeMechanic::POSITION);
            mpND_v2 = getSafeNodeDataPtr(mpP1, NodeMechanic::VELOCITY);
            cmpND_x2 = getSafeNodeDataPtr(mpP1, NodeMechanic::WAVEVARIABLE);
            mpND_Zx2 = getSafeNodeDataPtr(mpP1, NodeMechanic::CHARIMP);

            //Read data from nodes
            x2 = (*mpND_x2);
            v2 = (*mpND_v2);
            Zc1 = (*mpND_Zc1);
            Zc2 = (*mpND_Zc2);
            cx2 = (*cmpND_x2);
            Zx2 = (*mpND_Zx2);

            Zx1 = mArea1*mArea1*Zc1 + mArea2*mArea2*Zc2-mBp;

            //Initialization of filters
            posnum[0] = 0.0;
            posnum[1] = 0.0;
            posnum[2] = 1.0;
            posden[0] = mMass;
            posden[1] = mBl+Zx1+Zx2;
            posden[2] = mKl;
            velnum[0] = 0.0;
            velnum[1] = 1.0;
            velnum[2] = 0.0;
            velden[0] = 0.0;
            velden[1] = mTao;
            velden[2] = 1.0;

            mPositionFilter.initialize(mTimestep, posnum, posden, cx2, x2, 0.0, mStroke);
            mVelocityFilter.initialize(mTimestep, velnum, velden, x2, v2);
        }

        void simulateOneTimestep()
        {
            //Get variable values from nodes
            c1 = (*mpND_c1);
            Zc1 = (*mpND_Zc1);
            c2 = (*mpND_c2);
            Zc2 = (*mpND_Zc2);
            cx2 = (*cmpND_x2);
            Zx2 = (*mpND_Zx2);

            //CylinderCtest Equations

            //Internal mechanical port
            cx1 = mArea1*c1 - mArea2*c2;
            Zx1 = mArea1*mArea1*Zc1 + mArea2*mArea2*Zc2-mBp;

            //Piston
            posden [1] = mBl+Zx1+Zx2;
            mPositionFilter.setNumDen(posnum, posden);
            mPositionFilter.update(cx1-cx2);
            x2 = mPositionFilter.value();

            mVelocityFilter.update(x2);
            v2 = mVelocityFilter.value();

            v1 = -v2;
            f2 = cx2 + Zc2*v2;

            //Volumes
            q1 = mArea1*v1;
            q2 = mArea2*v2;
            p1 = c1 + Zc1*q1;
            p2 = c2 + Zc2*q2;

            //Cavitation check
            if(p1 < 0.0) { p1 = 0.0; }
            if(p2 < 0.0) { p2 = 0.0; }

            //Write new values to nodes
            (*mpND_p1) = p1;
            (*mpND_q1) = q1;
            (*mpND_p2) = p2;
            (*mpND_q2) = q2;
            (*mpND_f2) = f2;
            (*mpND_x2) = x2;
            (*mpND_v2) = v2;
        }
    };
}

#endif // HYDRAULICCYLINDERQ_HPP_INCLUDED
<commit_msg>changed filter call in cylinder Q, it does not work. But, it could not had worked before either.<commit_after>/*-----------------------------------------------------------------------------
 This source file is part of Hopsan NG

 Copyright (c) 2011
    Mikael Axin, Robert Braun, Alessandro Dell'Amico, Björn Eriksson,
    Peter Nordin, Karl Pettersson, Petter Krus, Ingo Staack

 This file is provided "as is", with no guarantee or warranty for the
 functionality or reliability of the contents. All contents in this file is
 the original work of the copyright holders at the Division of Fluid and
 Mechatronic Systems (Flumes) at Linköping University. Modifying, using or
 redistributing any part of this file is prohibited without explicit
 permission from the copyright holders.
-----------------------------------------------------------------------------*/

//!
//! @file   HydraulicCylinderQ.hpp
//! @author Robert Braun <robert.braun@liu.se>
//! @date   2010-01-21
//!
//! @brief Contains a Hydraulic Cylinder of Q type with mass load
//!
//$Id$

////////////////////////////////////////////////////////////////////////////////////
//                                                                                //
//   <--------------Stroke--------------->                                        //
//                                                                                //
//   XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX                XXXXXXXX                //
//   X       Area1  X  X  Area2          X               X        X               //
//   X              X  XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX        X               //
//   X x1,v1,f1 <---O  X                                 X  Mass  O---> x2,v2,f2  //
//   X              X  XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX        X               //
//   X              X  X                 X               X        X               //
//   XXOXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXOXX                XXXXXXXX                //
//     |                               |                                          //
//     |                               |                                          //
//     V p1,q1                         V p2,q2                                    //
//                                                                                //
////////////////////////////////////////////////////////////////////////////////////

#ifndef HYDRAULICCYLINDERQ_HPP_INCLUDED
#define HYDRAULICCYLINDERQ_HPP_INCLUDED

#include <iostream>
#include "../../ComponentEssentials.h"
#include "../../ComponentUtilities.h"

namespace hopsan {

    //!
    //! @brief
    //! @ingroup HydraulicComponents
    //!
    class HydraulicCylinderQ : public ComponentQ
    {
    private:
        double mArea1;
        double mArea2;
        double mStroke;
        double mMass;
        double mBp;
        double mBl;
        double mKl;
        double mTao;
        SecondOrderFilter mPositionFilter;
        SecondOrderFilter mVelocityFilter;
        double posnum[3], posden[3], velnum[3], velden[3];
        double p1, q1, c1, Zc1, p2, q2, c2, Zc2, v1, cx1, Zx1, f2, x2, v2, cx2, Zx2;
        double *mpND_p1, *mpND_q1, *mpND_c1, *mpND_Zc1, *mpND_p2, *mpND_q2, *mpND_c2, *mpND_Zc2, *mpND_f2, *mpND_x2, *mpND_v2, *cmpND_x2, *mpND_Zx2;
        Port *mpP1, *mpP2, *mpP3;

    public:
        static Component *Creator()
        {
            return new HydraulicCylinderQ("CylinderQ");
        }

        HydraulicCylinderQ(const std::string name) : ComponentQ(name)
        {
            mArea1  = 0.0001;
            mArea2  = 0.0001;
            mStroke = 0.01;
            mMass   = 0.05;
            mBp     = 0.0;
            mBl     = 0;
            mKl     = 1000;
            mTao    = 3.0/2.0*mTimestep;        //Velocity filter time constant, should be in initialize?

            mpP1 = addPowerPort("P1", "NodeHydraulic");
            mpP2 = addPowerPort("P2", "NodeHydraulic");
            mpP3 = addPowerPort("P3", "NodeMechanic");

            registerParameter("A_1", "Piston Area 1", "[m^2]", mArea1);
            registerParameter("A_2", "Piston Area 2", "[m^2]", mArea2);
            registerParameter("s_l", "Stroke", "[m]", mStroke);
            registerParameter("B_p", "Viscous Friction Coefficient of Piston", "[Ns/m]", mBp);
            registerParameter("m_l", "Inertia Load", "[kg]", mMass);
            registerParameter("B_l", "Viscous Friction of Load", "[Ns/m]", mBl);
            registerParameter("k_l", "Stiffness of Load", "[N/m]", mKl);
        }

        void initialize()
        {
            //Assign node data pointers
            mpND_p1 = getSafeNodeDataPtr(mpP1, NodeHydraulic::PRESSURE);
            mpND_q1 = getSafeNodeDataPtr(mpP1, NodeHydraulic::FLOW);
            mpND_c1 = getSafeNodeDataPtr(mpP1, NodeHydraulic::WAVEVARIABLE);
            mpND_Zc1 = getSafeNodeDataPtr(mpP1, NodeHydraulic::CHARIMP);
            mpND_p2 = getSafeNodeDataPtr(mpP1, NodeHydraulic::PRESSURE);
            mpND_q2 = getSafeNodeDataPtr(mpP1, NodeHydraulic::FLOW);
            mpND_c2 = getSafeNodeDataPtr(mpP1, NodeHydraulic::WAVEVARIABLE);
            mpND_Zc2 = getSafeNodeDataPtr(mpP1, NodeHydraulic::CHARIMP);
            mpND_f2 = getSafeNodeDataPtr(mpP1, NodeMechanic::FORCE);
            mpND_x2 = getSafeNodeDataPtr(mpP1, NodeMechanic::POSITION);
            mpND_v2 = getSafeNodeDataPtr(mpP1, NodeMechanic::VELOCITY);
            cmpND_x2 = getSafeNodeDataPtr(mpP1, NodeMechanic::WAVEVARIABLE);
            mpND_Zx2 = getSafeNodeDataPtr(mpP1, NodeMechanic::CHARIMP);

            //Read data from nodes
            x2 = (*mpND_x2);
            v2 = (*mpND_v2);
            Zc1 = (*mpND_Zc1);
            Zc2 = (*mpND_Zc2);
            cx2 = (*cmpND_x2);
            Zx2 = (*mpND_Zx2);

            Zx1 = mArea1*mArea1*Zc1 + mArea2*mArea2*Zc2-mBp;

            //Initialization of filters
            posnum[0] = 0.0;
            posnum[1] = 0.0;
            posnum[2] = 1.0;
            posden[0] = mKl;
            posden[1] = mBl+Zx1+Zx2;
            posden[2] = mMass;
            velnum[0] = 0.0;
            velnum[1] = 1.0;
            velnum[2] = 0.0;
            velden[0] = 1.0;
            velden[1] = mTao;
            velden[2] = 0.0;

            mPositionFilter.initialize(mTimestep, posnum, posden, cx2, x2, 0.0, mStroke);
            mVelocityFilter.initialize(mTimestep, velnum, velden, x2, v2);
        }

        void simulateOneTimestep()
        {
            //Get variable values from nodes
            c1 = (*mpND_c1);
            Zc1 = (*mpND_Zc1);
            c2 = (*mpND_c2);
            Zc2 = (*mpND_Zc2);
            cx2 = (*cmpND_x2);
            Zx2 = (*mpND_Zx2);

            //CylinderCtest Equations

            //Internal mechanical port
            cx1 = mArea1*c1 - mArea2*c2;
            Zx1 = mArea1*mArea1*Zc1 + mArea2*mArea2*Zc2-mBp;

            //Piston
            posden [1] = mBl+Zx1+Zx2;
            mPositionFilter.setNumDen(posnum, posden);
            mPositionFilter.update(cx1-cx2);
            x2 = mPositionFilter.value();

            mVelocityFilter.update(x2);
            v2 = mVelocityFilter.value();

            v1 = -v2;
            f2 = cx2 + Zc2*v2;

            //Volumes
            q1 = mArea1*v1;
            q2 = mArea2*v2;
            p1 = c1 + Zc1*q1;
            p2 = c2 + Zc2*q2;

            //Cavitation check
            if(p1 < 0.0) { p1 = 0.0; }
            if(p2 < 0.0) { p2 = 0.0; }

            //Write new values to nodes
            (*mpND_p1) = p1;
            (*mpND_q1) = q1;
            (*mpND_p2) = p2;
            (*mpND_q2) = q2;
            (*mpND_f2) = f2;
            (*mpND_x2) = x2;
            (*mpND_v2) = v2;
        }
    };
}

#endif // HYDRAULICCYLINDERQ_HPP_INCLUDED
<|endoftext|>


<commit_before>//
//  datarecovery.cpp
//  codeval1
//
//  Created by Malcolm Crum on 5/13/14.
//
//

#include <iostream>
#include <fstream>
#include <vector>
#include <string>
using namespace std;

int main(int argc, char** argv) {
    ifstream fileInput;
    fileInput.open(argv[1]);

    //while (fileInput.peek() != EOF) {

        string word;
        vector<string> words;
        fileInput >> word;
        while (word.find(';') == string::npos) {
            words.push_back(word);
            fileInput >> word;
        }
        // the last "word" would normally get grabbed as 'word;9'.
        // special handling is required to split it into 'word' and '9'
        int semicolonIndex = word.find(';');
        words.push_back(word.substr(0, semicolonIndex));
        cout << "read " << words.size() << " words" << endl;

        for (int i = 0; i < words.size(); i++) {
            cout << words[i] << " ";
        }
        cout << endl;

        int value;
        vector<string> orderedWords;
        orderedWords.resize(words.size());
        // again, special handling required to get the number out of 'word;9'
        value = atoi(word.substr(semicolonIndex, word.size()).c_str());
        orderedWords[0] = words[value];
        for(int i = 1; fileInput.peek() != '\n'; i++) {
            fileInput >> value;
            cout << "words[" << value << "] = " << words[value] << endl;
            cout << "words[" << i << "] = " << words[i] << endl;
            orderedWords[value] = words[i];
        }

        for (int i = 0; i < orderedWords.size(); i++) {
            cout << orderedWords[i] << " ";
        }
        cout << endl;
    //}
}<commit_msg>Forgot to actually finish this one. A hard 'easy'<commit_after>//
//  datarecovery.cpp
//  codeval1
//
//  Created by Malcolm Crum on 5/13/14.
//
//

#include <iostream>
#include <fstream>
#include <vector>
#include <sstream>
#include <algorithm>

using namespace std;

vector<string> splitString(string str) {
    vector<string> vec;
    stringstream ss(str);
    string s;
    while (ss >> s) {
        vec.push_back(s);
    }
    return vec;
}

vector<int> splitIntString(string str) {
    vector<int> vec;
    stringstream ss(str);
    int i;
    while (ss >> i) {
        vec.push_back(i);
    }
    return vec;
}

int main(int argc, char** argv) {
    ifstream fileInput;
    fileInput.open(argv[1]);

    string line;
    while (getline(fileInput, line)) {

        string wordString = line.substr(0, line.find(';'));
        vector<string> words = splitString(wordString);
        string orderString = line.substr(line.find(';') + 1);
        vector<int> order = splitIntString(orderString);

        vector<string> orderedWords(order.size() + 1);
        for (int i = 0; i < order.size(); ++i) {
            int index = order[i] - 1;
            //cout << words[i] << " ";
            orderedWords[index] = words[i];
        }

        int missingIndex = 1;
        for (int i = 1; i < words.size() + 1; ++i) {
            if (find(order.begin(), order.end(), i) == order.end()) {
                missingIndex = i;
                break;
            }
        }
        orderedWords[missingIndex - 1] = words.back();

        for (vector<string>::iterator it = orderedWords.begin(); it != orderedWords.end(); ++it) {
            cout << *it << " ";
        }
        cout << endl;
    }
}<|endoftext|>