<commit_before>/*
Copyright libCellML Contributors

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 "libcellml/model.h"

#include <algorithm>
#include <fstream>
#include <map>
#include <numeric>
#include <sstream>
#include <stack>
#include <utility>
#include <vector>

#include "libcellml/component.h"
#include "libcellml/importsource.h"
#include "libcellml/parser.h"
#include "libcellml/units.h"
#include "libcellml/variable.h"

#include "anycellmlelement_p.h"
#include "component_p.h"
#include "componententity_p.h"
#include "internaltypes.h"
#include "issue_p.h"
#include "model_p.h"
#include "units_p.h"
#include "utilities.h"
#include "xmldoc.h"
#include "xmlutils.h"

namespace libcellml {

std::vector<UnitsPtr>::const_iterator Model::ModelImpl::findUnits(const std::string &name) const
{
    return std::find_if(mUnits.begin(), mUnits.end(),
                        [=](const UnitsPtr &u) -> bool { return u->name() == name; });
}

std::vector<UnitsPtr>::const_iterator Model::ModelImpl::findUnits(const UnitsPtr &units) const
{
    auto result = std::find(mUnits.begin(), mUnits.end(), units);
    if (result != mUnits.end()) {
        return result;
    }
    return std::find_if(mUnits.begin(), mUnits.end(),
                        [=](const UnitsPtr &u) -> bool { return u->equals(units); });
}

bool Model::ModelImpl::equalUnits(const ModelPtr &other) const
{
    std::vector<EntityPtr> entities;
    std::copy(mUnits.begin(), mUnits.end(), std::back_inserter(entities));
    return equalEntities(other, entities);
}

Model::ModelImpl *Model::pFunc()
{
    return reinterpret_cast<Model::ModelImpl *>(Entity::pFunc());
}

const Model::ModelImpl *Model::pFunc() const
{
    return reinterpret_cast<Model::ModelImpl const *>(Entity::pFunc());
}

Model::Model()
    : ComponentEntity(new Model::ModelImpl())
{
}

Model::Model(const std::string &name)
    : ComponentEntity(new Model::ModelImpl())
{
    setName(name);
}

Model::~Model()
{
    delete pFunc();
}
ModelPtr Model::create() noexcept
{
    return std::shared_ptr<Model> {new Model {}};
}

ModelPtr Model::create(const std::string &name) noexcept
{
    return std::shared_ptr<Model> {new Model {name}};
}

bool Model::doAddComponent(const ComponentPtr &component)
{
    auto thisModel = shared_from_this();
    if (component->hasParent() && (thisModel != component->parent())) {
        removeComponentFromEntity(component->parent(), component);
    }
    component->pFunc()->setParent(thisModel);

    return ComponentEntity::doAddComponent(component);
}

bool Model::addUnits(const UnitsPtr &units)
{
    if (units == nullptr) {
        return false;
    }

    // Prevent adding to multiple models: move units to this model.
    auto thisModel = shared_from_this();
    if (units->hasParent() && (units->parent() != thisModel)) {
        auto otherParent = std::dynamic_pointer_cast<Model>(units->parent());
        otherParent->removeUnits(units);
    }
    pFunc()->mUnits.push_back(units);
    units->pFunc()->setParent(thisModel);

    return true;
}

bool Model::removeUnits(size_t index)
{
    bool status = false;
    if (index < pFunc()->mUnits.size()) {
        auto result = pFunc()->mUnits.begin() + ptrdiff_t(index);
        (*result)->pFunc()->removeParent();
        pFunc()->mUnits.erase(result);
        status = true;
    }

    return status;
}

bool Model::removeUnits(const std::string &name)
{
    bool status = false;
    auto result = pFunc()->findUnits(name);
    if (result != pFunc()->mUnits.end()) {
        (*result)->pFunc()->removeParent();
        pFunc()->mUnits.erase(result);
        status = true;
    }

    return status;
}

bool Model::removeUnits(const UnitsPtr &units)
{
    bool status = false;
    auto result = pFunc()->findUnits(units);
    if (result != pFunc()->mUnits.end()) {
        units->pFunc()->removeParent();
        pFunc()->mUnits.erase(result);
        status = 1;
    }

    return status;
}

void Model::removeAllUnits()
{
    for (const auto &u : pFunc()->mUnits) {
        u->pFunc()->removeParent();
    }
    pFunc()->mUnits.clear();
}

bool Model::hasUnits(const std::string &name) const
{
    return pFunc()->findUnits(name) != pFunc()->mUnits.end();
}

bool Model::hasUnits(const UnitsPtr &units) const
{
    return pFunc()->findUnits(units) != pFunc()->mUnits.end();
}

UnitsPtr Model::units(size_t index) const
{
    UnitsPtr units = nullptr;
    if (index < pFunc()->mUnits.size()) {
        units = pFunc()->mUnits.at(index);
    }

    return units;
}

UnitsPtr Model::units(const std::string &name) const
{
    UnitsPtr units = nullptr;
    auto result = pFunc()->findUnits(name);
    if (result != pFunc()->mUnits.end()) {
        units = *result;
    }

    return units;
}

UnitsPtr Model::takeUnits(size_t index)
{
    UnitsPtr units = nullptr;
    if (index < pFunc()->mUnits.size()) {
        units = pFunc()->mUnits.at(index);
        removeUnits(index);
        units->pFunc()->removeParent();
    }

    return units;
}

UnitsPtr Model::takeUnits(const std::string &name)
{
    return takeUnits(size_t(pFunc()->findUnits(name) - pFunc()->mUnits.begin()));
}

bool Model::replaceUnits(size_t index, const UnitsPtr &units)
{
    bool status = false;
    if (removeUnits(index)) {
        pFunc()->mUnits.insert(pFunc()->mUnits.begin() + ptrdiff_t(index), units);
        units->pFunc()->setParent(shared_from_this());
        status = true;
    }

    return status;
}

bool Model::replaceUnits(const std::string &name, const UnitsPtr &units)
{
    return replaceUnits(size_t(pFunc()->findUnits(name) - pFunc()->mUnits.begin()), units);
}

bool Model::replaceUnits(const UnitsPtr &oldUnits, const UnitsPtr &newUnits)
{
    return replaceUnits(size_t(pFunc()->findUnits(oldUnits) - pFunc()->mUnits.begin()), newUnits);
}

size_t Model::unitsCount() const
{
    return pFunc()->mUnits.size();
}

bool Model::linkUnits()
{
    return traverseComponentEntityTreeLinkingUnits(shared_from_this());
}

bool traverseComponentTreeForUnlinkedUnits(const ComponentPtr &component)
{
    bool unlinkedUnits = areComponentVariableUnitsUnlinked(component);
    for (size_t index = 0; index < component->componentCount() && !unlinkedUnits; ++index) {
        auto c = component->component(index);
        unlinkedUnits = traverseComponentTreeForUnlinkedUnits(c);
    }
    return unlinkedUnits;
}

bool Model::hasUnlinkedUnits()
{
    bool unlinkedUnits = false;
    for (size_t index = 0; index < componentCount() && !unlinkedUnits; ++index) {
        auto c = component(index);
        unlinkedUnits = traverseComponentTreeForUnlinkedUnits(c);
    }
    return unlinkedUnits;
}

bool Model::hasUnresolvedImports() const
{
    bool unresolvedImports = false;
    for (size_t n = 0; n < unitsCount() && !unresolvedImports; ++n) {
        unresolvedImports = !units(n)->isResolved();
    }
    for (size_t n = 0; (n < componentCount()) && !unresolvedImports; ++n) {
        unresolvedImports = !component(n)->isResolved();
    }
    return unresolvedImports;
}

bool hasComponentImports(const ComponentEntityConstPtr &componentEntity)
{
    bool importsPresent = false;
    for (size_t n = 0; (n < componentEntity->componentCount()) && !importsPresent; ++n) {
        libcellml::ComponentPtr childComponent = componentEntity->component(n);
        importsPresent = childComponent->isImport();
        if (!importsPresent) {
            importsPresent = hasComponentImports(childComponent);
        }
    }
    return importsPresent;
}

bool Model::hasImports() const
{
    bool importsPresent = false;
    for (size_t n = 0; (n < unitsCount()) && !importsPresent; ++n) {
        libcellml::UnitsPtr units = Model::units(n);
        if (units->isImport()) {
            importsPresent = true;
        }
    }

    if (!importsPresent) {
        importsPresent = hasComponentImports(shared_from_this());
    }

    return importsPresent;
}

void fixComponentUnits(const ModelPtr &model, const ComponentPtr &component)
{
    for (size_t v = 0; v < component->variableCount(); ++v) {
        auto variable = component->variable(v);
        if (variable->units() != nullptr) {
            // Find the units in the model and switch out.
            auto units = model->units(variable->units()->name());
            if (units != nullptr) {
                variable->setUnits(units);
            }
        }
    }
    for (size_t c = 0; c < component->componentCount(); ++c) {
        fixComponentUnits(model, component->component(c));
    }
}

ModelPtr Model::clone() const
{
    auto m = create();

    m->setId(id());
    m->setName(name());

    m->setEncapsulationId(encapsulationId());

    for (size_t index = 0; index < pFunc()->mUnits.size(); ++index) {
        m->addUnits(units(index)->clone());
    }

    for (size_t index = 0; index < componentCount(); ++index) {
        m->addComponent(component(index)->clone());
    }

    for (size_t index = 0; index < m->componentCount(); ++index) {
        fixComponentUnits(m, m->component(index));
    }

    // Generate equivalence map starting from the models components.
    EquivalenceMap map;
    IndexStack indexStack;
    for (size_t index = 0; index < componentCount(); ++index) {
        indexStack.push_back(index);
        auto c = component(index);
        recordVariableEquivalences(c, map, indexStack);
        generateEquivalenceMap(c, map, indexStack);
        indexStack.pop_back();
    }
    applyEquivalenceMapToModel(map, m);

    return m;
}

bool Model::fixVariableInterfaces()
{
    VariablePtrs variables;

    for (size_t index = 0; index < componentCount(); ++index) {
        findAllVariablesWithEquivalences(component(index), variables);
    }

    bool allOk = true;
    for (const auto &variable : variables) {
        Variable::InterfaceType interfaceType = determineInterfaceType(variable);
        if (interfaceType == Variable::InterfaceType::NONE) {
            allOk = false;
        } else if (!variable->permitsInterfaceType(interfaceType)) {
            variable->setInterfaceType(interfaceType);
        }
    }

    return allOk;
}

bool traverseHierarchyAndRemoveIfEmpty(const ComponentPtr &component)
{
    for (size_t i = component->componentCount() - 1; i != MAX_SIZE_T; --i) {
        if (traverseHierarchyAndRemoveIfEmpty(component->component(i))) {
            component->removeComponent(i);
        }
    }

    return (component->variableCount() + component->resetCount() + component->componentCount() == 0)
           && component->math().empty()
           && !component->isImport()
           && component->name().empty()
           && component->id().empty();
}

void Model::clean()
{
    // Remove empty components.
    for (size_t i = componentCount() - 1; i != MAX_SIZE_T; --i) {
        if (traverseHierarchyAndRemoveIfEmpty(component(i))) {
            removeComponent(i);
        }
    }

    // Remove empty units.
    for (size_t i = unitsCount() - 1; i != MAX_SIZE_T; --i) {
        auto u = units(i);
        if (!u->isImport()
            && u->name().empty()
            && u->id().empty()
            && (u->unitCount() == 0)) {
            removeUnits(i);
        }
    }
}

bool Model::doEquals(const EntityPtr &other) const
{
    if (ComponentEntity::doEquals(other)) {
        auto model = std::dynamic_pointer_cast<Model>(other);
        if ((model != nullptr) && pFunc()->equalUnits(model)) {
            return true;
        }
    }
    return false;
}

std::vector<std::string> Model::importRequirements() const
{
    std::vector<std::string> requirements;

    auto importedComponents = getImportedComponents(shared_from_this());
    auto importedUnits = getImportedUnits(shared_from_this());

    for (auto &component : importedComponents) {
        auto url = component->importSource()->url();
        if (std::find(requirements.begin(), requirements.end(), url) == requirements.end()) {
            requirements.push_back(url);
        }
    }
    for (auto &units : importedUnits) {
        auto url = units->importSource()->url();
        if (std::find(requirements.begin(), requirements.end(), url) == requirements.end()) {
            requirements.push_back(url);
        }
    }

    return requirements;
}

} // namespace libcellml
<commit_msg>Make Clang-Tidy happy.<commit_after>/*
Copyright libCellML Contributors

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 "libcellml/model.h"

#include <algorithm>
#include <fstream>
#include <map>
#include <numeric>
#include <sstream>
#include <stack>
#include <utility>
#include <vector>

#include "libcellml/component.h"
#include "libcellml/importsource.h"
#include "libcellml/parser.h"
#include "libcellml/units.h"
#include "libcellml/variable.h"

#include "anycellmlelement_p.h"
#include "component_p.h"
#include "componententity_p.h"
#include "internaltypes.h"
#include "issue_p.h"
#include "model_p.h"
#include "units_p.h"
#include "utilities.h"
#include "xmldoc.h"
#include "xmlutils.h"

namespace libcellml {

std::vector<UnitsPtr>::const_iterator Model::ModelImpl::findUnits(const std::string &name) const
{
    return std::find_if(mUnits.begin(), mUnits.end(),
                        [=](const UnitsPtr &u) -> bool { return u->name() == name; });
}

std::vector<UnitsPtr>::const_iterator Model::ModelImpl::findUnits(const UnitsPtr &units) const
{
    auto result = std::find(mUnits.begin(), mUnits.end(), units);
    if (result != mUnits.end()) {
        return result;
    }
    return std::find_if(mUnits.begin(), mUnits.end(),
                        [=](const UnitsPtr &u) -> bool { return u->equals(units); });
}

bool Model::ModelImpl::equalUnits(const ModelPtr &other) const
{
    std::vector<EntityPtr> entities;
    std::copy(mUnits.begin(), mUnits.end(), std::back_inserter(entities));
    return equalEntities(other, entities);
}

Model::ModelImpl *Model::pFunc()
{
    return reinterpret_cast<Model::ModelImpl *>(Entity::pFunc());
}

const Model::ModelImpl *Model::pFunc() const
{
    return reinterpret_cast<Model::ModelImpl const *>(Entity::pFunc());
}

Model::Model()
    : ComponentEntity(new Model::ModelImpl())
{
}

Model::Model(const std::string &name)
    : ComponentEntity(new Model::ModelImpl())
{
    setName(name);
}

Model::~Model()
{
    delete pFunc();
}
ModelPtr Model::create() noexcept
{
    return std::shared_ptr<Model> {new Model {}};
}

ModelPtr Model::create(const std::string &name) noexcept
{
    return std::shared_ptr<Model> {new Model {name}};
}

bool Model::doAddComponent(const ComponentPtr &component)
{
    auto thisModel = shared_from_this();
    if (component->hasParent() && (thisModel != component->parent())) {
        removeComponentFromEntity(component->parent(), component);
    }
    component->pFunc()->setParent(thisModel);

    return ComponentEntity::doAddComponent(component);
}

bool Model::addUnits(const UnitsPtr &units)
{
    if (units == nullptr) {
        return false;
    }

    // Prevent adding to multiple models: move units to this model.
    auto thisModel = shared_from_this();
    if (units->hasParent() && (units->parent() != thisModel)) {
        auto otherParent = std::dynamic_pointer_cast<Model>(units->parent());
        otherParent->removeUnits(units);
    }
    pFunc()->mUnits.push_back(units);
    units->pFunc()->setParent(thisModel);

    return true;
}

bool Model::removeUnits(size_t index)
{
    bool status = false;
    if (index < pFunc()->mUnits.size()) {
        auto result = pFunc()->mUnits.begin() + ptrdiff_t(index);
        (*result)->pFunc()->removeParent();
        pFunc()->mUnits.erase(result);
        status = true;
    }

    return status;
}

bool Model::removeUnits(const std::string &name)
{
    bool status = false;
    auto result = pFunc()->findUnits(name);
    if (result != pFunc()->mUnits.end()) {
        (*result)->pFunc()->removeParent();
        pFunc()->mUnits.erase(result);
        status = true;
    }

    return status;
}

bool Model::removeUnits(const UnitsPtr &units)
{
    bool status = false;
    auto result = pFunc()->findUnits(units);
    if (result != pFunc()->mUnits.end()) {
        units->pFunc()->removeParent();
        pFunc()->mUnits.erase(result);
        status = true;
    }

    return status;
}

void Model::removeAllUnits()
{
    for (const auto &u : pFunc()->mUnits) {
        u->pFunc()->removeParent();
    }
    pFunc()->mUnits.clear();
}

bool Model::hasUnits(const std::string &name) const
{
    return pFunc()->findUnits(name) != pFunc()->mUnits.end();
}

bool Model::hasUnits(const UnitsPtr &units) const
{
    return pFunc()->findUnits(units) != pFunc()->mUnits.end();
}

UnitsPtr Model::units(size_t index) const
{
    UnitsPtr units = nullptr;
    if (index < pFunc()->mUnits.size()) {
        units = pFunc()->mUnits.at(index);
    }

    return units;
}

UnitsPtr Model::units(const std::string &name) const
{
    UnitsPtr units = nullptr;
    auto result = pFunc()->findUnits(name);
    if (result != pFunc()->mUnits.end()) {
        units = *result;
    }

    return units;
}

UnitsPtr Model::takeUnits(size_t index)
{
    UnitsPtr units = nullptr;
    if (index < pFunc()->mUnits.size()) {
        units = pFunc()->mUnits.at(index);
        removeUnits(index);
        units->pFunc()->removeParent();
    }

    return units;
}

UnitsPtr Model::takeUnits(const std::string &name)
{
    return takeUnits(size_t(pFunc()->findUnits(name) - pFunc()->mUnits.begin()));
}

bool Model::replaceUnits(size_t index, const UnitsPtr &units)
{
    bool status = false;
    if (removeUnits(index)) {
        pFunc()->mUnits.insert(pFunc()->mUnits.begin() + ptrdiff_t(index), units);
        units->pFunc()->setParent(shared_from_this());
        status = true;
    }

    return status;
}

bool Model::replaceUnits(const std::string &name, const UnitsPtr &units)
{
    return replaceUnits(size_t(pFunc()->findUnits(name) - pFunc()->mUnits.begin()), units);
}

bool Model::replaceUnits(const UnitsPtr &oldUnits, const UnitsPtr &newUnits)
{
    return replaceUnits(size_t(pFunc()->findUnits(oldUnits) - pFunc()->mUnits.begin()), newUnits);
}

size_t Model::unitsCount() const
{
    return pFunc()->mUnits.size();
}

bool Model::linkUnits()
{
    return traverseComponentEntityTreeLinkingUnits(shared_from_this());
}

bool traverseComponentTreeForUnlinkedUnits(const ComponentPtr &component)
{
    bool unlinkedUnits = areComponentVariableUnitsUnlinked(component);
    for (size_t index = 0; index < component->componentCount() && !unlinkedUnits; ++index) {
        auto c = component->component(index);
        unlinkedUnits = traverseComponentTreeForUnlinkedUnits(c);
    }
    return unlinkedUnits;
}

bool Model::hasUnlinkedUnits()
{
    bool unlinkedUnits = false;
    for (size_t index = 0; index < componentCount() && !unlinkedUnits; ++index) {
        auto c = component(index);
        unlinkedUnits = traverseComponentTreeForUnlinkedUnits(c);
    }
    return unlinkedUnits;
}

bool Model::hasUnresolvedImports() const
{
    bool unresolvedImports = false;
    for (size_t n = 0; n < unitsCount() && !unresolvedImports; ++n) {
        unresolvedImports = !units(n)->isResolved();
    }
    for (size_t n = 0; (n < componentCount()) && !unresolvedImports; ++n) {
        unresolvedImports = !component(n)->isResolved();
    }
    return unresolvedImports;
}

bool hasComponentImports(const ComponentEntityConstPtr &componentEntity)
{
    bool importsPresent = false;
    for (size_t n = 0; (n < componentEntity->componentCount()) && !importsPresent; ++n) {
        libcellml::ComponentPtr childComponent = componentEntity->component(n);
        importsPresent = childComponent->isImport();
        if (!importsPresent) {
            importsPresent = hasComponentImports(childComponent);
        }
    }
    return importsPresent;
}

bool Model::hasImports() const
{
    bool importsPresent = false;
    for (size_t n = 0; (n < unitsCount()) && !importsPresent; ++n) {
        libcellml::UnitsPtr units = Model::units(n);
        if (units->isImport()) {
            importsPresent = true;
        }
    }

    if (!importsPresent) {
        importsPresent = hasComponentImports(shared_from_this());
    }

    return importsPresent;
}

void fixComponentUnits(const ModelPtr &model, const ComponentPtr &component)
{
    for (size_t v = 0; v < component->variableCount(); ++v) {
        auto variable = component->variable(v);
        if (variable->units() != nullptr) {
            // Find the units in the model and switch out.
            auto units = model->units(variable->units()->name());
            if (units != nullptr) {
                variable->setUnits(units);
            }
        }
    }
    for (size_t c = 0; c < component->componentCount(); ++c) {
        fixComponentUnits(model, component->component(c));
    }
}

ModelPtr Model::clone() const
{
    auto m = create();

    m->setId(id());
    m->setName(name());

    m->setEncapsulationId(encapsulationId());

    for (size_t index = 0; index < pFunc()->mUnits.size(); ++index) {
        m->addUnits(units(index)->clone());
    }

    for (size_t index = 0; index < componentCount(); ++index) {
        m->addComponent(component(index)->clone());
    }

    for (size_t index = 0; index < m->componentCount(); ++index) {
        fixComponentUnits(m, m->component(index));
    }

    // Generate equivalence map starting from the models components.
    EquivalenceMap map;
    IndexStack indexStack;
    for (size_t index = 0; index < componentCount(); ++index) {
        indexStack.push_back(index);
        auto c = component(index);
        recordVariableEquivalences(c, map, indexStack);
        generateEquivalenceMap(c, map, indexStack);
        indexStack.pop_back();
    }
    applyEquivalenceMapToModel(map, m);

    return m;
}

bool Model::fixVariableInterfaces()
{
    VariablePtrs variables;

    for (size_t index = 0; index < componentCount(); ++index) {
        findAllVariablesWithEquivalences(component(index), variables);
    }

    bool allOk = true;
    for (const auto &variable : variables) {
        Variable::InterfaceType interfaceType = determineInterfaceType(variable);
        if (interfaceType == Variable::InterfaceType::NONE) {
            allOk = false;
        } else if (!variable->permitsInterfaceType(interfaceType)) {
            variable->setInterfaceType(interfaceType);
        }
    }

    return allOk;
}

bool traverseHierarchyAndRemoveIfEmpty(const ComponentPtr &component)
{
    for (size_t i = component->componentCount() - 1; i != MAX_SIZE_T; --i) {
        if (traverseHierarchyAndRemoveIfEmpty(component->component(i))) {
            component->removeComponent(i);
        }
    }

    return (component->variableCount() + component->resetCount() + component->componentCount() == 0)
           && component->math().empty()
           && !component->isImport()
           && component->name().empty()
           && component->id().empty();
}

void Model::clean()
{
    // Remove empty components.
    for (size_t i = componentCount() - 1; i != MAX_SIZE_T; --i) {
        if (traverseHierarchyAndRemoveIfEmpty(component(i))) {
            removeComponent(i);
        }
    }

    // Remove empty units.
    for (size_t i = unitsCount() - 1; i != MAX_SIZE_T; --i) {
        auto u = units(i);
        if (!u->isImport()
            && u->name().empty()
            && u->id().empty()
            && (u->unitCount() == 0)) {
            removeUnits(i);
        }
    }
}

bool Model::doEquals(const EntityPtr &other) const
{
    if (ComponentEntity::doEquals(other)) {
        auto model = std::dynamic_pointer_cast<Model>(other);
        if ((model != nullptr) && pFunc()->equalUnits(model)) {
            return true;
        }
    }
    return false;
}

std::vector<std::string> Model::importRequirements() const
{
    std::vector<std::string> requirements;

    auto importedComponents = getImportedComponents(shared_from_this());
    auto importedUnits = getImportedUnits(shared_from_this());

    for (auto &component : importedComponents) {
        auto url = component->importSource()->url();
        if (std::find(requirements.begin(), requirements.end(), url) == requirements.end()) {
            requirements.push_back(url);
        }
    }
    for (auto &units : importedUnits) {
        auto url = units->importSource()->url();
        if (std::find(requirements.begin(), requirements.end(), url) == requirements.end()) {
            requirements.push_back(url);
        }
    }

    return requirements;
}

} // namespace libcellml
<|endoftext|>


<commit_before>#include "acrbslam/wifi.h"

namespace acrbslam
{

//wifi 参数读取函数
wifi_comu::wifi_comu()
:send_time(0)
{
	LOCALPORT    	= Config::get<int> ( "LOCALPORT" );
	REMOTEPORT	= Config::get<int> ( "REMOTEPORT" );

	string  localIP=Config::get<string> ( "LOCALIP" );
	LOCALIP=localIP.c_str();
	string  remoteIP=(Config::get<string> ( "REMOTEIP" ));
	REMOTEIP=remoteIP.c_str();
}

//wifi释放函数
wifi_comu::~wifi_comu()
{

}

//wifi初始化函数
void wifi_comu::wifi_init()
{
	if((pc_sock=socket(AF_INET,SOCK_DGRAM,0))<0) //建立socket
	{
		printf("socket error\n");
	}

	Local_Addr.sin_family = AF_INET;
	Local_Addr.sin_port = htons(LOCALPORT);
	Local_Addr.sin_addr.s_addr = inet_addr(LOCALIP);

	if(bind(pc_sock,(struct sockaddr *)&Local_Addr,sizeof(Local_Addr))<0)
	{
		printf("bind error\n");
		perror("wifi_bind");
		return ;
	}
	Remote_Addr.sin_family = AF_INET;
	Remote_Addr.sin_port = htons(REMOTEPORT);
	Remote_Addr.sin_addr.s_addr = inet_addr(REMOTEIP);
}

//根据CSDN 博客书写
void wifi_comu::wifi_init_uav()
{
	if (pc_sock=socket(AF_INET,SOCK_STREAM,0)<0)
	{
		printf("socket error\n");
	}
	server = gethostbyname(LOCALIP);
	if (server==NULL)
	{
		fprintf(stderr,"ERROR,no such host\n");
		exit(0);
	}
	bzero((char*)&Local_Addr,sizeof(Local_Addr));
	Local_Addr.sin_family = AF_INET;
	bcopy((char*)server->h_addr, (char *)&Local_Addr.sin_addr.s_addr,server->h_length);
	Local_Addr.sin_port = htons(LOCALPORT);
	if((connect(pc_sock,(struct sockaddr *)&Local_Addr,sizeof(Local_Addr)))<0)
	{
		perror("ERROR connecting");
	}

}

//wif函数接收端初始化
void wifi_comu::wifi_init_pc()
{
	if (uav_sock=socket(AF_INET,SOCK_STREAM,0)<0)
	{
		printf("socket error\n");
	}

	Local_Addr.sin_family = AF_INET;
	Local_Addr.sin_port = htons(LOCALPORT);
	Local_Addr.sin_addr.s_addr = inet_addr(LOCALIP);

	if(bind(uav_sock, (struct sockaddr *)&Local_Addr,sizeof(Local_Addr))<0)
	{
		printf("bind error\n");
		perror("wifi_bind");
		return ;
	}

	if(listen(uav_sock,5)==-1)
	{
		printf("listen error\n");
		return;
	}

	socklen_t addr_len=sizeof(Remote_Addr);

	cout<<"Wait.."<<endl;
	do
	{
		pc_sock=accept(uav_sock,(struct sockaddr*)&Remote_Addr,&addr_len);
	}while(pc_sock<0);

}

//
//wifi 发送数据函数
void wifi_comu::send_data(char *data,unsigned int num)
{
	unsigned int data_num=num;
	char *wifi_data=data;

	if(sendto(pc_sock,wifi_data,data_num,0,(struct sockaddr*)&Remote_Addr,sizeof(Remote_Addr))==-1)
	printf("wifi_send_error\n");

}

//wifi发送新函数
void wifi_comu::send_data_new(Mat frame)
{
	if(send(pc_sock,frame.data, frame.total()*frame.elemSize(),0)==-1);
	printf("wifi_send_error\n");
}

//

//wifi 接收数据函数
int wifi_comu::receive_data(char *data, long unsigned int num)
{
	long unsigned int data_num=num;
	int temp_data;
	char *wifi_data=data;
	socklen_t addr_len=sizeof(Remote_Addr);

	temp_data=recvfrom(pc_sock,wifi_data,data_num,0,(struct sockaddr*)&Remote_Addr,&addr_len);
	return temp_data;
}

//wifi pc端接收新函数
void wifi_comu::receive_data_pc(Mat frame)
{
	char receive_data[307200];
	int bytes=0;

	for (int i=0; i<307200; i+=bytes)
	{
		if((bytes=recv(pc_sock,receive_data+i, 307200-i, 0 ))==-1)
		{
			cout<<"Fault"<<endl;
			exit(-1);

		}
	}
	Mat temp_mat(Size(640,480), CV_8UC1, receive_data);
	frame=temp_mat;
	return;
}

}//namespace acrbslam

<commit_msg>修改pc 端接收函数中 uav_sock pc_sock顺序<commit_after>#include "acrbslam/wifi.h"

namespace acrbslam
{

//wifi 参数读取函数
wifi_comu::wifi_comu()
:send_time(0)
{
	LOCALPORT    	= Config::get<int> ( "LOCALPORT" );
	REMOTEPORT	= Config::get<int> ( "REMOTEPORT" );

	string  localIP=Config::get<string> ( "LOCALIP" );
	LOCALIP=localIP.c_str();
	string  remoteIP=(Config::get<string> ( "REMOTEIP" ));
	REMOTEIP=remoteIP.c_str();
}

//wifi释放函数
wifi_comu::~wifi_comu()
{

}

//wifi初始化函数
void wifi_comu::wifi_init()
{
	if((pc_sock=socket(AF_INET,SOCK_DGRAM,0))<0) //建立socket
	{
		printf("socket error\n");
	}

	Local_Addr.sin_family = AF_INET;
	Local_Addr.sin_port = htons(LOCALPORT);
	Local_Addr.sin_addr.s_addr = inet_addr(LOCALIP);

	if(bind(pc_sock,(struct sockaddr *)&Local_Addr,sizeof(Local_Addr))<0)
	{
		printf("bind error\n");
		perror("wifi_bind");
		return ;
	}
	Remote_Addr.sin_family = AF_INET;
	Remote_Addr.sin_port = htons(REMOTEPORT);
	Remote_Addr.sin_addr.s_addr = inet_addr(REMOTEIP);
}

//根据CSDN 博客书写
void wifi_comu::wifi_init_uav()
{
/*
	if (pc_sock=socket(AF_INET,SOCK_STREAM,0)<0)
	{
		printf("socket error\n");
	}
	server = gethostbyname(LOCALIP);
	if (server==NULL)
	{
		fprintf(stderr,"ERROR,no such host\n");
		exit(0);
	}
	bzero((char*)&Local_Addr,sizeof(Local_Addr));
	Local_Addr.sin_family = AF_INET;
	bcopy((char*)server->h_addr, (char *)&Local_Addr.sin_addr.s_addr,server->h_length);
	Local_Addr.sin_port = htons(LOCALPORT);
*/
	if((pc_sock=socket(AF_INET,SOCK_STREAM,0))<0) //建立socket
	{
		printf("socket error\n");
	}

	Local_Addr.sin_family = AF_INET;
	Local_Addr.sin_port = htons(LOCALPORT);
	Local_Addr.sin_addr.s_addr = inet_addr(LOCALIP);

	if((connect(pc_sock,(struct sockaddr *)&Local_Addr,sizeof(Local_Addr)))<0)

		perror("ERROR connecting");

}

//wif函数接收端初始化
void wifi_comu::wifi_init_pc()
{
	if (pc_sock=socket(AF_INET,SOCK_STREAM,0)<0)
	{
		printf("socket error\n");
	}

	Local_Addr.sin_family = AF_INET;
	Local_Addr.sin_port = htons(LOCALPORT);
	Local_Addr.sin_addr.s_addr = inet_addr(LOCALIP);

	if(bind(pc_sock, (struct sockaddr *)&Local_Addr,sizeof(Local_Addr))<0)
	{
		printf("bind error\n");
		perror("wifi_bind");
		return ;
	}

	if(listen(pc_sock,5)==-1)
	{
		printf("listen error\n");
		return;
	}

	socklen_t addr_len=sizeof(Remote_Addr);

	cout<<"Wait.."<<endl;
	do
	{
		uav_sock=accept(uav_sock,(struct sockaddr*)&Remote_Addr,&addr_len);
	}while(uav_sock<0);

}

//
//wifi 发送数据函数
void wifi_comu::send_data(char *data,unsigned int num)
{
	unsigned int data_num=num;
	char *wifi_data=data;

	if(sendto(pc_sock,wifi_data,data_num,0,(struct sockaddr*)&Remote_Addr,sizeof(Remote_Addr))==-1)
	printf("wifi_send_error\n");

}

//wifi发送新函数
void wifi_comu::send_data_new(Mat frame)
{
	if(send(pc_sock,frame.data, frame.total()*frame.elemSize(),0)==-1);
	printf("wifi_send_error\n");
}

//

//wifi 接收数据函数
int wifi_comu::receive_data(char *data, long unsigned int num)
{
	long unsigned int data_num=num;
	int temp_data;
	char *wifi_data=data;
	socklen_t addr_len=sizeof(Remote_Addr);

	temp_data=recvfrom(pc_sock,wifi_data,data_num,0,(struct sockaddr*)&Remote_Addr,&addr_len);
	return temp_data;
}

//wifi pc端接收新函数
void wifi_comu::receive_data_pc(Mat frame)
{
	char receive_data[307200];
	int bytes=0;

	for (int i=0; i<307200; i+=bytes)
	{
		if((bytes=recv(uav_sock,receive_data+i, 307200-i, 0 ))==-1)
		{
			cout<<"Fault"<<endl;
			exit(-1);

		}
	}
	Mat temp_mat(Size(640,480), CV_8UC1, receive_data);
	frame=temp_mat;
	return;
}

}//namespace acrbslam

<|endoftext|>


<commit_before>/*
 * Copyright 2009-2011 The VOTCA Development Team (http://www.votca.org)
 *
 * 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 <votca/csg/topology.h>
#include <votca/csg/interaction.h>
#include <votca/tools/rangeparser.h>
#include <stdexcept>

namespace votca { namespace csg {

Topology::~Topology()
{
    Cleanup();
    if(_bc)
        delete (_bc);
    _bc = NULL;
}

void Topology::Cleanup()
{
    // cleanup beads
    {
        BeadContainer::iterator i;
        for(i=_beads.begin();i<_beads.end();++i)
            delete *i;
        _beads.clear();
    }
    // cleanup molecules
    {
        MoleculeContainer::iterator i;
        for(i=_molecules.begin();i<_molecules.end();++i)
            delete *i;
        _molecules.clear();
    }
    // cleanup residues
    {
        ResidueContainer::iterator i;
        for(i=_residues.begin();i<_residues.end();++i)
            delete (*i);
        _residues.clear();
    }
    // cleanup interactions
    {
        InteractionContainer::iterator i;
        for(i=_interactions.begin();i<_interactions.end();++i)
            delete (*i);
        _interactions.clear();
    }
    // cleanup _bc object
    if(_bc)
        delete (_bc);
    _bc = new OpenBox();
}

/// \todo implement checking!!
void Topology::CreateMoleculesByRange(string name, int first, int nbeads, int nmolecules)
{
    Molecule *mol = CreateMolecule(name);
    int beadcount=0;

    BeadContainer::iterator bead;
    for(bead=_beads.begin(); bead!=_beads.end(); ++bead) {
        while(--first > 0) continue;
        string bname = //lexical_cast<string>(mol->getId()) + ":"
                      //lexical_cast<string>(bead->Residue()) + ":"
                      //+
                      (*bead)->getName();
        mol->AddBead((*bead), bname);
        if(++beadcount == nbeads) {
            if(--nmolecules <= 0) break;
            mol = CreateMolecule(name);
            beadcount = 0;
        }
    }
}

/// \todo clean up CreateMoleculesByResidue!
void Topology::CreateMoleculesByResidue()
{
    // first create a molecule for each residue
    ResidueContainer::iterator res;
    for(res=_residues.begin(); res!=_residues.end(); ++res) {
        CreateMolecule((*res)->getName());
    }

    // add the beads to the corresponding molecules based on their resid
    BeadContainer::iterator bead;
    for(bead=_beads.begin(); bead!=_beads.end(); ++bead) {
        //MoleculeByIndex((*bead)->getResnr())->AddBead((*bead)->getId(), (*bead)->getName());

        MoleculeByIndex((*bead)->getResnr())->AddBead((*bead), string("1:TRI:") + (*bead)->getName());
    }

    /// \todo sort beads in molecules that all beads are stored in the same order. This is needed for the mapping!
}

void Topology::CreateOneBigMolecule(string name)
{
    Molecule *mi = CreateMolecule(name);

    BeadContainer::iterator bead;

    for(bead=_beads.begin(); bead!=_beads.end(); ++bead) {
        stringstream n("");
        n << (*bead)->getResnr() +1 << ":" <<  _residues[(*bead)->getResnr()]->getName() << ":" << (*bead)->getName();
        //cout << n.str() << endl;
        mi->AddBead((*bead), n.str());
    }
}

void Topology::Add(Topology *top)
{
    BeadContainer::iterator bead;
    ResidueContainer::iterator res;
    MoleculeContainer::iterator mol;

    int res0=ResidueCount();

    for(bead=top->_beads.begin(); bead!=top->_beads.end(); ++bead) {
        Bead *bi = *bead;
        BeadType *type =  GetOrCreateBeadType(bi->getType()->getName());
        CreateBead(bi->getSymmetry(), bi->getName(), type, bi->getResnr()+res0, bi->getM(), bi->getQ());
    }

    for(res=top->_residues.begin();res!=top->_residues.end(); ++res) {
        CreateResidue((*res)->getName());
    }

    // \todo beadnames in molecules!!
    for(mol=top->_molecules.begin();mol!=top->_molecules.end(); ++mol) {
        Molecule *mi = CreateMolecule((*mol)->getName());
        for(int i=0; i<mi->BeadCount(); i++) {
            mi->AddBead(mi->getBead(i), "invalid");
        }
    }
}

void Topology::CopyTopologyData(Topology *top)
{
    BeadContainer::iterator it_bead;
    ResidueContainer::iterator it_res;
    MoleculeContainer::iterator it_mol;
    InteractionContainer::iterator it_ia;

    _bc->setBox(top->getBox());
    _time = top->_time;
    _step = top->_step;

    // cleanup old data
    Cleanup();

    // copy all residues
    for(it_res=top->_residues.begin();it_res!=top->_residues.end(); ++it_res) {
        CreateResidue((*it_res)->getName());
    }

    // create all beads
    for(it_bead=top->_beads.begin(); it_bead!=top->_beads.end(); ++it_bead) {
        Bead *bi = *it_bead;
        BeadType *type =  GetOrCreateBeadType(bi->getType()->getName());
        Bead *bn = CreateBead(bi->getSymmetry(), bi->getName(), type, bi->getResnr(), bi->getM(), bi->getQ());
        bn->setOptions(bi->Options());
    }

    // copy all molecules
    for(it_mol=top->_molecules.begin();it_mol!=top->_molecules.end(); ++it_mol) {
        Molecule *mi = CreateMolecule((*it_mol)->getName());
        for(int i=0; i<(*it_mol)->BeadCount(); i++) {
            int beadid = (*it_mol)->getBead(i)->getId();
            mi->AddBead(_beads[beadid], (*it_mol)->getBeadName(i));
        }
    }
    // TODO: copy interactions
    //for(it_ia=top->_interaction.begin();it_ia=top->_interactions.end();++it_ia) {

    //}
}

void Topology::RenameMolecules(string range, string name)
{
    RangeParser rp;
    RangeParser::iterator i;

    rp.Parse(range);
    for(i=rp.begin();i!=rp.end();++i) {
        if((unsigned int)*i > _molecules.size())
            throw runtime_error(string("RenameMolecules: num molecules smaller than"));
        getMolecule(*i-1)->setName(name);
    }
}

void Topology::CheckMoleculeNaming(void)
{
    map<string,int> nbeads;

    for(MoleculeContainer::iterator iter = _molecules.begin(); iter!=_molecules.end(); ++iter) {
        map<string,int>::iterator entry = nbeads.find((*iter)->getName());
        if(entry != nbeads.end()) {
            if(entry->second != (*iter)->BeadCount())
                throw runtime_error("There are molecules which have the same name but different number of bead "
                        "please check the section manual topology handling in the votca manual");
            continue;
        }
        nbeads[(*iter)->getName()] = (*iter)->BeadCount();
    }
}

void Topology::AddBondedInteraction(Interaction *ic)
{
    map<string,int>::iterator iter;
    iter = _interaction_groups.find(ic->getGroup());
    if(iter!=_interaction_groups.end())
        ic->setGroupId((*iter).second);
    else {
        int i= _interaction_groups.size();
        _interaction_groups[ic->getGroup()] = i;
        ic->setGroupId(i);
    }
    _interactions.push_back(ic);
    _interactions_by_group[ic->getGroup()].push_back(ic);
}

std::list<Interaction *> Topology::InteractionsInGroup(const string &group)
{
    map<string, list<Interaction*> >::iterator iter;
    iter = _interactions_by_group.find(group);
    if(iter == _interactions_by_group.end())
        return list<Interaction *>();
    return iter->second;
}

BeadType *Topology::GetOrCreateBeadType(string name)
{
    map<string, int>::iterator iter;

    iter = _beadtype_map.find(name);
    if(iter == _beadtype_map.end()) {
        BeadType *bt = new BeadType(this, _beadtypes.size(), name);
        _beadtypes.push_back(bt);
        _beadtype_map[name] = bt->getId();
        return bt;
    }
    else {
        return _beadtypes[(*iter).second];
    }
    return NULL;
}

vec Topology::BCShortestConnection(const vec &r_i, const vec &r_j) const
{
    return _bc->BCShortestConnection(r_i, r_j);
}

vec Topology::getDist(int bead1, int bead2) const
{
    return BCShortestConnection(
            getBead(bead1)->getPos(),
            getBead(bead2)->getPos());
}

double Topology::BoxVolume()
{
    return _bc->BoxVolume();
}

void Topology::RebuildExclusions()
{
    _exclusions.CreateExclusions(this);
}

BoundaryCondition::eBoxtype Topology::autoDetectBoxType(const matrix &box) {
    // set the box type to OpenBox in case "box" is the zero matrix,
    // to OrthorhombicBox in case "box" is a diagonal matrix,
    // or to TriclinicBox otherwise
    if(box.get(0,0)==0 && box.get(0,1)==0 && box.get(0,2)==0 &&
       box.get(1,0)==0 && box.get(1,1)==0 && box.get(1,2)==0 &&
       box.get(2,0)==0 && box.get(2,1)==0 && box.get(2,2)==0) {
        //cout << "box open\n";
        return BoundaryCondition::typeOpen;
    }
    else
    if(box.get(0,1)==0 && box.get(0,2)==0 &&
       box.get(1,0)==0 && box.get(1,2)==0 &&
       box.get(2,0)==0 && box.get(2,1)==0) {
        //cout << "box orth\n";
        return BoundaryCondition::typeOrthorhombic;
    }
    else {
        //cout << "box tric\n";
        return BoundaryCondition::typeTriclinic;
    }
    return BoundaryCondition::typeOpen;
}

double Topology::ShortestBoxSize()
{
    vec _box_a = getBox().getCol(0);
    vec _box_b = getBox().getCol(1);
    vec _box_c = getBox().getCol(2);

    // create plane normals
    vec _norm_a = _box_b ^ _box_c;
    vec _norm_b = _box_c ^ _box_a;
    vec _norm_c = _box_a ^ _box_b;

    _norm_a.normalize();
    _norm_b.normalize();
    _norm_c.normalize();

    double la = _box_a * _norm_a;
    double lb = _box_b * _norm_b;
    double lc = _box_c * _norm_c;

    return min(la, min(lb, lc));
}

}}
<commit_msg>fixed CreateMoleculesByRange for multiple molecule creates<commit_after>/*
 * Copyright 2009-2011 The VOTCA Development Team (http://www.votca.org)
 *
 * 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 <votca/csg/topology.h>
#include <votca/csg/interaction.h>
#include <votca/tools/rangeparser.h>
#include <stdexcept>

namespace votca { namespace csg {

Topology::~Topology()
{
    Cleanup();
    if(_bc)
        delete (_bc);
    _bc = NULL;
}

void Topology::Cleanup()
{
    // cleanup beads
    {
        BeadContainer::iterator i;
        for(i=_beads.begin();i<_beads.end();++i)
            delete *i;
        _beads.clear();
    }
    // cleanup molecules
    {
        MoleculeContainer::iterator i;
        for(i=_molecules.begin();i<_molecules.end();++i)
            delete *i;
        _molecules.clear();
    }
    // cleanup residues
    {
        ResidueContainer::iterator i;
        for(i=_residues.begin();i<_residues.end();++i)
            delete (*i);
        _residues.clear();
    }
    // cleanup interactions
    {
        InteractionContainer::iterator i;
        for(i=_interactions.begin();i<_interactions.end();++i)
            delete (*i);
        _interactions.clear();
    }
    // cleanup _bc object
    if(_bc)
        delete (_bc);
    _bc = new OpenBox();
}

/// \todo implement checking!!
void Topology::CreateMoleculesByRange(string name, int first, int nbeads, int nmolecules)
{
    Molecule *mol = CreateMolecule(name);
    int beadcount=0;

    BeadContainer::iterator bead;
    for(bead=_beads.begin(); bead!=_beads.end(); ++bead) {
        if(first-- > 0) continue;
        string bname = //lexical_cast<string>(mol->getId()) + ":"
                      //lexical_cast<string>(bead->Residue()) + ":"
                      //+
                      (*bead)->getName();
        mol->AddBead((*bead), bname);
        if(++beadcount == nbeads) {
            if(--nmolecules <= 0) break;
            mol = CreateMolecule(name);
            beadcount = 0;
        }
    }
}

/// \todo clean up CreateMoleculesByResidue!
void Topology::CreateMoleculesByResidue()
{
    // first create a molecule for each residue
    ResidueContainer::iterator res;
    for(res=_residues.begin(); res!=_residues.end(); ++res) {
        CreateMolecule((*res)->getName());
    }

    // add the beads to the corresponding molecules based on their resid
    BeadContainer::iterator bead;
    for(bead=_beads.begin(); bead!=_beads.end(); ++bead) {
        //MoleculeByIndex((*bead)->getResnr())->AddBead((*bead)->getId(), (*bead)->getName());

        MoleculeByIndex((*bead)->getResnr())->AddBead((*bead), string("1:TRI:") + (*bead)->getName());
    }

    /// \todo sort beads in molecules that all beads are stored in the same order. This is needed for the mapping!
}

void Topology::CreateOneBigMolecule(string name)
{
    Molecule *mi = CreateMolecule(name);

    BeadContainer::iterator bead;

    for(bead=_beads.begin(); bead!=_beads.end(); ++bead) {
        stringstream n("");
        n << (*bead)->getResnr() +1 << ":" <<  _residues[(*bead)->getResnr()]->getName() << ":" << (*bead)->getName();
        //cout << n.str() << endl;
        mi->AddBead((*bead), n.str());
    }
}

void Topology::Add(Topology *top)
{
    BeadContainer::iterator bead;
    ResidueContainer::iterator res;
    MoleculeContainer::iterator mol;

    int res0=ResidueCount();

    for(bead=top->_beads.begin(); bead!=top->_beads.end(); ++bead) {
        Bead *bi = *bead;
        BeadType *type =  GetOrCreateBeadType(bi->getType()->getName());
        CreateBead(bi->getSymmetry(), bi->getName(), type, bi->getResnr()+res0, bi->getM(), bi->getQ());
    }

    for(res=top->_residues.begin();res!=top->_residues.end(); ++res) {
        CreateResidue((*res)->getName());
    }

    // \todo beadnames in molecules!!
    for(mol=top->_molecules.begin();mol!=top->_molecules.end(); ++mol) {
        Molecule *mi = CreateMolecule((*mol)->getName());
        for(int i=0; i<mi->BeadCount(); i++) {
            mi->AddBead(mi->getBead(i), "invalid");
        }
    }
}

void Topology::CopyTopologyData(Topology *top)
{
    BeadContainer::iterator it_bead;
    ResidueContainer::iterator it_res;
    MoleculeContainer::iterator it_mol;
    InteractionContainer::iterator it_ia;

    _bc->setBox(top->getBox());
    _time = top->_time;
    _step = top->_step;

    // cleanup old data
    Cleanup();

    // copy all residues
    for(it_res=top->_residues.begin();it_res!=top->_residues.end(); ++it_res) {
        CreateResidue((*it_res)->getName());
    }

    // create all beads
    for(it_bead=top->_beads.begin(); it_bead!=top->_beads.end(); ++it_bead) {
        Bead *bi = *it_bead;
        BeadType *type =  GetOrCreateBeadType(bi->getType()->getName());
        Bead *bn = CreateBead(bi->getSymmetry(), bi->getName(), type, bi->getResnr(), bi->getM(), bi->getQ());
        bn->setOptions(bi->Options());
    }

    // copy all molecules
    for(it_mol=top->_molecules.begin();it_mol!=top->_molecules.end(); ++it_mol) {
        Molecule *mi = CreateMolecule((*it_mol)->getName());
        for(int i=0; i<(*it_mol)->BeadCount(); i++) {
            int beadid = (*it_mol)->getBead(i)->getId();
            mi->AddBead(_beads[beadid], (*it_mol)->getBeadName(i));
        }
    }
    // TODO: copy interactions
    //for(it_ia=top->_interaction.begin();it_ia=top->_interactions.end();++it_ia) {

    //}
}

void Topology::RenameMolecules(string range, string name)
{
    RangeParser rp;
    RangeParser::iterator i;

    rp.Parse(range);
    for(i=rp.begin();i!=rp.end();++i) {
        if((unsigned int)*i > _molecules.size())
            throw runtime_error(string("RenameMolecules: num molecules smaller than"));
        getMolecule(*i-1)->setName(name);
    }
}

void Topology::CheckMoleculeNaming(void)
{
    map<string,int> nbeads;

    for(MoleculeContainer::iterator iter = _molecules.begin(); iter!=_molecules.end(); ++iter) {
        map<string,int>::iterator entry = nbeads.find((*iter)->getName());
        if(entry != nbeads.end()) {
            if(entry->second != (*iter)->BeadCount())
                throw runtime_error("There are molecules which have the same name but different number of bead "
                        "please check the section manual topology handling in the votca manual");
            continue;
        }
        nbeads[(*iter)->getName()] = (*iter)->BeadCount();
    }
}

void Topology::AddBondedInteraction(Interaction *ic)
{
    map<string,int>::iterator iter;
    iter = _interaction_groups.find(ic->getGroup());
    if(iter!=_interaction_groups.end())
        ic->setGroupId((*iter).second);
    else {
        int i= _interaction_groups.size();
        _interaction_groups[ic->getGroup()] = i;
        ic->setGroupId(i);
    }
    _interactions.push_back(ic);
    _interactions_by_group[ic->getGroup()].push_back(ic);
}

std::list<Interaction *> Topology::InteractionsInGroup(const string &group)
{
    map<string, list<Interaction*> >::iterator iter;
    iter = _interactions_by_group.find(group);
    if(iter == _interactions_by_group.end())
        return list<Interaction *>();
    return iter->second;
}

BeadType *Topology::GetOrCreateBeadType(string name)
{
    map<string, int>::iterator iter;

    iter = _beadtype_map.find(name);
    if(iter == _beadtype_map.end()) {
        BeadType *bt = new BeadType(this, _beadtypes.size(), name);
        _beadtypes.push_back(bt);
        _beadtype_map[name] = bt->getId();
        return bt;
    }
    else {
        return _beadtypes[(*iter).second];
    }
    return NULL;
}

vec Topology::BCShortestConnection(const vec &r_i, const vec &r_j) const
{
    return _bc->BCShortestConnection(r_i, r_j);
}

vec Topology::getDist(int bead1, int bead2) const
{
    return BCShortestConnection(
            getBead(bead1)->getPos(),
            getBead(bead2)->getPos());
}

double Topology::BoxVolume()
{
    return _bc->BoxVolume();
}

void Topology::RebuildExclusions()
{
    _exclusions.CreateExclusions(this);
}

BoundaryCondition::eBoxtype Topology::autoDetectBoxType(const matrix &box) {
    // set the box type to OpenBox in case "box" is the zero matrix,
    // to OrthorhombicBox in case "box" is a diagonal matrix,
    // or to TriclinicBox otherwise
    if(box.get(0,0)==0 && box.get(0,1)==0 && box.get(0,2)==0 &&
       box.get(1,0)==0 && box.get(1,1)==0 && box.get(1,2)==0 &&
       box.get(2,0)==0 && box.get(2,1)==0 && box.get(2,2)==0) {
        //cout << "box open\n";
        return BoundaryCondition::typeOpen;
    }
    else
    if(box.get(0,1)==0 && box.get(0,2)==0 &&
       box.get(1,0)==0 && box.get(1,2)==0 &&
       box.get(2,0)==0 && box.get(2,1)==0) {
        //cout << "box orth\n";
        return BoundaryCondition::typeOrthorhombic;
    }
    else {
        //cout << "box tric\n";
        return BoundaryCondition::typeTriclinic;
    }
    return BoundaryCondition::typeOpen;
}

double Topology::ShortestBoxSize()
{
    vec _box_a = getBox().getCol(0);
    vec _box_b = getBox().getCol(1);
    vec _box_c = getBox().getCol(2);

    // create plane normals
    vec _norm_a = _box_b ^ _box_c;
    vec _norm_b = _box_c ^ _box_a;
    vec _norm_c = _box_a ^ _box_b;

    _norm_a.normalize();
    _norm_b.normalize();
    _norm_c.normalize();

    double la = _box_a * _norm_a;
    double lb = _box_b * _norm_b;
    double lc = _box_c * _norm_c;

    return min(la, min(lb, lc));
}

}}
<|endoftext|>


<commit_before>#include "SkBlitMask.h"
#include "SkColor.h"
#include "SkColorPriv.h"

static void D32_A8_Color(void* SK_RESTRICT dst, size_t dstRB,
                         const void* SK_RESTRICT maskPtr, size_t maskRB,
                         SkColor color, int width, int height) {
    SkPMColor pmc = SkPreMultiplyColor(color);
    size_t dstOffset = dstRB - (width << 2);
    size_t maskOffset = maskRB - width;
    SkPMColor* SK_RESTRICT device = (SkPMColor *)dst;
    const uint8_t* SK_RESTRICT mask = (const uint8_t*)maskPtr;

    do {
        int w = width;
        do {
            unsigned aa = *mask++;
            *device = SkBlendARGB32(pmc, *device, aa);
            device += 1;
        } while (--w != 0);
        device = (uint32_t*)((char*)device + dstOffset);
        mask += maskOffset;
    } while (--height != 0);
}

static void D32_A8_Opaque(void* SK_RESTRICT dst, size_t dstRB,
                          const void* SK_RESTRICT maskPtr, size_t maskRB,
                          SkColor color, int width, int height) {
    SkPMColor pmc = SkPreMultiplyColor(color);
    SkPMColor* SK_RESTRICT device = (SkPMColor*)dst;
    const uint8_t* SK_RESTRICT mask = (const uint8_t*)maskPtr;

    maskRB -= width;
    dstRB -= (width << 2);
    do {
        int w = width;
        do {
            unsigned aa = *mask++;
            *device = SkAlphaMulQ(pmc, SkAlpha255To256(aa)) + SkAlphaMulQ(*device, SkAlpha255To256(255 - aa));
            device += 1;
        } while (--w != 0);
        device = (uint32_t*)((char*)device + dstRB);
        mask += maskRB;
    } while (--height != 0);
}

static void D32_A8_Black(void* SK_RESTRICT dst, size_t dstRB,
                         const void* SK_RESTRICT maskPtr, size_t maskRB,
                         SkColor, int width, int height) {
    SkPMColor* SK_RESTRICT device = (SkPMColor*)dst;
    const uint8_t* SK_RESTRICT mask = (const uint8_t*)maskPtr;

    maskRB -= width;
    dstRB -= (width << 2);
    do {
        int w = width;
        do {
            unsigned aa = *mask++;
            *device = (aa << SK_A32_SHIFT) + SkAlphaMulQ(*device, SkAlpha255To256(255 - aa));
            device += 1;
        } while (--w != 0);
        device = (uint32_t*)((char*)device + dstRB);
        mask += maskRB;
    } while (--height != 0);
}

///////////////////////////////////////////////////////////////////////////////

static inline int upscale31To32(int value) {
    SkASSERT((unsigned)value <= 31);
    return value + (value >> 4);
}

static inline int blend32(int src, int dst, int scale) {
    SkASSERT((unsigned)src <= 0xFF);
    SkASSERT((unsigned)dst <= 0xFF);
    SkASSERT((unsigned)scale <= 32);
    return dst + ((src - dst) * scale >> 5);
}

static void blit_lcd16_row(SkPMColor dst[], const uint16_t src[],
                           SkColor color, int width, SkPMColor) {
    int srcA = SkColorGetA(color);
    int srcR = SkColorGetR(color);
    int srcG = SkColorGetG(color);
    int srcB = SkColorGetB(color);

    srcA = SkAlpha255To256(srcA);

    for (int i = 0; i < width; i++) {
        uint16_t mask = src[i];
        if (0 == mask) {
            continue;
        }

        SkPMColor d = dst[i];

        /*  We want all of these in 5bits, hence the shifts in case one of them
         *  (green) is 6bits.
         */
        int maskR = SkGetPackedR16(mask) >> (SK_R16_BITS - 5);
        int maskG = SkGetPackedG16(mask) >> (SK_G16_BITS - 5);
        int maskB = SkGetPackedB16(mask) >> (SK_B16_BITS - 5);

        // Now upscale them to 0..32, so we can use blend32
        maskR = upscale31To32(maskR);
        maskG = upscale31To32(maskG);
        maskB = upscale31To32(maskB);

        maskR = maskR * srcA >> 8;
        maskG = maskG * srcA >> 8;
        maskB = maskB * srcA >> 8;

        int dstR = SkGetPackedR32(d);
        int dstG = SkGetPackedG32(d);
        int dstB = SkGetPackedB32(d);

        // LCD blitting is only supported if the dst is known/required\
        // to be opaque
        dst[i] = SkPackARGB32(0xFF,
                              blend32(srcR, dstR, maskR),
                              blend32(srcG, dstG, maskG),
                              blend32(srcB, dstB, maskB));
    }
}

static void blit_lcd16_opaque_row(SkPMColor dst[], const uint16_t src[],
                                  SkColor color, int width, SkPMColor opaqueDst) {
    int srcR = SkColorGetR(color);
    int srcG = SkColorGetG(color);
    int srcB = SkColorGetB(color);

    for (int i = 0; i < width; i++) {
        uint16_t mask = src[i];
        if (0 == mask) {
            continue;
        }
        if (0xFFFF == mask) {
            dst[i] = opaqueDst;
            continue;
        }

        SkPMColor d = dst[i];

        /*  We want all of these in 5bits, hence the shifts in case one of them
         *  (green) is 6bits.
         */
        int maskR = SkGetPackedR16(mask) >> (SK_R16_BITS - 5);
        int maskG = SkGetPackedG16(mask) >> (SK_G16_BITS - 5);
        int maskB = SkGetPackedB16(mask) >> (SK_B16_BITS - 5);

        // Now upscale them to 0..32, so we can use blend32
        maskR = upscale31To32(maskR);
        maskG = upscale31To32(maskG);
        maskB = upscale31To32(maskB);

        int dstR = SkGetPackedR32(d);
        int dstG = SkGetPackedG32(d);
        int dstB = SkGetPackedB32(d);

        // LCD blitting is only supported if the dst is known/required
        // to be opaque
        dst[i] = SkPackARGB32(0xFF,
                              blend32(srcR, dstR, maskR),
                              blend32(srcG, dstG, maskG),
                              blend32(srcB, dstB, maskB));
    }
}

static void D32_LCD16_Proc(void* SK_RESTRICT dst, size_t dstRB,
                           const void* SK_RESTRICT mask, size_t maskRB,
                           SkColor color, int width, int height) {

    SkPMColor*		dstRow = (SkPMColor*)dst;
    const uint16_t* srcRow = (const uint16_t*)mask;
    SkPMColor       opaqueDst;

    void (*proc)(SkPMColor dst[], const uint16_t src[],
                 SkColor color, int width, SkPMColor);
    if (0xFF == SkColorGetA(color)) {
        proc = blit_lcd16_opaque_row;
        opaqueDst = SkPreMultiplyColor(color);
    } else {
        proc = blit_lcd16_row;
        opaqueDst = 0;  // ignored
    }

    do {
        proc(dstRow, srcRow, color, width, opaqueDst);
        dstRow = (SkPMColor*)((char*)dstRow + dstRB);
        srcRow = (const uint16_t*)((const char*)srcRow + maskRB);
    } while (--height != 0);
}

///////////////////////////////////////////////////////////////////////////////

static void blit_lcd32_opaque_row(SkPMColor* SK_RESTRICT dst,
                                  const SkPMColor* SK_RESTRICT src,
                                  SkColor color, int width) {
    int srcR = SkColorGetR(color);
    int srcG = SkColorGetG(color);
    int srcB = SkColorGetB(color);

    for (int i = 0; i < width; i++) {
        SkPMColor mask = src[i];
        if (0 == mask) {
            continue;
        }

        SkPMColor d = dst[i];

        int maskR = SkGetPackedR32(mask);
        int maskG = SkGetPackedG32(mask);
        int maskB = SkGetPackedB32(mask);

        // Now upscale them to 0..256, so we can use SkAlphaBlend
        maskR = SkAlpha255To256(maskR);
        maskG = SkAlpha255To256(maskG);
        maskB = SkAlpha255To256(maskB);

        int dstR = SkGetPackedR32(d);
        int dstG = SkGetPackedG32(d);
        int dstB = SkGetPackedB32(d);

        // LCD blitting is only supported if the dst is known/required
        // to be opaque
        dst[i] = SkPackARGB32(0xFF,
                              SkAlphaBlend(srcR, dstR, maskR),
                              SkAlphaBlend(srcG, dstG, maskG),
                              SkAlphaBlend(srcB, dstB, maskB));
    }
}

static void blit_lcd32_row(SkPMColor* SK_RESTRICT dst,
                           const SkPMColor* SK_RESTRICT src,
                           SkColor color, int width) {
    int srcA = SkColorGetA(color);
    int srcR = SkColorGetR(color);
    int srcG = SkColorGetG(color);
    int srcB = SkColorGetB(color);

    srcA = SkAlpha255To256(srcA);

    for (int i = 0; i < width; i++) {
        SkPMColor mask = src[i];
        if (0 == mask) {
            continue;
        }

        SkPMColor d = dst[i];

        int maskR = SkGetPackedR32(mask);
        int maskG = SkGetPackedG32(mask);
        int maskB = SkGetPackedB32(mask);

        // Now upscale them to 0..256, so we can use SkAlphaBlend
        maskR = SkAlpha255To256(maskR);
        maskG = SkAlpha255To256(maskG);
        maskB = SkAlpha255To256(maskB);

        maskR = maskR * srcA >> 8;
        maskG = maskG * srcA >> 8;
        maskB = maskB * srcA >> 8;

        int dstR = SkGetPackedR32(d);
        int dstG = SkGetPackedG32(d);
        int dstB = SkGetPackedB32(d);

        // LCD blitting is only supported if the dst is known/required
        // to be opaque
        dst[i] = SkPackARGB32(0xFF,
                              SkAlphaBlend(srcR, dstR, maskR),
                              SkAlphaBlend(srcG, dstG, maskG),
                              SkAlphaBlend(srcB, dstB, maskB));
    }
}

static void D32_LCD32_Blend(void* SK_RESTRICT dst, size_t dstRB,
                            const void* SK_RESTRICT mask, size_t maskRB,
                            SkColor color, int width, int height) {
    SkASSERT(height > 0);
    SkPMColor* SK_RESTRICT dstRow = (SkPMColor*)dst;
    const SkPMColor* SK_RESTRICT srcRow = (const SkPMColor*)mask;

    do {
        blit_lcd32_row(dstRow, srcRow, color, width);
        dstRow = (SkPMColor*)((char*)dstRow + dstRB);
        srcRow = (const SkPMColor*)((const char*)srcRow + maskRB);
    } while (--height != 0);
}

static void D32_LCD32_Opaque(void* SK_RESTRICT dst, size_t dstRB,
                             const void* SK_RESTRICT mask, size_t maskRB,
                             SkColor color, int width, int height) {
    SkASSERT(height > 0);
    SkPMColor* SK_RESTRICT dstRow = (SkPMColor*)dst;
    const SkPMColor* SK_RESTRICT srcRow = (const SkPMColor*)mask;

    do {
        blit_lcd32_opaque_row(dstRow, srcRow, color, width);
        dstRow = (SkPMColor*)((char*)dstRow + dstRB);
        srcRow = (const SkPMColor*)((const char*)srcRow + maskRB);
    } while (--height != 0);
}

///////////////////////////////////////////////////////////////////////////////

static SkBlitMask::Proc D32_A8_Factory(SkColor color) {
    if (SK_ColorBLACK == color) {
        return D32_A8_Black;
    } else if (0xFF == SkColorGetA(color)) {
        return D32_A8_Opaque;
    } else {
        return D32_A8_Color;
    }
}

static SkBlitMask::Proc D32_LCD32_Factory(SkColor color) {
    return (0xFF == SkColorGetA(color)) ? D32_LCD32_Opaque : D32_LCD32_Blend;
}

SkBlitMask::Proc SkBlitMask::Factory(SkBitmap::Config config,
                                     SkMask::Format format, SkColor color) {
    SkBlitMask::Proc proc = PlatformProcs(config, format, color);
    if (proc) {
        return proc;
    }

    switch (config) {
        case SkBitmap::kARGB_8888_Config:
            switch (format) {
                case SkMask::kA8_Format:
                    return D32_A8_Factory(color);
                case SkMask::kLCD16_Format:
                    return D32_LCD16_Proc;
                case SkMask::kLCD32_Format:
                    return D32_LCD32_Factory(color);
            }
            break;
        default:
            break;
    }
    return NULL;
}

static const int gMaskFormatToShift[] = {
    ~0, // BW
    0,  // A8
    0,  // 3D
    2,  // ARGB32
    1,  // LCD16
    2   // LCD32
};

static int maskFormatToShift(SkMask::Format format) {
    SkASSERT((unsigned)format < SK_ARRAY_COUNT(gMaskFormatToShift));
    SkASSERT(SkMask::kBW_Format != format);
    return gMaskFormatToShift[format];
}

static const void* getAddr(const SkMask& mask, int x, int y) {
    SkASSERT(mask.fBounds.contains(x, y));
    SkASSERT(mask.fImage);

    const char* addr = (const char*)mask.fImage;
    addr += (y - mask.fBounds.fTop) * mask.fRowBytes;
    addr += (x - mask.fBounds.fLeft) << maskFormatToShift(mask.fFormat);
    return addr;
}

bool SkBlitMask::BlitColor(const SkBitmap& device, const SkMask& mask,
                           const SkIRect& clip, SkColor color) {
    Proc proc = Factory(device.config(), mask.fFormat, color);
    if (proc) {
        int x = clip.fLeft;
        int y = clip.fTop;
        proc(device.getAddr32(x, y), device.rowBytes(), getAddr(mask, x, y),
             mask.fRowBytes, color, clip.width(), clip.height());
        return true;
    }
    return false;
}

<commit_msg>fix warning (add default in switch)<commit_after>#include "SkBlitMask.h"
#include "SkColor.h"
#include "SkColorPriv.h"

static void D32_A8_Color(void* SK_RESTRICT dst, size_t dstRB,
                         const void* SK_RESTRICT maskPtr, size_t maskRB,
                         SkColor color, int width, int height) {
    SkPMColor pmc = SkPreMultiplyColor(color);
    size_t dstOffset = dstRB - (width << 2);
    size_t maskOffset = maskRB - width;
    SkPMColor* SK_RESTRICT device = (SkPMColor *)dst;
    const uint8_t* SK_RESTRICT mask = (const uint8_t*)maskPtr;

    do {
        int w = width;
        do {
            unsigned aa = *mask++;
            *device = SkBlendARGB32(pmc, *device, aa);
            device += 1;
        } while (--w != 0);
        device = (uint32_t*)((char*)device + dstOffset);
        mask += maskOffset;
    } while (--height != 0);
}

static void D32_A8_Opaque(void* SK_RESTRICT dst, size_t dstRB,
                          const void* SK_RESTRICT maskPtr, size_t maskRB,
                          SkColor color, int width, int height) {
    SkPMColor pmc = SkPreMultiplyColor(color);
    SkPMColor* SK_RESTRICT device = (SkPMColor*)dst;
    const uint8_t* SK_RESTRICT mask = (const uint8_t*)maskPtr;

    maskRB -= width;
    dstRB -= (width << 2);
    do {
        int w = width;
        do {
            unsigned aa = *mask++;
            *device = SkAlphaMulQ(pmc, SkAlpha255To256(aa)) + SkAlphaMulQ(*device, SkAlpha255To256(255 - aa));
            device += 1;
        } while (--w != 0);
        device = (uint32_t*)((char*)device + dstRB);
        mask += maskRB;
    } while (--height != 0);
}

static void D32_A8_Black(void* SK_RESTRICT dst, size_t dstRB,
                         const void* SK_RESTRICT maskPtr, size_t maskRB,
                         SkColor, int width, int height) {
    SkPMColor* SK_RESTRICT device = (SkPMColor*)dst;
    const uint8_t* SK_RESTRICT mask = (const uint8_t*)maskPtr;

    maskRB -= width;
    dstRB -= (width << 2);
    do {
        int w = width;
        do {
            unsigned aa = *mask++;
            *device = (aa << SK_A32_SHIFT) + SkAlphaMulQ(*device, SkAlpha255To256(255 - aa));
            device += 1;
        } while (--w != 0);
        device = (uint32_t*)((char*)device + dstRB);
        mask += maskRB;
    } while (--height != 0);
}

///////////////////////////////////////////////////////////////////////////////

static inline int upscale31To32(int value) {
    SkASSERT((unsigned)value <= 31);
    return value + (value >> 4);
}

static inline int blend32(int src, int dst, int scale) {
    SkASSERT((unsigned)src <= 0xFF);
    SkASSERT((unsigned)dst <= 0xFF);
    SkASSERT((unsigned)scale <= 32);
    return dst + ((src - dst) * scale >> 5);
}

static void blit_lcd16_row(SkPMColor dst[], const uint16_t src[],
                           SkColor color, int width, SkPMColor) {
    int srcA = SkColorGetA(color);
    int srcR = SkColorGetR(color);
    int srcG = SkColorGetG(color);
    int srcB = SkColorGetB(color);

    srcA = SkAlpha255To256(srcA);

    for (int i = 0; i < width; i++) {
        uint16_t mask = src[i];
        if (0 == mask) {
            continue;
        }

        SkPMColor d = dst[i];

        /*  We want all of these in 5bits, hence the shifts in case one of them
         *  (green) is 6bits.
         */
        int maskR = SkGetPackedR16(mask) >> (SK_R16_BITS - 5);
        int maskG = SkGetPackedG16(mask) >> (SK_G16_BITS - 5);
        int maskB = SkGetPackedB16(mask) >> (SK_B16_BITS - 5);

        // Now upscale them to 0..32, so we can use blend32
        maskR = upscale31To32(maskR);
        maskG = upscale31To32(maskG);
        maskB = upscale31To32(maskB);

        maskR = maskR * srcA >> 8;
        maskG = maskG * srcA >> 8;
        maskB = maskB * srcA >> 8;

        int dstR = SkGetPackedR32(d);
        int dstG = SkGetPackedG32(d);
        int dstB = SkGetPackedB32(d);

        // LCD blitting is only supported if the dst is known/required\
        // to be opaque
        dst[i] = SkPackARGB32(0xFF,
                              blend32(srcR, dstR, maskR),
                              blend32(srcG, dstG, maskG),
                              blend32(srcB, dstB, maskB));
    }
}

static void blit_lcd16_opaque_row(SkPMColor dst[], const uint16_t src[],
                                  SkColor color, int width, SkPMColor opaqueDst) {
    int srcR = SkColorGetR(color);
    int srcG = SkColorGetG(color);
    int srcB = SkColorGetB(color);

    for (int i = 0; i < width; i++) {
        uint16_t mask = src[i];
        if (0 == mask) {
            continue;
        }
        if (0xFFFF == mask) {
            dst[i] = opaqueDst;
            continue;
        }

        SkPMColor d = dst[i];

        /*  We want all of these in 5bits, hence the shifts in case one of them
         *  (green) is 6bits.
         */
        int maskR = SkGetPackedR16(mask) >> (SK_R16_BITS - 5);
        int maskG = SkGetPackedG16(mask) >> (SK_G16_BITS - 5);
        int maskB = SkGetPackedB16(mask) >> (SK_B16_BITS - 5);

        // Now upscale them to 0..32, so we can use blend32
        maskR = upscale31To32(maskR);
        maskG = upscale31To32(maskG);
        maskB = upscale31To32(maskB);

        int dstR = SkGetPackedR32(d);
        int dstG = SkGetPackedG32(d);
        int dstB = SkGetPackedB32(d);

        // LCD blitting is only supported if the dst is known/required
        // to be opaque
        dst[i] = SkPackARGB32(0xFF,
                              blend32(srcR, dstR, maskR),
                              blend32(srcG, dstG, maskG),
                              blend32(srcB, dstB, maskB));
    }
}

static void D32_LCD16_Proc(void* SK_RESTRICT dst, size_t dstRB,
                           const void* SK_RESTRICT mask, size_t maskRB,
                           SkColor color, int width, int height) {

    SkPMColor*		dstRow = (SkPMColor*)dst;
    const uint16_t* srcRow = (const uint16_t*)mask;
    SkPMColor       opaqueDst;

    void (*proc)(SkPMColor dst[], const uint16_t src[],
                 SkColor color, int width, SkPMColor);
    if (0xFF == SkColorGetA(color)) {
        proc = blit_lcd16_opaque_row;
        opaqueDst = SkPreMultiplyColor(color);
    } else {
        proc = blit_lcd16_row;
        opaqueDst = 0;  // ignored
    }

    do {
        proc(dstRow, srcRow, color, width, opaqueDst);
        dstRow = (SkPMColor*)((char*)dstRow + dstRB);
        srcRow = (const uint16_t*)((const char*)srcRow + maskRB);
    } while (--height != 0);
}

///////////////////////////////////////////////////////////////////////////////

static void blit_lcd32_opaque_row(SkPMColor* SK_RESTRICT dst,
                                  const SkPMColor* SK_RESTRICT src,
                                  SkColor color, int width) {
    int srcR = SkColorGetR(color);
    int srcG = SkColorGetG(color);
    int srcB = SkColorGetB(color);

    for (int i = 0; i < width; i++) {
        SkPMColor mask = src[i];
        if (0 == mask) {
            continue;
        }

        SkPMColor d = dst[i];

        int maskR = SkGetPackedR32(mask);
        int maskG = SkGetPackedG32(mask);
        int maskB = SkGetPackedB32(mask);

        // Now upscale them to 0..256, so we can use SkAlphaBlend
        maskR = SkAlpha255To256(maskR);
        maskG = SkAlpha255To256(maskG);
        maskB = SkAlpha255To256(maskB);

        int dstR = SkGetPackedR32(d);
        int dstG = SkGetPackedG32(d);
        int dstB = SkGetPackedB32(d);

        // LCD blitting is only supported if the dst is known/required
        // to be opaque
        dst[i] = SkPackARGB32(0xFF,
                              SkAlphaBlend(srcR, dstR, maskR),
                              SkAlphaBlend(srcG, dstG, maskG),
                              SkAlphaBlend(srcB, dstB, maskB));
    }
}

static void blit_lcd32_row(SkPMColor* SK_RESTRICT dst,
                           const SkPMColor* SK_RESTRICT src,
                           SkColor color, int width) {
    int srcA = SkColorGetA(color);
    int srcR = SkColorGetR(color);
    int srcG = SkColorGetG(color);
    int srcB = SkColorGetB(color);

    srcA = SkAlpha255To256(srcA);

    for (int i = 0; i < width; i++) {
        SkPMColor mask = src[i];
        if (0 == mask) {
            continue;
        }

        SkPMColor d = dst[i];

        int maskR = SkGetPackedR32(mask);
        int maskG = SkGetPackedG32(mask);
        int maskB = SkGetPackedB32(mask);

        // Now upscale them to 0..256, so we can use SkAlphaBlend
        maskR = SkAlpha255To256(maskR);
        maskG = SkAlpha255To256(maskG);
        maskB = SkAlpha255To256(maskB);

        maskR = maskR * srcA >> 8;
        maskG = maskG * srcA >> 8;
        maskB = maskB * srcA >> 8;

        int dstR = SkGetPackedR32(d);
        int dstG = SkGetPackedG32(d);
        int dstB = SkGetPackedB32(d);

        // LCD blitting is only supported if the dst is known/required
        // to be opaque
        dst[i] = SkPackARGB32(0xFF,
                              SkAlphaBlend(srcR, dstR, maskR),
                              SkAlphaBlend(srcG, dstG, maskG),
                              SkAlphaBlend(srcB, dstB, maskB));
    }
}

static void D32_LCD32_Blend(void* SK_RESTRICT dst, size_t dstRB,
                            const void* SK_RESTRICT mask, size_t maskRB,
                            SkColor color, int width, int height) {
    SkASSERT(height > 0);
    SkPMColor* SK_RESTRICT dstRow = (SkPMColor*)dst;
    const SkPMColor* SK_RESTRICT srcRow = (const SkPMColor*)mask;

    do {
        blit_lcd32_row(dstRow, srcRow, color, width);
        dstRow = (SkPMColor*)((char*)dstRow + dstRB);
        srcRow = (const SkPMColor*)((const char*)srcRow + maskRB);
    } while (--height != 0);
}

static void D32_LCD32_Opaque(void* SK_RESTRICT dst, size_t dstRB,
                             const void* SK_RESTRICT mask, size_t maskRB,
                             SkColor color, int width, int height) {
    SkASSERT(height > 0);
    SkPMColor* SK_RESTRICT dstRow = (SkPMColor*)dst;
    const SkPMColor* SK_RESTRICT srcRow = (const SkPMColor*)mask;

    do {
        blit_lcd32_opaque_row(dstRow, srcRow, color, width);
        dstRow = (SkPMColor*)((char*)dstRow + dstRB);
        srcRow = (const SkPMColor*)((const char*)srcRow + maskRB);
    } while (--height != 0);
}

///////////////////////////////////////////////////////////////////////////////

static SkBlitMask::Proc D32_A8_Factory(SkColor color) {
    if (SK_ColorBLACK == color) {
        return D32_A8_Black;
    } else if (0xFF == SkColorGetA(color)) {
        return D32_A8_Opaque;
    } else {
        return D32_A8_Color;
    }
}

static SkBlitMask::Proc D32_LCD32_Factory(SkColor color) {
    return (0xFF == SkColorGetA(color)) ? D32_LCD32_Opaque : D32_LCD32_Blend;
}

SkBlitMask::Proc SkBlitMask::Factory(SkBitmap::Config config,
                                     SkMask::Format format, SkColor color) {
    SkBlitMask::Proc proc = PlatformProcs(config, format, color);
    if (proc) {
        return proc;
    }

    switch (config) {
        case SkBitmap::kARGB_8888_Config:
            switch (format) {
                case SkMask::kA8_Format:
                    return D32_A8_Factory(color);
                case SkMask::kLCD16_Format:
                    return D32_LCD16_Proc;
                case SkMask::kLCD32_Format:
                    return D32_LCD32_Factory(color);
                default:
                    break;
            }
            break;
        default:
            break;
    }
    return NULL;
}

static const int gMaskFormatToShift[] = {
    ~0, // BW
    0,  // A8
    0,  // 3D
    2,  // ARGB32
    1,  // LCD16
    2   // LCD32
};

static int maskFormatToShift(SkMask::Format format) {
    SkASSERT((unsigned)format < SK_ARRAY_COUNT(gMaskFormatToShift));
    SkASSERT(SkMask::kBW_Format != format);
    return gMaskFormatToShift[format];
}

static const void* getAddr(const SkMask& mask, int x, int y) {
    SkASSERT(mask.fBounds.contains(x, y));
    SkASSERT(mask.fImage);

    const char* addr = (const char*)mask.fImage;
    addr += (y - mask.fBounds.fTop) * mask.fRowBytes;
    addr += (x - mask.fBounds.fLeft) << maskFormatToShift(mask.fFormat);
    return addr;
}

bool SkBlitMask::BlitColor(const SkBitmap& device, const SkMask& mask,
                           const SkIRect& clip, SkColor color) {
    Proc proc = Factory(device.config(), mask.fFormat, color);
    if (proc) {
        int x = clip.fLeft;
        int y = clip.fTop;
        proc(device.getAddr32(x, y), device.rowBytes(), getAddr(mask, x, y),
             mask.fRowBytes, color, clip.width(), clip.height());
        return true;
    }
    return false;
}

<|endoftext|>


<commit_before>#pragma once
//=====================================================================//
/*!	@file
	@brief	RX62N, RX621, RX63T, RX64M グループ・CMT 定義 @n
			Copyright 2013, 2016 Kunihito Hiramatsu
	@author	平松邦仁 (hira@rvf-rc45.net)
*/
//=====================================================================//
#include "common/io_utils.hpp"
#if defined(SIG_RX63T)
#include "RX63T/peripheral.hpp"
#elif defined(SIG_RX64M)
#include "RX64M/peripheral.hpp"
#endif

namespace device {

	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	/*!
		@brief  CMT 定義基底クラス
		@param[in]	base	ベース・アドレス
		@param[in]	t		ペリフェラル
	*/
	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	template <uint32_t base, peripheral t>
	struct cmt_t {

		//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
		/*!
			@brief  CMSTR0 レジスタ
		*/
		//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
		struct cmstr0_t : public rw16_t<0x00088000> {
			typedef rw16_t<0x00088000> io_;
			using io_::operator =;
			using io_::operator ();
			using io_::operator |=;
			using io_::operator &=;

			bit_rw_t<io_, bitpos::B0> STR0;
			bit_rw_t<io_, bitpos::B1> STR1;
		};
		static cmstr0_t	CMSTR0;

		//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
		/*!
			@brief  CMSTR1 レジスタ
		*/
		//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
		struct cmstr1_t : public rw16_t<0x00088010> {
			typedef rw16_t<0x00088010> io_;
			using io_::operator =;
			using io_::operator ();
			using io_::operator |=;
			using io_::operator &=;

			bit_rw_t<io_, bitpos::B0> STR2;
			bit_rw_t<io_, bitpos::B1> STR3;
		};
		static cmstr1_t	CMSTR1;

		//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
		/*!
			@brief  CMCR レジスタ
		*/
		//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
		struct cmcr_t : public rw16_t<base + 0x00> {
			typedef rw16_t<base + 0x00> io_;
			using io_::operator =;
			using io_::operator ();
			using io_::operator |=;
			using io_::operator &=;

			bits_rw_t<io_, bitpos::B0, 2> CKS;
			bit_rw_t <io_, bitpos::B6>    CMIE;
		};
		static cmcr_t CMCR;

		//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
		/*!
			@brief  CMCNT レジスタ
		*/
		//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
		static rw16_t<base + 0x02> CMCNT;

		//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
		/*!
			@brief  CMCOR レジスタ
		*/
		//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
		static rw16_t<base + 0x04> CMCOR;

		//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
		/*!
			@brief  チャネルを返す
			@return チャネル
		*/
		//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
		static uint32_t get_chanel() {
			return (base >> 3) & 3;
		}

		//-----------------------------------------------------------------//
		/*!
			@brief  ペリフェラル型を返す
			@return ペリフェラル型
		*/
		//-----------------------------------------------------------------//
		static peripheral get_peripheral() { return t; }
	};

	typedef cmt_t<0x00088002, peripheral::CMT0> CMT0;
	typedef cmt_t<0x00088008, peripheral::CMT1> CMT1;
	typedef cmt_t<0x00088012, peripheral::CMT2> CMT2;
	typedef cmt_t<0x00088018, peripheral::CMT3> CMT3;
}
<commit_msg>update comment<commit_after>#pragma once
//=====================================================================//
/*!	@file
	@brief	RX62N, RX621, RX63T, RX64M グループ・CMT 定義 @n
			Copyright 2013, 2016 Kunihito Hiramatsu
	@author	平松邦仁 (hira@rvf-rc45.net)
*/
//=====================================================================//
#include "common/io_utils.hpp"
#if defined(SIG_RX63T)
#include "RX63T/peripheral.hpp"
#elif defined(SIG_RX64M)
#include "RX64M/peripheral.hpp"
#elif defined(SIG_RX24T)
#include "RX24T/peripheral.hpp"
#endif

namespace device {

	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	/*!
		@brief  CMT 定義基底クラス
		@param[in]	base	ベース・アドレス
		@param[in]	t		ペリフェラル
	*/
	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	template <uint32_t base, peripheral t>
	struct cmt_t {

		//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
		/*!
			@brief  CMSTR0 レジスタ
		*/
		//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
		struct cmstr0_t : public rw16_t<0x00088000> {
			typedef rw16_t<0x00088000> io_;
			using io_::operator =;
			using io_::operator ();
			using io_::operator |=;
			using io_::operator &=;

			bit_rw_t<io_, bitpos::B0> STR0;
			bit_rw_t<io_, bitpos::B1> STR1;
		};
		static cmstr0_t	CMSTR0;

		//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
		/*!
			@brief  CMSTR1 レジスタ
		*/
		//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
		struct cmstr1_t : public rw16_t<0x00088010> {
			typedef rw16_t<0x00088010> io_;
			using io_::operator =;
			using io_::operator ();
			using io_::operator |=;
			using io_::operator &=;

			bit_rw_t<io_, bitpos::B0> STR2;
			bit_rw_t<io_, bitpos::B1> STR3;
		};
		static cmstr1_t	CMSTR1;

		//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
		/*!
			@brief  CMCR レジスタ
		*/
		//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
		struct cmcr_t : public rw16_t<base + 0x00> {
			typedef rw16_t<base + 0x00> io_;
			using io_::operator =;
			using io_::operator ();
			using io_::operator |=;
			using io_::operator &=;

			bits_rw_t<io_, bitpos::B0, 2> CKS;
			bit_rw_t <io_, bitpos::B6>    CMIE;
		};
		static cmcr_t CMCR;

		//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
		/*!
			@brief  CMCNT レジスタ
		*/
		//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
		static rw16_t<base + 0x02> CMCNT;

		//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
		/*!
			@brief  CMCOR レジスタ
		*/
		//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
		static rw16_t<base + 0x04> CMCOR;

		//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
		/*!
			@brief  チャネルを返す
			@return チャネル
		*/
		//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
		static uint32_t get_chanel() {
			return (base >> 3) & 3;
		}

		//-----------------------------------------------------------------//
		/*!
			@brief  ペリフェラル型を返す
			@return ペリフェラル型
		*/
		//-----------------------------------------------------------------//
		static peripheral get_peripheral() { return t; }
	};

	typedef cmt_t<0x00088002, peripheral::CMT0> CMT0;
	typedef cmt_t<0x00088008, peripheral::CMT1> CMT1;
	typedef cmt_t<0x00088012, peripheral::CMT2> CMT2;
	typedef cmt_t<0x00088018, peripheral::CMT3> CMT3;
}
<|endoftext|>


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

#include <inttypes.h>
#include "string.h"

#include "stats.h"
#include "log.h"
#define CLASS_MODULE "stats"

#define DBG 0

#define dprintf(fmt, arg...) __dprintf(DBG_STATS, "(%s) "fmt, parent, ##arg)

stats::stats(const char *caller)
  : tei_count(0)
  , __timenow(0)
  , parent(caller)
  , streamtime_cb(NULL)
  , streamtime_priv(NULL)
  , statistics_cb(NULL)
  , statistics_priv(NULL)
{
	dprintf("(%s)", parent);
}

stats::~stats()
{
	dprintf("(%s)", parent);
	show(false);
}

#if 0
stats::stats(const stats&)
{
	dprintf("(%s, copy)", parent);
}

stats& stats::operator= (const stats& cSource)
{
	dprintf("(%s, operator=)", parent);

	if (this == &cSource)
		return *this;

	return *this;
}
#endif

static void parse_pcr(uint8_t *pcr, uint64_t *pcr_base, unsigned int *pcr_ext)
{
	*pcr_base = (pcr[0] * 0x2000000) +
		    (pcr[1] * 0x20000) +
		    (pcr[2] * 0x200) +
		    (pcr[3] * 0x02) +
		    ((pcr[4] & 0x80) >> 7);

	*pcr_ext = ((pcr[4] & 0x01) * 0x100) + pcr[5];

	return;
}

static time_t walltime(void *p) { return time(NULL); }

char *stats_scale_unit(char *b, size_t n, uint64_t x)
{
	memset(b, 0, n);

	if (x >= 1000000) {
		if ((x % 1000000) < 100)
			snprintf(b, n, "%3" PRIu64 ".%03" PRIu64 " m", x / 1000000, x % 1000000);
		else
			snprintf(b, n, "%3" PRIu64 ".%03" PRIu64 " m", x / 1000000, x % 1000000);
	} else if (x >= 1000) {
		if ((x % 1000) < 100)
			snprintf(b, n, "%3" PRIu64 ".%03" PRIu64 " k", x / 1000, x % 1000);
		else
			snprintf(b, n, "%3" PRIu64 ".%03" PRIu64 " k", x / 1000, x % 1000);
	} else
		snprintf(b, n, "    %3" PRIu64 "  ", x);
	return b;
}

void stats::show(bool per_sec)
{
	if (statistics_cb) {
		statistics_cb(statistics_priv, statistics, discontinuities, tei_count, per_sec);
		return;
	}
	for (stats_map::const_iterator iter = statistics.begin(); iter != statistics.end(); ++iter) {
		char a[16];
		char b[16];
		dprintf("pid %04x %5" PRIu64 " p%s  %sb%s  %sbit",
			iter->first, iter->second / 188, (per_sec) ? "/s" : "",
			stats_scale_unit(a, sizeof(a), iter->second), (per_sec) ? "/s" : "",
			stats_scale_unit(b, sizeof(b), iter->second * 8));
	}
	for (stats_map::const_iterator iter = discontinuities.begin(); iter != discontinuities.end(); ++iter)
		dprintf("pid %04x\t%" PRIu64 " continuity errors (%" PRIu64 "%%)", iter->first, iter->second, ((!iter->second) || (!statistics[iter->first])) ? 0 : (!statistics.count(iter->first)) ? 0 : (100 * iter->second / (statistics[iter->first] / 188)));

	if (tei_count) dprintf("tei count: %" PRIu64 " (%" PRIu64 "%%)", tei_count, (!statistics[0x2000]) ? 0 : (18800 * tei_count / statistics[0x2000]));
}

void stats::push_pid(int c, const uint16_t pid)
{
	streamtime_callback cb = (streamtime_cb) ? streamtime_cb : &walltime;
	time_t timenow = cb(streamtime_priv);

	if (timenow > __timenow) {
		show();
		clear_stats();
		__timenow = timenow;
	}

	__push_pid(c, pid);
}

pkt_stats_t *stats::parse(const uint8_t *p, pkt_stats_t *pkt_stats)
{
	if (pkt_stats) {
		memset(pkt_stats, 0, sizeof(pkt_stats));

		const uint8_t *q = p;

		hdr.sync_byte          = q[0];
		hdr.tei                = (q[1] & 0x80) >> 7;
		hdr.payload_unit_start = (q[1] & 0x40) >> 6;
		hdr.transport_priority = (q[1] & 0x20) >> 5;
		hdr.pid                = ((q[1] & 0x1f) << 8) | q[2];
		hdr.scrambling         = (q[3] & 0xc0) >> 6;
		hdr.adaptation_flags   = (q[3] & 0x30) >> 4;
		hdr.continuity_ctr     = (q[3] & 0x0f);

		if (hdr.adaptation_flags & 0x02) {
			q += 4;
			adapt.field_length   = q[0];
			adapt.discontinuity  = (q[1] & 0x80) >> 7;
			adapt.random_access  = (q[1] & 0x40) >> 6; /* set to 1 if the PES pkt in this TS pkt starts an a/v sequence */
			adapt.es_priority    = (q[1] & 0x20) >> 5;
			adapt.pcr            = (q[1] & 0x10) >> 4;
			adapt.opcr           = (q[1] & 0x08) >> 3;
			adapt.splicing_point = (q[1] & 0x04) >> 2;
			adapt.tp_priv_data   = (q[1] & 0x02) >> 1;
			adapt.field_ext      = (q[1] & 0x01) >> 0;

			if (adapt.pcr) {
				memcpy(adapt.PCR, &q[2], 6);
				q += 6;
			}
			if (adapt.opcr) {
				memcpy(adapt.OPCR, &q[2], 6);
				q += 6;
			}
			if (adapt.splicing_point) {
				adapt.splicing_countdown = q[2];
				q ++;
			}
		}

		pkt_stats->sync_loss = (hdr.sync_byte != 0x47) ? true : false;
		if (!pkt_stats->sync_loss) {
			pkt_stats->tei = (hdr.tei) ? true : false;
			pkt_stats->pid = hdr.pid;
		} else
			pkt_stats->pid = (uint16_t) - 1;
	}
	return pkt_stats;
}

void stats::clear_stats()
{
	statistics.clear();
	discontinuities.clear();
	last_pcr_base.clear();
	tei_count = 0;
}

void stats::push_stats(pkt_stats_t *pkt_stats)
{
	if (pkt_stats->tei) {
		tei_count++;
		push_pid((uint16_t) - 1);
	} else
		push_pid(pkt_stats->pid);
}

void stats::push(const uint8_t *p, pkt_stats_t *pkt_stats)
{
	if (!pkt_stats) {
		__push(p);
		return;
	}

	memset(pkt_stats, 0, sizeof(pkt_stats));

	parse(p, pkt_stats);

	if (hdr.adaptation_flags & 0x01) {// payload present
		if (continuity.count(hdr.pid)) {
			uint8_t next = (continuity[hdr.pid] + 1) & 0x0f;
			if ((next != (hdr.continuity_ctr & 0x0f)) && (hdr.continuity_ctr + continuity[hdr.pid] > 0)) {
				if (!(hdr.adaptation_flags & 0x02) && (adapt.discontinuity)) {
					push_discontinuity(hdr.pid);
#if DBG
					dprintf("CONTINUITY ERROR pid: %04x cur: 0x%x prev 0x%x", hdr.pid, hdr.continuity_ctr, continuity[hdr.pid]);
#endif
				}
			}
		}
		continuity[hdr.pid] = hdr.continuity_ctr;
	}

	if (hdr.adaptation_flags & 0x02) {
		if (adapt.pcr) {
			uint64_t pcr_base;
			unsigned int pcr_ext;

			parse_pcr(adapt.PCR, &pcr_base, &pcr_ext);
			dprintf("PID: 0x%04x, PCR base: %" PRIu64 ", ext: %d", hdr.pid, pcr_base, pcr_ext);

			stats_map::const_iterator iter = last_pcr_base.find(hdr.pid);
#if DBG
			if ((iter != last_pcr_base.end()) && (pcr_base < iter->second))
				fprintf(stderr, "%s: PID: 0x%04x, %" PRIu64 " < %" PRIu64 " !!!\n",
					__func__, hdr.pid, pcr_base, iter->second);
#endif
			last_pcr_base[hdr.pid] = pcr_base;
		}
		if (adapt.opcr) {
			uint64_t pcr_base;
			unsigned int pcr_ext;

			parse_pcr(adapt.OPCR, &pcr_base, &pcr_ext);
			dprintf("PID: 0x%04x, PCR base: %" PRIu64 ", ext: %d", hdr.pid, pcr_base, pcr_ext);
		}
		if (adapt.splicing_point) {
			dprintf("PID: 0x%04x, splicing countdown: %d", hdr.pid, adapt.splicing_countdown);
		}
	}

	push_stats(pkt_stats);
}
<commit_msg>stats: fix warning: argument to ‘sizeof’ in ‘void* memset(void*, int, size_t)’ call is the same expression as the destination; did you mean to dereference it? [-Wsizeof-pointer-memaccess]<commit_after>/*****************************************************************************
 * Copyright (C) 2011-2013 Michael Krufky
 *
 * Author: Michael Krufky <mkrufky@linuxtv.org>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

#include <inttypes.h>
#include "string.h"

#include "stats.h"
#include "log.h"
#define CLASS_MODULE "stats"

#define DBG 0

#define dprintf(fmt, arg...) __dprintf(DBG_STATS, "(%s) "fmt, parent, ##arg)

stats::stats(const char *caller)
  : tei_count(0)
  , __timenow(0)
  , parent(caller)
  , streamtime_cb(NULL)
  , streamtime_priv(NULL)
  , statistics_cb(NULL)
  , statistics_priv(NULL)
{
	dprintf("(%s)", parent);
}

stats::~stats()
{
	dprintf("(%s)", parent);
	show(false);
}

#if 0
stats::stats(const stats&)
{
	dprintf("(%s, copy)", parent);
}

stats& stats::operator= (const stats& cSource)
{
	dprintf("(%s, operator=)", parent);

	if (this == &cSource)
		return *this;

	return *this;
}
#endif

static void parse_pcr(uint8_t *pcr, uint64_t *pcr_base, unsigned int *pcr_ext)
{
	*pcr_base = (pcr[0] * 0x2000000) +
		    (pcr[1] * 0x20000) +
		    (pcr[2] * 0x200) +
		    (pcr[3] * 0x02) +
		    ((pcr[4] & 0x80) >> 7);

	*pcr_ext = ((pcr[4] & 0x01) * 0x100) + pcr[5];

	return;
}

static time_t walltime(void *p) { return time(NULL); }

char *stats_scale_unit(char *b, size_t n, uint64_t x)
{
	memset(b, 0, n);

	if (x >= 1000000) {
		if ((x % 1000000) < 100)
			snprintf(b, n, "%3" PRIu64 ".%03" PRIu64 " m", x / 1000000, x % 1000000);
		else
			snprintf(b, n, "%3" PRIu64 ".%03" PRIu64 " m", x / 1000000, x % 1000000);
	} else if (x >= 1000) {
		if ((x % 1000) < 100)
			snprintf(b, n, "%3" PRIu64 ".%03" PRIu64 " k", x / 1000, x % 1000);
		else
			snprintf(b, n, "%3" PRIu64 ".%03" PRIu64 " k", x / 1000, x % 1000);
	} else
		snprintf(b, n, "    %3" PRIu64 "  ", x);
	return b;
}

void stats::show(bool per_sec)
{
	if (statistics_cb) {
		statistics_cb(statistics_priv, statistics, discontinuities, tei_count, per_sec);
		return;
	}
	for (stats_map::const_iterator iter = statistics.begin(); iter != statistics.end(); ++iter) {
		char a[16];
		char b[16];
		dprintf("pid %04x %5" PRIu64 " p%s  %sb%s  %sbit",
			iter->first, iter->second / 188, (per_sec) ? "/s" : "",
			stats_scale_unit(a, sizeof(a), iter->second), (per_sec) ? "/s" : "",
			stats_scale_unit(b, sizeof(b), iter->second * 8));
	}
	for (stats_map::const_iterator iter = discontinuities.begin(); iter != discontinuities.end(); ++iter)
		dprintf("pid %04x\t%" PRIu64 " continuity errors (%" PRIu64 "%%)", iter->first, iter->second, ((!iter->second) || (!statistics[iter->first])) ? 0 : (!statistics.count(iter->first)) ? 0 : (100 * iter->second / (statistics[iter->first] / 188)));

	if (tei_count) dprintf("tei count: %" PRIu64 " (%" PRIu64 "%%)", tei_count, (!statistics[0x2000]) ? 0 : (18800 * tei_count / statistics[0x2000]));
}

void stats::push_pid(int c, const uint16_t pid)
{
	streamtime_callback cb = (streamtime_cb) ? streamtime_cb : &walltime;
	time_t timenow = cb(streamtime_priv);

	if (timenow > __timenow) {
		show();
		clear_stats();
		__timenow = timenow;
	}

	__push_pid(c, pid);
}

pkt_stats_t *stats::parse(const uint8_t *p, pkt_stats_t *pkt_stats)
{
	if (pkt_stats) {
		memset(pkt_stats, 0, sizeof(pkt_stats_t));

		const uint8_t *q = p;

		hdr.sync_byte          = q[0];
		hdr.tei                = (q[1] & 0x80) >> 7;
		hdr.payload_unit_start = (q[1] & 0x40) >> 6;
		hdr.transport_priority = (q[1] & 0x20) >> 5;
		hdr.pid                = ((q[1] & 0x1f) << 8) | q[2];
		hdr.scrambling         = (q[3] & 0xc0) >> 6;
		hdr.adaptation_flags   = (q[3] & 0x30) >> 4;
		hdr.continuity_ctr     = (q[3] & 0x0f);

		if (hdr.adaptation_flags & 0x02) {
			q += 4;
			adapt.field_length   = q[0];
			adapt.discontinuity  = (q[1] & 0x80) >> 7;
			adapt.random_access  = (q[1] & 0x40) >> 6; /* set to 1 if the PES pkt in this TS pkt starts an a/v sequence */
			adapt.es_priority    = (q[1] & 0x20) >> 5;
			adapt.pcr            = (q[1] & 0x10) >> 4;
			adapt.opcr           = (q[1] & 0x08) >> 3;
			adapt.splicing_point = (q[1] & 0x04) >> 2;
			adapt.tp_priv_data   = (q[1] & 0x02) >> 1;
			adapt.field_ext      = (q[1] & 0x01) >> 0;

			if (adapt.pcr) {
				memcpy(adapt.PCR, &q[2], 6);
				q += 6;
			}
			if (adapt.opcr) {
				memcpy(adapt.OPCR, &q[2], 6);
				q += 6;
			}
			if (adapt.splicing_point) {
				adapt.splicing_countdown = q[2];
				q ++;
			}
		}

		pkt_stats->sync_loss = (hdr.sync_byte != 0x47) ? true : false;
		if (!pkt_stats->sync_loss) {
			pkt_stats->tei = (hdr.tei) ? true : false;
			pkt_stats->pid = hdr.pid;
		} else
			pkt_stats->pid = (uint16_t) - 1;
	}
	return pkt_stats;
}

void stats::clear_stats()
{
	statistics.clear();
	discontinuities.clear();
	last_pcr_base.clear();
	tei_count = 0;
}

void stats::push_stats(pkt_stats_t *pkt_stats)
{
	if (pkt_stats->tei) {
		tei_count++;
		push_pid((uint16_t) - 1);
	} else
		push_pid(pkt_stats->pid);
}

void stats::push(const uint8_t *p, pkt_stats_t *pkt_stats)
{
	if (!pkt_stats) {
		__push(p);
		return;
	}

	memset(pkt_stats, 0, sizeof(pkt_stats_t));

	parse(p, pkt_stats);

	if (hdr.adaptation_flags & 0x01) {// payload present
		if (continuity.count(hdr.pid)) {
			uint8_t next = (continuity[hdr.pid] + 1) & 0x0f;
			if ((next != (hdr.continuity_ctr & 0x0f)) && (hdr.continuity_ctr + continuity[hdr.pid] > 0)) {
				if (!(hdr.adaptation_flags & 0x02) && (adapt.discontinuity)) {
					push_discontinuity(hdr.pid);
#if DBG
					dprintf("CONTINUITY ERROR pid: %04x cur: 0x%x prev 0x%x", hdr.pid, hdr.continuity_ctr, continuity[hdr.pid]);
#endif
				}
			}
		}
		continuity[hdr.pid] = hdr.continuity_ctr;
	}

	if (hdr.adaptation_flags & 0x02) {
		if (adapt.pcr) {
			uint64_t pcr_base;
			unsigned int pcr_ext;

			parse_pcr(adapt.PCR, &pcr_base, &pcr_ext);
			dprintf("PID: 0x%04x, PCR base: %" PRIu64 ", ext: %d", hdr.pid, pcr_base, pcr_ext);

			stats_map::const_iterator iter = last_pcr_base.find(hdr.pid);
#if DBG
			if ((iter != last_pcr_base.end()) && (pcr_base < iter->second))
				fprintf(stderr, "%s: PID: 0x%04x, %" PRIu64 " < %" PRIu64 " !!!\n",
					__func__, hdr.pid, pcr_base, iter->second);
#endif
			last_pcr_base[hdr.pid] = pcr_base;
		}
		if (adapt.opcr) {
			uint64_t pcr_base;
			unsigned int pcr_ext;

			parse_pcr(adapt.OPCR, &pcr_base, &pcr_ext);
			dprintf("PID: 0x%04x, PCR base: %" PRIu64 ", ext: %d", hdr.pid, pcr_base, pcr_ext);
		}
		if (adapt.splicing_point) {
			dprintf("PID: 0x%04x, splicing countdown: %d", hdr.pid, adapt.splicing_countdown);
		}
	}

	push_stats(pkt_stats);
}
<|endoftext|>