<commit_before>/*********************************************************************************
 *
 * Inviwo - Interactive Visualization Workshop
 *
 * Copyright (c) 2013-2016 Inviwo Foundation
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this
 * list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation
 * and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 *********************************************************************************/

#include <inviwo/core/datastructures/transferfunction.h>
#include <inviwo/core/datastructures/image/layerram.h>
#include <inviwo/core/datastructures/image/layer.h>
#include <inviwo/core/ports/imageport.h>
#include <inviwo/core/util/vectoroperations.h>
#include <math.h>

namespace inviwo {

TransferFunction::TransferFunction(int textureSize)
    : TransferFunctionObservable()
    , maskMin_(0.0f)
    , maskMax_(1.0f)
    , interpolationType_(InterpolationLinear)
    , textureSize_(textureSize)
    , invalidData_(true)
    , data_(new Layer(uvec2(textureSize, 1), DataVec4Float32::get())) {

    // initialize with standard ramp
    addPoint(vec2(0.0f,0.0f), vec4(0.0f,0.0f,0.0f,0.0f));
    addPoint(vec2(1.0f,1.0f), vec4(1.0f,1.0f,1.0f,1.0f));
}

TransferFunction::TransferFunction(const TransferFunction& rhs)
    : maskMin_(rhs.maskMin_)
    , maskMax_(rhs.maskMax_)
    , interpolationType_(rhs.interpolationType_)
    , textureSize_(rhs.textureSize_)
    , invalidData_(rhs.invalidData_)
    , data_(new Layer(*rhs.data_)) {

    for (int i = 0; i < rhs.getNumPoints(); i++) {
        addPoint(rhs.getPoint(i)->getPos(), rhs.getPoint(i)->getRGBA());
    }
}

TransferFunction& TransferFunction::operator=(const TransferFunction& rhs) {
    if (this != &rhs) {
        if (rhs.getData()->getDimensions() != data_->getDimensions()) {
            delete data_;
            data_ = new Layer(*rhs.data_);
        }
        clearPoints();
        textureSize_ = rhs.textureSize_;
        maskMin_ = rhs.maskMin_;
        maskMax_ = rhs.maskMax_;
        interpolationType_ = rhs.interpolationType_;

        for (int i = 0; i < rhs.getNumPoints(); i++) {
            addPoint(rhs.getPoint(i)->getPos(), rhs.getPoint(i)->getRGBA());
        }
    }
    invalidate();
    return *this;
}

TransferFunction::~TransferFunction() {
    clearPoints();
    delete data_;
}

TransferFunctionDataPoint* TransferFunction::getPoint(int i) const {
    return points_[i];
}

void TransferFunction::addPoint(const vec2& pos) {
    // determine color
    vec4 color = vec4(0.5f, 0.5f, 0.5f, pos.y);
    if (points_.size() > 0) {
        int leftNeighborID = 0;
        int rightNeighborID = 0;

        for (int i = 0; i < static_cast<int>(points_.size()); i++)
            if (points_[i]->getPos().x <= pos.x)
                leftNeighborID = i;
            else if (rightNeighborID == 0 && points_[i]->getPos().x > pos.x)
                rightNeighborID = i;

        vec4 colorL = points_[leftNeighborID]->getRGBA();
        vec4 colorR = points_[rightNeighborID]->getRGBA();
        float a = 0.5f;
        float denom = points_[rightNeighborID]->getPos().x - points_[leftNeighborID]->getPos().x;

        if (denom > 0.0) a = (points_[rightNeighborID]->getPos().x - pos.x) / denom;

        color = vec4(a * colorL.r + (1.0 - a) * colorR.r, a * colorL.g + (1.0 - a) * colorR.g,
                     a * colorL.b + (1.0 - a) * colorR.b, pos.y);
    }

    addPoint(pos, color);
}

void TransferFunction::addPoint(const vec2& pos, const vec4& color) {
    addPoint(new TransferFunctionDataPoint(pos, color));
}

void TransferFunction::addPoint(TransferFunctionDataPoint* dataPoint) {
    dataPoint->addObserver(this);
    TFPoints::iterator pos = std::lower_bound(points_.begin(), points_.end(), dataPoint,
                                              comparePtr<TransferFunctionDataPoint>);
    points_.insert(pos, dataPoint);

    invalidate();
    notifyControlPointAdded(dataPoint);
}

void TransferFunction::removePoint(TransferFunctionDataPoint* dataPoint) {
    TFPoints::iterator it = std::find(points_.begin(), points_.end(), dataPoint);
    if (it != points_.end()) {
        points_.erase(it);
        invalidate();
        notifyControlPointRemoved(dataPoint);
        delete dataPoint;
    }
}

void TransferFunction::clearPoints() {
    invalidate();
    while(points_.size() > 0) {
        TransferFunctionDataPoint* dataPoint = points_.back();
        points_.pop_back();
        notifyControlPointRemoved(dataPoint);
        delete dataPoint;
    }
}

void TransferFunction::onTransferFunctionPointChange(const TransferFunctionDataPoint* p){
    std::stable_sort(points_.begin(), points_.end(), comparePtr<TransferFunctionDataPoint>);
    invalidate();
    notifyControlPointChanged(p);
}

void TransferFunction::calcTransferValues() {
    vec4* dataArray = static_cast<vec4*>(data_->getEditableRepresentation<LayerRAM>()->getData());

    std::stable_sort(points_.begin(), points_.end(), comparePtr<TransferFunctionDataPoint>);

    if (points_.size() == 0) { // in case of 0 points
        for (int i = 0; i < textureSize_; i++) {
            dataArray[i] = vec4((float)i / (textureSize_ - 1.0), (float)i / (textureSize_ - 1.0),
                                (float)i / (textureSize_ - 1.0), 1.0);
        }
    } else if (points_.size() == 1) {  // in case of 1 point
        for (int i = 0; i < textureSize_; ++i) {
            dataArray[i] = points_[0]->getRGBA();
        }
    } else { // in case of more than 1 points
        int leftX = static_cast<int>(ceil(points_.front()->getPos().x * (textureSize_ - 1)));
        int rightX = static_cast<int>(ceil(points_.back()->getPos().x * (textureSize_ - 1)));

        for (int i = 0; i <= leftX; i++) dataArray[i] = points_.front()->getRGBA();
        for (int i = rightX; i < textureSize_; i++) dataArray[i] = points_.back()->getRGBA();

        // if (interpolationType_==TransferFunction::InterpolationLinear) {
        // linear interpolation
        auto pLeft = points_.begin();
        auto pRight = points_.begin() + 1;

        while (pRight != points_.end()) {
            int n = static_cast<int>(ceil((*pLeft)->getPos().x * (textureSize_ - 1)));

            while (n < ceil((*pRight)->getPos().x * (textureSize_ - 1))) {
                vec4 lrgba = (*pLeft)->getRGBA();
                vec4 rrgba = (*pRight)->getRGBA();
                float lx = (*pLeft)->getPos().x * (textureSize_ - 1);
                float rx = (*pRight)->getPos().x * (textureSize_ - 1);
                float alpha = (n - lx) / (rx - lx);
                dataArray[n] = alpha * rrgba + (1.0f - alpha) * lrgba;
                n++;
            }

            pLeft++;
            pRight++;
        }

        //} else {
        // cubic interpolation
        // TODO: implement cubic interpolation
        //}
    }

    for (int i = 0; i < int(maskMin_ * textureSize_); i++) dataArray[i].a = 0.0;
    for (int i = int(maskMax_ * textureSize_); i < textureSize_; i++) dataArray[i].a = 0.0;

    invalidData_ = false;
}

void TransferFunction::serialize(Serializer& s) const {
    s.serialize("maskMin", maskMin_);
    s.serialize("maskMax", maskMax_);
    s.serialize("dataPoints", points_, "point");
    s.serialize("interpolationType_", static_cast<int>(interpolationType_));
}

void TransferFunction::deserialize(Deserializer& d) {
    d.deserialize("maskMin", maskMin_);
    d.deserialize("maskMax", maskMax_);

    TFPoints toAdd;
    TFPoints toRemove;

    auto desPoints = util::IndexedDeserializer<TransferFunctionDataPoint*>("dataPoints", "point")
                         .setMakeNew([]() { return nullptr; })
                         .onNew([&](TransferFunctionDataPoint*& point) { toAdd.push_back(point); })
                         .onRemove([&](TransferFunctionDataPoint*& point) {
                             toRemove.push_back(point);
                             return false;
                         });
    desPoints(d, points_);
    for (auto point : toRemove) removePoint(point);
    for (auto point : toAdd) addPoint(point);

    int type = static_cast<int>(interpolationType_);
    d.deserialize("interpolationType_", type);
    interpolationType_ = static_cast<TransferFunction::InterpolationType>(type);

    invalidate();
}

inviwo::vec4 TransferFunction::sample(float v) const {
    if (v < 0) {
        return points_.front()->getRGBA();
    }
    else if (v > 1) {
        return points_.back()->getRGBA();
    }

    auto it = std::upper_bound(points_.begin(), points_.end(), v, [](float v , const TransferFunctionDataPoint* p) {
        return v < p->getPos().x;
    });
    if (it == points_.begin()) {
        return points_.front()->getRGBA();
    }
    if (it == points_.end()) {
        return points_.back()->getRGBA();
    }

    auto next = it--;
    float x = (v - (*it)->getPos().x) / ((*next)->getPos().x - (*it)->getPos().x);
    return Interpolation<vec4, float>::linear((*it)->getRGBA(), (*next)->getRGBA(), x);
}

const Layer* TransferFunction::getData() const {
    if (invalidData_) {
        const_cast<TransferFunction*>(this)->calcTransferValues();
    }
    return data_;
}

void TransferFunction::invalidate() {
    invalidData_ = true;
}

float TransferFunction::getMaskMin() const {
    return maskMin_;
}

void TransferFunction::setMaskMin(float maskMin) {
    maskMin_ = maskMin;
    invalidate();
}

float TransferFunction::getMaskMax() const {
    return maskMax_;
}

void TransferFunction::setMaskMax(float maskMax) {
    maskMax_ = maskMax;
    invalidate();
}

void TransferFunction::setInterpolationType(InterpolationType interpolationType) {
    interpolationType_ = interpolationType;
    invalidate();
}

inviwo::TransferFunction::InterpolationType TransferFunction::getInterpolationType() const {
    return interpolationType_;
}

int TransferFunction::getTextureSize() {
    return textureSize_;
}

int TransferFunction::getNumPoints() const {
    return static_cast<int>(points_.size());
}

void TransferFunctionObservable::notifyControlPointAdded(TransferFunctionDataPoint* p) {
    forEachObserver([&](TransferFunctionObserver* o){o->onControlPointAdded(p);});
}

void TransferFunctionObservable::notifyControlPointRemoved(TransferFunctionDataPoint* p) {
    forEachObserver([&](TransferFunctionObserver* o){o->onControlPointRemoved(p);});
}

void TransferFunctionObservable::notifyControlPointChanged(const TransferFunctionDataPoint* p) {
    forEachObserver([&](TransferFunctionObserver* o){o->onControlPointChanged(p);});
}

bool operator==(const TransferFunction& lhs, const TransferFunction& rhs) {
    return lhs.maskMin_ == rhs.maskMin_
        && lhs.maskMax_ == rhs.maskMax_
        && lhs.interpolationType_ == rhs.interpolationType_
        && lhs.points_ == rhs.points_;
}

bool operator!=(const TransferFunction& lhs, const TransferFunction& rhs) {
    return !operator==(lhs, rhs);
}

}<commit_msg>Core: Include fix<commit_after>/*********************************************************************************
 *
 * Inviwo - Interactive Visualization Workshop
 *
 * Copyright (c) 2013-2016 Inviwo Foundation
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this
 * list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation
 * and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 *********************************************************************************/

#include <inviwo/core/datastructures/transferfunction.h>
#include <inviwo/core/datastructures/image/layerram.h>
#include <inviwo/core/datastructures/image/layer.h>
#include <inviwo/core/ports/imageport.h>
#include <inviwo/core/util/vectoroperations.h>
#include <inviwo/core/util/interpolation.h>
#include <math.h>

namespace inviwo {

TransferFunction::TransferFunction(int textureSize)
    : TransferFunctionObservable()
    , maskMin_(0.0f)
    , maskMax_(1.0f)
    , interpolationType_(InterpolationLinear)
    , textureSize_(textureSize)
    , invalidData_(true)
    , data_(new Layer(uvec2(textureSize, 1), DataVec4Float32::get())) {

    // initialize with standard ramp
    addPoint(vec2(0.0f,0.0f), vec4(0.0f,0.0f,0.0f,0.0f));
    addPoint(vec2(1.0f,1.0f), vec4(1.0f,1.0f,1.0f,1.0f));
}

TransferFunction::TransferFunction(const TransferFunction& rhs)
    : maskMin_(rhs.maskMin_)
    , maskMax_(rhs.maskMax_)
    , interpolationType_(rhs.interpolationType_)
    , textureSize_(rhs.textureSize_)
    , invalidData_(rhs.invalidData_)
    , data_(new Layer(*rhs.data_)) {

    for (int i = 0; i < rhs.getNumPoints(); i++) {
        addPoint(rhs.getPoint(i)->getPos(), rhs.getPoint(i)->getRGBA());
    }
}

TransferFunction& TransferFunction::operator=(const TransferFunction& rhs) {
    if (this != &rhs) {
        if (rhs.getData()->getDimensions() != data_->getDimensions()) {
            delete data_;
            data_ = new Layer(*rhs.data_);
        }
        clearPoints();
        textureSize_ = rhs.textureSize_;
        maskMin_ = rhs.maskMin_;
        maskMax_ = rhs.maskMax_;
        interpolationType_ = rhs.interpolationType_;

        for (int i = 0; i < rhs.getNumPoints(); i++) {
            addPoint(rhs.getPoint(i)->getPos(), rhs.getPoint(i)->getRGBA());
        }
    }
    invalidate();
    return *this;
}

TransferFunction::~TransferFunction() {
    clearPoints();
    delete data_;
}

TransferFunctionDataPoint* TransferFunction::getPoint(int i) const {
    return points_[i];
}

void TransferFunction::addPoint(const vec2& pos) {
    // determine color
    vec4 color = vec4(0.5f, 0.5f, 0.5f, pos.y);
    if (points_.size() > 0) {
        int leftNeighborID = 0;
        int rightNeighborID = 0;

        for (int i = 0; i < static_cast<int>(points_.size()); i++)
            if (points_[i]->getPos().x <= pos.x)
                leftNeighborID = i;
            else if (rightNeighborID == 0 && points_[i]->getPos().x > pos.x)
                rightNeighborID = i;

        vec4 colorL = points_[leftNeighborID]->getRGBA();
        vec4 colorR = points_[rightNeighborID]->getRGBA();
        float a = 0.5f;
        float denom = points_[rightNeighborID]->getPos().x - points_[leftNeighborID]->getPos().x;

        if (denom > 0.0) a = (points_[rightNeighborID]->getPos().x - pos.x) / denom;

        color = vec4(a * colorL.r + (1.0 - a) * colorR.r, a * colorL.g + (1.0 - a) * colorR.g,
                     a * colorL.b + (1.0 - a) * colorR.b, pos.y);
    }

    addPoint(pos, color);
}

void TransferFunction::addPoint(const vec2& pos, const vec4& color) {
    addPoint(new TransferFunctionDataPoint(pos, color));
}

void TransferFunction::addPoint(TransferFunctionDataPoint* dataPoint) {
    dataPoint->addObserver(this);
    TFPoints::iterator pos = std::lower_bound(points_.begin(), points_.end(), dataPoint,
                                              comparePtr<TransferFunctionDataPoint>);
    points_.insert(pos, dataPoint);

    invalidate();
    notifyControlPointAdded(dataPoint);
}

void TransferFunction::removePoint(TransferFunctionDataPoint* dataPoint) {
    TFPoints::iterator it = std::find(points_.begin(), points_.end(), dataPoint);
    if (it != points_.end()) {
        points_.erase(it);
        invalidate();
        notifyControlPointRemoved(dataPoint);
        delete dataPoint;
    }
}

void TransferFunction::clearPoints() {
    invalidate();
    while(points_.size() > 0) {
        TransferFunctionDataPoint* dataPoint = points_.back();
        points_.pop_back();
        notifyControlPointRemoved(dataPoint);
        delete dataPoint;
    }
}

void TransferFunction::onTransferFunctionPointChange(const TransferFunctionDataPoint* p){
    std::stable_sort(points_.begin(), points_.end(), comparePtr<TransferFunctionDataPoint>);
    invalidate();
    notifyControlPointChanged(p);
}

void TransferFunction::calcTransferValues() {
    vec4* dataArray = static_cast<vec4*>(data_->getEditableRepresentation<LayerRAM>()->getData());

    std::stable_sort(points_.begin(), points_.end(), comparePtr<TransferFunctionDataPoint>);

    if (points_.size() == 0) { // in case of 0 points
        for (int i = 0; i < textureSize_; i++) {
            dataArray[i] = vec4((float)i / (textureSize_ - 1.0), (float)i / (textureSize_ - 1.0),
                                (float)i / (textureSize_ - 1.0), 1.0);
        }
    } else if (points_.size() == 1) {  // in case of 1 point
        for (int i = 0; i < textureSize_; ++i) {
            dataArray[i] = points_[0]->getRGBA();
        }
    } else { // in case of more than 1 points
        int leftX = static_cast<int>(ceil(points_.front()->getPos().x * (textureSize_ - 1)));
        int rightX = static_cast<int>(ceil(points_.back()->getPos().x * (textureSize_ - 1)));

        for (int i = 0; i <= leftX; i++) dataArray[i] = points_.front()->getRGBA();
        for (int i = rightX; i < textureSize_; i++) dataArray[i] = points_.back()->getRGBA();

        // if (interpolationType_==TransferFunction::InterpolationLinear) {
        // linear interpolation
        auto pLeft = points_.begin();
        auto pRight = points_.begin() + 1;

        while (pRight != points_.end()) {
            int n = static_cast<int>(ceil((*pLeft)->getPos().x * (textureSize_ - 1)));

            while (n < ceil((*pRight)->getPos().x * (textureSize_ - 1))) {
                vec4 lrgba = (*pLeft)->getRGBA();
                vec4 rrgba = (*pRight)->getRGBA();
                float lx = (*pLeft)->getPos().x * (textureSize_ - 1);
                float rx = (*pRight)->getPos().x * (textureSize_ - 1);
                float alpha = (n - lx) / (rx - lx);
                dataArray[n] = alpha * rrgba + (1.0f - alpha) * lrgba;
                n++;
            }

            pLeft++;
            pRight++;
        }

        //} else {
        // cubic interpolation
        // TODO: implement cubic interpolation
        //}
    }

    for (int i = 0; i < int(maskMin_ * textureSize_); i++) dataArray[i].a = 0.0;
    for (int i = int(maskMax_ * textureSize_); i < textureSize_; i++) dataArray[i].a = 0.0;

    invalidData_ = false;
}

void TransferFunction::serialize(Serializer& s) const {
    s.serialize("maskMin", maskMin_);
    s.serialize("maskMax", maskMax_);
    s.serialize("dataPoints", points_, "point");
    s.serialize("interpolationType_", static_cast<int>(interpolationType_));
}

void TransferFunction::deserialize(Deserializer& d) {
    d.deserialize("maskMin", maskMin_);
    d.deserialize("maskMax", maskMax_);

    TFPoints toAdd;
    TFPoints toRemove;

    auto desPoints = util::IndexedDeserializer<TransferFunctionDataPoint*>("dataPoints", "point")
                         .setMakeNew([]() { return nullptr; })
                         .onNew([&](TransferFunctionDataPoint*& point) { toAdd.push_back(point); })
                         .onRemove([&](TransferFunctionDataPoint*& point) {
                             toRemove.push_back(point);
                             return false;
                         });
    desPoints(d, points_);
    for (auto point : toRemove) removePoint(point);
    for (auto point : toAdd) addPoint(point);

    int type = static_cast<int>(interpolationType_);
    d.deserialize("interpolationType_", type);
    interpolationType_ = static_cast<TransferFunction::InterpolationType>(type);

    invalidate();
}

vec4 TransferFunction::sample(float v) const {
    if (v < 0) {
        return points_.front()->getRGBA();
    }
    else if (v > 1) {
        return points_.back()->getRGBA();
    }

    auto it = std::upper_bound(
        points_.begin(), points_.end(), v,
        [](float v, const TransferFunctionDataPoint* p) { return v < p->getPos().x; });
    if (it == points_.begin()) {
        return points_.front()->getRGBA();
    }
    if (it == points_.end()) {
        return points_.back()->getRGBA();
    }

    auto next = it--;
    float x = (v - (*it)->getPos().x) / ((*next)->getPos().x - (*it)->getPos().x);
    return Interpolation<vec4, float>::linear((*it)->getRGBA(), (*next)->getRGBA(), x);
}

const Layer* TransferFunction::getData() const {
    if (invalidData_) {
        const_cast<TransferFunction*>(this)->calcTransferValues();
    }
    return data_;
}

void TransferFunction::invalidate() {
    invalidData_ = true;
}

float TransferFunction::getMaskMin() const {
    return maskMin_;
}

void TransferFunction::setMaskMin(float maskMin) {
    maskMin_ = maskMin;
    invalidate();
}

float TransferFunction::getMaskMax() const {
    return maskMax_;
}

void TransferFunction::setMaskMax(float maskMax) {
    maskMax_ = maskMax;
    invalidate();
}

void TransferFunction::setInterpolationType(InterpolationType interpolationType) {
    interpolationType_ = interpolationType;
    invalidate();
}

inviwo::TransferFunction::InterpolationType TransferFunction::getInterpolationType() const {
    return interpolationType_;
}

int TransferFunction::getTextureSize() {
    return textureSize_;
}

int TransferFunction::getNumPoints() const {
    return static_cast<int>(points_.size());
}

void TransferFunctionObservable::notifyControlPointAdded(TransferFunctionDataPoint* p) {
    forEachObserver([&](TransferFunctionObserver* o){o->onControlPointAdded(p);});
}

void TransferFunctionObservable::notifyControlPointRemoved(TransferFunctionDataPoint* p) {
    forEachObserver([&](TransferFunctionObserver* o){o->onControlPointRemoved(p);});
}

void TransferFunctionObservable::notifyControlPointChanged(const TransferFunctionDataPoint* p) {
    forEachObserver([&](TransferFunctionObserver* o){o->onControlPointChanged(p);});
}

bool operator==(const TransferFunction& lhs, const TransferFunction& rhs) {
    return lhs.maskMin_ == rhs.maskMin_
        && lhs.maskMax_ == rhs.maskMax_
        && lhs.interpolationType_ == rhs.interpolationType_
        && lhs.points_ == rhs.points_;
}

bool operator!=(const TransferFunction& lhs, const TransferFunction& rhs) {
    return !operator==(lhs, rhs);
}

}<|endoftext|>


<commit_before>/*
 * Process.hpp
 *
 * Copyright (C) 2009-11 by RStudio, Inc.
 *
 * This program is licensed to you under the terms of version 3 of the
 * GNU Affero General Public License. This program is distributed WITHOUT
 * ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING THOSE OF NON-INFRINGEMENT,
 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Please refer to the
 * AGPL (http://www.gnu.org/licenses/agpl-3.0.txt) for more details.
 *
 */

#ifndef CORE_SYSTEM_PROCESS_HPP
#define CORE_SYSTEM_PROCESS_HPP

#include <vector>

#include <boost/optional.hpp>
#include <boost/utility.hpp>
#include <boost/function.hpp>
#include <boost/scoped_ptr.hpp>
#include <boost/date_time/posix_time/posix_time_types.hpp>

#include <core/system/Types.hpp>
#include <core/FilePath.hpp>

namespace core {

class Error;

namespace system {

////////////////////////////////////////////////////////////////////////////////
//
// Run child process synchronously
//
//

// Struct for speicfying pseudoterminal options
struct Pseudoterminal
{
   Pseudoterminal(int cols, int rows)
      : cols(cols), rows(rows)
   {
   }

   int cols;
   int rows;
};

// Struct for specifying process options
struct ProcessOptions
{
   ProcessOptions()
#ifdef _WIN32
      : terminateChildren(false),
        detachProcess(false),
        redirectStdErrToStdOut(false)
#else
      : terminateChildren(false),
        detachSession(false),
        redirectStdErrToStdOut(false)
#endif
   {
   }

   // environment variables to set for the child process
   // if you want to simply merge in some additional environment
   // variables you can use the helper functions in Environment.hpp
   // to derive the desired environment
   boost::optional<Options> environment;

   // terminate should also terminate all children owned by the process
   // NOTE: currently only supported on posix -- in the posix case this
   // results in a call to ::setpgid(0,0) to create a new process group
   // and the specification of -pid to kill so as to kill the child and
   // all of its subprocesses
   // NOTE: to support the same behavior on Win32 we'll need to use
   // CreateJobObject/CREATE_BREAKAWAY_FROM_JOB to get the same effect
   bool terminateChildren;

#ifndef _WIN32
   // Calls ::setsid after fork for POSIX (no effect on Windows)
   bool detachSession;

   // attach the child process to pseudoterminal pipes
   boost::optional<Pseudoterminal> pseudoterminal;
#endif

#ifdef _WIN32
   // Creates the process with DETACHED_PROCESS on Win32 (no effect on POSIX)
   bool detachProcess;

   // If true, uses ConsoleIO.exe to capture low-level console input and output
   // (that cannot be accessed by redirecting stdin/stdout). This is not
   // recommended unless absolutely necessary as it introduces a lot of
   // complexity.
   //
   // If true, detachProcess and redirectStdErrToStdOut are ignored.
   bool lowLevelConsoleIO;
#endif

   bool redirectStdErrToStdOut;

   // function to run within the child process immediately after the fork
   // NOTE: only supported on posix as there is no fork on Win32
   boost::function<void()> onAfterFork;

   core::FilePath workingDir;
};

// Struct for returning output and exit status from a process
struct ProcessResult
{
   ProcessResult() : exitStatus(-1) {}

   // Standard output from process
   std::string stdOut;

   // Standard error from process
   std::string stdErr;

   // Process exit status. Potential values:
   //   0   - successful execution
   //   1   - application defined failure code (1, 2, 3, etc.)
   //  15   - process killed by terminate()
   //  -1   - unable to determine exit status
   int exitStatus;
};

// Run a program synchronously. Note that if executable is not an absolute
// path then runProgram will duplicate the actions of the shell in searching
// for an executable to run. Some platform specific notes:
//
//  - Posix: The executable path is not executed by /bin/sh, rather it is
//    executed directly by ::execvp. This means that shell metacharacters
//    (e.g. stream redirection, piping, etc.) are not supported in the
//    command string.
//
//  - Win32: The search for the executable path includes auto-appending .exe
//    and .cmd (in that order) for the path search and invoking cmd.exe if
//    the target is a batch (.cmd) file.
//
Error runProgram(const std::string& executable,
                 const std::vector<std::string>& args,
                 const std::string& input,
                 const ProcessOptions& options,
                 ProcessResult* pResult);

// Run a command synchronously. The command will be passed to and executed
// by a command shell (/bin/sh on posix, cmd.exe on windows).
//
Error runCommand(const std::string& command,
                 const ProcessOptions& options,
                 ProcessResult* pResult);

Error runCommand(const std::string& command,
                 const std::string& input,
                 const ProcessOptions& options,
                 ProcessResult* pResult);

////////////////////////////////////////////////////////////////////////////////
//
// ProcessSupervisor -- run child processes asynchronously
//
// Any number of processes can be run by calling runProgram or runCommand and
// their results will be delivered using the provided callbacks. Note that
// the poll() method must be called periodically (e.g. during standard event
// pumping / idle time) in  order to check for output & status of children.
//
// If you want to pair a call to runProgam or runCommand with an object which
// will live for the lifetime of the child process you should create a
// shared_ptr to that object and then bind the applicable members to the
// callback function(s) -- the bind will keep the shared_ptr alive (see the
// implementation of the single-callback version of runProgram for an example)
//
//

// Operations that can be performed from within ProcessCallbacks
class ProcessOperations
{
public:
   virtual ~ProcessOperations() {}

   // Write (synchronously) to standard input
   virtual Error writeToStdin(const std::string& input, bool eof) = 0;

   // Operations which apply to Pseudoterminals (only available
   // if ProcessOptions::pseudoterminal is specified)
   virtual Error ptySetSize(int cols, int rows) = 0;
   virtual Error ptyInterrupt() = 0;

   // Terminate the process (SIGTERM)
   virtual Error terminate() = 0;
};

// Callbacks for reporting various states and streaming output (note that
// all callbacks are optional)
struct ProcessCallbacks
{
   // Called after the process begins running (note: is called during
   // the first call to poll and therefore after runAsync returns). Can
   // be used for writing initial standard input to the child
   boost::function<void(ProcessOperations&)> onStarted;

   // Called periodically (at whatever interval poll is called) during the
   // lifetime of the child process (will not be called until after the
   // first call to onStarted). If it returns false then the child process
   // is terminated.
   boost::function<bool(ProcessOperations&)> onContinue;

   // Streaming callback for standard output
   boost::function<void(ProcessOperations&, const std::string&)> onStdout;

   // Streaming callback for standard error
   boost::function<void(ProcessOperations&, const std::string&)> onStderr;

   boost::function<void(ProcessOperations&, const std::vector<char>&)>
                                                  onConsoleOutputSnapshot;

   // Called if an IO error occurs while reading from standard streams. The
   // default behavior if no callback is specified is to log and then terminate
   // the child (which will result in onExit being called w/ exitStatus == 15)
   boost::function<void(ProcessOperations&,const Error&)> onError;

   // Called after the process has exited. Passes exitStatus (see ProcessResult
   // comment above for potential values)
   boost::function<void(int)> onExit;
};

// Process supervisor
class ProcessSupervisor : boost::noncopyable
{
public:
   ProcessSupervisor();
   virtual ~ProcessSupervisor();

   // Run a child asynchronously, invoking callbacks as the process starts,
   // produces output, and exits. Output callbacks are streamed/interleaved,
   // but note that output is collected at a polling interval so it is
   // possible that e.g. two writes to standard output which had an
   // intervening write to standard input might still be concatenated. See
   // comment on runProgram above for the semantics of the "executable"
   // argument.
   Error runProgram(const std::string& executable,
                    const std::vector<std::string>& args,
                    const ProcessOptions& options,
                    const ProcessCallbacks& callbacks);

   // Run a command asynchronously (same as above but uses a command shell
   // rather than running the executable directly)
   Error runCommand(const std::string& command,
                    const ProcessOptions& options,
                    const ProcessCallbacks& callbacks);

   // Run a child asynchronously, invoking the completed callback when the
   // process exits. Note that if input is provided then then the standard
   // input stream is closed (so EOF is sent) after the input is written.
   // Note also that the standard error handler (log and terminate) is also
   // used. If you want more customized behavior then you can use the more
   // granular runProgram call above. See comment on runProgram above for the
   // semantics of the "command" argument.
   Error runProgram(
            const std::string& executable,
            const std::vector<std::string>& args,
            const std::string& input,
            const ProcessOptions& options,
            const boost::function<void(const ProcessResult&)>& onCompleted);

   // Run a command asynchronously (same as above but uses a command shell
   // rather than running the executable directly)
   Error runCommand(
            const std::string& command,
            const ProcessOptions& options,
            const boost::function<void(const ProcessResult&)>& onCompleted);

   Error runCommand(
            const std::string& command,
            const std::string& input,
            const ProcessOptions& options,
            const boost::function<void(const ProcessResult&)>& onCompleted);

   // Check whether any children are currently active
   bool hasRunningChildren();

   // Poll for child (output and exit) events. returns true if there
   // are still children being supervised after the poll
   bool poll();

   // Terminate all running children
   void terminateAll();

   // Wait for all children to exit. Returns false if the operaiton timed out
   bool wait(
      const boost::posix_time::time_duration& pollingInterval =
         boost::posix_time::milliseconds(100),
      const boost::posix_time::time_duration& maxWait =
         boost::posix_time::time_duration(boost::posix_time::not_a_date_time));

private:
   struct Impl;
   boost::scoped_ptr<Impl> pImpl_;
};

} // namespace system
} // namespace core

#endif // CORE_SYSTEM_PROCESS_HPP
<commit_msg>initialize lowLevelConsoleIO member of ProcessOptions during construction<commit_after>/*
 * Process.hpp
 *
 * Copyright (C) 2009-11 by RStudio, Inc.
 *
 * This program is licensed to you under the terms of version 3 of the
 * GNU Affero General Public License. This program is distributed WITHOUT
 * ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING THOSE OF NON-INFRINGEMENT,
 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Please refer to the
 * AGPL (http://www.gnu.org/licenses/agpl-3.0.txt) for more details.
 *
 */

#ifndef CORE_SYSTEM_PROCESS_HPP
#define CORE_SYSTEM_PROCESS_HPP

#include <vector>

#include <boost/optional.hpp>
#include <boost/utility.hpp>
#include <boost/function.hpp>
#include <boost/scoped_ptr.hpp>
#include <boost/date_time/posix_time/posix_time_types.hpp>

#include <core/system/Types.hpp>
#include <core/FilePath.hpp>

namespace core {

class Error;

namespace system {

////////////////////////////////////////////////////////////////////////////////
//
// Run child process synchronously
//
//

// Struct for speicfying pseudoterminal options
struct Pseudoterminal
{
   Pseudoterminal(int cols, int rows)
      : cols(cols), rows(rows)
   {
   }

   int cols;
   int rows;
};

// Struct for specifying process options
struct ProcessOptions
{
   ProcessOptions()
#ifdef _WIN32
      : terminateChildren(false),
        detachProcess(false),
        lowLevelConsoleIO(false),
        redirectStdErrToStdOut(false)
#else
      : terminateChildren(false),
        detachSession(false),
        redirectStdErrToStdOut(false)
#endif
   {
   }

   // environment variables to set for the child process
   // if you want to simply merge in some additional environment
   // variables you can use the helper functions in Environment.hpp
   // to derive the desired environment
   boost::optional<Options> environment;

   // terminate should also terminate all children owned by the process
   // NOTE: currently only supported on posix -- in the posix case this
   // results in a call to ::setpgid(0,0) to create a new process group
   // and the specification of -pid to kill so as to kill the child and
   // all of its subprocesses
   // NOTE: to support the same behavior on Win32 we'll need to use
   // CreateJobObject/CREATE_BREAKAWAY_FROM_JOB to get the same effect
   bool terminateChildren;

#ifndef _WIN32
   // Calls ::setsid after fork for POSIX (no effect on Windows)
   bool detachSession;

   // attach the child process to pseudoterminal pipes
   boost::optional<Pseudoterminal> pseudoterminal;
#endif

#ifdef _WIN32
   // Creates the process with DETACHED_PROCESS on Win32 (no effect on POSIX)
   bool detachProcess;

   // If true, uses ConsoleIO.exe to capture low-level console input and output
   // (that cannot be accessed by redirecting stdin/stdout). This is not
   // recommended unless absolutely necessary as it introduces a lot of
   // complexity.
   //
   // If true, detachProcess and redirectStdErrToStdOut are ignored.
   bool lowLevelConsoleIO;
#endif

   bool redirectStdErrToStdOut;

   // function to run within the child process immediately after the fork
   // NOTE: only supported on posix as there is no fork on Win32
   boost::function<void()> onAfterFork;

   core::FilePath workingDir;
};

// Struct for returning output and exit status from a process
struct ProcessResult
{
   ProcessResult() : exitStatus(-1) {}

   // Standard output from process
   std::string stdOut;

   // Standard error from process
   std::string stdErr;

   // Process exit status. Potential values:
   //   0   - successful execution
   //   1   - application defined failure code (1, 2, 3, etc.)
   //  15   - process killed by terminate()
   //  -1   - unable to determine exit status
   int exitStatus;
};

// Run a program synchronously. Note that if executable is not an absolute
// path then runProgram will duplicate the actions of the shell in searching
// for an executable to run. Some platform specific notes:
//
//  - Posix: The executable path is not executed by /bin/sh, rather it is
//    executed directly by ::execvp. This means that shell metacharacters
//    (e.g. stream redirection, piping, etc.) are not supported in the
//    command string.
//
//  - Win32: The search for the executable path includes auto-appending .exe
//    and .cmd (in that order) for the path search and invoking cmd.exe if
//    the target is a batch (.cmd) file.
//
Error runProgram(const std::string& executable,
                 const std::vector<std::string>& args,
                 const std::string& input,
                 const ProcessOptions& options,
                 ProcessResult* pResult);

// Run a command synchronously. The command will be passed to and executed
// by a command shell (/bin/sh on posix, cmd.exe on windows).
//
Error runCommand(const std::string& command,
                 const ProcessOptions& options,
                 ProcessResult* pResult);

Error runCommand(const std::string& command,
                 const std::string& input,
                 const ProcessOptions& options,
                 ProcessResult* pResult);

////////////////////////////////////////////////////////////////////////////////
//
// ProcessSupervisor -- run child processes asynchronously
//
// Any number of processes can be run by calling runProgram or runCommand and
// their results will be delivered using the provided callbacks. Note that
// the poll() method must be called periodically (e.g. during standard event
// pumping / idle time) in  order to check for output & status of children.
//
// If you want to pair a call to runProgam or runCommand with an object which
// will live for the lifetime of the child process you should create a
// shared_ptr to that object and then bind the applicable members to the
// callback function(s) -- the bind will keep the shared_ptr alive (see the
// implementation of the single-callback version of runProgram for an example)
//
//

// Operations that can be performed from within ProcessCallbacks
class ProcessOperations
{
public:
   virtual ~ProcessOperations() {}

   // Write (synchronously) to standard input
   virtual Error writeToStdin(const std::string& input, bool eof) = 0;

   // Operations which apply to Pseudoterminals (only available
   // if ProcessOptions::pseudoterminal is specified)
   virtual Error ptySetSize(int cols, int rows) = 0;
   virtual Error ptyInterrupt() = 0;

   // Terminate the process (SIGTERM)
   virtual Error terminate() = 0;
};

// Callbacks for reporting various states and streaming output (note that
// all callbacks are optional)
struct ProcessCallbacks
{
   // Called after the process begins running (note: is called during
   // the first call to poll and therefore after runAsync returns). Can
   // be used for writing initial standard input to the child
   boost::function<void(ProcessOperations&)> onStarted;

   // Called periodically (at whatever interval poll is called) during the
   // lifetime of the child process (will not be called until after the
   // first call to onStarted). If it returns false then the child process
   // is terminated.
   boost::function<bool(ProcessOperations&)> onContinue;

   // Streaming callback for standard output
   boost::function<void(ProcessOperations&, const std::string&)> onStdout;

   // Streaming callback for standard error
   boost::function<void(ProcessOperations&, const std::string&)> onStderr;

   boost::function<void(ProcessOperations&, const std::vector<char>&)>
                                                  onConsoleOutputSnapshot;

   // Called if an IO error occurs while reading from standard streams. The
   // default behavior if no callback is specified is to log and then terminate
   // the child (which will result in onExit being called w/ exitStatus == 15)
   boost::function<void(ProcessOperations&,const Error&)> onError;

   // Called after the process has exited. Passes exitStatus (see ProcessResult
   // comment above for potential values)
   boost::function<void(int)> onExit;
};

// Process supervisor
class ProcessSupervisor : boost::noncopyable
{
public:
   ProcessSupervisor();
   virtual ~ProcessSupervisor();

   // Run a child asynchronously, invoking callbacks as the process starts,
   // produces output, and exits. Output callbacks are streamed/interleaved,
   // but note that output is collected at a polling interval so it is
   // possible that e.g. two writes to standard output which had an
   // intervening write to standard input might still be concatenated. See
   // comment on runProgram above for the semantics of the "executable"
   // argument.
   Error runProgram(const std::string& executable,
                    const std::vector<std::string>& args,
                    const ProcessOptions& options,
                    const ProcessCallbacks& callbacks);

   // Run a command asynchronously (same as above but uses a command shell
   // rather than running the executable directly)
   Error runCommand(const std::string& command,
                    const ProcessOptions& options,
                    const ProcessCallbacks& callbacks);

   // Run a child asynchronously, invoking the completed callback when the
   // process exits. Note that if input is provided then then the standard
   // input stream is closed (so EOF is sent) after the input is written.
   // Note also that the standard error handler (log and terminate) is also
   // used. If you want more customized behavior then you can use the more
   // granular runProgram call above. See comment on runProgram above for the
   // semantics of the "command" argument.
   Error runProgram(
            const std::string& executable,
            const std::vector<std::string>& args,
            const std::string& input,
            const ProcessOptions& options,
            const boost::function<void(const ProcessResult&)>& onCompleted);

   // Run a command asynchronously (same as above but uses a command shell
   // rather than running the executable directly)
   Error runCommand(
            const std::string& command,
            const ProcessOptions& options,
            const boost::function<void(const ProcessResult&)>& onCompleted);

   Error runCommand(
            const std::string& command,
            const std::string& input,
            const ProcessOptions& options,
            const boost::function<void(const ProcessResult&)>& onCompleted);

   // Check whether any children are currently active
   bool hasRunningChildren();

   // Poll for child (output and exit) events. returns true if there
   // are still children being supervised after the poll
   bool poll();

   // Terminate all running children
   void terminateAll();

   // Wait for all children to exit. Returns false if the operaiton timed out
   bool wait(
      const boost::posix_time::time_duration& pollingInterval =
         boost::posix_time::milliseconds(100),
      const boost::posix_time::time_duration& maxWait =
         boost::posix_time::time_duration(boost::posix_time::not_a_date_time));

private:
   struct Impl;
   boost::scoped_ptr<Impl> pImpl_;
};

} // namespace system
} // namespace core

#endif // CORE_SYSTEM_PROCESS_HPP
<|endoftext|>


<commit_before>// trance typeinfo.hpp - Type identification Library
//
// Copyright (c) 2011 - 2011 Kohei Takahashi (Flast)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

#ifndef IG_TRANCE_TYPEINFO_HPP_ONCE_
#define IG_TRANCE_TYPEINFO_HPP_ONCE_

#include <trance/config.hpp>

#include <cstddef>
#include <string>
#include <typeinfo>

#if defined( BOOST_GNU_STDLIB ) && BOOST_GNU_STDLIB
#   include <cstdlib>
#   include <new>
#   include <stdexcept>
#   include <cxxabi.h>

// Boost 1.46.1's scoped_ptr.hpp missing detail/utilities.hpp for detail::do_swap.
#   include <boost/interprocess/detail/utilities.hpp>
#   include <boost/interprocess/smart_ptr/scoped_ptr.hpp>
#endif // BOOST_GNU_STDLIB

#include <trance/detail/typeof.hpp>

namespace trance
{

namespace typeinfo_detail
{

class _type_info_base
{
    type_info_base( const _type_info_base & ) TRANCE_DELETED_FUNCTION;

    _type_info_base &
    operator=( const _type_info_base & ) TRANCE_DELETED_FUNCTION;

protected:
    const ::std::type_info &_M_internal;

    explicit
    _type_info_base( const ::std::type_info &_ti )
      : _M_internal( _ti ) {}

public:
    const char *
    name( void ) const
    { return _M_internal.name(); }

    bool
    before( const ::std::type_info &_other ) const TRANCE_NOEXCEPT
    { return _M_internal.before( _other ); }

    bool
    operator==( const ::std::type_info &_other ) const TRANCE_NOEXCEPT
    { return _M_internal.operator==( _other ); }

    bool
    operator!=( const ::std::type_info &_other ) const TRANCE_NOEXCEPT
    { return _M_internal.operator!=( _other ); }

    operator const ::std::type_info &( void ) const TRANCE_NOEXCEPT
    { return _M_internal; }
};

#if defined( __GNUC__ ) && defined( __GNUC_MINOR__ )
#   if __GNUC__ >= 4 \
    && __GNUC_MINOR__ >= 6 \
    && defined( __GXX_EXPERIMENTAL_CXX0X__ )
#       define TRANCE_HAS_TYPEINFO_HASH_CODE true
#       define TRANCE_USE_TYPEINFO_PARTIAL_SPEC
#   else
#       define TRANCE_HAS_TYPEINFO_HASH_CODE false
#   endif // GCC >= 4.6 && -std=c++0x
#else // __GNUC__ && __GNUC_MINOR__
#   define TRANCE_HAS_TYPEINFO_HASH_CODE \
  ::trance::typeinfo_detail::_has_hash_code< ::std::type_info >::value
#   define TRANCE_USE_TYPEINFO_PARTIAL_SPEC

template < typename T >
struct _has_hash_code
{
    typedef char                         no_type;
    typedef struct { char _dummy[ 8 ]; } yes_type;

    template < typename >
    static no_type
    check( ... );

    template < typename U >
    static yes_type
    check( U *, ::std::size_t ( U::* )( void ) const = &T::hash_code );

    BOOST_STATIC_CONSTEXPR bool value =
      sizeof( check< T >( 0 ) ) == sizeof( yes_type );
};
#endif

template < bool >
class _type_info
  : public _type_info_base
{
    typedef _type_info_base _base_t;

protected:
    _type_info( const ::std::type_info &_ti )
      : _base_t( _ti ) {}
};

#if defined( TRANCE_USE_TYPEINFO_PARTIAL_SPEC )
#undef TRANCE_USE_TYPEINFO_PARTIAL_SPEC
template <>
class _type_info< true >
  : public _type_info_base
{
    typedef _type_info_base _base_t;

protected:
    _type_info( const ::std::type_info &_ti )
      : _base_t( _ti ) {}

public:
    ::std::size_t
    hash_code( void ) const TRANCE_NOEXCEPT
    { return _base_t::_M_internal.hash_code(); }
};
#endif // TRANCE_USE_TYPEINFO_PARTIAL_SPEC

} // namespace typeinfo_detail

class type_info
  : public typeinfo_detail::_type_info< TRANCE_HAS_TYPEINFO_HASH_CODE >
{
    typedef typeinfo_detail::_type_info< TRANCE_HAS_TYPEINFO_HASH_CODE > _base_t;

protected:
    explicit
    type_info( const ::std::type_info &_ti )
      : _base_t( _ti ) {}

public:
    virtual const char *
    demangled_name( void ) const TRANCE_NOEXCEPT = 0;
};

class bad_typeid
{
    const char * const _M_what_message;

protected:
    TRANCE_CONSTEXPR explicit
    bad_typeid( const char *_mes ) TRANCE_NOEXCEPT
      : _M_what_message( _mes ) {}

public:
    TRANCE_CONSTEXPR const char *
    what( void ) const TRANCE_NOEXCEPT
    { return _M_what_message; }

    /*[[noreturn]]*/ virtual void
    rethrow_composite_error( void ) const = 0;
};

namespace typeinfo_detail
{

template < typename _Exception >
/*[[noreturn]]*/ inline void
_throw_bad_typeid_with( const char *_mes )
{
    struct _internal_composite_error
      : public bad_typeid, public _Exception
    {
        TRANCE_CONSTEXPR explicit
        _internal_composite_error( const char *_mes ) TRANCE_NOEXCEPT
          : bad_typeid( _mes ),
            _Exception(
              "Trance.Typeid: "
              "To process exception correctly, "
              "catch trance::bad_typeid."
            ) {}

        /*[[noreturn]]*/ void
        rethrow_composite_error( void ) const
        { throw _Exception( bad_typeid::what() ); }
    };

    throw _internal_composite_error( _mes );
}

struct _deleter_with_free
{
    inline void
    operator()( void *ptr )
    { ::std::free( ptr ); }
};

struct _messaged_bad_alloc
  : public ::std::bad_alloc
{
    const char *_M_what_message;

    explicit
    _messaged_bad_alloc( const char *_mes ) TRANCE_NOEXCEPT
      : _M_what_message( _mes ) {}

    const char *
    what( void ) const TRANCE_EMPTY_THROW_SPEC_OR_NOEXCEPT
    { return _M_what_message; }
};

inline ::std::string
_demangle( const ::std::type_info &_ti )
{
    const char * const mangled_name = _ti.name();
#if defined( BOOST_GNU_STDLIB ) && BOOST_GNU_STDLIB
    using namespace ::std;
    using ::abi::__cxa_demangle;
    using ::boost::interprocess::scoped_ptr;

    typedef scoped_ptr< char, _deleter_with_free > demangled_ptr;

    int status;
    demangled_ptr demangled( __cxa_demangle( mangled_name, 0, 0, &status ) );
    const string demangled_name( demangled.get() ? demangled.get() : "" );

    switch ( status )
    {
      case 0: break; // no error
      case -1: // memory allocation faild.
        _throw_bad_typeid_with< _messaged_bad_alloc >(
          "Trance.Typeid: abi::__cxa_demangle memory allocation faild."
        );
      case -2: // mangled name is not valid name.
        _throw_bad_typeid_with< invalid_argument >(
          "Trance.Typeid: Mangled name is not valid name. "
          "The ABI version is same and correct?"
        );
      case -3: // one of the arguments is invalid.
        _throw_bad_typeid_with< invalid_argument >(
          "Trance.Typeid: One of the arguments is invalid. "
          "Please submit a full bug report."
        );
      default: // unknown.
        _throw_bad_typeid_with< logic_error >(
          "Trance.Typeid: Unknown error occurred. "
          "Please submit a full bug report."
        );
    }
    return demangled_name;
#else
    return mangled_name;
#endif // BOOST_GNU_STDLIB
}

class _type_info_impl
  : public type_info
{
    template < typename >
    friend const type_info &
    _typeid_by_type( void );

    typedef ::std::string _demangled_name_type;

    _demangled_name_type _M_demangled_name;

    explicit
    _type_info_impl( const ::std::type_info &_ti )
      : type_info( _ti ),
        _M_demangled_name( _demangle( _ti ) ) {}

    struct _generics_typeid_invoke_tag {};

public:
    BOOST_STATIC_CONSTEXPR _generics_typeid_invoke_tag _generics_typeid_invoke
#if !defined( BOOST_NO_CONSTEXPR )
      = _generics_typeid_invoke_tag{}
#endif // BOOST_NO_CONSTEXPR
      ;

    _type_info_impl( _generics_typeid_invoke_tag, const ::std::type_info &_ti )
      : type_info( _ti ),
        _M_demangled_name( _demangle( _ti ) ) {}

    const char *
    demangled_name( void ) const TRANCE_NOEXCEPT
    { return _M_demangled_name.c_str(); }
};

#define TRANCE_TYPEID( _typeid_or_expr )                                   \
  static_cast< const ::trance::type_info & >(                              \
    ::trance::typeinfo_detail::_type_info_impl(                            \
      ::trance::typeinfo_detail::_type_info_impl::_generics_typeid_invoke, \
      typeid( _typeid_or_expr )                                            \
    )                                                                      \
  )                                                                        \

#define TRANCE_TYPEID_BY_TYPE( _typeid )                    \
  static_cast< const ::trance::type_info & >(               \
    ::trance::typeinfo_detail::_typeid_by_type< _typeid >() \
  )                                                         \

#define TRANCE_TYPEID_BY_EXPR( _Expr )          \
  static_cast< const ::trance::type_info & >(   \
    ::trance::typeinfo_detail::_typeid_by_expr( \
      TRANCE_DETAIL_TYPEOF( _Expr )             \
    )                                           \
  )                                             \

template < typename T >
inline const type_info &
_typeid_by_type( void )
{
    static _type_info_impl _impl_instance( typeid( T ) );
    return _impl_instance;
}

template < typename T >
inline const type_info &
_typeid_by_expr( T * )
{ return TRANCE_TYPEID_BY_TYPE( T ); }

} // namespace typeinfo_detail

} // namespace trance

#endif // IG_TRANCE_TYPEINFO_HPP_ONCE_

<commit_msg>TRANCE_TYPEID returns const prvalue<commit_after>// trance typeinfo.hpp - Type identification Library
//
// Copyright (c) 2011 - 2011 Kohei Takahashi (Flast)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

#ifndef IG_TRANCE_TYPEINFO_HPP_ONCE_
#define IG_TRANCE_TYPEINFO_HPP_ONCE_

#include <trance/config.hpp>

#include <cstddef>
#include <string>
#include <typeinfo>

#if defined( BOOST_GNU_STDLIB ) && BOOST_GNU_STDLIB
#   include <cstdlib>
#   include <new>
#   include <stdexcept>
#   include <cxxabi.h>

// Boost 1.46.1's scoped_ptr.hpp missing detail/utilities.hpp for detail::do_swap.
#   include <boost/interprocess/detail/utilities.hpp>
#   include <boost/interprocess/smart_ptr/scoped_ptr.hpp>
#endif // BOOST_GNU_STDLIB

#include <trance/detail/typeof.hpp>

namespace trance
{

namespace typeinfo_detail
{

class _type_info_base
{
    type_info_base( const _type_info_base & ) TRANCE_DELETED_FUNCTION;

    _type_info_base &
    operator=( const _type_info_base & ) TRANCE_DELETED_FUNCTION;

protected:
    const ::std::type_info &_M_internal;

    explicit
    _type_info_base( const ::std::type_info &_ti )
      : _M_internal( _ti ) {}

public:
    const char *
    name( void ) const
    { return _M_internal.name(); }

    bool
    before( const ::std::type_info &_other ) const TRANCE_NOEXCEPT
    { return _M_internal.before( _other ); }

    bool
    operator==( const ::std::type_info &_other ) const TRANCE_NOEXCEPT
    { return _M_internal.operator==( _other ); }

    bool
    operator!=( const ::std::type_info &_other ) const TRANCE_NOEXCEPT
    { return _M_internal.operator!=( _other ); }

    operator const ::std::type_info &( void ) const TRANCE_NOEXCEPT
    { return _M_internal; }
};

#if defined( __GNUC__ ) && defined( __GNUC_MINOR__ )
#   if __GNUC__ >= 4 \
    && __GNUC_MINOR__ >= 6 \
    && defined( __GXX_EXPERIMENTAL_CXX0X__ )
#       define TRANCE_HAS_TYPEINFO_HASH_CODE true
#       define TRANCE_USE_TYPEINFO_PARTIAL_SPEC
#   else
#       define TRANCE_HAS_TYPEINFO_HASH_CODE false
#   endif // GCC >= 4.6 && -std=c++0x
#else // __GNUC__ && __GNUC_MINOR__
#   define TRANCE_HAS_TYPEINFO_HASH_CODE \
  ::trance::typeinfo_detail::_has_hash_code< ::std::type_info >::value
#   define TRANCE_USE_TYPEINFO_PARTIAL_SPEC

template < typename T >
struct _has_hash_code
{
    typedef char                         no_type;
    typedef struct { char _dummy[ 8 ]; } yes_type;

    template < typename >
    static no_type
    check( ... );

    template < typename U >
    static yes_type
    check( U *, ::std::size_t ( U::* )( void ) const = &T::hash_code );

    BOOST_STATIC_CONSTEXPR bool value =
      sizeof( check< T >( 0 ) ) == sizeof( yes_type );
};
#endif

template < bool >
class _type_info
  : public _type_info_base
{
    typedef _type_info_base _base_t;

protected:
    _type_info( const ::std::type_info &_ti )
      : _base_t( _ti ) {}
};

#if defined( TRANCE_USE_TYPEINFO_PARTIAL_SPEC )
#undef TRANCE_USE_TYPEINFO_PARTIAL_SPEC
template <>
class _type_info< true >
  : public _type_info_base
{
    typedef _type_info_base _base_t;

protected:
    _type_info( const ::std::type_info &_ti )
      : _base_t( _ti ) {}

public:
    ::std::size_t
    hash_code( void ) const TRANCE_NOEXCEPT
    { return _base_t::_M_internal.hash_code(); }
};
#endif // TRANCE_USE_TYPEINFO_PARTIAL_SPEC

} // namespace typeinfo_detail

class type_info
  : public typeinfo_detail::_type_info< TRANCE_HAS_TYPEINFO_HASH_CODE >
{
    typedef typeinfo_detail::_type_info< TRANCE_HAS_TYPEINFO_HASH_CODE > _base_t;

protected:
    explicit
    type_info( const ::std::type_info &_ti )
      : _base_t( _ti ) {}

public:
    virtual const char *
    demangled_name( void ) const TRANCE_NOEXCEPT = 0;
};

class bad_typeid
{
    const char * const _M_what_message;

protected:
    TRANCE_CONSTEXPR explicit
    bad_typeid( const char *_mes ) TRANCE_NOEXCEPT
      : _M_what_message( _mes ) {}

public:
    TRANCE_CONSTEXPR const char *
    what( void ) const TRANCE_NOEXCEPT
    { return _M_what_message; }

    /*[[noreturn]]*/ virtual void
    rethrow_composite_error( void ) const = 0;
};

namespace typeinfo_detail
{

#if defined( BOOST_GNU_STDLIB ) && BOOST_GNU_STDLIB
template < typename _Exception >
/*[[noreturn]]*/ inline void
_throw_bad_typeid_with( const char *_mes )
{
    struct _internal_composite_error
      : public bad_typeid, public _Exception
    {
        TRANCE_CONSTEXPR explicit
        _internal_composite_error( const char *_mes ) TRANCE_NOEXCEPT
          : bad_typeid( _mes ),
            _Exception(
              "Trance.Typeid: "
              "To process exception correctly, "
              "catch trance::bad_typeid."
            ) {}

        /*[[noreturn]]*/ void
        rethrow_composite_error( void ) const
        { throw _Exception( bad_typeid::what() ); }
    };

    throw _internal_composite_error( _mes );
}

struct _deleter_with_free
{
    inline void
    operator()( void *ptr )
    { ::std::free( ptr ); }
};

struct _messaged_bad_alloc
  : public ::std::bad_alloc
{
    const char *_M_what_message;

    explicit
    _messaged_bad_alloc( const char *_mes ) TRANCE_NOEXCEPT
      : _M_what_message( _mes ) {}

    const char *
    what( void ) const TRANCE_EMPTY_THROW_SPEC_OR_NOEXCEPT
    { return _M_what_message; }
};
#endif

inline ::std::string
_demangle( const ::std::type_info &_ti )
{
    const char * const mangled_name = _ti.name();
#if defined( BOOST_GNU_STDLIB ) && BOOST_GNU_STDLIB
    using namespace ::std;
    using ::abi::__cxa_demangle;
    using ::boost::interprocess::scoped_ptr;

    typedef scoped_ptr< char, _deleter_with_free > demangled_ptr;

    int status;
    demangled_ptr demangled( __cxa_demangle( mangled_name, 0, 0, &status ) );
    const string demangled_name( demangled.get() ? demangled.get() : "" );

    switch ( status )
    {
      case 0: break; // no error
      case -1: // memory allocation faild.
        _throw_bad_typeid_with< _messaged_bad_alloc >(
          "Trance.Typeid: abi::__cxa_demangle memory allocation faild."
        );
      case -2: // mangled name is not valid name.
        _throw_bad_typeid_with< invalid_argument >(
          "Trance.Typeid: Mangled name is not valid name. "
          "The ABI version is same and correct?"
        );
      case -3: // one of the arguments is invalid.
        _throw_bad_typeid_with< invalid_argument >(
          "Trance.Typeid: One of the arguments is invalid. "
          "Please submit a full bug report."
        );
      default: // unknown.
        _throw_bad_typeid_with< logic_error >(
          "Trance.Typeid: Unknown error occurred. "
          "Please submit a full bug report."
        );
    }
    return demangled_name;
#else
    return mangled_name;
#endif // BOOST_GNU_STDLIB
}

class _type_info_impl
  : public type_info
{
    template < typename >
    friend const type_info &
    _typeid_by_type( void );

    typedef ::std::string _demangled_name_type;

    _demangled_name_type _M_demangled_name;

    explicit
    _type_info_impl( const ::std::type_info &_ti )
      : type_info( _ti ),
        _M_demangled_name( _demangle( _ti ) ) {}

    _type_info_impl( const _type_info_impl &_impl )
      : type_info( _impl._M_internal ),
        _M_demangled_name( _impl._M_demangled_name ) {}

    struct _generics_typeid_invoke_tag {};

public:
    BOOST_STATIC_CONSTEXPR _generics_typeid_invoke_tag _generics_typeid_invoke
#if !defined( BOOST_NO_CONSTEXPR )
      = _generics_typeid_invoke_tag{}
#endif // BOOST_NO_CONSTEXPR
      ;

    _type_info_impl( _generics_typeid_invoke_tag, const ::std::type_info &_ti )
      : type_info( _ti ),
        _M_demangled_name( _demangle( _ti ) ) {}

    const char *
    demangled_name( void ) const TRANCE_NOEXCEPT
    { return _M_demangled_name.c_str(); }

    const _type_info_impl
    _internal_use_only_do_clone( void ) const
    { return *this; }
};

#define TRANCE_TYPEID( _typeid_or_expr )                                   \
  static_cast< const ::trance::typeinfo_detail::_type_info_impl & >(       \
    ::trance::typeinfo_detail::_type_info_impl(                            \
      ::trance::typeinfo_detail::_type_info_impl::_generics_typeid_invoke, \
      typeid( _typeid_or_expr )                                            \
    )                                                                      \
  )._internal_use_only_do_clone()                                          \

#define TRANCE_TYPEID_BY_TYPE( _typeid )                    \
  static_cast< const ::trance::type_info & >(               \
    ::trance::typeinfo_detail::_typeid_by_type< _typeid >() \
  )                                                         \

#define TRANCE_TYPEID_BY_EXPR( _Expr )          \
  static_cast< const ::trance::type_info & >(   \
    ::trance::typeinfo_detail::_typeid_by_expr( \
      TRANCE_DETAIL_TYPEOF( _Expr )             \
    )                                           \
  )                                             \

template < typename T >
inline const type_info &
_typeid_by_type( void )
{
    static _type_info_impl _impl_instance( typeid( T ) );
    return _impl_instance;
}

template < typename T >
inline const type_info &
_typeid_by_expr( T * )
{ return TRANCE_TYPEID_BY_TYPE( T ); }

} // namespace typeinfo_detail

} // namespace trance

#endif // IG_TRANCE_TYPEINFO_HPP_ONCE_

<|endoftext|>


<commit_before>// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "ui/app_list/views/search_result_tile_item_view.h"

#include "ui/app_list/app_list_view_delegate.h"
#include "ui/app_list/search_result.h"
#include "ui/app_list/views/search_result_container_view.h"
#include "ui/views/controls/menu/menu_runner.h"

namespace app_list {

SearchResultTileItemView::SearchResultTileItemView(
    SearchResultContainerView* result_container,
    AppListViewDelegate* view_delegate)
    : result_container_(result_container),
      item_(nullptr),
      view_delegate_(view_delegate) {
  // When |item_| is null, the tile is invisible. Calling SetSearchResult with a
  // non-null item makes the tile visible.
  SetVisible(false);

  set_context_menu_controller(this);
}

SearchResultTileItemView::~SearchResultTileItemView() {
  if (item_)
    item_->RemoveObserver(this);
}

void SearchResultTileItemView::SetSearchResult(SearchResult* item) {
  // Handle the case where this may be called from a nested run loop while its
  // context menu is showing. This cancels the menu (it's for the old item).
  context_menu_runner_.reset();

  SetVisible(item != NULL);

  SearchResult* old_item = item_;
  if (old_item)
    old_item->RemoveObserver(this);

  item_ = item;

  if (!item)
    return;

  item_->AddObserver(this);

  SetTitle(item_->title());

  // Only refresh the icon if it's different from the old one. This prevents
  // flickering.
  if (old_item == NULL ||
      !item->icon().BackedBySameObjectAs(old_item->icon())) {
    OnIconChanged();
  }
}

void SearchResultTileItemView::ButtonPressed(views::Button* sender,
                                             const ui::Event& event) {
  view_delegate_->OpenSearchResult(item_, false, event.flags());
}

bool SearchResultTileItemView::OnKeyPressed(const ui::KeyEvent& event) {
  if (event.key_code() == ui::VKEY_RETURN) {
    view_delegate_->OpenSearchResult(item_, false, event.flags());
    return true;
  }

  return false;
}

void SearchResultTileItemView::OnIconChanged() {
  SetIcon(item_->icon());
}

void SearchResultTileItemView::OnResultDestroying() {
  if (item_)
    item_->RemoveObserver(this);
  item_ = NULL;
}

void SearchResultTileItemView::ShowContextMenuForView(
    views::View* source,
    const gfx::Point& point,
    ui::MenuSourceType source_type) {
  // |item_| could be null when result list is changing.
  if (!item_)
    return;

  ui::MenuModel* menu_model = item_->GetContextMenuModel();
  if (!menu_model)
    return;

  if (!selected())
    result_container_->ClearSelectedIndex();

  context_menu_runner_.reset(
      new views::MenuRunner(menu_model, views::MenuRunner::HAS_MNEMONICS));
  // If RunMenuAt() fails, return immediately. This is future-proofing for
  // adding code after this call.
  if (context_menu_runner_->RunMenuAt(
          GetWidget(), nullptr, gfx::Rect(point, gfx::Size()),
          views::MENU_ANCHOR_TOPLEFT,
          source_type) == views::MenuRunner::MENU_DELETED)
    return;
}

}  // namespace app_list
<commit_msg>Fix use after free in SearchResultTileItemView<commit_after>// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "ui/app_list/views/search_result_tile_item_view.h"

#include "ui/app_list/app_list_view_delegate.h"
#include "ui/app_list/search_result.h"
#include "ui/app_list/views/search_result_container_view.h"
#include "ui/views/controls/menu/menu_runner.h"

namespace app_list {

SearchResultTileItemView::SearchResultTileItemView(
    SearchResultContainerView* result_container,
    AppListViewDelegate* view_delegate)
    : result_container_(result_container),
      item_(nullptr),
      view_delegate_(view_delegate) {
  // When |item_| is null, the tile is invisible. Calling SetSearchResult with a
  // non-null item makes the tile visible.
  SetVisible(false);

  set_context_menu_controller(this);
}

SearchResultTileItemView::~SearchResultTileItemView() {
  if (item_)
    item_->RemoveObserver(this);
}

void SearchResultTileItemView::SetSearchResult(SearchResult* item) {
  // Handle the case where this may be called from a nested run loop while its
  // context menu is showing. This cancels the menu (it's for the old item).
  context_menu_runner_.reset();

  SetVisible(item != NULL);

  SearchResult* old_item = item_;
  if (old_item)
    old_item->RemoveObserver(this);

  item_ = item;

  if (!item)
    return;

  item_->AddObserver(this);

  SetTitle(item_->title());

  // Only refresh the icon if it's different from the old one. This prevents
  // flickering.
  if (old_item == NULL ||
      !item->icon().BackedBySameObjectAs(old_item->icon())) {
    OnIconChanged();
  }
}

void SearchResultTileItemView::ButtonPressed(views::Button* sender,
                                             const ui::Event& event) {
  view_delegate_->OpenSearchResult(item_, false, event.flags());
}

bool SearchResultTileItemView::OnKeyPressed(const ui::KeyEvent& event) {
  if (event.key_code() == ui::VKEY_RETURN) {
    view_delegate_->OpenSearchResult(item_, false, event.flags());
    return true;
  }

  return false;
}

void SearchResultTileItemView::OnIconChanged() {
  SetIcon(item_->icon());
}

void SearchResultTileItemView::OnResultDestroying() {
  // The menu comes from |item_|. If we're showing a menu we need to cancel it.
  context_menu_runner_.reset();

  if (item_)
    item_->RemoveObserver(this);
  item_ = NULL;
}

void SearchResultTileItemView::ShowContextMenuForView(
    views::View* source,
    const gfx::Point& point,
    ui::MenuSourceType source_type) {
  // |item_| could be null when result list is changing.
  if (!item_)
    return;

  ui::MenuModel* menu_model = item_->GetContextMenuModel();
  if (!menu_model)
    return;

  if (!selected())
    result_container_->ClearSelectedIndex();

  context_menu_runner_.reset(
      new views::MenuRunner(menu_model, views::MenuRunner::HAS_MNEMONICS));
  // If RunMenuAt() fails, return immediately. This is future-proofing for
  // adding code after this call.
  if (context_menu_runner_->RunMenuAt(
          GetWidget(), nullptr, gfx::Rect(point, gfx::Size()),
          views::MENU_ANCHOR_TOPLEFT,
          source_type) == views::MenuRunner::MENU_DELETED)
    return;
}

}  // namespace app_list
<|endoftext|>


<commit_before>#include <gtest/gtest.h>
#include "cpp-json-qi/json.h"

#include <iostream>

using namespace jsonqi;

TEST(ASCIICharacters, CanBeWritten) {
  json_array arr;
  arr.push_back(json_string("äöüß")); // UTF-8

  std::ostringstream oss;
  oss << json_value(arr);

  std::string actual = oss.str();
  ASSERT_TRUE(!actual.empty());
  ASSERT_EQ(std::string("[ \"\\u00c3\\u00a4\\u00c3\\u00b6\\u00c3\\u00bc\\u00c3\\u009f\" ]"), actual);
}

TEST(WideCharacters, CanBeWritten) {
  wjson_array arr;
  arr.push_back(wjson_string(L"äöüß")); // UTF-8

  std::wostringstream oss;
  oss << wjson_value(arr);

  std::wstring actual = oss.str();
  ASSERT_TRUE(!actual.empty());
  ASSERT_EQ(std::wstring(L"[ \"\\u00e4\\u00f6\\u00fc\\u00df\" ]"), actual);
}
<commit_msg>disabled platform-specific test<commit_after>#include <gtest/gtest.h>
#include "cpp-json-qi/json.h"

#include <iostream>

using namespace jsonqi;

TEST(ASCIICharacters, CanBeWritten) {
  json_array arr;
  arr.push_back(json_string("äöüß")); // UTF-8

  std::ostringstream oss;
  oss << json_value(arr);

  std::string actual = oss.str();
  ASSERT_TRUE(!actual.empty());
  ASSERT_EQ(std::string("[ \"\\u00c3\\u00a4\\u00c3\\u00b6\\u00c3\\u00bc\\u00c3\\u009f\" ]"), actual);
}

TEST(WideCharacters, DISABLED_CanBeWritten) {
  wjson_array arr;
  arr.push_back(wjson_string(L"äöüß")); // UTF-8

  std::wostringstream oss;
  oss << wjson_value(arr);

  std::wstring actual = oss.str();
  ASSERT_TRUE(!actual.empty());
  ASSERT_EQ(std::wstring(L"[ \"\\u00e4\\u00f6\\u00fc\\u00df\" ]"), actual);
}
<|endoftext|>