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

#include "zippylog/stream.hpp"

#include <zippylog/platform.hpp>

#include <io.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>

#ifdef WIN32
#define lseek64 _lseeki64
#define open _open
#endif

namespace zippylog {

InputStream::InputStream()
{
    this->_fd = -1;
    this->_cis = NULL;
    this->_is = NULL;
}

InputStream::InputStream(string file, int64 seek_bytes)
{
    if (!this->OpenFile(file, seek_bytes)) {
        // TODO handle error
    }
}

InputStream::~InputStream() {
    delete _cis, _is;
    _close(this->_fd);
}

bool InputStream::OpenFile(string file, int64 start_offset)
{
    if (this->_fd >= 0) {
        _close(this->_fd);
        this->_fd = -1;
    }

    if (this->_is) delete this->_is;
    if (this->_cis) delete this->_cis;
    this->_have_next_size = false;
    this->_next_envelope_size = 0;

    this->_fd = open(file.c_str(), O_RDONLY | O_BINARY);
    if (this->_fd < 0) {
        GOOGLE_LOG(FATAL) << "could not open file for reading: " << file;
        return false;
    }

    if (start_offset > 0) {
        lseek64(this->_fd, start_offset, SEEK_SET);
    }

    this->_is = new FileInputStream(this->_fd, -1);
    this->_cis = new CodedInputStream(this->_is);

    if (start_offset == 0) {
        char v;
        if (!_cis->ReadRaw(&v, sizeof(v))) {
            GOOGLE_LOG(FATAL) << "could not read version byte from stream";
            return false;
        }
        else if (v != 1) {
            GOOGLE_LOG(FATAL) << "stream is not version 1";
            return false;
        }
    }

    return true;
}

uint32 InputStream::NextEnvelopeSize()
{
    if (this->_have_next_size) {
        return this->_next_envelope_size;
    }

    if (!this->_cis->ReadVarint32(&this->_next_envelope_size)) {
        return 0;
    }

    this->_have_next_size = true;

    return this->_next_envelope_size;
}

bool InputStream::ReadEnvelope(::zippylog::Envelope &e, uint32 &bytes_read)
{
    uint32 size = this->NextEnvelopeSize();
    if (!size) {
        bytes_read = 0;
        return false;
    }

    CodedInputStream::Limit limit = _cis->PushLimit(size);
    if (!e.envelope.ParseFromCodedStream(_cis) || !_cis->ConsumedEntireMessage()) {
        this->_have_next_size = false;
        bytes_read = 0;
        return false;
    }

    this->_have_next_size = false;

    _cis->PopLimit(limit);

    if (size <= 0x7f) {          // 127
        bytes_read = size + 1;
    }
    else if (size <= 0x3fff) {   // 16,383
        bytes_read = size + 2;
    }
    else if (size <= 0x1fffff) { // 2,097,151
        bytes_read = size + 3;
    }
    else {                       // 2,684,35,455 (well, actually a little less due to 32 bit limit
        bytes_read = size + 4;
    }

    return true;
}

bool InputStream::Seek(int64 offset)
{
    lseek(this->_fd, offset, SEEK_SET);

    return true;
}

OutputStream::OutputStream(const string file)
{
    if (!platform::OpenFile(this->file, file,
        platform::CREATE | platform::APPEND | platform::WRITE))
    {
        char error[8192];
        windows_error(&error[0], 8192);
        throw "could not open file";
    }

    platform::FileStat stat;
    if (!platform::stat(file, stat)) {
        throw "could not stat file opened for writing. weird";
    }

    // this is a new file, so we need to write out the version
    if (!stat.size) {
        char version = 0x01;
        if (write(this->file.fd, &version, 1) != 1) {
            int error;
            _get_errno(&error);
            char *errs = strerror(error);
            char doserror[1024];
            windows_error(&doserror[0], 1024);
            throw "could not write version byte to stream";
        }
    }

    this->os = new FileOutputStream(this->file.fd);
    this->cos = new CodedOutputStream(this->os);
}

OutputStream::~OutputStream()
{
    // we must delete the coded output stream first, so it returns unused
    // buffer to output stream
    delete this->cos;

    // we close the output stream manually, which incurs a flush
    this->os->Close();

    delete this->os;
}

bool OutputStream::WriteEnvelope(::zippylog::Envelope &e)
{
    int size = e.envelope.ByteSize();

    this->cos->WriteVarint32(size);
    return e.envelope.SerializeToCodedStream(this->cos);
}

bool OutputStream::WriteEnvelope(const void *data, int length)
{
    this->cos->WriteVarint32(length);
    this->cos->WriteRaw(data, length);

    return true;
}

bool OutputStream::WriteData(const void *data, int length)
{
    this->cos->WriteRaw(data, length);

    return true;
}

bool OutputStream::WriteString(const string &s)
{
    this->cos->WriteRaw(s.data(), s.size());

    return true;
}

bool OutputStream::Flush()
{
    // the coded output stream takes ownership of the buffer from the file
    // output stream, which screws with the later's Flush() API (it will
    // flush the whole buffer, even though only X bytes really contain data).
    // the solution is to nuke the coded output stream, which relinquishes
    // unused bytes back to file output stream. then, we flush the output
    // stream and create a new coded output stream
    // see http://code.google.com/p/protobuf/issues/detail?id=216

    delete this->cos;
    bool result = this->os->Flush();
    this->cos = new CodedOutputStream(this->os);

    // TODO consider using unbuffered I/O for the created file instead
    // of forcing a file descriptor flush
    return platform::FlushFile(this->file) && result;
}

} // namespace

#ifdef WIN32
#undef lseek64
#endif<commit_msg>fix bugs around input stream destructor and cleanup<commit_after>//  Copyright 2010 Gregory Szorc
//
//  Licensed under the Apache License, Version 2.0 (the "License");
//  you may not use this file except in compliance with the License.
//  You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
//  Unless required by applicable law or agreed to in writing, software
//  distributed under the License is distributed on an "AS IS" BASIS,
//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//  See the License for the specific language governing permissions and
//  limitations under the License.

#include "zippylog/stream.hpp"

#include <zippylog/platform.hpp>

#include <io.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>

#ifdef WIN32
#define lseek64 _lseeki64
#define open _open
#endif

namespace zippylog {

InputStream::InputStream()
{
    this->_fd = -1;
    this->_cis = NULL;
    this->_is = NULL;
}

InputStream::InputStream(string file, int64 seek_bytes)
{
    if (!this->OpenFile(file, seek_bytes)) {
        throw "could not open stream for reading";
    }
}

InputStream::~InputStream() {
    delete this->_cis;
    delete this->_is;
    //_close(this->_fd);
}

bool InputStream::OpenFile(string file, int64 start_offset)
{
    if (this->_fd >= 0) {
        _close(this->_fd);
        this->_fd = -1;
    }

    if (this->_cis) delete this->_cis;
    if (this->_is) delete this->_is;
    this->_have_next_size = false;
    this->_next_envelope_size = 0;

    this->_fd = open(file.c_str(), O_RDONLY | O_BINARY);
    if (this->_fd < 0) {
        GOOGLE_LOG(FATAL) << "could not open file for reading: " << file;
        return false;
    }

    if (start_offset > 0) {
        lseek64(this->_fd, start_offset, SEEK_SET);
    }

    this->_is = new FileInputStream(this->_fd);
    this->_cis = new CodedInputStream(this->_is);

    if (start_offset == 0) {
        char v;
        if (!_cis->ReadRaw(&v, sizeof(v))) {
            GOOGLE_LOG(FATAL) << "could not read version byte from stream";
            return false;
        }
        else if (v != 1) {
            GOOGLE_LOG(FATAL) << "stream is not version 1";
            return false;
        }
    }

    return true;
}

uint32 InputStream::NextEnvelopeSize()
{
    if (this->_have_next_size) {
        return this->_next_envelope_size;
    }

    if (!this->_cis->ReadVarint32(&this->_next_envelope_size)) {
        return 0;
    }

    this->_have_next_size = true;

    return this->_next_envelope_size;
}

bool InputStream::ReadEnvelope(::zippylog::Envelope &e, uint32 &bytes_read)
{
    uint32 size = this->NextEnvelopeSize();
    if (!size) {
        bytes_read = 0;
        return false;
    }

    CodedInputStream::Limit limit = _cis->PushLimit(size);
    if (!e.envelope.ParseFromCodedStream(_cis) || !_cis->ConsumedEntireMessage()) {
        this->_have_next_size = false;
        bytes_read = 0;
        return false;
    }

    this->_have_next_size = false;

    _cis->PopLimit(limit);

    if (size <= 0x7f) {          // 127
        bytes_read = size + 1;
    }
    else if (size <= 0x3fff) {   // 16,383
        bytes_read = size + 2;
    }
    else if (size <= 0x1fffff) { // 2,097,151
        bytes_read = size + 3;
    }
    else {                       // 2,684,35,455 (well, actually a little less due to 32 bit limit
        bytes_read = size + 4;
    }

    return true;
}

bool InputStream::Seek(int64 offset)
{
    lseek(this->_fd, offset, SEEK_SET);

    return true;
}

OutputStream::OutputStream(const string file)
{
    if (!platform::OpenFile(this->file, file,
        platform::CREATE | platform::APPEND | platform::WRITE))
    {
        char error[8192];
        windows_error(&error[0], 8192);
        throw "could not open file";
    }

    platform::FileStat stat;
    if (!platform::stat(file, stat)) {
        throw "could not stat file opened for writing. weird";
    }

    // this is a new file, so we need to write out the version
    if (!stat.size) {
        char version = 0x01;
        if (write(this->file.fd, &version, 1) != 1) {
            int error;
            _get_errno(&error);
            char *errs = strerror(error);
            char doserror[1024];
            windows_error(&doserror[0], 1024);
            throw "could not write version byte to stream";
        }
    }

    this->os = new FileOutputStream(this->file.fd);
    this->cos = new CodedOutputStream(this->os);
}

OutputStream::~OutputStream()
{
    // we must delete the coded output stream first, so it returns unused
    // buffer to output stream
    delete this->cos;

    // we close the output stream manually, which incurs a flush
    this->os->Close();

    delete this->os;
}

bool OutputStream::WriteEnvelope(::zippylog::Envelope &e)
{
    int size = e.envelope.ByteSize();

    this->cos->WriteVarint32(size);
    return e.envelope.SerializeToCodedStream(this->cos);
}

bool OutputStream::WriteEnvelope(const void *data, int length)
{
    this->cos->WriteVarint32(length);
    this->cos->WriteRaw(data, length);

    return true;
}

bool OutputStream::WriteData(const void *data, int length)
{
    this->cos->WriteRaw(data, length);

    return true;
}

bool OutputStream::WriteString(const string &s)
{
    this->cos->WriteRaw(s.data(), s.size());

    return true;
}

bool OutputStream::Flush()
{
    // the coded output stream takes ownership of the buffer from the file
    // output stream, which screws with the later's Flush() API (it will
    // flush the whole buffer, even though only X bytes really contain data).
    // the solution is to nuke the coded output stream, which relinquishes
    // unused bytes back to file output stream. then, we flush the output
    // stream and create a new coded output stream
    // see http://code.google.com/p/protobuf/issues/detail?id=216

    delete this->cos;
    bool result = this->os->Flush();
    this->cos = new CodedOutputStream(this->os);

    // TODO consider using unbuffered I/O for the created file instead
    // of forcing a file descriptor flush
    return platform::FlushFile(this->file) && result;
}

} // namespace

#ifdef WIN32
#undef lseek64
#endif<|endoftext|>


<commit_before>/*
 * Author: Brendan Le Foll <brendan.le.foll@intel.com>
 * Contributions: Mihai Tudor Panu <mihai.t.panu@intel.com>
 * Copyright (c) 2014 Intel Corporation.
 *
 * Permission is hereby granted, free of charge, to any person obtaining
 * a copy of this software and associated documentation files (the
 * "Software"), to deal in the Software without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish,
 * distribute, sublicense, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so, subject to
 * the following conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

#include <unistd.h>
#include "hmc5883l.h"

int
main(int argc, char **argv)
{
//! [Interesting]
    upm::Hmc5883l* compass = new upm::Hmc5883l(0);
    int16_t *pos;

    compass->set_declination(0.2749); // Set your declination from true north in radians

    while(true){
        compass->update(); // Update the coordinates
        pos = compass->coordinates();
        fprintf(stdout, "coor: %5d %5d %5d ", pos[0], pos[1], pos[2]);
        fprintf(stdout, "heading: %5.2f direction: %3.2f\n", compass->heading(), compass->direction());
        sleep(1);
    }
//! [Interesting]

    return 0;
}
<commit_msg>hmc5883l: Add comments to C++ example<commit_after>/*
 * Author: Brendan Le Foll <brendan.le.foll@intel.com>
 * Contributions: Mihai Tudor Panu <mihai.t.panu@intel.com>
 * Copyright (c) 2014 Intel Corporation.
 *
 * Permission is hereby granted, free of charge, to any person obtaining
 * a copy of this software and associated documentation files (the
 * "Software"), to deal in the Software without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish,
 * distribute, sublicense, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so, subject to
 * the following conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

#include <unistd.h>
#include "hmc5883l.h"

int
main(int argc, char **argv)
{
//! [Interesting]
    // Instantiate on I2C
    upm::Hmc5883l* compass = new upm::Hmc5883l(0);
    int16_t *pos;

    compass->set_declination(0.2749); // Set your declination from true north in radians

    // Print out the coordinates, heading, and direction every second
    while(true){
        compass->update(); // Update the coordinates
        pos = compass->coordinates();
        fprintf(stdout, "coor: %5d %5d %5d ", pos[0], pos[1], pos[2]);
        fprintf(stdout, "heading: %5.2f direction: %3.2f\n", compass->heading(), compass->direction());
        sleep(1);
    }
//! [Interesting]

    return 0;
}
<|endoftext|>


<commit_before>#include "Entity.hpp"
#include "compsys/Component.hpp"
#include "Logfile.hpp"

Entity::Entity():
    m_state(created)
{
}

Entity::~Entity()
{
    if (m_state == finished) {
        try { kill(); }
        catch (std::exception const& e) {
            LOG_E("Exception in Entity destructor: kill() threw:");
            LOG_EX(e);
        } catch (...) {
            LOG_F("Exception in Entity destructor:"
                  " kill() threw an unknown exception. Terminating.");
            std::terminate();
        }
    }
}

void Entity::add(Component& c)
{
    if (c.m_parent)
        throw std::invalid_argument("cannot add component: it already has a parent");
    if (m_state != created)
        throw std::logic_error("attempt to add a component to an Entity in a wrong state");
    if ((*this)[c.metaComponent()])
        throw std::logic_error("only one component per type per Entity allowed");
    c.m_parent = this;

    m_components.push_back(&c);
}

void Entity::finish()
{
    if (m_state == finished)
        return;
    if (m_state != created)
        throw std::logic_error("attempt to finish an Entity in a wrong state");
    m_state = finished;
    for (Component& c : m_components)
        c.initComponent();
}

Component* Entity::operator[](MetaComponent const& meta)
{
    auto const it = std::find_if(m_components.begin(), m_components.end(),
    [&meta](Component const& c) {
        return &c.metaComponent() == &meta;
    });
    return it == m_components.end() ? nullptr : &*it;
}

void Entity::kill()
{
    if (m_state == killed)
        return;
    if (m_state != finished)
        throw std::logic_error("attempt to kill an Entity in a wrong state");
    m_state = killed;
    for (Component& c : m_components)
        c.cleanupComponent();
}
<commit_msg>Entity::add: invalid_argument -> logic_error.<commit_after>#include "Entity.hpp"
#include "compsys/Component.hpp"
#include "Logfile.hpp"

Entity::Entity():
    m_state(created)
{
}

Entity::~Entity()
{
    if (m_state == finished) {
        try { kill(); }
        catch (std::exception const& e) {
            LOG_E("Exception in Entity destructor: kill() threw:");
            LOG_EX(e);
        } catch (...) {
            LOG_F("Exception in Entity destructor:"
                  " kill() threw an unknown exception. Terminating.");
            std::terminate();
        }
    }
}

void Entity::add(Component& c)
{
    if (c.m_parent)
        throw std::logic_error("cannot add component: it already has a parent");
    if (m_state != created)
        throw std::logic_error("attempt to add a component to an Entity in a wrong state");
    if ((*this)[c.metaComponent()])
        throw std::logic_error("only one component per type per Entity allowed");
    c.m_parent = this;

    m_components.push_back(&c);
}

void Entity::finish()
{
    if (m_state == finished)
        return;
    if (m_state != created)
        throw std::logic_error("attempt to finish an Entity in a wrong state");
    m_state = finished;
    for (Component& c : m_components)
        c.initComponent();
}

Component* Entity::operator[](MetaComponent const& meta)
{
    auto const it = std::find_if(m_components.begin(), m_components.end(),
    [&meta](Component const& c) {
        return &c.metaComponent() == &meta;
    });
    return it == m_components.end() ? nullptr : &*it;
}

void Entity::kill()
{
    if (m_state == killed)
        return;
    if (m_state != finished)
        throw std::logic_error("attempt to kill an Entity in a wrong state");
    m_state = killed;
    for (Component& c : m_components)
        c.cleanupComponent();
}
<|endoftext|>


<commit_before>//
// This file is part of the Marble Desktop Globe.
//
// This program is free software licensed under the GNU LGPL. You can
// find a copy of this license in LICENSE.txt in the top directory of
// the source code.
//
// Copyright 2008      Torsten Rahn   <rahn@kde.org>
// Copyright 2008      Inge Wallin    <inge@lysator.liu.se>
//

// Self
#include "RenderPlugin.h"

// Marble
#include "MarbleDataFacade.h"
#include "MarbleDebug.h"

// Qt
#include <QtGui/QAction>
#include <QtGui/QStandardItem>

namespace Marble
{

class RenderPluginPrivate
{
  public:
    RenderPluginPrivate()
        : m_dataFacade(0),
          m_action(0),
          m_item(0),
          m_enabled(true),
          m_visible(true)
    {
    }

    ~RenderPluginPrivate()
    {
    }

    MarbleDataFacade   *m_dataFacade;
    QAction            *m_action;
    QStandardItem      *m_item;

    bool                m_enabled;
    bool                m_visible;
};

RenderPlugin::RenderPlugin()
    : d( new RenderPluginPrivate() )
{
    d->m_action = new QAction( this );
    connect( d->m_action, SIGNAL( toggled( bool ) ),
	     this,        SLOT( setVisible( bool ) ) );

    d->m_item = new QStandardItem();
}

RenderPlugin::~RenderPlugin()
{
    delete d->m_item;
    delete d;

}

MarbleDataFacade* RenderPlugin::dataFacade() const
{
    return d->m_dataFacade;
}

void RenderPlugin::setDataFacade( MarbleDataFacade* dataFacade )
{
    d->m_dataFacade = dataFacade;
}

QAction* RenderPlugin::action() const
{
    d->m_action->setCheckable( true );
    d->m_action->setChecked( visible() );
    d->m_action->setIcon( icon() );
    d->m_action->setText( guiString() );
    d->m_action->setToolTip( description() );
    return d->m_action;
}

QList<QActionGroup*>* RenderPlugin::actionGroups() const
{
    return 0;
}

QList<QActionGroup*>* RenderPlugin::toolbarActionGroups() const
{
    return 0;
}

QStandardItem* RenderPlugin::item() const
{
    d->m_item->setIcon( icon() );
    d->m_item->setText( name() );
    d->m_item->setEditable( false );
    d->m_item->setCheckable( true );
    d->m_item->setCheckState( enabled() ?  Qt::Checked : Qt::Unchecked  );
    d->m_item->setToolTip( description() );
    d->m_item->setFlags( d->m_item->flags() & ~Qt::ItemIsSelectable );

    // Custom data
    d->m_item->setData( nameId(), RenderPlugin::NameId );
    d->m_item->setData( (bool) aboutDialog(), RenderPlugin::AboutDialogAvailable );
    d->m_item->setData( (bool) configDialog(), RenderPlugin::ConfigurationDialogAvailable );
    d->m_item->setData( backendTypes(), RenderPlugin::BackendTypes );

    return d->m_item;
}

void RenderPlugin::applyItemState()
{
    d->m_enabled = ( d->m_item->checkState() == Qt::Checked );

    d->m_action->setVisible( d->m_enabled );
}

void RenderPlugin::retrieveItemState()
{
    d->m_item->setCheckState( enabled() ?  Qt::Checked : Qt::Unchecked  );
}

void RenderPlugin::setEnabled( bool enabled )
{
    if ( enabled == d->m_enabled )
        return;

    d->m_enabled = enabled;
    d->m_action->setVisible( enabled );

    d->m_item->setCheckState( enabled ?  Qt::Checked : Qt::Unchecked  );
}

void RenderPlugin::setVisible( bool visible )
{
    if ( visible == d->m_visible )
        return;

    d->m_visible = visible;
    d->m_action->setChecked( visible );

    emit visibilityChanged( nameId(), visible );
}

bool RenderPlugin::enabled() const
{
    return d->m_enabled;
}

bool RenderPlugin::visible() const
{
    return d->m_visible;
}

QDialog *RenderPlugin::aboutDialog() const
{
    return 0;
}

QDialog *RenderPlugin::configDialog() const
{
    return 0;
}

QHash<QString,QVariant> RenderPlugin::settings() const
{
    return QHash<QString,QVariant>();
}

void RenderPlugin::setSettings( QHash<QString,QVariant> settings )
{
    Q_UNUSED( settings );
}

bool RenderPlugin::eventFilter( QObject *, QEvent * )
{
    return false;
}

} // namespace Marble

#include "RenderPlugin.moc"
<commit_msg>RenderPlugin: fix render plugins always being enabled for a short time during startup.<commit_after>//
// This file is part of the Marble Desktop Globe.
//
// This program is free software licensed under the GNU LGPL. You can
// find a copy of this license in LICENSE.txt in the top directory of
// the source code.
//
// Copyright 2008      Torsten Rahn   <rahn@kde.org>
// Copyright 2008      Inge Wallin    <inge@lysator.liu.se>
//

// Self
#include "RenderPlugin.h"

// Marble
#include "MarbleDataFacade.h"
#include "MarbleDebug.h"

// Qt
#include <QtGui/QAction>
#include <QtGui/QStandardItem>

namespace Marble
{

class RenderPluginPrivate
{
  public:
    RenderPluginPrivate()
        : m_dataFacade(0),
          m_action(0),
          m_item(0),
          m_enabled(false),
          m_visible(false)
    {
    }

    ~RenderPluginPrivate()
    {
    }

    MarbleDataFacade   *m_dataFacade;
    QAction            *m_action;
    QStandardItem      *m_item;

    bool                m_enabled;
    bool                m_visible;
};

RenderPlugin::RenderPlugin()
    : d( new RenderPluginPrivate() )
{
    d->m_action = new QAction( this );
    connect( d->m_action, SIGNAL( toggled( bool ) ),
	     this,        SLOT( setVisible( bool ) ) );

    d->m_item = new QStandardItem();
}

RenderPlugin::~RenderPlugin()
{
    delete d->m_item;
    delete d;

}

MarbleDataFacade* RenderPlugin::dataFacade() const
{
    return d->m_dataFacade;
}

void RenderPlugin::setDataFacade( MarbleDataFacade* dataFacade )
{
    d->m_dataFacade = dataFacade;
}

QAction* RenderPlugin::action() const
{
    d->m_action->setCheckable( true );
    d->m_action->setChecked( visible() );
    d->m_action->setIcon( icon() );
    d->m_action->setText( guiString() );
    d->m_action->setToolTip( description() );
    return d->m_action;
}

QList<QActionGroup*>* RenderPlugin::actionGroups() const
{
    return 0;
}

QList<QActionGroup*>* RenderPlugin::toolbarActionGroups() const
{
    return 0;
}

QStandardItem* RenderPlugin::item() const
{
    d->m_item->setIcon( icon() );
    d->m_item->setText( name() );
    d->m_item->setEditable( false );
    d->m_item->setCheckable( true );
    d->m_item->setCheckState( enabled() ?  Qt::Checked : Qt::Unchecked  );
    d->m_item->setToolTip( description() );
    d->m_item->setFlags( d->m_item->flags() & ~Qt::ItemIsSelectable );

    // Custom data
    d->m_item->setData( nameId(), RenderPlugin::NameId );
    d->m_item->setData( (bool) aboutDialog(), RenderPlugin::AboutDialogAvailable );
    d->m_item->setData( (bool) configDialog(), RenderPlugin::ConfigurationDialogAvailable );
    d->m_item->setData( backendTypes(), RenderPlugin::BackendTypes );

    return d->m_item;
}

void RenderPlugin::applyItemState()
{
    d->m_enabled = ( d->m_item->checkState() == Qt::Checked );

    d->m_action->setVisible( d->m_enabled );
}

void RenderPlugin::retrieveItemState()
{
    d->m_item->setCheckState( enabled() ?  Qt::Checked : Qt::Unchecked  );
}

void RenderPlugin::setEnabled( bool enabled )
{
    if ( enabled == d->m_enabled )
        return;

    d->m_enabled = enabled;
    d->m_action->setVisible( enabled );

    d->m_item->setCheckState( enabled ?  Qt::Checked : Qt::Unchecked  );
}

void RenderPlugin::setVisible( bool visible )
{
    if ( visible == d->m_visible )
        return;

    d->m_visible = visible;
    d->m_action->setChecked( visible );

    emit visibilityChanged( nameId(), visible );
}

bool RenderPlugin::enabled() const
{
    return d->m_enabled;
}

bool RenderPlugin::visible() const
{
    return d->m_visible;
}

QDialog *RenderPlugin::aboutDialog() const
{
    return 0;
}

QDialog *RenderPlugin::configDialog() const
{
    return 0;
}

QHash<QString,QVariant> RenderPlugin::settings() const
{
    return QHash<QString,QVariant>();
}

void RenderPlugin::setSettings( QHash<QString,QVariant> settings )
{
    Q_UNUSED( settings );
}

bool RenderPlugin::eventFilter( QObject *, QEvent * )
{
    return false;
}

} // namespace Marble

#include "RenderPlugin.moc"
<|endoftext|>


<commit_before>#include <ppasskeeper/key.h>

#include <cstring>
#include <sstream>
#include <cstdlib>
#include <iostream>

static size_t digits(unsigned int number)
{
	int digits = 0, step = 1;
	while (step <= number)
	{
		digits++;
		step *= 10;
	}
	return digits ? digits : 1;
}

extern "C"
{

size_t ppk_key_length(const ppk_entry* entry)
{
	size_t len = 0;
	switch(entry->type)
	{
	case ppk_network:
		if (entry->net.protocol && entry->net.protocol[0] != '\0')
			len = strlen(entry->net.protocol);

		len	+= strlen("://")
			+ strlen(entry->net.login) + strlen("@")
			+ strlen(entry->net.host) + strlen(":")
			+ digits(entry->net.port);

		break;
	case ppk_application:
		len = strlen(entry->app.username) + strlen("@") + strlen(entry->app.app_name);
		break;
	case ppk_item:
		len = strlen(entry->item);
		break;
	default:
		return 0;
	}
	return len + 1; // +1 for '\0'
}

ppk_boolean ppk_get_key(const ppk_entry* entry, char* returned_key, size_t max_key_length)
{
	std::string protocol="";

	if (max_key_length == 0)
		return PPK_FALSE;

	std::ostringstream key;
	switch(entry->type)
	{
	case ppk_network:
		if(entry->net.protocol!=NULL)
			protocol=entry->net.protocol;
		key << protocol << "://" << entry->net.login << '@' << entry->net.host << ':' << entry->net.port;
		break;
	case ppk_application:
		key << entry->app.username << '@' << entry->app.app_name;
		break;
	case ppk_item:
		key << entry->item;
		break;
	default:
		std::cerr << "ppk_get_key: Unknown entry type" << entry->type << " !" << std::endl;
		return PPK_FALSE;
	}

	std::string key_str = key.str();
	std::size_t key_len = key_str.size();
	if (key_len >= max_key_length)
	{
		//not enough room in returned_key for returning
		return PPK_FALSE;
	}
	else
	{
		key_str.copy(returned_key, key_len);
		returned_key[key_len]='\0';
		return PPK_TRUE;
	}
}

ppk_entry* ppk_entry_new_from_key(const char* key)
{
	std::string key_str(key);
	std::size_t key_len = key_str.size();
	std::size_t pos = key_str.find("://");
	if (pos != std::string::npos)
	{
		if (pos + 6 > key_len)
			return NULL;
		std::string protocol = key_str.substr(0, pos);
		std::size_t loginpos = pos + 3;
		std::size_t hostpos = key_str.find('@', loginpos + 1);
		if (hostpos == std::string::npos || hostpos == key_len - 1)
			return NULL;
		else
		{
			std::string login = key_str.substr(loginpos, hostpos - loginpos);
			hostpos++;
			std::size_t portpos = key_str.find(':', hostpos + 1);
			unsigned int port;
			std::string host;
			if (portpos == std::string::npos)
			{
				//port unspecified, use 0
				port = 0;
				host = key_str.substr(hostpos).c_str();
			}
			else
			{
				portpos++;
				// ppk://aaaaaaaaa@bbbbbbbb:111
				//       ^loginpos ^hostpos ^portpos
				//       6         17       26
				if (portpos == key_len || (port = atoi(key_str.substr(portpos).c_str())) == 0)
					return NULL;
				host = key_str.substr(hostpos, portpos - hostpos - 1);
			}
			return ppk_network_entry_new((protocol == URL_PREFIX) ? NULL : protocol.c_str(), login.c_str(), host.c_str(), port);
		}
	}
	else
	{
		pos = key_str.find('@');
		if (pos == std::string::npos)
		{
			return ppk_item_entry_new(key_str.c_str());
		}
		else
		{
			//it's an application key
			if (pos == key_len - 1)
				return NULL;
			std::string username = key_str.substr(0, pos);
			std::string app_name = key_str.substr(pos + 1);
			return ppk_application_entry_new(username.c_str(), app_name.c_str());
		}
	}
}

} /* extern "C" */
<commit_msg>Key.cpp: fixes a signed/unsigned comparaison issue<commit_after>#include <ppasskeeper/key.h>

#include <cstring>
#include <sstream>
#include <cstdlib>
#include <iostream>

static size_t digits(unsigned int number)
{
	int digits = 0;
	unsigned int step = 1;
	while (step <= number)
	{
		digits++;
		step *= 10;
	}
	return digits ? digits : 1;
}

extern "C"
{

size_t ppk_key_length(const ppk_entry* entry)
{
	size_t len = 0;
	switch(entry->type)
	{
	case ppk_network:
		if (entry->net.protocol && entry->net.protocol[0] != '\0')
			len = strlen(entry->net.protocol);

		len	+= strlen("://")
			+ strlen(entry->net.login) + strlen("@")
			+ strlen(entry->net.host) + strlen(":")
			+ digits(entry->net.port);

		break;
	case ppk_application:
		len = strlen(entry->app.username) + strlen("@") + strlen(entry->app.app_name);
		break;
	case ppk_item:
		len = strlen(entry->item);
		break;
	default:
		return 0;
	}
	return len + 1; // +1 for '\0'
}

ppk_boolean ppk_get_key(const ppk_entry* entry, char* returned_key, size_t max_key_length)
{
	std::string protocol="";

	if (max_key_length == 0)
		return PPK_FALSE;

	std::ostringstream key;
	switch(entry->type)
	{
	case ppk_network:
		if(entry->net.protocol!=NULL)
			protocol=entry->net.protocol;
		key << protocol << "://" << entry->net.login << '@' << entry->net.host << ':' << entry->net.port;
		break;
	case ppk_application:
		key << entry->app.username << '@' << entry->app.app_name;
		break;
	case ppk_item:
		key << entry->item;
		break;
	default:
		std::cerr << "ppk_get_key: Unknown entry type" << entry->type << " !" << std::endl;
		return PPK_FALSE;
	}

	std::string key_str = key.str();
	std::size_t key_len = key_str.size();
	if (key_len >= max_key_length)
	{
		//not enough room in returned_key for returning
		return PPK_FALSE;
	}
	else
	{
		key_str.copy(returned_key, key_len);
		returned_key[key_len]='\0';
		return PPK_TRUE;
	}
}

ppk_entry* ppk_entry_new_from_key(const char* key)
{
	std::string key_str(key);
	std::size_t key_len = key_str.size();
	std::size_t pos = key_str.find("://");
	if (pos != std::string::npos)
	{
		if (pos + 6 > key_len)
			return NULL;
		std::string protocol = key_str.substr(0, pos);
		std::size_t loginpos = pos + 3;
		std::size_t hostpos = key_str.find('@', loginpos + 1);
		if (hostpos == std::string::npos || hostpos == key_len - 1)
			return NULL;
		else
		{
			std::string login = key_str.substr(loginpos, hostpos - loginpos);
			hostpos++;
			std::size_t portpos = key_str.find(':', hostpos + 1);
			unsigned int port;
			std::string host;
			if (portpos == std::string::npos)
			{
				//port unspecified, use 0
				port = 0;
				host = key_str.substr(hostpos).c_str();
			}
			else
			{
				portpos++;
				// ppk://aaaaaaaaa@bbbbbbbb:111
				//       ^loginpos ^hostpos ^portpos
				//       6         17       26
				if (portpos == key_len || (port = atoi(key_str.substr(portpos).c_str())) == 0)
					return NULL;
				host = key_str.substr(hostpos, portpos - hostpos - 1);
			}
			return ppk_network_entry_new((protocol == URL_PREFIX) ? NULL : protocol.c_str(), login.c_str(), host.c_str(), port);
		}
	}
	else
	{
		pos = key_str.find('@');
		if (pos == std::string::npos)
		{
			return ppk_item_entry_new(key_str.c_str());
		}
		else
		{
			//it's an application key
			if (pos == key_len - 1)
				return NULL;
			std::string username = key_str.substr(0, pos);
			std::string app_name = key_str.substr(pos + 1);
			return ppk_application_entry_new(username.c_str(), app_name.c_str());
		}
	}
}

} /* extern "C" */
<|endoftext|>


<commit_before>// Copyright (c) 2009-2012 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include <map>

#include <openssl/ecdsa.h>
#include <openssl/obj_mac.h>

#include "key.h"
#include "util.h"

// Generate a private key from just the secret parameter
int EC_KEY_regenerate_key(EC_KEY *eckey, BIGNUM *priv_key)
{
    int ok = 0;
    BN_CTX *ctx = NULL;
    EC_POINT *pub_key = NULL;

    if (!eckey) return 0;

    const EC_GROUP *group = EC_KEY_get0_group(eckey);

    if ((ctx = BN_CTX_new()) == NULL)
        goto err;

    pub_key = EC_POINT_new(group);

    if (pub_key == NULL)
        goto err;

    if (!EC_POINT_mul(group, pub_key, priv_key, NULL, NULL, ctx))
        goto err;

    EC_KEY_set_private_key(eckey,priv_key);
    EC_KEY_set_public_key(eckey,pub_key);

    ok = 1;

err:

    if (pub_key)
        EC_POINT_free(pub_key);
    if (ctx != NULL)
        BN_CTX_free(ctx);

    return(ok);
}

// Perform ECDSA key recovery (see SEC1 4.1.6) for curves over (mod p)-fields
// recid selects which key is recovered
// if check is nonzero, additional checks are performed
int ECDSA_SIG_recover_key_GFp(EC_KEY *eckey, ECDSA_SIG *ecsig, const unsigned char *msg, int msglen, int recid, int check)
{
    if (!eckey) return 0;

    int ret = 0;
    BN_CTX *ctx = NULL;

    BIGNUM *x = NULL;
    BIGNUM *e = NULL;
    BIGNUM *order = NULL;
    BIGNUM *sor = NULL;
    BIGNUM *eor = NULL;
    BIGNUM *field = NULL;
    EC_POINT *R = NULL;
    EC_POINT *O = NULL;
    EC_POINT *Q = NULL;
    BIGNUM *rr = NULL;
    BIGNUM *zero = NULL;
    int n = 0;
    int i = recid / 2;

    const EC_GROUP *group = EC_KEY_get0_group(eckey);
    if ((ctx = BN_CTX_new()) == NULL) { ret = -1; goto err; }
    BN_CTX_start(ctx);
    order = BN_CTX_get(ctx);
    if (!EC_GROUP_get_order(group, order, ctx)) { ret = -2; goto err; }
    x = BN_CTX_get(ctx);
    if (!BN_copy(x, order)) { ret=-1; goto err; }
    if (!BN_mul_word(x, i)) { ret=-1; goto err; }
    if (!BN_add(x, x, ecsig->r)) { ret=-1; goto err; }
    field = BN_CTX_get(ctx);
    if (!EC_GROUP_get_curve_GFp(group, field, NULL, NULL, ctx)) { ret=-2; goto err; }
    if (BN_cmp(x, field) >= 0) { ret=0; goto err; }
    if ((R = EC_POINT_new(group)) == NULL) { ret = -2; goto err; }
    if (!EC_POINT_set_compressed_coordinates_GFp(group, R, x, recid % 2, ctx)) { ret=0; goto err; }
    if (check)
    {
        if ((O = EC_POINT_new(group)) == NULL) { ret = -2; goto err; }
        if (!EC_POINT_mul(group, O, NULL, R, order, ctx)) { ret=-2; goto err; }
        if (!EC_POINT_is_at_infinity(group, O)) { ret = 0; goto err; }
    }
    if ((Q = EC_POINT_new(group)) == NULL) { ret = -2; goto err; }
    n = EC_GROUP_get_degree(group);
    e = BN_CTX_get(ctx);
    if (!BN_bin2bn(msg, msglen, e)) { ret=-1; goto err; }
    if (8*msglen > n) BN_rshift(e, e, 8-(n & 7));
    zero = BN_CTX_get(ctx);
    if (!BN_zero(zero)) { ret=-1; goto err; }
    if (!BN_mod_sub(e, zero, e, order, ctx)) { ret=-1; goto err; }
    rr = BN_CTX_get(ctx);
    if (!BN_mod_inverse(rr, ecsig->r, order, ctx)) { ret=-1; goto err; }
    sor = BN_CTX_get(ctx);
    if (!BN_mod_mul(sor, ecsig->s, rr, order, ctx)) { ret=-1; goto err; }
    eor = BN_CTX_get(ctx);
    if (!BN_mod_mul(eor, e, rr, order, ctx)) { ret=-1; goto err; }
    if (!EC_POINT_mul(group, Q, eor, R, sor, ctx)) { ret=-2; goto err; }
    if (!EC_KEY_set_public_key(eckey, Q)) { ret=-2; goto err; }

    ret = 1;

err:
    if (ctx) {
        BN_CTX_end(ctx);
        BN_CTX_free(ctx);
    }
    if (R != NULL) EC_POINT_free(R);
    if (O != NULL) EC_POINT_free(O);
    if (Q != NULL) EC_POINT_free(Q);
    return ret;
}

void CKey::SetCompressedPubKey()
{
    EC_KEY_set_conv_form(pkey, POINT_CONVERSION_COMPRESSED);
    fCompressedPubKey = true;
}

void CKey::Reset()
{
    fCompressedPubKey = false;
    pkey = EC_KEY_new_by_curve_name(NID_secp256k1);
    if (pkey == NULL)
        throw key_error("CKey::CKey() : EC_KEY_new_by_curve_name failed");
    fSet = false;
}

CKey::CKey()
{
    Reset();
}

CKey::CKey(const CKey& b)
{
    pkey = EC_KEY_dup(b.pkey);
    if (pkey == NULL)
        throw key_error("CKey::CKey(const CKey&) : EC_KEY_dup failed");
    fSet = b.fSet;
}

CKey& CKey::operator=(const CKey& b)
{
    if (!EC_KEY_copy(pkey, b.pkey))
        throw key_error("CKey::operator=(const CKey&) : EC_KEY_copy failed");
    fSet = b.fSet;
    return (*this);
}

CKey::~CKey()
{
    EC_KEY_free(pkey);
}

bool CKey::IsNull() const
{
    return !fSet;
}

bool CKey::IsCompressed() const
{
    return fCompressedPubKey;
}

void CKey::MakeNewKey(bool fCompressed)
{
    if (!EC_KEY_generate_key(pkey))
        throw key_error("CKey::MakeNewKey() : EC_KEY_generate_key failed");
    if (fCompressed)
        SetCompressedPubKey();
    fSet = true;
}

bool CKey::SetPrivKey(const CPrivKey& vchPrivKey)
{
    const unsigned char* pbegin = &vchPrivKey[0];
    if (!d2i_ECPrivateKey(&pkey, &pbegin, vchPrivKey.size()))
        return false;
    fSet = true;
    return true;
}

bool CKey::SetSecret(const CSecret& vchSecret, bool fCompressed)
{
    EC_KEY_free(pkey);
    pkey = EC_KEY_new_by_curve_name(NID_secp256k1);
    if (pkey == NULL)
        throw key_error("CKey::SetSecret() : EC_KEY_new_by_curve_name failed");
    if (vchSecret.size() != 32)
        throw key_error("CKey::SetSecret() : secret must be 32 bytes");
    BIGNUM *bn = BN_bin2bn(&vchSecret[0],32,BN_new());
    if (bn == NULL)
        throw key_error("CKey::SetSecret() : BN_bin2bn failed");
    if (!EC_KEY_regenerate_key(pkey,bn))
    {
        BN_clear_free(bn);
        throw key_error("CKey::SetSecret() : EC_KEY_regenerate_key failed");
    }
    BN_clear_free(bn);
    fSet = true;
    if (fCompressed || fCompressedPubKey)
        SetCompressedPubKey();
    return true;
}

CSecret CKey::GetSecret(bool &fCompressed) const
{
    CSecret vchRet;
    vchRet.resize(32);
    const BIGNUM *bn = EC_KEY_get0_private_key(pkey);
    int nBytes = BN_num_bytes(bn);
    if (bn == NULL)
        throw key_error("CKey::GetSecret() : EC_KEY_get0_private_key failed");
    int n=BN_bn2bin(bn,&vchRet[32 - nBytes]);
    if (n != nBytes)
        throw key_error("CKey::GetSecret(): BN_bn2bin failed");
    fCompressed = fCompressedPubKey;
    return vchRet;
}

CPrivKey CKey::GetPrivKey() const
{
    int nSize = i2d_ECPrivateKey(pkey, NULL);
    if (!nSize)
        throw key_error("CKey::GetPrivKey() : i2d_ECPrivateKey failed");
    CPrivKey vchPrivKey(nSize, 0);
    unsigned char* pbegin = &vchPrivKey[0];
    if (i2d_ECPrivateKey(pkey, &pbegin) != nSize)
        throw key_error("CKey::GetPrivKey() : i2d_ECPrivateKey returned unexpected size");
    return vchPrivKey;
}

bool CKey::SetPubKey(const std::vector<unsigned char>& vchPubKey)
{
    const unsigned char* pbegin = &vchPubKey[0];
    if (!o2i_ECPublicKey(&pkey, &pbegin, vchPubKey.size()))
        return false;
    fSet = true;
    if (vchPubKey.size() == 33)
        SetCompressedPubKey();
    return true;
}

std::vector<unsigned char> CKey::GetPubKey() const
{
    int nSize = i2o_ECPublicKey(pkey, NULL);
    if (!nSize)
        throw key_error("CKey::GetPubKey() : i2o_ECPublicKey failed");
    std::vector<unsigned char> vchPubKey(nSize, 0);
    unsigned char* pbegin = &vchPubKey[0];
    if (i2o_ECPublicKey(pkey, &pbegin) != nSize)
        throw key_error("CKey::GetPubKey() : i2o_ECPublicKey returned unexpected size");
    return vchPubKey;
}

bool CKey::Sign(uint256 hash, std::vector<unsigned char>& vchSig)
{
    unsigned int nSize = ECDSA_size(pkey);
    vchSig.resize(nSize); // Make sure it is big enough
    if (!ECDSA_sign(0, (unsigned char*)&hash, sizeof(hash), &vchSig[0], &nSize, pkey))
    {
        vchSig.clear();
        return false;
    }
    vchSig.resize(nSize); // Shrink to fit actual size
    return true;
}

// create a compact signature (65 bytes), which allows reconstructing the used public key
// The format is one header byte, followed by two times 32 bytes for the serialized r and s values.
// The header byte: 0x1B = first key with even y, 0x1C = first key with odd y,
//                  0x1D = second key with even y, 0x1E = second key with odd y
bool CKey::SignCompact(uint256 hash, std::vector<unsigned char>& vchSig)
{
    bool fOk = false;
    ECDSA_SIG *sig = ECDSA_do_sign((unsigned char*)&hash, sizeof(hash), pkey);
    if (sig==NULL)
        return false;
    vchSig.clear();
    vchSig.resize(65,0);
    int nBitsR = BN_num_bits(sig->r);
    int nBitsS = BN_num_bits(sig->s);
    if (nBitsR <= 256 && nBitsS <= 256)
    {
        int nRecId = -1;
        for (int i=0; i<4; i++)
        {
            CKey keyRec;
            keyRec.fSet = true;
            if (fCompressedPubKey)
                keyRec.SetCompressedPubKey();
            if (ECDSA_SIG_recover_key_GFp(keyRec.pkey, sig, (unsigned char*)&hash, sizeof(hash), i, 1) == 1)
                if (keyRec.GetPubKey() == this->GetPubKey())
                {
                    nRecId = i;
                    break;
                }
        }

        if (nRecId == -1)
            throw key_error("CKey::SignCompact() : unable to construct recoverable key");

        vchSig[0] = nRecId+27+(fCompressedPubKey ? 4 : 0);
        BN_bn2bin(sig->r,&vchSig[33-(nBitsR+7)/8]);
        BN_bn2bin(sig->s,&vchSig[65-(nBitsS+7)/8]);
        fOk = true;
    }
    ECDSA_SIG_free(sig);
    return fOk;
}

// reconstruct public key from a compact signature
// This is only slightly more CPU intensive than just verifying it.
// If this function succeeds, the recovered public key is guaranteed to be valid
// (the signature is a valid signature of the given data for that key)
bool CKey::SetCompactSignature(uint256 hash, const std::vector<unsigned char>& vchSig)
{
    if (vchSig.size() != 65)
        return false;
    int nV = vchSig[0];
    if (nV<27 || nV>=35)
        return false;
    ECDSA_SIG *sig = ECDSA_SIG_new();
    BN_bin2bn(&vchSig[1],32,sig->r);
    BN_bin2bn(&vchSig[33],32,sig->s);

    EC_KEY_free(pkey);
    pkey = EC_KEY_new_by_curve_name(NID_secp256k1);
    if (nV >= 31)
    {
        SetCompressedPubKey();
        nV -= 4;
    }
    if (ECDSA_SIG_recover_key_GFp(pkey, sig, (unsigned char*)&hash, sizeof(hash), nV - 27, 0) == 1)
    {
        fSet = true;
        ECDSA_SIG_free(sig);
        return true;
    }
    return false;
}

bool CKey::Verify(uint256 hash, const std::vector<unsigned char>& vchSig)
{
    // -1 = error, 0 = bad sig, 1 = good
    if (ECDSA_verify(0, (unsigned char*)&hash, sizeof(hash), &vchSig[0], vchSig.size(), pkey) != 1)
        return false;

    return true;
}

bool CKey::VerifyCompact(uint256 hash, const std::vector<unsigned char>& vchSig)
{
    CKey key;
    if (!key.SetCompactSignature(hash, vchSig))
        return false;
    if (GetPubKey() != key.GetPubKey())
        return false;

    return true;
}

bool CKey::IsValid()
{
    if (!fSet)
        return false;

    bool fCompr;
    CSecret secret = GetSecret(fCompr);
    CKey key2;
    key2.SetSecret(secret, fCompr);
    return GetPubKey() == key2.GetPubKey();
}
<commit_msg>Fix memory leaks<commit_after>// Copyright (c) 2009-2012 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include <map>

#include <openssl/ecdsa.h>
#include <openssl/obj_mac.h>

#include "key.h"
#include "util.h"

// Generate a private key from just the secret parameter
int EC_KEY_regenerate_key(EC_KEY *eckey, BIGNUM *priv_key)
{
    int ok = 0;
    BN_CTX *ctx = NULL;
    EC_POINT *pub_key = NULL;

    if (!eckey) return 0;

    const EC_GROUP *group = EC_KEY_get0_group(eckey);

    if ((ctx = BN_CTX_new()) == NULL)
        goto err;

    pub_key = EC_POINT_new(group);

    if (pub_key == NULL)
        goto err;

    if (!EC_POINT_mul(group, pub_key, priv_key, NULL, NULL, ctx))
        goto err;

    EC_KEY_set_private_key(eckey,priv_key);
    EC_KEY_set_public_key(eckey,pub_key);

    ok = 1;

err:

    if (pub_key)
        EC_POINT_free(pub_key);
    if (ctx != NULL)
        BN_CTX_free(ctx);

    return(ok);
}

// Perform ECDSA key recovery (see SEC1 4.1.6) for curves over (mod p)-fields
// recid selects which key is recovered
// if check is nonzero, additional checks are performed
int ECDSA_SIG_recover_key_GFp(EC_KEY *eckey, ECDSA_SIG *ecsig, const unsigned char *msg, int msglen, int recid, int check)
{
    if (!eckey) return 0;

    int ret = 0;
    BN_CTX *ctx = NULL;

    BIGNUM *x = NULL;
    BIGNUM *e = NULL;
    BIGNUM *order = NULL;
    BIGNUM *sor = NULL;
    BIGNUM *eor = NULL;
    BIGNUM *field = NULL;
    EC_POINT *R = NULL;
    EC_POINT *O = NULL;
    EC_POINT *Q = NULL;
    BIGNUM *rr = NULL;
    BIGNUM *zero = NULL;
    int n = 0;
    int i = recid / 2;

    const EC_GROUP *group = EC_KEY_get0_group(eckey);
    if ((ctx = BN_CTX_new()) == NULL) { ret = -1; goto err; }
    BN_CTX_start(ctx);
    order = BN_CTX_get(ctx);
    if (!EC_GROUP_get_order(group, order, ctx)) { ret = -2; goto err; }
    x = BN_CTX_get(ctx);
    if (!BN_copy(x, order)) { ret=-1; goto err; }
    if (!BN_mul_word(x, i)) { ret=-1; goto err; }
    if (!BN_add(x, x, ecsig->r)) { ret=-1; goto err; }
    field = BN_CTX_get(ctx);
    if (!EC_GROUP_get_curve_GFp(group, field, NULL, NULL, ctx)) { ret=-2; goto err; }
    if (BN_cmp(x, field) >= 0) { ret=0; goto err; }
    if ((R = EC_POINT_new(group)) == NULL) { ret = -2; goto err; }
    if (!EC_POINT_set_compressed_coordinates_GFp(group, R, x, recid % 2, ctx)) { ret=0; goto err; }
    if (check)
    {
        if ((O = EC_POINT_new(group)) == NULL) { ret = -2; goto err; }
        if (!EC_POINT_mul(group, O, NULL, R, order, ctx)) { ret=-2; goto err; }
        if (!EC_POINT_is_at_infinity(group, O)) { ret = 0; goto err; }
    }
    if ((Q = EC_POINT_new(group)) == NULL) { ret = -2; goto err; }
    n = EC_GROUP_get_degree(group);
    e = BN_CTX_get(ctx);
    if (!BN_bin2bn(msg, msglen, e)) { ret=-1; goto err; }
    if (8*msglen > n) BN_rshift(e, e, 8-(n & 7));
    zero = BN_CTX_get(ctx);
    if (!BN_zero(zero)) { ret=-1; goto err; }
    if (!BN_mod_sub(e, zero, e, order, ctx)) { ret=-1; goto err; }
    rr = BN_CTX_get(ctx);
    if (!BN_mod_inverse(rr, ecsig->r, order, ctx)) { ret=-1; goto err; }
    sor = BN_CTX_get(ctx);
    if (!BN_mod_mul(sor, ecsig->s, rr, order, ctx)) { ret=-1; goto err; }
    eor = BN_CTX_get(ctx);
    if (!BN_mod_mul(eor, e, rr, order, ctx)) { ret=-1; goto err; }
    if (!EC_POINT_mul(group, Q, eor, R, sor, ctx)) { ret=-2; goto err; }
    if (!EC_KEY_set_public_key(eckey, Q)) { ret=-2; goto err; }

    ret = 1;

err:
    if (ctx) {
        BN_CTX_end(ctx);
        BN_CTX_free(ctx);
    }
    if (R != NULL) EC_POINT_free(R);
    if (O != NULL) EC_POINT_free(O);
    if (Q != NULL) EC_POINT_free(Q);
    return ret;
}

void CKey::SetCompressedPubKey()
{
    EC_KEY_set_conv_form(pkey, POINT_CONVERSION_COMPRESSED);
    fCompressedPubKey = true;
}

void CKey::Reset()
{
    fCompressedPubKey = false;
    pkey = EC_KEY_new_by_curve_name(NID_secp256k1);
    if (pkey == NULL)
        throw key_error("CKey::CKey() : EC_KEY_new_by_curve_name failed");
    fSet = false;
}

CKey::CKey()
{
    Reset();
}

CKey::CKey(const CKey& b)
{
    pkey = EC_KEY_dup(b.pkey);
    if (pkey == NULL)
        throw key_error("CKey::CKey(const CKey&) : EC_KEY_dup failed");
    fSet = b.fSet;
}

CKey& CKey::operator=(const CKey& b)
{
    if (!EC_KEY_copy(pkey, b.pkey))
        throw key_error("CKey::operator=(const CKey&) : EC_KEY_copy failed");
    fSet = b.fSet;
    return (*this);
}

CKey::~CKey()
{
    EC_KEY_free(pkey);
}

bool CKey::IsNull() const
{
    return !fSet;
}

bool CKey::IsCompressed() const
{
    return fCompressedPubKey;
}

void CKey::MakeNewKey(bool fCompressed)
{
    if (!EC_KEY_generate_key(pkey))
        throw key_error("CKey::MakeNewKey() : EC_KEY_generate_key failed");
    if (fCompressed)
        SetCompressedPubKey();
    fSet = true;
}

bool CKey::SetPrivKey(const CPrivKey& vchPrivKey)
{
    const unsigned char* pbegin = &vchPrivKey[0];
    if (!d2i_ECPrivateKey(&pkey, &pbegin, vchPrivKey.size()))
        return false;
    fSet = true;
    return true;
}

bool CKey::SetSecret(const CSecret& vchSecret, bool fCompressed)
{
    EC_KEY_free(pkey);
    pkey = EC_KEY_new_by_curve_name(NID_secp256k1);
    if (pkey == NULL)
        throw key_error("CKey::SetSecret() : EC_KEY_new_by_curve_name failed");
    if (vchSecret.size() != 32)
        throw key_error("CKey::SetSecret() : secret must be 32 bytes");
    BIGNUM *bn = BN_bin2bn(&vchSecret[0],32,BN_new());
    if (bn == NULL)
        throw key_error("CKey::SetSecret() : BN_bin2bn failed");
    if (!EC_KEY_regenerate_key(pkey,bn))
    {
        BN_clear_free(bn);
        throw key_error("CKey::SetSecret() : EC_KEY_regenerate_key failed");
    }
    BN_clear_free(bn);
    fSet = true;
    if (fCompressed || fCompressedPubKey)
        SetCompressedPubKey();
    return true;
}

CSecret CKey::GetSecret(bool &fCompressed) const
{
    CSecret vchRet;
    vchRet.resize(32);
    const BIGNUM *bn = EC_KEY_get0_private_key(pkey);
    int nBytes = BN_num_bytes(bn);
    if (bn == NULL)
        throw key_error("CKey::GetSecret() : EC_KEY_get0_private_key failed");
    int n=BN_bn2bin(bn,&vchRet[32 - nBytes]);
    if (n != nBytes)
        throw key_error("CKey::GetSecret(): BN_bn2bin failed");
    fCompressed = fCompressedPubKey;
    return vchRet;
}

CPrivKey CKey::GetPrivKey() const
{
    int nSize = i2d_ECPrivateKey(pkey, NULL);
    if (!nSize)
        throw key_error("CKey::GetPrivKey() : i2d_ECPrivateKey failed");
    CPrivKey vchPrivKey(nSize, 0);
    unsigned char* pbegin = &vchPrivKey[0];
    if (i2d_ECPrivateKey(pkey, &pbegin) != nSize)
        throw key_error("CKey::GetPrivKey() : i2d_ECPrivateKey returned unexpected size");
    return vchPrivKey;
}

bool CKey::SetPubKey(const std::vector<unsigned char>& vchPubKey)
{
    const unsigned char* pbegin = &vchPubKey[0];
    if (!o2i_ECPublicKey(&pkey, &pbegin, vchPubKey.size()))
        return false;
    fSet = true;
    if (vchPubKey.size() == 33)
        SetCompressedPubKey();
    return true;
}

std::vector<unsigned char> CKey::GetPubKey() const
{
    int nSize = i2o_ECPublicKey(pkey, NULL);
    if (!nSize)
        throw key_error("CKey::GetPubKey() : i2o_ECPublicKey failed");
    std::vector<unsigned char> vchPubKey(nSize, 0);
    unsigned char* pbegin = &vchPubKey[0];
    if (i2o_ECPublicKey(pkey, &pbegin) != nSize)
        throw key_error("CKey::GetPubKey() : i2o_ECPublicKey returned unexpected size");
    return vchPubKey;
}

bool CKey::Sign(uint256 hash, std::vector<unsigned char>& vchSig)
{
    unsigned int nSize = ECDSA_size(pkey);
    vchSig.resize(nSize); // Make sure it is big enough
    if (!ECDSA_sign(0, (unsigned char*)&hash, sizeof(hash), &vchSig[0], &nSize, pkey))
    {
        vchSig.clear();
        return false;
    }
    vchSig.resize(nSize); // Shrink to fit actual size
    return true;
}

// create a compact signature (65 bytes), which allows reconstructing the used public key
// The format is one header byte, followed by two times 32 bytes for the serialized r and s values.
// The header byte: 0x1B = first key with even y, 0x1C = first key with odd y,
//                  0x1D = second key with even y, 0x1E = second key with odd y
bool CKey::SignCompact(uint256 hash, std::vector<unsigned char>& vchSig)
{
    bool fOk = false;
    ECDSA_SIG *sig = ECDSA_do_sign((unsigned char*)&hash, sizeof(hash), pkey);
    if (sig==NULL)
        return false;
    vchSig.clear();
    vchSig.resize(65,0);
    int nBitsR = BN_num_bits(sig->r);
    int nBitsS = BN_num_bits(sig->s);
    if (nBitsR <= 256 && nBitsS <= 256)
    {
        int nRecId = -1;
        for (int i=0; i<4; i++)
        {
            CKey keyRec;
            keyRec.fSet = true;
            if (fCompressedPubKey)
                keyRec.SetCompressedPubKey();
            if (ECDSA_SIG_recover_key_GFp(keyRec.pkey, sig, (unsigned char*)&hash, sizeof(hash), i, 1) == 1)
                if (keyRec.GetPubKey() == this->GetPubKey())
                {
                    nRecId = i;
                    break;
                }
        }

        if (nRecId == -1)
        {
            ECDSA_SIG_free(sig);
            throw key_error("CKey::SignCompact() : unable to construct recoverable key");
        }

        vchSig[0] = nRecId+27+(fCompressedPubKey ? 4 : 0);
        BN_bn2bin(sig->r,&vchSig[33-(nBitsR+7)/8]);
        BN_bn2bin(sig->s,&vchSig[65-(nBitsS+7)/8]);
        fOk = true;
    }
    ECDSA_SIG_free(sig);
    return fOk;
}

// reconstruct public key from a compact signature
// This is only slightly more CPU intensive than just verifying it.
// If this function succeeds, the recovered public key is guaranteed to be valid
// (the signature is a valid signature of the given data for that key)
bool CKey::SetCompactSignature(uint256 hash, const std::vector<unsigned char>& vchSig)
{
    if (vchSig.size() != 65)
        return false;
    int nV = vchSig[0];
    if (nV<27 || nV>=35)
        return false;
    ECDSA_SIG *sig = ECDSA_SIG_new();
    BN_bin2bn(&vchSig[1],32,sig->r);
    BN_bin2bn(&vchSig[33],32,sig->s);

    EC_KEY_free(pkey);
    pkey = EC_KEY_new_by_curve_name(NID_secp256k1);
    if (nV >= 31)
    {
        SetCompressedPubKey();
        nV -= 4;
    }
    if (ECDSA_SIG_recover_key_GFp(pkey, sig, (unsigned char*)&hash, sizeof(hash), nV - 27, 0) == 1)
    {
        fSet = true;
        ECDSA_SIG_free(sig);
        return true;
    }
    ECDSA_SIG_free(sig);
    return false;
}

bool CKey::Verify(uint256 hash, const std::vector<unsigned char>& vchSig)
{
    // -1 = error, 0 = bad sig, 1 = good
    if (ECDSA_verify(0, (unsigned char*)&hash, sizeof(hash), &vchSig[0], vchSig.size(), pkey) != 1)
        return false;

    return true;
}

bool CKey::VerifyCompact(uint256 hash, const std::vector<unsigned char>& vchSig)
{
    CKey key;
    if (!key.SetCompactSignature(hash, vchSig))
        return false;
    if (GetPubKey() != key.GetPubKey())
        return false;

    return true;
}

bool CKey::IsValid()
{
    if (!fSet)
        return false;

    bool fCompr;
    CSecret secret = GetSecret(fCompr);
    CKey key2;
    key2.SetSecret(secret, fCompr);
    return GetPubKey() == key2.GetPubKey();
}
<|endoftext|>


<commit_before>/*
 * fMBT, free Model Based Testing tool
 * Copyright (c) 2011, Intel Corporation.
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms and conditions of the GNU Lesser General Public License,
 * version 2.1, as published by the Free Software Foundation.
 *
 * This program is distributed in the hope 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 program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
 *
 */

#include "dparse.h"
#include "helper.hh"
#include <getopt.h>
#include <glib.h>
#include <errno.h>

extern "C" {
extern D_ParserTables parser_tables_lang;
};

void print_usage()
{
  std::printf(
    "Usage: lang [options] inputfile\n"
    "Options:\n"
    "    -h     print usage\n"
    "    -o     output to a file (defaults to stdout)\n"
    "    -c     compile (needs to have output file)\n"
    );
}

extern std::string result;

std::string compile_command("g++ -fPIC -shared -x c++  - -I /usr/include/fmbt -o ");

int main(int argc,char** argv) {
  int c;
  bool lib=false;
  FILE* outputfile=stdout;
  static struct option long_opts[] = {
    {"help", no_argument, 0, 'h'},
    {0, 0, 0, 0}
  };

  while ((c = getopt_long (argc, argv, "b:hco:", long_opts, NULL)) != -1) {
    switch (c)
      {
      case 'b':
	compile_command=optarg;
	compile_command+=" ";
	break;
      case 'c':
	lib=true;
	break;
      case 'o':
	outputfile=fopen(optarg,"w");
	compile_command=compile_command+optarg;
	if (!outputfile) {
	  std::printf("Can't open output file \"%s\"\n",optarg);
	  return 1;
	}
	break;
      case 'h':
	print_usage();
	return 0;
      default:
	return 2;
      }
  }

  if (optind == argc || (lib && outputfile==stdout)) {
    print_usage();
    return -1;
  }

  char *s;
  D_Parser *p = new_D_Parser(&parser_tables_lang, 512);

  s=readfile(argv[optind]);
  if (!s) {
    std::printf("Can't read input file \"%s\"\n",argv[optind]);
    return 3;
  }
  dparse(p,s,std::strlen(s));
  if (lib) {
    int _stdin; //,_stdout,_stder;
    GPid pid;
    int argc;
    gchar **argv=(gchar**)malloc(42*sizeof(gchar*));
    GError *gerr=NULL;

    g_shell_parse_argv(compile_command.c_str(),
		       &argc,&argv,&gerr);

    g_spawn_async_with_pipes(NULL,argv,NULL,G_SPAWN_SEARCH_PATH,NULL,&pid,NULL,&_stdin,NULL,NULL,&gerr);

    unsigned int pos=0;
    unsigned int wrote=0;
    do {
      wrote=TEMP_FAILURE_RETRY(write(_stdin,result.c_str()+pos,result.length()-pos));
      pos+=wrote;
    } while (wrote>0 && pos<result.length());
  } else {
    fprintf(outputfile,"%s",result.c_str());
  }

  free_D_Parser(p);
  free(s);
  return 0;
}
<commit_msg>use non-C-preprocessed input when reading THE lang input files<commit_after>/*
 * fMBT, free Model Based Testing tool
 * Copyright (c) 2011, Intel Corporation.
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms and conditions of the GNU Lesser General Public License,
 * version 2.1, as published by the Free Software Foundation.
 *
 * This program is distributed in the hope 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 program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
 *
 */

#include "dparse.h"
#include "helper.hh"
#include <getopt.h>
#include <glib.h>
#include <errno.h>

extern "C" {
extern D_ParserTables parser_tables_lang;
};

void print_usage()
{
  std::printf(
    "Usage: lang [options] inputfile\n"
    "Options:\n"
    "    -h     print usage\n"
    "    -o     output to a file (defaults to stdout)\n"
    "    -c     compile (needs to have output file)\n"
    );
}

extern std::string result;

std::string compile_command("g++ -fPIC -shared -x c++  - -I /usr/include/fmbt -o ");

int main(int argc,char** argv) {
  int c;
  bool lib=false;
  FILE* outputfile=stdout;
  static struct option long_opts[] = {
    {"help", no_argument, 0, 'h'},
    {0, 0, 0, 0}
  };

  while ((c = getopt_long (argc, argv, "b:hco:", long_opts, NULL)) != -1) {
    switch (c)
      {
      case 'b':
	compile_command=optarg;
	compile_command+=" ";
	break;
      case 'c':
	lib=true;
	break;
      case 'o':
	outputfile=fopen(optarg,"w");
	compile_command=compile_command+optarg;
	if (!outputfile) {
	  std::printf("Can't open output file \"%s\"\n",optarg);
	  return 1;
	}
	break;
      case 'h':
	print_usage();
	return 0;
      default:
	return 2;
      }
  }

  if (optind == argc || (lib && outputfile==stdout)) {
    print_usage();
    return -1;
  }

  char *s;
  D_Parser *p = new_D_Parser(&parser_tables_lang, 512);

  s=readfile(argv[optind],false);
  if (!s) {
    std::printf("Can't read input file \"%s\"\n",argv[optind]);
    return 3;
  }
  dparse(p,s,std::strlen(s));
  if (lib) {
    int _stdin; //,_stdout,_stder;
    GPid pid;
    int argc;
    gchar **argv=(gchar**)malloc(42*sizeof(gchar*));
    GError *gerr=NULL;

    g_shell_parse_argv(compile_command.c_str(),
		       &argc,&argv,&gerr);

    g_spawn_async_with_pipes(NULL,argv,NULL,G_SPAWN_SEARCH_PATH,NULL,&pid,NULL,&_stdin,NULL,NULL,&gerr);

    unsigned int pos=0;
    unsigned int wrote=0;
    do {
      wrote=TEMP_FAILURE_RETRY(write(_stdin,result.c_str()+pos,result.length()-pos));
      pos+=wrote;
    } while (wrote>0 && pos<result.length());
  } else {
    fprintf(outputfile,"%s",result.c_str());
  }

  free_D_Parser(p);
  free(s);
  return 0;
}
<|endoftext|>


<commit_before>/*
 * Gradient.cpp
 *
 *  Created on: 25 lug 2017
 *      Author: gianmaria
 */

#include "Gradient.h"

Gradient::Gradient(ImageTensor G)
{
	l = 1;
	N = pow(2, l) + 1;
	Gx = Mat(G.getH(), G.getW(), CV_32F);
	Gy = Mat(G.getH(), G.getW(), CV_32F);

	for(int y = 0; y < G.getH(); y++)
	{
		for(int x = 0; x < G.getW(); x++)
		{
			float Vx = G.getTensor(x, y).getVx();
			float Vy = G.getTensor(x, y).getVy();
			Gx.at<float>(y,x) = Vx * expf(-abs(Vx) / (1 + abs(Vx)));
			Gy.at<float>(y,x) = Vy * expf(-abs(Vy) / (1 + abs(Vy)));
		}
	}
	updateAvg();
}

Gradient::~Gradient()
{
	// TODO Auto-generated destructor stub
}

void Gradient::updateAvg()
{
	Avg = Mat(3,N,CV_32F);
	for(int y = 0; y < 3; y++)
	{
		for(int x = 0; x < N; x++)
		{
			Avg.at<float>(y,x) = (float) 1.0f/(3*N);
		}
	}
}

void Gradient::updateGradient()
{
	Filter fx(Avg);
	Mat V2x = fx.apply(fx.apply(Gx));

	Mat AvgT;
	transpose(Avg, AvgT);
	Filter fy(AvgT);
	Mat V2y = fy.apply(fy.apply(Gy));

	for(int y = 0; y < Gy.rows; y++){
		for(int x = 0; x < Gx.cols; x++){
			float valX = V2x.at<float>(y,x) * (N + 1);
			V2x.at<float>(y,x) = valX;
			float valY = V2y.at<float>(y,x) * (N + 1);
			V2y.at<float>(y,x) = valY;
		}
	}

	for(int y = 0; y < Gy.rows; y++)
	{
		for(int x = 0; x < Gx.cols; x++)
		{
			float _v2x = (float) V2x.at<float>(y,x);
			float _v2y = (float) V2y.at<float>(y,x);
			Gx.at<float>(y,x) = _v2x * expf(-abs(_v2x) / (1 + abs(_v2x)));
			Gy.at<float>(y,x) = _v2y * expf(-abs(_v2y) / (1 + abs(_v2y)));
		}
	}
}

void Gradient::update(){
	do{
		l++;
		N = pow(2,l) + 1;
		this->updateGradient();
		/*Mat GxNorm, GyNorm;
		GxNorm = Mat(Gx.rows, Gx.cols, CV_32FC1);
		GyNorm = Mat(Gy.rows, Gy.cols, CV_32FC1);
		normalize(Gx, GxNorm, 1, 0, NORM_MINMAX);
		normalize(Gy, GyNorm, 1, 0, NORM_MINMAX);
		namedWindow("Gx", WINDOW_AUTOSIZE);
		namedWindow("Gy", WINDOW_AUTOSIZE);
		imshow("Gx", GxNorm);
		imshow("Gy", GyNorm);
		waitKey(0);*/
	} while(N < Gx.cols || N < Gy.rows);

}

void Gradient::generateDivG()
{
	int Imax = Gx.rows + 2;
	int Jmax = Gx.cols + 2;

	divG = Mat::zeros((Imax), (Jmax), CV_32F);

	for(int i = 0; i < Imax; i++)
	{
		for(int j = 0; j < Jmax; j++)
		{
			if((i != 0) && (j != 0) && (i != Imax-1) && (j != Jmax-1))
			{
				divG.at<float>(i-1, j-1) =(float) Gx.at<float>(i-1,j-1) - Gx.at<float>(i-1, j-2)
									  + Gy.at<float>(i-1,j-1) - Gy.at<float>(i-2,j-1);
			}
		}
	}
	int point[2] = {1,1};
	Mat cropG = crop(divG, point, Gx.rows, Gx.cols);
	divG = cropG;

//	namedWindow("divG", WINDOW_AUTOSIZE);
//	Mat divGNorm;
//	normalize(cropG, divGNorm, 1, 0, NORM_MINMAX);
//	imshow("divG", divGNorm);
//	waitKey(0);
}

void Gradient::poissonSolver()
{
	/*
	 * (1) Compute Bbar = inv(Q)*B*Q
  	   (2) For each j,k compute
         	 Ubar(j,k) = Bbar(j,k)/(Lambda(j,j)+Lambda(k,k))
  	   (3) Compute U = Q*Ubar*inv(Q)
	 */

	generateDivG();

	normalize(divG, divG, 0, 1, CV_MINMAX);

	/*
	 *  % Solve the discrete Poisson equation
		% on an n-by-n grid with right hand side b
		function X=Poisson_FFT(B)
		[n,m]=size(b);
		% Form eigenvalues of matrix T(nxn)
		L=2*(1-cos((1:n)*pi/(n+1)));
		% Form reciprocal sums of eigenvalues
		% Include scale factor 2/(n+1)
		LL=(2/(n+1))*ones(n,n)./(L'*ones(1,n)+ones(n,1)*L);
		% Solve, using the Fast Sine Transform
		X = fast_sine_transform(b');
		X = fast_sine_transform(X');
		X = LL.*X;
		X = fast_sine_transform(X');
		X = fast_sine_transform(X');
	 */

	int n = divG.rows;
	int m = divG.cols;

	Mat L(1, n, CV_32F);
	for(int i = 0; i < n; i++)
		L.at<float>(0,i) =(float) 2*(1-cos(i*M_PI/(n+1)));

	Mat LL = Mat::ones(n,n, CV_32F);
	for(int i = 0; i < n; i++)
	{
		for(int j = 0; j < n; j++)
		{
			LL.at<float>(i,j) =(float) (2.0f/(n+1)) /(L.at<float>(0,i) + L.at<float>(0,j));
		}
	}

	Mat divGT = divG.t();

	Mat X = fastSineTransform(divGT);
	Mat X2 = X.t();
	X = fastSineTransform(X2);

	for(int i = 0; i < n; i++)
	{
		for(int j = 0; j < n; j++)
		{
			X.at<float>(i,j) *= LL.at<float>(i,j);
		}
	}

	X2 = X.t();
	X = fastSineTransform(X2);
	X2 = X.t();
	X = fastSineTransform(X2);

	cout << X << endl;

	normalize(X, X, 0, 1, CV_MINMAX);
	namedWindow("image", WINDOW_AUTOSIZE);
	imshow("image", X );
	waitKey(0);

//	Mat padded;                            //expand input image to optimal size
//	int m = getOptimalDFTSize(divG.rows);
//	int n = getOptimalDFTSize(divG.cols); // on the border add zero values
//	copyMakeBorder(divG, padded, 0, m - divG.rows, 0, n - divG.cols, BORDER_CONSTANT, Scalar::all(0));
//	Mat planes[] = {Mat_<float>(padded), Mat::zeros(padded.size(), CV_32F)};
//	Mat complexI;
//	merge(planes, 2, complexI);         // Add to the expanded another plane with zeros
//
//	dft(complexI, complexI, DFT_COMPLEX_OUTPUT);            // this way the result may fit in the source matrix
//
//	split(complexI, planes);                   // planes[0] = Re(DFT(I), planes[1] = Im(DFT(I))
//	magnitude(planes[0], planes[1], planes[0]);// planes[0] = magnitude
//	Mat magI = planes[0];

//	magI += Scalar::all(1);                    // switch to logarithmic scale
//	log(magI, magI);

//	// crop the spectrum, if it has an odd number of rows or columns
//	magI = magI(Rect(0, 0, magI.cols & -2, magI.rows & -2));
//
//	// rearrange the quadrants of Fourier image  so that the origin is at the image center
//	int cx = magI.cols/2;
//	int cy = magI.rows/2;
//
//	Mat q0(magI, Rect(0, 0, cx, cy));   // Top-Left - Create a ROI per quadrant
//	Mat q1(magI, Rect(cx, 0, cx, cy));  // Top-Right
//	Mat q2(magI, Rect(0, cy, cx, cy));  // Bottom-Left
//	Mat q3(magI, Rect(cx, cy, cx, cy)); // Bottom-Right
//
//	Mat tmp;                           // swap quadrants (Top-Left with Bottom-Right)
//	q0.copyTo(tmp);
//	q3.copyTo(q0);
//	tmp.copyTo(q3);
//
//	q1.copyTo(tmp);                    // swap quadrant (Top-Right with Bottom-Left)
//	q2.copyTo(q1);
//	tmp.copyTo(q2);

//	normalize(magI, magI, 0, 1, CV_MINMAX); // Transform the matrix with float values into a
//											// viewable image form (float between values 0 and 1).
//
//	normalize(divG, divG, 0, 1, NORM_MINMAX);
//	namedWindow("Input Image", WINDOW_KEEPRATIO);
//	namedWindow("spectrum magnitude", WINDOW_KEEPRATIO);
//	imshow("Input Image"       , divG  );    // Show the result
//	imshow("spectrum magnitude", magI);
//	waitKey();
}

Mat Gradient::fastSineTransform(Mat v)
{
	/*% Fast Sine Transform on input matrix V
      % of dimension n-by-m
      function Y=fast_sine_transform(V)
      [n,m]=size(V);
      V1=[zeros(1,m);V;zeros(n+1,m)];
      V2=imag(fft(V1));
      % In Matlab vectors and matrices are indexed
      % starting at 1, not 0
      Y=V2(2:n+1,:);
	 */

	Mat V1 = Mat::zeros(v.rows+2, v.cols,CV_32F);
	for(int i = 0; i < v.rows; i++)
	{
		for(int j = 0; j < v.cols; j++)
		{
			V1.at<float>(i+1,j) = v.at<float>(i, j);
		}
	}

//	Mat padded;                            //expand input image to optimal size
//	int m = getOptimalDFTSize(V1.rows);
//	int n = getOptimalDFTSize(V1.cols); // on the border add zero values
//	copyMakeBorder(V1, padded, 0, m - V1.rows, 0, n - V1.cols, BORDER_CONSTANT, Scalar::all(0));
	Mat planes[] = {Mat_<float>(V1), Mat::zeros(V1.size(), CV_32F)};
	Mat complexI;
	merge(planes, 2, complexI);         // Add to the expanded another plane with zeros

	dft(complexI, complexI, DFT_COMPLEX_OUTPUT);            // this way the result may fit in the source matrix

	split(complexI, planes);

	Mat V2 = planes[1];
	int point[2] = {1,1};
	Mat res = crop(V2, point, V2.rows, V2.cols);
	normalize(res, res, 0, 1, NORM_MINMAX);
	// cout << res << endl;
	return res;
}
<commit_msg>Problems DFT implementation<commit_after>/*
 * Gradient.cpp
 *
 *  Created on: 25 lug 2017
 *      Author: gianmaria
 */

#include "Gradient.h"

Gradient::Gradient(ImageTensor G)
{
	l = 1;
	N = pow(2, l) + 1;
	Gx = Mat(G.getH(), G.getW(), CV_32F);
	Gy = Mat(G.getH(), G.getW(), CV_32F);

	for(int y = 0; y < G.getH(); y++)
	{
		for(int x = 0; x < G.getW(); x++)
		{
			float Vx = G.getTensor(x, y).getVx();
			float Vy = G.getTensor(x, y).getVy();
			Gx.at<float>(y,x) = Vx * expf(-abs(Vx) / (1 + abs(Vx)));
			Gy.at<float>(y,x) = Vy * expf(-abs(Vy) / (1 + abs(Vy)));
		}
	}
	updateAvg();
}

Gradient::~Gradient()
{
	// TODO Auto-generated destructor stub
}

void Gradient::updateAvg()
{
	Avg = Mat(3,N,CV_32F);
	for(int y = 0; y < 3; y++)
	{
		for(int x = 0; x < N; x++)
		{
			Avg.at<float>(y,x) = (float) 1.0f/(3*N);
		}
	}
}

void Gradient::updateGradient()
{
	Filter fx(Avg);
	Mat V2x = fx.apply(fx.apply(Gx));

	Mat AvgT;
	transpose(Avg, AvgT);
	Filter fy(AvgT);
	Mat V2y = fy.apply(fy.apply(Gy));

	for(int y = 0; y < Gy.rows; y++){
		for(int x = 0; x < Gx.cols; x++){
			float valX = V2x.at<float>(y,x) * (N + 1);
			V2x.at<float>(y,x) = valX;
			float valY = V2y.at<float>(y,x) * (N + 1);
			V2y.at<float>(y,x) = valY;
		}
	}

	for(int y = 0; y < Gy.rows; y++)
	{
		for(int x = 0; x < Gx.cols; x++)
		{
			float _v2x = (float) V2x.at<float>(y,x);
			float _v2y = (float) V2y.at<float>(y,x);
			Gx.at<float>(y,x) = _v2x * expf(-abs(_v2x) / (1 + abs(_v2x)));
			Gy.at<float>(y,x) = _v2y * expf(-abs(_v2y) / (1 + abs(_v2y)));
		}
	}
}

void Gradient::update(){
	do{
		l++;
		N = pow(2,l) + 1;
		this->updateGradient();
		/*Mat GxNorm, GyNorm;
		GxNorm = Mat(Gx.rows, Gx.cols, CV_32FC1);
		GyNorm = Mat(Gy.rows, Gy.cols, CV_32FC1);
		normalize(Gx, GxNorm, 1, 0, NORM_MINMAX);
		normalize(Gy, GyNorm, 1, 0, NORM_MINMAX);
		namedWindow("Gx", WINDOW_AUTOSIZE);
		namedWindow("Gy", WINDOW_AUTOSIZE);
		imshow("Gx", GxNorm);
		imshow("Gy", GyNorm);
		waitKey(0);*/
	} while(N < Gx.cols || N < Gy.rows);

}

void Gradient::generateDivG()
{
//	int Imax = Gx.rows + 2;
//	int Jmax = Gx.cols + 2;

	divG = Mat::zeros(Gx.rows, Gx.cols, CV_32F);

	for(int i = 0; i < divG.rows; i++)
	{
		for(int j = 0; j < divG.cols; j++)
		{
			float a,b,c,d;

			a = (float) Gx.at<float>(i,j);
			c = (float) Gy.at<float>(i,j);

			if( j - 1 >= 0)
				b = Gx.at<float>(i,j-1);
			else
				b = 0.0f;

			if( i - 1 >= 0)
				d = Gy.at<float>(i-1,j);
			else
				d = 0.0f;

			divG.at<float>(i,j) = a - b + c - d;
		}
	}

//	namedWindow("divG", WINDOW_AUTOSIZE);
//	Mat divGNorm;
//	normalize(divG, divGNorm, 1, 0, NORM_MINMAX);
//	imshow("divG", divGNorm);
//	waitKey(0);
}

void Gradient::poissonSolver()
{
	/*
	 * (1) Compute Bbar = inv(Q)*B*Q
  	   (2) For each j,k compute
         	 Ubar(j,k) = Bbar(j,k)/(Lambda(j,j)+Lambda(k,k))
  	   (3) Compute U = Q*Ubar*inv(Q)
	 */

	generateDivG();

	divG.convertTo(divG, CV_64F);

//	normalize(divG, divG, 0, 1, CV_MINMAX);

	/*
	 *  % Solve the discrete Poisson equation
		% on an n-by-n grid with right hand side b
		function X=Poisson_FFT(B)
		[n,m]=size(b);
		% Form eigenvalues of matrix T(nxn)
		L=2*(1-cos((1:n)*pi/(n+1)));
		% Form reciprocal sums of eigenvalues
		% Include scale factor 2/(n+1)
		LL=(2/(n+1))*ones(n,n)./(L'*ones(1,n)+ones(n,1)*L);
		% Solve, using the Fast Sine Transform
		X = fast_sine_transform(b');
		X = fast_sine_transform(X');
		X = LL.*X;
		X = fast_sine_transform(X');
		X = fast_sine_transform(X');
	 */

	int n = divG.rows;
	int m = divG.cols;

	Mat L(1, n, CV_64F);
	for(int i = 0; i < n; i++)
		L.at<double>(0,i) =(double) 2*(1-cos(i*M_PI/(n+1)));

	Mat LL = Mat::ones(n,n, CV_64F);
	for(int i = 0; i < n; i++)
	{
		for(int j = 0; j < n; j++)
		{
			LL.at<double>(i,j) =(double) (2.0f/(n+1)) /(L.at<double>(0,i) + L.at<double>(0,j));
		}
	}

	Mat divGT = divG.t();

	Mat X = fastSineTransform(divGT);
	Mat X2 = X.t();
	X = fastSineTransform(X2);

	for(int i = 0; i < n; i++)
	{
		for(int j = 0; j < n; j++)
		{
			X.at<double>(i,j) *= LL.at<double>(i,j);
		}
	}

//	normalize(X, X, 0, 1, NORM_MINMAX);
	cout <<"prima" << X << endl;
	namedWindow("image prima", WINDOW_AUTOSIZE);
	imshow("image prima", X );
	waitKey(0);
	X2 = X.t();
	X = fastSineTransform(X2);
	X2 = X.t();
	X = fastSineTransform(X2);

	normalize(X, X, 0, 1, NORM_MINMAX);
	cout <<"dopo" << X << endl;
	namedWindow("image", WINDOW_AUTOSIZE);
	imshow("image", X );
	waitKey(0);

//	Mat padded;                            //expand input image to optimal size
//	int m = getOptimalDFTSize(divG.rows);
//	int n = getOptimalDFTSize(divG.cols); // on the border add zero values
//	copyMakeBorder(divG, padded, 0, m - divG.rows, 0, n - divG.cols, BORDER_CONSTANT, Scalar::all(0));
//	Mat planes[] = {Mat_<float>(padded), Mat::zeros(padded.size(), CV_32F)};
//	Mat complexI;
//	merge(planes, 2, complexI);         // Add to the expanded another plane with zeros
//
//	dft(complexI, complexI, DFT_COMPLEX_OUTPUT);            // this way the result may fit in the source matrix
//
//	split(complexI, planes);                   // planes[0] = Re(DFT(I), planes[1] = Im(DFT(I))
//	magnitude(planes[0], planes[1], planes[0]);// planes[0] = magnitude
//	Mat magI = planes[0];

//	magI += Scalar::all(1);                    // switch to logarithmic scale
//	log(magI, magI);

//	// crop the spectrum, if it has an odd number of rows or columns
//	magI = magI(Rect(0, 0, magI.cols & -2, magI.rows & -2));
//
//	// rearrange the quadrants of Fourier image  so that the origin is at the image center
//	int cx = magI.cols/2;
//	int cy = magI.rows/2;
//
//	Mat q0(magI, Rect(0, 0, cx, cy));   // Top-Left - Create a ROI per quadrant
//	Mat q1(magI, Rect(cx, 0, cx, cy));  // Top-Right
//	Mat q2(magI, Rect(0, cy, cx, cy));  // Bottom-Left
//	Mat q3(magI, Rect(cx, cy, cx, cy)); // Bottom-Right
//
//	Mat tmp;                           // swap quadrants (Top-Left with Bottom-Right)
//	q0.copyTo(tmp);
//	q3.copyTo(q0);
//	tmp.copyTo(q3);
//
//	q1.copyTo(tmp);                    // swap quadrant (Top-Right with Bottom-Left)
//	q2.copyTo(q1);
//	tmp.copyTo(q2);

//	normalize(magI, magI, 0, 1, CV_MINMAX); // Transform the matrix with float values into a
//											// viewable image form (float between values 0 and 1).
//
//	normalize(divG, divG, 0, 1, NORM_MINMAX);
//	namedWindow("Input Image", WINDOW_KEEPRATIO);
//	namedWindow("spectrum magnitude", WINDOW_KEEPRATIO);
//	imshow("Input Image"       , divG  );    // Show the result
//	imshow("spectrum magnitude", magI);
//	waitKey();
}

Mat Gradient::fastSineTransform(Mat v)
{
	/*% Fast Sine Transform on input matrix V
      % of dimension n-by-m
      function Y=fast_sine_transform(V)
      [n,m]=size(V);
      V1=[zeros(1,m);V;zeros(n+1,m)];
      V2=imag(fft(V1));
      % In Matlab vectors and matrices are indexed
      % starting at 1, not 0
      Y=V2(2:n+1,:);
	 */

	Mat V1 = Mat::zeros(v.rows+2, v.cols+2,CV_64F);
	for(int i = 0; i < v.rows; i++)
	{
		for(int j = 0; j < v.cols; j++)
		{
			V1.at<double>(i+1,j+1) = v.at<double>(i, j);
		}
	}

//	for(int j = 0; j < V1.cols; j++)
//	{
//		Mat col = V1.col(j);
//		Mat planes[] = {col, Mat::zeros(col.size(), CV_64F)};
//		Mat complexI;
//		merge(planes, 2, complexI);         // Add to the expanded another plane with zeros
//
//		dft(complexI, complexI);            // this way the result may fit in the source matrix
//
//		split(complexI, planes);
//
//		Mat newCol = planes[1];
//
//		for(int i = 0; i < V1.rows; i++)
//			V1.at<double>(i,j) = newCol.at<double>(i,0);
//	}

//	Mat padded;                            //expand input image to optimal size
//	int m = getOptimalDFTSize(v.rows);
//	int n = getOptimalDFTSize(v.cols); // on the border add zero values
//	copyMakeBorder(v, padded, 0, m - v.rows, 0, n - v.cols, BORDER_CONSTANT, Scalar::all(0));
	Mat planes[] = {Mat_<double>(V1), Mat::zeros(V1.size(), CV_64F)};
	Mat complexI;
	merge(planes, 2, complexI);         // Add to the expanded another plane with zeros

	dft(complexI, complexI);            // this way the result may fit in the source matrix

	split(complexI, planes);

	Mat V2 = planes[1];
	int point[2] = {1,1};
	Mat res = crop(V1, point, V1.rows, V1.cols);
//	normalize(res, res, 0, 1, NORM_MINMAX);
	// cout << res << endl;
	return res;
}
<|endoftext|>


<commit_before>#include <stdint.h>

#define RAND16_SEED  1337
uint16_t rand16seed = RAND16_SEED;

// memset8, memcpy8, memmove8:
//  optimized avr replacements for the standard "C" library
//  routines memset, memcpy, and memmove.
//
//  There are two techniques that make these routines
//  faster than the standard avr-libc routines.
//  First, the loops are unrolled 2X, meaning that
//  the average loop overhead is cut in half.
//  And second, the compare-and-branch at the bottom
//  of each loop decrements the low byte of the
//  counter, and if the carry is clear, it branches
//  back up immediately.  Only if the low byte math
//  causes carry do we bother to decrement the high
//  byte and check that result for carry as well.
//  Results for a 100-byte buffer are 20-40% faster
//  than standard avr-libc, at a cost of a few extra
//  bytes of code.

extern "C" {
//__attribute__ ((noinline))
void * memset8 ( void * ptr, int val, uint16_t num )
{
    asm volatile(
                 "  movw r26, %[ptr]        \n\t"
                 "  sbrs %A[num], 0         \n\t"
                 "  rjmp Lseteven_%=           \n\t"
                 "  rjmp Lsetodd_%=            \n\t"
                 "Lsetloop_%=:                 \n\t"
                 "  st X+, %A[val]          \n\t"
                 "Lsetodd_%=:                  \n\t"
                 "  st X+, %A[val]          \n\t"
                 "Lseteven_%=:                 \n\t"
                 "  subi %A[num], 2         \n\t"
                 "  brcc Lsetloop_%=           \n\t"
                 "  sbci %B[num], 0         \n\t"
                 "  brcc Lsetloop_%=           \n\t"
                 : [num] "+r" (num)
                 : [ptr]  "r" (ptr),
                   [val]  "r" (val)
                 : "memory"
                 );
    return ptr;
}

//__attribute__ ((noinline))
void * memcpy8 ( void * dst, void* src, uint16_t num )
{
    asm volatile(
                 "  movw r30, %[src]        \n\t"
                 "  movw r26, %[dst]        \n\t"
                 "  sbrs %A[num], 0         \n\t"
                 "  rjmp Lcpyeven_%=           \n\t"
                 "  rjmp Lcpyodd_%=            \n\t"
                 "Lcpyloop_%=:                 \n\t"
                 "  ld __tmp_reg__, Z+      \n\t"
                 "  st X+, __tmp_reg__      \n\t"
                 "Lcpyodd_%=:                  \n\t"
                 "  ld __tmp_reg__, Z+      \n\t"
                 "  st X+, __tmp_reg__      \n\t"
                 "Lcpyeven_%=:                 \n\t"
                 "  subi %A[num], 2         \n\t"
                 "  brcc Lcpyloop_%=           \n\t"
                 "  sbci %B[num], 0         \n\t"
                 "  brcc Lcpyloop_%=           \n\t"
                 : [num] "+r" (num)
                 : [src] "r" (src),
                   [dst] "r" (dst)
                 : "memory"
                 );
    return dst;
}

//__attribute__ ((noinline))
void * memmove8 ( void * dst, void* src, uint16_t num )
{
    if( src < dst) {
        // if src < dst then we can use the forward-stepping memcpy8
        return memcpy8( dst, src, num);
    } else {
        // if src > dst then we have to step backward:
        dst = (char*)dst + num;
        src = (char*)src + num;
        asm volatile(
                     "  movw r30, %[src]        \n\t"
                     "  movw r26, %[dst]        \n\t"
                     "  sbrs %A[num], 0         \n\t"
                     "  rjmp Lmoveven_%=           \n\t"
                     "  rjmp Lmovodd_%=            \n\t"
                     "Lmovloop_%=:                 \n\t"
                     "  ld __tmp_reg__, -Z      \n\t"
                     "  st -X, __tmp_reg__      \n\t"
                     "Lmovodd_%=:                  \n\t"
                     "  ld __tmp_reg__, -Z      \n\t"
                     "  st -X, __tmp_reg__      \n\t"
                     "Lmoveven_%=:                 \n\t"
                     "  subi %A[num], 2         \n\t"
                     "  brcc Lmovloop_%=           \n\t"
                     "  sbci %B[num], 0         \n\t"
                     "  brcc Lmovloop_%=           \n\t"
                     : [num] "+r" (num)
                     : [src] "r" (src),
                       [dst] "r" (dst)
                     : "memory"
                     );
        return dst;
    }
}

} /* end extern "C" */

#if 0
// TEST / VERIFICATION CODE ONLY BELOW THIS POINT
#include <Arduino.h>
#include "lib8tion.h"

void test1abs( int8_t i)
{
    Serial.print("abs("); Serial.print(i); Serial.print(") = ");
    int8_t j = abs8(i);
    Serial.print(j); Serial.println(" ");
}

void testabs()
{
    delay(5000);
    for( int8_t q = -128; q != 127; q++) {
        test1abs(q);
    }
    for(;;){};
}

void testmul8()
{
    delay(5000);
    byte r, c;

    Serial.println("mul8:");
    for( r = 0; r <= 20; r += 1) {
        Serial.print(r); Serial.print(" : ");
        for( c = 0; c <= 20; c += 1) {
            byte t;
            t = mul8( r, c);
            Serial.print(t); Serial.print(' ');
        }
        Serial.println(' ');
    }
    Serial.println("done.");
    for(;;){};
}

void testscale8()
{
    delay(5000);
    byte r, c;

    Serial.println("scale8:");
    for( r = 0; r <= 240; r += 10) {
        Serial.print(r); Serial.print(" : ");
        for( c = 0; c <= 240; c += 10) {
            byte t;
            t = scale8( r, c);
            Serial.print(t); Serial.print(' ');
        }
        Serial.println(' ');
    }

    Serial.println(' ');
    Serial.println("scale8_video:");

    for( r = 0; r <= 100; r += 4) {
        Serial.print(r); Serial.print(" : ");
        for( c = 0; c <= 100; c += 4) {
            byte t;
            t = scale8_video( r, c);
            Serial.print(t); Serial.print(' ');
        }
        Serial.println(' ');
    }

    Serial.println("done.");
    for(;;){};
}

void testqadd8()
{
    delay(5000);
    byte r, c;
    for( r = 0; r <= 240; r += 10) {
        Serial.print(r); Serial.print(" : ");
        for( c = 0; c <= 240; c += 10) {
            byte t;
            t = qadd8( r, c);
            Serial.print(t); Serial.print(' ');
        }
        Serial.println(' ');
    }
    Serial.println("done.");
    for(;;){};
}

void testnscale8x3()
{
    delay(5000);
    byte r, g, b, sc;
    for( byte z = 0; z < 10; z++) {
        r = random8(); g = random8(); b = random8(); sc = random8();

        Serial.print("nscale8x3_video( ");
        Serial.print(r); Serial.print(", ");
        Serial.print(g); Serial.print(", ");
        Serial.print(b); Serial.print(", ");
        Serial.print(sc); Serial.print(") = [ ");

        nscale8x3_video( r, g, b, sc);

        Serial.print(r); Serial.print(", ");
        Serial.print(g); Serial.print(", ");
        Serial.print(b); Serial.print("]");

        Serial.println(' ');
    }
    Serial.println("done.");
    for(;;){};
}

#endif
<commit_msg>MEK: memmove8, memcpy8, and memset8 ARM handling (e.g., none -- just use libc on ARM)<commit_after>#include <stdint.h>

#define RAND16_SEED  1337
uint16_t rand16seed = RAND16_SEED;

// memset8, memcpy8, memmove8:
//  optimized avr replacements for the standard "C" library
//  routines memset, memcpy, and memmove.
//
//  There are two techniques that make these routines
//  faster than the standard avr-libc routines.
//  First, the loops are unrolled 2X, meaning that
//  the average loop overhead is cut in half.
//  And second, the compare-and-branch at the bottom
//  of each loop decrements the low byte of the
//  counter, and if the carry is clear, it branches
//  back up immediately.  Only if the low byte math
//  causes carry do we bother to decrement the high
//  byte and check that result for carry as well.
//  Results for a 100-byte buffer are 20-40% faster
//  than standard avr-libc, at a cost of a few extra
//  bytes of code.

#if defined(__AVR__)
extern "C" {
//__attribute__ ((noinline))
void * memset8 ( void * ptr, int val, uint16_t num )
{
    asm volatile(
                 "  movw r26, %[ptr]        \n\t"
                 "  sbrs %A[num], 0         \n\t"
                 "  rjmp Lseteven_%=           \n\t"
                 "  rjmp Lsetodd_%=            \n\t"
                 "Lsetloop_%=:                 \n\t"
                 "  st X+, %A[val]          \n\t"
                 "Lsetodd_%=:                  \n\t"
                 "  st X+, %A[val]          \n\t"
                 "Lseteven_%=:                 \n\t"
                 "  subi %A[num], 2         \n\t"
                 "  brcc Lsetloop_%=           \n\t"
                 "  sbci %B[num], 0         \n\t"
                 "  brcc Lsetloop_%=           \n\t"
                 : [num] "+r" (num)
                 : [ptr]  "r" (ptr),
                   [val]  "r" (val)
                 : "memory"
                 );
    return ptr;
}

//__attribute__ ((noinline))
void * memcpy8 ( void * dst, void* src, uint16_t num )
{
    asm volatile(
                 "  movw r30, %[src]        \n\t"
                 "  movw r26, %[dst]        \n\t"
                 "  sbrs %A[num], 0         \n\t"
                 "  rjmp Lcpyeven_%=           \n\t"
                 "  rjmp Lcpyodd_%=            \n\t"
                 "Lcpyloop_%=:                 \n\t"
                 "  ld __tmp_reg__, Z+      \n\t"
                 "  st X+, __tmp_reg__      \n\t"
                 "Lcpyodd_%=:                  \n\t"
                 "  ld __tmp_reg__, Z+      \n\t"
                 "  st X+, __tmp_reg__      \n\t"
                 "Lcpyeven_%=:                 \n\t"
                 "  subi %A[num], 2         \n\t"
                 "  brcc Lcpyloop_%=           \n\t"
                 "  sbci %B[num], 0         \n\t"
                 "  brcc Lcpyloop_%=           \n\t"
                 : [num] "+r" (num)
                 : [src] "r" (src),
                   [dst] "r" (dst)
                 : "memory"
                 );
    return dst;
}

//__attribute__ ((noinline))
void * memmove8 ( void * dst, void* src, uint16_t num )
{
    if( src < dst) {
        // if src < dst then we can use the forward-stepping memcpy8
        return memcpy8( dst, src, num);
    } else {
        // if src > dst then we have to step backward:
        dst = (char*)dst + num;
        src = (char*)src + num;
        asm volatile(
                     "  movw r30, %[src]        \n\t"
                     "  movw r26, %[dst]        \n\t"
                     "  sbrs %A[num], 0         \n\t"
                     "  rjmp Lmoveven_%=           \n\t"
                     "  rjmp Lmovodd_%=            \n\t"
                     "Lmovloop_%=:                 \n\t"
                     "  ld __tmp_reg__, -Z      \n\t"
                     "  st -X, __tmp_reg__      \n\t"
                     "Lmovodd_%=:                  \n\t"
                     "  ld __tmp_reg__, -Z      \n\t"
                     "  st -X, __tmp_reg__      \n\t"
                     "Lmoveven_%=:                 \n\t"
                     "  subi %A[num], 2         \n\t"
                     "  brcc Lmovloop_%=           \n\t"
                     "  sbci %B[num], 0         \n\t"
                     "  brcc Lmovloop_%=           \n\t"
                     : [num] "+r" (num)
                     : [src] "r" (src),
                       [dst] "r" (dst)
                     : "memory"
                     );
        return dst;
    }
}

} /* end extern "C" */

#endif /* AVR */

#if 0
// TEST / VERIFICATION CODE ONLY BELOW THIS POINT
#include <Arduino.h>
#include "lib8tion.h"

void test1abs( int8_t i)
{
    Serial.print("abs("); Serial.print(i); Serial.print(") = ");
    int8_t j = abs8(i);
    Serial.print(j); Serial.println(" ");
}

void testabs()
{
    delay(5000);
    for( int8_t q = -128; q != 127; q++) {
        test1abs(q);
    }
    for(;;){};
}

void testmul8()
{
    delay(5000);
    byte r, c;

    Serial.println("mul8:");
    for( r = 0; r <= 20; r += 1) {
        Serial.print(r); Serial.print(" : ");
        for( c = 0; c <= 20; c += 1) {
            byte t;
            t = mul8( r, c);
            Serial.print(t); Serial.print(' ');
        }
        Serial.println(' ');
    }
    Serial.println("done.");
    for(;;){};
}

void testscale8()
{
    delay(5000);
    byte r, c;

    Serial.println("scale8:");
    for( r = 0; r <= 240; r += 10) {
        Serial.print(r); Serial.print(" : ");
        for( c = 0; c <= 240; c += 10) {
            byte t;
            t = scale8( r, c);
            Serial.print(t); Serial.print(' ');
        }
        Serial.println(' ');
    }

    Serial.println(' ');
    Serial.println("scale8_video:");

    for( r = 0; r <= 100; r += 4) {
        Serial.print(r); Serial.print(" : ");
        for( c = 0; c <= 100; c += 4) {
            byte t;
            t = scale8_video( r, c);
            Serial.print(t); Serial.print(' ');
        }
        Serial.println(' ');
    }

    Serial.println("done.");
    for(;;){};
}

void testqadd8()
{
    delay(5000);
    byte r, c;
    for( r = 0; r <= 240; r += 10) {
        Serial.print(r); Serial.print(" : ");
        for( c = 0; c <= 240; c += 10) {
            byte t;
            t = qadd8( r, c);
            Serial.print(t); Serial.print(' ');
        }
        Serial.println(' ');
    }
    Serial.println("done.");
    for(;;){};
}

void testnscale8x3()
{
    delay(5000);
    byte r, g, b, sc;
    for( byte z = 0; z < 10; z++) {
        r = random8(); g = random8(); b = random8(); sc = random8();

        Serial.print("nscale8x3_video( ");
        Serial.print(r); Serial.print(", ");
        Serial.print(g); Serial.print(", ");
        Serial.print(b); Serial.print(", ");
        Serial.print(sc); Serial.print(") = [ ");

        nscale8x3_video( r, g, b, sc);

        Serial.print(r); Serial.print(", ");
        Serial.print(g); Serial.print(", ");
        Serial.print(b); Serial.print("]");

        Serial.println(' ');
    }
    Serial.println("done.");
    for(;;){};
}

#endif
<|endoftext|>