<commit_before>//------------------------------------------------------------------------------
// Includes
//------------------------------------------------------------------------------

#include "PIDController.h"

//------------------------------------------------------------------------------
// Constructors
//------------------------------------------------------------------------------

// Default constructor
PIDController::PIDController() {
    this->setGains(0, 0, 0);
    this->setInputLimits(-1, -1);
    this->setOutputLimits(-1, -1);
    lastControlVariable = 0;
    lastProcessVariable = 0;
    this->reset();
    this->off();
}

// Just gains, no limits
PIDController::PIDController(double kp, double ki, double kd) {
    this->setGains(kp, ki, kd);
    this->setInputLimits(-1, -1);
    this->setOutputLimits(-1, -1);
    lastControlVariable = 0;
    lastProcessVariable = 0;
    this->reset();
    this->off();
}
// Gains and output limits
PIDController::PIDController(double kp, double ki, double kd, double lowerOutputLimit, double upperOutputLimit) {
    this->setGains(kp, ki, kd);
    this->setInputLimits(-1, -1);
    this->setOutputLimits(lowerOutputLimit, upperOutputLimit);
    lastControlVariable = 0;
    lastProcessVariable = 0;
    this->reset();
    this->off();
}

// All gains and limits
PIDController::PIDController(double kp, double ki, double kd, double lowerInputLimit, double upperInputLimit, double lowerOutputLimit, double upperOutputLimit) {
    this->setGains(kp, ki, kd);
    this->setInputLimits(lowerInputLimit, upperInputLimit);
    this->setOutputLimits(lowerOutputLimit, upperOutputLimit);
    lastControlVariable = 0;
    lastProcessVariable = 0;
    this->reset();
    this->off();
}

// Copy constructor
PIDController::PIDController(const PIDController& orig) {
    this->setGains(orig.kp, orig.ki, orig.kd);
    this->setInputLimits(orig.lowerInputLimit, orig.upperInputLimit);
    this->setOutputLimits(orig.lowerOutputLimit, orig.lowerInputLimit);
    lastControlVariable = 0;
    lastProcessVariable = 0;
    this->reset();
    this->off();
}

// Destructor
PIDController::~PIDController() {
}

//------------------------------------------------------------------------------
// Accessors
//------------------------------------------------------------------------------

double PIDController::getSetpoint() {
    return setpoint;
}

double PIDController::getKp() {
    return kp;
}

double PIDController::getKi() {
    return ki;
}

double PIDController::getKd() {
    return kd;
}

//------------------------------------------------------------------------------
// Mutators
//------------------------------------------------------------------------------

//------------------------------------------------------------------------------
// targetSetpoint
//------------------------------------------------------------------------------
//
// Return Value : None
// Parameters   : setpoint
//
// This function sets the desired setpoint that the PID controller will
// attempt to track.
//------------------------------------------------------------------------------

void PIDController::targetSetpoint(double setpoint) {
    this->setpoint = limiter(setpoint, lowerInputLimit, upperInputLimit);
    sample_timer.start();
}

//------------------------------------------------------------------------------
// setGains
//------------------------------------------------------------------------------
//
// Return Value : None
// Parameters   : kp, ki, kd
//
// This function sets the control gains of the PID controller in order to
// achieve the desired performance characteristics.
//------------------------------------------------------------------------------

void PIDController::setGains(double kp, double ki, double kd) {
    this->kp = kp;
    this->ki = ki;
    this->kd = kd;
}

//------------------------------------------------------------------------------
// setInputLimits
//------------------------------------------------------------------------------
//
// Return Value : None
// Parameters   : lowerInputLimit, upperInputLimit
//
// This function allows the user to set bounds on the setpoint to prevent
// undesirable behavior of the system.
//------------------------------------------------------------------------------

void PIDController::setInputLimits(double lowerInputLimit, double upperInputLimit) {
    this->lowerInputLimit = lowerInputLimit;
    this->upperInputLimit = upperInputLimit;
}

//------------------------------------------------------------------------------
// setOutputLimits
//------------------------------------------------------------------------------
//
// Return Value : None
// Parameters   : lowerOutputLimit, upperOutputLimit
//
// This function allows the user to set bounds on the control variable to
// prevent undesirable behavior of the system.
//------------------------------------------------------------------------------

void PIDController::setOutputLimits(double lowerOutputLimit, double upperOutputLimit) {
    this->lowerOutputLimit = lowerOutputLimit;
    this->upperOutputLimit = upperOutputLimit;
}

//------------------------------------------------------------------------------
// Other Functions
//------------------------------------------------------------------------------

//------------------------------------------------------------------------------
// off
//------------------------------------------------------------------------------
//
// Return Value : None
// Parameters   : None
//
// This function disables the PID controller for adjustment of the plant through
// an external process.
//------------------------------------------------------------------------------

void PIDController::off() {
    isEnabled = false;
    setpointReached = false;
}

//------------------------------------------------------------------------------
// on
//------------------------------------------------------------------------------
//
// Return Value : None
// Parameters   : None
//
// This function re-enables the PID controller after it has been disabled by the
// off() function.
//------------------------------------------------------------------------------

void PIDController::on() {
    isEnabled = true;
    integrator = lastControlVariable;
    sample_timer.stop();
    this->targetSetpoint(setpoint);
}

//------------------------------------------------------------------------------
// limiter
//------------------------------------------------------------------------------
//
// Return Value : double
// Parameters   : value, lowerLimit, upperLimit
//
// This function compares the input 'value' to the specified limits. If the
// value exceeds the limits, the value is capped to one of the limits.
//------------------------------------------------------------------------------

double PIDController::limiter(double value, double lowerLimit, double upperLimit) {
    if (lowerLimit == upperLimit) {
        return value;
    }
    else if(value < lowerLimit) {
        return lowerLimit;
    }
    else if(value > upperLimit) {
        return upperLimit;
    }
    else
        return value;
}

//------------------------------------------------------------------------------
// reset
//------------------------------------------------------------------------------
//
// Return Value : None
// Parameters   : None
//
// This function initializes the PID controller to the default values.
//------------------------------------------------------------------------------

void PIDController::reset() {
    setpoint = 0;
    lastSetpoint = 0;
    integrator = lastControlVariable;
    sample_timer.stop();
}

//------------------------------------------------------------------------------
// hasSettled
//------------------------------------------------------------------------------
//
// Return Value : bool
// Parameters   : None
//
// This function returns true only when the PID controller has stabilized to
// within 5% of its final value.
//------------------------------------------------------------------------------

bool PIDController::hasSettled() {
    return setpointReached;
}

//------------------------------------------------------------------------------
// calc
//------------------------------------------------------------------------------
//
// Return Value : double
// Parameters   : processVariable
//
// This function calculates the next output value of the PID controller, given
// the current setpoint, elasped time, and feedback (processVariable). It also
// keeps track of peak time, settling time, and percent overshoot for quickly
// assessing the current performance of the controller.
//------------------------------------------------------------------------------

double PIDController::calc(double processVariable) {
    if(!isEnabled) {
        return lastControlVariable;
    }
    sample_timer.stop();

    double error = setpoint - processVariable;
    double samplingTime = (sample_timer.elapsed().wall)/1e9;

    double diffProcessVariable = (processVariable - lastProcessVariable)/samplingTime;
    double percent = (processVariable/setpoint) - 1;

    if(abs(diffProcessVariable) < 0.5) {
		setpointReached = true;
	}
	else {
		setpointReached = false;
	}

    double differentiator = (setpoint - lastSetpoint)/samplingTime;
    integrator += (error * samplingTime);
    integrator = limiter(integrator, lowerOutputLimit, upperOutputLimit);
    double controlVariable = kp * error + ki * integrator - kd * differentiator;

    controlVariable = limiter(controlVariable, lowerOutputLimit, upperOutputLimit);
    lastControlVariable = controlVariable;
    lastSetpoint = setpoint;
    lastProcessVariable = processVariable;

    sample_timer.start();

    return controlVariable;
}
<commit_msg>Add targetSetpoint check<commit_after>//------------------------------------------------------------------------------
// Includes
//------------------------------------------------------------------------------

#include "PIDController.h"

//------------------------------------------------------------------------------
// Constructors
//------------------------------------------------------------------------------

// Default constructor
PIDController::PIDController() {
    this->setGains(0, 0, 0);
    this->setInputLimits(-1, -1);
    this->setOutputLimits(-1, -1);
    lastControlVariable = 0;
    lastProcessVariable = 0;
    this->reset();
    this->off();
}

// Just gains, no limits
PIDController::PIDController(double kp, double ki, double kd) {
    this->setGains(kp, ki, kd);
    this->setInputLimits(-1, -1);
    this->setOutputLimits(-1, -1);
    lastControlVariable = 0;
    lastProcessVariable = 0;
    this->reset();
    this->off();
}
// Gains and output limits
PIDController::PIDController(double kp, double ki, double kd, double lowerOutputLimit, double upperOutputLimit) {
    this->setGains(kp, ki, kd);
    this->setInputLimits(-1, -1);
    this->setOutputLimits(lowerOutputLimit, upperOutputLimit);
    lastControlVariable = 0;
    lastProcessVariable = 0;
    this->reset();
    this->off();
}

// All gains and limits
PIDController::PIDController(double kp, double ki, double kd, double lowerInputLimit, double upperInputLimit, double lowerOutputLimit, double upperOutputLimit) {
    this->setGains(kp, ki, kd);
    this->setInputLimits(lowerInputLimit, upperInputLimit);
    this->setOutputLimits(lowerOutputLimit, upperOutputLimit);
    lastControlVariable = 0;
    lastProcessVariable = 0;
    this->reset();
    this->off();
}

// Copy constructor
PIDController::PIDController(const PIDController& orig) {
    this->setGains(orig.kp, orig.ki, orig.kd);
    this->setInputLimits(orig.lowerInputLimit, orig.upperInputLimit);
    this->setOutputLimits(orig.lowerOutputLimit, orig.lowerInputLimit);
    lastControlVariable = 0;
    lastProcessVariable = 0;
    this->reset();
    this->off();
}

// Destructor
PIDController::~PIDController() {
}

//------------------------------------------------------------------------------
// Accessors
//------------------------------------------------------------------------------

double PIDController::getSetpoint() {
    return setpoint;
}

double PIDController::getKp() {
    return kp;
}

double PIDController::getKi() {
    return ki;
}

double PIDController::getKd() {
    return kd;
}

//------------------------------------------------------------------------------
// Mutators
//------------------------------------------------------------------------------

//------------------------------------------------------------------------------
// targetSetpoint
//------------------------------------------------------------------------------
//
// Return Value : None
// Parameters   : setpoint
//
// This function sets the desired setpoint that the PID controller will
// attempt to track.
//------------------------------------------------------------------------------

void PIDController::targetSetpoint(double setpoint) {
    setpoint = limiter(setpoint, lowerInputLimit, upperInputLimit);
    if(setpoint != this->setpoint) {
        this->setpoint = newSetpoint;
        sample_timer.start();
    }
}

//------------------------------------------------------------------------------
// setGains
//------------------------------------------------------------------------------
//
// Return Value : None
// Parameters   : kp, ki, kd
//
// This function sets the control gains of the PID controller in order to
// achieve the desired performance characteristics.
//------------------------------------------------------------------------------

void PIDController::setGains(double kp, double ki, double kd) {
    this->kp = kp;
    this->ki = ki;
    this->kd = kd;
}

//------------------------------------------------------------------------------
// setInputLimits
//------------------------------------------------------------------------------
//
// Return Value : None
// Parameters   : lowerInputLimit, upperInputLimit
//
// This function allows the user to set bounds on the setpoint to prevent
// undesirable behavior of the system.
//------------------------------------------------------------------------------

void PIDController::setInputLimits(double lowerInputLimit, double upperInputLimit) {
    this->lowerInputLimit = lowerInputLimit;
    this->upperInputLimit = upperInputLimit;
}

//------------------------------------------------------------------------------
// setOutputLimits
//------------------------------------------------------------------------------
//
// Return Value : None
// Parameters   : lowerOutputLimit, upperOutputLimit
//
// This function allows the user to set bounds on the control variable to
// prevent undesirable behavior of the system.
//------------------------------------------------------------------------------

void PIDController::setOutputLimits(double lowerOutputLimit, double upperOutputLimit) {
    this->lowerOutputLimit = lowerOutputLimit;
    this->upperOutputLimit = upperOutputLimit;
}

//------------------------------------------------------------------------------
// Other Functions
//------------------------------------------------------------------------------

//------------------------------------------------------------------------------
// off
//------------------------------------------------------------------------------
//
// Return Value : None
// Parameters   : None
//
// This function disables the PID controller for adjustment of the plant through
// an external process.
//------------------------------------------------------------------------------

void PIDController::off() {
    isEnabled = false;
    setpointReached = false;
}

//------------------------------------------------------------------------------
// on
//------------------------------------------------------------------------------
//
// Return Value : None
// Parameters   : None
//
// This function re-enables the PID controller after it has been disabled by the
// off() function.
//------------------------------------------------------------------------------

void PIDController::on() {
    isEnabled = true;
    integrator = lastControlVariable;
    sample_timer.stop();
    this->targetSetpoint(setpoint);
}

//------------------------------------------------------------------------------
// limiter
//------------------------------------------------------------------------------
//
// Return Value : double
// Parameters   : value, lowerLimit, upperLimit
//
// This function compares the input 'value' to the specified limits. If the
// value exceeds the limits, the value is capped to one of the limits.
//------------------------------------------------------------------------------

double PIDController::limiter(double value, double lowerLimit, double upperLimit) {
    if (lowerLimit == upperLimit) {
        return value;
    }
    else if(value < lowerLimit) {
        return lowerLimit;
    }
    else if(value > upperLimit) {
        return upperLimit;
    }
    else
        return value;
}

//------------------------------------------------------------------------------
// reset
//------------------------------------------------------------------------------
//
// Return Value : None
// Parameters   : None
//
// This function initializes the PID controller to the default values.
//------------------------------------------------------------------------------

void PIDController::reset() {
    setpoint = 0;
    lastSetpoint = 0;
    integrator = lastControlVariable;
    sample_timer.stop();
}

//------------------------------------------------------------------------------
// hasSettled
//------------------------------------------------------------------------------
//
// Return Value : bool
// Parameters   : None
//
// This function returns true only when the PID controller has stabilized to
// within 5% of its final value.
//------------------------------------------------------------------------------

bool PIDController::hasSettled() {
    return setpointReached;
}

//------------------------------------------------------------------------------
// calc
//------------------------------------------------------------------------------
//
// Return Value : double
// Parameters   : processVariable
//
// This function calculates the next output value of the PID controller, given
// the current setpoint, elasped time, and feedback (processVariable). It also
// keeps track of peak time, settling time, and percent overshoot for quickly
// assessing the current performance of the controller.
//------------------------------------------------------------------------------

double PIDController::calc(double processVariable) {
    if(!isEnabled) {
        return lastControlVariable;
    }
    sample_timer.stop();

    double error = setpoint - processVariable;
    double samplingTime = (sample_timer.elapsed().wall)/1e9;

    double diffProcessVariable = (processVariable - lastProcessVariable)/samplingTime;
    double percent = (processVariable/setpoint) - 1;

    if(abs(diffProcessVariable) < 0.5) {
		setpointReached = true;
	}
	else {
		setpointReached = false;
	}

    double differentiator = (setpoint - lastSetpoint)/samplingTime;
    integrator += (error * samplingTime);
    integrator = limiter(integrator, lowerOutputLimit, upperOutputLimit);
    double controlVariable = kp * error + ki * integrator - kd * differentiator;

    controlVariable = limiter(controlVariable, lowerOutputLimit, upperOutputLimit);
    lastControlVariable = controlVariable;
    lastSetpoint = setpoint;
    lastProcessVariable = processVariable;

    sample_timer.start();

    return controlVariable;
}
<|endoftext|>


<commit_before>/*
 * opencog/spacetime/SpaceServer.cc
 *
 * Copyright (C) 2008-2010 OpenCog Foundation
 * Copyright (C) 2002-2007 Novamente LLC
 * All Rights Reserved
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License v3 as
 * published by the Free Software Foundation and including the exceptions
 * at http://opencog.org/wiki/Licenses
 *
 * This program 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 General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program; if not, write to:
 * Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */
#include <string>
#include <vector>
#include <cstdlib>

#include <boost/bind.hpp>

#include <opencog/util/Logger.h>
#include <opencog/util/StringTokenizer.h>
#include <opencog/util/StringManipulator.h>
#include <opencog/util/oc_assert.h>

#define DEPRECATED_ATOMSPACE_CALLS
#include <opencog/atomspace/AtomSpace.h>
#include <opencog/truthvalue/TruthValue.h>

#include <opencog/spatial/3DSpaceMap/Block3DMapUtil.h>

#include <opencog/spacetime/atom_types.h>
#include "SpaceServer.h"
#include "TimeServer.h"

//#define DPRINTF printf
#define DPRINTF(...)
// To simplify debug log output
#define ATOM_AS_STRING(h) (atomspace->atom_as_string(h).c_str())

using namespace opencog;
using namespace opencog::spatial;

SpaceServer::SpaceServer(AtomSpace &_atomspace) :
    atomspace(&_atomspace)
{
    // Default values (should only be used for test purposes)
    agentRadius = 0.25;
    agentHeight = 0;

    curSpaceMapHandle = Handle::UNDEFINED;
    curMap = NULL;
    curEntityRecorder = NULL;

    // connect signals
    removedAtomConnection = _atomspace.addAtomSignal(boost::bind(&SpaceServer::atomAdded, this, _1));
    addedAtomConnection = _atomspace.removeAtomSignal(boost::bind(&SpaceServer::atomRemoved, this, _1));

}

SpaceServer::~SpaceServer()
{
    // disconnect signals
    addedAtomConnection.disconnect();
    removedAtomConnection.disconnect();

    clear();
}

void SpaceServer::setTimeServer(TimeServer* ts)
{
    timeser = ts;
}

//TODO
void SpaceServer::atomAdded(const Handle& h)
{

}

void SpaceServer::atomRemoved(const AtomPtr& atom)
{
    Type type = atom->getType();
    if (not classserver().isA(type, OBJECT_NODE)) return;

    std::vector<std::string> timeDomains = timeser->getTimeDomains();
    for (auto timeDomain: timeDomains) {
        removeSpaceInfo(atom->getHandle(), curSpaceMapHandle, 0, timeDomain);
    }
}

void SpaceServer::setAgentRadius(unsigned int _radius)
{
    if (agentRadius != _radius) {
        agentRadius = _radius;
        logger().info("SpaceServer - AgentRadius: %d", agentRadius);
    }
}

void SpaceServer::setAgentHeight(unsigned int _height, Handle spaceMapHandle)
{
    auto scenePairItr = scenes.find(spaceMapHandle);
    if ( scenePairItr == scenes.end()) {
        logger().error("SpaceServer::setAgentHeight - Map not found!");
        return;
    }

    SpaceMap& theMap = (scenePairItr->second).spaceMap;

    if (agentHeight != _height) {
        agentHeight = _height;
        theMap.setAgentHeight(_height);
        logger().info("SpaceServer - AgentHeight: %d", agentHeight);
    }

}

const SpaceServer::SpaceMap& SpaceServer::getMap(Handle spaceMapHandle) const
    throw (opencog::RuntimeException, std::bad_exception)
{
    logger().fine("SpaceServer::getMap() for mapHandle = %s",
            spaceMapHandle != Handle::UNDEFINED ?
            ATOM_AS_STRING(spaceMapHandle)
            : "Handle::UNDEFINED");

    auto itr = scenes.find(spaceMapHandle);

    if (itr == scenes.end()) {
        throw opencog::RuntimeException(TRACE_INFO,
                "SpaceServer - Found no SpaceMap associate with handle: '%s'.",
                ATOM_AS_STRING(spaceMapHandle));
    }

    return (itr->second).spaceMap;
}

const EntityRecorder& SpaceServer::getEntityRecorder(Handle spaceMapHandle) const
    throw (opencog::RuntimeException, std::bad_exception)
{
    logger().fine("SpaceServer::getEntityRecorder() for mapHandle = %s",
            spaceMapHandle != Handle::UNDEFINED ?
            ATOM_AS_STRING(spaceMapHandle)
            : "Handle::UNDEFINED");

    auto itr = scenes.find(spaceMapHandle);

    if (itr == scenes.end()) {
        throw opencog::RuntimeException(TRACE_INFO,
                "SpaceServer - Found no EntityRecorder associate with handle: '%s'.",
                ATOM_AS_STRING(spaceMapHandle));
    }

    return (itr->second).entityRecorder;
}

const bool SpaceServer::containsMap(Handle spaceMapHandle) const
{
    return (scenes.find(spaceMapHandle) != scenes.end());
}

const bool SpaceServer::isLatestMapValid() const
{
    return ((curSpaceMapHandle != Handle::UNDEFINED) && (curMap != 0));
}

const SpaceServer::SpaceMap& SpaceServer::getLatestMap() const
    throw (opencog::AssertionException, std::bad_exception)
{
    return getMap(curSpaceMapHandle);
}

const SpaceServer::EntityRecorder& SpaceServer::getLatestEntityRecorder() const
{
    return getEntityRecorder(curSpaceMapHandle);
}

Handle SpaceServer::getLatestMapHandle() const
{
    return curSpaceMapHandle;
}

void SpaceServer::removeMap(Handle spaceMapHandle)
{
    auto itr = scenes.find(spaceMapHandle);
    if (itr != scenes.end()) {
        scenes.erase(itr);
    }
}

unsigned int SpaceServer::getSpaceMapsSize() const
{
    return scenes.size();
}

void SpaceServer::clear()
{
    scenes.clear();
}

SpaceServer::SpaceMap* SpaceServer::cloneTheLatestSpaceMap() const
{
    return cloneSpaceMap(curSpaceMapHandle);
}

SpaceServer::SpaceMap* SpaceServer::cloneSpaceMap(Handle spaceMapHandle) const
{
    auto itr = scenes.find(spaceMapHandle);
    return (itr == scenes.end())
        ? (itr->second).spaceMap.clone()
        : nullptr;
}

bool SpaceServer::addSpaceInfo(Handle objectNode, Handle spaceMapHandle, bool isSelfObject, bool isAvatarEntity, octime_t timestamp, double objX, double objY, double objZ, const TimeDomain& timeDomain)
{
    if (spaceMapHandle == Handle::UNDEFINED) {
        logger().error("SpaceServer::addSpaceInfo - No space map now!");
        return false;
    }

    auto scenePairItr = scenes.find(spaceMapHandle);
    if ( scenePairItr == scenes.end()) {
        logger().error("SpaceServer::removeSpaceInfo - No space map now!");
        return false;
    }

    timeser->addTimeInfo(spaceMapHandle, timestamp, timeDomain);

    // we should distinguish to add a block or other object
    // because when adding a block, maybe cause some change in the terrain and structures

    opencog::spatial::BlockVector pos(objX, objY, objZ);

    if (objectNode->getType() == STRUCTURE_NODE) {
        // it's a block
        SpaceMap& theSpaceMap = (scenePairItr->second).spaceMap;
        theSpaceMap.addSolidUnitBlock(objectNode, pos);
    } else {
        EntityRecorder& entityRecorder = (scenePairItr->second).entityRecorder;
        entityRecorder.addNoneBlockEntity(objectNode, pos, isSelfObject, isAvatarEntity, timestamp);
    }
    return true;
}

Handle SpaceServer::addOrGetSpaceMap(octime_t timestamp, std::string _mapName, double _resolution, const TimeDomain& timeDomain)
{
    Handle spaceMapHandle = atomspace->get_handle(SPACE_MAP_NODE,_mapName);

    // There is not a space map node for this map in the atomspace, so create a new one
    if (spaceMapHandle == Handle::UNDEFINED) {
        spaceMapHandle = atomspace->add_node(SPACE_MAP_NODE,_mapName);
        spaceMapHandle->setLTI(1);
        timeser->addTimeInfo(spaceMapHandle, timestamp, timeDomain);
        scenes.emplace(std::piecewise_construct, std::make_tuple(spaceMapHandle),
                       std::make_tuple(_mapName, _resolution));
    }

    curSpaceMapHandle = spaceMapHandle;
    return spaceMapHandle;
}

void SpaceServer::removeSpaceInfo(Handle objectNode, Handle spaceMapHandle, octime_t timestamp, const TimeDomain& timeDomain)
{
    if (spaceMapHandle == Handle::UNDEFINED) {
        logger().error("SpaceServer::removeSpaceInfo - Undefined SpaceMap!");
        return;
    }

    auto scenePairItr = scenes.find(spaceMapHandle);
    if ( scenePairItr == scenes.end()) {
        logger().error("SpaceServer::removeSpaceInfo - No space map now!");
        return;
    }

    if (timestamp != 0) {
        timeser->addTimeInfo(spaceMapHandle, timestamp, timeDomain);
    }

    if (objectNode->getType() == STRUCTURE_NODE) {
        SpaceMap& theSpaceMap = (scenePairItr->second).spaceMap;
        theSpaceMap.removeSolidUnitBlock(objectNode);
    } else {
        EntityRecorder& entityRecorder = (scenePairItr->second).entityRecorder;
        entityRecorder.removeNoneBlockEntity(objectNode);
    }

    logger().debug("%s(%s)\n", __FUNCTION__, atomspace->get_name(objectNode).c_str());

}

void SpaceServer::mapRemoved(Handle mapId)
{
    // Remove this atom from AtomSpace since its map does not exist anymore
    atomspace->remove_atom(mapId);
}

void SpaceServer::mapPersisted(Handle mapId)
{
    // set LTI to a value that prevents the corresponding atom to be removed
    // from AtomSpace
    mapId->setLTI(1);
}

std::string SpaceServer::getMapIdString(Handle mapHandle) const
{
    // Currently the mapHandle is of AtTimeLink(TimeNode:"<timestamp>" , ConceptNode:"SpaceMap")
    // So, just get the name of the TimeNode as its string representation
    // return atomspace->get_name(mapHandle->getOutgoingSet()[0])->get_result();

    return atomspace->get_name(mapHandle);
}

// TODO
std::string SpaceServer::mapToString(Handle mapHandle) const
{

    std::stringstream stringMap;
    stringMap.precision(25);
    stringMap << getMapIdString(mapHandle);
    // see localspacemap toString

    return stringMap.str( );
}

// TODO
Handle SpaceServer::mapFromString(const std::string& stringMap)
{
    return Handle::UNDEFINED;
}

Handle SpaceServer::addPropertyPredicate(
        std::string predicateName,
        Handle a,
        Handle b,
        TruthValuePtr tv)
{
    Handle ph = atomspace->add_node(PREDICATE_NODE, predicateName);
    Handle ll =  atomspace->add_link(LIST_LINK, a, b);
    Handle result = atomspace->add_link(EVALUATION_LINK, ph, ll);
    result->setTruthValue(tv);

    return result;
}
<commit_msg>Remove dprecated calls<commit_after>/*
 * opencog/spacetime/SpaceServer.cc
 *
 * Copyright (C) 2008-2010 OpenCog Foundation
 * Copyright (C) 2002-2007 Novamente LLC
 * All Rights Reserved
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License v3 as
 * published by the Free Software Foundation and including the exceptions
 * at http://opencog.org/wiki/Licenses
 *
 * This program 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 General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program; if not, write to:
 * Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */
#include <string>
#include <vector>
#include <cstdlib>

#include <boost/bind.hpp>

#include <opencog/util/Logger.h>
#include <opencog/util/StringTokenizer.h>
#include <opencog/util/StringManipulator.h>
#include <opencog/util/oc_assert.h>

#include <opencog/atomspace/AtomSpace.h>
#include <opencog/truthvalue/TruthValue.h>

#include <opencog/spatial/3DSpaceMap/Block3DMapUtil.h>

#include <opencog/spacetime/atom_types.h>
#include "SpaceServer.h"
#include "TimeServer.h"

//#define DPRINTF printf
#define DPRINTF(...)
// To simplify debug log output
#define ATOM_AS_STRING(h) (atomspace->atom_as_string(h).c_str())

using namespace opencog;
using namespace opencog::spatial;

SpaceServer::SpaceServer(AtomSpace &_atomspace) :
    atomspace(&_atomspace)
{
    // Default values (should only be used for test purposes)
    agentRadius = 0.25;
    agentHeight = 0;

    curSpaceMapHandle = Handle::UNDEFINED;
    curMap = NULL;
    curEntityRecorder = NULL;

    // connect signals
    removedAtomConnection = _atomspace.addAtomSignal(boost::bind(&SpaceServer::atomAdded, this, _1));
    addedAtomConnection = _atomspace.removeAtomSignal(boost::bind(&SpaceServer::atomRemoved, this, _1));

}

SpaceServer::~SpaceServer()
{
    // disconnect signals
    addedAtomConnection.disconnect();
    removedAtomConnection.disconnect();

    clear();
}

void SpaceServer::setTimeServer(TimeServer* ts)
{
    timeser = ts;
}

//TODO
void SpaceServer::atomAdded(const Handle& h)
{

}

void SpaceServer::atomRemoved(const AtomPtr& atom)
{
    Type type = atom->getType();
    if (not classserver().isA(type, OBJECT_NODE)) return;

    std::vector<std::string> timeDomains = timeser->getTimeDomains();
    for (auto timeDomain: timeDomains) {
        removeSpaceInfo(atom->getHandle(), curSpaceMapHandle, 0, timeDomain);
    }
}

void SpaceServer::setAgentRadius(unsigned int _radius)
{
    if (agentRadius != _radius) {
        agentRadius = _radius;
        logger().info("SpaceServer - AgentRadius: %d", agentRadius);
    }
}

void SpaceServer::setAgentHeight(unsigned int _height, Handle spaceMapHandle)
{
    auto scenePairItr = scenes.find(spaceMapHandle);
    if ( scenePairItr == scenes.end()) {
        logger().error("SpaceServer::setAgentHeight - Map not found!");
        return;
    }

    SpaceMap& theMap = (scenePairItr->second).spaceMap;

    if (agentHeight != _height) {
        agentHeight = _height;
        theMap.setAgentHeight(_height);
        logger().info("SpaceServer - AgentHeight: %d", agentHeight);
    }

}

const SpaceServer::SpaceMap& SpaceServer::getMap(Handle spaceMapHandle) const
    throw (opencog::RuntimeException, std::bad_exception)
{
    logger().fine("SpaceServer::getMap() for mapHandle = %s",
            spaceMapHandle != Handle::UNDEFINED ?
            ATOM_AS_STRING(spaceMapHandle)
            : "Handle::UNDEFINED");

    auto itr = scenes.find(spaceMapHandle);

    if (itr == scenes.end()) {
        throw opencog::RuntimeException(TRACE_INFO,
                "SpaceServer - Found no SpaceMap associate with handle: '%s'.",
                ATOM_AS_STRING(spaceMapHandle));
    }

    return (itr->second).spaceMap;
}

const EntityRecorder& SpaceServer::getEntityRecorder(Handle spaceMapHandle) const
    throw (opencog::RuntimeException, std::bad_exception)
{
    logger().fine("SpaceServer::getEntityRecorder() for mapHandle = %s",
            spaceMapHandle != Handle::UNDEFINED ?
            ATOM_AS_STRING(spaceMapHandle)
            : "Handle::UNDEFINED");

    auto itr = scenes.find(spaceMapHandle);

    if (itr == scenes.end()) {
        throw opencog::RuntimeException(TRACE_INFO,
                "SpaceServer - Found no EntityRecorder associate with handle: '%s'.",
                ATOM_AS_STRING(spaceMapHandle));
    }

    return (itr->second).entityRecorder;
}

const bool SpaceServer::containsMap(Handle spaceMapHandle) const
{
    return (scenes.find(spaceMapHandle) != scenes.end());
}

const bool SpaceServer::isLatestMapValid() const
{
    return ((curSpaceMapHandle != Handle::UNDEFINED) && (curMap != 0));
}

const SpaceServer::SpaceMap& SpaceServer::getLatestMap() const
    throw (opencog::AssertionException, std::bad_exception)
{
    return getMap(curSpaceMapHandle);
}

const SpaceServer::EntityRecorder& SpaceServer::getLatestEntityRecorder() const
{
    return getEntityRecorder(curSpaceMapHandle);
}

Handle SpaceServer::getLatestMapHandle() const
{
    return curSpaceMapHandle;
}

void SpaceServer::removeMap(Handle spaceMapHandle)
{
    auto itr = scenes.find(spaceMapHandle);
    if (itr != scenes.end()) {
        scenes.erase(itr);
    }
}

unsigned int SpaceServer::getSpaceMapsSize() const
{
    return scenes.size();
}

void SpaceServer::clear()
{
    scenes.clear();
}

SpaceServer::SpaceMap* SpaceServer::cloneTheLatestSpaceMap() const
{
    return cloneSpaceMap(curSpaceMapHandle);
}

SpaceServer::SpaceMap* SpaceServer::cloneSpaceMap(Handle spaceMapHandle) const
{
    auto itr = scenes.find(spaceMapHandle);
    return (itr == scenes.end())
        ? (itr->second).spaceMap.clone()
        : nullptr;
}

bool SpaceServer::addSpaceInfo(Handle objectNode, Handle spaceMapHandle, bool isSelfObject, bool isAvatarEntity, octime_t timestamp, double objX, double objY, double objZ, const TimeDomain& timeDomain)
{
    if (spaceMapHandle == Handle::UNDEFINED) {
        logger().error("SpaceServer::addSpaceInfo - No space map now!");
        return false;
    }

    auto scenePairItr = scenes.find(spaceMapHandle);
    if ( scenePairItr == scenes.end()) {
        logger().error("SpaceServer::removeSpaceInfo - No space map now!");
        return false;
    }

    timeser->addTimeInfo(spaceMapHandle, timestamp, timeDomain);

    // we should distinguish to add a block or other object
    // because when adding a block, maybe cause some change in the terrain and structures

    opencog::spatial::BlockVector pos(objX, objY, objZ);

    if (objectNode->getType() == STRUCTURE_NODE) {
        // it's a block
        SpaceMap& theSpaceMap = (scenePairItr->second).spaceMap;
        theSpaceMap.addSolidUnitBlock(objectNode, pos);
    } else {
        EntityRecorder& entityRecorder = (scenePairItr->second).entityRecorder;
        entityRecorder.addNoneBlockEntity(objectNode, pos, isSelfObject, isAvatarEntity, timestamp);
    }
    return true;
}

Handle SpaceServer::addOrGetSpaceMap(octime_t timestamp, std::string _mapName, double _resolution, const TimeDomain& timeDomain)
{
    Handle spaceMapHandle = atomspace->get_handle(SPACE_MAP_NODE,_mapName);

    // There is not a space map node for this map in the atomspace, so create a new one
    if (spaceMapHandle == Handle::UNDEFINED) {
        spaceMapHandle = atomspace->add_node(SPACE_MAP_NODE,_mapName);
        spaceMapHandle->setLTI(1);
        timeser->addTimeInfo(spaceMapHandle, timestamp, timeDomain);
        scenes.emplace(std::piecewise_construct, std::make_tuple(spaceMapHandle),
                       std::make_tuple(_mapName, _resolution));
    }

    curSpaceMapHandle = spaceMapHandle;
    return spaceMapHandle;
}

void SpaceServer::removeSpaceInfo(Handle objectNode, Handle spaceMapHandle, octime_t timestamp, const TimeDomain& timeDomain)
{
    if (spaceMapHandle == Handle::UNDEFINED) {
        logger().error("SpaceServer::removeSpaceInfo - Undefined SpaceMap!");
        return;
    }

    auto scenePairItr = scenes.find(spaceMapHandle);
    if ( scenePairItr == scenes.end()) {
        logger().error("SpaceServer::removeSpaceInfo - No space map now!");
        return;
    }

    if (timestamp != 0) {
        timeser->addTimeInfo(spaceMapHandle, timestamp, timeDomain);
    }

    if (objectNode->getType() == STRUCTURE_NODE) {
        SpaceMap& theSpaceMap = (scenePairItr->second).spaceMap;
        theSpaceMap.removeSolidUnitBlock(objectNode);
    } else {
        EntityRecorder& entityRecorder = (scenePairItr->second).entityRecorder;
        entityRecorder.removeNoneBlockEntity(objectNode);
    }

    logger().debug("%s(%s)\n", __FUNCTION__, atomspace->get_name(objectNode).c_str());

}

void SpaceServer::mapRemoved(Handle mapId)
{
    // Remove this atom from AtomSpace since its map does not exist anymore
    atomspace->remove_atom(mapId);
}

void SpaceServer::mapPersisted(Handle mapId)
{
    // set LTI to a value that prevents the corresponding atom to be removed
    // from AtomSpace
    mapId->setLTI(1);
}

std::string SpaceServer::getMapIdString(Handle mapHandle) const
{
    // Currently the mapHandle is of AtTimeLink(TimeNode:"<timestamp>" , ConceptNode:"SpaceMap")
    // So, just get the name of the TimeNode as its string representation
    // return atomspace->get_name(mapHandle->getOutgoingSet()[0])->get_result();

    return atomspace->get_name(mapHandle);
}

// TODO
std::string SpaceServer::mapToString(Handle mapHandle) const
{

    std::stringstream stringMap;
    stringMap.precision(25);
    stringMap << getMapIdString(mapHandle);
    // see localspacemap toString

    return stringMap.str( );
}

// TODO
Handle SpaceServer::mapFromString(const std::string& stringMap)
{
    return Handle::UNDEFINED;
}

Handle SpaceServer::addPropertyPredicate(
        std::string predicateName,
        Handle a,
        Handle b,
        TruthValuePtr tv)
{
    Handle ph = atomspace->add_node(PREDICATE_NODE, predicateName);
    Handle ll =  atomspace->add_link(LIST_LINK, a, b);
    Handle result = atomspace->add_link(EVALUATION_LINK, ph, ll);
    result->setTruthValue(tv);

    return result;
}
<|endoftext|>


<commit_before>//===--- SILGenLazyConformance.cpp ----------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2019 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//

#include "SILGen.h"
#include "swift/AST/Decl.h"
#include "swift/AST/ProtocolConformance.h"
#include "swift/ClangImporter/ClangModule.h"
#include "swift/SIL/SILInstruction.h"
#include "swift/SIL/SILVisitor.h"

using namespace swift;
using namespace swift::Lowering;

void SILGenModule::useConformance(ProtocolConformanceRef conformanceRef) {
  // We don't need to emit dependent conformances.
  if (conformanceRef.isAbstract())
    return;

  auto conformance = conformanceRef.getConcrete();

  // Always look through inherited conformances.
  if (auto *inherited = dyn_cast<InheritedProtocolConformance>(conformance))
    conformance = inherited->getInheritedConformance();

  // Get the normal conformance. If we don't have one, this is a self
  // conformance, which we can ignore.
  auto normal = dyn_cast<NormalProtocolConformance>(
      conformance->getRootConformance());
  if (normal == nullptr)
    return;

  // Emit any conformances implied by conditional requirements.
  if (auto *specialized = dyn_cast<SpecializedProtocolConformance>(conformance))
    useConformancesFromSubstitutions(specialized->getSubstitutionMap());

  // If this conformance was not synthesized by the ClangImporter, we're not
  // going to be emitting it lazily either, so we can avoid doing anything
  // below.
  if (!isa<ClangModuleUnit>(normal->getDeclContext()->getModuleScopeContext()))
    return;

  // If we already emitted this witness table, we don't need to track the fact
  // we need it.
  if (emittedWitnessTables.count(normal))
    return;

  // Check if we already forced this witness table but haven't emitted it yet.
  if (!forcedConformances.insert(normal).second)
    return;

  pendingConformances.push_back(normal);
}

void SILGenModule::useConformancesFromSubstitutions(
                                                const SubstitutionMap subs) {
  for (auto conf : subs.getConformances())
    useConformance(conf);
}

void SILGenModule::useConformancesFromType(CanType type) {
  if (!usedConformancesFromTypes.insert(type.getPointer()).second)
    return;

  type.visit([&](Type t) {
    auto *decl = t->getAnyNominal();
    if (!decl)
      return;

    if (isa<ProtocolDecl>(decl))
      return;

    auto genericSig = decl->getGenericSignature();
    if (!genericSig)
      return;

    auto subMap = t->getContextSubstitutionMap(SwiftModule, decl);
    useConformancesFromSubstitutions(subMap);
    return;
  });
}

void SILGenModule::useConformancesFromObjectiveCType(CanType type) {
  if (!usedConformancesFromObjectiveCTypes.insert(type.getPointer()).second)
    return;

  auto &ctx = getASTContext();
  auto objectiveCBridgeable = ctx.getProtocol(
      KnownProtocolKind::ObjectiveCBridgeable);
  auto bridgedStoredNSError = ctx.getProtocol(
      KnownProtocolKind::BridgedStoredNSError);
  if (!objectiveCBridgeable && !bridgedStoredNSError)
    return;

  type.visit([&](Type t) {
    auto *decl = t->getAnyNominal();
    if (!decl)
      return;

    if (!isa<ClangModuleUnit>(decl->getModuleScopeContext()))
      return;

    if (objectiveCBridgeable) {
      if (auto subConformance =
              SwiftModule->lookupConformance(t, objectiveCBridgeable))
        useConformance(subConformance);
    }

    if (bridgedStoredNSError) {
      if (auto subConformance =
              SwiftModule->lookupConformance(t, bridgedStoredNSError))
        useConformance(subConformance);
    }
  });
}

/// A visitor class that tries to guess which SIL instructions can cause
/// IRGen to emit references to witness tables. This is used to emit
/// ClangImporter-synthesized conformances lazily.
///
/// In the long run, we'll instead have IRGen directly ask SILGen to
/// generate a witness table when needed, so that we don't have to do
/// any "guessing" here.
class LazyConformanceEmitter : public SILInstructionVisitor<LazyConformanceEmitter> {
  SILGenModule &SGM;

public:
  LazyConformanceEmitter(SILGenModule &SGM) : SGM(SGM) {}

  void visitAllocExistentialBoxInst(AllocExistentialBoxInst *AEBI) {
    SGM.useConformancesFromType(AEBI->getFormalConcreteType());
    SGM.useConformancesFromObjectiveCType(AEBI->getFormalConcreteType());
    for (auto conformance : AEBI->getConformances())
      SGM.useConformance(conformance);
  }

  void visitAllocGlobalInst(AllocGlobalInst *AGI) {
    SGM.useConformancesFromType(
        AGI->getReferencedGlobal()->getLoweredType().getASTType());
  }

  void visitAllocRefInst(AllocRefInst *ARI) {
    SGM.useConformancesFromType(ARI->getType().getASTType());
  }

  void visitAllocStackInst(AllocStackInst *ASI) {
    SGM.useConformancesFromType(ASI->getType().getASTType());
  }

  void visitApplyInst(ApplyInst *AI) {
    SGM.useConformancesFromObjectiveCType(AI->getSubstCalleeType());
    SGM.useConformancesFromSubstitutions(AI->getSubstitutionMap());
  }

  void visitBeginApplyInst(BeginApplyInst *BAI) {
    SGM.useConformancesFromObjectiveCType(BAI->getSubstCalleeType());
    SGM.useConformancesFromSubstitutions(BAI->getSubstitutionMap());
  }

  void visitBuiltinInst(BuiltinInst *BI) {
    SGM.useConformancesFromSubstitutions(BI->getSubstitutions());
  }

  void visitCheckedCastBranchInst(CheckedCastBranchInst *CCBI) {
    SGM.useConformancesFromType(CCBI->getSourceFormalType());
    SGM.useConformancesFromType(CCBI->getTargetFormalType());
    SGM.useConformancesFromObjectiveCType(CCBI->getSourceFormalType());
    SGM.useConformancesFromObjectiveCType(CCBI->getTargetFormalType());
  }

  void visitCheckedCastAddrBranchInst(CheckedCastAddrBranchInst *CCABI) {
    SGM.useConformancesFromType(CCABI->getSourceFormalType());
    SGM.useConformancesFromType(CCABI->getTargetFormalType());
    SGM.useConformancesFromObjectiveCType(CCABI->getSourceFormalType());
    SGM.useConformancesFromObjectiveCType(CCABI->getTargetFormalType());
  }

  void visitCopyAddrInst(CopyAddrInst *CAI) {
    SGM.useConformancesFromType(CAI->getSrc()->getType().getASTType());
    SGM.useConformancesFromType(CAI->getDest()->getType().getASTType());
  }

  void visitMarkUnresolvedMoveAddrInst(MarkUnresolvedMoveAddrInst *MAI) {
    SGM.useConformancesFromType(MAI->getSrc()->getType().getASTType());
    SGM.useConformancesFromType(MAI->getDest()->getType().getASTType());
  }

  void visitCopyValueInst(CopyValueInst *CVI) {
    SGM.useConformancesFromType(CVI->getOperand()->getType().getASTType());
  }

  void visitDestroyAddrInst(DestroyAddrInst *DAI) {
    SGM.useConformancesFromType(DAI->getOperand()->getType().getASTType());
  }

  void visitDestroyValueInst(DestroyValueInst *DVI) {
    SGM.useConformancesFromType(DVI->getOperand()->getType().getASTType());
  }

  void visitGlobalAddrInst(GlobalAddrInst *GAI) {
    SGM.useConformancesFromType(
        GAI->getReferencedGlobal()->getLoweredType().getASTType());
  }

  void visitGlobalValueInst(GlobalValueInst *GVI) {
    SGM.useConformancesFromType(
        GVI->getReferencedGlobal()->getLoweredType().getASTType());
  }

  void visitKeyPathInst(KeyPathInst *KPI) {
    SGM.useConformancesFromSubstitutions(KPI->getSubstitutions());
  }

  void visitInitEnumDataAddrInst(InitEnumDataAddrInst *IEDAI) {
    SGM.useConformancesFromType(
        IEDAI->getOperand()->getType().getASTType());
  }

  void visitInjectEnumAddrInst(InjectEnumAddrInst *IEAI) {
    SGM.useConformancesFromType(IEAI->getOperand()->getType().getASTType());
  }

  void visitInitExistentialAddrInst(InitExistentialAddrInst *IEAI) {
    SGM.useConformancesFromType(IEAI->getFormalConcreteType());
    SGM.useConformancesFromObjectiveCType(IEAI->getFormalConcreteType());
    for (auto conformance : IEAI->getConformances())
      SGM.useConformance(conformance);
  }

  void visitInitExistentialMetatypeInst(InitExistentialMetatypeInst *IEMI) {
    SGM.useConformancesFromType(IEMI->getOperand()->getType().getASTType());
    for (auto conformance : IEMI->getConformances())
      SGM.useConformance(conformance);
  }

  void visitInitExistentialRefInst(InitExistentialRefInst *IERI) {
    SGM.useConformancesFromType(IERI->getFormalConcreteType());
    SGM.useConformancesFromObjectiveCType(IERI->getFormalConcreteType());
    for (auto conformance : IERI->getConformances())
      SGM.useConformance(conformance);
  }

  void visitInitExistentialValueInst(InitExistentialValueInst *IEVI) {
    SGM.useConformancesFromType(IEVI->getFormalConcreteType());
    SGM.useConformancesFromObjectiveCType(IEVI->getFormalConcreteType());
    for (auto conformance : IEVI->getConformances())
      SGM.useConformance(conformance);
  }

  void visitMetatypeInst(MetatypeInst *MI) {
    SGM.useConformancesFromType(MI->getType().getASTType());
  }

  void visitPartialApplyInst(PartialApplyInst *PAI) {
    SGM.useConformancesFromObjectiveCType(PAI->getSubstCalleeType());
    SGM.useConformancesFromSubstitutions(PAI->getSubstitutionMap());
  }

  void visitSelectEnumAddrInst(SelectEnumAddrInst *SEAI) {
    SGM.useConformancesFromType(
        SEAI->getEnumOperand()->getType().getASTType());
  }

  void visitStructElementAddrInst(StructElementAddrInst *SEAI) {
    SGM.useConformancesFromType(SEAI->getOperand()->getType().getASTType());
  }

  void visitTryApplyInst(TryApplyInst *TAI) {
    SGM.useConformancesFromObjectiveCType(TAI->getSubstCalleeType());
    SGM.useConformancesFromSubstitutions(TAI->getSubstitutionMap());
  }

  void visitTupleElementAddrInst(TupleElementAddrInst *TEAI) {
    SGM.useConformancesFromType(TEAI->getOperand()->getType().getASTType());
  }

  void visitUnconditionalCheckedCastInst(UnconditionalCheckedCastInst *UCCI) {
    SGM.useConformancesFromType(UCCI->getSourceFormalType());
    SGM.useConformancesFromType(UCCI->getTargetFormalType());
    SGM.useConformancesFromObjectiveCType(UCCI->getSourceFormalType());
    SGM.useConformancesFromObjectiveCType(UCCI->getTargetFormalType());
  }

  void visitUnconditionalCheckedCastAddrInst(UnconditionalCheckedCastAddrInst *UCCAI) {
    SGM.useConformancesFromType(UCCAI->getSourceFormalType());
    SGM.useConformancesFromType(UCCAI->getTargetFormalType());
    SGM.useConformancesFromObjectiveCType(UCCAI->getSourceFormalType());
    SGM.useConformancesFromObjectiveCType(UCCAI->getTargetFormalType());
  }

  void visitUncheckedTakeEnumDataAddrInst(UncheckedTakeEnumDataAddrInst *UTEDAI) {
    SGM.useConformancesFromType(UTEDAI->getOperand()->getType().getASTType());
  }

  void visitWitnessMethodInst(WitnessMethodInst *WMI) {
    SGM.useConformance(WMI->getConformance());
  }

  void visitSILInstruction(SILInstruction *I) {}
};

void SILGenModule::emitLazyConformancesForFunction(SILFunction *F) {
  LazyConformanceEmitter emitter(*this);

  for (auto &BB : *F)
    for (auto &I : BB)
      emitter.visit(&I);
}

void SILGenModule::emitLazyConformancesForType(NominalTypeDecl *NTD) {
  auto genericSig = NTD->getGenericSignature();

  for (auto reqt : genericSig.getRequirements()) {
    if (reqt.getKind() != RequirementKind::Layout)
      useConformancesFromType(reqt.getSecondType()->getCanonicalType());
  }

  if (auto *ED = dyn_cast<EnumDecl>(NTD)) {
    for (auto *EED : ED->getAllElements()) {
      if (EED->hasAssociatedValues()) {
        useConformancesFromType(EED->getArgumentInterfaceType()
                                   ->getCanonicalType(genericSig));
      }
    }
  }

  if (isa<StructDecl>(NTD) || isa<ClassDecl>(NTD)) {
    for (auto *VD : NTD->getStoredProperties()) {
      useConformancesFromType(VD->getValueInterfaceType()
                                ->getCanonicalType(genericSig));
    }
  }

  if (auto *CD = dyn_cast<ClassDecl>(NTD))
    if (auto superclass = CD->getSuperclass())
      useConformancesFromType(superclass->getCanonicalType(genericSig));

  if (auto *PD = dyn_cast<ProtocolDecl>(NTD)) {
    for (auto reqt : PD->getRequirementSignature().getRequirements()) {
      if (reqt.getKind() != RequirementKind::Layout)
        useConformancesFromType(reqt.getSecondType()->getCanonicalType());
    }
  }
}
<commit_msg>SILGen: Crash better when useConformance() is handed an invalid conformance<commit_after>//===--- SILGenLazyConformance.cpp ----------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2019 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//

#include "SILGen.h"
#include "swift/AST/Decl.h"
#include "swift/AST/ProtocolConformance.h"
#include "swift/ClangImporter/ClangModule.h"
#include "swift/SIL/SILInstruction.h"
#include "swift/SIL/SILVisitor.h"

using namespace swift;
using namespace swift::Lowering;

void SILGenModule::useConformance(ProtocolConformanceRef conformanceRef) {
  // If the conformance is invalid, crash deterministically even in noassert
  // builds.
  if (conformanceRef.isInvalid()) {
    llvm::report_fatal_error("Invalid conformance in type-checked AST");
  }

  // We don't need to emit dependent conformances.
  if (conformanceRef.isAbstract())
    return;

  auto conformance = conformanceRef.getConcrete();

  // Always look through inherited conformances.
  if (auto *inherited = dyn_cast<InheritedProtocolConformance>(conformance))
    conformance = inherited->getInheritedConformance();

  // Get the normal conformance. If we don't have one, this is a self
  // conformance, which we can ignore.
  auto normal = dyn_cast<NormalProtocolConformance>(
      conformance->getRootConformance());
  if (normal == nullptr)
    return;

  // Emit any conformances implied by conditional requirements.
  if (auto *specialized = dyn_cast<SpecializedProtocolConformance>(conformance))
    useConformancesFromSubstitutions(specialized->getSubstitutionMap());

  // If this conformance was not synthesized by the ClangImporter, we're not
  // going to be emitting it lazily either, so we can avoid doing anything
  // below.
  if (!isa<ClangModuleUnit>(normal->getDeclContext()->getModuleScopeContext()))
    return;

  // If we already emitted this witness table, we don't need to track the fact
  // we need it.
  if (emittedWitnessTables.count(normal))
    return;

  // Check if we already forced this witness table but haven't emitted it yet.
  if (!forcedConformances.insert(normal).second)
    return;

  pendingConformances.push_back(normal);
}

void SILGenModule::useConformancesFromSubstitutions(
                                                const SubstitutionMap subs) {
  for (auto conf : subs.getConformances())
    useConformance(conf);
}

void SILGenModule::useConformancesFromType(CanType type) {
  if (!usedConformancesFromTypes.insert(type.getPointer()).second)
    return;

  type.visit([&](Type t) {
    auto *decl = t->getAnyNominal();
    if (!decl)
      return;

    if (isa<ProtocolDecl>(decl))
      return;

    auto genericSig = decl->getGenericSignature();
    if (!genericSig)
      return;

    auto subMap = t->getContextSubstitutionMap(SwiftModule, decl);
    useConformancesFromSubstitutions(subMap);
    return;
  });
}

void SILGenModule::useConformancesFromObjectiveCType(CanType type) {
  if (!usedConformancesFromObjectiveCTypes.insert(type.getPointer()).second)
    return;

  auto &ctx = getASTContext();
  auto objectiveCBridgeable = ctx.getProtocol(
      KnownProtocolKind::ObjectiveCBridgeable);
  auto bridgedStoredNSError = ctx.getProtocol(
      KnownProtocolKind::BridgedStoredNSError);
  if (!objectiveCBridgeable && !bridgedStoredNSError)
    return;

  type.visit([&](Type t) {
    auto *decl = t->getAnyNominal();
    if (!decl)
      return;

    if (!isa<ClangModuleUnit>(decl->getModuleScopeContext()))
      return;

    if (objectiveCBridgeable) {
      if (auto subConformance =
              SwiftModule->lookupConformance(t, objectiveCBridgeable))
        useConformance(subConformance);
    }

    if (bridgedStoredNSError) {
      if (auto subConformance =
              SwiftModule->lookupConformance(t, bridgedStoredNSError))
        useConformance(subConformance);
    }
  });
}

/// A visitor class that tries to guess which SIL instructions can cause
/// IRGen to emit references to witness tables. This is used to emit
/// ClangImporter-synthesized conformances lazily.
///
/// In the long run, we'll instead have IRGen directly ask SILGen to
/// generate a witness table when needed, so that we don't have to do
/// any "guessing" here.
class LazyConformanceEmitter : public SILInstructionVisitor<LazyConformanceEmitter> {
  SILGenModule &SGM;

public:
  LazyConformanceEmitter(SILGenModule &SGM) : SGM(SGM) {}

  void visitAllocExistentialBoxInst(AllocExistentialBoxInst *AEBI) {
    SGM.useConformancesFromType(AEBI->getFormalConcreteType());
    SGM.useConformancesFromObjectiveCType(AEBI->getFormalConcreteType());
    for (auto conformance : AEBI->getConformances())
      SGM.useConformance(conformance);
  }

  void visitAllocGlobalInst(AllocGlobalInst *AGI) {
    SGM.useConformancesFromType(
        AGI->getReferencedGlobal()->getLoweredType().getASTType());
  }

  void visitAllocRefInst(AllocRefInst *ARI) {
    SGM.useConformancesFromType(ARI->getType().getASTType());
  }

  void visitAllocStackInst(AllocStackInst *ASI) {
    SGM.useConformancesFromType(ASI->getType().getASTType());
  }

  void visitApplyInst(ApplyInst *AI) {
    SGM.useConformancesFromObjectiveCType(AI->getSubstCalleeType());
    SGM.useConformancesFromSubstitutions(AI->getSubstitutionMap());
  }

  void visitBeginApplyInst(BeginApplyInst *BAI) {
    SGM.useConformancesFromObjectiveCType(BAI->getSubstCalleeType());
    SGM.useConformancesFromSubstitutions(BAI->getSubstitutionMap());
  }

  void visitBuiltinInst(BuiltinInst *BI) {
    SGM.useConformancesFromSubstitutions(BI->getSubstitutions());
  }

  void visitCheckedCastBranchInst(CheckedCastBranchInst *CCBI) {
    SGM.useConformancesFromType(CCBI->getSourceFormalType());
    SGM.useConformancesFromType(CCBI->getTargetFormalType());
    SGM.useConformancesFromObjectiveCType(CCBI->getSourceFormalType());
    SGM.useConformancesFromObjectiveCType(CCBI->getTargetFormalType());
  }

  void visitCheckedCastAddrBranchInst(CheckedCastAddrBranchInst *CCABI) {
    SGM.useConformancesFromType(CCABI->getSourceFormalType());
    SGM.useConformancesFromType(CCABI->getTargetFormalType());
    SGM.useConformancesFromObjectiveCType(CCABI->getSourceFormalType());
    SGM.useConformancesFromObjectiveCType(CCABI->getTargetFormalType());
  }

  void visitCopyAddrInst(CopyAddrInst *CAI) {
    SGM.useConformancesFromType(CAI->getSrc()->getType().getASTType());
    SGM.useConformancesFromType(CAI->getDest()->getType().getASTType());
  }

  void visitMarkUnresolvedMoveAddrInst(MarkUnresolvedMoveAddrInst *MAI) {
    SGM.useConformancesFromType(MAI->getSrc()->getType().getASTType());
    SGM.useConformancesFromType(MAI->getDest()->getType().getASTType());
  }

  void visitCopyValueInst(CopyValueInst *CVI) {
    SGM.useConformancesFromType(CVI->getOperand()->getType().getASTType());
  }

  void visitDestroyAddrInst(DestroyAddrInst *DAI) {
    SGM.useConformancesFromType(DAI->getOperand()->getType().getASTType());
  }

  void visitDestroyValueInst(DestroyValueInst *DVI) {
    SGM.useConformancesFromType(DVI->getOperand()->getType().getASTType());
  }

  void visitGlobalAddrInst(GlobalAddrInst *GAI) {
    SGM.useConformancesFromType(
        GAI->getReferencedGlobal()->getLoweredType().getASTType());
  }

  void visitGlobalValueInst(GlobalValueInst *GVI) {
    SGM.useConformancesFromType(
        GVI->getReferencedGlobal()->getLoweredType().getASTType());
  }

  void visitKeyPathInst(KeyPathInst *KPI) {
    SGM.useConformancesFromSubstitutions(KPI->getSubstitutions());
  }

  void visitInitEnumDataAddrInst(InitEnumDataAddrInst *IEDAI) {
    SGM.useConformancesFromType(
        IEDAI->getOperand()->getType().getASTType());
  }

  void visitInjectEnumAddrInst(InjectEnumAddrInst *IEAI) {
    SGM.useConformancesFromType(IEAI->getOperand()->getType().getASTType());
  }

  void visitInitExistentialAddrInst(InitExistentialAddrInst *IEAI) {
    SGM.useConformancesFromType(IEAI->getFormalConcreteType());
    SGM.useConformancesFromObjectiveCType(IEAI->getFormalConcreteType());
    for (auto conformance : IEAI->getConformances())
      SGM.useConformance(conformance);
  }

  void visitInitExistentialMetatypeInst(InitExistentialMetatypeInst *IEMI) {
    SGM.useConformancesFromType(IEMI->getOperand()->getType().getASTType());
    for (auto conformance : IEMI->getConformances())
      SGM.useConformance(conformance);
  }

  void visitInitExistentialRefInst(InitExistentialRefInst *IERI) {
    SGM.useConformancesFromType(IERI->getFormalConcreteType());
    SGM.useConformancesFromObjectiveCType(IERI->getFormalConcreteType());
    for (auto conformance : IERI->getConformances())
      SGM.useConformance(conformance);
  }

  void visitInitExistentialValueInst(InitExistentialValueInst *IEVI) {
    SGM.useConformancesFromType(IEVI->getFormalConcreteType());
    SGM.useConformancesFromObjectiveCType(IEVI->getFormalConcreteType());
    for (auto conformance : IEVI->getConformances())
      SGM.useConformance(conformance);
  }

  void visitMetatypeInst(MetatypeInst *MI) {
    SGM.useConformancesFromType(MI->getType().getASTType());
  }

  void visitPartialApplyInst(PartialApplyInst *PAI) {
    SGM.useConformancesFromObjectiveCType(PAI->getSubstCalleeType());
    SGM.useConformancesFromSubstitutions(PAI->getSubstitutionMap());
  }

  void visitSelectEnumAddrInst(SelectEnumAddrInst *SEAI) {
    SGM.useConformancesFromType(
        SEAI->getEnumOperand()->getType().getASTType());
  }

  void visitStructElementAddrInst(StructElementAddrInst *SEAI) {
    SGM.useConformancesFromType(SEAI->getOperand()->getType().getASTType());
  }

  void visitTryApplyInst(TryApplyInst *TAI) {
    SGM.useConformancesFromObjectiveCType(TAI->getSubstCalleeType());
    SGM.useConformancesFromSubstitutions(TAI->getSubstitutionMap());
  }

  void visitTupleElementAddrInst(TupleElementAddrInst *TEAI) {
    SGM.useConformancesFromType(TEAI->getOperand()->getType().getASTType());
  }

  void visitUnconditionalCheckedCastInst(UnconditionalCheckedCastInst *UCCI) {
    SGM.useConformancesFromType(UCCI->getSourceFormalType());
    SGM.useConformancesFromType(UCCI->getTargetFormalType());
    SGM.useConformancesFromObjectiveCType(UCCI->getSourceFormalType());
    SGM.useConformancesFromObjectiveCType(UCCI->getTargetFormalType());
  }

  void visitUnconditionalCheckedCastAddrInst(UnconditionalCheckedCastAddrInst *UCCAI) {
    SGM.useConformancesFromType(UCCAI->getSourceFormalType());
    SGM.useConformancesFromType(UCCAI->getTargetFormalType());
    SGM.useConformancesFromObjectiveCType(UCCAI->getSourceFormalType());
    SGM.useConformancesFromObjectiveCType(UCCAI->getTargetFormalType());
  }

  void visitUncheckedTakeEnumDataAddrInst(UncheckedTakeEnumDataAddrInst *UTEDAI) {
    SGM.useConformancesFromType(UTEDAI->getOperand()->getType().getASTType());
  }

  void visitWitnessMethodInst(WitnessMethodInst *WMI) {
    SGM.useConformance(WMI->getConformance());
  }

  void visitSILInstruction(SILInstruction *I) {}
};

void SILGenModule::emitLazyConformancesForFunction(SILFunction *F) {
  LazyConformanceEmitter emitter(*this);

  for (auto &BB : *F)
    for (auto &I : BB)
      emitter.visit(&I);
}

void SILGenModule::emitLazyConformancesForType(NominalTypeDecl *NTD) {
  auto genericSig = NTD->getGenericSignature();

  for (auto reqt : genericSig.getRequirements()) {
    if (reqt.getKind() != RequirementKind::Layout)
      useConformancesFromType(reqt.getSecondType()->getCanonicalType());
  }

  if (auto *ED = dyn_cast<EnumDecl>(NTD)) {
    for (auto *EED : ED->getAllElements()) {
      if (EED->hasAssociatedValues()) {
        useConformancesFromType(EED->getArgumentInterfaceType()
                                   ->getCanonicalType(genericSig));
      }
    }
  }

  if (isa<StructDecl>(NTD) || isa<ClassDecl>(NTD)) {
    for (auto *VD : NTD->getStoredProperties()) {
      useConformancesFromType(VD->getValueInterfaceType()
                                ->getCanonicalType(genericSig));
    }
  }

  if (auto *CD = dyn_cast<ClassDecl>(NTD))
    if (auto superclass = CD->getSuperclass())
      useConformancesFromType(superclass->getCanonicalType(genericSig));

  if (auto *PD = dyn_cast<ProtocolDecl>(NTD)) {
    for (auto reqt : PD->getRequirementSignature().getRequirements()) {
      if (reqt.getKind() != RequirementKind::Layout)
        useConformancesFromType(reqt.getSecondType()->getCanonicalType());
    }
  }
}
<|endoftext|>


<commit_before>/*
 * Copyright 2015, Gerasim Troeglazov, 3dEyes@gmail.com. All rights reserved.
 * Distributed under the terms of the MIT License.
 */

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#include "ConfigView.h"
#include "SVGTranslator.h"
#include "SVGLoader.h"

#define kSVGMimeType "image/svg+xml"
#define kSVGName "SVG Image"

static const translation_format sInputFormats[] = {
	{
		SVG_IMAGE_FORMAT,
		B_TRANSLATOR_BITMAP,
		SVG_IN_QUALITY,
		SVG_IN_CAPABILITY,
		kSVGMimeType,
		kSVGName
	},
};

static const translation_format sOutputFormats[] = {
	{
		B_TRANSLATOR_BITMAP,
		B_TRANSLATOR_BITMAP,
		BITS_OUT_QUALITY,
		BITS_OUT_CAPABILITY,
		"image/x-be-bitmap",
		"Be Bitmap Format (NanoSVGTranslator)"
	},
};

static const TranSetting sDefaultSettings[] = {
	{B_TRANSLATOR_EXT_HEADER_ONLY, TRAN_SETTING_BOOL, false},
	{B_TRANSLATOR_EXT_DATA_ONLY, TRAN_SETTING_BOOL, false},
	{SVG_SETTING_SCALE, TRAN_SETTING_INT32, 10}
};

const uint32 kNumInputFormats = sizeof(sInputFormats)
	/ sizeof(translation_format);
const uint32 kNumOutputFormats = sizeof(sOutputFormats)
	/ sizeof(translation_format);
const uint32 kNumDefaultSettings = sizeof(sDefaultSettings)
	/ sizeof(TranSetting);

SVGTranslator::SVGTranslator()
	: BaseTranslator("SVG Image",
		"SVG image translator",
		SVG_TRANSLATOR_VERSION,
		sInputFormats, kNumInputFormats,
		sOutputFormats, kNumOutputFormats,
		"NanoSVGTranslator",
		sDefaultSettings, kNumDefaultSettings,
		B_TRANSLATOR_BITMAP, SVG_IMAGE_FORMAT)
{
}

SVGTranslator::~SVGTranslator()
{
}

status_t
SVGTranslator::DerivedIdentify(BPositionIO *stream,
	const translation_format *format, BMessage *ioExtension,
	translator_info *info, uint32 outType)
{
	if (outType != B_TRANSLATOR_BITMAP)
		return B_NO_TRANSLATOR;

	char svgData[513];
	ssize_t readedBytes = 512;
	readedBytes = stream->Read(svgData, 512);
	svgData[readedBytes] = 0;

	if(strncasecmp(svgData, "<?xml", 5) != 0)
		return B_NO_TRANSLATOR;

	if(strcasestr(svgData, "<svg") == NULL
		&& strcasestr(svgData, "<!DOCTYPE SVG") == NULL) {
		return B_NO_TRANSLATOR;
	}

	info->type = SVG_IMAGE_FORMAT;
	info->group = B_TRANSLATOR_BITMAP;
	info->quality = SVG_IN_QUALITY;
	info->capability = SVG_IN_CAPABILITY;
	strcpy(info->name, kSVGName);
	strcpy(info->MIME, kSVGMimeType);

	return B_OK;
}

status_t
SVGTranslator::DerivedTranslate(BPositionIO *source,
	const translator_info *info, BMessage *ioExtension,
	uint32 outType, BPositionIO *target, int32 baseType)
{
	if (outType != B_TRANSLATOR_BITMAP)
		return B_NO_TRANSLATOR;

	switch (baseType) {
		case 0:
		{
			if (outType != B_TRANSLATOR_BITMAP)
				return B_NO_TRANSLATOR;

			SVGLoader SVGFile(source);
			if (!SVGFile.IsParsed())
				return B_NO_TRANSLATOR;
			float scale = fSettings->SetGetInt32(SVG_SETTING_SCALE) / 10.0;
			return SVGFile.RenderImage(target, scale);
		}

		default:
			return B_NO_TRANSLATOR;
	}
}

status_t
SVGTranslator::DerivedCanHandleImageSize(float width, float height) const
{
	return B_OK;
}

BView *
SVGTranslator::NewConfigView(TranslatorSettings *settings)
{
	return new ConfigView(settings);
}

BTranslator *
make_nth_translator(int32 n, image_id you, uint32 flags, ...)
{
	if (n != 0)
		return NULL;

	return new SVGTranslator();
}

<commit_msg>Fix image->images<commit_after>/*
 * Copyright 2015, Gerasim Troeglazov, 3dEyes@gmail.com. All rights reserved.
 * Distributed under the terms of the MIT License.
 */

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#include "ConfigView.h"
#include "SVGTranslator.h"
#include "SVGLoader.h"

#define kSVGMimeType "image/svg+xml"
#define kSVGName "SVG Image"

static const translation_format sInputFormats[] = {
	{
		SVG_IMAGE_FORMAT,
		B_TRANSLATOR_BITMAP,
		SVG_IN_QUALITY,
		SVG_IN_CAPABILITY,
		kSVGMimeType,
		kSVGName
	},
};

static const translation_format sOutputFormats[] = {
	{
		B_TRANSLATOR_BITMAP,
		B_TRANSLATOR_BITMAP,
		BITS_OUT_QUALITY,
		BITS_OUT_CAPABILITY,
		"image/x-be-bitmap",
		"Be Bitmap Format (NanoSVGTranslator)"
	},
};

static const TranSetting sDefaultSettings[] = {
	{B_TRANSLATOR_EXT_HEADER_ONLY, TRAN_SETTING_BOOL, false},
	{B_TRANSLATOR_EXT_DATA_ONLY, TRAN_SETTING_BOOL, false},
	{SVG_SETTING_SCALE, TRAN_SETTING_INT32, 10}
};

const uint32 kNumInputFormats = sizeof(sInputFormats)
	/ sizeof(translation_format);
const uint32 kNumOutputFormats = sizeof(sOutputFormats)
	/ sizeof(translation_format);
const uint32 kNumDefaultSettings = sizeof(sDefaultSettings)
	/ sizeof(TranSetting);

SVGTranslator::SVGTranslator()
	: BaseTranslator("SVG Images",
		"SVG image translator",
		SVG_TRANSLATOR_VERSION,
		sInputFormats, kNumInputFormats,
		sOutputFormats, kNumOutputFormats,
		"NanoSVGTranslator",
		sDefaultSettings, kNumDefaultSettings,
		B_TRANSLATOR_BITMAP, SVG_IMAGE_FORMAT)
{
}

SVGTranslator::~SVGTranslator()
{
}

status_t
SVGTranslator::DerivedIdentify(BPositionIO *stream,
	const translation_format *format, BMessage *ioExtension,
	translator_info *info, uint32 outType)
{
	if (outType != B_TRANSLATOR_BITMAP)
		return B_NO_TRANSLATOR;

	char svgData[513];
	ssize_t readedBytes = 512;
	readedBytes = stream->Read(svgData, 512);
	svgData[readedBytes] = 0;

	if(strncasecmp(svgData, "<?xml", 5) != 0)
		return B_NO_TRANSLATOR;

	if(strcasestr(svgData, "<svg") == NULL
		&& strcasestr(svgData, "<!DOCTYPE SVG") == NULL) {
		return B_NO_TRANSLATOR;
	}

	info->type = SVG_IMAGE_FORMAT;
	info->group = B_TRANSLATOR_BITMAP;
	info->quality = SVG_IN_QUALITY;
	info->capability = SVG_IN_CAPABILITY;
	strcpy(info->name, kSVGName);
	strcpy(info->MIME, kSVGMimeType);

	return B_OK;
}

status_t
SVGTranslator::DerivedTranslate(BPositionIO *source,
	const translator_info *info, BMessage *ioExtension,
	uint32 outType, BPositionIO *target, int32 baseType)
{
	if (outType != B_TRANSLATOR_BITMAP)
		return B_NO_TRANSLATOR;

	switch (baseType) {
		case 0:
		{
			if (outType != B_TRANSLATOR_BITMAP)
				return B_NO_TRANSLATOR;

			SVGLoader SVGFile(source);
			if (!SVGFile.IsParsed())
				return B_NO_TRANSLATOR;
			float scale = fSettings->SetGetInt32(SVG_SETTING_SCALE) / 10.0;
			return SVGFile.RenderImage(target, scale);
		}

		default:
			return B_NO_TRANSLATOR;
	}
}

status_t
SVGTranslator::DerivedCanHandleImageSize(float width, float height) const
{
	return B_OK;
}

BView *
SVGTranslator::NewConfigView(TranslatorSettings *settings)
{
	return new ConfigView(settings);
}

BTranslator *
make_nth_translator(int32 n, image_id you, uint32 flags, ...)
{
	if (n != 0)
		return NULL;

	return new SVGTranslator();
}

<|endoftext|>


<commit_before>// Setup.cpp : Defines the entry point for the application.
//

#include "stdafx.h"
#include "Setup.h"
#include "FxHelper.h"
#include "UpdateRunner.h"
#include "MachineInstaller.h"
#include "windows.h"
#include "fcntl.h"
#include "io.h"
#include <cstdio>

CAppModule* _Module;

typedef BOOL(WINAPI *SetDefaultDllDirectoriesFunction)(DWORD DirectoryFlags);

int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
                      _In_opt_ HINSTANCE hPrevInstance,
                      _In_ LPWSTR lpCmdLine,
                      _In_ int nCmdShow)
{
	// Attempt to mitigate http://textslashplain.com/2015/12/18/dll-hijacking-just-wont-die
	HMODULE hKernel32 = LoadLibrary(L"kernel32.dll");
	ATLASSERT(hKernel32 != NULL);

	SetDefaultDllDirectoriesFunction pfn = (SetDefaultDllDirectoriesFunction) GetProcAddress(hKernel32, "SetDefaultDllDirectories");
	if (pfn) { (*pfn)(LOAD_LIBRARY_SEARCH_SYSTEM32); }

	int exitCode = -1;
	CString cmdLine(lpCmdLine);

	if (cmdLine.Find(L"--checkInstall") >= 0) {
		// If we're already installed, exit as fast as possible
		if (!MachineInstaller::ShouldSilentInstall()) {
			exitCode = 0;
			goto out;
		}

		// Make sure update.exe gets silent
		wcscat(lpCmdLine, L" --silent");
	}

	HRESULT hr = ::CoInitialize(NULL);
	ATLASSERT(SUCCEEDED(hr));

	AtlInitCommonControls(ICC_COOL_CLASSES | ICC_BAR_CLASSES);
	_Module = new CAppModule();
	hr = _Module->Init(NULL, hInstance);

	bool isQuiet = (cmdLine.Find(L"-s") >= 0);
	bool weAreUACElevated = CUpdateRunner::AreWeUACElevated() == S_OK;
	bool attemptingToRerun = (cmdLine.Find(L"--rerunningWithoutUAC") >= 0);

	bool allUsersInstall = (cmdLine.Find(L"--allUsers") >= 0);

	if (allUsersInstall && !weAreUACElevated && !isQuiet)
	{
		// We will give a warning but NOT exit. Per BL-3404, it seems sometimes AreWeUACElevated
		// does not accurately indicate whether we will be able to install in program files.
		// So, we try to give the user a hint of what might be wrong in case it fails, but
		// go ahead and attempt the installation.

		// This bit of magic allows a windows application to attach to the console of its parent
		// (that is, to write to the DOS box from which we hope it was launched).
		// Currently (since about 3.9) it doesn't seem to be working, and I can't figure out why.
		// So I've gone back to the messagebox below.
		// Keeping this code for now since it just possibly might do something helpful in a network
		// install situation where the message box can't be seen.
		// If we can't attach to a parent console we just give up on sending this warning.
		// Some of the examples from which this code was adapted create a private console for the
		// program, but that isn't helpful in our most likely allUsers scenario when a domain
		// admin is installing on a remote machine.
		// If we really don't have admin privileges we will soon dialog saying we can't unpack the files.
		if (AttachConsole(ATTACH_PARENT_PROCESS)) {
			// A further part of the magic is to redirect unbuffered STDERR to the console.
			// We don't bother with stdout because we don't use it, but if we did it would
			// require its own redirection.
			HANDLE consoleHandleError = GetStdHandle(STD_ERROR_HANDLE);
			int fdError = _open_osfhandle((intptr_t)consoleHandleError, _O_TEXT);
			FILE * fpError = _fdopen(fdError, "w");
			*stderr = *fpError;
			setvbuf(stderr, NULL, _IONBF, 0);

			// Now we can actually write a message to stderr.
			fwprintf(stderr, L"\nWarning: all-users install requires the installer to be run with administrator privileges.\n");
			fflush(stderr);

			// Unfortunately, the dos box doesn't know to wait for this application to finish, so the
			// output appears following a command prompt. This attempts to type a return key to get a fresh prompt.
			INPUT ip;
			// Set up a generic keyboard event.
			ip.type = INPUT_KEYBOARD;
			ip.ki.wScan = 0; // hardware scan code for key
			ip.ki.time = 0;
			ip.ki.dwExtraInfo = 0;
			// Send the "Enter" key
			ip.ki.wVk = 0x0D; // virtual-key code for the "Enter" key
			ip.ki.dwFlags = 0; // 0 for key press
			SendInput(1, &ip, sizeof(INPUT));
			// Release the "Enter" key
			ip.ki.dwFlags = KEYEVENTF_KEYUP;  // KEYEVENTF_KEYUP for key release
			SendInput(1, &ip, sizeof(INPUT));
		}

		if (MessageBox(0L, L"Warning: you appear to be attempting an allUsers install without required administrator privileges\n.Do you want to try anyway?",
			L"Need to run as Administrator",
			MB_YESNO | MB_DEFBUTTON2 | MB_ICONWARNING) != IDYES)
		{
			exitCode = E_FAIL;
			goto out;
		}
	}

	if (weAreUACElevated && attemptingToRerun) {
		CUpdateRunner::DisplayErrorMessage(CString(L"Please re-run this installer as a normal user instead of \"Run as Administrator\"."), NULL);
		exitCode = E_FAIL;
		goto out;
	}

	if (!CFxHelper::CanInstallDotNet4_5()) {
		// Explain this as nicely as possible and give up.
		MessageBox(0L, L"Bloom cannot run on Windows XP or before; it requires a later version of Windows. You can still find Bloom 3.0, which runs on XP, on our website.", L"Incompatible Operating System", 0);
		exitCode = E_FAIL;
		goto out;
	}

	if (!CFxHelper::IsDotNet45OrHigherInstalled()) {
		hr = CFxHelper::InstallDotNetFramework(isQuiet);
		if (FAILED(hr)) {
			exitCode = hr; // #yolo
			CUpdateRunner::DisplayErrorMessage(CString(L"Failed to install the .NET Framework, try installing .NET 4.5 or higher manually"), NULL);
			goto out;
		}

		// S_FALSE isn't failure, but we still shouldn't try to install
		if (hr != S_OK) {
			exitCode = 0;
			goto out;
		}
	}

	// If we're UAC-elevated (and not doing all-users install), we shouldn't be because it will give us permissions
	// problems later. Just silently rerun ourselves.
	if (weAreUACElevated && !allUsersInstall) {
		wchar_t buf[4096];
		HMODULE hMod = GetModuleHandle(NULL);
		GetModuleFileNameW(hMod, buf, 4096);
		wcscat(lpCmdLine, L" --rerunningWithoutUAC");

		CUpdateRunner::ShellExecuteFromExplorer(buf, lpCmdLine);
		exitCode = 0;
		goto out;
	}

	exitCode = CUpdateRunner::ExtractUpdaterAndRun(lpCmdLine, false);

out:
	_Module->Term();
	::CoUninitialize();
	return exitCode;
}
<commit_msg>Fix typo<commit_after>// Setup.cpp : Defines the entry point for the application.
//

#include "stdafx.h"
#include "Setup.h"
#include "FxHelper.h"
#include "UpdateRunner.h"
#include "MachineInstaller.h"
#include "windows.h"
#include "fcntl.h"
#include "io.h"
#include <cstdio>

CAppModule* _Module;

typedef BOOL(WINAPI *SetDefaultDllDirectoriesFunction)(DWORD DirectoryFlags);

int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
                      _In_opt_ HINSTANCE hPrevInstance,
                      _In_ LPWSTR lpCmdLine,
                      _In_ int nCmdShow)
{
	// Attempt to mitigate http://textslashplain.com/2015/12/18/dll-hijacking-just-wont-die
	HMODULE hKernel32 = LoadLibrary(L"kernel32.dll");
	ATLASSERT(hKernel32 != NULL);

	SetDefaultDllDirectoriesFunction pfn = (SetDefaultDllDirectoriesFunction) GetProcAddress(hKernel32, "SetDefaultDllDirectories");
	if (pfn) { (*pfn)(LOAD_LIBRARY_SEARCH_SYSTEM32); }

	int exitCode = -1;
	CString cmdLine(lpCmdLine);

	if (cmdLine.Find(L"--checkInstall") >= 0) {
		// If we're already installed, exit as fast as possible
		if (!MachineInstaller::ShouldSilentInstall()) {
			exitCode = 0;
			goto out;
		}

		// Make sure update.exe gets silent
		wcscat(lpCmdLine, L" --silent");
	}

	HRESULT hr = ::CoInitialize(NULL);
	ATLASSERT(SUCCEEDED(hr));

	AtlInitCommonControls(ICC_COOL_CLASSES | ICC_BAR_CLASSES);
	_Module = new CAppModule();
	hr = _Module->Init(NULL, hInstance);

	bool isQuiet = (cmdLine.Find(L"-s") >= 0);
	bool weAreUACElevated = CUpdateRunner::AreWeUACElevated() == S_OK;
	bool attemptingToRerun = (cmdLine.Find(L"--rerunningWithoutUAC") >= 0);

	bool allUsersInstall = (cmdLine.Find(L"--allUsers") >= 0);

	if (allUsersInstall && !weAreUACElevated && !isQuiet)
	{
		// We will give a warning but NOT exit. Per BL-3404, it seems sometimes AreWeUACElevated
		// does not accurately indicate whether we will be able to install in program files.
		// So, we try to give the user a hint of what might be wrong in case it fails, but
		// go ahead and attempt the installation.

		// This bit of magic allows a windows application to attach to the console of its parent
		// (that is, to write to the DOS box from which we hope it was launched).
		// Currently (since about 3.9) it doesn't seem to be working, and I can't figure out why.
		// So I've gone back to the messagebox below.
		// Keeping this code for now since it just possibly might do something helpful in a network
		// install situation where the message box can't be seen.
		// If we can't attach to a parent console we just give up on sending this warning.
		// Some of the examples from which this code was adapted create a private console for the
		// program, but that isn't helpful in our most likely allUsers scenario when a domain
		// admin is installing on a remote machine.
		// If we really don't have admin privileges we will soon dialog saying we can't unpack the files.
		if (AttachConsole(ATTACH_PARENT_PROCESS)) {
			// A further part of the magic is to redirect unbuffered STDERR to the console.
			// We don't bother with stdout because we don't use it, but if we did it would
			// require its own redirection.
			HANDLE consoleHandleError = GetStdHandle(STD_ERROR_HANDLE);
			int fdError = _open_osfhandle((intptr_t)consoleHandleError, _O_TEXT);
			FILE * fpError = _fdopen(fdError, "w");
			*stderr = *fpError;
			setvbuf(stderr, NULL, _IONBF, 0);

			// Now we can actually write a message to stderr.
			fwprintf(stderr, L"\nWarning: all-users install requires the installer to be run with administrator privileges.\n");
			fflush(stderr);

			// Unfortunately, the dos box doesn't know to wait for this application to finish, so the
			// output appears following a command prompt. This attempts to type a return key to get a fresh prompt.
			INPUT ip;
			// Set up a generic keyboard event.
			ip.type = INPUT_KEYBOARD;
			ip.ki.wScan = 0; // hardware scan code for key
			ip.ki.time = 0;
			ip.ki.dwExtraInfo = 0;
			// Send the "Enter" key
			ip.ki.wVk = 0x0D; // virtual-key code for the "Enter" key
			ip.ki.dwFlags = 0; // 0 for key press
			SendInput(1, &ip, sizeof(INPUT));
			// Release the "Enter" key
			ip.ki.dwFlags = KEYEVENTF_KEYUP;  // KEYEVENTF_KEYUP for key release
			SendInput(1, &ip, sizeof(INPUT));
		}

		if (MessageBox(0L, L"Warning: you appear to be attempting an allUsers install without required administrator privileges.\nDo you want to try anyway?",
			L"Need to run as Administrator",
			MB_YESNO | MB_DEFBUTTON2 | MB_ICONWARNING) != IDYES)
		{
			exitCode = E_FAIL;
			goto out;
		}
	}

	if (weAreUACElevated && attemptingToRerun) {
		CUpdateRunner::DisplayErrorMessage(CString(L"Please re-run this installer as a normal user instead of \"Run as Administrator\"."), NULL);
		exitCode = E_FAIL;
		goto out;
	}

	if (!CFxHelper::CanInstallDotNet4_5()) {
		// Explain this as nicely as possible and give up.
		MessageBox(0L, L"Bloom cannot run on Windows XP or before; it requires a later version of Windows. You can still find Bloom 3.0, which runs on XP, on our website.", L"Incompatible Operating System", 0);
		exitCode = E_FAIL;
		goto out;
	}

	if (!CFxHelper::IsDotNet45OrHigherInstalled()) {
		hr = CFxHelper::InstallDotNetFramework(isQuiet);
		if (FAILED(hr)) {
			exitCode = hr; // #yolo
			CUpdateRunner::DisplayErrorMessage(CString(L"Failed to install the .NET Framework, try installing .NET 4.5 or higher manually"), NULL);
			goto out;
		}

		// S_FALSE isn't failure, but we still shouldn't try to install
		if (hr != S_OK) {
			exitCode = 0;
			goto out;
		}
	}

	// If we're UAC-elevated (and not doing all-users install), we shouldn't be because it will give us permissions
	// problems later. Just silently rerun ourselves.
	if (weAreUACElevated && !allUsersInstall) {
		wchar_t buf[4096];
		HMODULE hMod = GetModuleHandle(NULL);
		GetModuleFileNameW(hMod, buf, 4096);
		wcscat(lpCmdLine, L" --rerunningWithoutUAC");

		CUpdateRunner::ShellExecuteFromExplorer(buf, lpCmdLine);
		exitCode = 0;
		goto out;
	}

	exitCode = CUpdateRunner::ExtractUpdaterAndRun(lpCmdLine, false);

out:
	_Module->Term();
	::CoUninitialize();
	return exitCode;
}
<|endoftext|>