<commit_before>/*=====================================================================

 QGroundControl Open Source Ground Control Station

 (c) 2009 - 2015 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>

 This file is part of the QGROUNDCONTROL project

 QGROUNDCONTROL is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation, either version 3 of the License, or
 (at your option) any later version.

 QGROUNDCONTROL 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 General Public License for more details.

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

 ======================================================================*/

#include <QSettings>
#include <QDesktopWidget>

#include <QDir>

#include "SettingsDialog.h"
#include "MainWindow.h"
#include "ui_SettingsDialog.h"

#include "JoystickWidget.h"
#include "LinkManager.h"
#include "MAVLinkProtocol.h"
#include "MAVLinkSettingsWidget.h"
#include "GAudioOutput.h"
#include "QGCApplication.h"
#include "QGCFileDialog.h"
#include "QGCMessageBox.h"

SettingsDialog::SettingsDialog(JoystickInput *joystick, QWidget *parent, Qt::WindowFlags flags) :
QDialog(parent, flags),
_mainWindow(MainWindow::instance()),
_ui(new Ui::SettingsDialog)
{
    _ui->setupUi(this);

    // Center the window on the screen.
    QRect position = frameGeometry();
    position.moveCenter(QApplication::desktop()->availableGeometry().center());
    move(position.topLeft());

    // Add the joystick settings pane
    _ui->tabWidget->addTab(new JoystickWidget(joystick, this), "Controllers");

    // Add all protocols
    QList<ProtocolInterface*> protocols = LinkManager::instance()->getProtocols();
    foreach (ProtocolInterface* protocol, protocols) {
        MAVLinkProtocol* mavlink = dynamic_cast<MAVLinkProtocol*>(protocol);
        if (mavlink) {
            MAVLinkSettingsWidget* msettings = new MAVLinkSettingsWidget(mavlink, this);
            _ui->tabWidget->addTab(msettings, "MAVLink");
        }
    }

    this->window()->setWindowTitle(tr("QGroundControl Settings"));

    // Audio preferences
    _ui->audioMuteCheckBox->setChecked(GAudioOutput::instance()->isMuted());
    connect(_ui->audioMuteCheckBox, SIGNAL(toggled(bool)), GAudioOutput::instance(), SLOT(mute(bool)));
    connect(GAudioOutput::instance(), SIGNAL(mutedChanged(bool)), _ui->audioMuteCheckBox, SLOT(setChecked(bool)));

    // Reconnect
    _ui->reconnectCheckBox->setChecked(_mainWindow->autoReconnectEnabled());
    connect(_ui->reconnectCheckBox, SIGNAL(clicked(bool)), _mainWindow, SLOT(enableAutoReconnect(bool)));

    // Low power mode
    _ui->lowPowerCheckBox->setChecked(_mainWindow->lowPowerModeEnabled());
    connect(_ui->lowPowerCheckBox, SIGNAL(clicked(bool)), _mainWindow, SLOT(enableLowPowerMode(bool)));

    // Dock widget title bars
    _ui->titleBarCheckBox->setChecked(_mainWindow->dockWidgetTitleBarsEnabled());
    connect(_ui->titleBarCheckBox,SIGNAL(clicked(bool)),_mainWindow,SLOT(enableDockWidgetTitleBars(bool)));

    connect(_ui->deleteSettings, &QAbstractButton::toggled, this, &SettingsDialog::_deleteSettingsToggled);

    // Custom mode

    _ui->customModeComboBox->addItem(tr("Default: Generic MAVLink and serial links"), MainWindow::CUSTOM_MODE_NONE);
    _ui->customModeComboBox->addItem(tr("Wifi: Generic MAVLink, wifi or serial links"), MainWindow::CUSTOM_MODE_WIFI);
    _ui->customModeComboBox->addItem(tr("PX4: Optimized for PX4 Autopilot Users"), MainWindow::CUSTOM_MODE_PX4);

    _ui->customModeComboBox->setCurrentIndex(_ui->customModeComboBox->findData(_mainWindow->getCustomMode()));
    connect(_ui->customModeComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(selectCustomMode(int)));

    QDir dir;
    QStringList entry;
    entry.append("*.qm");
    QStringList trList = dir.entryList(entry, QDir::Files);
    qDebug()<<"Current path:"<<dir.currentPath();
    _ui->localeComboBox->addItem("Default");
    foreach(QString str, trList){

        _ui->localeComboBox->addItem(str.mid(0,str.length()-3));

    }

    //_ui->localeComboBox->addItems(dir.entryList(entry, QDir::Files));

    // Application color style
    MainWindow::QGC_MAINWINDOW_STYLE style = _mainWindow->getStyle();
    _ui->styleChooser->setCurrentIndex(style);

    _ui->savedFilesLocation->setText(qgcApp()->savedFilesLocation());
    _ui->promptFlightDataSave->setChecked(qgcApp()->promptFlightDataSave());

    // Connect signals
    connect(_ui->styleChooser, SIGNAL(currentIndexChanged(int)), this, SLOT(styleChanged(int)));
    connect(_ui->browseSavedFilesLocation, &QPushButton::clicked, this, &SettingsDialog::_selectSavedFilesDirectory);
    connect(_ui->buttonBox, &QDialogButtonBox::accepted, this, &SettingsDialog::_validateBeforeClose);
}

SettingsDialog::~SettingsDialog()
{
    delete _ui;
}

void SettingsDialog::styleChanged(int index)
{
    _mainWindow->loadStyle((index == 1) ? MainWindow::QGC_MAINWINDOW_STYLE_LIGHT : MainWindow::QGC_MAINWINDOW_STYLE_DARK);
}

void SettingsDialog::selectCustomMode(int mode)
{
    _mainWindow->setCustomMode(static_cast<enum MainWindow::CUSTOM_MODE>(_ui->customModeComboBox->itemData(mode).toInt()));
}

void SettingsDialog::_deleteSettingsToggled(bool checked)
{
    if (checked){
        QGCMessageBox::StandardButton answer = QGCMessageBox::question(tr("Delete Settings"),
                                                                       tr("All saved settings will be deleted the next time you start QGroundControl. Is this really what you want?"),
                                                                       QMessageBox::Yes | QMessageBox::No,
                                                                       QMessageBox::No);
        if (answer == QMessageBox::Yes) {
            qgcApp()->deleteAllSettingsNextBoot();
        } else {
            _ui->deleteSettings->setChecked(false);
        }
    } else {
        qgcApp()->clearDeleteAllSettingsNextBoot();
    }
}

/// @brief Validates the settings before closing
void SettingsDialog::_validateBeforeClose(void)
{
    QGCApplication* app = qgcApp();

    // Validate the saved file location

    QString saveLocation = _ui->savedFilesLocation->text();
    if (!app->validatePossibleSavedFilesLocation(saveLocation)) {
        QGCMessageBox::warning(tr("Bad save location"),
                               tr("The location to save files to is invalid, or cannot be written to. Please provide a valid directory."));
        return;
    }

    // Locations is valid, save
    app->setSavedFilesLocation(saveLocation);

    qgcApp()->setPromptFlightDataSave(_ui->promptFlightDataSave->checkState() == Qt::Checked);

    if(_ui->localeComboBox->currentText() != "Default"){

            qgcApp()->setLocaleFileName(_ui->localeComboBox->currentText() + ".qm");

    }

    // Close dialog
    accept();
}

/// @brief Displays a directory picker dialog to allow the user to select a saved file location
void SettingsDialog::_selectSavedFilesDirectory(void)
{
    QString newLocation = QGCFileDialog::getExistingDirectory(this,
                                                            tr("Select the directory where you want to save files to."),
                                                            _ui->savedFilesLocation->text());
    if (!newLocation.isEmpty()) {
        _ui->savedFilesLocation->setText(newLocation);
    }
}
<commit_msg>- Fixed hardcode in string of locate file name.<commit_after>/*=====================================================================

 QGroundControl Open Source Ground Control Station

 (c) 2009 - 2015 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>

 This file is part of the QGROUNDCONTROL project

 QGROUNDCONTROL is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation, either version 3 of the License, or
 (at your option) any later version.

 QGROUNDCONTROL 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 General Public License for more details.

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

 ======================================================================*/

#include <QSettings>
#include <QDesktopWidget>

#include <QDir>

#include "SettingsDialog.h"
#include "MainWindow.h"
#include "ui_SettingsDialog.h"

#include "JoystickWidget.h"
#include "LinkManager.h"
#include "MAVLinkProtocol.h"
#include "MAVLinkSettingsWidget.h"
#include "GAudioOutput.h"
#include "QGCApplication.h"
#include "QGCFileDialog.h"
#include "QGCMessageBox.h"

SettingsDialog::SettingsDialog(JoystickInput *joystick, QWidget *parent, Qt::WindowFlags flags) :
QDialog(parent, flags),
_mainWindow(MainWindow::instance()),
_ui(new Ui::SettingsDialog)
{
    _ui->setupUi(this);

    // Center the window on the screen.
    QRect position = frameGeometry();
    position.moveCenter(QApplication::desktop()->availableGeometry().center());
    move(position.topLeft());

    // Add the joystick settings pane
    _ui->tabWidget->addTab(new JoystickWidget(joystick, this), "Controllers");

    // Add all protocols
    QList<ProtocolInterface*> protocols = LinkManager::instance()->getProtocols();
    foreach (ProtocolInterface* protocol, protocols) {
        MAVLinkProtocol* mavlink = dynamic_cast<MAVLinkProtocol*>(protocol);
        if (mavlink) {
            MAVLinkSettingsWidget* msettings = new MAVLinkSettingsWidget(mavlink, this);
            _ui->tabWidget->addTab(msettings, "MAVLink");
        }
    }

    this->window()->setWindowTitle(tr("QGroundControl Settings"));

    // Audio preferences
    _ui->audioMuteCheckBox->setChecked(GAudioOutput::instance()->isMuted());
    connect(_ui->audioMuteCheckBox, SIGNAL(toggled(bool)), GAudioOutput::instance(), SLOT(mute(bool)));
    connect(GAudioOutput::instance(), SIGNAL(mutedChanged(bool)), _ui->audioMuteCheckBox, SLOT(setChecked(bool)));

    // Reconnect
    _ui->reconnectCheckBox->setChecked(_mainWindow->autoReconnectEnabled());
    connect(_ui->reconnectCheckBox, SIGNAL(clicked(bool)), _mainWindow, SLOT(enableAutoReconnect(bool)));

    // Low power mode
    _ui->lowPowerCheckBox->setChecked(_mainWindow->lowPowerModeEnabled());
    connect(_ui->lowPowerCheckBox, SIGNAL(clicked(bool)), _mainWindow, SLOT(enableLowPowerMode(bool)));

    // Dock widget title bars
    _ui->titleBarCheckBox->setChecked(_mainWindow->dockWidgetTitleBarsEnabled());
    connect(_ui->titleBarCheckBox,SIGNAL(clicked(bool)),_mainWindow,SLOT(enableDockWidgetTitleBars(bool)));

    connect(_ui->deleteSettings, &QAbstractButton::toggled, this, &SettingsDialog::_deleteSettingsToggled);

    // Custom mode

    _ui->customModeComboBox->addItem(tr("Default: Generic MAVLink and serial links"), MainWindow::CUSTOM_MODE_NONE);
    _ui->customModeComboBox->addItem(tr("Wifi: Generic MAVLink, wifi or serial links"), MainWindow::CUSTOM_MODE_WIFI);
    _ui->customModeComboBox->addItem(tr("PX4: Optimized for PX4 Autopilot Users"), MainWindow::CUSTOM_MODE_PX4);

    _ui->customModeComboBox->setCurrentIndex(_ui->customModeComboBox->findData(_mainWindow->getCustomMode()));
    connect(_ui->customModeComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(selectCustomMode(int)));

    QDir dir;
    QStringList entry;
    entry.append("*.qm");
    QStringList trList = dir.entryList(entry, QDir::Files);
    qDebug()<<"Current path:"<<dir.currentPath();
    _ui->localeComboBox->addItem("Default");
    foreach(QString str, trList){

        _ui->localeComboBox->addItem(str.left(str.indexOf(".")));

    }

    //_ui->localeComboBox->addItems(dir.entryList(entry, QDir::Files));

    // Application color style
    MainWindow::QGC_MAINWINDOW_STYLE style = _mainWindow->getStyle();
    _ui->styleChooser->setCurrentIndex(style);

    _ui->savedFilesLocation->setText(qgcApp()->savedFilesLocation());
    _ui->promptFlightDataSave->setChecked(qgcApp()->promptFlightDataSave());

    // Connect signals
    connect(_ui->styleChooser, SIGNAL(currentIndexChanged(int)), this, SLOT(styleChanged(int)));
    connect(_ui->browseSavedFilesLocation, &QPushButton::clicked, this, &SettingsDialog::_selectSavedFilesDirectory);
    connect(_ui->buttonBox, &QDialogButtonBox::accepted, this, &SettingsDialog::_validateBeforeClose);
}

SettingsDialog::~SettingsDialog()
{
    delete _ui;
}

void SettingsDialog::styleChanged(int index)
{
    _mainWindow->loadStyle((index == 1) ? MainWindow::QGC_MAINWINDOW_STYLE_LIGHT : MainWindow::QGC_MAINWINDOW_STYLE_DARK);
}

void SettingsDialog::selectCustomMode(int mode)
{
    _mainWindow->setCustomMode(static_cast<enum MainWindow::CUSTOM_MODE>(_ui->customModeComboBox->itemData(mode).toInt()));
}

void SettingsDialog::_deleteSettingsToggled(bool checked)
{
    if (checked){
        QGCMessageBox::StandardButton answer = QGCMessageBox::question(tr("Delete Settings"),
                                                                       tr("All saved settings will be deleted the next time you start QGroundControl. Is this really what you want?"),
                                                                       QMessageBox::Yes | QMessageBox::No,
                                                                       QMessageBox::No);
        if (answer == QMessageBox::Yes) {
            qgcApp()->deleteAllSettingsNextBoot();
        } else {
            _ui->deleteSettings->setChecked(false);
        }
    } else {
        qgcApp()->clearDeleteAllSettingsNextBoot();
    }
}

/// @brief Validates the settings before closing
void SettingsDialog::_validateBeforeClose(void)
{
    QGCApplication* app = qgcApp();

    // Validate the saved file location

    QString saveLocation = _ui->savedFilesLocation->text();
    if (!app->validatePossibleSavedFilesLocation(saveLocation)) {
        QGCMessageBox::warning(tr("Bad save location"),
                               tr("The location to save files to is invalid, or cannot be written to. Please provide a valid directory."));
        return;
    }

    // Locations is valid, save
    app->setSavedFilesLocation(saveLocation);

    qgcApp()->setPromptFlightDataSave(_ui->promptFlightDataSave->checkState() == Qt::Checked);

    if(_ui->localeComboBox->currentText() != "Default"){

            qgcApp()->setLocaleFileName(_ui->localeComboBox->currentText() + ".qm");

    }

    // Close dialog
    accept();
}

/// @brief Displays a directory picker dialog to allow the user to select a saved file location
void SettingsDialog::_selectSavedFilesDirectory(void)
{
    QString newLocation = QGCFileDialog::getExistingDirectory(this,
                                                            tr("Select the directory where you want to save files to."),
                                                            _ui->savedFilesLocation->text());
    if (!newLocation.isEmpty()) {
        _ui->savedFilesLocation->setText(newLocation);
    }
}
<|endoftext|>


<commit_before>/**
    This file is part of Deformable Shape Tracking (DEST).

    Copyright(C) 2015/2016 Christoph Heindl
    All rights reserved.

    This software may be modified and distributed under the terms
    of the BSD license.See the LICENSE file for details.
*/

#include <dest/core/config.h>
#ifdef DEST_WITH_OPENCV

#include <dest/core/shape.h>
#include <dest/util/triangulate.h>
#include <opencv2/imgproc.hpp>
#include <unordered_map>
#include <set>

namespace dest {
    namespace util {

        std::vector<core::Shape::Index> triangulateShape(const core::Shape & s)
        {
            Eigen::Vector2f minC = s.rowwise().minCoeff();
            Eigen::Vector2f maxC = s.rowwise().maxCoeff();

            // Don't make the bounds too tight.
            cv::Rect_<float> bounds(std::floor(minC.x() - 1.f),
                std::floor(minC.y() - 1.f),
                std::ceil(maxC.x() - minC.x() + 2.f),
                std::ceil(maxC.y() - minC.y() + 2.f));

            cv::Subdiv2D subdiv(bounds);

            std::vector<cv::Point2f> controlPoints;

            for (dest::core::Shape::Index i = 0; i < s.cols(); ++i) {
                cv::Point2f c(s(0, i), s(1, i));
                subdiv.insert(c);
                controlPoints.push_back(c);
            }

            std::vector<cv::Vec6f> triangleList;
            subdiv.getTriangleList(triangleList);

            std::vector<core::Shape::Index> triangleIds(triangleList.size() * 3);

            int validTris = 0;
            for (size_t i = 0; i < triangleList.size(); i++)
            {
                cv::Vec6f t = triangleList[i];

                cv::Point2f p0(t[0], t[1]);
                cv::Point2f p1(t[2], t[3]);
                cv::Point2f p2(t[4], t[5]);

                if (bounds.contains(p0) && bounds.contains(p1) && bounds.contains(p2)) {

                    auto iter0 = std::find(controlPoints.begin(), controlPoints.end(), p0);
                    auto iter1 = std::find(controlPoints.begin(), controlPoints.end(), p1);
                    auto iter2 = std::find(controlPoints.begin(), controlPoints.end(), p2);

                    triangleIds[validTris * 3 + 0] = (core::Shape::Index)std::distance(controlPoints.begin(), iter0);
                    triangleIds[validTris * 3 + 1] = (core::Shape::Index)std::distance(controlPoints.begin(), iter1);
                    triangleIds[validTris * 3 + 2] = (core::Shape::Index)std::distance(controlPoints.begin(), iter2);

                    ++validTris;
                }
            }

            return std::vector<core::Shape::Index>(triangleIds.begin(), triangleIds.begin() + validTris * 3);
        }

        typedef std::pair<core::Shape::Index, core::Shape::Index> Edge;

        inline Edge createEdge(core::Shape::Index a, core::Shape::Index b) {
            if (a > b) {
                std::swap(a, b);
            }
            return Edge(a, b);
        }

        /**
            Hash edge.
        */
        class EdgeHasher
        {
        public:
            EdgeHasher(core::Shape::Index nVertices)
                :_n(nVertices)
            {}

            size_t operator()(const Edge & p) const
            {
                return p.first * _n + p.second;
            }

        private:
            core::Shape::Index _n;
        };

        std::vector<core::Shape::Index> boundaryShapeVertices(const core::Shape & s, const std::vector<core::Shape::Index>& tris, core::Shape *boundaryShape)
        {
            // Find the outer shape boundary. That is all triangle edges sharing belonging to just one triangle.

            typedef std::unordered_map<Edge, int, EdgeHasher> EdgeCountMap;
            EdgeCountMap edgeCount(10, EdgeHasher(s.size()));

            for (size_t i = 0; i < tris.size() / 3; ++i) {
                std::pair<EdgeCountMap::iterator, bool> r0 = edgeCount.insert(std::make_pair(createEdge(tris[i * 3 + 0], tris[i * 3 + 1]), 1));
                std::pair<EdgeCountMap::iterator, bool> r1 = edgeCount.insert(std::make_pair(createEdge(tris[i * 3 + 1], tris[i * 3 + 2]), 1));
                std::pair<EdgeCountMap::iterator, bool> r2 = edgeCount.insert(std::make_pair(createEdge(tris[i * 3 + 2], tris[i * 3 + 0]), 1));

                if (!r0.second) r0.first->second++;
                if (!r1.second) r1.first->second++;
                if (!r2.second) r2.first->second++;
            }

            // Collect boundary edges

            std::set<Edge> boundaryEdges;
            for (EdgeCountMap::iterator i = edgeCount.begin(); i != edgeCount.end(); ++i) {
                if (i->second == 1)
                    boundaryEdges.insert(i->first);
            }

            std::vector<core::Shape::Index> orderedIndices;
            for (std::set<Edge>::iterator i = boundaryEdges.begin(); i != boundaryEdges.end(); ++i) {
                orderedIndices.push_back(i->first);
            }

            if (boundaryShape) {
                boundaryShape->resize(2, orderedIndices.size());
                for (size_t i = 0; i < orderedIndices.size(); ++i) {
                    boundaryShape->col(i) = s.col(orderedIndices[i]);
                }
            }

            return orderedIndices;
        }
    }
}

#endif<commit_msg>Changed include for compatibility with OpenCV 2.4<commit_after>/**
    This file is part of Deformable Shape Tracking (DEST).

    Copyright(C) 2015/2016 Christoph Heindl
    All rights reserved.

    This software may be modified and distributed under the terms
    of the BSD license.See the LICENSE file for details.
*/

#include <dest/core/config.h>
#ifdef DEST_WITH_OPENCV

#include <dest/core/shape.h>
#include <dest/util/triangulate.h>
#include <opencv2/imgproc/imgproc.hpp>
#include <unordered_map>
#include <set>

namespace dest {
    namespace util {

        std::vector<core::Shape::Index> triangulateShape(const core::Shape & s)
        {
            Eigen::Vector2f minC = s.rowwise().minCoeff();
            Eigen::Vector2f maxC = s.rowwise().maxCoeff();

            // Don't make the bounds too tight.
            cv::Rect_<float> bounds(std::floor(minC.x() - 1.f),
                std::floor(minC.y() - 1.f),
                std::ceil(maxC.x() - minC.x() + 2.f),
                std::ceil(maxC.y() - minC.y() + 2.f));

            cv::Subdiv2D subdiv(bounds);

            std::vector<cv::Point2f> controlPoints;

            for (dest::core::Shape::Index i = 0; i < s.cols(); ++i) {
                cv::Point2f c(s(0, i), s(1, i));
                subdiv.insert(c);
                controlPoints.push_back(c);
            }

            std::vector<cv::Vec6f> triangleList;
            subdiv.getTriangleList(triangleList);

            std::vector<core::Shape::Index> triangleIds(triangleList.size() * 3);

            int validTris = 0;
            for (size_t i = 0; i < triangleList.size(); i++)
            {
                cv::Vec6f t = triangleList[i];

                cv::Point2f p0(t[0], t[1]);
                cv::Point2f p1(t[2], t[3]);
                cv::Point2f p2(t[4], t[5]);

                if (bounds.contains(p0) && bounds.contains(p1) && bounds.contains(p2)) {

                    auto iter0 = std::find(controlPoints.begin(), controlPoints.end(), p0);
                    auto iter1 = std::find(controlPoints.begin(), controlPoints.end(), p1);
                    auto iter2 = std::find(controlPoints.begin(), controlPoints.end(), p2);

                    triangleIds[validTris * 3 + 0] = (core::Shape::Index)std::distance(controlPoints.begin(), iter0);
                    triangleIds[validTris * 3 + 1] = (core::Shape::Index)std::distance(controlPoints.begin(), iter1);
                    triangleIds[validTris * 3 + 2] = (core::Shape::Index)std::distance(controlPoints.begin(), iter2);

                    ++validTris;
                }
            }

            return std::vector<core::Shape::Index>(triangleIds.begin(), triangleIds.begin() + validTris * 3);
        }

        typedef std::pair<core::Shape::Index, core::Shape::Index> Edge;

        inline Edge createEdge(core::Shape::Index a, core::Shape::Index b) {
            if (a > b) {
                std::swap(a, b);
            }
            return Edge(a, b);
        }

        /**
            Hash edge.
        */
        class EdgeHasher
        {
        public:
            EdgeHasher(core::Shape::Index nVertices)
                :_n(nVertices)
            {}

            size_t operator()(const Edge & p) const
            {
                return p.first * _n + p.second;
            }

        private:
            core::Shape::Index _n;
        };

        std::vector<core::Shape::Index> boundaryShapeVertices(const core::Shape & s, const std::vector<core::Shape::Index>& tris, core::Shape *boundaryShape)
        {
            // Find the outer shape boundary. That is all triangle edges sharing belonging to just one triangle.

            typedef std::unordered_map<Edge, int, EdgeHasher> EdgeCountMap;
            EdgeCountMap edgeCount(10, EdgeHasher(s.size()));

            for (size_t i = 0; i < tris.size() / 3; ++i) {
                std::pair<EdgeCountMap::iterator, bool> r0 = edgeCount.insert(std::make_pair(createEdge(tris[i * 3 + 0], tris[i * 3 + 1]), 1));
                std::pair<EdgeCountMap::iterator, bool> r1 = edgeCount.insert(std::make_pair(createEdge(tris[i * 3 + 1], tris[i * 3 + 2]), 1));
                std::pair<EdgeCountMap::iterator, bool> r2 = edgeCount.insert(std::make_pair(createEdge(tris[i * 3 + 2], tris[i * 3 + 0]), 1));

                if (!r0.second) r0.first->second++;
                if (!r1.second) r1.first->second++;
                if (!r2.second) r2.first->second++;
            }

            // Collect boundary edges

            std::set<Edge> boundaryEdges;
            for (EdgeCountMap::iterator i = edgeCount.begin(); i != edgeCount.end(); ++i) {
                if (i->second == 1)
                    boundaryEdges.insert(i->first);
            }

            std::vector<core::Shape::Index> orderedIndices;
            for (std::set<Edge>::iterator i = boundaryEdges.begin(); i != boundaryEdges.end(); ++i) {
                orderedIndices.push_back(i->first);
            }

            if (boundaryShape) {
                boundaryShape->resize(2, orderedIndices.size());
                for (size_t i = 0; i < orderedIndices.size(); ++i) {
                    boundaryShape->col(i) = s.col(orderedIndices[i]);
                }
            }

            return orderedIndices;
        }
    }
}

#endif<|endoftext|>


<commit_before>#include <iostream>
#include <napi.h>
#include <stdexcept>
#include <string>
#include <vector>
#include "nexus_util.h"
#include "string_util.h"
#include "nxtranslate_debug.h"

// ----- start of declaring debug levels
#ifdef DEBUG3_NEXUS_UTIL
#define DEBUG2_NEXUS_UTIL
#endif
#ifdef DEBUG2_NEXUS_UTIL
#define DEBUG1_NEXUS_UTIL
#endif
// ----- end of declaring debug levels

using std::invalid_argument;
using std::runtime_error;
using std::string;
using std::vector;

typedef struct{
  string name;
  string type;
}SimpleNode;

typedef vector<string> StringVec;
typedef vector<SimpleNode> SimpleNodeVec;
typedef tree<Node> TreeNode;

static const int    GROUP_STRING_LEN = 128;
static const string NXROOT           = "NXroot";
static const string SDS              = "SDS";
static const string ATTR             = "ATTR";

static SimpleNodeVec get_groups(NXhandle *handle);

static bool node_exists(NXhandle *handle, const Node &node){
  SimpleNodeVec groups=get_groups(handle);

  for(SimpleNodeVec::const_iterator group=groups.begin() ; group!=groups.end() ; group++ ){
    if(group->name==node.name()){
      if(group->type==node.type())
        return true;
      if(node.is_data() && group->type==SDS)
        return true;
    }
  }

  return false;
}

extern void nexus_util::open(NXhandle *handle, const Node &node){
#ifdef DEBUG2_NEXUS_UTIL
  std::cout << "nexus_util::open(handle," << node.name() << ":" << node.type()
            << ")" << std::endl;
#endif
  // do nothing with a root
  if(node.name()==NXROOT) return;

  // the name is needed by all "make" functions
  char name[GROUP_STRING_LEN];
  strcpy(name,node.name().c_str());

  bool existing_node=node_exists(handle,node);

  if(node.is_data()){
    if(!existing_node){
      int type=(int)node.int_type(); // get the type and cast as an int
      int rank=node.rank();
      if(rank<=0) return;

      int dims[rank];
      { // copy the dimensions from the node
        vector<int> vec_dim=node.dims();
        for( int i=0 ; i<rank ; i++ )
          dims[i]=vec_dim[i];
      }

      // create the data
      if(node.compress_type()==Node::COMP_NONE){
        //std::cout << "in open: " << node.type() << " " << *(node.dims().begin()) << std::endl; // REMOVE
        if(NXmakedata(*handle,name,type,rank,dims)!=NX_OK){
          std::cout << "NXmakedata failed" << std::endl;
          throw runtime_error("NXmakedata failed");
        }
      }else{
        int comp_type=node.compress_type();
        // warn that this is not supported
        std::cout << "WARN: do not currently support compression (type=" << comp_type << ")" << std::endl;
        return;
        /* TAKEN FROM <napi.h>
           NX_EXTERNAL  NXstatus CALLING_STYLE NXcompmakedata (NXhandle handle, CONSTCHAR* label, int datatype, int rank, int dim[], int comp_typ, int bufsize[]);
        */
      }
    }
    // open the data that was just created
    if(NXopendata(*handle,name)!=NX_OK)
      throw runtime_error("NXopendata failed");
  }else{
    char type[GROUP_STRING_LEN];
    strcpy(type,node.type().c_str());
    if(!existing_node)
      if(NXmakegroup(*handle,name,type)!=NX_OK)
        throw runtime_error("NXmakegroup failed");
    if(NXopengroup(*handle,name,type)!=NX_OK)
      throw runtime_error("NXopengroup failed");
  }
}

static void add_attribute(NXhandle *handle, const Node& node,
                                                           const int attr_num){
  Attr attr=(node.get_attr(attr_num));

  char name[GROUP_STRING_LEN];
  strcpy(name,attr.name().c_str());

  if(NXputattr(*handle,name,attr.value(),attr.length(),attr.type())!=NX_OK)
    throw runtime_error("NXputattr failed");
}

extern void nexus_util::make_data(NXhandle *handle, const Node& node){
  //std::cout << "make(" << node.name() << ")" << std::endl; // REMOVE
  // do nothing with a root
  if(node.name()==NXROOT) return;
  // do nothing unless this is a data
  if(!node.is_data()) return;

  // put in the attributes
  for( int i=0 ; i<node.num_attr() ; i++ )
    add_attribute(handle,node,i);

  // put in the data
  void *data(NULL);
  node.copy_data(data);
  if(data==NULL)
    throw runtime_error("CANNOT ADD NULL DATA");// << std::endl;
  if(NXputdata(*handle,data)!=NX_OK)
    throw runtime_error("NXputdata failed");
  NXfree(&data);
}

static void recurse_make_data(NXhandle *handle, const TreeNode &tree, const TreeNode::sibling_iterator &begin, const TreeNode::sibling_iterator &end){
  using namespace nexus_util;
  for( TreeNode::sibling_iterator sib=begin ; sib!=end ; sib++ ){
    open(handle,*sib);
    if(sib->is_data())
      make_data(handle,*sib);
    else
      recurse_make_data(handle,tree,tree.begin(sib),tree.end(sib));
    close(handle,*sib);
    sib.skip_children();
  }
}

extern void nexus_util::make_data(NXhandle *handle, const TreeNode &tree){
  //std::cout << "make_data(handle,tree[" << tree.size() << "])" << std::endl; // REMOVE
  // check that the tree is not empty
  if(tree.size()<=0)
    throw invalid_argument("Cannot write empty tree to file");

  // recursively write out the tree
  for( TreeNode::iterator it=tree.begin() ; it!=tree.end() ; it++ ){
    open(handle,*it);
    if(it->is_data())
      make_data(handle,*it);
    else
      recurse_make_data(handle,tree,tree.begin(it),tree.end(it));
    close(handle,*it);
    it.skip_children();
  }
}

extern void nexus_util::close(NXhandle *handle, const Node &node){
#ifdef DEBUG2_NEXUS_UTIL
  std::cout << "nexus_util::close(handle," << node.name() << ":"
            << node.type() << ")" << std::endl;
#endif

  // do nothing with a root
  if(node.name()==NXROOT) return;

  if(node.is_data()){
    // check that there was something created
    if(node.rank()<=0) return;

    if(NXclosedata(*handle)!=NX_OK)
      throw runtime_error("NXclosedata failed");
  }else{
    if(NXclosegroup(*handle)!=NX_OK)
      throw runtime_error("NXclosegroup failed");
  }
}

static int num_group(NXhandle *handle){
  char group_name[GROUP_STRING_LEN];
  char group_class[GROUP_STRING_LEN];
  int num_groups;

  if(NXgetgroupinfo(*handle,&num_groups,group_name,group_class)!=NX_OK)
    throw runtime_error("NXgetgroupinfo failed");

  return num_groups;
}

static SimpleNode get_next_group(NXhandle *handle){
  //std::cout << "get_next_group(handle)" << std::endl;
  char name[GROUP_STRING_LEN], class_name[GROUP_STRING_LEN];
  int datatype;

  // get the information
  if(NXgetnextentry(*handle,name,class_name,&datatype)!=NX_OK)
    throw "NXgetnextentry failed";

  // copy it into the supplied node
  SimpleNode node;
  node.name=name;
  node.type=class_name;

  return node;
}

static bool node_is_okay(const SimpleNode& node){
  static const string UNKNOWN="UNKNOWN";
  if(node.name==UNKNOWN)
    return false;
  if(node.type==UNKNOWN)
    return false;
  if(node.type=="CDF0.0")
    return false;
  return true;
}

static SimpleNodeVec get_groups(NXhandle *handle){
  //std::cout << "get_groups(handle)" << std::endl; // REMOVE

  // reset the directory
  if(NXinitgroupdir(*handle)!=NX_OK)
    throw runtime_error("NXinitgroupdir failed");

  // determine the number of groups at the current location
  int num_groups;
  try{
    num_groups=num_group(handle);
  }catch(runtime_error &e){
    // let it drop on the floor
  }

  // set up for the listing
  SimpleNodeVec result;
  if(num_groups<=0) return result;

  // get the listing
  SimpleNode node;
  for( int i=0 ; i<num_groups ; i++ ){
    node=get_next_group(handle);
    if(node_is_okay(node))
      result.push_back(node);
  }

  return result;
}

extern vector<string> nexus_util::get_list(NXhandle *handle){
  SimpleNodeVec vec=get_groups(handle);

  vector<string> result;
  for( SimpleNodeVec::const_iterator it=vec.begin() ; it!=vec.end() ; it++ ){
    result.push_back(it->name);
    result.push_back(it->type);
  }

  return result;
}

static string get_type(NXhandle *handle, const string &name){
  SimpleNodeVec groups=get_groups(handle);

  for(SimpleNodeVec::const_iterator group=groups.begin() ; group!=groups.end() ; group++ ){
    if(group->name==name)
      return group->type;
  }
  return "";
}

static void open_node(NXhandle *handle, const string &name, const string &type, int &num_group, int &num_data){
  // do nothing for attributes
  if(type==ATTR)
    return;

  // everything else needs a name
  char ch_name[GROUP_STRING_LEN];
  strcpy(ch_name,name.c_str());

  // open a data if appropriate
  if(type==SDS){
    if(NXopendata(*handle,ch_name)!=NX_OK)
      throw runtime_error("NXopendata failed");
    num_data++;
    return;
  }

  // open the group
  char ch_type[GROUP_STRING_LEN];
  strcpy(ch_type,type.c_str());
  if(NXopengroup(*handle,ch_name,ch_type)!=NX_OK)
    throw runtime_error("NXopengroup failed");
  num_group++;
}

extern string nexus_util::open(NXhandle *handle, const string &name){
  string type=get_type(handle,name);
  if(type.size()<=0)
    throw runtime_error(string("could not find type for node[")+name+"]");
  int num_group=0;
  int num_data=0;
  open_node(handle,name,type,num_group,num_data);
  return type;
}

static string path_to_str(const StringVec &path){
  string str="";
  for( StringVec::const_iterator it=path.begin() ; it!=path.end() ; it++ )
    str+=("/"+*it);
  return str;
}

extern void nexus_util::open_path(NXhandle *handle, const StringVec &path, int &num_group, int &num_data){
#ifdef DEBUG1_NEXUS_UTIL
  std::cout << "open_path(" << handle << ",";
  for( StringVec::const_iterator it=path.begin() ; it!=path.end() ; it++ )
    std::cout << "/" << *it;
  std::cout << "," << num_group << "," << num_data << ")" << std::endl;
#endif
  for( StringVec::const_iterator it=path.begin() ; it!=path.end() ; it++ ){
    std::cout << "  ** " << *it; // REMOVE
    string type=get_type(handle,*it);
    std::cout << " : " << type << std::endl; // REMOVE
    if(type.size()<=0){
      close_path(handle,num_group,num_data);
      throw runtime_error("Path ["+path_to_str(path)+"] did not exist");
    }
    try{
      open_node(handle,*it,type,num_group,num_data);
    }catch(runtime_error &e){
      throw  runtime_error("Could not open path ["+path_to_str(path)+"]");
    }
  }
}

extern void nexus_util::close_path(NXhandle *handle, int &num_group, int &num_data){
#ifdef DEBUG1_NEXUS_UTIL
  std::cout << "close_path(" << handle << "," << num_group << ","
            << num_data << ")" << std::endl;
#endif
  if( (num_group<=0) && (num_data<=0) ){
    num_group=0;
    num_data=0;
    return;
  }

  if(num_data){
    if(NXclosedata(*handle)!=NX_OK)
      throw runtime_error("NXclosedata failed");
    num_data--;
  }

  for( ; num_group>0 ; num_group-- ){
    if(NXclosegroup(*handle)!=NX_OK)
      throw runtime_error("NXclosegroup failed");
  }
}

extern size_t nexus_util::calc_size(int rank, int *dims, int type){
  // check that the rank is reasonable
  if(rank<=0) throw invalid_argument("Do not understand rank<=0");

  // determine how much to copy
  size_t size=1;
  for( int i=0 ; i<rank ; i++ )
    size*=dims[i];
  if(type==NX_CHAR || type==NX_INT8 || type==NX_UINT8){
    // size is already correct
  }else if(type==NX_INT16 || type==NX_UINT16){
    size*=2;
  }else if(type==NX_INT32 || type==NX_UINT32 || type==NX_FLOAT32){
    size*=4;
  }else if(type==NX_FLOAT64){
    size*=8;
  }else{
    throw invalid_argument("Did not understand type in nexus_util::calc_size");
  }

  return size;
}

extern void nexus_util::make_link(NXhandle *handle, const vector<string> &link, const vector<string> &source){
/*
  // ********** begin debug print
  std::cout << "LINKING ";
  for( vector<string>::const_iterator it=link.begin() ; it!=link.end() ; it++ )
    std::cout << "/" << *it;
  std::cout << " -> ";
  for( vector<string>::const_iterator it=source.begin() ; it!=source.end() ; it++ )
    std::cout << "/" << *it;
  std::cout << std::endl;
  // ********** end debug print
*/
  // keep track of location in file
  NXlink *link_id=(NXlink *)malloc(sizeof(NXlink));
  int num_group=0;
  int num_data=0;

  // open the path to the source
  nexus_util::open_path(handle,source,num_group,num_data);

  // get the link_id
  bool is_group=false;
  if(num_data>0){
    if(NXgetdataID(*handle,link_id)!=NX_OK)
      throw new runtime_error("could not get data ID for linking");
  }else{
    if(NXgetgroupID(*handle,link_id)!=NX_OK)
      throw new runtime_error("could not get group ID for linking");
    is_group=true;
  }

  // return to the root node in the file
  nexus_util::close_path(handle,num_group,num_data);

  // open to link's parent location
  nexus_util::open_path(handle,link,num_group,num_data);

  // create the link
  if(NXmakelink(*handle,link_id)!=NX_OK)
    throw new runtime_error("could not create link");

  // return to the root node in the file
  nexus_util::close_path(handle,num_group,num_data);

  // free up the NXlink variable
  free(link_id);
}
<commit_msg>Removed debug prints.<commit_after>#include <iostream>
#include <napi.h>
#include <stdexcept>
#include <string>
#include <vector>
#include "nexus_util.h"
#include "string_util.h"
#include "nxtranslate_debug.h"

// ----- start of declaring debug levels
#ifdef DEBUG3_NEXUS_UTIL
#define DEBUG2_NEXUS_UTIL
#endif
#ifdef DEBUG2_NEXUS_UTIL
#define DEBUG1_NEXUS_UTIL
#endif
// ----- end of declaring debug levels

using std::invalid_argument;
using std::runtime_error;
using std::string;
using std::vector;

typedef struct{
  string name;
  string type;
}SimpleNode;

typedef vector<string> StringVec;
typedef vector<SimpleNode> SimpleNodeVec;
typedef tree<Node> TreeNode;

static const int    GROUP_STRING_LEN = 128;
static const string NXROOT           = "NXroot";
static const string SDS              = "SDS";
static const string ATTR             = "ATTR";

static SimpleNodeVec get_groups(NXhandle *handle);

static bool node_exists(NXhandle *handle, const Node &node){
  SimpleNodeVec groups=get_groups(handle);

  for(SimpleNodeVec::const_iterator group=groups.begin() ; group!=groups.end() ; group++ ){
    if(group->name==node.name()){
      if(group->type==node.type())
        return true;
      if(node.is_data() && group->type==SDS)
        return true;
    }
  }

  return false;
}

extern void nexus_util::open(NXhandle *handle, const Node &node){
#ifdef DEBUG2_NEXUS_UTIL
  std::cout << "nexus_util::open(handle," << node.name() << ":" << node.type()
            << ")" << std::endl;
#endif
  // do nothing with a root
  if(node.name()==NXROOT) return;

  // the name is needed by all "make" functions
  char name[GROUP_STRING_LEN];
  strcpy(name,node.name().c_str());

  bool existing_node=node_exists(handle,node);

  if(node.is_data()){
    if(!existing_node){
      int type=(int)node.int_type(); // get the type and cast as an int
      int rank=node.rank();
      if(rank<=0) return;

      int dims[rank];
      { // copy the dimensions from the node
        vector<int> vec_dim=node.dims();
        for( int i=0 ; i<rank ; i++ )
          dims[i]=vec_dim[i];
      }

      // create the data
      if(node.compress_type()==Node::COMP_NONE){
        //std::cout << "in open: " << node.type() << " " << *(node.dims().begin()) << std::endl; // REMOVE
        if(NXmakedata(*handle,name,type,rank,dims)!=NX_OK){
          std::cout << "NXmakedata failed" << std::endl;
          throw runtime_error("NXmakedata failed");
        }
      }else{
        int comp_type=node.compress_type();
        // warn that this is not supported
        std::cout << "WARN: do not currently support compression (type=" << comp_type << ")" << std::endl;
        return;
        /* TAKEN FROM <napi.h>
           NX_EXTERNAL  NXstatus CALLING_STYLE NXcompmakedata (NXhandle handle, CONSTCHAR* label, int datatype, int rank, int dim[], int comp_typ, int bufsize[]);
        */
      }
    }
    // open the data that was just created
    if(NXopendata(*handle,name)!=NX_OK)
      throw runtime_error("NXopendata failed");
  }else{
    char type[GROUP_STRING_LEN];
    strcpy(type,node.type().c_str());
    if(!existing_node)
      if(NXmakegroup(*handle,name,type)!=NX_OK)
        throw runtime_error("NXmakegroup failed");
    if(NXopengroup(*handle,name,type)!=NX_OK)
      throw runtime_error("NXopengroup failed");
  }
}

static void add_attribute(NXhandle *handle, const Node& node,
                                                           const int attr_num){
  Attr attr=(node.get_attr(attr_num));

  char name[GROUP_STRING_LEN];
  strcpy(name,attr.name().c_str());

  if(NXputattr(*handle,name,attr.value(),attr.length(),attr.type())!=NX_OK)
    throw runtime_error("NXputattr failed");
}

extern void nexus_util::make_data(NXhandle *handle, const Node& node){
  //std::cout << "make(" << node.name() << ")" << std::endl; // REMOVE
  // do nothing with a root
  if(node.name()==NXROOT) return;
  // do nothing unless this is a data
  if(!node.is_data()) return;

  // put in the attributes
  for( int i=0 ; i<node.num_attr() ; i++ )
    add_attribute(handle,node,i);

  // put in the data
  void *data(NULL);
  node.copy_data(data);
  if(data==NULL)
    throw runtime_error("CANNOT ADD NULL DATA");// << std::endl;
  if(NXputdata(*handle,data)!=NX_OK)
    throw runtime_error("NXputdata failed");
  NXfree(&data);
}

static void recurse_make_data(NXhandle *handle, const TreeNode &tree, const TreeNode::sibling_iterator &begin, const TreeNode::sibling_iterator &end){
  using namespace nexus_util;
  for( TreeNode::sibling_iterator sib=begin ; sib!=end ; sib++ ){
    open(handle,*sib);
    if(sib->is_data())
      make_data(handle,*sib);
    else
      recurse_make_data(handle,tree,tree.begin(sib),tree.end(sib));
    close(handle,*sib);
    sib.skip_children();
  }
}

extern void nexus_util::make_data(NXhandle *handle, const TreeNode &tree){
  //std::cout << "make_data(handle,tree[" << tree.size() << "])" << std::endl; // REMOVE
  // check that the tree is not empty
  if(tree.size()<=0)
    throw invalid_argument("Cannot write empty tree to file");

  // recursively write out the tree
  for( TreeNode::iterator it=tree.begin() ; it!=tree.end() ; it++ ){
    open(handle,*it);
    if(it->is_data())
      make_data(handle,*it);
    else
      recurse_make_data(handle,tree,tree.begin(it),tree.end(it));
    close(handle,*it);
    it.skip_children();
  }
}

extern void nexus_util::close(NXhandle *handle, const Node &node){
#ifdef DEBUG2_NEXUS_UTIL
  std::cout << "nexus_util::close(handle," << node.name() << ":"
            << node.type() << ")" << std::endl;
#endif

  // do nothing with a root
  if(node.name()==NXROOT) return;

  if(node.is_data()){
    // check that there was something created
    if(node.rank()<=0) return;

    if(NXclosedata(*handle)!=NX_OK)
      throw runtime_error("NXclosedata failed");
  }else{
    if(NXclosegroup(*handle)!=NX_OK)
      throw runtime_error("NXclosegroup failed");
  }
}

static int num_group(NXhandle *handle){
  char group_name[GROUP_STRING_LEN];
  char group_class[GROUP_STRING_LEN];
  int num_groups;

  if(NXgetgroupinfo(*handle,&num_groups,group_name,group_class)!=NX_OK)
    throw runtime_error("NXgetgroupinfo failed");

  return num_groups;
}

static SimpleNode get_next_group(NXhandle *handle){
  //std::cout << "get_next_group(handle)" << std::endl;
  char name[GROUP_STRING_LEN], class_name[GROUP_STRING_LEN];
  int datatype;

  // get the information
  if(NXgetnextentry(*handle,name,class_name,&datatype)!=NX_OK)
    throw "NXgetnextentry failed";

  // copy it into the supplied node
  SimpleNode node;
  node.name=name;
  node.type=class_name;

  return node;
}

static bool node_is_okay(const SimpleNode& node){
  static const string UNKNOWN="UNKNOWN";
  if(node.name==UNKNOWN)
    return false;
  if(node.type==UNKNOWN)
    return false;
  if(node.type=="CDF0.0")
    return false;
  return true;
}

static SimpleNodeVec get_groups(NXhandle *handle){
  //std::cout << "get_groups(handle)" << std::endl; // REMOVE

  // reset the directory
  if(NXinitgroupdir(*handle)!=NX_OK)
    throw runtime_error("NXinitgroupdir failed");

  // determine the number of groups at the current location
  int num_groups;
  try{
    num_groups=num_group(handle);
  }catch(runtime_error &e){
    // let it drop on the floor
  }

  // set up for the listing
  SimpleNodeVec result;
  if(num_groups<=0) return result;

  // get the listing
  SimpleNode node;
  for( int i=0 ; i<num_groups ; i++ ){
    node=get_next_group(handle);
    if(node_is_okay(node))
      result.push_back(node);
  }

  return result;
}

extern vector<string> nexus_util::get_list(NXhandle *handle){
  SimpleNodeVec vec=get_groups(handle);

  vector<string> result;
  for( SimpleNodeVec::const_iterator it=vec.begin() ; it!=vec.end() ; it++ ){
    result.push_back(it->name);
    result.push_back(it->type);
  }

  return result;
}

static string get_type(NXhandle *handle, const string &name){
  SimpleNodeVec groups=get_groups(handle);

  for(SimpleNodeVec::const_iterator group=groups.begin() ; group!=groups.end() ; group++ ){
    if(group->name==name)
      return group->type;
  }
  return "";
}

static void open_node(NXhandle *handle, const string &name, const string &type, int &num_group, int &num_data){
  // do nothing for attributes
  if(type==ATTR)
    return;

  // everything else needs a name
  char ch_name[GROUP_STRING_LEN];
  strcpy(ch_name,name.c_str());

  // open a data if appropriate
  if(type==SDS){
    if(NXopendata(*handle,ch_name)!=NX_OK)
      throw runtime_error("NXopendata failed");
    num_data++;
    return;
  }

  // open the group
  char ch_type[GROUP_STRING_LEN];
  strcpy(ch_type,type.c_str());
  if(NXopengroup(*handle,ch_name,ch_type)!=NX_OK)
    throw runtime_error("NXopengroup failed");
  num_group++;
}

extern string nexus_util::open(NXhandle *handle, const string &name){
  string type=get_type(handle,name);
  if(type.size()<=0)
    throw runtime_error(string("could not find type for node[")+name+"]");
  int num_group=0;
  int num_data=0;
  open_node(handle,name,type,num_group,num_data);
  return type;
}

static string path_to_str(const StringVec &path){
  string str="";
  for( StringVec::const_iterator it=path.begin() ; it!=path.end() ; it++ )
    str+=("/"+*it);
  return str;
}

extern void nexus_util::open_path(NXhandle *handle, const StringVec &path, int &num_group, int &num_data){
#ifdef DEBUG1_NEXUS_UTIL
  std::cout << "open_path(" << handle << ",";
  for( StringVec::const_iterator it=path.begin() ; it!=path.end() ; it++ )
    std::cout << "/" << *it;
  std::cout << "," << num_group << "," << num_data << ")" << std::endl;
#endif
  for( StringVec::const_iterator it=path.begin() ; it!=path.end() ; it++ ){
    string type=get_type(handle,*it);
    if(type.size()<=0){
      close_path(handle,num_group,num_data);
      throw runtime_error("Path ["+path_to_str(path)+"] did not exist");
    }
    try{
      open_node(handle,*it,type,num_group,num_data);
    }catch(runtime_error &e){
      throw  runtime_error("Could not open path ["+path_to_str(path)+"]");
    }
  }
}

extern void nexus_util::close_path(NXhandle *handle, int &num_group, int &num_data){
#ifdef DEBUG1_NEXUS_UTIL
  std::cout << "close_path(" << handle << "," << num_group << ","
            << num_data << ")" << std::endl;
#endif
  if( (num_group<=0) && (num_data<=0) ){
    num_group=0;
    num_data=0;
    return;
  }

  if(num_data){
    if(NXclosedata(*handle)!=NX_OK)
      throw runtime_error("NXclosedata failed");
    num_data--;
  }

  for( ; num_group>0 ; num_group-- ){
    if(NXclosegroup(*handle)!=NX_OK)
      throw runtime_error("NXclosegroup failed");
  }
}

extern size_t nexus_util::calc_size(int rank, int *dims, int type){
  // check that the rank is reasonable
  if(rank<=0) throw invalid_argument("Do not understand rank<=0");

  // determine how much to copy
  size_t size=1;
  for( int i=0 ; i<rank ; i++ )
    size*=dims[i];
  if(type==NX_CHAR || type==NX_INT8 || type==NX_UINT8){
    // size is already correct
  }else if(type==NX_INT16 || type==NX_UINT16){
    size*=2;
  }else if(type==NX_INT32 || type==NX_UINT32 || type==NX_FLOAT32){
    size*=4;
  }else if(type==NX_FLOAT64){
    size*=8;
  }else{
    throw invalid_argument("Did not understand type in nexus_util::calc_size");
  }

  return size;
}

extern void nexus_util::make_link(NXhandle *handle, const vector<string> &link, const vector<string> &source){
/*
  // ********** begin debug print
  std::cout << "LINKING ";
  for( vector<string>::const_iterator it=link.begin() ; it!=link.end() ; it++ )
    std::cout << "/" << *it;
  std::cout << " -> ";
  for( vector<string>::const_iterator it=source.begin() ; it!=source.end() ; it++ )
    std::cout << "/" << *it;
  std::cout << std::endl;
  // ********** end debug print
*/
  // keep track of location in file
  NXlink *link_id=(NXlink *)malloc(sizeof(NXlink));
  int num_group=0;
  int num_data=0;

  // open the path to the source
  nexus_util::open_path(handle,source,num_group,num_data);

  // get the link_id
  bool is_group=false;
  if(num_data>0){
    if(NXgetdataID(*handle,link_id)!=NX_OK)
      throw new runtime_error("could not get data ID for linking");
  }else{
    if(NXgetgroupID(*handle,link_id)!=NX_OK)
      throw new runtime_error("could not get group ID for linking");
    is_group=true;
  }

  // return to the root node in the file
  nexus_util::close_path(handle,num_group,num_data);

  // open to link's parent location
  nexus_util::open_path(handle,link,num_group,num_data);

  // create the link
  if(NXmakelink(*handle,link_id)!=NX_OK)
    throw new runtime_error("could not create link");

  // return to the root node in the file
  nexus_util::close_path(handle,num_group,num_data);

  // free up the NXlink variable
  free(link_id);
}
<|endoftext|>


<commit_before>/*=========================================================================
 *
 *  Copyright 2011-2013 The University of North Carolina at Chapel Hill
 *  All rights reserved.
 *
 *  Licensed under the MADAI Software License. You may obtain a copy of
 *  this license at
 *
 *         https://madai-public.cs.unc.edu/software/license/
 *
 *  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 <cstdlib>
#include <iostream>

static const char usage[] =
  "usage:\n"
  "  generateTrainingPoints [options] ParametersFile OutputDirectory\n"
  "\n"
  "ParametersFile is a file containing a list of parameters and their ranges\n"
  "\n"
  "  The file should be a text file with a separate line for each parameter\n"
  "  listing the name of the parameter followed by a numeric minimum and maximum\n"
  "  defining the range of the parameter, such as\n"
  "\n"
  "  temperature 245.2 288.0\n"
  "  pressure 4.7 5.9\n"
  "  ...\n"
  "\n"
  "OutputDirectory is a path to the name of the directory containing the parameter files\n"
  "\n"
  "Options:\n"
  "\n"
  "  -h,--help    Display help message\n"
  "\n"
  "  -v,--verbose Print extra information\n"
  "\n";

struct cmdLineOpts {
  bool verbose;
  const char * parametersFile;  // First non-flag argument.
  const char * outputDirectory; // Second non-flag argument.
};

bool parseCommandLineOptions( int argc, char* argv[], struct cmdLineOpts & opts)
{
  // Default values for command-line options
  opts.verbose = false;
  opts.parametersFile = NULL;
  opts.outputDirectory = NULL;

  // Parse options
  int argIndex;
  for ( argIndex = 1; argIndex < argc; ++argIndex ) {
    std::string argString( argv[ argIndex ] );

    if ( argString == "-v" || argString == "--verbose" ) {
      opts.verbose = true;
    } else if ( argString == "-h" || argString == "--help" ) {
      std::cerr << usage;
      return false;
    } else {
      break; // No switch
    }
  }

  if ( argIndex < argc ) {
    opts.parametersFile = argv[ argIndex++ ];
  } else {
    std::cerr << usage;
    return false;
  }

  if ( argIndex < argc ) {
    opts.outputDirectory = argv[ argIndex++ ];
  } else {
    std::cerr << usage;
    return false;
  }

  // Everything went well
  return true;
}

int main( int argc, char * argv[] ) {
  struct cmdLineOpts options;
  if ( !parseCommandLineOptions( argc, argv, options ) ) {
    return EXIT_FAILURE;
  }

  if ( options.verbose ) {
    std::cout << "Options: \n";
    std::cout << "  --verbose: " << options.verbose << "\n";
    std::cout << "  ParametersFile: " << options.parametersFile << "\n";
    std::cout << "  OutputDirectory: " << options.outputDirectory << "\n";
  }

  return EXIT_SUCCESS;
}

<commit_msg>Added reading of parameter_priors.dat file<commit_after>/*=========================================================================
 *
 *  Copyright 2011-2013 The University of North Carolina at Chapel Hill
 *  All rights reserved.
 *
 *  Licensed under the MADAI Software License. You may obtain a copy of
 *  this license at
 *
 *         https://madai-public.cs.unc.edu/software/license/
 *
 *  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 <cstdio>
#include <cstdlib>
#include <iostream>

#include "GaussianDistribution.h"
#include "Parameter.h"
#include "UniformDistribution.h"

static const char usage[] =
  "usage:\n"
  "  generateTrainingPoints [options] ParametersFile OutputDirectory\n"
  "\n"
  "ParametersFile is a file containing a list of parameters and their ranges\n"
  "\n"
  "  The file should be a text file with a separate line for each parameter\n"
  "  listing the name of the parameter followed by a numeric minimum and maximum\n"
  "  defining the range of the parameter, such as\n"
  "\n"
  "  temperature 245.2 288.0\n"
  "  pressure 4.7 5.9\n"
  "  ...\n"
  "\n"
  "OutputDirectory is a path to the name of the directory containing the parameter files\n"
  "\n"
  "Options:\n"
  "\n"
  "  -h,--help    Display help message\n"
  "\n"
  "  -v,--verbose Print extra information\n"
  "\n";

struct CommandLineOptions {
  bool verbose;
  const char * parametersFile;  // First non-flag argument.
  const char * outputDirectory; // Second non-flag argument.
};

bool ParseCommandLineOptions( int argc, char* argv[], struct CommandLineOptions & options)
{
  // Default values for command-line options
  options.verbose = false;
  options.parametersFile = NULL;
  options.outputDirectory = NULL;

  // Parse options
  int argIndex;
  for ( argIndex = 1; argIndex < argc; ++argIndex ) {
    std::string argString( argv[ argIndex ] );

    if ( argString == "-v" || argString == "--verbose" ) {
      options.verbose = true;
    } else if ( argString == "-h" || argString == "--help" ) {
      std::cerr << usage;
      return false;
    } else {
      break; // No switch
    }
  }

  if ( argIndex < argc ) {
    options.parametersFile = argv[ argIndex++ ];
  } else {
    std::cerr << usage;
    return false;
  }

  if ( argIndex < argc ) {
    options.outputDirectory = argv[ argIndex++ ];
  } else {
    std::cerr << usage;
    return false;
  }

  if ( argIndex < argc ) {
    std::cerr << "Extra arguments after '" << options.outputDirectory << "'\n";
    return false;
  }

  // Everything went well
  return true;
}

std::string LowerCase( char * buffer )
{
  std::string outBuffer( buffer );

  std::transform( outBuffer.begin(), outBuffer.end(),
                  outBuffer.begin(), ::tolower );

  return outBuffer;
}

bool ReadParameters( const struct CommandLineOptions & options,
                     std::vector< madai::Parameter > & parameters )
{
  parameters.clear();

  FILE *fp = fopen( options.parametersFile, "r" );
  if ( !fp ) {
    return false;
  }

  if ( options.verbose ) {
    std::cout << "Opened file '" << options.parametersFile << "'\n";
  }

  char buffer[4096];

  // Parse each parameter as it is listed on a line
  while ( 1 == fscanf( fp, "%4095s", buffer ) ) {
    std::string parameterName( buffer );

    if ( options.verbose ) {
      std::cout << "Read parameter '" << parameterName << "' ";
    }

    if ( 1 != fscanf( fp, "%4095s", buffer ) ) {
      std::cerr << "Could not read distribution type\n";
      fclose( fp );
      return false;
    }

    std::string distributionType( LowerCase( buffer ) );

    if ( options.verbose ) {
      std::cout << "which is of type '" << distributionType << "' ";
    }

    madai::Distribution *distribution = NULL;
    madai::UniformDistribution uniform;
    madai::GaussianDistribution gaussian;

    if ( distributionType == "uniform" ) {
      // Parse minimum and maximum values
      double minimum, maximum;
      if ( 2 != fscanf( fp, "%lf %lf", &minimum, &maximum ) ) {
        std::cerr << "Could not read uniform distribution minimum and maximum\n";
        fclose( fp );
        return false;
      }

      if ( options.verbose ) {
        std::cout << "with range [" << minimum << ", " << maximum << "]\n";
      }

      uniform.SetMinimum( minimum );
      uniform.SetMaximum( maximum );
      distribution = &uniform;

    } else if ( distributionType == "gaussian" ) {
      // Parse mean and standard deviation
      double mean, standardDeviation;
      if ( 2 != fscanf( fp, "%lf %lf", &mean, &standardDeviation ) ) {
        std::cerr << "Could not read Gaussian distribution mean and standard deviation\n";
        fclose( fp );
        return false;
      }

      if ( options.verbose ) {
        std::cout << "with mean " << mean << " and standard deviation "
                  << standardDeviation << "\n";
      }

      gaussian.SetMean( mean );
      gaussian.SetStandardDeviation( standardDeviation );
      distribution = &gaussian;
    } else {
      std::cerr << "Unknown distribution type '" << distributionType << "'\n";
      fclose( fp );
      return false;
    }

    parameters.push_back( madai::Parameter( parameterName, *distribution ) );
  }

  fclose( fp );

  // Everything went okay
  return true;
}

int main( int argc, char * argv[] ) {
  struct CommandLineOptions options;
  if ( !ParseCommandLineOptions( argc, argv, options ) ) {
    return EXIT_FAILURE;
  }

  if ( options.verbose ) {
    std::cout << "Options: \n";
    std::cout << "  --verbose: " << options.verbose << "\n";
    std::cout << "  ParametersFile: " << options.parametersFile << "\n";
    std::cout << "  OutputDirectory: " << options.outputDirectory << "\n";
  }

  // Read in parameter priors
  std::vector< madai::Parameter > parameters;
  bool parametersRead = ReadParameters( options, parameters );
  if ( !parametersRead ) {
    std::cerr << "Could not read parameters from prior file '"
              << options.parametersFile << "'" << std::endl;
    return EXIT_FAILURE;
  }

  return EXIT_SUCCESS;
}

<|endoftext|>


<commit_before>// Win32CommonControls.cpp : Defines the initialization routines for the DLL.
//

// Windows Header Files:
#define _WIN32_WINNT 0x0500
#include <windows.h>
#include <commctrl.h>
#include <commoncontrols.h>

#include <vector>
#include <string>

#include "BZWBAPI.h"

BZWB_GET_PLUGIN_VERSION

HWND	theAppWindow = NULL;
HINSTANCE	theInstance = NULL;

typedef struct
{
	std::string					filename;
	std::vector<std::string>	extensions;
	int							extension;
	std::string					title;
}trStandardFileOpen;

bool getStdFileOpen ( trStandardFileOpen &data )
{
	OPENFILENAME	ofn;

	memset(&ofn,0,sizeof(OPENFILENAME));
	ofn.lStructSize = sizeof(OPENFILENAME);
	ofn.hwndOwner = theAppWindow;
	ofn.hInstance = NULL;

	char filter[1024] = {0};

	int pos = 0;

	for (unsigned int i = 0; i < data.extensions.size(); i++)
	{
		int size = 0;
		char temp[128] = {0};
		sprintf(temp,"%s Files (*.%s)",data.extensions[i].c_str(),data.extensions[i].c_str());
		size += 11 + (data.extensions[i].size()*2);
		temp[size] = 0;
		size++;
		sprintf(temp+size,"*.%s",data.extensions[i].c_str());
		size += 2 + (data.extensions[i].size());
		temp[size] = 0;
		size++;
		memcpy(filter + pos,temp,size);
		pos += size;
	}
	strcat(filter+pos,"All Files (*.*)");
	pos += 15;
	filter[pos] = 0;
	pos++;
	strcat(filter+pos,"*.*");

	ofn.lpstrFilter = filter;
	ofn.nFilterIndex = data.extension;
	ofn.nMaxFile = _MAX_PATH;
	ofn.nMaxFileTitle = _MAX_PATH + _MAX_EXT;

	char defaultExtension[_MAX_EXT];
	if ( data.extensions.size() )
		strcpy(defaultExtension,data.extensions[data.extension].c_str());
	else
		strcpy(defaultExtension,"*");

	ofn.lpstrDefExt = defaultExtension;

	char filename[MAX_PATH];
	char title[MAX_PATH];

	strcpy(filename,data.filename.c_str());
	strcpy(title,data.title.c_str());

	ofn.lpstrFile = filename;
	ofn.lpstrFileTitle = title;
	ofn.Flags = OFN_HIDEREADONLY;

	bool good = GetOpenFileName(&ofn) != 0;
	if (good)
	{
		data.filename = ofn.lpstrFile;
	}
	else
	{
		DWORD err = CommDlgExtendedError();
		printf("open dialog err %d",err);
		//CDERR_DIALOGFAILURE
	}

	return good;
}

class  Win32OpenDialog : public bzw_OpenDialogControlHandler
{
public:
	Win32OpenDialog():bzw_OpenDialogControlHandler(){};

	virtual bool handle ( void )
	{
		std::string realExtension = extension;

		char filter[512];
		sprintf(filter,"%s files (%s)|%s|All Files (*.*)|*.*||",realExtension.c_str()+1,extension.c_str(),extension.c_str());

		realExtension.erase(realExtension.begin());

		std::string path = directory + file;

		trStandardFileOpen openData;

		openData.extensions.push_back(realExtension);
		openData.extension = 0;
		openData.filename = file;
		openData.title = description;
		if (getStdFileOpen(openData))
		{
			file = openData.filename;
			sucsessful = true;
		}
		else
			sucsessful = false;

		return true;
	}
};

Win32OpenDialog	openDialog;

BZWB_PLUGIN_CALL int bzwb_Load (const char* /*commandLine*/, void * instance )
{
	theAppWindow = (HWND) bzwb_getOSMainWindowHandle();
	theInstance = (HINSTANCE)instance;

	INITCOMMONCONTROLSEX InitCtrls;
	InitCtrls.dwICC = ICC_LISTVIEW_CLASSES;
	InitCtrls.dwSize = sizeof(INITCOMMONCONTROLSEX);
	BOOL bRet = InitCommonControlsEx(&InitCtrls);

	bzwb_registerCommonControlHandler(openDialog.type, &openDialog);
	return 0;
}

BZWB_PLUGIN_CALL int bzwb_Unload (void)
{
	bzwb_removeCommonControlHandlerr(openDialog.type, &openDialog);
	return 0;
}

<commit_msg>add a standard windows save dialog via the Win32CommonControls plug-in<commit_after>// Win32CommonControls.cpp : Defines the initialization routines for the DLL.
//

// Windows Header Files:
#define _WIN32_WINNT 0x0500
#include <windows.h>
#include <commctrl.h>
#include <commoncontrols.h>

#include <vector>
#include <string>

#include "BZWBAPI.h"

BZWB_GET_PLUGIN_VERSION

HWND	theAppWindow = NULL;
HINSTANCE	theInstance = NULL;

typedef struct
{
	std::string					filename;
	std::vector<std::string>	extensions;
	int							extension;
	std::string					title;
}trStandardFileOpen;

typedef struct
{
	std::string					filename;
	std::string					extension;
	std::string					title;
}trStandardFileSave;

bool getStdFileOpen ( trStandardFileOpen &data )
{
	OPENFILENAME	ofn;

	memset(&ofn,0,sizeof(OPENFILENAME));
	ofn.lStructSize = sizeof(OPENFILENAME);
	ofn.hwndOwner = theAppWindow;
	ofn.hInstance = NULL;

	char filter[1024] = {0};

	int pos = 0;

	for (unsigned int i = 0; i < data.extensions.size(); i++)
	{
		int size = 0;
		char temp[128] = {0};
		sprintf(temp,"%s Files (*.%s)",data.extensions[i].c_str(),data.extensions[i].c_str());
		size += 11 + (data.extensions[i].size()*2);
		temp[size] = 0;
		size++;
		sprintf(temp+size,"*.%s",data.extensions[i].c_str());
		size += 2 + (data.extensions[i].size());
		temp[size] = 0;
		size++;
		memcpy(filter + pos,temp,size);
		pos += size;
	}
	strcat(filter+pos,"All Files (*.*)");
	pos += 15;
	filter[pos] = 0;
	pos++;
	strcat(filter+pos,"*.*");

	ofn.lpstrFilter = filter;
	ofn.nFilterIndex = data.extension;
	ofn.nMaxFile = _MAX_PATH;
	ofn.nMaxFileTitle = _MAX_PATH + _MAX_EXT;

	char defaultExtension[_MAX_EXT];
	if ( data.extensions.size() )
		strcpy(defaultExtension,data.extensions[data.extension].c_str());
	else
		strcpy(defaultExtension,"*");

	ofn.lpstrDefExt = defaultExtension;

	char filename[MAX_PATH];
	char title[MAX_PATH];

	strcpy(filename,data.filename.c_str());
	strcpy(title,data.title.c_str());

	ofn.lpstrFile = filename;
	ofn.lpstrFileTitle = title;
	ofn.Flags = OFN_HIDEREADONLY;

	bool good = GetOpenFileName(&ofn) != 0;
	if (good)
	{
		data.filename = ofn.lpstrFile;
	}
	else
	{
		DWORD err = CommDlgExtendedError();
		printf("open dialog err %d",err);
		//CDERR_DIALOGFAILURE
	}

	return good;
}

bool getStdFileSave ( trStandardFileSave &data)
{
	OPENFILENAME	ofn;

	memset(&ofn,0,sizeof(OPENFILENAME));
	ofn.lStructSize = sizeof(OPENFILENAME);
	ofn.hwndOwner = theAppWindow;
	ofn.hInstance = NULL;

	char filter[1024] = {0};

	int pos = 0;

	if (data.extension.size())
	{
		int size = 0;
		char temp[128] = {0};
		sprintf(temp,"%s Files (*.%s)",data.extension.c_str(),data.extension.c_str());
		size += 11 + (data.extension.size()*2);
		temp[size] = 0;
		size++;
		sprintf(temp+size,"*.%s",data.extension.c_str());
		size += 2 + (1);
		temp[size] = 0;
		size++;
		memcpy(filter + pos,temp,size);
		pos += size;
	}
	strcat(filter+pos,"All Files (*.*)");
	pos += 15;
	filter[pos] = 0;
	pos++;
	strcat(filter+pos,"*.*");

	ofn.lpstrFilter = filter;
	ofn.nFilterIndex = 0;
	ofn.nMaxFile = _MAX_PATH;
	ofn.nMaxFileTitle = _MAX_PATH + _MAX_EXT;

	char defaultExtension[_MAX_EXT];
	if ( data.extension.size() )
		strcpy(defaultExtension,data.extension.c_str());
	else
		strcpy(defaultExtension,"*");

	ofn.lpstrDefExt = defaultExtension;

	char filename[MAX_PATH];
	char title[MAX_PATH];

	strcpy(filename,data.filename.c_str());
	strcpy(title,data.title.c_str());

	ofn.lpstrFile = filename;
	ofn.lpstrFileTitle = title;
	ofn.Flags = OFN_HIDEREADONLY;

	bool good = GetSaveFileName(&ofn) != 0;
	if (good)
	{
		data.filename = ofn.lpstrFile;
	}

	return good;
}

class  Win32OpenDialog : public bzw_OpenDialogControlHandler
{
public:
	Win32OpenDialog():bzw_OpenDialogControlHandler(){};

	virtual bool handle ( void )
	{
		std::string realExtension = extension;

		char filter[512];
		sprintf(filter,"%s files (%s)|%s|All Files (*.*)|*.*||",realExtension.c_str()+1,extension.c_str(),extension.c_str());

		realExtension.erase(realExtension.begin());

		std::string path = directory + file;

		trStandardFileOpen openData;

		openData.extensions.push_back(realExtension);
		openData.extension = 0;
		openData.filename = file;
		openData.title = description;
		if (getStdFileOpen(openData))
		{
			file = openData.filename;
			sucsessful = true;
		}
		else
			sucsessful = false;

		return true;
	}
};

Win32OpenDialog	openDialog;

class  Win32SaveDialog : public bzw_SaveDialogControlHandler
{
public:
	Win32SaveDialog():bzw_SaveDialogControlHandler(){};

	virtual bool handle ( void )
	{
		std::string realExtension = extension;

		char filter[512];
		sprintf(filter,"%s files (%s)|%s|All Files (*.*)|*.*||",realExtension.c_str()+1,extension.c_str(),extension.c_str());

		realExtension.erase(realExtension.begin());

		std::string path = directory + file;

		trStandardFileSave saveData;

		saveData.extension = realExtension;
		saveData.filename = file;
		saveData.title = description;
		if (getStdFileSave(saveData))
		{
			file = saveData.filename;
			sucsessful = true;
		}
		else
			sucsessful = false;

		return true;
	}
};

Win32SaveDialog	saveDialog;

BZWB_PLUGIN_CALL int bzwb_Load (const char* /*commandLine*/, void * instance )
{
	theAppWindow = (HWND) bzwb_getOSMainWindowHandle();
	theInstance = (HINSTANCE)instance;

	INITCOMMONCONTROLSEX InitCtrls;
	InitCtrls.dwICC = ICC_LISTVIEW_CLASSES;
	InitCtrls.dwSize = sizeof(INITCOMMONCONTROLSEX);
	BOOL bRet = InitCommonControlsEx(&InitCtrls);

	bzwb_registerCommonControlHandler(openDialog.type, &openDialog);
	bzwb_registerCommonControlHandler(saveDialog.type, &saveDialog);
	return 0;
}

BZWB_PLUGIN_CALL int bzwb_Unload (void)
{
	bzwb_removeCommonControlHandlerr(openDialog.type, &openDialog);
	bzwb_removeCommonControlHandlerr(saveDialog.type, &saveDialog);
	return 0;
}

<|endoftext|>


<commit_before>//
// Created by pkanev on 12/8/2017.
//

#include <include/v8.h>
#include <assert.h>
#include <android/log.h>
#include <cstdlib>
#include <chrono>
#include <iomanip>
#include <sstream>
#include <V8GlobalHelpers.h>
#include <v8_inspector/src/inspector/v8-log-agent-impl.h>
#include <JsV8InspectorClient.h>
#include "Console.h"

namespace tns {

v8::Local<v8::Object> Console::createConsole(v8::Local<v8::Context> context, const std::string& filesPath) {
    v8::Context::Scope contextScope(context);
    v8::Isolate* isolate = context->GetIsolate();

    v8::Local<v8::Object> console = v8::Object::New(isolate);
    bool success = console->SetPrototype(context, v8::Object::New(isolate)).FromMaybe(false);

    assert(success);

    std::map<std::string, double> timersMap;
    Console::s_isolateToConsoleTimersMap.insert(std::make_pair(context->GetIsolate(), timersMap));

    bindFunctionProperty(context, console, "assert", assertCallback);
    bindFunctionProperty(context, console, "error", errorCallback);
    bindFunctionProperty(context, console, "info", infoCallback);
    bindFunctionProperty(context, console, "log", logCallback);
    bindFunctionProperty(context, console, "warn", warnCallback);
    bindFunctionProperty(context, console, "dir", dirCallback);
    bindFunctionProperty(context, console, "trace", traceCallback);
    bindFunctionProperty(context, console, "time", timeCallback);
    bindFunctionProperty(context, console, "timeEnd", timeEndCallback);

    return console;
}

void Console::sendToADBLogcat(const std::string& message, android_LogPriority logPriority) {
    // split strings into chunks of 4000 characters
    // __android_log_write can't send more than 4000 to the stdout at a time

    auto messageLength = message.length();
    int maxStringLength = 4000;

    if (messageLength < maxStringLength) {
        __android_log_write(logPriority, Console::LOG_TAG, message.c_str());
    } else {
        for (int i = 0; i < messageLength; i += maxStringLength) {
            auto messagePart = message.substr(i, maxStringLength);

            __android_log_write(logPriority, Console::LOG_TAG, messagePart.c_str());
        }
    }
}

void Console::sendToDevToolsFrontEnd(v8::Isolate* isolate, const std::string& message, const std::string& logLevel) {
    if (!JsV8InspectorClient::inspectorIsConnected()) {
        return;
    }

    auto stack = v8::StackTrace::CurrentStackTrace(isolate, 1, v8::StackTrace::StackTraceOptions::kDetailed);

    auto frame = stack->GetFrame(0);

    // will be no-op in non-debuggable builds
    v8_inspector::V8LogAgentImpl::EntryAdded(message, logLevel, ArgConverter::ConvertToString(frame->GetScriptNameOrSourceURL()), frame->GetLineNumber());
}

const std::string buildLogString(const v8::FunctionCallbackInfo<v8::Value>& info, int startingIndex = 0) {
    auto isolate = info.GetIsolate();

    v8::HandleScope scope(isolate);

    std::stringstream ss;

    auto argLen = info.Length();
    if (argLen) {
        for (int i = startingIndex; i < argLen; i++) {
            v8::Local<v8::String> argString;
            if (info[i]->IsFunction()) {
                info[i]->ToDetailString(isolate->GetCurrentContext()).ToLocal(&argString);
            } else if (info[i]->IsObject()) {
                v8::Local<v8::Object> obj = info[i].As<v8::Object>();
                argString = JsonStringifyObject(isolate, obj);
            } else {
                info[i]->ToDetailString(isolate->GetCurrentContext()).ToLocal(&argString);
            }

            // separate args with a space
            if (i != 0) {
                ss << " ";
            }

            ss << ArgConverter::ConvertToString(argString);
        }
    } else {
        ss << std::endl;
    }

    std::string stringResult = ss.str();

    return stringResult;
}

void Console::assertCallback(const v8::FunctionCallbackInfo<v8::Value>& info) {
    auto isolate = info.GetIsolate();

    auto argLen = info.Length();
    auto expressionPasses = argLen && info[0]->BooleanValue();

    if (!expressionPasses) {
        std::stringstream assertionError;

        assertionError << "Assertion failed: ";

        if (argLen > 1) {
            assertionError << buildLogString(info, 1);
        } else {
            assertionError << "console.assert";
        }

        std::string log = assertionError.str();
        sendToADBLogcat(log, ANDROID_LOG_ERROR);
        sendToDevToolsFrontEnd(isolate, log, "error");
    }
}

void Console::errorCallback(const v8::FunctionCallbackInfo <v8::Value>& info) {
    std::string log = buildLogString(info);

    sendToADBLogcat(log, ANDROID_LOG_ERROR);
    sendToDevToolsFrontEnd(info.GetIsolate(), log, "error");
}

void Console::infoCallback(const v8::FunctionCallbackInfo<v8::Value>& info) {
    std::string log = buildLogString(info);

    sendToADBLogcat(log, ANDROID_LOG_INFO);
    sendToDevToolsFrontEnd(info.GetIsolate(), log, "info");
}

void Console::logCallback(const v8::FunctionCallbackInfo<v8::Value>& info) {
    std::string log = buildLogString(info);

    sendToADBLogcat(log, ANDROID_LOG_INFO);
    sendToDevToolsFrontEnd(info.GetIsolate(), log, "info");
}

void Console::warnCallback(const v8::FunctionCallbackInfo<v8::Value>& info) {
    std::string log = buildLogString(info);

    sendToADBLogcat(log, ANDROID_LOG_WARN);
    sendToDevToolsFrontEnd(info.GetIsolate(), log, "warning");
}

void Console::dirCallback(const v8::FunctionCallbackInfo<v8::Value>& info) {
    auto isolate = info.GetIsolate();
    auto context = isolate->GetCurrentContext();

    v8::HandleScope scope(isolate);

    std::stringstream ss;

    auto argLen = info.Length();
    if (argLen) {
        if (info[0]->IsObject()) {
            ss << "==== object dump start ====" << std::endl;
            v8::Local<v8::Object> argObject = info[0].As<v8::Object>();

            v8::Local<v8::Array> propNames;
            argObject->GetPropertyNames(context).ToLocal(&propNames);

            auto propertiesLen = propNames->Length();
            for (int i = 0; i < propertiesLen; i++) {
                auto propertyName = propNames->Get(context, i).ToLocalChecked();
                auto propertyValue = argObject->Get(context, propertyName).ToLocalChecked();

                auto propIsFunction = propertyValue->IsFunction();

                ss << ArgConverter::ConvertToString(propertyName->ToString(isolate));

                if (propIsFunction) {
                    ss << "()";
                }

                ss << std::endl;
            }

            ss << "==== object dump end ====" << std::endl;
        } else {
            std::string logString = buildLogString(info);

            ss << logString;
        }
    } else {
        ss << std::endl;
    }

    std::string log = ss.str();

    sendToADBLogcat(log, ANDROID_LOG_INFO);
    sendToDevToolsFrontEnd(isolate, log, "info");
}

const std::string buildStacktraceFrameLocationPart(v8::Local<v8::StackFrame> frame) {
    std::stringstream ss;

    auto scriptName = frame->GetScriptNameOrSourceURL();
    auto scriptNameConverted = ArgConverter::ConvertToString(scriptName);
    if (scriptNameConverted.length() < 1) {
        ss << "VM";
    } else {
        ss << scriptNameConverted << ":" << frame->GetLineNumber() << ":" << frame->GetColumn();
    }

    std::string stringResult = ss.str();

    return stringResult;
}

const std::string buildStacktraceFrameMessage(v8::Local<v8::StackFrame> frame) {
    std::stringstream ss;

    auto functionName = frame->GetFunctionName();
    auto functionNameConverted = ArgConverter::ConvertToString(functionName);
    if (functionNameConverted.length() < 1) {
        functionNameConverted = "<anonymous>";
    }

    if (frame->IsConstructor()) {
        ss << "at new " << functionNameConverted << " (" << buildStacktraceFrameLocationPart(frame) << ")";
    } else if (frame->IsEval()) {
        ss << "eval at " << buildStacktraceFrameLocationPart(frame) << std::endl;
    } else {
        ss << "at " << functionNameConverted << " (" << buildStacktraceFrameLocationPart(frame) << ")";
    }

    std::string stringResult = ss.str();

    return stringResult;
}

void Console::traceCallback(const v8::FunctionCallbackInfo<v8::Value>& info) {
    auto isolate = info.GetIsolate();
    std::stringstream ss;

    std::string logString = buildLogString(info);

    if (logString.compare("\n") == 0) {
        ss << "Trace";
    } else {
        ss << "Trace: " << logString;
    }

    ss << std::endl;

    v8::HandleScope scope(isolate);

    auto stack = v8::StackTrace::CurrentStackTrace(isolate, 10, v8::StackTrace::StackTraceOptions::kDetailed);

    auto framesCount = stack->GetFrameCount();

    for (int i = 0; i < framesCount; i++) {
        auto frame = stack->GetFrame(i);

        ss << buildStacktraceFrameMessage(frame) << std::endl;
    }

    std::string log = ss.str();
    __android_log_write(ANDROID_LOG_ERROR, LOG_TAG, log.c_str());
    sendToDevToolsFrontEnd(isolate, log, "error");
}

void Console::timeCallback(const v8::FunctionCallbackInfo<v8::Value>& info) {
    auto isolate = info.GetIsolate();

    v8::HandleScope scope(isolate);

    auto argLen = info.Length();
    std::string label = "default";

    v8::Local<v8::String> argString;
    if (argLen && info[0]->ToString(isolate->GetCurrentContext()).ToLocal(&argString)) {
        label = ArgConverter::ConvertToString(argString);
    }

    auto it = Console::s_isolateToConsoleTimersMap.find(isolate);
    if (it == Console::s_isolateToConsoleTimersMap.end()) {
        // throw?
    }

    auto nano = std::chrono::time_point_cast<std::chrono::milliseconds>(std::chrono::system_clock::now());
    double timeStamp = nano.time_since_epoch().count();

    it->second.insert(std::make_pair(label, timeStamp));
}

void Console::timeEndCallback(const v8::FunctionCallbackInfo<v8::Value>& info) {
    auto isolate = info.GetIsolate();

    auto argLen = info.Length();
    std::string label = "default";

    v8::Local<v8::String> argString;
    if (argLen && info[0]->ToString(isolate->GetCurrentContext()).ToLocal(&argString)) {
        label = ArgConverter::ConvertToString(argString);
    }

    auto it = Console::s_isolateToConsoleTimersMap.find(isolate);
    if (it == Console::s_isolateToConsoleTimersMap.end()) {
        // throw?
    }

    std::map<std::string, double> timersMap = it->second;

    auto itTimersMap = timersMap.find(label);
    if (itTimersMap == timersMap.end()) {
        std::string warning = std::string("No such label '" + label + "' for console.timeEnd()");

        __android_log_write(ANDROID_LOG_WARN, LOG_TAG, warning.c_str());
        sendToDevToolsFrontEnd(isolate, warning, "warning");

        return;
    }

    auto nano = std::chrono::time_point_cast<std::chrono::milliseconds>(std::chrono::system_clock::now());
    double endTimeStamp = nano.time_since_epoch().count();
    double startTimeStamp = itTimersMap->second;

    it->second.erase(label);

    auto diff = endTimeStamp - startTimeStamp;

    std::stringstream ss;
    ss << label << ": " << std::fixed << std::setprecision(2) << diff << "ms" ;
    std::string log = ss.str();

    __android_log_write(ANDROID_LOG_INFO, LOG_TAG, log.c_str());
    sendToDevToolsFrontEnd(isolate, log, "info");
}

const char* Console::LOG_TAG = "JS";
std::map<v8::Isolate*, std::map<std::string, double>> Console::s_isolateToConsoleTimersMap;
}<commit_msg>fix console.dir() implementation to display the values of object properties<commit_after>//
// Created by pkanev on 12/8/2017.
//

#include <include/v8.h>
#include <assert.h>
#include <android/log.h>
#include <cstdlib>
#include <chrono>
#include <iomanip>
#include <sstream>
#include <V8GlobalHelpers.h>
#include <v8_inspector/src/inspector/v8-log-agent-impl.h>
#include <JsV8InspectorClient.h>
#include "Console.h"

namespace tns {

v8::Local<v8::Object> Console::createConsole(v8::Local<v8::Context> context, const std::string& filesPath) {
    v8::Context::Scope contextScope(context);
    v8::Isolate* isolate = context->GetIsolate();

    v8::Local<v8::Object> console = v8::Object::New(isolate);
    bool success = console->SetPrototype(context, v8::Object::New(isolate)).FromMaybe(false);

    assert(success);

    std::map<std::string, double> timersMap;
    Console::s_isolateToConsoleTimersMap.insert(std::make_pair(context->GetIsolate(), timersMap));

    bindFunctionProperty(context, console, "assert", assertCallback);
    bindFunctionProperty(context, console, "error", errorCallback);
    bindFunctionProperty(context, console, "info", infoCallback);
    bindFunctionProperty(context, console, "log", logCallback);
    bindFunctionProperty(context, console, "warn", warnCallback);
    bindFunctionProperty(context, console, "dir", dirCallback);
    bindFunctionProperty(context, console, "trace", traceCallback);
    bindFunctionProperty(context, console, "time", timeCallback);
    bindFunctionProperty(context, console, "timeEnd", timeEndCallback);

    return console;
}

void Console::sendToADBLogcat(const std::string& message, android_LogPriority logPriority) {
    // split strings into chunks of 4000 characters
    // __android_log_write can't send more than 4000 to the stdout at a time

    auto messageLength = message.length();
    int maxStringLength = 4000;

    if (messageLength < maxStringLength) {
        __android_log_write(logPriority, Console::LOG_TAG, message.c_str());
    } else {
        for (int i = 0; i < messageLength; i += maxStringLength) {
            auto messagePart = message.substr(i, maxStringLength);

            __android_log_write(logPriority, Console::LOG_TAG, messagePart.c_str());
        }
    }
}

void Console::sendToDevToolsFrontEnd(v8::Isolate* isolate, const std::string& message, const std::string& logLevel) {
    if (!JsV8InspectorClient::inspectorIsConnected()) {
        return;
    }

    auto stack = v8::StackTrace::CurrentStackTrace(isolate, 1, v8::StackTrace::StackTraceOptions::kDetailed);

    auto frame = stack->GetFrame(0);

    // will be no-op in non-debuggable builds
    v8_inspector::V8LogAgentImpl::EntryAdded(message, logLevel, ArgConverter::ConvertToString(frame->GetScriptNameOrSourceURL()), frame->GetLineNumber());
}

const std::string buildLogString(const v8::FunctionCallbackInfo<v8::Value>& info, int startingIndex = 0) {
    auto isolate = info.GetIsolate();

    v8::HandleScope scope(isolate);

    std::stringstream ss;

    auto argLen = info.Length();
    if (argLen) {
        for (int i = startingIndex; i < argLen; i++) {
            v8::Local<v8::String> argString;
            if (info[i]->IsFunction()) {
                info[i]->ToDetailString(isolate->GetCurrentContext()).ToLocal(&argString);
            } else if (info[i]->IsObject()) {
                v8::Local<v8::Object> obj = info[i].As<v8::Object>();
                argString = JsonStringifyObject(isolate, obj);
            } else {
                info[i]->ToDetailString(isolate->GetCurrentContext()).ToLocal(&argString);
            }

            // separate args with a space
            if (i != 0) {
                ss << " ";
            }

            ss << ArgConverter::ConvertToString(argString);
        }
    } else {
        ss << std::endl;
    }

    std::string stringResult = ss.str();

    return stringResult;
}

void Console::assertCallback(const v8::FunctionCallbackInfo<v8::Value>& info) {
    auto isolate = info.GetIsolate();

    auto argLen = info.Length();
    auto expressionPasses = argLen && info[0]->BooleanValue();

    if (!expressionPasses) {
        std::stringstream assertionError;

        assertionError << "Assertion failed: ";

        if (argLen > 1) {
            assertionError << buildLogString(info, 1);
        } else {
            assertionError << "console.assert";
        }

        std::string log = assertionError.str();
        sendToADBLogcat(log, ANDROID_LOG_ERROR);
        sendToDevToolsFrontEnd(isolate, log, "error");
    }
}

void Console::errorCallback(const v8::FunctionCallbackInfo <v8::Value>& info) {
    std::string log = buildLogString(info);

    sendToADBLogcat(log, ANDROID_LOG_ERROR);
    sendToDevToolsFrontEnd(info.GetIsolate(), log, "error");
}

void Console::infoCallback(const v8::FunctionCallbackInfo<v8::Value>& info) {
    std::string log = buildLogString(info);

    sendToADBLogcat(log, ANDROID_LOG_INFO);
    sendToDevToolsFrontEnd(info.GetIsolate(), log, "info");
}

void Console::logCallback(const v8::FunctionCallbackInfo<v8::Value>& info) {
    std::string log = buildLogString(info);

    sendToADBLogcat(log, ANDROID_LOG_INFO);
    sendToDevToolsFrontEnd(info.GetIsolate(), log, "info");
}

void Console::warnCallback(const v8::FunctionCallbackInfo<v8::Value>& info) {
    std::string log = buildLogString(info);

    sendToADBLogcat(log, ANDROID_LOG_WARN);
    sendToDevToolsFrontEnd(info.GetIsolate(), log, "warning");
}

void Console::dirCallback(const v8::FunctionCallbackInfo<v8::Value>& info) {
    auto isolate = info.GetIsolate();
    auto context = isolate->GetCurrentContext();

    v8::HandleScope scope(isolate);

    std::stringstream ss;

    auto argLen = info.Length();
    if (argLen) {
        if (info[0]->IsObject()) {
            ss << "==== object dump start ====" << std::endl;
            v8::Local<v8::Object> argObject = info[0].As<v8::Object>();

            v8::Local<v8::Array> propNames;
            argObject->GetPropertyNames(context).ToLocal(&propNames);

            auto propertiesLen = propNames->Length();
            for (int i = 0; i < propertiesLen; i++) {
                auto propertyName = propNames->Get(context, i).ToLocalChecked();
                auto propertyValue = argObject->Get(context, propertyName).ToLocalChecked();

                auto propIsFunction = propertyValue->IsFunction();

                ss << ArgConverter::ConvertToString(propertyName->ToString(isolate));

                if (propIsFunction) {
                    ss << "()";
                } else if (propertyValue->IsObject()) {
                    ss << ": " << ArgConverter::ConvertToString(JsonStringifyObject(isolate, propertyValue));
                } else {
                    ss << ": " << ArgConverter::ConvertToString(propertyValue->ToDetailString(isolate));
                }

                ss << std::endl;
            }

            ss << "==== object dump end ====" << std::endl;
        } else {
            std::string logString = buildLogString(info);

            ss << logString;
        }
    } else {
        ss << std::endl;
    }

    std::string log = ss.str();

    sendToADBLogcat(log, ANDROID_LOG_INFO);
    sendToDevToolsFrontEnd(isolate, log, "info");
}

const std::string buildStacktraceFrameLocationPart(v8::Local<v8::StackFrame> frame) {
    std::stringstream ss;

    auto scriptName = frame->GetScriptNameOrSourceURL();
    auto scriptNameConverted = ArgConverter::ConvertToString(scriptName);
    if (scriptNameConverted.length() < 1) {
        ss << "VM";
    } else {
        ss << scriptNameConverted << ":" << frame->GetLineNumber() << ":" << frame->GetColumn();
    }

    std::string stringResult = ss.str();

    return stringResult;
}

const std::string buildStacktraceFrameMessage(v8::Local<v8::StackFrame> frame) {
    std::stringstream ss;

    auto functionName = frame->GetFunctionName();
    auto functionNameConverted = ArgConverter::ConvertToString(functionName);
    if (functionNameConverted.length() < 1) {
        functionNameConverted = "<anonymous>";
    }

    if (frame->IsConstructor()) {
        ss << "at new " << functionNameConverted << " (" << buildStacktraceFrameLocationPart(frame) << ")";
    } else if (frame->IsEval()) {
        ss << "eval at " << buildStacktraceFrameLocationPart(frame) << std::endl;
    } else {
        ss << "at " << functionNameConverted << " (" << buildStacktraceFrameLocationPart(frame) << ")";
    }

    std::string stringResult = ss.str();

    return stringResult;
}

void Console::traceCallback(const v8::FunctionCallbackInfo<v8::Value>& info) {
    auto isolate = info.GetIsolate();
    std::stringstream ss;

    std::string logString = buildLogString(info);

    if (logString.compare("\n") == 0) {
        ss << "Trace";
    } else {
        ss << "Trace: " << logString;
    }

    ss << std::endl;

    v8::HandleScope scope(isolate);

    auto stack = v8::StackTrace::CurrentStackTrace(isolate, 10, v8::StackTrace::StackTraceOptions::kDetailed);

    auto framesCount = stack->GetFrameCount();

    for (int i = 0; i < framesCount; i++) {
        auto frame = stack->GetFrame(i);

        ss << buildStacktraceFrameMessage(frame) << std::endl;
    }

    std::string log = ss.str();
    __android_log_write(ANDROID_LOG_ERROR, LOG_TAG, log.c_str());
    sendToDevToolsFrontEnd(isolate, log, "error");
}

void Console::timeCallback(const v8::FunctionCallbackInfo<v8::Value>& info) {
    auto isolate = info.GetIsolate();

    v8::HandleScope scope(isolate);

    auto argLen = info.Length();
    std::string label = "default";

    v8::Local<v8::String> argString;
    if (argLen && info[0]->ToString(isolate->GetCurrentContext()).ToLocal(&argString)) {
        label = ArgConverter::ConvertToString(argString);
    }

    auto it = Console::s_isolateToConsoleTimersMap.find(isolate);
    if (it == Console::s_isolateToConsoleTimersMap.end()) {
        // throw?
    }

    auto nano = std::chrono::time_point_cast<std::chrono::milliseconds>(std::chrono::system_clock::now());
    double timeStamp = nano.time_since_epoch().count();

    it->second.insert(std::make_pair(label, timeStamp));
}

void Console::timeEndCallback(const v8::FunctionCallbackInfo<v8::Value>& info) {
    auto isolate = info.GetIsolate();

    auto argLen = info.Length();
    std::string label = "default";

    v8::Local<v8::String> argString;
    if (argLen && info[0]->ToString(isolate->GetCurrentContext()).ToLocal(&argString)) {
        label = ArgConverter::ConvertToString(argString);
    }

    auto it = Console::s_isolateToConsoleTimersMap.find(isolate);
    if (it == Console::s_isolateToConsoleTimersMap.end()) {
        // throw?
    }

    std::map<std::string, double> timersMap = it->second;

    auto itTimersMap = timersMap.find(label);
    if (itTimersMap == timersMap.end()) {
        std::string warning = std::string("No such label '" + label + "' for console.timeEnd()");

        __android_log_write(ANDROID_LOG_WARN, LOG_TAG, warning.c_str());
        sendToDevToolsFrontEnd(isolate, warning, "warning");

        return;
    }

    auto nano = std::chrono::time_point_cast<std::chrono::milliseconds>(std::chrono::system_clock::now());
    double endTimeStamp = nano.time_since_epoch().count();
    double startTimeStamp = itTimersMap->second;

    it->second.erase(label);

    auto diff = endTimeStamp - startTimeStamp;

    std::stringstream ss;
    ss << label << ": " << std::fixed << std::setprecision(2) << diff << "ms" ;
    std::string log = ss.str();

    __android_log_write(ANDROID_LOG_INFO, LOG_TAG, log.c_str());
    sendToDevToolsFrontEnd(isolate, log, "info");
}

const char* Console::LOG_TAG = "JS";
std::map<v8::Isolate*, std::map<std::string, double>> Console::s_isolateToConsoleTimersMap;
}<|endoftext|>