<commit_before>#ifndef MJOLNIR_EXCLUDED_VOLUME_POTENTIAL
#define MJOLNIR_EXCLUDED_VOLUME_POTENTIAL
#include "GlobalPotentialBase.hpp"
#include <cmath>

namespace mjolnir
{

template<typename traitsT>
class ExcludedVolumePotential : public GlobalPotentialBase<traitsT>
{
  public:
    typedef traitsT traits_type;
    typedef typename traits_type::real_type real_type;
    typedef typename traits_type::coordinate_type coordinate_type;
    typedef real_type parameter_type;

    // rc = 2.5 * sigma
    constexpr static real_type cutoff_ratio = 2.5;

  public:
    ExcludedVolumePotential() = default;
    ExcludedVolumePotential(
            const real_type eps, const std::vector<parameter_type>& params)
        : epsilon_(eps), radii_(params)
    {}
    ExcludedVolumePotential(
            real_type&& eps, std::vector<parameter_type>&& params)
        : epsilon_(std::forward<real_type>(eps)),
          radii_(std::forward<std::vector<parameter_type>>(params))
    {}
    ~ExcludedVolumePotential() override = default;

    real_type  epsilon() const {return epsilon_;}
    real_type& epsilon()       {return epsilon_;}

    void emplace(const parameter_type& radius);
    void emplace(parameter_type&& radius);

    void set_radii(const std::vector<parameter_type>& radii);
    void set_radii(std::vector<parameter_type>&& radii);

    std::size_t size() const {return radii_.size();}
    void resize(const std::size_t i){radii_.resize(i);}
    void reserve(const std::size_t i){radii_.reserve(i);}
    void clear(){radii_.clear();}

    parameter_type&       operator[](const std::size_t i)       {return radii_[i];}
    parameter_type const& operator[](const std::size_t i) const {return radii_[i];}
    parameter_type&       at(const std::size_t i)       {return radii_.at(i);}
    parameter_type const& at(const std::size_t i) const {return radii_.at(i);}

    real_type potential(const std::size_t i, const std::size_t j,
                        const real_type r) const override;

    real_type derivative(const std::size_t i, const std::size_t j,
                         const real_type r) const override;

    real_type max_cutoff_length() const override;

  private:

    real_type epsilon_;
    std::vector<parameter_type> radii_;
};

template<typename traitsT>
inline void
ExcludedVolumePotential<traitsT>::emplace(const parameter_type& radius)
{
    radii_.push_back(radius);
    return ;
}

template<typename traitsT>
inline void
ExcludedVolumePotential<traitsT>::emplace(parameter_type&& radius)
{
    radii_.emplace_back(std::forward<parameter_type>(radius));
    return ;
}

template<typename traitsT>
inline void
ExcludedVolumePotential<traitsT>::set_radii(const std::vector<parameter_type>& radii)
{
    radii_ = radii;
    return ;
}

template<typename traitsT>
inline void
ExcludedVolumePotential<traitsT>::set_radii(std::vector<parameter_type>&& radii)
{
    radii_ = std::forward<std::vector<parameter_type>>(radii);
    return ;
}

template<typename traitsT>
inline typename ExcludedVolumePotential<traitsT>::real_type
ExcludedVolumePotential<traitsT>::potential(
        const std::size_t i, const std::size_t j, const real_type r) const
{
    const real_type d = radii_[i] + radii_[j];
    const real_type d_r = d / r;
    const real_type dr3 = d_r * d_r * d_r;
    const real_type dr6 = dr3 * dr3;
    const real_type dr12 = dr6 * dr6;
    return epsilon_ * dr12;
}

template<typename traitsT>
inline typename ExcludedVolumePotential<traitsT>::real_type
ExcludedVolumePotential<traitsT>::derivative(
        const std::size_t i, const std::size_t j, const real_type r) const
{
    const real_type d = radii_[i] + radii_[j];
    const real_type rinv = 1. / r;
    const real_type d_r = d * rinv;
    const real_type dr3 = d_r * d_r * d_r;
    const real_type dr6 = dr3 * dr3;
    const real_type dr12 = dr6 * dr6;
    return -12 * epsilon_ * dr12 * rinv;
}

template<typename traitsT>
inline typename ExcludedVolumePotential<traitsT>::real_type
ExcludedVolumePotential<traitsT>::max_cutoff_length() const
{
    const real_type max_sigma =
        *(std::max_element(radii_.cbegin(), radii_.cend()));
    return max_sigma * cutoff_ratio;
}

} // mjolnir
#endif /* MJOLNIR_EXCLUDED_VOLUME_POTENTIAL */
<commit_msg>add include file<commit_after>#ifndef MJOLNIR_EXCLUDED_VOLUME_POTENTIAL
#define MJOLNIR_EXCLUDED_VOLUME_POTENTIAL
#include "GlobalPotentialBase.hpp"
#include <algorithm>
#include <cmath>

namespace mjolnir
{

template<typename traitsT>
class ExcludedVolumePotential : public GlobalPotentialBase<traitsT>
{
  public:
    typedef traitsT traits_type;
    typedef typename traits_type::real_type real_type;
    typedef typename traits_type::coordinate_type coordinate_type;
    typedef real_type parameter_type;

    // rc = 2.5 * sigma
    constexpr static real_type cutoff_ratio = 2.5;

  public:
    ExcludedVolumePotential() = default;
    ExcludedVolumePotential(
            const real_type eps, const std::vector<parameter_type>& params)
        : epsilon_(eps), radii_(params)
    {}
    ExcludedVolumePotential(
            real_type&& eps, std::vector<parameter_type>&& params)
        : epsilon_(std::forward<real_type>(eps)),
          radii_(std::forward<std::vector<parameter_type>>(params))
    {}
    ~ExcludedVolumePotential() override = default;

    real_type  epsilon() const {return epsilon_;}
    real_type& epsilon()       {return epsilon_;}

    void emplace(const parameter_type& radius);
    void emplace(parameter_type&& radius);

    void set_radii(const std::vector<parameter_type>& radii);
    void set_radii(std::vector<parameter_type>&& radii);

    std::size_t size() const {return radii_.size();}
    void resize(const std::size_t i){radii_.resize(i);}
    void reserve(const std::size_t i){radii_.reserve(i);}
    void clear(){radii_.clear();}

    parameter_type&       operator[](const std::size_t i)       {return radii_[i];}
    parameter_type const& operator[](const std::size_t i) const {return radii_[i];}
    parameter_type&       at(const std::size_t i)       {return radii_.at(i);}
    parameter_type const& at(const std::size_t i) const {return radii_.at(i);}

    real_type potential(const std::size_t i, const std::size_t j,
                        const real_type r) const override;

    real_type derivative(const std::size_t i, const std::size_t j,
                         const real_type r) const override;

    real_type max_cutoff_length() const override;

  private:

    real_type epsilon_;
    std::vector<parameter_type> radii_;
};

template<typename traitsT>
inline void
ExcludedVolumePotential<traitsT>::emplace(const parameter_type& radius)
{
    radii_.push_back(radius);
    return ;
}

template<typename traitsT>
inline void
ExcludedVolumePotential<traitsT>::emplace(parameter_type&& radius)
{
    radii_.emplace_back(std::forward<parameter_type>(radius));
    return ;
}

template<typename traitsT>
inline void
ExcludedVolumePotential<traitsT>::set_radii(const std::vector<parameter_type>& radii)
{
    radii_ = radii;
    return ;
}

template<typename traitsT>
inline void
ExcludedVolumePotential<traitsT>::set_radii(std::vector<parameter_type>&& radii)
{
    radii_ = std::forward<std::vector<parameter_type>>(radii);
    return ;
}

template<typename traitsT>
inline typename ExcludedVolumePotential<traitsT>::real_type
ExcludedVolumePotential<traitsT>::potential(
        const std::size_t i, const std::size_t j, const real_type r) const
{
    const real_type d = radii_[i] + radii_[j];
    const real_type d_r = d / r;
    const real_type dr3 = d_r * d_r * d_r;
    const real_type dr6 = dr3 * dr3;
    const real_type dr12 = dr6 * dr6;
    return epsilon_ * dr12;
}

template<typename traitsT>
inline typename ExcludedVolumePotential<traitsT>::real_type
ExcludedVolumePotential<traitsT>::derivative(
        const std::size_t i, const std::size_t j, const real_type r) const
{
    const real_type d = radii_[i] + radii_[j];
    const real_type rinv = 1. / r;
    const real_type d_r = d * rinv;
    const real_type dr3 = d_r * d_r * d_r;
    const real_type dr6 = dr3 * dr3;
    const real_type dr12 = dr6 * dr6;
    return -12 * epsilon_ * dr12 * rinv;
}

template<typename traitsT>
inline typename ExcludedVolumePotential<traitsT>::real_type
ExcludedVolumePotential<traitsT>::max_cutoff_length() const
{
    const real_type max_sigma =
        *(std::max_element(radii_.cbegin(), radii_.cend()));
    return max_sigma * cutoff_ratio;
}

} // mjolnir
#endif /* MJOLNIR_EXCLUDED_VOLUME_POTENTIAL */
<|endoftext|>


<commit_before><commit_msg>ui: adjust e2e path width<commit_after><|endoftext|>


<commit_before>/*
 * Copyright (C) 2007, 2008, 2009, 2010 Apple Inc. All rights reserved.
 * Copyright (C) 2008 Matt Lilek <webkit@mattlilek.com>
 * Copyright (C) 2011 Google Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1.  Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 * 2.  Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
 *     its contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "config.h"
#include "core/inspector/InspectorInspectorAgent.h"

#include "bindings/v8/DOMWrapperWorld.h"
#include "bindings/v8/ScriptController.h"
#include "core/InspectorFrontend.h"
#include "core/dom/Document.h"
#include "core/frame/LocalFrame.h"
#include "core/inspector/InjectedScriptHost.h"
#include "core/inspector/InjectedScriptManager.h"
#include "core/inspector/InspectorController.h"
#include "core/inspector/InspectorState.h"
#include "core/inspector/InstrumentingAgents.h"
#include "core/loader/DocumentLoader.h"
#include "core/page/Page.h"
#include "platform/weborigin/SecurityOrigin.h"
#include "wtf/text/StringBuilder.h"

namespace WebCore {

namespace InspectorAgentState {
static const char inspectorAgentEnabled[] = "inspectorAgentEnabled";
}

InspectorInspectorAgent::InspectorInspectorAgent(Page* page, InjectedScriptManager* injectedScriptManager)
    : InspectorBaseAgent<InspectorInspectorAgent>("Inspector")
    , m_inspectedPage(page)
    , m_frontend(0)
    , m_injectedScriptManager(injectedScriptManager)
{
    ASSERT_ARG(page, page);
}

InspectorInspectorAgent::~InspectorInspectorAgent()
{
    m_instrumentingAgents->setInspectorInspectorAgent(0);
}

void InspectorInspectorAgent::didClearDocumentOfWindowObject(LocalFrame* frame)
{
    if (m_injectedScriptForOrigin.isEmpty())
        return;

    String origin = frame->document()->securityOrigin()->toRawString();
    String script = m_injectedScriptForOrigin.get(origin);
    if (script.isEmpty())
        return;
    int injectedScriptId = m_injectedScriptManager->injectedScriptIdFor(ScriptState::forMainWorld(frame));
    StringBuilder scriptSource;
    scriptSource.append(script);
    scriptSource.append("(");
    scriptSource.appendNumber(injectedScriptId);
    scriptSource.append(")");
    frame->script().executeScriptInMainWorld(scriptSource.toString());
}

void InspectorInspectorAgent::init()
{
    m_instrumentingAgents->setInspectorInspectorAgent(this);
}

void InspectorInspectorAgent::setFrontend(InspectorFrontend* inspectorFrontend)
{
    m_frontend = inspectorFrontend;
}

void InspectorInspectorAgent::clearFrontend()
{
    m_pendingEvaluateTestCommands.clear();
    m_frontend = 0;
    m_injectedScriptManager->discardInjectedScripts();
    ErrorString error;
    disable(&error);
}

void InspectorInspectorAgent::enable(ErrorString*)
{
    m_state->setBoolean(InspectorAgentState::inspectorAgentEnabled, true);

    if (m_pendingInspectData.first)
        inspect(m_pendingInspectData.first, m_pendingInspectData.second);

    for (Vector<pair<long, String> >::iterator it = m_pendingEvaluateTestCommands.begin(); m_frontend && it != m_pendingEvaluateTestCommands.end(); ++it)
        m_frontend->inspector()->evaluateForTestInFrontend(static_cast<int>((*it).first), (*it).second);
    m_pendingEvaluateTestCommands.clear();
}

void InspectorInspectorAgent::disable(ErrorString*)
{
    m_state->setBoolean(InspectorAgentState::inspectorAgentEnabled, false);
}

void InspectorInspectorAgent::reset(ErrorString*)
{
    m_inspectedPage->inspectorController().reconnectFrontend();
}

void InspectorInspectorAgent::domContentLoadedEventFired(LocalFrame* frame)
{
    if (frame->page()->mainFrame() != frame)
        return;

    m_injectedScriptManager->injectedScriptHost()->clearInspectedObjects();
}

void InspectorInspectorAgent::evaluateForTestInFrontend(long callId, const String& script)
{
    if (m_state->getBoolean(InspectorAgentState::inspectorAgentEnabled))
        m_frontend->inspector()->evaluateForTestInFrontend(static_cast<int>(callId), script);
    else
        m_pendingEvaluateTestCommands.append(pair<long, String>(callId, script));
}

void InspectorInspectorAgent::setInjectedScriptForOrigin(const String& origin, const String& source)
{
    m_injectedScriptForOrigin.set(origin, source);
}

void InspectorInspectorAgent::inspect(PassRefPtr<TypeBuilder::Runtime::RemoteObject> objectToInspect, PassRefPtr<JSONObject> hints)
{
    if (m_state->getBoolean(InspectorAgentState::inspectorAgentEnabled) && m_frontend) {
        m_frontend->inspector()->inspect(objectToInspect, hints);
        m_pendingInspectData.first = nullptr;
        m_pendingInspectData.second = nullptr;
        return;
    }
    m_pendingInspectData.first = objectToInspect;
    m_pendingInspectData.second = hints;
}

} // namespace WebCore
<commit_msg>Do not buffer evaluateForTestInFrontend commands<commit_after>/*
 * Copyright (C) 2007, 2008, 2009, 2010 Apple Inc. All rights reserved.
 * Copyright (C) 2008 Matt Lilek <webkit@mattlilek.com>
 * Copyright (C) 2011 Google Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1.  Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 * 2.  Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
 *     its contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "config.h"
#include "core/inspector/InspectorInspectorAgent.h"

#include "bindings/v8/DOMWrapperWorld.h"
#include "bindings/v8/ScriptController.h"
#include "core/InspectorFrontend.h"
#include "core/dom/Document.h"
#include "core/frame/LocalFrame.h"
#include "core/inspector/InjectedScriptHost.h"
#include "core/inspector/InjectedScriptManager.h"
#include "core/inspector/InspectorController.h"
#include "core/inspector/InspectorState.h"
#include "core/inspector/InstrumentingAgents.h"
#include "core/loader/DocumentLoader.h"
#include "core/page/Page.h"
#include "platform/weborigin/SecurityOrigin.h"
#include "wtf/text/StringBuilder.h"

namespace WebCore {

namespace InspectorAgentState {
static const char inspectorAgentEnabled[] = "inspectorAgentEnabled";
}

InspectorInspectorAgent::InspectorInspectorAgent(Page* page, InjectedScriptManager* injectedScriptManager)
    : InspectorBaseAgent<InspectorInspectorAgent>("Inspector")
    , m_inspectedPage(page)
    , m_frontend(0)
    , m_injectedScriptManager(injectedScriptManager)
{
    ASSERT_ARG(page, page);
}

InspectorInspectorAgent::~InspectorInspectorAgent()
{
    m_instrumentingAgents->setInspectorInspectorAgent(0);
}

void InspectorInspectorAgent::didClearDocumentOfWindowObject(LocalFrame* frame)
{
    if (m_injectedScriptForOrigin.isEmpty())
        return;

    String origin = frame->document()->securityOrigin()->toRawString();
    String script = m_injectedScriptForOrigin.get(origin);
    if (script.isEmpty())
        return;
    int injectedScriptId = m_injectedScriptManager->injectedScriptIdFor(ScriptState::forMainWorld(frame));
    StringBuilder scriptSource;
    scriptSource.append(script);
    scriptSource.append("(");
    scriptSource.appendNumber(injectedScriptId);
    scriptSource.append(")");
    frame->script().executeScriptInMainWorld(scriptSource.toString());
}

void InspectorInspectorAgent::init()
{
    m_instrumentingAgents->setInspectorInspectorAgent(this);
}

void InspectorInspectorAgent::setFrontend(InspectorFrontend* inspectorFrontend)
{
    m_frontend = inspectorFrontend;
}

void InspectorInspectorAgent::clearFrontend()
{
    m_pendingEvaluateTestCommands.clear();
    m_frontend = 0;
    m_injectedScriptManager->discardInjectedScripts();
    ErrorString error;
    disable(&error);
}

void InspectorInspectorAgent::enable(ErrorString*)
{
    m_state->setBoolean(InspectorAgentState::inspectorAgentEnabled, true);

    if (m_pendingInspectData.first)
        inspect(m_pendingInspectData.first, m_pendingInspectData.second);

    for (Vector<pair<long, String> >::iterator it = m_pendingEvaluateTestCommands.begin(); m_frontend && it != m_pendingEvaluateTestCommands.end(); ++it)
        m_frontend->inspector()->evaluateForTestInFrontend(static_cast<int>((*it).first), (*it).second);
    m_pendingEvaluateTestCommands.clear();
}

void InspectorInspectorAgent::disable(ErrorString*)
{
    m_state->setBoolean(InspectorAgentState::inspectorAgentEnabled, false);
}

void InspectorInspectorAgent::reset(ErrorString*)
{
    m_inspectedPage->inspectorController().reconnectFrontend();
}

void InspectorInspectorAgent::domContentLoadedEventFired(LocalFrame* frame)
{
    if (frame->page()->mainFrame() != frame)
        return;

    m_injectedScriptManager->injectedScriptHost()->clearInspectedObjects();
}

void InspectorInspectorAgent::evaluateForTestInFrontend(long callId, const String& script)
{
    if (m_state->getBoolean(InspectorAgentState::inspectorAgentEnabled)) {
        m_frontend->inspector()->evaluateForTestInFrontend(static_cast<int>(callId), script);
        m_frontend->inspector()->flush();
    } else {
        m_pendingEvaluateTestCommands.append(pair<long, String>(callId, script));
    }
}

void InspectorInspectorAgent::setInjectedScriptForOrigin(const String& origin, const String& source)
{
    m_injectedScriptForOrigin.set(origin, source);
}

void InspectorInspectorAgent::inspect(PassRefPtr<TypeBuilder::Runtime::RemoteObject> objectToInspect, PassRefPtr<JSONObject> hints)
{
    if (m_state->getBoolean(InspectorAgentState::inspectorAgentEnabled) && m_frontend) {
        m_frontend->inspector()->inspect(objectToInspect, hints);
        m_pendingInspectData.first = nullptr;
        m_pendingInspectData.second = nullptr;
        return;
    }
    m_pendingInspectData.first = objectToInspect;
    m_pendingInspectData.second = hints;
}

} // namespace WebCore
<|endoftext|>


<commit_before><commit_msg>🙈 Ignore SIGPIPE<commit_after><|endoftext|>


<commit_before>
#include "circularBuffer.h"
#include <iostream>

using namespace std;

int main() {
    char tmpBuf[1024];
    char helloBuf[] = "hello world"; // 11

    CircularBuffer buf(1024);

    cout << "capacity: " << buf.capacity() << endl;
    cout << "size: " << buf.size() << endl;

    int nwrite = buf.write(helloBuf, 11);
    cout << "nwrite: " << nwrite << endl;

    nwrite = buf.write(tmpBuf, 1024);
    cout << "nwrite: " << nwrite << endl;

    int nread = buf.read(tmpBuf, 1020);
    cout << "nread: " << nread << endl;

    nread = buf.read(tmpBuf, 100);
    cout << "nread: " << nread << endl;

    return 0;
}
<commit_msg>Add comment.<commit_after>
#include "circularBuffer.h"
#include <iostream>

// Thanks to: http://www.asawicki.info/news_1468_circular_buffer_of_raw_binary_data_in_c.html

using namespace std;

int main() {
    char tmpBuf[1024];
    char helloBuf[] = "hello world"; // 11

    CircularBuffer buf(1024);

    cout << "capacity: " << buf.capacity() << endl;
    cout << "size: " << buf.size() << endl;

    int nwrite = buf.write(helloBuf, 11);
    cout << "nwrite: " << nwrite << endl;

    nwrite = buf.write(tmpBuf, 1024);
    cout << "nwrite: " << nwrite << endl;

    int nread = buf.read(tmpBuf, 1020);
    cout << "nread: " << nread << endl;

    nread = buf.read(tmpBuf, 100);
    cout << "nread: " << nread << endl;

    return 0;
}
<|endoftext|>


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

#include <modules/qtwidgets/sliderwidgetqt.h>
#include <modules/qtwidgets/NumberLineEdit.h>

#include <limits>
#include <cmath>

#include <warn/push>
#include <warn/ignore/all>
#include <QStyle>
#include <QSlider>
#include <QHBoxLayout>
#include <QSignalBlocker>
#include <QMouseEvent>
#include <warn/pop>

namespace inviwo {

BaseSliderWidgetQt::BaseSliderWidgetQt(bool intMode)
    : QWidget()
    , spinBox_(new NumberLineEdit(intMode))
    , slider_(new QSlider())
    , spinnerValue_(0.0)
    , sliderValue_(0) {

    QHBoxLayout *hLayout = new QHBoxLayout();

    slider_->setOrientation(Qt::Horizontal);
    slider_->setPageStep(1);
    slider_->setMaximum(sliderMax_);
    slider_->installEventFilter(this);
    slider_->setFocusPolicy(Qt::ClickFocus);

    setFocusPolicy(spinBox_->focusPolicy());
    setFocusProxy(spinBox_);
    slider_->setFocusProxy(spinBox_);

    spinBox_->setKeyboardTracking(false);  // don't emit the valueChanged() signal while typing

    hLayout->addWidget(slider_);
    hLayout->addWidget(spinBox_);
    hLayout->setContentsMargins(0, 0, 0, 0);
    hLayout->setSpacing(5);
    hLayout->setStretch(0, 3);
    hLayout->setStretch(1, 1);

    setLayout(hLayout);
    connect(slider_, &QSlider::valueChanged, this, &BaseSliderWidgetQt::updateFromSlider);
    connect(spinBox_, static_cast<void (QDoubleSpinBox::*)(double)>(&QDoubleSpinBox::valueChanged),
            this, &BaseSliderWidgetQt::updateFromSpinBox);

    QSizePolicy sp = sizePolicy();
    sp.setVerticalPolicy(QSizePolicy::Fixed);
    setSizePolicy(sp);
}

void BaseSliderWidgetQt::setWrapping(bool wrap) { spinBox_->setWrapping(wrap); }

bool BaseSliderWidgetQt::wrapping() const { return spinBox_->wrapping(); }

void BaseSliderWidgetQt::applyInit() {
    updateSlider();
    updateSpinBox();
}

void BaseSliderWidgetQt::applyValue() {
    applyInit();
    emit valueChanged();
}
void BaseSliderWidgetQt::applyMinValue() {
    QSignalBlocker spinBlock(spinBox_);
    QSignalBlocker slideBlock(slider_);

    spinBox_->setMinimum(transformMinValueToSpinner());
    slider_->setMinimum(transformMinValueToSlider());
    updateSlider();
}
void BaseSliderWidgetQt::applyMaxValue() {
    QSignalBlocker spinBlock(spinBox_);
    QSignalBlocker slideBlock(slider_);

    spinBox_->setMaximum(transformMaxValueToSpinner());
    slider_->setMaximum(transformMaxValueToSlider());
    updateSlider();
}
void BaseSliderWidgetQt::applyIncrement() {
    QSignalBlocker spinBlock(spinBox_);
    QSignalBlocker slideBlock(slider_);

    spinBox_->setSingleStep(transformIncrementToSpinner());
    spinBox_->setDecimals(transformIncrementToSpinnerDecimals());
    slider_->setSingleStep(transformIncrementToSlider());
}

void BaseSliderWidgetQt::updateFromSlider() {
    int newValue = slider_->value();
    if (newValue != sliderValue_) {
        sliderValue_ = newValue;
        newSliderValue(sliderValue_);
        updateSpinBox();
        emit valueChanged();
    }
}

void BaseSliderWidgetQt::updateFromSpinBox() {
    double newValue = spinBox_->value();
    if (fabs(newValue - spinnerValue_) > std::numeric_limits<double>::epsilon()) {
        spinnerValue_ = newValue;
        newSpinnerValue(spinnerValue_);
        updateSlider();
        emit valueChanged();
    }
}

void BaseSliderWidgetQt::updateSpinBox() {
    QSignalBlocker spinBlock(spinBox_);

    spinnerValue_ = transformValueToSpinner();
    spinBox_->setValue(spinnerValue_);
}

void BaseSliderWidgetQt::updateSlider() {
    QSignalBlocker slideBlock(slider_);

    sliderValue_ = transformValueToSlider();
    bool isOutOfBounds = (slider_->maximum() < sliderValue_ || slider_->minimum() > sliderValue_);
    if (isOutOfBounds != slider_->property("outOfBounds").toBool()) {
        slider_->setProperty("outOfBounds", isOutOfBounds);
        slider_->style()->unpolish(slider_);
        slider_->style()->polish(slider_);
    }

    slider_->setValue(sliderValue_);
}

bool BaseSliderWidgetQt::eventFilter(QObject *watched, QEvent *event) {
    if (watched == slider_ && event->type() == QEvent::MouseButtonRelease) {
        QMouseEvent *me = static_cast<QMouseEvent *>(event);
        if (me->button() == Qt::LeftButton && !slider_->isSliderDown() && isEnabled()) {
            auto newPos = slider_->minimum() + static_cast<double>(me->pos().x()) *
                                                   (slider_->maximum() - slider_->minimum()) /
                                                   slider_->width();
            slider_->setValue(static_cast<int>(newPos));
            me->accept();
            return true;
        }
    }

    return QObject::eventFilter(watched, event);
}

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

#include <modules/qtwidgets/sliderwidgetqt.h>
#include <modules/qtwidgets/numberlineedit.h>

#include <limits>
#include <cmath>

#include <warn/push>
#include <warn/ignore/all>
#include <QStyle>
#include <QSlider>
#include <QHBoxLayout>
#include <QSignalBlocker>
#include <QMouseEvent>
#include <warn/pop>

namespace inviwo {

BaseSliderWidgetQt::BaseSliderWidgetQt(bool intMode)
    : QWidget()
    , spinBox_(new NumberLineEdit(intMode))
    , slider_(new QSlider())
    , spinnerValue_(0.0)
    , sliderValue_(0) {

    QHBoxLayout *hLayout = new QHBoxLayout();

    slider_->setOrientation(Qt::Horizontal);
    slider_->setPageStep(1);
    slider_->setMaximum(sliderMax_);
    slider_->installEventFilter(this);
    slider_->setFocusPolicy(Qt::ClickFocus);

    setFocusPolicy(spinBox_->focusPolicy());
    setFocusProxy(spinBox_);
    slider_->setFocusProxy(spinBox_);

    spinBox_->setKeyboardTracking(false);  // don't emit the valueChanged() signal while typing

    hLayout->addWidget(slider_);
    hLayout->addWidget(spinBox_);
    hLayout->setContentsMargins(0, 0, 0, 0);
    hLayout->setSpacing(5);
    hLayout->setStretch(0, 3);
    hLayout->setStretch(1, 1);

    setLayout(hLayout);
    connect(slider_, &QSlider::valueChanged, this, &BaseSliderWidgetQt::updateFromSlider);
    connect(spinBox_, static_cast<void (QDoubleSpinBox::*)(double)>(&QDoubleSpinBox::valueChanged),
            this, &BaseSliderWidgetQt::updateFromSpinBox);

    QSizePolicy sp = sizePolicy();
    sp.setVerticalPolicy(QSizePolicy::Fixed);
    setSizePolicy(sp);
}

void BaseSliderWidgetQt::setWrapping(bool wrap) { spinBox_->setWrapping(wrap); }

bool BaseSliderWidgetQt::wrapping() const { return spinBox_->wrapping(); }

void BaseSliderWidgetQt::applyInit() {
    updateSlider();
    updateSpinBox();
}

void BaseSliderWidgetQt::applyValue() {
    applyInit();
    emit valueChanged();
}
void BaseSliderWidgetQt::applyMinValue() {
    QSignalBlocker spinBlock(spinBox_);
    QSignalBlocker slideBlock(slider_);

    spinBox_->setMinimum(transformMinValueToSpinner());
    slider_->setMinimum(transformMinValueToSlider());
    updateSlider();
}
void BaseSliderWidgetQt::applyMaxValue() {
    QSignalBlocker spinBlock(spinBox_);
    QSignalBlocker slideBlock(slider_);

    spinBox_->setMaximum(transformMaxValueToSpinner());
    slider_->setMaximum(transformMaxValueToSlider());
    updateSlider();
}
void BaseSliderWidgetQt::applyIncrement() {
    QSignalBlocker spinBlock(spinBox_);
    QSignalBlocker slideBlock(slider_);

    spinBox_->setSingleStep(transformIncrementToSpinner());
    spinBox_->setDecimals(transformIncrementToSpinnerDecimals());
    slider_->setSingleStep(transformIncrementToSlider());
}

void BaseSliderWidgetQt::updateFromSlider() {
    int newValue = slider_->value();
    if (newValue != sliderValue_) {
        sliderValue_ = newValue;
        newSliderValue(sliderValue_);
        updateSpinBox();
        emit valueChanged();
    }
}

void BaseSliderWidgetQt::updateFromSpinBox() {
    double newValue = spinBox_->value();
    if (fabs(newValue - spinnerValue_) > std::numeric_limits<double>::epsilon()) {
        spinnerValue_ = newValue;
        newSpinnerValue(spinnerValue_);
        updateSlider();
        emit valueChanged();
    }
}

void BaseSliderWidgetQt::updateSpinBox() {
    QSignalBlocker spinBlock(spinBox_);

    spinnerValue_ = transformValueToSpinner();
    spinBox_->setValue(spinnerValue_);
}

void BaseSliderWidgetQt::updateSlider() {
    QSignalBlocker slideBlock(slider_);

    sliderValue_ = transformValueToSlider();
    bool isOutOfBounds = (slider_->maximum() < sliderValue_ || slider_->minimum() > sliderValue_);
    if (isOutOfBounds != slider_->property("outOfBounds").toBool()) {
        slider_->setProperty("outOfBounds", isOutOfBounds);
        slider_->style()->unpolish(slider_);
        slider_->style()->polish(slider_);
    }

    slider_->setValue(sliderValue_);
}

bool BaseSliderWidgetQt::eventFilter(QObject *watched, QEvent *event) {
    if (watched == slider_ && event->type() == QEvent::MouseButtonRelease) {
        QMouseEvent *me = static_cast<QMouseEvent *>(event);
        if (me->button() == Qt::LeftButton && !slider_->isSliderDown() && isEnabled()) {
            auto newPos = slider_->minimum() + static_cast<double>(me->pos().x()) *
                                                   (slider_->maximum() - slider_->minimum()) /
                                                   slider_->width();
            slider_->setValue(static_cast<int>(newPos));
            me->accept();
            return true;
        }
    }

    return QObject::eventFilter(watched, event);
}

}  // namespace inviwo
<|endoftext|>


<commit_before>/*
 * Copyright 2006-2013 The FLWOR Foundation.
 *
 * 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.
 */

// standard
#include <algorithm>
#include <cstdlib>
#include <cstring>                      /* for memcpy(3) */
#include <iostream>
#ifndef WIN32
#include <cerrno>
#include <sys/time.h>
#endif /* WIN32 */

// libcurl
#include <curl/multi.h>

// Zorba
#include "util/curl_streambuf.h"

#define ZORBA_LIBCURL_AT_LEAST(MAJOR,MINOR,PATCH) \
  (LIBCURL_VERSION_MAJOR >= (MAJOR) && LIBCURL_VERSION_MINOR >= (MINOR) && LIBCURL_VERSION_PATCH >= (PATCH))

using namespace std;

namespace zorba {
namespace curl {

///////////////////////////////////////////////////////////////////////////////

exception::exception( char const *function, char const *uri, char const *msg ) :
  std::exception(),
  curl_code_( CURLE_OK ), curlm_code_( CURLM_OK ), msg_( msg )
{
}

exception::exception( char const *function, char const *uri, CURLcode code ) :
  std::exception(),
  curl_code_( code ), curlm_code_( CURLM_OK ),
  msg_( curl_easy_strerror( code ) )
{
  ostringstream oss;
  oss << " (CURLcode " << (int)code << ')';
  msg_ += oss.str();
}

exception::exception( char const *function, char const *uri, CURLMcode code ) :
  std::exception(),
  curl_code_( CURLE_OK ), curlm_code_( code ),
  msg_( curl_multi_strerror( code ) )
{
  ostringstream oss;
  oss << " (CURLMcode " << (int)code << ')';
  msg_ += oss.str();
}

exception::~exception() throw() {
  // out-of-line since it's virtual
}

const char* exception::what() const throw() {
  return msg_.c_str();
}

///////////////////////////////////////////////////////////////////////////////

listener::~listener() {
  // out-of-line since it's virtual
}

///////////////////////////////////////////////////////////////////////////////

streambuf::streambuf() {
  init();
}

streambuf::streambuf( char const *uri ) {
  init();
  open( uri );
}

streambuf::streambuf( CURL *curl ) {
  init();
  curl_ = curl;
  curl_init();
  curlm_init();
}

streambuf::~streambuf() {
  close();
#ifdef WIN32
  closesocket( dummy_socket_ );
#endif /* WIN32 */
  if ( listener_owner_ )
    delete listener_;
}

void streambuf::close() {
  if ( curl_ ) {
    if ( curlm_ ) {
      curl_multi_remove_handle( curlm_, curl_ );
      curl_multi_cleanup( curlm_ );
      curlm_ = 0;
    }
    curl_destroy();
  }
}

void streambuf::curl_create() {
  //
  // Having cURL initialization wrapped by a class and using a singleton static
  // instance guarantees that cURL is initialized exactly once before use and
  // and also is cleaned-up at program termination (when destructors for static
  // objects are called).
  //
  struct curl_initializer {
    curl_initializer() {
      ZORBA_CURL_ASSERT( curl_global_init( CURL_GLOBAL_ALL ) );
    }
    ~curl_initializer() {
      curl_global_cleanup();
    }
  };
  static curl_initializer initializer;

  curl_ = curl_easy_init();
  if ( !curl_ )
    throw exception( "curl_easy_init()", "", "" );
  try {
    curl_init();
  }
  catch ( ... ) {
    curl_destroy();
    throw;
  }
}

void streambuf::curl_destroy() {
  if ( curl_ ) {
    curl_easy_reset( curl_ );
    curl_easy_cleanup( curl_ );
    curl_ = 0;
  }
}

void streambuf::curl_verbose( bool verbose ) {
  verbose_ = verbose;
  if ( curl_ )
    ZORBA_CURL_ASSERT( curl_easy_setopt( curl_, CURLOPT_VERBOSE, verbose_ ? 1 : 0 ) );
}

void streambuf::curl_init() {
  curl_easy_reset( curl_ );
#if ZORBA_LIBCURL_AT_LEAST(7,19,4)
  ZORBA_CURL_ASSERT( curl_easy_setopt( curl_, CURLOPT_FOLLOWLOCATION, 1 ) );
#endif
#if ZORBA_LIBCURL_AT_LEAST(7,15,1)
  ZORBA_CURL_ASSERT( curl_easy_setopt( curl_, CURLOPT_MAXREDIRS, 50L ) );
#endif
#if ZORBA_LIBCURL_AT_LEAST(7,25,0)
  ZORBA_CURL_ASSERT( curl_easy_setopt( curl_, CURLOPT_TCP_KEEPALIVE, 1L ) );
#endif
  ZORBA_CURL_ASSERT( curl_easy_setopt( curl_, CURLOPT_WRITEDATA, this ) );
  ZORBA_CURL_ASSERT( curl_easy_setopt( curl_, CURLOPT_WRITEFUNCTION, curl_write_callback ) );

  if ( verbose_ )
    ZORBA_CURL_ASSERT( curl_easy_setopt( curl_, CURLOPT_VERBOSE, 1 ) );
}

void streambuf::curl_io( size_t *len_ptr ) {
  *len_ptr = 0;
  while ( curl_running_ && !*len_ptr ) {
    fd_set fd_read, fd_write, fd_except;
    FD_ZERO( &fd_read );
    FD_ZERO( &fd_write );
    FD_ZERO( &fd_except );
    int max_fd = -1;
#ifdef WIN32
    //
    // Windows does not like a call to select where all arguments are 0, so we
    // just add a dummy socket to make the call to select happy.
    //
    FD_SET( dummy_socket_, &fd_read );
#endif /* WIN32 */
    ZORBA_CURLM_ASSERT(
      curl_multi_fdset( curlm_, &fd_read, &fd_write, &fd_except, &max_fd )
    );

    //
    // Note that the fopen.c sample code is unnecessary at best or wrong at
    // worst; see: http://curl.haxx.se/mail/lib-2011-05/0011.html
    //
    timeval timeout;
    long curl_timeout_ms;
    ZORBA_CURLM_ASSERT( curl_multi_timeout( curlm_, &curl_timeout_ms ) );
    if ( curl_timeout_ms > 0 ) {
      timeout.tv_sec  = curl_timeout_ms / 1000;
      timeout.tv_usec = curl_timeout_ms % 1000 * 1000;
    } else {
      //
      // From curl_multi_timeout(3):
      //
      //    Note: if libcurl returns a -1 timeout here, it just means that
      //    libcurl currently has no stored timeout value. You must not wait
      //    too long (more than a few seconds perhaps) before you call
      //    curl_multi_perform() again.
      //
      // So we just pick some not-too-long default.
      //
      timeout.tv_sec  = 1;
      timeout.tv_usec = 0;
    }

    switch ( select( max_fd + 1, &fd_read, &fd_write, &fd_except, &timeout ) ) {
      case -1:                          // select error
#ifdef WIN32
        char err_buf[8];
        sprintf( err_buf, "%d", WSAGetLastError() );
        throw exception( "select()", "", err_buf );
#else
        throw exception( "select()", "", strerror( errno ) );
#endif /* WIN32 */
      case 0:                           // timeout
        // no break;
      default:
        CURLMcode code;
        do {
          code = curl_multi_perform( curlm_, &curl_running_ );
        } while ( code == CURLM_CALL_MULTI_PERFORM );
        ZORBA_CURLM_ASSERT( code );
    } // switch
  } // while
}

CURLcode streambuf::curl_multi_info_read( bool throw_on_error ) {
  underflow();
  CURLMsg *msg;
  int msgs_in_q;
  CURLcode code = CURLE_OK;
  while ( (msg = ::curl_multi_info_read( curlm_, &msgs_in_q )) )
    if ( msg->msg == CURLMSG_DONE )
      code = msg->data.result;
  if ( code && throw_on_error )
    throw exception( "curl_multi_info_read()", "", code );
  return code;
}

size_t streambuf::curl_write_callback( void *ptr, size_t size, size_t nmemb,
                                       void *data ) {
  size *= nmemb;
  streambuf *const that = static_cast<streambuf*>( data );

  if ( that->listener_ )
    that->listener_->curl_read( ptr, size );

  size_t const gbuf_free = that->gbuf_.capacity_ - that->gbuf_.len_;
  if ( size > gbuf_free ) {
    size_t new_capacity = that->gbuf_.capacity_ + size - gbuf_free;
    if ( void *const new_buf = realloc( that->gbuf_.ptr_, new_capacity ) ) {
      that->gbuf_.ptr_ = static_cast<char*>( new_buf );
      that->gbuf_.capacity_ = new_capacity;
    } else
      throw exception( "realloc()", "" );
  }
  ::memcpy( that->gbuf_.ptr_ + that->gbuf_.len_, ptr, size );
  that->gbuf_.len_ += size;
  return size;
}

void streambuf::init() {
  curl_ = 0;
  curlm_ = 0;
  curl_running_ = 0;
#ifdef WIN32
  dummy_socket_ = socket( AF_INET, SOCK_DGRAM, 0 );
  if ( dummy_socket_ == CURL_SOCKET_BAD || dummy_socket_ == INVALID_SOCKET )
    throw exception( "socket()", "" );
#endif /* WIN32 */
  listener_ = 0;
  listener_owner_ = false;
}

void streambuf::curlm_init() {
  //
  // Lie about cURL running initially so the while-loop in curl_io() will run
  // at least once.
  //
  curl_running_ = 1;

  //
  // Set the "get" pointer to the end (gptr() == egptr()) so a call to
  // underflow() and initial data read will be triggered.
  //
  gbuf_.len_ = gbuf_.capacity_;
  setg( gbuf_.ptr_, gbuf_.ptr_ + gbuf_.len_, gbuf_.ptr_ + gbuf_.len_ );

  //
  // Clean-up has to be done here with try/catch (as opposed to relying on the
  // destructor) because open() can be called from the constructor.  If an
  // exception is thrown, the constructor will not have completed, hence the
  // object will not have been fully constructed; therefore the destructor will
  // not be called.
  //
  try {
    if ( !(curlm_ = curl_multi_init()) )
      throw exception( "curl_multi_init()", "" );
    try {
      ZORBA_CURLM_ASSERT( curl_multi_add_handle( curlm_, curl_ ) );
    }
    catch ( ... ) {
      curl_multi_cleanup( curlm_ );
      curlm_ = 0;
      throw;
    }
  }
  catch ( ... ) {
    curl_destroy();
    throw;
  }
}

void streambuf::open( char const *uri ) {
  if ( !curl_ ) {
    curl_create();
    curlm_init();
  }
  ZORBA_CURL_ASSERT( curl_easy_setopt( curl_, CURLOPT_URL, uri ) );
}

void streambuf::set_listener( listener *l, bool take_ownership ) {
  if ( listener_owner_ )
    delete listener_;
  listener_ = l;
  listener_owner_ = take_ownership;
}

streamsize streambuf::showmanyc() {
  return egptr() - gptr();
}

streambuf::int_type streambuf::underflow() {
  while ( true ) {
    if ( gptr() < egptr() )
      return traits_type::to_int_type( *gptr() );
    curl_io( &gbuf_.len_ );
    if ( !gbuf_.len_ )
      return traits_type::eof();
    setg( gbuf_.ptr_, gbuf_.ptr_, gbuf_.ptr_ + gbuf_.len_ );
  }
}

streamsize streambuf::xsgetn( char_type *to, streamsize size ) {
  streamsize return_size = 0;

  if ( streamsize const gsize = egptr() - gptr() ) {
    streamsize const n = min( gsize, size );
    traits_type::copy( to, gptr(), static_cast<size_t>( n ) );
    gbump( static_cast<int>( n ) );
    to += n;
    size -= n, return_size += n;
  }

  while ( size > 0 ) {
    streamsize const get = min( (streamsize)gbuf_.capacity_, size );
    curl_io( &gbuf_.len_ );
    if ( !gbuf_.len_ )
      break;
    setg( gbuf_.ptr_, gbuf_.ptr_, gbuf_.ptr_ + gbuf_.len_ );
    streamsize const n = min( (streamsize)gbuf_.len_, size );
    traits_type::copy( to, gptr(), n );
    gbump( static_cast<int>( n ) );
    to += n;
    size -= n, return_size += n;
  }
  return return_size;
}

///////////////////////////////////////////////////////////////////////////////

} // namespace curl
} // namespace zorba
/* vim:set et sw=2 ts=2: */
<commit_msg>Now setting verbose_ to false by default.<commit_after>/*
 * Copyright 2006-2013 The FLWOR Foundation.
 *
 * 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.
 */

// standard
#include <algorithm>
#include <cstdlib>
#include <cstring>                      /* for memcpy(3) */
#include <iostream>
#ifndef WIN32
#include <cerrno>
#include <sys/time.h>
#endif /* WIN32 */

// libcurl
#include <curl/multi.h>

// Zorba
#include "util/curl_streambuf.h"

#define ZORBA_LIBCURL_AT_LEAST(MAJOR,MINOR,PATCH) \
  (LIBCURL_VERSION_MAJOR >= (MAJOR) && LIBCURL_VERSION_MINOR >= (MINOR) && LIBCURL_VERSION_PATCH >= (PATCH))

using namespace std;

namespace zorba {
namespace curl {

///////////////////////////////////////////////////////////////////////////////

exception::exception( char const *function, char const *uri, char const *msg ) :
  std::exception(),
  curl_code_( CURLE_OK ), curlm_code_( CURLM_OK ), msg_( msg )
{
}

exception::exception( char const *function, char const *uri, CURLcode code ) :
  std::exception(),
  curl_code_( code ), curlm_code_( CURLM_OK ),
  msg_( curl_easy_strerror( code ) )
{
  ostringstream oss;
  oss << " (CURLcode " << (int)code << ')';
  msg_ += oss.str();
}

exception::exception( char const *function, char const *uri, CURLMcode code ) :
  std::exception(),
  curl_code_( CURLE_OK ), curlm_code_( code ),
  msg_( curl_multi_strerror( code ) )
{
  ostringstream oss;
  oss << " (CURLMcode " << (int)code << ')';
  msg_ += oss.str();
}

exception::~exception() throw() {
  // out-of-line since it's virtual
}

const char* exception::what() const throw() {
  return msg_.c_str();
}

///////////////////////////////////////////////////////////////////////////////

listener::~listener() {
  // out-of-line since it's virtual
}

///////////////////////////////////////////////////////////////////////////////

streambuf::streambuf() {
  init();
}

streambuf::streambuf( char const *uri ) {
  init();
  open( uri );
}

streambuf::streambuf( CURL *curl ) {
  init();
  curl_ = curl;
  curl_init();
  curlm_init();
}

streambuf::~streambuf() {
  close();
#ifdef WIN32
  closesocket( dummy_socket_ );
#endif /* WIN32 */
  if ( listener_owner_ )
    delete listener_;
}

void streambuf::close() {
  if ( curl_ ) {
    if ( curlm_ ) {
      curl_multi_remove_handle( curlm_, curl_ );
      curl_multi_cleanup( curlm_ );
      curlm_ = 0;
    }
    curl_destroy();
  }
}

void streambuf::curl_create() {
  //
  // Having cURL initialization wrapped by a class and using a singleton static
  // instance guarantees that cURL is initialized exactly once before use and
  // and also is cleaned-up at program termination (when destructors for static
  // objects are called).
  //
  struct curl_initializer {
    curl_initializer() {
      ZORBA_CURL_ASSERT( curl_global_init( CURL_GLOBAL_ALL ) );
    }
    ~curl_initializer() {
      curl_global_cleanup();
    }
  };
  static curl_initializer initializer;

  curl_ = curl_easy_init();
  if ( !curl_ )
    throw exception( "curl_easy_init()", "", "" );
  try {
    curl_init();
  }
  catch ( ... ) {
    curl_destroy();
    throw;
  }
}

void streambuf::curl_destroy() {
  if ( curl_ ) {
    curl_easy_reset( curl_ );
    curl_easy_cleanup( curl_ );
    curl_ = 0;
  }
}

void streambuf::curl_verbose( bool verbose ) {
  verbose_ = verbose;
  if ( curl_ )
    ZORBA_CURL_ASSERT( curl_easy_setopt( curl_, CURLOPT_VERBOSE, verbose_ ? 1 : 0 ) );
}

void streambuf::curl_init() {
  curl_easy_reset( curl_ );
#if ZORBA_LIBCURL_AT_LEAST(7,19,4)
  ZORBA_CURL_ASSERT( curl_easy_setopt( curl_, CURLOPT_FOLLOWLOCATION, 1 ) );
#endif
#if ZORBA_LIBCURL_AT_LEAST(7,15,1)
  ZORBA_CURL_ASSERT( curl_easy_setopt( curl_, CURLOPT_MAXREDIRS, 50L ) );
#endif
#if ZORBA_LIBCURL_AT_LEAST(7,25,0)
  ZORBA_CURL_ASSERT( curl_easy_setopt( curl_, CURLOPT_TCP_KEEPALIVE, 1L ) );
#endif
  ZORBA_CURL_ASSERT( curl_easy_setopt( curl_, CURLOPT_WRITEDATA, this ) );
  ZORBA_CURL_ASSERT( curl_easy_setopt( curl_, CURLOPT_WRITEFUNCTION, curl_write_callback ) );

  if ( verbose_ )
    ZORBA_CURL_ASSERT( curl_easy_setopt( curl_, CURLOPT_VERBOSE, 1 ) );
}

void streambuf::curl_io( size_t *len_ptr ) {
  *len_ptr = 0;
  while ( curl_running_ && !*len_ptr ) {
    fd_set fd_read, fd_write, fd_except;
    FD_ZERO( &fd_read );
    FD_ZERO( &fd_write );
    FD_ZERO( &fd_except );
    int max_fd = -1;
#ifdef WIN32
    //
    // Windows does not like a call to select where all arguments are 0, so we
    // just add a dummy socket to make the call to select happy.
    //
    FD_SET( dummy_socket_, &fd_read );
#endif /* WIN32 */
    ZORBA_CURLM_ASSERT(
      curl_multi_fdset( curlm_, &fd_read, &fd_write, &fd_except, &max_fd )
    );

    //
    // Note that the fopen.c sample code is unnecessary at best or wrong at
    // worst; see: http://curl.haxx.se/mail/lib-2011-05/0011.html
    //
    timeval timeout;
    long curl_timeout_ms;
    ZORBA_CURLM_ASSERT( curl_multi_timeout( curlm_, &curl_timeout_ms ) );
    if ( curl_timeout_ms > 0 ) {
      timeout.tv_sec  = curl_timeout_ms / 1000;
      timeout.tv_usec = curl_timeout_ms % 1000 * 1000;
    } else {
      //
      // From curl_multi_timeout(3):
      //
      //    Note: if libcurl returns a -1 timeout here, it just means that
      //    libcurl currently has no stored timeout value. You must not wait
      //    too long (more than a few seconds perhaps) before you call
      //    curl_multi_perform() again.
      //
      // So we just pick some not-too-long default.
      //
      timeout.tv_sec  = 1;
      timeout.tv_usec = 0;
    }

    switch ( select( max_fd + 1, &fd_read, &fd_write, &fd_except, &timeout ) ) {
      case -1:                          // select error
#ifdef WIN32
        char err_buf[8];
        sprintf( err_buf, "%d", WSAGetLastError() );
        throw exception( "select()", "", err_buf );
#else
        throw exception( "select()", "", strerror( errno ) );
#endif /* WIN32 */
      case 0:                           // timeout
        // no break;
      default:
        CURLMcode code;
        do {
          code = curl_multi_perform( curlm_, &curl_running_ );
        } while ( code == CURLM_CALL_MULTI_PERFORM );
        ZORBA_CURLM_ASSERT( code );
    } // switch
  } // while
}

CURLcode streambuf::curl_multi_info_read( bool throw_on_error ) {
  underflow();
  CURLMsg *msg;
  int msgs_in_q;
  CURLcode code = CURLE_OK;
  while ( (msg = ::curl_multi_info_read( curlm_, &msgs_in_q )) )
    if ( msg->msg == CURLMSG_DONE )
      code = msg->data.result;
  if ( code && throw_on_error )
    throw exception( "curl_multi_info_read()", "", code );
  return code;
}

size_t streambuf::curl_write_callback( void *ptr, size_t size, size_t nmemb,
                                       void *data ) {
  size *= nmemb;
  streambuf *const that = static_cast<streambuf*>( data );

  if ( that->listener_ )
    that->listener_->curl_read( ptr, size );

  size_t const gbuf_free = that->gbuf_.capacity_ - that->gbuf_.len_;
  if ( size > gbuf_free ) {
    size_t new_capacity = that->gbuf_.capacity_ + size - gbuf_free;
    if ( void *const new_buf = realloc( that->gbuf_.ptr_, new_capacity ) ) {
      that->gbuf_.ptr_ = static_cast<char*>( new_buf );
      that->gbuf_.capacity_ = new_capacity;
    } else
      throw exception( "realloc()", "" );
  }
  ::memcpy( that->gbuf_.ptr_ + that->gbuf_.len_, ptr, size );
  that->gbuf_.len_ += size;
  return size;
}

void streambuf::init() {
  curl_ = 0;
  curlm_ = 0;
  curl_running_ = 0;
#ifdef WIN32
  dummy_socket_ = socket( AF_INET, SOCK_DGRAM, 0 );
  if ( dummy_socket_ == CURL_SOCKET_BAD || dummy_socket_ == INVALID_SOCKET )
    throw exception( "socket()", "" );
#endif /* WIN32 */
  listener_ = 0;
  listener_owner_ = false;
  verbose_ = false;
}

void streambuf::curlm_init() {
  //
  // Lie about cURL running initially so the while-loop in curl_io() will run
  // at least once.
  //
  curl_running_ = 1;

  //
  // Set the "get" pointer to the end (gptr() == egptr()) so a call to
  // underflow() and initial data read will be triggered.
  //
  gbuf_.len_ = gbuf_.capacity_;
  setg( gbuf_.ptr_, gbuf_.ptr_ + gbuf_.len_, gbuf_.ptr_ + gbuf_.len_ );

  //
  // Clean-up has to be done here with try/catch (as opposed to relying on the
  // destructor) because open() can be called from the constructor.  If an
  // exception is thrown, the constructor will not have completed, hence the
  // object will not have been fully constructed; therefore the destructor will
  // not be called.
  //
  try {
    if ( !(curlm_ = curl_multi_init()) )
      throw exception( "curl_multi_init()", "" );
    try {
      ZORBA_CURLM_ASSERT( curl_multi_add_handle( curlm_, curl_ ) );
    }
    catch ( ... ) {
      curl_multi_cleanup( curlm_ );
      curlm_ = 0;
      throw;
    }
  }
  catch ( ... ) {
    curl_destroy();
    throw;
  }
}

void streambuf::open( char const *uri ) {
  if ( !curl_ ) {
    curl_create();
    curlm_init();
  }
  ZORBA_CURL_ASSERT( curl_easy_setopt( curl_, CURLOPT_URL, uri ) );
}

void streambuf::set_listener( listener *l, bool take_ownership ) {
  if ( listener_owner_ )
    delete listener_;
  listener_ = l;
  listener_owner_ = take_ownership;
}

streamsize streambuf::showmanyc() {
  return egptr() - gptr();
}

streambuf::int_type streambuf::underflow() {
  while ( true ) {
    if ( gptr() < egptr() )
      return traits_type::to_int_type( *gptr() );
    curl_io( &gbuf_.len_ );
    if ( !gbuf_.len_ )
      return traits_type::eof();
    setg( gbuf_.ptr_, gbuf_.ptr_, gbuf_.ptr_ + gbuf_.len_ );
  }
}

streamsize streambuf::xsgetn( char_type *to, streamsize size ) {
  streamsize return_size = 0;

  if ( streamsize const gsize = egptr() - gptr() ) {
    streamsize const n = min( gsize, size );
    traits_type::copy( to, gptr(), static_cast<size_t>( n ) );
    gbump( static_cast<int>( n ) );
    to += n;
    size -= n, return_size += n;
  }

  while ( size > 0 ) {
    streamsize const get = min( (streamsize)gbuf_.capacity_, size );
    curl_io( &gbuf_.len_ );
    if ( !gbuf_.len_ )
      break;
    setg( gbuf_.ptr_, gbuf_.ptr_, gbuf_.ptr_ + gbuf_.len_ );
    streamsize const n = min( (streamsize)gbuf_.len_, size );
    traits_type::copy( to, gptr(), n );
    gbump( static_cast<int>( n ) );
    to += n;
    size -= n, return_size += n;
  }
  return return_size;
}

///////////////////////////////////////////////////////////////////////////////

} // namespace curl
} // namespace zorba
/* vim:set et sw=2 ts=2: */
<|endoftext|>


<commit_before>/*************************************************************************/
/*  register_types.cpp                                                   */
/*************************************************************************/
/*                       This file is part of:                           */
/*                           GODOT ENGINE                                */
/*                      https://godotengine.org                          */
/*************************************************************************/
/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur.                 */
/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md).   */
/*                                                                       */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the       */
/* "Software"), to deal in the Software without restriction, including   */
/* without limitation the rights to use, copy, modify, merge, publish,   */
/* distribute, sublicense, and/or sell copies of the Software, and to    */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions:                                             */
/*                                                                       */
/* The above copyright notice and this permission notice shall be        */
/* included in all copies or substantial portions of the Software.       */
/*                                                                       */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
/*************************************************************************/

#include "register_types.h"

#include "core/error_macros.h"

#include "thirdparty/xatlas/xatlas.h"

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

extern bool (*array_mesh_lightmap_unwrap_callback)(float p_texel_size, const float *p_vertices, const float *p_normals, int p_vertex_count, const int *p_indices, const int *p_face_materials, int p_index_count, float **r_uv, int **r_vertex, int *r_vertex_count, int **r_index, int *r_index_count, int *r_size_hint_x, int *r_size_hint_y);

bool xatlas_mesh_lightmap_unwrap_callback(float p_texel_size, const float *p_vertices, const float *p_normals, int p_vertex_count, const int *p_indices, const int *p_face_materials, int p_index_count, float **r_uv, int **r_vertex, int *r_vertex_count, int **r_index, int *r_index_count, int *r_size_hint_x, int *r_size_hint_y) {

	// set up input mesh
	xatlas::MeshDecl input_mesh;
	input_mesh.indexData = p_indices;
	input_mesh.indexCount = p_index_count;
	input_mesh.indexFormat = xatlas::IndexFormat::UInt32;

	input_mesh.vertexCount = p_vertex_count;
	input_mesh.vertexPositionData = p_vertices;
	input_mesh.vertexPositionStride = sizeof(float) * 3;
	input_mesh.vertexNormalData = p_normals;
	input_mesh.vertexNormalStride = sizeof(uint32_t) * 3;
	input_mesh.vertexUvData = NULL;
	input_mesh.vertexUvStride = 0;

	xatlas::ChartOptions chart_options;
	chart_options.fixWinding = true;

	xatlas::PackOptions pack_options;
	pack_options.padding = 1;
	pack_options.maxChartSize = 4094; // Lightmap atlassing needs 2 for padding between meshes, so 4096-2
	pack_options.blockAlign = true;
	pack_options.texelsPerUnit = 1.0 / p_texel_size;

	xatlas::Atlas *atlas = xatlas::Create();

	xatlas::AddMeshError err = xatlas::AddMesh(atlas, input_mesh, 1);
	ERR_FAIL_COND_V_MSG(err != xatlas::AddMeshError::Success, false, xatlas::StringForEnum(err));

	xatlas::Generate(atlas, chart_options, pack_options);

	*r_size_hint_x = atlas->width;
	*r_size_hint_y = atlas->height;

	float w = *r_size_hint_x;
	float h = *r_size_hint_y;

	if (w == 0 || h == 0) {
		return false; //could not bake because there is no area
	}

	const xatlas::Mesh &output = atlas->meshes[0];

	*r_vertex = (int *)malloc(sizeof(int) * output.vertexCount);
	*r_uv = (float *)malloc(sizeof(float) * output.vertexCount * 2);
	*r_index = (int *)malloc(sizeof(int) * output.indexCount);

	float max_x = 0;
	float max_y = 0;
	for (uint32_t i = 0; i < output.vertexCount; i++) {
		(*r_vertex)[i] = output.vertexArray[i].xref;
		(*r_uv)[i * 2 + 0] = output.vertexArray[i].uv[0] / w;
		(*r_uv)[i * 2 + 1] = output.vertexArray[i].uv[1] / h;
		max_x = MAX(max_x, output.vertexArray[i].uv[0]);
		max_y = MAX(max_y, output.vertexArray[i].uv[1]);
	}

	*r_vertex_count = output.vertexCount;

	for (uint32_t i = 0; i < output.indexCount; i++) {
		(*r_index)[i] = output.indexArray[i];
	}

	*r_index_count = output.indexCount;

	xatlas::Destroy(atlas);

	return true;
}

void register_xatlas_unwrap_types() {

	array_mesh_lightmap_unwrap_callback = xatlas_mesh_lightmap_unwrap_callback;
}

void unregister_xatlas_unwrap_types() {
}
<commit_msg>Fix memory leak in Xatlas module<commit_after>/*************************************************************************/
/*  register_types.cpp                                                   */
/*************************************************************************/
/*                       This file is part of:                           */
/*                           GODOT ENGINE                                */
/*                      https://godotengine.org                          */
/*************************************************************************/
/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur.                 */
/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md).   */
/*                                                                       */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the       */
/* "Software"), to deal in the Software without restriction, including   */
/* without limitation the rights to use, copy, modify, merge, publish,   */
/* distribute, sublicense, and/or sell copies of the Software, and to    */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions:                                             */
/*                                                                       */
/* The above copyright notice and this permission notice shall be        */
/* included in all copies or substantial portions of the Software.       */
/*                                                                       */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
/*************************************************************************/

#include "register_types.h"

#include "core/error_macros.h"

#include "thirdparty/xatlas/xatlas.h"

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

extern bool (*array_mesh_lightmap_unwrap_callback)(float p_texel_size, const float *p_vertices, const float *p_normals, int p_vertex_count, const int *p_indices, const int *p_face_materials, int p_index_count, float **r_uv, int **r_vertex, int *r_vertex_count, int **r_index, int *r_index_count, int *r_size_hint_x, int *r_size_hint_y);

bool xatlas_mesh_lightmap_unwrap_callback(float p_texel_size, const float *p_vertices, const float *p_normals, int p_vertex_count, const int *p_indices, const int *p_face_materials, int p_index_count, float **r_uv, int **r_vertex, int *r_vertex_count, int **r_index, int *r_index_count, int *r_size_hint_x, int *r_size_hint_y) {

	// set up input mesh
	xatlas::MeshDecl input_mesh;
	input_mesh.indexData = p_indices;
	input_mesh.indexCount = p_index_count;
	input_mesh.indexFormat = xatlas::IndexFormat::UInt32;

	input_mesh.vertexCount = p_vertex_count;
	input_mesh.vertexPositionData = p_vertices;
	input_mesh.vertexPositionStride = sizeof(float) * 3;
	input_mesh.vertexNormalData = p_normals;
	input_mesh.vertexNormalStride = sizeof(uint32_t) * 3;
	input_mesh.vertexUvData = NULL;
	input_mesh.vertexUvStride = 0;

	xatlas::ChartOptions chart_options;
	chart_options.fixWinding = true;

	xatlas::PackOptions pack_options;
	pack_options.padding = 1;
	pack_options.maxChartSize = 4094; // Lightmap atlassing needs 2 for padding between meshes, so 4096-2
	pack_options.blockAlign = true;
	pack_options.texelsPerUnit = 1.0 / p_texel_size;

	xatlas::Atlas *atlas = xatlas::Create();

	xatlas::AddMeshError err = xatlas::AddMesh(atlas, input_mesh, 1);
	ERR_FAIL_COND_V_MSG(err != xatlas::AddMeshError::Success, false, xatlas::StringForEnum(err));

	xatlas::Generate(atlas, chart_options, pack_options);

	*r_size_hint_x = atlas->width;
	*r_size_hint_y = atlas->height;

	float w = *r_size_hint_x;
	float h = *r_size_hint_y;

	if (w == 0 || h == 0) {
		xatlas::Destroy(atlas);
		return false; //could not bake because there is no area
	}

	const xatlas::Mesh &output = atlas->meshes[0];

	*r_vertex = (int *)malloc(sizeof(int) * output.vertexCount);
	*r_uv = (float *)malloc(sizeof(float) * output.vertexCount * 2);
	*r_index = (int *)malloc(sizeof(int) * output.indexCount);

	float max_x = 0;
	float max_y = 0;
	for (uint32_t i = 0; i < output.vertexCount; i++) {
		(*r_vertex)[i] = output.vertexArray[i].xref;
		(*r_uv)[i * 2 + 0] = output.vertexArray[i].uv[0] / w;
		(*r_uv)[i * 2 + 1] = output.vertexArray[i].uv[1] / h;
		max_x = MAX(max_x, output.vertexArray[i].uv[0]);
		max_y = MAX(max_y, output.vertexArray[i].uv[1]);
	}

	*r_vertex_count = output.vertexCount;

	for (uint32_t i = 0; i < output.indexCount; i++) {
		(*r_index)[i] = output.indexArray[i];
	}

	*r_index_count = output.indexCount;

	xatlas::Destroy(atlas);

	return true;
}

void register_xatlas_unwrap_types() {

	array_mesh_lightmap_unwrap_callback = xatlas_mesh_lightmap_unwrap_callback;
}

void unregister_xatlas_unwrap_types() {
}
<|endoftext|>


<commit_before><commit_msg>Adds ability to split lines (Enter key works as expected when not at the end of a line)<commit_after><|endoftext|>


<commit_before>#pragma once

#include <array>
#include <memory>
#include <cstring>
#include <type_traits>
#include <typeinfo>
#include <cassert>
#include <sstream>
#include <string>

namespace detail { namespace static_any {

// Pointer to administrative function, function that will by type-specific, and will be able to perform all the required operations
enum class operation_t { query_type, copy, move, destroy };
using function_ptr_t = const std::type_info&(*)(operation_t operation, void* this_ptr, void* other_ptr);

template<typename _T>
static const std::type_info& operation(operation_t operation, void* this_void_ptr, void* other_void_ptr)
{
    _T* this_ptr = reinterpret_cast<_T*>(this_void_ptr);
    _T* other_ptr = reinterpret_cast<_T*>(other_void_ptr);

    assert(this_ptr);

    switch(operation)
    {
        case operation_t::query_type:
            break;

        case operation_t::copy:
            assert(other_ptr);
            new(this_ptr)_T(*other_ptr);
            break;

        case operation_t::move:
            assert(other_ptr);
            new(this_ptr)_T(std::move(*other_ptr));
            break;

        case operation_t::destroy:
            this_ptr->~_T();
            break;
    }

    return typeid(_T);
}

template<typename _T>
static function_ptr_t get_function_for_type()
{
    return &static_any::operation<std::remove_cv_t<std::remove_reference_t<_T>>>;
}

}}

template <std::size_t _N>
struct static_any
{
    typedef std::size_t size_type;

    static_any() = default;

    ~static_any()
    {
        destroy();
    }

    template<typename _T>
    static_any(_T&& v)
    {
        copy_or_move(std::forward<_T>(v));
    }

    static_any(const static_any& another)
    {
        copy_from_another(another);
    }

    static_any(static_any& another)
    {
        copy_from_another(another);
    }

    static_any(static_any&& another)
    {
        copy_from_another(another);
    }

    template<std::size_t _M>
    static_any(const static_any<_M>& another)
    {
        copy_from_another(another);
    }

    template<std::size_t _M>
    static_any(static_any<_M>& another)
    {
        copy_from_another(another);
    }

    template<std::size_t _M>
    static_any(static_any<_M>&& another)
    {
        copy_from_another(another);
    }

    static_any& operator=(const static_any& another)
    {
        destroy();
        copy_from_another(another);
        return *this;
    }

    static_any& operator=(static_any& another)
    {
        destroy();
        copy_from_another(another);
        return *this;
    }

    static_any& operator=(static_any&& another)
    {
        destroy();
        copy_from_another(another);
        return *this;
    }

    template<std::size_t _M>
    static_any& operator=(const static_any<_M>& another)
    {
        destroy();
        copy_from_another(another);
        return *this;
    }

    template<std::size_t _M>
    static_any& operator=(static_any<_M>& another)
    {
        destroy();
        copy_from_another(another);
        return *this;
    }

    template<std::size_t _M>
    static_any& operator=(static_any<_M>&& another)
    {
        destroy();
        copy_from_another(another);
        return *this;
    }

    template <typename _T>
    static_any& operator=(const _T& t)
    {
        destroy();
        copy_or_move(std::forward<_T>(t));
        return *this;
    }

    template <typename _T>
    static_any& operator=(_T&& t)
    {
        destroy();
        copy_or_move(std::forward<_T>(t));
        return *this;
    }

    inline void reset() { destroy(); }

    template<typename _T>
    inline const _T& get() const;

    template<typename _T>
    inline _T& get();

    template <typename _T>
    bool has() const
    {
        return function_ == detail::static_any::get_function_for_type<_T>();
    }

    const std::type_info& type() const
    {
        return function_(operation_t::query_type, const_cast<static_any*>(this), nullptr);
    }

    bool empty() const { return function_ == nullptr; }

    static constexpr size_type size() { return _N; }

    // Initializes with object of type T, created in-place with specified constructor params
    template<typename _T, typename... Args>
    void emplace(Args&&... args)
    {
        destroy();
        new(buff_.data()) _T(std::forward<Args>(args)...);
        function_ = detail::static_any::get_function_for_type<_T>();
    }

private:
    using operation_t = detail::static_any::operation_t;
    using function_ptr_t = detail::static_any::function_ptr_t;

    template <typename _T>
    void copy_or_move(_T&& t)
    {
        static_assert(size() >= sizeof(_T), "_T is too big to be copied to static_any");
        assert(function_ == nullptr);

        function_ = detail::static_any::get_function_for_type<_T>();

        using NonConstT = std::remove_cv_t<std::remove_reference_t<_T>>;
        NonConstT* non_const_t = const_cast<NonConstT*>(&t);

        call_function<_T&&>(buff_.data(), non_const_t);
    }

    template <typename Ref>
    std::enable_if_t<std::is_rvalue_reference<Ref>::value>
    call_function(void* this_void_ptr, void* other_void_ptr)
    {
        function_(operation_t::move, this_void_ptr, other_void_ptr);
    }

    template <typename Ref>
    std::enable_if_t<!std::is_rvalue_reference<Ref>::value>
    call_function(void* this_void_ptr, void* other_void_ptr)
    {
        function_(operation_t::copy, this_void_ptr, other_void_ptr);
    }

    void destroy()
    {
        if (function_)
        {
            function_(operation_t::destroy, buff_.data(), nullptr);
            function_ = nullptr;
        }
    }

    template<typename _T>
    const _T* as() const
    {
        return reinterpret_cast<const _T*>(buff_.data());
    }

    template<typename _T>
    _T* as()
    {
        return reinterpret_cast<_T*>(buff_.data());
    }

    template<std::size_t _M>
    void copy_from_another(const static_any<_M>& another)
    {
        if (another.function_)
        {
            function_= another.function_;
            char* other_data = const_cast<char*>(another.buff_.data());
            function_(operation_t::copy, buff_.data(), other_data);
        }
    }

    std::array<char, _N> buff_;
    function_ptr_t function_ = nullptr;

    template<std::size_t _S>
    friend struct static_any;

    template<typename _ValueT, std::size_t _S>
    friend _ValueT* any_cast(static_any<_S>*);

    template<typename _ValueT, std::size_t _S>
    friend _ValueT& any_cast(static_any<_S>&);
};

struct bad_any_cast : public std::bad_cast
{
    bad_any_cast(const std::type_info& from,
                 const std::type_info& to)
    : from_(from),
      to_(to)
    {
        std::ostringstream oss;
        oss << "failed conversion using any_cast: stored type "
            << from.name()
            << ", trying to cast to "
            << to.name();
        reason_ = oss.str();
    }

    const std::type_info& stored_type() const { return from_; }
    const std::type_info& target_type() const { return to_; }

    virtual const char* what() const throw()
    {
        return reason_.c_str();
    }

private:
    const std::type_info& from_;
    const std::type_info& to_;
    std::string reason_;
};

template <typename _ValueT,
          std::size_t _S>
inline _ValueT* any_cast(static_any<_S>* a)
{
    if (!a->template has<_ValueT>())
        return nullptr;

    return a->template as<_ValueT>();
}

template <typename _ValueT,
          std::size_t _S>
inline const _ValueT* any_cast(const static_any<_S>* a)
{
    return any_cast<const _ValueT>(const_cast<static_any<_S>*>(a));
}

template <typename _ValueT,
          std::size_t _S>
inline _ValueT& any_cast(static_any<_S>& a)
{
    if (!a.template has<_ValueT>())
        throw bad_any_cast(a.type(), typeid(_ValueT));

    return *a.template as<_ValueT>();
}

template <typename _ValueT,
          std::size_t _S>
inline const _ValueT& any_cast(const static_any<_S>& a)
{
    return any_cast<const _ValueT>(const_cast<static_any<_S>&>(a));
}

template <std::size_t _S>
template <typename _T>
const _T& static_any<_S>::get() const
{
    return any_cast<_T>(*this);
}

template <std::size_t _S>
template <typename _T>
_T& static_any<_S>::get()
{
    return any_cast<_T>(*this);
}

template <std::size_t _N>
struct static_any_t
{
    typedef std::size_t size_type;

    static constexpr size_type size() { return _N; }

    static_any_t() = default;
    static_any_t(const static_any_t&) = default;

    template <typename _ValueT>
    static_any_t(_ValueT&& t)
    {
        copy(std::forward<_ValueT>(t));
    }

    template <typename _ValueT>
    static_any_t& operator=(_ValueT&& t)
    {
        copy(std::forward<_ValueT>(t));
        return *this;
    }

    template <typename _ValueT>
    _ValueT& get() { return *reinterpret_cast<_ValueT*>(buff_.data()); }

    template <typename _ValueT>
    const _ValueT& get() const { return *reinterpret_cast<const _ValueT*>(buff_.data()); }

private:
    template <typename _ValueT>
    void copy(_ValueT&& t)
    {
        static_assert(std::is_trivially_copyable<_ValueT>::value, "_ValueT is not trivially copyable");
        static_assert(size() >= sizeof(_ValueT), "_ValueT is too big to be copied to static_any");

        std::memcpy(buff_.data(), (char*)&t, sizeof(_ValueT));
    }

    std::array<char, _N> buff_;
};
<commit_msg>static_any::has works across dll boundaries<commit_after>#pragma once

#include <array>
#include <memory>
#include <cstring>
#include <type_traits>
#include <typeinfo>
#include <typeindex>
#include <cassert>
#include <sstream>
#include <string>

namespace detail { namespace static_any {

// Pointer to administrative function, function that will by type-specific, and will be able to perform all the required operations
enum class operation_t { query_type, copy, move, destroy };
using function_ptr_t = const std::type_info&(*)(operation_t operation, void* this_ptr, void* other_ptr);

template<typename _T>
static const std::type_info& operation(operation_t operation, void* this_void_ptr, void* other_void_ptr)
{
    _T* this_ptr = reinterpret_cast<_T*>(this_void_ptr);
    _T* other_ptr = reinterpret_cast<_T*>(other_void_ptr);

    switch(operation)
    {
        case operation_t::query_type:
            break;

        case operation_t::copy:
            assert(this_ptr);
            assert(other_ptr);
            new(this_ptr)_T(*other_ptr);
            break;

        case operation_t::move:
            assert(this_ptr);
            assert(other_ptr);
            new(this_ptr)_T(std::move(*other_ptr));
            break;

        case operation_t::destroy:
            assert(this_ptr);
            this_ptr->~_T();
            break;
    }

    return typeid(_T);
}

template<typename _T>
static function_ptr_t get_function_for_type()
{
    return &static_any::operation<std::remove_cv_t<std::remove_reference_t<_T>>>;
}

}}

template <std::size_t _N>
struct static_any
{
    typedef std::size_t size_type;

    static_any() = default;

    ~static_any()
    {
        destroy();
    }

    template<typename _T>
    static_any(_T&& v)
    {
        copy_or_move(std::forward<_T>(v));
    }

    static_any(const static_any& another)
    {
        copy_from_another(another);
    }

    static_any(static_any& another)
    {
        copy_from_another(another);
    }

    static_any(static_any&& another)
    {
        copy_from_another(another);
    }

    template<std::size_t _M>
    static_any(const static_any<_M>& another)
    {
        copy_from_another(another);
    }

    template<std::size_t _M>
    static_any(static_any<_M>& another)
    {
        copy_from_another(another);
    }

    template<std::size_t _M>
    static_any(static_any<_M>&& another)
    {
        copy_from_another(another);
    }

    static_any& operator=(const static_any& another)
    {
        destroy();
        copy_from_another(another);
        return *this;
    }

    static_any& operator=(static_any& another)
    {
        destroy();
        copy_from_another(another);
        return *this;
    }

    static_any& operator=(static_any&& another)
    {
        destroy();
        copy_from_another(another);
        return *this;
    }

    template<std::size_t _M>
    static_any& operator=(const static_any<_M>& another)
    {
        destroy();
        copy_from_another(another);
        return *this;
    }

    template<std::size_t _M>
    static_any& operator=(static_any<_M>& another)
    {
        destroy();
        copy_from_another(another);
        return *this;
    }

    template<std::size_t _M>
    static_any& operator=(static_any<_M>&& another)
    {
        destroy();
        copy_from_another(another);
        return *this;
    }

    template <typename _T>
    static_any& operator=(const _T& t)
    {
        destroy();
        copy_or_move(std::forward<_T>(t));
        return *this;
    }

    template <typename _T>
    static_any& operator=(_T&& t)
    {
        destroy();
        copy_or_move(std::forward<_T>(t));
        return *this;
    }

    inline void reset() { destroy(); }

    template<typename _T>
    inline const _T& get() const;

    template<typename _T>
    inline _T& get();

    template <typename _T>
    bool has() const
    {
        if (function_ == detail::static_any::get_function_for_type<_T>())
        {
            return true;
        }
        else if (function_)
        {
            // need to try another, possibly more costly way, as we may compare types across DLL boundaries
            return std::type_index(typeid(_T)) == std::type_index(function_(operation_t::query_type, nullptr, nullptr));
        }
        return false;
    }

    const std::type_info& type() const
    {
        return function_(operation_t::query_type, const_cast<static_any*>(this), nullptr);
    }

    bool empty() const { return function_ == nullptr; }

    static constexpr size_type size() { return _N; }

    // Initializes with object of type T, created in-place with specified constructor params
    template<typename _T, typename... Args>
    void emplace(Args&&... args)
    {
        destroy();
        new(buff_.data()) _T(std::forward<Args>(args)...);
        function_ = detail::static_any::get_function_for_type<_T>();
    }

private:
    using operation_t = detail::static_any::operation_t;
    using function_ptr_t = detail::static_any::function_ptr_t;

    template <typename _T>
    void copy_or_move(_T&& t)
    {
        static_assert(size() >= sizeof(_T), "_T is too big to be copied to static_any");
        assert(function_ == nullptr);

        function_ = detail::static_any::get_function_for_type<_T>();

        using NonConstT = std::remove_cv_t<std::remove_reference_t<_T>>;
        NonConstT* non_const_t = const_cast<NonConstT*>(&t);

        call_function<_T&&>(buff_.data(), non_const_t);
    }

    template <typename Ref>
    std::enable_if_t<std::is_rvalue_reference<Ref>::value>
    call_function(void* this_void_ptr, void* other_void_ptr)
    {
        function_(operation_t::move, this_void_ptr, other_void_ptr);
    }

    template <typename Ref>
    std::enable_if_t<!std::is_rvalue_reference<Ref>::value>
    call_function(void* this_void_ptr, void* other_void_ptr)
    {
        function_(operation_t::copy, this_void_ptr, other_void_ptr);
    }

    void destroy()
    {
        if (function_)
        {
            function_(operation_t::destroy, buff_.data(), nullptr);
            function_ = nullptr;
        }
    }

    template<typename _T>
    const _T* as() const
    {
        return reinterpret_cast<const _T*>(buff_.data());
    }

    template<typename _T>
    _T* as()
    {
        return reinterpret_cast<_T*>(buff_.data());
    }

    template<std::size_t _M>
    void copy_from_another(const static_any<_M>& another)
    {
        if (another.function_)
        {
            function_= another.function_;
            char* other_data = const_cast<char*>(another.buff_.data());
            function_(operation_t::copy, buff_.data(), other_data);
        }
    }

    std::array<char, _N> buff_;
    function_ptr_t function_ = nullptr;

    template<std::size_t _S>
    friend struct static_any;

    template<typename _ValueT, std::size_t _S>
    friend _ValueT* any_cast(static_any<_S>*);

    template<typename _ValueT, std::size_t _S>
    friend _ValueT& any_cast(static_any<_S>&);
};

struct bad_any_cast : public std::bad_cast
{
    bad_any_cast(const std::type_info& from,
                 const std::type_info& to)
    : from_(from),
      to_(to)
    {
        std::ostringstream oss;
        oss << "failed conversion using any_cast: stored type "
            << from.name()
            << ", trying to cast to "
            << to.name();
        reason_ = oss.str();
    }

    const std::type_info& stored_type() const { return from_; }
    const std::type_info& target_type() const { return to_; }

    virtual const char* what() const throw()
    {
        return reason_.c_str();
    }

private:
    const std::type_info& from_;
    const std::type_info& to_;
    std::string reason_;
};

template <typename _ValueT,
          std::size_t _S>
inline _ValueT* any_cast(static_any<_S>* a)
{
    if (!a->template has<_ValueT>())
        return nullptr;

    return a->template as<_ValueT>();
}

template <typename _ValueT,
          std::size_t _S>
inline const _ValueT* any_cast(const static_any<_S>* a)
{
    return any_cast<const _ValueT>(const_cast<static_any<_S>*>(a));
}

template <typename _ValueT,
          std::size_t _S>
inline _ValueT& any_cast(static_any<_S>& a)
{
    if (!a.template has<_ValueT>())
        throw bad_any_cast(a.type(), typeid(_ValueT));

    return *a.template as<_ValueT>();
}

template <typename _ValueT,
          std::size_t _S>
inline const _ValueT& any_cast(const static_any<_S>& a)
{
    return any_cast<const _ValueT>(const_cast<static_any<_S>&>(a));
}

template <std::size_t _S>
template <typename _T>
const _T& static_any<_S>::get() const
{
    return any_cast<_T>(*this);
}

template <std::size_t _S>
template <typename _T>
_T& static_any<_S>::get()
{
    return any_cast<_T>(*this);
}

template <std::size_t _N>
struct static_any_t
{
    typedef std::size_t size_type;

    static constexpr size_type size() { return _N; }

    static_any_t() = default;
    static_any_t(const static_any_t&) = default;

    template <typename _ValueT>
    static_any_t(_ValueT&& t)
    {
        copy(std::forward<_ValueT>(t));
    }

    template <typename _ValueT>
    static_any_t& operator=(_ValueT&& t)
    {
        copy(std::forward<_ValueT>(t));
        return *this;
    }

    template <typename _ValueT>
    _ValueT& get() { return *reinterpret_cast<_ValueT*>(buff_.data()); }

    template <typename _ValueT>
    const _ValueT& get() const { return *reinterpret_cast<const _ValueT*>(buff_.data()); }

private:
    template <typename _ValueT>
    void copy(_ValueT&& t)
    {
        static_assert(std::is_trivially_copyable<_ValueT>::value, "_ValueT is not trivially copyable");
        static_assert(size() >= sizeof(_ValueT), "_ValueT is too big to be copied to static_any");

        std::memcpy(buff_.data(), (char*)&t, sizeof(_ValueT));
    }

    std::array<char, _N> buff_;
};
<|endoftext|>