<commit_before>/*********************************************************************************
 *
 * Inviwo - Interactive Visualization Workshop
 *
 * Copyright (c) 2013-2021 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 <modules/basegl/processors/background.h>

#include <inviwo/core/util/stringconversion.h>

#include <modules/opengl/texture/textureunit.h>
#include <modules/opengl/texture/textureutils.h>
#include <modules/opengl/image/imagegl.h>
#include <modules/opengl/image/layergl.h>
#include <modules/opengl/shader/shaderutils.h>
#include <modules/opengl/inviwoopengl.h>

namespace inviwo {

const ProcessorInfo Background::processorInfo_{
    "org.inviwo.Background",  // Class identifier
    "Background",             // Display name
    "Image Operation",        // Category
    CodeState::Stable,        // Code state
    Tags::GL,                 // Tags
};
const ProcessorInfo Background::getProcessorInfo() const { return processorInfo_; }

Background::Background()
    : Processor()
    , inport_("inport")
    , outport_("outport")
    , backgroundStyle_("backgroundStyle", "Style",
                       {{"linearGradientVertical", "Linear gradient (Vertical)",
                         BackgroundStyle::LinearVertical},
                        {"linearGradientHorizontal", "Linear gradient (Horizontal)",
                         BackgroundStyle::LinearHorizontal},
                        {"linearGradientSpherical", "Linear gradient (Spherical)",
                         BackgroundStyle::LinearSpherical},
                        {"uniformColor", "Uniform color", BackgroundStyle::Uniform},
                        {"checkerBoard", "Checker board", BackgroundStyle::CheckerBoard}},
                       0, InvalidationLevel::InvalidResources)
    , bgColor1_("bgColor1", "Color 1", vec4(0.0f, 0.0f, 0.0f, 1.0f))
    , bgColor2_("bgColor2", "Color 2", vec4(1.0f))
    , checkerBoardSize_("checkerBoardSize", "Checker Board Size", ivec2(10, 10), ivec2(1, 1),
                        ivec2(256, 256))
    , switchColors_("switchColors", "Switch Colors", InvalidationLevel::Valid)
    , blendMode_("blendMode", "Blend mode",
                 {{"backtofront", "Back To Front (Pre-multiplied)", BlendMode::BackToFront},
                  {"alphamixing", "Alpha Mixing", BlendMode::AlphaMixing}},
                 0, InvalidationLevel::InvalidResources)
    , shader_("background.frag", Shader::Build::No) {
    addPort(inport_);
    addPort(outport_);
    inport_.setOptional(true);

    addProperty(backgroundStyle_);
    bgColor1_.setSemantics(PropertySemantics::Color);
    addProperty(bgColor1_);
    bgColor2_.setSemantics(PropertySemantics::Color);
    addProperty(bgColor2_);
    addProperty(checkerBoardSize_);
    addProperty(switchColors_);
    addProperty(blendMode_);

    switchColors_.onChange([&]() {
        vec4 tmp = bgColor1_.get();
        bgColor1_.set(bgColor2_.get());
        bgColor2_.set(tmp);
    });
    shader_.onReload([this]() { invalidate(InvalidationLevel::InvalidResources); });
}

Background::~Background() = default;

void Background::initializeResources() {
    auto fs = shader_.getFragmentShaderObject();

    std::string_view bgStyleValue;
    switch (backgroundStyle_.get()) {
        default:
        case BackgroundStyle::LinearVertical:  // linear gradient
            bgStyleValue = "linearGradientVertical(texCoord)";
            checkerBoardSize_.setVisible(false);
            break;
        case BackgroundStyle::LinearHorizontal:  // linear gradient
            bgStyleValue = "linearGradientHorizontal(texCoord)";
            checkerBoardSize_.setVisible(false);
            break;
        case BackgroundStyle::LinearSpherical:  // linear spherical gradient
            bgStyleValue = "linearGradientSpherical(texCoord)";
            checkerBoardSize_.setVisible(false);
            break;
        case BackgroundStyle::Uniform:  // uniform color
            bgStyleValue = "bgColor1";
            checkerBoardSize_.setVisible(false);
            break;
        case BackgroundStyle::CheckerBoard:  // checker board
            bgStyleValue = "checkerBoard(texCoord)";
            checkerBoardSize_.setVisible(true);
            break;
    }
    fs->addShaderDefine("BACKGROUND_STYLE_FUNCTION", bgStyleValue);

    if (inport_.isReady()) {
        fs->addShaderDefine("SRC_COLOR", "texture(inportColor, texCoord)");
        // set shader inputs to match number of available color layers
        updateShaderInputs();

        fs->addShaderDefine("PICKING_LAYER");
        fs->addShaderDefine("DEPTH_LAYER");

        hadData_ = true;
    } else {
        fs->addShaderDefine("SRC_COLOR", "vec4(0)");
        fs->removeShaderDefine("PICKING_LAYER");
        fs->removeShaderDefine("DEPTH_LAYER");

        hadData_ = false;
    }

    const std::string_view blendfunc = [&]() {
        switch (blendMode_.get()) {
            case BlendMode::BackToFront:
                return "blendBackToFront";
            case BlendMode::AlphaMixing:
                [[fallthrough]];
            default:
                return "blendAlphaCompositing";
        }
    }();
    fs->addShaderDefine("BLENDFUNC", blendfunc);

    shader_.build();
}

void Background::process() {
    if (inport_.isReady() != hadData_) initializeResources();

    if (inport_.isReady()) {
        // Check data format, make sure we always have 4 channels
        auto inDataFromat = inport_.getData()->getDataFormat();
        auto format =
            DataFormatBase::get(inDataFromat->getNumericType(), 4,
                                inDataFromat->getSize() * 8 / inDataFromat->getComponents());

        if (outport_.getData()->getDataFormat() != format) {
            outport_.setData(std::make_shared<Image>(outport_.getDimensions(), format));
        }
    }
    utilgl::activateTarget(outport_, ImageType::AllLayers);

    shader_.activate();

    if (inport_.isReady()) {
        TextureUnitContainer textureUnits;

        auto image = inport_.getData();
        utilgl::bindAndSetUniforms(shader_, textureUnits, inport_, ImageType::AllLayers);

        {
            // bind all additional color layers
            const auto numColorLayers = image->getNumberOfColorLayers();
            auto imageGL = image->getRepresentation<ImageGL>();
            for (size_t i = 1; i < numColorLayers; ++i) {
                TextureUnit texUnit;
                imageGL->getColorLayerGL(i)->bindTexture(texUnit.getEnum());
                shader_.setUniform("color" + toString<size_t>(i), texUnit.getUnitNumber());
                textureUnits.push_back(std::move(texUnit));
            }
        }
    }

    utilgl::setUniforms(shader_, outport_, bgColor1_, bgColor2_, checkerBoardSize_);
    utilgl::singleDrawImagePlaneRect();
    shader_.deactivate();
    utilgl::deactivateCurrentTarget();
}

void Background::updateShaderInputs() {
    const auto numColorLayers = inport_.getData()->getNumberOfColorLayers();
    auto fs = shader_.getFragmentShaderObject();

    if (numColorLayers > 1) {
        fs->addShaderDefine("ADDITIONAL_COLOR_LAYERS");

        // location 0 is reserved for FragData0, location 1 for PickingData
        size_t outputLocation = 2;

        StrBuffer buff;
        buff.append("\n");
        for (size_t i = 1; i < numColorLayers; ++i) {
            buff.append("layout(location = {}) out vec4 FragData{};\n", outputLocation++, i);
        }
        for (size_t i = 1; i < numColorLayers; ++i) {
            buff.append("uniform sampler2D color{};\n", i);
        }
        fs->addShaderDefine("ADDITIONAL_COLOR_LAYER_OUT_UNIFORMS", buff);

        buff.clear();
        for (size_t i = 1; i < numColorLayers - 1; ++i) {
            buff.append("FragData{0} = texture(color{0}, texCoord.xy); \\\n", i);
        }
        buff.append("FragData{0} = texture(color{0}, texCoord.xy); \n", numColorLayers - 1);
        fs->addShaderDefine("ADDITIONAL_COLOR_LAYER_WRITE", buff);

    } else {
        fs->removeShaderDefine("ADDITIONAL_COLOR_LAYERS");
        fs->removeShaderDefine("ADDITIONAL_COLOR_LAYER_OUT_UNIFORMS");
        fs->removeShaderDefine("ADDITIONAL_COLOR_LAYER_WRITE");
    }
}

}  // namespace inviwo
<commit_msg>BaseGL: ordinal colors in Background processor<commit_after>/*********************************************************************************
 *
 * Inviwo - Interactive Visualization Workshop
 *
 * Copyright (c) 2013-2021 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 <modules/basegl/processors/background.h>

#include <inviwo/core/util/stringconversion.h>

#include <modules/opengl/texture/textureunit.h>
#include <modules/opengl/texture/textureutils.h>
#include <modules/opengl/image/imagegl.h>
#include <modules/opengl/image/layergl.h>
#include <modules/opengl/shader/shaderutils.h>
#include <modules/opengl/inviwoopengl.h>

namespace inviwo {

const ProcessorInfo Background::processorInfo_{
    "org.inviwo.Background",  // Class identifier
    "Background",             // Display name
    "Image Operation",        // Category
    CodeState::Stable,        // Code state
    Tags::GL,                 // Tags
};
const ProcessorInfo Background::getProcessorInfo() const { return processorInfo_; }

Background::Background()
    : Processor()
    , inport_("inport")
    , outport_("outport")
    , backgroundStyle_("backgroundStyle", "Style",
                       {{"linearGradientVertical", "Linear gradient (Vertical)",
                         BackgroundStyle::LinearVertical},
                        {"linearGradientHorizontal", "Linear gradient (Horizontal)",
                         BackgroundStyle::LinearHorizontal},
                        {"linearGradientSpherical", "Linear gradient (Spherical)",
                         BackgroundStyle::LinearSpherical},
                        {"uniformColor", "Uniform color", BackgroundStyle::Uniform},
                        {"checkerBoard", "Checker board", BackgroundStyle::CheckerBoard}},
                       0, InvalidationLevel::InvalidResources)
    , bgColor1_("bgColor1", "Color 1", util::ordinalColor(0.0f, 0.0f, 0.0f, 1.0f))
    , bgColor2_("bgColor2", "Color 2", util::ordinalColor(1.0f, 1.0f, 1.0f, 1.0f))
    , checkerBoardSize_("checkerBoardSize", "Checker Board Size", ivec2(10, 10), ivec2(1, 1),
                        ivec2(256, 256))
    , switchColors_("switchColors", "Switch Colors", InvalidationLevel::Valid)
    , blendMode_("blendMode", "Blend mode",
                 {{"backtofront", "Back To Front (Pre-multiplied)", BlendMode::BackToFront},
                  {"alphamixing", "Alpha Mixing", BlendMode::AlphaMixing}},
                 0, InvalidationLevel::InvalidResources)
    , shader_("background.frag", Shader::Build::No) {
    addPort(inport_);
    addPort(outport_);
    inport_.setOptional(true);

    addProperty(backgroundStyle_);
    addProperty(bgColor1_);
    addProperty(bgColor2_);
    addProperty(checkerBoardSize_);
    addProperty(switchColors_);
    addProperty(blendMode_);

    switchColors_.onChange([&]() {
        vec4 tmp = bgColor1_.get();
        bgColor1_.set(bgColor2_.get());
        bgColor2_.set(tmp);
    });
    shader_.onReload([this]() { invalidate(InvalidationLevel::InvalidResources); });
}

Background::~Background() = default;

void Background::initializeResources() {
    auto fs = shader_.getFragmentShaderObject();

    std::string_view bgStyleValue;
    switch (backgroundStyle_.get()) {
        default:
        case BackgroundStyle::LinearVertical:  // linear gradient
            bgStyleValue = "linearGradientVertical(texCoord)";
            checkerBoardSize_.setVisible(false);
            break;
        case BackgroundStyle::LinearHorizontal:  // linear gradient
            bgStyleValue = "linearGradientHorizontal(texCoord)";
            checkerBoardSize_.setVisible(false);
            break;
        case BackgroundStyle::LinearSpherical:  // linear spherical gradient
            bgStyleValue = "linearGradientSpherical(texCoord)";
            checkerBoardSize_.setVisible(false);
            break;
        case BackgroundStyle::Uniform:  // uniform color
            bgStyleValue = "bgColor1";
            checkerBoardSize_.setVisible(false);
            break;
        case BackgroundStyle::CheckerBoard:  // checker board
            bgStyleValue = "checkerBoard(texCoord)";
            checkerBoardSize_.setVisible(true);
            break;
    }
    fs->addShaderDefine("BACKGROUND_STYLE_FUNCTION", bgStyleValue);

    if (inport_.isReady()) {
        fs->addShaderDefine("SRC_COLOR", "texture(inportColor, texCoord)");
        // set shader inputs to match number of available color layers
        updateShaderInputs();

        fs->addShaderDefine("PICKING_LAYER");
        fs->addShaderDefine("DEPTH_LAYER");

        hadData_ = true;
    } else {
        fs->addShaderDefine("SRC_COLOR", "vec4(0)");
        fs->removeShaderDefine("PICKING_LAYER");
        fs->removeShaderDefine("DEPTH_LAYER");

        hadData_ = false;
    }

    const std::string_view blendfunc = [&]() {
        switch (blendMode_.get()) {
            case BlendMode::BackToFront:
                return "blendBackToFront";
            case BlendMode::AlphaMixing:
                [[fallthrough]];
            default:
                return "blendAlphaCompositing";
        }
    }();
    fs->addShaderDefine("BLENDFUNC", blendfunc);

    shader_.build();
}

void Background::process() {
    if (inport_.isReady() != hadData_) initializeResources();

    if (inport_.isReady()) {
        // Check data format, make sure we always have 4 channels
        auto inDataFromat = inport_.getData()->getDataFormat();
        auto format =
            DataFormatBase::get(inDataFromat->getNumericType(), 4,
                                inDataFromat->getSize() * 8 / inDataFromat->getComponents());

        if (outport_.getData()->getDataFormat() != format) {
            outport_.setData(std::make_shared<Image>(outport_.getDimensions(), format));
        }
    }
    utilgl::activateTarget(outport_, ImageType::AllLayers);

    shader_.activate();

    if (inport_.isReady()) {
        TextureUnitContainer textureUnits;

        auto image = inport_.getData();
        utilgl::bindAndSetUniforms(shader_, textureUnits, inport_, ImageType::AllLayers);

        {
            // bind all additional color layers
            const auto numColorLayers = image->getNumberOfColorLayers();
            auto imageGL = image->getRepresentation<ImageGL>();
            for (size_t i = 1; i < numColorLayers; ++i) {
                TextureUnit texUnit;
                imageGL->getColorLayerGL(i)->bindTexture(texUnit.getEnum());
                shader_.setUniform("color" + toString<size_t>(i), texUnit.getUnitNumber());
                textureUnits.push_back(std::move(texUnit));
            }
        }
    }

    utilgl::setUniforms(shader_, outport_, bgColor1_, bgColor2_, checkerBoardSize_);
    utilgl::singleDrawImagePlaneRect();
    shader_.deactivate();
    utilgl::deactivateCurrentTarget();
}

void Background::updateShaderInputs() {
    const auto numColorLayers = inport_.getData()->getNumberOfColorLayers();
    auto fs = shader_.getFragmentShaderObject();

    if (numColorLayers > 1) {
        fs->addShaderDefine("ADDITIONAL_COLOR_LAYERS");

        // location 0 is reserved for FragData0, location 1 for PickingData
        size_t outputLocation = 2;

        StrBuffer buff;
        buff.append("\n");
        for (size_t i = 1; i < numColorLayers; ++i) {
            buff.append("layout(location = {}) out vec4 FragData{};\n", outputLocation++, i);
        }
        for (size_t i = 1; i < numColorLayers; ++i) {
            buff.append("uniform sampler2D color{};\n", i);
        }
        fs->addShaderDefine("ADDITIONAL_COLOR_LAYER_OUT_UNIFORMS", buff);

        buff.clear();
        for (size_t i = 1; i < numColorLayers - 1; ++i) {
            buff.append("FragData{0} = texture(color{0}, texCoord.xy); \\\n", i);
        }
        buff.append("FragData{0} = texture(color{0}, texCoord.xy); \n", numColorLayers - 1);
        fs->addShaderDefine("ADDITIONAL_COLOR_LAYER_WRITE", buff);

    } else {
        fs->removeShaderDefine("ADDITIONAL_COLOR_LAYERS");
        fs->removeShaderDefine("ADDITIONAL_COLOR_LAYER_OUT_UNIFORMS");
        fs->removeShaderDefine("ADDITIONAL_COLOR_LAYER_WRITE");
    }
}

}  // namespace inviwo
<|endoftext|>


<commit_before>//Rubisks trying to wrap leveldb-mcpe
#include <leveldb/cache.h>
#include <leveldb/comparator.h>
#include <leveldb/db.h>
#include <leveldb/env.h>
#include <leveldb/filter_policy.h>
#include <leveldb/write_batch.h>

#define BOOST_PYTHON_STATIC_LIB

#include <boost/python/module.hpp>
#include <boost/python/def.hpp>
#include <boost/python/object.hpp>
#include <boost/python/str.hpp>
#include <boost/python/extract.hpp>
#include <boost/system/config.hpp>
#include <boost/python.hpp>
#include <stdint.h>
#include <stdio.h>

namespace bp = boost::python;

//Exception
class LevelDBException {
public:
	LevelDBException(const std::string msg)
		: message(msg) {}

	std::string getMessage() const {
		return message;
	}
private:
	std::string message;
};

static void ExceptionTranslator(const LevelDBException &err) {
	PyErr_SetString(PyExc_RuntimeError, err.getMessage().c_str());
};

struct IteratorWrapper{
	leveldb::Iterator* _it;

	IteratorWrapper(leveldb::Iterator* it){
		this->_it = it;
	}

	bool Valid()
	{
		return this->_it->Valid();
	}

	void SeekToFirst()
	{
		this->_it->SeekToFirst();
	}

	void SeekToLast()
	{
		this->_it->SeekToLast();
	}

	void Seek(PyObject* _target)
	{
		const std::string target = bp::extract<const std::string>(_target);
		return this->_it->Seek(target);
	}

	void Next()
	{
		this->_it->Next();
	}

	void Prev()
	{
		this->_it->Prev();
	}

	std::string key()
	{
		return this->_it->key().ToString();
	}

	std::string value()
	{
		return this->_it->value().ToString();
	}

	void status()
	{
		leveldb::Status s = this->_it->status();

		if (!s.ok()){
			throw LevelDBException(s.ToString());
		}
	}
};

//write_batch.h
struct WriteBatchWrapper
{
	leveldb::WriteBatch* _wb;

	WriteBatchWrapper(){
		_wb = new leveldb::WriteBatch();
	};

  ~WriteBatchWrapper(){
    delete _wb;
  };

	void Put(PyObject* _key, PyObject* _value)
	{
		const std::string key = bp::extract<const std::string>(_key);
		const std::string value = bp::extract<const std::string>(_value);
		this->_wb->Put(key, value);
	}

	void Delete(PyObject* _key)
	{
		const std::string key = bp::extract<const std::string>(_key);
		this->_wb->Delete(key);
	}
};

//leveldb::DB wrapper
class DBWrap
{
public:
  leveldb::DB * _db;

  DBWrap(PyObject* _options, PyObject* _name) //Open(options, name, db)
  {
    const leveldb::Options options = bp::extract<const leveldb::Options&>(_options);
    std::string name = bp::extract<std::string>(_name);
    leveldb::Status s = leveldb::DB::Open(options, name, &_db);

    if(!s.ok())
    {
      throw LevelDBException(s.ToString());
    }
  }

  void Put(PyObject* _options, PyObject* _key, PyObject* _value) //Put(options, key, value)
  {
	  const leveldb::WriteOptions& options = bp::extract<const leveldb::WriteOptions&>(_options);
	  const std::string key = bp::extract<const std::string>(_key);
	  const std::string value = bp::extract<const std::string>(_value);
	  leveldb::Status s = this->_db->Put(options, key, value);

	  if (!s.ok()){
		  throw LevelDBException(s.ToString());
	  }
  }

  void Delete(PyObject* _options, PyObject* _key) //Delete(options, key)
  {
	  const leveldb::WriteOptions& options = bp::extract<const leveldb::WriteOptions&>(_options);
	  const std::string key = bp::extract<const std::string>(_key);
	  leveldb::Status s = this->_db->Delete(options, key);

	  if (!s.ok()){
		  throw LevelDBException(s.ToString());
	  }
  }

  std::string Get(PyObject* _options, PyObject* _key) //Delete(options, key)
  {
	  const leveldb::ReadOptions& options = bp::extract<const leveldb::ReadOptions&>(_options);
	  const std::string key = bp::extract<const std::string>(_key);
	  std::string value;
	  leveldb::Status s = this->_db->Get(options, key, &value);

	  if (!s.ok()){
		  throw LevelDBException(s.ToString());
	  }
	  return value;
  }

  void Write(PyObject* _options, PyObject* _updates)
  {
	  const leveldb::WriteOptions& options = bp::extract<const leveldb::WriteOptions&>(_options);
	  WriteBatchWrapper& __updates = bp::extract<WriteBatchWrapper&>(_updates);
	  leveldb::Status s = this->_db->Write(options, __updates._wb);

	  if (!s.ok()){
		  throw LevelDBException(s.ToString());
	  }
  }

  IteratorWrapper NewIterator(const leveldb::ReadOptions& options)
  {
	  leveldb::Iterator* it = this->_db->NewIterator(options);
	  return IteratorWrapper(it);
  }

  const leveldb::Snapshot* GetSnapshot()
  {
    return this->_db->GetSnapshot();
  }

  void GetApproximateSizes(const leveldb::Range* range, int n, uint64_t* sizes)
  {
    this->_db->GetApproximateSizes(range, n, sizes);
  }

  void ReleaseSnapshot(const leveldb::Snapshot* snapshot)
  {
    this->_db->ReleaseSnapshot(snapshot);
  }

  bool GetProperty(const leveldb::Slice& property, std::string* value)
  {
    return this->_db->GetProperty(property, value);
  }

  void CompactRange(const leveldb::Slice* begin, const leveldb::Slice* end)
  {
    this->_db->CompactRange(begin, end);
  }
};

BOOST_PYTHON_MODULE(leveldb_mcpe)
{
  //Exceptions
  bp::register_exception_translator<LevelDBException>(&ExceptionTranslator);

  //leveldb/db.h
  bp::class_<DBWrap, boost::noncopyable>("DB", bp::init<PyObject*, PyObject*>())
    .def("Put", &DBWrap::Put)
    .def("Delete", &DBWrap::Delete)
    .def("Write", &DBWrap::Write)
    .def("Get", &DBWrap::Get)
    .def("NewIterator", &DBWrap::NewIterator)
    .def("GetSnapshot", &DBWrap::GetSnapshot,
		bp::return_value_policy<bp::reference_existing_object>())
    .def("ReleaseSnapshot", &DBWrap::ReleaseSnapshot)
    .def("GetProperty", &DBWrap::GetProperty)
	.def("GetApproximateSizes", &DBWrap::GetApproximateSizes)
	.def("CompactRange", &DBWrap::CompactRange);

  //leveldb/options.h
  bp::class_<leveldb::Options>("Options", bp::init<>())
	  .def_readonly("comparator", &leveldb::Options::comparator) //Pointer, maybe needs better wrapper? Untested
	  .def_readwrite("create_if_missing", &leveldb::Options::create_if_missing)
	  .def_readwrite("error_if_exists", &leveldb::Options::error_if_exists)
	  .def_readwrite("env", &leveldb::Options::env) //Pointer, maybe needs better wrapper? Untested
	  .def_readwrite("info_log", &leveldb::Options::info_log) //Pointer, maybe needs better wrapper? Untested
	  .def_readwrite("write_buffer_size", &leveldb::Options::write_buffer_size)
	  .def_readwrite("max_open_files", &leveldb::Options::max_open_files)
	  .def_readwrite("block_cache", &leveldb::Options::block_cache) //Pointer, maybe needs better wrapper? Untested
	  .def_readwrite("block_size", &leveldb::Options::block_size)
	  .def_readwrite("block_restart_interval", &leveldb::Options::block_restart_interval)
	  //TODO setup a way to include compressor array //Pointer, maybe needs better wrapper? Untested
	  .def_readonly("filter_policy", &leveldb::Options::filter_policy); //Pointer, maybe needs better wrapper? Untested
	;

  bp::class_<leveldb::ReadOptions>("ReadOptions", bp::init<>())
	  .def_readwrite("verify_checksums", &leveldb::ReadOptions::verify_checksums)
	  .def_readwrite("fill_cache", &leveldb::ReadOptions::fill_cache)
	  .def_readwrite("snapshot", &leveldb::ReadOptions::snapshot) //Pointer, maybe needs better wrapper? Untested
	;

  bp::class_<leveldb::WriteOptions>("WriteOptions", bp::init<>())
	  .def_readwrite("sync", &leveldb::WriteOptions::sync)
	;

  //leveldb/iterator.h
  bp::class_<IteratorWrapper>("Iterator", bp::no_init)
	  .def("Valid", &IteratorWrapper::Valid)
	  .def("SeekToFirst", &IteratorWrapper::SeekToFirst)
	  .def("SeekToLast", &IteratorWrapper::SeekToLast)
	  .def("Seek", &IteratorWrapper::Seek)
	  .def("Next", &IteratorWrapper::Next)
	  .def("Prev", &IteratorWrapper::Prev)
	  .def("key", &IteratorWrapper::key)
	  .def("value", &IteratorWrapper::value)
	  .def("status", &IteratorWrapper::status)

	  ;

  //leveldb/write_batch.h
  bp::class_<WriteBatchWrapper>("WriteBatch", bp::init<>())
	  .def("Put", &WriteBatchWrapper::Put)
	  .def("Delete", &WriteBatchWrapper::Delete)
	  ;
}
<commit_msg>Added destructors for IteratorWrapper and DBWrap<commit_after>//Rubisks trying to wrap leveldb-mcpe
#include <leveldb/cache.h>
#include <leveldb/comparator.h>
#include <leveldb/db.h>
#include <leveldb/env.h>
#include <leveldb/filter_policy.h>
#include <leveldb/write_batch.h>

#define BOOST_PYTHON_STATIC_LIB

#include <boost/python/module.hpp>
#include <boost/python/def.hpp>
#include <boost/python/object.hpp>
#include <boost/python/str.hpp>
#include <boost/python/extract.hpp>
#include <boost/system/config.hpp>
#include <boost/python.hpp>
#include <stdint.h>
#include <stdio.h>

namespace bp = boost::python;

//Exception
class LevelDBException {
public:
	LevelDBException(const std::string msg)
		: message(msg) {}

	std::string getMessage() const {
		return message;
	}
private:
	std::string message;
};

static void ExceptionTranslator(const LevelDBException &err) {
	PyErr_SetString(PyExc_RuntimeError, err.getMessage().c_str());
};

struct IteratorWrapper{
	leveldb::Iterator* _it;

	IteratorWrapper(leveldb::Iterator* it){
		this->_it = it;
	}

	~IteratorWrapper{
		delete _it;
	}

	bool Valid()
	{
		return this->_it->Valid();
	}

	void SeekToFirst()
	{
		this->_it->SeekToFirst();
	}

	void SeekToLast()
	{
		this->_it->SeekToLast();
	}

	void Seek(PyObject* _target)
	{
		const std::string target = bp::extract<const std::string>(_target);
		return this->_it->Seek(target);
	}

	void Next()
	{
		this->_it->Next();
	}

	void Prev()
	{
		this->_it->Prev();
	}

	std::string key()
	{
		return this->_it->key().ToString();
	}

	std::string value()
	{
		return this->_it->value().ToString();
	}

	void status()
	{
		leveldb::Status s = this->_it->status();

		if (!s.ok()){
			throw LevelDBException(s.ToString());
		}
	}
};

//write_batch.h
struct WriteBatchWrapper
{
	leveldb::WriteBatch* _wb;

	WriteBatchWrapper(){
		_wb = new leveldb::WriteBatch();
	};

  ~WriteBatchWrapper(){
    delete _wb;
  }

	void Put(PyObject* _key, PyObject* _value)
	{
		const std::string key = bp::extract<const std::string>(_key);
		const std::string value = bp::extract<const std::string>(_value);
		this->_wb->Put(key, value);
	}

	void Delete(PyObject* _key)
	{
		const std::string key = bp::extract<const std::string>(_key);
		this->_wb->Delete(key);
	}
};

//leveldb::DB wrapper
class DBWrap
{
public:
  leveldb::DB * _db;

  ~DBWrap(){
	  delete _db;
  };

  DBWrap(PyObject* _options, PyObject* _name) //Open(options, name, db)
  {
    const leveldb::Options options = bp::extract<const leveldb::Options&>(_options);
    std::string name = bp::extract<std::string>(_name);
    leveldb::Status s = leveldb::DB::Open(options, name, &_db);

    if(!s.ok())
    {
      throw LevelDBException(s.ToString());
    }
  }

  void Put(PyObject* _options, PyObject* _key, PyObject* _value) //Put(options, key, value)
  {
	  const leveldb::WriteOptions& options = bp::extract<const leveldb::WriteOptions&>(_options);
	  const std::string key = bp::extract<const std::string>(_key);
	  const std::string value = bp::extract<const std::string>(_value);
	  leveldb::Status s = this->_db->Put(options, key, value);

	  if (!s.ok()){
		  throw LevelDBException(s.ToString());
	  }
  }

  void Delete(PyObject* _options, PyObject* _key) //Delete(options, key)
  {
	  const leveldb::WriteOptions& options = bp::extract<const leveldb::WriteOptions&>(_options);
	  const std::string key = bp::extract<const std::string>(_key);
	  leveldb::Status s = this->_db->Delete(options, key);

	  if (!s.ok()){
		  throw LevelDBException(s.ToString());
	  }
  }

  std::string Get(PyObject* _options, PyObject* _key) //Delete(options, key)
  {
	  const leveldb::ReadOptions& options = bp::extract<const leveldb::ReadOptions&>(_options);
	  const std::string key = bp::extract<const std::string>(_key);
	  std::string value;
	  leveldb::Status s = this->_db->Get(options, key, &value);

	  if (!s.ok()){
		  throw LevelDBException(s.ToString());
	  }
	  return value;
  }

  void Write(PyObject* _options, PyObject* _updates)
  {
	  const leveldb::WriteOptions& options = bp::extract<const leveldb::WriteOptions&>(_options);
	  WriteBatchWrapper& __updates = bp::extract<WriteBatchWrapper&>(_updates);
	  leveldb::Status s = this->_db->Write(options, __updates._wb);

	  if (!s.ok()){
		  throw LevelDBException(s.ToString());
	  }
  }

  IteratorWrapper NewIterator(const leveldb::ReadOptions& options)
  {
	  leveldb::Iterator* it = this->_db->NewIterator(options);
	  return IteratorWrapper(it);
  }

  const leveldb::Snapshot* GetSnapshot()
  {
    return this->_db->GetSnapshot();
  }

  void GetApproximateSizes(const leveldb::Range* range, int n, uint64_t* sizes)
  {
    this->_db->GetApproximateSizes(range, n, sizes);
  }

  void ReleaseSnapshot(const leveldb::Snapshot* snapshot)
  {
    this->_db->ReleaseSnapshot(snapshot);
  }

  bool GetProperty(const leveldb::Slice& property, std::string* value)
  {
    return this->_db->GetProperty(property, value);
  }

  void CompactRange(const leveldb::Slice* begin, const leveldb::Slice* end)
  {
    this->_db->CompactRange(begin, end);
  }
};

BOOST_PYTHON_MODULE(leveldb_mcpe)
{
  //Exceptions
  bp::register_exception_translator<LevelDBException>(&ExceptionTranslator);

  //leveldb/db.h
  bp::class_<DBWrap, boost::noncopyable>("DB", bp::init<PyObject*, PyObject*>())
    .def("Put", &DBWrap::Put)
    .def("Delete", &DBWrap::Delete)
    .def("Write", &DBWrap::Write)
    .def("Get", &DBWrap::Get)
    .def("NewIterator", &DBWrap::NewIterator)
    .def("GetSnapshot", &DBWrap::GetSnapshot,
		bp::return_value_policy<bp::reference_existing_object>())
    .def("ReleaseSnapshot", &DBWrap::ReleaseSnapshot)
    .def("GetProperty", &DBWrap::GetProperty)
	.def("GetApproximateSizes", &DBWrap::GetApproximateSizes)
	.def("CompactRange", &DBWrap::CompactRange);

  //leveldb/options.h
  bp::class_<leveldb::Options>("Options", bp::init<>())
	  .def_readonly("comparator", &leveldb::Options::comparator) //Pointer, maybe needs better wrapper? Untested
	  .def_readwrite("create_if_missing", &leveldb::Options::create_if_missing)
	  .def_readwrite("error_if_exists", &leveldb::Options::error_if_exists)
	  .def_readwrite("env", &leveldb::Options::env) //Pointer, maybe needs better wrapper? Untested
	  .def_readwrite("info_log", &leveldb::Options::info_log) //Pointer, maybe needs better wrapper? Untested
	  .def_readwrite("write_buffer_size", &leveldb::Options::write_buffer_size)
	  .def_readwrite("max_open_files", &leveldb::Options::max_open_files)
	  .def_readwrite("block_cache", &leveldb::Options::block_cache) //Pointer, maybe needs better wrapper? Untested
	  .def_readwrite("block_size", &leveldb::Options::block_size)
	  .def_readwrite("block_restart_interval", &leveldb::Options::block_restart_interval)
	  //TODO setup a way to include compressor array //Pointer, maybe needs better wrapper? Untested
	  .def_readonly("filter_policy", &leveldb::Options::filter_policy); //Pointer, maybe needs better wrapper? Untested
	;

  bp::class_<leveldb::ReadOptions>("ReadOptions", bp::init<>())
	  .def_readwrite("verify_checksums", &leveldb::ReadOptions::verify_checksums)
	  .def_readwrite("fill_cache", &leveldb::ReadOptions::fill_cache)
	  .def_readwrite("snapshot", &leveldb::ReadOptions::snapshot) //Pointer, maybe needs better wrapper? Untested
	;

  bp::class_<leveldb::WriteOptions>("WriteOptions", bp::init<>())
	  .def_readwrite("sync", &leveldb::WriteOptions::sync)
	;

  //leveldb/iterator.h
  bp::class_<IteratorWrapper>("Iterator", bp::no_init)
	  .def("Valid", &IteratorWrapper::Valid)
	  .def("SeekToFirst", &IteratorWrapper::SeekToFirst)
	  .def("SeekToLast", &IteratorWrapper::SeekToLast)
	  .def("Seek", &IteratorWrapper::Seek)
	  .def("Next", &IteratorWrapper::Next)
	  .def("Prev", &IteratorWrapper::Prev)
	  .def("key", &IteratorWrapper::key)
	  .def("value", &IteratorWrapper::value)
	  .def("status", &IteratorWrapper::status)

	  ;

  //leveldb/write_batch.h
  bp::class_<WriteBatchWrapper>("WriteBatch", bp::init<>())
	  .def("Put", &WriteBatchWrapper::Put)
	  .def("Delete", &WriteBatchWrapper::Delete)
	  ;
}
<|endoftext|>


<commit_before>// @(#)root/editline:$Id$
// Author: Mary-Louise Gill, 2009

/*************************************************************************
 * Copyright (C) 1995-2011, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

#include "Getline_color.h"

#include <stack>
#include <string>

#include "TClass.h"
#include "TClassTable.h"
#include "TInterpreter.h"
#include "TROOT.h"
#include "textinput/Range.h"
#include "textinput/Text.h"

using namespace std;
using namespace textinput;

namespace {

   Color ColorFromName(const char* name) {
      // Convert a color name to a Color.
      Color ret;

      std::string lowname(name);
      size_t lenname = strlen(name);
      for (size_t i = 0; i < lenname; ++i)
         lowname[i] = tolower(lowname[i]);

      if (lowname.find("bold") != std::string::npos
          || lowname.find("light") != std::string::npos)
         ret.fModifiers |= Color::kModBold;
      if (lowname.find("under") != std::string::npos)
         ret.fModifiers |= Color::kModUnderline;

      size_t poshash = lowname.find('#');
      size_t lenrgb = 0;
      if (poshash != std::string::npos) {
         int endrgb = poshash + 1;
         while ((lowname[endrgb] >= '0' && lowname[endrgb] <= '9')
                || (lowname[endrgb] >= 'a' && lowname[endrgb] <= 'f')) {
            ++endrgb;
         }
         lenrgb = endrgb - poshash - 1;
      }

      int rgb[3] = {0};
      if (lenrgb == 3) {
         for (int i = 0; i < 3; ++i) {
            rgb[i] = lowname[poshash + 1 + i] - '0';
            if (rgb[i] > 9) {
               rgb[i] = rgb[i] + '0' - 'a' + 10;
            }
            rgb[i] *= 16; // only upper 4 bits are set.
         }
         return ret;
      } else if (lenrgb == 6) {
         for (int i = 0; i < 6; ++i) {
            int v = lowname[poshash + 1 + i] - '0';
            if (v > 9) {
               v = v + '0' - 'a' + 10;
            }
            if (i % 2 == 0) {
               v *= 16;
            }
            rgb[i / 2] += v;
         }
         ret.fR = rgb[0];
         ret.fG = rgb[1];
         ret.fB = rgb[2];
         return ret;
      } else {
         if (lowname.find("default") != std::string::npos) {
            return ret;
         }

         static const char* colornames[] = {
            "black", "red", "green", "yellow",
            "blue", "magenta", "cyan", "white", 0
         };
         static const unsigned char colorrgb[][3] = {
            {0,0,0}, {127,0,0}, {0,127,0}, {127,127,0},
            {0,0,127}, {127,0,127}, {0,127,127}, {127,127,127},
            {0}
         };

         for (int i = 0; colornames[i]; ++i) {
            if (lowname.find(colornames[i]) != std::string::npos) {
               int boldify = 0;
               if (ret.fModifiers & Color::kModBold)
                  boldify = 64;
               ret.fR = colorrgb[i][0] + boldify;
               ret.fG = colorrgb[i][1] + boldify;
               ret.fB = colorrgb[i][2] + boldify;
               return ret;
            }
         }
      }
      fprintf(stderr, "Getline_color/ColorFromName: cannot parse color %s!\n", name);
      return Color();
   } // ColorFromName()

   bool IsAlnum_(char c) { return c == '_' || isalnum(c); }
   bool IsAlpha_(char c) { return c == '_' || isalpha(c); }
} // unnamed namespace

ROOT::TextInputColorizer::TextInputColorizer():
   fColorIsDefault(), fPrevBracketColor(kColorNone) {
   // Set the default colors.
   // fColors[kColorNone] stays default initialized.
   fColors[kColorType] = ColorFromName("blue");
   fColors[kColorTabComp] = ColorFromName("magenta");
   fColors[kColorBracket] = ColorFromName("green");
   fColors[kColorBadBracket] = ColorFromName("red");
   fColors[kColorPrompt] = ColorFromName("default");
   fColorIsDefault[kColorPrompt] = true;
}

ROOT::TextInputColorizer::~TextInputColorizer() {
   // pin vtable
}

void ROOT::TextInputColorizer::ExtendRangeAndSetColor(Text& input,
                                                      size_t idx, char col,
                                                      Range& disp) {
   // Utility function that updates the display modification range if the
   // color at index idx is different from what it was before.

   if (fColorIsDefault[(int)col]) {
      // Never mind the color: use use default.
      col = 0;
   }
   if (input.GetColor(idx) != col) {
      input.SetColor(idx, col);
      disp.Extend(idx);
   }
}

bool ROOT::TextInputColorizer::GetColor(char type, Color& col) {
   // Set the Color corresponding to an entry in EColorTypes.
   // Returns false if the type index is out of range.

   if (type < (int)kNumColors) {
      col = fColors[(size_t)type];
      return true;
   }
   col = Color();
   return false;
}

void ROOT::TextInputColorizer::SetColors(const char* colorType,
                                         const char* colorTabComp,
                                         const char* colorBracket,
                                         const char* colorBadBracket,
                                         const char* colorPrompt) {
   // Set the colors of the different items as either
   // #RGB
   // #RRGGBB or
   // color name, optionally prepended by "underline" or "bold"

   fColors[kColorType] = ColorFromName(colorType);
   fColorIsDefault[kColorType] = (fColors[kColorType] == Color());
   fColors[kColorTabComp] = ColorFromName(colorTabComp);
   fColorIsDefault[kColorTabComp] = (fColors[kColorTabComp] == Color());
   fColors[kColorBracket] = ColorFromName(colorBracket);
   fColorIsDefault[kColorBracket] = (fColors[kColorBracket] == Color());
   fColors[kColorBadBracket] = ColorFromName(colorBadBracket);
   fColorIsDefault[kColorBadBracket] = (fColors[kColorBadBracket] == Color());
   fColors[kColorPrompt] = ColorFromName(colorPrompt);
   fColorIsDefault[kColorPrompt] = (fColors[kColorPrompt] == Color());
}

void ROOT::TextInputColorizer::ProcessTextChange(EditorRange& Modification,
                                                 Text& input) {
   // The text has changed; look for word that are types.

   const std::string& text = input.GetText();

   size_t modStart = Modification.fEdit.fStart;
   size_t inputLength = input.length();

   // Find end of modified word:
   size_t modEnd = Modification.fEdit.fLength;
   if (modEnd == (size_t) -1) {
      modEnd = inputLength;
   } else {
      modEnd += modStart;
      if (modEnd > inputLength) {
         modEnd = inputLength;
      } else {
         while (modEnd < inputLength && IsAlnum_(text[modEnd]))
            ++modEnd;
      }
   }

   // Find beginning of modified word. Don't treat
   // "12ull" specially, it will fall out below.
   while (modStart && IsAlnum_(text[modStart])) --modStart;

   // Ignore spaces
   while (modStart < modEnd && isspace(text[modStart]))
      ++modStart;
   while (modEnd > modStart && isspace(text[modEnd]))
      --modStart;

   for (size_t i = modStart; i < modEnd;) {
      // i points to beginning of word here.
      if (isdigit(text[i])) {
         // "12", or "12ull". Default color.
         ExtendRangeAndSetColor(input, i, 0, Modification.fDisplay);
         ++i;
         while (i < modEnd && IsAlnum_(text[i])) {
            ExtendRangeAndSetColor(input, i, 0, Modification.fDisplay);
            ++i;
         }
      } else if (IsAlpha_(text[i])) {
         // identifier, but is it a type?
         size_t wordLen = 1;
         while (i + wordLen < modEnd && IsAlnum_(text[i + wordLen])) {
            ++wordLen;
         }
         std::string word = text.substr(i, wordLen);
         char color = kColorNone;
         if (gROOT->GetListOfTypes()->FindObject(word.c_str())
             || gClassTable->GetDict(word.c_str())
             || gInterpreter->GetClassSharedLibs(word.c_str())
             || TClass::GetClass(word.c_str(), kFALSE)) {
            color = kColorType;
         }
         for (size_t ic = i; ic < i + wordLen; ++ic) {
            ExtendRangeAndSetColor(input, ic, color, Modification.fDisplay);
         }
         i += wordLen;
      } else {
         size_t wordLen = 1;
         while (i + wordLen < modEnd && !IsAlnum_(text[i + wordLen]))
            ++wordLen;
         for (size_t ic = i; ic < i + wordLen; ++ic) {
            // protect colored parens
            char oldColor = input.GetColor(ic);
            if (oldColor != kColorBracket && oldColor != kColorBadBracket) {
               ExtendRangeAndSetColor(input, ic, kColorNone, Modification.fDisplay);
            }
         }
         i += wordLen;
      }

      // skip trailing whitespace.
      while (i < modEnd && isspace(text[i])) {
         ExtendRangeAndSetColor(input, i, kColorNone, Modification.fDisplay);
         ++i;
      }
   }
}

void ROOT::TextInputColorizer::ProcessPromptChange(Text& prompt) {
   int idx = kColorPrompt;
   if (fColorIsDefault[kColorPrompt]) {
      idx = 0;
   }
   prompt.SetColor(Range::AllText(), idx);
}

void ROOT::TextInputColorizer::ProcessCursorChange(size_t Cursor,
                                                   Text& input,
                                                   Range& DisplayR) {
   // Check each char to see if it is an opening bracket,
   // if so, check for its closing one and color them green.

   static const int numBrackets = 3;
   static const char bTypes[numBrackets][3] = {"()", "{}", "[]"};

   if (input.empty()) return;

   if (fPrevBracketColor != kColorNone) {
      // Remove previous bracket coloring.
      const char* colors = &input.GetColors()[0];
      const char* prevBracket = (const char*) memchr(colors, fPrevBracketColor,
                                                     input.length());
      if (prevBracket) {
         ExtendRangeAndSetColor(input, prevBracket - colors, kColorNone, DisplayR);
         if (fPrevBracketColor == kColorBracket) {
            // There will be two.
            prevBracket = (const char*) memchr(prevBracket, fPrevBracketColor,
                                               input.length() - (prevBracket - colors));
            if (prevBracket) {
               ExtendRangeAndSetColor(input, prevBracket - colors, kColorNone,
                                      DisplayR);
            }
         }
      }
   }

   // locations of brackets
   stack<size_t> locBrackets;
   int foundParenIdx = -1;
   int parenType = 0;
   const std::string& text = input.GetText();

   if (Cursor < input.length()) {
      // check against each bracket type
      for (; parenType < numBrackets; parenType++) {
         // if current char is equal to opening bracket, push onto stack
         if (text[Cursor] == bTypes[parenType][0]) {
            locBrackets.push(Cursor);
            foundParenIdx = 0;
            break;
         } else if (text[Cursor] == bTypes[parenType][1]) {
            locBrackets.push(Cursor);
            foundParenIdx = 1;
            break;
         }
      }
   }

   // current cursor char is not an open bracket, and there is a previous char
   // to check
   if (foundParenIdx == -1 && Cursor > 0) {
      // check previously typed char for being a closing bracket
      --Cursor;
      // check against each bracket type
      parenType = 0;

      for (; parenType < numBrackets; parenType++) {
         // if current char is equal to closing bracket, push onto stack
         if (text[Cursor] == bTypes[parenType][1]) {
            locBrackets.push(Cursor);
            foundParenIdx = 1;
            break;
         }
      }
   }
   // no bracket found on either current or previous char, return.
   if (foundParenIdx == -1) {
      return;
   }

   // terate through remaining letters until find a matching closing bracket
   // if another open bracket of the same type is found, push onto stack
   // and pop on next closing bracket match
   int direction = 1;

   if (foundParenIdx == 1) {
      direction = -1;
   }

   size_t lenLine = input.length();
   // direction == -1: Cursor - 1 to front.
   size_t scanBegin = (Cursor > 0) ? Cursor - 1 : 0;
   size_t scanLast = 0;
   if (direction == 1) {
      // direction == 1: Cursor + 1 to end.
      scanBegin = Cursor + 1;
      scanLast = lenLine - 1;
      if (scanBegin > scanLast) return;
   }
   for (size_t i = scanBegin; true /*avoid "unsigned >= 0" condition*/; i += direction) {
      // if current char is equal to another opening bracket, push onto stack
      if (text[i] == bTypes[parenType][foundParenIdx]) {
         // push index of bracket
         locBrackets.push(i);
      }
      // if current char is equal to closing bracket
      else if (text[i] == bTypes[parenType][1 - foundParenIdx]) {
         // pop previous opening bracket off stack
         locBrackets.pop();
         // if previous opening was the last entry and we are at the cursor, then highlight match
         if (locBrackets.empty()) {
            ExtendRangeAndSetColor(input, i, kColorBracket, DisplayR);
            ExtendRangeAndSetColor(input, Cursor, kColorBracket, DisplayR);
            fPrevBracketColor = kColorBracket;
            break;
         }
      }
      // loop termination check before possible underflow ("--0")
      if (i == scanLast) break;
   }

   if (!locBrackets.empty()) {
      ExtendRangeAndSetColor(input, Cursor, kColorBadBracket, DisplayR);
      fPrevBracketColor = kColorBadBracket;
   }

} // matchParentheses
<commit_msg>Don't use TClass::GetClass() but TInterpreter::CheckClassInfo() with disabled autoloading to see whether a class is known to the interpreter.<commit_after>// @(#)root/editline:$Id$
// Author: Mary-Louise Gill, 2009

/*************************************************************************
 * Copyright (C) 1995-2011, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

#include "Getline_color.h"

#include <stack>
#include <string>

#include "TClass.h"
#include "TClassTable.h"
#include "TInterpreter.h"
#include "TROOT.h"
#include "textinput/Range.h"
#include "textinput/Text.h"

using namespace std;
using namespace textinput;

namespace {

   Color ColorFromName(const char* name) {
      // Convert a color name to a Color.
      Color ret;

      std::string lowname(name);
      size_t lenname = strlen(name);
      for (size_t i = 0; i < lenname; ++i)
         lowname[i] = tolower(lowname[i]);

      if (lowname.find("bold") != std::string::npos
          || lowname.find("light") != std::string::npos)
         ret.fModifiers |= Color::kModBold;
      if (lowname.find("under") != std::string::npos)
         ret.fModifiers |= Color::kModUnderline;

      size_t poshash = lowname.find('#');
      size_t lenrgb = 0;
      if (poshash != std::string::npos) {
         int endrgb = poshash + 1;
         while ((lowname[endrgb] >= '0' && lowname[endrgb] <= '9')
                || (lowname[endrgb] >= 'a' && lowname[endrgb] <= 'f')) {
            ++endrgb;
         }
         lenrgb = endrgb - poshash - 1;
      }

      int rgb[3] = {0};
      if (lenrgb == 3) {
         for (int i = 0; i < 3; ++i) {
            rgb[i] = lowname[poshash + 1 + i] - '0';
            if (rgb[i] > 9) {
               rgb[i] = rgb[i] + '0' - 'a' + 10;
            }
            rgb[i] *= 16; // only upper 4 bits are set.
         }
         return ret;
      } else if (lenrgb == 6) {
         for (int i = 0; i < 6; ++i) {
            int v = lowname[poshash + 1 + i] - '0';
            if (v > 9) {
               v = v + '0' - 'a' + 10;
            }
            if (i % 2 == 0) {
               v *= 16;
            }
            rgb[i / 2] += v;
         }
         ret.fR = rgb[0];
         ret.fG = rgb[1];
         ret.fB = rgb[2];
         return ret;
      } else {
         if (lowname.find("default") != std::string::npos) {
            return ret;
         }

         static const char* colornames[] = {
            "black", "red", "green", "yellow",
            "blue", "magenta", "cyan", "white", 0
         };
         static const unsigned char colorrgb[][3] = {
            {0,0,0}, {127,0,0}, {0,127,0}, {127,127,0},
            {0,0,127}, {127,0,127}, {0,127,127}, {127,127,127},
            {0}
         };

         for (int i = 0; colornames[i]; ++i) {
            if (lowname.find(colornames[i]) != std::string::npos) {
               int boldify = 0;
               if (ret.fModifiers & Color::kModBold)
                  boldify = 64;
               ret.fR = colorrgb[i][0] + boldify;
               ret.fG = colorrgb[i][1] + boldify;
               ret.fB = colorrgb[i][2] + boldify;
               return ret;
            }
         }
      }
      fprintf(stderr, "Getline_color/ColorFromName: cannot parse color %s!\n", name);
      return Color();
   } // ColorFromName()

   bool IsAlnum_(char c) { return c == '_' || isalnum(c); }
   bool IsAlpha_(char c) { return c == '_' || isalpha(c); }
} // unnamed namespace

ROOT::TextInputColorizer::TextInputColorizer():
   fColorIsDefault(), fPrevBracketColor(kColorNone) {
   // Set the default colors.
   // fColors[kColorNone] stays default initialized.
   fColors[kColorType] = ColorFromName("blue");
   fColors[kColorTabComp] = ColorFromName("magenta");
   fColors[kColorBracket] = ColorFromName("green");
   fColors[kColorBadBracket] = ColorFromName("red");
   fColors[kColorPrompt] = ColorFromName("default");
   fColorIsDefault[kColorPrompt] = true;
}

ROOT::TextInputColorizer::~TextInputColorizer() {
   // pin vtable
}

void ROOT::TextInputColorizer::ExtendRangeAndSetColor(Text& input,
                                                      size_t idx, char col,
                                                      Range& disp) {
   // Utility function that updates the display modification range if the
   // color at index idx is different from what it was before.

   if (fColorIsDefault[(int)col]) {
      // Never mind the color: use use default.
      col = 0;
   }
   if (input.GetColor(idx) != col) {
      input.SetColor(idx, col);
      disp.Extend(idx);
   }
}

bool ROOT::TextInputColorizer::GetColor(char type, Color& col) {
   // Set the Color corresponding to an entry in EColorTypes.
   // Returns false if the type index is out of range.

   if (type < (int)kNumColors) {
      col = fColors[(size_t)type];
      return true;
   }
   col = Color();
   return false;
}

void ROOT::TextInputColorizer::SetColors(const char* colorType,
                                         const char* colorTabComp,
                                         const char* colorBracket,
                                         const char* colorBadBracket,
                                         const char* colorPrompt) {
   // Set the colors of the different items as either
   // #RGB
   // #RRGGBB or
   // color name, optionally prepended by "underline" or "bold"

   fColors[kColorType] = ColorFromName(colorType);
   fColorIsDefault[kColorType] = (fColors[kColorType] == Color());
   fColors[kColorTabComp] = ColorFromName(colorTabComp);
   fColorIsDefault[kColorTabComp] = (fColors[kColorTabComp] == Color());
   fColors[kColorBracket] = ColorFromName(colorBracket);
   fColorIsDefault[kColorBracket] = (fColors[kColorBracket] == Color());
   fColors[kColorBadBracket] = ColorFromName(colorBadBracket);
   fColorIsDefault[kColorBadBracket] = (fColors[kColorBadBracket] == Color());
   fColors[kColorPrompt] = ColorFromName(colorPrompt);
   fColorIsDefault[kColorPrompt] = (fColors[kColorPrompt] == Color());
}

void ROOT::TextInputColorizer::ProcessTextChange(EditorRange& Modification,
                                                 Text& input) {
   // The text has changed; look for word that are types.

   const std::string& text = input.GetText();

   size_t modStart = Modification.fEdit.fStart;
   size_t inputLength = input.length();

   // Find end of modified word:
   size_t modEnd = Modification.fEdit.fLength;
   if (modEnd == (size_t) -1) {
      modEnd = inputLength;
   } else {
      modEnd += modStart;
      if (modEnd > inputLength) {
         modEnd = inputLength;
      } else {
         while (modEnd < inputLength && IsAlnum_(text[modEnd]))
            ++modEnd;
      }
   }

   // Find beginning of modified word. Don't treat
   // "12ull" specially, it will fall out below.
   while (modStart && IsAlnum_(text[modStart])) --modStart;

   // Ignore spaces
   while (modStart < modEnd && isspace(text[modStart]))
      ++modStart;
   while (modEnd > modStart && isspace(text[modEnd]))
      --modStart;

   for (size_t i = modStart; i < modEnd;) {
      // i points to beginning of word here.
      if (isdigit(text[i])) {
         // "12", or "12ull". Default color.
         ExtendRangeAndSetColor(input, i, 0, Modification.fDisplay);
         ++i;
         while (i < modEnd && IsAlnum_(text[i])) {
            ExtendRangeAndSetColor(input, i, 0, Modification.fDisplay);
            ++i;
         }
      } else if (IsAlpha_(text[i])) {
         // identifier, but is it a type?
         size_t wordLen = 1;
         while (i + wordLen < modEnd && IsAlnum_(text[i + wordLen])) {
            ++wordLen;
         }
         std::string word = text.substr(i, wordLen);
         char color = kColorNone;
         if (gROOT->GetListOfTypes()->FindObject(word.c_str())
             || gClassTable->GetDict(word.c_str())
             || gInterpreter->GetClassSharedLibs(word.c_str())
             || gInterpreter->CheckClassInfo(word.c_str(), false /*autoload*/)) {
            color = kColorType;
         }
         for (size_t ic = i; ic < i + wordLen; ++ic) {
            ExtendRangeAndSetColor(input, ic, color, Modification.fDisplay);
         }
         i += wordLen;
      } else {
         size_t wordLen = 1;
         while (i + wordLen < modEnd && !IsAlnum_(text[i + wordLen]))
            ++wordLen;
         for (size_t ic = i; ic < i + wordLen; ++ic) {
            // protect colored parens
            char oldColor = input.GetColor(ic);
            if (oldColor != kColorBracket && oldColor != kColorBadBracket) {
               ExtendRangeAndSetColor(input, ic, kColorNone, Modification.fDisplay);
            }
         }
         i += wordLen;
      }

      // skip trailing whitespace.
      while (i < modEnd && isspace(text[i])) {
         ExtendRangeAndSetColor(input, i, kColorNone, Modification.fDisplay);
         ++i;
      }
   }
}

void ROOT::TextInputColorizer::ProcessPromptChange(Text& prompt) {
   int idx = kColorPrompt;
   if (fColorIsDefault[kColorPrompt]) {
      idx = 0;
   }
   prompt.SetColor(Range::AllText(), idx);
}

void ROOT::TextInputColorizer::ProcessCursorChange(size_t Cursor,
                                                   Text& input,
                                                   Range& DisplayR) {
   // Check each char to see if it is an opening bracket,
   // if so, check for its closing one and color them green.

   static const int numBrackets = 3;
   static const char bTypes[numBrackets][3] = {"()", "{}", "[]"};

   if (input.empty()) return;

   if (fPrevBracketColor != kColorNone) {
      // Remove previous bracket coloring.
      const char* colors = &input.GetColors()[0];
      const char* prevBracket = (const char*) memchr(colors, fPrevBracketColor,
                                                     input.length());
      if (prevBracket) {
         ExtendRangeAndSetColor(input, prevBracket - colors, kColorNone, DisplayR);
         if (fPrevBracketColor == kColorBracket) {
            // There will be two.
            prevBracket = (const char*) memchr(prevBracket, fPrevBracketColor,
                                               input.length() - (prevBracket - colors));
            if (prevBracket) {
               ExtendRangeAndSetColor(input, prevBracket - colors, kColorNone,
                                      DisplayR);
            }
         }
      }
   }

   // locations of brackets
   stack<size_t> locBrackets;
   int foundParenIdx = -1;
   int parenType = 0;
   const std::string& text = input.GetText();

   if (Cursor < input.length()) {
      // check against each bracket type
      for (; parenType < numBrackets; parenType++) {
         // if current char is equal to opening bracket, push onto stack
         if (text[Cursor] == bTypes[parenType][0]) {
            locBrackets.push(Cursor);
            foundParenIdx = 0;
            break;
         } else if (text[Cursor] == bTypes[parenType][1]) {
            locBrackets.push(Cursor);
            foundParenIdx = 1;
            break;
         }
      }
   }

   // current cursor char is not an open bracket, and there is a previous char
   // to check
   if (foundParenIdx == -1 && Cursor > 0) {
      // check previously typed char for being a closing bracket
      --Cursor;
      // check against each bracket type
      parenType = 0;

      for (; parenType < numBrackets; parenType++) {
         // if current char is equal to closing bracket, push onto stack
         if (text[Cursor] == bTypes[parenType][1]) {
            locBrackets.push(Cursor);
            foundParenIdx = 1;
            break;
         }
      }
   }
   // no bracket found on either current or previous char, return.
   if (foundParenIdx == -1) {
      return;
   }

   // terate through remaining letters until find a matching closing bracket
   // if another open bracket of the same type is found, push onto stack
   // and pop on next closing bracket match
   int direction = 1;

   if (foundParenIdx == 1) {
      direction = -1;
   }

   size_t lenLine = input.length();
   // direction == -1: Cursor - 1 to front.
   size_t scanBegin = (Cursor > 0) ? Cursor - 1 : 0;
   size_t scanLast = 0;
   if (direction == 1) {
      // direction == 1: Cursor + 1 to end.
      scanBegin = Cursor + 1;
      scanLast = lenLine - 1;
      if (scanBegin > scanLast) return;
   }
   for (size_t i = scanBegin; true /*avoid "unsigned >= 0" condition*/; i += direction) {
      // if current char is equal to another opening bracket, push onto stack
      if (text[i] == bTypes[parenType][foundParenIdx]) {
         // push index of bracket
         locBrackets.push(i);
      }
      // if current char is equal to closing bracket
      else if (text[i] == bTypes[parenType][1 - foundParenIdx]) {
         // pop previous opening bracket off stack
         locBrackets.pop();
         // if previous opening was the last entry and we are at the cursor, then highlight match
         if (locBrackets.empty()) {
            ExtendRangeAndSetColor(input, i, kColorBracket, DisplayR);
            ExtendRangeAndSetColor(input, Cursor, kColorBracket, DisplayR);
            fPrevBracketColor = kColorBracket;
            break;
         }
      }
      // loop termination check before possible underflow ("--0")
      if (i == scanLast) break;
   }

   if (!locBrackets.empty()) {
      ExtendRangeAndSetColor(input, Cursor, kColorBadBracket, DisplayR);
      fPrevBracketColor = kColorBadBracket;
   }

} // matchParentheses
<|endoftext|>


<commit_before>// @(#)root/editline:$Id$
// Author: Mary-Louise Gill, 2009

/*************************************************************************
 * Copyright (C) 1995-2011, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

#include "Getline_color.h"

#include <stack>
#include <string>

#include "TROOT.h"
#include "TInterpreter.h"
#include "textinput/Range.h"
#include "textinput/Text.h"

using namespace std;
using namespace textinput;

namespace {

   Color ColorFromName(const char* name) {
      // Convert a color name to a Color.
      Color ret;

      std::string lowname(name);
      size_t lenname = strlen(name);
      for (size_t i = 0; i < lenname; ++i)
         lowname[i] = tolower(lowname[i]);

      if (lowname.find("bold") != std::string::npos
          || lowname.find("light") != std::string::npos)
         ret.fModifiers |= Color::kModBold;
      if (lowname.find("under") != std::string::npos)
         ret.fModifiers |= Color::kModUnderline;

      size_t poshash = lowname.find('#');
      size_t lenrgb = 0;
      if (poshash != std::string::npos) {
         int endrgb = poshash + 1;
         while ((lowname[endrgb] >= '0' && lowname[endrgb] <= '9')
                || (lowname[endrgb] >= 'a' && lowname[endrgb] <= 'f')) {
            ++endrgb;
         }
         lenrgb = endrgb - poshash - 1;
      }

      int rgb[3] = {0};
      if (lenrgb == 3) {
         for (int i = 0; i < 3; ++i) {
            rgb[i] = lowname[poshash + 1 + i] - '0';
            if (rgb[i] > 9) {
               rgb[i] = rgb[i] + '0' - 'a' + 10;
            }
            rgb[i] *= 16; // only upper 4 bits are set.
         }
         return ret;
      } else if (lenrgb == 6) {
         for (int i = 0; i < 6; ++i) {
            int v = lowname[poshash + 1 + i] - '0';
            if (v > 9) {
               v = v + '0' - 'a' + 10;
            }
            if (i % 2 == 0) {
               v *= 16;
            }
            rgb[i / 2] += v;
         }
         ret.fR = rgb[0];
         ret.fG = rgb[1];
         ret.fB = rgb[2];
         return ret;
      } else {
         if (lowname.find("default") != std::string::npos) {
            return ret;
         }

         static const char* colornames[] = {
            "black", "red", "green", "yellow",
            "blue", "magenta", "cyan", "white", 0
         };
         static const unsigned char colorrgb[][3] = {
            {0,0,0}, {127,0,0}, {0,127,0}, {127,127,0},
            {0,0,127}, {127,0,127}, {0,127,127}, {127,127,127},
            {0}
         };

         for (int i = 0; colornames[i]; ++i) {
            if (lowname.find(colornames[i]) != std::string::npos) {
               int boldify = 0;
               if (ret.fModifiers & Color::kModBold)
                  boldify = 64;
               ret.fR = colorrgb[i][0] + boldify;
               ret.fG = colorrgb[i][1] + boldify;
               ret.fB = colorrgb[i][2] + boldify;
               return ret;
            }
         }
      }
      fprintf(stderr, "Getline_color/ColorFromName: cannot parse color %s!\n", name);
      return Color();
   } // ColorFromName()

   bool IsAlnum_(char c) { return c == '_' || isalnum(c); }
   bool IsAlpha_(char c) { return c == '_' || isalpha(c); }

   void ExtendRangeAndSetColor(Text& input, size_t idx, char col, Range& disp) {
      // Utility function that updates the display modification range if the
      // color at index idx is different from what it was before.

      if (input.GetColor(idx) != col) {
         input.SetColor(idx, col);
         disp.Extend(idx);
      }
   }
} // unnamed namespace

ROOT::TextInputColorizer::TextInputColorizer():
   fPrevBracketColor(kColorNone) {
   // Set the default colors.
   // fColors[kColorNone] stays default initialized.
   fColors[kColorType] = ColorFromName("blue");
   fColors[kColorTabComp] = ColorFromName("magenta");
   fColors[kColorBracket] = ColorFromName("green");
   fColors[kColorBadBracket] = ColorFromName("red");
   fColors[kColorPrompt] = ColorFromName("cyan");
}

ROOT::TextInputColorizer::~TextInputColorizer() {
   // pin vtable
}

bool ROOT::TextInputColorizer::GetColor(char type, Color& col) {
   // Set the Color corresponding to an entry in EColorTypes.
   // Returns false if the type index is out of range.

   if (type < (int)kNumColors) {
      col = fColors[(size_t)type];
      return true;
   }
   col = Color();
   return false;
}

void ROOT::TextInputColorizer::SetColors(const char* colorType,
                                         const char* colorTabComp,
                                         const char* colorBracket,
                                         const char* colorBadBracket,
                                         const char* colorPrompt) {
   // Set the colors of the different items as either
   // #RGB
   // #RRGGBB or
   // color name, optionally prepended by "underline" or "bold"

   fColors[kColorType] = ColorFromName(colorType);
   fColors[kColorTabComp] = ColorFromName(colorTabComp);
   fColors[kColorBracket] = ColorFromName(colorBracket);
   fColors[kColorBadBracket] = ColorFromName(colorBadBracket);
   fColors[kColorPrompt] = ColorFromName(colorPrompt);
}

void ROOT::TextInputColorizer::ProcessTextChange(EditorRange& Modification,
                                                 Text& input) {
   // The text has changed; look for word that are types.

   const std::string& text = input.GetText();

   size_t modStart = Modification.fEdit.fStart;
   size_t inputLength = input.length();

   // Find end of modified word:
   size_t modEnd = Modification.fEdit.fLength;
   if (modEnd == (size_t) -1) {
      modEnd = inputLength;
   } else {
      modEnd += modStart;
      if (modEnd > inputLength) {
         modEnd = inputLength;
      } else {
         while (modEnd < inputLength && IsAlnum_(text[modEnd]))
            ++modEnd;
      }
   }

   // Find beginning of modified word. Don't treat
   // "12ull" specially, it will fall out below.
   while (modStart && IsAlnum_(text[modStart])) --modStart;

   // Ignore spaces
   while (modStart < modEnd && isspace(text[modStart]))
      ++modStart;
   while (modEnd > modStart && isspace(text[modEnd]))
      --modStart;

   for (size_t i = modStart; i < modEnd;) {
      // i points to beginning of word here.
      if (isdigit(text[i])) {
         // "12", or "12ull". Default color.
         ExtendRangeAndSetColor(input, i, 0, Modification.fDisplay);
         ++i;
         while (i < modEnd && IsAlnum_(text[i])) {
            ExtendRangeAndSetColor(input, i, 0, Modification.fDisplay);
            ++i;
         }
      } else if (IsAlpha_(text[i])) {
         // identifier, but is it a type?
         size_t wordLen = 1;
         while (i + wordLen < modEnd && IsAlnum_(text[i + wordLen])) {
            ++wordLen;
         }
         std::string word = text.substr(i, wordLen);
         char color = kColorNone;
         if (gROOT->GetListOfTypes()->FindObject(word.c_str())
             || gInterpreter->CheckClassInfo(word.c_str(), kFALSE)) {
            color = kColorType;
         }
         for (size_t ic = i; ic < i + wordLen; ++ic) {
            ExtendRangeAndSetColor(input, ic, color, Modification.fDisplay);
         }
         i += wordLen;
      } else {
         size_t wordLen = 1;
         while (i + wordLen < modEnd && !IsAlnum_(text[i + wordLen]))
            ++wordLen;
         for (size_t ic = i; ic < i + wordLen; ++ic) {
            // protect colored parens
            char oldColor = input.GetColor(ic);
            if (oldColor != kColorBracket && oldColor != kColorBadBracket) {
               ExtendRangeAndSetColor(input, ic, kColorNone, Modification.fDisplay);
            }
         }
         i += wordLen;
      }

      // skip trailing whitespace.
      while (i < modEnd && isspace(text[i])) {
         ExtendRangeAndSetColor(input, i, kColorNone, Modification.fDisplay);
         ++i;
      }
   }
}

void ROOT::TextInputColorizer::ProcessPromptChange(Text& prompt) {
   prompt.SetColor(Range::AllText(), kColorPrompt);
}

void ROOT::TextInputColorizer::ProcessCursorChange(size_t Cursor,
                                                   Text& input,
                                                   Range& DisplayR) {
   // Check each char to see if it is an opening bracket,
   // if so, check for its closing one and color them green.

   static const int numBrackets = 3;
   static const char bTypes[numBrackets][3] = {"()", "{}", "[]"};

   if (input.empty()) return;

   if (fPrevBracketColor != kColorNone) {
      // Remove previous bracket coloring.
      const char* colors = &input.GetColors()[0];
      const char* prevBracket = (const char*) memchr(colors, fPrevBracketColor,
                                                     input.length());
      if (prevBracket) {
         ExtendRangeAndSetColor(input, prevBracket - colors, kColorNone, DisplayR);
         if (fPrevBracketColor == kColorBracket) {
            // There will be two.
            prevBracket = (const char*) memchr(prevBracket, fPrevBracketColor,
                                               input.length() - (prevBracket - colors));
            if (prevBracket) {
               ExtendRangeAndSetColor(input, prevBracket - colors, kColorNone,
                                      DisplayR);
            }
         }
      }
   }

   // locations of brackets
   stack<size_t> locBrackets;
   int foundParenIdx = -1;
   int parenType = 0;
   const std::string& text = input.GetText();

   if (Cursor < input.length()) {
      // check against each bracket type
      for (; parenType < numBrackets; parenType++) {
         // if current char is equal to opening bracket, push onto stack
         if (text[Cursor] == bTypes[parenType][0]) {
            locBrackets.push(Cursor);
            foundParenIdx = 0;
            break;
         } else if (text[Cursor] == bTypes[parenType][1]) {
            locBrackets.push(Cursor);
            foundParenIdx = 1;
            break;
         }
      }
   }

   // current cursor char is not an open bracket, and there is a previous char
   // to check
   if (foundParenIdx == -1 && Cursor > 0) {
      // check previously typed char for being a closing bracket
      --Cursor;
      // check against each bracket type
      parenType = 0;

      for (; parenType < numBrackets; parenType++) {
         // if current char is equal to closing bracket, push onto stack
         if (text[Cursor] == bTypes[parenType][1]) {
            locBrackets.push(Cursor);
            foundParenIdx = 1;
            break;
         }
      }

      // no bracket found on either current or previous char, return.
      if (foundParenIdx == -1) {
         return;
      }
   }

   // terate through remaining letters until find a matching closing bracket
   // if another open bracket of the same type is found, push onto stack
   // and pop on next closing bracket match
   int direction = 1;

   if (foundParenIdx == 1) {
      direction = -1;
   }

   size_t lenLine = input.length();
   // direction == -1: Cursor - 1 to front.
   size_t scanBegin = Cursor - 1;
   size_t scanLast = 0;
   if (direction == 1) {
      // direction == 1: Cursor + 1 to end.
      scanBegin = Cursor + 1;
      scanLast = lenLine - 1;
   }
   for (size_t i = scanBegin; true /*avoid "unsigned >= 0" condition*/; i += direction) {
      // if current char is equal to another opening bracket, push onto stack
      if (text[i] == bTypes[parenType][foundParenIdx]) {
         // push index of bracket
         locBrackets.push(i);
      }
      // if current char is equal to closing bracket
      else if (text[i] == bTypes[parenType][1 - foundParenIdx]) {
         // pop previous opening bracket off stack
         locBrackets.pop();
         // if previous opening was the last entry and we are at the cursor, then highlight match
         if (locBrackets.empty()) {
            ExtendRangeAndSetColor(input, i, kColorBracket, DisplayR);
            ExtendRangeAndSetColor(input, Cursor, kColorBracket, DisplayR);
            fPrevBracketColor = kColorBracket;
            break;
         }
      }
      // loop termination check before possible underflow ("--0")
      if (i == scanLast) break;
   }

   if (!locBrackets.empty()) {
      ExtendRangeAndSetColor(input, Cursor, kColorBadBracket, DisplayR);
      fPrevBracketColor = kColorBadBracket;
   }

} // matchParentheses
<commit_msg>Default prompt has default color.<commit_after>// @(#)root/editline:$Id$
// Author: Mary-Louise Gill, 2009

/*************************************************************************
 * Copyright (C) 1995-2011, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

#include "Getline_color.h"

#include <stack>
#include <string>

#include "TROOT.h"
#include "TInterpreter.h"
#include "textinput/Range.h"
#include "textinput/Text.h"

using namespace std;
using namespace textinput;

namespace {

   Color ColorFromName(const char* name) {
      // Convert a color name to a Color.
      Color ret;

      std::string lowname(name);
      size_t lenname = strlen(name);
      for (size_t i = 0; i < lenname; ++i)
         lowname[i] = tolower(lowname[i]);

      if (lowname.find("bold") != std::string::npos
          || lowname.find("light") != std::string::npos)
         ret.fModifiers |= Color::kModBold;
      if (lowname.find("under") != std::string::npos)
         ret.fModifiers |= Color::kModUnderline;

      size_t poshash = lowname.find('#');
      size_t lenrgb = 0;
      if (poshash != std::string::npos) {
         int endrgb = poshash + 1;
         while ((lowname[endrgb] >= '0' && lowname[endrgb] <= '9')
                || (lowname[endrgb] >= 'a' && lowname[endrgb] <= 'f')) {
            ++endrgb;
         }
         lenrgb = endrgb - poshash - 1;
      }

      int rgb[3] = {0};
      if (lenrgb == 3) {
         for (int i = 0; i < 3; ++i) {
            rgb[i] = lowname[poshash + 1 + i] - '0';
            if (rgb[i] > 9) {
               rgb[i] = rgb[i] + '0' - 'a' + 10;
            }
            rgb[i] *= 16; // only upper 4 bits are set.
         }
         return ret;
      } else if (lenrgb == 6) {
         for (int i = 0; i < 6; ++i) {
            int v = lowname[poshash + 1 + i] - '0';
            if (v > 9) {
               v = v + '0' - 'a' + 10;
            }
            if (i % 2 == 0) {
               v *= 16;
            }
            rgb[i / 2] += v;
         }
         ret.fR = rgb[0];
         ret.fG = rgb[1];
         ret.fB = rgb[2];
         return ret;
      } else {
         if (lowname.find("default") != std::string::npos) {
            return ret;
         }

         static const char* colornames[] = {
            "black", "red", "green", "yellow",
            "blue", "magenta", "cyan", "white", 0
         };
         static const unsigned char colorrgb[][3] = {
            {0,0,0}, {127,0,0}, {0,127,0}, {127,127,0},
            {0,0,127}, {127,0,127}, {0,127,127}, {127,127,127},
            {0}
         };

         for (int i = 0; colornames[i]; ++i) {
            if (lowname.find(colornames[i]) != std::string::npos) {
               int boldify = 0;
               if (ret.fModifiers & Color::kModBold)
                  boldify = 64;
               ret.fR = colorrgb[i][0] + boldify;
               ret.fG = colorrgb[i][1] + boldify;
               ret.fB = colorrgb[i][2] + boldify;
               return ret;
            }
         }
      }
      fprintf(stderr, "Getline_color/ColorFromName: cannot parse color %s!\n", name);
      return Color();
   } // ColorFromName()

   bool IsAlnum_(char c) { return c == '_' || isalnum(c); }
   bool IsAlpha_(char c) { return c == '_' || isalpha(c); }

   void ExtendRangeAndSetColor(Text& input, size_t idx, char col, Range& disp) {
      // Utility function that updates the display modification range if the
      // color at index idx is different from what it was before.

      if (input.GetColor(idx) != col) {
         input.SetColor(idx, col);
         disp.Extend(idx);
      }
   }
} // unnamed namespace

ROOT::TextInputColorizer::TextInputColorizer():
   fPrevBracketColor(kColorNone) {
   // Set the default colors.
   // fColors[kColorNone] stays default initialized.
   fColors[kColorType] = ColorFromName("blue");
   fColors[kColorTabComp] = ColorFromName("magenta");
   fColors[kColorBracket] = ColorFromName("green");
   fColors[kColorBadBracket] = ColorFromName("red");
   fColors[kColorPrompt] = ColorFromName("default");
}

ROOT::TextInputColorizer::~TextInputColorizer() {
   // pin vtable
}

bool ROOT::TextInputColorizer::GetColor(char type, Color& col) {
   // Set the Color corresponding to an entry in EColorTypes.
   // Returns false if the type index is out of range.

   if (type < (int)kNumColors) {
      col = fColors[(size_t)type];
      return true;
   }
   col = Color();
   return false;
}

void ROOT::TextInputColorizer::SetColors(const char* colorType,
                                         const char* colorTabComp,
                                         const char* colorBracket,
                                         const char* colorBadBracket,
                                         const char* colorPrompt) {
   // Set the colors of the different items as either
   // #RGB
   // #RRGGBB or
   // color name, optionally prepended by "underline" or "bold"

   fColors[kColorType] = ColorFromName(colorType);
   fColors[kColorTabComp] = ColorFromName(colorTabComp);
   fColors[kColorBracket] = ColorFromName(colorBracket);
   fColors[kColorBadBracket] = ColorFromName(colorBadBracket);
   fColors[kColorPrompt] = ColorFromName(colorPrompt);
}

void ROOT::TextInputColorizer::ProcessTextChange(EditorRange& Modification,
                                                 Text& input) {
   // The text has changed; look for word that are types.

   const std::string& text = input.GetText();

   size_t modStart = Modification.fEdit.fStart;
   size_t inputLength = input.length();

   // Find end of modified word:
   size_t modEnd = Modification.fEdit.fLength;
   if (modEnd == (size_t) -1) {
      modEnd = inputLength;
   } else {
      modEnd += modStart;
      if (modEnd > inputLength) {
         modEnd = inputLength;
      } else {
         while (modEnd < inputLength && IsAlnum_(text[modEnd]))
            ++modEnd;
      }
   }

   // Find beginning of modified word. Don't treat
   // "12ull" specially, it will fall out below.
   while (modStart && IsAlnum_(text[modStart])) --modStart;

   // Ignore spaces
   while (modStart < modEnd && isspace(text[modStart]))
      ++modStart;
   while (modEnd > modStart && isspace(text[modEnd]))
      --modStart;

   for (size_t i = modStart; i < modEnd;) {
      // i points to beginning of word here.
      if (isdigit(text[i])) {
         // "12", or "12ull". Default color.
         ExtendRangeAndSetColor(input, i, 0, Modification.fDisplay);
         ++i;
         while (i < modEnd && IsAlnum_(text[i])) {
            ExtendRangeAndSetColor(input, i, 0, Modification.fDisplay);
            ++i;
         }
      } else if (IsAlpha_(text[i])) {
         // identifier, but is it a type?
         size_t wordLen = 1;
         while (i + wordLen < modEnd && IsAlnum_(text[i + wordLen])) {
            ++wordLen;
         }
         std::string word = text.substr(i, wordLen);
         char color = kColorNone;
         if (gROOT->GetListOfTypes()->FindObject(word.c_str())
             || gInterpreter->CheckClassInfo(word.c_str(), kFALSE)) {
            color = kColorType;
         }
         for (size_t ic = i; ic < i + wordLen; ++ic) {
            ExtendRangeAndSetColor(input, ic, color, Modification.fDisplay);
         }
         i += wordLen;
      } else {
         size_t wordLen = 1;
         while (i + wordLen < modEnd && !IsAlnum_(text[i + wordLen]))
            ++wordLen;
         for (size_t ic = i; ic < i + wordLen; ++ic) {
            // protect colored parens
            char oldColor = input.GetColor(ic);
            if (oldColor != kColorBracket && oldColor != kColorBadBracket) {
               ExtendRangeAndSetColor(input, ic, kColorNone, Modification.fDisplay);
            }
         }
         i += wordLen;
      }

      // skip trailing whitespace.
      while (i < modEnd && isspace(text[i])) {
         ExtendRangeAndSetColor(input, i, kColorNone, Modification.fDisplay);
         ++i;
      }
   }
}

void ROOT::TextInputColorizer::ProcessPromptChange(Text& prompt) {
   prompt.SetColor(Range::AllText(), kColorPrompt);
}

void ROOT::TextInputColorizer::ProcessCursorChange(size_t Cursor,
                                                   Text& input,
                                                   Range& DisplayR) {
   // Check each char to see if it is an opening bracket,
   // if so, check for its closing one and color them green.

   static const int numBrackets = 3;
   static const char bTypes[numBrackets][3] = {"()", "{}", "[]"};

   if (input.empty()) return;

   if (fPrevBracketColor != kColorNone) {
      // Remove previous bracket coloring.
      const char* colors = &input.GetColors()[0];
      const char* prevBracket = (const char*) memchr(colors, fPrevBracketColor,
                                                     input.length());
      if (prevBracket) {
         ExtendRangeAndSetColor(input, prevBracket - colors, kColorNone, DisplayR);
         if (fPrevBracketColor == kColorBracket) {
            // There will be two.
            prevBracket = (const char*) memchr(prevBracket, fPrevBracketColor,
                                               input.length() - (prevBracket - colors));
            if (prevBracket) {
               ExtendRangeAndSetColor(input, prevBracket - colors, kColorNone,
                                      DisplayR);
            }
         }
      }
   }

   // locations of brackets
   stack<size_t> locBrackets;
   int foundParenIdx = -1;
   int parenType = 0;
   const std::string& text = input.GetText();

   if (Cursor < input.length()) {
      // check against each bracket type
      for (; parenType < numBrackets; parenType++) {
         // if current char is equal to opening bracket, push onto stack
         if (text[Cursor] == bTypes[parenType][0]) {
            locBrackets.push(Cursor);
            foundParenIdx = 0;
            break;
         } else if (text[Cursor] == bTypes[parenType][1]) {
            locBrackets.push(Cursor);
            foundParenIdx = 1;
            break;
         }
      }
   }

   // current cursor char is not an open bracket, and there is a previous char
   // to check
   if (foundParenIdx == -1 && Cursor > 0) {
      // check previously typed char for being a closing bracket
      --Cursor;
      // check against each bracket type
      parenType = 0;

      for (; parenType < numBrackets; parenType++) {
         // if current char is equal to closing bracket, push onto stack
         if (text[Cursor] == bTypes[parenType][1]) {
            locBrackets.push(Cursor);
            foundParenIdx = 1;
            break;
         }
      }

      // no bracket found on either current or previous char, return.
      if (foundParenIdx == -1) {
         return;
      }
   }

   // terate through remaining letters until find a matching closing bracket
   // if another open bracket of the same type is found, push onto stack
   // and pop on next closing bracket match
   int direction = 1;

   if (foundParenIdx == 1) {
      direction = -1;
   }

   size_t lenLine = input.length();
   // direction == -1: Cursor - 1 to front.
   size_t scanBegin = Cursor - 1;
   size_t scanLast = 0;
   if (direction == 1) {
      // direction == 1: Cursor + 1 to end.
      scanBegin = Cursor + 1;
      scanLast = lenLine - 1;
   }
   for (size_t i = scanBegin; true /*avoid "unsigned >= 0" condition*/; i += direction) {
      // if current char is equal to another opening bracket, push onto stack
      if (text[i] == bTypes[parenType][foundParenIdx]) {
         // push index of bracket
         locBrackets.push(i);
      }
      // if current char is equal to closing bracket
      else if (text[i] == bTypes[parenType][1 - foundParenIdx]) {
         // pop previous opening bracket off stack
         locBrackets.pop();
         // if previous opening was the last entry and we are at the cursor, then highlight match
         if (locBrackets.empty()) {
            ExtendRangeAndSetColor(input, i, kColorBracket, DisplayR);
            ExtendRangeAndSetColor(input, Cursor, kColorBracket, DisplayR);
            fPrevBracketColor = kColorBracket;
            break;
         }
      }
      // loop termination check before possible underflow ("--0")
      if (i == scanLast) break;
   }

   if (!locBrackets.empty()) {
      ExtendRangeAndSetColor(input, Cursor, kColorBadBracket, DisplayR);
      fPrevBracketColor = kColorBadBracket;
   }

} // matchParentheses
<|endoftext|>


<commit_before>#include "dreal/solver/icp_seq.h"

#include <tuple>
#include <utility>

#include "dreal/solver/branch.h"
#include "dreal/solver/icp_stat.h"
#include "dreal/util/interrupt.h"
#include "dreal/util/logging.h"

using std::pair;
using std::tie;
using std::vector;

namespace dreal {

IcpSeq::IcpSeq(const Config& config) : Icp{config} {}

bool IcpSeq::CheckSat(const Contractor& contractor,
                      const vector<FormulaEvaluator>& formula_evaluators,
                      ContractorStatus* const cs) {
  // Use the stacking policy set by the configuration.
  stack_left_box_first_ = config().stack_left_box_first();
  static IcpStat stat{DREAL_LOG_INFO_ENABLED};
  DREAL_LOG_DEBUG("IcpSeq::CheckSat()");
  // Stack of Box x BranchingPoint.
  vector<pair<Box, int>> stack;
  stack.emplace_back(
      cs->box(),
      // -1 indicates that the very first box does not come from a branching.
      -1);

  // `current_box` always points to the box in the contractor status
  // as a mutable reference.
  Box& current_box{cs->mutable_box()};
  // `current_branching_point` always points to the branching_point in
  // the contractor status as a mutable reference.
  int& current_branching_point{cs->mutable_branching_point()};

  TimerGuard prune_timer_guard(&stat.timer_prune_, stat.enabled(),
                               false /* start_timer */);
  TimerGuard eval_timer_guard(&stat.timer_eval_, stat.enabled(),
                              false /* start_timer */);
  TimerGuard branch_timer_guard(&stat.timer_branch_, stat.enabled(),
                                false /* start_timer */);

  while (!stack.empty()) {
    DREAL_LOG_DEBUG("IcpSeq::CheckSat() Loop Head");

    // Note that 'DREAL_CHECK_INTERRUPT' is only defined in setup.py,
    // when we build dReal python package.
#ifdef DREAL_CHECK_INTERRUPT
    if (g_interrupted) {
      DREAL_LOG_DEBUG("KeyboardInterrupt(SIGINT) Detected.");
      throw std::runtime_error("KeyboardInterrupt(SIGINT) Detected.");
    }
#endif

    // 1. Pop the current box from the stack
    tie(current_box, current_branching_point) = stack.back();
    stack.pop_back();

    // 2. Prune the current box.
    DREAL_LOG_TRACE("IcpSeq::CheckSat() Current Box:\n{}", current_box);
    prune_timer_guard.resume();
    contractor.Prune(cs);
    prune_timer_guard.pause();
    stat.num_prune_++;
    DREAL_LOG_TRACE("IcpSeq::CheckSat() After pruning, the current box =\n{}",
                    current_box);

    if (current_box.empty()) {
      // 3.1. The box is empty after pruning.
      DREAL_LOG_DEBUG("IcpSeq::CheckSat() Box is empty after pruning");
      continue;
    }
    // 3.2. The box is non-empty. Check if the box is still feasible
    // under evaluation and it's small enough.
    eval_timer_guard.resume();
    const optional<ibex::BitSet> evaluation_result{
        EvaluateBox(formula_evaluators, current_box, config().precision(), cs)};
    if (!evaluation_result) {
      // 3.2.1. We detect that the current box is not a feasible solution.
      DREAL_LOG_DEBUG(
          "IcpSeq::CheckSat() Detect that the current box is not feasible by "
          "evaluation:\n{}",
          current_box);
      continue;
    }
    if (evaluation_result->empty()) {
      // 3.2.2. delta-SAT : We find a box which is smaller enough.
      DREAL_LOG_DEBUG("IcpSeq::CheckSat() Found a delta-box:\n{}", current_box);
      return true;
    }
    eval_timer_guard.pause();

    // 3.2.3. This box is bigger than delta. Need branching.
    branch_timer_guard.resume();
    if (!Branch(current_box, *evaluation_result, stack_left_box_first_,
                &stack)) {
      DREAL_LOG_DEBUG(
          "IcpSeq::CheckSat() Found that the current box is not satisfying "
          "delta-condition but it's not bisectable.:\n{}",
          current_box);
      return true;
    }
    branch_timer_guard.pause();

    // We alternate between adding-the-left-box-first policy and
    // adding-the-right-box-first policy.
    stack_left_box_first_ = !stack_left_box_first_;
    stat.num_branch_++;
  }
  DREAL_LOG_DEBUG("IcpSeq::CheckSat() No solution");
  return false;
}
}  // namespace dreal
<commit_msg>fix(solver/icp_seq.cc): Fix eval timer<commit_after>#include "dreal/solver/icp_seq.h"

#include <tuple>
#include <utility>

#include "dreal/solver/branch.h"
#include "dreal/solver/icp_stat.h"
#include "dreal/util/interrupt.h"
#include "dreal/util/logging.h"

using std::pair;
using std::tie;
using std::vector;

namespace dreal {

IcpSeq::IcpSeq(const Config& config) : Icp{config} {}

bool IcpSeq::CheckSat(const Contractor& contractor,
                      const vector<FormulaEvaluator>& formula_evaluators,
                      ContractorStatus* const cs) {
  // Use the stacking policy set by the configuration.
  stack_left_box_first_ = config().stack_left_box_first();
  static IcpStat stat{DREAL_LOG_INFO_ENABLED};
  DREAL_LOG_DEBUG("IcpSeq::CheckSat()");
  // Stack of Box x BranchingPoint.
  vector<pair<Box, int>> stack;
  stack.emplace_back(
      cs->box(),
      // -1 indicates that the very first box does not come from a branching.
      -1);

  // `current_box` always points to the box in the contractor status
  // as a mutable reference.
  Box& current_box{cs->mutable_box()};
  // `current_branching_point` always points to the branching_point in
  // the contractor status as a mutable reference.
  int& current_branching_point{cs->mutable_branching_point()};

  TimerGuard prune_timer_guard(&stat.timer_prune_, stat.enabled(),
                               false /* start_timer */);
  TimerGuard eval_timer_guard(&stat.timer_eval_, stat.enabled(),
                              false /* start_timer */);
  TimerGuard branch_timer_guard(&stat.timer_branch_, stat.enabled(),
                                false /* start_timer */);

  while (!stack.empty()) {
    DREAL_LOG_DEBUG("IcpSeq::CheckSat() Loop Head");

    // Note that 'DREAL_CHECK_INTERRUPT' is only defined in setup.py,
    // when we build dReal python package.
#ifdef DREAL_CHECK_INTERRUPT
    if (g_interrupted) {
      DREAL_LOG_DEBUG("KeyboardInterrupt(SIGINT) Detected.");
      throw std::runtime_error("KeyboardInterrupt(SIGINT) Detected.");
    }
#endif

    // 1. Pop the current box from the stack
    tie(current_box, current_branching_point) = stack.back();
    stack.pop_back();

    // 2. Prune the current box.
    DREAL_LOG_TRACE("IcpSeq::CheckSat() Current Box:\n{}", current_box);
    prune_timer_guard.resume();
    contractor.Prune(cs);
    prune_timer_guard.pause();
    stat.num_prune_++;
    DREAL_LOG_TRACE("IcpSeq::CheckSat() After pruning, the current box =\n{}",
                    current_box);

    if (current_box.empty()) {
      // 3.1. The box is empty after pruning.
      DREAL_LOG_DEBUG("IcpSeq::CheckSat() Box is empty after pruning");
      continue;
    }
    // 3.2. The box is non-empty. Check if the box is still feasible
    // under evaluation and it's small enough.
    eval_timer_guard.resume();
    const optional<ibex::BitSet> evaluation_result{
        EvaluateBox(formula_evaluators, current_box, config().precision(), cs)};
    if (!evaluation_result) {
      // 3.2.1. We detect that the current box is not a feasible solution.
      DREAL_LOG_DEBUG(
          "IcpSeq::CheckSat() Detect that the current box is not feasible by "
          "evaluation:\n{}",
          current_box);
      eval_timer_guard.pause();
      continue;
    }
    if (evaluation_result->empty()) {
      // 3.2.2. delta-SAT : We find a box which is smaller enough.
      DREAL_LOG_DEBUG("IcpSeq::CheckSat() Found a delta-box:\n{}", current_box);
      return true;
    }
    eval_timer_guard.pause();

    // 3.2.3. This box is bigger than delta. Need branching.
    branch_timer_guard.resume();
    if (!Branch(current_box, *evaluation_result, stack_left_box_first_,
                &stack)) {
      DREAL_LOG_DEBUG(
          "IcpSeq::CheckSat() Found that the current box is not satisfying "
          "delta-condition but it's not bisectable.:\n{}",
          current_box);
      return true;
    }
    branch_timer_guard.pause();

    // We alternate between adding-the-left-box-first policy and
    // adding-the-right-box-first policy.
    stack_left_box_first_ = !stack_left_box_first_;
    stat.num_branch_++;
  }
  DREAL_LOG_DEBUG("IcpSeq::CheckSat() No solution");
  return false;
}
}  // namespace dreal
<|endoftext|>