<commit_before>/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2009 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 "filesearch.h"
#include <cctype>

#include <QtCore/QIODevice>
#include <QtCore/QBuffer>
#include <QtCore/QFile>
#include <QtCore/QFutureInterface>
#include <QtCore/QtConcurrentRun>
#include <QtCore/QRegExp>
#include <QtCore/QCoreApplication>

#include <qtconcurrent/runextensions.h>

using namespace Utils;

static inline QString msgCanceled(const QString &searchTerm, int numMatches, int numFilesSearched)
{
    return QCoreApplication::translate("Utils::FileSearch",
                                       "%1: canceled. %n occurrences found in %2 files.",
                                       0, QCoreApplication::CodecForTr, numMatches).
                                       arg(searchTerm).arg(numFilesSearched);
}

static inline QString msgFound(const QString &searchTerm, int numMatches, int numFilesSearched)
{
    return QCoreApplication::translate("Utils::FileSearch",
                                       "%1: %n occurrences found in %2 files.",
                                       0, QCoreApplication::CodecForTr, numMatches).
                                       arg(searchTerm).arg(numFilesSearched);
}

static inline QString msgFound(const QString &searchTerm, int numMatches, int numFilesSearched, int filesSize)
{
    return QCoreApplication::translate("Utils::FileSearch",
                                       "%1: %n occurrences found in %2 of %3 files.",
                                       0, QCoreApplication::CodecForTr, numMatches).
                                       arg(searchTerm).arg(numFilesSearched).arg(filesSize);
}

namespace {

void runFileSearch(QFutureInterface<FileSearchResult> &future,
                   QString searchTerm,
                   QStringList files,
                   QTextDocument::FindFlags flags,
                   QMap<QString, QString> fileToContentsMap)
{
    future.setProgressRange(0, files.size());
    int numFilesSearched = 0;
    int numMatches = 0;

    bool caseInsensitive = !(flags & QTextDocument::FindCaseSensitively);
    bool wholeWord = (flags & QTextDocument::FindWholeWords);

    QByteArray sa = searchTerm.toUtf8();
    int scMaxIndex = sa.length()-1;
    const char *sc = sa.constData();

    QByteArray sal = searchTerm.toLower().toUtf8();
    const char *scl = sal.constData();

    QByteArray sau = searchTerm.toUpper().toUtf8();
    const char *scu = sau.constData();

    int chunkSize = qMax(100000, sa.length());

    QFile file;
    QBuffer buffer;
    foreach (const QString &s, files) {
        if (future.isPaused())
            future.waitForResume();
        if (future.isCanceled()) {
            future.setProgressValueAndText(numFilesSearched, msgCanceled(searchTerm, numMatches, numFilesSearched));
            break;
        }
        QIODevice *device;
        if (fileToContentsMap.contains(s)) {
            buffer.setData(fileToContentsMap.value(s).toLocal8Bit());
            device = &buffer;
        } else {
            file.setFileName(s);
            device = &file;
        }
        if (!device->open(QIODevice::ReadOnly))
            continue;
        int lineNr = 1;
        const char *startOfLastLine = NULL;

        bool firstChunk = true;
        while (!device->atEnd()) {
            if (!firstChunk)
                device->seek(device->pos()-sa.length()+1);

            const QByteArray chunk = device->read(chunkSize);
            const char *chunkPtr = chunk.constData();
            startOfLastLine = chunkPtr;
            for (const char *regionPtr = chunkPtr; regionPtr < chunkPtr + chunk.length()-scMaxIndex; ++regionPtr) {
                const char *regionEnd = regionPtr + scMaxIndex;

                if (*regionPtr == '\n') {
                    startOfLastLine = regionPtr + 1;
                    ++lineNr;
                }
                else if (
                        // case sensitive
                        (!caseInsensitive && *regionPtr == sc[0] && *regionEnd == sc[scMaxIndex])
                        ||
                        // case insensitive
                        (caseInsensitive && (*regionPtr == scl[0] || *regionPtr == scu[0])
                        && (*regionEnd == scl[scMaxIndex] || *regionEnd == scu[scMaxIndex]))
                         ) {
                    const char *afterRegion = regionEnd + 1;
                    const char *beforeRegion = regionPtr - 1;
                    bool equal = true;
                    if (wholeWord &&
                            (  isalnum(*beforeRegion)
                            || (*beforeRegion == '_')
                            || isalnum(*afterRegion)
                            || (*afterRegion == '_'))) {
                        equal = false;
                    }

                    int regionIndex = 1;
                    for (const char *regionCursor = regionPtr + 1; regionCursor < regionEnd; ++regionCursor, ++regionIndex) {
                        if (  // case sensitive
                              (!caseInsensitive && equal && *regionCursor != sc[regionIndex])
                              ||
                              // case insensitive
                              (caseInsensitive && equal && *regionCursor != sc[regionIndex] && *regionCursor != scl[regionIndex] && *regionCursor != scu[regionIndex])
                               ) {
                         equal = false;
                        }
                    }
                    if (equal) {
                        int textLength = chunk.length() - (startOfLastLine - chunkPtr);
                        if (textLength > 0) {
                            QByteArray res;
                            res.reserve(256);
                            int i = 0;
                            int n = 0;
                            while (startOfLastLine[i] != '\n' && startOfLastLine[i] != '\r' && i < textLength && n++ < 256)
                                res.append(startOfLastLine[i++]);
                            future.reportResult(FileSearchResult(s, lineNr, QString(res),
                                                          regionPtr - startOfLastLine, sa.length()));
                            ++numMatches;
                        }
                    }
                }
            }
            firstChunk = false;
        }
        ++numFilesSearched;
        future.setProgressValueAndText(numFilesSearched, msgFound(searchTerm, numMatches, numFilesSearched, files.size()));
        device->close();
    }
    if (!future.isCanceled())
        future.setProgressValueAndText(numFilesSearched, msgFound(searchTerm, numMatches, numFilesSearched));
}

void runFileSearchRegExp(QFutureInterface<FileSearchResult> &future,
                   QString searchTerm,
                   QStringList files,
                   QTextDocument::FindFlags flags,
                   QMap<QString, QString> fileToContentsMap)
{
    future.setProgressRange(0, files.size());
    int numFilesSearched = 0;
    int numMatches = 0;
    if (flags & QTextDocument::FindWholeWords)
        searchTerm = QString::fromLatin1("\\b%1\\b").arg(searchTerm);
    const Qt::CaseSensitivity caseSensitivity = (flags & QTextDocument::FindCaseSensitively) ? Qt::CaseSensitive : Qt::CaseInsensitive;
    const QRegExp expression(searchTerm, caseSensitivity);

    QFile file;
    QString str;
    QTextStream stream;
    foreach (const QString &s, files) {
        if (future.isPaused())
            future.waitForResume();
        if (future.isCanceled()) {
            future.setProgressValueAndText(numFilesSearched, msgCanceled(searchTerm, numMatches, numFilesSearched));
            break;
        }

        bool needsToCloseFile = false;
        if (fileToContentsMap.contains(s)) {
            str = fileToContentsMap.value(s);
            stream.setString(&str);
        } else {
            file.setFileName(s);
            if (!file.open(QIODevice::ReadOnly))
                continue;
            needsToCloseFile = true;
            stream.setDevice(&file);
        }
        int lineNr = 1;
        QString line;
        while (!stream.atEnd()) {
            line = stream.readLine();
            int pos = 0;
            while ((pos = expression.indexIn(line, pos)) != -1) {
                future.reportResult(FileSearchResult(s, lineNr, line,
                                              pos, expression.matchedLength()));
                pos += expression.matchedLength();
            }
            ++lineNr;
        }
        ++numFilesSearched;
        future.setProgressValueAndText(numFilesSearched, msgFound(searchTerm, numMatches, numFilesSearched, files.size()));
        if (needsToCloseFile)
            file.close();
    }
    if (!future.isCanceled())
        future.setProgressValueAndText(numFilesSearched, msgFound(searchTerm, numMatches, numFilesSearched));
}

} // namespace

QFuture<FileSearchResult> Utils::findInFiles(const QString &searchTerm, const QStringList &files,
    QTextDocument::FindFlags flags, QMap<QString, QString> fileToContentsMap)
{
    return QtConcurrent::run<FileSearchResult, QString, QStringList, QTextDocument::FindFlags, QMap<QString, QString> >
            (runFileSearch, searchTerm, files, flags, fileToContentsMap);
}

QFuture<FileSearchResult> Utils::findInFilesRegExp(const QString &searchTerm, const QStringList &files,
    QTextDocument::FindFlags flags, QMap<QString, QString> fileToContentsMap)
{
    return QtConcurrent::run<FileSearchResult, QString, QStringList, QTextDocument::FindFlags, QMap<QString, QString> >
            (runFileSearchRegExp, searchTerm, files, flags, fileToContentsMap);
}
<commit_msg>Fixed crash. Passing negative values to isalnum compiled with MSVC crashed.<commit_after>/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2009 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 "filesearch.h"
#include <cctype>

#include <QtCore/QIODevice>
#include <QtCore/QBuffer>
#include <QtCore/QFile>
#include <QtCore/QFutureInterface>
#include <QtCore/QtConcurrentRun>
#include <QtCore/QRegExp>
#include <QtCore/QCoreApplication>

#include <qtconcurrent/runextensions.h>

using namespace Utils;

static inline QString msgCanceled(const QString &searchTerm, int numMatches, int numFilesSearched)
{
    return QCoreApplication::translate("Utils::FileSearch",
                                       "%1: canceled. %n occurrences found in %2 files.",
                                       0, QCoreApplication::CodecForTr, numMatches).
                                       arg(searchTerm).arg(numFilesSearched);
}

static inline QString msgFound(const QString &searchTerm, int numMatches, int numFilesSearched)
{
    return QCoreApplication::translate("Utils::FileSearch",
                                       "%1: %n occurrences found in %2 files.",
                                       0, QCoreApplication::CodecForTr, numMatches).
                                       arg(searchTerm).arg(numFilesSearched);
}

static inline QString msgFound(const QString &searchTerm, int numMatches, int numFilesSearched, int filesSize)
{
    return QCoreApplication::translate("Utils::FileSearch",
                                       "%1: %n occurrences found in %2 of %3 files.",
                                       0, QCoreApplication::CodecForTr, numMatches).
                                       arg(searchTerm).arg(numFilesSearched).arg(filesSize);
}

namespace {

void runFileSearch(QFutureInterface<FileSearchResult> &future,
                   QString searchTerm,
                   QStringList files,
                   QTextDocument::FindFlags flags,
                   QMap<QString, QString> fileToContentsMap)
{
    future.setProgressRange(0, files.size());
    int numFilesSearched = 0;
    int numMatches = 0;

    bool caseInsensitive = !(flags & QTextDocument::FindCaseSensitively);
    bool wholeWord = (flags & QTextDocument::FindWholeWords);

    QByteArray sa = searchTerm.toUtf8();
    int scMaxIndex = sa.length()-1;
    const char *sc = sa.constData();

    QByteArray sal = searchTerm.toLower().toUtf8();
    const char *scl = sal.constData();

    QByteArray sau = searchTerm.toUpper().toUtf8();
    const char *scu = sau.constData();

    int chunkSize = qMax(100000, sa.length());

    QFile file;
    QBuffer buffer;
    foreach (const QString &s, files) {
        if (future.isPaused())
            future.waitForResume();
        if (future.isCanceled()) {
            future.setProgressValueAndText(numFilesSearched, msgCanceled(searchTerm, numMatches, numFilesSearched));
            break;
        }
        QIODevice *device;
        if (fileToContentsMap.contains(s)) {
            buffer.setData(fileToContentsMap.value(s).toLocal8Bit());
            device = &buffer;
        } else {
            file.setFileName(s);
            device = &file;
        }
        if (!device->open(QIODevice::ReadOnly))
            continue;
        int lineNr = 1;
        const char *startOfLastLine = NULL;

        bool firstChunk = true;
        while (!device->atEnd()) {
            if (!firstChunk)
                device->seek(device->pos()-sa.length()+1);

            const QByteArray chunk = device->read(chunkSize);
            const char *chunkPtr = chunk.constData();
            startOfLastLine = chunkPtr;
            for (const char *regionPtr = chunkPtr; regionPtr < chunkPtr + chunk.length()-scMaxIndex; ++regionPtr) {
                const char *regionEnd = regionPtr + scMaxIndex;

                if (*regionPtr == '\n') {
                    startOfLastLine = regionPtr + 1;
                    ++lineNr;
                }
                else if (
                        // case sensitive
                        (!caseInsensitive && *regionPtr == sc[0] && *regionEnd == sc[scMaxIndex])
                        ||
                        // case insensitive
                        (caseInsensitive && (*regionPtr == scl[0] || *regionPtr == scu[0])
                        && (*regionEnd == scl[scMaxIndex] || *regionEnd == scu[scMaxIndex]))
                         ) {
                    const char *afterRegion = regionEnd + 1;
                    const char *beforeRegion = regionPtr - 1;
                    bool equal = true;
                    if (wholeWord &&
                            (  isalnum((unsigned char)*beforeRegion)
                            || (*beforeRegion == '_')
                            || isalnum((unsigned char)*afterRegion)
                            || (*afterRegion == '_'))) {
                        equal = false;
                    }

                    int regionIndex = 1;
                    for (const char *regionCursor = regionPtr + 1; regionCursor < regionEnd; ++regionCursor, ++regionIndex) {
                        if (  // case sensitive
                              (!caseInsensitive && equal && *regionCursor != sc[regionIndex])
                              ||
                              // case insensitive
                              (caseInsensitive && equal && *regionCursor != sc[regionIndex] && *regionCursor != scl[regionIndex] && *regionCursor != scu[regionIndex])
                               ) {
                         equal = false;
                        }
                    }
                    if (equal) {
                        int textLength = chunk.length() - (startOfLastLine - chunkPtr);
                        if (textLength > 0) {
                            QByteArray res;
                            res.reserve(256);
                            int i = 0;
                            int n = 0;
                            while (startOfLastLine[i] != '\n' && startOfLastLine[i] != '\r' && i < textLength && n++ < 256)
                                res.append(startOfLastLine[i++]);
                            future.reportResult(FileSearchResult(s, lineNr, QString(res),
                                                          regionPtr - startOfLastLine, sa.length()));
                            ++numMatches;
                        }
                    }
                }
            }
            firstChunk = false;
        }
        ++numFilesSearched;
        future.setProgressValueAndText(numFilesSearched, msgFound(searchTerm, numMatches, numFilesSearched, files.size()));
        device->close();
    }
    if (!future.isCanceled())
        future.setProgressValueAndText(numFilesSearched, msgFound(searchTerm, numMatches, numFilesSearched));
}

void runFileSearchRegExp(QFutureInterface<FileSearchResult> &future,
                   QString searchTerm,
                   QStringList files,
                   QTextDocument::FindFlags flags,
                   QMap<QString, QString> fileToContentsMap)
{
    future.setProgressRange(0, files.size());
    int numFilesSearched = 0;
    int numMatches = 0;
    if (flags & QTextDocument::FindWholeWords)
        searchTerm = QString::fromLatin1("\\b%1\\b").arg(searchTerm);
    const Qt::CaseSensitivity caseSensitivity = (flags & QTextDocument::FindCaseSensitively) ? Qt::CaseSensitive : Qt::CaseInsensitive;
    const QRegExp expression(searchTerm, caseSensitivity);

    QFile file;
    QString str;
    QTextStream stream;
    foreach (const QString &s, files) {
        if (future.isPaused())
            future.waitForResume();
        if (future.isCanceled()) {
            future.setProgressValueAndText(numFilesSearched, msgCanceled(searchTerm, numMatches, numFilesSearched));
            break;
        }

        bool needsToCloseFile = false;
        if (fileToContentsMap.contains(s)) {
            str = fileToContentsMap.value(s);
            stream.setString(&str);
        } else {
            file.setFileName(s);
            if (!file.open(QIODevice::ReadOnly))
                continue;
            needsToCloseFile = true;
            stream.setDevice(&file);
        }
        int lineNr = 1;
        QString line;
        while (!stream.atEnd()) {
            line = stream.readLine();
            int pos = 0;
            while ((pos = expression.indexIn(line, pos)) != -1) {
                future.reportResult(FileSearchResult(s, lineNr, line,
                                              pos, expression.matchedLength()));
                pos += expression.matchedLength();
            }
            ++lineNr;
        }
        ++numFilesSearched;
        future.setProgressValueAndText(numFilesSearched, msgFound(searchTerm, numMatches, numFilesSearched, files.size()));
        if (needsToCloseFile)
            file.close();
    }
    if (!future.isCanceled())
        future.setProgressValueAndText(numFilesSearched, msgFound(searchTerm, numMatches, numFilesSearched));
}

} // namespace

QFuture<FileSearchResult> Utils::findInFiles(const QString &searchTerm, const QStringList &files,
    QTextDocument::FindFlags flags, QMap<QString, QString> fileToContentsMap)
{
    return QtConcurrent::run<FileSearchResult, QString, QStringList, QTextDocument::FindFlags, QMap<QString, QString> >
            (runFileSearch, searchTerm, files, flags, fileToContentsMap);
}

QFuture<FileSearchResult> Utils::findInFilesRegExp(const QString &searchTerm, const QStringList &files,
    QTextDocument::FindFlags flags, QMap<QString, QString> fileToContentsMap)
{
    return QtConcurrent::run<FileSearchResult, QString, QStringList, QTextDocument::FindFlags, QMap<QString, QString> >
            (runFileSearchRegExp, searchTerm, files, flags, fileToContentsMap);
}
<|endoftext|>


<commit_before>#include "Exception.hpp"
#include "MeshBoolean.hpp"
#include "libslic3r/TriangleMesh.hpp"
#include "libslic3r/TryCatchSignal.hpp"
#undef PI

// Include igl first. It defines "L" macro which then clashes with our localization
#include <igl/copyleft/cgal/mesh_boolean.h>
#undef L

// CGAL headers
#include <CGAL/Polygon_mesh_processing/corefinement.h>
#include <CGAL/Exact_integer.h>
#include <CGAL/Surface_mesh.h>
#include <CGAL/Polygon_mesh_processing/orient_polygon_soup.h>
#include <CGAL/Polygon_mesh_processing/repair.h>
#include <CGAL/Polygon_mesh_processing/remesh.h>
#include <CGAL/Polygon_mesh_processing/polygon_soup_to_polygon_mesh.h>
#include <CGAL/Polygon_mesh_processing/orientation.h>
#include <CGAL/Cartesian_converter.h>

namespace Slic3r {
namespace MeshBoolean {

using MapMatrixXfUnaligned = Eigen::Map<const Eigen::Matrix<float, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor | Eigen::DontAlign>>;
using MapMatrixXiUnaligned = Eigen::Map<const Eigen::Matrix<int,   Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor | Eigen::DontAlign>>;

TriangleMesh eigen_to_triangle_mesh(const EigenMesh &emesh)
{
    auto &VC = emesh.first; auto &FC = emesh.second;

    Pointf3s points(size_t(VC.rows()));
    std::vector<Vec3i> facets(size_t(FC.rows()));

    for (Eigen::Index i = 0; i < VC.rows(); ++i)
        points[size_t(i)] = VC.row(i);

    for (Eigen::Index i = 0; i < FC.rows(); ++i)
        facets[size_t(i)] = FC.row(i);

    TriangleMesh out{points, facets};
    out.require_shared_vertices();
    return out;
}

EigenMesh triangle_mesh_to_eigen(const TriangleMesh &mesh)
{
    EigenMesh emesh;
    emesh.first = MapMatrixXfUnaligned(mesh.its.vertices.front().data(),
                                       Eigen::Index(mesh.its.vertices.size()),
                                       3).cast<double>();

    emesh.second = MapMatrixXiUnaligned(mesh.its.indices.front().data(),
                                        Eigen::Index(mesh.its.indices.size()),
                                        3);
    return emesh;
}

void minus(EigenMesh &A, const EigenMesh &B)
{
    auto &[VA, FA] = A;
    auto &[VB, FB] = B;

    Eigen::MatrixXd VC;
    Eigen::MatrixXi FC;
    igl::MeshBooleanType boolean_type(igl::MESH_BOOLEAN_TYPE_MINUS);
    igl::copyleft::cgal::mesh_boolean(VA, FA, VB, FB, boolean_type, VC, FC);

    VA = std::move(VC); FA = std::move(FC);
}

void minus(TriangleMesh& A, const TriangleMesh& B)
{
    EigenMesh eA = triangle_mesh_to_eigen(A);
    minus(eA, triangle_mesh_to_eigen(B));
    A = eigen_to_triangle_mesh(eA);
}

void self_union(EigenMesh &A)
{
    EigenMesh result;
    auto &[V, F] = A;
    auto &[VC, FC] = result;

    igl::MeshBooleanType boolean_type(igl::MESH_BOOLEAN_TYPE_UNION);
    igl::copyleft::cgal::mesh_boolean(V, F, Eigen::MatrixXd(), Eigen::MatrixXi(), boolean_type, VC, FC);

    A = std::move(result);
}

void self_union(TriangleMesh& mesh)
{
    auto eM = triangle_mesh_to_eigen(mesh);
    self_union(eM);
    mesh = eigen_to_triangle_mesh(eM);
}

namespace cgal {

namespace CGALProc    = CGAL::Polygon_mesh_processing;
namespace CGALParams  = CGAL::Polygon_mesh_processing::parameters;

using EpecKernel = CGAL::Exact_predicates_exact_constructions_kernel;
using EpicKernel = CGAL::Exact_predicates_inexact_constructions_kernel;
using _EpicMesh = CGAL::Surface_mesh<EpicKernel::Point_3>;
using _EpecMesh = CGAL::Surface_mesh<EpecKernel::Point_3>;

struct CGALMesh { _EpicMesh m; };

// /////////////////////////////////////////////////////////////////////////////
// Converions from and to CGAL mesh
// /////////////////////////////////////////////////////////////////////////////

template<class _Mesh>
void triangle_mesh_to_cgal(const std::vector<stl_vertex> &                 V,
                           const std::vector<stl_triangle_vertex_indices> &F,
                           _Mesh &out)
{
    if (F.empty()) return;

    for (auto &v : V)
        out.add_vertex(typename _Mesh::Point{v.x(), v.y(), v.z()});

    using VI = typename _Mesh::Vertex_index;
    for (auto &f : F)
        out.add_face(VI(f(0)), VI(f(1)), VI(f(2)));
}

inline Vec3d to_vec3d(const _EpicMesh::Point &v)
{
    return {v.x(), v.y(), v.z()};
}

inline Vec3d to_vec3d(const _EpecMesh::Point &v)
{
    CGAL::Cartesian_converter<EpecKernel, EpicKernel> cvt;
    auto iv = cvt(v);
    return {iv.x(), iv.y(), iv.z()};
}

template<class _Mesh> TriangleMesh cgal_to_triangle_mesh(const _Mesh &cgalmesh)
{
    Pointf3s points;
    std::vector<Vec3i> facets;
    points.reserve(cgalmesh.num_vertices());
    facets.reserve(cgalmesh.num_faces());

    for (auto &vi : cgalmesh.vertices()) {
        auto &v = cgalmesh.point(vi); // Don't ask...
        points.emplace_back(to_vec3d(v));
    }

    for (auto &face : cgalmesh.faces()) {
        auto vtc = cgalmesh.vertices_around_face(cgalmesh.halfedge(face));

        int i = 0;
        Vec3i facet;
        for (auto v : vtc) {
            if (i > 2) { i = 0; break; }
            facet(i++) = v;
        }

        if (i == 3)
            facets.emplace_back(facet);
    }

    TriangleMesh out{points, facets};
    out.repair();
    return out;
}

std::unique_ptr<CGALMesh, CGALMeshDeleter>
triangle_mesh_to_cgal(const std::vector<stl_vertex> &V,
                      const std::vector<stl_triangle_vertex_indices> &F)
{
    std::unique_ptr<CGALMesh, CGALMeshDeleter> out(new CGALMesh{});
    triangle_mesh_to_cgal(V, F, out->m);
    return out;
}

TriangleMesh cgal_to_triangle_mesh(const CGALMesh &cgalmesh)
{
    return cgal_to_triangle_mesh(cgalmesh.m);
}

// /////////////////////////////////////////////////////////////////////////////
// Boolean operations for CGAL meshes
// /////////////////////////////////////////////////////////////////////////////

static bool _cgal_diff(CGALMesh &A, CGALMesh &B, CGALMesh &R)
{
    const auto &p = CGALParams::throw_on_self_intersection(true);
    return CGALProc::corefine_and_compute_difference(A.m, B.m, R.m, p, p);
}

static bool _cgal_union(CGALMesh &A, CGALMesh &B, CGALMesh &R)
{
    const auto &p = CGALParams::throw_on_self_intersection(true);
    return CGALProc::corefine_and_compute_union(A.m, B.m, R.m, p, p);
}

static bool _cgal_intersection(CGALMesh &A, CGALMesh &B, CGALMesh &R)
{
    const auto &p = CGALParams::throw_on_self_intersection(true);
    return CGALProc::corefine_and_compute_intersection(A.m, B.m, R.m, p, p);
}

template<class Op> void _cgal_do(Op &&op, CGALMesh &A, CGALMesh &B)
{
    bool success = false;
    bool hw_fail = false;
    try {
        CGALMesh result;
        try_catch_signal({SIGSEGV, SIGFPE}, [&success, &A, &B, &result, &op] {
            success = op(A, B, result);
        }, [&] { hw_fail = true; });
        A = std::move(result);      // In-place operation does not work
    } catch (...) {
        success = false;
    }

    if (hw_fail)
        throw Slic3r::HardCrash("CGAL mesh boolean operation crashed.");

    if (! success)
        throw Slic3r::RuntimeError("CGAL mesh boolean operation failed.");
}

void minus(CGALMesh &A, CGALMesh &B) { _cgal_do(_cgal_diff, A, B); }
void plus(CGALMesh &A, CGALMesh &B) { _cgal_do(_cgal_union, A, B); }
void intersect(CGALMesh &A, CGALMesh &B) { _cgal_do(_cgal_intersection, A, B); }
bool does_self_intersect(const CGALMesh &mesh) { return CGALProc::does_self_intersect(mesh.m); }

// /////////////////////////////////////////////////////////////////////////////
// Now the public functions for TriangleMesh input:
// /////////////////////////////////////////////////////////////////////////////

template<class Op> void _mesh_boolean_do(Op &&op, TriangleMesh &A, const TriangleMesh &B)
{
    CGALMesh meshA;
    CGALMesh meshB;
    triangle_mesh_to_cgal(A.its.vertices, A.its.indices, meshA.m);
    triangle_mesh_to_cgal(B.its.vertices, B.its.indices, meshB.m);

    _cgal_do(op, meshA, meshB);

    A = cgal_to_triangle_mesh(meshA.m);
}

void minus(TriangleMesh &A, const TriangleMesh &B)
{
    _mesh_boolean_do(_cgal_diff, A, B);
}

void plus(TriangleMesh &A, const TriangleMesh &B)
{
    _mesh_boolean_do(_cgal_union, A, B);
}

void intersect(TriangleMesh &A, const TriangleMesh &B)
{
    _mesh_boolean_do(_cgal_intersection, A, B);
}

bool does_self_intersect(const TriangleMesh &mesh)
{
    CGALMesh cgalm;
    triangle_mesh_to_cgal(mesh.its.vertices, mesh.its.indices, cgalm.m);
    return CGALProc::does_self_intersect(cgalm.m);
}

void CGALMeshDeleter::operator()(CGALMesh *ptr) { delete ptr; }

bool does_bound_a_volume(const CGALMesh &mesh)
{
    return CGALProc::does_bound_a_volume(mesh.m);
}

bool empty(const CGALMesh &mesh)
{
    return mesh.m.is_empty();
}

} // namespace cgal

} // namespace MeshBoolean
} // namespace Slic3r
<commit_msg>Add reserve to mesh boolean operation<commit_after>#include "Exception.hpp"
#include "MeshBoolean.hpp"
#include "libslic3r/TriangleMesh.hpp"
#include "libslic3r/TryCatchSignal.hpp"
#undef PI

// Include igl first. It defines "L" macro which then clashes with our localization
#include <igl/copyleft/cgal/mesh_boolean.h>
#undef L

// CGAL headers
#include <CGAL/Polygon_mesh_processing/corefinement.h>
#include <CGAL/Exact_integer.h>
#include <CGAL/Surface_mesh.h>
#include <CGAL/Polygon_mesh_processing/orient_polygon_soup.h>
#include <CGAL/Polygon_mesh_processing/repair.h>
#include <CGAL/Polygon_mesh_processing/remesh.h>
#include <CGAL/Polygon_mesh_processing/polygon_soup_to_polygon_mesh.h>
#include <CGAL/Polygon_mesh_processing/orientation.h>
#include <CGAL/Cartesian_converter.h>

namespace Slic3r {
namespace MeshBoolean {

using MapMatrixXfUnaligned = Eigen::Map<const Eigen::Matrix<float, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor | Eigen::DontAlign>>;
using MapMatrixXiUnaligned = Eigen::Map<const Eigen::Matrix<int,   Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor | Eigen::DontAlign>>;

TriangleMesh eigen_to_triangle_mesh(const EigenMesh &emesh)
{
    auto &VC = emesh.first; auto &FC = emesh.second;

    Pointf3s points(size_t(VC.rows()));
    std::vector<Vec3i> facets(size_t(FC.rows()));

    for (Eigen::Index i = 0; i < VC.rows(); ++i)
        points[size_t(i)] = VC.row(i);

    for (Eigen::Index i = 0; i < FC.rows(); ++i)
        facets[size_t(i)] = FC.row(i);

    TriangleMesh out{points, facets};
    out.require_shared_vertices();
    return out;
}

EigenMesh triangle_mesh_to_eigen(const TriangleMesh &mesh)
{
    EigenMesh emesh;
    emesh.first = MapMatrixXfUnaligned(mesh.its.vertices.front().data(),
                                       Eigen::Index(mesh.its.vertices.size()),
                                       3).cast<double>();

    emesh.second = MapMatrixXiUnaligned(mesh.its.indices.front().data(),
                                        Eigen::Index(mesh.its.indices.size()),
                                        3);
    return emesh;
}

void minus(EigenMesh &A, const EigenMesh &B)
{
    auto &[VA, FA] = A;
    auto &[VB, FB] = B;

    Eigen::MatrixXd VC;
    Eigen::MatrixXi FC;
    igl::MeshBooleanType boolean_type(igl::MESH_BOOLEAN_TYPE_MINUS);
    igl::copyleft::cgal::mesh_boolean(VA, FA, VB, FB, boolean_type, VC, FC);

    VA = std::move(VC); FA = std::move(FC);
}

void minus(TriangleMesh& A, const TriangleMesh& B)
{
    EigenMesh eA = triangle_mesh_to_eigen(A);
    minus(eA, triangle_mesh_to_eigen(B));
    A = eigen_to_triangle_mesh(eA);
}

void self_union(EigenMesh &A)
{
    EigenMesh result;
    auto &[V, F] = A;
    auto &[VC, FC] = result;

    igl::MeshBooleanType boolean_type(igl::MESH_BOOLEAN_TYPE_UNION);
    igl::copyleft::cgal::mesh_boolean(V, F, Eigen::MatrixXd(), Eigen::MatrixXi(), boolean_type, VC, FC);

    A = std::move(result);
}

void self_union(TriangleMesh& mesh)
{
    auto eM = triangle_mesh_to_eigen(mesh);
    self_union(eM);
    mesh = eigen_to_triangle_mesh(eM);
}

namespace cgal {

namespace CGALProc    = CGAL::Polygon_mesh_processing;
namespace CGALParams  = CGAL::Polygon_mesh_processing::parameters;

using EpecKernel = CGAL::Exact_predicates_exact_constructions_kernel;
using EpicKernel = CGAL::Exact_predicates_inexact_constructions_kernel;
using _EpicMesh = CGAL::Surface_mesh<EpicKernel::Point_3>;
using _EpecMesh = CGAL::Surface_mesh<EpecKernel::Point_3>;

struct CGALMesh { _EpicMesh m; };

// /////////////////////////////////////////////////////////////////////////////
// Converions from and to CGAL mesh
// /////////////////////////////////////////////////////////////////////////////

template<class _Mesh>
void triangle_mesh_to_cgal(const std::vector<stl_vertex> &                 V,
                           const std::vector<stl_triangle_vertex_indices> &F,
                           _Mesh &out)
{
    if (F.empty()) return;

    size_t vertices_count = V.size();
    size_t edges_count    = (F.size()* 3) / 2;
    size_t faces_count    = F.size();
    out.reserve(vertices_count, edges_count, faces_count);

    for (auto &v : V)
        out.add_vertex(typename _Mesh::Point{v.x(), v.y(), v.z()});

    using VI = typename _Mesh::Vertex_index;
    for (auto &f : F)
        out.add_face(VI(f(0)), VI(f(1)), VI(f(2)));
}

inline Vec3d to_vec3d(const _EpicMesh::Point &v)
{
    return {v.x(), v.y(), v.z()};
}

inline Vec3d to_vec3d(const _EpecMesh::Point &v)
{
    CGAL::Cartesian_converter<EpecKernel, EpicKernel> cvt;
    auto iv = cvt(v);
    return {iv.x(), iv.y(), iv.z()};
}

template<class _Mesh> TriangleMesh cgal_to_triangle_mesh(const _Mesh &cgalmesh)
{
    Pointf3s points;
    std::vector<Vec3i> facets;
    points.reserve(cgalmesh.num_vertices());
    facets.reserve(cgalmesh.num_faces());

    for (auto &vi : cgalmesh.vertices()) {
        auto &v = cgalmesh.point(vi); // Don't ask...
        points.emplace_back(to_vec3d(v));
    }

    for (auto &face : cgalmesh.faces()) {
        auto vtc = cgalmesh.vertices_around_face(cgalmesh.halfedge(face));

        int i = 0;
        Vec3i facet;
        for (auto v : vtc) {
            if (i > 2) { i = 0; break; }
            facet(i++) = v;
        }

        if (i == 3)
            facets.emplace_back(facet);
    }

    TriangleMesh out{points, facets};
    out.repair();
    return out;
}

std::unique_ptr<CGALMesh, CGALMeshDeleter>
triangle_mesh_to_cgal(const std::vector<stl_vertex> &V,
                      const std::vector<stl_triangle_vertex_indices> &F)
{
    std::unique_ptr<CGALMesh, CGALMeshDeleter> out(new CGALMesh{});
    triangle_mesh_to_cgal(V, F, out->m);
    return out;
}

TriangleMesh cgal_to_triangle_mesh(const CGALMesh &cgalmesh)
{
    return cgal_to_triangle_mesh(cgalmesh.m);
}

// /////////////////////////////////////////////////////////////////////////////
// Boolean operations for CGAL meshes
// /////////////////////////////////////////////////////////////////////////////

static bool _cgal_diff(CGALMesh &A, CGALMesh &B, CGALMesh &R)
{
    const auto &p = CGALParams::throw_on_self_intersection(true);
    return CGALProc::corefine_and_compute_difference(A.m, B.m, R.m, p, p);
}

static bool _cgal_union(CGALMesh &A, CGALMesh &B, CGALMesh &R)
{
    const auto &p = CGALParams::throw_on_self_intersection(true);
    return CGALProc::corefine_and_compute_union(A.m, B.m, R.m, p, p);
}

static bool _cgal_intersection(CGALMesh &A, CGALMesh &B, CGALMesh &R)
{
    const auto &p = CGALParams::throw_on_self_intersection(true);
    return CGALProc::corefine_and_compute_intersection(A.m, B.m, R.m, p, p);
}

template<class Op> void _cgal_do(Op &&op, CGALMesh &A, CGALMesh &B)
{
    bool success = false;
    bool hw_fail = false;
    try {
        CGALMesh result;
        try_catch_signal({SIGSEGV, SIGFPE}, [&success, &A, &B, &result, &op] {
            success = op(A, B, result);
        }, [&] { hw_fail = true; });
        A = std::move(result);      // In-place operation does not work
    } catch (...) {
        success = false;
    }

    if (hw_fail)
        throw Slic3r::HardCrash("CGAL mesh boolean operation crashed.");

    if (! success)
        throw Slic3r::RuntimeError("CGAL mesh boolean operation failed.");
}

void minus(CGALMesh &A, CGALMesh &B) { _cgal_do(_cgal_diff, A, B); }
void plus(CGALMesh &A, CGALMesh &B) { _cgal_do(_cgal_union, A, B); }
void intersect(CGALMesh &A, CGALMesh &B) { _cgal_do(_cgal_intersection, A, B); }
bool does_self_intersect(const CGALMesh &mesh) { return CGALProc::does_self_intersect(mesh.m); }

// /////////////////////////////////////////////////////////////////////////////
// Now the public functions for TriangleMesh input:
// /////////////////////////////////////////////////////////////////////////////

template<class Op> void _mesh_boolean_do(Op &&op, TriangleMesh &A, const TriangleMesh &B)
{
    CGALMesh meshA;
    CGALMesh meshB;
    triangle_mesh_to_cgal(A.its.vertices, A.its.indices, meshA.m);
    triangle_mesh_to_cgal(B.its.vertices, B.its.indices, meshB.m);

    _cgal_do(op, meshA, meshB);

    A = cgal_to_triangle_mesh(meshA.m);
}

void minus(TriangleMesh &A, const TriangleMesh &B)
{
    _mesh_boolean_do(_cgal_diff, A, B);
}

void plus(TriangleMesh &A, const TriangleMesh &B)
{
    _mesh_boolean_do(_cgal_union, A, B);
}

void intersect(TriangleMesh &A, const TriangleMesh &B)
{
    _mesh_boolean_do(_cgal_intersection, A, B);
}

bool does_self_intersect(const TriangleMesh &mesh)
{
    CGALMesh cgalm;
    triangle_mesh_to_cgal(mesh.its.vertices, mesh.its.indices, cgalm.m);
    return CGALProc::does_self_intersect(cgalm.m);
}

void CGALMeshDeleter::operator()(CGALMesh *ptr) { delete ptr; }

bool does_bound_a_volume(const CGALMesh &mesh)
{
    return CGALProc::does_bound_a_volume(mesh.m);
}

bool empty(const CGALMesh &mesh)
{
    return mesh.m.is_empty();
}

} // namespace cgal

} // namespace MeshBoolean
} // namespace Slic3r
<|endoftext|>


<commit_before>/*
    <one line to give the program's name and a brief idea of what it does.>
    Copyright (C) <year>  <name of author>

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.

*/

#include "gluonobject.h"
#include "gluonobjectprivate.h"
#include <QVariant>
#include <QColor>

using namespace Gluon;

REGISTER_OBJECTTYPE(GluonObject)

GluonObject::GluonObject(QObject * parent)
{
    d = new GluonObjectPrivate();
}

GluonObject::~GluonObject()
{
}

GluonObject *
GluonObject::instantiate()
{
    return new GluonObject(this);
}

void
GluonObject::sanitize()
{
    GluonObject * theChild = 0;
    foreach(QObject * child, this->children())
    {
        if(child->inherits("GluonObject"))
        {
            theChild = qobject_cast<GluonObject*>(child);
            theChild->sanitize();
        }
    }
}

QString
GluonObject::name() const
{
    return d->name;
}

void
GluonObject::setName(const QString &newName)
{
    d->name = newName;
}

void
GluonObject::setPropertyFromString(const QString &propertyName, const QString &propertyValue)
{
    QVariant value;

    QString theTypeName = propertyValue.left(propertyValue.indexOf('(')).toLower();
    QString theValue = propertyValue.mid(theTypeName.length(), propertyValue.length() - theTypeName.length() - 1);

    if(theTypeName == "qstring")
        value = theValue;
    else if(theTypeName == "qcolor")
    {
        int r = 0, g = 0, b = 0, a = 0;
        QStringList splitValues = theValue.split(";");
        if(splitValues.length() > 0)
            r = splitValues[0].toInt();
        if(splitValues.length() > 1)
            g = splitValues[1].toInt();
        if(splitValues.length() > 2)
            b = splitValues[2].toInt();
        if(splitValues.length() > 3)
            a = splitValues[3].toInt();
        value = QColor(r, g, b, a);
    }
    else if(theTypeName == "bool")
        value = theValue.toFloat();
    else if(theTypeName == "float")
        value = theValue.toFloat();
    else if(theTypeName == "int")
        value = theValue.toInt();
    else
        // If all else fails, pass the value through verbatim
        value = propertyValue;

    this->setProperty(propertyName.toUtf8(), value);
}

QString
GluonObject::getStringFromProperty(const QString &propertyName)
{
    QString value;

    return value;
}
<commit_msg>Begin adding more data types and removing prefixes from existing.<commit_after>/*
    <one line to give the program's name and a brief idea of what it does.>
    Copyright (C) <year>  <name of author>

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.

*/

#include "gluonobject.h"
#include "gluonobjectprivate.h"
#include <QVariant>
#include <QPointF>
#include <QColor>
#include <Eigen/Geometry>

using namespace Gluon;

REGISTER_OBJECTTYPE(GluonObject)

GluonObject::GluonObject(QObject * parent)
{
    d = new GluonObjectPrivate();
}

GluonObject::~GluonObject()
{
}

GluonObject *
GluonObject::instantiate()
{
    return new GluonObject(this);
}

void
GluonObject::sanitize()
{
    GluonObject * theChild = 0;
    foreach(QObject * child, this->children())
    {
        if(child->inherits("GluonObject"))
        {
            theChild = qobject_cast<GluonObject*>(child);
            theChild->sanitize();
        }
    }
}

QString
GluonObject::name() const
{
    return d->name;
}

void
GluonObject::setName(const QString &newName)
{
    d->name = newName;
}

void
GluonObject::setPropertyFromString(const QString &propertyName, const QString &propertyValue)
{
    QVariant value;

    QString theTypeName = propertyValue.left(propertyValue.indexOf('(')).toLower();
    QString theValue = propertyValue.mid(theTypeName.length(), propertyValue.length() - theTypeName.length() - 1);

    if(theTypeName == "string")
        value = theValue;
    else if(theTypeName == "bool")
        value = theValue.toFloat();
    else if(theTypeName == "float")
        value = theValue.toFloat();
    else if(theTypeName == "int")
        value = theValue.toInt();
    else if(theTypeName == "vector2d")
    {
        float x = 0.0f, y = 0.0f;
        //, z = 0.0f;
        QStringList splitValues = theValue.split(";");
        if(splitValues.length() > 0)
        {
            x = splitValues.at(0).toFloat();
            y = splitValues.at(1).toFloat();
            //z = splitValues.at(2).toFloat();
        }
        value = QPointF(x, y);
    }
    else if(theTypeName == "rgba")
    {
        int r = 0, g = 0, b = 0, a = 0;
        QStringList splitValues = theValue.split(";");
        if(splitValues.length() > 0)
            r = splitValues[0].toInt();
        if(splitValues.length() > 1)
            g = splitValues[1].toInt();
        if(splitValues.length() > 2)
            b = splitValues[2].toInt();
        if(splitValues.length() > 3)
            a = splitValues[3].toInt();
        value = QColor(r, g, b, a);
    }
    else
        // If all else fails, pass the value through verbatim
        value = propertyValue;

    this->setProperty(propertyName.toUtf8(), value);
}

QString
GluonObject::getStringFromProperty(const QString &propertyName)
{
    QString value;

    return value;
}
<|endoftext|>


<commit_before><commit_msg>GTK: Allow keypad to be used for all tab selection accelerators.<commit_after><|endoftext|>


<commit_before>/*
 * Copyright (C) 2009 Toni Gundogdu.
 *
 * This file is part of cclive.
 *
 * cclive is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License as published by the Free Software
 * Foundation, either version 3 of the License, or (at your option) any later
 * version.
 *
 * cclive is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
 * details.
 *
 * You should have received a copy of the GNU General Public License along with
 * this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "config.h"

#include <fstream>
#include <string>
#include <vector>

#ifdef HAVE_ICONV
#include <iconv.h>
#endif

#include "hosthandler.h"
#include "opts.h"
#include "log.h"
#include "curl.h"

HostHandler::HostHandler()
    : pageContent(""), props(VideoProperties())
{
}

HostHandler::~HostHandler() {
}

const bool
HostHandler::isHost(std::string url) {
    return Util::toLower(url).find(props.getDomain())
        != std::string::npos;
}

void
HostHandler::parsePage(const std::string& url) {

    props.setPageLink(url);
    pageContent = curlmgr.fetchToMem(url);

    // Call overridden functions.
    parseTitle();
    parseId   ();
    parseLink ();

    // Handle title encoding. Done here since we still have page html.
    toUnicode();

    // Apply regexp to title.
    std::string title = props.getTitle();
    Options opts      = optsmgr.getOptions();

    if (opts.regexp_given)
        applyRegexp(title);

    // Remove leading and trailing whitespace.
    pcrecpp::RE("(\\s+)").Replace("", &title);
    pcrecpp::RE("(\\s+)$").Replace("", &title);

    props.setTitle(title);

    pageContent.clear();
}

void
HostHandler::toUnicode() {
#ifdef HAVE_ICONV
    std::string charset;
    try {
        charset =
            Util::subStr(pageContent, "charset=", "\"");

        iconv_t cd =
            iconv_open( "UTF-8", charset.c_str() );

        if (cd == (iconv_t)-1) {
            if (errno == EINVAL) {
                logmgr.cerr()
                    << "warn: conversion from "
                    << charset
                    << " to UTF-8 not available"
                    << std::endl;
            }
            else
                perror("iconv_popen");
            return;
        }

        char inbuf[256];
        ICONV_CONST char *inptr = inbuf;
        size_t insize = props.getTitle().length();

        if (insize >= sizeof(inbuf))
            insize = sizeof(inbuf);

        snprintf(inbuf, sizeof(inbuf), props.getTitle().c_str());

        char outbuf[256];
        size_t avail = sizeof(outbuf);
        char *wptr   = (char *)outbuf;
        memset(wptr, 0, sizeof(outbuf));

        size_t rc = iconv(cd, &inptr, &insize, &wptr, &avail);
        if (rc == (size_t)-1) {
            logmgr.cerr()
                << "error while converting characters from "
                << charset
                << " to UTF-8"
                << std::endl;
            return;
        }
        iconv_close(cd);
        cd = 0;

        props.setTitle(outbuf);
    }
    catch (const HostHandler::ParseException&) { }
#endif
}

void
HostHandler::applyRegexp(std::string& title) {

    Options opts = optsmgr.getOptions();

    if (opts.find_all_given) {
        pcrecpp::StringPiece sp(title);
        pcrecpp::RE re(opts.regexp_arg, pcrecpp::UTF8());

        title.clear();

        std::string s;
        while (re.FindAndConsume(&sp, &s))
            title += s;
    }
    else {
        std::string tmp = title;
        title.clear();

        pcrecpp::RE(opts.regexp_arg, pcrecpp::UTF8())
            .PartialMatch(tmp, &title);
    }

    props.setTitle(title);
}

void
HostHandler::partialMatch(
    const std::string& re,
    const pcrecpp::Arg& dst,
    const std::string& data/*=""*/)
{
    const std::string& content = !data.empty() ? data : pageContent;
    if (!pcrecpp::RE(re).PartialMatch(content, dst))
        throw HostHandler::ParseException("no match: "+re);
}

const VideoProperties&
HostHandler::getVideoProperties() const {
    return props;
}

HostHandler::
    ParseException::ParseException(const std::string& error)
        : RuntimeException(CCLIVE_PARSE, error)
{
}
<commit_msg>hosthandler.cpp: tweak lead/trail whitespace removal.<commit_after>/*
 * Copyright (C) 2009 Toni Gundogdu.
 *
 * This file is part of cclive.
 *
 * cclive is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License as published by the Free Software
 * Foundation, either version 3 of the License, or (at your option) any later
 * version.
 *
 * cclive is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
 * details.
 *
 * You should have received a copy of the GNU General Public License along with
 * this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "config.h"

#include <fstream>
#include <string>
#include <vector>

#ifdef HAVE_ICONV
#include <iconv.h>
#endif

#include "hosthandler.h"
#include "opts.h"
#include "log.h"
#include "curl.h"

HostHandler::HostHandler()
    : pageContent(""), props(VideoProperties())
{
}

HostHandler::~HostHandler() {
}

const bool
HostHandler::isHost(std::string url) {
    return Util::toLower(url).find(props.getDomain())
        != std::string::npos;
}

void
HostHandler::parsePage(const std::string& url) {

    props.setPageLink(url);
    pageContent = curlmgr.fetchToMem(url);

    // Call overridden functions.
    parseTitle();
    parseId   ();
    parseLink ();

    // Handle title encoding. Done here since we still have page html.
    toUnicode();

    // Apply regexp.
    std::string title = props.getTitle();

    if (optsmgr.getOptions().regexp_given)
        applyRegexp(title);

    // Remove leading and trailing whitespace.
    pcrecpp::RE("^[\\s]+").Replace("", &title);
    pcrecpp::RE("\\s+$").Replace("", &title);

    props.setTitle(title);

    pageContent.clear();
}

void
HostHandler::toUnicode() {
#ifdef HAVE_ICONV
    std::string charset;
    try {
        charset =
            Util::subStr(pageContent, "charset=", "\"");

        iconv_t cd =
            iconv_open( "UTF-8", charset.c_str() );

        if (cd == (iconv_t)-1) {
            if (errno == EINVAL) {
                logmgr.cerr()
                    << "warn: conversion from "
                    << charset
                    << " to UTF-8 not available"
                    << std::endl;
            }
            else
                perror("iconv_popen");
            return;
        }

        char inbuf[256];
        ICONV_CONST char *inptr = inbuf;
        size_t insize = props.getTitle().length();

        if (insize >= sizeof(inbuf))
            insize = sizeof(inbuf);

        snprintf(inbuf, sizeof(inbuf), props.getTitle().c_str());

        char outbuf[256];
        size_t avail = sizeof(outbuf);
        char *wptr   = (char *)outbuf;
        memset(wptr, 0, sizeof(outbuf));

        size_t rc = iconv(cd, &inptr, &insize, &wptr, &avail);
        if (rc == (size_t)-1) {
            logmgr.cerr()
                << "error while converting characters from "
                << charset
                << " to UTF-8"
                << std::endl;
            return;
        }
        iconv_close(cd);
        cd = 0;

        props.setTitle(outbuf);
    }
    catch (const HostHandler::ParseException&) { }
#endif
}

void
HostHandler::applyRegexp(std::string& title) {

    Options opts = optsmgr.getOptions();

    if (opts.find_all_given) {
        pcrecpp::StringPiece sp(title);
        pcrecpp::RE re(opts.regexp_arg, pcrecpp::UTF8());

        title.clear();

        std::string s;
        while (re.FindAndConsume(&sp, &s))
            title += s;
    }
    else {
        std::string tmp = title;
        title.clear();

        pcrecpp::RE(opts.regexp_arg, pcrecpp::UTF8())
            .PartialMatch(tmp, &title);
    }

    props.setTitle(title);
}

void
HostHandler::partialMatch(
    const std::string& re,
    const pcrecpp::Arg& dst,
    const std::string& data/*=""*/)
{
    const std::string& content = !data.empty() ? data : pageContent;
    if (!pcrecpp::RE(re).PartialMatch(content, dst))
        throw HostHandler::ParseException("no match: "+re);
}

const VideoProperties&
HostHandler::getVideoProperties() const {
    return props;
}

HostHandler::
    ParseException::ParseException(const std::string& error)
        : RuntimeException(CCLIVE_PARSE, error)
{
}
<|endoftext|>


<commit_before>/*
 *            Copyright 2009-2018 The VOTCA Development Team
 *                       (http://www.votca.org)
 *
 *      Licensed under the Apache License, Version 2.0 (the "License")
 *
 * You may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *              http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

#include <set>
#include <vector>
#include <exception>
#include <votca/tools/edge.h>
#include <votca/tools/edgecontainer.h>
#include <algorithm>

namespace votca {
  namespace tools {

using namespace std;

EdgeContainer::EdgeContainer(Edge ed) { addEdge(ed); }

EdgeContainer::EdgeContainer(vector<Edge> eds) {
  for (auto ed : eds) {
    addEdge(ed);
  }
}

int EdgeContainer::getMaxDegree(void) const{
  int max = 0;
  for(auto const& it : adj_list_) {
    int degree = getDegree(it.first);
    if(degree>max) {
      max = degree;
    }
  }
  return max;
}

int EdgeContainer::getDegree(const int vert) const{
  if(!adj_list_.count(vert)) throw invalid_argument("vertex is not defined");
  int degree_count=0;
  for(auto neighbor_and_count : adj_list_[vert]){
    degree_count+=neighbor_and_count.second;
  }
  return degree_count;
}

vector<int> EdgeContainer::getVerticesDegree(int degree) const{
  vector<int> verts;
  for(auto v_list : adj_list_){
    int degree_count= getDegree(v_list.first);
    if(degree_count==degree){
      verts.push_back(v_list.first);
    }
  }
  return verts;
}

bool EdgeContainer::edgeExist(Edge ed) {
  return adj_list_[ed.getEndPoint1()].count(ed.getEndPoint2()) ||
    adj_list_[ed.getEndPoint2()].count(ed.getEndPoint1());
}

bool EdgeContainer::vertexExist(int vert) { return adj_list_.count(vert); }

void EdgeContainer::addEdge(Edge ed) {

  int point1 = ed.getEndPoint1();
  int point2 = ed.getEndPoint2();
  if(adj_list_[point1].count(point2)){
    ++adj_list_[point1][point2];
  }else{
    adj_list_[point1][point2]=1;
  }

  // Do not add the same edge if the points are the same
  if(point1!=point2){
    if(adj_list_[point2].count(point1)){
      ++adj_list_[point2][point1];
    }else{
      adj_list_[point2][point1]=1;
    }
  }
  return;
}

vector<int> EdgeContainer::getVertices() {
  vector<int> vertices;
  for (auto const& it : adj_list_) vertices.push_back(it.first);
  return vertices;
}

vector<int> EdgeContainer::getNeighVertices(int vert) {
  vector<int> neigh_verts;
  for (auto const& neigh_vert : adj_list_[vert]) {
    neigh_verts.push_back(neigh_vert.first);
  }
  return neigh_verts;
}

vector<Edge> EdgeContainer::getNeighEdges(int vert) {
  vector<Edge> neigh_edges;
  for (auto const& neigh_vert : adj_list_[vert]) {
    for(int count=0;count<adj_list_[vert][neigh_vert.first];++count){
      neigh_edges.push_back(Edge(vert, neigh_vert.first));
    }
  }
  return neigh_edges;
}

vector<Edge> EdgeContainer::getEdges() const {
  unordered_map<Edge,int> extra_edge_count;
  for (auto const& it : adj_list_) {
    for (auto const& vert : it.second) {
      extra_edge_count[Edge(it.first,vert.first)]=vert.second;
    }
  }
  vector<Edge> vec_edgs;
  for(auto edge_count : extra_edge_count){
    for(int count = 0; count < edge_count.second;++count){
      vec_edgs.push_back(edge_count.first);
    }
  }
  return vec_edgs;
}

ostream& operator<<(ostream& os, const EdgeContainer edgecontainer){
  auto edges = edgecontainer.getEdges();
  for(auto edge : edges){
    os << edge << endl;
  }
  return os;
}

}
}
<commit_msg>Updated functionality<commit_after>/*
 *            Copyright 2009-2018 The VOTCA Development Team
 *                       (http://www.votca.org)
 *
 *      Licensed under the Apache License, Version 2.0 (the "License")
 *
 * You may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *              http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

#include <set>
#include <vector>
#include <exception>
#include <votca/tools/edge.h>
#include <votca/tools/edgecontainer.h>
#include <algorithm>

namespace votca {
  namespace tools {

using namespace std;

EdgeContainer::EdgeContainer(Edge ed) { addEdge(ed); }

EdgeContainer::EdgeContainer(vector<Edge> eds) {
  for (auto ed : eds) {
    addEdge(ed);
  }
}

int EdgeContainer::getMaxDegree(void) const{
  int max = 0;
  for(auto const& it : adj_list_) {
    int degree = getDegree(it.first);
    if(degree>max) {
      max = degree;
    }
  }
  return max;
}

int EdgeContainer::getDegree(const int vert) const{
  if(!adj_list_.count(vert)) throw invalid_argument("vertex is not defined");
  int degree_count=0;
  for(auto neighbor_and_count : adj_list_.at(vert)){
    degree_count+=neighbor_and_count.second;
  }
  return degree_count;
}

vector<int> EdgeContainer::getVerticesDegree(int degree) const{
  vector<int> verts;
  for(auto v_list : adj_list_){
    int degree_count= getDegree(v_list.first);
    if(degree_count==degree){
      verts.push_back(v_list.first);
    }
  }
  return verts;
}

bool EdgeContainer::edgeExist(Edge ed) {
  return adj_list_[ed.getEndPoint1()].count(ed.getEndPoint2()) ||
    adj_list_[ed.getEndPoint2()].count(ed.getEndPoint1());
}

bool EdgeContainer::vertexExist(int vert) { return adj_list_.count(vert); }

void EdgeContainer::addEdge(Edge ed) {

  int point1 = ed.getEndPoint1();
  int point2 = ed.getEndPoint2();
  if(adj_list_[point1].count(point2)){
    ++adj_list_[point1][point2];
  }else{
    adj_list_[point1][point2]=1;
  }

  // Do not add the same edge if the points are the same
  if(point1!=point2){
    if(adj_list_[point2].count(point1)){
      ++adj_list_[point2][point1];
    }else{
      adj_list_[point2][point1]=1;
    }
  }
  return;
}

vector<int> EdgeContainer::getVertices() {
  vector<int> vertices;
  for (auto const& it : adj_list_) vertices.push_back(it.first);
  return vertices;
}

vector<int> EdgeContainer::getNeighVertices(int vert) {
  vector<int> neigh_verts;
  for (auto const& neigh_vert : adj_list_[vert]) {
    neigh_verts.push_back(neigh_vert.first);
  }
  return neigh_verts;
}

vector<Edge> EdgeContainer::getNeighEdges(int vert) {
  vector<Edge> neigh_edges;
  for (auto const& neigh_vert : adj_list_[vert]) {
    for(int count=0;count<adj_list_[vert][neigh_vert.first];++count){
      neigh_edges.push_back(Edge(vert, neigh_vert.first));
    }
  }
  return neigh_edges;
}

vector<Edge> EdgeContainer::getEdges() const {
  unordered_map<Edge,int> extra_edge_count;
  for (auto const& it : adj_list_) {
    for (auto const& vert : it.second) {
      extra_edge_count[Edge(it.first,vert.first)]=vert.second;
    }
  }
  vector<Edge> vec_edgs;
  for(auto edge_count : extra_edge_count){
    for(int count = 0; count < edge_count.second;++count){
      vec_edgs.push_back(edge_count.first);
    }
  }
  return vec_edgs;
}

ostream& operator<<(ostream& os, const EdgeContainer edgecontainer){
  auto edges = edgecontainer.getEdges();
  for(auto edge : edges){
    os << edge << endl;
  }
  return os;
}

}
}
<|endoftext|>


<commit_before>//=======================================================================
// Copyright Baptiste Wicht 2011-2013.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================

#include "logging.hpp"
#include "GlobalContext.hpp"
#include "FunctionContext.hpp"

#include "mtac/Function.hpp"
#include "mtac/loop.hpp"
#include "mtac/loop_unswitching.hpp"
#include "mtac/Utils.hpp"
#include "mtac/variable_usage.hpp"

using namespace eddic;

bool mtac::loop_unswitching::gate(std::shared_ptr<Configuration> configuration){
    return configuration->option_defined("funswitch-loops");
}

bool mtac::loop_unswitching::operator()(mtac::Function& function){
    if(function.loops().empty()){
        return false;
    }

    bool optimized = false;

    for(auto& loop : function.loops()){
        if(loop.single_exit()){
            auto entry = loop.find_entry();
            auto exit = loop.find_exit();

            if(entry && exit && entry->size() == 1){
                if(entry->successors.size() == 2 && exit->predecessors.size() == 2){
                    if(std::is_permutation(entry->successors.begin(), entry->successors.end(), exit->predecessors.begin())){
                        auto& condition = *entry->begin();

                        if(condition.is_if() || condition.is_if_false()){
                            auto usage = mtac::compute_write_usage(loop);

                            if(condition.arg1){
                                if(auto* ptr = boost::get<std::shared_ptr<Variable>>(&*condition.arg1)){
                                    if(usage.written[*ptr] > 0){
                                        continue;
                                    }
                                }
                            }

                            if(condition.arg2){
                                if(auto* ptr = boost::get<std::shared_ptr<Variable>>(&*condition.arg2)){
                                    if(usage.written[*ptr] > 0){
                                        continue;
                                    }
                                }
                            }

                            //TODO Unswitch the loop

                            std::cout << "Find out" << std::endl;
                        }
                    }
                }
            }
        }
    }

    return optimized;
}
<commit_msg>Continue prototype<commit_after>//=======================================================================
// Copyright Baptiste Wicht 2011-2013.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================

#include "logging.hpp"
#include "GlobalContext.hpp"
#include "FunctionContext.hpp"

#include "mtac/Function.hpp"
#include "mtac/loop.hpp"
#include "mtac/loop_unswitching.hpp"
#include "mtac/Utils.hpp"
#include "mtac/variable_usage.hpp"

using namespace eddic;

bool mtac::loop_unswitching::gate(std::shared_ptr<Configuration> configuration){
    return configuration->option_defined("funswitch-loops");
}

bool mtac::loop_unswitching::operator()(mtac::Function& function){
    if(function.loops().empty()){
        return false;
    }

    bool optimized = false;

    for(auto& loop : function.loops()){
        if(loop.single_exit()){
            auto entry = loop.find_entry();
            auto exit = loop.find_exit();

            if(entry && exit && entry->size() == 1){
                if(entry->successors.size() == 2 && exit->predecessors.size() == 2){
                    if(std::is_permutation(entry->successors.begin(), entry->successors.end(), exit->predecessors.begin())){
                        auto& condition = *entry->begin();

                        if(condition.is_if() || condition.is_if_false()){
                            auto usage = mtac::compute_write_usage(loop);

                            if(condition.arg1){
                                if(auto* ptr = boost::get<std::shared_ptr<Variable>>(&*condition.arg1)){
                                    if(usage.written[*ptr] > 0){
                                        continue;
                                    }
                                }
                            }

                            if(condition.arg2){
                                if(auto* ptr = boost::get<std::shared_ptr<Variable>>(&*condition.arg2)){
                                    if(usage.written[*ptr] > 0){
                                        continue;
                                    }
                                }
                            }

                            auto loop_1_entry = entry->successors.front();
                            auto loop_2_entry = entry->successors.back();

                            entry->predecessors.erase(std::remove(entry->predecessors.begin(), entry->predecessors.end(), entry), entry->predecessors.end());

                            exit_copy = mtac::clone(function, exit);

                            exit_copy->successors.erase(std::remove(exit_copy->successors.begin(), exit_copy->successors.end(), entry), exit_copy->successors.end());
                            exit_copy->successors.push_back(loop_1_entry);

                            exit->successors.erase(std::remove(exit->successors.begin(), exit->successors.end(), entry), exit->successors.end());
                            exit->successors.push_back(loop_2_entry);

                            //TODO Unswitch the loop

                            std::cout << "Find out" << std::endl;
                        }
                    }
                }
            }
        }
    }

    return optimized;
}
<|endoftext|>


<commit_before>// This file is a part of the IncludeOS unikernel - www.includeos.org
//
// Copyright 2016-2017 Oslo and Akershus University College of Applied Sciences
// and Alfred Bratterud
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <net/http/basic_client.hpp>

namespace http {

  const Basic_client::timeout_duration Basic_client::DEFAULT_TIMEOUT{std::chrono::seconds(5)};
  int Basic_client::default_follow_redirect{0};

  Basic_client::Basic_client(TCP& tcp, Request_handler on_send)
    : Basic_client(tcp, std::move(on_send), false)
  {
  }

  Basic_client::Basic_client(TCP& tcp, Request_handler on_send, const bool https_supported)
    : tcp_(tcp),
      on_send_{std::move(on_send)},
      supports_https(https_supported)
  {
  }

  Request_ptr Basic_client::create_request(Method method) const
  {
    auto req = std::make_unique<Request>();
    req->set_method(method);

    auto& header = req->header();
    header.set_field(header::User_Agent, "IncludeOS/0.12");
    set_connection_header(*req);

    return req;
  }

  void Basic_client::send(Request_ptr req, Host host, Response_handler cb,
                    const bool secure, Options options)
  {
    Expects(cb != nullptr);
    using namespace std;
    auto& conn = (not secure) ?
      get_connection(host) : get_secure_connection(host);

    auto&& header = req->header();

    // Set Host if not already set
    if(! header.has_field(header::Host))
      header.set_field(header::Host, host.to_string());

    // Set Origin if not already set
    if(! header.has_field(header::Origin))
      header.set_field(header::Origin, origin());

    debug("<http::Basic_client> Sending Request:\n%s\n", req->to_string().c_str());

    if(on_send_)
      on_send_(*req, options, host);

    conn.send(move(req), move(cb), options.follow_redirect, options.timeout);
  }

  void Basic_client::send(Request_ptr req, URI url, Response_handler cb, Options options)
  {
    // find out if this is a secured request or not
    const bool secure = url.scheme_is_secure();
    validate_secure(secure);

    using namespace std;

    // Default to port 80 if non given
    const uint16_t port = (url.port() != 0xFFFF) ? url.port() : 80;

    if (url.host_is_ip4())
    {
      std::string host(url.host());
      auto ip = net::ip4::Addr(host);

      send(move(req), {ip, port}, move(cb), secure, move(options));
    }
    else
    {
      tcp_.stack().resolve(std::string(url.host()),
      ResolveCallback::make_packed(
      [
        this,
        request = move(req),
        url{move(url)},
        cb{move(cb)},
        opt{move(options)},
        secure,
        port
      ]
        (net::dns::Response_ptr res, const net::Error&) mutable
      {
        auto addr = res->get_first_addr();
        if(UNLIKELY(addr == net::Addr::addr_any))
        {
          cb({Error::RESOLVE_HOST}, nullptr, Connection::empty());
          return;
        }
        // Host resolved
        send(move(request), {addr, port}, move(cb), secure, move(opt));
      }));
    }
  }

  void Basic_client::request(Method method, URI url, Header_set hfields,
                       Response_handler cb, Options options)
  {
    Expects(url.is_valid());
    Expects(cb != nullptr);

    // find out if this is a secured request or not
    const bool secure = url.scheme_is_secure();
    validate_secure(secure);

    using namespace std;

    if (url.host_is_ip4())
    {
      std::string host(url.host());
      auto ip = net::ip4::Addr(host);
      // setup request with method and headers
      auto req = create_request(method);
      *req << hfields;

      // Set Host and URI path
      populate_from_url(*req, url);

      // Default to port 80 if non given
      const uint16_t port = (url.port() != 0xFFFF) ? url.port() : 80;

      send(move(req), {ip, port}, move(cb), secure, move(options));
    }
    else
    {
      tcp_.stack().resolve(std::string(url.host()),
      ResolveCallback::make_packed(
      [
        this,
        method,
        url{move(url)},
        hfields{move(hfields)},
        cb{move(cb)},
        opt{move(options)},
        secure
      ]
        (net::dns::Response_ptr res, const net::Error& err)
      {
        // Host resolved
        if (not err)
        {
          auto addr = res->get_first_addr();
          if(UNLIKELY(addr == net::Addr::addr_any))
          {
            cb({Error::RESOLVE_HOST}, nullptr, Connection::empty());
            return;
          }
          // setup request with method and headers
          auto req = create_request(method);
          *req << hfields;

          // Set Host and URI path
          populate_from_url(*req, url);

          // Default to port 80 if non given
          const uint16_t port = (url.port() != 0xFFFF) ? url.port() : 80;

          send(move(req), {addr, port}, move(cb), secure, move(opt));
        }
        else
        {
          cb({Error::RESOLVE_HOST}, nullptr, Connection::empty());
        }
      }));
    }
  }

  void Basic_client::request(Method method, Host host, std::string path,
                       Header_set hfields, Response_handler cb,
                      const bool secure, Options options)
  {
    validate_secure(secure);

    using namespace std;
    // setup request with method and headers
    auto req = create_request(method);
    *req << hfields;

    //set uri (default "/")
    req->set_uri((!path.empty()) ? URI{move(path)} : URI{"/"});

    send(move(req), move(host), move(cb), secure, move(options));
  }

  void Basic_client::request(Method method, URI url, Header_set hfields,
                       std::string data, Response_handler cb,
                       Options options)
  {
    // find out if this is a secured request or not
    const bool secure = url.scheme_is_secure();
    validate_secure(secure);

    using namespace std;
    if (url.host_is_ip4())
    {
      std::string host(url.host());
      auto ip = net::ip4::Addr(host);
      // setup request with method and headers
      auto req = create_request(method);
      *req << hfields;

      // Set Host and URI path
      populate_from_url(*req, url);

      // Add data and content length
      this->add_data(*req, data);

      // Default to port 80 if non given
      const uint16_t port = (url.port() != 0xFFFF) ? url.port() : 80;

      send(move(req), {ip, port}, move(cb), secure, move(options));
    }
    else
    {
      tcp_.stack().resolve(
        std::string(url.host()),
        ResolveCallback::make_packed(
        [
          this,
          method,
          url{move(url)},
          hfields{move(hfields)},
          data{move(data)},
          cb{move(cb)},
          opt{move(options)},
          secure
        ]
          (net::dns::Response_ptr res, const net::Error& err)
        {
          // Host resolved
          if (not err)
          {
            auto addr = res->get_first_addr();
            if(UNLIKELY(addr == net::Addr::addr_any))
            {
              cb({Error::RESOLVE_HOST}, nullptr, Connection::empty());
              return;
            }
            // setup request with method and headers
            auto req = this->create_request(method);
            *req << hfields;

            // Set Host & path from url
            this->populate_from_url(*req, url);

            // Add data and content length
            this->add_data(*req, data);

            // Default to port 80 if non given
            const uint16_t port = (url.port() != 0xFFFF) ? url.port() : 80;

            this->send(move(req), {addr, port}, move(cb), secure, move(opt));
          }
          else
          {
            cb({Error::RESOLVE_HOST}, nullptr, Connection::empty());
          }
        })
      );
    }
  }

  void Basic_client::request(Method method, Host host, std::string path,
                       Header_set hfields, const std::string& data,
                       Response_handler cb, const bool secure, Options options)
  {
    validate_secure(secure);

    using namespace std;
    // setup request with method and headers
    auto req = create_request(method);
    *req << hfields;

    // set uri (default "/")
    req->set_uri((!path.empty()) ? URI{move(path)} : URI{"/"});

    // Add data and content length
    add_data(*req, data);

    send(move(req), move(host), move(cb), secure, move(options));
  }

  void Basic_client::add_data(Request& req, const std::string& data)
  {
    auto& header = req.header();
    if(!header.has_field(header::Content_Type))
      header.set_field(header::Content_Type, "text/plain");

    // Set Content-Length to be equal data length
    req.header().set_field(header::Content_Length, std::to_string(data.size()));

    // Add data
    req.add_body(data);
  }

  void Basic_client::populate_from_url(Request& req, const URI& url)
  {
    // Set uri path (default "/")
    req.set_uri((!url.path().empty()) ? URI{url.path()} : URI{"/"});

    // Set Host: host(:port)
    const auto port = url.port();
    req.header().set_field(header::Host,
      (port != 0xFFFF and port != 80) ?
      std::string(url.host()) + ":" + std::to_string(port)
      : std::string(url.host())); // to_string madness
  }

  void Basic_client::resolve(const std::string& host, ResolveCallback cb)
  {
    static auto&& stack = tcp_.stack();
    stack.resolve(host, cb);
  }

  Client_connection& Basic_client::get_connection(const Host host)
  {
    // return/create a set for the given host
    auto& cset = conns_[host];

    // iterate all the connection and return the first free one
    for(auto& conn : cset)
    {
      if(!conn->occupied())
        return *conn;
    }

    // no non-occupied connections, emplace a new one
    cset.push_back(std::make_unique<Client_connection>(
      *this, std::make_unique<net::tcp::Stream>(tcp_.connect(host)))
    );
    return *cset.back();
  }

  Client_connection& Basic_client::get_secure_connection(const Host)
  {
    throw Client_error{"Secured connections not supported (use the HTTPS Client)."};
  }

  void Basic_client::close(Client_connection& c)
  {
    debug("<http::Basic_client> Closing %u:%s %p\n", c.local_port(), c.peer().to_string().c_str(), &c);
    auto& cset = conns_.at(c.peer());

    cset.erase(std::remove_if(cset.begin(), cset.end(),
    [port = c.local_port()] (const std::unique_ptr<Client_connection>& conn)->bool
    {
      return conn->local_port() == port;
    }));
  }

}
<commit_msg>http: Expect valid URI in client<commit_after>// This file is a part of the IncludeOS unikernel - www.includeos.org
//
// Copyright 2016-2017 Oslo and Akershus University College of Applied Sciences
// and Alfred Bratterud
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <net/http/basic_client.hpp>

namespace http {

  const Basic_client::timeout_duration Basic_client::DEFAULT_TIMEOUT{std::chrono::seconds(5)};
  int Basic_client::default_follow_redirect{0};

  Basic_client::Basic_client(TCP& tcp, Request_handler on_send)
    : Basic_client(tcp, std::move(on_send), false)
  {
  }

  Basic_client::Basic_client(TCP& tcp, Request_handler on_send, const bool https_supported)
    : tcp_(tcp),
      on_send_{std::move(on_send)},
      supports_https(https_supported)
  {
  }

  Request_ptr Basic_client::create_request(Method method) const
  {
    auto req = std::make_unique<Request>();
    req->set_method(method);

    auto& header = req->header();
    header.set_field(header::User_Agent, "IncludeOS/0.12");
    set_connection_header(*req);

    return req;
  }

  void Basic_client::send(Request_ptr req, Host host, Response_handler cb,
                    const bool secure, Options options)
  {
    Expects(cb != nullptr);
    using namespace std;
    auto& conn = (not secure) ?
      get_connection(host) : get_secure_connection(host);

    auto&& header = req->header();

    // Set Host if not already set
    if(! header.has_field(header::Host))
      header.set_field(header::Host, host.to_string());

    // Set Origin if not already set
    if(! header.has_field(header::Origin))
      header.set_field(header::Origin, origin());

    debug("<http::Basic_client> Sending Request:\n%s\n", req->to_string().c_str());

    if(on_send_)
      on_send_(*req, options, host);

    conn.send(move(req), move(cb), options.follow_redirect, options.timeout);
  }

  void Basic_client::send(Request_ptr req, URI url, Response_handler cb, Options options)
  {
    Expects(url.is_valid() && "Invalid URI (missing scheme?)");
    // find out if this is a secured request or not
    const bool secure = url.scheme_is_secure();
    validate_secure(secure);

    using namespace std;

    // Default to port 80 if non given
    const uint16_t port = (url.port() != 0xFFFF) ? url.port() : 80;

    if (url.host_is_ip4())
    {
      std::string host(url.host());
      auto ip = net::ip4::Addr(host);

      send(move(req), {ip, port}, move(cb), secure, move(options));
    }
    else
    {
      tcp_.stack().resolve(std::string(url.host()),
      ResolveCallback::make_packed(
      [
        this,
        request = move(req),
        url{move(url)},
        cb{move(cb)},
        opt{move(options)},
        secure,
        port
      ]
        (net::dns::Response_ptr res, const net::Error&) mutable
      {
        auto addr = res->get_first_addr();
        if(UNLIKELY(addr == net::Addr::addr_any))
        {
          cb({Error::RESOLVE_HOST}, nullptr, Connection::empty());
          return;
        }
        // Host resolved
        send(move(request), {addr, port}, move(cb), secure, move(opt));
      }));
    }
  }

  void Basic_client::request(Method method, URI url, Header_set hfields,
                       Response_handler cb, Options options)
  {
    Expects(url.is_valid() && "Invalid URI (missing scheme?)");
    Expects(cb != nullptr);

    // find out if this is a secured request or not
    const bool secure = url.scheme_is_secure();
    validate_secure(secure);

    using namespace std;

    if (url.host_is_ip4())
    {
      std::string host(url.host());
      auto ip = net::ip4::Addr(host);
      // setup request with method and headers
      auto req = create_request(method);
      *req << hfields;

      // Set Host and URI path
      populate_from_url(*req, url);

      // Default to port 80 if non given
      const uint16_t port = (url.port() != 0xFFFF) ? url.port() : 80;

      send(move(req), {ip, port}, move(cb), secure, move(options));
    }
    else
    {
      tcp_.stack().resolve(std::string(url.host()),
      ResolveCallback::make_packed(
      [
        this,
        method,
        url{move(url)},
        hfields{move(hfields)},
        cb{move(cb)},
        opt{move(options)},
        secure
      ]
        (net::dns::Response_ptr res, const net::Error& err)
      {
        // Host resolved
        if (not err)
        {
          auto addr = res->get_first_addr();
          if(UNLIKELY(addr == net::Addr::addr_any))
          {
            cb({Error::RESOLVE_HOST}, nullptr, Connection::empty());
            return;
          }
          // setup request with method and headers
          auto req = create_request(method);
          *req << hfields;

          // Set Host and URI path
          populate_from_url(*req, url);

          // Default to port 80 if non given
          const uint16_t port = (url.port() != 0xFFFF) ? url.port() : 80;

          send(move(req), {addr, port}, move(cb), secure, move(opt));
        }
        else
        {
          cb({Error::RESOLVE_HOST}, nullptr, Connection::empty());
        }
      }));
    }
  }

  void Basic_client::request(Method method, Host host, std::string path,
                       Header_set hfields, Response_handler cb,
                      const bool secure, Options options)
  {
    validate_secure(secure);

    using namespace std;
    // setup request with method and headers
    auto req = create_request(method);
    *req << hfields;

    //set uri (default "/")
    req->set_uri((!path.empty()) ? URI{move(path)} : URI{"/"});

    send(move(req), move(host), move(cb), secure, move(options));
  }

  void Basic_client::request(Method method, URI url, Header_set hfields,
                       std::string data, Response_handler cb,
                       Options options)
  {
    Expects(url.is_valid() && "Invalid URI (missing scheme?)");
    // find out if this is a secured request or not
    const bool secure = url.scheme_is_secure();
    validate_secure(secure);

    using namespace std;
    if (url.host_is_ip4())
    {
      std::string host(url.host());
      auto ip = net::ip4::Addr(host);
      // setup request with method and headers
      auto req = create_request(method);
      *req << hfields;

      // Set Host and URI path
      populate_from_url(*req, url);

      // Add data and content length
      this->add_data(*req, data);

      // Default to port 80 if non given
      const uint16_t port = (url.port() != 0xFFFF) ? url.port() : 80;

      send(move(req), {ip, port}, move(cb), secure, move(options));
    }
    else
    {
      tcp_.stack().resolve(
        std::string(url.host()),
        ResolveCallback::make_packed(
        [
          this,
          method,
          url{move(url)},
          hfields{move(hfields)},
          data{move(data)},
          cb{move(cb)},
          opt{move(options)},
          secure
        ]
          (net::dns::Response_ptr res, const net::Error& err)
        {
          // Host resolved
          if (not err)
          {
            auto addr = res->get_first_addr();
            if(UNLIKELY(addr == net::Addr::addr_any))
            {
              cb({Error::RESOLVE_HOST}, nullptr, Connection::empty());
              return;
            }
            // setup request with method and headers
            auto req = this->create_request(method);
            *req << hfields;

            // Set Host & path from url
            this->populate_from_url(*req, url);

            // Add data and content length
            this->add_data(*req, data);

            // Default to port 80 if non given
            const uint16_t port = (url.port() != 0xFFFF) ? url.port() : 80;

            this->send(move(req), {addr, port}, move(cb), secure, move(opt));
          }
          else
          {
            cb({Error::RESOLVE_HOST}, nullptr, Connection::empty());
          }
        })
      );
    }
  }

  void Basic_client::request(Method method, Host host, std::string path,
                       Header_set hfields, const std::string& data,
                       Response_handler cb, const bool secure, Options options)
  {
    validate_secure(secure);

    using namespace std;
    // setup request with method and headers
    auto req = create_request(method);
    *req << hfields;

    // set uri (default "/")
    req->set_uri((!path.empty()) ? URI{move(path)} : URI{"/"});

    // Add data and content length
    add_data(*req, data);

    send(move(req), move(host), move(cb), secure, move(options));
  }

  void Basic_client::add_data(Request& req, const std::string& data)
  {
    auto& header = req.header();
    if(!header.has_field(header::Content_Type))
      header.set_field(header::Content_Type, "text/plain");

    // Set Content-Length to be equal data length
    req.header().set_field(header::Content_Length, std::to_string(data.size()));

    // Add data
    req.add_body(data);
  }

  void Basic_client::populate_from_url(Request& req, const URI& url)
  {
    Expects(url.is_valid() && "Invalid URI (missing scheme?)");
    // Set uri path (default "/")
    req.set_uri((!url.path().empty()) ? URI{url.path()} : URI{"/"});

    // Set Host: host(:port)
    const auto port = url.port();
    req.header().set_field(header::Host,
      (port != 0xFFFF and port != 80) ?
      std::string(url.host()) + ":" + std::to_string(port)
      : std::string(url.host())); // to_string madness
  }

  void Basic_client::resolve(const std::string& host, ResolveCallback cb)
  {
    static auto&& stack = tcp_.stack();
    stack.resolve(host, cb);
  }

  Client_connection& Basic_client::get_connection(const Host host)
  {
    // return/create a set for the given host
    auto& cset = conns_[host];

    // iterate all the connection and return the first free one
    for(auto& conn : cset)
    {
      if(!conn->occupied())
        return *conn;
    }

    // no non-occupied connections, emplace a new one
    cset.push_back(std::make_unique<Client_connection>(
      *this, std::make_unique<net::tcp::Stream>(tcp_.connect(host)))
    );
    return *cset.back();
  }

  Client_connection& Basic_client::get_secure_connection(const Host)
  {
    throw Client_error{"Secured connections not supported (use the HTTPS Client)."};
  }

  void Basic_client::close(Client_connection& c)
  {
    debug("<http::Basic_client> Closing %u:%s %p\n", c.local_port(), c.peer().to_string().c_str(), &c);
    auto& cset = conns_.at(c.peer());

    cset.erase(std::remove_if(cset.begin(), cset.end(),
    [port = c.local_port()] (const std::unique_ptr<Client_connection>& conn)->bool
    {
      return conn->local_port() == port;
    }));
  }

}
<|endoftext|>


<commit_before>/*
 * Copyright 2016 - 2019 gtalent2@gmail.com
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#include <ox/fs/fs.hpp>
#include <ox/std/units.hpp>
#include <nostalgia/world/world.hpp>

using namespace nostalgia::common;
using namespace nostalgia::core;
using namespace nostalgia::world;

ox::Error run(ox::FileSystem *fs) {
	Context ctx;
	ctx.rom = fs;
	oxReturnError(init(&ctx));
	//Zone zone;
	//oxReturnError(zone.init(&ctx, Bounds{0, 0, 40, 40}, "/TileSheets/Charset.ng", "/Palettes/Charset.npal"));
	//zone.draw(&ctx);
	oxReturnError(initConsole(&ctx));
	puts(&ctx, 10, 9, "DOPENESS!!!");
	oxReturnError(run());
	oxReturnError(shutdownGfx());
	return OxError(0);
}

int main(int argc, const char **argv) {
	if (argc > 1) {
		ox::FileSystem *fs = nullptr;
		uint8_t *rom = nullptr;
		auto path = argv[1];
		const auto lastDot = ox_lastIndexOf(path, '.');
		const auto fsExt = lastDot != -1 ? path + lastDot : "";
		if (ox_strcmp(fsExt, ".oxfs") == 0) {
			rom = loadRom(path);
			if (!rom) {
				return 1;
			}
			fs = new (ox_alloca(sizeof(ox::FileStore32))) ox::FileSystem32(ox::FileStore32(rom, 32 * ox::units::MB));
#ifdef OX_HAS_PASSTHROUGHFS
		} else {
			fs = new (ox_alloca(sizeof(ox::PassThroughFS))) ox::PassThroughFS(path);
#endif
		}
		auto err = run(fs);
		oxAssert(err, "Something went wrong...");
		unloadRom(rom);
		return err;
	}
	return 2;
}
<commit_msg>[nostalgia/player] Make no-FS case an error<commit_after>/*
 * Copyright 2016 - 2019 gtalent2@gmail.com
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#include <ox/fs/fs.hpp>
#include <ox/std/units.hpp>
#include <nostalgia/world/world.hpp>

using namespace nostalgia::common;
using namespace nostalgia::core;
using namespace nostalgia::world;

ox::Error run(ox::FileSystem *fs) {
	Context ctx;
	ctx.rom = fs;
	oxReturnError(init(&ctx));
	//Zone zone;
	//oxReturnError(zone.init(&ctx, Bounds{0, 0, 40, 40}, "/TileSheets/Charset.ng", "/Palettes/Charset.npal"));
	//zone.draw(&ctx);
	oxReturnError(initConsole(&ctx));
	puts(&ctx, 10, 9, "DOPENESS!!!");
	oxReturnError(run());
	oxReturnError(shutdownGfx());
	return OxError(0);
}

int main(int argc, const char **argv) {
	if (argc > 1) {
		ox::FileSystem *fs = nullptr;
		uint8_t *rom = nullptr;
		auto path = argv[1];
		const auto lastDot = ox_lastIndexOf(path, '.');
		const auto fsExt = lastDot != -1 ? path + lastDot : "";
		if (ox_strcmp(fsExt, ".oxfs") == 0) {
			rom = loadRom(path);
			if (!rom) {
				return 1;
			}
			fs = new (ox_alloca(sizeof(ox::FileStore32))) ox::FileSystem32(ox::FileStore32(rom, 32 * ox::units::MB));
		} else {
#ifdef OX_HAS_PASSTHROUGHFS
			fs = new (ox_alloca(sizeof(ox::PassThroughFS))) ox::PassThroughFS(path);
#else
			return 2;
#endif
		}
		auto err = run(fs);
		oxAssert(err, "Something went wrong...");
		unloadRom(rom);
		return err;
	}
	return 3;
}
<|endoftext|>


<commit_before>/**
 *  @file
 *  @author     2012 Stefan Radomski (stefan.radomski@cs.tu-darmstadt.de)
 *  @copyright  Simplified BSD
 *
 *  @cond
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the FreeBSD license as published by the FreeBSD
 *  project.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 *
 *  You should have received a copy of the FreeBSD license along with this
 *  program. If not, see <http://www.opensource.org/licenses/bsd-license>.
 *  @endcond
 */

#include "umundo/discovery/avahi/AvahiNodeStub.h"
#include "umundo/discovery/avahi/AvahiNodeDiscovery.h"

namespace umundo {

AvahiNodeStub::AvahiNodeStub() {
	_isRemote = false;
};

AvahiNodeStub::~AvahiNodeStub() {
}

const std::string AvahiNodeStub::getIP() const {
	return (_interfacesIPv4.begin())->second;
}

std::ostream& operator<<(std::ostream &out, const AvahiNodeStub* n) {
	out << n->_uuid;
	return out;
}

}
<commit_msg>Forgot to initialize isInProcess flag<commit_after>/**
 *  @file
 *  @author     2012 Stefan Radomski (stefan.radomski@cs.tu-darmstadt.de)
 *  @copyright  Simplified BSD
 *
 *  @cond
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the FreeBSD license as published by the FreeBSD
 *  project.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 *
 *  You should have received a copy of the FreeBSD license along with this
 *  program. If not, see <http://www.opensource.org/licenses/bsd-license>.
 *  @endcond
 */

#include "umundo/discovery/avahi/AvahiNodeStub.h"
#include "umundo/discovery/avahi/AvahiNodeDiscovery.h"

namespace umundo {

AvahiNodeStub::AvahiNodeStub() {
	_isRemote = false;
	_isInProcess = false;
};

AvahiNodeStub::~AvahiNodeStub() {
}

const std::string AvahiNodeStub::getIP() const {
	return (_interfacesIPv4.begin())->second;
}

std::ostream& operator<<(std::ostream &out, const AvahiNodeStub* n) {
	out << n->_uuid;
	return out;
}

}
<|endoftext|>