<commit_before>// Copyright 2008-present Contributors to the OpenImageIO project.
// SPDX-License-Identifier: BSD-3-Clause
// https://github.com/OpenImageIO/oiio

#include <cstdio>

#include <OpenImageIO/filesystem.h>
#include <OpenImageIO/imageio.h>
#include <OpenImageIO/strutil.h>

#include "bmp_pvt.h"

OIIO_PLUGIN_NAMESPACE_BEGIN

using namespace bmp_pvt;

class BmpOutput final : public ImageOutput {
public:
    BmpOutput() { init(); }
    ~BmpOutput() override { close(); }
    const char* format_name(void) const override { return "bmp"; }
    int supports(string_view feature) const override;
    bool open(const std::string& name, const ImageSpec& spec,
              OpenMode mode) override;
    bool close(void) override;
    bool write_scanline(int y, int z, TypeDesc format, const void* data,
                        stride_t xstride) override;
    bool write_tile(int x, int y, int z, TypeDesc format, const void* data,
                    stride_t xstride, stride_t ystride,
                    stride_t zstride) override;

private:
    int64_t m_padded_scanline_size;
    std::string m_filename;
    bmp_pvt::BmpFileHeader m_bmp_header;
    bmp_pvt::DibInformationHeader m_dib_header;
    int64_t m_image_start;
    unsigned int m_dither;
    std::vector<unsigned char> m_tilebuffer;
    std::vector<unsigned char> m_scratch;
    std::vector<unsigned char> m_buf;  // more tmp space for write_scanline

    void init(void)
    {
        m_padded_scanline_size = 0;
        m_filename.clear();
        ioproxy_clear();
    }

    void create_and_write_file_header(void);

    void create_and_write_bitmap_header(void);
};

// Obligatory material to make this a recognizable imageio plugin
OIIO_PLUGIN_EXPORTS_BEGIN

OIIO_EXPORT ImageOutput*
bmp_output_imageio_create()
{
    return new BmpOutput;
}

OIIO_EXPORT const char* bmp_output_extensions[] = { "bmp", nullptr };

OIIO_PLUGIN_EXPORTS_END

int
BmpOutput::supports(string_view feature) const
{
    return (feature == "alpha" || feature == "ioproxy");
}

bool
BmpOutput::open(const std::string& name, const ImageSpec& spec, OpenMode mode)
{
    if (mode != Create) {
        errorfmt("{} does not support subimages or MIP levels", format_name());
        return false;
    }

    // saving 'name' and 'spec' for later use
    m_filename = name;
    m_spec     = spec;

    if (m_spec.nchannels != 1 && m_spec.nchannels != 3
        && m_spec.nchannels != 4) {
        errorfmt("{} does not support {}-channel images\n", format_name(),
                 m_spec.nchannels);
        return false;
    }

    // Only support 8 bit channels for now.
    m_spec.set_format(TypeDesc::UINT8);
    m_dither = m_spec.get_int_attribute("oiio:dither", 0);

    int64_t file_size = m_spec.image_bytes() + BMP_HEADER_SIZE + WINDOWS_V3;
    if (file_size >= int64_t(1) << 32) {
        errorfmt("{} does not support files over 4GB in size\n", format_name());
        return false;
    }

    ioproxy_retrieve_from_config(m_spec);
    if (!ioproxy_use_or_open(name))
        return false;

    // Scanline size is rounded up to align to 4-byte boundary
    m_padded_scanline_size = round_to_multiple(m_spec.scanline_bytes(), 4);

    create_and_write_file_header();
    create_and_write_bitmap_header();

    m_image_start = iotell();

    // If user asked for tiles -- which this format doesn't support, emulate
    // it by buffering the whole image.
    if (m_spec.tile_width && m_spec.tile_height)
        m_tilebuffer.resize(m_spec.image_bytes());

    return true;
}

bool
BmpOutput::write_scanline(int y, int z, TypeDesc format, const void* data,
                          stride_t xstride)
{
    if (y > m_spec.height) {
        errorfmt("Attempt to write too many scanlines to {}", m_filename);
        close();
        return false;
    }

    if (m_spec.width >= 0)
        y = (m_spec.height - y - 1);
    int64_t scanline_off = y * m_padded_scanline_size;
    ioseek(m_image_start + scanline_off);

    m_scratch.clear();
    data = to_native_scanline(format, data, xstride, m_scratch, m_dither, y, z);
    m_buf.assign((const unsigned char*)data,
                 (const unsigned char*)data + m_spec.scanline_bytes());
    m_buf.resize(m_padded_scanline_size, 0);  // pad with zeroes if needed

    // Swap RGB pixels into BGR format
    if (m_spec.nchannels >= 3)
        for (int i = 0, iend = m_buf.size() - 2; i < iend;
             i += m_spec.nchannels)
            std::swap(m_buf[i], m_buf[i + 2]);

    return iowrite(&m_buf[0], m_buf.size());
}

bool
BmpOutput::write_tile(int x, int y, int z, TypeDesc format, const void* data,
                      stride_t xstride, stride_t ystride, stride_t zstride)
{
    // Emulate tiles by buffering the whole image
    return copy_tile_to_image_buffer(x, y, z, format, data, xstride, ystride,
                                     zstride, &m_tilebuffer[0]);
}

bool
BmpOutput::close(void)
{
    if (!ioproxy_opened()) {  // already closed
        init();
        return true;
    }

    bool ok = true;
    if (m_spec.tile_width) {
        // Handle tile emulation -- output the buffered pixels
        OIIO_DASSERT(m_tilebuffer.size());
        ok &= write_scanlines(m_spec.y, m_spec.y + m_spec.height, 0,
                              m_spec.format, &m_tilebuffer[0]);
        std::vector<unsigned char>().swap(m_tilebuffer);
    }

    init();
    return ok;
}

void
BmpOutput::create_and_write_file_header(void)
{
    m_bmp_header.magic = MAGIC_BM;
    int64_t data_size  = m_padded_scanline_size * m_spec.height;
    int palettesize    = (m_spec.nchannels == 1) ? 4 * 256 : 0;
    int64_t file_size  = data_size + BMP_HEADER_SIZE + WINDOWS_V3 + palettesize;
    m_bmp_header.fsize = file_size;
    m_bmp_header.res1  = 0;
    m_bmp_header.res2  = 0;
    m_bmp_header.offset = BMP_HEADER_SIZE + WINDOWS_V3 + palettesize;

    m_bmp_header.write_header(ioproxy());
}

void
BmpOutput::create_and_write_bitmap_header(void)
{
    m_dib_header.size        = WINDOWS_V3;
    m_dib_header.width       = m_spec.width;
    m_dib_header.height      = m_spec.height;
    m_dib_header.cplanes     = 1;
    m_dib_header.compression = NO_COMPRESSION;

    if (m_spec.nchannels == 1) {
        // Special case -- write a 1-channel image as a gray palette
        m_dib_header.bpp       = 8;
        m_dib_header.cpalete   = 256;
        m_dib_header.important = 256;
    } else {
        m_dib_header.bpp       = m_spec.nchannels * 8;
        m_dib_header.cpalete   = 0;
        m_dib_header.important = 0;
    }

    m_dib_header.isize = int32_t(m_spec.image_pixels());
    m_dib_header.hres  = 0;
    m_dib_header.vres  = 0;

    string_view res_units = m_spec.get_string_attribute("ResolutionUnit");
    if (Strutil::iequals(res_units, "m")
        || Strutil::iequals(res_units, "pixel per meter")) {
        m_dib_header.hres = m_spec.get_int_attribute("XResolution");
        m_dib_header.vres = m_spec.get_int_attribute("YResolution");
    }

    m_dib_header.write_header(ioproxy());

    // Write palette, if there is one. This is only used for grayscale
    // images, and the palette is just the 256 possible gray values.
    for (int i = 0; i < m_dib_header.cpalete; ++i) {
        unsigned char val[4] = { uint8_t(i), uint8_t(i), uint8_t(i), 255 };
        iowrite(&val, 4);
    }
}

OIIO_PLUGIN_NAMESPACE_END
<commit_msg>BMP output safety (#3673)<commit_after>// Copyright 2008-present Contributors to the OpenImageIO project.
// SPDX-License-Identifier: BSD-3-Clause
// https://github.com/OpenImageIO/oiio

#include <cstdio>

#include <OpenImageIO/filesystem.h>
#include <OpenImageIO/imageio.h>
#include <OpenImageIO/strutil.h>

#include "bmp_pvt.h"

OIIO_PLUGIN_NAMESPACE_BEGIN

using namespace bmp_pvt;

class BmpOutput final : public ImageOutput {
public:
    BmpOutput() { init(); }
    ~BmpOutput() override { close(); }
    const char* format_name(void) const override { return "bmp"; }
    int supports(string_view feature) const override;
    bool open(const std::string& name, const ImageSpec& spec,
              OpenMode mode) override;
    bool close(void) override;
    bool write_scanline(int y, int z, TypeDesc format, const void* data,
                        stride_t xstride) override;
    bool write_tile(int x, int y, int z, TypeDesc format, const void* data,
                    stride_t xstride, stride_t ystride,
                    stride_t zstride) override;

private:
    int64_t m_padded_scanline_size;
    std::string m_filename;
    bmp_pvt::BmpFileHeader m_bmp_header;
    bmp_pvt::DibInformationHeader m_dib_header;
    int64_t m_image_start;
    unsigned int m_dither;
    std::vector<unsigned char> m_tilebuffer;
    std::vector<unsigned char> m_scratch;
    std::vector<unsigned char> m_buf;  // more tmp space for write_scanline

    void init(void)
    {
        m_padded_scanline_size = 0;
        m_filename.clear();
        ioproxy_clear();
    }

    void create_and_write_file_header(void);

    void create_and_write_bitmap_header(void);
};

// Obligatory material to make this a recognizable imageio plugin
OIIO_PLUGIN_EXPORTS_BEGIN

OIIO_EXPORT ImageOutput*
bmp_output_imageio_create()
{
    return new BmpOutput;
}

OIIO_EXPORT const char* bmp_output_extensions[] = { "bmp", nullptr };

OIIO_PLUGIN_EXPORTS_END

int
BmpOutput::supports(string_view feature) const
{
    return (feature == "alpha" || feature == "ioproxy");
}

bool
BmpOutput::open(const std::string& name, const ImageSpec& spec, OpenMode mode)
{
    if (mode != Create) {
        errorfmt("{} does not support subimages or MIP levels", format_name());
        return false;
    }

    // saving 'name' and 'spec' for later use
    m_filename = name;
    m_spec     = spec;

    if (m_spec.nchannels != 1 && m_spec.nchannels != 3
        && m_spec.nchannels != 4) {
        errorfmt("{} does not support {}-channel images\n", format_name(),
                 m_spec.nchannels);
        return false;
    }

    if (m_spec.x || m_spec.y || m_spec.z) {
        errorfmt("{} does not support images with non-zero image origin offset",
                 format_name());
        return false;
    }

    // Only support 8 bit channels for now.
    m_spec.set_format(TypeDesc::UINT8);
    m_dither = m_spec.get_int_attribute("oiio:dither", 0);

    int64_t file_size = m_spec.image_bytes() + BMP_HEADER_SIZE + WINDOWS_V3;
    if (file_size >= int64_t(1) << 32) {
        errorfmt("{} does not support files over 4GB in size\n", format_name());
        return false;
    }

    ioproxy_retrieve_from_config(m_spec);
    if (!ioproxy_use_or_open(name))
        return false;

    // Scanline size is rounded up to align to 4-byte boundary
    m_padded_scanline_size = round_to_multiple(m_spec.scanline_bytes(), 4);

    create_and_write_file_header();
    create_and_write_bitmap_header();

    m_image_start = iotell();

    // If user asked for tiles -- which this format doesn't support, emulate
    // it by buffering the whole image.
    if (m_spec.tile_width && m_spec.tile_height)
        m_tilebuffer.resize(m_spec.image_bytes());

    return true;
}

bool
BmpOutput::write_scanline(int y, int z, TypeDesc format, const void* data,
                          stride_t xstride)
{
    if (!ioproxy_opened()) {
        errorfmt("write_scanline called but file is not open.");
        return false;
    }

    if (y > m_spec.y + m_spec.height) {
        errorfmt("Attempt to write too many scanlines to {}", m_filename);
        close();
        return false;
    }

    y -= m_spec.y;
    if (m_spec.width >= 0)
        y = (m_spec.height - y - 1);
    int64_t scanline_off = y * m_padded_scanline_size;
    ioseek(m_image_start + scanline_off);

    m_scratch.clear();
    data = to_native_scanline(format, data, xstride, m_scratch, m_dither, y, z);
    m_buf.assign((const unsigned char*)data,
                 (const unsigned char*)data + m_spec.scanline_bytes());
    m_buf.resize(m_padded_scanline_size, 0);  // pad with zeroes if needed

    // Swap RGB pixels into BGR format
    if (m_spec.nchannels >= 3)
        for (int i = 0, iend = m_buf.size() - 2; i < iend;
             i += m_spec.nchannels)
            std::swap(m_buf[i], m_buf[i + 2]);

    return iowrite(&m_buf[0], m_buf.size());
}

bool
BmpOutput::write_tile(int x, int y, int z, TypeDesc format, const void* data,
                      stride_t xstride, stride_t ystride, stride_t zstride)
{
    if (!ioproxy_opened()) {
        errorfmt("write_tile called but file is not open.");
        return false;
    }

    // Emulate tiles by buffering the whole image
    return copy_tile_to_image_buffer(x, y, z, format, data, xstride, ystride,
                                     zstride, m_tilebuffer.data());
}

bool
BmpOutput::close(void)
{
    if (!ioproxy_opened()) {  // already closed
        init();
        return true;
    }

    bool ok = true;
    if (m_spec.tile_width && m_tilebuffer.size()) {
        // Handle tile emulation -- output the buffered pixels
        OIIO_DASSERT(m_tilebuffer.size());
        ok &= write_scanlines(m_spec.y, m_spec.y + m_spec.height, 0,
                              m_spec.format, m_tilebuffer.data());
        std::vector<unsigned char>().swap(m_tilebuffer);
    }

    init();
    return ok;
}

void
BmpOutput::create_and_write_file_header(void)
{
    m_bmp_header.magic = MAGIC_BM;
    int64_t data_size  = m_padded_scanline_size * m_spec.height;
    int palettesize    = (m_spec.nchannels == 1) ? 4 * 256 : 0;
    int64_t file_size  = data_size + BMP_HEADER_SIZE + WINDOWS_V3 + palettesize;
    m_bmp_header.fsize = file_size;
    m_bmp_header.res1  = 0;
    m_bmp_header.res2  = 0;
    m_bmp_header.offset = BMP_HEADER_SIZE + WINDOWS_V3 + palettesize;

    m_bmp_header.write_header(ioproxy());
}

void
BmpOutput::create_and_write_bitmap_header(void)
{
    m_dib_header.size        = WINDOWS_V3;
    m_dib_header.width       = m_spec.width;
    m_dib_header.height      = m_spec.height;
    m_dib_header.cplanes     = 1;
    m_dib_header.compression = NO_COMPRESSION;

    if (m_spec.nchannels == 1) {
        // Special case -- write a 1-channel image as a gray palette
        m_dib_header.bpp       = 8;
        m_dib_header.cpalete   = 256;
        m_dib_header.important = 256;
    } else {
        m_dib_header.bpp       = m_spec.nchannels * 8;
        m_dib_header.cpalete   = 0;
        m_dib_header.important = 0;
    }

    m_dib_header.isize = int32_t(m_spec.image_pixels());
    m_dib_header.hres  = 0;
    m_dib_header.vres  = 0;

    string_view res_units = m_spec.get_string_attribute("ResolutionUnit");
    if (Strutil::iequals(res_units, "m")
        || Strutil::iequals(res_units, "pixel per meter")) {
        m_dib_header.hres = m_spec.get_int_attribute("XResolution");
        m_dib_header.vres = m_spec.get_int_attribute("YResolution");
    }

    m_dib_header.write_header(ioproxy());

    // Write palette, if there is one. This is only used for grayscale
    // images, and the palette is just the 256 possible gray values.
    for (int i = 0; i < m_dib_header.cpalete; ++i) {
        unsigned char val[4] = { uint8_t(i), uint8_t(i), uint8_t(i), 255 };
        iowrite(&val, 4);
    }
}

OIIO_PLUGIN_NAMESPACE_END
<|endoftext|>


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

//-----------------------------------------------------------------------------
// Qt
#include <QMessageBox>
//------------------------------------------------------------------------------
// Repo
#include "repogui.h"
#include "ui_repogui.h"
#include "widgets/repo_widgetrepository.h"
//------------------------------------------------------------------------------

repo::gui::RepoGUI::RepoGUI(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::RepoGUI)
{
    ui->setupUi(this);
    this->setWindowIcon(
                RepoFontAwesome::getInstance().getIcon(
                            RepoFontAwesome::fa_database,
                            QColor(246, 101, 60)));

    //--------------------------------------------------------------------------
    // For docks and windows not to update as they are slow to repaint.
    this->setAnimated(false);

    //--------------------------------------------------------------------------
    // Force opengl format settings by default.
    QGLFormat format(QGL::SampleBuffers);
    format.setSwapInterval(1); // vsync
    format.setSamples(16); // Antialiasing (multisample)
    QGLFormat::setDefaultFormat(format);

    //--------------------------------------------------------------------------
    // Connect
    QObject::connect(ui->actionConnect, SIGNAL(triggered()), this, SLOT(connect()));
    ui->actionConnect->setIcon(RepoDialogConnect::getIcon());

    //--------------------------------------------------------------------------
    // Refresh
    QObject::connect(ui->actionRefresh, SIGNAL(triggered()), this, SLOT(refresh()));
    ui->actionRefresh->setIcon(RepoFontAwesome::getInstance().getIcon(RepoFontAwesome::fa_refresh));

    //--------------------------------------------------------------------------
    // Drop
    QObject::connect(ui->actionDrop, SIGNAL(triggered()), this, SLOT(dropDatabase()));
    ui->actionDrop->setIcon(RepoFontAwesome::getInstance().getIcon(RepoFontAwesome::fa_trash_o));

    //--------------------------------------------------------------------------
    // Exit
    QObject::connect(ui->actionExit, SIGNAL(triggered()),
                     QApplication::instance(), SLOT(quit()));
    ui->actionExit->setIcon(
                RepoFontAwesome::getInstance().getIcon(
                    RepoFontAwesome::fa_sign_out, QColor(Qt::darkRed)));
}

repo::gui::RepoGUI::~RepoGUI()
{
    delete ui;
}

void repo::gui::RepoGUI::connect()
{
    RepoDialogConnect connectionDialog(this);

    if(!connectionDialog.exec()) // if not clicked "Connect"
    {
        std::cout<< "Connection dialog cancelled by user" << std::endl;
    }
    else
    {
        // TODO move mongo creation outside of this main GUI to repository widget
        // or similar
        core::MongoClientWrapper mongo;

        //----------------------------------------------------------------------
        // if not successfully connected
        if (!mongo.connect(
                    connectionDialog.getHost().toStdString(),
                    connectionDialog.getPort()))
        {
            std::cerr << "Connection error" << std::endl;
        }
        else
        {
            if (!connectionDialog.getUsername().isEmpty())
            {
                mongo.authenticate(
                    connectionDialog.getUsername().toStdString(),
                    connectionDialog.getPassword().toStdString());
            }
            ui->widgetRepository->fetchDatabases(mongo);

            //-----------------------------------------------------------------
            // enable buttons
            ui->actionRefresh->setEnabled(true);
            ui->actionHead->setEnabled(true);
            ui->actionHistory->setEnabled(true);
            ui->actionCommit->setEnabled(true);
            ui->actionDrop->setEnabled(true);
        }
    }
}

void repo::gui::RepoGUI::refresh()
{
    ui->widgetRepository->refresh();
}

void repo::gui::RepoGUI::dropDatabase()
{
    QString dbName = ui->widgetRepository->getSelectedDatabase();
    if (!dbName.isNull() &&
        !dbName.isEmpty() &&
        dbName != "local" &&
        dbName != "admin")
    {
        switch (QMessageBox::warning(this,
            "Drop Database?",
            "Are you sure you want to drop '" + dbName + "' repository?",
            "&Yes",
            "&No",
            QString::null, 1, 1))
        {
            case 0:
                // yes
                if (ui->widgetRepository->getSelectedConnection().deleteDatabase(dbName.toStdString()))
                {
                    std::cout << dbName.toStdString() << " deleted successfully."
                                 << std::endl;
                }
                else
                   std::cout << "Delete unsuccessful" << std::endl;
                refresh();
                break;
            }
    }
    else
    {
        std::cout << "You are not allowed to delete 'local' and 'admin' databases." << std::endl;
    }
}
<commit_msg>Added delete<commit_after>/**
 *  Copyright (C) 2014 3D Repo Ltd
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU Affero General Public License as
 *  published by the Free Software Foundation, either version 3 of the
 *  License, or (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Affero General Public License for more details.
 *
 *  You should have received a copy of the GNU Affero General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

//-----------------------------------------------------------------------------
// Qt
#include <QMessageBox>
//------------------------------------------------------------------------------
// Repo
#include "repogui.h"
#include "ui_repogui.h"
#include "widgets/repo_widgetrepository.h"
//------------------------------------------------------------------------------

repo::gui::RepoGUI::RepoGUI(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::RepoGUI)
{
    ui->setupUi(this);
    this->setWindowIcon(
                RepoFontAwesome::getInstance().getIcon(
                            RepoFontAwesome::fa_database,
                            QColor(246, 101, 60)));

    //--------------------------------------------------------------------------
    // For docks and windows not to update as they are slow to repaint.
    this->setAnimated(false);

    //--------------------------------------------------------------------------
    // Force opengl format settings by default.
    QGLFormat format(QGL::SampleBuffers);
    format.setSwapInterval(1); // vsync
    format.setSamples(16); // Antialiasing (multisample)
    QGLFormat::setDefaultFormat(format);

    //--------------------------------------------------------------------------
    // Connect
    QObject::connect(ui->actionConnect, SIGNAL(triggered()), this, SLOT(connect()));
    ui->actionConnect->setIcon(RepoDialogConnect::getIcon());

    //--------------------------------------------------------------------------
    // Refresh
    QObject::connect(ui->actionRefresh, SIGNAL(triggered()), this, SLOT(refresh()));
    ui->actionRefresh->setIcon(RepoFontAwesome::getInstance().getIcon(RepoFontAwesome::fa_refresh));

    //--------------------------------------------------------------------------
    // Drop
    QObject::connect(ui->actionDrop, SIGNAL(triggered()), this, SLOT(dropDatabase()));
    ui->actionDrop->setIcon(RepoFontAwesome::getInstance().getIcon(RepoFontAwesome::fa_trash_o));

    //--------------------------------------------------------------------------
    // Exit
    QObject::connect(ui->actionExit, SIGNAL(triggered()),
                     QApplication::instance(), SLOT(quit()));
    ui->actionExit->setIcon(
                RepoFontAwesome::getInstance().getIcon(
                    RepoFontAwesome::fa_sign_out, QColor(Qt::darkRed)));
}

repo::gui::RepoGUI::~RepoGUI()
{
    delete ui;
}

void repo::gui::RepoGUI::connect()
{
    RepoDialogConnect connectionDialog(this);

    if(!connectionDialog.exec()) // if not clicked "Connect"
    {
        std::cout<< "Connection dialog cancelled by user" << std::endl;
    }
    else
    {
        // TODO move mongo creation outside of this main GUI to repository widget
        // or similar
        core::MongoClientWrapper mongo;

        //----------------------------------------------------------------------
        // if not successfully connected
        if (!mongo.connect(
                    connectionDialog.getHost().toStdString(),
                    connectionDialog.getPort()))
        {
            std::cerr << "Connection error" << std::endl;
        }
        else
        {
            if (!connectionDialog.getUsername().isEmpty())
            {
                mongo.authenticate(
                    connectionDialog.getUsername().toStdString(),
                    connectionDialog.getPassword().toStdString());
            }
            ui->widgetRepository->fetchDatabases(mongo);

            //-----------------------------------------------------------------
            // enable buttons
            ui->actionRefresh->setEnabled(true);
            ui->actionHead->setEnabled(true);
            ui->actionHistory->setEnabled(true);
            ui->actionCommit->setEnabled(true);
            ui->actionDrop->setEnabled(true);
        }
    }
}

void repo::gui::RepoGUI::refresh()
{
    ui->widgetRepository->refresh();
}

void repo::gui::RepoGUI::dropDatabase()
{
    QString dbName = ui->widgetRepository->getSelectedDatabase();
    if (!dbName.isNull() &&
        !dbName.isEmpty() &&
        dbName != "local" &&
        dbName != "admin")
    {
        switch (QMessageBox::warning(this,
            "Drop Database?",
            "Are you sure you want to drop '" + dbName + "' repository?",
            "&Yes",
            "&No",
            QString::null, 1, 1))
        {
            case 0:
                // yes

                core::MongoClientWrapper mongo = ui->widgetRepository->getSelectedConnection();
                mongo.reconnectAndReauthenticate();
                if (mongo.dropDatabase(dbName.toStdString()))
                {
                    std::cout << dbName.toStdString() << " deleted successfully."
                                 << std::endl;
                }
                else
                   std::cout << "Delete unsuccessful" << std::endl;
                refresh();
                break;
            }
    }
    else
    {
        std::cout << "You are not allowed to delete 'local' and 'admin' databases." << std::endl;
    }
}
<|endoftext|>


<commit_before>////////////////////////////////////////////////////////////////////////////////
//
// Copyright 2006 - 2014, Paul Beckingham, Federico Hernandez.
//
// 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.
//
// http://www.opensource.org/licenses/mit-license.php
//
////////////////////////////////////////////////////////////////////////////////

#include <cmake.h>
#include <sstream>
#include <stdlib.h>
#include <Context.h>
#include <ViewText.h>
#include <Date.h>
#include <main.h>
#include <i18n.h>
#include <text.h>
#include <CmdTimesheet.h>

extern Context context;

////////////////////////////////////////////////////////////////////////////////
CmdTimesheet::CmdTimesheet ()
{
  _keyword     = "timesheet";
  _usage       = "task          timesheet [weeks]";
  _description = STRING_CMD_TIMESHEET_USAGE;
  _read_only   = true;
  _displays_id = false;
}

////////////////////////////////////////////////////////////////////////////////
int CmdTimesheet::execute (std::string& output)
{
  int rc = 0;

  // Scan the pending tasks.
  handleRecurrence ();
  std::vector <Task> all = context.tdb2.all_tasks ();
  context.tdb2.commit ();

  // What day of the week does the user consider the first?
  int weekStart = Date::dayOfWeek (context.config.get ("weekstart"));
  if (weekStart != 0 && weekStart != 1)
    throw std::string (STRING_DATE_BAD_WEEKSTART);

  // Determine the date of the first day of the most recent report.
  Date today;
  Date start;
  start -= (((today.dayOfWeek () - weekStart) + 7) % 7) * 86400;

  // Roll back to midnight.
  start = Date (start.month (), start.day (), start.year ());
  Date end = start + (7 * 86400);

  // Determine how many reports to run.
  int quantity = 1;
  std::vector <std::string> words = context.parser.getWords ();
  if (words.size () == 1)
    quantity = strtol (words[0].c_str (), NULL, 10);;

  std::stringstream out;
  for (int week = 0; week < quantity; ++week)
  {
    Date endString (end);
    endString -= 86400;

    std::string title = start.toString (context.config.get ("dateformat"))
                        + " - "
                        + endString.toString (context.config.get ("dateformat"));

    Color bold (Color::nocolor, Color::nocolor, false, true, false);
    out << "\n"
        << (context.color () ? bold.colorize (title) : title)
        << "\n";

    // Render the completed table.
    ViewText completed;
    completed.width (context.getWidth ());
    completed.add (Column::factory ("string",       "   "));
    completed.add (Column::factory ("string",       STRING_COLUMN_LABEL_PROJECT));
    completed.add (Column::factory ("string.right", STRING_COLUMN_LABEL_DUE));
    completed.add (Column::factory ("string",       STRING_COLUMN_LABEL_DESC));

    std::vector <Task>::iterator task;
    for (task = all.begin (); task != all.end (); ++task)
    {
      // If task completed within range.
      if (task->getStatus () == Task::completed)
      {
        Date compDate (task->get_date ("end"));
        if (compDate >= start && compDate < end)
        {
          Color c;
          if (context.color ())
            autoColorize (*task, c);

          int row = completed.addRow ();
          std::string format = context.config.get ("dateformat.report");
          if (format == "")
            format = context.config.get ("dateformat");
          completed.set (row, 1, task->get ("project"), c);

          if(task->has ("due"))
          {
            Date dt (task->get_date ("due"));
            completed.set (row, 2, dt.toString (format));
          }

          std::string description = task->get ("description");
          int indent = context.config.getInteger ("indent.annotation");

          std::map <std::string, std::string> annotations;
          task->getAnnotations (annotations);
          std::map <std::string, std::string>::iterator ann;
          for (ann = annotations.begin (); ann != annotations.end (); ++ann)
            description += "\n"
                         + std::string (indent, ' ')
                         + Date (ann->first.substr (11)).toString (context.config.get ("dateformat"))
                         + " "
                         + ann->second;

          completed.set (row, 3, description, c);
        }
      }
    }

    out << "  " << format (STRING_CMD_TIMESHEET_DONE, completed.rows ()) << "\n";

    if (completed.rows ())
      out << completed.render ()
          << "\n";

    // Now render the started table.
    ViewText started;
    started.width (context.getWidth ());
    started.add (Column::factory ("string",       "   "));
    started.add (Column::factory ("string",       STRING_COLUMN_LABEL_PROJECT));
    started.add (Column::factory ("string.right", STRING_COLUMN_LABEL_DUE));
    started.add (Column::factory ("string",       STRING_COLUMN_LABEL_DESC));

    for (task = all.begin (); task != all.end (); ++task)
    {
      // If task started within range, but not completed withing range.
      if (task->getStatus () == Task::pending &&
          task->has ("start"))
      {
        Date startDate (task->get_date ("start"));
        if (startDate >= start && startDate < end)
        {
          Color c;
          if (context.color ())
            autoColorize (*task, c);

          int row = started.addRow ();
          std::string format = context.config.get ("dateformat.report");
          if (format == "")
            format = context.config.get ("dateformat");
          started.set (row, 1, task->get ("project"), c);

          if(task->has ("due"))
          {
            Date dt (task->get_date ("due"));
            started.set (row, 2, dt.toString (format));
          }

          std::string description = task->get ("description");
          int indent = context.config.getInteger ("indent.annotation");

          std::map <std::string, std::string> annotations;
          task->getAnnotations (annotations);
          std::map <std::string, std::string>::iterator ann;
          for (ann = annotations.begin (); ann != annotations.end (); ++ann)
            description += "\n"
                         + std::string (indent, ' ')
                         + Date (ann->first.substr (11)).toString (context.config.get ("dateformat"))
                         + " "
                         + ann->second;

          started.set (row, 3, description, c);
        }
      }
    }

    out << "  " << format (STRING_CMD_TIMESHEET_STARTED, started.rows ()) << "\n";

    if (started.rows ())
      out << started.render ()
          << "\n\n";

    // Prior week.
    start -= 7 * 86400;
    end   -= 7 * 86400;
  }

  output = out.str ();
  return rc;
}

////////////////////////////////////////////////////////////////////////////////
<commit_msg>CmdTimesheet<commit_after>////////////////////////////////////////////////////////////////////////////////
//
// Copyright 2006 - 2014, Paul Beckingham, Federico Hernandez.
//
// 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.
//
// http://www.opensource.org/licenses/mit-license.php
//
////////////////////////////////////////////////////////////////////////////////

#include <cmake.h>
#include <sstream>
#include <stdlib.h>
#include <Context.h>
#include <ViewText.h>
#include <Date.h>
#include <main.h>
#include <i18n.h>
#include <text.h>
#include <CmdTimesheet.h>

extern Context context;

////////////////////////////////////////////////////////////////////////////////
CmdTimesheet::CmdTimesheet ()
{
  _keyword     = "timesheet";
  _usage       = "task          timesheet [weeks]";
  _description = STRING_CMD_TIMESHEET_USAGE;
  _read_only   = true;
  _displays_id = false;
}

////////////////////////////////////////////////////////////////////////////////
int CmdTimesheet::execute (std::string& output)
{
  int rc = 0;

  // Scan the pending tasks.
  handleRecurrence ();
  std::vector <Task> all = context.tdb2.all_tasks ();

  // What day of the week does the user consider the first?
  int weekStart = Date::dayOfWeek (context.config.get ("weekstart"));
  if (weekStart != 0 && weekStart != 1)
    throw std::string (STRING_DATE_BAD_WEEKSTART);

  // Determine the date of the first day of the most recent report.
  Date today;
  Date start;
  start -= (((today.dayOfWeek () - weekStart) + 7) % 7) * 86400;

  // Roll back to midnight.
  start = Date (start.month (), start.day (), start.year ());
  Date end = start + (7 * 86400);

  // Determine how many reports to run.
  int quantity = 1;
  std::vector <std::string> words = context.parser.getWords ();
  if (words.size () == 1)
    quantity = strtol (words[0].c_str (), NULL, 10);;

  std::stringstream out;
  for (int week = 0; week < quantity; ++week)
  {
    Date endString (end);
    endString -= 86400;

    std::string title = start.toString (context.config.get ("dateformat"))
                        + " - "
                        + endString.toString (context.config.get ("dateformat"));

    Color bold (Color::nocolor, Color::nocolor, false, true, false);
    out << "\n"
        << (context.color () ? bold.colorize (title) : title)
        << "\n";

    // Render the completed table.
    ViewText completed;
    completed.width (context.getWidth ());
    completed.add (Column::factory ("string",       "   "));
    completed.add (Column::factory ("string",       STRING_COLUMN_LABEL_PROJECT));
    completed.add (Column::factory ("string.right", STRING_COLUMN_LABEL_DUE));
    completed.add (Column::factory ("string",       STRING_COLUMN_LABEL_DESC));

    std::vector <Task>::iterator task;
    for (task = all.begin (); task != all.end (); ++task)
    {
      // If task completed within range.
      if (task->getStatus () == Task::completed)
      {
        Date compDate (task->get_date ("end"));
        if (compDate >= start && compDate < end)
        {
          Color c;
          if (context.color ())
            autoColorize (*task, c);

          int row = completed.addRow ();
          std::string format = context.config.get ("dateformat.report");
          if (format == "")
            format = context.config.get ("dateformat");
          completed.set (row, 1, task->get ("project"), c);

          if(task->has ("due"))
          {
            Date dt (task->get_date ("due"));
            completed.set (row, 2, dt.toString (format));
          }

          std::string description = task->get ("description");
          int indent = context.config.getInteger ("indent.annotation");

          std::map <std::string, std::string> annotations;
          task->getAnnotations (annotations);
          std::map <std::string, std::string>::iterator ann;
          for (ann = annotations.begin (); ann != annotations.end (); ++ann)
            description += "\n"
                         + std::string (indent, ' ')
                         + Date (ann->first.substr (11)).toString (context.config.get ("dateformat"))
                         + " "
                         + ann->second;

          completed.set (row, 3, description, c);
        }
      }
    }

    out << "  " << format (STRING_CMD_TIMESHEET_DONE, completed.rows ()) << "\n";

    if (completed.rows ())
      out << completed.render ()
          << "\n";

    // Now render the started table.
    ViewText started;
    started.width (context.getWidth ());
    started.add (Column::factory ("string",       "   "));
    started.add (Column::factory ("string",       STRING_COLUMN_LABEL_PROJECT));
    started.add (Column::factory ("string.right", STRING_COLUMN_LABEL_DUE));
    started.add (Column::factory ("string",       STRING_COLUMN_LABEL_DESC));

    for (task = all.begin (); task != all.end (); ++task)
    {
      // If task started within range, but not completed withing range.
      if (task->getStatus () == Task::pending &&
          task->has ("start"))
      {
        Date startDate (task->get_date ("start"));
        if (startDate >= start && startDate < end)
        {
          Color c;
          if (context.color ())
            autoColorize (*task, c);

          int row = started.addRow ();
          std::string format = context.config.get ("dateformat.report");
          if (format == "")
            format = context.config.get ("dateformat");
          started.set (row, 1, task->get ("project"), c);

          if(task->has ("due"))
          {
            Date dt (task->get_date ("due"));
            started.set (row, 2, dt.toString (format));
          }

          std::string description = task->get ("description");
          int indent = context.config.getInteger ("indent.annotation");

          std::map <std::string, std::string> annotations;
          task->getAnnotations (annotations);
          std::map <std::string, std::string>::iterator ann;
          for (ann = annotations.begin (); ann != annotations.end (); ++ann)
            description += "\n"
                         + std::string (indent, ' ')
                         + Date (ann->first.substr (11)).toString (context.config.get ("dateformat"))
                         + " "
                         + ann->second;

          started.set (row, 3, description, c);
        }
      }
    }

    out << "  " << format (STRING_CMD_TIMESHEET_STARTED, started.rows ()) << "\n";

    if (started.rows ())
      out << started.render ()
          << "\n\n";

    // Prior week.
    start -= 7 * 86400;
    end   -= 7 * 86400;
  }

  output = out.str ();
  return rc;
}

////////////////////////////////////////////////////////////////////////////////
<|endoftext|>


<commit_before>#include "sensors.h"
#include "freertos/semphr.h"
#include "freertos/task.h"
#include "SparkFunBME280.h"

#include "esp_log.h"

static float readings[SENS_MAX-1];

static QueueHandle_t *subscriptions;
static size_t num_subscriptions;
static SemaphoreHandle_t sensor_mutex;

static const char *TAG = "sensors";

static void sensor_task(void *arg);

void sensors_initialize()
{
  xTaskCreate(sensor_task, "sensor_task", 4096, NULL, 1, NULL);
}

/* Internal function to update a cached sensor reading */
static void sensor_set(tuz_sensor_t sensor, float value)
{
  if (sensor >= SENS_MAX) {
  return;
  }
  /* Update our cache copy of the reading */
  xSemaphoreTake(sensor_mutex, portMAX_DELAY);
  readings[sensor] = value;
  xSemaphoreGive(sensor_mutex);

  /* Try to push a reading to all subscribed tasks */
  sensor_reading_t reading = {
	.sensor = sensor,
	.value = value,
  };
  for (int i = 0; i < num_subscriptions; i++) {
	/* TODO: we assume that queueing the reading succeeds.
	   if queue is full, we may want to pop from the front
	   of the queue and then push again so the stale values
	   are always recent.
	*/
	xQueueSendToBack(subscriptions[i], &reading, 0);
  }
}

float sensor_get(tuz_sensor_t sensor)
{
  float result;
  if (sensor >= SENS_MAX) {
	return 0.0;
  }
  /* note: using 32-bit floats, mutex is not strictly
	 necessary here as reading is atomic. */
  xSemaphoreTake(sensor_mutex, portMAX_DELAY);
  result = readings[sensor];
  xSemaphoreGive(sensor_mutex);

  return result;
}

bool sensors_subscribe(QueueHandle_t queue)
{
  void *new_subscriptions = realloc(subscriptions, (num_subscriptions + 1) * sizeof(QueueHandle_t));
  if (!new_subscriptions) {
	ESP_LOGE(TAG, "Failed to allocate new subscription #%d", (num_subscriptions+1));
	return false;
  }

  num_subscriptions++;
  subscriptions = (QueueHandle_t *)new_subscriptions;
  subscriptions[num_subscriptions-1] = queue;
  return true;
}

int loops;

static void sensor_task(void *arg)
{
  ESP_LOGI(TAG, "sensor task running");

  TwoWire i2cWire(1);

  i2cWire.begin(GPIO_NUM_21, GPIO_NUM_22);
  i2cWire.setClock(100000L);

  BME280 bme280(0x77, &i2cWire);
  sensor_mutex = xSemaphoreCreateMutex();

  ESP_LOGI(TAG, "BME280 0x%02x", bme280.begin());
  ESP_LOGI(TAG, "ID(0xD0) 0x%02x", bme280.readRegister(BME280_CHIP_ID_REG));

  ESP_LOGI(TAG, "Displaying ID, reset and ctrl regs\n");

  ESP_LOGI(TAG, "ID(0xD0): 0x%02x", bme280.readRegister(BME280_CHIP_ID_REG));
  ESP_LOGI(TAG, "Reset register(0xE0): 0x%02x", bme280.readRegister(BME280_RST_REG));
  ESP_LOGI(TAG, "ctrl_meas(0xF4): 0x%02x", bme280.readRegister(BME280_CTRL_MEAS_REG));
  ESP_LOGI(TAG, "ctrl_hum(0xF2): 0x%02x", bme280.readRegister(BME280_CTRL_HUMIDITY_REG));

  bme280.settings.runMode = 3; //Normal mode
  bme280.settings.tStandby = 0;
  bme280.settings.filter = 2;
  bme280.settings.tempOverSample = 1;
  bme280.settings.pressOverSample = 1;
  bme280.settings.humidOverSample = 1;

  loops = 0;

  while (1) {
	vTaskDelay(100 / portTICK_PERIOD_MS);

  if (loops < 100) {
    loops++;
    continue;
  }

	for (int i = 0; i < SENS_MAX; i++) {
	  float value;

	  /* TODO: actually take readings here */
	  switch((tuz_sensor_t)i) {
	  case SENS_TEMPERATURE:
		value = bme280.readTempC();
		break;
	  case SENS_HUMIDITY:
    value = bme280.readFloatHumidity();
		break;
	  case SENS_ALTITUDE:
    value = bme280.readFloatAltitudeMeters();
		break;
	  case SENS_BAROMETRIC:
		value = bme280.readFloatPressure();
		break;
	  default:
		ESP_LOGE(TAG, "invalid tuz_sensor_t value %d", i);
		continue;
	  }

 	  sensor_set((tuz_sensor_t)i, value);

    loops = 0;
	}
  }

}

const char *sensor_name(tuz_sensor_t sensor) {
  switch(sensor) {
  case SENS_TEMPERATURE:
	return "temperature";
  case SENS_HUMIDITY:
	return "humidity";
  case SENS_ALTITUDE:
	return "altitude";
  case SENS_BAROMETRIC:
	return "barometric";
  default:
	return "unknownsensor";
  }
}

<commit_msg>sensors: Make readings array large enough<commit_after>#include "sensors.h"
#include "freertos/semphr.h"
#include "freertos/task.h"
#include "SparkFunBME280.h"

#include "esp_log.h"

static float readings[SENS_MAX];

static QueueHandle_t *subscriptions;
static size_t num_subscriptions;
static SemaphoreHandle_t sensor_mutex;

static const char *TAG = "sensors";

static void sensor_task(void *arg);

void sensors_initialize()
{
  xTaskCreate(sensor_task, "sensor_task", 4096, NULL, 1, NULL);
}

/* Internal function to update a cached sensor reading */
static void sensor_set(tuz_sensor_t sensor, float value)
{
  if (sensor >= SENS_MAX) {
  return;
  }
  /* Update our cache copy of the reading */
  xSemaphoreTake(sensor_mutex, portMAX_DELAY);
  readings[sensor] = value;
  xSemaphoreGive(sensor_mutex);

  /* Try to push a reading to all subscribed tasks */
  sensor_reading_t reading = {
	.sensor = sensor,
	.value = value,
  };
  for (int i = 0; i < num_subscriptions; i++) {
	/* TODO: we assume that queueing the reading succeeds.
	   if queue is full, we may want to pop from the front
	   of the queue and then push again so the stale values
	   are always recent.
	*/
	xQueueSendToBack(subscriptions[i], &reading, 0);
  }
}

float sensor_get(tuz_sensor_t sensor)
{
  float result;
  if (sensor >= SENS_MAX) {
	return 0.0;
  }
  /* note: using 32-bit floats, mutex is not strictly
	 necessary here as reading is atomic. */
  xSemaphoreTake(sensor_mutex, portMAX_DELAY);
  result = readings[sensor];
  xSemaphoreGive(sensor_mutex);

  return result;
}

bool sensors_subscribe(QueueHandle_t queue)
{
  void *new_subscriptions = realloc(subscriptions, (num_subscriptions + 1) * sizeof(QueueHandle_t));
  if (!new_subscriptions) {
	ESP_LOGE(TAG, "Failed to allocate new subscription #%d", (num_subscriptions+1));
	return false;
  }

  num_subscriptions++;
  subscriptions = (QueueHandle_t *)new_subscriptions;
  subscriptions[num_subscriptions-1] = queue;
  return true;
}

int loops;

static void sensor_task(void *arg)
{
  ESP_LOGI(TAG, "sensor task running");

  TwoWire i2cWire(1);

  i2cWire.begin(GPIO_NUM_21, GPIO_NUM_22);
  i2cWire.setClock(100000L);

  BME280 bme280(0x77, &i2cWire);
  sensor_mutex = xSemaphoreCreateMutex();

  ESP_LOGI(TAG, "BME280 0x%02x", bme280.begin());
  ESP_LOGI(TAG, "ID(0xD0) 0x%02x", bme280.readRegister(BME280_CHIP_ID_REG));

  ESP_LOGI(TAG, "Displaying ID, reset and ctrl regs\n");

  ESP_LOGI(TAG, "ID(0xD0): 0x%02x", bme280.readRegister(BME280_CHIP_ID_REG));
  ESP_LOGI(TAG, "Reset register(0xE0): 0x%02x", bme280.readRegister(BME280_RST_REG));
  ESP_LOGI(TAG, "ctrl_meas(0xF4): 0x%02x", bme280.readRegister(BME280_CTRL_MEAS_REG));
  ESP_LOGI(TAG, "ctrl_hum(0xF2): 0x%02x", bme280.readRegister(BME280_CTRL_HUMIDITY_REG));

  bme280.settings.runMode = 3; //Normal mode
  bme280.settings.tStandby = 0;
  bme280.settings.filter = 2;
  bme280.settings.tempOverSample = 1;
  bme280.settings.pressOverSample = 1;
  bme280.settings.humidOverSample = 1;

  loops = 0;

  while (1) {
	vTaskDelay(100 / portTICK_PERIOD_MS);

  if (loops < 100) {
    loops++;
    continue;
  }

	for (int i = 0; i < SENS_MAX; i++) {
	  float value;

	  /* TODO: actually take readings here */
	  switch((tuz_sensor_t)i) {
	  case SENS_TEMPERATURE:
		value = bme280.readTempC();
		break;
	  case SENS_HUMIDITY:
    value = bme280.readFloatHumidity();
		break;
	  case SENS_ALTITUDE:
    value = bme280.readFloatAltitudeMeters();
		break;
	  case SENS_BAROMETRIC:
		value = bme280.readFloatPressure();
		break;
	  default:
		ESP_LOGE(TAG, "invalid tuz_sensor_t value %d", i);
		continue;
	  }

 	  sensor_set((tuz_sensor_t)i, value);

    loops = 0;
	}
  }

}

const char *sensor_name(tuz_sensor_t sensor) {
  switch(sensor) {
  case SENS_TEMPERATURE:
	return "temperature";
  case SENS_HUMIDITY:
	return "humidity";
  case SENS_ALTITUDE:
	return "altitude";
  case SENS_BAROMETRIC:
	return "barometric";
  default:
	return "unknownsensor";
  }
}

<|endoftext|>


<commit_before>/*
Copyright (c) 2015 Microsoft Corporation. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.

Author: Leonardo de Moura
*/
#include "kernel/type_checker.h"
#include "kernel/abstract.h"
#include "kernel/instantiate.h"
#include "kernel/inductive/inductive.h"
#include "library/replace_visitor.h"
#include "library/constants.h"
#include "library/util.h"
#include "compiler/util.h"

namespace lean {
class simp_pr1_rec_fn : public replace_visitor {
    environment    m_env;
    name_generator m_ngen;
    type_checker   m_tc;

    struct failed {};

    struct elim_nested_pr1_fn : public replace_visitor {
        buffer<bool> const & minor_is_rec_arg;
        buffer<expr> const & minor_ctx;

        elim_nested_pr1_fn(buffer<bool> const & b1, buffer<expr> const & b2):
            minor_is_rec_arg(b1), minor_ctx(b2) {
            lean_assert(minor_is_rec_arg.size() == minor_ctx.size());
        }

        bool is_rec_arg(expr const & e) {
            if (!is_local(e))
                return false;
            for (unsigned i = 0; i < minor_ctx.size(); i++) {
                if (minor_is_rec_arg[i] && mlocal_name(minor_ctx[i]) == mlocal_name(e))
                    return true;
            }
            return false;
        }

        virtual expr visit_app(expr const & e) {
            expr const & f = get_app_fn(e);
            if (is_constant(f) && const_name(f) == get_prod_pr1_name()) {
                buffer<expr> args;
                get_app_args(e, args);
                if (args.size() >= 3 && is_rec_arg(args[2])) {
                    for (unsigned i = 3; i < args.size(); i++)
                        args[i] = visit(args[i]);
                    return mk_app(args[2], args.size() - 3, args.data() + 3);
                }
            }
            return replace_visitor::visit_app(e);
        }

        virtual expr visit_local(expr const & e) {
            if (is_rec_arg(e))
                throw failed();
            return replace_visitor::visit_local(e);
        }
    };

    optional<expr> simplify(expr const & e) {
        expr const & f = get_app_fn(e);
        if (!is_constant(f) || const_name(f) != get_prod_pr1_name())
            return none_expr();
        buffer<expr> args;
        get_app_args(e, args);
        if (args.size() < 3)
            return none_expr();
        for (unsigned i = 3; i < args.size(); i++)
            args[i] = visit(args[i]);
        expr const & rec    = args[2];
        buffer<expr> rec_args;
        expr const & rec_fn = get_app_args(rec, rec_args);
        if (!is_constant(rec_fn))
            return none_expr();
        auto I_name = inductive::is_elim_rule(m_env, const_name(rec_fn));
        if (!I_name)
            return none_expr();
        buffer<buffer<bool>> is_rec_arg;
        get_rec_args(m_env, *I_name, is_rec_arg);
        unsigned nparams       = *inductive::get_num_params(m_env, *I_name);
        unsigned ntypeformers  = *inductive::get_num_type_formers(m_env, *I_name);
        unsigned nminors       = *inductive::get_num_minor_premises(m_env, *I_name);
        if (rec_args.size() < nparams + ntypeformers + nminors)
            return none_expr();
        // update type formers
        for (unsigned i = nparams; i < nparams + ntypeformers; i++) {
            // Check whether each type former is of the form
            //  (lambda ctx, prod c1 c2), and replace it with (lambda ctx, c1)
            expr typeformer = rec_args[i];
            buffer<expr> typeformer_ctx;
            expr typeformer_body = fun_to_telescope(m_ngen, typeformer, typeformer_ctx, optional<binder_info>());

            buffer<expr> typeformer_body_args;
            expr typeformer_body_fn = get_app_args(typeformer_body, typeformer_body_args);
            if (!is_constant(typeformer_body_fn) || const_name(typeformer_body_fn) != get_prod_name() || typeformer_body_args.size() != 2) {
                return none_expr();
            }
            typeformer_body = typeformer_body_args[0];
            rec_args[i] = Fun(typeformer_ctx, typeformer_body);
        }
        // update minor premises
        for (unsigned i = nparams + ntypeformers, j = 0; i < nparams + ntypeformers + nminors; i++, j++) {
            buffer<bool> const & minor_is_rec_arg = is_rec_arg[j];
            expr minor = rec_args[i];
            buffer<expr> minor_ctx;
            expr minor_body = fun_to_telescope(m_ngen, minor, minor_ctx, optional<binder_info>());
            if (minor_is_rec_arg.size() != minor_ctx.size()) {
                return none_expr();
            }
            // We have to check:
            //   1- For each local r in the context minor_ctx s.t. r is marked as recursive in minor_is_rec_arg,
            //      its type is of the form (prod A B). The new type will be just A.
            //   2- minor body is of the form (prod.mk A B c1 c2)
            //   3- In c1, all occurrences of recursive arguments r are of the form (prod.pr1 A B r)

            // Step 1.
            for (unsigned i = 0; i < minor_ctx.size(); i++) {
                if (minor_is_rec_arg[i]) {
                    expr type = m_tc.whnf(mlocal_type(minor_ctx[i])).first;
                    buffer<expr> type_args;
                    expr type_fn = get_app_args(type, type_args);
                    if (!is_constant(type_fn) || const_name(type_fn) != get_prod_name() || type_args.size() != 2)
                        return none_expr();
                    minor_ctx[i] = update_mlocal(minor_ctx[i], type_args[0]);
                }
            }

            // Step 2
            buffer<expr> minor_body_args;
            expr minor_body_fn = get_app_args(minor_body, minor_body_args);
            if (!is_constant(minor_body_fn) || const_name(minor_body_fn) != get_prod_mk_name() || minor_body_args.size() != 4)
                return none_expr();
            minor_body = minor_body_args[2];

            // Step 3
            try {
                elim_nested_pr1_fn elim(minor_is_rec_arg, minor_ctx);
                minor_body = elim(minor_body);
            } catch (failed &) {
                return none_expr();
            }
            // Update minor premise
            rec_args[i] = Fun(minor_ctx, minor_body);
        }
        expr new_rec = mk_app(rec_fn, rec_args.size(), rec_args.data());
        return some_expr(mk_app(new_rec, args.size() - 3, args.data() + 3));
    }

    virtual expr visit_app(expr const & e) {
        if (auto r = simplify(e))
            return *r;
        else
            return replace_visitor::visit_app(e);
    }

    virtual expr visit_binding(expr const & b) {
        expr new_domain = visit(binding_domain(b));
        expr l          = mk_local(m_ngen.next(), new_domain);
        expr new_body   = abstract_local(visit(instantiate(binding_body(b), l)), l);
        return update_binding(b, new_domain, new_body);
    }

public:
    simp_pr1_rec_fn(environment const & env):m_env(env), m_tc(env, m_ngen.mk_child()) {}
};

expr simp_pr1_rec(environment const & env, expr const & e) {
    return simp_pr1_rec_fn(env)(e);
}
}
<commit_msg>fix(compiler/simp_pr1_rec): missing recursor nested inside recursor<commit_after>/*
Copyright (c) 2015 Microsoft Corporation. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.

Author: Leonardo de Moura
*/
#include "kernel/type_checker.h"
#include "kernel/abstract.h"
#include "kernel/instantiate.h"
#include "kernel/inductive/inductive.h"
#include "library/replace_visitor.h"
#include "library/constants.h"
#include "library/util.h"
#include "compiler/util.h"

namespace lean {
class simp_pr1_rec_fn : public replace_visitor {
    environment    m_env;
    name_generator m_ngen;
    type_checker   m_tc;

    struct failed {};

    struct elim_nested_pr1_fn : public replace_visitor {
        buffer<bool> const & minor_is_rec_arg;
        buffer<expr> const & minor_ctx;

        elim_nested_pr1_fn(buffer<bool> const & b1, buffer<expr> const & b2):
            minor_is_rec_arg(b1), minor_ctx(b2) {
            lean_assert(minor_is_rec_arg.size() == minor_ctx.size());
        }

        bool is_rec_arg(expr const & e) {
            if (!is_local(e))
                return false;
            for (unsigned i = 0; i < minor_ctx.size(); i++) {
                if (minor_is_rec_arg[i] && mlocal_name(minor_ctx[i]) == mlocal_name(e))
                    return true;
            }
            return false;
        }

        virtual expr visit_app(expr const & e) {
            expr const & f = get_app_fn(e);
            if (is_constant(f) && const_name(f) == get_prod_pr1_name()) {
                buffer<expr> args;
                get_app_args(e, args);
                if (args.size() >= 3 && is_rec_arg(args[2])) {
                    for (unsigned i = 3; i < args.size(); i++)
                        args[i] = visit(args[i]);
                    return mk_app(args[2], args.size() - 3, args.data() + 3);
                }
            }
            return replace_visitor::visit_app(e);
        }

        virtual expr visit_local(expr const & e) {
            if (is_rec_arg(e))
                throw failed();
            return replace_visitor::visit_local(e);
        }
    };

    optional<expr> simplify(expr const & e) {
        expr const & f = get_app_fn(e);
        if (!is_constant(f) || const_name(f) != get_prod_pr1_name())
            return none_expr();
        buffer<expr> args;
        get_app_args(e, args);
        if (args.size() < 3)
            return none_expr();
        for (unsigned i = 3; i < args.size(); i++)
            args[i] = visit(args[i]);
        expr const & rec    = args[2];
        buffer<expr> rec_args;
        expr const & rec_fn = get_app_args(rec, rec_args);
        if (!is_constant(rec_fn))
            return none_expr();
        auto I_name = inductive::is_elim_rule(m_env, const_name(rec_fn));
        if (!I_name)
            return none_expr();
        buffer<buffer<bool>> is_rec_arg;
        get_rec_args(m_env, *I_name, is_rec_arg);
        unsigned nparams       = *inductive::get_num_params(m_env, *I_name);
        unsigned ntypeformers  = *inductive::get_num_type_formers(m_env, *I_name);
        unsigned nminors       = *inductive::get_num_minor_premises(m_env, *I_name);
        if (rec_args.size() < nparams + ntypeformers + nminors)
            return none_expr();
        // update type formers
        for (unsigned i = nparams; i < nparams + ntypeformers; i++) {
            // Check whether each type former is of the form
            //  (lambda ctx, prod c1 c2), and replace it with (lambda ctx, c1)
            expr typeformer = rec_args[i];
            buffer<expr> typeformer_ctx;
            expr typeformer_body = fun_to_telescope(m_ngen, typeformer, typeformer_ctx, optional<binder_info>());

            buffer<expr> typeformer_body_args;
            expr typeformer_body_fn = get_app_args(typeformer_body, typeformer_body_args);
            if (!is_constant(typeformer_body_fn) || const_name(typeformer_body_fn) != get_prod_name() || typeformer_body_args.size() != 2) {
                return none_expr();
            }
            typeformer_body = typeformer_body_args[0];
            rec_args[i] = Fun(typeformer_ctx, typeformer_body);
        }
        // update minor premises
        for (unsigned i = nparams + ntypeformers, j = 0; i < nparams + ntypeformers + nminors; i++, j++) {
            buffer<bool> const & minor_is_rec_arg = is_rec_arg[j];
            expr minor = rec_args[i];
            buffer<expr> minor_ctx;
            expr minor_body = fun_to_telescope(m_ngen, minor, minor_ctx, optional<binder_info>());
            if (minor_is_rec_arg.size() != minor_ctx.size()) {
                return none_expr();
            }
            // We have to check:
            //   1- For each local r in the context minor_ctx s.t. r is marked as recursive in minor_is_rec_arg,
            //      its type is of the form (prod A B). The new type will be just A.
            //   2- minor body is of the form (prod.mk A B c1 c2)
            //   3- In c1, all occurrences of recursive arguments r are of the form (prod.pr1 A B r)

            // Step 1.
            for (unsigned i = 0; i < minor_ctx.size(); i++) {
                if (minor_is_rec_arg[i]) {
                    expr type = m_tc.whnf(mlocal_type(minor_ctx[i])).first;
                    buffer<expr> type_args;
                    expr type_fn = get_app_args(type, type_args);
                    if (!is_constant(type_fn) || const_name(type_fn) != get_prod_name() || type_args.size() != 2)
                        return none_expr();
                    minor_ctx[i] = update_mlocal(minor_ctx[i], type_args[0]);
                }
            }

            // Step 2
            buffer<expr> minor_body_args;
            expr minor_body_fn = get_app_args(minor_body, minor_body_args);
            if (!is_constant(minor_body_fn) || const_name(minor_body_fn) != get_prod_mk_name() || minor_body_args.size() != 4)
                return none_expr();
            minor_body = minor_body_args[2];

            // Step 3
            try {
                elim_nested_pr1_fn elim(minor_is_rec_arg, minor_ctx);
                minor_body = elim(minor_body);
            } catch (failed &) {
                return none_expr();
            }
            // Update minor premise
            rec_args[i] = Fun(minor_ctx, minor_body);
        }
        expr new_rec = mk_app(rec_fn, rec_args.size(), rec_args.data());
        return some_expr(visit(mk_app(new_rec, args.size() - 3, args.data() + 3)));
    }

    virtual expr visit_app(expr const & e) {
        if (auto r = simplify(e))
            return *r;
        else
            return replace_visitor::visit_app(e);
    }

    virtual expr visit_binding(expr const & b) {
        expr new_domain = visit(binding_domain(b));
        expr l          = mk_local(m_ngen.next(), new_domain);
        expr new_body   = abstract_local(visit(instantiate(binding_body(b), l)), l);
        return update_binding(b, new_domain, new_body);
    }

public:
    simp_pr1_rec_fn(environment const & env):m_env(env), m_tc(env, m_ngen.mk_child()) {}
};

expr simp_pr1_rec(environment const & env, expr const & e) {
    return simp_pr1_rec_fn(env)(e);
}
}
<|endoftext|>


<commit_before>// Copyright 2015 Google Inc. All rights reserved.
//
// 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 "components/rendermesh.h"
#include "components/transform.h"
#include "components_generated.h"
#include "fplbase/mesh.h"

using mathfu::vec3;
using mathfu::mat4;

namespace fpl {
namespace fpl_project {

// Offset the frustrum by this many world-units.  As long as no objects are
// larger than this number, they should still all draw, even if their
// registration points technically fall outside our frustrum.
static const float kFrustrumOffset = 50.0f;

void RenderMeshComponent::Initialize(mathfu::vec3 light_position,
                                     MaterialManager* material_manager) {
  light_position_ = light_position;
  material_manager_ = material_manager;
}

// Rendermesh depends on transform:
void RenderMeshComponent::InitEntity(entity::EntityRef& entity) {
  entity_manager_->AddEntityToComponent<TransformComponent>(entity);
}

void RenderMeshComponent::RenderEntity(entity::EntityRef& entity,
                                       Renderer& renderer,
                                       const Camera& camera) {
  TransformData* transform_data = Data<TransformData>(entity);
  RenderMeshData* rendermesh_data = Data<RenderMeshData>(entity);

  // Check to make sure objects are inside the frustrum of our view-cone:
  float max_cos = cos(camera.viewport_angle());
  vec3 camera_facing = camera.facing();
  vec3 entity_position = transform_data->world_transform.TranslationVector3D();
  vec3 pos_relative_to_camera = (entity_position - camera.position()) +
      camera_facing * kFrustrumOffset;

  if (vec3::DotProduct(pos_relative_to_camera.Normalized(),
                       camera_facing.Normalized()) < max_cos) {
    // The origin point for this mesh is not in our field of view.  Cut out
    // early, and don't bother rendering it.
    return;
  }

  mat4 world_transform = transform_data->world_transform;

  const mat4 mvp = camera.GetTransformMatrix() * world_transform;
  const mat4 world_matrix_inverse = world_transform.Inverse();

  renderer.camera_pos() = world_matrix_inverse * camera.position();
  renderer.light_pos() = world_matrix_inverse * light_position_;
  renderer.model_view_projection() = mvp;

  if (rendermesh_data->shader) {
    rendermesh_data->shader->Set(renderer);
  }
  rendermesh_data->mesh->Render(renderer);
}

void RenderMeshComponent::RenderAllEntities(Renderer& renderer,
                                            const Camera& camera) {
  // todo(ccornell) - instead of iterating like this, sort by
  // z depth and alpha blend mode.
  for (auto iter = component_data_.begin();
       iter != component_data_.end(); ++iter) {
    RenderEntity(iter->entity, renderer, camera);
  }
}

void RenderMeshComponent::AddFromRawData(entity::EntityRef& entity,
                                         const void* raw_data) {
  auto component_data = static_cast<const ComponentDefInstance*>(raw_data);
  assert(component_data->data_type() == ComponentDataUnion_RenderMeshDef);
  auto rendermesh_def =
      static_cast<const RenderMeshDef*>(component_data->data());

  // You need to call set_material_manager before you can add from raw data,
  // otherwise it can't load up new meshes!
  assert(material_manager_ != nullptr);
  assert(rendermesh_def->source_file() != nullptr);
  assert(rendermesh_def->shader() != nullptr);

  RenderMeshData* rendermesh_data = AddEntity(entity);

  rendermesh_data->mesh =
      material_manager_->LoadMesh(rendermesh_def->source_file()->c_str());
  rendermesh_data->shader =
      material_manager_->LoadShader(rendermesh_def->shader()->c_str());

  // TODO: Load this from a flatbuffer file instead of setting it.
  rendermesh_data->tint = mathfu::kOnes4f;
}

}  // fpl_project
}  // fpl
<commit_msg>Added support for tinting rendermeshes<commit_after>// Copyright 2015 Google Inc. All rights reserved.
//
// 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 "components/rendermesh.h"
#include "components/transform.h"
#include "components_generated.h"
#include "fplbase/mesh.h"

using mathfu::vec3;
using mathfu::mat4;

namespace fpl {
namespace fpl_project {

// Offset the frustrum by this many world-units.  As long as no objects are
// larger than this number, they should still all draw, even if their
// registration points technically fall outside our frustrum.
static const float kFrustrumOffset = 50.0f;

void RenderMeshComponent::Initialize(mathfu::vec3 light_position,
                                     MaterialManager* material_manager) {
  light_position_ = light_position;
  material_manager_ = material_manager;
}

// Rendermesh depends on transform:
void RenderMeshComponent::InitEntity(entity::EntityRef& entity) {
  entity_manager_->AddEntityToComponent<TransformComponent>(entity);
}

void RenderMeshComponent::RenderEntity(entity::EntityRef& entity,
                                       Renderer& renderer,
                                       const Camera& camera) {
  TransformData* transform_data = Data<TransformData>(entity);
  RenderMeshData* rendermesh_data = Data<RenderMeshData>(entity);

  // Check to make sure objects are inside the frustrum of our view-cone:
  float max_cos = cos(camera.viewport_angle());
  vec3 camera_facing = camera.facing();
  vec3 entity_position = transform_data->world_transform.TranslationVector3D();
  vec3 pos_relative_to_camera = (entity_position - camera.position()) +
      camera_facing * kFrustrumOffset;

  if (vec3::DotProduct(pos_relative_to_camera.Normalized(),
                       camera_facing.Normalized()) < max_cos) {
    // The origin point for this mesh is not in our field of view.  Cut out
    // early, and don't bother rendering it.
    return;
  }

  mat4 world_transform = transform_data->world_transform;

  const mat4 mvp = camera.GetTransformMatrix() * world_transform;
  const mat4 world_matrix_inverse = world_transform.Inverse();

  renderer.camera_pos() = world_matrix_inverse * camera.position();
  renderer.light_pos() = world_matrix_inverse * light_position_;
  renderer.model_view_projection() = mvp;
  renderer.color() = rendermesh_data->tint;

  if (rendermesh_data->shader) {
    rendermesh_data->shader->Set(renderer);
  }
  rendermesh_data->mesh->Render(renderer);
}

void RenderMeshComponent::RenderAllEntities(Renderer& renderer,
                                            const Camera& camera) {
  // todo(ccornell) - instead of iterating like this, sort by
  // z depth and alpha blend mode.
  for (auto iter = component_data_.begin();
       iter != component_data_.end(); ++iter) {
    RenderEntity(iter->entity, renderer, camera);
  }
}

void RenderMeshComponent::AddFromRawData(entity::EntityRef& entity,
                                         const void* raw_data) {
  auto component_data = static_cast<const ComponentDefInstance*>(raw_data);
  assert(component_data->data_type() == ComponentDataUnion_RenderMeshDef);
  auto rendermesh_def =
      static_cast<const RenderMeshDef*>(component_data->data());

  // You need to call set_material_manager before you can add from raw data,
  // otherwise it can't load up new meshes!
  assert(material_manager_ != nullptr);
  assert(rendermesh_def->source_file() != nullptr);
  assert(rendermesh_def->shader() != nullptr);

  RenderMeshData* rendermesh_data = AddEntity(entity);

  rendermesh_data->mesh =
      material_manager_->LoadMesh(rendermesh_def->source_file()->c_str());
  rendermesh_data->shader =
      material_manager_->LoadShader(rendermesh_def->shader()->c_str());

  // TODO: Load this from a flatbuffer file instead of setting it.
  rendermesh_data->tint = mathfu::kOnes4f;
}

}  // fpl_project
}  // fpl
<|endoftext|>