<commit_before>/*  This file is part of the KDE project
    Copyright (C) 2006-2007 Matthias Kretz <kretz@kde.org>

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2.1 of the License, or (at your option) version 3, or any
    later version accepted by the membership of KDE e.V. (or its
    successor approved by the membership of KDE e.V.), Nokia Corporation
    (or its successors, if any) and the KDE Free Qt Foundation, which shall
    act as a proxy defined in Section 6 of version 3 of the license.

    This library 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
    Lesser General Public License for more details.

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

*/

#include "effectwidget.h"
#include "effectwidget_p.h"

#include <QtCore/QtAlgorithms>
#include <QtCore/QList>

#include "effect.h"
#include "effectparameter.h"
#include "phonondefs_p.h"
#include <QtGui/QBoxLayout>
#include <QtGui/QLabel>
#include <QtGui/QSpinBox>
#include <QtGui/QCheckBox>
#include <QtGui/QComboBox>
#include <QtGui/QSlider>
#include <limits>

#ifdef min
#undef min
#endif
#ifdef max
#undef max
#endif
static const qreal DEFAULT_MIN = std::numeric_limits<qreal>::min();
static const qreal DEFAULT_MAX = std::numeric_limits<qreal>::max();
static const int DEFAULT_MIN_INT = std::numeric_limits<int>::min();
static const int DEFAULT_MAX_INT = std::numeric_limits<int>::max();
static const int SLIDER_RANGE = 8;
static const int TICKINTERVAL = 4;

QT_BEGIN_NAMESPACE

#ifndef QT_NO_PHONON_EFFECTWIDGET

namespace Phonon
{

EffectWidget::EffectWidget(Effect *effect, QWidget *parent)
    : QWidget(parent),
    k_ptr(new EffectWidgetPrivate(effect))
{
    K_D(EffectWidget);
    d->q_ptr = this;
    d->autogenerateUi();
}

EffectWidget::~EffectWidget()
{
    delete k_ptr;
}

/*
EffectWidget::EffectWidget(EffectWidgetPrivate &dd, QWidget *parent)
    : QWidget(parent)
    , k_ptr(&dd)
{
    K_D(EffectWidget);
    d->q_ptr = this;
    d->autogenerateUi();
}
*/

EffectWidgetPrivate::EffectWidgetPrivate(Effect *e)
    : effect(e)
{
    //TODO: look up whether there is a specialized widget for this effect. This
    //could be a DSO or a Designer ui file found via KTrader.
    //
    //if no specialized widget is available:
}

void EffectWidgetPrivate::autogenerateUi()
{
    Q_Q(EffectWidget);
    QVBoxLayout *mainLayout = new QVBoxLayout(q);
    mainLayout->setMargin(0);
    for (int i = 0; i < effect->parameters().count(); ++i) {
        const EffectParameter &para = effect->parameters().at(i);
        QVariant value = effect->parameterValue(para);
        QHBoxLayout *pLayout = new QHBoxLayout;
        mainLayout->addLayout(pLayout);

        QLabel *label = new QLabel(q);
        pLayout->addWidget(label);
        label->setText(para.name());
#ifndef QT_NO_TOOLTIP
        label->setToolTip(para.description());
#endif

        QWidget *control = 0;
        switch (para.userType()) {
        case QVariant::String:
            {
                QComboBox *cb = new QComboBox(q);
                control = cb;
                if (value.type() == QVariant::Int) {
                    //value just defines the item index
                    for (int i = 0; i < para.possibleValues().count(); ++i) {
                        cb->addItem(para.possibleValues().at(i).toString());
                    }
                    cb->setCurrentIndex(value.toInt());
                    QObject::connect(cb, SIGNAL(currentIndexChanged(int)), q, SLOT(_k_setIntParameter(int)));
                } else {
                    for (int i = 0; i < para.possibleValues().count(); ++i) {
                        const QVariant &item = para.possibleValues().at(i);
                        cb->addItem(item.toString());
                        if (item == value) {
                            cb->setCurrentIndex(cb->count() - 1);
                        }
                    }
                    QObject::connect(cb, SIGNAL(currentIndexChanged(QString)), q, SLOT(_k_setStringParameter(QString)));
                }
            }
            break;
        case QVariant::Bool:
            {
                QCheckBox *cb = new QCheckBox(q);
                control = cb;
                cb->setChecked(value.toBool());
                QObject::connect(cb, SIGNAL(toggled(bool)), q, SLOT(_k_setToggleParameter(bool)));
            }
            break;
        case QVariant::Int:
            {
                QSpinBox *sb = new QSpinBox(q);
                control = sb;
                bool minValueOk = false;
                bool maxValueOk = false;
                const int minValue = para.minimumValue().toInt(&minValueOk);
                const int maxValue = para.minimumValue().toInt(&maxValueOk);

                sb->setRange(minValueOk ? minValue : DEFAULT_MIN_INT, maxValueOk ? maxValue : DEFAULT_MAX_INT);
                sb->setValue(value.toInt());
                QObject::connect(sb, SIGNAL(valueChanged(int)), q, SLOT(_k_setIntParameter(int)));
            }
            break;
        case QMetaType::Float:
        case QVariant::Double:
            {
                const qreal minValue = para.minimumValue().canConvert(QVariant::Double) ?
                    para.minimumValue().toReal(&ok) : DEFAULT_MIN;
                const qreal maxValue = para.maximumValue().canConvert(QVariant::Double) ?
                    para.maximumValue().toReal(&ok) : DEFAULT_MAX;

                if (minValue == -1. && maxValue == 1.) {
                    //Special case values between -1 and 1.0 to use a slider for improved usability
                    QSlider *slider = new QSlider(Qt::Horizontal, q);
                    control = slider;
                    slider->setRange(-SLIDER_RANGE, +SLIDER_RANGE);
                    slider->setValue(int(SLIDER_RANGE * value.toReal()));
                    slider->setTickPosition(QSlider::TicksBelow);
                    slider->setTickInterval(TICKINTERVAL);
                    QObject::connect(slider, SIGNAL(valueChanged(int)), q, SLOT(_k_setSliderParameter(int)));
                } else {
                    double step = 0.1;
                    if (qAbs(maxValue - minValue) > 50)
                        step = 1.0;
                    QDoubleSpinBox *sb = new QDoubleSpinBox(q);
                    control = sb;
                    sb->setRange(minValue, maxValue);
                    sb->setValue(value.toDouble());
                    sb->setSingleStep(step);
                    QObject::connect(sb, SIGNAL(valueChanged(double)), q,
                        SLOT(_k_setDoubleParameter(double)));
                }
            }
            break;
        default:
            break;
        }

        if (control) {
#ifndef QT_NO_TOOLTIP
        control->setToolTip(para.description());
#endif
#ifndef QT_NO_SHORTCUT
            label->setBuddy(control);
#endif
            pLayout->addWidget(control);
            parameterForObject.insert(control, para);
        }
    }
}

void EffectWidgetPrivate::_k_setToggleParameter(bool checked)
{
    Q_Q(EffectWidget);
    if (parameterForObject.contains(q->sender())) {
        effect->setParameterValue(parameterForObject[q->sender()], checked);
    }
}

void EffectWidgetPrivate::_k_setIntParameter(int value)
{
    Q_Q(EffectWidget);
    if (parameterForObject.contains(q->sender())) {
        effect->setParameterValue(parameterForObject[q->sender()], value);
    }
}

void EffectWidgetPrivate::_k_setDoubleParameter(double value)
{
    Q_Q(EffectWidget);
    if (parameterForObject.contains(q->sender())) {
        effect->setParameterValue(parameterForObject[q->sender()], value);
    }
}

void EffectWidgetPrivate::_k_setStringParameter(const QString &value)
{
    Q_Q(EffectWidget);
    if (parameterForObject.contains(q->sender())) {
        effect->setParameterValue(parameterForObject[q->sender()], value);
    }
}

void EffectWidgetPrivate::_k_setSliderParameter(int value)
{
    Q_Q(EffectWidget);
    if (parameterForObject.contains(q->sender())) {
        effect->setParameterValue(parameterForObject[q->sender()], double(value) / double(SLIDER_RANGE));
    }
}

} // namespace Phonon

#endif // QT_NO_PHONON_EFFECTWIDGET

QT_END_NAMESPACE

#include "moc_effectwidget.cpp"

// vim: sw=4 ts=4
<commit_msg>Fixed compile.<commit_after>/*  This file is part of the KDE project
    Copyright (C) 2006-2007 Matthias Kretz <kretz@kde.org>

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2.1 of the License, or (at your option) version 3, or any
    later version accepted by the membership of KDE e.V. (or its
    successor approved by the membership of KDE e.V.), Nokia Corporation
    (or its successors, if any) and the KDE Free Qt Foundation, which shall
    act as a proxy defined in Section 6 of version 3 of the license.

    This library 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
    Lesser General Public License for more details.

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

*/

#include "effectwidget.h"
#include "effectwidget_p.h"

#include <QtCore/QtAlgorithms>
#include <QtCore/QList>

#include "effect.h"
#include "effectparameter.h"
#include "phonondefs_p.h"
#include <QtGui/QBoxLayout>
#include <QtGui/QLabel>
#include <QtGui/QSpinBox>
#include <QtGui/QCheckBox>
#include <QtGui/QComboBox>
#include <QtGui/QSlider>
#include <limits>

#ifdef min
#undef min
#endif
#ifdef max
#undef max
#endif
static const qreal DEFAULT_MIN = std::numeric_limits<qreal>::min();
static const qreal DEFAULT_MAX = std::numeric_limits<qreal>::max();
static const int DEFAULT_MIN_INT = std::numeric_limits<int>::min();
static const int DEFAULT_MAX_INT = std::numeric_limits<int>::max();
static const int SLIDER_RANGE = 8;
static const int TICKINTERVAL = 4;

QT_BEGIN_NAMESPACE

#ifndef QT_NO_PHONON_EFFECTWIDGET

namespace Phonon
{

EffectWidget::EffectWidget(Effect *effect, QWidget *parent)
    : QWidget(parent),
    k_ptr(new EffectWidgetPrivate(effect))
{
    K_D(EffectWidget);
    d->q_ptr = this;
    d->autogenerateUi();
}

EffectWidget::~EffectWidget()
{
    delete k_ptr;
}

/*
EffectWidget::EffectWidget(EffectWidgetPrivate &dd, QWidget *parent)
    : QWidget(parent)
    , k_ptr(&dd)
{
    K_D(EffectWidget);
    d->q_ptr = this;
    d->autogenerateUi();
}
*/

EffectWidgetPrivate::EffectWidgetPrivate(Effect *e)
    : effect(e)
{
    //TODO: look up whether there is a specialized widget for this effect. This
    //could be a DSO or a Designer ui file found via KTrader.
    //
    //if no specialized widget is available:
}

void EffectWidgetPrivate::autogenerateUi()
{
    Q_Q(EffectWidget);
    QVBoxLayout *mainLayout = new QVBoxLayout(q);
    mainLayout->setMargin(0);
    for (int i = 0; i < effect->parameters().count(); ++i) {
        const EffectParameter &para = effect->parameters().at(i);
        QVariant value = effect->parameterValue(para);
        QHBoxLayout *pLayout = new QHBoxLayout;
        mainLayout->addLayout(pLayout);

        QLabel *label = new QLabel(q);
        pLayout->addWidget(label);
        label->setText(para.name());
#ifndef QT_NO_TOOLTIP
        label->setToolTip(para.description());
#endif

        QWidget *control = 0;
        switch (para.type()) {
        case QVariant::String:
            {
                QComboBox *cb = new QComboBox(q);
                control = cb;
                if (value.type() == QVariant::Int) {
                    //value just defines the item index
                    for (int i = 0; i < para.possibleValues().count(); ++i) {
                        cb->addItem(para.possibleValues().at(i).toString());
                    }
                    cb->setCurrentIndex(value.toInt());
                    QObject::connect(cb, SIGNAL(currentIndexChanged(int)), q, SLOT(_k_setIntParameter(int)));
                } else {
                    for (int i = 0; i < para.possibleValues().count(); ++i) {
                        const QVariant &item = para.possibleValues().at(i);
                        cb->addItem(item.toString());
                        if (item == value) {
                            cb->setCurrentIndex(cb->count() - 1);
                        }
                    }
                    QObject::connect(cb, SIGNAL(currentIndexChanged(QString)), q, SLOT(_k_setStringParameter(QString)));
                }
            }
            break;
        case QVariant::Bool:
            {
                QCheckBox *cb = new QCheckBox(q);
                control = cb;
                cb->setChecked(value.toBool());
                QObject::connect(cb, SIGNAL(toggled(bool)), q, SLOT(_k_setToggleParameter(bool)));
            }
            break;
        case QVariant::Int:
            {
                QSpinBox *sb = new QSpinBox(q);
                control = sb;
                bool minValueOk = false;
                bool maxValueOk = false;
                const int minValue = para.minimumValue().toInt(&minValueOk);
                const int maxValue = para.minimumValue().toInt(&maxValueOk);

                sb->setRange(minValueOk ? minValue : DEFAULT_MIN_INT, maxValueOk ? maxValue : DEFAULT_MAX_INT);
                sb->setValue(value.toInt());
                QObject::connect(sb, SIGNAL(valueChanged(int)), q, SLOT(_k_setIntParameter(int)));
            }
            break;
        case QMetaType::Float:
        case QVariant::Double:
            {
                const qreal minValue = para.minimumValue().canConvert(QVariant::Double) ?
                    para.minimumValue().toReal() : DEFAULT_MIN;
                const qreal maxValue = para.maximumValue().canConvert(QVariant::Double) ?
                    para.maximumValue().toReal() : DEFAULT_MAX;

                if (minValue == -1. && maxValue == 1.) {
                    //Special case values between -1 and 1.0 to use a slider for improved usability
                    QSlider *slider = new QSlider(Qt::Horizontal, q);
                    control = slider;
                    slider->setRange(-SLIDER_RANGE, +SLIDER_RANGE);
                    slider->setValue(int(SLIDER_RANGE * value.toReal()));
                    slider->setTickPosition(QSlider::TicksBelow);
                    slider->setTickInterval(TICKINTERVAL);
                    QObject::connect(slider, SIGNAL(valueChanged(int)), q, SLOT(_k_setSliderParameter(int)));
                } else {
                    double step = 0.1;
                    if (qAbs(maxValue - minValue) > 50)
                        step = 1.0;
                    QDoubleSpinBox *sb = new QDoubleSpinBox(q);
                    control = sb;
                    sb->setRange(minValue, maxValue);
                    sb->setValue(value.toDouble());
                    sb->setSingleStep(step);
                    QObject::connect(sb, SIGNAL(valueChanged(double)), q,
                        SLOT(_k_setDoubleParameter(double)));
                }
            }
            break;
        default:
            break;
        }

        if (control) {
#ifndef QT_NO_TOOLTIP
        control->setToolTip(para.description());
#endif
#ifndef QT_NO_SHORTCUT
            label->setBuddy(control);
#endif
            pLayout->addWidget(control);
            parameterForObject.insert(control, para);
        }
    }
}

void EffectWidgetPrivate::_k_setToggleParameter(bool checked)
{
    Q_Q(EffectWidget);
    if (parameterForObject.contains(q->sender())) {
        effect->setParameterValue(parameterForObject[q->sender()], checked);
    }
}

void EffectWidgetPrivate::_k_setIntParameter(int value)
{
    Q_Q(EffectWidget);
    if (parameterForObject.contains(q->sender())) {
        effect->setParameterValue(parameterForObject[q->sender()], value);
    }
}

void EffectWidgetPrivate::_k_setDoubleParameter(double value)
{
    Q_Q(EffectWidget);
    if (parameterForObject.contains(q->sender())) {
        effect->setParameterValue(parameterForObject[q->sender()], value);
    }
}

void EffectWidgetPrivate::_k_setStringParameter(const QString &value)
{
    Q_Q(EffectWidget);
    if (parameterForObject.contains(q->sender())) {
        effect->setParameterValue(parameterForObject[q->sender()], value);
    }
}

void EffectWidgetPrivate::_k_setSliderParameter(int value)
{
    Q_Q(EffectWidget);
    if (parameterForObject.contains(q->sender())) {
        effect->setParameterValue(parameterForObject[q->sender()], double(value) / double(SLIDER_RANGE));
    }
}

} // namespace Phonon

#endif // QT_NO_PHONON_EFFECTWIDGET

QT_END_NAMESPACE

#include "moc_effectwidget.cpp"

// vim: sw=4 ts=4
<|endoftext|>


<commit_before>// Copyright (C) 2017 Elviss Strazdins
// This file is part of the Ouzel engine.

#pragma once

#include "core/CompileConfig.h"

#if OUZEL_SUPPORTS_OPENAL

#include <thread>

#if OUZEL_PLATFORM_MACOS || OUZEL_PLATFORM_IOS || OUZEL_PLATFORM_TVOS
#include <OpenAl/al.h>
#include <OpenAl/alc.h>
#else
#include <AL/al.h>
#include <AL/alc.h>
#endif
#undef OPENAL

#include "audio/AudioDevice.hpp"

namespace ouzel
{
    namespace audio
    {
        class Audio;

        class AudioDeviceAL: public AudioDevice
        {
            friend Audio;
        public:
            bool checkALCError(bool logError = true);
            static bool checkOpenALError(bool logError = true);

            virtual ~AudioDeviceAL();

            virtual bool process() override;

            ALCdevice* getDevice() const { return device; }
            ALCcontext* getContext() const { return context; }

        protected:
            AudioDeviceAL();
            virtual bool init(bool debugAudio) override;

            void run();

            ALCdevice* device = nullptr;
            ALCcontext* context = nullptr;

            ALenum format40 = 0;
            ALenum format51 = 0;
            ALenum format61 = 0;
            ALenum format71 = 0;

            ALuint sourceId = 0;
            ALenum sampleFormat = 0;
            uint32_t nextBuffer = 0;
            ALuint buffers[2];

            std::vector<uint8_t> data;

#if OUZEL_MULTITHREADED
            std::atomic<bool> running;
            std::thread audioThread;
#endif
        };
    } // namespace audio
} // namespace ouzel

#endif
<commit_msg>Add missing atomic include<commit_after>// Copyright (C) 2017 Elviss Strazdins
// This file is part of the Ouzel engine.

#pragma once

#include "core/CompileConfig.h"

#if OUZEL_SUPPORTS_OPENAL

#include <atomic>
#include <thread>

#if OUZEL_PLATFORM_MACOS || OUZEL_PLATFORM_IOS || OUZEL_PLATFORM_TVOS
#include <OpenAl/al.h>
#include <OpenAl/alc.h>
#else
#include <AL/al.h>
#include <AL/alc.h>
#endif
#undef OPENAL

#include "audio/AudioDevice.hpp"

namespace ouzel
{
    namespace audio
    {
        class Audio;

        class AudioDeviceAL: public AudioDevice
        {
            friend Audio;
        public:
            bool checkALCError(bool logError = true);
            static bool checkOpenALError(bool logError = true);

            virtual ~AudioDeviceAL();

            virtual bool process() override;

            ALCdevice* getDevice() const { return device; }
            ALCcontext* getContext() const { return context; }

        protected:
            AudioDeviceAL();
            virtual bool init(bool debugAudio) override;

            void run();

            ALCdevice* device = nullptr;
            ALCcontext* context = nullptr;

            ALenum format40 = 0;
            ALenum format51 = 0;
            ALenum format61 = 0;
            ALenum format71 = 0;

            ALuint sourceId = 0;
            ALenum sampleFormat = 0;
            uint32_t nextBuffer = 0;
            ALuint buffers[2];

            std::vector<uint8_t> data;

#if OUZEL_MULTITHREADED
            std::atomic<bool> running;
            std::thread audioThread;
#endif
        };
    } // namespace audio
} // namespace ouzel

#endif
<|endoftext|>


<commit_before>/*
 * libjingle
 * Copyright 2011, Google Inc.
 *
 * 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. The name of the author may not be used to endorse or promote products
 *     derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 "talk/p2p/base/basicpacketsocketfactory.h"

#include "webrtc/base/asyncudpsocket.h"
#include "webrtc/base/asynctcpsocket.h"
#include "webrtc/base/logging.h"
#include "webrtc/base/nethelpers.h"
#include "webrtc/base/physicalsocketserver.h"
#include "webrtc/base/scoped_ptr.h"
#include "webrtc/base/socketadapters.h"
#include "webrtc/base/thread.h"
#include "talk/p2p/base/asyncstuntcpsocket.h"
#include "talk/p2p/base/stun.h"

namespace rtc {

BasicPacketSocketFactory::BasicPacketSocketFactory()
    : thread_(Thread::Current()),
      socket_factory_(NULL) {
}

BasicPacketSocketFactory::BasicPacketSocketFactory(Thread* thread)
    : thread_(thread),
      socket_factory_(NULL) {
}

BasicPacketSocketFactory::BasicPacketSocketFactory(
    SocketFactory* socket_factory)
    : thread_(NULL),
      socket_factory_(socket_factory) {
}

BasicPacketSocketFactory::~BasicPacketSocketFactory() {
}

AsyncPacketSocket* BasicPacketSocketFactory::CreateUdpSocket(
    const SocketAddress& address, int min_port, int max_port) {
  // UDP sockets are simple.
  rtc::AsyncSocket* socket =
      socket_factory()->CreateAsyncSocket(
          address.family(), SOCK_DGRAM);
  if (!socket) {
    return NULL;
  }
  if (BindSocket(socket, address, min_port, max_port) < 0) {
    LOG(LS_ERROR) << "UDP bind failed with error "
                    << socket->GetError();
    delete socket;
    return NULL;
  }
  return new rtc::AsyncUDPSocket(socket);
}

AsyncPacketSocket* BasicPacketSocketFactory::CreateServerTcpSocket(
    const SocketAddress& local_address, int min_port, int max_port, int opts) {

  // Fail if TLS is required.
  if (opts & PacketSocketFactory::OPT_TLS) {
    LOG(LS_ERROR) << "TLS support currently is not available.";
    return NULL;
  }

  rtc::AsyncSocket* socket =
      socket_factory()->CreateAsyncSocket(local_address.family(),
                                          SOCK_STREAM);
  if (!socket) {
    return NULL;
  }

  if (BindSocket(socket, local_address, min_port, max_port) < 0) {
    LOG(LS_ERROR) << "TCP bind failed with error "
                  << socket->GetError();
    delete socket;
    return NULL;
  }

  // If using SSLTCP, wrap the TCP socket in a pseudo-SSL socket.
  if (opts & PacketSocketFactory::OPT_SSLTCP) {
    ASSERT(!(opts & PacketSocketFactory::OPT_TLS));
    socket = new rtc::AsyncSSLSocket(socket);
  }

  // Set TCP_NODELAY (via OPT_NODELAY) for improved performance.
  // See http://go/gtalktcpnodelayexperiment
  socket->SetOption(rtc::Socket::OPT_NODELAY, 1);

  if (opts & PacketSocketFactory::OPT_STUN)
    return new cricket::AsyncStunTCPSocket(socket, true);

  return new rtc::AsyncTCPSocket(socket, true);
}

AsyncPacketSocket* BasicPacketSocketFactory::CreateClientTcpSocket(
    const SocketAddress& local_address, const SocketAddress& remote_address,
    const ProxyInfo& proxy_info, const std::string& user_agent, int opts) {

  // Fail if TLS is required.
  if (opts & PacketSocketFactory::OPT_TLS) {
    LOG(LS_ERROR) << "TLS support currently is not available.";
    return NULL;
  }

  rtc::AsyncSocket* socket =
      socket_factory()->CreateAsyncSocket(local_address.family(), SOCK_STREAM);
  if (!socket) {
    return NULL;
  }

  if (BindSocket(socket, local_address, 0, 0) < 0) {
    LOG(LS_ERROR) << "TCP bind failed with error "
                  << socket->GetError();
    delete socket;
    return NULL;
  }

  // If using a proxy, wrap the socket in a proxy socket.
  if (proxy_info.type == rtc::PROXY_SOCKS5) {
    socket = new rtc::AsyncSocksProxySocket(
        socket, proxy_info.address, proxy_info.username, proxy_info.password);
  } else if (proxy_info.type == rtc::PROXY_HTTPS) {
    socket = new rtc::AsyncHttpsProxySocket(
        socket, user_agent, proxy_info.address,
        proxy_info.username, proxy_info.password);
  }

  // If using SSLTCP, wrap the TCP socket in a pseudo-SSL socket.
  if (opts & PacketSocketFactory::OPT_SSLTCP) {
    ASSERT(!(opts & PacketSocketFactory::OPT_TLS));
    socket = new rtc::AsyncSSLSocket(socket);
  }

  if (socket->Connect(remote_address) < 0) {
    LOG(LS_ERROR) << "TCP connect failed with error "
                  << socket->GetError();
    delete socket;
    return NULL;
  }

  // Finally, wrap that socket in a TCP or STUN TCP packet socket.
  AsyncPacketSocket* tcp_socket;
  if (opts & PacketSocketFactory::OPT_STUN) {
    tcp_socket = new cricket::AsyncStunTCPSocket(socket, false);
  } else {
    tcp_socket = new rtc::AsyncTCPSocket(socket, false);
  }

  // Set TCP_NODELAY (via OPT_NODELAY) for improved performance.
  // See http://go/gtalktcpnodelayexperiment
  tcp_socket->SetOption(rtc::Socket::OPT_NODELAY, 1);

  return tcp_socket;
}

AsyncResolverInterface* BasicPacketSocketFactory::CreateAsyncResolver() {
  return new rtc::AsyncResolver();
}

int BasicPacketSocketFactory::BindSocket(
    AsyncSocket* socket, const SocketAddress& local_address,
    int min_port, int max_port) {
  int ret = -1;
  if (min_port == 0 && max_port == 0) {
    // If there's no port range, let the OS pick a port for us.
    ret = socket->Bind(local_address);
  } else {
    // Otherwise, try to find a port in the provided range.
    for (int port = min_port; ret < 0 && port <= max_port; ++port) {
      ret = socket->Bind(rtc::SocketAddress(local_address.ipaddr(),
                                                  port));
    }
  }
  return ret;
}

SocketFactory* BasicPacketSocketFactory::socket_factory() {
  if (thread_) {
    ASSERT(thread_ == Thread::Current());
    return thread_->socketserver();
  } else {
    return socket_factory_;
  }
}

}  // namespace rtc
<commit_msg>Support for TURN/TLS.<commit_after>/*
 * libjingle
 * Copyright 2011, Google Inc.
 *
 * 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. The name of the author may not be used to endorse or promote products
 *     derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 "talk/p2p/base/basicpacketsocketfactory.h"

#include "webrtc/base/asyncudpsocket.h"
#include "webrtc/base/asynctcpsocket.h"
#include "webrtc/base/logging.h"
#include "webrtc/base/nethelpers.h"
#include "webrtc/base/physicalsocketserver.h"
#include "webrtc/base/scoped_ptr.h"
#include "webrtc/base/socketadapters.h"
#include "webrtc/base/ssladapter.h"
#include "webrtc/base/thread.h"
#include "talk/p2p/base/asyncstuntcpsocket.h"
#include "talk/p2p/base/stun.h"

namespace rtc {

BasicPacketSocketFactory::BasicPacketSocketFactory()
    : thread_(Thread::Current()),
      socket_factory_(NULL) {
}

BasicPacketSocketFactory::BasicPacketSocketFactory(Thread* thread)
    : thread_(thread),
      socket_factory_(NULL) {
}

BasicPacketSocketFactory::BasicPacketSocketFactory(
    SocketFactory* socket_factory)
    : thread_(NULL),
      socket_factory_(socket_factory) {
}

BasicPacketSocketFactory::~BasicPacketSocketFactory() {
}

AsyncPacketSocket* BasicPacketSocketFactory::CreateUdpSocket(
    const SocketAddress& address, int min_port, int max_port) {
  // UDP sockets are simple.
  rtc::AsyncSocket* socket =
      socket_factory()->CreateAsyncSocket(
          address.family(), SOCK_DGRAM);
  if (!socket) {
    return NULL;
  }
  if (BindSocket(socket, address, min_port, max_port) < 0) {
    LOG(LS_ERROR) << "UDP bind failed with error "
                    << socket->GetError();
    delete socket;
    return NULL;
  }
  return new rtc::AsyncUDPSocket(socket);
}

AsyncPacketSocket* BasicPacketSocketFactory::CreateServerTcpSocket(
    const SocketAddress& local_address, int min_port, int max_port, int opts) {

  // Fail if TLS is required.
  if (opts & PacketSocketFactory::OPT_TLS) {
    LOG(LS_ERROR) << "TLS support currently is not available.";
    return NULL;
  }

  rtc::AsyncSocket* socket =
      socket_factory()->CreateAsyncSocket(local_address.family(),
                                          SOCK_STREAM);
  if (!socket) {
    return NULL;
  }

  if (BindSocket(socket, local_address, min_port, max_port) < 0) {
    LOG(LS_ERROR) << "TCP bind failed with error "
                  << socket->GetError();
    delete socket;
    return NULL;
  }

  // If using SSLTCP, wrap the TCP socket in a pseudo-SSL socket.
  if (opts & PacketSocketFactory::OPT_SSLTCP) {
    ASSERT(!(opts & PacketSocketFactory::OPT_TLS));
    socket = new rtc::AsyncSSLSocket(socket);
  }

  // Set TCP_NODELAY (via OPT_NODELAY) for improved performance.
  // See http://go/gtalktcpnodelayexperiment
  socket->SetOption(rtc::Socket::OPT_NODELAY, 1);

  if (opts & PacketSocketFactory::OPT_STUN)
    return new cricket::AsyncStunTCPSocket(socket, true);

  return new rtc::AsyncTCPSocket(socket, true);
}

AsyncPacketSocket* BasicPacketSocketFactory::CreateClientTcpSocket(
    const SocketAddress& local_address, const SocketAddress& remote_address,
    const ProxyInfo& proxy_info, const std::string& user_agent, int opts) {

  rtc::AsyncSocket* socket =
      socket_factory()->CreateAsyncSocket(local_address.family(), SOCK_STREAM);
  if (!socket) {
    return NULL;
  }

  if (BindSocket(socket, local_address, 0, 0) < 0) {
    LOG(LS_ERROR) << "TCP bind failed with error "
                  << socket->GetError();
    delete socket;
    return NULL;
  }

  // If using a proxy, wrap the socket in a proxy socket.
  if (proxy_info.type == rtc::PROXY_SOCKS5) {
    socket = new rtc::AsyncSocksProxySocket(
        socket, proxy_info.address, proxy_info.username, proxy_info.password);
  } else if (proxy_info.type == rtc::PROXY_HTTPS) {
    socket = new rtc::AsyncHttpsProxySocket(
        socket, user_agent, proxy_info.address,
        proxy_info.username, proxy_info.password);
  }

  // If using TLS, wrap the socket in an SSL adapter.
  if (opts & PacketSocketFactory::OPT_TLS) {
    ASSERT(!(opts & PacketSocketFactory::OPT_SSLTCP));

    rtc::SSLAdapter* ssl_adapter = rtc::SSLAdapter::Create(socket);
    if (!ssl_adapter) {
      return NULL;
    }

    socket = ssl_adapter;

    if (ssl_adapter->StartSSL(remote_address.hostname().c_str(), false) != 0) {
      delete ssl_adapter;
      return NULL;
    }

  // If using SSLTCP, wrap the TCP socket in a pseudo-SSL socket.
  } else if (opts & PacketSocketFactory::OPT_SSLTCP) {
    ASSERT(!(opts & PacketSocketFactory::OPT_TLS));
    socket = new rtc::AsyncSSLSocket(socket);
  }

  if (socket->Connect(remote_address) < 0) {
    LOG(LS_ERROR) << "TCP connect failed with error "
                  << socket->GetError();
    delete socket;
    return NULL;
  }

  // Finally, wrap that socket in a TCP or STUN TCP packet socket.
  AsyncPacketSocket* tcp_socket;
  if (opts & PacketSocketFactory::OPT_STUN) {
    tcp_socket = new cricket::AsyncStunTCPSocket(socket, false);
  } else {
    tcp_socket = new rtc::AsyncTCPSocket(socket, false);
  }

  // Set TCP_NODELAY (via OPT_NODELAY) for improved performance.
  // See http://go/gtalktcpnodelayexperiment
  tcp_socket->SetOption(rtc::Socket::OPT_NODELAY, 1);

  return tcp_socket;
}

AsyncResolverInterface* BasicPacketSocketFactory::CreateAsyncResolver() {
  return new rtc::AsyncResolver();
}

int BasicPacketSocketFactory::BindSocket(
    AsyncSocket* socket, const SocketAddress& local_address,
    int min_port, int max_port) {
  int ret = -1;
  if (min_port == 0 && max_port == 0) {
    // If there's no port range, let the OS pick a port for us.
    ret = socket->Bind(local_address);
  } else {
    // Otherwise, try to find a port in the provided range.
    for (int port = min_port; ret < 0 && port <= max_port; ++port) {
      ret = socket->Bind(rtc::SocketAddress(local_address.ipaddr(),
                                                  port));
    }
  }
  return ret;
}

SocketFactory* BasicPacketSocketFactory::socket_factory() {
  if (thread_) {
    ASSERT(thread_ == Thread::Current());
    return thread_->socketserver();
  } else {
    return socket_factory_;
  }
}

}  // namespace rtc
<|endoftext|>


<commit_before>/***************************************************
  This is a library for the CAP1188 I2C/SPI 8-chan Capacitive Sensor

  Designed specifically to work with the CAP1188 sensor from Adafruit
  ----> https://www.adafruit.com/products/1602

  These sensors use I2C/SPI to communicate, 2+ pins are required to
  interface
  Adafruit invests time and resources providing this open source code,
  please support Adafruit and open-source hardware by purchasing
  products from Adafruit!

  Written by Limor Fried/Ladyada for Adafruit Industries.
  BSD license, all text above must be included in any redistribution
 ****************************************************/

#include "Adafruit_CAP1188.h"

uint8_t mySPCR, SPCRback;

Adafruit_CAP1188::Adafruit_CAP1188(int8_t resetpin) {
  // I2C
  _resetpin = resetpin;
  _i2c = true;
}

Adafruit_CAP1188::Adafruit_CAP1188(int8_t cspin, int8_t resetpin) {
  // Hardware SPI
  _cs = cspin;
  _resetpin = resetpin;
  _clk = -1;
  _i2c = false;
}

Adafruit_CAP1188::Adafruit_CAP1188(int8_t clkpin, int8_t misopin,
				   int8_t mosipin,int8_t cspin,
				   int8_t resetpin) {
  // Software SPI
  _cs = cspin;
  _resetpin = resetpin;
  _clk = clkpin;
  _miso = misopin;
  _mosi = mosipin;
  _i2c = false;
}

boolean Adafruit_CAP1188::begin(uint8_t i2caddr) {
  if (_i2c) {
    Wire.begin();

    _i2caddr = i2caddr;
  }
  // else if (_clk == -1) {
    //Hardware SPI
    // digitalWrite(_cs, HIGH);
    // SPCRback = SPCR;
    // SPI.begin();
    // SPI.setClockDivider(SPI_CLOCK_DIV8);
    // SPI.setDataMode(SPI_MODE0);
    // mySPCR = SPCR;
    // SPCR = SPCRback;
  // } else {
    //Sofware SPI
    // pinMode(_clk, OUTPUT);
    // pinMode(_mosi, OUTPUT);
    // pinMode(_cs, OUTPUT);
    // digitalWrite(_cs, HIGH);
    // digitalWrite(_clk, HIGH);
  // }

  if (_resetpin != -1) {
    pinMode(_resetpin, OUTPUT);
    digitalWrite(_resetpin, LOW);
    delay(100);
    digitalWrite(_resetpin, HIGH);
    delay(100);
    digitalWrite(_resetpin, LOW);
    delay(100);
  }

  readRegister(CAP1188_PRODID);

  // Useful debugging info

  Serial.print("Product ID: 0x");
  Serial.println(readRegister(CAP1188_PRODID), HEX);
  Serial.print("Manuf. ID: 0x");
  Serial.println(readRegister(CAP1188_MANUID), HEX);
  Serial.print("Revision: 0x");
  Serial.println(readRegister(CAP1188_REV), HEX);

  if ( (readRegister(CAP1188_PRODID) != 0x50) ||
       (readRegister(CAP1188_MANUID) != 0x5D) ||
       (readRegister(CAP1188_REV) != 0x83)) {
    return false;
  }
  // allow multiple touches
  writeRegister(CAP1188_MTBLK, 0);
  // Have LEDs follow touches
  writeRegister(CAP1188_LEDLINK, 0xFF);
  // speed up a bit
  writeRegister(CAP1188_STANDBYCFG, 0x30);
  return true;
}

uint8_t  Adafruit_CAP1188::touched(void) {
  uint8_t t = readRegister(CAP1188_SENINPUTSTATUS);
  if (t) {
    writeRegister(CAP1188_MAIN, readRegister(CAP1188_MAIN) & ~CAP1188_MAIN_INT);
  }
  return t;
}

void Adafruit_CAP1188::LEDpolarity(uint8_t x) {
  writeRegister(CAP1188_LEDPOL, x);
}

/*********************************************************************/

/**************************************************************************/
/*!
    @brief  Abstract away platform differences in Arduino wire library
*/
/**************************************************************************/
static uint8_t i2cread(void) {
  // #if ARDUINO >= 100
  return Wire.read();
  // #else
  // return Wire.receive();
  // #endif
}

/**************************************************************************/
/*!
    @brief  Abstract away platform differences in Arduino wire library
*/
/**************************************************************************/
static void i2cwrite(uint8_t x) {
  // #if ARDUINO >= 100
  Wire.write((uint8_t)x);
  // #else
  // Wire.send(x);
  // #endif
}

/**************************************************************************/
/*!
    @brief  Reads 8-bits from the specified register
*/
/**************************************************************************/
uint8_t Adafruit_CAP1188::spixfer(uint8_t data) {
  if (_clk == -1) {
   //Serial.println("Hardware SPI");
    return SPI.transfer(data);
  } else {
   // Serial.println("Software SPI");
    uint8_t reply = 0;
    for (int i=7; i>=0; i--) {
      reply <<= 1;
      digitalWrite(_clk, LOW);
      digitalWrite(_mosi, data & (1<<i));
      digitalWrite(_clk, HIGH);
      if (digitalRead(_miso))
	reply |= 1;
    }
    return reply;
  }
}

uint8_t Adafruit_CAP1188::readRegister(uint8_t reg) {
  if (_i2c) {
    Wire.beginTransmission(_i2caddr);
    i2cwrite(reg);
    Wire.endTransmission();
    Wire.requestFrom(_i2caddr, 1);
    return (i2cread());
  }
  // else {
    // if (_clk == -1) {
      // SPCRback = SPCR;
      // SPCR = mySPCR;
    // }
    // digitalWrite(_cs, LOW);
    //set address
    // spixfer(0x7D);
    // spixfer(reg);
    // digitalWrite(_cs, HIGH);
    // digitalWrite(_cs, LOW);
    // spixfer(0x7F);
    // uint8_t reply = spixfer(0);
    // digitalWrite(_cs, HIGH);
    // if (_clk == -1) {
      // SPCR = SPCRback;
    // }
    // return reply;
  // }
  else {
	return 0;
  }
}

/**************************************************************************/
/*!
    @brief  Writes 8-bits to the specified destination register
*/
/**************************************************************************/
void Adafruit_CAP1188::writeRegister(uint8_t reg, uint8_t value) {
  if (_i2c) {
    Wire.beginTransmission(_i2caddr);
    i2cwrite((uint8_t)reg);
    i2cwrite((uint8_t)(value));
    Wire.endTransmission();
  }
  // else {
    // if (_clk == -1) {
      // SPCRback = SPCR;
      // SPCR = mySPCR;
    // }
    // digitalWrite(_cs, LOW);
    //set address
    // spixfer(0x7D);
    // spixfer(reg);
    // digitalWrite(_cs, HIGH);
    // digitalWrite(_cs, LOW);
    // spixfer(0x7E);
    // spixfer(value);
    // digitalWrite(_cs, HIGH);
    // if (_clk == -1) {
      // SPCR = SPCRback;
    // }
  // }
}
<commit_msg>Update Adafruit_CAP1188.cpp<commit_after>/***************************************************
  This is a library for the CAP1188 I2C/SPI 8-chan Capacitive Sensor

  Designed specifically to work with the CAP1188 sensor from Adafruit
  ----> https://www.adafruit.com/products/1602

  These sensors use I2C/SPI to communicate, 2+ pins are required to
  interface
  Adafruit invests time and resources providing this open source code,
  please support Adafruit and open-source hardware by purchasing
  products from Adafruit!

  Written by Limor Fried/Ladyada for Adafruit Industries.
  BSD license, all text above must be included in any redistribution
 ****************************************************/

#include "Adafruit_CAP1188.h"

// byte mySPCR, SPCRback;

Adafruit_CAP1188::Adafruit_CAP1188(char resetpin) {
  // I2C
  _resetpin = resetpin;
  _i2c = true;
}

// Adafruit_CAP1188::Adafruit_CAP1188(char cspin, char resetpin) {
  //Hardware SPI
  // _cs = cspin;
  // _resetpin = resetpin;
  // _clk = -1;
  // _i2c = false;
// }

// Adafruit_CAP1188::Adafruit_CAP1188(char clkpin, char misopin,
				   // char mosipin,char cspin,
				   // char resetpin) {
  //Software SPI
  // _cs = cspin;
  // _resetpin = resetpin;
  // _clk = clkpin;
  // _miso = misopin;
  // _mosi = mosipin;
  // _i2c = false;
// }

boolean Adafruit_CAP1188::begin(byte i2caddr) {
  if (_i2c) {
    Wire.begin();

    _i2caddr = i2caddr;
  }
  // else if (_clk == -1) {
    //Hardware SPI
    // digitalWrite(_cs, HIGH);
    // SPCRback = SPCR;
    // SPI.begin();
    // SPI.setClockDivider(SPI_CLOCK_DIV8);
    // SPI.setDataMode(SPI_MODE0);
    // mySPCR = SPCR;
    // SPCR = SPCRback;
  // } else {
    //Sofware SPI
    // pinMode(_clk, OUTPUT);
    // pinMode(_mosi, OUTPUT);
    // pinMode(_cs, OUTPUT);
    // digitalWrite(_cs, HIGH);
    // digitalWrite(_clk, HIGH);
  // }

  if (_resetpin != -1) {
    pinMode(_resetpin, OUTPUT);
    digitalWrite(_resetpin, LOW);
    delay(100);
    digitalWrite(_resetpin, HIGH);
    delay(100);
    digitalWrite(_resetpin, LOW);
    delay(100);
  }

  readRegister(CAP1188_PRODID);

  // Useful debugging info

  Serial.print("Product ID: 0x");
  Serial.println(readRegister(CAP1188_PRODID), HEX);
  Serial.print("Manuf. ID: 0x");
  Serial.println(readRegister(CAP1188_MANUID), HEX);
  Serial.print("Revision: 0x");
  Serial.println(readRegister(CAP1188_REV), HEX);

  if ( (readRegister(CAP1188_PRODID) != 0x50) ||
       (readRegister(CAP1188_MANUID) != 0x5D) ||
       (readRegister(CAP1188_REV) != 0x83)) {
    return false;
  }
  // allow multiple touches
  writeRegister(CAP1188_MTBLK, 0);
  // Have LEDs follow touches
  writeRegister(CAP1188_LEDLINK, 0xFF);
  // speed up a bit
  writeRegister(CAP1188_STANDBYCFG, 0x30);
  return true;
}

byte  Adafruit_CAP1188::touched(void) {
  byte t = readRegister(CAP1188_SENINPUTSTATUS);
  if (t) {
    writeRegister(CAP1188_MAIN, readRegister(CAP1188_MAIN) & ~CAP1188_MAIN_INT);
  }
  return t;
}

void Adafruit_CAP1188::LEDpolarity(byte x) {
  writeRegister(CAP1188_LEDPOL, x);
}

/*********************************************************************/

/**************************************************************************/
/*!
    @brief  Abstract away platform differences in Arduino wire library
*/
/**************************************************************************/
static byte i2cread(void) {
  // #if ARDUINO >= 100
  return Wire.read();
  // #else
  // return Wire.receive();
  // #endif
}

/**************************************************************************/
/*!
    @brief  Abstract away platform differences in Arduino wire library
*/
/**************************************************************************/
static void i2cwrite(byte x) {
  // #if ARDUINO >= 100
  Wire.write((byte)x);
  // #else
  // Wire.send(x);
  // #endif
}

/**************************************************************************/
/*!
    @brief  Reads 8-bits from the specified register
*/
/**************************************************************************/
// byte Adafruit_CAP1188::spixfer(byte data) {
  // if (_clk == -1) {
   //Serial.println("Hardware SPI");
    // return SPI.transfer(data);
  // } else {
   //Serial.println("Software SPI");
    // byte reply = 0;
    // for (int i=7; i>=0; i--) {
      // reply <<= 1;
      // digitalWrite(_clk, LOW);
      // digitalWrite(_mosi, data & (1<<i));
      // digitalWrite(_clk, HIGH);
      // if (digitalRead(_miso))
	// reply |= 1;
    // }
    // return reply;
  // }
// }

byte Adafruit_CAP1188::readRegister(byte reg) {
  if (_i2c) {
    Wire.beginTransmission(_i2caddr);
    i2cwrite(reg);
    Wire.endTransmission();
    Wire.requestFrom(_i2caddr, 1);
    return (i2cread());
  }
  // else {
    // if (_clk == -1) {
      // SPCRback = SPCR;
      // SPCR = mySPCR;
    // }
    // digitalWrite(_cs, LOW);
    //set address
    // spixfer(0x7D);
    // spixfer(reg);
    // digitalWrite(_cs, HIGH);
    // digitalWrite(_cs, LOW);
    // spixfer(0x7F);
    // byte reply = spixfer(0);
    // digitalWrite(_cs, HIGH);
    // if (_clk == -1) {
      // SPCR = SPCRback;
    // }
    // return reply;
  // }
  else {
	  return 0;
  }
}

/**************************************************************************/
/*!
    @brief  Writes 8-bits to the specified destination register
*/
/**************************************************************************/
void Adafruit_CAP1188::writeRegister(byte reg, byte value) {
  if (_i2c) {
    Wire.beginTransmission(_i2caddr);
    i2cwrite((byte)reg);
    i2cwrite((byte)(value));
    Wire.endTransmission();
  }
  // else {
    // if (_clk == -1) {
      // SPCRback = SPCR;
      // SPCR = mySPCR;
    // }
    // digitalWrite(_cs, LOW);
    //set address
    // spixfer(0x7D);
    // spixfer(reg);
    // digitalWrite(_cs, HIGH);
    // digitalWrite(_cs, LOW);
    // spixfer(0x7E);
    // spixfer(value);
    // digitalWrite(_cs, HIGH);
    // if (_clk == -1) {
      // SPCR = SPCRback;
    // }
  // }
}
<|endoftext|>


<commit_before>#include "Math/LineEquation.h"
#include "Structure.h"

Edge::Edge(unsigned int index, Center* center1, Center* center2, Corner* corner1, Corner* corner2) :
	m_index(index), m_d0(center1), m_d1(center2), m_v0(corner1), m_v1(corner2), m_riverVolume(0.0)
{

}

bool Center::RemoveEdge(Edge* e)
{
	for (auto edgeIter = m_edges.begin(); edgeIter != m_edges.end(); ++edgeIter)
	{
		if (*edgeIter == e)
		{
			m_edges.erase(edgeIter);
			return true;
		}
	}

	return false;
}

bool Center::RemoveCorner(Corner* c)
{
	for (auto iter = m_corners.begin(); iter != m_corners.end(); ++iter)
	{
		if (*iter == c)
		{
			m_corners.erase(iter);
			return true;
		}
	}

	return false;
}

Edge* Center::GetEdgeWith(Center* c)
{
	for (auto iter = m_edges.begin(); iter != m_edges.end(); ++iter)
	{
		if ((*iter)->m_d0 == c || (*iter)->m_d1 == c)
		{
			return *iter;
		}
	}

	return nullptr;
}

void Center::MakeBorder()
{
	m_border = true;
	m_water = true;
	m_ocean = true;

	for (auto iter = m_corners.begin(); iter != m_corners.end(); ++iter)
	{
		(*iter)->m_border = true;
		(*iter)->m_water = true;
		(*iter)->m_ocean = true;
	}
}<commit_msg>Implement struct Center's methods<commit_after>#include "Math/LineEquation.h"
#include "Structure.h"

Edge::Edge(unsigned int index, Center* center1, Center* center2, Corner* corner1, Corner* corner2) :
	m_index(index), m_d0(center1), m_d1(center2), m_v0(corner1), m_v1(corner2), m_riverVolume(0.0)
{

}

bool Center::RemoveEdge(Edge* e)
{
	for (auto edgeIter = m_edges.begin(); edgeIter != m_edges.end(); ++edgeIter)
	{
		if (*edgeIter == e)
		{
			m_edges.erase(edgeIter);
			return true;
		}
	}

	return false;
}

bool Center::RemoveCorner(Corner* c)
{
	for (auto iter = m_corners.begin(); iter != m_corners.end(); ++iter)
	{
		if (*iter == c)
		{
			m_corners.erase(iter);
			return true;
		}
	}

	return false;
}

Edge* Center::GetEdgeWith(Center* c)
{
	for (auto iter = m_edges.begin(); iter != m_edges.end(); ++iter)
	{
		if ((*iter)->m_d0 == c || (*iter)->m_d1 == c)
		{
			return *iter;
		}
	}

	return nullptr;
}

void Center::MakeBorder()
{
	m_border = true;
	m_water = true;
	m_ocean = true;

	for (auto iter = m_corners.begin(); iter != m_corners.end(); ++iter)
	{
		(*iter)->m_border = true;
		(*iter)->m_water = true;
		(*iter)->m_ocean = true;
	}
}

bool Center::IsInsideBoundingBox(int width, int height) const
{
	if (m_position.x < 0 || m_position.x >= width || m_position.y < 0 || m_position.y >= height)
	{
		return false;
	}

	return true;
}

bool Center::IsContain(Vector2 pos)
{
	if (m_corners.size() < 3)
	{
		return false;
	}

	Vector2 firstSec(m_corners[0]->m_position, m_corners[1]->m_position);
	Vector2 firstPos(m_corners[0]->m_position, pos);
	bool sign = firstSec.CrossProduct(firstPos) > 0;

	for (auto iter = m_corners.begin() + 1; iter != m_corners.end() - 1; ++iter)
	{
		Vector2 ab((*iter)->m_position, (*(iter + 1))->m_position);
		Vector2 ap((*iter)->m_position, pos);

		if (sign != ab.CrossProduct(ap) > 0)
		{
			return false;
		}
	}

	return true;
}

std::pair<Vector2, Vector2> Center::GetBoundingBox()
{
	double minX = m_corners[0]->m_position.x, maxX = m_corners[0]->m_position.x;
	double minY = m_corners[0]->m_position.y, maxY = m_corners[0]->m_position.y;

	for (auto iter = m_corners.begin() + 1; iter != m_corners.end(); ++iter)
	{
		if ((*iter)->m_position.x < minX)
		{
			minX = (*iter)->m_position.x;
		}
		else if ((*iter)->m_position.x > maxX)
		{
			maxX = (*iter)->m_position.x;
		}

		if ((*iter)->m_position.y < minY)
		{
			minY = (*iter)->m_position.y;
		}
		else if ((*iter)->m_position.y > maxY)
		{
			maxY = (*iter)->m_position.y;
		}
	}

	Vector2 minPos(minX, minY);
	Vector2 maxPos(maxX, maxY);
	Vector2 halfDiagonal(Vector2(minPos, maxPos) / 2);

	return std::make_pair(minPos + halfDiagonal, halfDiagonal);
}

void SortCorners();
bool IsGoesBefore(Vector2 a, Vector2 b);<|endoftext|>


<commit_before>/**
 * This file is part of the "libfnord" project
 *   Copyright (c) 2015 Paul Asmuth
 *
 * FnordMetric is free software: you can redistribute it and/or modify it under
 * the terms of the GNU General Public License v3.0. 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 <unistd.h>
#include <fnord-base/io/file.h>
#include <fnord-base/io/fileutil.h>
#include <fnord-base/io/mmappedfile.h>
#include <fnord-base/logging.h>
#include <fnord-base/io/fileutil.h>
#include <fnord-dproc/LocalScheduler.h>

namespace fnord {
namespace dproc {

LocalScheduler::LocalScheduler(
    const String& tempdir /* = "/tmp" */,
    size_t max_threads /* = 8 */,
    size_t max_requests /* = 32 */) :
    tempdir_(tempdir),
    tpool_(max_threads),
    req_tpool_(max_requests) {}

void LocalScheduler::start() {
  req_tpool_.start();
  tpool_.start();
}

void LocalScheduler::stop() {
  req_tpool_.stop();
  tpool_.stop();
}

RefPtr<TaskResultFuture> LocalScheduler::run(
    RefPtr<Application> app,
    const TaskSpec& task) {
  RefPtr<TaskResultFuture> result(new TaskResultFuture());

  try {
    auto instance = mkRef(
        new LocalTaskRef(
            app,
            task.task_name(),
            Buffer(task.params().data(), task.params().size())));

    req_tpool_.run([this, app, result, instance] () {
      try {
        LocalTaskPipeline pipeline;
        pipeline.tasks.push_back(instance);
        runPipeline(app.get(), &pipeline, result);

        if (instance->failed) {
          RAISE(kRuntimeError, "task failed");
        }

        result->returnResult(instance->task);
      } catch (const StandardException& e) {
        fnord::logError("dproc.scheduler", e, "task failed");
        result->returnError(e);
      }
    });
  } catch (const StandardException& e) {
    fnord::logError("dproc.scheduler", e, "task failed");
    result->returnError(e);
  }

  return result;
}

void LocalScheduler::runPipeline(
    Application* app,
    LocalTaskPipeline* pipeline,
    RefPtr<TaskResultFuture> result) {
  fnord::logInfo(
      "fnord.dproc",
      "Starting local pipeline id=$0 tasks=$1",
      (void*) pipeline,
      pipeline->tasks.size());

  std::unique_lock<std::mutex> lk(pipeline->mutex);
  result->updateStatus([&pipeline] (TaskStatus* status) {
    status->num_subtasks_total = pipeline->tasks.size();
  });

  while (pipeline->tasks.size() > 0) {
    bool waiting = true;
    size_t num_waiting = 0;
    size_t num_running = 0;
    size_t num_completed = 0;

    for (auto& taskref : pipeline->tasks) {

      if (taskref->finished) {
        ++num_completed;
        continue;
      }

      if (taskref->running) {
        ++num_running;
        continue;
      }

      if (!taskref->expanded) {
        taskref->expanded = true;

        auto cache_key = taskref->task->cacheKey();
        if (!cache_key.isEmpty()) {
          taskref->cache_filename = FileUtil::joinPaths(
              tempdir_,
              StringUtil::format("cache_$0", cache_key.get()));
        }

        auto cached =
            !cache_key.isEmpty() &&
            FileUtil::exists(taskref->cache_filename);

        if (cached) {
          fnord::logDebug(
              "fnord.dproc",
              "Running task [cached]: $0",
              taskref->debug_name);

          taskref->task->decode(
              new io::MmappedFile(
                  File::openFile(taskref->cache_filename, File::O_READ)));

          result->updateStatus([&pipeline] (TaskStatus* status) {
            ++status->num_subtasks_completed;
          });

          taskref->finished = true;
          waiting = false;
          break;
        }

        auto parent_task = taskref;
        size_t numdeps = 0;
        for (const auto& dep : taskref->task->dependencies()) {
          RefPtr<LocalTaskRef> depref(new LocalTaskRef(app, dep.task_name, dep.params));
          parent_task->dependencies.emplace_back(depref);
          pipeline->tasks.emplace_back(depref);
          ++numdeps;
        }

        if (numdeps > 0) {
          result->updateStatus([numdeps] (TaskStatus* status) {
            status->num_subtasks_total += numdeps;
          });
        }

        waiting = false;
        break;
      }

      bool deps_finished = true;
      for (const auto& dep : taskref->dependencies) {
        if (dep->failed) {
          taskref->failed = true;
          taskref->finished = true;
          waiting = false;
        }

        if (!dep->finished) {
          deps_finished = false;
        }
      }

      if (!taskref->finished) {
        if (!deps_finished) {
          ++num_waiting;
          continue;
        }

        fnord::logDebug("fnord.dproc", "Running task: $0", taskref->debug_name);
        taskref->running = true;
        tpool_.run(std::bind(
            &LocalScheduler::runTask,
            this,
            pipeline,
            taskref,
            result));

        waiting = false;
      }
    }

    fnord::logDebug(
        "fnord.dproc",
        "Running local pipeline id=$0: $1",
        (void*) pipeline,
        result->status().toString());

    if (waiting) {
      pipeline->wakeup.wait(lk);
    }

    while (pipeline->tasks.size() > 0 && pipeline->tasks.back()->finished) {
      pipeline->tasks.pop_back();
    }
  }

  fnord::logDebug(
      "fnord.dproc",
      "Completed local pipeline id=$0",
      (void*) pipeline);
}

void LocalScheduler::runTask(
    LocalTaskPipeline* pipeline,
    RefPtr<LocalTaskRef> task,
    RefPtr<TaskResultFuture> result) {
  auto output_file = task->cache_filename;

  try {
    task->task->compute(task.get());

    if (!task->cache_filename.empty()) {
      auto res = task->task->encode();

      auto file = File::openFile(
          output_file + "~",
          File::O_CREATEOROPEN | File::O_WRITE);

      file.write(res->data(), res->size());
      FileUtil::mv(output_file + "~", output_file);
    }
  } catch (const std::exception& e) {
    task->failed = true;
    fnord::logError("fnord.dproc", e, "error");
  }

  result->updateStatus([&pipeline] (TaskStatus* status) {
    ++status->num_subtasks_completed;
  });

  std::unique_lock<std::mutex> lk(pipeline->mutex);
  task->finished = true;
  lk.unlock();
  pipeline->wakeup.notify_all();
}

LocalScheduler::LocalTaskRef::LocalTaskRef(
    RefPtr<Application> app,
    const String& task_name,
    const Buffer& params) :
    task(app->getTaskInstance(task_name, params)),
    debug_name(StringUtil::format("$0#$1", app->name(), task_name)),
    running(false),
    expanded(false),
    finished(false),
    failed(false) {}

RefPtr<Task> LocalScheduler::LocalTaskRef::getDependency(size_t index) {
  if (index >= dependencies.size()) {
    RAISEF(kIndexError, "invalid dependecy index: $0", index);
  }

  const auto& dep = dependencies[index];
  return dep->task;
}

size_t LocalScheduler::LocalTaskRef::numDependencies() const {
  return dependencies.size();
}

} // namespace dproc
} // namespace fnord
<commit_msg>cache versioning<commit_after>/**
 * This file is part of the "libfnord" project
 *   Copyright (c) 2015 Paul Asmuth
 *
 * FnordMetric is free software: you can redistribute it and/or modify it under
 * the terms of the GNU General Public License v3.0. 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 <unistd.h>
#include <fnord-base/io/file.h>
#include <fnord-base/io/fileutil.h>
#include <fnord-base/io/mmappedfile.h>
#include <fnord-base/logging.h>
#include <fnord-base/io/fileutil.h>
#include <fnord-base/util/binarymessagereader.h>
#include <fnord-base/util/binarymessagewriter.h>
#include <fnord-dproc/LocalScheduler.h>

namespace fnord {
namespace dproc {

LocalScheduler::LocalScheduler(
    const String& tempdir /* = "/tmp" */,
    size_t max_threads /* = 8 */,
    size_t max_requests /* = 32 */) :
    tempdir_(tempdir),
    tpool_(max_threads),
    req_tpool_(max_requests) {}

void LocalScheduler::start() {
  req_tpool_.start();
  tpool_.start();
}

void LocalScheduler::stop() {
  req_tpool_.stop();
  tpool_.stop();
}

RefPtr<TaskResultFuture> LocalScheduler::run(
    RefPtr<Application> app,
    const TaskSpec& task) {
  RefPtr<TaskResultFuture> result(new TaskResultFuture());

  try {
    auto instance = mkRef(
        new LocalTaskRef(
            app,
            task.task_name(),
            Buffer(task.params().data(), task.params().size())));

    req_tpool_.run([this, app, result, instance] () {
      try {
        LocalTaskPipeline pipeline;
        pipeline.tasks.push_back(instance);
        runPipeline(app.get(), &pipeline, result);

        if (instance->failed) {
          RAISE(kRuntimeError, "task failed");
        }

        result->returnResult(instance->task);
      } catch (const StandardException& e) {
        fnord::logError("dproc.scheduler", e, "task failed");
        result->returnError(e);
      }
    });
  } catch (const StandardException& e) {
    fnord::logError("dproc.scheduler", e, "task failed");
    result->returnError(e);
  }

  return result;
}

void LocalScheduler::runPipeline(
    Application* app,
    LocalTaskPipeline* pipeline,
    RefPtr<TaskResultFuture> result) {
  fnord::logInfo(
      "fnord.dproc",
      "Starting local pipeline id=$0 tasks=$1",
      (void*) pipeline,
      pipeline->tasks.size());

  std::unique_lock<std::mutex> lk(pipeline->mutex);
  result->updateStatus([&pipeline] (TaskStatus* status) {
    status->num_subtasks_total = pipeline->tasks.size();
  });

  while (pipeline->tasks.size() > 0) {
    bool waiting = true;
    size_t num_waiting = 0;
    size_t num_running = 0;
    size_t num_completed = 0;

    for (auto& taskref : pipeline->tasks) {

      if (taskref->finished) {
        ++num_completed;
        continue;
      }

      if (taskref->running) {
        ++num_running;
        continue;
      }

      if (!taskref->expanded) {
        taskref->expanded = true;

        auto cache_key = taskref->task->cacheKey();
        if (!cache_key.isEmpty()) {
          taskref->cache_filename = FileUtil::joinPaths(
              tempdir_,
              StringUtil::format("cache_$0", cache_key.get()));
        }

        auto cached =
            !cache_key.isEmpty() &&
            FileUtil::exists(taskref->cache_filename);

        if (cached) {
          auto cache_file = File::openFile(
              taskref->cache_filename,
              File::O_READ);

          Buffer cache_hdr(sizeof(uint64_t));
          cache_file.read(&cache_hdr);
          util::BinaryMessageReader reader(cache_hdr.data(), cache_hdr.size());
          auto cache_version = *reader.readUInt64();
          auto cache_size = cache_file.size() - cache_hdr.size();

          fnord::logDebug(
              "fnord.dproc",
              "Reading RDD from cache: $0, version=$1",
              taskref->debug_name,
              cache_version);

          taskref->task->decode(
                new io::MmappedFile(
                    std::move(cache_file),
                    cache_hdr.size(),
                    cache_size));

          result->updateStatus([&pipeline] (TaskStatus* status) {
            ++status->num_subtasks_completed;
          });

          taskref->finished = true;
          waiting = false;
          break;
        }

        auto parent_task = taskref;
        size_t numdeps = 0;
        for (const auto& dep : taskref->task->dependencies()) {
          RefPtr<LocalTaskRef> depref(new LocalTaskRef(app, dep.task_name, dep.params));
          parent_task->dependencies.emplace_back(depref);
          pipeline->tasks.emplace_back(depref);
          ++numdeps;
        }

        if (numdeps > 0) {
          result->updateStatus([numdeps] (TaskStatus* status) {
            status->num_subtasks_total += numdeps;
          });
        }

        waiting = false;
        break;
      }

      bool deps_finished = true;
      for (const auto& dep : taskref->dependencies) {
        if (dep->failed) {
          taskref->failed = true;
          taskref->finished = true;
          waiting = false;
        }

        if (!dep->finished) {
          deps_finished = false;
        }
      }

      if (!taskref->finished) {
        if (!deps_finished) {
          ++num_waiting;
          continue;
        }

        fnord::logDebug(
            "fnord.dproc",
            "Computing RDD: $0, version=$1",
            taskref->debug_name,
            taskref->task->cacheVersion());

        taskref->running = true;
        tpool_.run(std::bind(
            &LocalScheduler::runTask,
            this,
            pipeline,
            taskref,
            result));

        waiting = false;
      }
    }

    fnord::logDebug(
        "fnord.dproc",
        "Running local pipeline id=$0: $1",
        (void*) pipeline,
        result->status().toString());

    if (waiting) {
      pipeline->wakeup.wait(lk);
    }

    while (pipeline->tasks.size() > 0 && pipeline->tasks.back()->finished) {
      pipeline->tasks.pop_back();
    }
  }

  fnord::logDebug(
      "fnord.dproc",
      "Completed local pipeline id=$0",
      (void*) pipeline);
}

void LocalScheduler::runTask(
    LocalTaskPipeline* pipeline,
    RefPtr<LocalTaskRef> task,
    RefPtr<TaskResultFuture> result) {

  try {
    task->task->compute(task.get());

    if (!task->cache_filename.empty()) {
      auto cache_file = task->cache_filename;

      {
        auto f = File::openFile(
            cache_file + "~",
            File::O_CREATEOROPEN | File::O_WRITE | File::O_TRUNCATE);

        util::BinaryMessageWriter hdr;
        hdr.appendUInt64(task->task->cacheVersion());
        f.write(hdr.data(), hdr.size());

        auto res = task->task->encode();
        f.write(res->data(), res->size());
      }

      FileUtil::mv(cache_file + "~", cache_file);
    }
  } catch (const std::exception& e) {
    task->failed = true;
    fnord::logError("fnord.dproc", e, "error");
  }

  result->updateStatus([&pipeline] (TaskStatus* status) {
    ++status->num_subtasks_completed;
  });

  std::unique_lock<std::mutex> lk(pipeline->mutex);
  task->finished = true;
  lk.unlock();
  pipeline->wakeup.notify_all();
}

LocalScheduler::LocalTaskRef::LocalTaskRef(
    RefPtr<Application> app,
    const String& task_name,
    const Buffer& params) :
    task(app->getTaskInstance(task_name, params)),
    debug_name(StringUtil::format("$0#$1", app->name(), task_name)),
    running(false),
    expanded(false),
    finished(false),
    failed(false) {}

RefPtr<Task> LocalScheduler::LocalTaskRef::getDependency(size_t index) {
  if (index >= dependencies.size()) {
    RAISEF(kIndexError, "invalid dependecy index: $0", index);
  }

  const auto& dep = dependencies[index];
  return dep->task;
}

size_t LocalScheduler::LocalTaskRef::numDependencies() const {
  return dependencies.size();
}

} // namespace dproc
} // namespace fnord
<|endoftext|>


<commit_before>
// Copyright (c) 2012 Christopher Lux <christopherlux@gmail.com>
// Distributed under the Modified BSD License, see license.txt.

#include "texture_data_util.h"

#include <memory.h>

#include <scm/gl_core/log.h>
#include <scm/gl_core/texture_objects/texture_image.h>
#include <scm/gl_util/data/imaging/mip_map_generation.h>

namespace scm {
namespace gl {
namespace util {

namespace nv {
// thanks nvidia for providing the source code to flip dxt images
typedef struct
{
    unsigned short col0, col1;
    unsigned char row[4];
} DXTColorBlock_t;

typedef struct
{
    unsigned short row[4];
} DXT3AlphaBlock_t;

typedef struct
{
    unsigned char alpha0, alpha1;
    unsigned char row[6];
} DXT5AlphaBlock_t;

inline
void
SwapMem(void *byte1, void *byte2, int size)
{
    unsigned char *tmp=(unsigned char *)malloc(sizeof(unsigned char)*size);
    memcpy(tmp, byte1, size);
    memcpy(byte1, byte2, size);
    memcpy(byte2, tmp, size);
    free(tmp);
}

inline
void
SwapChar(unsigned char * x, unsigned char * y)
{
    unsigned char z = *x;
    *x = *y;
    *y = z;
}

inline
void
SwapShort(unsigned short * x, unsigned short * y)
{
    unsigned short z = *x;
    *x = *y;
    *y = z;
}

inline
void
flipDXT1Blocks(DXTColorBlock_t *Block, int NumBlocks)
{
    int i;
    DXTColorBlock_t *ColorBlock=Block;
    for(i=0; i<NumBlocks; ++i) {
        SwapChar( &ColorBlock->row[0], &ColorBlock->row[3] );
        SwapChar( &ColorBlock->row[1], &ColorBlock->row[2] );
        ++ColorBlock;
    }
}

inline
void
flipDXT3Blocks(DXTColorBlock_t *Block, int NumBlocks)
{
    int i;
    DXTColorBlock_t *ColorBlock=Block;
    DXT3AlphaBlock_t *AlphaBlock;
    for(i=0; i<NumBlocks; ++i) {
        AlphaBlock=(DXT3AlphaBlock_t *)ColorBlock;
        SwapShort( &AlphaBlock->row[0], &AlphaBlock->row[3] );
        SwapShort( &AlphaBlock->row[1], &AlphaBlock->row[2] );
        ++ColorBlock;
        SwapChar( &ColorBlock->row[0], &ColorBlock->row[3] );
        SwapChar( &ColorBlock->row[1], &ColorBlock->row[2] );
        ++ColorBlock;
    }
}

inline
void
flipDXT5Alpha(DXT5AlphaBlock_t *Block)
{
    unsigned long *Bits, Bits0=0, Bits1=0;

    memcpy(&Bits0, &Block->row[0], sizeof(unsigned char)*3);
    memcpy(&Bits1, &Block->row[3], sizeof(unsigned char)*3);

    Bits=((unsigned long *)&(Block->row[0]));
    *Bits&=0xff000000;
    *Bits|=(unsigned char)(Bits1>>12)&0x00000007;
    *Bits|=(unsigned char)((Bits1>>15)&0x00000007)<<3;
    *Bits|=(unsigned char)((Bits1>>18)&0x00000007)<<6;
    *Bits|=(unsigned char)((Bits1>>21)&0x00000007)<<9;
    *Bits|=(unsigned char)(Bits1&0x00000007)<<12;
    *Bits|=(unsigned char)((Bits1>>3)&0x00000007)<<15;
    *Bits|=(unsigned char)((Bits1>>6)&0x00000007)<<18;
    *Bits|=(unsigned char)((Bits1>>9)&0x00000007)<<21;

    Bits=((unsigned long *)&(Block->row[3]));
    *Bits&=0xff000000;
    *Bits|=(unsigned char)(Bits0>>12)&0x00000007;
    *Bits|=(unsigned char)((Bits0>>15)&0x00000007)<<3;
    *Bits|=(unsigned char)((Bits0>>18)&0x00000007)<<6;
    *Bits|=(unsigned char)((Bits0>>21)&0x00000007)<<9;
    *Bits|=(unsigned char)(Bits0&0x00000007)<<12;
    *Bits|=(unsigned char)((Bits0>>3)&0x00000007)<<15;
    *Bits|=(unsigned char)((Bits0>>6)&0x00000007)<<18;
    *Bits|=(unsigned char)((Bits0>>9)&0x00000007)<<21;
}

inline
void
flipDXT5Blocks(DXTColorBlock_t *Block, int NumBlocks)
{
    DXTColorBlock_t *ColorBlock=Block;
    DXT5AlphaBlock_t *AlphaBlock;
    int i;

    for(i=0; i<NumBlocks; ++i) {
        AlphaBlock=(DXT5AlphaBlock_t *)ColorBlock;

        flipDXT5Alpha(AlphaBlock);
        ++ColorBlock;

        SwapChar( &ColorBlock->row[0], &ColorBlock->row[3] );
        SwapChar( &ColorBlock->row[1], &ColorBlock->row[2] );
        ++ColorBlock;
    }
}

inline
void
flipBC4Blocks(DXTColorBlock_t *Block, int NumBlocks)
{
    DXTColorBlock_t  *ColorBlock = Block;
    DXT5AlphaBlock_t *RedBlock;

    for(int i = 0; i < NumBlocks; ++i) {
        RedBlock = reinterpret_cast<DXT5AlphaBlock_t*>(ColorBlock);

        flipDXT5Alpha(RedBlock);
        ++ColorBlock;
    }
}

inline
void
flipBC5Blocks(DXTColorBlock_t *Block, int NumBlocks)
{
    DXTColorBlock_t  *ColorBlock = Block;
    DXT5AlphaBlock_t *RBlock;
    DXT5AlphaBlock_t *GBlock;

    for(int i = 0; i < NumBlocks; ++i) {
        RBlock = reinterpret_cast<DXT5AlphaBlock_t*>(ColorBlock);
        flipDXT5Alpha(RBlock);
        ++ColorBlock;

        GBlock = reinterpret_cast<DXT5AlphaBlock_t*>(ColorBlock);
        flipDXT5Alpha(GBlock);
        ++ColorBlock;
    }
}

} // namespace nv

bool
image_layer_vert_flip_raw(scm::uint8*const data,
                          data_format      fmt,
                          unsigned         w,
                          unsigned         h)
{
    if (is_compressed_format(fmt)) {
        using namespace scm::gl::util::nv;

        int bw  = (w + 3) / 4;
        int bh  = (h + 3) / 4;
        int bs  = compressed_block_size(fmt);
        int bls = bw * bs;

        if (1 == h) {
            return true;
        }
        else if (1 < h && h < 4) {
            DXTColorBlock_t *line = reinterpret_cast<DXTColorBlock_t*>(data);
            switch (fmt) {
                case FORMAT_BC1_RGBA:
                case FORMAT_BC1_SRGBA:
                    flipDXT1Blocks(line, bw);
                    break;
                case FORMAT_BC2_RGBA:
                case FORMAT_BC2_SRGBA:
                    flipDXT3Blocks(line, bw);
                    break;
                case FORMAT_BC3_RGBA:
                case FORMAT_BC3_SRGBA:
                    flipDXT5Blocks(line, bw);
                    break;
                case FORMAT_BC4_R:
                case FORMAT_BC4_R_S:
                    flipBC4Blocks(line, bw);
                    break;
                case FORMAT_BC5_RG:
                case FORMAT_BC5_RG_S:
                    flipBC5Blocks(line, bw);
                    break;
                default:
                    return false;
            }
            return true;
        }
        else if (4 <= h) {
            DXTColorBlock_t *top_line;
            DXTColorBlock_t *bottom_line;

            switch (fmt) {
                case FORMAT_BC1_RGBA:
                case FORMAT_BC1_SRGBA:
                    for(int bl = 0; bl < (bh / 2); ++bl) {
                        top_line    = reinterpret_cast<DXTColorBlock_t*>(data + bl * bls);
                        bottom_line = reinterpret_cast<DXTColorBlock_t*>(data + (bh - (bl + 1)) * bls);
                        flipDXT1Blocks(top_line,    bw);
                        flipDXT1Blocks(bottom_line, bw);
                        SwapMem(bottom_line, top_line, bls);
                    }
                    break;
                case FORMAT_BC2_RGBA:
                case FORMAT_BC2_SRGBA:
                    for(int bl = 0; bl < (bh / 2); ++bl) {
                        top_line    = reinterpret_cast<DXTColorBlock_t*>(data + bl * bls);
                        bottom_line = reinterpret_cast<DXTColorBlock_t*>(data + (bh - (bl + 1)) * bls);
                        flipDXT3Blocks(top_line,    bw);
                        flipDXT3Blocks(bottom_line, bw);
                        SwapMem(bottom_line, top_line, bls);
                    }
                    break;
                case FORMAT_BC3_RGBA:
                case FORMAT_BC3_SRGBA:
                    for(int bl = 0; bl < (bh / 2); ++bl) {
                        top_line    = reinterpret_cast<DXTColorBlock_t*>(data + bl * bls);
                        bottom_line = reinterpret_cast<DXTColorBlock_t*>(data + (bh - (bl + 1)) * bls);
                        flipDXT5Blocks(top_line,    bw);
                        flipDXT5Blocks(bottom_line, bw);
                        SwapMem(bottom_line, top_line, bls);
                    }
                    break;
                case FORMAT_BC4_R:
                case FORMAT_BC4_R_S:
                    for(int bl = 0; bl < (bh / 2); ++bl) {
                        top_line    = reinterpret_cast<DXTColorBlock_t*>(data + bl * bls);
                        bottom_line = reinterpret_cast<DXTColorBlock_t*>(data + (bh - (bl + 1)) * bls);
                        flipBC4Blocks(top_line,    bw);
                        flipBC4Blocks(bottom_line, bw);
                        SwapMem(bottom_line, top_line, bls);
                    }
                    break;
                case FORMAT_BC5_RG:
                case FORMAT_BC5_RG_S:
                    for(int bl = 0; bl < (bh / 2); ++bl) {
                        top_line    = reinterpret_cast<DXTColorBlock_t*>(data + bl * bls);
                        bottom_line = reinterpret_cast<DXTColorBlock_t*>(data + (bh - (bl + 1)) * bls);
                        flipBC5Blocks(top_line,    bw);
                        flipBC5Blocks(bottom_line, bw);
                        SwapMem(bottom_line, top_line, bls);
                    }
                    break;
                default:
                    return false;
            }
            return true;
        }
        else {
            return false;
        }
    }
    else {
        size_t              lsize = static_cast<size_t>(w) * size_of_format(fmt);
        scoped_array<uint8> tmp_line(new uint8[lsize]);

        for (unsigned l = 0; l < (h / 2); ++l) {
            size_t r = lsize * l;
            size_t w = lsize * (h - (l + 1));

            memcpy(tmp_line.get(), data + r,       lsize);
            memcpy(data + r,       data + w,       lsize);
            memcpy(data + w,       tmp_line.get(), lsize);
        }
        return true;
    }
}

bool
image_flip_vertical(const shared_array<uint8>& data,
                          data_format          fmt,
                          unsigned             w,
                          unsigned             h)
{
    return image_layer_vert_flip_raw(data.get(), fmt, w, h);
}

bool
volume_flip_vertical(const shared_array<uint8>& data,
                           data_format          fmt,
                           unsigned             w,
                           unsigned             h,
                           unsigned             d)
{
    size_t ssize = (static_cast<size_t>(w) * h * bit_per_pixel(fmt)) / 8;

    for (unsigned s = 0; s < d; ++s) {
        if (!image_layer_vert_flip_raw(data.get() + ssize * s, fmt, w, h)) {
            return false;
        }
    }

    return true;
}

bool
generate_mipmaps(const math::vec3ui&        src_dim,
                       gl::data_format      src_fmt,
                       uint8*               src_data,
                       std::vector<uint8*>& dst_data)
{
    using namespace scm::gl;
    using namespace scm::math;

    switch (src_fmt) {
    case FORMAT_R_32F:
        typed_generate_mipmaps<float, 1, 2>(src_dim, src_data, dst_data);
        break;
    case FORMAT_R_8:
        typed_generate_mipmaps<uint8, 1, 2>(src_dim, src_data, dst_data);
        break;
    case FORMAT_R_16:
        typed_generate_mipmaps<uint16, 1, 2>(src_dim, src_data, dst_data);
        break;
    case FORMAT_RGBA_8:
        typed_generate_mipmaps<uint8, 4, 2>(src_dim, src_data, dst_data);
        break;
    default:
        glerr() << log::error
                << "generate_mipmaps(): error unsupported source data format (" << format_string(src_fmt) << ")." << log::end;
        return false;
    }

    return true;
}

} // namespace util
} // namespace gl
} // namespace scm
<commit_msg>extended supported data formats in gl_util generate_mipmaps()<commit_after>
// Copyright (c) 2012 Christopher Lux <christopherlux@gmail.com>
// Distributed under the Modified BSD License, see license.txt.

#include "texture_data_util.h"

#include <memory.h>

#include <scm/gl_core/log.h>
#include <scm/gl_core/texture_objects/texture_image.h>
#include <scm/gl_util/data/imaging/mip_map_generation.h>

namespace scm {
namespace gl {
namespace util {

namespace nv {
// thanks nvidia for providing the source code to flip dxt images
typedef struct
{
    unsigned short col0, col1;
    unsigned char row[4];
} DXTColorBlock_t;

typedef struct
{
    unsigned short row[4];
} DXT3AlphaBlock_t;

typedef struct
{
    unsigned char alpha0, alpha1;
    unsigned char row[6];
} DXT5AlphaBlock_t;

inline
void
SwapMem(void *byte1, void *byte2, int size)
{
    unsigned char *tmp=(unsigned char *)malloc(sizeof(unsigned char)*size);
    memcpy(tmp, byte1, size);
    memcpy(byte1, byte2, size);
    memcpy(byte2, tmp, size);
    free(tmp);
}

inline
void
SwapChar(unsigned char * x, unsigned char * y)
{
    unsigned char z = *x;
    *x = *y;
    *y = z;
}

inline
void
SwapShort(unsigned short * x, unsigned short * y)
{
    unsigned short z = *x;
    *x = *y;
    *y = z;
}

inline
void
flipDXT1Blocks(DXTColorBlock_t *Block, int NumBlocks)
{
    int i;
    DXTColorBlock_t *ColorBlock=Block;
    for(i=0; i<NumBlocks; ++i) {
        SwapChar( &ColorBlock->row[0], &ColorBlock->row[3] );
        SwapChar( &ColorBlock->row[1], &ColorBlock->row[2] );
        ++ColorBlock;
    }
}

inline
void
flipDXT3Blocks(DXTColorBlock_t *Block, int NumBlocks)
{
    int i;
    DXTColorBlock_t *ColorBlock=Block;
    DXT3AlphaBlock_t *AlphaBlock;
    for(i=0; i<NumBlocks; ++i) {
        AlphaBlock=(DXT3AlphaBlock_t *)ColorBlock;
        SwapShort( &AlphaBlock->row[0], &AlphaBlock->row[3] );
        SwapShort( &AlphaBlock->row[1], &AlphaBlock->row[2] );
        ++ColorBlock;
        SwapChar( &ColorBlock->row[0], &ColorBlock->row[3] );
        SwapChar( &ColorBlock->row[1], &ColorBlock->row[2] );
        ++ColorBlock;
    }
}

inline
void
flipDXT5Alpha(DXT5AlphaBlock_t *Block)
{
    unsigned long *Bits, Bits0=0, Bits1=0;

    memcpy(&Bits0, &Block->row[0], sizeof(unsigned char)*3);
    memcpy(&Bits1, &Block->row[3], sizeof(unsigned char)*3);

    Bits=((unsigned long *)&(Block->row[0]));
    *Bits&=0xff000000;
    *Bits|=(unsigned char)(Bits1>>12)&0x00000007;
    *Bits|=(unsigned char)((Bits1>>15)&0x00000007)<<3;
    *Bits|=(unsigned char)((Bits1>>18)&0x00000007)<<6;
    *Bits|=(unsigned char)((Bits1>>21)&0x00000007)<<9;
    *Bits|=(unsigned char)(Bits1&0x00000007)<<12;
    *Bits|=(unsigned char)((Bits1>>3)&0x00000007)<<15;
    *Bits|=(unsigned char)((Bits1>>6)&0x00000007)<<18;
    *Bits|=(unsigned char)((Bits1>>9)&0x00000007)<<21;

    Bits=((unsigned long *)&(Block->row[3]));
    *Bits&=0xff000000;
    *Bits|=(unsigned char)(Bits0>>12)&0x00000007;
    *Bits|=(unsigned char)((Bits0>>15)&0x00000007)<<3;
    *Bits|=(unsigned char)((Bits0>>18)&0x00000007)<<6;
    *Bits|=(unsigned char)((Bits0>>21)&0x00000007)<<9;
    *Bits|=(unsigned char)(Bits0&0x00000007)<<12;
    *Bits|=(unsigned char)((Bits0>>3)&0x00000007)<<15;
    *Bits|=(unsigned char)((Bits0>>6)&0x00000007)<<18;
    *Bits|=(unsigned char)((Bits0>>9)&0x00000007)<<21;
}

inline
void
flipDXT5Blocks(DXTColorBlock_t *Block, int NumBlocks)
{
    DXTColorBlock_t *ColorBlock=Block;
    DXT5AlphaBlock_t *AlphaBlock;
    int i;

    for(i=0; i<NumBlocks; ++i) {
        AlphaBlock=(DXT5AlphaBlock_t *)ColorBlock;

        flipDXT5Alpha(AlphaBlock);
        ++ColorBlock;

        SwapChar( &ColorBlock->row[0], &ColorBlock->row[3] );
        SwapChar( &ColorBlock->row[1], &ColorBlock->row[2] );
        ++ColorBlock;
    }
}

inline
void
flipBC4Blocks(DXTColorBlock_t *Block, int NumBlocks)
{
    DXTColorBlock_t  *ColorBlock = Block;
    DXT5AlphaBlock_t *RedBlock;

    for(int i = 0; i < NumBlocks; ++i) {
        RedBlock = reinterpret_cast<DXT5AlphaBlock_t*>(ColorBlock);

        flipDXT5Alpha(RedBlock);
        ++ColorBlock;
    }
}

inline
void
flipBC5Blocks(DXTColorBlock_t *Block, int NumBlocks)
{
    DXTColorBlock_t  *ColorBlock = Block;
    DXT5AlphaBlock_t *RBlock;
    DXT5AlphaBlock_t *GBlock;

    for(int i = 0; i < NumBlocks; ++i) {
        RBlock = reinterpret_cast<DXT5AlphaBlock_t*>(ColorBlock);
        flipDXT5Alpha(RBlock);
        ++ColorBlock;

        GBlock = reinterpret_cast<DXT5AlphaBlock_t*>(ColorBlock);
        flipDXT5Alpha(GBlock);
        ++ColorBlock;
    }
}

} // namespace nv

bool
image_layer_vert_flip_raw(scm::uint8*const data,
                          data_format      fmt,
                          unsigned         w,
                          unsigned         h)
{
    if (is_compressed_format(fmt)) {
        using namespace scm::gl::util::nv;

        int bw  = (w + 3) / 4;
        int bh  = (h + 3) / 4;
        int bs  = compressed_block_size(fmt);
        int bls = bw * bs;

        if (1 == h) {
            return true;
        }
        else if (1 < h && h < 4) {
            DXTColorBlock_t *line = reinterpret_cast<DXTColorBlock_t*>(data);
            switch (fmt) {
                case FORMAT_BC1_RGBA:
                case FORMAT_BC1_SRGBA:
                    flipDXT1Blocks(line, bw);
                    break;
                case FORMAT_BC2_RGBA:
                case FORMAT_BC2_SRGBA:
                    flipDXT3Blocks(line, bw);
                    break;
                case FORMAT_BC3_RGBA:
                case FORMAT_BC3_SRGBA:
                    flipDXT5Blocks(line, bw);
                    break;
                case FORMAT_BC4_R:
                case FORMAT_BC4_R_S:
                    flipBC4Blocks(line, bw);
                    break;
                case FORMAT_BC5_RG:
                case FORMAT_BC5_RG_S:
                    flipBC5Blocks(line, bw);
                    break;
                default:
                    return false;
            }
            return true;
        }
        else if (4 <= h) {
            DXTColorBlock_t *top_line;
            DXTColorBlock_t *bottom_line;

            switch (fmt) {
                case FORMAT_BC1_RGBA:
                case FORMAT_BC1_SRGBA:
                    for(int bl = 0; bl < (bh / 2); ++bl) {
                        top_line    = reinterpret_cast<DXTColorBlock_t*>(data + bl * bls);
                        bottom_line = reinterpret_cast<DXTColorBlock_t*>(data + (bh - (bl + 1)) * bls);
                        flipDXT1Blocks(top_line,    bw);
                        flipDXT1Blocks(bottom_line, bw);
                        SwapMem(bottom_line, top_line, bls);
                    }
                    break;
                case FORMAT_BC2_RGBA:
                case FORMAT_BC2_SRGBA:
                    for(int bl = 0; bl < (bh / 2); ++bl) {
                        top_line    = reinterpret_cast<DXTColorBlock_t*>(data + bl * bls);
                        bottom_line = reinterpret_cast<DXTColorBlock_t*>(data + (bh - (bl + 1)) * bls);
                        flipDXT3Blocks(top_line,    bw);
                        flipDXT3Blocks(bottom_line, bw);
                        SwapMem(bottom_line, top_line, bls);
                    }
                    break;
                case FORMAT_BC3_RGBA:
                case FORMAT_BC3_SRGBA:
                    for(int bl = 0; bl < (bh / 2); ++bl) {
                        top_line    = reinterpret_cast<DXTColorBlock_t*>(data + bl * bls);
                        bottom_line = reinterpret_cast<DXTColorBlock_t*>(data + (bh - (bl + 1)) * bls);
                        flipDXT5Blocks(top_line,    bw);
                        flipDXT5Blocks(bottom_line, bw);
                        SwapMem(bottom_line, top_line, bls);
                    }
                    break;
                case FORMAT_BC4_R:
                case FORMAT_BC4_R_S:
                    for(int bl = 0; bl < (bh / 2); ++bl) {
                        top_line    = reinterpret_cast<DXTColorBlock_t*>(data + bl * bls);
                        bottom_line = reinterpret_cast<DXTColorBlock_t*>(data + (bh - (bl + 1)) * bls);
                        flipBC4Blocks(top_line,    bw);
                        flipBC4Blocks(bottom_line, bw);
                        SwapMem(bottom_line, top_line, bls);
                    }
                    break;
                case FORMAT_BC5_RG:
                case FORMAT_BC5_RG_S:
                    for(int bl = 0; bl < (bh / 2); ++bl) {
                        top_line    = reinterpret_cast<DXTColorBlock_t*>(data + bl * bls);
                        bottom_line = reinterpret_cast<DXTColorBlock_t*>(data + (bh - (bl + 1)) * bls);
                        flipBC5Blocks(top_line,    bw);
                        flipBC5Blocks(bottom_line, bw);
                        SwapMem(bottom_line, top_line, bls);
                    }
                    break;
                default:
                    return false;
            }
            return true;
        }
        else {
            return false;
        }
    }
    else {
        size_t              lsize = static_cast<size_t>(w) * size_of_format(fmt);
        scoped_array<uint8> tmp_line(new uint8[lsize]);

        for (unsigned l = 0; l < (h / 2); ++l) {
            size_t r = lsize * l;
            size_t w = lsize * (h - (l + 1));

            memcpy(tmp_line.get(), data + r,       lsize);
            memcpy(data + r,       data + w,       lsize);
            memcpy(data + w,       tmp_line.get(), lsize);
        }
        return true;
    }
}

bool
image_flip_vertical(const shared_array<uint8>& data,
                          data_format          fmt,
                          unsigned             w,
                          unsigned             h)
{
    return image_layer_vert_flip_raw(data.get(), fmt, w, h);
}

bool
volume_flip_vertical(const shared_array<uint8>& data,
                           data_format          fmt,
                           unsigned             w,
                           unsigned             h,
                           unsigned             d)
{
    size_t ssize = (static_cast<size_t>(w) * h * bit_per_pixel(fmt)) / 8;

    for (unsigned s = 0; s < d; ++s) {
        if (!image_layer_vert_flip_raw(data.get() + ssize * s, fmt, w, h)) {
            return false;
        }
    }

    return true;
}

bool
generate_mipmaps(const math::vec3ui&        src_dim,
                       gl::data_format      src_fmt,
                       uint8*               src_data,
                       std::vector<uint8*>& dst_data)
{
    using namespace scm::gl;
    using namespace scm::math;

    switch (src_fmt) {
    case FORMAT_R_32F:
        typed_generate_mipmaps<float, 1, 2>(src_dim, src_data, dst_data);
        break;
    case FORMAT_RG_32F:
        typed_generate_mipmaps<float, 2, 2>(src_dim, src_data, dst_data);
        break;
    case FORMAT_RGB_32F:
        typed_generate_mipmaps<float, 3, 2>(src_dim, src_data, dst_data);
        break;
    case FORMAT_RGBA_32F:
        typed_generate_mipmaps<float, 4, 2>(src_dim, src_data, dst_data);
        break;
    case FORMAT_R_8:
        typed_generate_mipmaps<uint8, 1, 2>(src_dim, src_data, dst_data);
        break;
    case FORMAT_RG_8:
        typed_generate_mipmaps<uint8, 2, 2>(src_dim, src_data, dst_data);
        break;
    case FORMAT_RGB_8:
        typed_generate_mipmaps<uint8, 3, 2>(src_dim, src_data, dst_data);
        break;
    case FORMAT_RGBA_8:
        typed_generate_mipmaps<uint8, 4, 2>(src_dim, src_data, dst_data);
        break;
    case FORMAT_R_16:
        typed_generate_mipmaps<uint16, 1, 2>(src_dim, src_data, dst_data);
        break;
    case FORMAT_RG_16:
        typed_generate_mipmaps<uint16, 2, 2>(src_dim, src_data, dst_data);
        break;
    case FORMAT_RGB_16:
        typed_generate_mipmaps<uint16, 3, 2>(src_dim, src_data, dst_data);
        break;
    case FORMAT_RGBA_16:
        typed_generate_mipmaps<uint16, 4, 2>(src_dim, src_data, dst_data);
        break;
    default:
        glerr() << log::error
                << "generate_mipmaps(): error unsupported source data format (" << format_string(src_fmt) << ")." << log::end;
        return false;
    }

    return true;
}

} // namespace util
} // namespace gl
} // namespace scm
<|endoftext|>


<commit_before>#include "file.h"
#include <iostream>
#include <cstdio>
#include <memory>

namespace File
{
    bool Load(const char* fileName, char*& buffer, size_t& size)
    {
        if (!fileName)
            return false;

        FILE* file = fopen(fileName, "rb");
        if (!file)
        {
            std::cerr << "File::Load: Could not open file " << fileName << " (fopen)" << std::endl;
            return false;
        }

        // Get file size
        fseek(file, 0, SEEK_END);
        size = (size_t)ftell(file);
        rewind(file);

        if (!size)
        {
            std::cerr << "File::Load: Could not open file " << fileName << " (size is 0)" << std::endl;
            fclose(file);
            return false;
        }

        buffer = new char[size];
        if (!buffer)
        {
            std::cerr << "File::Load: Failed to allocate buffer for file " << fileName << " (size " << size << ")" << std::endl;
            fclose(file);
            return false;
        }

        size_t result = fread(buffer, sizeof(char), size, file);
        if (result != size)
        {
            std::cerr << "File::Load: Could not read the same number of bytes (size != result) for file " << fileName << " (size " << size << ", result " << result << ")" << std::endl;
            delete[] buffer;
            fclose(file);
            return false;
        }

        fclose(file);
        return true;
    }

    bool Save(const char* fileName, const char* buffer, size_t size)
    {
        if (!fileName || !buffer || !size)
            return false;

        FILE* file = fopen(fileName, "wb");
        if (!file)
        {
            std::cerr << "File::Save: Could not open file " << fileName << " (fopen)" << std::endl;
            return false;
        }

        size_t result = fwrite(buffer, sizeof(char), size, file);
        if (result != size)
        {
            fclose(file);
            std::cerr << "File::Save: Could not write the same number of bytes (size != result) for file " << fileName << " (size " << size << ", result " << result << ")" << std::endl;
            return false;
        }

        fclose(file);
        return true;
    }

    bool Remove(const char* fileName)
    {
        return !remove(fileName);
    }

    bool Exists(const char* fileName)
    {
        DIR *dir;
        struct dirent *ent;
        if ((dir = opendir(".")) != NULL)
        {
            while ((ent = readdir(dir)) != NULL)
                if (ent->d_type == DT_REG) // file
                    if (strcmp(ent->d_name, fileName) == 0)
                    {
                        closedir(dir);
                        return true;
                    }

            closedir(dir);
        }

        return false;
    }
}
<commit_msg>Fix warnings in file.cpp<commit_after>#include "file.h"
#include <iostream>
#include <cstdio>
#include <memory>

namespace File
{
    bool Load(const char* fileName, char*& buffer, size_t& size)
    {
        if (!fileName)
            return false;

        FILE* file;
        fopen_s(&file, fileName, "rb");
        if (!file)
        {
            std::cerr << "File::Load: Could not open file " << fileName << " (fopen)" << std::endl;
            return false;
        }

        // Get file size
        fseek(file, 0, SEEK_END);
        size = (size_t)ftell(file);
        rewind(file);

        if (!size)
        {
            std::cerr << "File::Load: Could not open file " << fileName << " (size is 0)" << std::endl;
            fclose(file);
            return false;
        }

        buffer = new char[size];
        if (!buffer)
        {
            std::cerr << "File::Load: Failed to allocate buffer for file " << fileName << " (size " << size << ")" << std::endl;
            fclose(file);
            return false;
        }

        size_t result = fread(buffer, sizeof(char), size, file);
        if (result != size)
        {
            std::cerr << "File::Load: Could not read the same number of bytes (size != result) for file " << fileName << " (size " << size << ", result " << result << ")" << std::endl;
            delete[] buffer;
            fclose(file);
            return false;
        }

        fclose(file);
        return true;
    }

    bool Save(const char* fileName, const char* buffer, size_t size)
    {
        if (!fileName || !buffer || !size)
            return false;

        FILE* file;
        fopen_s(&file, fileName, "wb");
        if (!file)
        {
            std::cerr << "File::Save: Could not open file " << fileName << " (fopen)" << std::endl;
            return false;
        }

        size_t result = fwrite(buffer, sizeof(char), size, file);
        if (result != size)
        {
            fclose(file);
            std::cerr << "File::Save: Could not write the same number of bytes (size != result) for file " << fileName << " (size " << size << ", result " << result << ")" << std::endl;
            return false;
        }

        fclose(file);
        return true;
    }

    bool Remove(const char* fileName)
    {
        return !remove(fileName);
    }

    bool Exists(const char* fileName)
    {
        DIR *dir;
        struct dirent *ent;
        if ((dir = opendir(".")) != NULL)
        {
            while ((ent = readdir(dir)) != NULL)
                if (ent->d_type == DT_REG) // file
                    if (strcmp(ent->d_name, fileName) == 0)
                    {
                        closedir(dir);
                        return true;
                    }

            closedir(dir);
        }

        return false;
    }
}
<|endoftext|>