<commit_before>#include "bspzipgui.h"

#include <iostream>

#include <QFile>
#include <qfiledialog>
#include <QMessageBox>
#include <QProcess>
#include <QSettings>
#include <QTextStream>

BspZipGui::BspZipGui(QWidget *parent, Qt::WindowFlags flags)
    : QDialog(parent, flags),
    bspzip_process_(NULL)
    //progress_dialog_(NULL)
{
    ui.setupUi(this);

    bspzip_process_ = new QProcess(this);
    bool b = connect(bspzip_process_, SIGNAL(finished(int, QProcess::ExitStatus)), this, SLOT(onBspZipProcessFinished(int, QProcess::ExitStatus)));
    Q_ASSERT(b);

    //progress_dialog_ = new QProgressDialog(tr("Performing operation"),
    //                                       tr("Cancel"), 0, 100, this);
    //progress_dialog_->setMinimumDuration(0);

    QSettings settings("settings.ini", QSettings::IniFormat, this);
    QString bzip = tr("E:\\Games\\Steam\\SteamApps\\common\\nuclear dawn\\bin\\bspzip.exe");
    QString bsp = tr("E:\\Games\\Steam\\SteamApps\\common\\nuclear dawn\\nucleardawn\\maps\\sk_sandbrick.bsp");
    QString data_folder = tr("D:\\Programming\\AlienSwarmMaps\\nucleardawn\\sk_sandbrick");
    ui.bspzip_path->setText(settings.value("BSPZIP_PATH", bzip).toString());
    ui.bspfile_path->setText(settings.value("BSP_FILE_PATH", bsp).toString());
    ui.data_folder_path->setText(settings.value("DATA_FOLDER_PATH", data_folder).toString());
    this->resize(settings.value("SIZE", QSize(this->width(), this->height())).toSize());
}

BspZipGui::~BspZipGui()
{
    QSettings settings("settings.ini", QSettings::IniFormat, this);
    settings.setValue("BSPZIP_PATH", ui.bspzip_path->text());
    settings.setValue("BSP_FILE_PATH", ui.bspfile_path->text());
    settings.setValue("DATA_FOLDER_PATH", ui.data_folder_path->text());
    settings.setValue("SIZE", this->size());
}

void BspZipGui::on_browse_bspzip_clicked()
{
    QString default_dir_path;;
    QFileInfo fi(ui.bspzip_path->text());
    if (fi.exists())
    {
        default_dir_path = fi.absolutePath();
    }
    else
    {
        default_dir_path = QDir::homePath();
    }

    QFileDialog d;
    QString path = d.getOpenFileName(this, tr("Select bspzip.exe file"), default_dir_path);

    if (!path.isEmpty())
        ui.bspzip_path->setText(QDir::toNativeSeparators(path));
}

void BspZipGui::on_browse_bsp_file_clicked()
{
    QString default_dir_path;;
    QFileInfo fi(ui.bspfile_path->text());
    if (fi.exists())
    {
        default_dir_path = fi.absolutePath();
    }
    else
    {
        default_dir_path = QDir::homePath();
    }

    QFileDialog d;
    QString path = d.getOpenFileName(this, tr("Select BSP file"), default_dir_path);

    if (!path.isEmpty())
        ui.bspfile_path->setText(QDir::toNativeSeparators(path));
}

void BspZipGui::on_browse_data_folder_clicked()
{
    QString default_dir_path;;
    QFileInfo fi(ui.data_folder_path->text());
    if (fi.exists())
    {
        if (fi.isDir())
            default_dir_path = fi.absoluteFilePath();
        else
            default_dir_path = fi.absolutePath();
    }
    else
    {
        default_dir_path = QDir::homePath();
    }

    QFileDialog d;
    QString path = d.getExistingDirectory(this, tr("Select folder where to extract BSP or which to embed in BSP"), default_dir_path);

    if (!path.isEmpty())
        ui.data_folder_path->setText(QDir::toNativeSeparators(path));
}

void BspZipGui::on_embed_clicked()
{
    disableAllButtons();

    QStringList check_list;
    check_list << ui.bspzip_path->text() << ui.bspfile_path->text() << ui.data_folder_path->text();
    if (!filesExist(check_list))
    {
        enableAllButtons();
        return;
    }

    QFile bspzip_filelist_file(QDir::homePath() + "/bspzip_filelist.txt");
    log(tr("Opening file for writing: %1").arg( bspzip_filelist_file.fileName() ));
    if (!bspzip_filelist_file.open(QIODevice::WriteOnly | QIODevice::Text))
    {
        log(tr("Failed to open file for writing: %1").arg(bspzip_filelist_file.fileName()));
        enableAllButtons();
        return;
    }

    QDir data_dir( ui.data_folder_path->text(), "", QDir::Name | QDir::IgnoreCase, QDir::AllDirs | QDir::Files|  QDir::NoDotAndDotDot );
    getDataFolderFiles(data_dir, &data_folder_files_);

    if (data_folder_files_.isEmpty())
    {
        log(tr("No files found for embedding in directory: %1 Aborting...").arg(data_dir.absolutePath()));
        enableAllButtons();
        return;
    }

    log("Adding file list into filelist.txt...");

    QTextStream out(&bspzip_filelist_file);
    QString absolute_file_path;
    Q_FOREACH(absolute_file_path, data_folder_files_)
    {
        absolute_file_path = QDir::toNativeSeparators(absolute_file_path);
        QString relative_file_path = absolute_file_path.mid(ui.data_folder_path->text().size() + 1);

        log(relative_file_path);
        log(absolute_file_path);

        // no quotes here as BSPZIP doesn't handle them
        out << relative_file_path << "\n";
        out << absolute_file_path << "\n";
    }
    data_folder_files_.clear(); // must be cleared! or we get bugs

    bspzip_filelist_file.close();
    log(tr("File bspzip_filelist.txt was successfully created"));

    QString bsp_file_path = QDir::toNativeSeparators(ui.bspfile_path->text());
    QString filelist_path = QDir::toNativeSeparators(bspzip_filelist_file.fileName());
    QStringList process_arguments;
    process_arguments << "-addorupdatelist";
    process_arguments << bsp_file_path;
    process_arguments << filelist_path;
    process_arguments << bsp_file_path;

//     if (bspzip_process_)
//     {
//         delete bspzip_process_;
//     }

    log(tr("Starting BSPZIP.EXE with following arguments"));
    Q_FOREACH(QString argument, process_arguments)
    {
        log(argument);
    }

    bspzip_process_->start(ui.bspzip_path->text(), process_arguments);
}

void BspZipGui::on_extract_clicked()
{
    QString bsp_file_path = QDir::toNativeSeparators(ui.bspfile_path->text());
    QString data_folder = QDir::toNativeSeparators(ui.data_folder_path->text());

    QStringList check_list;
    check_list << ui.bspzip_path->text() << bsp_file_path << data_folder;
    if (!filesExist(check_list))
    {
        return;
    }

    QStringList process_arguments;
    process_arguments << "-extractfiles";
    process_arguments << bsp_file_path;
    process_arguments << data_folder;

//     if (bspzip_process_)
//     {
//         delete bspzip_process_;
//     }

//     bspzip_process_ = new QProcess(this);
//     bool b = connect(bspzip_process_, SIGNAL(finished(int, QProcess::ExitStatus)), this, SLOT(onBspZipProcessFinished(int, QProcess::ExitStatus)));
//    Q_ASSERT(b);

    bspzip_process_->start(ui.bspzip_path->text(), process_arguments);
}

void BspZipGui::getDataFolderFiles(const QDir &dir, QStringList *file_list)
{
    QFileInfoList files = dir.entryInfoList();

    //log(tr("In directory: %1 parsing...").arg(dir.absolutePath()));

    Q_FOREACH(QFileInfo file, files)
    {
        if (file.isDir())
        {
            QDir d( file.absoluteFilePath(), "", QDir::Name | QDir::IgnoreCase, QDir::AllDirs | QDir::Files|  QDir::NoDotAndDotDot );

            //QString logstr = tr("Found directory: %1 parsing...").arg(d.absolutePath());
            //log(logstr);

            getDataFolderFiles(d, file_list);
        }
        else
        {
            (*file_list) << file.absoluteFilePath();

            //log(tr("Found file: %1").arg(file.absoluteFilePath()));
        }
    }
}

void BspZipGui::log(const QString &logstr)
{
    ui.console->appendPlainText(logstr);
    //std::cout << logstr.toLatin1().constData() << std::endl;
}

void BspZipGui::onBspZipProcessFinished(int exitCode, QProcess::ExitStatus exitStatus)
{
    Q_ASSERT(bspzip_process_);
    QByteArray standard_output = bspzip_process_->readAllStandardOutput();
    QByteArray error_output = bspzip_process_->readAllStandardError();

    QString status = exitStatus == QProcess::NormalExit ? "Normal" : "Crashed";

    log(tr("BSPZIP.exe finished with status: %1, exit code: %2").arg(status).arg(exitCode));
    log(tr("BSPZIP.exe output: "));
    log(standard_output);
    if (error_output.size() > 0)
    {
        log(tr("BSPZIP.exe error output: "));
        log(error_output);
    }

    enableAllButtons();

    QMessageBox::information(
        this, tr("Operation Completed"),
        tr("Operation completed. See output window for details"),
        QMessageBox::Ok);
}

bool BspZipGui::filesExist(const QStringList &files)
{
    Q_FOREACH(QString file_path, files)
    {
        QFileInfo fi(file_path);
        if (!fi.exists())
        {
            QMessageBox::warning(this, tr("File Not Found"), tr("The file doesn't exist: %1. Aborting ").arg(file_path));
            return false;
        }
    }
    return true;
}

void BspZipGui::disableAllButtons()
{
    ui.embed->setDisabled(true);
    ui.extract->setDisabled(true);
}

void BspZipGui::enableAllButtons()
{
    ui.embed->setEnabled(true);
    ui.extract->setEnabled(true);
}
<commit_msg>Add minimize, maximize buttons to the main window<commit_after>#include "bspzipgui.h"

#include <iostream>

#include <QFile>
#include <qfiledialog>
#include <QMessageBox>
#include <QProcess>
#include <QSettings>
#include <QTextStream>

BspZipGui::BspZipGui(QWidget *parent, Qt::WindowFlags flags)
    : QDialog(parent, flags),
    bspzip_process_(NULL)
    //progress_dialog_(NULL)
{
    ui.setupUi(this);

    this->setWindowFlags(Qt::Window);

    bspzip_process_ = new QProcess(this);
    bool b = connect(bspzip_process_, SIGNAL(finished(int, QProcess::ExitStatus)), this, SLOT(onBspZipProcessFinished(int, QProcess::ExitStatus)));
    Q_ASSERT(b);

    //progress_dialog_ = new QProgressDialog(tr("Performing operation"),
    //                                       tr("Cancel"), 0, 100, this);
    //progress_dialog_->setMinimumDuration(0);

    QSettings settings("settings.ini", QSettings::IniFormat, this);
    QString bzip = tr("E:\\Games\\Steam\\SteamApps\\common\\nuclear dawn\\bin\\bspzip.exe");
    QString bsp = tr("E:\\Games\\Steam\\SteamApps\\common\\nuclear dawn\\nucleardawn\\maps\\sk_sandbrick.bsp");
    QString data_folder = tr("D:\\Programming\\AlienSwarmMaps\\nucleardawn\\sk_sandbrick");
    ui.bspzip_path->setText(settings.value("BSPZIP_PATH", bzip).toString());
    ui.bspfile_path->setText(settings.value("BSP_FILE_PATH", bsp).toString());
    ui.data_folder_path->setText(settings.value("DATA_FOLDER_PATH", data_folder).toString());
    this->resize(settings.value("SIZE", QSize(this->width(), this->height())).toSize());
}

BspZipGui::~BspZipGui()
{
    QSettings settings("settings.ini", QSettings::IniFormat, this);
    settings.setValue("BSPZIP_PATH", ui.bspzip_path->text());
    settings.setValue("BSP_FILE_PATH", ui.bspfile_path->text());
    settings.setValue("DATA_FOLDER_PATH", ui.data_folder_path->text());
    settings.setValue("SIZE", this->size());
}

void BspZipGui::on_browse_bspzip_clicked()
{
    QString default_dir_path;;
    QFileInfo fi(ui.bspzip_path->text());
    if (fi.exists())
    {
        default_dir_path = fi.absolutePath();
    }
    else
    {
        default_dir_path = QDir::homePath();
    }

    QFileDialog d;
    QString path = d.getOpenFileName(this, tr("Select bspzip.exe file"), default_dir_path);

    if (!path.isEmpty())
        ui.bspzip_path->setText(QDir::toNativeSeparators(path));
}

void BspZipGui::on_browse_bsp_file_clicked()
{
    QString default_dir_path;;
    QFileInfo fi(ui.bspfile_path->text());
    if (fi.exists())
    {
        default_dir_path = fi.absolutePath();
    }
    else
    {
        default_dir_path = QDir::homePath();
    }

    QFileDialog d;
    QString path = d.getOpenFileName(this, tr("Select BSP file"), default_dir_path);

    if (!path.isEmpty())
        ui.bspfile_path->setText(QDir::toNativeSeparators(path));
}

void BspZipGui::on_browse_data_folder_clicked()
{
    QString default_dir_path;;
    QFileInfo fi(ui.data_folder_path->text());
    if (fi.exists())
    {
        if (fi.isDir())
            default_dir_path = fi.absoluteFilePath();
        else
            default_dir_path = fi.absolutePath();
    }
    else
    {
        default_dir_path = QDir::homePath();
    }

    QFileDialog d;
    QString path = d.getExistingDirectory(this, tr("Select folder where to extract BSP or which to embed in BSP"), default_dir_path);

    if (!path.isEmpty())
        ui.data_folder_path->setText(QDir::toNativeSeparators(path));
}

void BspZipGui::on_embed_clicked()
{
    disableAllButtons();

    QStringList check_list;
    check_list << ui.bspzip_path->text() << ui.bspfile_path->text() << ui.data_folder_path->text();
    if (!filesExist(check_list))
    {
        enableAllButtons();
        return;
    }

    QFile bspzip_filelist_file(QDir::homePath() + "/bspzip_filelist.txt");
    log(tr("Opening file for writing: %1").arg( bspzip_filelist_file.fileName() ));
    if (!bspzip_filelist_file.open(QIODevice::WriteOnly | QIODevice::Text))
    {
        log(tr("Failed to open file for writing: %1").arg(bspzip_filelist_file.fileName()));
        enableAllButtons();
        return;
    }

    QDir data_dir( ui.data_folder_path->text(), "", QDir::Name | QDir::IgnoreCase, QDir::AllDirs | QDir::Files|  QDir::NoDotAndDotDot );
    getDataFolderFiles(data_dir, &data_folder_files_);

    if (data_folder_files_.isEmpty())
    {
        log(tr("No files found for embedding in directory: %1 Aborting...").arg(data_dir.absolutePath()));
        enableAllButtons();
        return;
    }

    log("Adding file list into filelist.txt...");

    QTextStream out(&bspzip_filelist_file);
    QString absolute_file_path;
    Q_FOREACH(absolute_file_path, data_folder_files_)
    {
        absolute_file_path = QDir::toNativeSeparators(absolute_file_path);
        QString relative_file_path = absolute_file_path.mid(ui.data_folder_path->text().size() + 1);

        log(relative_file_path);
        log(absolute_file_path);

        // no quotes here as BSPZIP doesn't handle them
        out << relative_file_path << "\n";
        out << absolute_file_path << "\n";
    }
    data_folder_files_.clear(); // must be cleared! or we get bugs

    bspzip_filelist_file.close();
    log(tr("File bspzip_filelist.txt was successfully created"));

    QString bsp_file_path = QDir::toNativeSeparators(ui.bspfile_path->text());
    QString filelist_path = QDir::toNativeSeparators(bspzip_filelist_file.fileName());
    QStringList process_arguments;
    process_arguments << "-addorupdatelist";
    process_arguments << bsp_file_path;
    process_arguments << filelist_path;
    process_arguments << bsp_file_path;

//     if (bspzip_process_)
//     {
//         delete bspzip_process_;
//     }

    log(tr("Starting BSPZIP.EXE with following arguments"));
    Q_FOREACH(QString argument, process_arguments)
    {
        log(argument);
    }

    bspzip_process_->start(ui.bspzip_path->text(), process_arguments);
}

void BspZipGui::on_extract_clicked()
{
    QString bsp_file_path = QDir::toNativeSeparators(ui.bspfile_path->text());
    QString data_folder = QDir::toNativeSeparators(ui.data_folder_path->text());

    QStringList check_list;
    check_list << ui.bspzip_path->text() << bsp_file_path << data_folder;
    if (!filesExist(check_list))
    {
        return;
    }

    QStringList process_arguments;
    process_arguments << "-extractfiles";
    process_arguments << bsp_file_path;
    process_arguments << data_folder;

//     if (bspzip_process_)
//     {
//         delete bspzip_process_;
//     }

//     bspzip_process_ = new QProcess(this);
//     bool b = connect(bspzip_process_, SIGNAL(finished(int, QProcess::ExitStatus)), this, SLOT(onBspZipProcessFinished(int, QProcess::ExitStatus)));
//    Q_ASSERT(b);

    bspzip_process_->start(ui.bspzip_path->text(), process_arguments);
}

void BspZipGui::getDataFolderFiles(const QDir &dir, QStringList *file_list)
{
    QFileInfoList files = dir.entryInfoList();

    //log(tr("In directory: %1 parsing...").arg(dir.absolutePath()));

    Q_FOREACH(QFileInfo file, files)
    {
        if (file.isDir())
        {
            QDir d( file.absoluteFilePath(), "", QDir::Name | QDir::IgnoreCase, QDir::AllDirs | QDir::Files|  QDir::NoDotAndDotDot );

            //QString logstr = tr("Found directory: %1 parsing...").arg(d.absolutePath());
            //log(logstr);

            getDataFolderFiles(d, file_list);
        }
        else
        {
            (*file_list) << file.absoluteFilePath();

            //log(tr("Found file: %1").arg(file.absoluteFilePath()));
        }
    }
}

void BspZipGui::log(const QString &logstr)
{
    ui.console->appendPlainText(logstr);
    //std::cout << logstr.toLatin1().constData() << std::endl;
}

void BspZipGui::onBspZipProcessFinished(int exitCode, QProcess::ExitStatus exitStatus)
{
    Q_ASSERT(bspzip_process_);
    QByteArray standard_output = bspzip_process_->readAllStandardOutput();
    QByteArray error_output = bspzip_process_->readAllStandardError();

    QString status = exitStatus == QProcess::NormalExit ? "Normal" : "Crashed";

    log(tr("BSPZIP.exe finished with status: %1, exit code: %2").arg(status).arg(exitCode));
    log(tr("BSPZIP.exe output: "));
    log(standard_output);
    if (error_output.size() > 0)
    {
        log(tr("BSPZIP.exe error output: "));
        log(error_output);
    }

    enableAllButtons();

    QMessageBox::information(
        this, tr("Operation Completed"),
        tr("Operation completed. See output window for details"),
        QMessageBox::Ok);
}

bool BspZipGui::filesExist(const QStringList &files)
{
    Q_FOREACH(QString file_path, files)
    {
        QFileInfo fi(file_path);
        if (!fi.exists())
        {
            QMessageBox::warning(this, tr("File Not Found"), tr("The file doesn't exist: %1. Aborting ").arg(file_path));
            return false;
        }
    }
    return true;
}

void BspZipGui::disableAllButtons()
{
    ui.embed->setDisabled(true);
    ui.extract->setDisabled(true);
}

void BspZipGui::enableAllButtons()
{
    ui.embed->setEnabled(true);
    ui.extract->setEnabled(true);
}
<|endoftext|>


<commit_before>/** @file
    @brief Main file for a video-based HMD tracker.

    @date 2015

    @author
    Sensics, Inc.
    <http://sensics.com/osvr>
*/

// Copyright 2015 Sensics, Inc.
//
// 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.

// Internal Includes
#include "VideoBasedTracker.h"
#include "HDKLedIdentifierFactory.h"
#include "CameraParameters.h"
#include "ImageSource.h"
#include "ImageSourceFactories.h"
#include <osvr/PluginKit/PluginKit.h>
#include <osvr/PluginKit/TrackerInterfaceC.h>
#include "GetOptionalParameter.h"

// Generated JSON header file
#include "com_osvr_VideoBasedHMDTracker_json.h"

// Library/third-party includes
#include <opencv2/core/core.hpp> // for basic OpenCV types
#include <opencv2/core/operations.hpp>
#include <opencv2/highgui/highgui.hpp> // for image capture
#include <opencv2/imgproc/imgproc.hpp> // for image scaling
#include <json/value.h>
#include <json/reader.h>

#include <boost/noncopyable.hpp>

// Standard includes
#include <iostream>
#include <iomanip>
#include <sstream>
#include <memory>

// Define the constant below to print timing information (how many updates
// per second we are getting).
//#define VBHMD_TIMING

// Define the constant below to set a directory to save the video frames that
// are acquired with files in a format that can later be read by
// VBHMD_FAKE_IMAGES
//#define VBHMD_SAVE_IMAGES "./Frames"

// Anonymous namespace to avoid symbol collision
namespace {

class VideoBasedHMDTracker : boost::noncopyable {
  public:
    VideoBasedHMDTracker(OSVR_PluginRegContext ctx,
                         osvr::vbtracker::ImageSourcePtr &&source,
                         int devNumber = 0,
                         osvr::vbtracker::ConfigParams const &params =
                             osvr::vbtracker::ConfigParams{})
        : m_source(std::move(source)), m_vbtracker(params), m_params(params) {
        // Set the number of threads for OpenCV to use.
        cv::setNumThreads(params.numThreads);

        /// Create the initialization options
        OSVR_DeviceInitOptions opts = osvrDeviceCreateInitOptions(ctx);

        // Configure the tracker interface.
        osvrDeviceTrackerConfigure(opts, &m_tracker);

        /// Come up with a device name
        std::ostringstream os;
        os << "TrackedCamera" << devNumber << "_" << 0;

        /// Create an asynchronous (threaded) device
        m_dev.initAsync(ctx, os.str(), opts);

        /// Send JSON descriptor
        m_dev.sendJsonDescriptor(com_osvr_VideoBasedHMDTracker_json);

        /// Register update callback
        m_dev.registerUpdateCallback(this);
    }

    OSVR_ReturnCode update();

    /// Should be called immediately after construction for specifying the
    /// particulars of tracking.
    void addSensor(osvr::vbtracker::LedIdentifierPtr &&identifier,
                   osvr::vbtracker::CameraParameters const &params,
                   osvr::vbtracker::Point3Vector const &locations,
                   size_t requiredInliers = 4, size_t permittedOutliers = 2) {
        m_vbtracker.addSensor(std::move(identifier), params.cameraMatrix,
                              params.distortionParameters, locations,
                              requiredInliers, permittedOutliers);
    }
    void addSensor(osvr::vbtracker::LedIdentifierPtr &&identifier,
                   osvr::vbtracker::CameraParameters const &params,
                   osvr::vbtracker::Point3Vector const &locations,
                   std::vector<double> const &variance,
                   size_t requiredInliers = 4, size_t permittedOutliers = 2) {
        m_vbtracker.addSensor(std::move(identifier), params.cameraMatrix,
                              params.distortionParameters, locations, variance,
                              requiredInliers, permittedOutliers);
    }

  private:
    osvr::pluginkit::DeviceToken m_dev;
    OSVR_TrackerDeviceInterface m_tracker;
    osvr::vbtracker::ImageSourcePtr m_source;
    osvr::vbtracker::ConfigParams const m_params;
#ifdef VBHMD_SAVE_IMAGES
    int m_imageNum = 1;
#endif
    cv::Mat m_frame;
    cv::Mat m_imageGray;

    osvr::vbtracker::VideoBasedTracker m_vbtracker;
};

inline OSVR_ReturnCode VideoBasedHMDTracker::update() {
    if (!m_source->ok()) {
        // Couldn't open the camera.  Failing silently for now. Maybe the
        // camera will be plugged back in later.
        return OSVR_RETURN_SUCCESS;
    }

    //==================================================================
    // Trigger a camera grab.
    if (!m_source->grab()) {
        // Couldn't open the camera.  Failing silently for now. Maybe the
        // camera will be plugged back in later.
        return OSVR_RETURN_SUCCESS;
    }

    //==================================================================
    // Keep track of when we got the image, since that is our
    // best estimate for when the tracker was at the specified
    // pose.
    // TODO: Back-date the aquisition time by the expected image
    // transfer time and perhaps by half the exposure time to say
    // when the photons actually arrived.
    OSVR_TimeValue timestamp;
    osvrTimeValueGetNow(&timestamp);
    // Pull the image into an OpenCV matrix named m_frame.
    m_source->retrieve(m_frame, m_imageGray);

#ifdef VBHMD_SAVE_IMAGES
    // If we're supposed to save images, make file names that match the
    // format we need to read them back in again and save the images.
    std::ostringstream fileName;
    fileName << VBHMD_SAVE_IMAGES << "/";
    fileName << std::setfill('0') << std::setw(4) << m_imageNum++;
    fileName << ".tif";
    if (!cv::imwrite(fileName.str(), m_frame)) {
        std::cerr << "Could not write image to " << fileName.str() << std::endl;
    }

#endif

#ifdef VBHMD_TIMING
    //==================================================================
    // Time our performance
    static struct timeval last = {0, 0};
    if (last.tv_sec == 0) {
        vrpn_gettimeofday(&last, NULL);
    }
    static unsigned count = 0;
    if (++count == 100) {
        struct timeval now;
        vrpn_gettimeofday(&now, NULL);
        double duration = vrpn_TimevalDurationSeconds(now, last);
        std::cout << "Video-based tracker: update rate " << count / duration
                  << " hz" << std::endl;
        count = 0;
        last = now;
    }
#endif

    m_vbtracker.processImage(
        m_frame, m_imageGray, timestamp,
        [&](OSVR_ChannelCount sensor, OSVR_Pose3 const &pose) {

            //==================================================================
            // Report the new pose, time-stamped with the time we
            // received the image from the camera.
            osvrDeviceTrackerSendPoseTimestamped(m_dev, m_tracker, &pose,
                                                 sensor, &timestamp);
        });

    return OSVR_RETURN_SUCCESS;
}

class HardwareDetection {
  public:
    using CameraFactoryType = std::function<osvr::vbtracker::ImageSourcePtr()>;
    using SensorSetupType = std::function<void(VideoBasedHMDTracker &)>;
    HardwareDetection(CameraFactoryType camFactory, SensorSetupType setup,
                      int cameraID = 0,
                      osvr::vbtracker::ConfigParams const &params =
                          osvr::vbtracker::ConfigParams{})
        : m_found(false), m_cameraFactory(camFactory), m_sensorSetup(setup),
          m_cameraID(cameraID), m_params(params) {}

    OSVR_ReturnCode operator()(OSVR_PluginRegContext ctx) {
        if (m_found) {
            return OSVR_RETURN_SUCCESS;
        }
        auto src = m_cameraFactory();
        if (!src || !src->ok()) {
            return OSVR_RETURN_FAILURE;
        }
        m_found = true;

        /// Create our device object, passing the context and moving the camera.
        std::cout << "Opening camera " << m_cameraID << std::endl;
        auto newTracker = osvr::pluginkit::registerObjectForDeletion(
            ctx, new VideoBasedHMDTracker(ctx, std::move(src), m_cameraID,
                                          m_params));
        m_sensorSetup(*newTracker);
        return OSVR_RETURN_SUCCESS;
    }

  private:
    /// @brief Have we found our device yet? (this limits the plugin to one
    /// instance, so that only one tracker will use this camera.)
    bool m_found = false;

    CameraFactoryType m_cameraFactory;
    SensorSetupType m_sensorSetup;

    int m_cameraID; //< Which OpenCV camera should we open?
    osvr::vbtracker::ConfigParams const m_params;
};

class ConfiguredDeviceConstructor {
  public:
    /// @brief This is the required signature for a device instantiation
    /// callback.
    OSVR_ReturnCode operator()(OSVR_PluginRegContext ctx, const char *params) {
        // Read the JSON data from parameters.
        Json::Value root;
        if (params) {
            Json::Reader r;
            if (!r.parse(params, root)) {
                std::cerr << "Could not parse parameters!" << std::endl;
            }
        }

        // Read these parameters from a "params" field in the device Json
        // configuration file.

        // Using `get` here instead of `[]` lets us provide a default value.
        int cameraID = root.get("cameraID", 0).asInt();
        bool showDebug = root.get("showDebug", false).asBool();
        osvr::vbtracker::ConfigParams config;
        config.debug = showDebug;

        using osvr::vbtracker::getOptionalParameter;
        getOptionalParameter(config.additionalPrediction, root,
                             "additionalPrediction");
        getOptionalParameter(config.maxResidual, root, "maxResidual");
        getOptionalParameter(config.initialBeaconError, root,
                             "initialBeaconError");
        getOptionalParameter(config.blobMoveThreshold, root,
                             "blobMoveThreshold");
        getOptionalParameter(config.numThreads, root, "numThreads");

        Json::Value const &processNoise = root["processNoiseAutocorrelation"];
        if (processNoise.isArray()) {
            if (processNoise.size() != 6) {
                std::cout << "Got a processNoiseAutocorrelation array, but it "
                             "needs exactly 6 elements, and instead contains "
                          << processNoise.size() << " so will be ignored."
                          << std::endl;
            } else {
                for (Json::Value::ArrayIndex i = 0; i < 6; ++i) {
                    config.processNoiseAutocorrelation[i] =
                        processNoise[i].asDouble();
                }
            }
        }
        getOptionalParameter(config.linearVelocityDecayCoefficient, root,
                             "linearVelocityDecayCoefficient");
        getOptionalParameter(config.angularVelocityDecayCoefficient, root,
                             "angularVelocityDecayCoefficient");
        getOptionalParameter(config.measurementVarianceScaleFactor, root,
                             "measurementVarianceScaleFactor");

        if (root.isMember("blobParams")) {
            Json::Value const &blob = root["blobParams"];

            getOptionalParameter(config.blobParams.absoluteMinThreshold, blob,
                                 "absoluteMinThreshold");
            getOptionalParameter(config.blobParams.minDistBetweenBlobs, blob,
                                 "minDistBetweenBlobs");
            getOptionalParameter(config.blobParams.minArea, blob, "minArea");
            getOptionalParameter(config.blobParams.minCircularity, blob,
                                 "minCircularity");
            getOptionalParameter(config.blobParams.minThresholdAlpha, blob,
                                 "minThresholdAlpha");
            getOptionalParameter(config.blobParams.maxThresholdAlpha, blob,
                                 "maxThresholdAlpha");
            getOptionalParameter(config.blobParams.thresholdSteps, blob,
                                 "thresholdSteps");
        }

        /// @todo get this (and the path) from the config file
        bool fakeImages = false;
        if (fakeImages) {
            /// Immediately create a "fake images" tracker.
            auto path = std::string{};
            // fake images
            auto src = osvr::vbtracker::openImageFileSequence(path);
            if (!src) {
                return OSVR_RETURN_FAILURE;
            }
            auto newTracker = osvr::pluginkit::registerObjectForDeletion(
                ctx, new VideoBasedHMDTracker(ctx, std::move(src), cameraID,
                                              config));
            auto camParams = osvr::vbtracker::getSimulatedHDKCameraParameters();
            newTracker->addSensor(
                osvr::vbtracker::createHDKLedIdentifierSimulated(0), camParams,
                osvr::vbtracker::OsvrHdkLedLocations_SENSOR0, 4, 2);
            // There are sometimes only four beacons on the back unit (two of
            // the LEDs are disabled), so we let things work with just those.
            newTracker->addSensor(
                osvr::vbtracker::createHDKLedIdentifierSimulated(1), camParams,
                osvr::vbtracker::OsvrHdkLedLocations_SENSOR1, 4, 0);
            return OSVR_RETURN_SUCCESS;
        }
#if 0
        bool isOculusCamera = (width == 376) && (height == 480);
#endif

#ifdef _WIN32
        /// @todo speed of a function pointer here vs a lambda?
        auto cameraFactory = &osvr::vbtracker::openHDKCameraDirectShow;

#else // !_WIN32
        /// @todo This is rather crude, as we can't select the exact camera we
        /// want, nor set the "50Hz" high-gain mode (and only works with HDK
        /// camera firmware v7 and up). Presumably eventually use libuvc on
        /// other platforms instead, at least for the HDK IR camera.

        auto cameraFactory = [=] {
            return osvr::vbtracker::openOpenCVCamera(cameraID);
        };
#endif

        /// Function to execute after the device is created, to add the sensors.
        auto setupHDKParamsAndSensors = [](VideoBasedHMDTracker &newTracker) {
            auto camParams = osvr::vbtracker::getHDKCameraParameters();
            newTracker.addSensor(
                osvr::vbtracker::createHDKLedIdentifier(0), camParams,
                osvr::vbtracker::OsvrHdkLedLocations_SENSOR0,
                osvr::vbtracker::OsvrHdkLedVariances_SENSOR0, 6, 0);
            newTracker.addSensor(
                osvr::vbtracker::createHDKLedIdentifier(1), camParams,
                osvr::vbtracker::OsvrHdkLedLocations_SENSOR1, 4, 0);
        };

        // OK, now that we have our parameters, create the device.
        osvr::pluginkit::PluginContext context(ctx);
        context.registerHardwareDetectCallback(new HardwareDetection(
            cameraFactory, setupHDKParamsAndSensors, cameraID, config));

        return OSVR_RETURN_SUCCESS;
    }
};

} // namespace

OSVR_PLUGIN(com_osvr_VideoBasedHMDTracker) {
    osvr::pluginkit::PluginContext context(ctx);

    /// Tell the core we're available to create a device object.
    osvr::pluginkit::registerDriverInstantiationCallback(
        ctx, "VideoBasedHMDTracker", new ConfiguredDeviceConstructor);

    return OSVR_RETURN_SUCCESS;
}
<commit_msg>Use the new overload to read the noise params<commit_after>/** @file
    @brief Main file for a video-based HMD tracker.

    @date 2015

    @author
    Sensics, Inc.
    <http://sensics.com/osvr>
*/

// Copyright 2015 Sensics, Inc.
//
// 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.

// Internal Includes
#include "VideoBasedTracker.h"
#include "HDKLedIdentifierFactory.h"
#include "CameraParameters.h"
#include "ImageSource.h"
#include "ImageSourceFactories.h"
#include <osvr/PluginKit/PluginKit.h>
#include <osvr/PluginKit/TrackerInterfaceC.h>
#include "GetOptionalParameter.h"

// Generated JSON header file
#include "com_osvr_VideoBasedHMDTracker_json.h"

// Library/third-party includes
#include <opencv2/core/core.hpp> // for basic OpenCV types
#include <opencv2/core/operations.hpp>
#include <opencv2/highgui/highgui.hpp> // for image capture
#include <opencv2/imgproc/imgproc.hpp> // for image scaling
#include <json/value.h>
#include <json/reader.h>

#include <boost/noncopyable.hpp>

// Standard includes
#include <iostream>
#include <iomanip>
#include <sstream>
#include <memory>

// Define the constant below to print timing information (how many updates
// per second we are getting).
//#define VBHMD_TIMING

// Define the constant below to set a directory to save the video frames that
// are acquired with files in a format that can later be read by
// VBHMD_FAKE_IMAGES
//#define VBHMD_SAVE_IMAGES "./Frames"

// Anonymous namespace to avoid symbol collision
namespace {

class VideoBasedHMDTracker : boost::noncopyable {
  public:
    VideoBasedHMDTracker(OSVR_PluginRegContext ctx,
                         osvr::vbtracker::ImageSourcePtr &&source,
                         int devNumber = 0,
                         osvr::vbtracker::ConfigParams const &params =
                             osvr::vbtracker::ConfigParams{})
        : m_source(std::move(source)), m_vbtracker(params), m_params(params) {
        // Set the number of threads for OpenCV to use.
        cv::setNumThreads(params.numThreads);

        /// Create the initialization options
        OSVR_DeviceInitOptions opts = osvrDeviceCreateInitOptions(ctx);

        // Configure the tracker interface.
        osvrDeviceTrackerConfigure(opts, &m_tracker);

        /// Come up with a device name
        std::ostringstream os;
        os << "TrackedCamera" << devNumber << "_" << 0;

        /// Create an asynchronous (threaded) device
        m_dev.initAsync(ctx, os.str(), opts);

        /// Send JSON descriptor
        m_dev.sendJsonDescriptor(com_osvr_VideoBasedHMDTracker_json);

        /// Register update callback
        m_dev.registerUpdateCallback(this);
    }

    OSVR_ReturnCode update();

    /// Should be called immediately after construction for specifying the
    /// particulars of tracking.
    void addSensor(osvr::vbtracker::LedIdentifierPtr &&identifier,
                   osvr::vbtracker::CameraParameters const &params,
                   osvr::vbtracker::Point3Vector const &locations,
                   size_t requiredInliers = 4, size_t permittedOutliers = 2) {
        m_vbtracker.addSensor(std::move(identifier), params.cameraMatrix,
                              params.distortionParameters, locations,
                              requiredInliers, permittedOutliers);
    }
    void addSensor(osvr::vbtracker::LedIdentifierPtr &&identifier,
                   osvr::vbtracker::CameraParameters const &params,
                   osvr::vbtracker::Point3Vector const &locations,
                   std::vector<double> const &variance,
                   size_t requiredInliers = 4, size_t permittedOutliers = 2) {
        m_vbtracker.addSensor(std::move(identifier), params.cameraMatrix,
                              params.distortionParameters, locations, variance,
                              requiredInliers, permittedOutliers);
    }

  private:
    osvr::pluginkit::DeviceToken m_dev;
    OSVR_TrackerDeviceInterface m_tracker;
    osvr::vbtracker::ImageSourcePtr m_source;
    osvr::vbtracker::ConfigParams const m_params;
#ifdef VBHMD_SAVE_IMAGES
    int m_imageNum = 1;
#endif
    cv::Mat m_frame;
    cv::Mat m_imageGray;

    osvr::vbtracker::VideoBasedTracker m_vbtracker;
};

inline OSVR_ReturnCode VideoBasedHMDTracker::update() {
    if (!m_source->ok()) {
        // Couldn't open the camera.  Failing silently for now. Maybe the
        // camera will be plugged back in later.
        return OSVR_RETURN_SUCCESS;
    }

    //==================================================================
    // Trigger a camera grab.
    if (!m_source->grab()) {
        // Couldn't open the camera.  Failing silently for now. Maybe the
        // camera will be plugged back in later.
        return OSVR_RETURN_SUCCESS;
    }

    //==================================================================
    // Keep track of when we got the image, since that is our
    // best estimate for when the tracker was at the specified
    // pose.
    // TODO: Back-date the aquisition time by the expected image
    // transfer time and perhaps by half the exposure time to say
    // when the photons actually arrived.
    OSVR_TimeValue timestamp;
    osvrTimeValueGetNow(&timestamp);
    // Pull the image into an OpenCV matrix named m_frame.
    m_source->retrieve(m_frame, m_imageGray);

#ifdef VBHMD_SAVE_IMAGES
    // If we're supposed to save images, make file names that match the
    // format we need to read them back in again and save the images.
    std::ostringstream fileName;
    fileName << VBHMD_SAVE_IMAGES << "/";
    fileName << std::setfill('0') << std::setw(4) << m_imageNum++;
    fileName << ".tif";
    if (!cv::imwrite(fileName.str(), m_frame)) {
        std::cerr << "Could not write image to " << fileName.str() << std::endl;
    }

#endif

#ifdef VBHMD_TIMING
    //==================================================================
    // Time our performance
    static struct timeval last = {0, 0};
    if (last.tv_sec == 0) {
        vrpn_gettimeofday(&last, NULL);
    }
    static unsigned count = 0;
    if (++count == 100) {
        struct timeval now;
        vrpn_gettimeofday(&now, NULL);
        double duration = vrpn_TimevalDurationSeconds(now, last);
        std::cout << "Video-based tracker: update rate " << count / duration
                  << " hz" << std::endl;
        count = 0;
        last = now;
    }
#endif

    m_vbtracker.processImage(
        m_frame, m_imageGray, timestamp,
        [&](OSVR_ChannelCount sensor, OSVR_Pose3 const &pose) {

            //==================================================================
            // Report the new pose, time-stamped with the time we
            // received the image from the camera.
            osvrDeviceTrackerSendPoseTimestamped(m_dev, m_tracker, &pose,
                                                 sensor, &timestamp);
        });

    return OSVR_RETURN_SUCCESS;
}

class HardwareDetection {
  public:
    using CameraFactoryType = std::function<osvr::vbtracker::ImageSourcePtr()>;
    using SensorSetupType = std::function<void(VideoBasedHMDTracker &)>;
    HardwareDetection(CameraFactoryType camFactory, SensorSetupType setup,
                      int cameraID = 0,
                      osvr::vbtracker::ConfigParams const &params =
                          osvr::vbtracker::ConfigParams{})
        : m_found(false), m_cameraFactory(camFactory), m_sensorSetup(setup),
          m_cameraID(cameraID), m_params(params) {}

    OSVR_ReturnCode operator()(OSVR_PluginRegContext ctx) {
        if (m_found) {
            return OSVR_RETURN_SUCCESS;
        }
        auto src = m_cameraFactory();
        if (!src || !src->ok()) {
            return OSVR_RETURN_FAILURE;
        }
        m_found = true;

        /// Create our device object, passing the context and moving the camera.
        std::cout << "Opening camera " << m_cameraID << std::endl;
        auto newTracker = osvr::pluginkit::registerObjectForDeletion(
            ctx, new VideoBasedHMDTracker(ctx, std::move(src), m_cameraID,
                                          m_params));
        m_sensorSetup(*newTracker);
        return OSVR_RETURN_SUCCESS;
    }

  private:
    /// @brief Have we found our device yet? (this limits the plugin to one
    /// instance, so that only one tracker will use this camera.)
    bool m_found = false;

    CameraFactoryType m_cameraFactory;
    SensorSetupType m_sensorSetup;

    int m_cameraID; //< Which OpenCV camera should we open?
    osvr::vbtracker::ConfigParams const m_params;
};

class ConfiguredDeviceConstructor {
  public:
    /// @brief This is the required signature for a device instantiation
    /// callback.
    OSVR_ReturnCode operator()(OSVR_PluginRegContext ctx, const char *params) {
        // Read the JSON data from parameters.
        Json::Value root;
        if (params) {
            Json::Reader r;
            if (!r.parse(params, root)) {
                std::cerr << "Could not parse parameters!" << std::endl;
            }
        }

        // Read these parameters from a "params" field in the device Json
        // configuration file.

        // Using `get` here instead of `[]` lets us provide a default value.
        int cameraID = root.get("cameraID", 0).asInt();
        bool showDebug = root.get("showDebug", false).asBool();
        osvr::vbtracker::ConfigParams config;
        config.debug = showDebug;

        using osvr::vbtracker::getOptionalParameter;
        getOptionalParameter(config.additionalPrediction, root,
                             "additionalPrediction");
        getOptionalParameter(config.maxResidual, root, "maxResidual");
        getOptionalParameter(config.initialBeaconError, root,
                             "initialBeaconError");
        getOptionalParameter(config.blobMoveThreshold, root,
                             "blobMoveThreshold");
        getOptionalParameter(config.numThreads, root, "numThreads");

        getOptionalParameter(config.processNoiseAutocorrelation, root,
                             "processNoiseAutocorrelation");
        getOptionalParameter(config.linearVelocityDecayCoefficient, root,
                             "linearVelocityDecayCoefficient");
        getOptionalParameter(config.angularVelocityDecayCoefficient, root,
                             "angularVelocityDecayCoefficient");
        getOptionalParameter(config.measurementVarianceScaleFactor, root,
                             "measurementVarianceScaleFactor");

        if (root.isMember("blobParams")) {
            Json::Value const &blob = root["blobParams"];

            getOptionalParameter(config.blobParams.absoluteMinThreshold, blob,
                                 "absoluteMinThreshold");
            getOptionalParameter(config.blobParams.minDistBetweenBlobs, blob,
                                 "minDistBetweenBlobs");
            getOptionalParameter(config.blobParams.minArea, blob, "minArea");
            getOptionalParameter(config.blobParams.minCircularity, blob,
                                 "minCircularity");
            getOptionalParameter(config.blobParams.minThresholdAlpha, blob,
                                 "minThresholdAlpha");
            getOptionalParameter(config.blobParams.maxThresholdAlpha, blob,
                                 "maxThresholdAlpha");
            getOptionalParameter(config.blobParams.thresholdSteps, blob,
                                 "thresholdSteps");
        }

        /// @todo get this (and the path) from the config file
        bool fakeImages = false;
        if (fakeImages) {
            /// Immediately create a "fake images" tracker.
            auto path = std::string{};
            // fake images
            auto src = osvr::vbtracker::openImageFileSequence(path);
            if (!src) {
                return OSVR_RETURN_FAILURE;
            }
            auto newTracker = osvr::pluginkit::registerObjectForDeletion(
                ctx, new VideoBasedHMDTracker(ctx, std::move(src), cameraID,
                                              config));
            auto camParams = osvr::vbtracker::getSimulatedHDKCameraParameters();
            newTracker->addSensor(
                osvr::vbtracker::createHDKLedIdentifierSimulated(0), camParams,
                osvr::vbtracker::OsvrHdkLedLocations_SENSOR0, 4, 2);
            // There are sometimes only four beacons on the back unit (two of
            // the LEDs are disabled), so we let things work with just those.
            newTracker->addSensor(
                osvr::vbtracker::createHDKLedIdentifierSimulated(1), camParams,
                osvr::vbtracker::OsvrHdkLedLocations_SENSOR1, 4, 0);
            return OSVR_RETURN_SUCCESS;
        }
#if 0
        bool isOculusCamera = (width == 376) && (height == 480);
#endif

#ifdef _WIN32
        /// @todo speed of a function pointer here vs a lambda?
        auto cameraFactory = &osvr::vbtracker::openHDKCameraDirectShow;

#else // !_WIN32
        /// @todo This is rather crude, as we can't select the exact camera we
        /// want, nor set the "50Hz" high-gain mode (and only works with HDK
        /// camera firmware v7 and up). Presumably eventually use libuvc on
        /// other platforms instead, at least for the HDK IR camera.

        auto cameraFactory = [=] {
            return osvr::vbtracker::openOpenCVCamera(cameraID);
        };
#endif

        /// Function to execute after the device is created, to add the sensors.
        auto setupHDKParamsAndSensors = [](VideoBasedHMDTracker &newTracker) {
            auto camParams = osvr::vbtracker::getHDKCameraParameters();
            newTracker.addSensor(
                osvr::vbtracker::createHDKLedIdentifier(0), camParams,
                osvr::vbtracker::OsvrHdkLedLocations_SENSOR0,
                osvr::vbtracker::OsvrHdkLedVariances_SENSOR0, 6, 0);
            newTracker.addSensor(
                osvr::vbtracker::createHDKLedIdentifier(1), camParams,
                osvr::vbtracker::OsvrHdkLedLocations_SENSOR1, 4, 0);
        };

        // OK, now that we have our parameters, create the device.
        osvr::pluginkit::PluginContext context(ctx);
        context.registerHardwareDetectCallback(new HardwareDetection(
            cameraFactory, setupHDKParamsAndSensors, cameraID, config));

        return OSVR_RETURN_SUCCESS;
    }
};

} // namespace

OSVR_PLUGIN(com_osvr_VideoBasedHMDTracker) {
    osvr::pluginkit::PluginContext context(ctx);

    /// Tell the core we're available to create a device object.
    osvr::pluginkit::registerDriverInstantiationCallback(
        ctx, "VideoBasedHMDTracker", new ConfiguredDeviceConstructor);

    return OSVR_RETURN_SUCCESS;
}
<|endoftext|>


<commit_before>//
// Copyright (c) 2017 The nanoFramework project contributors
// See LICENSE file in the project root for full license information.
//

#include <hal.h>
#include <cmsis_os.h>

#include "nanoCLR_Types.h"

#if (__CORTEX_M == 0)
    #error "ITM port is not available on Cortex-M0(+) cores. Need to set CMake option SWO_OUTPUT to OFF."
#else

// number of attempts to write to the ITM port before quit
#define ITM_WRITE_ATTEMPTS      10

extern "C" void SwoInit()
{
    // set SWO pin (PB3) to alternate mode (0 == the status after RESET)
    // in case it's being set to a different function in board config
    palSetPadMode(GPIOB, 0x03, PAL_MODE_ALTERNATE(0) );

    // enable trace in core debug register
    CoreDebug->DEMCR = CoreDebug_DEMCR_TRCENA_Msk;

    // enable trace pins with async trace
    DBGMCU->CR |= DBGMCU_CR_TRACE_IOEN | ~DBGMCU_CR_TRACE_MODE;

    // default speed for ST-Link is 2000kHz
    uint32_t swoSpeed = 2000000;
    uint32_t swoPrescaler = (STM32_SYSCLK / swoSpeed) + 1;

    // Write the TPIU Current Port Size Register to the desired value (default is 0x1 for a 1-bit port size)
    TPI->CSPSR = 1;
    // Write TPIU Formatter and Flush Control Register
    TPI->FFCR = 0x100;
    // Write the TPIU Select Pin Protocol to select the sync or async mode. Example: 0x2 for async NRZ mode (UART like)
    TPI->SPPR = 2;

    // Write clock prescaler
    TPI->ACPR = swoPrescaler;

    // unlock Write Access to the ITM registers
    ITM->LAR = 0xC5ACCE55;

    // core debug:
    // Trace bus ID for TPIU
    // enable events
    // enable sync packets
    // time stamp enable
    // trace main enable
    ITM->TCR = ITM_TCR_TraceBusID_Msk | ITM_TCR_SWOENA_Msk | ITM_TCR_SYNCENA_Msk | ITM_TCR_ITMENA_Msk; /* ITM Trace Control Register */

    // enable stimulus port 0
    // we are not using any other port right now
    ITM->TER |= 1;
    ITM->TPR = ITM_TPR_PRIVMASK_Msk;
}

extern "C" void SwoPrintChar(char c)
{
    ASSERT((ITM->TCR & ITM_TCR_ITMENA_Msk) != 0UL);
    ASSERT((ITM->TER & 1UL               ) != 0UL);

    uint32_t retryCounter = ITM_WRITE_ATTEMPTS;
    bool okToTx = ITM->PORT[0U].u32 == 0UL;

    // wait (with timeout) until ITM port TX buffer is available
    while( !okToTx &&
           (retryCounter > 0) )
    {
        // do... nothing
        __NOP();

        // decrease retry counter
        retryCounter--;

        // check again
        okToTx = (ITM->PORT[0U].u32 == 0UL);
    }

    if(okToTx)
    {
        ITM->PORT[0U].u8 = (uint8_t)c;
    }
}

extern "C" void SwoPrintString(const char *s)
{
    // print char until terminator is found
    while(*s)
    {
        SwoPrintChar(*s++);
    }
}

// this function is heavily based in the CMSIS ITM_SendChar
// but with small performance improvements as we are sending a string not individual chars
__STATIC_INLINE uint32_t GenericPort_Write_CMSIS(int portNum, const char* data, size_t size)
{
    (void)portNum;

    ASSERT((ITM->TCR & ITM_TCR_ITMENA_Msk) != 0UL);
    ASSERT((ITM->TER & 1UL               ) != 0UL);

    char* p = (char*)data;
    uint32_t counter = 0;
    uint32_t retryCounter;
    bool okToTx = ITM->PORT[0U].u32 == 0UL;

    while(  *p != '\0' &&
            counter < size )
    {
        retryCounter = ITM_WRITE_ATTEMPTS;

        // wait (with timeout) until ITM port TX buffer is available
        while( !okToTx &&
               (retryCounter > 0) )
        {
            // do... nothing
            __NOP();

            // decrease retry counter
            retryCounter--;

            // check again
            okToTx = (ITM->PORT[0U].u32 == 0UL);
        }

        if(okToTx)
        {
            ITM->PORT[0U].u8 = (uint8_t)*p++;
        }

        counter++;
    }

    return counter;
}

uint32_t GenericPort_Write(int portNum, const char* data, size_t size)
{
    return GenericPort_Write_CMSIS(portNum, data, size);
}

#endif // (__CORTEX_M == 0)
<commit_msg>Fix SWO output (#1535)<commit_after>//
// Copyright (c) 2017 The nanoFramework project contributors
// See LICENSE file in the project root for full license information.
//

#include <hal.h>
#include <cmsis_os.h>

#include "nanoCLR_Types.h"

#if (__CORTEX_M == 0)
    #error "ITM port is not available on Cortex-M0(+) cores. Need to set CMake option SWO_OUTPUT to OFF."
#else

// number of attempts to write to the ITM port before quitting
// developer note: this is an arbitrary value from trial & error attempts to get a satisfactory output on ST-Link SWO viewer
#define ITM_WRITE_ATTEMPTS      20000

extern "C" void SwoInit()
{
    // set SWO pin (PB3) to alternate mode (0 == the status after RESET)
    // in case it's being set to a different function in board config
    palSetPadMode(GPIOB, 0x03, PAL_MODE_ALTERNATE(0) );

    // enable trace in core debug register
    CoreDebug->DEMCR = CoreDebug_DEMCR_TRCENA_Msk;

    // enable trace pins with async trace
    DBGMCU->CR |= DBGMCU_CR_TRACE_IOEN | ~DBGMCU_CR_TRACE_MODE;

    // default speed for ST-Link is 2000kHz
    uint32_t swoSpeed = 2000000;
    uint32_t swoPrescaler = (STM32_SYSCLK / swoSpeed) + 1;

    // Write the TPIU Current Port Size Register to the desired value (default is 0x1 for a 1-bit port size)
    TPI->CSPSR = 1;
    // Write TPIU Formatter and Flush Control Register
    TPI->FFCR = 0x100;
    // Write the TPIU Select Pin Protocol to select the sync or async mode. Example: 0x2 for async NRZ mode (UART like)
    TPI->SPPR = 2;

    // Write clock prescaler
    TPI->ACPR = swoPrescaler;

    // unlock Write Access to the ITM registers
    ITM->LAR = 0xC5ACCE55;

    // core debug:
    // Trace bus ID for TPIU
    // enable events
    // enable sync packets
    // time stamp enable
    // trace main enable
    ITM->TCR = ITM_TCR_TraceBusID_Msk | ITM_TCR_SWOENA_Msk | ITM_TCR_SYNCENA_Msk | ITM_TCR_ITMENA_Msk; /* ITM Trace Control Register */

    // enable stimulus port 0
    // we are not using any other port right now
    ITM->TER |= 1;
    ITM->TPR = ITM_TPR_PRIVMASK_Msk;
}

extern "C" void SwoPrintChar(char c)
{
    ASSERT((ITM->TCR & ITM_TCR_ITMENA_Msk) != 0UL);
    ASSERT((ITM->TER & 1UL               ) != 0UL);

    uint32_t retryCounter = ITM_WRITE_ATTEMPTS;
    bool okToTx = (ITM->PORT[0U].u32 == 1UL);

    // wait (with timeout) until ITM port TX buffer is available
    while( !okToTx &&
           (retryCounter > 0) )
    {
        // do... nothing
        __NOP();

        // decrease retry counter
        retryCounter--;

        // check again
        okToTx = (ITM->PORT[0U].u32 == 1UL);
    }

    if(okToTx)
    {
        ITM->PORT[0U].u8 = (uint8_t)c;
    }
}

extern "C" void SwoPrintString(const char *s)
{
    // print char until terminator is found
    while(*s)
    {
        SwoPrintChar(*s++);
    }
}

// this function is heavily based in the CMSIS ITM_SendChar
// but with small performance improvements as we are sending a string not individual chars
__STATIC_INLINE uint32_t GenericPort_Write_CMSIS(int portNum, const char* data, size_t size)
{
    (void)portNum;

    ASSERT((ITM->TCR & ITM_TCR_ITMENA_Msk) != 0UL);
    ASSERT((ITM->TER & 1UL               ) != 0UL);

    char* p = (char*)data;
    uint32_t counter = 0;
    uint32_t retryCounter;
    bool okToTx;

    while(  *p != '\0' &&
            counter < size )
    {
        retryCounter = ITM_WRITE_ATTEMPTS;
        okToTx = (ITM->PORT[0U].u32 == 1UL);

        // wait (with timeout) until ITM port TX buffer is available
        while( !okToTx &&
               (retryCounter > 0) )
        {
            // do... nothing
            __NOP();

            // decrease retry counter
            retryCounter--;

            // check again
            okToTx = (ITM->PORT[0U].u32 == 1UL);
        }

        if(okToTx)
        {
            ITM->PORT[0U].u8 = (uint8_t)*p++;
        }

        counter++;
    }

    return counter;
}

uint32_t GenericPort_Write(int portNum, const char* data, size_t size)
{
    return GenericPort_Write_CMSIS(portNum, data, size);
}

#endif // (__CORTEX_M == 0)
<|endoftext|>


<commit_before>#ifndef _SDD_DD_NODE_HH_
#define _SDD_DD_NODE_HH_

#include <algorithm>  // equal, for_each
#include <functional> // hash
#include <iosfwd>

#include "sdd/dd/alpha.hh"
#include "sdd/dd/definition.hh"
#include "sdd/internal/util/hash.hh"
#include "sdd/internal/util/packed.hh"

namespace sdd {

/*-------------------------------------------------------------------------------------------*/

/// @brief  A non-terminal node in an SDD.
/// \tparam Valuation If a set of values, define a flat node; if an SDD, define a hierarchical
/// node.
///
/// For the sake of canonicity, a node shall not exist in several locations, thus we prevent
/// its copy. Also, to enforce this canonicity, we need that nodes have always the same
/// address, thus they can't be moved to an other memory location once created.
template <typename C, typename Valuation>
class _LIBSDD_ATTRIBUTE_PACKED node
{
  // Can't copy a node.
  node& operator=(const node&) = delete;
  node(const node&) = delete;

  // Can't move a node.
  node& operator=(node&&) = delete;
  node(node&&) = delete;

public:

  /// @brief The type of the variable of this node.
  typedef typename C::Variable          variable_type;

  /// @brief The type of the valuation of this node.
  typedef Valuation                     valuation_type;

  /// @brief The type used to store the number of arcs of this node.
  typedef typename C::alpha_size_type   alpha_size_type;

  /// @brief A (const) iterator on the arcs of this node.
  typedef const arc<C, Valuation>*      const_iterator;

private:

  /// @brief The variable of this node.
  const variable_type variable_;

  /// @brief The number of arcs of this node.
  const alpha_size_type size_;

public:

  /// @brief Constructor.
  ///
  /// O(n) where n is the number of arcs in the builder.
  /// It can't throw as the memory for the alpha has already been allocated.
  node(const variable_type& var, alpha_builder<C, Valuation>& builder)
  noexcept
    : variable_(var)
    , size_(static_cast<alpha_size_type>(builder.size()))
  {
    // Instruct the alpha builder to place it right after the node.
    builder.consolidate(alpha_addr());
  }

  /// @brief Destructor.
  ///
  /// O(n) where n is the number of arcs in the node.
  ~node()
  {
    for (auto& arc : *this)
    {
      arc.~arc<C, Valuation>();
    }
  }

  /// @brief Get the variable of this node.
  ///
  /// O(1).
  const variable_type&
  variable()
  const noexcept
  {
    return variable_;
  }

  /// @brief Get the beginning of arcs.
  ///
  /// O(1).
  const_iterator
  begin()
  const noexcept
  {
    return reinterpret_cast<const arc<C, Valuation>*>(alpha_addr());
  }

  /// @brief Get the end of arcs.
  ///
  /// O(1).
  const_iterator
  end()
  const noexcept
  {
    return reinterpret_cast<const arc<C, Valuation>*>(alpha_addr()) + size_;
  }

  /// @brief Get the number of arcs.
  ///
  /// O(1).
  alpha_size_type
  size()
  const noexcept
  {
    return size_;
  }

private:

  /// @brief Return the address of the alpha function.
  ///
  /// O(1).
  /// The alpha function is located right after the current node, so to compute its address,
  /// we just have to add the size of a node to the address of the current node.
  char*
  alpha_addr()
  const noexcept
  {
    return reinterpret_cast<char*>(const_cast<node*>(this)) + sizeof(node);
  }
};

/*-------------------------------------------------------------------------------------------*/

/// @brief   Equality of two nodes.
/// @related node
///
/// O(1) if nodes don't have the same number of arcs; otherwise O(n) where n is the number of
/// arcs.
template <typename C, typename Valuation>
inline
bool
operator==(const node<C, Valuation>& lhs, const node<C, Valuation>& rhs)
noexcept
{
  return lhs.size() == rhs.size() and lhs.variable() == rhs.variable()
     and std::equal(lhs.begin(), lhs.end(), rhs.begin());
}

/// @brief   Export a node to a stream.
/// @related node
template <typename C, typename Valuation>
std::ostream&
operator<<(std::ostream& os, const node<C, Valuation>& n)
{
  os << n.variable() << "[";
  std::for_each( n.begin(), n.end() - 1
               , [&](const arc<C, Valuation>& a)
                    {os << a.valuation() << " --> " << a.successor() << " || ";});
  return os << (n.end() - 1)->valuation() << " --> " << (n.end() - 1)->successor() << "]";
}

/*-------------------------------------------------------------------------------------------*/

} // namespace sdd

/// @cond INTERNAL_DOC

namespace std {

/*-------------------------------------------------------------------------------------------*/

/// @brief Hash specialization for sdd::node
template <typename C, typename Valuation>
struct hash<sdd::node<C, Valuation>>
{
  std::size_t
  operator()(const sdd::node<C, Valuation>& n)
  const noexcept
  {
    std::size_t seed = 0;
    sdd::internal::util::hash_combine(seed, n.variable());
    for (auto& arc : n)
    {
      sdd::internal::util::hash_combine(seed, arc.valuation());
      sdd::internal::util::hash_combine(seed, arc.successor());
    }
    return seed;
  }
};

/*-------------------------------------------------------------------------------------------*/

} // namespace std

/// @endcond

#endif // _SDD_DD_NODE_HH_
<commit_msg>Renaming for gcc.<commit_after>#ifndef _SDD_DD_NODE_HH_
#define _SDD_DD_NODE_HH_

#include <algorithm>  // equal, for_each
#include <functional> // hash
#include <iosfwd>

#include "sdd/dd/alpha.hh"
#include "sdd/dd/definition.hh"
#include "sdd/internal/util/hash.hh"
#include "sdd/internal/util/packed.hh"

namespace sdd {

/*-------------------------------------------------------------------------------------------*/

/// @brief  A non-terminal node in an SDD.
/// \tparam Valuation If a set of values, define a flat node; if an SDD, define a hierarchical
/// node.
///
/// For the sake of canonicity, a node shall not exist in several locations, thus we prevent
/// its copy. Also, to enforce this canonicity, we need that nodes have always the same
/// address, thus they can't be moved to an other memory location once created.
template <typename C, typename Valuation>
class _LIBSDD_ATTRIBUTE_PACKED node
{
  // Can't copy a node.
  node& operator=(const node&) = delete;
  node(const node&) = delete;

  // Can't move a node.
  node& operator=(node&&) = delete;
  node(node&&) = delete;

public:

  /// @brief The type of the variable of this node.
  typedef typename C::Variable          variable_type;

  /// @brief The type of the valuation of this node.
  typedef Valuation                     valuation_type;

  /// @brief The type used to store the number of arcs of this node.
  typedef typename C::alpha_size_type   alpha_size_type;

  /// @brief A (const) iterator on the arcs of this node.
  typedef const arc<C, Valuation>*      const_iterator;

private:

  /// @brief The variable of this node.
  const variable_type variable_;

  /// @brief The number of arcs of this node.
  const alpha_size_type size_;

public:

  /// @brief Constructor.
  ///
  /// O(n) where n is the number of arcs in the builder.
  /// It can't throw as the memory for the alpha has already been allocated.
  node(const variable_type& var, alpha_builder<C, Valuation>& builder)
  noexcept
    : variable_(var)
    , size_(static_cast<alpha_size_type>(builder.size()))
  {
    // Instruct the alpha builder to place it right after the node.
    builder.consolidate(alpha_addr());
  }

  /// @brief Destructor.
  ///
  /// O(n) where n is the number of arcs in the node.
  ~node()
  {
    for (auto& a : *this)
    {
      a.~arc<C, Valuation>();
    }
  }

  /// @brief Get the variable of this node.
  ///
  /// O(1).
  const variable_type&
  variable()
  const noexcept
  {
    return variable_;
  }

  /// @brief Get the beginning of arcs.
  ///
  /// O(1).
  const_iterator
  begin()
  const noexcept
  {
    return reinterpret_cast<const arc<C, Valuation>*>(alpha_addr());
  }

  /// @brief Get the end of arcs.
  ///
  /// O(1).
  const_iterator
  end()
  const noexcept
  {
    return reinterpret_cast<const arc<C, Valuation>*>(alpha_addr()) + size_;
  }

  /// @brief Get the number of arcs.
  ///
  /// O(1).
  alpha_size_type
  size()
  const noexcept
  {
    return size_;
  }

private:

  /// @brief Return the address of the alpha function.
  ///
  /// O(1).
  /// The alpha function is located right after the current node, so to compute its address,
  /// we just have to add the size of a node to the address of the current node.
  char*
  alpha_addr()
  const noexcept
  {
    return reinterpret_cast<char*>(const_cast<node*>(this)) + sizeof(node);
  }
};

/*-------------------------------------------------------------------------------------------*/

/// @brief   Equality of two nodes.
/// @related node
///
/// O(1) if nodes don't have the same number of arcs; otherwise O(n) where n is the number of
/// arcs.
template <typename C, typename Valuation>
inline
bool
operator==(const node<C, Valuation>& lhs, const node<C, Valuation>& rhs)
noexcept
{
  return lhs.size() == rhs.size() and lhs.variable() == rhs.variable()
     and std::equal(lhs.begin(), lhs.end(), rhs.begin());
}

/// @brief   Export a node to a stream.
/// @related node
template <typename C, typename Valuation>
std::ostream&
operator<<(std::ostream& os, const node<C, Valuation>& n)
{
  os << n.variable() << "[";
  std::for_each( n.begin(), n.end() - 1
               , [&](const arc<C, Valuation>& a)
                    {os << a.valuation() << " --> " << a.successor() << " || ";});
  return os << (n.end() - 1)->valuation() << " --> " << (n.end() - 1)->successor() << "]";
}

/*-------------------------------------------------------------------------------------------*/

} // namespace sdd

/// @cond INTERNAL_DOC

namespace std {

/*-------------------------------------------------------------------------------------------*/

/// @brief Hash specialization for sdd::node
template <typename C, typename Valuation>
struct hash<sdd::node<C, Valuation>>
{
  std::size_t
  operator()(const sdd::node<C, Valuation>& n)
  const noexcept
  {
    std::size_t seed = 0;
    sdd::internal::util::hash_combine(seed, n.variable());
    for (auto& arc : n)
    {
      sdd::internal::util::hash_combine(seed, arc.valuation());
      sdd::internal::util::hash_combine(seed, arc.successor());
    }
    return seed;
  }
};

/*-------------------------------------------------------------------------------------------*/

} // namespace std

/// @endcond

#endif // _SDD_DD_NODE_HH_
<|endoftext|>


<commit_before>#ifndef RING_BUFFER_HPP
#define RING_BUFFER_HPP

#include <boost/assert.hpp>

static const size_t RING_SIZE=1048576;

template<class T>
class Sample {
public:
  Sample() : mpSample(0), mLength(0) {}

  Sample(const Sample &copy) : mpSample(copy.mpSample), mLength(copy.mLength) {
  }

  ~Sample() {
    mpSample = 0;
    mLength = 0;
  }

  Sample& operator=(const Sample& other) {
    mpSample = other.mpSample;
    mLength = other.mLength;
    return *this;
  }

  void configure(T* pSample, int length) {
    mpSample = pSample;
    mLength = length;
  }

  T* sample() {
    return mpSample;
  }

  size_t length() {
    return mLength;
  }

private:
  T* mpSample;
  int mLength;
};

template<class T>
class SampleBuffer {
public:
  SampleBuffer() : mpBuffer(0), mPosition(0) {
    mpBuffer = new T[RING_SIZE];
  }

  SampleBuffer(const SampleBuffer& copy) :mpBuffer(copy.mpBuffer), mPosition(copy.mPosition) {
  }

  SampleBuffer& operator=(const SampleBuffer& other) {
    mpBuffer = other.mpBuffer;
    mPosition = other.mPosition;
  }

  ~SampleBuffer() {
    BOOST_VERIFY(mpBuffer != 0);
    delete[] mpBuffer;
  }

  size_t maximum_reservation() {
    return RING_SIZE-1;
  }

  T* reserve(size_t samples) {
    BOOST_VERIFY(mpBuffer != 0 && samples < RING_SIZE);

    if (samples >= RING_SIZE) {
      return 0;
    }

    if ((mPosition + samples) > RING_SIZE) {
      mPosition = 0;
    }

    T* ret = mpBuffer+mPosition;
    mPosition += samples;
    return ret;
  }

private:
  T* mpBuffer;
  size_t mPosition;
};

#endif
<commit_msg>More refactoring<commit_after>#ifndef SAMPLE_HPP
#define SAMPLE_HPP

#include <cstddef>

template<class T>
class Sample {
public:
    Sample() : mpSample(0), mLength(0) {}

    Sample(const Sample &copy) : mpSample(copy.mpSample), mLength(copy.mLength) {
    }

    ~Sample() {
        mpSample = 0;
        mLength = 0;
    }

    Sample& operator=(const Sample& other) {
        mpSample = other.mpSample;
        mLength = other.mLength;
        return *this;
    }

    void configure(T* pSample, int length) {
        mpSample = pSample;
        mLength = length;
    }

    T* sample() {
        return mpSample;
    }

    size_t length() {
        return mLength;
    }

private:
    T* mpSample;
    size_t mLength;
};

#endif<|endoftext|>


<commit_before>/*
 * Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved.
 *
 * 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 <onnx/onnx_pb.h>
#include <google/protobuf/io/coded_stream.h>
#include <google/protobuf/io/zero_copy_stream_impl.h>
#include <google/protobuf/text_format.h>
#include <sstream>
#include <iostream>
#include <fstream>

using std::cerr;
using std::endl;

#pragma once

namespace {

// Helper function to convert ONNX dims to TRT dims
template<typename OnnxDims>
inline bool convert_dims(OnnxDims const& onnx_dims, nvinfer1::Dims& trt_dims)
{
  std::vector<int> onnx_dims_vector;
  std::vector<nvinfer1::DimensionType> onnx_type_vector;
  for( auto const& onnx_dim : onnx_dims ) {
    int val = (onnx_dim.dim_param() != "" || onnx_dim.dim_value() == 0) ? -1 : onnx_dim.dim_value();
    onnx_dims_vector.push_back(val);
    onnx_type_vector.push_back(static_cast<nvinfer1::DimensionType>(0));
  }

  trt_dims.nbDims = onnx_dims_vector.size();
  if (trt_dims.nbDims > nvinfer1::Dims::MAX_DIMS){
    return false;
  }
  std::copy(onnx_dims_vector.begin(), onnx_dims_vector.end(), trt_dims.d);
  std::copy(onnx_type_vector.begin(), onnx_type_vector.end(), trt_dims.type);
  return true;
}

// Removes raw data from the text representation of an ONNX model
inline void remove_raw_data_strings(std::string& s) {
  std::string::size_type beg = 0;
  const std::string key = "raw_data: \"";
  const std::string sub = "...";
  while( (beg = s.find(key, beg)) != std::string::npos ) {
    beg += key.length();
    std::string::size_type end = beg - 1;
    // Note: Must skip over escaped end-quotes
    while( s[(end = s.find("\"", ++end)) - 1] == '\\' ) {}
    if( end - beg > 128 ) { // Only remove large data strings
      s.replace(beg, end - beg, "...");
    }
    beg += sub.length();
  }
}

// Removes float_data, int32_data etc. from the text representation of an ONNX model
inline std::string remove_repeated_data_strings(std::string& s) {
  std::istringstream iss(s);
  std::ostringstream oss;
  bool is_repeat = false;
  for( std::string line; std::getline(iss, line); ) {
    if(  line.find("float_data:") != std::string::npos ||
         line.find("int32_data:") != std::string::npos ||
         line.find("int64_data:") != std::string::npos ) {
      if( !is_repeat ) {
        is_repeat = true;
        oss << line.substr(0, line.find(":") + 1) << " ...\n";
      }
    } else {
      is_repeat = false;
      oss << line << "\n";
    }
  }
  return oss.str();
}

} // anonymous namespace

inline std::string pretty_print_onnx_to_string(::google::protobuf::Message const& message) {
  std::string s;
  ::google::protobuf::TextFormat::PrintToString(message, &s);
  remove_raw_data_strings(s);
  s = remove_repeated_data_strings(s);
  return s;
}

inline std::ostream& operator<<(std::ostream& stream, ::ONNX_NAMESPACE::ModelProto const& message) {
  stream << pretty_print_onnx_to_string(message);
  return stream;
}

inline std::ostream& operator<<(std::ostream& stream, ::ONNX_NAMESPACE::NodeProto const& message) {
  stream << pretty_print_onnx_to_string(message);
  return stream;
}

//...
//...Consider moving all of the below functions into a stand alone
//...

inline bool ParseFromFile_WAR(google::protobuf::Message* msg,
                       const char*                filename) {

  std::ifstream stream(filename, std::ios::in | std::ios::binary);
  if (!stream) {
      cerr <<  "Could not open file " << std::string(filename) <<endl;
      return false;
  }
  google::protobuf::io::IstreamInputStream rawInput(&stream);

  google::protobuf::io::CodedInputStream coded_input(&rawInput);
  // Note: This WARs the very low default size limit (64MB)
  coded_input.SetTotalBytesLimit(std::numeric_limits<int>::max(),
                                 std::numeric_limits<int>::max()/4);
  return msg->ParseFromCodedStream(&coded_input);
}

inline bool ParseFromTextFile(google::protobuf::Message* msg,
                       const char*                filename) {
  std::ifstream stream(filename, std::ios::in );
  if (!stream) {
      cerr <<  "Could not open file " << std::string(filename) <<endl;
      return false;
  }

  google::protobuf::io::IstreamInputStream rawInput(&stream);

  return google::protobuf::TextFormat::Parse(&rawInput, msg);
}

inline std::string onnx_ir_version_string(int64_t ir_version=::ONNX_NAMESPACE::IR_VERSION) {
int onnx_ir_major = ir_version / 1000000;
int onnx_ir_minor = ir_version % 1000000 / 10000;
int onnx_ir_patch = ir_version % 10000;
return (std::to_string(onnx_ir_major) + "." +
std::to_string(onnx_ir_minor) + "." +
std::to_string(onnx_ir_patch));
}

<commit_msg>fix error:numeric_limits (#268)<commit_after>/*
 * Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved.
 *
 * 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 <onnx/onnx_pb.h>
#include <google/protobuf/io/coded_stream.h>
#include <google/protobuf/io/zero_copy_stream_impl.h>
#include <google/protobuf/text_format.h>
#include <sstream>
#include <iostream>
#include <fstream>
#include <limits>
using std::cerr;
using std::endl;

#pragma once

namespace {

// Helper function to convert ONNX dims to TRT dims
template<typename OnnxDims>
inline bool convert_dims(OnnxDims const& onnx_dims, nvinfer1::Dims& trt_dims)
{
  std::vector<int> onnx_dims_vector;
  std::vector<nvinfer1::DimensionType> onnx_type_vector;
  for( auto const& onnx_dim : onnx_dims ) {
    int val = (onnx_dim.dim_param() != "" || onnx_dim.dim_value() == 0) ? -1 : onnx_dim.dim_value();
    onnx_dims_vector.push_back(val);
    onnx_type_vector.push_back(static_cast<nvinfer1::DimensionType>(0));
  }

  trt_dims.nbDims = onnx_dims_vector.size();
  if (trt_dims.nbDims > nvinfer1::Dims::MAX_DIMS){
    return false;
  }
  std::copy(onnx_dims_vector.begin(), onnx_dims_vector.end(), trt_dims.d);
  std::copy(onnx_type_vector.begin(), onnx_type_vector.end(), trt_dims.type);
  return true;
}

// Removes raw data from the text representation of an ONNX model
inline void remove_raw_data_strings(std::string& s) {
  std::string::size_type beg = 0;
  const std::string key = "raw_data: \"";
  const std::string sub = "...";
  while( (beg = s.find(key, beg)) != std::string::npos ) {
    beg += key.length();
    std::string::size_type end = beg - 1;
    // Note: Must skip over escaped end-quotes
    while( s[(end = s.find("\"", ++end)) - 1] == '\\' ) {}
    if( end - beg > 128 ) { // Only remove large data strings
      s.replace(beg, end - beg, "...");
    }
    beg += sub.length();
  }
}

// Removes float_data, int32_data etc. from the text representation of an ONNX model
inline std::string remove_repeated_data_strings(std::string& s) {
  std::istringstream iss(s);
  std::ostringstream oss;
  bool is_repeat = false;
  for( std::string line; std::getline(iss, line); ) {
    if(  line.find("float_data:") != std::string::npos ||
         line.find("int32_data:") != std::string::npos ||
         line.find("int64_data:") != std::string::npos ) {
      if( !is_repeat ) {
        is_repeat = true;
        oss << line.substr(0, line.find(":") + 1) << " ...\n";
      }
    } else {
      is_repeat = false;
      oss << line << "\n";
    }
  }
  return oss.str();
}

} // anonymous namespace

inline std::string pretty_print_onnx_to_string(::google::protobuf::Message const& message) {
  std::string s;
  ::google::protobuf::TextFormat::PrintToString(message, &s);
  remove_raw_data_strings(s);
  s = remove_repeated_data_strings(s);
  return s;
}

inline std::ostream& operator<<(std::ostream& stream, ::ONNX_NAMESPACE::ModelProto const& message) {
  stream << pretty_print_onnx_to_string(message);
  return stream;
}

inline std::ostream& operator<<(std::ostream& stream, ::ONNX_NAMESPACE::NodeProto const& message) {
  stream << pretty_print_onnx_to_string(message);
  return stream;
}

//...
//...Consider moving all of the below functions into a stand alone
//...

inline bool ParseFromFile_WAR(google::protobuf::Message* msg,
                       const char*                filename) {

  std::ifstream stream(filename, std::ios::in | std::ios::binary);
  if (!stream) {
      cerr <<  "Could not open file " << std::string(filename) <<endl;
      return false;
  }
  google::protobuf::io::IstreamInputStream rawInput(&stream);

  google::protobuf::io::CodedInputStream coded_input(&rawInput);
  // Note: This WARs the very low default size limit (64MB)
  coded_input.SetTotalBytesLimit(std::numeric_limits<int>::max(),
                                 std::numeric_limits<int>::max()/4);
  return msg->ParseFromCodedStream(&coded_input);
}

inline bool ParseFromTextFile(google::protobuf::Message* msg,
                       const char*                filename) {
  std::ifstream stream(filename, std::ios::in );
  if (!stream) {
      cerr <<  "Could not open file " << std::string(filename) <<endl;
      return false;
  }

  google::protobuf::io::IstreamInputStream rawInput(&stream);

  return google::protobuf::TextFormat::Parse(&rawInput, msg);
}

inline std::string onnx_ir_version_string(int64_t ir_version=::ONNX_NAMESPACE::IR_VERSION) {
int onnx_ir_major = ir_version / 1000000;
int onnx_ir_minor = ir_version % 1000000 / 10000;
int onnx_ir_patch = ir_version % 10000;
return (std::to_string(onnx_ir_major) + "." +
std::to_string(onnx_ir_minor) + "." +
std::to_string(onnx_ir_patch));
}

<|endoftext|>


<commit_before>#include "parser.h"
#include <iostream>
#include <string>
#include <memory>

namespace kaleidoscope {
  std::unique_ptr<ExprAST> Parser::log_error(const char* str) {
    std::cerr << "Error: " << str << "\n";
    return nullptr;
  }

  std::unique_ptr<PrototypeAST> Parser::log_error_p(const char* str) {
    log_error(str);
    return nullptr;
  }

  std::unique_ptr<PrototypeAST> Parser::parse_proto() {
    // parse function name
    if (_cur_token != Lexer::tok_identifier)
      return log_error_p("Expected function name in prototype");
    auto fn_name = _lexer.token_value().identifier_str;

    //parse arg list
    get_next_token();
    if (_cur_token != '(')
        return log_error_p("Expected \"(\" after function name in prototype");

    std::vector<std::string> args;
    do {
      get_next_token();

      if (_cur_token != Lexer::tok_identifier)
        return log_error_p("Expected argument name in argument list in prototype");
      args.push_back(_lexer.token_value().identifier_str);

      get_next_token();

      if (_cur_token != ',' || _cur_token != ')')
        return log_error_p("Expected \",\" or \")\" in argument list in prototype");

    } while (_cur_token != ')');

    return std::make_unique<PrototypeAST>(fn_name, args);
  }

  std::unique_ptr<FunctionAST> Parser::parse_def() {
    get_next_token();
    auto proto = parse_proto();
    return nullptr;
  }

  void Parser::parse() {
    while (true) {
      switch(_cur_token) {
        case Lexer::tok_eof:
          return;
        case ';':
          get_next_token();
          break;
        case Lexer::tok_def:
          if (parse_def()) {
            std::cout << "Parsed function definition.\n";
          }
          else {
            get_next_token();
          }
          break;
        default:
          std::cout << "Default hit!\n";
          get_next_token();
          break;
      }
    }
  }

}
<commit_msg>Fix incorrect error checking in parsing function prototype<commit_after>#include "parser.h"
#include <iostream>
#include <string>
#include <memory>

namespace kaleidoscope {
  std::unique_ptr<ExprAST> Parser::log_error(const char* str) {
    std::cerr << "Error: " << str << "\n";
    return nullptr;
  }

  std::unique_ptr<PrototypeAST> Parser::log_error_p(const char* str) {
    log_error(str);
    return nullptr;
  }

  std::unique_ptr<PrototypeAST> Parser::parse_proto() {
    // parse function name
    if (_cur_token != Lexer::tok_identifier)
      return log_error_p("Expected function name in prototype");
    auto fn_name = _lexer.token_value().identifier_str;

    //parse arg list
    get_next_token();
    if (_cur_token != '(')
        return log_error_p("Expected \"(\" after function name in prototype");

    std::vector<std::string> args;
    do {
      get_next_token();

      if (_cur_token != Lexer::tok_identifier)
        return log_error_p("Expected argument name in argument list in prototype");
      args.push_back(_lexer.token_value().identifier_str);

      get_next_token();

      if (_cur_token != ',' && _cur_token != ')')
        return log_error_p("Expected \",\" or \")\" in argument list in prototype");

    } while (_cur_token != ')');

    return std::make_unique<PrototypeAST>(fn_name, args);
  }

  std::unique_ptr<FunctionAST> Parser::parse_def() {
    get_next_token();
    auto proto = parse_proto();
    return nullptr;
  }

  void Parser::parse() {
    while (true) {
      switch(_cur_token) {
        case Lexer::tok_eof:
          return;
        case ';':
          get_next_token();
          break;
        case Lexer::tok_def:
          if (parse_def()) {
            std::cout << "Parsed function definition.\n";
          }
          else {
            get_next_token();
          }
          break;
        default:
          std::cout << "Default hit!\n";
          get_next_token();
          break;
      }
    }
  }

}
<|endoftext|>