<commit_before>/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** GNU Lesser General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://qt.nokia.com/contact.
**
**************************************************************************/

#include "uncommentselection.h"
#include <QtGui/QPlainTextEdit>
#include <QtGui/QTextCursor>
#include <QtGui/QTextBlock>
#include <QtGui/QTextDocument>

void Utils::unCommentSelection(QPlainTextEdit *edit)
{
    QTextCursor cursor = edit->textCursor();
    QTextDocument *doc = cursor.document();
    cursor.beginEditBlock();

    int pos = cursor.position();
    int anchor = cursor.anchor();
    int start = qMin(anchor, pos);
    int end = qMax(anchor, pos);
    bool anchorIsStart = (anchor == start);

    QTextBlock startBlock = doc->findBlock(start);
    QTextBlock endBlock = doc->findBlock(end);

    if (end > start && endBlock.position() == end) {
        --end;
        endBlock = endBlock.previous();
    }

    bool doCStyleUncomment = false;
    bool doCStyleComment = false;
    bool doCppStyleUncomment = false;

    bool hasSelection = cursor.hasSelection();

    if (hasSelection) {
        QString startText = startBlock.text();
        int startPos = start - startBlock.position();
        bool hasLeadingCharacters = !startText.left(startPos).trimmed().isEmpty();
        if ((startPos >= 2
            && startText.at(startPos-2) == QLatin1Char('/')
             && startText.at(startPos-1) == QLatin1Char('*'))) {
            startPos -= 2;
            start -= 2;
        }

        bool hasSelStart = (startPos < startText.length() - 2
                            && startText.at(startPos) == QLatin1Char('/')
                            && startText.at(startPos+1) == QLatin1Char('*'));

        QString endText = endBlock.text();
        int endPos = end - endBlock.position();
        bool hasTrailingCharacters = !endText.left(endPos).remove(QLatin1String("//")).trimmed().isEmpty()
                                     && !endText.mid(endPos).trimmed().isEmpty();
        if ((endPos <= endText.length() - 2
            && endText.at(endPos) == QLatin1Char('*')
             && endText.at(endPos+1) == QLatin1Char('/'))) {
            endPos += 2;
            end += 2;
        }

        bool hasSelEnd = (endPos >= 2
                          && endText.at(endPos-2) == QLatin1Char('*')
                          && endText.at(endPos-1) == QLatin1Char('/'));

        doCStyleUncomment = hasSelStart && hasSelEnd;
        doCStyleComment = !doCStyleUncomment && (hasLeadingCharacters || hasTrailingCharacters);
    }

    if (doCStyleUncomment) {
        cursor.setPosition(end);
        cursor.movePosition(QTextCursor::PreviousCharacter, QTextCursor::KeepAnchor, 2);
        cursor.removeSelectedText();
        cursor.setPosition(start);
        cursor.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor, 2);
        cursor.removeSelectedText();
    } else if (doCStyleComment) {
        cursor.setPosition(end);
        cursor.insertText(QLatin1String("*/"));
        cursor.setPosition(start);
        cursor.insertText(QLatin1String("/*"));
    } else {
        endBlock = endBlock.next();
        doCppStyleUncomment = true;
        for (QTextBlock block = startBlock; block != endBlock; block = block.next()) {
            QString text = block.text();
            if (!text.trimmed().startsWith(QLatin1String("//"))) {
                doCppStyleUncomment = false;
                break;
            }
        }
        for (QTextBlock block = startBlock; block != endBlock; block = block.next()) {
            if (doCppStyleUncomment) {
                QString text = block.text();
                int i = 0;
                while (i < text.size() - 1) {
                    if (text.at(i) == QLatin1Char('/')
                        && text.at(i + 1) == QLatin1Char('/')) {
                        cursor.setPosition(block.position() + i);
                        cursor.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor, 2);
                        cursor.removeSelectedText();
                        break;
                    }
                    if (!text.at(i).isSpace())
                        break;
                    ++i;
                }
            } else {
                cursor.setPosition(block.position());
                cursor.insertText(QLatin1String("//"));
            }
        }
    }

    // adjust selection when commenting out
    if (hasSelection && !doCStyleUncomment && !doCppStyleUncomment) {
        cursor = edit->textCursor();
        if (!doCStyleComment)
            start = startBlock.position(); // move the double slashes into the selection
        int lastSelPos = anchorIsStart ? cursor.position() : cursor.anchor();
        if (anchorIsStart) {
            cursor.setPosition(start);
            cursor.setPosition(lastSelPos, QTextCursor::KeepAnchor);
        } else {
            cursor.setPosition(lastSelPos);
            cursor.setPosition(start, QTextCursor::KeepAnchor);
        }
        edit->setTextCursor(cursor);
    }

    cursor.endEditBlock();
}

<commit_msg>Improve (un)comment selection in C++ style<commit_after>/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** GNU Lesser General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://qt.nokia.com/contact.
**
**************************************************************************/

#include "uncommentselection.h"
#include <QtGui/QPlainTextEdit>
#include <QtGui/QTextCursor>
#include <QtGui/QTextBlock>
#include <QtGui/QTextDocument>

void Utils::unCommentSelection(QPlainTextEdit *edit)
{
    QTextCursor cursor = edit->textCursor();
    QTextDocument *doc = cursor.document();
    cursor.beginEditBlock();

    int pos = cursor.position();
    int anchor = cursor.anchor();
    int start = qMin(anchor, pos);
    int end = qMax(anchor, pos);
    bool anchorIsStart = (anchor == start);

    QTextBlock startBlock = doc->findBlock(start);
    QTextBlock endBlock = doc->findBlock(end);

    if (end > start && endBlock.position() == end) {
        --end;
        endBlock = endBlock.previous();
    }

    bool doCStyleUncomment = false;
    bool doCStyleComment = false;
    bool doCppStyleUncomment = false;

    bool hasSelection = cursor.hasSelection();

    if (hasSelection) {
        QString startText = startBlock.text();
        int startPos = start - startBlock.position();
        bool hasLeadingCharacters = !startText.left(startPos).trimmed().isEmpty();
        if ((startPos >= 2
            && startText.at(startPos-2) == QLatin1Char('/')
             && startText.at(startPos-1) == QLatin1Char('*'))) {
            startPos -= 2;
            start -= 2;
        }

        bool hasSelStart = (startPos < startText.length() - 2
                            && startText.at(startPos) == QLatin1Char('/')
                            && startText.at(startPos+1) == QLatin1Char('*'));

        QString endText = endBlock.text();
        int endPos = end - endBlock.position();
        bool hasTrailingCharacters = !endText.left(endPos).remove(QLatin1String("//")).trimmed().isEmpty()
                                     && !endText.mid(endPos).trimmed().isEmpty();
        if ((endPos <= endText.length() - 2
            && endText.at(endPos) == QLatin1Char('*')
             && endText.at(endPos+1) == QLatin1Char('/'))) {
            endPos += 2;
            end += 2;
        }

        bool hasSelEnd = (endPos >= 2
                          && endText.at(endPos-2) == QLatin1Char('*')
                          && endText.at(endPos-1) == QLatin1Char('/'));

        doCStyleUncomment = hasSelStart && hasSelEnd;
        doCStyleComment = !doCStyleUncomment && (hasLeadingCharacters || hasTrailingCharacters);
    }

    if (doCStyleUncomment) {
        cursor.setPosition(end);
        cursor.movePosition(QTextCursor::PreviousCharacter, QTextCursor::KeepAnchor, 2);
        cursor.removeSelectedText();
        cursor.setPosition(start);
        cursor.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor, 2);
        cursor.removeSelectedText();
    } else if (doCStyleComment) {
        cursor.setPosition(end);
        cursor.insertText(QLatin1String("*/"));
        cursor.setPosition(start);
        cursor.insertText(QLatin1String("/*"));
    } else {
        endBlock = endBlock.next();
        doCppStyleUncomment = true;
        for (QTextBlock block = startBlock; block != endBlock; block = block.next()) {
            QString text = block.text().trimmed();
            if (!text.isEmpty() && !text.startsWith(QLatin1String("//"))) {
                doCppStyleUncomment = false;
                break;
            }
        }
        for (QTextBlock block = startBlock; block != endBlock; block = block.next()) {
            if (doCppStyleUncomment) {
                QString text = block.text();
                int i = 0;
                while (i < text.size() - 1) {
                    if (text.at(i) == QLatin1Char('/')
                        && text.at(i + 1) == QLatin1Char('/')) {
                        cursor.setPosition(block.position() + i);
                        cursor.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor, 2);
                        cursor.removeSelectedText();
                        break;
                    }
                    if (!text.at(i).isSpace())
                        break;
                    ++i;
                }
            } else {
                QString text = block.text();
                foreach(QChar c, text) {
                    if (!c.isSpace()) {
                        cursor.setPosition(block.position());
                        cursor.insertText(QLatin1String("//"));
                        break;
                    }
                }
            }
        }
    }

    // adjust selection when commenting out
    if (hasSelection && !doCStyleUncomment && !doCppStyleUncomment) {
        cursor = edit->textCursor();
        if (!doCStyleComment)
            start = startBlock.position(); // move the double slashes into the selection
        int lastSelPos = anchorIsStart ? cursor.position() : cursor.anchor();
        if (anchorIsStart) {
            cursor.setPosition(start);
            cursor.setPosition(lastSelPos, QTextCursor::KeepAnchor);
        } else {
            cursor.setPosition(lastSelPos);
            cursor.setPosition(start, QTextCursor::KeepAnchor);
        }
        edit->setTextCursor(cursor);
    }

    cursor.endEditBlock();
}

<|endoftext|>


<commit_before>#ifndef SLAAUTOSUPPORTS_HPP_
#define SLAAUTOSUPPORTS_HPP_

#include <libslic3r/ClipperUtils.hpp>
#include <libslic3r/Point.hpp>
#include <libslic3r/TriangleMesh.hpp>
#include <libslic3r/SLA/SLACommon.hpp>

#include <boost/container/small_vector.hpp>

// #define SLA_AUTOSUPPORTS_DEBUG

namespace Slic3r {

class SLAAutoSupports {
public:
    struct Config {
            float density_relative;
            float minimal_distance;
            float head_diameter;
            ///////////////
            inline float support_force() const { return 10.f / density_relative; } // a force one point can support       (arbitrary force unit)
            inline float tear_pressure() const { return 1.f; }  // pressure that the display exerts    (the force unit per mm2)
        };

    SLAAutoSupports(const TriangleMesh& mesh, const sla::EigenMesh3D& emesh, const std::vector<ExPolygons>& slices,
                     const std::vector<float>& heights, const Config& config, std::function<void(void)> throw_on_cancel);
    const std::vector<sla::SupportPoint>& output() { return m_output; }

	struct MyLayer;

    struct Structure {
        Structure(MyLayer &layer, const ExPolygon& poly, const BoundingBox &bbox, const Vec2f &centroid, float area, float h) :
            layer(&layer), polygon(&poly), bbox(bbox), centroid(centroid), area(area), height(h)
#ifdef SLA_AUTOSUPPORTS_DEBUG
            , unique_id(std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()))
#endif /* SLA_AUTOSUPPORTS_DEBUG */
            {}
        MyLayer *layer;
        const ExPolygon* polygon = nullptr;
        const BoundingBox bbox;
        const Vec2f centroid = Vec2f::Zero();
        const float area = 0.f;
        float height = 0;
        // How well is this ExPolygon held to the print base?
        // Positive number, the higher the better.
        float supports_force_this_layer     = 0.f;
        float supports_force_inherited      = 0.f;
        float supports_force_total() const { return this->supports_force_this_layer + this->supports_force_inherited; }
#ifdef SLA_AUTOSUPPORTS_DEBUG
        std::chrono::milliseconds unique_id;
#endif /* SLA_AUTOSUPPORTS_DEBUG */

        struct Link {
			Link(Structure *island, float overlap_area) : island(island), overlap_area(overlap_area) {}
            Structure   *island;
            float        overlap_area;
        };

#ifdef NDEBUG
		// In release mode, use the optimized container.
        boost::container::small_vector<Link, 4> islands_above;
        boost::container::small_vector<Link, 4> islands_below;
#else
		// In debug mode, use the standard vector, which is well handled by debugger visualizer.
		std::vector<Link>					 	islands_above;
		std::vector<Link>						islands_below;
#endif
        // Overhangs, that are dangling considerably.
        ExPolygons                              dangling_areas;
        // Complete overhands.
        ExPolygons                              overhangs;
        // Overhangs, where the surface must slope.
        ExPolygons                              overhangs_slopes;
        float                                   overhangs_area;

        bool overlaps(const Structure &rhs) const {
            return this->bbox.overlap(rhs.bbox) && (this->polygon->overlaps(*rhs.polygon) || rhs.polygon->overlaps(*this->polygon));
        }
        float overlap_area(const Structure &rhs) const {
            double out = 0.;
            if (this->bbox.overlap(rhs.bbox)) {
                 Polygons polys = intersection(to_polygons(*this->polygon), to_polygons(*rhs.polygon), false);
                 for (const Polygon &poly : polys)
                    out += poly.area();
            }
            return float(out);
        }
        float area_below() const {
            float area = 0.f;
            for (const Link &below : this->islands_below)
                area += below.island->area;
            return area;
        }
        Polygons polygons_below() const {
            size_t cnt = 0;
			for (const Link &below : this->islands_below)
                cnt += 1 + below.island->polygon->holes.size();
            Polygons out;
            out.reserve(cnt);
			for (const Link &below : this->islands_below) {
                out.emplace_back(below.island->polygon->contour);
				append(out, below.island->polygon->holes);
            }
            return out;
        }
        ExPolygons expolygons_below() const {
            ExPolygons out;
            out.reserve(this->islands_below.size());
            for (const Link &below : this->islands_below)
                out.emplace_back(*below.island->polygon);
            return out;
        }
        // Positive deficit of the supports. If negative, this area is well supported. If positive, more supports need to be added.
        float support_force_deficit(const float tear_pressure) const { return this->area * tear_pressure - this->supports_force_total(); }
    };

    struct MyLayer {
		MyLayer(const size_t layer_id, coordf_t print_z) : layer_id(layer_id), print_z(print_z) {}
        size_t                  layer_id;
        coordf_t                print_z;
        std::vector<Structure>  islands;
    };

    struct RichSupportPoint {
        Vec3f        position;
        Structure   *island;
    };

    struct PointGrid3D {
        struct GridHash {
            std::size_t operator()(const Vec3i &cell_id) const {
                return std::hash<int>()(cell_id.x()) ^ std::hash<int>()(cell_id.y() * 593) ^ std::hash<int>()(cell_id.z() * 7919);
            }
        };
        typedef std::unordered_multimap<Vec3i, RichSupportPoint, GridHash> Grid;

        Vec3f   cell_size;
        Grid    grid;

        Vec3i cell_id(const Vec3f &pos) {
            return Vec3i(int(floor(pos.x() / cell_size.x())),
                         int(floor(pos.y() / cell_size.y())),
                         int(floor(pos.z() / cell_size.z())));
        }

        void insert(const Vec2f &pos, Structure *island) {
            RichSupportPoint pt;
			pt.position = Vec3f(pos.x(), pos.y(), float(island->layer->print_z));
            pt.island   = island;
            grid.emplace(cell_id(pt.position), pt);
        }

        bool collides_with(const Vec2f &pos, Structure *island, float radius) {
            Vec3f pos3d(pos.x(), pos.y(), float(island->layer->print_z));
            Vec3i cell = cell_id(pos3d);
            std::pair<Grid::const_iterator, Grid::const_iterator> it_pair = grid.equal_range(cell);
            if (collides_with(pos3d, radius, it_pair.first, it_pair.second))
                return true;
            for (int i = -1; i < 2; ++ i)
                for (int j = -1; j < 2; ++ j)
                    for (int k = -1; k < 1; ++ k) {
                        if (i == 0 && j == 0 && k == 0)
                            continue;
                        it_pair = grid.equal_range(cell + Vec3i(i, j, k));
                        if (collides_with(pos3d, radius, it_pair.first, it_pair.second))
                            return true;
                    }
            return false;
        }

    private:
        bool collides_with(const Vec3f &pos, float radius, Grid::const_iterator it_begin, Grid::const_iterator it_end) {
            for (Grid::const_iterator it = it_begin; it != it_end; ++ it) {
				float dist2 = (it->second.position - pos).squaredNorm();
                if (dist2 < radius * radius)
                    return true;
            }
            return false;
        }
    };

private:
    std::vector<sla::SupportPoint> m_output;

    SLAAutoSupports::Config m_config;

    float m_supports_force_total = 0.f;

    void process(const std::vector<ExPolygons>& slices, const std::vector<float>& heights);
    void uniformly_cover(const ExPolygons& islands, Structure& structure, PointGrid3D &grid3d, bool is_new_island = false, bool just_one = false);
    void project_onto_mesh(std::vector<sla::SupportPoint>& points) const;

#ifdef SLA_AUTOSUPPORTS_DEBUG
    static void output_expolygons(const ExPolygons& expolys, const std::string &filename);
    static void output_structures(const std::vector<Structure> &structures);
#endif // SLA_AUTOSUPPORTS_DEBUG

    std::function<void(void)> m_throw_on_cancel;
    const sla::EigenMesh3D& m_emesh;
};

} // namespace Slic3r

#endif // SLAAUTOSUPPORTS_HPP_<commit_msg>Increased the default SLA support density to 130% of the previous value (100% now works as 130% before)<commit_after>#ifndef SLAAUTOSUPPORTS_HPP_
#define SLAAUTOSUPPORTS_HPP_

#include <libslic3r/ClipperUtils.hpp>
#include <libslic3r/Point.hpp>
#include <libslic3r/TriangleMesh.hpp>
#include <libslic3r/SLA/SLACommon.hpp>

#include <boost/container/small_vector.hpp>

// #define SLA_AUTOSUPPORTS_DEBUG

namespace Slic3r {

class SLAAutoSupports {
public:
    struct Config {
            float density_relative;
            float minimal_distance;
            float head_diameter;
            ///////////////
            inline float support_force() const { return 7.7f / density_relative; } // a force one point can support       (arbitrary force unit)
            inline float tear_pressure() const { return 1.f; }  // pressure that the display exerts    (the force unit per mm2)
        };

    SLAAutoSupports(const TriangleMesh& mesh, const sla::EigenMesh3D& emesh, const std::vector<ExPolygons>& slices,
                     const std::vector<float>& heights, const Config& config, std::function<void(void)> throw_on_cancel);
    const std::vector<sla::SupportPoint>& output() { return m_output; }

	struct MyLayer;

    struct Structure {
        Structure(MyLayer &layer, const ExPolygon& poly, const BoundingBox &bbox, const Vec2f &centroid, float area, float h) :
            layer(&layer), polygon(&poly), bbox(bbox), centroid(centroid), area(area), height(h)
#ifdef SLA_AUTOSUPPORTS_DEBUG
            , unique_id(std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()))
#endif /* SLA_AUTOSUPPORTS_DEBUG */
            {}
        MyLayer *layer;
        const ExPolygon* polygon = nullptr;
        const BoundingBox bbox;
        const Vec2f centroid = Vec2f::Zero();
        const float area = 0.f;
        float height = 0;
        // How well is this ExPolygon held to the print base?
        // Positive number, the higher the better.
        float supports_force_this_layer     = 0.f;
        float supports_force_inherited      = 0.f;
        float supports_force_total() const { return this->supports_force_this_layer + this->supports_force_inherited; }
#ifdef SLA_AUTOSUPPORTS_DEBUG
        std::chrono::milliseconds unique_id;
#endif /* SLA_AUTOSUPPORTS_DEBUG */

        struct Link {
			Link(Structure *island, float overlap_area) : island(island), overlap_area(overlap_area) {}
            Structure   *island;
            float        overlap_area;
        };

#ifdef NDEBUG
		// In release mode, use the optimized container.
        boost::container::small_vector<Link, 4> islands_above;
        boost::container::small_vector<Link, 4> islands_below;
#else
		// In debug mode, use the standard vector, which is well handled by debugger visualizer.
		std::vector<Link>					 	islands_above;
		std::vector<Link>						islands_below;
#endif
        // Overhangs, that are dangling considerably.
        ExPolygons                              dangling_areas;
        // Complete overhands.
        ExPolygons                              overhangs;
        // Overhangs, where the surface must slope.
        ExPolygons                              overhangs_slopes;
        float                                   overhangs_area;

        bool overlaps(const Structure &rhs) const {
            return this->bbox.overlap(rhs.bbox) && (this->polygon->overlaps(*rhs.polygon) || rhs.polygon->overlaps(*this->polygon));
        }
        float overlap_area(const Structure &rhs) const {
            double out = 0.;
            if (this->bbox.overlap(rhs.bbox)) {
                 Polygons polys = intersection(to_polygons(*this->polygon), to_polygons(*rhs.polygon), false);
                 for (const Polygon &poly : polys)
                    out += poly.area();
            }
            return float(out);
        }
        float area_below() const {
            float area = 0.f;
            for (const Link &below : this->islands_below)
                area += below.island->area;
            return area;
        }
        Polygons polygons_below() const {
            size_t cnt = 0;
			for (const Link &below : this->islands_below)
                cnt += 1 + below.island->polygon->holes.size();
            Polygons out;
            out.reserve(cnt);
			for (const Link &below : this->islands_below) {
                out.emplace_back(below.island->polygon->contour);
				append(out, below.island->polygon->holes);
            }
            return out;
        }
        ExPolygons expolygons_below() const {
            ExPolygons out;
            out.reserve(this->islands_below.size());
            for (const Link &below : this->islands_below)
                out.emplace_back(*below.island->polygon);
            return out;
        }
        // Positive deficit of the supports. If negative, this area is well supported. If positive, more supports need to be added.
        float support_force_deficit(const float tear_pressure) const { return this->area * tear_pressure - this->supports_force_total(); }
    };

    struct MyLayer {
		MyLayer(const size_t layer_id, coordf_t print_z) : layer_id(layer_id), print_z(print_z) {}
        size_t                  layer_id;
        coordf_t                print_z;
        std::vector<Structure>  islands;
    };

    struct RichSupportPoint {
        Vec3f        position;
        Structure   *island;
    };

    struct PointGrid3D {
        struct GridHash {
            std::size_t operator()(const Vec3i &cell_id) const {
                return std::hash<int>()(cell_id.x()) ^ std::hash<int>()(cell_id.y() * 593) ^ std::hash<int>()(cell_id.z() * 7919);
            }
        };
        typedef std::unordered_multimap<Vec3i, RichSupportPoint, GridHash> Grid;

        Vec3f   cell_size;
        Grid    grid;

        Vec3i cell_id(const Vec3f &pos) {
            return Vec3i(int(floor(pos.x() / cell_size.x())),
                         int(floor(pos.y() / cell_size.y())),
                         int(floor(pos.z() / cell_size.z())));
        }

        void insert(const Vec2f &pos, Structure *island) {
            RichSupportPoint pt;
			pt.position = Vec3f(pos.x(), pos.y(), float(island->layer->print_z));
            pt.island   = island;
            grid.emplace(cell_id(pt.position), pt);
        }

        bool collides_with(const Vec2f &pos, Structure *island, float radius) {
            Vec3f pos3d(pos.x(), pos.y(), float(island->layer->print_z));
            Vec3i cell = cell_id(pos3d);
            std::pair<Grid::const_iterator, Grid::const_iterator> it_pair = grid.equal_range(cell);
            if (collides_with(pos3d, radius, it_pair.first, it_pair.second))
                return true;
            for (int i = -1; i < 2; ++ i)
                for (int j = -1; j < 2; ++ j)
                    for (int k = -1; k < 1; ++ k) {
                        if (i == 0 && j == 0 && k == 0)
                            continue;
                        it_pair = grid.equal_range(cell + Vec3i(i, j, k));
                        if (collides_with(pos3d, radius, it_pair.first, it_pair.second))
                            return true;
                    }
            return false;
        }

    private:
        bool collides_with(const Vec3f &pos, float radius, Grid::const_iterator it_begin, Grid::const_iterator it_end) {
            for (Grid::const_iterator it = it_begin; it != it_end; ++ it) {
				float dist2 = (it->second.position - pos).squaredNorm();
                if (dist2 < radius * radius)
                    return true;
            }
            return false;
        }
    };

private:
    std::vector<sla::SupportPoint> m_output;

    SLAAutoSupports::Config m_config;

    float m_supports_force_total = 0.f;

    void process(const std::vector<ExPolygons>& slices, const std::vector<float>& heights);
    void uniformly_cover(const ExPolygons& islands, Structure& structure, PointGrid3D &grid3d, bool is_new_island = false, bool just_one = false);
    void project_onto_mesh(std::vector<sla::SupportPoint>& points) const;

#ifdef SLA_AUTOSUPPORTS_DEBUG
    static void output_expolygons(const ExPolygons& expolys, const std::string &filename);
    static void output_structures(const std::vector<Structure> &structures);
#endif // SLA_AUTOSUPPORTS_DEBUG

    std::function<void(void)> m_throw_on_cancel;
    const sla::EigenMesh3D& m_emesh;
};

} // namespace Slic3r

#endif // SLAAUTOSUPPORTS_HPP_<|endoftext|>


<commit_before>#ifndef SLAAUTOSUPPORTS_HPP_
#define SLAAUTOSUPPORTS_HPP_

#include <libslic3r/Point.hpp>

namespace Slic3r {

class ModelObject;

class SLAAutoSupports {
public:
    struct Config {
            float density_at_horizontal;
            float density_at_45;
            float minimal_z;
        };

    SLAAutoSupports(ModelObject& mo, const SLAAutoSupports::Config& c);
    void generate();

private:
    TriangleMesh mesh;
    static float angle_from_normal(const stl_normal& normal) { return acos((-normal.normalized())(2)); }
    float get_required_density(float angle) const;
    static float approximate_geodesic_distance(const Vec3f& p1, const Vec3f& p2, Vec3f& n1, Vec3f& n2);

    ModelObject& m_model_object;
    SLAAutoSupports::Config m_config;
};

} // namespace Slic3r

#endif // SLAAUTOSUPPORTS_HPP_<commit_msg>Fixed OSX build.<commit_after>#ifndef SLAAUTOSUPPORTS_HPP_
#define SLAAUTOSUPPORTS_HPP_

#include <libslic3r/Point.hpp>
#include <libslic3r/TriangleMesh.hpp>

namespace Slic3r {

class ModelObject;

class SLAAutoSupports {
public:
    struct Config {
            float density_at_horizontal;
            float density_at_45;
            float minimal_z;
        };

    SLAAutoSupports(ModelObject& mo, const SLAAutoSupports::Config& c);
    void generate();

private:
    TriangleMesh mesh;
    static float angle_from_normal(const stl_normal& normal) { return acos((-normal.normalized())(2)); }
    float get_required_density(float angle) const;
    static float approximate_geodesic_distance(const Vec3f& p1, const Vec3f& p2, Vec3f& n1, Vec3f& n2);

    ModelObject& m_model_object;
    SLAAutoSupports::Config m_config;
};

} // namespace Slic3r

#endif // SLAAUTOSUPPORTS_HPP_<|endoftext|>


<commit_before>#pragma once
/*
**  Copyright (C) 2012 Aldebaran Robotics
**  See COPYING for the license
*/

#ifndef _QIMESSAGING_TYPETUPLE_HXX_
#define _QIMESSAGING_TYPETUPLE_HXX_

#include <qi/preproc.hpp>

namespace qi
{
  namespace detail {
    template<typename T> void setFromStorage(T& ref, void* storage)
    {
      ref = *(T*)typeOf<T>()->ptrFromStorage(&storage);
    }
  }
}

#define QI_TYPE_STRUCT_DECLARE(name)                                      \
namespace qi {                                                            \
  template<> struct TypeImpl<name>: public TypeTuple                      \
  {                                                                       \
  public:                                                                 \
    virtual std::vector<Type*> memberTypes(void*);                        \
    virtual void* get(void* storage, unsigned int index);                 \
    virtual void set(void** storage, unsigned int index, void* valStorage); \
    _QI_BOUNCE_TYPE_METHODS(DefaultTypeImplMethods<name>);                \
 }; }

#define __QI_TUPLE_TYPE(_, what, field) res.push_back(typeOf(ptr->field));
#define __QI_TUPLE_GET(_, what, field) if (i == index) return typeOf(ptr->field)->initializeStorage(&ptr->field); i++;
#define __QI_TUPLE_SET(_, what, field) if (i == index) detail::setFromStorage(ptr->field, valueStorage); i++;
#define __QI_TYPE_STRUCT_IMPLEMENT(name, inl, onSet, ...)                                    \
namespace qi {                                                                        \
  inl std::vector<Type*> TypeImpl<name>::memberTypes(void* storage)                   \
  {                                                                                \
    name* ptr = 0;                                                                    \
    std::vector<Type*> res;                                                           \
    QI_VAARGS_APPLY(__QI_TUPLE_TYPE, _, __VA_ARGS__);                                 \
    return res;                                                                       \
  }                                                                                \
  inl void* TypeImpl<name>::get(void* storage, unsigned int index)                    \
  {                                                                                \
    unsigned int i = 0;                                                                        \
    name* ptr = (name*)ptrFromStorage(&storage);                                      \
    QI_VAARGS_APPLY(__QI_TUPLE_GET, _, __VA_ARGS__);                                  \
    return 0;                                                                         \
  }                                                                                \
  inl void TypeImpl<name>::set(void** storage, unsigned int index, void* valueStorage)\
  {                                                                                \
    unsigned int i=0;                                                                 \
    name* ptr = (name*)ptrFromStorage(storage);                                       \
    QI_VAARGS_APPLY(__QI_TUPLE_SET, _, __VA_ARGS__);                                  \
    onSet                                                                      \
  }\
}

#define QI_TYPE_STRUCT_PRIVATE_ACCESS(name) \
friend class qi::TypeImpl<name>;

#define QI_TYPE_STRUCT(name, ...) \
  QI_TYPE_STRUCT_DECLARE(name) \
  __QI_TYPE_STRUCT_IMPLEMENT(name, inline, /**/, __VA_ARGS__)

#define QI_TYPE_STRUCT_EX(name, onSet, ...) \
  QI_TYPE_STRUCT_DECLARE(name) \
  __QI_TYPE_STRUCT_IMPLEMENT(name, inline, onSet, __VA_ARGS__)

#define QI_TYPE_STRUCT_IMPLEMENT(name, ...) \
  __QI_TYPE_STRUCT_IMPLEMENT(name, /**/, /**/, __VA_ARGS__)

#define QI_TYPE_STRUCT_BOUNCE(name, bounceTo, conversion)                 \
namespace qi {                                                            \
template<> class TypeImpl<name>: public TypeTupleBouncer<name, bounceTo>  \
{                                                                         \
public:                                                                   \
  void adaptStorage(void** storage, void** adapted)                       \
  {                                                                       \
    name* ptr = (name*)ptrFromStorage(storage);                           \
    bounceTo * tptr = conversion(ptr);                                    \
    *adapted = bounceType()->initializeStorage(tptr);                     \
  }                                                                       \
};}

namespace qi {
  template<typename T, typename TO> class TypeTupleBouncer: public TypeTuple
  {
  public:
    TypeTuple* bounceType()
    {
      static Type* result = 0;
      if (!result)
        result = typeOf<TO>();
      return static_cast<TypeTuple*>(result);
    }
    virtual void adaptStorage(void** storage, void** adapted) = 0;
    typedef DefaultTypeImplMethods<T> Methods;
    virtual std::vector<Type*> memberTypes(void* storage)
    {
      void* astorage = 0;
      if (storage) // memberTypes should not require storage
        adaptStorage(&storage, &astorage);
      return bounceType()->memberTypes(astorage);
    }
    virtual void* get(void* storage, unsigned int index)
    {
      void* astorage;
      adaptStorage(&storage, &astorage);
      return bounceType()->get(astorage, index);
    }
    virtual void set(void** storage, unsigned int index, void* valStorage)
    {
      void* astorage;
      adaptStorage(storage, &astorage);
      bounceType()->set(&astorage, index, valStorage);
    }
    _QI_BOUNCE_TYPE_METHODS(Methods);
  };
}
#endif
<commit_msg>indentation<commit_after>#pragma once
/*
**  Copyright (C) 2012 Aldebaran Robotics
**  See COPYING for the license
*/

#ifndef _QIMESSAGING_TYPETUPLE_HXX_
#define _QIMESSAGING_TYPETUPLE_HXX_

#include <qi/preproc.hpp>

namespace qi
{
  namespace detail {
    template<typename T> void setFromStorage(T& ref, void* storage)
    {
      ref = *(T*)typeOf<T>()->ptrFromStorage(&storage);
    }
  }
}

#define QI_TYPE_STRUCT_DECLARE(name)                                      \
namespace qi {                                                            \
  template<> struct TypeImpl<name>: public TypeTuple                      \
  {                                                                       \
  public:                                                                 \
    virtual std::vector<Type*> memberTypes(void*);                        \
    virtual void* get(void* storage, unsigned int index);                 \
    virtual void set(void** storage, unsigned int index, void* valStorage); \
    _QI_BOUNCE_TYPE_METHODS(DefaultTypeImplMethods<name>);                \
 }; }

#define __QI_TUPLE_TYPE(_, what, field) res.push_back(typeOf(ptr->field));
#define __QI_TUPLE_GET(_, what, field) if (i == index) return typeOf(ptr->field)->initializeStorage(&ptr->field); i++;
#define __QI_TUPLE_SET(_, what, field) if (i == index) detail::setFromStorage(ptr->field, valueStorage); i++;
#define __QI_TYPE_STRUCT_IMPLEMENT(name, inl, onSet, ...)                                    \
namespace qi {                                                                        \
  inl std::vector<Type*> TypeImpl<name>::memberTypes(void* storage)                   \
  {                                                                                \
    name* ptr = 0;                                                                    \
    std::vector<Type*> res;                                                           \
    QI_VAARGS_APPLY(__QI_TUPLE_TYPE, _, __VA_ARGS__);                                 \
    return res;                                                                       \
  }                                                                                \
  inl void* TypeImpl<name>::get(void* storage, unsigned int index)                    \
  {                                                                                \
    unsigned int i = 0;                                                                        \
    name* ptr = (name*)ptrFromStorage(&storage);                                      \
    QI_VAARGS_APPLY(__QI_TUPLE_GET, _, __VA_ARGS__);                                  \
    return 0;                                                                         \
  }                                                                                \
  inl void TypeImpl<name>::set(void** storage, unsigned int index, void* valueStorage)\
  {                                                                                \
    unsigned int i=0;                                                                 \
    name* ptr = (name*)ptrFromStorage(storage);                                       \
    QI_VAARGS_APPLY(__QI_TUPLE_SET, _, __VA_ARGS__);                                  \
    onSet                                                                      \
  }\
}

#define QI_TYPE_STRUCT_PRIVATE_ACCESS(name) \
friend class qi::TypeImpl<name>;

#define QI_TYPE_STRUCT(name, ...) \
  QI_TYPE_STRUCT_DECLARE(name) \
  __QI_TYPE_STRUCT_IMPLEMENT(name, inline, /**/, __VA_ARGS__)

#define QI_TYPE_STRUCT_EX(name, onSet, ...) \
  QI_TYPE_STRUCT_DECLARE(name) \
  __QI_TYPE_STRUCT_IMPLEMENT(name, inline, onSet, __VA_ARGS__)

#define QI_TYPE_STRUCT_IMPLEMENT(name, ...) \
  __QI_TYPE_STRUCT_IMPLEMENT(name, /**/, /**/, __VA_ARGS__)

#define QI_TYPE_STRUCT_BOUNCE(name, bounceTo, conversion)                 \
namespace qi {                                                            \
template<> class TypeImpl<name>: public TypeTupleBouncer<name, bounceTo>  \
{                                                                         \
public:                                                                   \
  void adaptStorage(void** storage, void** adapted)                       \
  {                                                                       \
    name* ptr = (name*)ptrFromStorage(storage);                           \
    bounceTo * tptr = conversion(ptr);                                    \
    *adapted = bounceType()->initializeStorage(tptr);                     \
  }                                                                       \
};}

namespace qi {
  template<typename T, typename TO> class TypeTupleBouncer: public TypeTuple
  {
  public:
    TypeTuple* bounceType()
    {
      static Type* result = 0;
      if (!result)
        result = typeOf<TO>();
      return static_cast<TypeTuple*>(result);
    }

    virtual void adaptStorage(void** storage, void** adapted) = 0;

    typedef DefaultTypeImplMethods<T> Methods;
    virtual std::vector<Type*> memberTypes(void* storage)
    {
      void* astorage = 0;
      if (storage) // memberTypes should not require storage
        adaptStorage(&storage, &astorage);
      return bounceType()->memberTypes(astorage);
    }

    virtual void* get(void* storage, unsigned int index)
    {
      void* astorage;
      adaptStorage(&storage, &astorage);
      return bounceType()->get(astorage, index);
    }

    virtual void set(void** storage, unsigned int index, void* valStorage)
    {
      void* astorage;
      adaptStorage(storage, &astorage);
      bounceType()->set(&astorage, index, valStorage);
    }

    _QI_BOUNCE_TYPE_METHODS(Methods);
  };
}
#endif
<|endoftext|>


<commit_before>/*
 * This file is part of Maliit Plugins
 *
 * Copyright (C) 2012 Openismus GmbH
 *
 * Contact: maliit-discuss@lists.maliit.org
 *
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice, this list
 * of conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright notice, this list
 * of conditions and the following disclaimer in the documentation and/or other materials
 * provided with the distribution.
 * Neither the name of Nokia Corporation nor the names of its contributors may be
 * used to endorse or promote products derived from this software without specific
 * prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
 * THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 */

#include "abstractwordengine.h"

namespace MaliitKeyboard {
namespace Logic {

//! \class AbstractWordEngine
//! Provides word candidates based on text model. Derived classes need to
//! provide an implementation for \a fetchCandidates().
//! \sa Model::Text, computeCandidates().

//! \fn void AbstractWordEngine::enabledChanged(bool enabled)
//! \brief Emitted when word engine toggles word candidate updates on/off.
//! \param enabled Whether word engine is enabled.

//! \fn void AbstractWordEngine::candidatesChanged(const WordCandidateList &candidates)
//! \brief Emitted when new candidates have been computed.
//! \param candidates The list of updated candidates.

//! \fn WordCandidateList AbstractWordEngine::fetchCandidates(Model::Text *text)
//! \brief Returns a list of candidates.
//!
//! Needs to be implemented by derived classes. Will not be called if engine
//! is disabled or text model has no preedit.
//! \param text The text model.

class AbstractWordEnginePrivate
{
public:
    bool enabled;

    explicit AbstractWordEnginePrivate();
};

AbstractWordEnginePrivate::AbstractWordEnginePrivate()
    : enabled(false)
{}

//! \param parent The owner of this instance. Can be 0, in case QObject
//!               ownership is not required.
AbstractWordEngine::AbstractWordEngine(QObject *parent)
    : QObject(parent)
    , d_ptr(new AbstractWordEnginePrivate)
{}

AbstractWordEngine::~AbstractWordEngine()
{}

//! \brief Returns whether the engine provides updates for word candidates.
bool AbstractWordEngine::isEnabled() const
{
    Q_D(const AbstractWordEngine);
    return d->enabled;
}

//! \brief Set whether the engine should provide updates for word candidates.
//! \param enabled Setting to true will be ignored if there's no word
//!                prediction or error correction backend available.
void AbstractWordEngine::setEnabled(bool enabled)
{
    Q_D(AbstractWordEngine);

    if (d->enabled != enabled) {
        clearCandidates();
        d->enabled = enabled;
        Q_EMIT enabledChanged(d->enabled);
    }
}

//! \brief Clears the current candidates.
//!
//! Only has an effect when word engine is enabled, in which case
//! candidatesCanged() is emitted.
void AbstractWordEngine::clearCandidates()
{
    if (isEnabled()) {
        Q_EMIT candidatesChanged(WordCandidateList());
    }
}

//! \brief Computes new candidates, based on text model.
//! \param text The text model. Can trigger emission of candidatesChanged().
void AbstractWordEngine::computeCandidates(Model::Text *text)
{
    // FIXME: add possiblity to turn off the error correction for
    // entries that does not need it (like password entries).  Also,
    // with that we probably will want to turn off preedit styling at
    // all.

    if (not isEnabled()
        || not text
        || text->preedit().isEmpty()
        || not text->preedit().at(text->preedit().length() - 1).isLetterOrNumber()) {
        // FIXME: We should here set some special preedit face in text
        // model (say Disabled or None) which would be interpreted by
        // editor to send no formatting informations along with
        // preedit string. When this is done, preedit-string test
        // needs to be adapted.
        return;
    }

    Q_EMIT candidatesChanged(fetchCandidates(text));
}

void AbstractWordEngine::addToUserDictionary(const QString &word)
{
    Q_UNUSED(word);
}

}} // namespace MaliitKeyboard, Logic
<commit_msg>Document AbstractWordEngine bit more.<commit_after>/*
 * This file is part of Maliit Plugins
 *
 * Copyright (C) 2012 Openismus GmbH
 *
 * Contact: maliit-discuss@lists.maliit.org
 *
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice, this list
 * of conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright notice, this list
 * of conditions and the following disclaimer in the documentation and/or other materials
 * provided with the distribution.
 * Neither the name of Nokia Corporation nor the names of its contributors may be
 * used to endorse or promote products derived from this software without specific
 * prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
 * THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 */

#include "abstractwordengine.h"

namespace MaliitKeyboard {
namespace Logic {

//! \class AbstractWordEngine
//! \brief Provides word candidates based on text model.
//!
//! Derived classes need to provide an implementation for
//! fetchCandidates() and, optionally, addToUserDictionary().
//! \sa Model::Text, computeCandidates().

//! \fn void AbstractWordEngine::enabledChanged(bool enabled)
//! \brief Emitted when word engine toggles word candidate updates on/off.
//! \param enabled Whether word engine is enabled.

//! \fn void AbstractWordEngine::candidatesChanged(const WordCandidateList &candidates)
//! \brief Emitted when new candidates have been computed.
//! \param candidates The list of updated candidates.

//! \fn WordCandidateList AbstractWordEngine::fetchCandidates(Model::Text *text)
//! \brief Returns a list of candidates.
//! \param text The text model.
//!
//! Needs to be implemented by derived classes. Will not be called if engine
//! is disabled or text model has no preedit.

//! \property AbstractWordEngine::enabled
//! \brief Whether the engine provides updates for word candidates.

class AbstractWordEnginePrivate
{
public:
    bool enabled;

    explicit AbstractWordEnginePrivate();
};

AbstractWordEnginePrivate::AbstractWordEnginePrivate()
    : enabled(false)
{}

//! \brief Constructor.
//! \param parent The owner of this instance. Can be 0, in case QObject
//!               ownership is not required.
AbstractWordEngine::AbstractWordEngine(QObject *parent)
    : QObject(parent)
    , d_ptr(new AbstractWordEnginePrivate)
{}

//! \brief Destructor.
//!
//! Needs to be implemented in derived classes.
AbstractWordEngine::~AbstractWordEngine()
{}

//! \brief Returns whether the word engine is enabled.
//! \sa AbstractWordEngine::enabled
bool AbstractWordEngine::isEnabled() const
{
    Q_D(const AbstractWordEngine);
    return d->enabled;
}

//! \brief Set whether the engine should be enabled.
//! \param enabled Setting to true will be ignored if there's no word
//!                prediction or error correction backend available.
//! \sa AbstractWordEngine::enabled
void AbstractWordEngine::setEnabled(bool enabled)
{
    Q_D(AbstractWordEngine);

    if (d->enabled != enabled) {
        clearCandidates();
        d->enabled = enabled;
        Q_EMIT enabledChanged(d->enabled);
    }
}

//! \brief Clears the current candidates.
//!
//! Only has an effect when word engine is enabled, in which case
//! candidatesCanged() is emitted.
void AbstractWordEngine::clearCandidates()
{
    if (isEnabled()) {
        Q_EMIT candidatesChanged(WordCandidateList());
    }
}

//! \brief Computes new candidates, based on text model.
//! \param text The text model.
//!
//! Can trigger emission of candidatesChanged().
void AbstractWordEngine::computeCandidates(Model::Text *text)
{
    // FIXME: add possiblity to turn off the error correction for
    // entries that does not need it (like password entries).  Also,
    // with that we probably will want to turn off preedit styling at
    // all.

    if (not isEnabled()
        || not text
        || text->preedit().isEmpty()
        || not text->preedit().at(text->preedit().length() - 1).isLetterOrNumber()) {
        // FIXME: We should here set some special preedit face in text
        // model (say Disabled or None) which would be interpreted by
        // editor to send no formatting informations along with
        // preedit string. When this is done, preedit-string test
        // needs to be adapted.
        return;
    }

    Q_EMIT candidatesChanged(fetchCandidates(text));
}

//! \brief Adds a word to user dictionary.
//! \param word A word.
//!
//! Needs to be implemented in derived classes. This does nothing.
void AbstractWordEngine::addToUserDictionary(const QString &word)
{
    Q_UNUSED(word);
}

}} // namespace MaliitKeyboard, Logic
<|endoftext|>


<commit_before>// Copyright 2010-2015 RethinkDB, all rights reserved.
#ifndef CLUSTERING_TABLE_MANAGER_TABLE_META_CLIENT_HPP_
#define CLUSTERING_TABLE_MANAGER_TABLE_META_CLIENT_HPP_

#include "clustering/table_manager/table_metadata.hpp"
#include "concurrency/cross_thread_watchable.hpp"
#include "concurrency/watchable_map.hpp"

class multi_table_manager_t;

class no_such_table_exc_t : public std::runtime_error {
public:
    no_such_table_exc_t() :
        std::runtime_error("there is no table with the given name / UUID") { }
};

class ambiguous_table_exc_t : public std::runtime_error {
public:
    ambiguous_table_exc_t() :
        std::runtime_error("there are multiple tables with the given name") { }
};

class failed_table_op_exc_t : public std::runtime_error {
public:
    failed_table_op_exc_t() : std::runtime_error("the attempt to read or modify the "
        "table's configuration failed because none of the servers were accessible") { }
};

class maybe_failed_table_op_exc_t : public std::runtime_error {
public:
    maybe_failed_table_op_exc_t() : std::runtime_error("something went wrong while we "
        "were trying to modify the table's configuration; the modification may or may "
        "not have been applied") { }
};

/* `table_meta_client_t` is responsible for submitting client requests over the network
to the `multi_table_manager_t`. It doesn't have any real state of its own; it's just a
convenient way of bundling together all of the objects that are necessary for submitting
a client request. */
class table_meta_client_t :
    public home_thread_mixin_t {
public:
    table_meta_client_t(
        mailbox_manager_t *_mailbox_manager,
        multi_table_manager_t *_multi_table_manager,
        watchable_map_t<peer_id_t, multi_table_manager_bcard_t>
            *_multi_table_manager_directory,
        watchable_map_t<std::pair<peer_id_t, namespace_id_t>, table_manager_bcard_t>
            *_table_manager_directory);

    /* All of these functions can be called from any thread. */

    /* `find()` determines the ID of the table with the given name in the given database.
    */
    void find(
        const database_id_t &database, const name_string_t &name,
        namespace_id_t *table_id_out, std::string *primary_key_out = nullptr)
        THROWS_ONLY(no_such_table_exc_t, ambiguous_table_exc_t);

    /* `exists()` returns `true` if one or more tables exist with the given name in the
    given database. */
    bool exists(const database_id_t &database, const name_string_t &name);

    /* `get_name()` determines the name, database, and primary key of the table with the
    given ID; it's the reverse of `find()`. It returns `false` if there is no existing
    table with that ID. `get_name()` will not block. */
    void get_name(
        const namespace_id_t &table_id,
        table_basic_config_t *basic_config_out)
        THROWS_ONLY(no_such_table_exc_t);

    /* `list_names()` determines the IDs, names, databases, and primary keys of every
    table. It will not block. */
    void list_names(
        std::map<namespace_id_t, table_basic_config_t> *names_out);

    /* `get_config()` fetches the configuration of the table with the given ID. It may
    block and it may fail. */
    void get_config(
        const namespace_id_t &table_id,
        signal_t *interruptor,
        table_config_and_shards_t *config_out)
        THROWS_ONLY(interrupted_exc_t, no_such_table_exc_t, failed_table_op_exc_t);

    /* `list_configs()` fetches the configurations of every table at once. It may block.
    */
    void list_configs(
        signal_t *interruptor,
        std::map<namespace_id_t, table_config_and_shards_t> *configs_out)
        THROWS_ONLY(interrupted_exc_t, failed_table_op_exc_t);

    /* `get_status()` returns the secondary index status of the table with the given ID.
    It may block. */
    void get_status(
        const namespace_id_t &table_id,
        signal_t *interruptor,
        std::map<std::string, std::pair<sindex_config_t, sindex_status_t> >
            *index_statuses_out,
        std::map<peer_id_t, contracts_and_contract_acks_t> *contracts_and_acks_out)
        THROWS_ONLY(interrupted_exc_t, no_such_table_exc_t, failed_table_op_exc_t);

    /* `create()` creates a table with the given configuration. It sets `*table_id_out`
    to the ID of the newly generated table. It may block. If it returns successfully, the
    change will be visible in `find()`, etc. */
    void create(
        namespace_id_t new_table_id,
        const table_config_and_shards_t &new_config,
        signal_t *interruptor)
        THROWS_ONLY(interrupted_exc_t, failed_table_op_exc_t,
            maybe_failed_table_op_exc_t);

    /* `drop()` drops the table with the given ID. It may block. If it returns `false`,
    the change may or may not have succeeded. If it returns successfully, the change will
    be visible in `find()`, etc. */
    void drop(
        const namespace_id_t &table_id,
        signal_t *interruptor)
        THROWS_ONLY(interrupted_exc_t, no_such_table_exc_t, failed_table_op_exc_t,
            maybe_failed_table_op_exc_t);

    /* `set_config()` changes the configuration of the table with the given ID. It may
    block. If it returns successfully, the change will be visible in `find()`, etc. */
    void set_config(
        const namespace_id_t &table_id,
        const table_config_and_shards_t &new_config,
        signal_t *interruptor)
        THROWS_ONLY(interrupted_exc_t, no_such_table_exc_t, failed_table_op_exc_t,
            maybe_failed_table_op_exc_t);

private:
    typedef std::pair<table_basic_config_t, multi_table_manager_bcard_t::timestamp_t>
        timestamped_basic_config_t;

    [[noreturn]] void throw_appropriate_exception(const namespace_id_t &table_id)
        THROWS_ONLY(no_such_table_exc_t, failed_table_op_exc_t);

    void wait_until_change_visible(
        const namespace_id_t &table_id,
        const std::function<bool(const timestamped_basic_config_t *)> &cb,
        signal_t *interruptor)
        THROWS_ONLY(interrupted_exc_t, maybe_failed_table_op_exc_t);

    mailbox_manager_t *const mailbox_manager;
    multi_table_manager_t *const multi_table_manager;
    watchable_map_t<peer_id_t, multi_table_manager_bcard_t>
        *const multi_table_manager_directory;
    watchable_map_t<std::pair<peer_id_t, namespace_id_t>, table_manager_bcard_t>
        *const table_manager_directory;

    /* `table_basic_configs` distributes the `table_basic_config_t`s from the
    `multi_table_manager_t` to each thread, so that `find()`, `get_name()`, and
    `list_names()` can run without blocking. */
    all_thread_watchable_map_var_t<namespace_id_t, timestamped_basic_config_t>
        table_basic_configs;
};

#endif /* CLUSTERING_TABLE_MANAGER_TABLE_META_CLIENT_HPP_ */

<commit_msg>Add a comment explaining the exceptions in table_meta_client.hpp.<commit_after>// Copyright 2010-2015 RethinkDB, all rights reserved.
#ifndef CLUSTERING_TABLE_MANAGER_TABLE_META_CLIENT_HPP_
#define CLUSTERING_TABLE_MANAGER_TABLE_META_CLIENT_HPP_

#include "clustering/table_manager/table_metadata.hpp"
#include "concurrency/cross_thread_watchable.hpp"
#include "concurrency/watchable_map.hpp"

class multi_table_manager_t;

/* These four exception classes are all thrown by `table_meta_client_t` to describe
different error conditions. There are several reasons why this is better than having
`table_meta_client_t` just throw an `admin_op_exc_t`:

 1. Sometimes we want to catch `no_such_table_exc_t` instead of reporting it to the user.
    For example, if we call `list_names()` and then run some other operation on each
    table in the list, we want to ignore any `no_such_table_exc_t`s thrown by that
    operation.

 2. `table_meta_client_t` usually doesn't have access to the name of the table. The
    caller will typically catch the exception at a point where the table name is known
    and then produce a user-readable error message that includes the table name.

 3. `table_meta_client_t` often doesn't have enough context to produce an optimal error
    message. The caller will typically add more context when it catches the exception and
    forwards it to the user. For example, instead of saying "the table's configuration
    was not modified" it can say "the secondary index was not renamed".

Note that the exception descriptions here are mostly just for documentation; unless there
is a bug, they will never be shown to the user. */

class no_such_table_exc_t : public std::runtime_error {
public:
    no_such_table_exc_t() :
        std::runtime_error("there is no table with the given name / UUID") { }
};

class ambiguous_table_exc_t : public std::runtime_error {
public:
    ambiguous_table_exc_t() :
        std::runtime_error("there are multiple tables with the given name") { }
};

class failed_table_op_exc_t : public std::runtime_error {
public:
    failed_table_op_exc_t() : std::runtime_error("the attempt to read or modify the "
        "table's configuration failed because none of the servers were accessible. if "
        "it was an attempt to modify, the modification did not take place.") { }
};

class maybe_failed_table_op_exc_t : public std::runtime_error {
public:
    maybe_failed_table_op_exc_t() : std::runtime_error("the attempt to modify the "
        "table's configuration failed because we lost contact with the servers after "
        "initiating the modification, or the Raft leader lost contact with its "
        "followers, or we timed out while waiting for the changes to propagate. the "
        "modification may or may not have taken place.") { }
};

/* `table_meta_client_t` is responsible for submitting client requests over the network
to the `multi_table_manager_t`. It doesn't have any real state of its own; it's just a
convenient way of bundling together all of the objects that are necessary for submitting
a client request. */
class table_meta_client_t :
    public home_thread_mixin_t {
public:
    table_meta_client_t(
        mailbox_manager_t *_mailbox_manager,
        multi_table_manager_t *_multi_table_manager,
        watchable_map_t<peer_id_t, multi_table_manager_bcard_t>
            *_multi_table_manager_directory,
        watchable_map_t<std::pair<peer_id_t, namespace_id_t>, table_manager_bcard_t>
            *_table_manager_directory);

    /* All of these functions can be called from any thread. */

    /* `find()` determines the ID of the table with the given name in the given database.
    */
    void find(
        const database_id_t &database, const name_string_t &name,
        namespace_id_t *table_id_out, std::string *primary_key_out = nullptr)
        THROWS_ONLY(no_such_table_exc_t, ambiguous_table_exc_t);

    /* `exists()` returns `true` if one or more tables exist with the given name in the
    given database. */
    bool exists(const database_id_t &database, const name_string_t &name);

    /* `get_name()` determines the name, database, and primary key of the table with the
    given ID; it's the reverse of `find()`. It returns `false` if there is no existing
    table with that ID. `get_name()` will not block. */
    void get_name(
        const namespace_id_t &table_id,
        table_basic_config_t *basic_config_out)
        THROWS_ONLY(no_such_table_exc_t);

    /* `list_names()` determines the IDs, names, databases, and primary keys of every
    table. It will not block. */
    void list_names(
        std::map<namespace_id_t, table_basic_config_t> *names_out);

    /* `get_config()` fetches the configuration of the table with the given ID. It may
    block and it may fail. */
    void get_config(
        const namespace_id_t &table_id,
        signal_t *interruptor,
        table_config_and_shards_t *config_out)
        THROWS_ONLY(interrupted_exc_t, no_such_table_exc_t, failed_table_op_exc_t);

    /* `list_configs()` fetches the configurations of every table at once. It may block.
    */
    void list_configs(
        signal_t *interruptor,
        std::map<namespace_id_t, table_config_and_shards_t> *configs_out)
        THROWS_ONLY(interrupted_exc_t, failed_table_op_exc_t);

    /* `get_status()` returns the secondary index status of the table with the given ID.
    It may block. */
    void get_status(
        const namespace_id_t &table_id,
        signal_t *interruptor,
        std::map<std::string, std::pair<sindex_config_t, sindex_status_t> >
            *index_statuses_out,
        std::map<peer_id_t, contracts_and_contract_acks_t> *contracts_and_acks_out)
        THROWS_ONLY(interrupted_exc_t, no_such_table_exc_t, failed_table_op_exc_t);

    /* `create()` creates a table with the given configuration. It sets `*table_id_out`
    to the ID of the newly generated table. It may block. If it returns successfully, the
    change will be visible in `find()`, etc. */
    void create(
        namespace_id_t new_table_id,
        const table_config_and_shards_t &new_config,
        signal_t *interruptor)
        THROWS_ONLY(interrupted_exc_t, failed_table_op_exc_t,
            maybe_failed_table_op_exc_t);

    /* `drop()` drops the table with the given ID. It may block. If it returns `false`,
    the change may or may not have succeeded. If it returns successfully, the change will
    be visible in `find()`, etc. */
    void drop(
        const namespace_id_t &table_id,
        signal_t *interruptor)
        THROWS_ONLY(interrupted_exc_t, no_such_table_exc_t, failed_table_op_exc_t,
            maybe_failed_table_op_exc_t);

    /* `set_config()` changes the configuration of the table with the given ID. It may
    block. If it returns successfully, the change will be visible in `find()`, etc. */
    void set_config(
        const namespace_id_t &table_id,
        const table_config_and_shards_t &new_config,
        signal_t *interruptor)
        THROWS_ONLY(interrupted_exc_t, no_such_table_exc_t, failed_table_op_exc_t,
            maybe_failed_table_op_exc_t);

private:
    typedef std::pair<table_basic_config_t, multi_table_manager_bcard_t::timestamp_t>
        timestamped_basic_config_t;

    [[noreturn]] void throw_appropriate_exception(const namespace_id_t &table_id)
        THROWS_ONLY(no_such_table_exc_t, failed_table_op_exc_t);

    void wait_until_change_visible(
        const namespace_id_t &table_id,
        const std::function<bool(const timestamped_basic_config_t *)> &cb,
        signal_t *interruptor)
        THROWS_ONLY(interrupted_exc_t, maybe_failed_table_op_exc_t);

    mailbox_manager_t *const mailbox_manager;
    multi_table_manager_t *const multi_table_manager;
    watchable_map_t<peer_id_t, multi_table_manager_bcard_t>
        *const multi_table_manager_directory;
    watchable_map_t<std::pair<peer_id_t, namespace_id_t>, table_manager_bcard_t>
        *const table_manager_directory;

    /* `table_basic_configs` distributes the `table_basic_config_t`s from the
    `multi_table_manager_t` to each thread, so that `find()`, `get_name()`, and
    `list_names()` can run without blocking. */
    all_thread_watchable_map_var_t<namespace_id_t, timestamped_basic_config_t>
        table_basic_configs;
};

#endif /* CLUSTERING_TABLE_MANAGER_TABLE_META_CLIENT_HPP_ */

<|endoftext|>


<commit_before>// str.cpp            see license.txt for copyright and terms of use
// code for str.h
// Scott McPeak, 1995-2000  This file is public domain.

#include "str.h"            // this module

#include <stdlib.h>         // atoi
#include <stdio.h>          // sprintf
#include <ctype.h>          // isspace
#include <string.h>         // strcmp
#include <iostream.h>       // ostream << char*
#include <assert.h>         // assert
#include <unistd.h>         // write

#include "xassert.h"        // xassert
#include "ckheap.h"         // checkHeapNode
#include "flatten.h"        // Flatten
#include "nonport.h"        // vnprintf
#include "array.h"          // Array

// ----------------------- string ---------------------

// put the empty string itself in read-only memory
char const nul_byte = 0;

// deliberately cast away the constness; I cannot declare
// 'emptyString' to be const because it gets assigned to 's', but it
// is nevertheless the intent that I never modify 'nul_byte'
char * const string::emptyString = const_cast<char*>(&nul_byte);

string::string(char const *src, int length, SmbaseStringFunc)
{
  s=emptyString;
  setlength(length);       // setlength already has the +1; sets final NUL
  memcpy(s, src, length);
}

void string::dup(char const *src)
{
  // std::string does not accept NULL pointers
  xassert(src != NULL);

  if (src[0]==0) {
    s = emptyString;
  }
  else {
    s = new char[ strlen(src) + 1 ];
    xassert(s);
    strcpy(s, src);
  }
}

void string::kill()
{
  if (s != emptyString) {
    delete[] s;         // found by Coverity Prevent
  }
}

string::string(Flatten&)
  : s(emptyString)
{}

void string::xfer(Flatten &flat)
{
  flat.xferCharString(s);
}

int string::length() const
{
  xassert(s);
  return strlen(s);
}

bool string::contains(char c) const
{
  xassert(s);
  return !!strchr(s, c);
}

string string::substring(int startIndex, int len) const
{
  xassert(startIndex >= 0 &&
          len >= 0 &&
          startIndex + len <= length());

  return ::substring(s+startIndex, len);
}

string &string::setlength(int length)
{
  kill();
  if (length > 0) {
    s = new char[ length+1 ];
    xassert(s);
    s[length] = 0;      // final NUL in expectation of 'length' chars
    s[0] = 0;           // in case we just wanted to set allocated length
  }
  else {
    xassert(length == 0);     // negative wouldn't make sense
    s = emptyString;
  }
  return *this;
}

int string::compareTo(string const &src) const
{
  return compareTo(src.s);
}

int string::compareTo(char const *src) const
{
  if (src == NULL) {
    src = emptyString;
  }
  return strcmp(s, src);
}

string string::operator&(string const &tail) const
{
  string dest(length() + tail.length(), SMBASE_STRING_FUNC);
  strcpy(dest.s, s);
  strcat(dest.s, tail.s);
  return dest;
}

string& string::operator&=(string const &tail)
{
  return *this = *this & tail;
}

void string::readdelim(istream &is, char const *delim)
{
  stringBuilder sb;
  sb.readdelim(is, delim);
  operator= (sb);
}

void string::write(ostream &os) const
{
  os << s;     // standard char* writing routine
}

void string::selfCheck() const
{
  if (s != emptyString) {
    checkHeapNode(s);
  }
}

// ----------------------- rostring ---------------------
int strcmp(rostring s1, rostring s2)
  { return strcmp(s1.c_str(), s2.c_str()); }
int strcmp(rostring s1, char const *s2)
  { return strcmp(s1.c_str(), s2); }
int strcmp(char const *s1, rostring s2)
  { return strcmp(s1, s2.c_str()); }

char const *strstr(rostring haystack, char const *needle)
{
  return strstr(haystack.c_str(), needle);
}

int atoi(rostring s)
{
  return atoi(toCStr(s));
}

string substring(char const *p, int n)
{
  return string(p, n, SMBASE_STRING_FUNC);
}

// --------------------- stringBuilder ------------------
stringBuilder::stringBuilder(int len)
{
  init(len);
}

void stringBuilder::init(int initSize)
{
  size = initSize + EXTRA_SPACE + 1;     // +1 to be like string::setlength
  s = new char[size];
  end = s;
  end[initSize] = 0;
}

void stringBuilder::dup(char const *str)
{
  int len = strlen(str);
  init(len);
  strcpy(s, str);
  end += len;
}

stringBuilder::stringBuilder(char const *str)
{
  dup(str);
}

stringBuilder::stringBuilder(char const *str, int len)
{
  init(len);
  memcpy(s, str, len);
  end += len;
}

stringBuilder& stringBuilder::operator=(char const *src)
{
  if (s != src) {
    kill();
    dup(src);
  }
  return *this;
}

stringBuilder& stringBuilder::setlength(int newlen)
{
  kill();
  init(newlen);
  return *this;
}

void stringBuilder::adjustend(char* newend)
{
  xassert(s <= newend  &&  newend < s + size);

  end = newend;
  *end = 0;        // sm 9/29/00: maintain invariant
}

void stringBuilder::truncate(int newLength)
{
  xassert(0 <= newLength && newLength <= length());
  adjustend(s + newLength);
}

stringBuilder& stringBuilder::operator&= (char const *tail)
{
  append(tail, strlen(tail));
  return *this;
}

void stringBuilder::append(char const *tail, int len)
{
  ensure(length() + len);

  memcpy(end, tail, len);
  end += len;
  *end = 0;
}

stringBuilder& stringBuilder::indent(int amt)
{
  xassert(amt >= 0);
  ensure(length() + amt);

  memset(end, ' ', amt);
  end += amt;
  *end = 0;

  return *this;
}

void stringBuilder::grow(int newMinLength)
{
  // I want at least EXTRA_SPACE extra
  int newMinSize = newMinLength + EXTRA_SPACE + 1;         // compute resulting allocated size

  // I want to grow at the rate of at least 50% each time
  int suggest = size * 3 / 2;

  // see which is bigger
  newMinSize = max(newMinSize, suggest);

  // remember old length..
  int len = length();

  // realloc s to be newMinSize bytes
  char *temp = new char[newMinSize];
  xassert(len+1 <= newMinSize);    // prevent overrun
  memcpy(temp, s, len+1);          // copy null too
  delete[] s;
  s = temp;

  // adjust other variables
  end = s + len;
  size = newMinSize;
}

stringBuilder& stringBuilder::operator<< (char c)
{
  ensure(length() + 1);
  *(end++) = c;
  *end = 0;
  return *this;
}

#define MAKE_LSHIFT(Argtype, fmt)                        \
  stringBuilder& stringBuilder::operator<< (Argtype arg) \
  {                                                      \
    char buf[60];      /* big enough for all types */    \
    int len = sprintf(buf, fmt, arg);                    \
    if (len >= 60) {					 \
      abort();    /* too big */                          \
    }                                                    \
    return *this << buf;                                 \
  }

MAKE_LSHIFT(long, "%ld")
MAKE_LSHIFT(unsigned long, "%lu")
MAKE_LSHIFT(double, "%g")
MAKE_LSHIFT(void*, "%p")

#undef MAKE_LSHIFT

stringBuilder& stringBuilder::operator<< (
  stringBuilder::Hex const &h)
{
  char buf[32];        // should only need 19 for 64-bit word..
  int len = sprintf(buf, "0x%lX", h.value);
  if (len >= 20) {
    abort();
  }
  return *this << buf;

  // the length check above isn't perfect because we only find out there is
  // a problem *after* trashing the environment.  it is for this reason I
  // use 'assert' instead of 'xassert' -- the former calls abort(), while the
  // latter throws an exception in anticipation of recoverability
}

stringBuilder& stringBuilder::operator<< (Manipulator manip)
{
  return manip(*this);
}

// slow but reliable
void stringBuilder::readdelim(istream &is, char const *delim)
{
  char c;
  is.get(c);
  while (!is.eof() &&
         (!delim || !strchr(delim, c))) {
    *this << c;
    is.get(c);
  }
}

// ---------------------- toString ---------------------
#define TOSTRING(type)        \
  string toString(type val)   \
  {                           \
    return stringc << val;    \
  }

TOSTRING(int)
TOSTRING(unsigned)
TOSTRING(char)
TOSTRING(long)
TOSTRING(float)

#undef TOSTRING

// this one is more liberal than 'stringc << null' because it gets
// used by the PRINT_GENERIC macro in my astgen tool
string toString(char const *str)
{
  if (!str) {
    return string("(null)");
  }
  else {
    return string(str);
  }
}

// ------------------- stringf -----------------
string stringf(char const *format, ...)
{
  va_list args;
  va_start(args, format);
  string ret = vstringf(format, args);
  va_end(args);
  return ret;
}

// this should eventually be put someplace more general...
#ifndef va_copy
  #ifdef __va_copy
    #define va_copy(a,b) __va_copy(a,b)
  #else
    #define va_copy(a,b) (a)=(b)
  #endif
#endif

string vstringf(char const *format, va_list args)
{
  // estimate string length
  va_list args2;
  va_copy(args2, args);
  int est = vnprintf(format, args2);
  va_end(args2);

  // allocate space
  Array<char> buf(est+1);

  // render the string
  int len = vsprintf(buf, format, args);

  // check the estimate, and fail *hard* if it was low, to avoid any
  // possibility that this might become exploitable in some context
  // (do *not* turn this check off in an NDEGUG build)
  if (len > est) {
    // don't go through fprintf, etc., because the state of memory
    // makes that risky
    static char const msg[] =
      "fatal error: vnprintf failed to provide a conservative estimate,\n"
      "memory is most likely corrupted\n";
    write(2 /*stderr*/, msg, strlen(msg));
    abort();
  }

  // happy
  return string(buf);
}

// ------------------ test code --------------------
#ifdef TEST_STR

#include <iostream.h>    // cout

void test(unsigned long val)
{
  //cout << stringb(val << " in hex: 0x" << stringBuilder::Hex(val)) << endl;

  cout << stringb(val << " in hex: " << SBHex(val)) << endl;
}

int main()
{
  // for the moment I just want to test the hex formatting
  test(64);
  test(0xFFFFFFFF);
  test(0);
  test((unsigned long)(-1));
  test(1);

  cout << "stringf: " << stringf("int=%d hex=%X str=%s char=%c float=%f",
                                 5, 0xAA, "hi", 'f', 3.4) << endl;

  cout << "tests passed\n";

  return 0;
}

#endif // TEST_STR
<commit_msg>Optimize stringBuilder::operator=: don't re-allocate buffer unless necessary.<commit_after>// str.cpp            see license.txt for copyright and terms of use
// code for str.h
// Scott McPeak, 1995-2000  This file is public domain.

#include "str.h"            // this module

#include <stdlib.h>         // atoi
#include <stdio.h>          // sprintf
#include <ctype.h>          // isspace
#include <string.h>         // strcmp
#include <iostream.h>       // ostream << char*
#include <assert.h>         // assert
#include <unistd.h>         // write

#include "xassert.h"        // xassert
#include "ckheap.h"         // checkHeapNode
#include "flatten.h"        // Flatten
#include "nonport.h"        // vnprintf
#include "array.h"          // Array

// ----------------------- string ---------------------

// put the empty string itself in read-only memory
char const nul_byte = 0;

// deliberately cast away the constness; I cannot declare
// 'emptyString' to be const because it gets assigned to 's', but it
// is nevertheless the intent that I never modify 'nul_byte'
char * const string::emptyString = const_cast<char*>(&nul_byte);

string::string(char const *src, int length, SmbaseStringFunc)
{
  s=emptyString;
  setlength(length);       // setlength already has the +1; sets final NUL
  memcpy(s, src, length);
}

void string::dup(char const *src)
{
  // std::string does not accept NULL pointers
  xassert(src != NULL);

  if (src[0]==0) {
    s = emptyString;
  }
  else {
    s = new char[ strlen(src) + 1 ];
    xassert(s);
    strcpy(s, src);
  }
}

void string::kill()
{
  if (s != emptyString) {
    delete[] s;         // found by Coverity Prevent
  }
}

string::string(Flatten&)
  : s(emptyString)
{}

void string::xfer(Flatten &flat)
{
  flat.xferCharString(s);
}

int string::length() const
{
  xassert(s);
  return strlen(s);
}

bool string::contains(char c) const
{
  xassert(s);
  return !!strchr(s, c);
}

string string::substring(int startIndex, int len) const
{
  xassert(startIndex >= 0 &&
          len >= 0 &&
          startIndex + len <= length());

  return ::substring(s+startIndex, len);
}

string &string::setlength(int length)
{
  kill();
  if (length > 0) {
    s = new char[ length+1 ];
    xassert(s);
    s[length] = 0;      // final NUL in expectation of 'length' chars
    s[0] = 0;           // in case we just wanted to set allocated length
  }
  else {
    xassert(length == 0);     // negative wouldn't make sense
    s = emptyString;
  }
  return *this;
}

int string::compareTo(string const &src) const
{
  return compareTo(src.s);
}

int string::compareTo(char const *src) const
{
  if (src == NULL) {
    src = emptyString;
  }
  return strcmp(s, src);
}

string string::operator&(string const &tail) const
{
  string dest(length() + tail.length(), SMBASE_STRING_FUNC);
  strcpy(dest.s, s);
  strcat(dest.s, tail.s);
  return dest;
}

string& string::operator&=(string const &tail)
{
  return *this = *this & tail;
}

void string::readdelim(istream &is, char const *delim)
{
  stringBuilder sb;
  sb.readdelim(is, delim);
  operator= (sb);
}

void string::write(ostream &os) const
{
  os << s;     // standard char* writing routine
}

void string::selfCheck() const
{
  if (s != emptyString) {
    checkHeapNode(s);
  }
}

// ----------------------- rostring ---------------------
int strcmp(rostring s1, rostring s2)
  { return strcmp(s1.c_str(), s2.c_str()); }
int strcmp(rostring s1, char const *s2)
  { return strcmp(s1.c_str(), s2); }
int strcmp(char const *s1, rostring s2)
  { return strcmp(s1, s2.c_str()); }

char const *strstr(rostring haystack, char const *needle)
{
  return strstr(haystack.c_str(), needle);
}

int atoi(rostring s)
{
  return atoi(toCStr(s));
}

string substring(char const *p, int n)
{
  return string(p, n, SMBASE_STRING_FUNC);
}

// --------------------- stringBuilder ------------------
stringBuilder::stringBuilder(int len)
{
  init(len);
}

void stringBuilder::init(int initSize)
{
  size = initSize + EXTRA_SPACE + 1;     // +1 to be like string::setlength
  s = new char[size];
  end = s;
  end[initSize] = 0;
}

void stringBuilder::dup(char const *str)
{
  int len = strlen(str);
  init(len);
  strcpy(s, str);
  end += len;
}

stringBuilder::stringBuilder(char const *str)
{
  dup(str);
}

stringBuilder::stringBuilder(char const *str, int len)
{
  init(len);
  memcpy(s, str, len);
  end += len;
}

stringBuilder& stringBuilder::operator=(char const *src)
{
#if 1
  // quarl 2006-06-01
  //    This implementation avoids re-allocation unless necessary.
  if (s != src) {
    int srclen = strlen(src)+1;
    if (srclen > size) { // need to re-allocate?
      delete s;
      s = new char[ srclen ];
    }
    xassert(s);
    memcpy(s, src, srclen); // copy string including NULL
    end = s + srclen - 1; // point to NULL
  }
  return *this;
#else
  if (s != src) {
    kill();
    dup(src);
  }
  return *this;
#endif
}

stringBuilder& stringBuilder::setlength(int newlen)
{
  kill();
  init(newlen);
  return *this;
}

void stringBuilder::adjustend(char* newend)
{
  xassert(s <= newend  &&  newend < s + size);

  end = newend;
  *end = 0;        // sm 9/29/00: maintain invariant
}

void stringBuilder::truncate(int newLength)
{
  xassert(0 <= newLength && newLength <= length());
  adjustend(s + newLength);
}

stringBuilder& stringBuilder::operator&= (char const *tail)
{
  append(tail, strlen(tail));
  return *this;
}

void stringBuilder::append(char const *tail, int len)
{
  ensure(length() + len);

  memcpy(end, tail, len);
  end += len;
  *end = 0;
}

stringBuilder& stringBuilder::indent(int amt)
{
  xassert(amt >= 0);
  ensure(length() + amt);

  memset(end, ' ', amt);
  end += amt;
  *end = 0;

  return *this;
}

void stringBuilder::grow(int newMinLength)
{
  // I want at least EXTRA_SPACE extra
  int newMinSize = newMinLength + EXTRA_SPACE + 1;         // compute resulting allocated size

  // I want to grow at the rate of at least 50% each time
  int suggest = size * 3 / 2;

  // see which is bigger
  newMinSize = max(newMinSize, suggest);

  // remember old length..
  int len = length();

  // realloc s to be newMinSize bytes
  char *temp = new char[newMinSize];
  xassert(len+1 <= newMinSize);    // prevent overrun
  memcpy(temp, s, len+1);          // copy null too
  delete[] s;
  s = temp;

  // adjust other variables
  end = s + len;
  size = newMinSize;
}

stringBuilder& stringBuilder::operator<< (char c)
{
  ensure(length() + 1);
  *(end++) = c;
  *end = 0;
  return *this;
}

#define MAKE_LSHIFT(Argtype, fmt)                        \
  stringBuilder& stringBuilder::operator<< (Argtype arg) \
  {                                                      \
    char buf[60];      /* big enough for all types */    \
    int len = sprintf(buf, fmt, arg);                    \
    if (len >= 60) {					 \
      abort();    /* too big */                          \
    }                                                    \
    return *this << buf;                                 \
  }

MAKE_LSHIFT(long, "%ld")
MAKE_LSHIFT(unsigned long, "%lu")
MAKE_LSHIFT(double, "%g")
MAKE_LSHIFT(void*, "%p")

#undef MAKE_LSHIFT

stringBuilder& stringBuilder::operator<< (
  stringBuilder::Hex const &h)
{
  char buf[32];        // should only need 19 for 64-bit word..
  int len = sprintf(buf, "0x%lX", h.value);
  if (len >= 20) {
    abort();
  }
  return *this << buf;

  // the length check above isn't perfect because we only find out there is
  // a problem *after* trashing the environment.  it is for this reason I
  // use 'assert' instead of 'xassert' -- the former calls abort(), while the
  // latter throws an exception in anticipation of recoverability
}

stringBuilder& stringBuilder::operator<< (Manipulator manip)
{
  return manip(*this);
}

// slow but reliable
void stringBuilder::readdelim(istream &is, char const *delim)
{
  char c;
  is.get(c);
  while (!is.eof() &&
         (!delim || !strchr(delim, c))) {
    *this << c;
    is.get(c);
  }
}

// ---------------------- toString ---------------------
#define TOSTRING(type)        \
  string toString(type val)   \
  {                           \
    return stringc << val;    \
  }

TOSTRING(int)
TOSTRING(unsigned)
TOSTRING(char)
TOSTRING(long)
TOSTRING(float)

#undef TOSTRING

// this one is more liberal than 'stringc << null' because it gets
// used by the PRINT_GENERIC macro in my astgen tool
string toString(char const *str)
{
  if (!str) {
    return string("(null)");
  }
  else {
    return string(str);
  }
}

// ------------------- stringf -----------------
string stringf(char const *format, ...)
{
  va_list args;
  va_start(args, format);
  string ret = vstringf(format, args);
  va_end(args);
  return ret;
}

// this should eventually be put someplace more general...
#ifndef va_copy
  #ifdef __va_copy
    #define va_copy(a,b) __va_copy(a,b)
  #else
    #define va_copy(a,b) (a)=(b)
  #endif
#endif

string vstringf(char const *format, va_list args)
{
  // estimate string length
  va_list args2;
  va_copy(args2, args);
  int est = vnprintf(format, args2);
  va_end(args2);

  // allocate space
  Array<char> buf(est+1);

  // render the string
  int len = vsprintf(buf, format, args);

  // check the estimate, and fail *hard* if it was low, to avoid any
  // possibility that this might become exploitable in some context
  // (do *not* turn this check off in an NDEGUG build)
  if (len > est) {
    // don't go through fprintf, etc., because the state of memory
    // makes that risky
    static char const msg[] =
      "fatal error: vnprintf failed to provide a conservative estimate,\n"
      "memory is most likely corrupted\n";
    write(2 /*stderr*/, msg, strlen(msg));
    abort();
  }

  // happy
  return string(buf);
}

// ------------------ test code --------------------
#ifdef TEST_STR

#include <iostream.h>    // cout

void test(unsigned long val)
{
  //cout << stringb(val << " in hex: 0x" << stringBuilder::Hex(val)) << endl;

  cout << stringb(val << " in hex: " << SBHex(val)) << endl;
}

int main()
{
  // for the moment I just want to test the hex formatting
  test(64);
  test(0xFFFFFFFF);
  test(0);
  test((unsigned long)(-1));
  test(1);

  cout << "stringf: " << stringf("int=%d hex=%X str=%s char=%c float=%f",
                                 5, 0xAA, "hi", 'f', 3.4) << endl;

  cout << "tests passed\n";

  return 0;
}

#endif // TEST_STR
<|endoftext|>


<commit_before>//! @Alan
//!
//! Exercise 11.9:
//! Define a map that associates words with a list of
//! line numbers on which the word might occur.
//!
//! Exercise 11.10:
//! Could we define a map from vector<int>::iterator
//! to int? What about from list<int>::iterator to int?
//! In each case, if not, why not?
//  vector<int>::iterator to int is ok ,because < is defined
//  vector<int>::iterator to int is not ok,as no < is defined.
#include <iostream>
#include <map>
#include <string>
#include <algorithm>
#include <list>

int main()
{
    //! ex 11.9
    std::map<std::string, std::list<std::size_t>> m;

    //! ex 11.10
    //! can be declared.
    std::map<std::vector<int>::iterator, int> mv;
    std::map<std::list<int>::iterator, int> ml;

    std::vector<int> vi;
    mv.insert(std::pair<std::vector<int>::iterator, int>(vi.begin(),0));

    //! but when using this one the compiler complained that
    //! error: no match for 'operator<' in '__x < __y'
    std::list<int> li;
    ml.insert(std::pair<std::list<int>::iterator,int>(li.begin(),0));

    return 0;
}

<commit_msg>fix error<commit_after>//! @Alan
//!
//! Exercise 11.9:
//! Define a map that associates words with a list of
//! line numbers on which the word might occur.
//!
//! Exercise 11.10:
//! Could we define a map from vector<int>::iterator
//! to int? What about from list<int>::iterator to int?
//! In each case, if not, why not?
//  vector<int>::iterator to int is ok ,because < is defined
//  list<int>::iterator to int is not ok,as no < is defined.
#include <iostream>
#include <map>
#include <string>
#include <algorithm>
#include <list>

int main()
{
    //! ex 11.9
    std::map<std::string, std::list<std::size_t>> m;

    //! ex 11.10
    //! can be declared.
    std::map<std::vector<int>::iterator, int> mv;
    std::map<std::list<int>::iterator, int> ml;

    std::vector<int> vi;
    mv.insert(std::pair<std::vector<int>::iterator, int>(vi.begin(),0));

    //! but when using this one the compiler complained that
    //! error: no match for 'operator<' in '__x < __y'
    std::list<int> li;
    ml.insert(std::pair<std::list<int>::iterator,int>(li.begin(),0));

    return 0;
}

<|endoftext|>


<commit_before>//
// ogles_gpgpu project - GPGPU for mobile devices and embedded systems using OpenGL ES 2.0
//
// Author: Markus Konrad <post@mkonrad.net>, Winter 2014/2015
// http://www.mkonrad.net
//
// See LICENSE file in project repository root for the license.
//

#include "../common_includes.h"
#include "grad.h"

using namespace std;
using namespace ogles_gpgpu;

const char *GradProc::fshaderGradSrc = OG_TO_STR
(
#if defined(OGLES_GPGPU_OPENGLES)
precision highp float;
#endif

 varying vec2 textureCoordinate;
 varying vec2 leftTextureCoordinate;
 varying vec2 rightTextureCoordinate;

 varying vec2 topTextureCoordinate;
 varying vec2 topLeftTextureCoordinate;
 varying vec2 topRightTextureCoordinate;

 varying vec2 bottomTextureCoordinate;
 varying vec2 bottomLeftTextureCoordinate;
 varying vec2 bottomRightTextureCoordinate;

 uniform sampler2D inputImageTexture;

 uniform float strength;

 void main()
 {
     float bottomLeftIntensity = texture2D(inputImageTexture, bottomLeftTextureCoordinate).r;
     float topRightIntensity = texture2D(inputImageTexture, topRightTextureCoordinate).r;
     float topLeftIntensity = texture2D(inputImageTexture, topLeftTextureCoordinate).r;
     float bottomRightIntensity = texture2D(inputImageTexture, bottomRightTextureCoordinate).r;
     float leftIntensity = texture2D(inputImageTexture, leftTextureCoordinate).r;
     float rightIntensity = texture2D(inputImageTexture, rightTextureCoordinate).r;
     float bottomIntensity = texture2D(inputImageTexture, bottomTextureCoordinate).r;
     float topIntensity = texture2D(inputImageTexture, topTextureCoordinate).r;
     float y = -topLeftIntensity - (2.0 * topIntensity) - topRightIntensity + bottomLeftIntensity + (2.0 * bottomIntensity) + bottomRightIntensity;
     float x = -bottomLeftIntensity - (2.0 * leftIntensity) - topLeftIntensity + bottomRightIntensity + (2.0 * rightIntensity) + topRightIntensity;

     y = y / 8.0;
     x = x / 8.0;

     //y = (bottomIntensity - topIntensity) / 2.0;
     //x = (rightIntensity - leftIntensity) / 2.0;

     float mag = length(vec2(x, y));
     float theta = atan(y, x);
     if(theta < 0.0)
     {
         theta = theta + 3.14159;
     }

     float dx = (x + 1.0) / 2.0;
     float dy = (y + 1.0) / 2.0;

     mag = clamp(mag * strength, 0.0, 1.0);

     //gl_FragColor = vec4(mag, mag, mag, 1.0);
     //gl_FragColor = vec4(bottomLeftIntensity,bottomLeftIntensity,bottomLeftIntensity,1.0);
     gl_FragColor = vec4(mag, theta/3.14159, clamp(dx, 0.0, 1.0), clamp(dy, 0.0, 1.0));
 }
 );

GradProc::GradProc(float strength) : strength(strength) {

}

void GradProc::setUniforms() {
    Filter3x3Proc::setUniforms();
    glUniform1f(shParamUStrength, strength);
}

void GradProc::getUniforms() {
    Filter3x3Proc::getUniforms();
    shParamUInputTex = shader->getParam(UNIF, "inputImageTexture");
    shParamUStrength = shader->getParam(UNIF, "strength");
}
<commit_msg>added pi constant; don't clamp the magnitude in the output texture<commit_after>//
// ogles_gpgpu project - GPGPU for mobile devices and embedded systems using OpenGL ES 2.0
//
// Author: Markus Konrad <post@mkonrad.net>, Winter 2014/2015
// http://www.mkonrad.net
//
// See LICENSE file in project repository root for the license.
//

#include "../common_includes.h"
#include "grad.h"

using namespace std;
using namespace ogles_gpgpu;

const char *GradProc::fshaderGradSrc = OG_TO_STR
(
#if defined(OGLES_GPGPU_OPENGLES)
precision highp float;
#endif

 varying vec2 textureCoordinate;
 varying vec2 leftTextureCoordinate;
 varying vec2 rightTextureCoordinate;

 varying vec2 topTextureCoordinate;
 varying vec2 topLeftTextureCoordinate;
 varying vec2 topRightTextureCoordinate;

 varying vec2 bottomTextureCoordinate;
 varying vec2 bottomLeftTextureCoordinate;
 varying vec2 bottomRightTextureCoordinate;

 uniform sampler2D inputImageTexture;

 uniform float strength;

 const float pi = 3.14159265359;

 void main()
 {
     float bottomLeftIntensity = texture2D(inputImageTexture, bottomLeftTextureCoordinate).r;
     float topRightIntensity = texture2D(inputImageTexture, topRightTextureCoordinate).r;
     float topLeftIntensity = texture2D(inputImageTexture, topLeftTextureCoordinate).r;
     float bottomRightIntensity = texture2D(inputImageTexture, bottomRightTextureCoordinate).r;
     float leftIntensity = texture2D(inputImageTexture, leftTextureCoordinate).r;
     float rightIntensity = texture2D(inputImageTexture, rightTextureCoordinate).r;
     float bottomIntensity = texture2D(inputImageTexture, bottomTextureCoordinate).r;
     float topIntensity = texture2D(inputImageTexture, topTextureCoordinate).r;
     float y = -topLeftIntensity - (2.0 * topIntensity) - topRightIntensity + bottomLeftIntensity + (2.0 * bottomIntensity) + bottomRightIntensity;
     float x = -bottomLeftIntensity - (2.0 * leftIntensity) - topLeftIntensity + bottomRightIntensity + (2.0 * rightIntensity) + topRightIntensity;

     y = y / 8.0;
     x = x / 8.0;

     //y = (bottomIntensity - topIntensity) / 2.0;
     //x = (rightIntensity - leftIntensity) / 2.0;

     float mag = length(vec2(x, y));
     float theta = atan(y, x);
     if(theta < 0.0)
     {
         theta = theta + pi;
     }

     float dx = (x + 1.0) / 2.0;
     float dy = (y + 1.0) / 2.0;

     //gl_FragColor = vec4(mag, mag, mag, 1.0);
     //gl_FragColor = vec4(bottomLeftIntensity,bottomLeftIntensity,bottomLeftIntensity,1.0);
     gl_FragColor = vec4(mag, clamp(theta/pi, 0.0, 1.0), clamp(dx, 0.0, 1.0), clamp(dy, 0.0, 1.0));
 }
 );

GradProc::GradProc(float strength) : strength(strength) {

}

void GradProc::setUniforms() {
    Filter3x3Proc::setUniforms();
    glUniform1f(shParamUStrength, strength);
}

void GradProc::getUniforms() {
    Filter3x3Proc::getUniforms();
    shParamUInputTex = shader->getParam(UNIF, "inputImageTexture");
    shParamUStrength = shader->getParam(UNIF, "strength");
}
<|endoftext|>