<commit_before>#include "UI/lyricdownloaderwindow.h"
#include <QMessageBox>
#include <QMimeData>
#include <QFileInfo>
#include <QDir>
#include <QMessageBox>
#include <QAction>

LyricDownloaderWindow::LyricDownloaderWindow(QWidget *parent) : QMainWindow(parent) {
    qRegisterMetaType<LyricStatus>("LyricStatus");

    fileList = new QTreeWidget;
    fileList->setIndentation(0);
    fileList->setColumnCount(2);
    fileList->setHeaderLabels({ "Lyrics?", "File" });
    fileList->header()->setStretchLastSection(true);
    fileList->header()->setSectionResizeMode(0, QHeaderView::ResizeToContents);
    fileList->header()->setSectionResizeMode(1, QHeaderView::ResizeToContents);
    fileList->header()->setStretchLastSection(true);
//  fileList->model()->setHeaderData(0, Qt::Horizontal, Qt::AlignCenter, Qt::TextAlignmentRole);
    fileList->setSelectionMode(QAbstractItemView::ExtendedSelection);
    fileList->installEventFilter(this);

    vbox = new QVBoxLayout;
    bottomHbox = new QHBoxLayout;

    addFolderButton = new QPushButton("Add folder...");
    addFilesButton = new QPushButton("Add file(s)...");
    startDownloadButton = new QPushButton("Start download");
    startDownloadButton->setEnabled(false);
    overwriteLyricsCheckBox = new QCheckBox("Download and overwrite lyrics for files that already have them");
    progressBar = new QProgressBar;
    progressBar->setMinimum(0);
    progressBar->setMaximum(10);
    progressBar->setValue(0);
    progressBar->setTextVisible(false);

    bottomHbox->addStretch();
    bottomHbox->addWidget(addFolderButton);
    bottomHbox->addWidget(addFilesButton);
    bottomHbox->addWidget(startDownloadButton);

    QWidget *central = new QWidget;
    central->setLayout(vbox);
    vbox->addWidget(fileList);
    vbox->addWidget(progressBar);
    vbox->addWidget(overwriteLyricsCheckBox);
    vbox->addLayout(bottomHbox);
    setCentralWidget(central);

    connect(addFolderButton, &QPushButton::clicked, [&] {
        QFileDialog fileDialog;
        fileDialog.setFileMode(QFileDialog::Directory);
        fileDialog.setOption(QFileDialog::ShowDirsOnly, true);
        if (fileDialog.exec()) {
            if (fileDialog.selectedFiles().length() > 0)
                startDownloadButton->setEnabled(true);
            // Only one directory is supposed to be selectable, but just in case...
            for (const QString &dir : fileDialog.selectedFiles()) {
                addFilesRecursively(dir, 15);
            }
        }

        if (fileList->topLevelItemCount() > 0)
            startDownloadButton->setEnabled(true);
    });

    connect(addFilesButton, &QPushButton::clicked, [&] {
        QFileDialog fileDialog;
        fileDialog.setNameFilter("Supported files (*.mp3 *.m4a);;MP3 files (*.mp3);;M4A files (*.m4a)");
        fileDialog.setFileMode(QFileDialog::ExistingFiles);
        if (fileDialog.exec()) {
            if (fileDialog.selectedFiles().length() > 0)
                startDownloadButton->setEnabled(true);
            for (const QString &file : fileDialog.selectedFiles()) {
                addFile(file);
            }
        }

        if (fileList->topLevelItemCount() > 0)
            startDownloadButton->setEnabled(true);
    });

    connect(startDownloadButton, &QPushButton::clicked, this, &LyricDownloaderWindow::startButtonClicked);

    resize(900, 600);

    setAcceptDrops(true);
}

void LyricDownloaderWindow::startButtonClicked() {
    if (workerThread) {
        Q_ASSERT(!workerThread->isRunning());
        delete workerThread;
        workerThread = nullptr;
    }
    if (worker) {
        delete worker;
        worker = nullptr;
    }

    // <index, path> -- this is used because the index into filesToProcess may not equal the index of the fileList.
    // They only match if every track is NotProcessed, so this would fail if a previous operation had been aborted
    // and then resumed.
    // The worker needs to know the index into the fileList (for status updates), so we include it here.
    QList<QPair<int, QString>> filesToProcess;
    for (int i = 0; i < fileList->topLevelItemCount(); i++) {
        auto *item = fileList->topLevelItem(i);
        LyricStatus status = item->data(0, Qt::UserRole).value<LyricStatus>();
        if (status == LyricStatus::NotProcessed)
            filesToProcess.append({ i, item->data(1, Qt::DisplayRole).toString() });
    }

    if (filesToProcess.length() == 0) {
        QMessageBox::information(this, "Done", "Nothing to do -- all tracks are already processed!", QMessageBox::Ok);
        return;
    }

    progressBar->setValue(0);
    progressBar->setMaximum(filesToProcess.length());
    progressBar->setTextVisible(true);

    worker = new LyricDownloaderWorker(filesToProcess, overwriteLyricsCheckBox->isChecked()); // Copy the data to the worker
    workerThread = new QThread;
    worker->moveToThread(workerThread);

    connect(workerThread, &QThread::started, worker, &LyricDownloaderWorker::process);
    connect(worker, &LyricDownloaderWorker::finished, workerThread, &QThread::quit);

    connect(worker, &LyricDownloaderWorker::updateProgress, this, &LyricDownloaderWindow::progressUpdate);
    connect(worker, &LyricDownloaderWorker::finished, this, [this] {
        progressBar->setValue(0);
        progressBar->setTextVisible(false);

        disconnect(startDownloadButton, &QPushButton::clicked, 0, 0);
        connect(startDownloadButton, &QPushButton::clicked, this, &LyricDownloaderWindow::startButtonClicked);
        startDownloadButton->setText("Start download");
        startDownloadButton->setEnabled(true);
    }, Qt::QueuedConnection);

    fileList->topLevelItem(0)->setBackgroundColor(0, QColor(133, 137, 255)); // Highlight the current item in blue

    workerThread->start();

    connect(worker, &LyricDownloaderWorker::aborted, this, [this](int lastProcessedIndex) {
        auto *item = fileList->topLevelItem(lastProcessedIndex + 1);
        if (item)
            item->setBackgroundColor(0, QColor(Qt::red));
    }, Qt::QueuedConnection);

    disconnect(startDownloadButton, &QPushButton::clicked, 0, 0);
    connect(startDownloadButton, &QPushButton::clicked, worker, &LyricDownloaderWorker::abort);
    startDownloadButton->setText("Stop download");
    startDownloadButton->setEnabled(true);
}

void LyricDownloaderWindow::progressUpdate(int index, LyricStatus status) {
    Q_ASSERT(index < fileList->topLevelItemCount());
    auto *item = fileList->topLevelItem(index);

    item->setData(0, Qt::UserRole, qVariantFromValue(status));

    if (status == LyricStatus::DownloadFailed) {
        item->setBackgroundColor(0, QColor(Qt::red));
        item->setData(0, Qt::DisplayRole, "Error");
    }
    else if (status == LyricStatus::NoLyricsFound) {
        item->setBackgroundColor(0, QColor(Qt::yellow));
        item->setData(0, Qt::DisplayRole, "No");
    }
    else if (status == LyricStatus::HadLyrics || status == LyricStatus::LyricsDownloaded) {
        item->setBackground(0, QColor(Qt::green));
        item->setData(0, Qt::DisplayRole, "Yes");
    }

    auto *nextItem = fileList->topLevelItem(index + 1);
    if (nextItem) {
        nextItem->setBackgroundColor(0, QColor(133, 137, 255)); // Highlight the current item in blue
        fileList->scrollToItem(nextItem);
    }
    else
        fileList->scrollToItem(item);

    progressBar->setValue(index + 1);
}

bool LyricDownloaderWindow::eventFilter(QObject *target, QEvent *event) {
    Q_ASSERT(target == fileList);
    if (event->type() == QEvent::KeyPress) {
        QKeyEvent *keyEvent = static_cast<QKeyEvent*>(event);
        if (keyEvent->key() == Qt::Key_Delete) {
            for (const auto &item : fileList->selectedItems()) {
                delete item;
            }

            if (fileList->topLevelItemCount() == 0)
                startDownloadButton->setEnabled(false);
        }
    }

    return QMainWindow::eventFilter(target, event);
}

void LyricDownloaderWindow::dragEnterEvent(QDragEnterEvent *e) {
    if (workerThread && workerThread->isRunning())
        return;

    // If at least one of the files dragged inside is an MP3 file, an M4A file, or a folder, accept the drop.
    // If not, deny it.
    // This means we might get a folder full of JPEG files, but we can't recursively check everything here,
    // or the UI will be laggy like all hell when big folders are dragged.
    // Careful checking will need to happen on drop.
    for (const QUrl &url : e->mimeData()->urls()) {
        QString local = url.toLocalFile();
        QFileInfo fileInfo(local);
        if (fileInfo.isDir() || fileInfo.suffix() == "mp3" || fileInfo.suffix() == "m4a") {
            e->acceptProposedAction();
            return;
        }
    }
}

void LyricDownloaderWindow::dropEvent(QDropEvent *e) {
    QStringList types = { "mp3", "m4a" };
    for (const QUrl &url : e->mimeData()->urls()) {
        QString local = url.toLocalFile();
        QFileInfo fileInfo(local);
        if (fileInfo.suffix() == "mp3" || fileInfo.suffix() == "m4a") {
            addFile(local);
        }
        else if (fileInfo.isDir()) {
            addFilesRecursively(local, 15);
        }
        else
            continue;
    }

    if (fileList->topLevelItemCount() > 0)
        startDownloadButton->setEnabled(true);
}

void LyricDownloaderWindow::addFile(const QString &file) {
    auto *item = new QTreeWidgetItem({"?", file});
    item->setData(0, Qt::UserRole, qVariantFromValue(LyricStatus::NotProcessed));
    fileList->addTopLevelItem(item);
}

void LyricDownloaderWindow::addFilesRecursively(const QString &sDir, int max_depth) {
    QDir dir(sDir);
    QFileInfoList list = dir.entryInfoList(dir.nameFilters(), QDir::AllEntries | QDir::NoDotAndDotDot);

    for (QFileInfo info : list) {
//        if (Application::shouldTerminate)
//            return {};
        QString sFilePath = info.filePath();
        QString absPath = info.absoluteFilePath();

        if (absPath.endsWith(".mp3", Qt::CaseInsensitive)|| absPath.endsWith(".m4a", Qt::CaseInsensitive)) {
            addFile(absPath);
        }

        if (max_depth > 0 && info.isDir() && !info.isSymLink()) {
            addFilesRecursively(sFilePath, max_depth - 1);
        }
    }
}

<commit_msg>Disable buttons and checkboxes when the downloader is running<commit_after>#include "UI/lyricdownloaderwindow.h"
#include <QMessageBox>
#include <QMimeData>
#include <QFileInfo>
#include <QDir>
#include <QMessageBox>
#include <QAction>

LyricDownloaderWindow::LyricDownloaderWindow(QWidget *parent) : QMainWindow(parent) {
    qRegisterMetaType<LyricStatus>("LyricStatus");

    fileList = new QTreeWidget;
    fileList->setIndentation(0);
    fileList->setColumnCount(2);
    fileList->setHeaderLabels({ "Lyrics?", "File" });
    fileList->header()->setStretchLastSection(true);
    fileList->header()->setSectionResizeMode(0, QHeaderView::ResizeToContents);
    fileList->header()->setSectionResizeMode(1, QHeaderView::ResizeToContents);
    fileList->header()->setStretchLastSection(true);
//  fileList->model()->setHeaderData(0, Qt::Horizontal, Qt::AlignCenter, Qt::TextAlignmentRole);
    fileList->setSelectionMode(QAbstractItemView::ExtendedSelection);
    fileList->installEventFilter(this);

    vbox = new QVBoxLayout;
    bottomHbox = new QHBoxLayout;

    addFolderButton = new QPushButton("Add folder...");
    addFilesButton = new QPushButton("Add file(s)...");
    startDownloadButton = new QPushButton("Start download");
    startDownloadButton->setEnabled(false);
    overwriteLyricsCheckBox = new QCheckBox("Download and overwrite lyrics for files that already have them");
    progressBar = new QProgressBar;
    progressBar->setMinimum(0);
    progressBar->setMaximum(10);
    progressBar->setValue(0);
    progressBar->setTextVisible(false);

    bottomHbox->addStretch();
    bottomHbox->addWidget(addFolderButton);
    bottomHbox->addWidget(addFilesButton);
    bottomHbox->addWidget(startDownloadButton);

    QWidget *central = new QWidget;
    central->setLayout(vbox);
    vbox->addWidget(fileList);
    vbox->addWidget(progressBar);
    vbox->addWidget(overwriteLyricsCheckBox);
    vbox->addLayout(bottomHbox);
    setCentralWidget(central);

    connect(addFolderButton, &QPushButton::clicked, [&] {
        QFileDialog fileDialog;
        fileDialog.setFileMode(QFileDialog::Directory);
        fileDialog.setOption(QFileDialog::ShowDirsOnly, true);
        if (fileDialog.exec()) {
            if (fileDialog.selectedFiles().length() > 0)
                startDownloadButton->setEnabled(true);
            // Only one directory is supposed to be selectable, but just in case...
            for (const QString &dir : fileDialog.selectedFiles()) {
                addFilesRecursively(dir, 15);
            }
        }

        if (fileList->topLevelItemCount() > 0)
            startDownloadButton->setEnabled(true);
    });

    connect(addFilesButton, &QPushButton::clicked, [&] {
        QFileDialog fileDialog;
        fileDialog.setNameFilter("Supported files (*.mp3 *.m4a);;MP3 files (*.mp3);;M4A files (*.m4a)");
        fileDialog.setFileMode(QFileDialog::ExistingFiles);
        if (fileDialog.exec()) {
            if (fileDialog.selectedFiles().length() > 0)
                startDownloadButton->setEnabled(true);
            for (const QString &file : fileDialog.selectedFiles()) {
                addFile(file);
            }
        }

        if (fileList->topLevelItemCount() > 0)
            startDownloadButton->setEnabled(true);
    });

    connect(startDownloadButton, &QPushButton::clicked, this, &LyricDownloaderWindow::startButtonClicked);

    resize(900, 600);

    setAcceptDrops(true);
}

void LyricDownloaderWindow::startButtonClicked() {
    if (workerThread) {
        Q_ASSERT(!workerThread->isRunning());
        delete workerThread;
        workerThread = nullptr;
    }
    if (worker) {
        delete worker;
        worker = nullptr;
    }

    // <index, path> -- this is used because the index into filesToProcess may not equal the index of the fileList.
    // They only match if every track is NotProcessed, so this would fail if a previous operation had been aborted
    // and then resumed.
    // The worker needs to know the index into the fileList (for status updates), so we include it here.
    QList<QPair<int, QString>> filesToProcess;
    for (int i = 0; i < fileList->topLevelItemCount(); i++) {
        auto *item = fileList->topLevelItem(i);
        LyricStatus status = item->data(0, Qt::UserRole).value<LyricStatus>();
        if (status == LyricStatus::NotProcessed)
            filesToProcess.append({ i, item->data(1, Qt::DisplayRole).toString() });
    }

    if (filesToProcess.length() == 0) {
        QMessageBox::information(this, "Done", "Nothing to do -- all tracks are already processed!", QMessageBox::Ok);
        return;
    }

    progressBar->setValue(0);
    progressBar->setMaximum(filesToProcess.length());
    progressBar->setTextVisible(true);

    worker = new LyricDownloaderWorker(filesToProcess, overwriteLyricsCheckBox->isChecked()); // Copy the data to the worker
    workerThread = new QThread;
    worker->moveToThread(workerThread);

    connect(workerThread, &QThread::started, worker, &LyricDownloaderWorker::process);
    connect(worker, &LyricDownloaderWorker::finished, workerThread, &QThread::quit);

    connect(worker, &LyricDownloaderWorker::updateProgress, this, &LyricDownloaderWindow::progressUpdate);
    connect(worker, &LyricDownloaderWorker::finished, this, [this] {
        progressBar->setValue(0);
        progressBar->setTextVisible(false);

        disconnect(startDownloadButton, &QPushButton::clicked, 0, 0);
        connect(startDownloadButton, &QPushButton::clicked, this, &LyricDownloaderWindow::startButtonClicked);
        startDownloadButton->setText("Start download");
        startDownloadButton->setEnabled(true);

        addFilesButton->setEnabled(true);
        addFolderButton->setEnabled(true);
        overwriteLyricsCheckBox->setEnabled(true);
    }, Qt::QueuedConnection);

    fileList->topLevelItem(0)->setBackgroundColor(0, QColor(133, 137, 255)); // Highlight the current item in blue

    workerThread->start();

    connect(worker, &LyricDownloaderWorker::aborted, this, [this](int lastProcessedIndex) {
        auto *item = fileList->topLevelItem(lastProcessedIndex + 1);
        if (item)
            item->setBackgroundColor(0, QColor(Qt::red));
    }, Qt::QueuedConnection);

    disconnect(startDownloadButton, &QPushButton::clicked, 0, 0);
    connect(startDownloadButton, &QPushButton::clicked, worker, &LyricDownloaderWorker::abort);
    startDownloadButton->setText("Stop download");
    startDownloadButton->setEnabled(true);

    addFilesButton->setEnabled(false);
    addFolderButton->setEnabled(false);
    overwriteLyricsCheckBox->setEnabled(false);
}

void LyricDownloaderWindow::progressUpdate(int index, LyricStatus status) {
    Q_ASSERT(index < fileList->topLevelItemCount());
    auto *item = fileList->topLevelItem(index);

    item->setData(0, Qt::UserRole, qVariantFromValue(status));

    if (status == LyricStatus::DownloadFailed) {
        item->setBackgroundColor(0, QColor(Qt::red));
        item->setData(0, Qt::DisplayRole, "Error");
    }
    else if (status == LyricStatus::NoLyricsFound) {
        item->setBackgroundColor(0, QColor(Qt::yellow));
        item->setData(0, Qt::DisplayRole, "No");
    }
    else if (status == LyricStatus::HadLyrics || status == LyricStatus::LyricsDownloaded) {
        item->setBackground(0, QColor(Qt::green));
        item->setData(0, Qt::DisplayRole, "Yes");
    }

    auto *nextItem = fileList->topLevelItem(index + 1);
    if (nextItem) {
        nextItem->setBackgroundColor(0, QColor(133, 137, 255)); // Highlight the current item in blue
        fileList->scrollToItem(nextItem);
    }
    else
        fileList->scrollToItem(item);

    progressBar->setValue(index + 1);
}

bool LyricDownloaderWindow::eventFilter(QObject *target, QEvent *event) {
    Q_ASSERT(target == fileList);
    if (event->type() == QEvent::KeyPress) {
        QKeyEvent *keyEvent = static_cast<QKeyEvent*>(event);
        if (keyEvent->key() == Qt::Key_Delete && (workerThread == nullptr || !workerThread->isRunning())) {
            for (const auto &item : fileList->selectedItems()) {
                delete item;
            }

            if (fileList->topLevelItemCount() == 0)
                startDownloadButton->setEnabled(false);
        }
    }

    return QMainWindow::eventFilter(target, event);
}

void LyricDownloaderWindow::dragEnterEvent(QDragEnterEvent *e) {
    if (workerThread && workerThread->isRunning())
        return;

    // If at least one of the files dragged inside is an MP3 file, an M4A file, or a folder, accept the drop.
    // If not, deny it.
    // This means we might get a folder full of JPEG files, but we can't recursively check everything here,
    // or the UI will be laggy like all hell when big folders are dragged.
    // Careful checking will need to happen on drop.
    for (const QUrl &url : e->mimeData()->urls()) {
        QString local = url.toLocalFile();
        QFileInfo fileInfo(local);
        if (fileInfo.isDir() || fileInfo.suffix() == "mp3" || fileInfo.suffix() == "m4a") {
            e->acceptProposedAction();
            return;
        }
    }
}

void LyricDownloaderWindow::dropEvent(QDropEvent *e) {
    QStringList types = { "mp3", "m4a" };
    for (const QUrl &url : e->mimeData()->urls()) {
        QString local = url.toLocalFile();
        QFileInfo fileInfo(local);
        if (fileInfo.suffix() == "mp3" || fileInfo.suffix() == "m4a") {
            addFile(local);
        }
        else if (fileInfo.isDir()) {
            addFilesRecursively(local, 15);
        }
        else
            continue;
    }

    if (fileList->topLevelItemCount() > 0)
        startDownloadButton->setEnabled(true);
}

void LyricDownloaderWindow::addFile(const QString &file) {
    auto *item = new QTreeWidgetItem({"?", file});
    item->setData(0, Qt::UserRole, qVariantFromValue(LyricStatus::NotProcessed));
    fileList->addTopLevelItem(item);
}

void LyricDownloaderWindow::addFilesRecursively(const QString &sDir, int max_depth) {
    QDir dir(sDir);
    QFileInfoList list = dir.entryInfoList(dir.nameFilters(), QDir::AllEntries | QDir::NoDotAndDotDot);

    for (QFileInfo info : list) {
//        if (Application::shouldTerminate)
//            return {};
        QString sFilePath = info.filePath();
        QString absPath = info.absoluteFilePath();

        if (absPath.endsWith(".mp3", Qt::CaseInsensitive)|| absPath.endsWith(".m4a", Qt::CaseInsensitive)) {
            addFile(absPath);
        }

        if (max_depth > 0 && info.isDir() && !info.isSymLink()) {
            addFilesRecursively(sFilePath, max_depth - 1);
        }
    }
}

<|endoftext|>


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

/* Test_Permutations.cpp - Applying plaintext permutation to encrypted vector
 */
#include <NTL/ZZ.h>
NTL_CLIENT

#include "NumbTh.h"
#include "timing.h"
#include "permutations.h"
#include "EncryptedArray.h"

static bool noPrint = false;

void testCtxt(long m, long p, long widthBound=0, long L=0, long r=1);

void usage(char *prog)
{
  cout << "Usage: "<<prog<<" [test=? [optional parameters...]]\n";
  cout << "  optional parameters have the form 'attr1=val1 attr2=val2 ...'\n";
  cout << "  e.g, 'test=1 m=108 p=2 r=1\n";
  cout << "  test is either 0 (plaintext) or 1 (ciphertext)[default=1]\n\n";
  cout << "test=0, permuting plaintext hypercubes (dimension upto 4):\n";
  cout << "  ord1,ord2,ord3,ord4 size of dimensions 1..4 [default ord1=30, ord2,3,4=0]\n";
  cout << "  good1,good2,good3,good4 native rotation flags (0/1) [default=1]\n";
  cout << "  depth bounds the depth of permutation network [default=5]\n";
  cout << "\ntest=1, permuting ciphertext slots:\n";
  cout << "  m is the cyclotomic field [default=4369]\n";
  cout << "  p,r define the plaintext space p^r [default p=2,r=1]\n";
  cout << "  depth bounds the depth of permutation network [default=5]\n";
  cout << "  L is number of levels in chain [default=depth]\n\n";
  cout << "dry=1 for dry run [default=0]\n";
  exit(0);
}

void testCube(Vec<GenDescriptor>& vec, long widthBound)
{
  GeneratorTrees trees;
  long cost = trees.buildOptimalTrees(vec, widthBound);
  if (!noPrint) {
    cout << "@TestCube: trees=" << trees << endl;
    cout << " cost =" << cost << endl;
  }
  Vec<long> dims;
  trees.getCubeDims(dims);
  CubeSignature sig(dims);

  for (long cnt=0; cnt<3; cnt++) {
    Permut pi;
    randomPerm(pi, trees.getSize());

    PermNetwork net;
    net.buildNetwork(pi, trees);

    HyperCube<long> cube1(sig), cube2(sig);
    for (long i=0; i<cube1.getSize(); i++) cube1[i] = i;
    HyperCube<long> cube3 = cube1;
    applyPermToVec(cube2.getData(), cube1.getData(), pi); // direct application
    net.applyToCube(cube3); // applying permutation netwrok
    if (cube2==cube3) cout << "GOOD\n";
    else {
      cout << "BAD\n";
      if (cube1.getSize()<100) {
	cout << "in="<<cube1.getData() << endl;
	cout << "out1="<<cube2.getData()<<", out2="
	     << cube3.getData()<<endl<<endl;
      }
    }
  }
}

void testCtxt(long m, long p, long widthBound, long L, long r)
{
  if (!noPrint)
    cout << "@testCtxt(m="<<m<<",p="<<p<<",depth="<<widthBound<< ",r="<<r<<")";

  FHEcontext context(m,p,r);
  EncryptedArray ea(context); // Use G(X)=X for this ea object

  // Some arbitrary initial plaintext array
  vector<long> in(ea.size());
  for (long i=0; i<ea.size(); i++) in[i] = i % p;

  // Setup generator-descriptors for the PAlgebra generators
  Vec<GenDescriptor> vec(INIT_SIZE, ea.dimension());
  for (long i=0; i<ea.dimension(); i++)
    vec[i] = GenDescriptor(/*order=*/ea.sizeOfDimension(i),
			   /*good=*/ ea.nativeDimension(i), /*genIdx=*/i);

  // Some default for the width-bound, if not provided
  if (widthBound<=0) widthBound = 1+log2((double)ea.size());

  // Get the generator-tree structures and the corresponding hypercube
  GeneratorTrees trees;
  long cost = trees.buildOptimalTrees(vec, widthBound);
  if (!noPrint) {
    cout << ": trees=" << trees << endl;
    cout << " cost =" << cost << endl;
  }
  //  Vec<long> dims;
  //  trees.getCubeDims(dims);
  //  CubeSignature sig(dims);

  // 1/2 prime per level should be more or less enough, here we use 1 per layer
  if (L<=0) L = 1+trees.numLayers();
  buildModChain(context, /*nLevels=*/L, /*nDigits=*/3);
  if (!noPrint) cout << "**Using "<<L<<" primes (of which "
		     << context.ctxtPrimes.card() << " are Ctxt-primes)\n";

  // Generate a sk/pk pair
  FHESecKey secretKey(context);
  const FHEPubKey& publicKey = secretKey;
  secretKey.GenSecKey(64); // A Hamming-weight-64 secret key
  Ctxt ctxt(publicKey);

  for (long cnt=0; cnt<3; cnt++) {
    resetAllTimers();
    // Choose a random permutation
    Permut pi;
    randomPerm(pi, trees.getSize());

    // Build a permutation network for pi
    PermNetwork net;
    net.buildNetwork(pi, trees);

    // make sure we have the key-switching matrices needed for this network
    addMatrices4Network(secretKey, net);

    // Apply the permutation pi to the plaintext
    vector<long> out1(ea.size());
    vector<long> out2(ea.size());
    applyPermToVec(out1, in, pi); // direct application

    // Encrypt plaintext array, then apply permutation network to ciphertext
    ea.encrypt(ctxt, publicKey, in);
    if (!noPrint)
      cout << "  ** applying permutation network to ciphertext... " << flush;
    double t = GetTime();
    net.applyToCtxt(ctxt, ea); // applying permutation netwrok
    t = GetTime() -t;
    if (!noPrint)
      cout << "done in " << t << " seconds" << endl;
    ea.decrypt(ctxt, secretKey, out2);

    if (out1==out2) cout << "GOOD\n";
    else {
      cout << "************ BAD\n";
    }
    // printAllTimers();
  }
}

/* m = 31, p = 2, phi(m) = 30
  ord(p)=5
  generator 6 has order (== Z_m^*) of 6
  T = [1 6 5 30 25 26 ]

  m = 61, p = 3, phi(m) = 60
  ord(p)=10
  generator 13 has order (== Z_m^*) of 3
  generator 2 has order (!= Z_m^*) of 2
  T = [1 2 13 26 47 33 ]

  m = 683, p = 2, phi(m) = 682
  ord(p)=22
  generator 3 has order (== Z_m^*) of 31

  m = 47127, p = 2, phi(m) = 30008
  ord(p)=22
  generator 5 has order (== Z_m^*) of 682
  generator 13661 has order (== Z_m^*) of 2
*/

int main(int argc, char *argv[])
{
  argmap_t argmap;
  argmap["test"] = "1";
  argmap["m"] = "4369";
  argmap["p"] = "2";
  argmap["r"] = "1";
  argmap["depth"] = "5";
  argmap["L"] = "0";
  argmap["ord1"] = "30";
  argmap["ord2"] = "0";
  argmap["ord3"] = "0";
  argmap["ord4"] = "0";
  argmap["good1"] = "1";
  argmap["good2"] = "1";
  argmap["good3"] = "1";
  argmap["good4"] = "1";
  argmap["dry"] = "1";
  argmap["noPrint"] = "0";

  // get parameters from the command line

  if (!parseArgs(argc, argv, argmap)) usage(argv[0]);

  long test = atoi(argmap["test"]);
  long p = atoi(argmap["p"]);
  long r = atoi(argmap["r"]);
  long m = atoi(argmap["m"]);
  long depth = atoi(argmap["depth"]);
  long L = atoi(argmap["L"]);

  long ord1 = atoi(argmap["ord1"]);
  long ord2 = atoi(argmap["ord2"]);
  long ord3 = atoi(argmap["ord3"]);
  long ord4 = atoi(argmap["ord4"]);
  long good1 = atoi(argmap["good1"]);
  long good2 = atoi(argmap["good2"]);
  long good3 = atoi(argmap["good3"]);
  long good4 = atoi(argmap["good4"]);

  bool dry = atoi(argmap["dry"]);
  noPrint = atoi(argmap["noPrint"]);

  setDryRun(dry);
  if (test==0) {
    Vec<GenDescriptor> vec;
    long nGens;
    if (ord2<=1) nGens=1;
    else if (ord3<=1) nGens=2;
    else if (ord4<=1) nGens=3;
    else nGens=4;
    vec.SetLength(nGens);

    switch (nGens) {
    case 4:  vec[3] = GenDescriptor(ord4, good4, /*genIdx=*/3);
    case 3:  vec[2] = GenDescriptor(ord3, good3, /*genIdx=*/2);
    case 2:  vec[1] = GenDescriptor(ord2, good2, /*genIdx=*/1);
    default: vec[0] = GenDescriptor(ord1, good1, /*genIdx=*/0);
    }
    cout << "***Testing ";
    if (isDryRun()) cout << "(dry run) ";
    for (long i=0; i<vec.length(); i++)
      cout << "("<<vec[i].order<<","<<vec[i].good<<")";
    cout << ", depth="<<depth<<"\n";
    testCube(vec, depth);
  }
  else {
    setTimersOn();
    cout << "***Testing m="<<m<<", p="<<p<<", depth="<<depth<< endl;
    testCtxt(m,p,depth,L,r);
  }
}

#if 0
  cout << "***Testing m=31, p=2, width=3\n"; // (6 good)
  testCtxt(/*m=*/31, /*p=*/2, /*width=*/3);

  cout << "\n***Testing m=61, p=3, width=3\n"; // (3 good), (2, bad)
  testCtxt(/*m=*/61, /*p=*/3, /*width=*/3);

  cout << "\n***Testing m=683, p=2, width=5\n"; // (31, good)
  testCtxt(/*m=*/683, /*p=*/2, /*width=*/5);

  //  cout << "\n***Testing m=47127, p=2, width=11\n"; // (682,good),(2,good)
  //  testCtxt(/*m=*/47127, /*p=*/2, /*width=*/11);

  // Test 1: a single good small prime-order generator (3)
  {
  Vec<GenDescriptor> vec(INIT_SIZE, 1);
  vec[0] = GenDescriptor(/*order=*/3, /*good=*/true, /*genIdx=*/0);
  cout << "***Testing (3,good), width=1\n";
  testCube(vec, /*width=*/1);
  }

  // Test 2: a single bad larger prime-order generator (31)
  {
  Vec<GenDescriptor> vec(INIT_SIZE, 1);
  vec[0] = GenDescriptor(/*order=*/31, /*good=*/false, /*genIdx=*/0);
  cout << "\n***Testing (31,bad), width=5\n";
  testCube(vec, /*width=*/5);
  }

  // Test 3: two generators with small prime orders (2,3), both bad
  {
  Vec<GenDescriptor> vec(INIT_SIZE, 2);
  vec[0] = GenDescriptor(/*order=*/2, /*good=*/false, /*genIdx=*/0);
  vec[1] = GenDescriptor(/*order=*/3, /*good=*/false, /*genIdx=*/1);
  cout << "\n***Testing [(2,bad),(3,bad)], width=3\n";
  testCube(vec, /*width=*/3);
  }

  // Test 4: two generators with small prime orders (2,3), one good
  {
  Vec<GenDescriptor> vec(INIT_SIZE, 2);
  vec[0] = GenDescriptor(/*order=*/3, /*good=*/true, /*genIdx=*/0);
  vec[1] = GenDescriptor(/*order=*/2, /*good=*/false, /*genIdx=*/1);
  cout << "\n***Testing [(3,good),(2,bad)], width=3\n";
  testCube(vec, /*width=*/3);
  }

  // Test 5: a single good composite-order generator (6)
  {
  Vec<GenDescriptor> vec(INIT_SIZE, 1);
  vec[0] = GenDescriptor(/*order=*/6, /*good=*/true, /*genIdx=*/0);
  cout << "\n***Testing (6,good), width=3\n";
  testCube(vec, /*width=*/3);
  }

  // Test 6: (6,good),(2,bad)
  {
  Vec<GenDescriptor> vec(INIT_SIZE, 2);
  vec[0] = GenDescriptor(/*order=*/6,/*good=*/true, /*genIdx=*/0);
  vec[1] = GenDescriptor(/*order=*/ 2, /*good=*/false,/*genIdx=*/1);
  cout << "\n**Testing [(6,good),(2,bad)], width=5\n";
  testCube(vec, /*width=*/5);
  }

  // Test 7: the "general case", (682,good),(2,bad)
  {
  Vec<GenDescriptor> vec(INIT_SIZE, 2);
  vec[0] = GenDescriptor(/*order=*/682,/*good=*/true, /*genIdx=*/0);
  vec[1] = GenDescriptor(/*order=*/ 2, /*good=*/false,/*genIdx=*/1);
  cout << "\n**Testing [(682,good),(2,bad)], width=11\n";
  testCube(vec, /*width=*/11);
  }
#endif
<commit_msg>dry=0 by default in Test_Permutations<commit_after>/* Copyright (C) 2012-2017 IBM Corp.
 * This program is Licensed under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at
 *   http://www.apache.org/licenses/LICENSE-2.0
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License. See accompanying LICENSE file.
 */

/* Test_Permutations.cpp - Applying plaintext permutation to encrypted vector
 */
#include <NTL/ZZ.h>
NTL_CLIENT

#include "NumbTh.h"
#include "timing.h"
#include "permutations.h"
#include "EncryptedArray.h"

static bool noPrint = false;

void testCtxt(long m, long p, long widthBound=0, long L=0, long r=1);

void usage(char *prog)
{
  cout << "Usage: "<<prog<<" [test=? [optional parameters...]]\n";
  cout << "  optional parameters have the form 'attr1=val1 attr2=val2 ...'\n";
  cout << "  e.g, 'test=1 m=108 p=2 r=1\n";
  cout << "  test is either 0 (plaintext) or 1 (ciphertext)[default=1]\n\n";
  cout << "test=0, permuting plaintext hypercubes (dimension upto 4):\n";
  cout << "  ord1,ord2,ord3,ord4 size of dimensions 1..4 [default ord1=30, ord2,3,4=0]\n";
  cout << "  good1,good2,good3,good4 native rotation flags (0/1) [default=1]\n";
  cout << "  depth bounds the depth of permutation network [default=5]\n";
  cout << "\ntest=1, permuting ciphertext slots:\n";
  cout << "  m is the cyclotomic field [default=4369]\n";
  cout << "  p,r define the plaintext space p^r [default p=2,r=1]\n";
  cout << "  depth bounds the depth of permutation network [default=5]\n";
  cout << "  L is number of levels in chain [default=depth]\n\n";
  cout << "dry=1 for dry run [default=0]\n";
  exit(0);
}

void testCube(Vec<GenDescriptor>& vec, long widthBound)
{
  GeneratorTrees trees;
  long cost = trees.buildOptimalTrees(vec, widthBound);
  if (!noPrint) {
    cout << "@TestCube: trees=" << trees << endl;
    cout << " cost =" << cost << endl;
  }
  Vec<long> dims;
  trees.getCubeDims(dims);
  CubeSignature sig(dims);

  for (long cnt=0; cnt<3; cnt++) {
    Permut pi;
    randomPerm(pi, trees.getSize());

    PermNetwork net;
    net.buildNetwork(pi, trees);

    HyperCube<long> cube1(sig), cube2(sig);
    for (long i=0; i<cube1.getSize(); i++) cube1[i] = i;
    HyperCube<long> cube3 = cube1;
    applyPermToVec(cube2.getData(), cube1.getData(), pi); // direct application
    net.applyToCube(cube3); // applying permutation netwrok
    if (cube2==cube3) cout << "GOOD\n";
    else {
      cout << "BAD\n";
      if (cube1.getSize()<100) {
	cout << "in="<<cube1.getData() << endl;
	cout << "out1="<<cube2.getData()<<", out2="
	     << cube3.getData()<<endl<<endl;
      }
    }
  }
}

void testCtxt(long m, long p, long widthBound, long L, long r)
{
  if (!noPrint)
    cout << "@testCtxt(m="<<m<<",p="<<p<<",depth="<<widthBound<< ",r="<<r<<")";

  FHEcontext context(m,p,r);
  EncryptedArray ea(context); // Use G(X)=X for this ea object

  // Some arbitrary initial plaintext array
  vector<long> in(ea.size());
  for (long i=0; i<ea.size(); i++) in[i] = i % p;

  // Setup generator-descriptors for the PAlgebra generators
  Vec<GenDescriptor> vec(INIT_SIZE, ea.dimension());
  for (long i=0; i<ea.dimension(); i++)
    vec[i] = GenDescriptor(/*order=*/ea.sizeOfDimension(i),
			   /*good=*/ ea.nativeDimension(i), /*genIdx=*/i);

  // Some default for the width-bound, if not provided
  if (widthBound<=0) widthBound = 1+log2((double)ea.size());

  // Get the generator-tree structures and the corresponding hypercube
  GeneratorTrees trees;
  long cost = trees.buildOptimalTrees(vec, widthBound);
  if (!noPrint) {
    context.zMStar.printout();
    cout << ": trees=" << trees << endl;
    cout << " cost =" << cost << endl;
  }
  //  Vec<long> dims;
  //  trees.getCubeDims(dims);
  //  CubeSignature sig(dims);

  // 1/2 prime per level should be more or less enough, here we use 1 per layer
  if (L<=0) L = 1+trees.numLayers();
  buildModChain(context, /*nLevels=*/L, /*nDigits=*/3);
  if (!noPrint) cout << "**Using "<<L<<" primes (of which "
		     << context.ctxtPrimes.card() << " are Ctxt-primes)\n";

  // Generate a sk/pk pair
  FHESecKey secretKey(context);
  const FHEPubKey& publicKey = secretKey;
  secretKey.GenSecKey(64); // A Hamming-weight-64 secret key
  Ctxt ctxt(publicKey);

  for (long cnt=0; cnt<3; cnt++) {
    resetAllTimers();
    // Choose a random permutation
    Permut pi;
    randomPerm(pi, trees.getSize());

    // Build a permutation network for pi
    PermNetwork net;
    net.buildNetwork(pi, trees);

    // make sure we have the key-switching matrices needed for this network
    addMatrices4Network(secretKey, net);

    // Apply the permutation pi to the plaintext
    vector<long> out1(ea.size());
    vector<long> out2(ea.size());
    applyPermToVec(out1, in, pi); // direct application

    // Encrypt plaintext array, then apply permutation network to ciphertext
    ea.encrypt(ctxt, publicKey, in);
    if (!noPrint)
      cout << "  ** applying permutation network to ciphertext... " << flush;
    double t = GetTime();
    net.applyToCtxt(ctxt, ea); // applying permutation netwrok
    t = GetTime() -t;
    if (!noPrint)
      cout << "done in " << t << " seconds" << endl;
    ea.decrypt(ctxt, secretKey, out2);

    if (out1==out2) cout << "GOOD\n";
    else {
      cout << "************ BAD\n";
    }
    // printAllTimers();
  }
}

/* m = 31, p = 2, phi(m) = 30
  ord(p)=5
  generator 6 has order (== Z_m^*) of 6
  T = [1 6 5 30 25 26 ]

  m = 61, p = 3, phi(m) = 60
  ord(p)=10
  generator 13 has order (== Z_m^*) of 3
  generator 2 has order (!= Z_m^*) of 2
  T = [1 2 13 26 47 33 ]

  m = 683, p = 2, phi(m) = 682
  ord(p)=22
  generator 3 has order (== Z_m^*) of 31

  m = 47127, p = 2, phi(m) = 30008
  ord(p)=22
  generator 5 has order (== Z_m^*) of 682
  generator 13661 has order (== Z_m^*) of 2
*/

int main(int argc, char *argv[])
{
  argmap_t argmap;
  argmap["test"] = "1";
  argmap["m"] = "4369";
  argmap["p"] = "2";
  argmap["r"] = "1";
  argmap["depth"] = "5";
  argmap["L"] = "0";
  argmap["ord1"] = "30";
  argmap["ord2"] = "0";
  argmap["ord3"] = "0";
  argmap["ord4"] = "0";
  argmap["good1"] = "1";
  argmap["good2"] = "1";
  argmap["good3"] = "1";
  argmap["good4"] = "1";
  argmap["dry"] = "0";
  argmap["noPrint"] = "0";

  // get parameters from the command line

  if (!parseArgs(argc, argv, argmap)) usage(argv[0]);

  long test = atoi(argmap["test"]);
  long p = atoi(argmap["p"]);
  long r = atoi(argmap["r"]);
  long m = atoi(argmap["m"]);
  long depth = atoi(argmap["depth"]);
  long L = atoi(argmap["L"]);

  long ord1 = atoi(argmap["ord1"]);
  long ord2 = atoi(argmap["ord2"]);
  long ord3 = atoi(argmap["ord3"]);
  long ord4 = atoi(argmap["ord4"]);
  long good1 = atoi(argmap["good1"]);
  long good2 = atoi(argmap["good2"]);
  long good3 = atoi(argmap["good3"]);
  long good4 = atoi(argmap["good4"]);

  bool dry = atoi(argmap["dry"]);
  noPrint = atoi(argmap["noPrint"]);

  setDryRun(dry);
  if (test==0 || dry!=0) {
    Vec<GenDescriptor> vec;
    long nGens;
    if (ord2<=1) nGens=1;
    else if (ord3<=1) nGens=2;
    else if (ord4<=1) nGens=3;
    else nGens=4;
    vec.SetLength(nGens);

    switch (nGens) {
    case 4:  vec[3] = GenDescriptor(ord4, good4, /*genIdx=*/3);
    case 3:  vec[2] = GenDescriptor(ord3, good3, /*genIdx=*/2);
    case 2:  vec[1] = GenDescriptor(ord2, good2, /*genIdx=*/1);
    default: vec[0] = GenDescriptor(ord1, good1, /*genIdx=*/0);
    }
    cout << "***Testing ";
    if (isDryRun()) cout << "(dry run) ";
    for (long i=0; i<vec.length(); i++)
      cout << "("<<vec[i].order<<","<<vec[i].good<<")";
    cout << ", depth="<<depth<<"\n";
    testCube(vec, depth);
  }
  else {
    setTimersOn();
    cout << "***Testing m="<<m<<", p="<<p<<", depth="<<depth<< endl;
    testCtxt(m,p,depth,L,r);
  }
}

#if 0
  cout << "***Testing m=31, p=2, width=3\n"; // (6 good)
  testCtxt(/*m=*/31, /*p=*/2, /*width=*/3);

  cout << "\n***Testing m=61, p=3, width=3\n"; // (3 good), (2, bad)
  testCtxt(/*m=*/61, /*p=*/3, /*width=*/3);

  cout << "\n***Testing m=683, p=2, width=5\n"; // (31, good)
  testCtxt(/*m=*/683, /*p=*/2, /*width=*/5);

  //  cout << "\n***Testing m=47127, p=2, width=11\n"; // (682,good),(2,good)
  //  testCtxt(/*m=*/47127, /*p=*/2, /*width=*/11);

  // Test 1: a single good small prime-order generator (3)
  {
  Vec<GenDescriptor> vec(INIT_SIZE, 1);
  vec[0] = GenDescriptor(/*order=*/3, /*good=*/true, /*genIdx=*/0);
  cout << "***Testing (3,good), width=1\n";
  testCube(vec, /*width=*/1);
  }

  // Test 2: a single bad larger prime-order generator (31)
  {
  Vec<GenDescriptor> vec(INIT_SIZE, 1);
  vec[0] = GenDescriptor(/*order=*/31, /*good=*/false, /*genIdx=*/0);
  cout << "\n***Testing (31,bad), width=5\n";
  testCube(vec, /*width=*/5);
  }

  // Test 3: two generators with small prime orders (2,3), both bad
  {
  Vec<GenDescriptor> vec(INIT_SIZE, 2);
  vec[0] = GenDescriptor(/*order=*/2, /*good=*/false, /*genIdx=*/0);
  vec[1] = GenDescriptor(/*order=*/3, /*good=*/false, /*genIdx=*/1);
  cout << "\n***Testing [(2,bad),(3,bad)], width=3\n";
  testCube(vec, /*width=*/3);
  }

  // Test 4: two generators with small prime orders (2,3), one good
  {
  Vec<GenDescriptor> vec(INIT_SIZE, 2);
  vec[0] = GenDescriptor(/*order=*/3, /*good=*/true, /*genIdx=*/0);
  vec[1] = GenDescriptor(/*order=*/2, /*good=*/false, /*genIdx=*/1);
  cout << "\n***Testing [(3,good),(2,bad)], width=3\n";
  testCube(vec, /*width=*/3);
  }

  // Test 5: a single good composite-order generator (6)
  {
  Vec<GenDescriptor> vec(INIT_SIZE, 1);
  vec[0] = GenDescriptor(/*order=*/6, /*good=*/true, /*genIdx=*/0);
  cout << "\n***Testing (6,good), width=3\n";
  testCube(vec, /*width=*/3);
  }

  // Test 6: (6,good),(2,bad)
  {
  Vec<GenDescriptor> vec(INIT_SIZE, 2);
  vec[0] = GenDescriptor(/*order=*/6,/*good=*/true, /*genIdx=*/0);
  vec[1] = GenDescriptor(/*order=*/ 2, /*good=*/false,/*genIdx=*/1);
  cout << "\n**Testing [(6,good),(2,bad)], width=5\n";
  testCube(vec, /*width=*/5);
  }

  // Test 7: the "general case", (682,good),(2,bad)
  {
  Vec<GenDescriptor> vec(INIT_SIZE, 2);
  vec[0] = GenDescriptor(/*order=*/682,/*good=*/true, /*genIdx=*/0);
  vec[1] = GenDescriptor(/*order=*/ 2, /*good=*/false,/*genIdx=*/1);
  cout << "\n**Testing [(682,good),(2,bad)], width=11\n";
  testCube(vec, /*width=*/11);
  }
#endif
<|endoftext|>


<commit_before>/* bzflag
 * Copyright (c) 1993 - 2005 Tim Riker
 *
 * This package is free software;  you can redistribute it and/or
 * modify it under the terms of the license found in the file
 * named COPYING that should have accompanied this file.
 *
 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

#include "common.h"

// implementation header
#include "MeshDrawMgr.h"

// common headers
#include "bzfgl.h"
#include "OpenGLGState.h"
#include "MeshDrawInfo.h"
#include "bzfio.h" // for DEBUGx()

GLuint MeshDrawMgr::unloadList = INVALID_GL_LIST_ID;

static bool haveVBOs = false;
static void (*bzGenBuffers)(GLsizei, GLuint*) = NULL;
static void (*bzBufferData)(GLenum, GLsizeiptr, const GLvoid*, GLenum) = NULL;
static void (*bzBindBuffer)(GLenum, GLuint) = NULL;
static void (*bzDeleteBuffers)(GLsizei, const GLuint*) = NULL;

void MeshDrawMgr::init()
{
  haveVBOs = false;
  bzGenBuffers = NULL;
  bzBufferData = NULL;
  bzBindBuffer = NULL;
  bzDeleteBuffers = NULL;
}

void MeshDrawMgr::kill()
{
  haveVBOs = false;
  bzGenBuffers = NULL;
  bzBufferData = NULL;
  bzBindBuffer = NULL;
  bzDeleteBuffers = NULL;
}

MeshDrawMgr::MeshDrawMgr(const MeshDrawInfo* _drawInfo)
{
  drawInfo = _drawInfo;
  if ((drawInfo == NULL) || !drawInfo->isValid()) {
    printf("MeshDrawMgr: invalid drawInfo\n");
    fflush(stdout);
    return;
  } else {
    DEBUG4("MeshDrawMgr: initializing\n");
    fflush(stdout);
  }

  drawLods = drawInfo->getDrawLods();
  vertices = (const GLfloat*)drawInfo->getVertices();
  normals = (const GLfloat*)drawInfo->getNormals();
  texcoords = (const GLfloat*)drawInfo->getTexcoords();

  lodCount = drawInfo->getLodCount();
  lodLists = new LodList[lodCount];

  for (int i = 0; i < lodCount; i++) {
    LodList& lodList = lodLists[i];
    lodList.count = drawLods[i].count;
    lodList.setLists = new GLuint[lodList.count];
    for (int j = 0; j < lodList.count; j++) {
      lodList.setLists[j] = INVALID_GL_LIST_ID;
    }
  }

  makeLists();
  OpenGLGState::registerContextInitializer(freeContext, initContext, this);
  return;
}

MeshDrawMgr::~MeshDrawMgr()
{
  DEBUG4("MeshDrawMgr: killing\n");

  OpenGLGState::unregisterContextInitializer(freeContext, initContext, this);
  freeLists();

  for (int i = 0; i < lodCount; i++) {
    delete[] lodLists[i].setLists;
  }
  delete[] lodLists;

  return;
}

inline void MeshDrawMgr::rawExecuteCommands(int lod, int set)
{
  const DrawLod& drawLod = drawLods[lod];
  const DrawSet& drawSet = drawLod.sets[set];
  const int cmdCount = drawSet.count;
  for (int i = 0; i < cmdCount; i++) {
    const DrawCmd& cmd = drawSet.cmds[i];
    glDrawElements(cmd.drawMode, cmd.count, cmd.indexType, cmd.indices);
  }
  return;
}

void MeshDrawMgr::executeSet(int lod, int set, bool _normals, bool _texcoords)
{
  // FIXME
  const AnimationInfo* animInfo = drawInfo->getAnimationInfo();
  if (animInfo != NULL) {
    glPushMatrix();
    glRotatef(animInfo->angle, 0.0f, 0.0f, 1.0f);
  }

  const GLuint list = lodLists[lod].setLists[set];
  if (list != INVALID_GL_LIST_ID) {
    glCallList(list);
  } else {
    glVertexPointer(3, GL_FLOAT, 0, vertices);
    glEnableClientState(GL_VERTEX_ARRAY);
    if (_normals) {
      glNormalPointer(GL_FLOAT, 0, normals);
      glEnableClientState(GL_NORMAL_ARRAY);
    }
    if (_texcoords) {
      glTexCoordPointer(2, GL_FLOAT, 0, texcoords);
      glEnableClientState(GL_TEXTURE_COORD_ARRAY);
    }
    rawExecuteCommands(lod, set);
    disableArrays();
  }

  if (animInfo != NULL) {
    glPopMatrix();
  }

  return;
}

inline void MeshDrawMgr::rawDisableArrays()
{
  glDisableClientState(GL_VERTEX_ARRAY);
  glDisableClientState(GL_NORMAL_ARRAY);
  glDisableClientState(GL_TEXTURE_COORD_ARRAY);
  return;
}

void MeshDrawMgr::disableArrays()
{
  if (unloadList == INVALID_GL_LIST_ID) {
    rawDisableArrays();
  } else {
    glCallList(unloadList);
  }
  return;
}

void MeshDrawMgr::makeLists()
{
  int errCount = 0;
  // reset the error state
  while (glGetError() != GL_NO_ERROR) {
    errCount++; // avoid a possible spin-lock?
    if (errCount > 666) {
      DEBUG1("MeshDrawMgr::makeLists() glError\n");
      return; // don't make the lists, something is borked
    }
  };

  if (unloadList == INVALID_GL_LIST_ID) {
    unloadList = glGenLists(1);
    glNewList(unloadList, GL_COMPILE);
    {
      disableArrays();
    }
    glEndList();
    if (glGetError() != GL_NO_ERROR) {
      DEBUG1("MeshDrawMgr::makeLists() glError\n");
      unloadList = INVALID_GL_LIST_ID;
    }
  }

  glVertexPointer(3, GL_FLOAT, 0, vertices);
  glEnableClientState(GL_VERTEX_ARRAY);
  glNormalPointer(GL_FLOAT, 0, normals);
  glEnableClientState(GL_NORMAL_ARRAY);
  glTexCoordPointer(2, GL_FLOAT, 0, texcoords);
  glEnableClientState(GL_TEXTURE_COORD_ARRAY);

  for (int lod = 0; lod < lodCount; lod++) {
    const DrawLod& drawLod = drawLods[lod];
    for (int set = 0; set < drawLod.count; set++) {
      const DrawSet& drawSet = drawLod.sets[set];
      if (drawSet.wantList) {
        lodLists[lod].setLists[set] = glGenLists(1);

        glNewList(lodLists[lod].setLists[set], GL_COMPILE);
        {
          rawExecuteCommands(lod, set);
        }
        glEndList();

        if (glGetError() != GL_NO_ERROR) {
          DEBUG1("MeshDrawMgr::makeLists() %i/%i glError\n", lod, set);
          lodLists[lod].setLists[set] = INVALID_GL_LIST_ID;
        } else {
          DEBUG3("MeshDrawMgr::makeLists() %i/%i created\n", lod, set);
        }
      }
    }
  }

  disableArrays();

  return;
}

void MeshDrawMgr::freeLists()
{
  if (unloadList != INVALID_GL_LIST_ID) {
    glDeleteLists(unloadList, 1);
    unloadList = INVALID_GL_LIST_ID;
  }

  for (int lod = 0; lod < lodCount; lod++) {
    for (int set = 0; set < lodLists[lod].count; set++) {
      if (lodLists[lod].setLists[set] != INVALID_GL_LIST_ID) {
        glDeleteLists(lodLists[lod].setLists[set], 1);
        lodLists[lod].setLists[set] = INVALID_GL_LIST_ID;
      }
    }
  }

  return;
}

void MeshDrawMgr::initContext(void* data)
{
  ((MeshDrawMgr*)data)->makeLists();
  return;
}

void MeshDrawMgr::freeContext(void* data)
{
  ((MeshDrawMgr*)data)->freeLists();
  return;
}

// Local Variables: ***
// mode:C++ ***
// tab-width: 8 ***
// c-basic-offset: 2 ***
// indent-tabs-mode: t ***
// End: ***
// ex: shiftwidth=2 tabstop=8

<commit_msg>oops, thought those were cleaned out<commit_after>/* bzflag
 * Copyright (c) 1993 - 2005 Tim Riker
 *
 * This package is free software;  you can redistribute it and/or
 * modify it under the terms of the license found in the file
 * named COPYING that should have accompanied this file.
 *
 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

#include "common.h"

// implementation header
#include "MeshDrawMgr.h"

// common headers
#include "bzfgl.h"
#include "OpenGLGState.h"
#include "MeshDrawInfo.h"
#include "bzfio.h" // for DEBUGx()

GLuint MeshDrawMgr::unloadList = INVALID_GL_LIST_ID;

void MeshDrawMgr::init()
{
}

void MeshDrawMgr::kill()
{
}

MeshDrawMgr::MeshDrawMgr(const MeshDrawInfo* _drawInfo)
{
  drawInfo = _drawInfo;
  if ((drawInfo == NULL) || !drawInfo->isValid()) {
    printf("MeshDrawMgr: invalid drawInfo\n");
    fflush(stdout);
    return;
  } else {
    DEBUG4("MeshDrawMgr: initializing\n");
    fflush(stdout);
  }

  drawLods = drawInfo->getDrawLods();
  vertices = (const GLfloat*)drawInfo->getVertices();
  normals = (const GLfloat*)drawInfo->getNormals();
  texcoords = (const GLfloat*)drawInfo->getTexcoords();

  lodCount = drawInfo->getLodCount();
  lodLists = new LodList[lodCount];

  for (int i = 0; i < lodCount; i++) {
    LodList& lodList = lodLists[i];
    lodList.count = drawLods[i].count;
    lodList.setLists = new GLuint[lodList.count];
    for (int j = 0; j < lodList.count; j++) {
      lodList.setLists[j] = INVALID_GL_LIST_ID;
    }
  }

  makeLists();
  OpenGLGState::registerContextInitializer(freeContext, initContext, this);
  return;
}

MeshDrawMgr::~MeshDrawMgr()
{
  DEBUG4("MeshDrawMgr: killing\n");

  OpenGLGState::unregisterContextInitializer(freeContext, initContext, this);
  freeLists();

  for (int i = 0; i < lodCount; i++) {
    delete[] lodLists[i].setLists;
  }
  delete[] lodLists;

  return;
}

inline void MeshDrawMgr::rawExecuteCommands(int lod, int set)
{
  const DrawLod& drawLod = drawLods[lod];
  const DrawSet& drawSet = drawLod.sets[set];
  const int cmdCount = drawSet.count;
  for (int i = 0; i < cmdCount; i++) {
    const DrawCmd& cmd = drawSet.cmds[i];
    glDrawElements(cmd.drawMode, cmd.count, cmd.indexType, cmd.indices);
  }
  return;
}

void MeshDrawMgr::executeSet(int lod, int set, bool _normals, bool _texcoords)
{
  // FIXME
  const AnimationInfo* animInfo = drawInfo->getAnimationInfo();
  if (animInfo != NULL) {
    glPushMatrix();
    glRotatef(animInfo->angle, 0.0f, 0.0f, 1.0f);
  }

  const GLuint list = lodLists[lod].setLists[set];
  if (list != INVALID_GL_LIST_ID) {
    glCallList(list);
  } else {
    glVertexPointer(3, GL_FLOAT, 0, vertices);
    glEnableClientState(GL_VERTEX_ARRAY);
    if (_normals) {
      glNormalPointer(GL_FLOAT, 0, normals);
      glEnableClientState(GL_NORMAL_ARRAY);
    }
    if (_texcoords) {
      glTexCoordPointer(2, GL_FLOAT, 0, texcoords);
      glEnableClientState(GL_TEXTURE_COORD_ARRAY);
    }
    rawExecuteCommands(lod, set);
    disableArrays();
  }

  if (animInfo != NULL) {
    glPopMatrix();
  }

  return;
}

inline void MeshDrawMgr::rawDisableArrays()
{
  glDisableClientState(GL_VERTEX_ARRAY);
  glDisableClientState(GL_NORMAL_ARRAY);
  glDisableClientState(GL_TEXTURE_COORD_ARRAY);
  return;
}

void MeshDrawMgr::disableArrays()
{
  if (unloadList == INVALID_GL_LIST_ID) {
    rawDisableArrays();
  } else {
    glCallList(unloadList);
  }
  return;
}

void MeshDrawMgr::makeLists()
{
  int errCount = 0;
  // reset the error state
  while (glGetError() != GL_NO_ERROR) {
    errCount++; // avoid a possible spin-lock?
    if (errCount > 666) {
      DEBUG1("MeshDrawMgr::makeLists() glError\n");
      return; // don't make the lists, something is borked
    }
  };

  if (unloadList == INVALID_GL_LIST_ID) {
    unloadList = glGenLists(1);
    glNewList(unloadList, GL_COMPILE);
    {
      disableArrays();
    }
    glEndList();
    if (glGetError() != GL_NO_ERROR) {
      DEBUG1("MeshDrawMgr::makeLists() glError\n");
      unloadList = INVALID_GL_LIST_ID;
    }
  }

  glVertexPointer(3, GL_FLOAT, 0, vertices);
  glEnableClientState(GL_VERTEX_ARRAY);
  glNormalPointer(GL_FLOAT, 0, normals);
  glEnableClientState(GL_NORMAL_ARRAY);
  glTexCoordPointer(2, GL_FLOAT, 0, texcoords);
  glEnableClientState(GL_TEXTURE_COORD_ARRAY);

  for (int lod = 0; lod < lodCount; lod++) {
    const DrawLod& drawLod = drawLods[lod];
    for (int set = 0; set < drawLod.count; set++) {
      const DrawSet& drawSet = drawLod.sets[set];
      if (drawSet.wantList) {
        lodLists[lod].setLists[set] = glGenLists(1);

        glNewList(lodLists[lod].setLists[set], GL_COMPILE);
        {
          rawExecuteCommands(lod, set);
        }
        glEndList();

        if (glGetError() != GL_NO_ERROR) {
          DEBUG1("MeshDrawMgr::makeLists() %i/%i glError\n", lod, set);
          lodLists[lod].setLists[set] = INVALID_GL_LIST_ID;
        } else {
          DEBUG3("MeshDrawMgr::makeLists() %i/%i created\n", lod, set);
        }
      }
    }
  }

  disableArrays();

  return;
}

void MeshDrawMgr::freeLists()
{
  if (unloadList != INVALID_GL_LIST_ID) {
    glDeleteLists(unloadList, 1);
    unloadList = INVALID_GL_LIST_ID;
  }

  for (int lod = 0; lod < lodCount; lod++) {
    for (int set = 0; set < lodLists[lod].count; set++) {
      if (lodLists[lod].setLists[set] != INVALID_GL_LIST_ID) {
        glDeleteLists(lodLists[lod].setLists[set], 1);
        lodLists[lod].setLists[set] = INVALID_GL_LIST_ID;
      }
    }
  }

  return;
}

void MeshDrawMgr::initContext(void* data)
{
  ((MeshDrawMgr*)data)->makeLists();
  return;
}

void MeshDrawMgr::freeContext(void* data)
{
  ((MeshDrawMgr*)data)->freeLists();
  return;
}

// Local Variables: ***
// mode:C++ ***
// tab-width: 8 ***
// c-basic-offset: 2 ***
// indent-tabs-mode: t ***
// End: ***
// ex: shiftwidth=2 tabstop=8

<|endoftext|>


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

#include "ConsoleUtils.h"

#include <qpid/console/Value.h>

#include <boost/lexical_cast.hpp>

std::string ConsoleUtils::getName(const qpid::console::Object &object,
                                  const bool allowNodeName)
{
    const qpid::console::Object::AttributeMap &attributes = object.getAttributes();
    qpid::console::Object::AttributeMap::const_iterator name = attributes.find("name");
    if ((name == attributes.end()) && (allowNodeName)) {
        name == attributes.find("nodeName");
    }
    return (name == attributes.end()) ? std::string() : name->second->asString();
}

ConsoleUtils::ObjectSchemaType ConsoleUtils::getType(const qpid::console::Object &object)
{
    return getType(object.getClassKey());
}

ConsoleUtils::ObjectSchemaType ConsoleUtils::getType(const qpid::console::ClassKey &classKey)
{
    if (classKey.getPackageName() == "org.apache.qpid.broker") {
        const std::string &className = classKey.getClassName();
        if (className == "broker") return Broker;
        if (className == "queue")  return Queue;
        if (className == "system") return System;
    }
    return Other;
}

std::string ConsoleUtils::toString(const qpid::console::ClassKey &classKey)
{
    return classKey.getPackageName() + ':' + classKey.getClassName();
}

std::string ConsoleUtils::toString(const qpid::console::Object &object,
                                   bool includePackageName)
{
    const qpid::console::ClassKey &classKey = object.getClassKey();
    return (includePackageName ? toString(classKey) : classKey.getClassName()) +
           " '" + getName(object) + "' (" + toString(object.getObjectId()) + ')';
}

std::string ConsoleUtils::toString(const qpid::console::ObjectId &id)
{
    std::ostringstream stream;
    stream << id;
    return stream.str();
}

std::string ConsoleUtils::toString(const qpid::console::SchemaProperty &property)
{
    return property.name + ':' + qmfTypeCodeToString(property.typeCode) + ':' +
           property.unit + ':' + property.desc;
}

std::string ConsoleUtils::toString(const qpid::console::SchemaStatistic &statistic)
{
    return statistic.name + ':' + qmfTypeCodeToString(statistic.typeCode) + ':' +
           statistic.unit + ':' + statistic.desc;
}

std::string ConsoleUtils::qmfTypeCodeToString(const uint8_t typeCode)
{
    // See Qpid's cpp/include/qmf/engine/Typecode.h
    switch (typeCode) {
        case 1: return "UINT8";
        case 2: return "UINT16";
        case 3: return "UINT32";
        case 4: return "UINT64";
      //case 5: // There is no type 5.
        case 6: return "SSTR";
        case 7: return "LSTR";
        case 8: return "ABSTIME";
        case 9: return "DELTATIME";
        case 10: return "REF";
        case 11: return "BOOL";
        case 12: return "FLOAT";
        case 13: return "DOUBLE";
        case 14: return "UUID";
        case 15: return "MAP";
        case 16: return "INT8";
        case 17: return "INT16";
        case 18: return "INT32";
        case 19: return "INT64";
        case 20: return "OBJECT";
        case 21: return "LIST";
        case 22: return "ARRAY";
        default:
            return "unknown (" + boost::lexical_cast<std::string>(typeCode) + ')';
    }
}
<commit_msg>Small typo fix.<commit_after>/*
 * Copyright 2013-2014 Paul Colby
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "ConsoleUtils.h"

#include <qpid/console/Value.h>

#include <boost/lexical_cast.hpp>

std::string ConsoleUtils::getName(const qpid::console::Object &object,
                                  const bool allowNodeName)
{
    const qpid::console::Object::AttributeMap &attributes = object.getAttributes();
    qpid::console::Object::AttributeMap::const_iterator name = attributes.find("name");
    if ((name == attributes.end()) && (allowNodeName)) {
        name = attributes.find("nodeName");
    }
    return (name == attributes.end()) ? std::string() : name->second->asString();
}

ConsoleUtils::ObjectSchemaType ConsoleUtils::getType(const qpid::console::Object &object)
{
    return getType(object.getClassKey());
}

ConsoleUtils::ObjectSchemaType ConsoleUtils::getType(const qpid::console::ClassKey &classKey)
{
    if (classKey.getPackageName() == "org.apache.qpid.broker") {
        const std::string &className = classKey.getClassName();
        if (className == "broker") return Broker;
        if (className == "queue")  return Queue;
        if (className == "system") return System;
    }
    return Other;
}

std::string ConsoleUtils::toString(const qpid::console::ClassKey &classKey)
{
    return classKey.getPackageName() + ':' + classKey.getClassName();
}

std::string ConsoleUtils::toString(const qpid::console::Object &object,
                                   bool includePackageName)
{
    const qpid::console::ClassKey &classKey = object.getClassKey();
    return (includePackageName ? toString(classKey) : classKey.getClassName()) +
           " '" + getName(object) + "' (" + toString(object.getObjectId()) + ')';
}

std::string ConsoleUtils::toString(const qpid::console::ObjectId &id)
{
    std::ostringstream stream;
    stream << id;
    return stream.str();
}

std::string ConsoleUtils::toString(const qpid::console::SchemaProperty &property)
{
    return property.name + ':' + qmfTypeCodeToString(property.typeCode) + ':' +
           property.unit + ':' + property.desc;
}

std::string ConsoleUtils::toString(const qpid::console::SchemaStatistic &statistic)
{
    return statistic.name + ':' + qmfTypeCodeToString(statistic.typeCode) + ':' +
           statistic.unit + ':' + statistic.desc;
}

std::string ConsoleUtils::qmfTypeCodeToString(const uint8_t typeCode)
{
    // See Qpid's cpp/include/qmf/engine/Typecode.h
    switch (typeCode) {
        case 1: return "UINT8";
        case 2: return "UINT16";
        case 3: return "UINT32";
        case 4: return "UINT64";
      //case 5: // There is no type 5.
        case 6: return "SSTR";
        case 7: return "LSTR";
        case 8: return "ABSTIME";
        case 9: return "DELTATIME";
        case 10: return "REF";
        case 11: return "BOOL";
        case 12: return "FLOAT";
        case 13: return "DOUBLE";
        case 14: return "UUID";
        case 15: return "MAP";
        case 16: return "INT8";
        case 17: return "INT16";
        case 18: return "INT32";
        case 19: return "INT64";
        case 20: return "OBJECT";
        case 21: return "LIST";
        case 22: return "ARRAY";
        default:
            return "unknown (" + boost::lexical_cast<std::string>(typeCode) + ')';
    }
}
<|endoftext|>


<commit_before>#include "sendcoinsentry.h"
#include "ui_sendcoinsentry.h"

#include "guiutil.h"
#include "bitcoinunits.h"
#include "addressbookpage.h"
#include "walletmodel.h"
#include "optionsmodel.h"
#include "addresstablemodel.h"

#include <QApplication>
#include <QClipboard>

SendCoinsEntry::SendCoinsEntry(QWidget *parent) :
    QStackedWidget(parent),
    ui(new Ui::SendCoinsEntry),
    model(0)
{
    ui->setupUi(this);

    setCurrentWidget(ui->SendCoinsInsecure);

#ifdef Q_OS_MAC
    ui->payToLayout->setSpacing(4);
#endif
#if QT_VERSION >= 0x040700
    /* Do not move this to the XML file, Qt before 4.7 will choke on it */
    ui->addAsLabel->setPlaceholderText(tr("Enter a label for this address to add it to your address book"));
    ui->payTo->setPlaceholderText(tr("Enter a Bitcoin address (e.g. 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L)"));
#endif
    setFocusPolicy(Qt::TabFocus);
    setFocusProxy(ui->payTo);

    GUIUtil::setupAddressWidget(ui->payTo, this);
}

SendCoinsEntry::~SendCoinsEntry()
{
    delete ui;
}

void SendCoinsEntry::on_pasteButton_clicked()
{
    // Paste text from clipboard into recipient field
    ui->payTo->setText(QApplication::clipboard()->text());
}

void SendCoinsEntry::on_addressBookButton_clicked()
{
    if(!model)
        return;
    AddressBookPage dlg(AddressBookPage::ForSending, AddressBookPage::SendingTab, this);
    dlg.setModel(model->getAddressTableModel());
    if(dlg.exec())
    {
        ui->payTo->setText(dlg.getReturnValue());
        ui->payAmount->setFocus();
    }
}

void SendCoinsEntry::on_payTo_textChanged(const QString &address)
{
    if(!model)
        return;
    // Fill in label from address book, if address has an associated label
    QString associatedLabel = model->getAddressTableModel()->labelForAddress(address);
    if(!associatedLabel.isEmpty())
        ui->addAsLabel->setText(associatedLabel);
}

void SendCoinsEntry::setModel(WalletModel *model)
{
    this->model = model;

    if(model && model->getOptionsModel())
        connect(model->getOptionsModel(), SIGNAL(displayUnitChanged(int)), this, SLOT(updateDisplayUnit()));

    clear();
}

void SendCoinsEntry::setRemoveEnabled(bool enabled)
{
    ui->deleteButton->setEnabled(enabled);
}

void SendCoinsEntry::clear()
{
    ui->payTo->clear();
    ui->addAsLabel->clear();
    ui->payAmount->clear();
    ui->payTo->setFocus();
    // update the display unit, to not use the default ("BTC")
    updateDisplayUnit();
}

void SendCoinsEntry::on_deleteButton_clicked()
{
    emit removeEntry(this);
}

bool SendCoinsEntry::validate()
{
    // Check input validity
    bool retval = true;

    if (!recipient.authenticatedMerchant.isEmpty())
        return retval;

    if (!ui->payTo->hasAcceptableInput() ||
        (model && !model->validateAddress(ui->payTo->text())))
    {
        ui->payTo->setValid(false);
        retval = false;
    }

    if(!ui->payAmount->validate())
    {
        retval = false;
    }

    // Reject dust outputs:
    if (retval && GUIUtil::isDust(ui->payTo->text(), ui->payAmount->value())) {
        ui->payAmount->setValid(false);
        retval = false;
    }

    return retval;
}

SendCoinsRecipient SendCoinsEntry::getValue()
{
    if (!recipient.authenticatedMerchant.isEmpty())
        return recipient;

    // User-entered or non-authenticated:
    recipient.address = ui->payTo->text();
    recipient.label = ui->addAsLabel->text();
    recipient.amount = ui->payAmount->value();

    return recipient;
}

QWidget *SendCoinsEntry::setupTabChain(QWidget *prev)
{
    QWidget::setTabOrder(prev, ui->payTo);
    QWidget::setTabOrder(ui->payTo, ui->addressBookButton);
    QWidget::setTabOrder(ui->addressBookButton, ui->pasteButton);
    QWidget::setTabOrder(ui->pasteButton, ui->deleteButton);
    QWidget::setTabOrder(ui->deleteButton, ui->addAsLabel);
    return ui->payAmount->setupTabChain(ui->addAsLabel);
}

void SendCoinsEntry::setValue(const SendCoinsRecipient &value)
{
    recipient = value;

    ui->payTo->setText(value.address);
    ui->addAsLabel->setText(value.label);
    ui->payAmount->setValue(value.amount);

    if (!recipient.authenticatedMerchant.isEmpty())
    {
        const payments::PaymentDetails& details = value.paymentRequest.getDetails();

        ui->payTo_s->setText(value.authenticatedMerchant);
        ui->memoTextLabel_s->setText(QString::fromStdString(details.memo()));
        ui->payAmount_s->setValue(value.amount);
        setCurrentWidget(ui->SendCoinsSecure);
    }
}

void SendCoinsEntry::setAddress(const QString &address)
{
    ui->payTo->setText(address);
    ui->payAmount->setFocus();
}

bool SendCoinsEntry::isClear()
{
    return ui->payTo->text().isEmpty() && ui->payTo_s->text().isEmpty();
}

void SendCoinsEntry::setFocus()
{
    ui->payTo->setFocus();
}

void SendCoinsEntry::updateDisplayUnit()
{
    if(model && model->getOptionsModel())
    {
        // Update payAmount with the current unit
        ui->payAmount->setDisplayUnit(model->getOptionsModel()->getDisplayUnit());
        ui->payAmount_s->setDisplayUnit(model->getOptionsModel()->getDisplayUnit());
    }
}
<commit_msg>sendcoinsentry: small clear() and setValue() changes<commit_after>#include "sendcoinsentry.h"
#include "ui_sendcoinsentry.h"

#include "guiutil.h"
#include "bitcoinunits.h"
#include "addressbookpage.h"
#include "walletmodel.h"
#include "optionsmodel.h"
#include "addresstablemodel.h"

#include <QApplication>
#include <QClipboard>

SendCoinsEntry::SendCoinsEntry(QWidget *parent) :
    QStackedWidget(parent),
    ui(new Ui::SendCoinsEntry),
    model(0)
{
    ui->setupUi(this);

    setCurrentWidget(ui->SendCoinsInsecure);

#ifdef Q_OS_MAC
    ui->payToLayout->setSpacing(4);
#endif
#if QT_VERSION >= 0x040700
    /* Do not move this to the XML file, Qt before 4.7 will choke on it */
    ui->addAsLabel->setPlaceholderText(tr("Enter a label for this address to add it to your address book"));
    ui->payTo->setPlaceholderText(tr("Enter a Bitcoin address (e.g. 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L)"));
#endif
    setFocusPolicy(Qt::TabFocus);
    setFocusProxy(ui->payTo);

    GUIUtil::setupAddressWidget(ui->payTo, this);
}

SendCoinsEntry::~SendCoinsEntry()
{
    delete ui;
}

void SendCoinsEntry::on_pasteButton_clicked()
{
    // Paste text from clipboard into recipient field
    ui->payTo->setText(QApplication::clipboard()->text());
}

void SendCoinsEntry::on_addressBookButton_clicked()
{
    if(!model)
        return;
    AddressBookPage dlg(AddressBookPage::ForSending, AddressBookPage::SendingTab, this);
    dlg.setModel(model->getAddressTableModel());
    if(dlg.exec())
    {
        ui->payTo->setText(dlg.getReturnValue());
        ui->payAmount->setFocus();
    }
}

void SendCoinsEntry::on_payTo_textChanged(const QString &address)
{
    if(!model)
        return;
    // Fill in label from address book, if address has an associated label
    QString associatedLabel = model->getAddressTableModel()->labelForAddress(address);
    if(!associatedLabel.isEmpty())
        ui->addAsLabel->setText(associatedLabel);
}

void SendCoinsEntry::setModel(WalletModel *model)
{
    this->model = model;

    if(model && model->getOptionsModel())
        connect(model->getOptionsModel(), SIGNAL(displayUnitChanged(int)), this, SLOT(updateDisplayUnit()));

    clear();
}

void SendCoinsEntry::setRemoveEnabled(bool enabled)
{
    ui->deleteButton->setEnabled(enabled);
}

void SendCoinsEntry::clear()
{
    // clear UI elements for insecure payments
    ui->payTo->clear();
    ui->addAsLabel->clear();
    ui->payAmount->clear();
    // and the ones for secure payments just to be sure
    ui->payTo_s->clear();
    ui->memoTextLabel_s->clear();
    ui->payAmount_s->clear();

    ui->payTo->setFocus();

    // update the display unit, to not use the default ("BTC")
    updateDisplayUnit();
}

void SendCoinsEntry::on_deleteButton_clicked()
{
    emit removeEntry(this);
}

bool SendCoinsEntry::validate()
{
    // Check input validity
    bool retval = true;

    if (!recipient.authenticatedMerchant.isEmpty())
        return retval;

    if (!ui->payTo->hasAcceptableInput() ||
        (model && !model->validateAddress(ui->payTo->text())))
    {
        ui->payTo->setValid(false);
        retval = false;
    }

    if(!ui->payAmount->validate())
    {
        retval = false;
    }

    // Reject dust outputs:
    if (retval && GUIUtil::isDust(ui->payTo->text(), ui->payAmount->value())) {
        ui->payAmount->setValid(false);
        retval = false;
    }

    return retval;
}

SendCoinsRecipient SendCoinsEntry::getValue()
{
    if (!recipient.authenticatedMerchant.isEmpty())
        return recipient;

    // User-entered or non-authenticated:
    recipient.address = ui->payTo->text();
    recipient.label = ui->addAsLabel->text();
    recipient.amount = ui->payAmount->value();

    return recipient;
}

QWidget *SendCoinsEntry::setupTabChain(QWidget *prev)
{
    QWidget::setTabOrder(prev, ui->payTo);
    QWidget::setTabOrder(ui->payTo, ui->addressBookButton);
    QWidget::setTabOrder(ui->addressBookButton, ui->pasteButton);
    QWidget::setTabOrder(ui->pasteButton, ui->deleteButton);
    QWidget::setTabOrder(ui->deleteButton, ui->addAsLabel);
    return ui->payAmount->setupTabChain(ui->addAsLabel);
}

void SendCoinsEntry::setValue(const SendCoinsRecipient &value)
{
    recipient = value;

    if (recipient.authenticatedMerchant.isEmpty())
    {
        ui->payTo->setText(recipient.address);
        ui->addAsLabel->setText(recipient.label);
        ui->payAmount->setValue(recipient.amount);
    }
    else
    {
        const payments::PaymentDetails& details = recipient.paymentRequest.getDetails();

        ui->payTo_s->setText(recipient.authenticatedMerchant);
        ui->memoTextLabel_s->setText(QString::fromStdString(details.memo()));
        ui->payAmount_s->setValue(recipient.amount);
        setCurrentWidget(ui->SendCoinsSecure);
    }
}

void SendCoinsEntry::setAddress(const QString &address)
{
    ui->payTo->setText(address);
    ui->payAmount->setFocus();
}

bool SendCoinsEntry::isClear()
{
    return ui->payTo->text().isEmpty() && ui->payTo_s->text().isEmpty();
}

void SendCoinsEntry::setFocus()
{
    ui->payTo->setFocus();
}

void SendCoinsEntry::updateDisplayUnit()
{
    if(model && model->getOptionsModel())
    {
        // Update payAmount with the current unit
        ui->payAmount->setDisplayUnit(model->getOptionsModel()->getDisplayUnit());
        ui->payAmount_s->setDisplayUnit(model->getOptionsModel()->getDisplayUnit());
    }
}
<|endoftext|>


<commit_before>
#include "OrientationSensorsWrapper.h"
#include "TireContactModule.h"

// a module that determines whether the tires have contact to the surface, based on AHRS data

static float thresholdForTireLostContact;

// init the module
void tiresContactInit(float thresholdForLostOfContact)
{
    thresholdForTireLostContact = thresholdForLostOfContact;
}

// read left tire contact state
uint8_t getLeftTireContactState()
{
    // TODO validate
    if(position.getPitch > thresholdForTireLostContact)
    {
        return 0;
    }
    else
    {
        return 1;
    }
}

// read right tire contact state
uint8_t getRightTireContactState()
{
    // TODO validate
    if(position.getPitch < -thresholdForTireLostContact)
    {
        return 0;
    }
    else
    {
        return 1;
    }
}<commit_msg>bug fix<commit_after>
#include "OrientationSensorsWrapper.h"
#include "TireContactModule.h"

// a module that determines whether the tires have contact to the surface, based on AHRS data

static float thresholdForTireLostContact;

// init the module
void tiresContactInit(float thresholdForLostOfContact)
{
    thresholdForTireLostContact = thresholdForLostOfContact;
}

// read left tire contact state
uint8_t getLeftTireContactState()
{
    // TODO validate
    if(position.getPitch() > thresholdForTireLostContact)
    {
        return 0;
    }
    else
    {
        return 1;
    }
}

// read right tire contact state
uint8_t getRightTireContactState()
{
    // TODO validate
    if(position.getPitch() < -thresholdForTireLostContact)
    {
        return 0;
    }
    else
    {
        return 1;
    }
}<|endoftext|>


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

// Configuration parameters
#include "./config.h"

// CONSTANTS
#define NODE_PREFIX "leaves/leaf_"
#define SESSION_FILE ".tree.session"
#define DEFAULT -1

// Standard Streams
#include <iostream>
#include <fstream>

// STL
#include <string>
#include <cstring>
#include <vector>
#include <queue>
#include <algorithm>

// Math
#include <math.h>
#include <limits>

// Timing
#include <chrono>

#include <stdlib.h>

using namespace std;

namespace RTree {
    class Node {
        private:
            static long fileCount;
            static long lowerBound;
            static long upperBound;

        public:
            // Initialize the lower and upper bounds
            static void initialize();

            // Get the fileCount
            static long getFileCount() { return fileCount; }

            // Set the fileCount
            static void setFileCount(long _fileCount) { Node::fileCount = _fileCount; }

        private:
            // Entries required to completely specify a node
            bool leaf = false;
            long fileIndex = DEFAULT;
            long parentIndex = DEFAULT;
            long sizeOfSubtree = DEFAULT;
            vector<long> upperPoints = vector<long>(DIMENSION, DEFAULT);
            vector<long> lowerPoints = vector<long>(DIMENSION, DEFAULT);

            // A node can store either of the below
            vector<long> childIndices;
            vector<long> objectIndices;

        public:
            // Construct a node object for the first time
            Node ();

            //  Read a node from disk
            Node (long _fileIndex);

            // Get the role of the node
            bool isLeaf() const { return leaf; }

            // Get the index of the file
            long getFileIndex() const { return fileIndex; }

            // Get the name of the file
            string getFileName() const { return NODE_PREFIX + to_string(fileIndex); };

            // Store the node to disk
            void storeNodeToDisk() const;

            // Read the node from the disk
            void readNodeFromDisk();
    };

    // The root of the tree
    Node *RRoot = nullptr;

    // Initial static values
    long Node::fileCount = 0;
    long Node::lowerBound = 0;
    long Node::upperBound = 0;

    Node::Node() {
        // Assign a fileIndex to the current node
        fileIndex = ++fileCount;
    }

    Node::Node(long _fileIndex) {
        // Assign the given fileIndex to the node
        fileIndex = _fileIndex;

        // Load the node from the disk
        readNodeFromDisk();
    }

    void Node::initialize() {
        // Save some place in the file for the header
        long headerSize =
            sizeof(leaf)
            + sizeof(fileIndex)
            + sizeof(parentIndex)
            + sizeof(sizeOfSubtree);
        long pageSize = PAGESIZE - headerSize;
        long keySize = sizeof(childIndices.front());
        long nodeSize = sizeof(fileIndex);

        // Compute the bounds
        upperBound = pageSize / (2 * DIMENSION * keySize + nodeSize);
        lowerBound = upperBound / 2;

        // TODO: clear this up
        upperBound = 10;
        lowerBound = 5;
    }

    void Node::storeNodeToDisk() const {
        char buffer[PAGESIZE];
        long location = 0;

        // Store the contents to disk
        memcpy(buffer + location, &leaf, sizeof(leaf));
        location += sizeof(leaf);

        memcpy(buffer + location, &fileIndex, sizeof(fileIndex));
        location +=sizeof(fileIndex);

        memcpy(buffer + location, &parentIndex, sizeof(parentIndex));
        location += sizeof(parentIndex);

        memcpy(buffer + location, &sizeOfSubtree, sizeof(sizeOfSubtree));
        location += sizeof(sizeOfSubtree);

        // Add the bounds of the MBR to the tree
        for (auto upperPoint : upperPoints) {
            memcpy(buffer + location, &upperPoint, sizeof(upperPoint));
            location += sizeof(upperPoint);
        }

        for (auto lowerPoint : lowerPoints) {
            memcpy(buffer + location, &lowerPoint, sizeof(lowerPoint));
            location += sizeof(lowerPoint);
        }

        // We store the objects for a leaf and children for internal node
        if (!leaf) {
            // We have to store the bumber of children so that we can load them properly
            long numberOfChildren = childIndices.size();
            memcpy(buffer + location, &numberOfChildren, sizeof(numberOfChildren));
            location += sizeof(numberOfChildren);

            // Now we get the childIndices from the buffer
            for (long i = 0, childIndex = 0; i < numberOfChildren; ++i) {
                memcpy(buffer + location, &childIndex, sizeof(childIndex));
                location += sizeof(childIndex);
            }
        }

        // Now we copy the buffer to disk
        ofstream nodeFile(getFileName(), ios::binary | ios::out);
        nodeFile.write(buffer, PAGESIZE);
        nodeFile.close();
    }

    void Node::readNodeFromDisk() {
        // Create a char buffer to read contents from disk
        char buffer[PAGESIZE];
        long location = 0;

        // Open the binary file ane read into memory
        ifstream nodeFile(getFileName(), ios::binary | ios::in);
        nodeFile.read(buffer, PAGESIZE);
        nodeFile.close();

        // Retrieve the contents
        memcpy((char *) &leaf, buffer + location, sizeof(leaf));
        location += sizeof(leaf);

        memcpy((char *) &fileIndex, buffer + location, sizeof(fileIndex));
        location += sizeof(fileIndex);

        memcpy((char *) &parentIndex, buffer + location, sizeof(parentIndex));
        location += sizeof(parentIndex);

        memcpy((char *) &sizeOfSubtree, buffer + location, sizeof(sizeOfSubtree));
        location += sizeof(sizeOfSubtree);

        // Retrieve upperPoints
        upperPoints.clear();
        for (long i = 0, upperPoint = 0; i < DIMENSION; ++i) {
            memcpy((char *) &upperPoint, buffer + location, sizeof(upperPoint));
            upperPoints.push_back(upperPoint);
            location += sizeof(upperPoint);
        }

        // Retrieve lowerPoints
        lowerPoints.clear();
        for (long i = 0, lowerPoint = 0; i < DIMENSION; ++i) {
            memcpy((char *) &lowerPoint, buffer + location, sizeof(lowerPoint));
            lowerPoints.push_back(lowerPoint);
            location += sizeof(lowerPoint);
        }

        // We load the objects for a leaf and children for internal node
        if (!leaf) {
            // We need to get the number of children in this case
            long numberOfChildren = 0;
            memcpy((char *) &numberOfChildren, buffer + location, sizeof(numberOfChildren));
            location += sizeof(numberOfChildren);

            // Now we get the childIndices from the buffer
            childIndices.clear();
            for (long i = 0, childIndex = 0; i < numberOfChildren; ++i) {
                memcpy((char *) &childIndex, buffer + location, sizeof(childIndex));
                childIndices.push_back(childIndex);
                location += sizeof(childIndex);
            }
        }
    }

    // Store the current session to disk
    void storeSession() {
        // Create a character buffer which will be written to disk
        char buffer[PAGESIZE];
        long location = 0;

        // Store RRoot's fileIndex
        long fileIndex = RRoot->getFileIndex();
        memcpy(buffer + location, &fileIndex, sizeof(fileIndex));
        location += sizeof(fileIndex);

        // Store the global fileCount
        long fileCount = Node::getFileCount();
        memcpy(buffer + location, &fileCount, sizeof(fileCount));
        location += sizeof(fileCount);

        // Create a binary file and write to memory
        ofstream sessionFile(SESSION_FILE, ios::binary | ios::out);
        sessionFile.write(buffer, PAGESIZE);
        sessionFile.close();
    }

    void loadSession() {
        // Create a character buffer which will be written to disk
        long location = 0;
        char buffer[PAGESIZE];

        // Open the binary file ane read into memory
        ifstream sessionFile(SESSION_FILE, ios::binary | ios::in);
        sessionFile.read(buffer, PAGESIZE);
        sessionFile.close();

        // Retrieve the fileIndex of RRoot
        long fileIndex = 0;
        memcpy((char *) &fileIndex, buffer + location, sizeof(fileIndex));
        location += sizeof(fileIndex);

        // Retreive the global fileCount
        long fileCount = 0;
        memcpy((char *) &fileCount, buffer + location, sizeof(fileCount));
        location += sizeof(fileCount);

        // Store the session variables
        Node::setFileCount(fileCount);

        // Delete the current root and load it from disk
        delete RRoot;
        RRoot = new Node(fileIndex);
        RRoot->readNodeFromDisk();
    }
};

using namespace RTree;

int main() {
    // Initialize the BPlusTree module
    Node::initialize();

    // Create a new tree
    RRoot = new Node();

    // Load session or build a new tree
    // ifstream sessionFile(SESSION_FILE);
    // if (sessionFile.good()) {
        // loadSession();
    // } else {
        // buildTree();
    // }

    // Process queries
    // processQuery();

    cout << RRoot->getFileName();

    // Store the session
    // storeSession();

    return 0;
}
<commit_msg>Reorder static functions<commit_after>/*
 * Copyright (c) 2015 Srijan R Shetty <srijan.shetty+code@gmail.com>
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of
 * this software and associated documentation files (the "Software"), to deal in
 * the Software without restriction, including without limitation the rights to
 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
 * the Software, and to permit persons to whom the Software is furnished to do so,
 * subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

// Configuration parameters
#include "./config.h"

// CONSTANTS
#define NODE_PREFIX "leaves/leaf_"
#define SESSION_FILE ".tree.session"
#define DEFAULT -1

// Standard Streams
#include <iostream>
#include <fstream>

// STL
#include <string>
#include <cstring>
#include <vector>
#include <queue>
#include <algorithm>

// Math
#include <math.h>
#include <limits>

// Timing
#include <chrono>

#include <stdlib.h>

using namespace std;

namespace RTree {
    class Node {
        private:
            static long fileCount;
            static long lowerBound;
            static long upperBound;

        public:
            // Initialize the lower and upper bounds
            static void initialize();

            // Get the fileCount
            static long getFileCount() { return fileCount; }

            // Set the fileCount
            static void setFileCount(long _fileCount) { Node::fileCount = _fileCount; }

        private:
            // Entries required to completely specify a node
            bool leaf = false;
            long fileIndex = DEFAULT;
            long parentIndex = DEFAULT;
            long sizeOfSubtree = DEFAULT;
            vector<long> upperPoints = vector<long>(DIMENSION, DEFAULT);
            vector<long> lowerPoints = vector<long>(DIMENSION, DEFAULT);

            // A node can store either of the below
            vector<long> childIndices;
            vector<long> objectIndices;

        public:
            // Construct a node object for the first time
            Node ();

            //  Read a node from disk
            Node (long _fileIndex);

            // Get the role of the node
            bool isLeaf() const { return leaf; }

            // Get the index of the file
            long getFileIndex() const { return fileIndex; }

            // Get the name of the file
            string getFileName() const { return NODE_PREFIX + to_string(fileIndex); };

            // Store the node to disk
            void storeNodeToDisk() const;

            // Read the node from the disk
            void readNodeFromDisk();
    };

    // The root of the tree
    Node *RRoot = nullptr;

    // Initial static values
    long Node::fileCount = 0;
    long Node::lowerBound = 0;
    long Node::upperBound = 0;

    void Node::initialize() {
        // Save some place in the file for the header
        long headerSize =
            sizeof(leaf)
            + sizeof(fileIndex)
            + sizeof(parentIndex)
            + sizeof(sizeOfSubtree);
        long pageSize = PAGESIZE - headerSize;
        long keySize = sizeof(childIndices.front());
        long nodeSize = sizeof(fileIndex);

        // Compute the bounds
        upperBound = pageSize / (2 * DIMENSION * keySize + nodeSize);
        lowerBound = upperBound / 2;

        // TODO: clear this up
        upperBound = 10;
        lowerBound = 5;
    }

    Node::Node() {
        // Assign a fileIndex to the current node
        fileIndex = ++fileCount;
    }

    Node::Node(long _fileIndex) {
        // Assign the given fileIndex to the node
        fileIndex = _fileIndex;

        // Load the node from the disk
        readNodeFromDisk();
    }

    void Node::storeNodeToDisk() const {
        char buffer[PAGESIZE];
        long location = 0;

        // Store the contents to disk
        memcpy(buffer + location, &leaf, sizeof(leaf));
        location += sizeof(leaf);

        memcpy(buffer + location, &fileIndex, sizeof(fileIndex));
        location +=sizeof(fileIndex);

        memcpy(buffer + location, &parentIndex, sizeof(parentIndex));
        location += sizeof(parentIndex);

        memcpy(buffer + location, &sizeOfSubtree, sizeof(sizeOfSubtree));
        location += sizeof(sizeOfSubtree);

        // Add the bounds of the MBR to the tree
        for (auto upperPoint : upperPoints) {
            memcpy(buffer + location, &upperPoint, sizeof(upperPoint));
            location += sizeof(upperPoint);
        }

        for (auto lowerPoint : lowerPoints) {
            memcpy(buffer + location, &lowerPoint, sizeof(lowerPoint));
            location += sizeof(lowerPoint);
        }

        // We store the objects for a leaf and children for internal node
        if (!leaf) {
            // We have to store the bumber of children so that we can load them properly
            long numberOfChildren = childIndices.size();
            memcpy(buffer + location, &numberOfChildren, sizeof(numberOfChildren));
            location += sizeof(numberOfChildren);

            // Now we get the childIndices from the buffer
            for (long i = 0, childIndex = 0; i < numberOfChildren; ++i) {
                memcpy(buffer + location, &childIndex, sizeof(childIndex));
                location += sizeof(childIndex);
            }
        }

        // Now we copy the buffer to disk
        ofstream nodeFile(getFileName(), ios::binary | ios::out);
        nodeFile.write(buffer, PAGESIZE);
        nodeFile.close();
    }

    void Node::readNodeFromDisk() {
        // Create a char buffer to read contents from disk
        char buffer[PAGESIZE];
        long location = 0;

        // Open the binary file ane read into memory
        ifstream nodeFile(getFileName(), ios::binary | ios::in);
        nodeFile.read(buffer, PAGESIZE);
        nodeFile.close();

        // Retrieve the contents
        memcpy((char *) &leaf, buffer + location, sizeof(leaf));
        location += sizeof(leaf);

        memcpy((char *) &fileIndex, buffer + location, sizeof(fileIndex));
        location += sizeof(fileIndex);

        memcpy((char *) &parentIndex, buffer + location, sizeof(parentIndex));
        location += sizeof(parentIndex);

        memcpy((char *) &sizeOfSubtree, buffer + location, sizeof(sizeOfSubtree));
        location += sizeof(sizeOfSubtree);

        // Retrieve upperPoints
        upperPoints.clear();
        for (long i = 0, upperPoint = 0; i < DIMENSION; ++i) {
            memcpy((char *) &upperPoint, buffer + location, sizeof(upperPoint));
            upperPoints.push_back(upperPoint);
            location += sizeof(upperPoint);
        }

        // Retrieve lowerPoints
        lowerPoints.clear();
        for (long i = 0, lowerPoint = 0; i < DIMENSION; ++i) {
            memcpy((char *) &lowerPoint, buffer + location, sizeof(lowerPoint));
            lowerPoints.push_back(lowerPoint);
            location += sizeof(lowerPoint);
        }

        // We load the objects for a leaf and children for internal node
        if (!leaf) {
            // We need to get the number of children in this case
            long numberOfChildren = 0;
            memcpy((char *) &numberOfChildren, buffer + location, sizeof(numberOfChildren));
            location += sizeof(numberOfChildren);

            // Now we get the childIndices from the buffer
            childIndices.clear();
            for (long i = 0, childIndex = 0; i < numberOfChildren; ++i) {
                memcpy((char *) &childIndex, buffer + location, sizeof(childIndex));
                childIndices.push_back(childIndex);
                location += sizeof(childIndex);
            }
        }
    }

    // Store the current session to disk
    void storeSession() {
        // Create a character buffer which will be written to disk
        char buffer[PAGESIZE];
        long location = 0;

        // Store RRoot's fileIndex
        long fileIndex = RRoot->getFileIndex();
        memcpy(buffer + location, &fileIndex, sizeof(fileIndex));
        location += sizeof(fileIndex);

        // Store the global fileCount
        long fileCount = Node::getFileCount();
        memcpy(buffer + location, &fileCount, sizeof(fileCount));
        location += sizeof(fileCount);

        // Create a binary file and write to memory
        ofstream sessionFile(SESSION_FILE, ios::binary | ios::out);
        sessionFile.write(buffer, PAGESIZE);
        sessionFile.close();
    }

    void loadSession() {
        // Create a character buffer which will be written to disk
        long location = 0;
        char buffer[PAGESIZE];

        // Open the binary file ane read into memory
        ifstream sessionFile(SESSION_FILE, ios::binary | ios::in);
        sessionFile.read(buffer, PAGESIZE);
        sessionFile.close();

        // Retrieve the fileIndex of RRoot
        long fileIndex = 0;
        memcpy((char *) &fileIndex, buffer + location, sizeof(fileIndex));
        location += sizeof(fileIndex);

        // Retreive the global fileCount
        long fileCount = 0;
        memcpy((char *) &fileCount, buffer + location, sizeof(fileCount));
        location += sizeof(fileCount);

        // Store the session variables
        Node::setFileCount(fileCount);

        // Delete the current root and load it from disk
        delete RRoot;
        RRoot = new Node(fileIndex);
        RRoot->readNodeFromDisk();
    }
};

using namespace RTree;

int main() {
    // Initialize the BPlusTree module
    Node::initialize();

    // Create a new tree
    RRoot = new Node();

    // Load session or build a new tree
    // ifstream sessionFile(SESSION_FILE);
    // if (sessionFile.good()) {
        // loadSession();
    // } else {
        // buildTree();
    // }

    // Process queries
    // processQuery();

    cout << RRoot->getFileName();

    // Store the session
    // storeSession();

    return 0;
}
<|endoftext|>


<commit_before>#ifndef ID_HXX_HQ5DONMJ
#define ID_HXX_HQ5DONMJ

#include "string.hxx"
#include "ptr.hxx"
#include "ppr.hxx"

#include <string>
#include <ostream>
#include <functional>

namespace miniml
{

/// Identifiers keep a hash for quick equality testing.
class Id final
{
public:
  /// Creates an identifier. \a str isn't copied.
  Id(const Ptr<String> str):
    m_val(str),
    m_hash(make_hash(*str))
  { }

  /// If the hashes are the same then the values are also checked in case of a
  /// collision.
  /// \return Whether the two identifiers are the same.
  bool operator==(const Id &other) const
  { return m_hash == other.m_hash && m_val == other.m_val; }

  /// \return The value of the identifier.
  const Ptr<String> val() const { return m_val; }

  /// \return The identifier in \ref String form.
  operator const Ptr<String>() const { return val(); }

  /// Pretty prints an identifier.
  /// \relates PprString
  const Ptr<Ppr> ppr() const { return ppr::string(*val()); }

private:
  /// Hash function for \ref String.
  static std::hash<String> make_hash;

  const Ptr<String> m_val;  ///< Value.
  unsigned long m_hash;     ///< Hash.
};

/// Outputs an identifier to the given output stream.
inline OStream& operator<<(OStream &out, const Id &id)
{
  return out << *id.val();
}

}

#endif /* end of include guard: ID_HXX_HQ5DONMJ */
<commit_msg>Add constructor Id(const String&)<commit_after>#ifndef ID_HXX_HQ5DONMJ
#define ID_HXX_HQ5DONMJ

#include "string.hxx"
#include "ptr.hxx"
#include "ppr.hxx"

#include <string>
#include <ostream>
#include <functional>

namespace miniml
{

/// Identifiers keep a hash for quick equality testing.
class Id final
{
public:
  /// Creates an identifier. \a str isn't copied.
  Id(const Ptr<String> str):
    m_val(str),
    m_hash(make_hash(*str))
  { }

  /// Copies a string onto the heap and constructs an identifier from it.
  Id(const String &str):
    Id(ptr<String>(str))
  { }

  /// If the hashes are the same then the values are also checked in case of a
  /// collision.
  /// \return Whether the two identifiers are the same.
  bool operator==(const Id &other) const
  { return m_hash == other.m_hash && m_val == other.m_val; }

  /// \return The value of the identifier.
  const Ptr<String> val() const { return m_val; }

  /// \return The identifier in \ref String form.
  operator const Ptr<String>() const { return val(); }

  /// Pretty prints an identifier.
  /// \relates PprString
  const Ptr<Ppr> ppr() const { return ppr::string(*val()); }

private:
  /// Hash function for \ref String.
  static std::hash<String> make_hash;

  const Ptr<String> m_val;  ///< Value.
  unsigned long m_hash;     ///< Hash.
};

/// Outputs an identifier to the given output stream.
inline OStream& operator<<(OStream &out, const Id &id)
{
  return out << *id.val();
}

}

#endif /* end of include guard: ID_HXX_HQ5DONMJ */
<|endoftext|>