<commit_before>/******************************************************************************
 * $Id$
 *
 * Project:  libLAS - http://liblas.org - A BSD library for LAS format data.
 * Purpose:  LAS Schema implementation for C++ libLAS
 * Author:   Howard Butler, hobu.inc@gmail.com
 *
 ******************************************************************************
 * Copyright (c) 2010, Howard Butler
 *
 * 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 Martin Isenburg or Iowa Department
 *       of Natural Resources 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.
 ****************************************************************************/

#include <pdal/Schema.hpp>

#include <iostream>
#include <map>

#include <boost/lexical_cast.hpp>
#include <boost/property_tree/json_parser.hpp>

#include <boost/uuid/uuid_io.hpp>
#include <boost/concept_check.hpp> // ignore_unused_variable_warning
#include <boost/algorithm/string.hpp>

#ifdef PDAL_HAVE_LIBXML2
#include <pdal/XMLSchema.hpp>
#endif

namespace pdal
{

Schema::Schema()
    : m_byteSize(0)
{
    return;
}

Schema::Schema(std::vector<Dimension> const& dimensions)
    : m_byteSize(0)
{

    for (std::vector<Dimension>::const_iterator i = dimensions.begin();
            i != dimensions.end(); ++i)
    {
        appendDimension(*i);
    }
}

/// copy constructor
Schema::Schema(Schema const& other)
    : m_byteSize(other.m_byteSize)
    , m_index(other.m_index)
{

}

// assignment constructor
Schema& Schema::operator=(Schema const& rhs)
{
    if (&rhs != this)
    {
        m_byteSize = rhs.m_byteSize;
        m_index = rhs.m_index;
    }

    return *this;
}

bool Schema::operator==(const Schema& other) const
{
    if (m_byteSize != other.m_byteSize) return false;

    if (m_index.size() != other.m_index.size()) return false;

    schema::index_by_index const& idx = m_index.get<schema::index>();
    schema::index_by_index const& idx2 = m_index.get<schema::index>();

    schema::index_by_index::size_type i(0);
    for (i = 0; i < idx.size(); ++i)
    {
        if (!(idx[i] == idx2[i]))
        {
            return false;
        }
    }

    return true;
}

bool Schema::operator!=(const Schema& other) const
{
    return !(*this==other);
}

void Schema::appendDimension(const Dimension& dim)
{
    // Copy the Dimension because we're going to overwrite/set some of
    // its attributes
    Dimension d(dim);

    schema::index_by_position& position_index = m_index.get<schema::position>();

    schema::index_by_position::const_reverse_iterator r = position_index.rbegin();

    // If we do not have anything in the index, set our current values.
    // Otherwise, use the values from the last entry in the index as our
    // starting point
    if (r != position_index.rend())
    {
        Dimension const& t = *r;

        m_byteSize = m_byteSize + d.getByteSize();

        d.setByteOffset(t.getByteOffset() + t.getByteSize());
    }
    else
    {
        m_byteSize = d.getByteSize();
        d.setByteOffset(0);
    }

    d.setPosition(m_index.size());

    std::pair<schema::index_by_position::iterator, bool> q = position_index.insert(d);
    if (!q.second)
    {
        std::ostringstream oss;
        oss << "Could not insert into schema index because of " << q.first->getName();
        throw schema_error(oss.str());
    }

    return;
}

const Dimension& Schema::getDimension(std::size_t t) const
{
    schema::index_by_index const& idx = m_index.get<schema::index>();

    if (t >= idx.size())
        throw dimension_not_found("Index position is not valid");

    return idx.at(t);
}

boost::optional<Dimension const&> Schema::getDimensionOptional(std::size_t t) const
{
    try
    {
        Dimension const& dim = getDimension(t);
        return boost::optional<Dimension const&>(dim);
    }
    catch (pdal::dimension_not_found&)
    {
        return boost::optional<Dimension const&>();
    }
}

const Dimension& Schema::getDimension(std::string const& t, std::string const& ns) const
{
    schema::index_by_name const& name_index = m_index.get<schema::name>();
    schema::index_by_name::const_iterator it = name_index.find(t);

    schema::index_by_name::size_type count = name_index.count(t);

    std::ostringstream oss;
    oss << "Dimension with name '" << t << "' not found, unable to Schema::getDimension";

    // FIXME: If there are two dimensions with the same name here, we're
    // scrwed

    // std::cout << "finding dimension with name " << t << " and ns: " << ns << std::endl;
    if (it != name_index.end())
    {

        if (ns.size())
        {
            while (it != name_index.end())
            {
                if (boost::equals(ns, it->getNamespace()))
                {
                    return *it;
                }

                ++it;
            }

        }

        if (count > 1)
        {

            std::pair<schema::index_by_name::const_iterator, schema::index_by_name::const_iterator> ret = name_index.equal_range(t);
            boost::uint32_t num_parents(0);
            boost::uint32_t num_children(0);
            std::map<dimension::id, dimension::id> relationships;

            // Test to make sure that the number of parent dimensions all with
            // the same name is equal to only 1. If there are multiple
            // dimensions with the same name, but no relationships defined,
            // we are in an error condition
            for (schema::index_by_name::const_iterator  o = ret.first; o != ret.second; ++o)
            {
                // Put a map together that maps parents to children that
                // we are going to walk to find the very last child in the
                // graph.
                std::pair<dimension::id, dimension::id> p(o->getParent(), o->getUUID());
                relationships.insert(p);

                // The parent dimension should have a nil parent of its own.
                // nil_uuid is the default parent of all dimensions as the y
                // are created
                if (o->getParent().is_nil())
                {
                    num_parents++;
                }
                else
                {
                    num_children++;
                }

            }

            if (num_parents != 1)
            {
                std::ostringstream oss;

                oss << "Schema has multiple dimensions with name '" << t << "', but "
                    "their parent/child relationships are not coherent. Multiple "
                    "parents are present.";

                throw multiple_parent_dimensions(oss.str());
            }

            dimension::id parent = boost::uuids::nil_uuid();

            // Starting at the parent (nil uuid), walk the child/parent graph down to the
            // end.  When we're done finding dimensions, what's left is the child
            // at the end of the graph.
            std::map<dimension::id, dimension::id>::const_iterator p = relationships.find(parent);
            dimension::id child;
            while (p != relationships.end())
            {
                child = p->second;
                p = relationships.find(p->second);
            }
            schema::index_by_uid::const_iterator pi = m_index.get<schema::uid>().find(child);
            if (pi != m_index.get<schema::uid>().end())
            {
                return *pi;
            }
            else
            {
                std::ostringstream errmsg;
                errmsg << "Unable to fetch subjugate dimension with id '" << child << "' in schema";
                throw dimension_not_found(errmsg.str());
            }
        }
        // we don't have a ns or we don't have multiples, return what we found
        return *it;
    }
    else
    {
        boost::uuids::uuid ps1;
        try
        {
            boost::uuids::string_generator gen;
            ps1 = gen(t);
        }
        catch (std::runtime_error&)
        {
            // invalid string for uuid
            throw dimension_not_found(oss.str());
        }

        schema::index_by_uid::const_iterator i = m_index.get<schema::uid>().find(ps1);

        if (i != m_index.get<schema::uid>().end())
        {
            if (ns.size())
            {
                while (i != m_index.get<schema::uid>().end())
                {
                    if (boost::equals(ns, i->getNamespace()))
                    {
                        return *i;
                    }

                    ++i;
                }

            }

            return *i;
        }
        else
        {
            oss.str("");
            oss << "Dimension with name '" << t << "' not found, unable to Schema::getDimension";
            throw dimension_not_found(oss.str());
        }

    }

}

boost::optional<Dimension const&> Schema::getDimensionOptional(std::string const& t, std::string const& ns) const
{

    try
    {
        Dimension const& dim = getDimension(t, ns);
        return boost::optional<Dimension const&>(dim);
    }
    catch (pdal::dimension_not_found&)
    {
        return boost::optional<Dimension const&>();
    }

}

bool Schema::setDimension(Dimension const& dim)
{
    // Try setting based on UUID first if it's there and not null.
    if (dim.getUUID() != boost::uuids::nil_uuid())
    {
        schema::index_by_uid& id_index = m_index.get<schema::uid>();
        schema::index_by_uid::const_iterator id = id_index.find(dim.getUUID());
        if (id != id_index.end())
        {
            id_index.replace(id, dim);
            return true;
        }
    }

    schema::index_by_name& name_index = m_index.get<schema::name>();
    schema::index_by_name::iterator it = name_index.find(dim.getName());
    // FIXME: If there are two dimensions with the same name here, we're
    // screwed if they both have the same namespace too
    if (it != name_index.end())
    {
        while (it != name_index.end())
        {
            if (boost::equals(dim.getNamespace(), it->getNamespace()))
            {
                name_index.replace(it, dim);
                return true;
            }
            ++it;
        }
    }
    else
    {
        std::ostringstream oss;
        oss << "Dimension with name '" << dim.getName() << "' not found, unable to Schema::setDimension";
        throw dimension_not_found(oss.str());
    }

    return true;
}

const Dimension& Schema::getDimension(dimension::id const& t) const
{
    /// getDimension for a dimension::id will not respect the isIgnored setting
    /// of the dimension.  Stages that wish to operate with dimensions with exacting
    /// specificity should take care to use uuids as their keys rather than
    /// names.
    schema::index_by_uid::const_iterator it = m_index.get<schema::uid>().find(t);

    if (it != m_index.get<schema::uid>().end())
    {
        return *it;
    }

    std::ostringstream oss;
    oss << "getDimension: dimension not found with uuid '" << boost::lexical_cast<std::string>(t) << "'";
    throw dimension_not_found(oss.str());
}

boost::optional<Dimension const&> Schema::getDimensionOptional(dimension::id const& t) const
{
    try
    {
        Dimension const& dim = getDimension(t);
        return boost::optional<Dimension const&>(dim);
    }
    catch (pdal::dimension_not_found&)
    {
        return boost::optional<Dimension const&>();
    }
}

Schema Schema::from_xml(std::string const& xml, std::string const& xsd)
{
#ifdef PDAL_HAVE_LIBXML2

    pdal::schema::Reader reader(xml, xsd);

    pdal::Schema schema = reader.getSchema();
    return schema;

#else
    boost::ignore_unused_variable_warning(xml);
    boost::ignore_unused_variable_warning(xsd);
    return Schema();
#endif
}

Schema Schema::from_xml(std::string const& xml)
{
#ifdef PDAL_HAVE_LIBXML2

    std::string xsd("");

    pdal::schema::Reader reader(xml, xsd);

    pdal::Schema schema = reader.getSchema();
    return schema;

#else
    boost::ignore_unused_variable_warning(xml);
    return Schema();
#endif
}

std::string Schema::to_xml(Schema const& schema)
{
#ifdef PDAL_HAVE_LIBXML2

    pdal::schema::Writer writer(schema);

    return writer.getXML();

#else
    boost::ignore_unused_variable_warning(schema);
    return std::string("");
#endif
}

boost::property_tree::ptree Schema::toPTree() const
{
    boost::property_tree::ptree tree;

    schema::index_by_index const& idx = m_index.get<schema::index>();

    for (schema::index_by_index::const_iterator iter = idx.begin(); iter != idx.end(); ++iter)
    {
        const Dimension& dim = *iter;
        tree.add_child("dimension", dim.toPTree());
    }

    return tree;
}

void Schema::dump() const
{
    std::cout << *this;
}

std::ostream& operator<<(std::ostream& os, pdal::Schema const& schema)
{
    boost::property_tree::ptree tree = schema.toPTree();

    boost::property_tree::write_json(os, tree);

    return os;
}

} // namespace pdal
<commit_msg>getDimension now supports asking for dotted names in the name variable, ie, 'drivers.las.reader.X', and it will separate the name and namespace on the last . that's found if .'s exist in the name argument<commit_after>/******************************************************************************
 * $Id$
 *
 * Project:  libLAS - http://liblas.org - A BSD library for LAS format data.
 * Purpose:  LAS Schema implementation for C++ libLAS
 * Author:   Howard Butler, hobu.inc@gmail.com
 *
 ******************************************************************************
 * Copyright (c) 2010, Howard Butler
 *
 * 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 Martin Isenburg or Iowa Department
 *       of Natural Resources 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.
 ****************************************************************************/

#include <pdal/Schema.hpp>

#include <iostream>
#include <map>

#include <boost/lexical_cast.hpp>
#include <boost/property_tree/json_parser.hpp>

#include <boost/uuid/uuid_io.hpp>
#include <boost/concept_check.hpp> // ignore_unused_variable_warning
#include <boost/algorithm/string.hpp>
#include <boost/tokenizer.hpp>

#ifdef PDAL_HAVE_LIBXML2
#include <pdal/XMLSchema.hpp>
#endif

namespace pdal
{

Schema::Schema()
    : m_byteSize(0)
{
    return;
}

Schema::Schema(std::vector<Dimension> const& dimensions)
    : m_byteSize(0)
{

    for (std::vector<Dimension>::const_iterator i = dimensions.begin();
            i != dimensions.end(); ++i)
    {
        appendDimension(*i);
    }
}

/// copy constructor
Schema::Schema(Schema const& other)
    : m_byteSize(other.m_byteSize)
    , m_index(other.m_index)
{

}

// assignment constructor
Schema& Schema::operator=(Schema const& rhs)
{
    if (&rhs != this)
    {
        m_byteSize = rhs.m_byteSize;
        m_index = rhs.m_index;
    }

    return *this;
}

bool Schema::operator==(const Schema& other) const
{
    if (m_byteSize != other.m_byteSize) return false;

    if (m_index.size() != other.m_index.size()) return false;

    schema::index_by_index const& idx = m_index.get<schema::index>();
    schema::index_by_index const& idx2 = m_index.get<schema::index>();

    schema::index_by_index::size_type i(0);
    for (i = 0; i < idx.size(); ++i)
    {
        if (!(idx[i] == idx2[i]))
        {
            return false;
        }
    }

    return true;
}

bool Schema::operator!=(const Schema& other) const
{
    return !(*this==other);
}

void Schema::appendDimension(const Dimension& dim)
{
    // Copy the Dimension because we're going to overwrite/set some of
    // its attributes
    Dimension d(dim);

    schema::index_by_position& position_index = m_index.get<schema::position>();

    schema::index_by_position::const_reverse_iterator r = position_index.rbegin();

    // If we do not have anything in the index, set our current values.
    // Otherwise, use the values from the last entry in the index as our
    // starting point
    if (r != position_index.rend())
    {
        Dimension const& t = *r;

        m_byteSize = m_byteSize + d.getByteSize();

        d.setByteOffset(t.getByteOffset() + t.getByteSize());
    }
    else
    {
        m_byteSize = d.getByteSize();
        d.setByteOffset(0);
    }

    d.setPosition(m_index.size());

    std::pair<schema::index_by_position::iterator, bool> q = position_index.insert(d);
    if (!q.second)
    {
        std::ostringstream oss;
        oss << "Could not insert into schema index because of " << q.first->getName();
        throw schema_error(oss.str());
    }

    return;
}

const Dimension& Schema::getDimension(std::size_t t) const
{
    schema::index_by_index const& idx = m_index.get<schema::index>();

    if (t >= idx.size())
        throw dimension_not_found("Index position is not valid");

    return idx.at(t);
}

boost::optional<Dimension const&> Schema::getDimensionOptional(std::size_t t) const
{
    try
    {
        Dimension const& dim = getDimension(t);
        return boost::optional<Dimension const&>(dim);
    }
    catch (pdal::dimension_not_found&)
    {
        return boost::optional<Dimension const&>();
    }
}

const Dimension& Schema::getDimension(std::string const& name, std::string const& namespc) const
{

    std::size_t dot_position = name.find_last_of(".");

    std::string ns(namespc);
    std::string t(name);
    if (dot_position != std::string::npos && namespc.empty())
    {
        // We were given a dotted name instead of a name + ns.  Let's split them up.
        ns = name.substr(0,dot_position);
        t = name.substr(dot_position+1 /*skip the '.'*/, name.size());
    }

    schema::index_by_name const& name_index = m_index.get<schema::name>();
    schema::index_by_name::const_iterator it = name_index.find(t);

    schema::index_by_name::size_type count = name_index.count(t);

    std::ostringstream oss;
    oss << "Dimension with name '" << t << "' not found, unable to Schema::getDimension";

    if (it != name_index.end())
    {

        if (ns.size())
        {
            while (it != name_index.end())
            {
                if (boost::equals(ns, it->getNamespace()))
                {
                    return *it;
                }

                ++it;
            }

        }

        if (count > 1)
        {

            std::pair<schema::index_by_name::const_iterator, schema::index_by_name::const_iterator> ret = name_index.equal_range(t);
            boost::uint32_t num_parents(0);
            boost::uint32_t num_children(0);
            std::map<dimension::id, dimension::id> relationships;

            // Test to make sure that the number of parent dimensions all with
            // the same name is equal to only 1. If there are multiple
            // dimensions with the same name, but no relationships defined,
            // we are in an error condition
            for (schema::index_by_name::const_iterator  o = ret.first; o != ret.second; ++o)
            {
                // Put a map together that maps parents to children that
                // we are going to walk to find the very last child in the
                // graph.
                std::pair<dimension::id, dimension::id> p(o->getParent(), o->getUUID());
                relationships.insert(p);

                // The parent dimension should have a nil parent of its own.
                // nil_uuid is the default parent of all dimensions as the y
                // are created
                if (o->getParent().is_nil())
                {
                    num_parents++;
                }
                else
                {
                    num_children++;
                }

            }

            if (num_parents != 1)
            {
                std::ostringstream oss;

                oss << "Schema has multiple dimensions with name '" << t << "', but "
                    "their parent/child relationships are not coherent. Multiple "
                    "parents are present.";

                throw multiple_parent_dimensions(oss.str());
            }

            dimension::id parent = boost::uuids::nil_uuid();

            // Starting at the parent (nil uuid), walk the child/parent graph down to the
            // end.  When we're done finding dimensions, what's left is the child
            // at the end of the graph.
            std::map<dimension::id, dimension::id>::const_iterator p = relationships.find(parent);
            dimension::id child;
            while (p != relationships.end())
            {
                child = p->second;
                p = relationships.find(p->second);
            }
            schema::index_by_uid::const_iterator pi = m_index.get<schema::uid>().find(child);
            if (pi != m_index.get<schema::uid>().end())
            {
                return *pi;
            }
            else
            {
                std::ostringstream errmsg;
                errmsg << "Unable to fetch subjugate dimension with id '" << child << "' in schema";
                throw dimension_not_found(errmsg.str());
            }
        }
        // we don't have a ns or we don't have multiples, return what we found
        return *it;
    }
    else
    {
        boost::uuids::uuid ps1;
        try
        {
            boost::uuids::string_generator gen;
            ps1 = gen(t);
        }
        catch (std::runtime_error&)
        {
            // invalid string for uuid
            throw dimension_not_found(oss.str());
        }

        schema::index_by_uid::const_iterator i = m_index.get<schema::uid>().find(ps1);

        if (i != m_index.get<schema::uid>().end())
        {
            if (ns.size())
            {
                while (i != m_index.get<schema::uid>().end())
                {
                    if (boost::equals(ns, i->getNamespace()))
                    {
                        return *i;
                    }

                    ++i;
                }

            }

            return *i;
        }
        else
        {
            oss.str("");
            oss << "Dimension with name '" << t << "' not found, unable to Schema::getDimension";
            throw dimension_not_found(oss.str());
        }

    }

}

boost::optional<Dimension const&> Schema::getDimensionOptional(std::string const& t, std::string const& ns) const
{

    try
    {
        Dimension const& dim = getDimension(t, ns);
        return boost::optional<Dimension const&>(dim);
    }
    catch (pdal::dimension_not_found&)
    {
        return boost::optional<Dimension const&>();
    }

}

bool Schema::setDimension(Dimension const& dim)
{
    // Try setting based on UUID first if it's there and not null.
    if (dim.getUUID() != boost::uuids::nil_uuid())
    {
        schema::index_by_uid& id_index = m_index.get<schema::uid>();
        schema::index_by_uid::const_iterator id = id_index.find(dim.getUUID());
        if (id != id_index.end())
        {
            id_index.replace(id, dim);
            return true;
        }
    }

    schema::index_by_name& name_index = m_index.get<schema::name>();
    schema::index_by_name::iterator it = name_index.find(dim.getName());
    // FIXME: If there are two dimensions with the same name here, we're
    // screwed if they both have the same namespace too
    if (it != name_index.end())
    {
        while (it != name_index.end())
        {
            if (boost::equals(dim.getNamespace(), it->getNamespace()))
            {
                name_index.replace(it, dim);
                return true;
            }
            ++it;
        }
    }
    else
    {
        std::ostringstream oss;
        oss << "Dimension with name '" << dim.getName() << "' not found, unable to Schema::setDimension";
        throw dimension_not_found(oss.str());
    }

    return true;
}

const Dimension& Schema::getDimension(dimension::id const& t) const
{
    /// getDimension for a dimension::id will not respect the isIgnored setting
    /// of the dimension.  Stages that wish to operate with dimensions with exacting
    /// specificity should take care to use uuids as their keys rather than
    /// names.
    schema::index_by_uid::const_iterator it = m_index.get<schema::uid>().find(t);

    if (it != m_index.get<schema::uid>().end())
    {
        return *it;
    }

    std::ostringstream oss;
    oss << "getDimension: dimension not found with uuid '" << boost::lexical_cast<std::string>(t) << "'";
    throw dimension_not_found(oss.str());
}

boost::optional<Dimension const&> Schema::getDimensionOptional(dimension::id const& t) const
{
    try
    {
        Dimension const& dim = getDimension(t);
        return boost::optional<Dimension const&>(dim);
    }
    catch (pdal::dimension_not_found&)
    {
        return boost::optional<Dimension const&>();
    }
}

Schema Schema::from_xml(std::string const& xml, std::string const& xsd)
{
#ifdef PDAL_HAVE_LIBXML2

    pdal::schema::Reader reader(xml, xsd);

    pdal::Schema schema = reader.getSchema();
    return schema;

#else
    boost::ignore_unused_variable_warning(xml);
    boost::ignore_unused_variable_warning(xsd);
    return Schema();
#endif
}

Schema Schema::from_xml(std::string const& xml)
{
#ifdef PDAL_HAVE_LIBXML2

    std::string xsd("");

    pdal::schema::Reader reader(xml, xsd);

    pdal::Schema schema = reader.getSchema();
    return schema;

#else
    boost::ignore_unused_variable_warning(xml);
    return Schema();
#endif
}

std::string Schema::to_xml(Schema const& schema)
{
#ifdef PDAL_HAVE_LIBXML2

    pdal::schema::Writer writer(schema);

    return writer.getXML();

#else
    boost::ignore_unused_variable_warning(schema);
    return std::string("");
#endif
}

boost::property_tree::ptree Schema::toPTree() const
{
    boost::property_tree::ptree tree;

    schema::index_by_index const& idx = m_index.get<schema::index>();

    for (schema::index_by_index::const_iterator iter = idx.begin(); iter != idx.end(); ++iter)
    {
        const Dimension& dim = *iter;
        tree.add_child("dimension", dim.toPTree());
    }

    return tree;
}

void Schema::dump() const
{
    std::cout << *this;
}

std::ostream& operator<<(std::ostream& os, pdal::Schema const& schema)
{
    boost::property_tree::ptree tree = schema.toPTree();

    boost::property_tree::write_json(os, tree);

    return os;
}

} // namespace pdal
<|endoftext|>


<commit_before>/* Copyright 2016 Google Inc. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/

#include "tensorflow/contrib/session_bundle/session_bundle.h"

#include <string>
#include <utility>
#include <vector>

#include "google/protobuf/any.pb.h"
#include "tensorflow/contrib/session_bundle/manifest.pb.h"
#include "tensorflow/core/framework/graph.pb.h"
#include "tensorflow/core/framework/tensor.h"
#include "tensorflow/core/framework/tensor_shape.h"
#include "tensorflow/core/framework/tensor_types.h"
#include "tensorflow/core/framework/types.pb.h"
#include "tensorflow/core/lib/core/errors.h"
#include "tensorflow/core/lib/core/status.h"
#include "tensorflow/core/lib/io/path.h"
#include "tensorflow/core/platform/env.h"
#include "tensorflow/core/platform/protobuf.h"
#include "tensorflow/core/platform/types.h"
#include "tensorflow/core/protobuf/meta_graph.pb.h"
#include "tensorflow/core/protobuf/saver.pb.h"
#include "tensorflow/core/public/session_options.h"

namespace tensorflow {
namespace serving {
namespace {

// Create a session using the given options and load the graph.
Status CreateSessionFromGraphDef(const SessionOptions& options,
                                 const GraphDef& graph,
                                 std::unique_ptr<Session>* session) {
  session->reset(NewSession(options));
  return (*session)->Create(graph);
}

Status GetMetaGraphDefFromExport(const StringPiece export_dir,
                                 MetaGraphDef* meta_graph_def) {
  const string meta_graph_def_path =
      io::JoinPath(export_dir, kMetaGraphDefFilename);
  return ReadBinaryProto(Env::Default(), meta_graph_def_path, meta_graph_def);
}

// Creates a string tensor.
Tensor CreateStringTensor(const string& value) {
  Tensor tensor(DT_STRING, TensorShape({}));
  tensor.scalar<string>()() = value;
  return tensor;
}

// Adds Assets related tensors (assets_dir and asset files) to the inputs.
void AddAssetsTensorsToInputs(const StringPiece export_dir,
                              const std::vector<AssetFile>& asset_files,
                              std::vector<std::pair<string, Tensor>>* inputs) {
  if (asset_files.empty()) {
    return;
  }
  for (auto& asset : asset_files) {
    Tensor assets_file_tensor = CreateStringTensor(io::JoinPath(
        io::JoinPath(export_dir, kAssetsDirectory), asset.filename()));
    inputs->push_back(
        {asset.tensor_binding().tensor_name(), assets_file_tensor});
    }
}

// Historically, model exporter(exporter.py) takes only saver with
// sharded=True, and therefore always exports checkpoint in pattern file names.
// In practice, instead of training from scratch and export directly, we
// usually want to restore from existing checkpoints and then export directly.
// To support such case, model exporter now supports reusing saver object
// restored from existing checkpoint, that may have sharded=False - it will
// then export checkpoint file in plain file name.
// This method is to support models exported by both types of saver object.
// The change is backward-compatible, therefore no changes are needed for
// existing model exports.
string GetVariablesFilename(const StringPiece export_dir) {
  const char kVariablesFilename[] = "export";
  const char kVariablesFilenamePattern[] = "export-\?\?\?\?\?-of-\?\?\?\?\?";
  if (Env::Default()->FileExists(
          io::JoinPath(export_dir, kVariablesFilename))) {
    return io::JoinPath(export_dir, kVariablesFilename);
  } else {
    return io::JoinPath(export_dir, kVariablesFilenamePattern);
  }
}

Status RunRestoreOp(const RunOptions& run_options, const StringPiece export_dir,
                    const std::vector<AssetFile>& asset_files,
                    const StringPiece restore_op_name,
                    const StringPiece variables_filename_const_op_name,
                    Session* session) {
  LOG(INFO) << "Running restore op for SessionBundle";
  Tensor variables_tensor =
      CreateStringTensor(GetVariablesFilename(export_dir));
  std::vector<std::pair<string, Tensor>> inputs = {
      {variables_filename_const_op_name.ToString(), variables_tensor}};
  AddAssetsTensorsToInputs(export_dir, asset_files, &inputs);
  RunMetadata run_metadata;
  return session->Run(run_options, inputs, {}, {restore_op_name.ToString()},
                      nullptr /* outputs */, &run_metadata);
}

Status RunInitOp(const RunOptions& run_options, const StringPiece export_dir,
                 const std::vector<AssetFile>& asset_files,
                 const StringPiece init_op_name, Session* session) {
  LOG(INFO) << "Running init op for SessionBundle";
  std::vector<std::pair<string, Tensor>> inputs;
  AddAssetsTensorsToInputs(export_dir, asset_files, &inputs);
  RunMetadata run_metadata;
  return session->Run(run_options, inputs, {}, {init_op_name.ToString()},
                      nullptr /* outputs */, &run_metadata);
}

}  // namespace

Status LoadSessionBundleFromPath(const SessionOptions& options,
                                 const StringPiece export_dir,
                                 SessionBundle* const bundle) {
  TF_RETURN_IF_ERROR(LoadSessionBundleFromPathUsingRunOptions(
      options, RunOptions(), export_dir, bundle));
  return Status::OK();
}

Status LoadSessionBundleFromPathUsingRunOptions(const SessionOptions& options,
                                                const RunOptions& run_options,
                                                const StringPiece export_dir,
                                                SessionBundle* const bundle) {
  LOG(INFO) << "Attempting to load a SessionBundle from: " << export_dir;
  const int64 start_seconds = Env::Default()->NowSeconds();
  TF_RETURN_IF_ERROR(
      GetMetaGraphDefFromExport(export_dir, &(bundle->meta_graph_def)));

  const auto& collection_def_map = bundle->meta_graph_def.collection_def();
  const auto graph_it = bundle->meta_graph_def.collection_def().find(kGraphKey);
  if (graph_it != collection_def_map.end()) {
    const CollectionDef& graph_collection_def = graph_it->second;
    // Use serving graph_def in MetaGraphDef collection_def.
    if (graph_collection_def.any_list().value_size() != 1) {
      return errors::FailedPrecondition(
          "Expected exactly one serving GraphDef in : ",
          bundle->meta_graph_def.DebugString());
    }
    const auto& any = graph_collection_def.any_list().value(0);
    if (!any.Is<GraphDef>()) {
      return errors::FailedPrecondition(
          "Expected Any type_url for: ",
          GraphDef::default_instance().descriptor()->full_name(), ". Got: ",
          string(any.type_url().data(), any.type_url().size()), ".");
    }
    GraphDef graph_def;
    if (!any.UnpackTo(&graph_def)) {
      return errors::FailedPrecondition("Failed to unpack: ",
                                        any.DebugString());
    }
    TF_RETURN_IF_ERROR(
        CreateSessionFromGraphDef(options, graph_def, &bundle->session));
  } else {
    // Fallback to use the graph_def in the MetaGraphDef.
    const GraphDef& graph_def = bundle->meta_graph_def.graph_def();
    TF_RETURN_IF_ERROR(
        CreateSessionFromGraphDef(options, graph_def, &bundle->session));
  }

  std::vector<AssetFile> asset_files;
  const auto assets_it = collection_def_map.find(kAssetsKey);
  if (assets_it != collection_def_map.end()) {
    const auto& any_assets = assets_it->second.any_list().value();
    for (const auto& any_asset : any_assets) {
      AssetFile asset_file;
      if (!any_asset.Is<AssetFile>()) {
        return errors::FailedPrecondition(
            "Expected asset Any type_url for: ",
            asset_file.descriptor()->full_name(), ". Got: ",
            string(any_asset.type_url().data(), any_asset.type_url().size()),
            ".");
      }
      if (!any_asset.UnpackTo(&asset_file)) {
        return errors::FailedPrecondition("Failed to unpack: ",
                                          any_asset.DebugString());
      }
      asset_files.push_back(asset_file);
    }
  }

  TF_RETURN_IF_ERROR(
      RunRestoreOp(run_options, export_dir, asset_files,
                   bundle->meta_graph_def.saver_def().restore_op_name(),
                   bundle->meta_graph_def.saver_def().filename_tensor_name(),
                   bundle->session.get()));

  const auto init_op_it = collection_def_map.find(kInitOpKey);
  if (init_op_it != collection_def_map.end()) {
    if (init_op_it->second.node_list().value_size() != 1) {
      return errors::FailedPrecondition(
          strings::StrCat("Expected exactly one serving init op in : ",
                          bundle->meta_graph_def.DebugString()));
    }
    TF_RETURN_IF_ERROR(RunInitOp(run_options, export_dir, asset_files,
                                 init_op_it->second.node_list().value(0),
                                 bundle->session.get()));
  }

  LOG(INFO) << "Done loading SessionBundle. Took "
            << Env::Default()->NowSeconds() - start_seconds << " seconds.";
  return Status::OK();
}

bool IsPossibleExportDirectory(const StringPiece directory) {
  const string meta_graph_def_path =
      io::JoinPath(directory, kMetaGraphDefFilename);
  return Env::Default()->FileExists(meta_graph_def_path);
}

}  // namespace serving
}  // namespace tensorflow
<commit_msg>Adds logging for RunOptions and retains copy of config when lambda for source adapter creation is defined.<commit_after>/* Copyright 2016 Google Inc. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/

#include "tensorflow/contrib/session_bundle/session_bundle.h"

#include <string>
#include <utility>
#include <vector>

#include "google/protobuf/any.pb.h"
#include "tensorflow/contrib/session_bundle/manifest.pb.h"
#include "tensorflow/core/framework/graph.pb.h"
#include "tensorflow/core/framework/tensor.h"
#include "tensorflow/core/framework/tensor_shape.h"
#include "tensorflow/core/framework/tensor_types.h"
#include "tensorflow/core/framework/types.pb.h"
#include "tensorflow/core/lib/core/errors.h"
#include "tensorflow/core/lib/core/status.h"
#include "tensorflow/core/lib/io/path.h"
#include "tensorflow/core/platform/env.h"
#include "tensorflow/core/platform/protobuf.h"
#include "tensorflow/core/platform/types.h"
#include "tensorflow/core/protobuf/meta_graph.pb.h"
#include "tensorflow/core/protobuf/saver.pb.h"
#include "tensorflow/core/public/session_options.h"

namespace tensorflow {
namespace serving {
namespace {

// Create a session using the given options and load the graph.
Status CreateSessionFromGraphDef(const SessionOptions& options,
                                 const GraphDef& graph,
                                 std::unique_ptr<Session>* session) {
  session->reset(NewSession(options));
  return (*session)->Create(graph);
}

Status GetMetaGraphDefFromExport(const StringPiece export_dir,
                                 MetaGraphDef* meta_graph_def) {
  const string meta_graph_def_path =
      io::JoinPath(export_dir, kMetaGraphDefFilename);
  return ReadBinaryProto(Env::Default(), meta_graph_def_path, meta_graph_def);
}

// Creates a string tensor.
Tensor CreateStringTensor(const string& value) {
  Tensor tensor(DT_STRING, TensorShape({}));
  tensor.scalar<string>()() = value;
  return tensor;
}

// Adds Assets related tensors (assets_dir and asset files) to the inputs.
void AddAssetsTensorsToInputs(const StringPiece export_dir,
                              const std::vector<AssetFile>& asset_files,
                              std::vector<std::pair<string, Tensor>>* inputs) {
  if (asset_files.empty()) {
    return;
  }
  for (auto& asset : asset_files) {
    Tensor assets_file_tensor = CreateStringTensor(io::JoinPath(
        io::JoinPath(export_dir, kAssetsDirectory), asset.filename()));
    inputs->push_back(
        {asset.tensor_binding().tensor_name(), assets_file_tensor});
    }
}

// Historically, model exporter(exporter.py) takes only saver with
// sharded=True, and therefore always exports checkpoint in pattern file names.
// In practice, instead of training from scratch and export directly, we
// usually want to restore from existing checkpoints and then export directly.
// To support such case, model exporter now supports reusing saver object
// restored from existing checkpoint, that may have sharded=False - it will
// then export checkpoint file in plain file name.
// This method is to support models exported by both types of saver object.
// The change is backward-compatible, therefore no changes are needed for
// existing model exports.
string GetVariablesFilename(const StringPiece export_dir) {
  const char kVariablesFilename[] = "export";
  const char kVariablesFilenamePattern[] = "export-\?\?\?\?\?-of-\?\?\?\?\?";
  if (Env::Default()->FileExists(
          io::JoinPath(export_dir, kVariablesFilename))) {
    return io::JoinPath(export_dir, kVariablesFilename);
  } else {
    return io::JoinPath(export_dir, kVariablesFilenamePattern);
  }
}

Status RunRestoreOp(const RunOptions& run_options, const StringPiece export_dir,
                    const std::vector<AssetFile>& asset_files,
                    const StringPiece restore_op_name,
                    const StringPiece variables_filename_const_op_name,
                    Session* session) {
  LOG(INFO) << "Running restore op for SessionBundle";
  Tensor variables_tensor =
      CreateStringTensor(GetVariablesFilename(export_dir));
  std::vector<std::pair<string, Tensor>> inputs = {
      {variables_filename_const_op_name.ToString(), variables_tensor}};
  AddAssetsTensorsToInputs(export_dir, asset_files, &inputs);
  RunMetadata run_metadata;
  return session->Run(run_options, inputs, {}, {restore_op_name.ToString()},
                      nullptr /* outputs */, &run_metadata);
}

Status RunInitOp(const RunOptions& run_options, const StringPiece export_dir,
                 const std::vector<AssetFile>& asset_files,
                 const StringPiece init_op_name, Session* session) {
  LOG(INFO) << "Running init op for SessionBundle";
  std::vector<std::pair<string, Tensor>> inputs;
  AddAssetsTensorsToInputs(export_dir, asset_files, &inputs);
  RunMetadata run_metadata;
  return session->Run(run_options, inputs, {}, {init_op_name.ToString()},
                      nullptr /* outputs */, &run_metadata);
}

}  // namespace

Status LoadSessionBundleFromPath(const SessionOptions& options,
                                 const StringPiece export_dir,
                                 SessionBundle* const bundle) {
  TF_RETURN_IF_ERROR(LoadSessionBundleFromPathUsingRunOptions(
      options, RunOptions(), export_dir, bundle));
  return Status::OK();
}

Status LoadSessionBundleFromPathUsingRunOptions(const SessionOptions& options,
                                                const RunOptions& run_options,
                                                const StringPiece export_dir,
                                                SessionBundle* const bundle) {
  LOG(INFO) << "Attempting to load a SessionBundle from: " << export_dir;
  LOG(INFO) << "Using RunOptions: " << run_options.DebugString();
  const int64 start_seconds = Env::Default()->NowSeconds();
  TF_RETURN_IF_ERROR(
      GetMetaGraphDefFromExport(export_dir, &(bundle->meta_graph_def)));

  const auto& collection_def_map = bundle->meta_graph_def.collection_def();
  const auto graph_it = bundle->meta_graph_def.collection_def().find(kGraphKey);
  if (graph_it != collection_def_map.end()) {
    const CollectionDef& graph_collection_def = graph_it->second;
    // Use serving graph_def in MetaGraphDef collection_def.
    if (graph_collection_def.any_list().value_size() != 1) {
      return errors::FailedPrecondition(
          "Expected exactly one serving GraphDef in : ",
          bundle->meta_graph_def.DebugString());
    }
    const auto& any = graph_collection_def.any_list().value(0);
    if (!any.Is<GraphDef>()) {
      return errors::FailedPrecondition(
          "Expected Any type_url for: ",
          GraphDef::default_instance().descriptor()->full_name(), ". Got: ",
          string(any.type_url().data(), any.type_url().size()), ".");
    }
    GraphDef graph_def;
    if (!any.UnpackTo(&graph_def)) {
      return errors::FailedPrecondition("Failed to unpack: ",
                                        any.DebugString());
    }
    TF_RETURN_IF_ERROR(
        CreateSessionFromGraphDef(options, graph_def, &bundle->session));
  } else {
    // Fallback to use the graph_def in the MetaGraphDef.
    const GraphDef& graph_def = bundle->meta_graph_def.graph_def();
    TF_RETURN_IF_ERROR(
        CreateSessionFromGraphDef(options, graph_def, &bundle->session));
  }

  std::vector<AssetFile> asset_files;
  const auto assets_it = collection_def_map.find(kAssetsKey);
  if (assets_it != collection_def_map.end()) {
    const auto& any_assets = assets_it->second.any_list().value();
    for (const auto& any_asset : any_assets) {
      AssetFile asset_file;
      if (!any_asset.Is<AssetFile>()) {
        return errors::FailedPrecondition(
            "Expected asset Any type_url for: ",
            asset_file.descriptor()->full_name(), ". Got: ",
            string(any_asset.type_url().data(), any_asset.type_url().size()),
            ".");
      }
      if (!any_asset.UnpackTo(&asset_file)) {
        return errors::FailedPrecondition("Failed to unpack: ",
                                          any_asset.DebugString());
      }
      asset_files.push_back(asset_file);
    }
  }

  TF_RETURN_IF_ERROR(
      RunRestoreOp(run_options, export_dir, asset_files,
                   bundle->meta_graph_def.saver_def().restore_op_name(),
                   bundle->meta_graph_def.saver_def().filename_tensor_name(),
                   bundle->session.get()));

  const auto init_op_it = collection_def_map.find(kInitOpKey);
  if (init_op_it != collection_def_map.end()) {
    if (init_op_it->second.node_list().value_size() != 1) {
      return errors::FailedPrecondition(
          strings::StrCat("Expected exactly one serving init op in : ",
                          bundle->meta_graph_def.DebugString()));
    }
    TF_RETURN_IF_ERROR(RunInitOp(run_options, export_dir, asset_files,
                                 init_op_it->second.node_list().value(0),
                                 bundle->session.get()));
  }

  LOG(INFO) << "Done loading SessionBundle. Took "
            << Env::Default()->NowSeconds() - start_seconds << " seconds.";
  return Status::OK();
}

bool IsPossibleExportDirectory(const StringPiece directory) {
  const string meta_graph_def_path =
      io::JoinPath(directory, kMetaGraphDefFilename);
  return Env::Default()->FileExists(meta_graph_def_path);
}

}  // namespace serving
}  // namespace tensorflow
<|endoftext|>


<commit_before>/* Copyright 2018 The TensorFlow Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/

#ifdef INTEL_MKL

#include "tensorflow/core/common_runtime/mkl_cpu_allocator.h"

namespace tensorflow {

}  // namespace tensorflow

#endif  // INTEL_MKL
<commit_msg>Restore definitions of static members in MklCpuAllocator.<commit_after>/* Copyright 2018 The TensorFlow Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/

#ifdef INTEL_MKL

#include "tensorflow/core/common_runtime/mkl_cpu_allocator.h"

namespace tensorflow {

constexpr const char* MklCPUAllocator::kMaxLimitStr;
constexpr const size_t MklCPUAllocator::kDefaultMaxLimit;

}  // namespace tensorflow

#endif  // INTEL_MKL
<|endoftext|>


<commit_before>/* Copyright 2015 The TensorFlow Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/

#include "tensorflow/core/common_runtime/threadpool_device.h"

#include "tensorflow/core/common_runtime/local_device.h"
#include "tensorflow/core/common_runtime/scoped_allocator.h"
#include "tensorflow/core/common_runtime/scoped_allocator_mgr.h"
#include "tensorflow/core/framework/allocator.h"
#include "tensorflow/core/framework/allocator_registry.h"
#include "tensorflow/core/framework/device_base.h"
#include "tensorflow/core/framework/op_kernel.h"
#include "tensorflow/core/framework/tensor.pb.h"
#include "tensorflow/core/framework/tensor_util.h"
#include "tensorflow/core/framework/types.h"
#include "tensorflow/core/graph/types.h"
#include "tensorflow/core/lib/hash/hash.h"
#include "tensorflow/core/platform/tracing.h"
#include "tensorflow/core/platform/types.h"
#include "tensorflow/core/public/session_options.h"
#include "tensorflow/core/util/util.h"

#ifdef INTEL_MKL
#ifdef _OPENMP
#include <omp.h>
#endif
#include "tensorflow/core/common_runtime/mkl_cpu_allocator.h"
#include "tensorflow/core/platform/cpu_info.h"
#endif

namespace tensorflow {

ThreadPoolDevice::ThreadPoolDevice(const SessionOptions& options,
                                   const string& name, Bytes memory_limit,
                                   const DeviceLocality& locality,
                                   Allocator* allocator)
    : LocalDevice(options, Device::BuildDeviceAttributes(
                               name, DEVICE_CPU, memory_limit, locality)),
      allocator_(allocator),
      scoped_allocator_mgr_(new ScopedAllocatorMgr(name)) {
#if !defined(ENABLE_MKLDNN_THREADPOOL) && defined(INTEL_MKL)
  // Early return when MKL is disabled
  if (DisableMKL()) return;
#ifdef _OPENMP
  const char* user_omp_threads = getenv("OMP_NUM_THREADS");
  if (user_omp_threads == nullptr) {
    // OMP_NUM_THREADS controls MKL's intra-op parallelization
    // Default to available physical cores
    const int mkl_intra_op = port::NumSchedulableCPUs();
    const int ht = port::NumHyperthreadsPerCore();
    std::call_once(omp_setting_flag, omp_set_num_threads,
		     (mkl_intra_op + ht - 1) / ht);
  }
#endif  // _OPENMP
#endif  // !defined(ENABLE_MKLDNN_THREADPOOL) && defined(INTEL_MKL)
}

ThreadPoolDevice::~ThreadPoolDevice() {}

Allocator* ThreadPoolDevice::GetAllocator(AllocatorAttributes attr) {
  return allocator_;
}

Allocator* ThreadPoolDevice::GetScopedAllocator(AllocatorAttributes attr,
                                                int64 step_id) {
  if (attr.scope_id > 0) {
    return scoped_allocator_mgr_->GetContainer(step_id)->GetInstance(
        attr.scope_id);
  }
  LOG(FATAL) << "Unexpected call to ThreadPoolDevice::GetScopedAllocator "
             << "attr.scope_id = " << attr.scope_id;
  return allocator_;
}

Status ThreadPoolDevice::MakeTensorFromProto(
    const TensorProto& tensor_proto, const AllocatorAttributes alloc_attrs,
    Tensor* tensor) {
  if (tensor_proto.dtype() > 0 && tensor_proto.dtype() <= DataType_MAX) {
    Tensor parsed(tensor_proto.dtype());
    if (parsed.FromProto(allocator_, tensor_proto)) {
      *tensor = std::move(parsed);
      return Status::OK();
    }
  }
  return errors::InvalidArgument("Cannot parse tensor from proto: ",
                                 tensor_proto.DebugString());
}

void ThreadPoolDevice::CopyTensorInSameDevice(
    const Tensor* input_tensor, Tensor* output_tensor,
    const DeviceContext* device_context, StatusCallback done) {
  if (input_tensor->NumElements() != output_tensor->NumElements()) {
    done(errors::Internal(
        "CPU->CPU copy shape mismatch: input=", input_tensor->shape(),
        ", output=", output_tensor->shape()));
    return;
  }
  tensor::DeepCopy(*input_tensor, output_tensor);
  done(Status::OK());
}

#ifdef INTEL_MKL
namespace {
class MklCPUAllocatorFactory : public AllocatorFactory {
 public:
  bool NumaEnabled() override { return false; }

  Allocator* CreateAllocator() override { return new MklCPUAllocator; }

  // Note: Ignores numa_node, for now.
  virtual SubAllocator* CreateSubAllocator(int numa_node) {
    return new MklSubAllocator;
  }
};

#ifdef ENABLE_MKL
REGISTER_MEM_ALLOCATOR("MklCPUAllocator", (DisableMKL() ? 50 : 200),
                       MklCPUAllocatorFactory);
#endif  // ENABLE_MKL

}  // namespace
#endif  // INTEL_MKL

}  // namespace tensorflow
<commit_msg>Apply code format<commit_after>/* Copyright 2015 The TensorFlow Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/

#include "tensorflow/core/common_runtime/threadpool_device.h"

#include "tensorflow/core/common_runtime/local_device.h"
#include "tensorflow/core/common_runtime/scoped_allocator.h"
#include "tensorflow/core/common_runtime/scoped_allocator_mgr.h"
#include "tensorflow/core/framework/allocator.h"
#include "tensorflow/core/framework/allocator_registry.h"
#include "tensorflow/core/framework/device_base.h"
#include "tensorflow/core/framework/op_kernel.h"
#include "tensorflow/core/framework/tensor.pb.h"
#include "tensorflow/core/framework/tensor_util.h"
#include "tensorflow/core/framework/types.h"
#include "tensorflow/core/graph/types.h"
#include "tensorflow/core/lib/hash/hash.h"
#include "tensorflow/core/platform/tracing.h"
#include "tensorflow/core/platform/types.h"
#include "tensorflow/core/public/session_options.h"
#include "tensorflow/core/util/util.h"

#ifdef INTEL_MKL
#ifdef _OPENMP
#include <omp.h>
#endif
#include "tensorflow/core/common_runtime/mkl_cpu_allocator.h"
#include "tensorflow/core/platform/cpu_info.h"
#endif

namespace tensorflow {

ThreadPoolDevice::ThreadPoolDevice(const SessionOptions& options,
                                   const string& name, Bytes memory_limit,
                                   const DeviceLocality& locality,
                                   Allocator* allocator)
    : LocalDevice(options, Device::BuildDeviceAttributes(
                               name, DEVICE_CPU, memory_limit, locality)),
      allocator_(allocator),
      scoped_allocator_mgr_(new ScopedAllocatorMgr(name)) {
#if !defined(ENABLE_MKLDNN_THREADPOOL) && defined(INTEL_MKL)
  // Early return when MKL is disabled
  if (DisableMKL()) return;
#ifdef _OPENMP
  const char* user_omp_threads = getenv("OMP_NUM_THREADS");
  if (user_omp_threads == nullptr) {
    // OMP_NUM_THREADS controls MKL's intra-op parallelization
    // Default to available physical cores
    const int mkl_intra_op = port::NumSchedulableCPUs();
    const int ht = port::NumHyperthreadsPerCore();
    std::call_once(omp_setting_flag, omp_set_num_threads,
                   (mkl_intra_op + ht - 1) / ht);
  }
#endif  // _OPENMP
#endif  // !defined(ENABLE_MKLDNN_THREADPOOL) && defined(INTEL_MKL)
}

ThreadPoolDevice::~ThreadPoolDevice() {}

Allocator* ThreadPoolDevice::GetAllocator(AllocatorAttributes attr) {
  return allocator_;
}

Allocator* ThreadPoolDevice::GetScopedAllocator(AllocatorAttributes attr,
                                                int64 step_id) {
  if (attr.scope_id > 0) {
    return scoped_allocator_mgr_->GetContainer(step_id)->GetInstance(
        attr.scope_id);
  }
  LOG(FATAL) << "Unexpected call to ThreadPoolDevice::GetScopedAllocator "
             << "attr.scope_id = " << attr.scope_id;
  return allocator_;
}

Status ThreadPoolDevice::MakeTensorFromProto(
    const TensorProto& tensor_proto, const AllocatorAttributes alloc_attrs,
    Tensor* tensor) {
  if (tensor_proto.dtype() > 0 && tensor_proto.dtype() <= DataType_MAX) {
    Tensor parsed(tensor_proto.dtype());
    if (parsed.FromProto(allocator_, tensor_proto)) {
      *tensor = std::move(parsed);
      return Status::OK();
    }
  }
  return errors::InvalidArgument("Cannot parse tensor from proto: ",
                                 tensor_proto.DebugString());
}

void ThreadPoolDevice::CopyTensorInSameDevice(
    const Tensor* input_tensor, Tensor* output_tensor,
    const DeviceContext* device_context, StatusCallback done) {
  if (input_tensor->NumElements() != output_tensor->NumElements()) {
    done(errors::Internal(
        "CPU->CPU copy shape mismatch: input=", input_tensor->shape(),
        ", output=", output_tensor->shape()));
    return;
  }
  tensor::DeepCopy(*input_tensor, output_tensor);
  done(Status::OK());
}

#ifdef INTEL_MKL
namespace {
class MklCPUAllocatorFactory : public AllocatorFactory {
 public:
  bool NumaEnabled() override { return false; }

  Allocator* CreateAllocator() override { return new MklCPUAllocator; }

  // Note: Ignores numa_node, for now.
  virtual SubAllocator* CreateSubAllocator(int numa_node) {
    return new MklSubAllocator;
  }
};

#ifdef ENABLE_MKL
REGISTER_MEM_ALLOCATOR("MklCPUAllocator", (DisableMKL() ? 50 : 200),
                       MklCPUAllocatorFactory);
#endif  // ENABLE_MKL

}  // namespace
#endif  // INTEL_MKL

}  // namespace tensorflow
<|endoftext|>


<commit_before>/*
 *  caosVM_core.cpp
 *  openc2e
 *
 *  Created by Alyssa Milburn on Tue May 25 2004.
 *  Copyright (c) 2004 Alyssa Milburn. All rights reserved.
 *
 *  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 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.
 *
 */

#include "caosVM.h"
#include <iostream>

using std::cout;
using std::cerr;

/**
 OUTS (command) val (string)
*/
void caosVM::c_OUTS() {
	VM_VERIFY_SIZE(1)
	VM_PARAM_STRING(val)

	cout << val;
}

/**
 OUTV (command) val (decimal)
*/
void caosVM::c_OUTV() {
  VM_VERIFY_SIZE(1)
	VM_PARAM_DECIMAL(val)

	if (val.hasFloat()) {
		cout << val.floatValue;
	} else {
		cout << val.intValue;
	}
}

/**
	GAME (variable) name (string)

	returns game variable with name given (unchecked)
*/
void caosVM::v_GAME() {
	// todo: ;-)
	static caosVar gamehack;
	result = gamehack;
	result.setVariable(&gamehack);
}

/**
 SCRP (command)
*/
void caosVM::c_SCRP() {
	cerr << "hit SCRP. shouldn't ever happen.\n";
}

/**
 RSCR (command)
*/
void caosVM::c_RSCR() {
	cerr << "hit RSCR. shouldn't ever happen.\n";
}

/**
 ENDM (command)
*/
void caosVM::c_ENDM() {
	c_STOP();
}
<commit_msg>add some VM checks<commit_after>/*
 *  caosVM_core.cpp
 *  openc2e
 *
 *  Created by Alyssa Milburn on Tue May 25 2004.
 *  Copyright (c) 2004 Alyssa Milburn. All rights reserved.
 *
 *  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 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.
 *
 */

#include "caosVM.h"
#include <iostream>

using std::cout;
using std::cerr;

/**
 OUTS (command) val (string)
*/
void caosVM::c_OUTS() {
	VM_VERIFY_SIZE(1)
	VM_PARAM_STRING(val)

	cout << val;
}

/**
 OUTV (command) val (decimal)
*/
void caosVM::c_OUTV() {
	VM_VERIFY_SIZE(1)
	VM_PARAM_DECIMAL(val)

	if (val.hasFloat()) {
		cout << val.floatValue;
	} else {
		cout << val.intValue;
	}
}

/**
	GAME (variable) name (string)

	returns game variable with name given (unchecked)
*/
void caosVM::v_GAME() {
	VM_VERIFY_SIZE(1)
	VM_PARAM_STRING(name)
	// todo: ;-)
	static caosVar gamehack;
	result = gamehack;
	result.setVariable(&gamehack);
}

/**
 SCRP (command)
*/
void caosVM::c_SCRP() {
	VM_VERIFY_SIZE(0)
	cerr << "hit SCRP. shouldn't ever happen.\n";
}

/**
 RSCR (command)
*/
void caosVM::c_RSCR() {
	VM_VERIFY_SIZE(0)
	cerr << "hit RSCR. shouldn't ever happen.\n";
}

/**
 ENDM (command)
*/
void caosVM::c_ENDM() {
	VM_VERIFY_SIZE(0)
	c_STOP();
}
<|endoftext|>


<commit_before>/*
 *  caosVM_flow.cpp
 *  openc2e
 *
 *  Created by Alyssa Milburn on Sun May 30 2004.
 *  Copyright (c) 2004 Alyssa Milburn. All rights reserved.
 *
 *  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 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.
 *
 */

#include "caosVM.h"
#include <iostream>
#include "openc2e.h"
#include "World.h" // enum
#include <cmath>   // sqrt
#include <sstream>

/**
 DOIF (command) condition (condition)
 %pragma parser new DoifParser()
 %status maybe

 Part of a DOIF/ELIF/ELSE/ENDI block. Jumps to the next part of the block if condition is false,
 otherwise continues executing the script.
*/

/**
 ELIF (command) condition (condition)
 %pragma parser new DoifParser()
 %status maybe

 Part of a DOIF/ELIF/ELSE/ENDI block. If none of the previous DOIF/ELIF conditions have been true, and condition evaluates to true, then the code in the ELIF block is executed.
 If found outside a DOIF block, it is equivalent to a DOIF. If you take advantage of this behavior, fuzzie is of the opinion that you should be shot.
*/

/**
 ELSE (command)
 %pragma noparse
 %status maybe

 Part of a DOIF/ELIF/ELSE/ENDI block. If ELSE is present, it is jumped to when none of the previous DOIF/ELIF conditions are true.
*/

/**
 ENDI (command)
 %pragma noparse
 %status maybe

 The end of a DOIF/ELIF/ELSE/ENDI block.
*/

/**
 REPS (command) reps (integer)
 %pragma parser new parseREPS()
 %status maybe

 The start of a REPS...REPE loop. The body of the loop will be executed (reps) times.
*/

/**
 REPE (command)
 %pragma noparse
 %status maybe

 The end of a REPS...REPE loop.
*/

/**
 LOOP (command)
 %pragma parser new parseLOOP()
 %status maybe

 The start of a LOOP...EVER or LOOP...UNTL loop.
*/

/**
 EVER (command)
 %pragma noparse
 %status maybe

 Jumps back to the matching LOOP, no matter what.
*/

/**
 UNTL (command) condition (condition)
 %pragma noparse
 %status maybe

 Jumps back to the matching LOOP unless the condition evaluates to true.
*/

/**
 GSUB (command) label (label)
 %pragma parser new parseGSUB()
 %pragma retc -1
 %status maybe

 Jumps to a subroutine defined by SUBR with label (label).
*/

/**
 SUBR (command) label (label)
 %pragma parser new parseSUBR()
 %status maybe

 Defines the start of a subroute to be called with GSUB, with label (label).
 If the command is encountered during execution, it acts like a STOP.
*/

/**
 RETN (command)
 %pragma retc -1
 %status maybe

 Returns from a subroutine called with GSUB.
*/
void caosVM::c_RETN() {
	if (callStack.empty())
		throw creaturesException("RETN with an empty callstack");
	nip = callStack.back().nip;
	valueStack = callStack.back().valueStack;
	callStack.pop_back();
}

/**
 NEXT (command)
 %pragma noparse
 %status maybe

 The end of an ENUM...NEXT loop.
*/

/**
 ENUM (command) family (integer) genus (integer) species (integer)
 %status maybe
 %pragma parserclass ENUMhelper
 %pragma retc -1

 Loops through all agents with the given classifier.  0 on any field is a
 wildcard. The loop body is terminated by a NEXT.
*/
void caosVM::c_ENUM() {
	VM_VERIFY_SIZE(3)
	VM_PARAM_INTEGER(species) caos_assert(species >= 0); caos_assert(species <= 65535);
	VM_PARAM_INTEGER(genus) caos_assert(genus >= 0); caos_assert(genus <= 255);
	VM_PARAM_INTEGER(family) caos_assert(family >= 0); caos_assert(family <= 255);

	caosVar nullv; nullv.reset();
	valueStack.push_back(nullv);

	for (std::list<boost::shared_ptr<Agent> >::iterator i
			= world.agents.begin(); i != world.agents.end(); i++) {
		boost::shared_ptr<Agent> a = (*i);
		if (!a) continue;
		if (species && species != a->species) continue;
		if (genus && genus != a->genus) continue;
		if (family && family != a->family) continue;

		caosVar v; v.setAgent(a);
		valueStack.push_back(v);
	}
}

/**
 ESEE (command) family (integer) genus (integer) species (integer)
 %status maybe
 %pragma parserclass ENUMhelper
 %pragma retc -1

 Simular to ENUM, but iterates through agents visible to OWNR.  An agent can be seen if it is within the
 range set by RNGE, and is visible (this includes the PERM value of walls that lie between them,
 and, if the agent is a Creature, it not having the 'invisible' attribute).
*/
void caosVM::c_ESEE() {
	VM_VERIFY_SIZE(3)
	VM_PARAM_INTEGER(species) caos_assert(species >= 0); caos_assert(species <= 65535);
	VM_PARAM_INTEGER(genus) caos_assert(genus >= 0); caos_assert(genus <= 255);
	VM_PARAM_INTEGER(family) caos_assert(family >= 0); caos_assert(family <= 255);

	caos_assert(owner);

	caosVar nullv; nullv.reset();
	valueStack.push_back(nullv);

	for (std::list<boost::shared_ptr<Agent> >::iterator i
			= world.agents.begin(); i != world.agents.end(); i++) {
		boost::shared_ptr<Agent> a = (*i);
		if (!a) continue;
		if (species && species != a->species) continue;
		if (genus && genus != a->genus) continue;
		if (family && family != a->family) continue;

		// XXX: measure from center?
		double deltax = (*i)->x - owner->x;
		double deltay = (*i)->y - owner->y;
		deltax *= deltax;
		deltay *= deltay;

		double distance = sqrt(deltax + deltay);
		if (distance > owner->range) continue;

		caosVar v; v.setAgent(a);
		valueStack.push_back(v);
	}
}

/**
 ETCH (command) family (integer) genus (integer) species (integer)
 %pragma parserclass ENUMhelper
 %pragma retc -1
 %status maybe

 Similar to ENUM, but iterates through the agents OWNR is touching.
*/
void caosVM::c_ETCH() {
	VM_VERIFY_SIZE(3)
	VM_PARAM_INTEGER(species) caos_assert(species >= 0); caos_assert(species <= 65535);
	VM_PARAM_INTEGER(genus) caos_assert(genus >= 0); caos_assert(genus <= 255);
	VM_PARAM_INTEGER(family) caos_assert(family >= 0); caos_assert(family <= 255);

	caos_assert(owner);

	caosVar nullv; nullv.reset();
	valueStack.push_back(nullv);

	for (std::list<boost::shared_ptr<Agent> >::iterator i
			= world.agents.begin(); i != world.agents.end(); i++) {
		boost::shared_ptr<Agent> a = (*i);
		if (!a) continue;
		if (species && species != a->species) continue;
		if (genus && genus != a->genus) continue;
		if (family && family != a->family) continue;

		if (a->x < owner->x) {
			if ((a->x + a->getWidth()) < owner->x) continue;
		} else {
			if ((owner->x + owner->getWidth()) < a->x) continue;
		}

		if (a->y < owner->y) {
			if ((a->y + a->getHeight()) < owner->y) continue;
		} else {
			if ((owner->y + owner->getHeight()) < a->y) continue;
		}

		caosVar v; v.setAgent(a);
		valueStack.push_back(v);
	}
}

/**
 EPAS (command) family (integer) genus (integer) species (integer)
 %pragma parserclass ENUMhelper
 %pragma retc -1
 %status stub

 Similar to ENUM, but iterates through the OWNR vehicle's passengers.
*/
void caosVM::c_EPAS() {
	VM_VERIFY_SIZE(3)
	VM_PARAM_INTEGER(species) caos_assert(species >= 0); caos_assert(species <= 65535);
	VM_PARAM_INTEGER(genus) caos_assert(genus >= 0); caos_assert(genus <= 255);
	VM_PARAM_INTEGER(family) caos_assert(family >= 0); caos_assert(family <= 255);

	// TODO: should probably implement this (ESEE)

	caosVar nullv; nullv.reset();
	valueStack.push_back(nullv);
}

/**
 ECON (command) agent (agent)
 %pragma parserclass ENUMhelper
 %pragma retc -1
 %status stub

 Loops through all the agents in the connective system containing the given agent.
*/
void caosVM::c_ECON() {
	VM_VERIFY_SIZE(3)
	VM_PARAM_VALIDAGENT(agent)

	// TODO: should probably implement this (ESEE)

	caosVar nullv; nullv.reset();
	valueStack.push_back(nullv);
}

/**
 CALL (command) script_no (integer) p1 (any) p2 (any)
 %status maybe

 Calls script_no on OWNR, then waits for it to return. The invoked script
 will inherit the caller's INST setting, but any changes it makes to it will
 be reversed once it returns - so eg if you call a script when in INST mode,
 it calls OVEr and returns, you'll still be in INST.

 Script variables (VAxx) will not be preserved - you'll have to use OVxx
 for any parameters.
 */
void caosVM::c_CALL() {
	VM_PARAM_VALUE(p2)
	VM_PARAM_VALUE(p1)
	VM_PARAM_INTEGER(script_no)

	caos_assert(owner);
	caos_assert(script_no >= 0 && script_no < 65536);

	shared_ptr<script> s = owner->findScript(script_no);
	if (!s) return;
	caosVM *newvm = world.getVM(owner);

	assert(newvm->fireScript(s, false));
	newvm->inst = inst;
	newvm->_p_[0] = p1;
	newvm->_p_[1] = p2;
	owner->pushVM(newvm);
	stop_loop = true;
}

/**
 CAOS (string) inline (integer) state_trans (integer) p1 (anything) p2 (anything) commands (string) throws (integer) catches (integer) report (variable)
 %status maybe

 Runs commands as caos code immediately. If inline, copy _IT_ VAxx TARG OWNR, etc. If state_trans, copy FROM and
 OWNR.  If an error occurs, it catches it and stuffs it in the report. (XXX: non-conforming)
*/

// XXX: exception catching is very broken right now

void caosVM::v_CAOS() {
	// XXX: capture output
	VM_PARAM_VARIABLE(report)
	VM_PARAM_INTEGER(catches)
	VM_PARAM_INTEGER(throws)
	VM_PARAM_STRING(commands)
	VM_PARAM_VALUE(p2)
	VM_PARAM_VALUE(p1)
	VM_PARAM_INTEGER(state_trans)
	VM_PARAM_INTEGER(inl)

	caosVM *sub = world.getVM(NULL);
	if (inl) {
		for (int i = 0; i < 100; i++)
			sub->var[i] = var[i];
		sub->targ = targ;
		sub->_it_ = _it_;
		sub->part = part;
		sub->owner = owner;
		// sub->from = from;
	}
	if (state_trans) {
		sub->owner = owner;
		// sub->from = from;
	}
	sub->_p_[0] = p1;
	sub->_p_[1] = p2;
	try {
		std::istringstream iss(commands);
		std::ostringstream oss;
		caosScript s("c3", "CAOS command"); // XXX: variant
		s.parse(iss);
		s.installScripts();
		sub->outputstream = &oss;
		sub->runEntirely(s.installer);
		sub->outputstream = &std::cout;
		result.setString(oss.str());
	} catch (std::exception &e) {
		sub->outputstream = &std::cout;
		if (!throws || catches) {
			report->setString(e.what());
			result.setString("###");
		} else {
			world.freeVM(sub);
			throw;
		}
	}
	world.freeVM(sub);
}

/* vim: set noet: */
<commit_msg>Inherit DBG: TRACE over CALL<commit_after>/*
 *  caosVM_flow.cpp
 *  openc2e
 *
 *  Created by Alyssa Milburn on Sun May 30 2004.
 *  Copyright (c) 2004 Alyssa Milburn. All rights reserved.
 *
 *  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 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.
 *
 */

#include "caosVM.h"
#include <iostream>
#include "openc2e.h"
#include "World.h" // enum
#include <cmath>   // sqrt
#include <sstream>

/**
 DOIF (command) condition (condition)
 %pragma parser new DoifParser()
 %status maybe

 Part of a DOIF/ELIF/ELSE/ENDI block. Jumps to the next part of the block if condition is false,
 otherwise continues executing the script.
*/

/**
 ELIF (command) condition (condition)
 %pragma parser new DoifParser()
 %status maybe

 Part of a DOIF/ELIF/ELSE/ENDI block. If none of the previous DOIF/ELIF conditions have been true, and condition evaluates to true, then the code in the ELIF block is executed.
 If found outside a DOIF block, it is equivalent to a DOIF. If you take advantage of this behavior, fuzzie is of the opinion that you should be shot.
*/

/**
 ELSE (command)
 %pragma noparse
 %status maybe

 Part of a DOIF/ELIF/ELSE/ENDI block. If ELSE is present, it is jumped to when none of the previous DOIF/ELIF conditions are true.
*/

/**
 ENDI (command)
 %pragma noparse
 %status maybe

 The end of a DOIF/ELIF/ELSE/ENDI block.
*/

/**
 REPS (command) reps (integer)
 %pragma parser new parseREPS()
 %status maybe

 The start of a REPS...REPE loop. The body of the loop will be executed (reps) times.
*/

/**
 REPE (command)
 %pragma noparse
 %status maybe

 The end of a REPS...REPE loop.
*/

/**
 LOOP (command)
 %pragma parser new parseLOOP()
 %status maybe

 The start of a LOOP...EVER or LOOP...UNTL loop.
*/

/**
 EVER (command)
 %pragma noparse
 %status maybe

 Jumps back to the matching LOOP, no matter what.
*/

/**
 UNTL (command) condition (condition)
 %pragma noparse
 %status maybe

 Jumps back to the matching LOOP unless the condition evaluates to true.
*/

/**
 GSUB (command) label (label)
 %pragma parser new parseGSUB()
 %pragma retc -1
 %status maybe

 Jumps to a subroutine defined by SUBR with label (label).
*/

/**
 SUBR (command) label (label)
 %pragma parser new parseSUBR()
 %status maybe

 Defines the start of a subroute to be called with GSUB, with label (label).
 If the command is encountered during execution, it acts like a STOP.
*/

/**
 RETN (command)
 %pragma retc -1
 %status maybe

 Returns from a subroutine called with GSUB.
*/
void caosVM::c_RETN() {
	if (callStack.empty())
		throw creaturesException("RETN with an empty callstack");
	nip = callStack.back().nip;
	valueStack = callStack.back().valueStack;
	callStack.pop_back();
}

/**
 NEXT (command)
 %pragma noparse
 %status maybe

 The end of an ENUM...NEXT loop.
*/

/**
 ENUM (command) family (integer) genus (integer) species (integer)
 %status maybe
 %pragma parserclass ENUMhelper
 %pragma retc -1

 Loops through all agents with the given classifier.  0 on any field is a
 wildcard. The loop body is terminated by a NEXT.
*/
void caosVM::c_ENUM() {
	VM_VERIFY_SIZE(3)
	VM_PARAM_INTEGER(species) caos_assert(species >= 0); caos_assert(species <= 65535);
	VM_PARAM_INTEGER(genus) caos_assert(genus >= 0); caos_assert(genus <= 255);
	VM_PARAM_INTEGER(family) caos_assert(family >= 0); caos_assert(family <= 255);

	caosVar nullv; nullv.reset();
	valueStack.push_back(nullv);

	for (std::list<boost::shared_ptr<Agent> >::iterator i
			= world.agents.begin(); i != world.agents.end(); i++) {
		boost::shared_ptr<Agent> a = (*i);
		if (!a) continue;
		if (species && species != a->species) continue;
		if (genus && genus != a->genus) continue;
		if (family && family != a->family) continue;

		caosVar v; v.setAgent(a);
		valueStack.push_back(v);
	}
}

/**
 ESEE (command) family (integer) genus (integer) species (integer)
 %status maybe
 %pragma parserclass ENUMhelper
 %pragma retc -1

 Simular to ENUM, but iterates through agents visible to OWNR.  An agent can be seen if it is within the
 range set by RNGE, and is visible (this includes the PERM value of walls that lie between them,
 and, if the agent is a Creature, it not having the 'invisible' attribute).
*/
void caosVM::c_ESEE() {
	VM_VERIFY_SIZE(3)
	VM_PARAM_INTEGER(species) caos_assert(species >= 0); caos_assert(species <= 65535);
	VM_PARAM_INTEGER(genus) caos_assert(genus >= 0); caos_assert(genus <= 255);
	VM_PARAM_INTEGER(family) caos_assert(family >= 0); caos_assert(family <= 255);

	caos_assert(owner);

	caosVar nullv; nullv.reset();
	valueStack.push_back(nullv);

	for (std::list<boost::shared_ptr<Agent> >::iterator i
			= world.agents.begin(); i != world.agents.end(); i++) {
		boost::shared_ptr<Agent> a = (*i);
		if (!a) continue;
		if (species && species != a->species) continue;
		if (genus && genus != a->genus) continue;
		if (family && family != a->family) continue;

		// XXX: measure from center?
		double deltax = (*i)->x - owner->x;
		double deltay = (*i)->y - owner->y;
		deltax *= deltax;
		deltay *= deltay;

		double distance = sqrt(deltax + deltay);
		if (distance > owner->range) continue;

		caosVar v; v.setAgent(a);
		valueStack.push_back(v);
	}
}

/**
 ETCH (command) family (integer) genus (integer) species (integer)
 %pragma parserclass ENUMhelper
 %pragma retc -1
 %status maybe

 Similar to ENUM, but iterates through the agents OWNR is touching.
*/
void caosVM::c_ETCH() {
	VM_VERIFY_SIZE(3)
	VM_PARAM_INTEGER(species) caos_assert(species >= 0); caos_assert(species <= 65535);
	VM_PARAM_INTEGER(genus) caos_assert(genus >= 0); caos_assert(genus <= 255);
	VM_PARAM_INTEGER(family) caos_assert(family >= 0); caos_assert(family <= 255);

	caos_assert(owner);

	caosVar nullv; nullv.reset();
	valueStack.push_back(nullv);

	for (std::list<boost::shared_ptr<Agent> >::iterator i
			= world.agents.begin(); i != world.agents.end(); i++) {
		boost::shared_ptr<Agent> a = (*i);
		if (!a) continue;
		if (species && species != a->species) continue;
		if (genus && genus != a->genus) continue;
		if (family && family != a->family) continue;

		if (a->x < owner->x) {
			if ((a->x + a->getWidth()) < owner->x) continue;
		} else {
			if ((owner->x + owner->getWidth()) < a->x) continue;
		}

		if (a->y < owner->y) {
			if ((a->y + a->getHeight()) < owner->y) continue;
		} else {
			if ((owner->y + owner->getHeight()) < a->y) continue;
		}

		caosVar v; v.setAgent(a);
		valueStack.push_back(v);
	}
}

/**
 EPAS (command) family (integer) genus (integer) species (integer)
 %pragma parserclass ENUMhelper
 %pragma retc -1
 %status stub

 Similar to ENUM, but iterates through the OWNR vehicle's passengers.
*/
void caosVM::c_EPAS() {
	VM_VERIFY_SIZE(3)
	VM_PARAM_INTEGER(species) caos_assert(species >= 0); caos_assert(species <= 65535);
	VM_PARAM_INTEGER(genus) caos_assert(genus >= 0); caos_assert(genus <= 255);
	VM_PARAM_INTEGER(family) caos_assert(family >= 0); caos_assert(family <= 255);

	// TODO: should probably implement this (ESEE)

	caosVar nullv; nullv.reset();
	valueStack.push_back(nullv);
}

/**
 ECON (command) agent (agent)
 %pragma parserclass ENUMhelper
 %pragma retc -1
 %status stub

 Loops through all the agents in the connective system containing the given agent.
*/
void caosVM::c_ECON() {
	VM_VERIFY_SIZE(3)
	VM_PARAM_VALIDAGENT(agent)

	// TODO: should probably implement this (ESEE)

	caosVar nullv; nullv.reset();
	valueStack.push_back(nullv);
}

/**
 CALL (command) script_no (integer) p1 (any) p2 (any)
 %status maybe

 Calls script_no on OWNR, then waits for it to return. The invoked script
 will inherit the caller's INST setting, but any changes it makes to it will
 be reversed once it returns - so eg if you call a script when in INST mode,
 it calls OVEr and returns, you'll still be in INST.

 Script variables (VAxx) will not be preserved - you'll have to use OVxx
 for any parameters.
 */
void caosVM::c_CALL() {
	VM_PARAM_VALUE(p2)
	VM_PARAM_VALUE(p1)
	VM_PARAM_INTEGER(script_no)

	caos_assert(owner);
	caos_assert(script_no >= 0 && script_no < 65536);

	shared_ptr<script> s = owner->findScript(script_no);
	if (!s) return;
	caosVM *newvm = world.getVM(owner);
	newvm->trace = trace;

	assert(newvm->fireScript(s, false));
	newvm->inst = inst;
	newvm->_p_[0] = p1;
	newvm->_p_[1] = p2;
	owner->pushVM(newvm);
	stop_loop = true;
}

/**
 CAOS (string) inline (integer) state_trans (integer) p1 (anything) p2 (anything) commands (string) throws (integer) catches (integer) report (variable)
 %status maybe

 Runs commands as caos code immediately. If inline, copy _IT_ VAxx TARG OWNR, etc. If state_trans, copy FROM and
 OWNR.  If an error occurs, it catches it and stuffs it in the report. (XXX: non-conforming)
*/

// XXX: exception catching is very broken right now

void caosVM::v_CAOS() {
	// XXX: capture output
	VM_PARAM_VARIABLE(report)
	VM_PARAM_INTEGER(catches)
	VM_PARAM_INTEGER(throws)
	VM_PARAM_STRING(commands)
	VM_PARAM_VALUE(p2)
	VM_PARAM_VALUE(p1)
	VM_PARAM_INTEGER(state_trans)
	VM_PARAM_INTEGER(inl)

	caosVM *sub = world.getVM(NULL);
	if (inl) {
		for (int i = 0; i < 100; i++)
			sub->var[i] = var[i];
		sub->targ = targ;
		sub->_it_ = _it_;
		sub->part = part;
		sub->owner = owner;
		// sub->from = from;
	}
	if (state_trans) {
		sub->owner = owner;
		// sub->from = from;
	}
	sub->_p_[0] = p1;
	sub->_p_[1] = p2;
	try {
		std::istringstream iss(commands);
		std::ostringstream oss;
		caosScript s("c3", "CAOS command"); // XXX: variant
		s.parse(iss);
		s.installScripts();
		sub->outputstream = &oss;
		sub->runEntirely(s.installer);
		sub->outputstream = &std::cout;
		result.setString(oss.str());
	} catch (std::exception &e) {
		sub->outputstream = &std::cout;
		if (!throws || catches) {
			report->setString(e.what());
			result.setString("###");
		} else {
			world.freeVM(sub);
			throw;
		}
	}
	world.freeVM(sub);
}

/* vim: set noet: */
<|endoftext|>


<commit_before>#pragma once

// https://infektor.net/posts/2017-03-31-range-based-enumerate.html

#include <iterator>
#include <utility>

// ----------------------------------------------------------------------

namespace _enumerate_internal
{
    template <class Iterator> struct enumerate_iterator
    {
        using iterator = Iterator;
        using index_type = typename std::iterator_traits<iterator>::difference_type;
        using reference = typename std::iterator_traits<iterator>::reference;

        enumerate_iterator(index_type aIndex, iterator aIterator) : index(aIndex), iter(aIterator) {}
        enumerate_iterator& operator++() { ++index; ++iter; return *this; }
        bool operator!=(const enumerate_iterator &other) const { return iter != other.iter; }
        std::pair<index_type&, reference> operator*() { return {index, *iter}; }

     private:
        index_type index;
        iterator iter;
    };

      // ----------------------------------------------------------------------

    template <class Iterator> struct enumerate_range
    {
        using index_type = typename std::iterator_traits<Iterator>::difference_type;
        using iterator = enumerate_iterator<Iterator>;

        enumerate_range(Iterator aFirst, Iterator aLast, index_type aInitial) : first(aFirst), last(aLast), initial(aInitial) {}
        iterator begin() const { return iterator(initial, first); }
        iterator end() const { return iterator(0, last); }

     private:
        Iterator first;
        Iterator last;
        index_type initial;
    };

} // namespace _enumerate_internal

// ----------------------------------------------------------------------

namespace acmacs
{
    template <typename Iterator> auto enumerate(Iterator first, Iterator last, typename std::iterator_traits<Iterator>::difference_type initial = 0)
    {
        return _enumerate_internal::enumerate_range<Iterator>(first, last, initial);
    }

    template <typename Container> auto enumerate(Container& content)
    {
        using iter_type = decltype(std::begin(content));
        return _enumerate_internal::enumerate_range<iter_type>(std::begin(content), std::end(content), 0);
    }

    template <typename Container> auto enumerate(const Container& content)
    {
        using iter_type = decltype(std::begin(content));
        return _enumerate_internal::enumerate_range<iter_type>(std::begin(content), std::end(content), 0);
    }
}

// ----------------------------------------------------------------------
/// Local Variables:
/// eval: (if (fboundp 'eu-rename-buffer) (eu-rename-buffer))
/// End:
<commit_msg>enumerate index is size_t<commit_after>#pragma once

// https://infektor.net/posts/2017-03-31-range-based-enumerate.html

#include <iterator>
#include <utility>

// ----------------------------------------------------------------------

namespace _enumerate_internal
{
    template <typename Iterator, typename index_type> struct enumerate_iterator
    {
        using iterator = Iterator;
          //using index_type = typename std::iterator_traits<iterator>::difference_type;
        using reference = typename std::iterator_traits<iterator>::reference;

        enumerate_iterator(index_type aIndex, iterator aIterator) : index(aIndex), iter(aIterator) {}
        enumerate_iterator& operator++() { ++index; ++iter; return *this; }
        bool operator!=(const enumerate_iterator &other) const { return iter != other.iter; }
        std::pair<index_type&, reference> operator*() { return {index, *iter}; }

     private:
        index_type index;
        iterator iter;
    };

      // ----------------------------------------------------------------------

    template <typename Iterator, typename index_type> struct enumerate_range
    {
        // using index_type = typename std::iterator_traits<Iterator>::difference_type;
        using iterator = enumerate_iterator<Iterator, index_type>;

        enumerate_range(Iterator aFirst, Iterator aLast, index_type aInitial) : first(aFirst), last(aLast), initial(aInitial) {}
        iterator begin() const { return iterator(initial, first); }
        iterator end() const { return iterator(0, last); }

     private:
        Iterator first;
        Iterator last;
        index_type initial;
    };

} // namespace _enumerate_internal

// ----------------------------------------------------------------------

namespace acmacs
{
    template <typename Iterator, typename index_type> auto enumerate(Iterator first, Iterator last, index_type initial = 0)
    {
        return _enumerate_internal::enumerate_range<Iterator, index_type>(first, last, initial);
    }

    template <typename Container> auto enumerate(Container& content)
    {
        using iter_type = decltype(std::begin(content));
        return _enumerate_internal::enumerate_range<iter_type, size_t>(std::begin(content), std::end(content), 0U);
    }

    template <typename Container> auto enumerate(const Container& content)
    {
        using iter_type = decltype(std::begin(content));
        return _enumerate_internal::enumerate_range<iter_type, size_t>(std::begin(content), std::end(content), 0U);
    }
}

// ----------------------------------------------------------------------
/// Local Variables:
/// eval: (if (fboundp 'eu-rename-buffer) (eu-rename-buffer))
/// End:
<|endoftext|>


<commit_before>#include "Sprite.h"

Sprite::Sprite() {

}

void
Sprite::draw() {

}

<commit_msg>Add destructor<commit_after>#include "Sprite.h"

Sprite::Sprite() {

}

void
Sprite::draw() {

}

Sprite::~Sprite(){

}

<|endoftext|>


<commit_before>// prints the numbers from ten down to zero.(use while)

#include <iostream>

int main()
{
    int val = 10;
    while (val >= 0)
        std::cout << val-- << std::endl;
    return 0;
}
<commit_msg>Update ex1_10.cpp<commit_after>// prints the numbers from ten down to zero.(use while)

#include <iostream>

int main()
{
    int i = 10;
    while (i >= 0)
        std::cout << i-- << " ";
    return 0;
}
<|endoftext|>