<commit_before>/*
 * Copyright (c) 2002-2005 The Regents of The University of Michigan
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Authors: Ali Saidi
 */

#ifndef __ARCH_SPARC_SYSTEM_HH__
#define __ARCH_SPARC_SYSTEM_HH__

#include <string>
#include <vector>

#include "base/loader/symtab.hh"
#include "cpu/pc_event.hh"
#include "kern/system_events.hh"
#include "sim/sim_object.hh"
#include "sim/system.hh"

class SparcSystem : public System
{
  public:
    struct Params : public System::Params
    {
        std::string reset_bin;
        std::string hypervisor_bin;
        std::string openboot_bin;
        std::string boot_osflags;
        uint64_t system_type;
        uint64_t system_rev;
    };

    SparcSystem(Params *p);

    ~SparcSystem();

    virtual bool breakpoint();

/**
 * Serialization stuff
 */
  public:
    virtual void serialize(std::ostream &os);
    virtual void unserialize(Checkpoint *cp, const std::string &section);

    /** reset binary symbol table */
    SymbolTable *resetSymtab;

    /** hypervison binary symbol table */
    SymbolTable *hypervisorSymtab;

    /** openboot symbol table */
    SymbolTable *openbootSymtab;

    /** Object pointer for the reset binary */
    ObjectFile *reset;

    /** Object pointer for the hypervisor code */
    ObjectFile *hypervisor;

    /** Object pointer for the openboot code */
    ObjectFile *openboot;

    /** System Tick for syncronized tick across all cpus. */
    Tick sysTick;

  protected:
    const Params *params() const { return (const Params *)_params; }

    /** Add a function-based event to reset binary. */
    template <class T>
    T *SparcSystem::addResetFuncEvent(const char *lbl)
    {
        return addFuncEvent<T>(resetSymtab, lbl);
    }

    /** Add a function-based event to the hypervisor. */
    template <class T>
    T *SparcSystem::addHypervisorFuncEvent(const char *lbl)
    {
        return addFuncEvent<T>(hypervisorSymtab, lbl);
    }

    /** Add a function-based event to the openboot. */
    template <class T>
    T *SparcSystem::addOpenbootFuncEvent(const char *lbl)
    {
        return addFuncEvent<T>(openbootSymtab, lbl);
    }

    virtual Addr fixFuncEventAddr(Addr addr);

};

#endif

<commit_msg>Added a stub implementation of fixFuncEventAddr to get past linker errors.<commit_after>/*
 * Copyright (c) 2002-2005 The Regents of The University of Michigan
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Authors: Ali Saidi
 */

#ifndef __ARCH_SPARC_SYSTEM_HH__
#define __ARCH_SPARC_SYSTEM_HH__

#include <string>
#include <vector>

#include "base/loader/symtab.hh"
#include "cpu/pc_event.hh"
#include "kern/system_events.hh"
#include "sim/sim_object.hh"
#include "sim/system.hh"

class SparcSystem : public System
{
  public:
    struct Params : public System::Params
    {
        std::string reset_bin;
        std::string hypervisor_bin;
        std::string openboot_bin;
        std::string boot_osflags;
        uint64_t system_type;
        uint64_t system_rev;
    };

    SparcSystem(Params *p);

    ~SparcSystem();

    virtual bool breakpoint();

/**
 * Serialization stuff
 */
  public:
    virtual void serialize(std::ostream &os);
    virtual void unserialize(Checkpoint *cp, const std::string &section);

    /** reset binary symbol table */
    SymbolTable *resetSymtab;

    /** hypervison binary symbol table */
    SymbolTable *hypervisorSymtab;

    /** openboot symbol table */
    SymbolTable *openbootSymtab;

    /** Object pointer for the reset binary */
    ObjectFile *reset;

    /** Object pointer for the hypervisor code */
    ObjectFile *hypervisor;

    /** Object pointer for the openboot code */
    ObjectFile *openboot;

    /** System Tick for syncronized tick across all cpus. */
    Tick sysTick;

  protected:
    const Params *params() const { return (const Params *)_params; }

    /** Add a function-based event to reset binary. */
    template <class T>
    T *SparcSystem::addResetFuncEvent(const char *lbl)
    {
        return addFuncEvent<T>(resetSymtab, lbl);
    }

    /** Add a function-based event to the hypervisor. */
    template <class T>
    T *SparcSystem::addHypervisorFuncEvent(const char *lbl)
    {
        return addFuncEvent<T>(hypervisorSymtab, lbl);
    }

    /** Add a function-based event to the openboot. */
    template <class T>
    T *SparcSystem::addOpenbootFuncEvent(const char *lbl)
    {
        return addFuncEvent<T>(openbootSymtab, lbl);
    }

    virtual Addr fixFuncEventAddr(Addr addr)
    {
        //XXX This may eventually have to do something useful.
        return addr;
    }
};

#endif

<|endoftext|>


<commit_before>#include <msgpack.hpp>
#include <string>
#include <iostream>
#include <sstream>

namespace myprotocol {
	using namespace msgpack::type;
	using msgpack::define;

	struct Get : define< tuple<uint32_t, std::string> > {
		Get() { }
		Get(uint32_t f, const std::string& k) :
			define_type(msgpack_type(f, k)) { }
		uint32_t&    flags() { return get<0>(); }
		std::string& key()   { return get<1>(); }
	};

	struct Put : define< tuple<uint32_t, std::string, raw_ref> > {
		Put() { }
		Put(uint32_t f, const std::string& k, const char* valref, uint32_t vallen) :
			define_type(msgpack_type( f, k, raw_ref(valref,vallen) )) { }
		uint32_t&    flags() { return get<0>(); }
		std::string& key()   { return get<1>(); }
		raw_ref&     value() { return get<2>(); }
	};

	struct MultiGet : define< std::vector<Get> > {
	};
}

int main(void)
{
	// send Get request
	std::stringstream stream;
	{
		myprotocol::Get req;
		req.flags() = 0;
		req.key()   = "key0";
		msgpack::pack(stream, req);
	}

	stream.seekg(0);

	// receive Get request
	{
		std::string buffer(stream.str());

		msgpack::zone mempool;
		msgpack::object o =
			msgpack::unpack(buffer.data(), buffer.size(), mempool);

		myprotocol::Get req;
		msgpack::convert(req, o);
		std::cout << "received: " << o << std::endl;
	}

	stream.str("");

	// send MultiGet request
	{
		myprotocol::MultiGet req;
		req.push_back( myprotocol::Get(1, "key1") );
		req.push_back( myprotocol::Get(2, "key2") );
		req.push_back( myprotocol::Get(3, "key3") );
		msgpack::pack(stream, req);
	}

	stream.seekg(0);

	// receive MultiGet request
	{
		std::string buffer(stream.str());

		msgpack::zone mempool;
		msgpack::object o =
			msgpack::unpack(buffer.data(), buffer.size(), mempool);

		myprotocol::MultiGet req;
		msgpack::convert(req, o);
		std::cout << "received: " << o << std::endl;
	}
}

<commit_msg>Modified tuple's get calling from member function to free function.<commit_after>#include <msgpack.hpp>
#include <string>
#include <iostream>
#include <sstream>

namespace myprotocol {
	using namespace msgpack::type;
	using msgpack::define;

	struct Get : define< tuple<uint32_t, std::string> > {
		Get() { }
		Get(uint32_t f, const std::string& k) :
			define_type(msgpack_type(f, k)) { }
		uint32_t&    flags() { return msgpack::type::get<0>(*this); }
		std::string& key()   { return msgpack::type::get<1>(*this); }
	};

	struct Put : define< tuple<uint32_t, std::string, raw_ref> > {
		Put() { }
		Put(uint32_t f, const std::string& k, const char* valref, uint32_t vallen) :
			define_type(msgpack_type( f, k, raw_ref(valref,vallen) )) { }
		uint32_t&    flags() { return msgpack::type::get<0>(*this); }
		std::string& key()   { return msgpack::type::get<1>(*this); }
		raw_ref&     value() { return msgpack::type::get<2>(*this); }
	};

	struct MultiGet : define< std::vector<Get> > {
	};
}

int main(void)
{
	// send Get request
	std::stringstream stream;
	{
		myprotocol::Get req;
		req.flags() = 0;
		req.key()   = "key0";
		msgpack::pack(stream, req);
	}

	stream.seekg(0);

	// receive Get request
	{
		std::string buffer(stream.str());

		msgpack::zone mempool;
		msgpack::object o =
			msgpack::unpack(buffer.data(), buffer.size(), mempool);

		myprotocol::Get req;
		msgpack::convert(req, o);
		std::cout << "received: " << o << std::endl;
	}

	stream.str("");

	// send MultiGet request
	{
		myprotocol::MultiGet req;
		req.push_back( myprotocol::Get(1, "key1") );
		req.push_back( myprotocol::Get(2, "key2") );
		req.push_back( myprotocol::Get(3, "key3") );
		msgpack::pack(stream, req);
	}

	stream.seekg(0);

	// receive MultiGet request
	{
		std::string buffer(stream.str());

		msgpack::zone mempool;
		msgpack::object o =
			msgpack::unpack(buffer.data(), buffer.size(), mempool);

		myprotocol::MultiGet req;
		msgpack::convert(req, o);
		std::cout << "received: " << o << std::endl;
	}
}

<|endoftext|>


<commit_before>/*
 * qlibxmlnodemodel - A QAbstractXmlNodeModel for using with libxml2 library
 * Copyright (C) 2012 Alexey Torkhov
 * Copyright (C) 2011 Jonas Gehring
 * All rights reserved.
 *
 * Based on qhtmlnodemodel by Jonas Gehring
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of the copyright holders nor the
 *       names of its contributors may be used to endorse or promote products
 *       derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#include <QDebug>

#include <libxml/HTMLparser.h>
#include <libxml/tree.h>

#include "qlibxmlnodemodel.h"

// Internal private data
class QLibXmlNodeModelPrivate
{
public:
    QLibXmlNodeModel *model;
    QUrl uri;

    xmlDoc *doc;

    QLibXmlNodeModelPrivate(QLibXmlNodeModel *model)
        : model(model), doc(NULL)
    {
    }

    ~QLibXmlNodeModelPrivate()
    {
        xmlFreeDoc(doc);
        doc = NULL;
    }

    // Parses the given source tree
    void parse(const QByteArray &source)
    {
        doc = htmlReadMemory(source.data(), source.size(), uri.toString().toUtf8(), "utf-8", 0);

        if (doc == NULL) {
            qDebug() << "could not parse source" << source;
        }
    }

    // Converts a model index to a HTML node
    xmlNode *toNode(const QXmlNodeModelIndex &index) const
    {
        return (xmlNode *)index.internalPointer();
    }

    // Converts a HTML node to a model index
    QXmlNodeModelIndex toNodeIndex(xmlNode *node) const
    {
        return model->createIndex((void *)node);
    }
    QXmlNodeModelIndex toNodeIndex(xmlDoc *node) const
    {
        return model->createIndex((void *)node);
    }
    QXmlNodeModelIndex toNodeIndex(xmlAttr *node) const
    {
        return model->createIndex((void *)node);
    }
};

void libXmlErrorFunc(void *ctx, const char *msg, ...)
{
   char buf[1024];
   va_list args;
   va_start(args, msg);
   vsnprintf(buf, 1024, msg, args);
   va_end(args);

   qDebug() << buf;
   return;
}

/*!
 * Constructor passes \a pool to the base class
 */
QLibXmlNodeModel::QLibXmlNodeModel(const QXmlNamePool& namePool, const QByteArray &source, const QUrl &uri)
    : QSimpleXmlNodeModel(namePool), d(new QLibXmlNodeModelPrivate(this))
{
    xmlSetGenericErrorFunc(NULL, libXmlErrorFunc);

    d->uri = uri;
    d->parse(source);
}

/*!
 * Destructor
 */
QLibXmlNodeModel::~QLibXmlNodeModel()
{
    delete d;
}

/*!
 * This function is called by the QtXmlPatterns query engine when it
 * wants to move to the next node in the model. It moves along an \a
 * axis, \e from the node specified by \a nodeIndex.
 */
QXmlNodeModelIndex
QLibXmlNodeModel::nextFromSimpleAxis(SimpleAxis axis, const QXmlNodeModelIndex &nodeIndex) const
{
    xmlNode *node = d->toNode(nodeIndex);
    //qDebug() << "nextFromSimpleAxis()" << node << axis;
    if (!node) {
        //qDebug() << "Invalid node";
        return QXmlNodeModelIndex();
    }

    switch (axis) {
        case Parent:
            //qDebug() << "Parent " << node->parent;
            if (!node->parent) {
                return QXmlNodeModelIndex();
            }
            return d->toNodeIndex(node->parent);

        case FirstChild:
            //qDebug() << "Child " << node->children;
            if (!node->children) {
                return QXmlNodeModelIndex();
            }
            return d->toNodeIndex(node->children);

        case PreviousSibling:
            //qDebug() << "Prev " << node->prev;
            if (!node->prev) {
                return QXmlNodeModelIndex();
            }
            return d->toNodeIndex(node->prev);

        case NextSibling:
            //qDebug() << "Next " << node->next;
            if (!node->next) {
                return QXmlNodeModelIndex();
            }
            return d->toNodeIndex(node->next);
    }

    Q_ASSERT_X(false, Q_FUNC_INFO, "Invalid axis!");
    return QXmlNodeModelIndex();
}

/*!
 * Returns the document URI of \a n. The document URI identifies the
 * resource which is the document. For example, the document could be a
 * regular file, e.g., \c{file:/}, or it could be the \c{http://} URL of
 * the location of a file. The document URI is used for resolving URIs
 * and to simply know where the document is.
 */
QUrl QLibXmlNodeModel::documentUri(const QXmlNodeModelIndex &node) const
{
    Q_UNUSED(node);
    return d->uri;
}

/*!
 * Returns a value indicating the kind of node identified by \a ni.
 * The caller guarantees that \a ni is not null and that it identifies
 * a node in this node model. This function maps to the \c
 * dm:node-kind() accessor.
 */
QXmlNodeModelIndex::NodeKind
QLibXmlNodeModel::kind(const QXmlNodeModelIndex &nodeIndex) const
{
    xmlNode *node = d->toNode(nodeIndex);
    //qDebug() << "kind()" << node;

    //qDebug() << "Node type" << node->type;

    switch (node->type) {
        case XML_ELEMENT_NODE:
            return QXmlNodeModelIndex::Element;
        case XML_ATTRIBUTE_NODE:
            return QXmlNodeModelIndex::Attribute;
        case XML_TEXT_NODE:
        case XML_CDATA_SECTION_NODE:
            return QXmlNodeModelIndex::Text;
        case XML_COMMENT_NODE:
            return QXmlNodeModelIndex::Comment;
        case XML_DOCUMENT_NODE:
        case XML_HTML_DOCUMENT_NODE:
            return QXmlNodeModelIndex::Document;
        case XML_NAMESPACE_DECL:
            return QXmlNodeModelIndex::Namespace;
        case XML_PI_NODE:
            return QXmlNodeModelIndex::ProcessingInstruction;
        // Don't show message
        case XML_DTD_NODE:
            return QXmlNodeModelIndex::Text;
    }

    //qDebug() << "Node type is not handled properly in kind()" << node->type;
    return QXmlNodeModelIndex::Text;
}

/*!
 * This function returns the relative document order for the
 * nodes indexed by \a ni1 and \a ni2. It is used for the \c Is
 * operator and for sorting nodes in document order.
 */
QXmlNodeModelIndex::DocumentOrder QLibXmlNodeModel::compareOrder(const QXmlNodeModelIndex &nodeIndex1, const QXmlNodeModelIndex &nodeIndex2) const
{
    xmlNode *node1 = d->toNode(nodeIndex1);
    xmlNode *node2 = d->toNode(nodeIndex2);
    xmlNode *cur;

    //qDebug() << "compareOrder()" << node1 << node2;

    // Check is nodes are root
    if (node1->parent == NULL) {
        return QXmlNodeModelIndex::Precedes;
    }
    if (node2->parent == NULL) {
        return QXmlNodeModelIndex::Follows;
    }

    // Find nodes which has common parent
    if (node1->parent != node2->parent) {
        QList<xmlNode*> tree1;
        QList<xmlNode*> tree2;

        // Build trees for node1 and node2
        for (cur = node1->parent; cur != NULL; cur = cur->parent) {
            tree1.push_front(cur);
        }
        for (cur = node2->parent; cur != NULL; cur = cur->parent) {
            tree2.push_front(cur);
        }

        // Find last common element in lists (common parent of nodes)
        QList<xmlNode*>::const_iterator iter1;
        QList<xmlNode*>::const_iterator iter2;
        node1 = node2 = NULL;
        for (iter1 = tree1.begin(), iter2 = tree2.begin(); iter1 != tree1.end() && iter2 != tree2.end(); ++iter1, ++iter2) {
            if (*iter1 != *iter2) {
                break;
            }
        }

        // One node is successor of another
        if (iter1 == tree1.end()) {
            return QXmlNodeModelIndex::Precedes;
        }
        if (iter2 == tree2.end()) {
            return QXmlNodeModelIndex::Follows;
        }

        // Asign nodes from nodes' tree which are children of common parent
        node1 = *iter1;
        node2 = *iter2;

        //qDebug() << tree1 << tree2 << node1 << node2;
        Q_ASSERT_X(node1 && node2, Q_FUNC_INFO, "Nodes has no common parent");
    }

    Q_ASSERT_X(node1 != node2, Q_FUNC_INFO, "Different nodes' parent is equal");
    Q_ASSERT_X(node1->parent == node2->parent, Q_FUNC_INFO, "Common parent is found improperly");
    Q_ASSERT_X(node1->parent->children, Q_FUNC_INFO, "Node parent has no children");

    // Find which node precedes
    for (cur = node1->parent->children; cur != NULL; cur = cur->next) {
        if (cur == node1) {
            return QXmlNodeModelIndex::Precedes;
        } else if (cur == node2) {
            return QXmlNodeModelIndex::Follows;
        }
    }

    Q_ASSERT_X(false, Q_FUNC_INFO, "Should not get here");
    return QXmlNodeModelIndex::Precedes;
}

/*!
 * Returns the name of \a node. The caller guarantees that \a node is
 * not null and that it is contained in this node model.
 */
QXmlName QLibXmlNodeModel::name(const QXmlNodeModelIndex &nodeIndex) const
{
    xmlNode *node = d->toNode(nodeIndex);
    //qDebug() << "name()" << node;
    Q_ASSERT_X(node, Q_FUNC_INFO, "Invalid node");

    //qDebug() << "Node name" << (const char *)node->name;
    return QXmlName(namePool(), QString::fromUtf8((const char *)node->name));
}

/*!
 * Returns the root node of the tree that contains the node whose index
 * is \a n. The caller guarantees that \a n is not \c null and that it
 * identifies a node in this node model.
 */
QXmlNodeModelIndex QLibXmlNodeModel::root(const QXmlNodeModelIndex &nodeIndex) const
{
    Q_UNUSED(nodeIndex);
    return d->toNodeIndex(d->doc);
}

/*!
 * Returns the typed value for \a node, which must be either an
 * attribute or an element. The QVariant returned represents the atomic
 * value of an attribute or the atomic value contained in an element.
 *
 * If the QVariant is returned as a default constructed variant,
 * it means that \a node has no typed value.
 */
QVariant QLibXmlNodeModel::typedValue(const QXmlNodeModelIndex &nodeIndex) const
{
    xmlNode *node = d->toNode(nodeIndex);
    //qDebug() << "typedValue()" << node;
    Q_ASSERT_X(node, Q_FUNC_INFO, "Invalid node");

    xmlChar *buf = xmlNodeListGetString(node->doc, node->children, 1);
    QString str = QString::fromUtf8((const char *)buf);
    xmlFree(buf);

    //qDebug() << "Attribute typed value" << str;
    return str;
}

/*!
 * Returns the attributes of \a element. The caller guarantees
 * that \a element is an element in this node model.
 */
QVector<QXmlNodeModelIndex> QLibXmlNodeModel::attributes(const QXmlNodeModelIndex &nodeIndex) const
{
    xmlNode *node = d->toNode(nodeIndex);
    //qDebug() << "attributes()" << node;
    Q_ASSERT_X(node, Q_FUNC_INFO, "Invalid node");

    QVector<QXmlNodeModelIndex> result;
    for (xmlAttr *cur = node->properties; cur != NULL; cur = cur->next) {
        result += d->toNodeIndex(cur);
    }

    return result;
}

/*!
 * Returns the string value for node \a n.
 *
 * The caller guarantees that \a n is not \c null and that it belong to
 * this QAbstractXmlNodeModel instance.
 *
 * This function maps to the \c dm:string-value() accessor, which the
 * specification completely specifies. Here's a summary:
 *
 * \list
 * \o For processing instructions, the string value is the data
 * section(excluding any whitespace appearing between the name and the
 * data).
 * \o For text nodes, the string value equals the text node.
 * \o For comments, the content of the comment
 * \o For elements, the concatenation of all text nodes that are
 * descendants. Note, this is not only the children, but the
 * childrens' childrens' text nodes, and so forth.
 * \o For document nodes, the concatenation of all text nodes in the
 * document.
 * \endlist
 */
QString QLibXmlNodeModel::stringValue (const QXmlNodeModelIndex &nodeIndex) const
{
    xmlNode *node = d->toNode(nodeIndex);
    //qDebug() << "stringValue()" << node;

    if (node->type == XML_TEXT_NODE ||
        node->type == XML_CDATA_SECTION_NODE ||
        node->type == XML_COMMENT_NODE) {
        xmlChar *buf = xmlNodeGetContent(node);
        QString str = QString::fromUtf8((const char *)buf);
        xmlFree(buf);

        return str;
    }

    if (node->type == XML_ELEMENT_NODE ||
        node->type == XML_ATTRIBUTE_NODE) {
        return QSimpleXmlNodeModel::stringValue(nodeIndex);
    }

    // TODO: handle other node types
    //qDebug() << "Node type is not handled properly in stringValue()" << node->type;

    return QString();
}
<commit_msg>Use xmlNodeGetContent() to get full node content.<commit_after>/*
 * qlibxmlnodemodel - A QAbstractXmlNodeModel for using with libxml2 library
 * Copyright (C) 2012 Alexey Torkhov
 * Copyright (C) 2011 Jonas Gehring
 * All rights reserved.
 *
 * Based on qhtmlnodemodel by Jonas Gehring
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of the copyright holders nor the
 *       names of its contributors may be used to endorse or promote products
 *       derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#include <QDebug>

#include <libxml/HTMLparser.h>
#include <libxml/tree.h>

#include "qlibxmlnodemodel.h"

// Internal private data
class QLibXmlNodeModelPrivate
{
public:
    QLibXmlNodeModel *model;
    QUrl uri;

    xmlDoc *doc;

    QLibXmlNodeModelPrivate(QLibXmlNodeModel *model)
        : model(model), doc(NULL)
    {
    }

    ~QLibXmlNodeModelPrivate()
    {
        xmlFreeDoc(doc);
        doc = NULL;
    }

    // Parses the given source tree
    void parse(const QByteArray &source)
    {
        doc = htmlReadMemory(source.data(), source.size(), uri.toString().toUtf8(), "utf-8", 0);

        if (doc == NULL) {
            qDebug() << "could not parse source" << source;
        }
    }

    // Converts a model index to a HTML node
    xmlNode *toNode(const QXmlNodeModelIndex &index) const
    {
        return (xmlNode *)index.internalPointer();
    }

    // Converts a HTML node to a model index
    QXmlNodeModelIndex toNodeIndex(xmlNode *node) const
    {
        return model->createIndex((void *)node);
    }
    QXmlNodeModelIndex toNodeIndex(xmlDoc *node) const
    {
        return model->createIndex((void *)node);
    }
    QXmlNodeModelIndex toNodeIndex(xmlAttr *node) const
    {
        return model->createIndex((void *)node);
    }
};

void libXmlErrorFunc(void *ctx, const char *msg, ...)
{
   char buf[1024];
   va_list args;
   va_start(args, msg);
   vsnprintf(buf, 1024, msg, args);
   va_end(args);

   qDebug() << buf;
   return;
}

/*!
 * Constructor passes \a pool to the base class
 */
QLibXmlNodeModel::QLibXmlNodeModel(const QXmlNamePool& namePool, const QByteArray &source, const QUrl &uri)
    : QSimpleXmlNodeModel(namePool), d(new QLibXmlNodeModelPrivate(this))
{
    xmlSetGenericErrorFunc(NULL, libXmlErrorFunc);

    d->uri = uri;
    d->parse(source);
}

/*!
 * Destructor
 */
QLibXmlNodeModel::~QLibXmlNodeModel()
{
    delete d;
}

/*!
 * This function is called by the QtXmlPatterns query engine when it
 * wants to move to the next node in the model. It moves along an \a
 * axis, \e from the node specified by \a nodeIndex.
 */
QXmlNodeModelIndex
QLibXmlNodeModel::nextFromSimpleAxis(SimpleAxis axis, const QXmlNodeModelIndex &nodeIndex) const
{
    xmlNode *node = d->toNode(nodeIndex);
    //qDebug() << "nextFromSimpleAxis()" << node << axis;
    if (!node) {
        //qDebug() << "Invalid node";
        return QXmlNodeModelIndex();
    }

    switch (axis) {
        case Parent:
            //qDebug() << "Parent " << node->parent;
            if (!node->parent) {
                return QXmlNodeModelIndex();
            }
            return d->toNodeIndex(node->parent);

        case FirstChild:
            //qDebug() << "Child " << node->children;
            if (!node->children) {
                return QXmlNodeModelIndex();
            }
            return d->toNodeIndex(node->children);

        case PreviousSibling:
            //qDebug() << "Prev " << node->prev;
            if (!node->prev) {
                return QXmlNodeModelIndex();
            }
            return d->toNodeIndex(node->prev);

        case NextSibling:
            //qDebug() << "Next " << node->next;
            if (!node->next) {
                return QXmlNodeModelIndex();
            }
            return d->toNodeIndex(node->next);
    }

    Q_ASSERT_X(false, Q_FUNC_INFO, "Invalid axis!");
    return QXmlNodeModelIndex();
}

/*!
 * Returns the document URI of \a n. The document URI identifies the
 * resource which is the document. For example, the document could be a
 * regular file, e.g., \c{file:/}, or it could be the \c{http://} URL of
 * the location of a file. The document URI is used for resolving URIs
 * and to simply know where the document is.
 */
QUrl QLibXmlNodeModel::documentUri(const QXmlNodeModelIndex &node) const
{
    Q_UNUSED(node);
    return d->uri;
}

/*!
 * Returns a value indicating the kind of node identified by \a ni.
 * The caller guarantees that \a ni is not null and that it identifies
 * a node in this node model. This function maps to the \c
 * dm:node-kind() accessor.
 */
QXmlNodeModelIndex::NodeKind
QLibXmlNodeModel::kind(const QXmlNodeModelIndex &nodeIndex) const
{
    xmlNode *node = d->toNode(nodeIndex);
    //qDebug() << "kind()" << node;

    //qDebug() << "Node type" << node->type;

    switch (node->type) {
        case XML_ELEMENT_NODE:
            return QXmlNodeModelIndex::Element;
        case XML_ATTRIBUTE_NODE:
            return QXmlNodeModelIndex::Attribute;
        case XML_TEXT_NODE:
        case XML_CDATA_SECTION_NODE:
            return QXmlNodeModelIndex::Text;
        case XML_COMMENT_NODE:
            return QXmlNodeModelIndex::Comment;
        case XML_DOCUMENT_NODE:
        case XML_HTML_DOCUMENT_NODE:
            return QXmlNodeModelIndex::Document;
        case XML_NAMESPACE_DECL:
            return QXmlNodeModelIndex::Namespace;
        case XML_PI_NODE:
            return QXmlNodeModelIndex::ProcessingInstruction;
        // Don't show message
        case XML_DTD_NODE:
            return QXmlNodeModelIndex::Text;
    }

    //qDebug() << "Node type is not handled properly in kind()" << node->type;
    return QXmlNodeModelIndex::Text;
}

/*!
 * This function returns the relative document order for the
 * nodes indexed by \a ni1 and \a ni2. It is used for the \c Is
 * operator and for sorting nodes in document order.
 */
QXmlNodeModelIndex::DocumentOrder QLibXmlNodeModel::compareOrder(const QXmlNodeModelIndex &nodeIndex1, const QXmlNodeModelIndex &nodeIndex2) const
{
    xmlNode *node1 = d->toNode(nodeIndex1);
    xmlNode *node2 = d->toNode(nodeIndex2);
    xmlNode *cur;

    //qDebug() << "compareOrder()" << node1 << node2;

    // Check is nodes are root
    if (node1->parent == NULL) {
        return QXmlNodeModelIndex::Precedes;
    }
    if (node2->parent == NULL) {
        return QXmlNodeModelIndex::Follows;
    }

    // Find nodes which has common parent
    if (node1->parent != node2->parent) {
        QList<xmlNode*> tree1;
        QList<xmlNode*> tree2;

        // Build trees for node1 and node2
        for (cur = node1->parent; cur != NULL; cur = cur->parent) {
            tree1.push_front(cur);
        }
        for (cur = node2->parent; cur != NULL; cur = cur->parent) {
            tree2.push_front(cur);
        }

        // Find last common element in lists (common parent of nodes)
        QList<xmlNode*>::const_iterator iter1;
        QList<xmlNode*>::const_iterator iter2;
        node1 = node2 = NULL;
        for (iter1 = tree1.begin(), iter2 = tree2.begin(); iter1 != tree1.end() && iter2 != tree2.end(); ++iter1, ++iter2) {
            if (*iter1 != *iter2) {
                break;
            }
        }

        // One node is successor of another
        if (iter1 == tree1.end()) {
            return QXmlNodeModelIndex::Precedes;
        }
        if (iter2 == tree2.end()) {
            return QXmlNodeModelIndex::Follows;
        }

        // Asign nodes from nodes' tree which are children of common parent
        node1 = *iter1;
        node2 = *iter2;

        //qDebug() << tree1 << tree2 << node1 << node2;
        Q_ASSERT_X(node1 && node2, Q_FUNC_INFO, "Nodes has no common parent");
    }

    Q_ASSERT_X(node1 != node2, Q_FUNC_INFO, "Different nodes' parent is equal");
    Q_ASSERT_X(node1->parent == node2->parent, Q_FUNC_INFO, "Common parent is found improperly");
    Q_ASSERT_X(node1->parent->children, Q_FUNC_INFO, "Node parent has no children");

    // Find which node precedes
    for (cur = node1->parent->children; cur != NULL; cur = cur->next) {
        if (cur == node1) {
            return QXmlNodeModelIndex::Precedes;
        } else if (cur == node2) {
            return QXmlNodeModelIndex::Follows;
        }
    }

    Q_ASSERT_X(false, Q_FUNC_INFO, "Should not get here");
    return QXmlNodeModelIndex::Precedes;
}

/*!
 * Returns the name of \a node. The caller guarantees that \a node is
 * not null and that it is contained in this node model.
 */
QXmlName QLibXmlNodeModel::name(const QXmlNodeModelIndex &nodeIndex) const
{
    xmlNode *node = d->toNode(nodeIndex);
    //qDebug() << "name()" << node;
    Q_ASSERT_X(node, Q_FUNC_INFO, "Invalid node");

    //qDebug() << "Node name" << (const char *)node->name;
    return QXmlName(namePool(), QString::fromUtf8((const char *)node->name));
}

/*!
 * Returns the root node of the tree that contains the node whose index
 * is \a n. The caller guarantees that \a n is not \c null and that it
 * identifies a node in this node model.
 */
QXmlNodeModelIndex QLibXmlNodeModel::root(const QXmlNodeModelIndex &nodeIndex) const
{
    Q_UNUSED(nodeIndex);
    return d->toNodeIndex(d->doc);
}

/*!
 * Returns the typed value for \a node, which must be either an
 * attribute or an element. The QVariant returned represents the atomic
 * value of an attribute or the atomic value contained in an element.
 *
 * If the QVariant is returned as a default constructed variant,
 * it means that \a node has no typed value.
 */
QVariant QLibXmlNodeModel::typedValue(const QXmlNodeModelIndex &nodeIndex) const
{
    xmlNode *node = d->toNode(nodeIndex);
    //qDebug() << "typedValue()" << node;
    Q_ASSERT_X(node, Q_FUNC_INFO, "Invalid node");

    xmlChar *buf = xmlNodeGetContent(node);
    QString str = QString::fromUtf8((const char *)buf);
    xmlFree(buf);

    //qDebug() << "Attribute typed value" << str;
    return str;
}

/*!
 * Returns the attributes of \a element. The caller guarantees
 * that \a element is an element in this node model.
 */
QVector<QXmlNodeModelIndex> QLibXmlNodeModel::attributes(const QXmlNodeModelIndex &nodeIndex) const
{
    xmlNode *node = d->toNode(nodeIndex);
    //qDebug() << "attributes()" << node;
    Q_ASSERT_X(node, Q_FUNC_INFO, "Invalid node");

    QVector<QXmlNodeModelIndex> result;
    for (xmlAttr *cur = node->properties; cur != NULL; cur = cur->next) {
        result += d->toNodeIndex(cur);
    }

    return result;
}

/*!
 * Returns the string value for node \a n.
 *
 * The caller guarantees that \a n is not \c null and that it belong to
 * this QAbstractXmlNodeModel instance.
 *
 * This function maps to the \c dm:string-value() accessor, which the
 * specification completely specifies. Here's a summary:
 *
 * \list
 * \o For processing instructions, the string value is the data
 * section(excluding any whitespace appearing between the name and the
 * data).
 * \o For text nodes, the string value equals the text node.
 * \o For comments, the content of the comment
 * \o For elements, the concatenation of all text nodes that are
 * descendants. Note, this is not only the children, but the
 * childrens' childrens' text nodes, and so forth.
 * \o For document nodes, the concatenation of all text nodes in the
 * document.
 * \endlist
 */
QString QLibXmlNodeModel::stringValue (const QXmlNodeModelIndex &nodeIndex) const
{
    xmlNode *node = d->toNode(nodeIndex);
    //qDebug() << "stringValue()" << node;

    if (node->type == XML_TEXT_NODE ||
        node->type == XML_CDATA_SECTION_NODE ||
        node->type == XML_COMMENT_NODE) {
        xmlChar *buf = xmlNodeGetContent(node);
        QString str = QString::fromUtf8((const char *)buf);
        xmlFree(buf);

        return str;
    }

    if (node->type == XML_ELEMENT_NODE ||
        node->type == XML_ATTRIBUTE_NODE) {
        return QSimpleXmlNodeModel::stringValue(nodeIndex);
    }

    // TODO: handle other node types
    //qDebug() << "Node type is not handled properly in stringValue()" << node->type;

    return QString();
}
<|endoftext|>


<commit_before>// Copyright (c) 2009-2014 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "uritests.h"

#include "guiutil.h"
#include "walletmodel.h"

#include <QUrl>

void URITests::uriTests()
{
    SendCoinsRecipient rv;
    QUrl uri;
    uri.setUrl(QString("viacoin:175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?req-dontexist="));
    QVERIFY(!GUIUtil::parseBitcoinURI(uri, &rv));

    uri.setUrl(QString("viacoin:175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?dontexist="));
    QVERIFY(GUIUtil::parseBitcoinURI(uri, &rv));
    QVERIFY(rv.address == QString("175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W"));
    QVERIFY(rv.label == QString());
    QVERIFY(rv.amount == 0);

    uri.setUrl(QString("viacoin:175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?label=Wikipedia Example Address"));
    QVERIFY(GUIUtil::parseBitcoinURI(uri, &rv));
    QVERIFY(rv.address == QString("175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W"));
    QVERIFY(rv.label == QString("Wikipedia Example Address"));
    QVERIFY(rv.amount == 0);

    uri.setUrl(QString("viacoin:175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?amount=0.001"));
    QVERIFY(GUIUtil::parseBitcoinURI(uri, &rv));
    QVERIFY(rv.address == QString("175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W"));
    QVERIFY(rv.label == QString());
    QVERIFY(rv.amount == 100000);

    uri.setUrl(QString("viacoin:175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?amount=1.001"));
    QVERIFY(GUIUtil::parseBitcoinURI(uri, &rv));
    QVERIFY(rv.address == QString("175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W"));
    QVERIFY(rv.label == QString());
    QVERIFY(rv.amount == 100100000);

    uri.setUrl(QString("viacoin:175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?amount=100&label=Wikipedia Example"));
    QVERIFY(GUIUtil::parseBitcoinURI(uri, &rv));
    QVERIFY(rv.address == QString("175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W"));
    QVERIFY(rv.amount == 10000000000LL);
    QVERIFY(rv.label == QString("Wikipedia Example"));

    uri.setUrl(QString("viacoin:175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?message=Wikipedia Example Address"));
    QVERIFY(GUIUtil::parseBitcoinURI(uri, &rv));
    QVERIFY(rv.address == QString("175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W"));
    QVERIFY(rv.label == QString());

    QVERIFY(GUIUtil::parseBitcoinURI("viacoin://175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?message=Wikipedia Example Address", &rv));
    QVERIFY(rv.address == QString("175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W"));
    QVERIFY(rv.label == QString());

    uri.setUrl(QString("viacoin:175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?req-message=Wikipedia Example Address"));
    QVERIFY(GUIUtil::parseBitcoinURI(uri, &rv));

    uri.setUrl(QString("viacoin:175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?amount=1,000&label=Wikipedia Example"));
    QVERIFY(!GUIUtil::parseBitcoinURI(uri, &rv));

    uri.setUrl(QString("viacoin:175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?amount=1,000.0&label=Wikipedia Example"));
    QVERIFY(!GUIUtil::parseBitcoinURI(uri, &rv));
}<commit_msg>Viacoin: uritests<commit_after>// Copyright (c) 2009-2014 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "uritests.h"

#include "guiutil.h"
#include "walletmodel.h"

#include <QUrl>

void URITests::uriTests()
{
    SendCoinsRecipient rv;
    QUrl uri;
    uri.setUrl(QString("viacoin:Vg5iRXkaipLKSYBDJjkV5qa1CE9b1djeHn?req-dontexist="));
    QVERIFY(!GUIUtil::parseBitcoinURI(uri, &rv));

    uri.setUrl(QString("viacoin:Vg5iRXkaipLKSYBDJjkV5qa1CE9b1djeHn?dontexist="));
    QVERIFY(GUIUtil::parseBitcoinURI(uri, &rv));
    QVERIFY(rv.address == QString("Vg5iRXkaipLKSYBDJjkV5qa1CE9b1djeHn"));
    QVERIFY(rv.label == QString());
    QVERIFY(rv.amount == 0);

    uri.setUrl(QString("viacoin:Vg5iRXkaipLKSYBDJjkV5qa1CE9b1djeHn?label=Wikipedia Example Address"));
    QVERIFY(GUIUtil::parseBitcoinURI(uri, &rv));
    QVERIFY(rv.address == QString("Vg5iRXkaipLKSYBDJjkV5qa1CE9b1djeHn"));
    QVERIFY(rv.label == QString("Wikipedia Example Address"));
    QVERIFY(rv.amount == 0);

    uri.setUrl(QString("viacoin:Vg5iRXkaipLKSYBDJjkV5qa1CE9b1djeHn?amount=0.001"));
    QVERIFY(GUIUtil::parseBitcoinURI(uri, &rv));
    QVERIFY(rv.address == QString("Vg5iRXkaipLKSYBDJjkV5qa1CE9b1djeHn"));
    QVERIFY(rv.label == QString());
    QVERIFY(rv.amount == 100000);

    uri.setUrl(QString("viacoin:Vg5iRXkaipLKSYBDJjkV5qa1CE9b1djeHn?amount=1.001"));
    QVERIFY(GUIUtil::parseBitcoinURI(uri, &rv));
    QVERIFY(rv.address == QString("Vg5iRXkaipLKSYBDJjkV5qa1CE9b1djeHn"));
    QVERIFY(rv.label == QString());
    QVERIFY(rv.amount == 100100000);

    uri.setUrl(QString("viacoin:Vg5iRXkaipLKSYBDJjkV5qa1CE9b1djeHn?amount=100&label=Wikipedia Example"));
    QVERIFY(GUIUtil::parseBitcoinURI(uri, &rv));
    QVERIFY(rv.address == QString("Vg5iRXkaipLKSYBDJjkV5qa1CE9b1djeHn"));
    QVERIFY(rv.amount == 10000000000LL);
    QVERIFY(rv.label == QString("Wikipedia Example"));

    uri.setUrl(QString("viacoin:Vg5iRXkaipLKSYBDJjkV5qa1CE9b1djeHn?message=Wikipedia Example Address"));
    QVERIFY(GUIUtil::parseBitcoinURI(uri, &rv));
    QVERIFY(rv.address == QString("Vg5iRXkaipLKSYBDJjkV5qa1CE9b1djeHn"));
    QVERIFY(rv.label == QString());

    QVERIFY(GUIUtil::parseBitcoinURI("viacoin://Vg5iRXkaipLKSYBDJjkV5qa1CE9b1djeHn?message=Wikipedia Example Address", &rv));
    QVERIFY(rv.address == QString("Vg5iRXkaipLKSYBDJjkV5qa1CE9b1djeHn"));
    QVERIFY(rv.label == QString());

    uri.setUrl(QString("viacoin:Vg5iRXkaipLKSYBDJjkV5qa1CE9b1djeHn?req-message=Wikipedia Example Address"));
    QVERIFY(GUIUtil::parseBitcoinURI(uri, &rv));

    uri.setUrl(QString("viacoin:Vg5iRXkaipLKSYBDJjkV5qa1CE9b1djeHn?amount=1,000&label=Wikipedia Example"));
    QVERIFY(!GUIUtil::parseBitcoinURI(uri, &rv));

    uri.setUrl(QString("viacoin:Vg5iRXkaipLKSYBDJjkV5qa1CE9b1djeHn?amount=1,000.0&label=Wikipedia Example"));
    QVERIFY(!GUIUtil::parseBitcoinURI(uri, &rv));
}
<|endoftext|>


<commit_before>/*****************************************************************************
 * Licensed to Qualys, Inc. (QUALYS) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * QUALYS licenses this file to You 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.
 ****************************************************************************/

/**
 * @file
 * @brief Predicate --- Validation Support
 *
 * @author Christopher Alfeld <calfeld@qualys.com>
 */

#ifndef __PREDICATE__VALIDATION__
#define __PREDICATE__VALIDATION__

#include <predicate/dag.hpp>
#include <predicate/reporter.hpp>

namespace IronBee {
namespace Predicate {

/**
 * Easy validation of Call nodes.
 *
 * This namespace defines a set of templates and routines designed to do
 * easy common validation checks on custom Call nodes such as
 * "has N children".  It uses template metaprogramming and multiple
 * inheritance to accomplish this.  Example of use:
 *
 * @code
 * class MyCustomCallClass :
 *   public Validate::Call<MyCustomCallClass>,
 *   public Validate::NChildren<5,
            Validate::NthChildStatic<3
 *          > >
 * {
 *     ...
 * };
 * @endcode
 *
 * Use involves two parts:
 *
 * - The class publicly inherits from Validate::Call, passing itself in as
 *   the template parameter.  Validate::Call will implement pre_transform()
 *   and post_transform() to call the validation code defined by the
 *   the validation chain (see below).
 * - A validation chain of 1 or more validations.  The chain is a sequence of
 *   one or more validation templates with the next element of the chain
 *   passed in as the last template argument.  The final element of the chain
 *   omits the last template argument or uses the default, Validate::Base.
 *   The validation chain will add the method
 *   `virtual void validate(NodeReporter) const` to the class that performs
 *   all the validations in the chain.
 *
 * How it works: Validate::Call::pre_transform() (similar for
 * Validate::Call::post_transform()) will dynamic cast @c *this to the
 * subclass type (passed in as a template argument) and call @c validate() of
 * that.  As this is now at the bottom of the class hierarchy, it will be able
 * to find the @c validate() defined by the validation chain and call it.
 *
 * Why not have Validate::Call be the top of the validation chain?  This
 * technique would work perfectly well if Validate::Call was used in place of
 * Validate::Base at the top of the validation chain.  Doing so would also
 * remove the need for the dynamic cast Validate::Call would be able to
 * define the virtual method validate in its own definition and thus have
 * access to it without the need of a dynamic cast.  However, this approach
 * would result in an extremely complicated parent for the subclass making it
 * difficult to further override Node::pre_transform() and
 * Node::post_transform().  Under the current approach, these can be further
 * used via:
 *
 * @code
 * virtual void pre_transform(NodeReporter reporter) const
 * {
 *    Validate::Call<MyCustomCallClass>::pre_transform(reporter);
 *    // Custom pre_transform code.
 *    ...
 * }
 * @endcode
 *
 * How to write a new validator:
 *
 * - If possible, write the validator logic is a function (see, e.g.,
 *   n_children()).  Recall that the node to be validated is
 *   available via NodeReporter::node().
 * - Write a template that calls your function.  You can use typed template
 *   parameters to parameterize your validator, i.e., pass additional
 *   arguments to your function.  At present, there is no way to pass complex
 *   types in.  Your template should chain via the last argument, e.g.,
 *
 * @code
 * template <size_t arg1, class Chain = Validate::Base>
 * struct MyCustomValidator : public Chain
 * {
 *     virtual void validate(NodeReporter reporter) const
 *     {
 *         my_custom_validator(reporter, arg1);
 *         Chain::validate(reporter);
 *     }
 * };
 * @endcode
 **/
namespace Validate {

/**
 * Subclass this instead of Call to make use of validation chains.
 *
 * Subclassing from this will implement Node::pre_transform() and
 * Node::post_transform() to dynamic cast to @a Subclass and then call
 * validate().  See Predicate::Validate.
 *
 * @tparam Subclass Type of subclass.
 **/
template <class Subclass>
class Call :
    virtual public Predicate::Call
{
public:
    //! Dynamic cast to @a Subclass and call Base::validate().
    virtual void pre_transform(NodeReporter reporter) const
    {
        assert(reporter.node().get() == this);
        Predicate::Call::pre_transform(reporter);
        dynamic_cast<const Subclass&>(*this).validate(reporter);
    }

    //! Dynamic cast to @a Subclass and call Base::validate().
    virtual void post_transform(NodeReporter reporter) const
    {
        assert(reporter.node().get() == this);
        Predicate::Call::post_transform(reporter);
        dynamic_cast<const Subclass&>(*this).validate(reporter);
    }
};

/**
 * Top of a validation chain.  Defines validate().
 *
 * You will not normally need to reference this class directly.  It is the
 * default argument of the @a Chain parameters of validation templates.
 **/
class Base
{
public:
    //! Validate this node.  Currently nop.
    virtual void validate(NodeReporter) const
    {
        // nop
    }
};

/**
 * Metafunction to construct a validator from a function taking a size_t.
 *
 * @tparam F Function of @c NodeReporter and @c size_t to call.
 **/
template <bool (*F)(NodeReporter, size_t)>
struct make_validator_size
{
    //! Value; a validator.
    template <size_t N, class Chain = Validate::Base>
    struct value : public Chain
    {
        //! See Base::validate() and Predicate::Validate.
        virtual void validate(NodeReporter reporter) const
        {
            F(reporter, N);
            Chain::validate(reporter);
        }
    };
};

/**
 * Metafunction to construct a validator from a function taking nothing.
 *
 * @tparam F Function of @c NodeReporter to call.
 **/
template <bool (*F)(NodeReporter)>
struct make_validator
{
    //! Value; a validator.
    template <class Chain = Validate::Base>
    struct value : public Chain
    {
        //! See Base::validate() and Predicate::Validate.
        virtual void validate(NodeReporter reporter) const
        {
            F(reporter);
            Chain::validate(reporter);
        }
    };
};

/**
 * Report error if not exactly @a n children.
 *
 * @param[in] reporter Reporter to use.
 * @param[in] n        How many children expected.
 * @return true iff validation succeeded.
 **/
bool n_children(NodeReporter reporter, size_t n);

/**
 * Report error if not @a n or more children.
 *
 * @param[in] reporter Reporter to use.
 * @param[in] n        Minimum number of children expected.
 * @return true iff validation succeeded.
 **/
bool n_or_more_children(NodeReporter reporter, size_t n);

/**
 * Report error if not @a n or fewer children.
 *
 * @param[in] reporter Reporter to use.
 * @param[in] n        Maximum number of children expected.
 * @return true iff validation succeeded.
 **/
bool n_or_fewer_children(NodeReporter reporter, size_t n);

/**
 * Report error if @a nth child is not string literal.
 *
 * @param[in] reporter Reporter to use.
 * @param[in] n        Which child should be a string literal.
 * @return true iff validation succeeded.
 **/
bool nth_child_is_string(NodeReporter reporter, size_t n);

/**
 * Report error if @a nth child is not number literal.
 *
 * @param[in] reporter Reporter to use.
 * @param[in] n        Which child should be a number literal.
 * @return true iff validation succeeded.
 **/
bool nth_child_is_integer(NodeReporter reporter, size_t n);

/**
 * Report error if @a nth child is not float literal.
 *
 * @param[in] reporter Reporter to use.
 * @param[in] n        Which child should be a float literal.
 * @return true iff validation succeeded.
 **/
bool nth_child_is_float(NodeReporter reporter, size_t n);

/**
 * Report error if @a nth child is not a null.
 *
 * @param[in] reporter Reporter to use.
 * @param[in] n        Which child should be a null.
 * @return true iff validation succeeded.
 **/
bool nth_child_is_null(NodeReporter reporter, size_t n);

/**
 * Report error if @a nth child is a null.
 *
 * @param[in] reporter Reporter to use.
 * @param[in] n        Which child should not be a null.
 * @return true iff validation succeeded.
 **/
bool nth_child_is_not_null(NodeReporter reporter, size_t n);

/**
 * Report error if any child is literal.
 *
 * @param[in] reporter Reporter to use.
 * @return true iff validation succeeded.
 **/
bool no_child_is_literal(NodeReporter reporter);

/**
 * Report error if any child is null.
 *
 * @param[in] reporter Reporter to use.
 * @return true iff validation succeeded.
 **/
bool no_child_is_null(NodeReporter reporter);

/**
 * Validator: n_children()
 **/
template <size_t N, class Chain = Base>
struct NChildren :
    public make_validator_size<
        &n_children
    >::value<N, Chain>
{};

/**
 * Validator: n_or_more_children()
 **/
template <size_t N, class Chain = Base>
struct NOrMoreChildren :
    public make_validator_size<
        &n_or_more_children
    >::value<N, Chain>
{};

/**
 * Validator: n_or_fewer_children()
 **/
template <size_t N, class Chain = Base>
struct NOrFewerChildren :
    public make_validator_size<
        &n_or_fewer_children
    >::value<N, Chain>
{};

/**
 * Validator: nth_child_is_string()
 **/
template <size_t N, class Chain = Base>
struct NthChildIsString :
    public make_validator_size<
        &nth_child_is_string
    >::value<N, Chain>
{};

/**
 * Validator: nth_child_is_integer()
 **/
template <size_t N, class Chain = Base>
struct NthChildIsInteger :
    public make_validator_size<
        &nth_child_is_integer
    >::value<N, Chain>
{};

/**
 * Validator: nth_child_is_float()
 **/
template <size_t N, class Chain = Base>
struct NthChildIsFloat :
    public make_validator_size<
        &nth_child_is_float
    >::value<N, Chain>
{};

/**
 * Validator: nth_child_is_null()
 **/
template <size_t N, class Chain = Base>
struct NthChildIsNull :
    public make_validator_size<
        &nth_child_is_null
    >::value<N, Chain>
{};

/**
 * Validator: nth_child_is_not_null()
 **/
template <size_t N, class Chain = Base>
struct NthChildIsNotNull :
    public make_validator_size<
        &nth_child_is_not_null
    >::value<N, Chain>
{};

/**
 * Validator: no_child_is_literal()
 **/
template <class Chain = Base>
struct NoChildIsLiteral :
    public make_validator<
        &no_child_is_literal
    >::value<Chain>
{};

/**
 * Validator: no_child_is_null()
 **/
template <class Chain = Base>
struct NoChildIsNull :
    public make_validator<
        &no_child_is_null
    >::value<Chain>
{};

} // Validate
} // Predicate
} // IronBee

#endif
<commit_msg>predicate/validate: Validate users may now define local_validate() to easily add custom validation code that is called on pre and post transform.<commit_after>/*****************************************************************************
 * Licensed to Qualys, Inc. (QUALYS) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * QUALYS licenses this file to You 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.
 ****************************************************************************/

/**
 * @file
 * @brief Predicate --- Validation Support
 *
 * @author Christopher Alfeld <calfeld@qualys.com>
 */

#ifndef __PREDICATE__VALIDATION__
#define __PREDICATE__VALIDATION__

#include <predicate/dag.hpp>
#include <predicate/reporter.hpp>

namespace IronBee {
namespace Predicate {

/**
 * Easy validation of Call nodes.
 *
 * This namespace defines a set of templates and routines designed to do
 * easy common validation checks on custom Call nodes such as
 * "has N children".  It uses template metaprogramming and multiple
 * inheritance to accomplish this.  Example of use:
 *
 * @code
 * class MyCustomCallClass :
 *   public Validate::Call<MyCustomCallClass>,
 *   public Validate::NChildren<5,
            Validate::NthChildStatic<3
 *          > >
 * {
 *     ...
 * };
 * @endcode
 *
 * Use involves two parts:
 *
 * - The class publicly inherits from Validate::Call, passing itself in as
 *   the template parameter.  Validate::Call will implement pre_transform()
 *   and post_transform() to call the validation code defined by the
 *   the validation chain (see below).
 * - A validation chain of 1 or more validations.  The chain is a sequence of
 *   one or more validation templates with the next element of the chain
 *   passed in as the last template argument.  The final element of the chain
 *   omits the last template argument or uses the default, Validate::Base.
 *   The validation chain will add the method
 *   `virtual void validate(NodeReporter) const` to the class that performs
 *   all the validations in the chain.
 *
 * How it works: Validate::Call::pre_transform() (similar for
 * Validate::Call::post_transform()) will dynamic cast @c *this to the
 * subclass type (passed in as a template argument) and call @c validate() of
 * that.  As this is now at the bottom of the class hierarchy, it will be able
 * to find the @c validate() defined by the validation chain and call it.
 *
 * Why not have Validate::Call be the top of the validation chain?  This
 * technique would work perfectly well if Validate::Call was used in place of
 * Validate::Base at the top of the validation chain.  Doing so would also
 * remove the need for the dynamic cast Validate::Call would be able to
 * define the virtual method validate in its own definition and thus have
 * access to it without the need of a dynamic cast.  However, this approach
 * would result in an extremely complicated parent for the subclass making it
 * difficult to further override Node::pre_transform() and
 * Node::post_transform().  Under the current approach, these can be further
 * used via:
 *
 * @code
 * virtual void pre_transform(NodeReporter reporter) const
 * {
 *    Validate::Call<MyCustomCallClass>::pre_transform(reporter);
 *    // Custom pre_transform code.
 *    ...
 * }
 * @endcode
 *
 * After all validation classes are called, Base will be reached, which will
 * call another virtual function, local_validate().  Classes can override
 * local_validate() to easily provide their own checks that run after
 * all Validate checks.
 *
 * How to write a new validator:
 *
 * - If possible, write the validator logic is a function (see, e.g.,
 *   n_children()).  Recall that the node to be validated is
 *   available via NodeReporter::node().
 * - Write a template that calls your function.  You can use typed template
 *   parameters to parameterize your validator, i.e., pass additional
 *   arguments to your function.  At present, there is no way to pass complex
 *   types in.  Your template should chain via the last argument, e.g.,
 *
 * @code
 * template <size_t arg1, class Chain = Validate::Base>
 * struct MyCustomValidator : public Chain
 * {
 *     virtual void validate(NodeReporter reporter) const
 *     {
 *         my_custom_validator(reporter, arg1);
 *         Chain::validate(reporter);
 *     }
 * };
 * @endcode
 **/
namespace Validate {

/**
 * Subclass this instead of Call to make use of validation chains.
 *
 * Subclassing from this will implement Node::pre_transform() and
 * Node::post_transform() to dynamic cast to @a Subclass and then call
 * validate().  See Predicate::Validate.
 *
 * @tparam Subclass Type of subclass.
 **/
template <class Subclass>
class Call :
    virtual public Predicate::Call
{
public:
    //! Dynamic cast to @a Subclass and call Base::validate().
    virtual void pre_transform(NodeReporter reporter) const
    {
        assert(reporter.node().get() == this);
        Predicate::Call::pre_transform(reporter);
        dynamic_cast<const Subclass&>(*this).validate(reporter);
    }

    //! Dynamic cast to @a Subclass and call Base::validate().
    virtual void post_transform(NodeReporter reporter) const
    {
        assert(reporter.node().get() == this);
        Predicate::Call::post_transform(reporter);
        dynamic_cast<const Subclass&>(*this).validate(reporter);
    }
};

/**
 * Top of a validation chain.  Defines validate().
 *
 * You will not normally need to reference this class directly.  It is the
 * default argument of the @a Chain parameters of validation templates.
 **/
class Base
{
public:
    //! Local validation.  Default nop.
    virtual void local_validate(NodeReporter) const
    {
        // nop
    }

    //! Validate this node.
    virtual void validate(NodeReporter reporter) const
    {
        local_validate(reporter);
    }
};

/**
 * Metafunction to construct a validator from a function taking a size_t.
 *
 * @tparam F Function of @c NodeReporter and @c size_t to call.
 **/
template <bool (*F)(NodeReporter, size_t)>
struct make_validator_size
{
    //! Value; a validator.
    template <size_t N, class Chain = Validate::Base>
    struct value : public Chain
    {
        //! See Base::validate() and Predicate::Validate.
        virtual void validate(NodeReporter reporter) const
        {
            F(reporter, N);
            Chain::validate(reporter);
        }
    };
};

/**
 * Metafunction to construct a validator from a function taking nothing.
 *
 * @tparam F Function of @c NodeReporter to call.
 **/
template <bool (*F)(NodeReporter)>
struct make_validator
{
    //! Value; a validator.
    template <class Chain = Validate::Base>
    struct value : public Chain
    {
        //! See Base::validate() and Predicate::Validate.
        virtual void validate(NodeReporter reporter) const
        {
            F(reporter);
            Chain::validate(reporter);
        }
    };
};

/**
 * Report error if not exactly @a n children.
 *
 * @param[in] reporter Reporter to use.
 * @param[in] n        How many children expected.
 * @return true iff validation succeeded.
 **/
bool n_children(NodeReporter reporter, size_t n);

/**
 * Report error if not @a n or more children.
 *
 * @param[in] reporter Reporter to use.
 * @param[in] n        Minimum number of children expected.
 * @return true iff validation succeeded.
 **/
bool n_or_more_children(NodeReporter reporter, size_t n);

/**
 * Report error if not @a n or fewer children.
 *
 * @param[in] reporter Reporter to use.
 * @param[in] n        Maximum number of children expected.
 * @return true iff validation succeeded.
 **/
bool n_or_fewer_children(NodeReporter reporter, size_t n);

/**
 * Report error if @a nth child is not string literal.
 *
 * @param[in] reporter Reporter to use.
 * @param[in] n        Which child should be a string literal.
 * @return true iff validation succeeded.
 **/
bool nth_child_is_string(NodeReporter reporter, size_t n);

/**
 * Report error if @a nth child is not number literal.
 *
 * @param[in] reporter Reporter to use.
 * @param[in] n        Which child should be a number literal.
 * @return true iff validation succeeded.
 **/
bool nth_child_is_integer(NodeReporter reporter, size_t n);

/**
 * Report error if @a nth child is not float literal.
 *
 * @param[in] reporter Reporter to use.
 * @param[in] n        Which child should be a float literal.
 * @return true iff validation succeeded.
 **/
bool nth_child_is_float(NodeReporter reporter, size_t n);

/**
 * Report error if @a nth child is not a null.
 *
 * @param[in] reporter Reporter to use.
 * @param[in] n        Which child should be a null.
 * @return true iff validation succeeded.
 **/
bool nth_child_is_null(NodeReporter reporter, size_t n);

/**
 * Report error if @a nth child is a null.
 *
 * @param[in] reporter Reporter to use.
 * @param[in] n        Which child should not be a null.
 * @return true iff validation succeeded.
 **/
bool nth_child_is_not_null(NodeReporter reporter, size_t n);

/**
 * Report error if any child is literal.
 *
 * @param[in] reporter Reporter to use.
 * @return true iff validation succeeded.
 **/
bool no_child_is_literal(NodeReporter reporter);

/**
 * Report error if any child is null.
 *
 * @param[in] reporter Reporter to use.
 * @return true iff validation succeeded.
 **/
bool no_child_is_null(NodeReporter reporter);

/**
 * Validator: n_children()
 **/
template <size_t N, class Chain = Base>
struct NChildren :
    public make_validator_size<
        &n_children
    >::value<N, Chain>
{};

/**
 * Validator: n_or_more_children()
 **/
template <size_t N, class Chain = Base>
struct NOrMoreChildren :
    public make_validator_size<
        &n_or_more_children
    >::value<N, Chain>
{};

/**
 * Validator: n_or_fewer_children()
 **/
template <size_t N, class Chain = Base>
struct NOrFewerChildren :
    public make_validator_size<
        &n_or_fewer_children
    >::value<N, Chain>
{};

/**
 * Validator: nth_child_is_string()
 **/
template <size_t N, class Chain = Base>
struct NthChildIsString :
    public make_validator_size<
        &nth_child_is_string
    >::value<N, Chain>
{};

/**
 * Validator: nth_child_is_integer()
 **/
template <size_t N, class Chain = Base>
struct NthChildIsInteger :
    public make_validator_size<
        &nth_child_is_integer
    >::value<N, Chain>
{};

/**
 * Validator: nth_child_is_float()
 **/
template <size_t N, class Chain = Base>
struct NthChildIsFloat :
    public make_validator_size<
        &nth_child_is_float
    >::value<N, Chain>
{};

/**
 * Validator: nth_child_is_null()
 **/
template <size_t N, class Chain = Base>
struct NthChildIsNull :
    public make_validator_size<
        &nth_child_is_null
    >::value<N, Chain>
{};

/**
 * Validator: nth_child_is_not_null()
 **/
template <size_t N, class Chain = Base>
struct NthChildIsNotNull :
    public make_validator_size<
        &nth_child_is_not_null
    >::value<N, Chain>
{};

/**
 * Validator: no_child_is_literal()
 **/
template <class Chain = Base>
struct NoChildIsLiteral :
    public make_validator<
        &no_child_is_literal
    >::value<Chain>
{};

/**
 * Validator: no_child_is_null()
 **/
template <class Chain = Base>
struct NoChildIsNull :
    public make_validator<
        &no_child_is_null
    >::value<Chain>
{};

} // Validate
} // Predicate
} // IronBee

#endif
<|endoftext|>


<commit_before>// Copyright  (C)  2009  Ruben Smits <ruben dot smits at mech dot kuleuven dot be>

// Version: 1.0
// Author: Ruben Smits <ruben dot smits at mech dot kuleuven dot be>
// Maintainer: Ruben Smits <ruben dot smits at mech dot kuleuven dot be>
// URL: http://www.orocos.org/kdl

// 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 St, Fifth Floor, Boston, MA  02110-1301  USA

#ifndef KDL_RIGIDBODYINERTIA_HPP
#define KDL_RIGIDBODYINERTIA_HPP

#include "frames.hpp"

#include "rotationalinertia.hpp"

namespace KDL {

    /**
     *	\brief 6D Inertia of a rigid body
     *
     *	The inertia is defined in a certain reference point and a certain reference base.
     *	The reference point does not have to coincide with the origin of the reference frame.
     */
    class RigidBodyInertia{
    public:

        /**
         * 	This constructor creates a cartesian space inertia matrix,
         * 	the arguments are the mass, the vector from the reference point to cog and the rotational inertia in the cog.
         */
        RigidBodyInertia(double m, const Vector& oc=Vector::Zero(), const RotationalInertia& Ic=RotationalInertia::Zero());

        /**
         * Creates an inertia with zero mass, and zero RotationalInertia
         */
        static inline RigidBodyInertia Zero(){
            return RigidBodyInertia(0.0,Vector::Zero(),RotationalInertia::Zero());
        };

        ~RigidBodyInertia(){};

        /**
         * Scalar product: I_new = double * I_old
         */
        friend RigidBodyInertia operator*(double a,const RigidBodyInertia& I);
        /**
         * addition I: I_new = I_old1 + I_old2, make sure that I_old1
         * and I_old2 are expressed in the same reference frame/point,
         * otherwise the result is worth nothing
         */
        friend RigidBodyInertia operator+(const RigidBodyInertia& Ia,const RigidBodyInertia& Ib);

        /**
         * calculate spatial momentum: h = I*v
         * make sure that the twist v and the inertia are expressed in the same reference frame/point
         */
        friend Wrench operator*(const RigidBodyInertia& I,const Twist& t);

        /**
         * Coordinate system transform Ia = T_a_b*Ib with T_a_b the frame from a to b.
         */
        friend RigidBodyInertia operator*(const Frame& T,const RigidBodyInertia& I);
        /**
         * Reference frame orientation change Ia = R_a_b*Ib with R_a_b
         * the rotation of b expressed in a
         */
        friend RigidBodyInertia operator*(const Rotation& R,const RigidBodyInertia& I);

        /**
         * Reference point change with v the vector from the old to
         * the new point expressed in the current reference frame
         */
        RigidBodyInertia RefPoint(const Vector& p);

        /**
         * Get the mass of the rigid body
         */
        double getMass() const{
            return m;
        };

        /**
         * Get the center of gravity of the rigid body
         */
        Vector getCOG() const{
            if(m==0) return Vector::Zero();
            else return h/m;
        };

        /**
         * Get the rotational inertia expressed in the reference frame (not the cog)
         */
        RotationalInertia getRotationalInertia() const{
            return I;
        };

    private:
        RigidBodyInertia(double m,const Vector& h,const RotationalInertia& I,bool mhi);
        double m;
        RotationalInertia I;
        Vector h;

    };
}//namespace

#endif
<commit_msg>make abi a friend of rbi, and add default constructor with mass=0<commit_after>// Copyright  (C)  2009  Ruben Smits <ruben dot smits at mech dot kuleuven dot be>

// Version: 1.0
// Author: Ruben Smits <ruben dot smits at mech dot kuleuven dot be>
// Maintainer: Ruben Smits <ruben dot smits at mech dot kuleuven dot be>
// URL: http://www.orocos.org/kdl

// 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 St, Fifth Floor, Boston, MA  02110-1301  USA

#ifndef KDL_RIGIDBODYINERTIA_HPP
#define KDL_RIGIDBODYINERTIA_HPP

#include "frames.hpp"

#include "rotationalinertia.hpp"

namespace KDL {

    /**
     *	\brief 6D Inertia of a rigid body
     *
     *	The inertia is defined in a certain reference point and a certain reference base.
     *	The reference point does not have to coincide with the origin of the reference frame.
     */
    class RigidBodyInertia{
    public:

        /**
         * 	This constructor creates a cartesian space inertia matrix,
         * 	the arguments are the mass, the vector from the reference point to cog and the rotational inertia in the cog.
         */
        RigidBodyInertia(double m=0, const Vector& oc=Vector::Zero(), const RotationalInertia& Ic=RotationalInertia::Zero());

        /**
         * Creates an inertia with zero mass, and zero RotationalInertia
         */
        static inline RigidBodyInertia Zero(){
            return RigidBodyInertia(0.0,Vector::Zero(),RotationalInertia::Zero());
        };

        ~RigidBodyInertia(){};

        /**
         * Scalar product: I_new = double * I_old
         */
        friend RigidBodyInertia operator*(double a,const RigidBodyInertia& I);
        /**
         * addition I: I_new = I_old1 + I_old2, make sure that I_old1
         * and I_old2 are expressed in the same reference frame/point,
         * otherwise the result is worth nothing
         */
        friend RigidBodyInertia operator+(const RigidBodyInertia& Ia,const RigidBodyInertia& Ib);

        /**
         * calculate spatial momentum: h = I*v
         * make sure that the twist v and the inertia are expressed in the same reference frame/point
         */
        friend Wrench operator*(const RigidBodyInertia& I,const Twist& t);

        /**
         * Coordinate system transform Ia = T_a_b*Ib with T_a_b the frame from a to b.
         */
        friend RigidBodyInertia operator*(const Frame& T,const RigidBodyInertia& I);
        /**
         * Reference frame orientation change Ia = R_a_b*Ib with R_a_b
         * the rotation of b expressed in a
         */
        friend RigidBodyInertia operator*(const Rotation& R,const RigidBodyInertia& I);

        /**
         * Reference point change with v the vector from the old to
         * the new point expressed in the current reference frame
         */
        RigidBodyInertia RefPoint(const Vector& p);

        /**
         * Get the mass of the rigid body
         */
        double getMass() const{
            return m;
        };

        /**
         * Get the center of gravity of the rigid body
         */
        Vector getCOG() const{
            if(m==0) return Vector::Zero();
            else return h/m;
        };

        /**
         * Get the rotational inertia expressed in the reference frame (not the cog)
         */
        RotationalInertia getRotationalInertia() const{
            return I;
        };

    private:
        RigidBodyInertia(double m,const Vector& h,const RotationalInertia& I,bool mhi);
        double m;
        RotationalInertia I;
        Vector h;

        friend class ArticulatedBodyInertia;

    };
}//namespace

#endif
<|endoftext|>


<commit_before>#include "HalideRuntime.h"

// This is a trick used to ensure that halide_filter_metadata_t (and related types)
// are included in the runtime bitcode; since no (other) runtime function references them
// they are ordinarily stripped, making Codegen_LLVM fail when we attempt to access
// the types.

#define INLINE inline __attribute__((weak)) __attribute__((used)) __attribute__((always_inline)) __attribute__((nothrow)) __attribute__((pure))

INLINE void __force_include_halide_filter_metadata_t_types(halide_filter_metadata_t*) {}
<commit_msg>Prevent scalar runtime struct from being anonymized<commit_after>#include "HalideRuntime.h"

// This is a trick used to ensure that halide_filter_metadata_t (and related types)
// are included in the runtime bitcode; since no (other) runtime function references them
// they are ordinarily stripped, making Codegen_LLVM fail when we attempt to access
// the types.

#define INLINE inline __attribute__((weak)) __attribute__((used)) __attribute__((always_inline)) __attribute__((nothrow)) __attribute__((pure))

INLINE void __force_include_halide_filter_metadata_t_types(halide_filter_metadata_t*, halide_scalar_value_t*) {}
<|endoftext|>


<commit_before>/*
 * Ionosphere.cpp
 *
 *  Created on: 22 Jan 2015
 *      Author: rian
 */

#include <iostream>
#include <iomanip>
#include <cmath>
#include <iostream>
#include "Ionosphere.h"
#include "../math/Constants.h"
#include "../exporter/Data.h"
#include "../core/Application.h"
#include "../core/Config.h"
#include "../math/NormalDistribution.h"

namespace raytracer {
namespace scene {

	using namespace std;
	using namespace exporter;
	using namespace core;

	Ionosphere::Ionosphere() {}

	Ionosphere::Ionosphere(Vector2d begin, Vector2d end) : Geometry(begin, end) {

		type = Geometry::ionosphere;
	}

	/**
	 * Precalculate fixed values for this ionospheric layer. Assume static ionosphere as the
	 * time periods that we're interested in are an order of magnitude lower than the processes
	 * of photochemical reactions (discussion with Cyril Simon Wedlund)
	 */
	void Ionosphere::setup() {

		_altitude = getAltitude();
		_peakProductionAltitude = Ionosphere::peakProductionAltitude;//NormalDistribution::getInstance().get(Ionosphere::peakProductionAltitude, 1);
		_electronPeakDensity = Ionosphere::electronPeakDensity; //NormalDistribution::getInstance().get(Ionosphere::electronPeakDensity, electronDensityVariability);
	}

	/**
	 * Interaction between ray and ionospheric layer
	 */
	void Ionosphere::interact(Ray *r, Vector2d &hitpos) {

		setup();

		double magnitude = r->o.distance(hitpos);

		refract(r, hitpos);

		attenuate(r, magnitude);

		exportData(r);
	}

	void Ionosphere::refract(Ray *r, Vector2d &hitpos) {

		double refractiveIndex = getRefractiveIndex(r, Ionosphere::REFRACTION_KELSO);
		double SZA = getSolarZenithAngle2d();
		double beta = atan(r->d.y/r->d.x);
		double theta_i = getIncidentAngle(r);
		int waveBehaviour = determineWaveBehaviour(r);

		if (waveBehaviour == Ray::wave_reflection) {
			r->behaviour = Ray::wave_reflection;
			double beta_r = - beta - 2*SZA;
			r->setAngle(beta_r);
//			cout << "Reflect this ray! beta_r:" << beta_r * 180 / Constants::PI << " d.x,d.y:" << r->d.x << "," << r->d.y << "\n";
		} else if (waveBehaviour == Ray::wave_refraction) {
			if (r->d.y < 0) {
				theta_i = Constants::PI - theta_i;
			}
			r->behaviour = Ray::wave_refraction;
			double theta_r = asin((r->previousRefractiveIndex/refractiveIndex * sin(theta_i)));
			double beta_2 = Constants::PI/2 - theta_r - SZA;
			if (r->d.y < 0) {
				beta_2 = -Constants::PI/2 + theta_r - SZA;
			}
			r->setAngle(beta_2);
//			cout << "Bend this ray! refraction: " << refractiveIndex << " theta_i:" << theta_i * 180 / Constants::PI << ", theta_r:" << theta_r * 180 / Constants::PI << " \n";
		} else if (waveBehaviour == Ray::wave_none) {
			r->behaviour = Ray::wave_none;
			cout << "Ray goes straight!\n";
		} else {
			cerr << "No idea what to do with this ray!";
		}
		r->o.x = hitpos.x;
		r->o.y = hitpos.y;
		r->previousRefractiveIndex = refractiveIndex;
	}

	/**
	 * A radio wave is attenuated by its propagation through the ionosphere.
	 * The attenuation calculation is based on Nielsen, 2007. Attenuation depends
	 * on the electron-neutral collision frequency, the altitude w.r.t the peak
	 * production altitude and the radio wave frequency. The result is in db/m
	 * and thus is internally converted to attenuation in db, taking the layer
	 * height and the ray angle into account.
	 * A ray with a higher SZA will travel a longer path through the layer and
	 * thus face more attenuation.
	 */
	void Ionosphere::attenuate(Ray *r, double magnitude) {

		double theta_r = r->getAngle() - Constants::PI/2 + getSolarZenithAngle2d();
		if (r->d.y < 0) {
			theta_r = - r->getAngle() - Constants::PI/2 + getSolarZenithAngle2d();
		}

		double mu_r = sqrt(1 - pow(getPlasmaFrequency(), 2) / pow(2 * Constants::PI * r->frequency, 2));

		double ki = (-pow(getPlasmaFrequency(), 2) / (2 * Constants::C * mu_r))
				* getCollisionFrequency() / (pow(2 * Constants::PI * r->frequency, 2) + pow(getCollisionFrequency(), 2));

//		printf("wp: %4.2e, f: %4.2e, mu_r: %4.2e, colFreq: %4.2e, ki: %4.2e ", getPlasmaFrequency(), r->frequency, mu_r, getCollisionFrequency(), ki);

		double loss = 20 * log10(exp(1)) * ki * magnitude * abs(1 / cos(getSolarZenithAngle2d())) * cos(abs(theta_r));

//		printf("magnitude: %4.2f, totalLoss: %4.2e, theta: %4.2f, alt: %4.2f \n", magnitude, r->signalPower, theta_r, _altitude());

//		printf("Loss: %4.2e ", loss);

		r->signalPower += loss;
	}

	/**
	 * A radio wave is attenuated by its propagation through the ionosphere.
	 * The attenuation calculation is based on Withers, 2011. The ray frequencies
	 * are considered intermediate frequencies with neither rayFreq << plasmaFreq and
	 * plasmaFreq << rayFreq. Thus, the altitude w.r.t scale height depends what
	 * attenuation factor (A) needs to be used.
	 * Possible cases:
	 *  A = P_lo if (z0 - zl)/H < -1
	 *  A = minimum[P_lo, P_hi] if (z0 - zl)/H > -1
	 * Subsequently: P = P_t / A where P is the resulting power
	 */
	void Ionosphere::attenuateWithers(Ray *r) {

		double zL = Constants::NEUTRAL_SCALE_HEIGHT * log(Ionosphere::surfaceCollisionFrequency
				/ (2 * Constants::PI * r->frequency));

		printf("zL: %4.2e", zL);

		double pLowDb = 8.69 * (1/cos(getSolarZenithAngle2d())) * ((Constants::NEUTRAL_SCALE_HEIGHT * getElectronPeakDensity())
				/(2 * Constants::ELECTRON_MASS * Constants::C * Constants::PERMITTIVITY_VACUUM * r->frequency * 2 *Constants::PI));

		pLowDb = 7.3e-10 * (1/cos(getSolarZenithAngle2d())) * Constants::NEUTRAL_SCALE_HEIGHT * 1e9 / r->frequency;
		double pLowW =  pow(10, pLowDb/10);
		printf("pLowDb: %4.2e, pLowW: %4.2e ", pLowDb, pLowW);

		if (_peakProductionAltitude < zL - Constants::NEUTRAL_SCALE_HEIGHT) {
			r->signalPower /= pLowDb;
		} else {
			double pHigh = 8.69 * (1/cos(getSolarZenithAngle2d())) * ((Constants::NEUTRAL_SCALE_HEIGHT *
					_peakProductionAltitude * pow(Constants::ELEMENTARY_CHARGE, 2) * Ionosphere::surfaceCollisionFrequency)
					/(2 * Constants::ELECTRON_MASS * Constants::C * pow(2 * Constants::PI * r->frequency,2)));
			printf("pHigh: %4.2e, ", pHigh);
			if (pLowDb < pHigh) r->signalPower /= pLowW;
			else r->signalPower /= pHigh;
		}
	}

	void Ionosphere::exportData(Ray *r) {

		Data d;
		d.x = r->o.x;
		d.y = r->o.y;
		d.rayNumber = r->rayNumber;
		d.mu_r_sqrt = pow(r->previousRefractiveIndex, 2);
		d.n_e = getElectronNumberDensity();
		d.omega_p = getPlasmaFrequency();
		d.theta_0 = r->originalAngle;
		d.frequency = r->frequency;
		d.signalPower = r->signalPower;
		d.collisionType = Geometry::ionosphere;
		Application::getInstance().addToDataset(d);
	}

	/**
	 * Return a randomly distributed electron peak density. The electron peak randomly varies with a certain
	 * standard deviation. The mean and standard deviation are based on the normal peak electron density and
	 * delta ne as given by [Gurnett, 2009].
	 * @unit: particles m^-3
	 */
	double Ionosphere::getElectronPeakDensity() {

		return _electronPeakDensity;
	}

	/**
	 * Calculate the plasma frequency which depends on the electron number density
	 * which depends on the altitude (y). Use a chapman profile.
	 * @unit: rad s^-1
	 */
	double Ionosphere::getPlasmaFrequency() {

		return sqrt(getElectronNumberDensity() * pow(Constants::ELEMENTARY_CHARGE, 2)
				/ (Constants::ELECTRON_MASS * Constants::PERMITTIVITY_VACUUM));
	}

	/**
	 * Use a chapmanProfile to calculate the electron number density
	 * @unit: particles m^-3
	 */
	double Ionosphere::getElectronNumberDensity() {

		double normalizedHeight = (_altitude - _peakProductionAltitude) / Constants::NEUTRAL_SCALE_HEIGHT;

		return getElectronPeakDensity() *
				exp(0.5f * (1.0f - normalizedHeight - (1.0 / cos(getSolarZenithAngle2d())) * exp(-normalizedHeight) ));
	}

	/**
	 * Compute the plasma refractive index. Three refractive methods are supplied:
	 * - SIMPLE:
	 * - KELSO: The simplified method as described in Kelso, 1964, p.208
	 * - AHDR: Refractive index according to the Appleton-Hartree
	 * dispersion relation
	 */
	double Ionosphere::getRefractiveIndex(Ray *r, refractiveMethod m) {

		double n = 1.0;

		if (m == REFRACTION_SIMPLE) {

			n = sqrt(1 - getPlasmaFrequency() / (2 * Constants::PI * r->frequency));
		} else if (m == REFRACTION_KELSO) {

			n = sqrt(1 - getElectronNumberDensity() * pow(Constants::ELEMENTARY_CHARGE, 2) /
								(Constants::ELECTRON_MASS * Constants::PERMITTIVITY_VACUUM * pow(2 * Constants::PI * r->frequency,2)));
		} else if (m == REFRACTION_AHDR) {

			//n = 1 - X / (1);
		}

		return n;
	}

	/**
	 * Interpolate the altitude of this ionospheric layer. Throw an exception
	 * if the difference between the y-components of the edges of the mesh is
	 * too large, for this would imply the ionospheric layer is under an angle
	 * which does not make sense.
	 */
	double Ionosphere::getAltitude() {

		double xAvg = (mesh2d.begin.x + mesh2d.end.x)/2;
		double yAvg = (mesh2d.begin.y + mesh2d.end.y)/2;

		return sqrt(pow(xAvg, 2) + pow(yAvg, 2)) - Application::getInstance().getCelestialConfig().getInt("radius");
	}

	/**
	 * The incident angle of a ray with respect to the ionospheric layer. This angle depends
	 * on the propagation angle of the ray and the angle of the layer w.r.t. the sun (SZA)
	 */
	double Ionosphere::getIncidentAngle(Ray *r) {

		double SZA = getSolarZenithAngle2d();
		double beta = atan(r->d.y/r->d.x);
		double theta_i = Constants::PI/2 - beta - SZA;

		return theta_i;
	}

	/**
	 * Model the collision frequency according to Nielsen 2007, figure 4. This is an interpolated
	 * approximation and therefore only valid between 30 and 200km altitude.
	 */
	double Ionosphere::getCollisionFrequency() {

		if (_altitude < 30e3 || _altitude > 200e3) {
			cerr << "Altitude: " << _altitude << endl;
			printf("Begin x,y, end x,y (%4.2f, %4.2f), (%4.2f, %4.2f)\n",
					mesh2d.begin.x, mesh2d.begin.y, mesh2d.end.x, mesh2d.end.y);
			throw std::invalid_argument("Collision frequency interpolation not valid for this altitude! Altitude must be between 30 and 200km.");
		}

		return Ionosphere::surfaceCollisionFrequency * exp(-(_altitude - 73e3) / 6200);
	}

	/**
	 * A wave is either reflected or refracted depending on its incident angle. According to
	 * Snells' law, a critical angle exists for which the reflected angle is 90 deg. Incident
	 * angles above this critical angle are reflected, not refracted.
	 */
	int Ionosphere::determineWaveBehaviour(Ray *r) {

		double refractiveIndex = getRefractiveIndex(r, Ionosphere::REFRACTION_KELSO);
		double criticalAngle;
		double incidentAngle = getIncidentAngle(r);

		if (incidentAngle > Constants::PI/2)
			incidentAngle -= Constants::PI/2;

		if (refractiveIndex <= r->previousRefractiveIndex)
			criticalAngle = asin(refractiveIndex / r->previousRefractiveIndex);
		else
			criticalAngle = asin(r->previousRefractiveIndex / refractiveIndex);

		if (incidentAngle >= criticalAngle)
			return Ray::wave_reflection;
		else
			return Ray::wave_refraction;

		return Ray::wave_none;
	}

} /* namespace scene */
} /* namespace raytracer */
<commit_msg>Begin improvements on refraction/reflection determination<commit_after>/*
 * Ionosphere.cpp
 *
 *  Created on: 22 Jan 2015
 *      Author: rian
 */

#include <iostream>
#include <iomanip>
#include <cmath>
#include <iostream>
#include "Ionosphere.h"
#include "../math/Constants.h"
#include "../exporter/Data.h"
#include "../core/Application.h"
#include "../core/Config.h"
#include "../math/NormalDistribution.h"

namespace raytracer {
namespace scene {

	using namespace std;
	using namespace exporter;
	using namespace core;

	Ionosphere::Ionosphere() {}

	Ionosphere::Ionosphere(Vector2d begin, Vector2d end) : Geometry(begin, end) {

		type = Geometry::ionosphere;
	}

	/**
	 * Precalculate fixed values for this ionospheric layer. Assume static ionosphere as the
	 * time periods that we're interested in are an order of magnitude lower than the processes
	 * of photochemical reactions (discussion with Cyril Simon Wedlund)
	 */
	void Ionosphere::setup() {

		_altitude = getAltitude();
		_peakProductionAltitude = Ionosphere::peakProductionAltitude;//NormalDistribution::getInstance().get(Ionosphere::peakProductionAltitude, 1);
		_electronPeakDensity = Ionosphere::electronPeakDensity; //NormalDistribution::getInstance().get(Ionosphere::electronPeakDensity, electronDensityVariability);
	}

	/**
	 * Interaction between ray and ionospheric layer
	 */
	void Ionosphere::interact(Ray *r, Vector2d &hitpos) {

		setup();

		double magnitude = r->o.distance(hitpos);

		refract(r, hitpos);

		attenuate(r, magnitude);

		exportData(r);
	}

	void Ionosphere::refract(Ray *r, Vector2d &hitpos) {

		double refractiveIndex = getRefractiveIndex(r, Ionosphere::REFRACTION_KELSO);
		double SZA = getSolarZenithAngle2d();
		double beta = atan(r->d.y/r->d.x);
		double theta_i = getIncidentAngle(r);
		int waveBehaviour = determineWaveBehaviour(r);

		if (waveBehaviour == Ray::wave_reflection) {
			r->behaviour = Ray::wave_reflection;
			double beta_r = - beta - 2*SZA;
			r->setAngle(beta_r);
//			cout << "Reflect this ray! beta_r:" << beta_r * 180 / Constants::PI << " d.x,d.y:" << r->d.x << "," << r->d.y << "\n";
		} else if (waveBehaviour == Ray::wave_refraction) {
			if (r->d.y < 0) {
				theta_i = Constants::PI - theta_i;
			}
			r->behaviour = Ray::wave_refraction;
			double theta_r = asin((r->previousRefractiveIndex/refractiveIndex * sin(theta_i)));
			double beta_2 = Constants::PI/2 - theta_r - SZA;
			if (r->d.y < 0) {
				beta_2 = -Constants::PI/2 + theta_r - SZA;
			}
			r->setAngle(beta_2);
//			cout << "Bend this ray! refraction: " << refractiveIndex << " theta_i:" << theta_i * 180 / Constants::PI << ", theta_r:" << theta_r * 180 / Constants::PI << " \n";
		} else if (waveBehaviour == Ray::wave_none) {
			r->behaviour = Ray::wave_none;
			cout << "Ray goes straight!\n";
		} else {
			cerr << "No idea what to do with this ray!";
		}
		r->o.x = hitpos.x;
		r->o.y = hitpos.y;
		r->previousRefractiveIndex = refractiveIndex;
	}

	/**
	 * A radio wave is attenuated by its propagation through the ionosphere.
	 * The attenuation calculation is based on Nielsen, 2007. Attenuation depends
	 * on the electron-neutral collision frequency, the altitude w.r.t the peak
	 * production altitude and the radio wave frequency. The result is in db/m
	 * and thus is internally converted to attenuation in db, taking the layer
	 * height and the ray angle into account.
	 * A ray with a higher SZA will travel a longer path through the layer and
	 * thus face more attenuation.
	 */
	void Ionosphere::attenuate(Ray *r, double magnitude) {

		double theta_r = r->getAngle() - Constants::PI/2 + getSolarZenithAngle2d();
		if (r->d.y < 0) {
			theta_r = - r->getAngle() - Constants::PI/2 + getSolarZenithAngle2d();
		}

		double mu_r = sqrt(1 - pow(getPlasmaFrequency(), 2) / pow(2 * Constants::PI * r->frequency, 2));

		double ki = (-pow(getPlasmaFrequency(), 2) / (2 * Constants::C * mu_r))
				* getCollisionFrequency() / (pow(2 * Constants::PI * r->frequency, 2) + pow(getCollisionFrequency(), 2));

//		printf("wp: %4.2e, f: %4.2e, mu_r: %4.2e, colFreq: %4.2e, ki: %4.2e ", getPlasmaFrequency(), r->frequency, mu_r, getCollisionFrequency(), ki);

		double loss = 20 * log10(exp(1)) * ki * magnitude * abs(1 / cos(getSolarZenithAngle2d())) * cos(abs(theta_r));

//		printf("magnitude: %4.2f, totalLoss: %4.2e, theta: %4.2f, alt: %4.2f \n", magnitude, r->signalPower, theta_r, _altitude());

//		printf("Loss: %4.2e ", loss);

		r->signalPower += loss;
	}

	/**
	 * A radio wave is attenuated by its propagation through the ionosphere.
	 * The attenuation calculation is based on Withers, 2011. The ray frequencies
	 * are considered intermediate frequencies with neither rayFreq << plasmaFreq and
	 * plasmaFreq << rayFreq. Thus, the altitude w.r.t scale height depends what
	 * attenuation factor (A) needs to be used.
	 * Possible cases:
	 *  A = P_lo if (z0 - zl)/H < -1
	 *  A = minimum[P_lo, P_hi] if (z0 - zl)/H > -1
	 * Subsequently: P = P_t / A where P is the resulting power
	 */
	void Ionosphere::attenuateWithers(Ray *r) {

		double zL = Constants::NEUTRAL_SCALE_HEIGHT * log(Ionosphere::surfaceCollisionFrequency
				/ (2 * Constants::PI * r->frequency));

		printf("zL: %4.2e", zL);

		double pLowDb = 8.69 * (1/cos(getSolarZenithAngle2d())) * ((Constants::NEUTRAL_SCALE_HEIGHT * getElectronPeakDensity())
				/(2 * Constants::ELECTRON_MASS * Constants::C * Constants::PERMITTIVITY_VACUUM * r->frequency * 2 *Constants::PI));

		pLowDb = 7.3e-10 * (1/cos(getSolarZenithAngle2d())) * Constants::NEUTRAL_SCALE_HEIGHT * 1e9 / r->frequency;
		double pLowW =  pow(10, pLowDb/10);
		printf("pLowDb: %4.2e, pLowW: %4.2e ", pLowDb, pLowW);

		if (_peakProductionAltitude < zL - Constants::NEUTRAL_SCALE_HEIGHT) {
			r->signalPower /= pLowDb;
		} else {
			double pHigh = 8.69 * (1/cos(getSolarZenithAngle2d())) * ((Constants::NEUTRAL_SCALE_HEIGHT *
					_peakProductionAltitude * pow(Constants::ELEMENTARY_CHARGE, 2) * Ionosphere::surfaceCollisionFrequency)
					/(2 * Constants::ELECTRON_MASS * Constants::C * pow(2 * Constants::PI * r->frequency,2)));
			printf("pHigh: %4.2e, ", pHigh);
			if (pLowDb < pHigh) r->signalPower /= pLowW;
			else r->signalPower /= pHigh;
		}
	}

	void Ionosphere::exportData(Ray *r) {

		Data d;
		d.x = r->o.x;
		d.y = r->o.y;
		d.rayNumber = r->rayNumber;
		d.mu_r_sqrt = pow(r->previousRefractiveIndex, 2);
		d.n_e = getElectronNumberDensity();
		d.omega_p = getPlasmaFrequency();
		d.theta_0 = r->originalAngle;
		d.frequency = r->frequency;
		d.signalPower = r->signalPower;
		d.collisionType = Geometry::ionosphere;
		Application::getInstance().addToDataset(d);
	}

	/**
	 * Return a randomly distributed electron peak density. The electron peak randomly varies with a certain
	 * standard deviation. The mean and standard deviation are based on the normal peak electron density and
	 * delta ne as given by [Gurnett, 2009].
	 * @unit: particles m^-3
	 */
	double Ionosphere::getElectronPeakDensity() {

		return _electronPeakDensity;
	}

	/**
	 * Calculate the plasma frequency which depends on the electron number density
	 * which depends on the altitude (y). Use a chapman profile.
	 * @unit: rad s^-1
	 */
	double Ionosphere::getPlasmaFrequency() {

		return sqrt(getElectronNumberDensity() * pow(Constants::ELEMENTARY_CHARGE, 2)
				/ (Constants::ELECTRON_MASS * Constants::PERMITTIVITY_VACUUM));
	}

	/**
	 * Use a chapmanProfile to calculate the electron number density
	 * @unit: particles m^-3
	 */
	double Ionosphere::getElectronNumberDensity() {

		double normalizedHeight = (_altitude - _peakProductionAltitude) / Constants::NEUTRAL_SCALE_HEIGHT;

		return getElectronPeakDensity() *
				exp(0.5f * (1.0f - normalizedHeight - (1.0 / cos(getSolarZenithAngle2d())) * exp(-normalizedHeight) ));
	}

	/**
	 * Compute the plasma refractive index. Three refractive methods are supplied:
	 * - SIMPLE:
	 * - KELSO: The simplified method as described in Kelso, 1964, p.208
	 * - AHDR: Refractive index according to the Appleton-Hartree
	 * dispersion relation
	 */
	double Ionosphere::getRefractiveIndex(Ray *r, refractiveMethod m) {

		double n = 1.0;

		if (m == REFRACTION_KELSO) {

			n = sqrt(1 - getPlasmaFrequency() / (2 * Constants::PI * r->frequency));
		} else if (m == REFRACTION_AHDR) {

			//n = 1 - X / (1);
		}

		return n;
	}

	/**
	 * Interpolate the altitude of this ionospheric layer. Throw an exception
	 * if the difference between the y-components of the edges of the mesh is
	 * too large, for this would imply the ionospheric layer is under an angle
	 * which does not make sense.
	 */
	double Ionosphere::getAltitude() {

		double xAvg = (mesh2d.begin.x + mesh2d.end.x)/2;
		double yAvg = (mesh2d.begin.y + mesh2d.end.y)/2;

		return sqrt(pow(xAvg, 2) + pow(yAvg, 2)) - Application::getInstance().getCelestialConfig().getInt("radius");
	}

	/**
	 * The incident angle of a ray with respect to the ionospheric layer. This angle depends
	 * on the propagation angle of the ray and the angle of the layer w.r.t. the sun (SZA)
	 */
	double Ionosphere::getIncidentAngle(Ray *r) {

		double SZA = getSolarZenithAngle2d();
		double beta = atan(r->d.y/r->d.x);
		double theta_i = Constants::PI/2 - beta - SZA;

		return theta_i;
	}

	/**
	 * Model the collision frequency according to Nielsen 2007, figure 4. This is an interpolated
	 * approximation and therefore only valid between 30 and 200km altitude.
	 */
	double Ionosphere::getCollisionFrequency() {

		if (_altitude < 30e3 || _altitude > 200e3) {
			cerr << "Altitude: " << _altitude << endl;
			printf("Begin x,y, end x,y (%4.2f, %4.2f), (%4.2f, %4.2f)\n",
					mesh2d.begin.x, mesh2d.begin.y, mesh2d.end.x, mesh2d.end.y);
			throw std::invalid_argument("Collision frequency interpolation not valid for this altitude! Altitude must be between 30 and 200km.");
		}

		return Ionosphere::surfaceCollisionFrequency * exp(-(_altitude - 73e3) / 6200);
	}

	/**
	 * A wave is either reflected or refracted depending on its incident angle. According to
	 * Snells' law, a critical angle exists for which the reflected angle is 90 deg. Incident
	 * angles above this critical angle are reflected, not refracted.
	 * @ todo: REWRITE COMPLETELY
	 */
	int Ionosphere::determineWaveBehaviour(Ray *r) {

		double refractiveIndex = getRefractiveIndex(r, Ionosphere::REFRACTION_KELSO);
		double criticalAngle;
		double incidentAngle = getIncidentAngle(r);

		if (incidentAngle > Constants::PI/2)
			incidentAngle -= Constants::PI/2;

		if (refractiveIndex <= r->previousRefractiveIndex)
			criticalAngle = asin(refractiveIndex / r->previousRefractiveIndex);
		else
			criticalAngle = asin(r->previousRefractiveIndex / refractiveIndex);

		if (incidentAngle >= criticalAngle)
			return Ray::wave_reflection;
		else
			return Ray::wave_refraction;

		return Ray::wave_none;
	}

} /* namespace scene */
} /* namespace raytracer */
<|endoftext|>