<commit_before>#include "mainwindow.h"
#include "ui_mainwindow.h"

#include <QFileDialog>
#include <QDesktopServices>
#include <QUrl>
#include <QDebug>

namespace
{
	enum TableColum
	{
		COL_ENABLED,
		COL_PATH,
		COL_EXISTS
	};

}

MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent)
  , ui(new Ui::MainWindow)
  , m_reader(HKEY_CURRENT_USER)
  , m_config("QtPathEditor")
{
	ui->setupUi(this);
	getPaths();

	const QIcon tick(":/icons/tick.png");
	const QIcon cross(":/icons/cross.png");
	ui->tableWidget->setRowCount(m_paths.size());

	int itemIdxInTable = 0;

	/// \todo use the indexes
	for (int i = 0; i < m_paths.size(); ++i)
	{
		const QString & pathQt = m_paths[i];

		QTableWidgetItem *itemEn   = new QTableWidgetItem(); // enabled
		QTableWidgetItem *itemPath = new QTableWidgetItem(pathQt);
		QTableWidgetItem *itemEx   = new QTableWidgetItem(); // exist
		itemEn->setFlags(Qt::NoItemFlags | Qt::ItemIsEnabled | Qt::ItemIsUserCheckable);
		itemEx->setFlags(Qt::NoItemFlags | Qt::ItemIsEnabled);

		itemEn->setCheckState(m_statuses[i] ? Qt::Checked : Qt::Unchecked);
		itemEn->setTextAlignment(Qt::AlignHCenter);
		itemEx->setIcon(QFile::exists(pathQt) ? tick : cross);

		ui->tableWidget->setItem(itemIdxInTable,   COL_ENABLED, itemEn);
		ui->tableWidget->setItem(itemIdxInTable,   COL_PATH, itemPath);
		ui->tableWidget->setItem(itemIdxInTable++, COL_EXISTS, itemEx);
	}

	setupVisualAspect();
	makeConnections();
}

MainWindow::~MainWindow()
{
	on_buttonSave_clicked();
	delete ui;
}

void MainWindow::getPaths()
{
	StringListT  listFromRegistry;
	m_reader.Read(listFromRegistry);

	// Read from the registry (all must be enabled)
	for (int i = 0; i < static_cast<int>(listFromRegistry.size()); ++i)
	{
		m_paths     << QString::fromWCharArray(listFromRegistry[i].c_str());
		m_statuses  << true;
		m_indexes   << i;
	}

	// Read from the config file (it can override the status of the previous paths)
	const QStringList paths    = m_config.getPaths();
	const QBitArray   statuses = m_config.getStatus();
	Q_ASSERT (paths.size() == statuses.size());

	for (int i = 0; i < paths.size(); ++i)
	{
		const int idx = m_paths.indexOf(paths[i]);
		if (idx != -1) // Already in the list -> update the status
		{
			m_statuses[i] = statuses[i];
		}
		else
		{
			m_paths     << m_paths[i];
			m_statuses  << statuses[i];
			m_indexes   << (m_paths.size() - 1);
		}
	}
}

void MainWindow::on_buttonSave_clicked()
{
	saveConfigFile();
	saveRegistry();
}

void MainWindow::itemPressed(QTableWidgetItem *item)
{
	switch (item->column())
	{
	case COL_ENABLED :
	{
		const int idx = m_indexes[item->row()];
		const bool checked = item->checkState() == Qt::Checked;
		m_statuses[idx] = checked;
		qDebug() << "Path changed its status to: " << checked;
		break;
	}
	default:
	{
		qDebug() << "itemPressed. Action not implemented with colum: " << item->column();
	}
	}
}

void MainWindow::saveRegistry()
{
	StringListT listToRegistry;

	for (int i = 0; i < m_paths.size(); ++i)
	{
		const int idx = m_indexes[i];
		if (m_statuses[idx])
		{
			listToRegistry.push_back(m_paths[idx].toStdWString());
		}
	}

	m_reader.Write(listToRegistry);
}

void MainWindow::saveConfigFile()
{
	m_config.setPaths(m_paths);
	m_config.setOrder(m_indexes);

	QBitArray array (m_statuses.size());
	for (int i = 0; i < m_statuses.size(); ++i)
	{
		array.setBit(i, m_statuses[i]);
	}
	m_config.setStatus(array);
}

void MainWindow::on_buttonBrowse_clicked()
{
	const int idx = m_indexes[ui->tableWidget->currentRow()];
	if (m_statuses[idx])
	{
		QDesktopServices::openUrl(m_paths[idx]);
	}
	else
	{
		qDebug() << "Non existing path will be not opened";
	}
}

void MainWindow::sectionMoved(int logicalIndex, int oldVisualIndex, int newVisualIndex)
{
	qDebug() << "Section moved: " << logicalIndex << oldVisualIndex << newVisualIndex;
}

void MainWindow::setupVisualAspect()
{
	ui->tableWidget->verticalHeader()->setMovable(true);
	ui->tableWidget->verticalHeader()->setDragEnabled(true);
	ui->tableWidget->verticalHeader()->setDragDropMode(QAbstractItemView::InternalMove);

	ui->tableWidget->setColumnWidth(COL_ENABLED,  50);
	ui->tableWidget->resizeColumnToContents(COL_PATH);
	ui->tableWidget->setColumnWidth(COL_EXISTS,   50);
}

void MainWindow::makeConnections()
{
	connect(ui->tableWidget, SIGNAL(itemChanged(QTableWidgetItem *)),
			this, SLOT(itemPressed(QTableWidgetItem *)));
	connect(ui->tableWidget->verticalHeader(), SIGNAL(sectionMoved(int,int,int)),
			this, SLOT(sectionMoved(int,int,int)));
}

void MainWindow::on_buttonAddPath_clicked()
{
	QString dir = QFileDialog::getExistingDirectory(this, tr("Select path to add"),
		QDir::homePath(), QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks);

	if (!dir.isEmpty())
	{
		/// \todo check if the path exists?
		const QIcon tick(":/icons/tick.png");
		m_paths     << dir;
		m_statuses  << true;
		m_indexes   << (m_paths.size() - 1);

		const int row = ui->tableWidget->rowCount();

		ui->tableWidget->insertRow(row);

		QTableWidgetItem *itemEn   = new QTableWidgetItem(); // enabled
		QTableWidgetItem *itemPath = new QTableWidgetItem(dir);
		QTableWidgetItem *itemEx   = new QTableWidgetItem(); // exist
		itemEn->setFlags(Qt::NoItemFlags | Qt::ItemIsEnabled | Qt::ItemIsUserCheckable);
		itemEx->setFlags(Qt::NoItemFlags | Qt::ItemIsEnabled);

		itemEn->setCheckState(Qt::Checked);
		itemEn->setTextAlignment(Qt::AlignHCenter);
		itemEx->setIcon(tick);

		ui->tableWidget->setItem(row, COL_ENABLED,  itemEn);
		ui->tableWidget->setItem(row, COL_PATH,     itemPath);
		ui->tableWidget->setItem(row, COL_EXISTS,   itemEx);
	}
}

void MainWindow::on_buttonDeletePath_clicked()
{

}
<commit_msg>Implement the delete function<commit_after>#include "mainwindow.h"
#include "ui_mainwindow.h"

#include <QFileDialog>
#include <QDesktopServices>
#include <QUrl>
#include <QDebug>

namespace
{
	enum TableColum
	{
		COL_ENABLED,
		COL_PATH,
		COL_EXISTS
	};

}

MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent)
  , ui(new Ui::MainWindow)
  , m_reader(HKEY_CURRENT_USER)
  , m_config("QtPathEditor")
{
	ui->setupUi(this);
	getPaths();

	const QIcon tick(":/icons/tick.png");
	const QIcon cross(":/icons/cross.png");
	ui->tableWidget->setRowCount(m_paths.size());

	int itemIdxInTable = 0;

	/// \todo use the indexes
	for (int i = 0; i < m_paths.size(); ++i)
	{
		const QString & pathQt = m_paths[i];

		QTableWidgetItem *itemEn   = new QTableWidgetItem(); // enabled
		QTableWidgetItem *itemPath = new QTableWidgetItem(pathQt);
		QTableWidgetItem *itemEx   = new QTableWidgetItem(); // exist
		itemEn->setFlags(Qt::NoItemFlags | Qt::ItemIsEnabled | Qt::ItemIsUserCheckable);
		itemEx->setFlags(Qt::NoItemFlags | Qt::ItemIsEnabled);

		itemEn->setCheckState(m_statuses[i] ? Qt::Checked : Qt::Unchecked);
		itemEn->setTextAlignment(Qt::AlignHCenter);
		itemEx->setIcon(QFile::exists(pathQt) ? tick : cross);

		ui->tableWidget->setItem(itemIdxInTable,   COL_ENABLED, itemEn);
		ui->tableWidget->setItem(itemIdxInTable,   COL_PATH, itemPath);
		ui->tableWidget->setItem(itemIdxInTable++, COL_EXISTS, itemEx);
	}

	setupVisualAspect();
	makeConnections();
}

MainWindow::~MainWindow()
{
	on_buttonSave_clicked();
	delete ui;
}

void MainWindow::getPaths()
{
	StringListT  listFromRegistry;
	m_reader.Read(listFromRegistry);

	// Read from the registry (all must be enabled)
	for (int i = 0; i < static_cast<int>(listFromRegistry.size()); ++i)
	{
		m_paths     << QString::fromWCharArray(listFromRegistry[i].c_str());
		m_statuses  << true;
		m_indexes   << i;
	}

	// Read from the config file (it can override the status of the previous paths)
	const QStringList paths    = m_config.getPaths();
	const QBitArray   statuses = m_config.getStatus();
	Q_ASSERT (paths.size() == statuses.size());

	for (int i = 0; i < paths.size(); ++i)
	{
		const int idx = m_paths.indexOf(paths[i]);
		if (idx != -1) // Already in the list -> update the status
		{
			m_statuses[i] = statuses[i];
		}
		else
		{
			m_paths     << m_paths[i];
			m_statuses  << statuses[i];
			m_indexes   << (m_paths.size() - 1);
		}
	}
}

void MainWindow::on_buttonSave_clicked()
{
	saveConfigFile();
	saveRegistry();
}

void MainWindow::itemPressed(QTableWidgetItem *item)
{
	switch (item->column())
	{
	case COL_ENABLED :
	{
		const int idx = m_indexes[item->row()];
		const bool checked = item->checkState() == Qt::Checked;
		m_statuses[idx] = checked;
		qDebug() << "Path changed its status to: " << checked;
		break;
	}
	default:
	{
		qDebug() << "itemPressed. Action not implemented with colum: " << item->column();
	}
	}
}

void MainWindow::saveRegistry()
{
	StringListT listToRegistry;

	for (int i = 0; i < m_paths.size(); ++i)
	{
		const int idx = m_indexes[i];
		if (m_statuses[idx])
		{
			listToRegistry.push_back(m_paths[idx].toStdWString());
		}
	}

	m_reader.Write(listToRegistry);
}

void MainWindow::saveConfigFile()
{
	m_config.setPaths(m_paths);
	m_config.setOrder(m_indexes);

	QBitArray array (m_statuses.size());
	for (int i = 0; i < m_statuses.size(); ++i)
	{
		array.setBit(i, m_statuses[i]);
	}
	m_config.setStatus(array);
}

void MainWindow::on_buttonBrowse_clicked()
{
	const int idx = m_indexes[ui->tableWidget->currentRow()];
	if (m_statuses[idx])
	{
		QDesktopServices::openUrl(m_paths[idx]);
	}
	else
	{
		qDebug() << "Non existing path will be not opened";
	}
}

void MainWindow::sectionMoved(int logicalIndex, int oldVisualIndex, int newVisualIndex)
{
	qDebug() << "Section moved: " << logicalIndex << oldVisualIndex << newVisualIndex;
}

void MainWindow::setupVisualAspect()
{
	ui->tableWidget->verticalHeader()->setMovable(true);
	ui->tableWidget->verticalHeader()->setDragEnabled(true);
	ui->tableWidget->verticalHeader()->setDragDropMode(QAbstractItemView::InternalMove);

	ui->tableWidget->setColumnWidth(COL_ENABLED,  50);
	ui->tableWidget->resizeColumnToContents(COL_PATH);
	ui->tableWidget->setColumnWidth(COL_EXISTS,   50);
}

void MainWindow::makeConnections()
{
	connect(ui->tableWidget, SIGNAL(itemChanged(QTableWidgetItem *)),
			this, SLOT(itemPressed(QTableWidgetItem *)));
	connect(ui->tableWidget->verticalHeader(), SIGNAL(sectionMoved(int,int,int)),
			this, SLOT(sectionMoved(int,int,int)));
}

void MainWindow::on_buttonAddPath_clicked()
{
	QString dir = QFileDialog::getExistingDirectory(this, tr("Select path to add"),
		QDir::homePath(), QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks);

	if (!dir.isEmpty())
	{
		/// \todo check if the path exists?
		const QIcon tick(":/icons/tick.png");
		m_paths     << dir;
		m_statuses  << true;
		m_indexes   << (m_paths.size() - 1);

		const int row = ui->tableWidget->rowCount();

		ui->tableWidget->insertRow(row);

		QTableWidgetItem *itemEn   = new QTableWidgetItem(); // enabled
		QTableWidgetItem *itemPath = new QTableWidgetItem(dir);
		QTableWidgetItem *itemEx   = new QTableWidgetItem(); // exist
		itemEn->setFlags(Qt::NoItemFlags | Qt::ItemIsEnabled | Qt::ItemIsUserCheckable);
		itemEx->setFlags(Qt::NoItemFlags | Qt::ItemIsEnabled);

		itemEn->setCheckState(Qt::Checked);
		itemEn->setTextAlignment(Qt::AlignHCenter);
		itemEx->setIcon(tick);

		ui->tableWidget->setItem(row, COL_ENABLED,  itemEn);
		ui->tableWidget->setItem(row, COL_PATH,     itemPath);
		ui->tableWidget->setItem(row, COL_EXISTS,   itemEx);
	}
}

void MainWindow::on_buttonDeletePath_clicked()
{
	const int dataIndex = m_indexes[ui->tableWidget->currentRow()];
	m_paths.erase(m_paths.begin() + m_indexes[dataIndex]);
	m_statuses.erase(m_statuses.begin() + m_indexes[dataIndex]);
	m_indexes.erase(m_indexes.begin() + dataIndex);
	ui->tableWidget->removeRow(ui->tableWidget->currentRow());

}
<|endoftext|>


<commit_before>#include <string>
#include <sstream>
#include <vector>

#include "commands.h"
#include "RamCloud.h"
#include "ClientException.h"

std::string unsupportedCommand(RAMCloud::RamCloud *client,
    uint64_t tableId,
    std::vector<std::string> *argv) {
  std::string res("+Unsupported command.\r\n");
  return res;
}

std::string getCommand(RAMCloud::RamCloud *client,
    uint64_t tableId,
    std::vector<std::string> *argv) {
  RAMCloud::Buffer buffer;
  try {
    client->read(tableId, (*argv)[1].c_str(),
        (*argv)[1].length(), &buffer);
    std::stringstream ss;
    ss << "$" << buffer.size();
    const char* data = static_cast<const char*>(buffer.getRange(0,
            buffer.size()));
    ss.write(data, buffer.size());
    ss << "\r\n";
    return ss.str();
  } catch (RAMCloud::ObjectDoesntExistException& e) {
    std::string res("+Unknown key.\r\n");
    return res;
  }
}

std::string incrCommand(RAMCloud::RamCloud *client,
    uint64_t tableId,
    std::vector<std::string> *argv) {
  try {
    uint64_t newValue = client->incrementInt64(tableId, (*argv)[1].c_str(),
        (*argv)[1].length(), 1);
    std::stringstream ss;
    ss << ":" << newValue;
    ss << "\r\n";
    return ss.str();
  } catch (RAMCloud::ObjectDoesntExistException& e) {
    std::string res("+Unknown key.\r\n");
    return res;
  }
}

std::string setCommand(RAMCloud::RamCloud *client,
    uint64_t tableId,
    std::vector<std::string> *argv) {
  client->write(tableId, (*argv)[1].c_str(),
      (*argv)[1].length(),
      (*argv)[2].c_str());
  return std::string("+OK\r\n");
}

std::string lpushCommand(RAMCloud::RamCloud *client,
    uint64_t tableId,
    std::vector<std::string> *argv) {

  // Arg validation.
  if ((*argv)[2].length() >= (1 << (sizeof(uint16_t)*8))) {
    std::string res("+List element must be less than 64KB in size.\r\n");
    return res;
  }

  // Read out old list, if it exists.
  RAMCloud::Buffer buffer;
  bool listExists = true;
  try {
    client->read(tableId, (*argv)[1].c_str(),
        (*argv)[1].length(), &buffer);
  } catch (RAMCloud::ObjectDoesntExistException& e) {
    listExists = false;
  }

  // Append new element to list.
  size_t newListSize;
  uint16_t elementLength = (uint16_t)(*argv)[2].length();
  if (listExists) {
    newListSize = sizeof(uint16_t) + elementLength + buffer.size();
  } else {
    newListSize = sizeof(uint16_t) + elementLength;
  }

  char* newList = (char*)malloc(newListSize);
  memcpy(newList, &elementLength, sizeof(uint16_t));
  memcpy(newList + sizeof(uint16_t), (*argv)[2].c_str(), elementLength);

  if (listExists) {
    const char* oldList = static_cast<const char*>(buffer.getRange(0,
            buffer.size()));
    memcpy(newList + sizeof(uint16_t) + elementLength, oldList, buffer.size());
  }

  // Write new list.
  client->write(tableId,
      (*argv)[1].c_str(),
      (*argv)[1].length(),
      newList,
      newListSize);

  free(newList);

  // Count number of elements in the new list.
  uint32_t pos = 0;
  uint32_t count = 0;
  while (pos < newListSize) {
    count++;
    uint16_t len = *(uint16_t*)(newList + pos);
    pos += sizeof(uint16_t) + len;
  }

  std::ostringstream oss;
  oss << ":" << count << "\r\n";

  return oss.str();
}

std::string rpushCommand(RAMCloud::RamCloud *client,
    uint64_t tableId,
    std::vector<std::string> *argv) {

  // Arg validation.
  if ((*argv)[2].length() >= (1 << (sizeof(uint16_t)*8))) {
    std::string res("+List element must be less than 64KB in size.\r\n");
    return res;
  }

  // Read out old list, if it exists.
  RAMCloud::Buffer buffer;
  bool listExists = true;
  try {
    client->read(tableId, (*argv)[1].c_str(),
        (*argv)[1].length(), &buffer);
  } catch (RAMCloud::ObjectDoesntExistException& e) {
    listExists = false;
  }

  // Append new element to list.
  size_t newListSize;
  uint16_t elementLength = (uint16_t)(*argv)[2].length();
  char* newList;
  if (listExists) {
    newListSize = sizeof(uint16_t) + elementLength + buffer.size();
    newList = (char*)malloc(newListSize);
    const char* oldList = static_cast<const char*>(buffer.getRange(0,
            buffer.size()));
    memcpy(newList, oldList, buffer.size());
    memcpy(newList + buffer.size(), &elementLength, sizeof(uint16_t));
    memcpy(newList + buffer.size() + sizeof(uint16_t), (*argv)[2].c_str(),
        elementLength);
  } else {
    newListSize = sizeof(uint16_t) + elementLength;
    newList = (char*)malloc(newListSize);
    memcpy(newList, &elementLength, sizeof(uint16_t));
    memcpy(newList + sizeof(uint16_t), (*argv)[2].c_str(), elementLength);
  }

  // Write new list.
  client->write(tableId,
      (*argv)[1].c_str(),
      (*argv)[1].length(),
      newList,
      newListSize);

  free(newList);

  // Count number of elements in the new list.
  uint32_t pos = 0;
  uint32_t count = 0;
  printf("newListSize: %d\n", newListSize);
  while (pos < newListSize) {
    count++;
    uint16_t len = *(uint16_t*)(newList + pos);
    pos += sizeof(uint16_t) + len;
  }

  std::ostringstream oss;
  oss << ":" << count << "\r\n";

  return oss.str();
}

std::string lpopCommand(RAMCloud::RamCloud *client,
    uint64_t tableId,
    std::vector<std::string> *argv) {

  // Read out list.
  RAMCloud::Buffer buffer;
  try {
    client->read(tableId, (*argv)[1].c_str(),
        (*argv)[1].length(), &buffer);
  } catch (RAMCloud::ObjectDoesntExistException& e) {
    return std::string("+Unknown key.");
  }

  if (buffer.size() == 0) {
    return std::string("$-1\r\n");
  }

  const char* list = static_cast<const char*>(buffer.getRange(0,
        buffer.size()));
  uint16_t len = *(uint16_t*)(list);
  std::string element(list + sizeof(uint16_t), len);

  size_t newListSize = buffer.size() - sizeof(uint16_t) - len;
  char* newList = (char*)malloc(newListSize);
  memcpy(newList, list + sizeof(uint16_t) + len, newListSize);

  // Write new list.
  client->write(tableId,
      (*argv)[1].c_str(),
      (*argv)[1].length(),
      newList,
      newListSize);

  free(newList);

  std::ostringstream oss;
  oss << "+" << element << "\r\n";

  return oss.str();
}

std::string rpopCommand(RAMCloud::RamCloud *client,
    uint64_t tableId,
    std::vector<std::string> *argv) {

  // Read out list.
  RAMCloud::Buffer buffer;
  try {
    client->read(tableId, (*argv)[1].c_str(),
        (*argv)[1].length(), &buffer);
  } catch (RAMCloud::ObjectDoesntExistException& e) {
    return std::string("+Unknown key.");
  }

  if (buffer.size() == 0) {
    return std::string("$-1\r\n");
  }

  const char* list = static_cast<const char*>(buffer.getRange(0,
        buffer.size()));

  // Find last element of the list.
  uint32_t pos = 0;
  uint16_t len;
  while (true) {
    len = *(uint16_t*)(list + pos);
    if (pos + sizeof(uint16_t) + len == buffer.size()) {
      break;
    }
    pos += sizeof(uint16_t) + len;
  }

  std::string element(list + pos + sizeof(uint16_t), len);

  size_t newListSize = buffer.size() - sizeof(uint16_t) - len;
  char* newList = (char*)malloc(newListSize);
  memcpy(newList, list, newListSize);

  // Write new list.
  client->write(tableId,
      (*argv)[1].c_str(),
      (*argv)[1].length(),
      newList,
      newListSize);

  free(newList);

  std::ostringstream oss;
  oss << "+" << element << "\r\n";

  return oss.str();
}

std::string lrangeCommand(RAMCloud::RamCloud *client,
    uint64_t tableId,
    std::vector<std::string> *argv) {

  int start = atoi((*argv)[2].c_str());
  int end = atoi((*argv)[3].c_str());

  // Read out old list, if it exists.
  RAMCloud::Buffer buffer;
  try {
    client->read(tableId, (*argv)[1].c_str(),
        (*argv)[1].length(), &buffer);
  } catch (RAMCloud::ObjectDoesntExistException& e) {
    std::string res("+Unknown key.\r\n");
    return res;
  }

  const char* list = static_cast<const char*>(buffer.getRange(0,
        buffer.size()));

  // Parse the elements.
  uint32_t pos = 0;
  std::vector<std::string> elements;
  while (pos < buffer.size()) {
    uint16_t len = *(uint16_t*)(list + pos);
    pos += sizeof(uint16_t);
    elements.emplace_back(list + pos, len);
    pos += len;
  }

  uint32_t startIndex;
  if (start < 0) {
    startIndex = elements.size() + start;
  } else {
    startIndex = start;
  }

  uint32_t endIndex;
  if (end < 0) {
    endIndex = elements.size() + end;
  } else {
    if (end >= elements.size()) {
      endIndex = elements.size() - 1;
    }
  }

  // Generate return message.
  std::ostringstream oss;
  oss << "*" << elements.size() << "\r\n";

  uint32_t count = 0;
  for(auto const& e: elements) {
    if (count >= start && count <= end) {
      oss << "$" << e.length() << "\r\n" << e << "\r\n";
    }
    count++;
  }

  return oss.str();
}

<commit_msg>Fix couple of bugs.<commit_after>#include <string>
#include <sstream>
#include <vector>

#include "commands.h"
#include "RamCloud.h"
#include "ClientException.h"

std::string unsupportedCommand(RAMCloud::RamCloud *client,
    uint64_t tableId,
    std::vector<std::string> *argv) {
  std::string res("+Unsupported command.\r\n");
  return res;
}

std::string getCommand(RAMCloud::RamCloud *client,
    uint64_t tableId,
    std::vector<std::string> *argv) {
  RAMCloud::Buffer buffer;
  try {
    client->read(tableId, (*argv)[1].c_str(),
        (*argv)[1].length(), &buffer);
    std::stringstream ss;
    ss << "$" << buffer.size();
    const char* data = static_cast<const char*>(buffer.getRange(0,
            buffer.size()));
    ss.write(data, buffer.size());
    ss << "\r\n";
    return ss.str();
  } catch (RAMCloud::ObjectDoesntExistException& e) {
    std::string res("+Unknown key.\r\n");
    return res;
  }
}

std::string incrCommand(RAMCloud::RamCloud *client,
    uint64_t tableId,
    std::vector<std::string> *argv) {
  try {
    uint64_t newValue = client->incrementInt64(tableId, (*argv)[1].c_str(),
        (*argv)[1].length(), 1);
    std::stringstream ss;
    ss << ":" << newValue;
    ss << "\r\n";
    return ss.str();
  } catch (RAMCloud::ObjectDoesntExistException& e) {
    std::string res("+Unknown key.\r\n");
    return res;
  }
}

std::string setCommand(RAMCloud::RamCloud *client,
    uint64_t tableId,
    std::vector<std::string> *argv) {
  client->write(tableId, (*argv)[1].c_str(),
      (*argv)[1].length(),
      (*argv)[2].c_str());
  return std::string("+OK\r\n");
}

std::string lpushCommand(RAMCloud::RamCloud *client,
    uint64_t tableId,
    std::vector<std::string> *argv) {

  // Arg validation.
  if ((*argv)[2].length() >= (1 << (sizeof(uint16_t)*8))) {
    std::string res("+List element must be less than 64KB in size.\r\n");
    return res;
  }

  // Read out old list, if it exists.
  RAMCloud::Buffer buffer;
  bool listExists = true;
  try {
    client->read(tableId, (*argv)[1].c_str(),
        (*argv)[1].length(), &buffer);
  } catch (RAMCloud::ObjectDoesntExistException& e) {
    listExists = false;
  }

  // Append new element to list.
  size_t newListSize;
  uint16_t elementLength = (uint16_t)(*argv)[2].length();
  if (listExists) {
    newListSize = sizeof(uint16_t) + elementLength + buffer.size();
  } else {
    newListSize = sizeof(uint16_t) + elementLength;
  }

  char* newList = (char*)malloc(newListSize);
  memcpy(newList, &elementLength, sizeof(uint16_t));
  memcpy(newList + sizeof(uint16_t), (*argv)[2].c_str(), elementLength);

  if (listExists) {
    const char* oldList = static_cast<const char*>(buffer.getRange(0,
            buffer.size()));
    memcpy(newList + sizeof(uint16_t) + elementLength, oldList, buffer.size());
  }

  // Write new list.
  client->write(tableId,
      (*argv)[1].c_str(),
      (*argv)[1].length(),
      newList,
      newListSize);

  // Count number of elements in the new list.
  uint32_t pos = 0;
  uint32_t count = 0;
  while (pos < newListSize) {
    count++;
    uint16_t len = *(uint16_t*)(newList + pos);
    pos += sizeof(uint16_t) + len;
  }

  free(newList);

  std::ostringstream oss;
  oss << ":" << count << "\r\n";

  return oss.str();
}

std::string rpushCommand(RAMCloud::RamCloud *client,
    uint64_t tableId,
    std::vector<std::string> *argv) {

  // Arg validation.
  if ((*argv)[2].length() >= (1 << (sizeof(uint16_t)*8))) {
    std::string res("+List element must be less than 64KB in size.\r\n");
    return res;
  }

  // Read out old list, if it exists.
  RAMCloud::Buffer buffer;
  bool listExists = true;
  try {
    client->read(tableId, (*argv)[1].c_str(),
        (*argv)[1].length(), &buffer);
  } catch (RAMCloud::ObjectDoesntExistException& e) {
    listExists = false;
  }

  // Append new element to list.
  size_t newListSize;
  uint16_t elementLength = (uint16_t)(*argv)[2].length();
  char* newList;
  if (listExists) {
    newListSize = sizeof(uint16_t) + elementLength + buffer.size();
    newList = (char*)malloc(newListSize);
    const char* oldList = static_cast<const char*>(buffer.getRange(0,
            buffer.size()));
    memcpy(newList, oldList, buffer.size());
    memcpy(newList + buffer.size(), &elementLength, sizeof(uint16_t));
    memcpy(newList + buffer.size() + sizeof(uint16_t), (*argv)[2].c_str(),
        elementLength);
  } else {
    newListSize = sizeof(uint16_t) + elementLength;
    newList = (char*)malloc(newListSize);
    memcpy(newList, &elementLength, sizeof(uint16_t));
    memcpy(newList + sizeof(uint16_t), (*argv)[2].c_str(), elementLength);
  }

  // Write new list.
  client->write(tableId,
      (*argv)[1].c_str(),
      (*argv)[1].length(),
      newList,
      newListSize);

  // Count number of elements in the new list.
  uint32_t pos = 0;
  uint32_t count = 0;
  printf("newListSize: %d\n", newListSize);
  while (pos < newListSize) {
    count++;
    uint16_t len = *(uint16_t*)(newList + pos);
    pos += sizeof(uint16_t) + len;
  }

  free(newList);

  std::ostringstream oss;
  oss << ":" << count << "\r\n";

  return oss.str();
}

std::string lpopCommand(RAMCloud::RamCloud *client,
    uint64_t tableId,
    std::vector<std::string> *argv) {

  // Read out list.
  RAMCloud::Buffer buffer;
  try {
    client->read(tableId, (*argv)[1].c_str(),
        (*argv)[1].length(), &buffer);
  } catch (RAMCloud::ObjectDoesntExistException& e) {
    return std::string("+Unknown key.");
  }

  if (buffer.size() == 0) {
    return std::string("$-1\r\n");
  }

  const char* list = static_cast<const char*>(buffer.getRange(0,
        buffer.size()));
  uint16_t len = *(uint16_t*)(list);
  std::string element(list + sizeof(uint16_t), len);

  size_t newListSize = buffer.size() - sizeof(uint16_t) - len;
  char* newList = (char*)malloc(newListSize);
  memcpy(newList, list + sizeof(uint16_t) + len, newListSize);

  // Write new list.
  client->write(tableId,
      (*argv)[1].c_str(),
      (*argv)[1].length(),
      newList,
      newListSize);

  free(newList);

  std::ostringstream oss;
  oss << "+" << element << "\r\n";

  return oss.str();
}

std::string rpopCommand(RAMCloud::RamCloud *client,
    uint64_t tableId,
    std::vector<std::string> *argv) {

  // Read out list.
  RAMCloud::Buffer buffer;
  try {
    client->read(tableId, (*argv)[1].c_str(),
        (*argv)[1].length(), &buffer);
  } catch (RAMCloud::ObjectDoesntExistException& e) {
    return std::string("+Unknown key.");
  }

  if (buffer.size() == 0) {
    return std::string("$-1\r\n");
  }

  const char* list = static_cast<const char*>(buffer.getRange(0,
        buffer.size()));

  // Find last element of the list.
  uint32_t pos = 0;
  uint16_t len;
  while (true) {
    len = *(uint16_t*)(list + pos);
    if (pos + sizeof(uint16_t) + len == buffer.size()) {
      break;
    }
    pos += sizeof(uint16_t) + len;
  }

  std::string element(list + pos + sizeof(uint16_t), len);

  size_t newListSize = buffer.size() - sizeof(uint16_t) - len;
  char* newList = (char*)malloc(newListSize);
  memcpy(newList, list, newListSize);

  // Write new list.
  client->write(tableId,
      (*argv)[1].c_str(),
      (*argv)[1].length(),
      newList,
      newListSize);

  free(newList);

  std::ostringstream oss;
  oss << "+" << element << "\r\n";

  return oss.str();
}

std::string lrangeCommand(RAMCloud::RamCloud *client,
    uint64_t tableId,
    std::vector<std::string> *argv) {

  int start = atoi((*argv)[2].c_str());
  int end = atoi((*argv)[3].c_str());

  // Read out old list, if it exists.
  RAMCloud::Buffer buffer;
  try {
    client->read(tableId, (*argv)[1].c_str(),
        (*argv)[1].length(), &buffer);
  } catch (RAMCloud::ObjectDoesntExistException& e) {
    std::string res("+Unknown key.\r\n");
    return res;
  }

  const char* list = static_cast<const char*>(buffer.getRange(0,
        buffer.size()));

  // Parse the elements.
  uint32_t pos = 0;
  std::vector<std::string> elements;
  while (pos < buffer.size()) {
    uint16_t len = *(uint16_t*)(list + pos);
    pos += sizeof(uint16_t);
    elements.emplace_back(list + pos, len);
    pos += len;
  }

  uint32_t startIndex;
  if (start < 0) {
    startIndex = elements.size() + start;
  } else {
    startIndex = start;
  }

  uint32_t endIndex;
  if (end < 0) {
    endIndex = elements.size() + end;
  } else {
    if (end >= elements.size()) {
      endIndex = elements.size() - 1;
    }
  }

  // Generate return message.
  std::ostringstream oss;
  oss << "*" << (endIndex - startIndex + 1) << "\r\n";

  uint32_t count = 0;
  for(auto const& e: elements) {
    if (count >= start && count <= end) {
      oss << "$" << e.length() << "\r\n" << e << "\r\n";
    }
    count++;
  }

  return oss.str();
}

<|endoftext|>


<commit_before>/*-------------------------------------------------------------------------
 *
 *   FILE
 *	connection.cxx
 *
 *   DESCRIPTION
 *      implementation of the pqxx::connection and sibling classes.
 *   Different ways of setting up a backend connection.
 *
 * Copyright (c) 2001-2004, Jeroen T. Vermeulen <jtv@xs4all.nl>
 *
 * See COPYING for copyright license.  If you did not receive a file called
 * COPYING with this source code, please notify the distributor of this mistake,
 * or contact the author.
 *
 *-------------------------------------------------------------------------
 */
#include "pqxx/compiler.h"

#include <stdexcept>

#include "libpq-fe.h"

#include "pqxx/connection"

using namespace PGSTD;

pqxx::connection::connection() :
  connection_base(0)
{
  do_startconnect();
}

pqxx::connection::connection(const string &ConnInfo) :
  connection_base(ConnInfo)
{
  do_startconnect();
}

pqxx::connection::connection(const char ConnInfo[]) :
  connection_base(ConnInfo)
{
  do_startconnect();
}

void pqxx::connection::do_startconnect()
{
  if (!get_conn()) set_conn(PQconnectdb(options()));
}

void pqxx::lazyconnection::completeconnect()
{
  if (!get_conn()) set_conn(PQconnectdb(options()));
}

pqxx::asyncconnection::asyncconnection() :
  connection_base(0),
  m_connecting(false)
{
  do_startconnect();
}

pqxx::asyncconnection::asyncconnection(const string &ConnInfo) :
  connection_base(ConnInfo),
  m_connecting(false)
{
  do_startconnect();
}

pqxx::asyncconnection::asyncconnection(const char ConnInfo[]) :
  connection_base(ConnInfo),
  m_connecting(false)
{
  do_startconnect();
}

void pqxx::asyncconnection::do_startconnect()
{
  if (get_conn()) return;	// Already connecting or connected
  m_connecting = false;
  set_conn(PQconnectStart(options()));
  if (!get_conn()) throw bad_alloc();
  if (PQconnectPoll(get_conn()) == PGRES_POLLING_FAILED)
    throw broken_connection();
  m_connecting = true;
}

void pqxx::asyncconnection::completeconnect()
{
  if (!get_conn()) startconnect();
  if (!m_connecting) return;

  // Our "attempt to connect" state ends here, for better or for worse
  m_connecting = false;

  if (!get_conn()) throw broken_connection();

  PostgresPollingStatusType pollstatus;

  do
  {
    pollstatus = PQconnectPoll(get_conn());
    switch (pollstatus)
    {
    case PGRES_POLLING_FAILED:
      throw broken_connection();

    case PGRES_POLLING_READING:
      wait_read();
      break;

    case PGRES_POLLING_WRITING:
      wait_write();
      break;

    case PGRES_POLLING_ACTIVE:
    case PGRES_POLLING_OK:
      break;
    }
  } while (pollstatus != PGRES_POLLING_OK);
}

pqxx::nullconnection::~nullconnection() throw ()
{
}

// Conflicting workarounds for Windows and SUN CC 5.1; see header
#ifndef _WIN32
pqxx::connection::~connection() throw () { close(); }
pqxx::lazyconnection::~lazyconnection() throw () { close(); }
pqxx::asyncconnection::~asyncconnection() throw () {do_dropconnect(); close();}
#endif	// _WIN32

<commit_msg>Corrected copyright message<commit_after>/*-------------------------------------------------------------------------
 *
 *   FILE
 *	connection.cxx
 *
 *   DESCRIPTION
 *      implementation of the pqxx::connection and sibling classes.
 *   Different ways of setting up a backend connection.
 *
 * Copyright (c) 2001-2005, Jeroen T. Vermeulen <jtv@xs4all.nl>
 *
 * See COPYING for copyright license.  If you did not receive a file called
 * COPYING with this source code, please notify the distributor of this mistake,
 * or contact the author.
 *
 *-------------------------------------------------------------------------
 */
#include "pqxx/compiler.h"

#include <stdexcept>

#include "libpq-fe.h"

#include "pqxx/connection"

using namespace PGSTD;

pqxx::connection::connection() :
  connection_base(0)
{
  do_startconnect();
}

pqxx::connection::connection(const string &ConnInfo) :
  connection_base(ConnInfo)
{
  do_startconnect();
}

pqxx::connection::connection(const char ConnInfo[]) :
  connection_base(ConnInfo)
{
  do_startconnect();
}

void pqxx::connection::do_startconnect()
{
  if (!get_conn()) set_conn(PQconnectdb(options()));
}

void pqxx::lazyconnection::completeconnect()
{
  if (!get_conn()) set_conn(PQconnectdb(options()));
}

pqxx::asyncconnection::asyncconnection() :
  connection_base(0),
  m_connecting(false)
{
  do_startconnect();
}

pqxx::asyncconnection::asyncconnection(const string &ConnInfo) :
  connection_base(ConnInfo),
  m_connecting(false)
{
  do_startconnect();
}

pqxx::asyncconnection::asyncconnection(const char ConnInfo[]) :
  connection_base(ConnInfo),
  m_connecting(false)
{
  do_startconnect();
}

void pqxx::asyncconnection::do_startconnect()
{
  if (get_conn()) return;	// Already connecting or connected
  m_connecting = false;
  set_conn(PQconnectStart(options()));
  if (!get_conn()) throw bad_alloc();
  if (PQconnectPoll(get_conn()) == PGRES_POLLING_FAILED)
    throw broken_connection();
  m_connecting = true;
}

void pqxx::asyncconnection::completeconnect()
{
  if (!get_conn()) startconnect();
  if (!m_connecting) return;

  // Our "attempt to connect" state ends here, for better or for worse
  m_connecting = false;

  if (!get_conn()) throw broken_connection();

  PostgresPollingStatusType pollstatus;

  do
  {
    pollstatus = PQconnectPoll(get_conn());
    switch (pollstatus)
    {
    case PGRES_POLLING_FAILED:
      throw broken_connection();

    case PGRES_POLLING_READING:
      wait_read();
      break;

    case PGRES_POLLING_WRITING:
      wait_write();
      break;

    case PGRES_POLLING_ACTIVE:
    case PGRES_POLLING_OK:
      break;
    }
  } while (pollstatus != PGRES_POLLING_OK);
}

pqxx::nullconnection::~nullconnection() throw ()
{
}

// Conflicting workarounds for Windows and SUN CC 5.1; see header
#ifndef _WIN32
pqxx::connection::~connection() throw () { close(); }
pqxx::lazyconnection::~lazyconnection() throw () { close(); }
pqxx::asyncconnection::~asyncconnection() throw () {do_dropconnect(); close();}
#endif	// _WIN32

<|endoftext|>


<commit_before>/*
 * Copyright(c) Sophist Solutions, Inc. 1990-2014.  All rights reserved
 */
#include    "../StroikaPreComp.h"

#include    <cstdlib>
#include    <cstring>
#include    <ctime>

#if     qPlatform_POXIX
#include    <time.h>
#endif

#include    "../Configuration/Common.h"
#include    "../Characters/String.h"
#include    "../Debug/Assertions.h"
#include    "DateTime.h"

#include    "Timezone.h"

using   namespace   Stroika;
using   namespace   Stroika::Foundation;
using   namespace   Stroika::Foundation::Time;

/*
 ********************************************************************************
 ********************************* Time::GetTimezone ****************************
 ********************************************************************************
 */
String    Time::GetTimezone ()
{
#if     qPlatform_Windows
    TIME_ZONE_INFORMATION   tzInfo;
    memset (&tzInfo, 0, sizeof (tzInfo));
    (void)::GetTimeZoneInformation (&tzInfo);
    return String::FromSDKString (tzInfo.StandardName);
#elif   qPlatform_POXIX
    // @see http://pubs.opengroup.org/onlinepubs/7908799/xsh/tzset.html
    return String::FromSDKString (IsDaylightSavingsTime () ? tzname[1] : tzname[0]);
#else
    AssertNotImplemented ();
    return String ();
#endif
}

/*
 ********************************************************************************
 *********************** Time::IsDaylightSavingsTime ****************************
 ********************************************************************************
 */
bool    Time::IsDaylightSavingsTime ()
{
    static  bool    sCalledOnce_ = false;
    if (not sCalledOnce_) {
        DISABLE_COMPILER_MSC_WARNING_START(4996)// MSVC warns tzset() unsafe, but I think the way I use it will be safe
        tzset ();
        DISABLE_COMPILER_MSC_WARNING_END(4996)
        sCalledOnce_ = true;
    }
    DISABLE_COMPILER_MSC_WARNING_START(4996)// MSVC warns tzset() unsafe, but I think the way I use it will be safe
    return !!daylight;
    DISABLE_COMPILER_MSC_WARNING_END(4996)
}

bool    Time::IsDaylightSavingsTime (const DateTime& d)
{
    struct  tm  asTM    =   d.As<struct tm> ();
    asTM.tm_isdst = -1; // force calc of correct daylight savings time flag
    // THINK this is true - not totally clear - docs on mktime () don't specify unambiguously that this should work...
    // So far it seems too however, --LGP 2011-10-15
    time_t  result  =   mktime (&asTM);
    return asTM.tm_isdst >= 1;
}

/*
 ********************************************************************************
 ********************* Time::GetLocaltimeToGMTOffset ****************************
 ********************************************************************************
 */
time_t  Time::GetLocaltimeToGMTOffset (bool applyDST)
{
#if     0
    // WRONG - but COULD use this API - but not sure needed
#if     qPlatform_Windows
    TIME_ZONE_INFORMATION   tzInfo;
    memset (&tzInfo, 0, sizeof (tzInfo));
    (void)::GetTimeZoneInformation (&tzInfo);
    int unsignedBias    =   abs (tzInfo.Bias);
    int hrs =   unsignedBias / 60;
    int mins = unsignedBias - hrs * 60;
    tzBiasString = ::Format (L"%s%.2d:%.2d", (tzInfo.Bias >= 0 ? L"-" : L"+"), hrs, mins);
#endif
#endif

    /*
     * COULD this be cached? It SHOULD be - but what about when the timezone changes? there maybe a better way to compute this using the
     * timezone global var???
     */
    struct tm tm;
    memset (&tm, 0, sizeof(tm));
    tm.tm_year = 70;
    tm.tm_mon = 0;      // Jan
    tm.tm_mday = 1;
    tm.tm_isdst = applyDST;
    time_t  result  =   mktime (&tm);
    return result;
}
<commit_msg>fixed typo<commit_after>/*
 * Copyright(c) Sophist Solutions, Inc. 1990-2014.  All rights reserved
 */
#include    "../StroikaPreComp.h"

#include    <cstdlib>
#include    <cstring>
#include    <ctime>

#if     qPlatform_POSIX
#include    <time.h>
#endif

#include    "../Configuration/Common.h"
#include    "../Characters/String.h"
#include    "../Debug/Assertions.h"
#include    "DateTime.h"

#include    "Timezone.h"

using   namespace   Stroika;
using   namespace   Stroika::Foundation;
using   namespace   Stroika::Foundation::Time;

/*
 ********************************************************************************
 ********************************* Time::GetTimezone ****************************
 ********************************************************************************
 */
String    Time::GetTimezone ()
{
#if     qPlatform_Windows
    TIME_ZONE_INFORMATION   tzInfo;
    memset (&tzInfo, 0, sizeof (tzInfo));
    (void)::GetTimeZoneInformation (&tzInfo);
    return String::FromSDKString (tzInfo.StandardName);
#elif   qPlatform_POSIX
    // @see http://pubs.opengroup.org/onlinepubs/7908799/xsh/tzset.html
    return String::FromSDKString (IsDaylightSavingsTime () ? tzname[1] : tzname[0]);
#else
    AssertNotImplemented ();
    return String ();
#endif
}

/*
 ********************************************************************************
 *********************** Time::IsDaylightSavingsTime ****************************
 ********************************************************************************
 */
bool    Time::IsDaylightSavingsTime ()
{
    static  bool    sCalledOnce_ = false;
    if (not sCalledOnce_) {
        DISABLE_COMPILER_MSC_WARNING_START(4996)// MSVC warns tzset() unsafe, but I think the way I use it will be safe
        tzset ();
        DISABLE_COMPILER_MSC_WARNING_END(4996)
        sCalledOnce_ = true;
    }
    DISABLE_COMPILER_MSC_WARNING_START(4996)// MSVC warns tzset() unsafe, but I think the way I use it will be safe
    return !!daylight;
    DISABLE_COMPILER_MSC_WARNING_END(4996)
}

bool    Time::IsDaylightSavingsTime (const DateTime& d)
{
    struct  tm  asTM    =   d.As<struct tm> ();
    asTM.tm_isdst = -1; // force calc of correct daylight savings time flag
    // THINK this is true - not totally clear - docs on mktime () don't specify unambiguously that this should work...
    // So far it seems too however, --LGP 2011-10-15
    time_t  result  =   mktime (&asTM);
    return asTM.tm_isdst >= 1;
}

/*
 ********************************************************************************
 ********************* Time::GetLocaltimeToGMTOffset ****************************
 ********************************************************************************
 */
time_t  Time::GetLocaltimeToGMTOffset (bool applyDST)
{
#if     0
    // WRONG - but COULD use this API - but not sure needed
#if     qPlatform_Windows
    TIME_ZONE_INFORMATION   tzInfo;
    memset (&tzInfo, 0, sizeof (tzInfo));
    (void)::GetTimeZoneInformation (&tzInfo);
    int unsignedBias    =   abs (tzInfo.Bias);
    int hrs =   unsignedBias / 60;
    int mins = unsignedBias - hrs * 60;
    tzBiasString = ::Format (L"%s%.2d:%.2d", (tzInfo.Bias >= 0 ? L"-" : L"+"), hrs, mins);
#endif
#endif

    /*
     * COULD this be cached? It SHOULD be - but what about when the timezone changes? there maybe a better way to compute this using the
     * timezone global var???
     */
    struct tm tm;
    memset (&tm, 0, sizeof(tm));
    tm.tm_year = 70;
    tm.tm_mon = 0;      // Jan
    tm.tm_mday = 1;
    tm.tm_isdst = applyDST;
    time_t  result  =   mktime (&tm);
    return result;
}
<|endoftext|>


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

The Medical Imaging Interaction Toolkit (MITK)

Copyright (c) German Cancer Research Center,
Division of Medical and Biological Informatics.
All rights reserved.

This software is distributed WITHOUT ANY WARRANTY; without
even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE.

See LICENSE.txt or http://www.mitk.org for details.

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

#include "QmitkPythonVariableStackTableView.h"
#include <usModuleContext.h>
#include <usServiceReference.h>
#include <usGetModuleContext.h>
#include <mitkRenderingManager.h>
#include <mitkSurface.h>

QmitkPythonVariableStackTableView::QmitkPythonVariableStackTableView(QWidget *parent)
    :QTableView(parent)
{
    m_TableModel = new QmitkPythonVariableStackTableModel(parent);
    m_TableModel->CommandExecuted("");

    this->setSelectionBehavior( QAbstractItemView::SelectRows );
    this->setAlternatingRowColors(true);
    this->setDropIndicatorShown(true);
    this->setAcceptDrops(true);
    this->setModel( m_TableModel );

    us::ModuleContext* context = us::GetModuleContext();
    us::ServiceReference<mitk::IPythonService> serviceRef = context->GetServiceReference<mitk::IPythonService>();
    m_PythonService = context->GetService<mitk::IPythonService>(serviceRef);

    connect( this, SIGNAL(doubleClicked ( const QModelIndex& )), this, SLOT( OnVariableStackDoubleClicked(const QModelIndex&) ) );
}

QmitkPythonVariableStackTableView::~QmitkPythonVariableStackTableView()
{
}

void QmitkPythonVariableStackTableView::SetDataStorage(mitk::DataStorage *_DataStorage)
{
    m_DataStorage = _DataStorage;
}

void QmitkPythonVariableStackTableView::OnVariableStackDoubleClicked(const QModelIndex &index)
{
    if( m_DataStorage.IsNull() || m_PythonService == 0 )
    {
        MITK_ERROR << "QmitkPythonVariableStackTableView not configured correctly. Quit";
        return;
    }

    int row = index.row();
    std::vector<mitk::PythonVariable> variableStack = m_TableModel->GetVariableStack();
    {
      MITK_DEBUG("QmitkPythonVariableStackTableView") << "row " << row;
      MITK_DEBUG("QmitkPythonVariableStackTableView") << "variableStack.size(): " << variableStack.size();
    }

    QString varName = QString::fromStdString( variableStack.at(row).m_Name );
    QString type = QString::fromStdString( variableStack.at(row).m_Type );
    QString value = QString::fromStdString( variableStack.at(row).m_Value );

    {
      MITK_DEBUG("QmitkPythonVariableStackTableView") << "varName: " << varName.toStdString();
      MITK_DEBUG("QmitkPythonVariableStackTableView") << "type: " << type.toStdString();
    }

    mitk::Image::Pointer mitkImage;
    mitk::Surface::Pointer mitkSurface;

    if( type.startsWith("itkImage") )
    {
      mitkImage = m_PythonService->CopyItkImageFromPython(varName.toStdString());
    }
    else if( type.startsWith("numpy.ndarray") )
    {
      mitkImage = m_PythonService->CopyCvImageFromPython(varName.toStdString());
    }
    else if( value.startsWith("(vtkPolyData)") )
    {
      mitkSurface = m_PythonService->CopyVtkPolyDataFromPython(varName.toStdString());
    }

    std::string nodeName = varName.toStdString();
    mitk::DataNode::Pointer node = mitk::DataNode::New();
    node->SetName ( nodeName );

    if( mitkImage.IsNotNull() )
    {
      node->SetData( mitkImage );
    }
    else if( mitkSurface.IsNotNull() )
    {
      node->SetData( mitkSurface );
    }

    m_DataStorage->Add(node);
    mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
<commit_msg>replacing data in nodes when node is already present, init view based on geometry on new objects<commit_after>/*===================================================================

The Medical Imaging Interaction Toolkit (MITK)

Copyright (c) German Cancer Research Center,
Division of Medical and Biological Informatics.
All rights reserved.

This software is distributed WITHOUT ANY WARRANTY; without
even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE.

See LICENSE.txt or http://www.mitk.org for details.

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

#include "QmitkPythonVariableStackTableView.h"
#include <usModuleContext.h>
#include <usServiceReference.h>
#include <usGetModuleContext.h>
#include <mitkRenderingManager.h>
#include <mitkSurface.h>
#include <vtkPolyData.h>

QmitkPythonVariableStackTableView::QmitkPythonVariableStackTableView(QWidget *parent)
    :QTableView(parent)
{
    m_TableModel = new QmitkPythonVariableStackTableModel(parent);
    m_TableModel->CommandExecuted("");

    this->setSelectionBehavior( QAbstractItemView::SelectRows );
    this->setAlternatingRowColors(true);
    this->setDropIndicatorShown(true);
    this->setAcceptDrops(true);
    this->setModel( m_TableModel );

    us::ModuleContext* context = us::GetModuleContext();
    us::ServiceReference<mitk::IPythonService> serviceRef = context->GetServiceReference<mitk::IPythonService>();
    m_PythonService = context->GetService<mitk::IPythonService>(serviceRef);

    connect( this, SIGNAL(doubleClicked ( const QModelIndex& )), this, SLOT( OnVariableStackDoubleClicked(const QModelIndex&) ) );
}

QmitkPythonVariableStackTableView::~QmitkPythonVariableStackTableView()
{
}

void QmitkPythonVariableStackTableView::SetDataStorage(mitk::DataStorage *_DataStorage)
{
    m_DataStorage = _DataStorage;
}

void QmitkPythonVariableStackTableView::OnVariableStackDoubleClicked(const QModelIndex &index)
{
    if( m_DataStorage.IsNull() || m_PythonService == 0 )
    {
        MITK_ERROR << "QmitkPythonVariableStackTableView not configured correctly. Quit";
        return;
    }

    int row = index.row();
    std::vector<mitk::PythonVariable> variableStack = m_TableModel->GetVariableStack();
    {
      MITK_DEBUG("QmitkPythonVariableStackTableView") << "row " << row;
      MITK_DEBUG("QmitkPythonVariableStackTableView") << "variableStack.size(): " << variableStack.size();
    }

    QString varName = QString::fromStdString( variableStack.at(row).m_Name );
    QString type = QString::fromStdString( variableStack.at(row).m_Type );
    QString value = QString::fromStdString( variableStack.at(row).m_Value );

    {
      MITK_DEBUG("QmitkPythonVariableStackTableView") << "varName: " << varName.toStdString();
      MITK_DEBUG("QmitkPythonVariableStackTableView") << "type: " << type.toStdString();
    }

    mitk::Image::Pointer mitkImage;
    mitk::Surface::Pointer mitkSurface;

    if( type.startsWith("itkImage") )
    {
      mitkImage = m_PythonService->CopyItkImageFromPython(varName.toStdString());
    }
    else if( type.startsWith("numpy.ndarray") )
    {
      mitkImage = m_PythonService->CopyCvImageFromPython(varName.toStdString());
    }
    else if( value.startsWith("(vtkPolyData)") )
    {
      mitkSurface = m_PythonService->CopyVtkPolyDataFromPython(varName.toStdString());
    }

    std::string nodeName = varName.toStdString();
    mitk::DataNode::Pointer node = m_DataStorage->GetNamedNode(nodeName);

    // only create data node if it does not exist
    if ( node.IsNull() )
    {
      node = mitk::DataNode::New();
      node->SetName ( nodeName );
      m_DataStorage->Add(node);
    }

    if( mitkImage.IsNotNull() )
    {
      node->SetData( mitkImage );
    }
    else if( mitkSurface.IsNotNull() )
    {
      node->SetData( mitkSurface );
      // init renderwindow geometry
      mitk::RenderingManager::GetInstance()->InitializeViews(mitkSurface->GetGeometry());
    }

    mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
<|endoftext|>


<commit_before>#include "ParticleSystem.h"
#include "Helper.h"

#include <DirectXColors.h>

using DirectX::Colors::Black;

ParticleSystem::ParticleSystem(ComPtr<ID3D11Device> device, ComPtr<ID3D11DeviceContext> deviceContext, const ParticleSettings& settings)
	: first_active_particle(0), first_free_particle(0), first_new_particle(0), first_retired_particle(0), current_time(0.0f),
	startIndex(0), length(0), timeLeftOver(0.0f), settings(settings)
{
	// each particle system needs it own particle shader because we rely on
	// constant shader values, and we can't stomp over another particle system's
	// cbuffer space (alternative is to re-write these values per frame, instead of per
	// lifetime of the system).

	particle_shader.reset(new ParticleShader(device, settings));

	texture = std::make_shared<Texture>(device, deviceContext, settings.texture_name);
	Initialize();
	LoadContent(device);
}

void ParticleSystem::Update(const Matrix& viewMatrix, const Matrix& projectionMatrix, float dt)
{
	current_time += dt;

	float timeBetweenParticles = 1.0f / settings.particles_per_second;

	if (dt > 0)
	{
		float timeToSpend = timeLeftOver + dt;

		float currentTime = -timeLeftOver;

		while (timeToSpend > timeBetweenParticles)
		{
			currentTime += timeBetweenParticles;
			timeToSpend -= timeBetweenParticles;

			LOG_INFO("Adding particle...");

			Vector3 pos = Vector3(
				RandomFloat(settings.min_position.x, settings.max_position.x),
				RandomFloat(settings.min_position.y, settings.max_position.y),
				RandomFloat(settings.min_position.z, settings.max_position.z));
			AddParticle(pos);
		}

		timeLeftOver = timeToSpend;
	}

	RetireActiveParticles();
	FreeRetiredParticles();

	if (first_active_particle == first_free_particle)
		current_time = 0.0f;

	if (first_retired_particle == first_active_particle)
		draw_counter = 0.0f;

	particle_shader->Update(Matrix::Identity, viewMatrix, projectionMatrix);
}

void ParticleSystem::Draw(ComPtr<ID3D11Device> device, ComPtr<ID3D11DeviceContext> deviceContext)
{
	if (first_new_particle != first_free_particle)
	{
		AddNewParticlesToVertexBuffer(deviceContext);
	}

	if (first_active_particle != first_free_particle)
	{
		if (settings.blend_state == BLEND_STATE::Alpha)
		{
			deviceContext->OMSetBlendState(StatesHelper::GetInstance().GetStates()->NonPremultiplied(), Black, 0xFFFFFFFF);
		}
		else if (settings.blend_state == BLEND_STATE::Additive)
		{
			deviceContext->OMSetBlendState(StatesHelper::GetInstance().GetStates()->Additive(), Black, 0xFFFFFFFF);
		}

		deviceContext->OMSetDepthStencilState(StatesHelper::GetInstance().GetStates()->DepthRead(), 0);

		unsigned int stride = sizeof(ParticleVertex);
		unsigned int offset = 0;

		deviceContext->IASetVertexBuffers(0, 1, vertex_buffer->GetVertexBuffer().GetAddressOf(), &stride, &offset);
		deviceContext->IASetIndexBuffer(this->vertex_buffer->GetIndexBuffer().Get() , DXGI_FORMAT_R32_UINT, 0);
		deviceContext->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY::D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);

		if (first_active_particle < first_free_particle)
		{
			particle_shader.get()->Draw(deviceContext, (first_free_particle - first_active_particle) * 6,
				first_active_particle * 6, 0, texture.get(), Vector2::Zero, current_time);
		}
		else
		{
			particle_shader.get()->Draw(deviceContext, (settings.max_particles - first_active_particle) * 6,
				first_active_particle * 6, 0, texture.get(), Vector2::Zero, current_time);

			if (first_free_particle > 0)
			{
				particle_shader.get()->Draw(deviceContext, first_free_particle * 6, 0, 0, texture.get(),
					Vector2::Zero, current_time, false);
			}
		}
	}

	draw_counter++;
}

void ParticleSystem::Initialize()
{
	particles = shared_ptr<ParticleVertex>(new ParticleVertex[settings.max_particles * 4]);
	auto p_particles = particles.get();

	// make quads
	for (int i = 0; i < settings.max_particles; ++i)
	{
		p_particles[i * 4 + 0].Corner = Vector2(-1.0f, -1.0f); // bottom left
		p_particles[i * 4 + 1].Corner = Vector2(1.0f, -1.0f);  // bottom right
		p_particles[i * 4 + 2].Corner = Vector2(1.0f, 1.0f);   // top right
		p_particles[i * 4 + 3].Corner = Vector2(-1.0f, 1.0f);  // top left
	}
}

void ParticleSystem::LoadContent(ComPtr<ID3D11Device> device)
{
	LoadParticleEffect();

	vector<unsigned long> indices;

	for (int i = 0; i < settings.max_particles; ++i)
	{
		indices.push_back(i * 4 + 0);
		indices.push_back(i * 4 + 2);
		indices.push_back(i * 4 + 1);

		indices.push_back(i * 4 + 0);
		indices.push_back(i * 4 + 3);
		indices.push_back(i * 4 + 2);
	}

	// create a dynamic vertex buffer
	vertex_buffer = VertexBuffer::CreateDynamic(device, sizeof(ParticleVertex),
		settings.max_particles * 4, indices, indices.size());
}

void ParticleSystem::LoadParticleEffect()
{
}

void ParticleSystem::RetireActiveParticles()
{
	float particle_duration = settings.duration;

	while (first_active_particle != first_new_particle)
	{
		float particle_age = current_time - particles.get()[first_active_particle * 4].Time;

		if (particle_age < particle_duration)
			break;

		particles.get()[first_active_particle * 4].Time = draw_counter;

		first_active_particle++;

		if (first_active_particle >= settings.max_particles)
			first_active_particle = 0;
	}
}

void ParticleSystem::FreeRetiredParticles()
{
	while (first_retired_particle != first_active_particle)
	{
		int age = draw_counter - (int)particles.get()[first_retired_particle * 4].Time;

		if (age < 3)
			break;

		first_retired_particle++;

		if (first_retired_particle >= settings.max_particles)
			first_retired_particle = 0;
	}
}

void ParticleSystem::AddNewParticlesToVertexBuffer(ComPtr<ID3D11DeviceContext> deviceContext)
{
	int stride = ParticleVertex::GetSize();

	if (first_new_particle < first_free_particle)
	{
		// all new particles are in one consecutive range
		// can upload with a single write
		vertex_buffer.get()->SetData<ParticleVertex>(deviceContext, particles.get(),
			first_new_particle * 4, (first_free_particle - first_new_particle) * 4);
	}
	else
	{
		// our new particle range wraps past the end of the array, need to do 2 writes
		vertex_buffer.get()->SetData<ParticleVertex>(deviceContext, particles.get(),
			first_new_particle * 4, (settings.max_particles - first_new_particle) * 4);

		if (first_free_particle > 0)
		{
			vertex_buffer.get()->SetData<ParticleVertex>(deviceContext, particles.get(),
				0, first_free_particle * 4);
		}
	}

	first_new_particle = first_free_particle;
}

void ParticleSystem::AddParticle(Vector3 position)
{
	int next_free_particle = first_free_particle + 1;

	if (next_free_particle >= settings.max_particles)
		next_free_particle = 0;

	if (next_free_particle == first_retired_particle)
		return;

	Vector3 velocity = Vector3
	(
		RandomFloat(settings.min_velocity.x, settings.max_velocity.x),
		RandomFloat(settings.min_velocity.y, settings.max_velocity.y),
		RandomFloat(settings.min_velocity.z, settings.max_velocity.z)
	);

	Color random = Color(RandomFloat(0.0f, 1.0f), RandomFloat(0.0f, 1.0f),
		RandomFloat(0.0f, 1.0f), RandomFloat(0.0f, 1.0f));

	for (int i = 0; i < 4; i++)
	{
		particles.get()[first_free_particle * 4 + i].Position = position;
		particles.get()[first_free_particle * 4 + i].Velocity = velocity;
		particles.get()[first_free_particle * 4 + i].Random = random;
		particles.get()[first_free_particle * 4 + i].Time = current_time;
	}

	first_free_particle = next_free_particle;
}
<commit_msg>Remote LOG_INFO from Update<commit_after>#include "ParticleSystem.h"
#include "Helper.h"

#include <DirectXColors.h>

using DirectX::Colors::Black;

ParticleSystem::ParticleSystem(ComPtr<ID3D11Device> device, ComPtr<ID3D11DeviceContext> deviceContext, const ParticleSettings& settings)
	: first_active_particle(0), first_free_particle(0), first_new_particle(0), first_retired_particle(0), current_time(0.0f),
	startIndex(0), length(0), timeLeftOver(0.0f), settings(settings)
{
	// each particle system needs it own particle shader because we rely on
	// constant shader values, and we can't stomp over another particle system's
	// cbuffer space (alternative is to re-write these values per frame, instead of per
	// lifetime of the system).

	particle_shader.reset(new ParticleShader(device, settings));

	texture = std::make_shared<Texture>(device, deviceContext, settings.texture_name);
	Initialize();
	LoadContent(device);
}

void ParticleSystem::Update(const Matrix& viewMatrix, const Matrix& projectionMatrix, float dt)
{
	current_time += dt;

	float timeBetweenParticles = 1.0f / settings.particles_per_second;

	if (dt > 0)
	{
		float timeToSpend = timeLeftOver + dt;

		float currentTime = -timeLeftOver;

		while (timeToSpend > timeBetweenParticles)
		{
			currentTime += timeBetweenParticles;
			timeToSpend -= timeBetweenParticles;

			Vector3 pos = Vector3(
				RandomFloat(settings.min_position.x, settings.max_position.x),
				RandomFloat(settings.min_position.y, settings.max_position.y),
				RandomFloat(settings.min_position.z, settings.max_position.z));
			AddParticle(pos);
		}

		timeLeftOver = timeToSpend;
	}

	RetireActiveParticles();
	FreeRetiredParticles();

	if (first_active_particle == first_free_particle)
		current_time = 0.0f;

	if (first_retired_particle == first_active_particle)
		draw_counter = 0.0f;

	particle_shader->Update(Matrix::Identity, viewMatrix, projectionMatrix);
}

void ParticleSystem::Draw(ComPtr<ID3D11Device> device, ComPtr<ID3D11DeviceContext> deviceContext)
{
	if (first_new_particle != first_free_particle)
	{
		AddNewParticlesToVertexBuffer(deviceContext);
	}

	if (first_active_particle != first_free_particle)
	{
		if (settings.blend_state == BLEND_STATE::Alpha)
		{
			deviceContext->OMSetBlendState(StatesHelper::GetInstance().GetStates()->NonPremultiplied(), Black, 0xFFFFFFFF);
		}
		else if (settings.blend_state == BLEND_STATE::Additive)
		{
			deviceContext->OMSetBlendState(StatesHelper::GetInstance().GetStates()->Additive(), Black, 0xFFFFFFFF);
		}

		deviceContext->OMSetDepthStencilState(StatesHelper::GetInstance().GetStates()->DepthRead(), 0);

		unsigned int stride = sizeof(ParticleVertex);
		unsigned int offset = 0;

		deviceContext->IASetVertexBuffers(0, 1, vertex_buffer->GetVertexBuffer().GetAddressOf(), &stride, &offset);
		deviceContext->IASetIndexBuffer(this->vertex_buffer->GetIndexBuffer().Get() , DXGI_FORMAT_R32_UINT, 0);
		deviceContext->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY::D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);

		if (first_active_particle < first_free_particle)
		{
			particle_shader.get()->Draw(deviceContext, (first_free_particle - first_active_particle) * 6,
				first_active_particle * 6, 0, texture.get(), Vector2::Zero, current_time);
		}
		else
		{
			particle_shader.get()->Draw(deviceContext, (settings.max_particles - first_active_particle) * 6,
				first_active_particle * 6, 0, texture.get(), Vector2::Zero, current_time);

			if (first_free_particle > 0)
			{
				particle_shader.get()->Draw(deviceContext, first_free_particle * 6, 0, 0, texture.get(),
					Vector2::Zero, current_time, false);
			}
		}
	}

	draw_counter++;
}

void ParticleSystem::Initialize()
{
	particles = shared_ptr<ParticleVertex>(new ParticleVertex[settings.max_particles * 4]);
	auto p_particles = particles.get();

	// make quads
	for (int i = 0; i < settings.max_particles; ++i)
	{
		p_particles[i * 4 + 0].Corner = Vector2(-1.0f, -1.0f); // bottom left
		p_particles[i * 4 + 1].Corner = Vector2(1.0f, -1.0f);  // bottom right
		p_particles[i * 4 + 2].Corner = Vector2(1.0f, 1.0f);   // top right
		p_particles[i * 4 + 3].Corner = Vector2(-1.0f, 1.0f);  // top left
	}
}

void ParticleSystem::LoadContent(ComPtr<ID3D11Device> device)
{
	LoadParticleEffect();

	vector<unsigned long> indices;

	for (int i = 0; i < settings.max_particles; ++i)
	{
		indices.push_back(i * 4 + 0);
		indices.push_back(i * 4 + 2);
		indices.push_back(i * 4 + 1);

		indices.push_back(i * 4 + 0);
		indices.push_back(i * 4 + 3);
		indices.push_back(i * 4 + 2);
	}

	// create a dynamic vertex buffer
	vertex_buffer = VertexBuffer::CreateDynamic(device, sizeof(ParticleVertex),
		settings.max_particles * 4, indices, indices.size());
}

void ParticleSystem::LoadParticleEffect()
{
}

void ParticleSystem::RetireActiveParticles()
{
	float particle_duration = settings.duration;

	while (first_active_particle != first_new_particle)
	{
		float particle_age = current_time - particles.get()[first_active_particle * 4].Time;

		if (particle_age < particle_duration)
			break;

		particles.get()[first_active_particle * 4].Time = draw_counter;

		first_active_particle++;

		if (first_active_particle >= settings.max_particles)
			first_active_particle = 0;
	}
}

void ParticleSystem::FreeRetiredParticles()
{
	while (first_retired_particle != first_active_particle)
	{
		int age = draw_counter - (int)particles.get()[first_retired_particle * 4].Time;

		if (age < 3)
			break;

		first_retired_particle++;

		if (first_retired_particle >= settings.max_particles)
			first_retired_particle = 0;
	}
}

void ParticleSystem::AddNewParticlesToVertexBuffer(ComPtr<ID3D11DeviceContext> deviceContext)
{
	int stride = ParticleVertex::GetSize();

	if (first_new_particle < first_free_particle)
	{
		// all new particles are in one consecutive range
		// can upload with a single write
		vertex_buffer.get()->SetData<ParticleVertex>(deviceContext, particles.get(),
			first_new_particle * 4, (first_free_particle - first_new_particle) * 4);
	}
	else
	{
		// our new particle range wraps past the end of the array, need to do 2 writes
		vertex_buffer.get()->SetData<ParticleVertex>(deviceContext, particles.get(),
			first_new_particle * 4, (settings.max_particles - first_new_particle) * 4);

		if (first_free_particle > 0)
		{
			vertex_buffer.get()->SetData<ParticleVertex>(deviceContext, particles.get(),
				0, first_free_particle * 4);
		}
	}

	first_new_particle = first_free_particle;
}

void ParticleSystem::AddParticle(Vector3 position)
{
	int next_free_particle = first_free_particle + 1;

	if (next_free_particle >= settings.max_particles)
		next_free_particle = 0;

	if (next_free_particle == first_retired_particle)
		return;

	Vector3 velocity = Vector3
	(
		RandomFloat(settings.min_velocity.x, settings.max_velocity.x),
		RandomFloat(settings.min_velocity.y, settings.max_velocity.y),
		RandomFloat(settings.min_velocity.z, settings.max_velocity.z)
	);

	Color random = Color(RandomFloat(0.0f, 1.0f), RandomFloat(0.0f, 1.0f),
		RandomFloat(0.0f, 1.0f), RandomFloat(0.0f, 1.0f));

	for (int i = 0; i < 4; i++)
	{
		particles.get()[first_free_particle * 4 + i].Position = position;
		particles.get()[first_free_particle * 4 + i].Velocity = velocity;
		particles.get()[first_free_particle * 4 + i].Random = random;
		particles.get()[first_free_particle * 4 + i].Time = current_time;
	}

	first_free_particle = next_free_particle;
}
<|endoftext|>


<commit_before>/***********************************************************************
 tcp_connection.cpp - Implements the TCPConnection class.

 Copyright (c) 2007-2008 by Educational Technology Resources, Inc.
 Others may also hold copyrights on code in this file.  See the
 CREDITS file in the top directory of the distribution for details.

 This file is part of MySQL++.

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

 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#define MYSQLPP_NOT_HEADER
#include "common.h"
#include "tcp_connection.h"

#include "exceptions.h"

#if !defined(MYSQLPP_PLATFORM_WINDOWS)
#	include <netdb.h>
#endif

#include <ctype.h>
#include <stdlib.h>

using namespace std;

namespace mysqlpp {

bool
TCPConnection::connect(const char* addr, const char* db,
		const char* user, const char* pass)
{
	error_message_.clear();

	unsigned int port = 0;
	string address;
	if (addr) {
		address = addr;
		if (!parse_address(address, port, error_message_)) {
			return false;
		}
	}

	if (error_message_.empty()) {
		return Connection::connect(db, address.c_str(), user, pass, port);
	}
	else {
		if (throw_exceptions()) {
			throw ConnectionFailed(error_message_.c_str());
		}
		else {
			return false;
		}
	}
}

bool
TCPConnection::parse_address(std::string& addr, unsigned int& port,
		std::string& error)
{
	error.clear();

	// Pull off service name or port number, if any
	string service;
	if (addr[0] == '[') {
		// Might be IPv6 address plus port/service in RFC 2732 form.
		string::size_type pos = addr.find(']');
		if ((pos == string::npos) ||
				(addr.find(':', pos + 1) != (pos + 1)) ||
				(addr.find_first_of("[]", pos + 2) != string::npos)) {
			error = "Malformed IPv6 [address]:service combination";
			return false;
		}

		// We can separate address from port/service now
		service = addr.substr(pos + 2);
		addr = addr.substr(1, pos - 1);

		// Ensure that address part is empty or has at least two colons
		if (addr.size() &&
				(((pos = addr.find(':')) == string::npos) ||
				(addr.find(':', pos + 1) == string::npos))) {
			error = "IPv6 literal needs at least two colons";
			return false;
		}
	}
	else {
		// Can only be IPv4 address, so check for 0-1 colons
		string::size_type pos = addr.find(':');
		if (pos != string::npos) {
			if (addr.find(':', pos + 1) != string::npos) {
				error = "IPv4 address:service combo can have only one colon";
				return false;
			}

			service = addr.substr(pos + 1);
			addr = addr.substr(0, pos);
		}
	}

	// Turn service into a port number, if it was given.  If not, don't
	// overwrite port because it could have a legal value passed in from
	// Connection.
	if (!service.empty()) {
		if (isdigit(service[0])) {
			port = atoi(service.c_str());
			if ((port < 1) || (port > USHRT_MAX)) {
				error = "Invalid TCP port number " + service;
				return false;
			}
		}
		else {
			servent* pse = getservbyname(service.c_str(), "tcp");
			if (pse) {
				port = ntohs(pse->s_port);
			}
			else {
				error = "Failed to look up TCP service " + service;
				return false;
			}
		}
	}

	// Ensure that there are only alphanumeric characters, dots,
	// dashes and colons in address.  Anything else must be an error.
	for (string::const_iterator it = addr.begin(); it != addr.end(); ++it) {
		string::value_type c = *it;
		if (!(isalnum(c) || (c == '.') || (c == '-') || (c == ':'))) {
			error = "Bad character '";
			error += c;
			error += "' in TCP/IP address";
			return false;
		}
	}

	return true;
}

} // end namespace mysqlpp

<commit_msg>Another #include fix for GCC 4.3, by Remi Collet<commit_after>/***********************************************************************
 tcp_connection.cpp - Implements the TCPConnection class.

 Copyright (c) 2007-2008 by Educational Technology Resources, Inc.
 Others may also hold copyrights on code in this file.  See the
 CREDITS file in the top directory of the distribution for details.

 This file is part of MySQL++.

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

 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#define MYSQLPP_NOT_HEADER
#include "common.h"
#include "tcp_connection.h"

#include "exceptions.h"

#if !defined(MYSQLPP_PLATFORM_WINDOWS)
#	include <netdb.h>
#endif

#include <ctype.h>
#include <stdlib.h>
#include <climits>

using namespace std;

namespace mysqlpp {

bool
TCPConnection::connect(const char* addr, const char* db,
		const char* user, const char* pass)
{
	error_message_.clear();

	unsigned int port = 0;
	string address;
	if (addr) {
		address = addr;
		if (!parse_address(address, port, error_message_)) {
			return false;
		}
	}

	if (error_message_.empty()) {
		return Connection::connect(db, address.c_str(), user, pass, port);
	}
	else {
		if (throw_exceptions()) {
			throw ConnectionFailed(error_message_.c_str());
		}
		else {
			return false;
		}
	}
}

bool
TCPConnection::parse_address(std::string& addr, unsigned int& port,
		std::string& error)
{
	error.clear();

	// Pull off service name or port number, if any
	string service;
	if (addr[0] == '[') {
		// Might be IPv6 address plus port/service in RFC 2732 form.
		string::size_type pos = addr.find(']');
		if ((pos == string::npos) ||
				(addr.find(':', pos + 1) != (pos + 1)) ||
				(addr.find_first_of("[]", pos + 2) != string::npos)) {
			error = "Malformed IPv6 [address]:service combination";
			return false;
		}

		// We can separate address from port/service now
		service = addr.substr(pos + 2);
		addr = addr.substr(1, pos - 1);

		// Ensure that address part is empty or has at least two colons
		if (addr.size() &&
				(((pos = addr.find(':')) == string::npos) ||
				(addr.find(':', pos + 1) == string::npos))) {
			error = "IPv6 literal needs at least two colons";
			return false;
		}
	}
	else {
		// Can only be IPv4 address, so check for 0-1 colons
		string::size_type pos = addr.find(':');
		if (pos != string::npos) {
			if (addr.find(':', pos + 1) != string::npos) {
				error = "IPv4 address:service combo can have only one colon";
				return false;
			}

			service = addr.substr(pos + 1);
			addr = addr.substr(0, pos);
		}
	}

	// Turn service into a port number, if it was given.  If not, don't
	// overwrite port because it could have a legal value passed in from
	// Connection.
	if (!service.empty()) {
		if (isdigit(service[0])) {
			port = atoi(service.c_str());
			if ((port < 1) || (port > USHRT_MAX)) {
				error = "Invalid TCP port number " + service;
				return false;
			}
		}
		else {
			servent* pse = getservbyname(service.c_str(), "tcp");
			if (pse) {
				port = ntohs(pse->s_port);
			}
			else {
				error = "Failed to look up TCP service " + service;
				return false;
			}
		}
	}

	// Ensure that there are only alphanumeric characters, dots,
	// dashes and colons in address.  Anything else must be an error.
	for (string::const_iterator it = addr.begin(); it != addr.end(); ++it) {
		string::value_type c = *it;
		if (!(isalnum(c) || (c == '.') || (c == '-') || (c == ':'))) {
			error = "Bad character '";
			error += c;
			error += "' in TCP/IP address";
			return false;
		}
	}

	return true;
}

} // end namespace mysqlpp

<|endoftext|>


<commit_before>//
//  main.cpp
//  Clock Signal
//
//  Created by Thomas Harte on 04/11/2017.
//  Copyright © 2017 Thomas Harte. All rights reserved.
//

#include <iostream>
#include <memory>
#include <cstdio>

#include <SDL2/SDL.h>

#include "../../StaticAnalyser/StaticAnalyser.hpp"
#include "../../Machines/Utility/MachineForTarget.hpp"

#include "../../Machines/ConfigurationTarget.hpp"
#include "../../Machines/CRTMachine.hpp"

#include "../../Concurrency/BestEffortUpdater.hpp"

namespace {

struct CRTMachineDelegate: public CRTMachine::Machine::Delegate {
	void machine_did_change_clock_rate(CRTMachine::Machine *machine) {
		best_effort_updater->set_clock_rate(machine->get_clock_rate());
	}

	void machine_did_change_clock_is_unlimited(CRTMachine::Machine *machine) {
	}

	Concurrency::BestEffortUpdater *best_effort_updater;
};

struct BestEffortUpdaterDelegate: public Concurrency::BestEffortUpdater::Delegate {
	void update(Concurrency::BestEffortUpdater *updater, int cycles, bool did_skip_previous_update) {
		machine->crt_machine()->run_for(Cycles(cycles));
	}

	Machine::DynamicMachine *machine;
};

// This is set to a relatively large number for now.
const int AudioBufferSize = 1024;

struct SpeakerDelegate: public Outputs::Speaker::Delegate {
	void speaker_did_complete_samples(Outputs::Speaker *speaker, const std::vector<int16_t> &buffer) {
		if(SDL_GetQueuedAudioSize(audio_device) < AudioBufferSize*3)
			SDL_QueueAudio(audio_device, reinterpret_cast<const void *>(buffer.data()), static_cast<Uint32>(buffer.size() * sizeof(uint16_t)));
		updater->update();
	}

	SDL_AudioDeviceID audio_device;
	Concurrency::BestEffortUpdater *updater;
};

bool KeyboardKeyForSDLScancode(SDL_Keycode scancode, Inputs::Keyboard::Key &key) {
#define BIND(x, y) case SDL_SCANCODE_##x: key = Inputs::Keyboard::Key::y; break;
	switch(scancode) {
		default: return false;

		BIND(F1, F1)	BIND(F2, F2)	BIND(F3, F3)	BIND(F4, F4)	BIND(F5, F5)	BIND(F6, F6)
		BIND(F7, F7)	BIND(F8, F8)	BIND(F9, F9)	BIND(F10, F10)	BIND(F11, F11)	BIND(F12, F12)

		BIND(1, k1)		BIND(2, k2)		BIND(3, k3)		BIND(4, k4)		BIND(5, k5)
		BIND(6, k6)		BIND(7, k7)		BIND(8, k8)		BIND(9, k9)		BIND(0, k0)

		BIND(Q, Q)		BIND(W, W)		BIND(E, E)		BIND(R, R)		BIND(T, T)
		BIND(Y, Y)		BIND(U, U)		BIND(I, I)		BIND(O, O)		BIND(P, P)
		BIND(A, A)		BIND(S, S)		BIND(D, D)		BIND(F, F)		BIND(G, G)
		BIND(H, H)		BIND(J, J)		BIND(K, K)		BIND(L, L)
		BIND(Z, Z)		BIND(X, X)		BIND(C, C)		BIND(V, V)
		BIND(B, B)		BIND(N, N)		BIND(M, M)

		BIND(KP_7, KeyPad7)	BIND(KP_8, KeyPad8)	BIND(KP_9, KeyPad9)
		BIND(KP_4, KeyPad4)	BIND(KP_5, KeyPad5)	BIND(KP_6, KeyPad6)
		BIND(KP_1, KeyPad1)	BIND(KP_2, KeyPad2)	BIND(KP_3, KeyPad3)
		BIND(KP_0, KeyPad0)

		BIND(ESCAPE, Escape)

		BIND(PRINTSCREEN, PrintScreen)	BIND(SCROLLLOCK, ScrollLock)	BIND(PAUSE, Pause)

		BIND(GRAVE, BackTick)		BIND(MINUS, Hyphen)		BIND(EQUALS, Equals)	BIND(BACKSPACE, BackSpace)

		BIND(TAB, Tab)
		BIND(LEFTBRACKET, OpenSquareBracket)	BIND(RIGHTBRACKET, CloseSquareBracket)
		BIND(BACKSLASH, BackSlash)

		BIND(CAPSLOCK, CapsLock)	BIND(SEMICOLON, Semicolon)
		BIND(APOSTROPHE, Quote)		BIND(RETURN, Enter)

		BIND(LSHIFT, LeftShift)		BIND(COMMA, Comma)		BIND(PERIOD, FullStop)
		BIND(SLASH, ForwardSlash)	BIND(RSHIFT, RightShift)

		BIND(LCTRL, LeftControl)	BIND(LALT, LeftOption)		BIND(LGUI, LeftMeta)
		BIND(SPACE, Space)
		BIND(RCTRL, RightControl)	BIND(RALT, RightOption)	BIND(RGUI, RightMeta)

		BIND(LEFT, Left)	BIND(RIGHT, Right)		BIND(UP, Up)	BIND(DOWN, Down)

		BIND(INSERT, Insert)	BIND(HOME, Home)	BIND(PAGEUP, PageUp)
		BIND(DELETE, Delete)	BIND(END, End)		BIND(PAGEDOWN, PageDown)

		BIND(NUMLOCKCLEAR, NumLock)		BIND(KP_DIVIDE, KeyPadSlash)		BIND(KP_MULTIPLY, KeyPadAsterisk)
		BIND(KP_PLUS, KeyPadPlus)		BIND(KP_MINUS, KeyPadMinus)			BIND(KP_ENTER, KeyPadEnter)
		BIND(KP_DECIMAL, KeyPadDecimalPoint)
		BIND(KP_EQUALS, KeyPadEquals)
		BIND(HELP, Help)

		// SDL doesn't seem to have scancodes for hash or keypad delete?
	}
#undef BIND
	return true;
}

}

int main(int argc, char *argv[]) {
	SDL_Window *window = nullptr;

	// Perform a sanity check on arguments.
	if(argc < 2) {
		std::cerr << "Usage: " << argv[0] << " [file]" << std::endl;
		return -1;
	}

	// Determine the machine for the supplied file.
	std::list<StaticAnalyser::Target> targets = StaticAnalyser::GetTargets(argv[1]);
	if(targets.empty()) {
		std::cerr << "Cannot open " << argv[1] << std::endl;
		return -1;
	}

	Concurrency::BestEffortUpdater updater;
	BestEffortUpdaterDelegate best_effort_updater_delegate;
	CRTMachineDelegate crt_delegate;
	SpeakerDelegate speaker_delegate;

	// Create and configure a machine.
	std::unique_ptr<::Machine::DynamicMachine> machine(::Machine::MachineForTarget(targets.front()));

	updater.set_clock_rate(machine->crt_machine()->get_clock_rate());
	crt_delegate.best_effort_updater = &updater;
	best_effort_updater_delegate.machine = machine.get();
	speaker_delegate.updater = &updater;

	machine->crt_machine()->set_delegate(&crt_delegate);
	updater.set_delegate(&best_effort_updater_delegate);

	// Attempt to set up video and audio.
	if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) < 0) {
		std::cerr << "SDL could not initialize! SDL_Error: " << SDL_GetError() << std::endl;
		return -1;
	}

	// Ask for no depth buffer, a core profile and vsync-aligned rendering.
	SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 0);
	SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
	SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
	SDL_GL_SetSwapInterval(1);

	window = SDL_CreateWindow(	"Clock Signal",
								SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
								400, 300,
								SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE);

	if(!window)
	{
		std::cerr << "Could not create window" << std::endl;
		return -1;
	}

	SDL_GLContext gl_context = SDL_GL_CreateContext(window);
	SDL_GL_MakeCurrent(window, gl_context);

	// For vanilla SDL purposes, assume system ROMs can be found in one of:
	//
	//	/usr/local/share/CLK/[system]; or
	//	/usr/share/CLK/[system]
	bool roms_loaded = machine->crt_machine()->set_rom_fetcher( [] (const std::string &machine, const std::vector<std::string> &names) -> std::vector<std::unique_ptr<std::vector<uint8_t>>> {
		std::vector<std::unique_ptr<std::vector<uint8_t>>> results;
		for(auto &name: names) {
			std::string local_path = "/usr/local/share/CLK/" + machine + "/" + name;
			FILE *file = fopen(local_path.c_str(), "r");
			if(!file) {
				std::string path = "/usr/share/CLK/" + machine + "/" + name;
				file = fopen(path.c_str(), "r");
			}

			if(!file) {
				results.emplace_back(nullptr);
				continue;
			}

			std::unique_ptr<std::vector<uint8_t>> data(new std::vector<uint8_t>);

			fseek(file, 0, SEEK_END);
			data->resize(ftell(file));
			fseek(file, 0, SEEK_SET);
			fread(data->data(), 1, data->size(), file);
			fclose(file);

			results.emplace_back(std::move(data));
		}

		return results;
	});

	if(!roms_loaded) {
		std::cerr << "Could not find system ROMs; please install to /usr/local/share/CLK/ or /usr/share/CLK/" << std::endl;
		return -1;
	}

	machine->configuration_target()->configure_as_target(targets.front());

	// Setup output, assuming a CRT machine for now, and prepare a best-effort updater.
	machine->crt_machine()->setup_output(4.0 / 3.0);
	machine->crt_machine()->get_crt()->set_output_gamma(2.2f);

	// For now, lie about audio output intentions.
	auto speaker = machine->crt_machine()->get_speaker();
	if(speaker) {
		// Create an audio pipe.
		SDL_AudioSpec desired_audio_spec;
		SDL_AudioSpec obtained_audio_spec;

		SDL_zero(desired_audio_spec);
		desired_audio_spec.freq = 48000;	// TODO: how can I get SDL to reveal the output rate of this machine?
		desired_audio_spec.format = AUDIO_S16;
		desired_audio_spec.channels = 1;
		desired_audio_spec.samples = AudioBufferSize;

		speaker_delegate.audio_device = SDL_OpenAudioDevice(nullptr, 0, &desired_audio_spec, &obtained_audio_spec, SDL_AUDIO_ALLOW_FREQUENCY_CHANGE);

		speaker->set_output_rate(obtained_audio_spec.freq, obtained_audio_spec.samples);
		speaker->set_delegate(&speaker_delegate);
		SDL_PauseAudioDevice(speaker_delegate.audio_device, 0);
	}

	// Run the main event loop until the OS tells us to quit.
	bool should_quit = false;
	while(!should_quit) {
		// Process all pending events.
		SDL_Event event;
		while(SDL_PollEvent(&event)) {
			switch(event.type) {
				case SDL_QUIT:	should_quit = true;	break;

				case SDL_KEYDOWN:
				case SDL_KEYUP:
					KeyboardMachine::Machine *keyboard_machine = machine->keyboard_machine();
					if(!keyboard_machine) break;

					Inputs::Keyboard::Key key = Inputs::Keyboard::Key::Space;
					if(!KeyboardKeyForSDLScancode(event.key.keysym.scancode, key)) break;
					keyboard_machine->get_keyboard().set_key_pressed(key, event.type == SDL_KEYDOWN);
				break;
			}
		}

		// Display a new frame and wait for vsync.
		updater.update();
		int width, height;
		SDL_GetWindowSize(window, &width, &height);
		machine->crt_machine()->get_crt()->draw_frame(static_cast<unsigned int>(width), static_cast<unsigned int>(height), false);
		SDL_GL_SwapWindow(window);
	}

	// Clean up.
	SDL_DestroyWindow( window );
	SDL_Quit();

	return 0;
}
<commit_msg>Added check in SDL main that the expected number of bytes is read.<commit_after>//
//  main.cpp
//  Clock Signal
//
//  Created by Thomas Harte on 04/11/2017.
//  Copyright © 2017 Thomas Harte. All rights reserved.
//

#include <iostream>
#include <memory>
#include <cstdio>

#include <SDL2/SDL.h>

#include "../../StaticAnalyser/StaticAnalyser.hpp"
#include "../../Machines/Utility/MachineForTarget.hpp"

#include "../../Machines/ConfigurationTarget.hpp"
#include "../../Machines/CRTMachine.hpp"

#include "../../Concurrency/BestEffortUpdater.hpp"

namespace {

struct CRTMachineDelegate: public CRTMachine::Machine::Delegate {
	void machine_did_change_clock_rate(CRTMachine::Machine *machine) {
		best_effort_updater->set_clock_rate(machine->get_clock_rate());
	}

	void machine_did_change_clock_is_unlimited(CRTMachine::Machine *machine) {
	}

	Concurrency::BestEffortUpdater *best_effort_updater;
};

struct BestEffortUpdaterDelegate: public Concurrency::BestEffortUpdater::Delegate {
	void update(Concurrency::BestEffortUpdater *updater, int cycles, bool did_skip_previous_update) {
		machine->crt_machine()->run_for(Cycles(cycles));
	}

	Machine::DynamicMachine *machine;
};

// This is set to a relatively large number for now.
const int AudioBufferSize = 1024;

struct SpeakerDelegate: public Outputs::Speaker::Delegate {
	void speaker_did_complete_samples(Outputs::Speaker *speaker, const std::vector<int16_t> &buffer) {
		if(SDL_GetQueuedAudioSize(audio_device) < AudioBufferSize*3)
			SDL_QueueAudio(audio_device, reinterpret_cast<const void *>(buffer.data()), static_cast<Uint32>(buffer.size() * sizeof(uint16_t)));
		updater->update();
	}

	SDL_AudioDeviceID audio_device;
	Concurrency::BestEffortUpdater *updater;
};

bool KeyboardKeyForSDLScancode(SDL_Keycode scancode, Inputs::Keyboard::Key &key) {
#define BIND(x, y) case SDL_SCANCODE_##x: key = Inputs::Keyboard::Key::y; break;
	switch(scancode) {
		default: return false;

		BIND(F1, F1)	BIND(F2, F2)	BIND(F3, F3)	BIND(F4, F4)	BIND(F5, F5)	BIND(F6, F6)
		BIND(F7, F7)	BIND(F8, F8)	BIND(F9, F9)	BIND(F10, F10)	BIND(F11, F11)	BIND(F12, F12)

		BIND(1, k1)		BIND(2, k2)		BIND(3, k3)		BIND(4, k4)		BIND(5, k5)
		BIND(6, k6)		BIND(7, k7)		BIND(8, k8)		BIND(9, k9)		BIND(0, k0)

		BIND(Q, Q)		BIND(W, W)		BIND(E, E)		BIND(R, R)		BIND(T, T)
		BIND(Y, Y)		BIND(U, U)		BIND(I, I)		BIND(O, O)		BIND(P, P)
		BIND(A, A)		BIND(S, S)		BIND(D, D)		BIND(F, F)		BIND(G, G)
		BIND(H, H)		BIND(J, J)		BIND(K, K)		BIND(L, L)
		BIND(Z, Z)		BIND(X, X)		BIND(C, C)		BIND(V, V)
		BIND(B, B)		BIND(N, N)		BIND(M, M)

		BIND(KP_7, KeyPad7)	BIND(KP_8, KeyPad8)	BIND(KP_9, KeyPad9)
		BIND(KP_4, KeyPad4)	BIND(KP_5, KeyPad5)	BIND(KP_6, KeyPad6)
		BIND(KP_1, KeyPad1)	BIND(KP_2, KeyPad2)	BIND(KP_3, KeyPad3)
		BIND(KP_0, KeyPad0)

		BIND(ESCAPE, Escape)

		BIND(PRINTSCREEN, PrintScreen)	BIND(SCROLLLOCK, ScrollLock)	BIND(PAUSE, Pause)

		BIND(GRAVE, BackTick)		BIND(MINUS, Hyphen)		BIND(EQUALS, Equals)	BIND(BACKSPACE, BackSpace)

		BIND(TAB, Tab)
		BIND(LEFTBRACKET, OpenSquareBracket)	BIND(RIGHTBRACKET, CloseSquareBracket)
		BIND(BACKSLASH, BackSlash)

		BIND(CAPSLOCK, CapsLock)	BIND(SEMICOLON, Semicolon)
		BIND(APOSTROPHE, Quote)		BIND(RETURN, Enter)

		BIND(LSHIFT, LeftShift)		BIND(COMMA, Comma)		BIND(PERIOD, FullStop)
		BIND(SLASH, ForwardSlash)	BIND(RSHIFT, RightShift)

		BIND(LCTRL, LeftControl)	BIND(LALT, LeftOption)		BIND(LGUI, LeftMeta)
		BIND(SPACE, Space)
		BIND(RCTRL, RightControl)	BIND(RALT, RightOption)	BIND(RGUI, RightMeta)

		BIND(LEFT, Left)	BIND(RIGHT, Right)		BIND(UP, Up)	BIND(DOWN, Down)

		BIND(INSERT, Insert)	BIND(HOME, Home)	BIND(PAGEUP, PageUp)
		BIND(DELETE, Delete)	BIND(END, End)		BIND(PAGEDOWN, PageDown)

		BIND(NUMLOCKCLEAR, NumLock)		BIND(KP_DIVIDE, KeyPadSlash)		BIND(KP_MULTIPLY, KeyPadAsterisk)
		BIND(KP_PLUS, KeyPadPlus)		BIND(KP_MINUS, KeyPadMinus)			BIND(KP_ENTER, KeyPadEnter)
		BIND(KP_DECIMAL, KeyPadDecimalPoint)
		BIND(KP_EQUALS, KeyPadEquals)
		BIND(HELP, Help)

		// SDL doesn't seem to have scancodes for hash or keypad delete?
	}
#undef BIND
	return true;
}

}

int main(int argc, char *argv[]) {
	SDL_Window *window = nullptr;

	// Perform a sanity check on arguments.
	if(argc < 2) {
		std::cerr << "Usage: " << argv[0] << " [file]" << std::endl;
		return -1;
	}

	// Determine the machine for the supplied file.
	std::list<StaticAnalyser::Target> targets = StaticAnalyser::GetTargets(argv[1]);
	if(targets.empty()) {
		std::cerr << "Cannot open " << argv[1] << std::endl;
		return -1;
	}

	Concurrency::BestEffortUpdater updater;
	BestEffortUpdaterDelegate best_effort_updater_delegate;
	CRTMachineDelegate crt_delegate;
	SpeakerDelegate speaker_delegate;

	// Create and configure a machine.
	std::unique_ptr<::Machine::DynamicMachine> machine(::Machine::MachineForTarget(targets.front()));

	updater.set_clock_rate(machine->crt_machine()->get_clock_rate());
	crt_delegate.best_effort_updater = &updater;
	best_effort_updater_delegate.machine = machine.get();
	speaker_delegate.updater = &updater;

	machine->crt_machine()->set_delegate(&crt_delegate);
	updater.set_delegate(&best_effort_updater_delegate);

	// Attempt to set up video and audio.
	if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) < 0) {
		std::cerr << "SDL could not initialize! SDL_Error: " << SDL_GetError() << std::endl;
		return -1;
	}

	// Ask for no depth buffer, a core profile and vsync-aligned rendering.
	SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 0);
	SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
	SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
	SDL_GL_SetSwapInterval(1);

	window = SDL_CreateWindow(	"Clock Signal",
								SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
								400, 300,
								SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE);

	if(!window)
	{
		std::cerr << "Could not create window" << std::endl;
		return -1;
	}

	SDL_GLContext gl_context = SDL_GL_CreateContext(window);
	SDL_GL_MakeCurrent(window, gl_context);

	// For vanilla SDL purposes, assume system ROMs can be found in one of:
	//
	//	/usr/local/share/CLK/[system]; or
	//	/usr/share/CLK/[system]
	bool roms_loaded = machine->crt_machine()->set_rom_fetcher( [] (const std::string &machine, const std::vector<std::string> &names) -> std::vector<std::unique_ptr<std::vector<uint8_t>>> {
		std::vector<std::unique_ptr<std::vector<uint8_t>>> results;
		for(auto &name: names) {
			std::string local_path = "/usr/local/share/CLK/" + machine + "/" + name;
			FILE *file = std::fopen(local_path.c_str(), "rb");
			if(!file) {
				std::string path = "/usr/share/CLK/" + machine + "/" + name;
				file = std::fopen(path.c_str(), "rb");
			}

			if(!file) {
				results.emplace_back(nullptr);
				continue;
			}

			std::unique_ptr<std::vector<uint8_t>> data(new std::vector<uint8_t>);

			std::fseek(file, 0, SEEK_END);
			data->resize(std::ftell(file));
			std::fseek(file, 0, SEEK_SET);
			std::size_t read = fread(data->data(), 1, data->size(), file);
			std::fclose(file);

			if(read == data->size())
				results.emplace_back(std::move(data));
			else
				results.emplace_back(nullptr);
		}

		return results;
	});

	if(!roms_loaded) {
		std::cerr << "Could not find system ROMs; please install to /usr/local/share/CLK/ or /usr/share/CLK/" << std::endl;
		return -1;
	}

	machine->configuration_target()->configure_as_target(targets.front());

	// Setup output, assuming a CRT machine for now, and prepare a best-effort updater.
	machine->crt_machine()->setup_output(4.0 / 3.0);
	machine->crt_machine()->get_crt()->set_output_gamma(2.2f);

	// For now, lie about audio output intentions.
	auto speaker = machine->crt_machine()->get_speaker();
	if(speaker) {
		// Create an audio pipe.
		SDL_AudioSpec desired_audio_spec;
		SDL_AudioSpec obtained_audio_spec;

		SDL_zero(desired_audio_spec);
		desired_audio_spec.freq = 48000;	// TODO: how can I get SDL to reveal the output rate of this machine?
		desired_audio_spec.format = AUDIO_S16;
		desired_audio_spec.channels = 1;
		desired_audio_spec.samples = AudioBufferSize;

		speaker_delegate.audio_device = SDL_OpenAudioDevice(nullptr, 0, &desired_audio_spec, &obtained_audio_spec, SDL_AUDIO_ALLOW_FREQUENCY_CHANGE);

		speaker->set_output_rate(obtained_audio_spec.freq, obtained_audio_spec.samples);
		speaker->set_delegate(&speaker_delegate);
		SDL_PauseAudioDevice(speaker_delegate.audio_device, 0);
	}

	// Run the main event loop until the OS tells us to quit.
	bool should_quit = false;
	while(!should_quit) {
		// Process all pending events.
		SDL_Event event;
		while(SDL_PollEvent(&event)) {
			switch(event.type) {
				case SDL_QUIT:	should_quit = true;	break;

				case SDL_KEYDOWN:
				case SDL_KEYUP:
					KeyboardMachine::Machine *keyboard_machine = machine->keyboard_machine();
					if(!keyboard_machine) break;

					Inputs::Keyboard::Key key = Inputs::Keyboard::Key::Space;
					if(!KeyboardKeyForSDLScancode(event.key.keysym.scancode, key)) break;
					keyboard_machine->get_keyboard().set_key_pressed(key, event.type == SDL_KEYDOWN);
				break;
			}
		}

		// Display a new frame and wait for vsync.
		updater.update();
		int width, height;
		SDL_GetWindowSize(window, &width, &height);
		machine->crt_machine()->get_crt()->draw_frame(static_cast<unsigned int>(width), static_cast<unsigned int>(height), false);
		SDL_GL_SwapWindow(window);
	}

	// Clean up.
	SDL_DestroyWindow( window );
	SDL_Quit();

	return 0;
}
<|endoftext|>


<commit_before>/**
 * @file
 * brief description, full stop.
 *
 * long description, many sentences.
 *
 */
#include "angort.h"
#include "hash.h"
#include "cycle.h"
#include "types/symbol.h"

namespace angort {

HashObject::HashObject() : GarbageCollected() {
    hash = new Hash();
}

HashObject::~HashObject(){
    delete hash;
}

Iterator<Value *> *HashObject::makeValueIterator() {
    return hash->createIterator(false);
}

Iterator<Value *> *HashObject::makeKeyIterator() {
    return hash->createIterator(true);
}

Hash *HashType::set(Value *v){
    v->clr();
    v->t = this;
    HashObject *h = new HashObject();
    v->v.hash = h;
    incRef(v);
    return h->hash;
}

void HashType::set(Value *v,HashObject *ho){
    v->clr();
    v->t = this;
    v->v.hash = ho;
    incRef(v);
}

Hash *HashType::get(Value *v){
    if(v->t != this)
        throw RUNT("not a hash");
    return v->v.hash->hash;
}

void HashType::setValue(Value *coll,Value *k,Value *v){
    Hash *h = coll->v.hash->hash;
    h->set(k,v);
}

void HashType::getValue(Value *coll,Value *k,Value *result){
    Hash *h = coll->v.hash->hash;
    if(h->find(k))
        result->copy(h->getval());
    else
        result->clr();
}

int HashType::getCount(Value *coll){
    Hash *h = coll->v.hash->hash;
    return h->count();
}

void HashType::removeAndReturn(Value *coll,Value *k,Value *result){
    Hash *h = coll->v.hash->hash;
    if(h->find(k)){
        result->copy(h->getval());
        h->del(k);
    } else
        result->clr();
}

bool HashType::isIn(Value *coll,Value *item){
    Hash *h = coll->v.hash->hash;
    if(h->find(item))
        return true;
    else
        return false;
}

void HashType::clone(Value *out,const Value *in,bool deep){
    HashObject *p = new HashObject();
    Hash *h = get(const_cast<Value *>(in));

    // cast away constness - makeIterator() can't be const
    // because it modifies refcounts

    HashKeyIterator iter(h);
    for(iter.first();!iter.isDone();iter.next()){
        Value *k = iter.current();
        Value *v;
        if(h->find(k))
            v = h->getval();
        else
            throw WTF;

        // because collections can't be keys, we only need worry
        // about the value for deep cloning.

        if(deep){
            Value deepv;
            v->t->clone(&deepv,v);
            p->hash->set(k,&deepv); // hash will copy the value
        } else {
            p->hash->set(k,v);
        }

    }

    out->clr();
    out->t = this;
    out->v.hash = p;
    incRef(out);
}

const char *HashType::toString(bool *allocated,const Value *v) const {
    // first, does the hash contain the toString symbol key?

    static int symbKey=-1;
    if(symbKey<0)
        symbKey = Types::tSymbol->getSymbol("toString");

    Value k;
    Types::tSymbol->set(&k,symbKey);

    Hash *h = v->v.hash->hash;
    if(h->find(&k)){
        // is it a function?
        Value *outval = h->getval();
        if(outval->t->isCallable()){
            Angort *a = Angort::getCallingInstance();
            // Yes, so call the function and get the returned value
            a->pushval()->copy(v);
            // have to turn debugging off during this to avoid
            // infinite recursion
            int olddeb = a->debug;
            a->debug=0;
            a->runValue(outval);
            outval = a->popval();
            a->debug=olddeb;
            return outval->t->toString(allocated,outval);
        } else {
            // if not, just turn it into a string and use that
            return outval->t->toString(allocated,outval);
        }
    }

    // otherwise, do the default operation
    return Type::toString(allocated,v);
}

}
<commit_msg>Typechecking for hash set value.<commit_after>/**
 * @file
 * brief description, full stop.
 *
 * long description, many sentences.
 *
 */
#include "angort.h"
#include "hash.h"
#include "cycle.h"
#include "types/symbol.h"

namespace angort {

HashObject::HashObject() : GarbageCollected() {
    hash = new Hash();
}

HashObject::~HashObject(){
    delete hash;
}

Iterator<Value *> *HashObject::makeValueIterator() {
    return hash->createIterator(false);
}

Iterator<Value *> *HashObject::makeKeyIterator() {
    return hash->createIterator(true);
}

Hash *HashType::set(Value *v){
    v->clr();
    v->t = this;
    HashObject *h = new HashObject();
    v->v.hash = h;
    incRef(v);
    return h->hash;
}

void HashType::set(Value *v,HashObject *ho){
    v->clr();
    v->t = this;
    v->v.hash = ho;
    incRef(v);
}

Hash *HashType::get(Value *v){
    if(v->t != this)
        throw RUNT("").set("not a hash, is a %s",v->t->name);
    return v->v.hash->hash;
}

void HashType::setValue(Value *coll,Value *k,Value *v){
    if(coll->t != this)
        throw RUNT("").set("not a hash, is a %s",coll->t->name);
    Hash *h = coll->v.hash->hash;
    h->set(k,v);
}

void HashType::getValue(Value *coll,Value *k,Value *result){
    Hash *h = coll->v.hash->hash;
    if(h->find(k))
        result->copy(h->getval());
    else
        result->clr();
}

int HashType::getCount(Value *coll){
    Hash *h = coll->v.hash->hash;
    return h->count();
}

void HashType::removeAndReturn(Value *coll,Value *k,Value *result){
    Hash *h = coll->v.hash->hash;
    if(h->find(k)){
        result->copy(h->getval());
        h->del(k);
    } else
        result->clr();
}

bool HashType::isIn(Value *coll,Value *item){
    Hash *h = coll->v.hash->hash;
    if(h->find(item))
        return true;
    else
        return false;
}

void HashType::clone(Value *out,const Value *in,bool deep){
    HashObject *p = new HashObject();
    Hash *h = get(const_cast<Value *>(in));

    // cast away constness - makeIterator() can't be const
    // because it modifies refcounts

    HashKeyIterator iter(h);
    for(iter.first();!iter.isDone();iter.next()){
        Value *k = iter.current();
        Value *v;
        if(h->find(k))
            v = h->getval();
        else
            throw WTF;

        // because collections can't be keys, we only need worry
        // about the value for deep cloning.

        if(deep){
            Value deepv;
            v->t->clone(&deepv,v);
            p->hash->set(k,&deepv); // hash will copy the value
        } else {
            p->hash->set(k,v);
        }

    }

    out->clr();
    out->t = this;
    out->v.hash = p;
    incRef(out);
}

const char *HashType::toString(bool *allocated,const Value *v) const {
    // first, does the hash contain the toString symbol key?

    static int symbKey=-1;
    if(symbKey<0)
        symbKey = Types::tSymbol->getSymbol("toString");

    Value k;
    Types::tSymbol->set(&k,symbKey);

    Hash *h = v->v.hash->hash;
    if(h->find(&k)){
        // is it a function?
        Value *outval = h->getval();
        if(outval->t->isCallable()){
            Angort *a = Angort::getCallingInstance();
            // Yes, so call the function and get the returned value
            a->pushval()->copy(v);
            // have to turn debugging off during this to avoid
            // infinite recursion
            int olddeb = a->debug;
            a->debug=0;
            a->runValue(outval);
            outval = a->popval();
            a->debug=olddeb;
            return outval->t->toString(allocated,outval);
        } else {
            // if not, just turn it into a string and use that
            return outval->t->toString(allocated,outval);
        }
    }

    // otherwise, do the default operation
    return Type::toString(allocated,v);
}

}
<|endoftext|>