<commit_before>#include <QCommandLineParser>
#include <QCoreApplication>
#include <QJsonArray>
#include <QJsonDocument>
#include <QJsonObject>
#include <QTimer>
#include "functions.h"
#include "logger.h"
#include "models/api/api.h"
#include "models/page.h"
#include "models/page-api.h"
#include "models/profile.h"
#include "models/site.h"
#include "models/source.h"
#include "tags/tag.h"

bool opCompare(const QString &op, int left, int right)
{
	if (right == -1) {
		return true;
	}
	if (op == ">") {
		return left > right;
	}
	if (op == "<") {
		return left < right;
	}
	return left == right;
}

bool jsonCompare(const QVariant &value, QJsonValue opt)
{
	QString op = "=";
	if (opt.isArray()) {
		QJsonArray arrOpt = opt.toArray();
		op = arrOpt[0].toString();
		opt = arrOpt[1];
	}

	if (value.type() == QVariant::String) {
		return value.toString() == opt.toString();
	}

	return opCompare(op, value.toInt(), opt.toInt());
}

int main(int argc, char *argv[])
{
	const QCoreApplication app(argc, argv);

	QCommandLineParser parser;
	parser.addHelpOption();

	const QCommandLineOption inputOption(QStringList() << "i" << "input", "Input JSON configuration file", "input");
	const QCommandLineOption outputOption(QStringList() << "o" << "output", "Output JSON result file", "output");
	parser.addOption(inputOption);
	parser.addOption(outputOption);
	parser.process(app);

	Logger::getInstance().setLogLevel(Logger::Warning);

	QFile f(parser.value(inputOption));
	if (!f.open(QFile::ReadOnly | QFile::Text)) {
		return 1;
	}

	QJsonObject allJson;
	QJsonDocument input = QJsonDocument::fromJson(f.readAll());
	f.close();

	Profile *profile = new Profile(savePath());
	auto allSources = profile->getSources();
	auto allSites = profile->getSites();

	const auto oldBlacklist = profile->getBlacklist();
	profile->setBlacklistedTags(Blacklist());

	const QJsonObject root = input.object();
	const QJsonArray rootSearch = root.value("search").toArray();
	const QJsonObject sources = root.value("sources").toObject();

	for (auto it = sources.constBegin(); it != sources.constEnd(); ++it) {
		const QString &sourceName = it.key();
		qDebug() << "#" << "Source" << sourceName;
		QJsonObject sourceJson;

		Source *source = allSources.value(sourceName);
		QJsonObject sites = it.value().toObject();

		const QJsonObject sourceApis = sites.value("apis").toObject();
		QJsonArray sourceSearch = rootSearch;
		if (sites.contains("search")) {
			sourceSearch = sites.value("search").toArray();
		}

		for (Site *site : source->getSites()) {
			qDebug() << "##" << "Site" << site->url();
			QJsonObject siteJson;

			QJsonObject siteApis = sourceApis;
			QJsonArray siteSearch = sourceSearch;
			if (sites.contains(site->url())) {
				QJsonObject override = sites.value(site->url()).toObject();
				if (override.contains("apis")) {
					siteApis = override.value("apis").toObject();
				}
				if (override.contains("search")) {
					siteSearch = override.value("search").toArray();
				}
			}

			for (auto ita = siteApis.constBegin(); ita != siteApis.constEnd(); ++ita) {
				const QString &apiName = ita.key();
				qDebug() << "###" << "API" << apiName;
				QJsonObject apiJson;
				QJsonArray checks = ita.value().toArray();

				QJsonArray apiSearch = siteSearch;
				if (checks.count() > 4) {
					apiSearch = checks[4].toArray();
				}

				const QString search = apiSearch[0].toString();
				const int pageI = apiSearch[1].toInt();
				const int limit = apiSearch[2].toInt();

				Api *api = nullptr;
				for (Api *a : site->getApis()) {
					if (a->getName().toLower() == apiName.toLower()) {
						api = a;
					}
				}
				if (api == nullptr) {
					continue;
				}

				auto page = new Page(profile, site, allSites.values(), QStringList() << search, pageI, limit);
				auto pageApi = new PageApi(page, profile, site, api, search.split(' '), pageI, limit);
				QEventLoop loop;
				QObject::connect(pageApi, &PageApi::finishedLoading, &loop, &QEventLoop::quit);
				QTimer::singleShot(1, pageApi, SLOT(load()));
				loop.exec();

				apiJson["status"] = "ok";
				QStringList message;

				// Checks
				if (!jsonCompare(pageApi->errors().join(", "), checks[0])) {
					apiJson["status"] = "error";
					message.append(pageApi->errors());
				}
				if (!jsonCompare(pageApi->imagesCount(false), checks[1])) {
					if (apiJson["status"] == "ok") {
						apiJson["status"] = "warning";
					}
					message.append("Image count error: " + QString::number(pageApi->imagesCount(false)));
				}
				if (!jsonCompare(pageApi->images().count(), checks[2])) {
					apiJson["status"] = "error";
					message.append("Number of images error: " + QString::number(pageApi->images().count()));
				}
				if (!jsonCompare(pageApi->tags().count(), checks[3])) {
					if (apiJson["status"] == "ok") {
						apiJson["status"] = "warning";
					}
					QStringList tags;
					for (const Tag& tag : pageApi->tags()) {
						tags.append(tag.text());
					}
					message.append("Number of tags error: " + QString::number(pageApi->tags().count()) + " [" + tags.join(", ") + "]");
				}

				if (!message.isEmpty()) {
					apiJson["message"] = message.join(", ");
					siteJson[apiName] = apiJson;
				} else {
					siteJson[apiName] = apiJson["status"];
				}

				pageApi->deleteLater();
				page->deleteLater();
			}
			sourceJson[site->url()] = siteJson;
		}
		allJson[sourceName] = sourceJson;
	}

	profile->setBlacklistedTags(oldBlacklist);

	QJsonDocument outDoc(allJson);
	QFile fOut(parser.value(outputOption));
	if (!fOut.open(QFile::WriteOnly | QFile::Truncate | QFile::Text)) {
		return 1;
	}

	fOut.write(outDoc.toJson());
	fOut.close();

	return 0;
}
<commit_msg>Fix missing E2E includes<commit_after>#include <QCommandLineParser>
#include <QCoreApplication>
#include <QFile>
#include <QJsonArray>
#include <QJsonDocument>
#include <QJsonObject>
#include <QStringList>
#include <QTimer>
#include "functions.h"
#include "logger.h"
#include "models/api/api.h"
#include "models/page.h"
#include "models/page-api.h"
#include "models/profile.h"
#include "models/site.h"
#include "models/source.h"
#include "tags/tag.h"

bool opCompare(const QString &op, int left, int right)
{
	if (right == -1) {
		return true;
	}
	if (op == ">") {
		return left > right;
	}
	if (op == "<") {
		return left < right;
	}
	return left == right;
}

bool jsonCompare(const QVariant &value, QJsonValue opt)
{
	QString op = "=";
	if (opt.isArray()) {
		QJsonArray arrOpt = opt.toArray();
		op = arrOpt[0].toString();
		opt = arrOpt[1];
	}

	if (value.type() == QVariant::String) {
		return value.toString() == opt.toString();
	}

	return opCompare(op, value.toInt(), opt.toInt());
}

int main(int argc, char *argv[])
{
	const QCoreApplication app(argc, argv);

	QCommandLineParser parser;
	parser.addHelpOption();

	const QCommandLineOption inputOption(QStringList() << "i" << "input", "Input JSON configuration file", "input");
	const QCommandLineOption outputOption(QStringList() << "o" << "output", "Output JSON result file", "output");
	parser.addOption(inputOption);
	parser.addOption(outputOption);
	parser.process(app);

	Logger::getInstance().setLogLevel(Logger::Warning);

	QFile f(parser.value(inputOption));
	if (!f.open(QFile::ReadOnly | QFile::Text)) {
		return 1;
	}

	QJsonObject allJson;
	QJsonDocument input = QJsonDocument::fromJson(f.readAll());
	f.close();

	Profile *profile = new Profile(savePath());
	auto allSources = profile->getSources();
	auto allSites = profile->getSites();

	const auto oldBlacklist = profile->getBlacklist();
	profile->setBlacklistedTags(Blacklist());

	const QJsonObject root = input.object();
	const QJsonArray rootSearch = root.value("search").toArray();
	const QJsonObject sources = root.value("sources").toObject();

	for (auto it = sources.constBegin(); it != sources.constEnd(); ++it) {
		const QString &sourceName = it.key();
		qDebug() << "#" << "Source" << sourceName;
		QJsonObject sourceJson;

		Source *source = allSources.value(sourceName);
		QJsonObject sites = it.value().toObject();

		const QJsonObject sourceApis = sites.value("apis").toObject();
		QJsonArray sourceSearch = rootSearch;
		if (sites.contains("search")) {
			sourceSearch = sites.value("search").toArray();
		}

		for (Site *site : source->getSites()) {
			qDebug() << "##" << "Site" << site->url();
			QJsonObject siteJson;

			QJsonObject siteApis = sourceApis;
			QJsonArray siteSearch = sourceSearch;
			if (sites.contains(site->url())) {
				QJsonObject override = sites.value(site->url()).toObject();
				if (override.contains("apis")) {
					siteApis = override.value("apis").toObject();
				}
				if (override.contains("search")) {
					siteSearch = override.value("search").toArray();
				}
			}

			for (auto ita = siteApis.constBegin(); ita != siteApis.constEnd(); ++ita) {
				const QString &apiName = ita.key();
				qDebug() << "###" << "API" << apiName;
				QJsonObject apiJson;
				QJsonArray checks = ita.value().toArray();

				QJsonArray apiSearch = siteSearch;
				if (checks.count() > 4) {
					apiSearch = checks[4].toArray();
				}

				const QString search = apiSearch[0].toString();
				const int pageI = apiSearch[1].toInt();
				const int limit = apiSearch[2].toInt();

				Api *api = nullptr;
				for (Api *a : site->getApis()) {
					if (a->getName().toLower() == apiName.toLower()) {
						api = a;
					}
				}
				if (api == nullptr) {
					continue;
				}

				auto page = new Page(profile, site, allSites.values(), QStringList() << search, pageI, limit);
				auto pageApi = new PageApi(page, profile, site, api, search.split(' '), pageI, limit);
				QEventLoop loop;
				QObject::connect(pageApi, &PageApi::finishedLoading, &loop, &QEventLoop::quit);
				QTimer::singleShot(1, pageApi, SLOT(load()));
				loop.exec();

				apiJson["status"] = "ok";
				QStringList message;

				// Checks
				if (!jsonCompare(pageApi->errors().join(", "), checks[0])) {
					apiJson["status"] = "error";
					message.append(pageApi->errors());
				}
				if (!jsonCompare(pageApi->imagesCount(false), checks[1])) {
					if (apiJson["status"] == "ok") {
						apiJson["status"] = "warning";
					}
					message.append("Image count error: " + QString::number(pageApi->imagesCount(false)));
				}
				if (!jsonCompare(pageApi->images().count(), checks[2])) {
					apiJson["status"] = "error";
					message.append("Number of images error: " + QString::number(pageApi->images().count()));
				}
				if (!jsonCompare(pageApi->tags().count(), checks[3])) {
					if (apiJson["status"] == "ok") {
						apiJson["status"] = "warning";
					}
					QStringList tags;
					for (const Tag& tag : pageApi->tags()) {
						tags.append(tag.text());
					}
					message.append("Number of tags error: " + QString::number(pageApi->tags().count()) + " [" + tags.join(", ") + "]");
				}

				if (!message.isEmpty()) {
					apiJson["message"] = message.join(", ");
					siteJson[apiName] = apiJson;
				} else {
					siteJson[apiName] = apiJson["status"];
				}

				pageApi->deleteLater();
				page->deleteLater();
			}
			sourceJson[site->url()] = siteJson;
		}
		allJson[sourceName] = sourceJson;
	}

	profile->setBlacklistedTags(oldBlacklist);

	QJsonDocument outDoc(allJson);
	QFile fOut(parser.value(outputOption));
	if (!fOut.open(QFile::WriteOnly | QFile::Truncate | QFile::Text)) {
		return 1;
	}

	fOut.write(outDoc.toJson());
	fOut.close();

	return 0;
}
<|endoftext|>


<commit_before><commit_msg>Avoid OS X sandbox messages when just checking if a pathname is a directory<commit_after><|endoftext|>


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

#include <configuration.hpp>
#include <CommandLine.hpp>
#include <Kernels.hpp>
#include <Memory.hpp>
#include <Pipeline.hpp>

int main(int argc, char * argv[]) {
  // Command line options
  Options options {};
  DeviceOptions deviceOptions {};
  DataOptions dataOptions {};
  GeneratorOptions generatorOptions {};
  // Memory
  HostMemory hostMemory {};
  DeviceMemory deviceMemory {};
  // OpenCL kernels
  OpenCLRunTime openclRunTime {};
  KernelConfigurations kernelConfigurations {};
  Kernels kernels {};
  KernelRunTimeConfigurations kernelRunTimeConfigurations {};
  // Timers
  Timers timers {};
  // Observation
  AstroData::Observation observation;

  // Process command line arguments
  isa::utils::ArgumentList args(argc, argv);
  try {
    processCommandLineOptions(args, options, deviceOptions, dataOptions, kernelConfigurations, generatorOptions,
                              observation);
  } catch ( std::exception & err ) {
    return 1;
  }

  // Load or generate input data
  try {
    try {
      hostMemory.zappedChannels.resize(observation.getNrChannels(deviceOptions.padding.at(deviceOptions.deviceName)
                                                                 / sizeof(unsigned int)));
    } catch ( std::out_of_range & err ) {
      std::cerr << "No padding specified for " << deviceOptions.deviceName << "." << std::endl;
      return 1;
    }
    try {
      AstroData::readZappedChannels(observation, dataOptions.channelsFile, hostMemory.zappedChannels);
      AstroData::readIntegrationSteps(observation, dataOptions.integrationFile, hostMemory.integrationSteps);
    } catch ( AstroData::FileError & err ) {
      std::cerr << err.what() << std::endl;
      return 1;
    }
    hostMemory.input.resize(observation.getNrBeams());
    if ( dataOptions.dataLOFAR || dataOptions.dataSIGPROC || dataOptions.dataPSRDADA ) {
      loadInput(observation, deviceOptions, dataOptions, hostMemory, timers);
    } else {
      for ( unsigned int beam = 0; beam < observation.getNrBeams(); beam++ ) {
        // TODO: if there are multiple synthesized beams, the generated data should take this into account
        hostMemory.input.at(beam) = new std::vector<std::vector<inputDataType> *>(observation.getNrBatches());
        AstroData::generateSinglePulse(generatorOptions.width, generatorOptions.DM, observation,
                                       deviceOptions.padding.at(deviceOptions.deviceName),
                                       *(hostMemory.input.at(beam)), inputBits, generatorOptions.random);
      }
    }
  } catch ( std::exception & err ) {
    std::cerr << err.what() << std::endl;
    return 1;
  }

  // Print message with observation and search information
  if ( options.print) {
    std::cout << "Device: " << deviceOptions.deviceName << "(" + std::to_string(deviceOptions.platformID) +  ", ";
    std::cout << std::to_string(deviceOptions.deviceID) + ")" << std::endl;
    std::cout << "Padding: " << deviceOptions.padding[deviceOptions.deviceName] << " bytes" << std::endl;
    std::cout << std::endl;
    std::cout << "Beams: " << observation.getNrBeams() << std::endl;
    std::cout << "Synthesized Beams: " << observation.getNrSynthesizedBeams() << std::endl;
    std::cout << "Batches: " << observation.getNrBatches() << std::endl;
    std::cout << "Samples: " << observation.getNrSamplesPerBatch() << std::endl;
    std::cout << "Sampling time: " << observation.getSamplingTime() << std::endl;
    std::cout << "Frequency range: " << observation.getMinFreq() << " MHz, " << observation.getMaxFreq() << " MHz";
    std::cout << std::endl;
    std::cout << "Subbands: " << observation.getNrSubbands() << " (" << observation.getSubbandBandwidth() << " MHz)";
    std::cout << std::endl;
    std::cout << "Channels: " << observation.getNrChannels() << " (" << observation.getChannelBandwidth() << " MHz)";
    std::cout << std::endl;
    std::cout << "Zapped Channels: " << observation.getNrZappedChannels() << std::endl;
    std::cout << "Integration steps: " << hostMemory.integrationSteps.size() << std::endl;
    if ( options.subbandDedispersion ) {
      std::cout << "Subbanding DMs: " << observation.getNrDMs(true) << " (" << observation.getFirstDM(true) << ", ";
      std::cout << observation.getFirstDM(true) + ((observation.getNrDMs(true) - 1) * observation.getDMStep(true));
      std::cout << ")" << std::endl;
    }
    std::cout << "DMs: " << observation.getNrDMs() << " (" << observation.getFirstDM() << ", ";
    std::cout << observation.getFirstDM() + ((observation.getNrDMs() - 1) * observation.getDMStep()) << ")";
    std::cout << std::endl;
    std::cout << std::endl;
  }

  // Initialize OpenCL
  openclRunTime.context = new cl::Context();
  openclRunTime.platforms = new std::vector<cl::Platform>();
  openclRunTime.devices = new std::vector<cl::Device>();
  openclRunTime.queues = new std::vector<std::vector<cl::CommandQueue>>();
  try {
    isa::OpenCL::initializeOpenCL(deviceOptions.platformID, 1, openclRunTime.platforms, openclRunTime.context,
                                  openclRunTime.devices, openclRunTime.queues);
  } catch ( isa::OpenCL::OpenCLError & err ) {
    std::cerr << err.what() << std::endl;
    return 1;
  }

  // Memory allocation
  allocateHostMemory(observation, options, deviceOptions, dataOptions, kernelConfigurations, hostMemory);
  if ( observation.getNrDelayBatches() > observation.getNrBatches() ) {
    std::cerr << "Not enough input batches for the specified search." << std::endl;
    return 1;
  }
  try {
    allocateDeviceMemory(openclRunTime, options, deviceOptions, hostMemory, deviceMemory);
  } catch ( cl::Error & err ) {
    std::cerr << "Memory error: " << err.what() << " " << err.err() << std::endl;
    return 1;
  }

  // Generate OpenCL kernels
  try {
    generateOpenCLKernels(openclRunTime, observation, options, deviceOptions, kernelConfigurations, hostMemory,
                          deviceMemory, kernels);
  } catch ( std::exception & err ) {
    std::cerr << "OpenCL code generation error: " << err.what() << std::endl;
    return 1;
  }

  // Generate run time configurations for the OpenCL kernels
  generateOpenCLRunTimeConfigurations(observation, options, deviceOptions, kernelConfigurations, hostMemory,
                                      kernelRunTimeConfigurations);

  // Search loop
  pipeline(openclRunTime, observation, options, deviceOptions, dataOptions, timers, kernels, kernelConfigurations,
           kernelRunTimeConfigurations, hostMemory, deviceMemory);

  // Store performance statistics before shutting down
  std::ofstream outputStats;
  outputStats.open(dataOptions.outputFile + ".stats");
  outputStats << std::fixed << std::setprecision(6);
  outputStats << "# nrDMs" << std::endl;
  if ( options.subbandDedispersion ) {
    outputStats << observation.getNrDMs(true) * observation.getNrDMs() << std::endl;
  } else {
    outputStats << observation.getNrDMs() << std::endl;
  }
  outputStats << "# timers.inputLoad" << std::endl;
  outputStats << timers.inputLoad.getTotalTime() << std::endl;
  outputStats << "# timers.search" << std::endl;
  outputStats << timers.search.getTotalTime() << std::endl;
  outputStats << "# inputHandlingTotal inputHandlingAvg err" << std::endl;
  outputStats << timers.inputHandling.getTotalTime() << " " << timers.inputHandling.getAverageTime() << " ";
  outputStats << timers.inputHandling.getStandardDeviation() << std::endl;
  outputStats << "# inputCopyTotal inputCopyAvg err" << std::endl;
  outputStats << timers.inputCopy.getTotalTime() << " " << timers.inputCopy.getAverageTime() << " ";
  outputStats << timers.inputCopy.getStandardDeviation() << std::endl;
  if ( ! options.subbandDedispersion ) {
    outputStats << "# dedispersionSingleStepTotal dedispersionSingleStepAvg err" << std::endl;
    outputStats << timers.dedispersionSingleStep.getTotalTime() << " ";
    outputStats << timers.dedispersionSingleStep.getAverageTime() << " ";
    outputStats << timers.dedispersionSingleStep.getStandardDeviation() << std::endl;
  } else {
    outputStats << "# dedispersionStepOneTotal dedispersionStepOneAvg err" << std::endl;
    outputStats << timers.dedispersionStepOne.getTotalTime() << " ";
    outputStats << timers.dedispersionStepOne.getAverageTime() << " ";
    outputStats << timers.dedispersionStepOne.getStandardDeviation() << std::endl;
    outputStats << "# dedispersionStepTwoTotal dedispersionStepTwoAvg err" << std::endl;
    outputStats << timers.dedispersionStepTwo.getTotalTime() << " ";
    outputStats << timers.dedispersionStepTwo.getAverageTime() << " ";
    outputStats << timers.dedispersionStepTwo.getStandardDeviation() << std::endl;
  }
  outputStats << "# integrationTotal integrationAvg err" << std::endl;
  outputStats << timers.integration.getTotalTime() << " " << timers.integration.getAverageTime() << " ";
  outputStats << timers.integration.getStandardDeviation() << std::endl;
  outputStats << "# snrTotal snrAvg err" << std::endl;
  outputStats << timers.snr.getTotalTime() << " " << timers.snr.getAverageTime() << " ";
  outputStats << timers.snr.getStandardDeviation() << std::endl;
  outputStats << "# outputCopyTotal outputCopyAvg err" << std::endl;
  outputStats << timers.outputCopy.getTotalTime() << " " << timers.outputCopy.getAverageTime() << " ";
  outputStats << timers.outputCopy.getStandardDeviation() << std::endl;
  outputStats << "# triggerTimeTotal triggerTimeAvg err" << std::endl;
  outputStats << timers.trigger.getTotalTime() << " " << timers.trigger.getAverageTime() << " ";
  outputStats << timers.trigger.getStandardDeviation() << std::endl;
  outputStats.close();

  return 0;
}

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

#include <configuration.hpp>
#include <CommandLine.hpp>
#include <Kernels.hpp>
#include <Memory.hpp>
#include <Pipeline.hpp>

int main(int argc, char * argv[]) {
  // Command line options
  Options options {};
  DeviceOptions deviceOptions {};
  DataOptions dataOptions {};
  GeneratorOptions generatorOptions {};
  // Memory
  HostMemory hostMemory {};
  DeviceMemory deviceMemory {};
  // OpenCL kernels
  OpenCLRunTime openclRunTime {};
  KernelConfigurations kernelConfigurations {};
  Kernels kernels {};
  KernelRunTimeConfigurations kernelRunTimeConfigurations {};
  // Timers
  Timers timers {};
  // Observation
  AstroData::Observation observation;

  // Process command line arguments
  isa::utils::ArgumentList args(argc, argv);
  try {
    processCommandLineOptions(args, options, deviceOptions, dataOptions, kernelConfigurations, generatorOptions,
                              observation);
  } catch ( std::exception & err ) {
    return 1;
  }

  // Load or generate input data
  try {
    try {
      hostMemory.zappedChannels.resize(observation.getNrChannels(deviceOptions.padding.at(deviceOptions.deviceName)
                                                                 / sizeof(unsigned int)));
    } catch ( std::out_of_range & err ) {
      std::cerr << "No padding specified for " << deviceOptions.deviceName << "." << std::endl;
      return 1;
    }
    try {
      AstroData::readZappedChannels(observation, dataOptions.channelsFile, hostMemory.zappedChannels);
      AstroData::readIntegrationSteps(observation, dataOptions.integrationFile, hostMemory.integrationSteps);
    } catch ( AstroData::FileError & err ) {
      std::cerr << err.what() << std::endl;
      return 1;
    }
    hostMemory.input.resize(observation.getNrBeams());
    if ( dataOptions.dataLOFAR || dataOptions.dataSIGPROC || dataOptions.dataPSRDADA ) {
      loadInput(observation, deviceOptions, dataOptions, hostMemory, timers);
    } else {
      for ( unsigned int beam = 0; beam < observation.getNrBeams(); beam++ ) {
        // TODO: if there are multiple synthesized beams, the generated data should take this into account
        hostMemory.input.at(beam) = new std::vector<std::vector<inputDataType> *>(observation.getNrBatches());
        AstroData::generateSinglePulse(generatorOptions.width, generatorOptions.DM, observation,
                                       deviceOptions.padding.at(deviceOptions.deviceName),
                                       *(hostMemory.input.at(beam)), inputBits, generatorOptions.random);
      }
    }
  } catch ( std::exception & err ) {
    std::cerr << err.what() << std::endl;
    return 1;
  }

  // Print message with observation and search information
  if ( options.print) {
    std::cout << "Device: " << deviceOptions.deviceName << " (" + std::to_string(deviceOptions.platformID) +  ", ";
    std::cout << std::to_string(deviceOptions.deviceID) + ")" << std::endl;
    std::cout << "Padding: " << deviceOptions.padding[deviceOptions.deviceName] << " bytes" << std::endl;
    std::cout << std::endl;
    std::cout << "Beams: " << observation.getNrBeams() << std::endl;
    std::cout << "Synthesized Beams: " << observation.getNrSynthesizedBeams() << std::endl;
    std::cout << "Batches: " << observation.getNrBatches() << std::endl;
    std::cout << "Samples: " << observation.getNrSamplesPerBatch() << std::endl;
    std::cout << "Sampling time: " << observation.getSamplingTime() << std::endl;
    std::cout << "Frequency range: " << observation.getMinFreq() << " MHz, " << observation.getMaxFreq() << " MHz";
    std::cout << std::endl;
    std::cout << "Subbands: " << observation.getNrSubbands() << " (" << observation.getSubbandBandwidth() << " MHz)";
    std::cout << std::endl;
    std::cout << "Channels: " << observation.getNrChannels() << " (" << observation.getChannelBandwidth() << " MHz)";
    std::cout << std::endl;
    std::cout << "Zapped Channels: " << observation.getNrZappedChannels() << std::endl;
    std::cout << "Integration steps: " << hostMemory.integrationSteps.size() << std::endl;
    if ( options.subbandDedispersion ) {
      std::cout << "Subbanding DMs: " << observation.getNrDMs(true) << " (" << observation.getFirstDM(true) << ", ";
      std::cout << observation.getFirstDM(true) + ((observation.getNrDMs(true) - 1) * observation.getDMStep(true));
      std::cout << ")" << std::endl;
    }
    std::cout << "DMs: " << observation.getNrDMs() << " (" << observation.getFirstDM() << ", ";
    std::cout << observation.getFirstDM() + ((observation.getNrDMs() - 1) * observation.getDMStep()) << ")";
    std::cout << std::endl;
    std::cout << std::endl;
  }

  // Initialize OpenCL
  openclRunTime.context = new cl::Context();
  openclRunTime.platforms = new std::vector<cl::Platform>();
  openclRunTime.devices = new std::vector<cl::Device>();
  openclRunTime.queues = new std::vector<std::vector<cl::CommandQueue>>();
  try {
    isa::OpenCL::initializeOpenCL(deviceOptions.platformID, 1, openclRunTime.platforms, openclRunTime.context,
                                  openclRunTime.devices, openclRunTime.queues);
  } catch ( isa::OpenCL::OpenCLError & err ) {
    std::cerr << err.what() << std::endl;
    return 1;
  }

  // Memory allocation
  allocateHostMemory(observation, options, deviceOptions, dataOptions, kernelConfigurations, hostMemory);
  if ( observation.getNrDelayBatches() > observation.getNrBatches() ) {
    std::cerr << "Not enough input batches for the specified search." << std::endl;
    return 1;
  }
  try {
    allocateDeviceMemory(openclRunTime, options, deviceOptions, hostMemory, deviceMemory);
  } catch ( cl::Error & err ) {
    std::cerr << "Memory error: " << err.what() << " " << err.err() << std::endl;
    return 1;
  }

  // Generate OpenCL kernels
  try {
    generateOpenCLKernels(openclRunTime, observation, options, deviceOptions, kernelConfigurations, hostMemory,
                          deviceMemory, kernels);
  } catch ( std::exception & err ) {
    std::cerr << "OpenCL code generation error: " << err.what() << std::endl;
    return 1;
  }

  // Generate run time configurations for the OpenCL kernels
  generateOpenCLRunTimeConfigurations(observation, options, deviceOptions, kernelConfigurations, hostMemory,
                                      kernelRunTimeConfigurations);

  // Search loop
  pipeline(openclRunTime, observation, options, deviceOptions, dataOptions, timers, kernels, kernelConfigurations,
           kernelRunTimeConfigurations, hostMemory, deviceMemory);

  // Store performance statistics before shutting down
  std::ofstream outputStats;
  outputStats.open(dataOptions.outputFile + ".stats");
  outputStats << std::fixed << std::setprecision(6);
  outputStats << "# nrDMs" << std::endl;
  if ( options.subbandDedispersion ) {
    outputStats << observation.getNrDMs(true) * observation.getNrDMs() << std::endl;
  } else {
    outputStats << observation.getNrDMs() << std::endl;
  }
  outputStats << "# timers.inputLoad" << std::endl;
  outputStats << timers.inputLoad.getTotalTime() << std::endl;
  outputStats << "# timers.search" << std::endl;
  outputStats << timers.search.getTotalTime() << std::endl;
  outputStats << "# inputHandlingTotal inputHandlingAvg err" << std::endl;
  outputStats << timers.inputHandling.getTotalTime() << " " << timers.inputHandling.getAverageTime() << " ";
  outputStats << timers.inputHandling.getStandardDeviation() << std::endl;
  outputStats << "# inputCopyTotal inputCopyAvg err" << std::endl;
  outputStats << timers.inputCopy.getTotalTime() << " " << timers.inputCopy.getAverageTime() << " ";
  outputStats << timers.inputCopy.getStandardDeviation() << std::endl;
  if ( ! options.subbandDedispersion ) {
    outputStats << "# dedispersionSingleStepTotal dedispersionSingleStepAvg err" << std::endl;
    outputStats << timers.dedispersionSingleStep.getTotalTime() << " ";
    outputStats << timers.dedispersionSingleStep.getAverageTime() << " ";
    outputStats << timers.dedispersionSingleStep.getStandardDeviation() << std::endl;
  } else {
    outputStats << "# dedispersionStepOneTotal dedispersionStepOneAvg err" << std::endl;
    outputStats << timers.dedispersionStepOne.getTotalTime() << " ";
    outputStats << timers.dedispersionStepOne.getAverageTime() << " ";
    outputStats << timers.dedispersionStepOne.getStandardDeviation() << std::endl;
    outputStats << "# dedispersionStepTwoTotal dedispersionStepTwoAvg err" << std::endl;
    outputStats << timers.dedispersionStepTwo.getTotalTime() << " ";
    outputStats << timers.dedispersionStepTwo.getAverageTime() << " ";
    outputStats << timers.dedispersionStepTwo.getStandardDeviation() << std::endl;
  }
  outputStats << "# integrationTotal integrationAvg err" << std::endl;
  outputStats << timers.integration.getTotalTime() << " " << timers.integration.getAverageTime() << " ";
  outputStats << timers.integration.getStandardDeviation() << std::endl;
  outputStats << "# snrTotal snrAvg err" << std::endl;
  outputStats << timers.snr.getTotalTime() << " " << timers.snr.getAverageTime() << " ";
  outputStats << timers.snr.getStandardDeviation() << std::endl;
  outputStats << "# outputCopyTotal outputCopyAvg err" << std::endl;
  outputStats << timers.outputCopy.getTotalTime() << " " << timers.outputCopy.getAverageTime() << " ";
  outputStats << timers.outputCopy.getStandardDeviation() << std::endl;
  outputStats << "# triggerTimeTotal triggerTimeAvg err" << std::endl;
  outputStats << timers.trigger.getTotalTime() << " " << timers.trigger.getAverageTime() << " ";
  outputStats << timers.trigger.getStandardDeviation() << std::endl;
  outputStats.close();

  return 0;
}

<|endoftext|>


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

//--------
// #include's
//--------
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "Config2Cpp.h"
#include "danek/Configuration.h"
#include "danek/SchemaValidator.h"

using namespace danek;

void calculateRuleForName(const Configuration* cfg, const char* name, const char* uName,
    const StringVector& wildcardedNamesAndTypes, StringBuffer& rule)
{
    rule.clear();
    int len = wildcardedNamesAndTypes.size();
    for (int i = 0; i < len; i += 3)
    {
        const char* keyword = wildcardedNamesAndTypes[i + 0].c_str(); // @optional or @required
        const char* wildcardedName = wildcardedNamesAndTypes[i + 1].c_str();
        const char* type = wildcardedNamesAndTypes[i + 2].c_str();
        if (Configuration::patternMatch(uName, wildcardedName))
        {
            rule << keyword << " " << uName << " = " << type;
            return;
        }
    }

    //--------
    // We couldn's determine the type from the wildcarded_names_and_types
    // table. So we fall back to using heuristics to guess a good type.
    //--------
    if (cfg->type("", name) == ConfType::Scope)
    {
        rule << uName << " = scope";
    }
    else if (cfg->type("", name) == ConfType::List)
    {
        rule << uName << " = list[string]";
    }
    else
    {
        const char* str = cfg->lookupString("", name);
        if (cfg->isBoolean(str))
        {
            rule << uName << " = boolean";
        }
        else if (cfg->isInt(str))
        {
            rule << uName << " = int";
        }
        else if (cfg->isFloat(str))
        {
            rule << uName << " = float";
        }
        else if (cfg->isDurationSeconds(str))
        {
            rule << uName << " = durationSeconds";
        }
        else if (cfg->isDurationMilliseconds(str))
        {
            rule << uName << " = durationMilliseconds";
        }
        else if (cfg->isDurationMicroseconds(str))
        {
            rule << uName << " = durationMicroseconds";
        }
        else if (cfg->isMemorySizeBytes(str))
        {
            rule << uName << " = memorySizeBytes";
        }
        else if (cfg->isMemorySizeKB(str))
        {
            rule << uName << " = memorySizeKB";
        }
        else if (cfg->isMemorySizeMB(str))
        {
            rule << uName << " = memorySizeMB";
        }
        else
        {
            rule << uName << " = string";
        }
    }
}

bool doesVectorcontainString(const StringVector& vec, const char* str)
{
    int i;
    int len;

    len = vec.size();
    for (i = 0; i < len; i++)
    {
        if (strcmp(vec[i].c_str(), str) == 0)
        {
            return true;
        }
    }
    return false;
}

void calculateSchema(const Configuration* cfg, const StringVector& namesList,
    const StringVector& recipeUserTypes, const StringVector& wildcardedNamesAndTypes,
    const StringVector& recipeIgnoreRules, StringVector& schema) throw(ConfigurationException)
{
    StringBuffer rule;
    StringBuffer buf;
    StringVector uidNames;

    schema.clear();

    for( const auto& str : recipeIgnoreRules )
    {
        schema.push_back(str);
    }

    for( const auto& str : recipeUserTypes )
    {
        schema.push_back(str);
    }

    int len = namesList.size();
    for (int i = 0; i < len; i++)
    {
        const char* name = namesList[i].c_str();
        if (strstr(name, "uid-") == nullptr)
        {
            calculateRuleForName(cfg, name, name, wildcardedNamesAndTypes, rule);
            schema.push_back(rule.str());
        }
        else
        {
            const char* uName = cfg->unexpandUid(name, buf);
            if (!doesVectorcontainString(uidNames, uName))
            {
                uidNames.push_back(uName);
                calculateRuleForName(cfg, name, uName, wildcardedNamesAndTypes, rule);
                schema.push_back(rule.str());
            }
        }
    }
}

bool doesPatternMatchAnyUnexpandedNameInList(
    const Configuration* cfg, const char* pattern, const StringVector& namesList)
{
    StringBuffer buf;

    int len = namesList.size();
    for (int i = 0; i < len; i++)
    {
        const char* uName = cfg->unexpandUid(namesList[i].c_str(), buf);
        if (Configuration::patternMatch(uName, pattern))
        {
            return true;
        }
    }
    return false;
}

void checkForUnmatchedPatterns(const Configuration* cfg, const StringVector& namesList,
    const StringVector& wildcardedNamesAndTypes,
    StringVector& unmatchedPatterns) throw(ConfigurationException)
{
    unmatchedPatterns.clear();
    //--------
    // Check if there is a wildcarded name that does not match anything
    //--------
    int len = wildcardedNamesAndTypes.size();
    for (int i = 0; i < len; i += 3)
    {
        const char* wildcardedName = wildcardedNamesAndTypes[i + 1].c_str();
        if (!doesPatternMatchAnyUnexpandedNameInList(cfg, wildcardedName, namesList))
        {
            unmatchedPatterns.push_back(wildcardedName);
        }
    }
}

//----------------------------------------------------------------------
// File: main()
//
// Description: Mainline of "config2cpp"
//----------------------------------------------------------------------

int main(int argc, char** argv)
{
    Config2Cpp util("config2cpp");
    StringVector namesList;
    StringVector recipeUserTypes;
    StringVector wildcardedNamesAndTypes;
    StringVector recipeIgnoreRules;
    StringVector unmatchedPatterns;
    StringVector schema;
    SchemaValidator sv;

    bool ok = util.parseCmdLineArgs(argc, argv);

    Configuration* cfg = Configuration::create();
    Configuration* schemaCfg = Configuration::create();
    if (ok && util.wantSchema())
    {
        try
        {
            cfg->parse(util.cfgFileName());
            cfg->listFullyScopedNames("", "", ConfType::ScopesAndVars, true, namesList);
            if (util.schemaOverrideCfg() != nullptr)
            {
                const char* overrideSchema[] = {
                    "@typedef keyword = enum[\"@optional\", \"@required\"]",
                    "user_types = list[string]",
                    "wildcarded_names_and_types = table[keyword,keyword, "
                    "string,wildcarded-name, string,type]",
                    "ignore_rules = list[string]",
                    nullptr // null-terminated array
                };

                schemaCfg->parse(util.schemaOverrideCfg());
                const char* scope = util.schemaOverrideScope();
                sv.parseSchema(overrideSchema);
                sv.validate(schemaCfg, scope, "");
                schemaCfg->lookupList(scope, "user_types", recipeUserTypes);
                schemaCfg->lookupList(scope, "wildcarded_names_and_types", wildcardedNamesAndTypes);
                schemaCfg->lookupList(scope, "ignore_rules", recipeIgnoreRules);
            }
            calculateSchema(
                cfg, namesList, recipeUserTypes, wildcardedNamesAndTypes, recipeIgnoreRules, schema);
            checkForUnmatchedPatterns(cfg, namesList, wildcardedNamesAndTypes, unmatchedPatterns);
        }
        catch (const ConfigurationException& ex)
        {
            fprintf(stderr, "%s\n", ex.c_str());
            ok = false;
        }
        int len = unmatchedPatterns.size();
        if (len != 0)
        {
            fprintf(stderr,
                "%s %s\n",
                "Error: the following patterns in the schema",
                "recipe did not match anything");
            for (int i = 0; i < len; i++)
            {
                fprintf(stderr, "\t'%s'\n", unmatchedPatterns[i].c_str());
            }
            ok = false;
        }
    }

    if (ok)
    {
        const auto data = schema.get();
        std::vector<const char*> buffer; // Deprecated conversion; kept for compatibility

        for( const auto& str : data )
        {
            buffer.push_back(&str.front());
        }

        ok = util.generateFiles(buffer.data(), buffer.size());
    }

    cfg->destroy();
    if (ok)
    {
        return 0;
    }
    else
    {
        return 1;
    }
}
<commit_msg>Exception specification removed.<commit_after>// Copyright (c) 2017 offa
// Copyright 2011 Ciaran McHale.
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions.
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

//--------
// #include's
//--------
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "Config2Cpp.h"
#include "danek/Configuration.h"
#include "danek/SchemaValidator.h"

using namespace danek;

void calculateRuleForName(const Configuration* cfg, const char* name, const char* uName,
    const StringVector& wildcardedNamesAndTypes, StringBuffer& rule)
{
    rule.clear();
    int len = wildcardedNamesAndTypes.size();
    for (int i = 0; i < len; i += 3)
    {
        const char* keyword = wildcardedNamesAndTypes[i + 0].c_str(); // @optional or @required
        const char* wildcardedName = wildcardedNamesAndTypes[i + 1].c_str();
        const char* type = wildcardedNamesAndTypes[i + 2].c_str();
        if (Configuration::patternMatch(uName, wildcardedName))
        {
            rule << keyword << " " << uName << " = " << type;
            return;
        }
    }

    //--------
    // We couldn's determine the type from the wildcarded_names_and_types
    // table. So we fall back to using heuristics to guess a good type.
    //--------
    if (cfg->type("", name) == ConfType::Scope)
    {
        rule << uName << " = scope";
    }
    else if (cfg->type("", name) == ConfType::List)
    {
        rule << uName << " = list[string]";
    }
    else
    {
        const char* str = cfg->lookupString("", name);
        if (cfg->isBoolean(str))
        {
            rule << uName << " = boolean";
        }
        else if (cfg->isInt(str))
        {
            rule << uName << " = int";
        }
        else if (cfg->isFloat(str))
        {
            rule << uName << " = float";
        }
        else if (cfg->isDurationSeconds(str))
        {
            rule << uName << " = durationSeconds";
        }
        else if (cfg->isDurationMilliseconds(str))
        {
            rule << uName << " = durationMilliseconds";
        }
        else if (cfg->isDurationMicroseconds(str))
        {
            rule << uName << " = durationMicroseconds";
        }
        else if (cfg->isMemorySizeBytes(str))
        {
            rule << uName << " = memorySizeBytes";
        }
        else if (cfg->isMemorySizeKB(str))
        {
            rule << uName << " = memorySizeKB";
        }
        else if (cfg->isMemorySizeMB(str))
        {
            rule << uName << " = memorySizeMB";
        }
        else
        {
            rule << uName << " = string";
        }
    }
}

bool doesVectorcontainString(const StringVector& vec, const char* str)
{
    int i;
    int len;

    len = vec.size();
    for (i = 0; i < len; i++)
    {
        if (strcmp(vec[i].c_str(), str) == 0)
        {
            return true;
        }
    }
    return false;
}

void calculateSchema(const Configuration* cfg, const StringVector& namesList,
    const StringVector& recipeUserTypes, const StringVector& wildcardedNamesAndTypes,
    const StringVector& recipeIgnoreRules, StringVector& schema)
{
    StringBuffer rule;
    StringBuffer buf;
    StringVector uidNames;

    schema.clear();

    for( const auto& str : recipeIgnoreRules )
    {
        schema.push_back(str);
    }

    for( const auto& str : recipeUserTypes )
    {
        schema.push_back(str);
    }

    int len = namesList.size();
    for (int i = 0; i < len; i++)
    {
        const char* name = namesList[i].c_str();
        if (strstr(name, "uid-") == nullptr)
        {
            calculateRuleForName(cfg, name, name, wildcardedNamesAndTypes, rule);
            schema.push_back(rule.str());
        }
        else
        {
            const char* uName = cfg->unexpandUid(name, buf);
            if (!doesVectorcontainString(uidNames, uName))
            {
                uidNames.push_back(uName);
                calculateRuleForName(cfg, name, uName, wildcardedNamesAndTypes, rule);
                schema.push_back(rule.str());
            }
        }
    }
}

bool doesPatternMatchAnyUnexpandedNameInList(
    const Configuration* cfg, const char* pattern, const StringVector& namesList)
{
    StringBuffer buf;

    int len = namesList.size();
    for (int i = 0; i < len; i++)
    {
        const char* uName = cfg->unexpandUid(namesList[i].c_str(), buf);
        if (Configuration::patternMatch(uName, pattern))
        {
            return true;
        }
    }
    return false;
}

void checkForUnmatchedPatterns(const Configuration* cfg, const StringVector& namesList,
    const StringVector& wildcardedNamesAndTypes,
    StringVector& unmatchedPatterns)
{
    unmatchedPatterns.clear();
    //--------
    // Check if there is a wildcarded name that does not match anything
    //--------
    int len = wildcardedNamesAndTypes.size();
    for (int i = 0; i < len; i += 3)
    {
        const char* wildcardedName = wildcardedNamesAndTypes[i + 1].c_str();
        if (!doesPatternMatchAnyUnexpandedNameInList(cfg, wildcardedName, namesList))
        {
            unmatchedPatterns.push_back(wildcardedName);
        }
    }
}

//----------------------------------------------------------------------
// File: main()
//
// Description: Mainline of "config2cpp"
//----------------------------------------------------------------------

int main(int argc, char** argv)
{
    Config2Cpp util("config2cpp");
    StringVector namesList;
    StringVector recipeUserTypes;
    StringVector wildcardedNamesAndTypes;
    StringVector recipeIgnoreRules;
    StringVector unmatchedPatterns;
    StringVector schema;
    SchemaValidator sv;

    bool ok = util.parseCmdLineArgs(argc, argv);

    Configuration* cfg = Configuration::create();
    Configuration* schemaCfg = Configuration::create();
    if (ok && util.wantSchema())
    {
        try
        {
            cfg->parse(util.cfgFileName());
            cfg->listFullyScopedNames("", "", ConfType::ScopesAndVars, true, namesList);
            if (util.schemaOverrideCfg() != nullptr)
            {
                const char* overrideSchema[] = {
                    "@typedef keyword = enum[\"@optional\", \"@required\"]",
                    "user_types = list[string]",
                    "wildcarded_names_and_types = table[keyword,keyword, "
                    "string,wildcarded-name, string,type]",
                    "ignore_rules = list[string]",
                    nullptr // null-terminated array
                };

                schemaCfg->parse(util.schemaOverrideCfg());
                const char* scope = util.schemaOverrideScope();
                sv.parseSchema(overrideSchema);
                sv.validate(schemaCfg, scope, "");
                schemaCfg->lookupList(scope, "user_types", recipeUserTypes);
                schemaCfg->lookupList(scope, "wildcarded_names_and_types", wildcardedNamesAndTypes);
                schemaCfg->lookupList(scope, "ignore_rules", recipeIgnoreRules);
            }
            calculateSchema(
                cfg, namesList, recipeUserTypes, wildcardedNamesAndTypes, recipeIgnoreRules, schema);
            checkForUnmatchedPatterns(cfg, namesList, wildcardedNamesAndTypes, unmatchedPatterns);
        }
        catch (const ConfigurationException& ex)
        {
            fprintf(stderr, "%s\n", ex.c_str());
            ok = false;
        }
        int len = unmatchedPatterns.size();
        if (len != 0)
        {
            fprintf(stderr,
                "%s %s\n",
                "Error: the following patterns in the schema",
                "recipe did not match anything");
            for (int i = 0; i < len; i++)
            {
                fprintf(stderr, "\t'%s'\n", unmatchedPatterns[i].c_str());
            }
            ok = false;
        }
    }

    if (ok)
    {
        const auto data = schema.get();
        std::vector<const char*> buffer; // Deprecated conversion; kept for compatibility

        for( const auto& str : data )
        {
            buffer.push_back(&str.front());
        }

        ok = util.generateFiles(buffer.data(), buffer.size());
    }

    cfg->destroy();
    if (ok)
    {
        return 0;
    }
    else
    {
        return 1;
    }
}
<|endoftext|>


<commit_before>#define BOOST_TEST_STATIC_LINK

#include <boost/test/unit_test.hpp>

#include <string>
#include <limits>
#include <stdexcept>

#include "./../../fixed_point_lib/src/number.hpp"

namespace utils { namespace unit_tests {
    namespace {
        using utils::SOU_number;
        using utils::UOU_number;
    }

    BOOST_AUTO_TEST_SUITE(Range)

    // FIXED-POINT RANGE TESTS
    //////////////////////////////////////////////////////////////////////////
    /// idea of test 'rangeFitBuiltinCheck':
    ///     checks if range of fixed-point of word length 8,16,32,64 is the same
    ///     as for built-in integers
    BOOST_AUTO_TEST_CASE(rangeFitBultinCheck)
    {
        typedef SOU_number<7, 6>::type type1;
        typedef UOU_number<16, 23>::type type2;
        typedef UOU_number<32, 12>::type type3;
        typedef UOU_number<64, 54>::type type4;
        typedef SOU_number<15, 12>::type type5;

        std::string const message("fixed-point has wrong range");
        typedef boost::int_t<8>::exact bit8_stype;
        BOOST_CHECK_MESSAGE(std::numeric_limits<bit8_stype>::max() == type1::bounds::max, message);
        BOOST_CHECK_MESSAGE(std::numeric_limits<bit8_stype>::min() == type1::bounds::min, message);

        typedef boost::uint_t<16>::exact bit16_utype;
        BOOST_CHECK_MESSAGE(std::numeric_limits<bit16_utype>::max() == type2::bounds::max, message);
        BOOST_CHECK_MESSAGE(std::numeric_limits<bit16_utype>::min() == type2::bounds::min, message);

        typedef boost::uint_t<32>::exact bit32_utype;
        BOOST_CHECK_MESSAGE(std::numeric_limits<bit32_utype>::max() == type3::bounds::max, message);
        BOOST_CHECK_MESSAGE(std::numeric_limits<bit32_utype>::min() == type3::bounds::min, message);

        typedef boost::uint_t<64>::exact bit64_utype;
        BOOST_CHECK_MESSAGE(std::numeric_limits<bit64_utype>::max() == type4::bounds::max, message);
        BOOST_CHECK_MESSAGE(std::numeric_limits<bit64_utype>::min() == type4::bounds::min, message);

        typedef boost::int_t<16>::exact bit16_stype;
        BOOST_CHECK_MESSAGE(std::numeric_limits<bit16_stype>::max() == type5::bounds::max, message);
        BOOST_CHECK_MESSAGE(std::numeric_limits<bit16_stype>::min() == type5::bounds::min, message);
    }

    /// idea of test 'outOfRangeCheck':
    ///     common checks if integer value (interpreted as fixed-point) is out
    ///     of range
    BOOST_AUTO_TEST_CASE(outOfRangeCheck)
    {
        typedef SOU_number<8, 13>::type type1;
        typedef UOU_number<13, 1>::type type2;

        std::string const message("Positive overflow was not detected");
        try {
            type1(300u);

            BOOST_FAIL(message);
        }
        catch (std::overflow_error e){}

        try {
            type2(10000u);

            BOOST_FAIL(message);
        }
        catch (std::overflow_error e){}

    }
    BOOST_AUTO_TEST_SUITE_END()
}}
<commit_msg>range_cases.cpp: refactoring due to changes in fixed_point.hpp<commit_after>#define BOOST_TEST_STATIC_LINK

#include <boost/test/unit_test.hpp>

#include <string>
#include <limits>
#include <stdexcept>

#include "./../../fixed_point_lib/src/fixed_point.hpp"

namespace core { namespace unit_tests {
    namespace {
        using core::SOU_fixed_point;
        using core::UOU_fixed_point;
    }

    BOOST_AUTO_TEST_SUITE(Range)

    // FIXED-POINT RANGE TESTS
    //////////////////////////////////////////////////////////////////////////
    /// idea of test 'rangeFitBuiltinCheck':
    ///     checks if range of fixed-point of word length 8,16,32,64 is the same
    ///     as for built-in integers
    BOOST_AUTO_TEST_CASE(rangeFitBultinCheck)
    {
        typedef SOU_fixed_point<7, 6>::type type1;
        typedef UOU_fixed_point<16, 23>::type type2;
        typedef UOU_fixed_point<32, 12>::type type3;
        typedef UOU_fixed_point<64, 54>::type type4;
        typedef SOU_fixed_point<15, 12>::type type5;

        std::string const message("fixed-point has wrong range");
        typedef boost::int_t<8>::exact bit8_stype;
        BOOST_CHECK_MESSAGE(std::numeric_limits<bit8_stype>::max() == type1::bounds::max, message);
        BOOST_CHECK_MESSAGE(std::numeric_limits<bit8_stype>::min() == type1::bounds::min, message);

        typedef boost::uint_t<16>::exact bit16_utype;
        BOOST_CHECK_MESSAGE(std::numeric_limits<bit16_utype>::max() == type2::bounds::max, message);
        BOOST_CHECK_MESSAGE(std::numeric_limits<bit16_utype>::min() == type2::bounds::min, message);

        typedef boost::uint_t<32>::exact bit32_utype;
        BOOST_CHECK_MESSAGE(std::numeric_limits<bit32_utype>::max() == type3::bounds::max, message);
        BOOST_CHECK_MESSAGE(std::numeric_limits<bit32_utype>::min() == type3::bounds::min, message);

        typedef boost::uint_t<64>::exact bit64_utype;
        BOOST_CHECK_MESSAGE(std::numeric_limits<bit64_utype>::max() == type4::bounds::max, message);
        BOOST_CHECK_MESSAGE(std::numeric_limits<bit64_utype>::min() == type4::bounds::min, message);

        typedef boost::int_t<16>::exact bit16_stype;
        BOOST_CHECK_MESSAGE(std::numeric_limits<bit16_stype>::max() == type5::bounds::max, message);
        BOOST_CHECK_MESSAGE(std::numeric_limits<bit16_stype>::min() == type5::bounds::min, message);
    }

    /// idea of test 'outOfRangeCheck':
    ///     common checks if integer value (interpreted as fixed-point) is out
    ///     of range
    BOOST_AUTO_TEST_CASE(outOfRangeCheck)
    {
        typedef SOU_fixed_point<8, 13>::type type1;
        typedef UOU_fixed_point<13, 1>::type type2;

        std::string const message("Positive overflow was not detected");
        try {
            type1(300u);

            BOOST_FAIL(message);
        }
        catch (std::overflow_error e){}

        try {
            type2(10000u);

            BOOST_FAIL(message);
        }
        catch (std::overflow_error e){}

    }
    BOOST_AUTO_TEST_SUITE_END()
}}
<|endoftext|>


<commit_before>// Interface for 2D Canvas element
//
// Copyright (C) 2012  Thomas Geymayer <tomgey@gmail.com>
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Library General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
//
// This library 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
// Library General Public License for more details.
//
// You should have received a copy of the GNU Library General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA

#include "CanvasElement.hxx"
#include <simgear/canvas/Canvas.hxx>
#include <simgear/canvas/CanvasEventListener.hxx>
#include <simgear/canvas/CanvasEventVisitor.hxx>
#include <simgear/canvas/MouseEvent.hxx>

#include <osg/Drawable>
#include <osg/Geode>
#include <osg/Scissor>

#include <boost/algorithm/string/predicate.hpp>
#include <boost/foreach.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/make_shared.hpp>
#include <boost/tokenizer.hpp>

#include <cassert>
#include <cstring>

namespace simgear
{
namespace canvas
{
  const std::string NAME_TRANSFORM = "tf";

  //----------------------------------------------------------------------------
  void Element::removeListener()
  {
    _node->removeChangeListener(this);
  }

  //----------------------------------------------------------------------------
  Element::~Element()
  {
    removeListener();

    BOOST_FOREACH(osg::Group* parent, _transform->getParents())
    {
      parent->removeChild(_transform);
    }
  }

  //----------------------------------------------------------------------------
  ElementWeakPtr Element::getWeakPtr() const
  {
    return boost::static_pointer_cast<Element>(_self.lock());
  }

  //----------------------------------------------------------------------------
  void Element::update(double dt)
  {
    if( !_transform->getNodeMask() )
      // Don't do anything if element is hidden
      return;

    if( _transform_dirty )
    {
      osg::Matrix m;
      for( size_t i = 0; i < _transform_types.size(); ++i )
      {
        // Skip unused indizes...
        if( _transform_types[i] == TT_NONE )
          continue;

        SGPropertyNode* tf_node = _node->getChild("tf", i, true);

        // Build up the matrix representation of the current transform node
        osg::Matrix tf;
        switch( _transform_types[i] )
        {
          case TT_MATRIX:
            tf = osg::Matrix( tf_node->getDoubleValue("m[0]", 1),
                              tf_node->getDoubleValue("m[1]", 0),
                              0,
                              tf_node->getDoubleValue("m[6]", 0),

                              tf_node->getDoubleValue("m[2]", 0),
                              tf_node->getDoubleValue("m[3]", 1),
                              0,
                              tf_node->getDoubleValue("m[7]", 0),

                              0,
                              0,
                              1,
                              0,

                              tf_node->getDoubleValue("m[4]", 0),
                              tf_node->getDoubleValue("m[5]", 0),
                              0,
                              tf_node->getDoubleValue("m[8]", 1) );
            break;
          case TT_TRANSLATE:
            tf.makeTranslate( osg::Vec3f( tf_node->getDoubleValue("t[0]", 0),
                                          tf_node->getDoubleValue("t[1]", 0),
                                          0 ) );
            break;
          case TT_ROTATE:
            tf.makeRotate( tf_node->getDoubleValue("rot", 0), 0, 0, 1 );
            break;
          case TT_SCALE:
          {
            float sx = tf_node->getDoubleValue("s[0]", 1);
            // sy defaults to sx...
            tf.makeScale( sx, tf_node->getDoubleValue("s[1]", sx), 1 );
            break;
          }
          default:
            break;
        }
        m.postMult( tf );
      }
      _transform->setMatrix(m);
      _transform_dirty = false;
    }
  }

  //----------------------------------------------------------------------------
  naRef Element::addEventListener(const nasal::CallContext& ctx)
  {
    const std::string type_str = ctx.requireArg<std::string>(0);
    naRef code = ctx.requireArg<naRef>(1);

    SG_LOG
    (
      SG_NASAL,
      SG_INFO,
      "addEventListener(" << _node->getPath() << ", " << type_str << ")"
    );

    Event::Type type = Event::strToType(type_str);
    if( type == Event::UNKNOWN )
      naRuntimeError( ctx.c,
                      "addEventListener: Unknown event type %s",
                      type_str.c_str() );

    _listener[ type ].push_back
    (
      boost::make_shared<EventListener>( code,
                                         _canvas.lock()->getSystemAdapter() )
    );

    return naNil();
  }

  //----------------------------------------------------------------------------
  bool Element::accept(EventVisitor& visitor)
  {
    return visitor.apply(*this);
  }

  //----------------------------------------------------------------------------
  bool Element::ascend(EventVisitor& visitor)
  {
    if( _parent )
      return _parent->accept(visitor);
    return true;
  }

  //----------------------------------------------------------------------------
  bool Element::traverse(EventVisitor& visitor)
  {
    return true;
  }

  //----------------------------------------------------------------------------
  void Element::callListeners(const canvas::EventPtr& event)
  {
    ListenerMap::iterator listeners = _listener.find(event->getType());
    if( listeners == _listener.end() )
      return;

    BOOST_FOREACH(EventListenerPtr listener, listeners->second)
      listener->call(event);
  }

  //----------------------------------------------------------------------------
  bool Element::hitBound( const osg::Vec2f& pos,
                          const osg::Vec2f& local_pos ) const
  {
    const osg::Vec3f pos3(pos, 0);

    // Drawables have a bounding box...
    if( _drawable )
    {
      if( !_drawable->getBound().contains(osg::Vec3f(local_pos, 0)) )
        return false;
    }
    // ... for other elements, i.e. groups only a bounding sphere is available
    else if( !_transform->getBound().contains(osg::Vec3f(pos, 0)) )
        return false;

    return true;
  }

  //----------------------------------------------------------------------------
  osg::ref_ptr<osg::MatrixTransform> Element::getMatrixTransform()
  {
    return _transform;
  }

  //----------------------------------------------------------------------------
  void Element::childAdded(SGPropertyNode* parent, SGPropertyNode* child)
  {
    if(    parent == _node
        && child->getNameString() == NAME_TRANSFORM )
    {
      if( child->getIndex() >= static_cast<int>(_transform_types.size()) )
        _transform_types.resize( child->getIndex() + 1 );

      _transform_types[ child->getIndex() ] = TT_NONE;
      _transform_dirty = true;
      return;
    }
    else if(    parent->getParent() == _node
             && parent->getNameString() == NAME_TRANSFORM )
    {
      assert(parent->getIndex() < static_cast<int>(_transform_types.size()));

      const std::string& name = child->getNameString();

      TransformType& type = _transform_types[parent->getIndex()];

      if(      name == "m" )
        type = TT_MATRIX;
      else if( name == "t" )
        type = TT_TRANSLATE;
      else if( name == "rot" )
        type = TT_ROTATE;
      else if( name == "s" )
        type = TT_SCALE;

      _transform_dirty = true;
      return;
    }

    childAdded(child);
  }

  //----------------------------------------------------------------------------
  void Element::childRemoved(SGPropertyNode* parent, SGPropertyNode* child)
  {
    if( parent == _node && child->getNameString() == NAME_TRANSFORM )
    {
      if( child->getIndex() >= static_cast<int>(_transform_types.size()) )
      {
        SG_LOG
        (
          SG_GENERAL,
          SG_WARN,
          "Element::childRemoved: unknown transform: " << child->getPath()
        );
        return;
      }

      _transform_types[ child->getIndex() ] = TT_NONE;

      while( !_transform_types.empty() && _transform_types.back() == TT_NONE )
        _transform_types.pop_back();

      _transform_dirty = true;
      return;
    }

    childRemoved(child);
  }

  //----------------------------------------------------------------------------
  void Element::valueChanged(SGPropertyNode* child)
  {
    SGPropertyNode *parent = child->getParent();
    if( parent == _node )
    {
      if( setStyle(child) )
        return;
      else if( child->getNameString() == "update" )
        return update(0);
      else if( child->getNameString() == "visible" )
        // TODO check if we need another nodemask
        return _transform->setNodeMask( child->getBoolValue() ? 0xffffffff : 0 );
    }
    else if(   parent->getParent() == _node
            && parent->getNameString() == NAME_TRANSFORM )
    {
      _transform_dirty = true;
      return;
    }

    childChanged(child);
  }

  //----------------------------------------------------------------------------
  bool Element::setStyle(const SGPropertyNode* child)
  {
    StyleSetters::const_iterator setter =
      _style_setters.find(child->getNameString());
    if( setter == _style_setters.end() )
      return false;

    setter->second(child);
    return true;
  }

  //----------------------------------------------------------------------------
  void Element::setClip(const std::string& clip)
  {
    if( clip.empty() || clip == "auto" )
    {
      getOrCreateStateSet()->removeAttribute(osg::StateAttribute::SCISSOR);
      return;
    }

    // TODO generalize CSS property parsing
    const std::string RECT("rect(");
    if(    !boost::ends_with(clip, ")")
        || !boost::starts_with(clip, RECT) )
    {
      SG_LOG(SG_GENERAL, SG_WARN, "Canvas: invalid clip: " << clip);
      return;
    }

    typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
    const boost::char_separator<char> del(", \t\npx");

    tokenizer tokens(clip.begin() + RECT.size(), clip.end() - 1, del);
    int comp = 0;
    int values[4];
    for( tokenizer::const_iterator tok = tokens.begin();
         tok != tokens.end() && comp < 4;
         ++tok, ++comp )
    {
      values[comp] = boost::lexical_cast<int>(*tok);
    }

    if( comp < 4 )
    {
      SG_LOG(SG_GENERAL, SG_WARN, "Canvas: invalid clip: " << clip);
      return;
    }

    float scale_x = 1,
          scale_y = 1;

    CanvasPtr canvas = _canvas.lock();
    if( canvas )
    {
      // The scissor rectangle isn't affected by any transformation, so we need
      // to convert to image/canvas coordinates on our selves.
      scale_x = canvas->getSizeX()
              / static_cast<float>(canvas->getViewWidth());
      scale_y = canvas->getSizeY()
              / static_cast<float>(canvas->getViewHeight());
    }

    osg::Scissor* scissor = new osg::Scissor();
    // <top>, <right>, <bottom>, <left>
    scissor->x() = scale_x * values[3];
    scissor->y() = scale_y * values[0];
    scissor->width() = scale_x * (values[1] - values[3]);
    scissor->height() = scale_y * (values[2] - values[0]);

    if( canvas )
      // Canvas has y axis upside down
      scissor->y() = canvas->getSizeY() - scissor->y() - scissor->height();

    getOrCreateStateSet()->setAttributeAndModes(scissor);
  }

  //----------------------------------------------------------------------------
  void Element::setBoundingBox(const osg::BoundingBox& bb)
  {
    if( _bounding_box.empty() )
    {
      SGPropertyNode* bb_node = _node->getChild("bounding-box", 0, true);
      _bounding_box.resize(4);
      _bounding_box[0] = bb_node->getChild("min-x", 0, true);
      _bounding_box[1] = bb_node->getChild("min-y", 0, true);
      _bounding_box[2] = bb_node->getChild("max-x", 0, true);
      _bounding_box[3] = bb_node->getChild("max-y", 0, true);
    }

    _bounding_box[0]->setFloatValue(bb._min.x());
    _bounding_box[1]->setFloatValue(bb._min.y());
    _bounding_box[2]->setFloatValue(bb._max.x());
    _bounding_box[3]->setFloatValue(bb._max.y());
  }

  //----------------------------------------------------------------------------
  osg::BoundingBox Element::getTransformedBounds(const osg::Matrix& m) const
  {
    return osg::BoundingBox();
  }

  //----------------------------------------------------------------------------
  Element::Element( const CanvasWeakPtr& canvas,
                    const SGPropertyNode_ptr& node,
                    const Style& parent_style,
                    Element* parent ):
    PropertyBasedElement(node),
    _canvas( canvas ),
    _parent( parent ),
    _transform_dirty( false ),
    _transform( new osg::MatrixTransform ),
    _style( parent_style ),
    _drawable( 0 )
  {
    SG_LOG
    (
      SG_GL,
      SG_DEBUG,
      "New canvas element " << node->getPath()
    );

    addStyle("clip", &Element::setClip, this);
  }

  //----------------------------------------------------------------------------
  void Element::setDrawable( osg::Drawable* drawable )
  {
    _drawable = drawable;
    assert( _drawable );

    osg::ref_ptr<osg::Geode> geode = new osg::Geode;
    geode->addDrawable(_drawable);
    _transform->addChild(geode);
  }

  //----------------------------------------------------------------------------
  osg::StateSet* Element::getOrCreateStateSet()
  {
    return _drawable ? _drawable->getOrCreateStateSet()
                     : _transform->getOrCreateStateSet();
  }

  //----------------------------------------------------------------------------
  void Element::setupStyle()
  {
    BOOST_FOREACH( Style::value_type style, _style )
      setStyle(style.second);
  }

} // namespace canvas
} // namespace simgear
<commit_msg>Canvas: Provide sane default bounding box (For Image & Text)<commit_after>// Interface for 2D Canvas element
//
// Copyright (C) 2012  Thomas Geymayer <tomgey@gmail.com>
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Library General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
//
// This library 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
// Library General Public License for more details.
//
// You should have received a copy of the GNU Library General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA

#include "CanvasElement.hxx"
#include <simgear/canvas/Canvas.hxx>
#include <simgear/canvas/CanvasEventListener.hxx>
#include <simgear/canvas/CanvasEventVisitor.hxx>
#include <simgear/canvas/MouseEvent.hxx>

#include <osg/Drawable>
#include <osg/Geode>
#include <osg/Scissor>

#include <boost/algorithm/string/predicate.hpp>
#include <boost/foreach.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/make_shared.hpp>
#include <boost/tokenizer.hpp>

#include <cassert>
#include <cstring>

namespace simgear
{
namespace canvas
{
  const std::string NAME_TRANSFORM = "tf";

  //----------------------------------------------------------------------------
  void Element::removeListener()
  {
    _node->removeChangeListener(this);
  }

  //----------------------------------------------------------------------------
  Element::~Element()
  {
    removeListener();

    BOOST_FOREACH(osg::Group* parent, _transform->getParents())
    {
      parent->removeChild(_transform);
    }
  }

  //----------------------------------------------------------------------------
  ElementWeakPtr Element::getWeakPtr() const
  {
    return boost::static_pointer_cast<Element>(_self.lock());
  }

  //----------------------------------------------------------------------------
  void Element::update(double dt)
  {
    if( !_transform->getNodeMask() )
      // Don't do anything if element is hidden
      return;

    if( _transform_dirty )
    {
      osg::Matrix m;
      for( size_t i = 0; i < _transform_types.size(); ++i )
      {
        // Skip unused indizes...
        if( _transform_types[i] == TT_NONE )
          continue;

        SGPropertyNode* tf_node = _node->getChild("tf", i, true);

        // Build up the matrix representation of the current transform node
        osg::Matrix tf;
        switch( _transform_types[i] )
        {
          case TT_MATRIX:
            tf = osg::Matrix( tf_node->getDoubleValue("m[0]", 1),
                              tf_node->getDoubleValue("m[1]", 0),
                              0,
                              tf_node->getDoubleValue("m[6]", 0),

                              tf_node->getDoubleValue("m[2]", 0),
                              tf_node->getDoubleValue("m[3]", 1),
                              0,
                              tf_node->getDoubleValue("m[7]", 0),

                              0,
                              0,
                              1,
                              0,

                              tf_node->getDoubleValue("m[4]", 0),
                              tf_node->getDoubleValue("m[5]", 0),
                              0,
                              tf_node->getDoubleValue("m[8]", 1) );
            break;
          case TT_TRANSLATE:
            tf.makeTranslate( osg::Vec3f( tf_node->getDoubleValue("t[0]", 0),
                                          tf_node->getDoubleValue("t[1]", 0),
                                          0 ) );
            break;
          case TT_ROTATE:
            tf.makeRotate( tf_node->getDoubleValue("rot", 0), 0, 0, 1 );
            break;
          case TT_SCALE:
          {
            float sx = tf_node->getDoubleValue("s[0]", 1);
            // sy defaults to sx...
            tf.makeScale( sx, tf_node->getDoubleValue("s[1]", sx), 1 );
            break;
          }
          default:
            break;
        }
        m.postMult( tf );
      }
      _transform->setMatrix(m);
      _transform_dirty = false;
    }
  }

  //----------------------------------------------------------------------------
  naRef Element::addEventListener(const nasal::CallContext& ctx)
  {
    const std::string type_str = ctx.requireArg<std::string>(0);
    naRef code = ctx.requireArg<naRef>(1);

    SG_LOG
    (
      SG_NASAL,
      SG_INFO,
      "addEventListener(" << _node->getPath() << ", " << type_str << ")"
    );

    Event::Type type = Event::strToType(type_str);
    if( type == Event::UNKNOWN )
      naRuntimeError( ctx.c,
                      "addEventListener: Unknown event type %s",
                      type_str.c_str() );

    _listener[ type ].push_back
    (
      boost::make_shared<EventListener>( code,
                                         _canvas.lock()->getSystemAdapter() )
    );

    return naNil();
  }

  //----------------------------------------------------------------------------
  bool Element::accept(EventVisitor& visitor)
  {
    return visitor.apply(*this);
  }

  //----------------------------------------------------------------------------
  bool Element::ascend(EventVisitor& visitor)
  {
    if( _parent )
      return _parent->accept(visitor);
    return true;
  }

  //----------------------------------------------------------------------------
  bool Element::traverse(EventVisitor& visitor)
  {
    return true;
  }

  //----------------------------------------------------------------------------
  void Element::callListeners(const canvas::EventPtr& event)
  {
    ListenerMap::iterator listeners = _listener.find(event->getType());
    if( listeners == _listener.end() )
      return;

    BOOST_FOREACH(EventListenerPtr listener, listeners->second)
      listener->call(event);
  }

  //----------------------------------------------------------------------------
  bool Element::hitBound( const osg::Vec2f& pos,
                          const osg::Vec2f& local_pos ) const
  {
    const osg::Vec3f pos3(pos, 0);

    // Drawables have a bounding box...
    if( _drawable )
    {
      if( !_drawable->getBound().contains(osg::Vec3f(local_pos, 0)) )
        return false;
    }
    // ... for other elements, i.e. groups only a bounding sphere is available
    else if( !_transform->getBound().contains(osg::Vec3f(pos, 0)) )
        return false;

    return true;
  }

  //----------------------------------------------------------------------------
  osg::ref_ptr<osg::MatrixTransform> Element::getMatrixTransform()
  {
    return _transform;
  }

  //----------------------------------------------------------------------------
  void Element::childAdded(SGPropertyNode* parent, SGPropertyNode* child)
  {
    if(    parent == _node
        && child->getNameString() == NAME_TRANSFORM )
    {
      if( child->getIndex() >= static_cast<int>(_transform_types.size()) )
        _transform_types.resize( child->getIndex() + 1 );

      _transform_types[ child->getIndex() ] = TT_NONE;
      _transform_dirty = true;
      return;
    }
    else if(    parent->getParent() == _node
             && parent->getNameString() == NAME_TRANSFORM )
    {
      assert(parent->getIndex() < static_cast<int>(_transform_types.size()));

      const std::string& name = child->getNameString();

      TransformType& type = _transform_types[parent->getIndex()];

      if(      name == "m" )
        type = TT_MATRIX;
      else if( name == "t" )
        type = TT_TRANSLATE;
      else if( name == "rot" )
        type = TT_ROTATE;
      else if( name == "s" )
        type = TT_SCALE;

      _transform_dirty = true;
      return;
    }

    childAdded(child);
  }

  //----------------------------------------------------------------------------
  void Element::childRemoved(SGPropertyNode* parent, SGPropertyNode* child)
  {
    if( parent == _node && child->getNameString() == NAME_TRANSFORM )
    {
      if( child->getIndex() >= static_cast<int>(_transform_types.size()) )
      {
        SG_LOG
        (
          SG_GENERAL,
          SG_WARN,
          "Element::childRemoved: unknown transform: " << child->getPath()
        );
        return;
      }

      _transform_types[ child->getIndex() ] = TT_NONE;

      while( !_transform_types.empty() && _transform_types.back() == TT_NONE )
        _transform_types.pop_back();

      _transform_dirty = true;
      return;
    }

    childRemoved(child);
  }

  //----------------------------------------------------------------------------
  void Element::valueChanged(SGPropertyNode* child)
  {
    SGPropertyNode *parent = child->getParent();
    if( parent == _node )
    {
      if( setStyle(child) )
        return;
      else if( child->getNameString() == "update" )
        return update(0);
      else if( child->getNameString() == "visible" )
        // TODO check if we need another nodemask
        return _transform->setNodeMask( child->getBoolValue() ? 0xffffffff : 0 );
    }
    else if(   parent->getParent() == _node
            && parent->getNameString() == NAME_TRANSFORM )
    {
      _transform_dirty = true;
      return;
    }

    childChanged(child);
  }

  //----------------------------------------------------------------------------
  bool Element::setStyle(const SGPropertyNode* child)
  {
    StyleSetters::const_iterator setter =
      _style_setters.find(child->getNameString());
    if( setter == _style_setters.end() )
      return false;

    setter->second(child);
    return true;
  }

  //----------------------------------------------------------------------------
  void Element::setClip(const std::string& clip)
  {
    if( clip.empty() || clip == "auto" )
    {
      getOrCreateStateSet()->removeAttribute(osg::StateAttribute::SCISSOR);
      return;
    }

    // TODO generalize CSS property parsing
    const std::string RECT("rect(");
    if(    !boost::ends_with(clip, ")")
        || !boost::starts_with(clip, RECT) )
    {
      SG_LOG(SG_GENERAL, SG_WARN, "Canvas: invalid clip: " << clip);
      return;
    }

    typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
    const boost::char_separator<char> del(", \t\npx");

    tokenizer tokens(clip.begin() + RECT.size(), clip.end() - 1, del);
    int comp = 0;
    int values[4];
    for( tokenizer::const_iterator tok = tokens.begin();
         tok != tokens.end() && comp < 4;
         ++tok, ++comp )
    {
      values[comp] = boost::lexical_cast<int>(*tok);
    }

    if( comp < 4 )
    {
      SG_LOG(SG_GENERAL, SG_WARN, "Canvas: invalid clip: " << clip);
      return;
    }

    float scale_x = 1,
          scale_y = 1;

    CanvasPtr canvas = _canvas.lock();
    if( canvas )
    {
      // The scissor rectangle isn't affected by any transformation, so we need
      // to convert to image/canvas coordinates on our selves.
      scale_x = canvas->getSizeX()
              / static_cast<float>(canvas->getViewWidth());
      scale_y = canvas->getSizeY()
              / static_cast<float>(canvas->getViewHeight());
    }

    osg::Scissor* scissor = new osg::Scissor();
    // <top>, <right>, <bottom>, <left>
    scissor->x() = scale_x * values[3];
    scissor->y() = scale_y * values[0];
    scissor->width() = scale_x * (values[1] - values[3]);
    scissor->height() = scale_y * (values[2] - values[0]);

    if( canvas )
      // Canvas has y axis upside down
      scissor->y() = canvas->getSizeY() - scissor->y() - scissor->height();

    getOrCreateStateSet()->setAttributeAndModes(scissor);
  }

  //----------------------------------------------------------------------------
  void Element::setBoundingBox(const osg::BoundingBox& bb)
  {
    if( _bounding_box.empty() )
    {
      SGPropertyNode* bb_node = _node->getChild("bounding-box", 0, true);
      _bounding_box.resize(4);
      _bounding_box[0] = bb_node->getChild("min-x", 0, true);
      _bounding_box[1] = bb_node->getChild("min-y", 0, true);
      _bounding_box[2] = bb_node->getChild("max-x", 0, true);
      _bounding_box[3] = bb_node->getChild("max-y", 0, true);
    }

    _bounding_box[0]->setFloatValue(bb._min.x());
    _bounding_box[1]->setFloatValue(bb._min.y());
    _bounding_box[2]->setFloatValue(bb._max.x());
    _bounding_box[3]->setFloatValue(bb._max.y());
  }

  //----------------------------------------------------------------------------
  osg::BoundingBox Element::getTransformedBounds(const osg::Matrix& m) const
  {
    if( !_drawable )
      return osg::BoundingBox();

    osg::BoundingBox transformed;
    const osg::BoundingBox& bb = _drawable->getBound();
    for(int i = 0; i < 4; ++i)
      transformed.expandBy( m * bb.corner(i) );

    return transformed;
  }

  //----------------------------------------------------------------------------
  Element::Element( const CanvasWeakPtr& canvas,
                    const SGPropertyNode_ptr& node,
                    const Style& parent_style,
                    Element* parent ):
    PropertyBasedElement(node),
    _canvas( canvas ),
    _parent( parent ),
    _transform_dirty( false ),
    _transform( new osg::MatrixTransform ),
    _style( parent_style ),
    _drawable( 0 )
  {
    SG_LOG
    (
      SG_GL,
      SG_DEBUG,
      "New canvas element " << node->getPath()
    );

    addStyle("clip", &Element::setClip, this);
  }

  //----------------------------------------------------------------------------
  void Element::setDrawable( osg::Drawable* drawable )
  {
    _drawable = drawable;
    assert( _drawable );

    osg::ref_ptr<osg::Geode> geode = new osg::Geode;
    geode->addDrawable(_drawable);
    _transform->addChild(geode);
  }

  //----------------------------------------------------------------------------
  osg::StateSet* Element::getOrCreateStateSet()
  {
    return _drawable ? _drawable->getOrCreateStateSet()
                     : _transform->getOrCreateStateSet();
  }

  //----------------------------------------------------------------------------
  void Element::setupStyle()
  {
    BOOST_FOREACH( Style::value_type style, _style )
      setStyle(style.second);
  }

} // namespace canvas
} // namespace simgear
<|endoftext|>


<commit_before>/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB

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

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

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */

/* Read language depeneded messagefile */

#include "mysql_priv.h"
#include "mysys_err.h"

static void read_texts(const char *file_name,const char ***point,
		       uint error_messages);
static void init_myfunc_errs(void);

	/* Read messages from errorfile */

void init_errmessage(void)
{
  DBUG_ENTER("init_errmessage");

  read_texts(ERRMSG_FILE,&my_errmsg[ERRMAPP],ER_ERROR_MESSAGES);
  errmesg=my_errmsg[ERRMAPP];		/* Init global variabel */
  init_myfunc_errs();			/* Init myfunc messages */
  DBUG_VOID_RETURN;
}

	/* Read text from packed textfile in language-directory */
	/* If we can't read messagefile then it's panic- we can't continue */

static void read_texts(const char *file_name,const char ***point,
		       uint error_messages)
{
  register uint i;
  uint count,funktpos,length,textcount;
  File file;
  char name[FN_REFLEN];
  const char *buff;
  uchar head[32],*pos;
  CHARSET_INFO *cset;
  DBUG_ENTER("read_texts");

  *point=0;					// If something goes wrong
  LINT_INIT(buff);
  funktpos=0;
  if ((file=my_open(fn_format(name,file_name,language,"",4),
		    O_RDONLY | O_SHARE | O_BINARY,
		    MYF(0))) < 0)
    goto err; /* purecov: inspected */

  funktpos=1;
  if (my_read(file,(byte*) head,32,MYF(MY_NABP))) goto err;
  if (head[0] != (uchar) 254 || head[1] != (uchar) 254 ||
      head[2] != 2 || head[3] != 1)
    goto err; /* purecov: inspected */
  textcount=head[4];

  if (!head[30])
  {
    sql_print_error("No character set information in '%s'. \
You probably haven't reinstalled the latest file version.",name);
    goto err1;
  }

  if (!(cset= get_charset(head[30],MYF(MY_WME))))
  {
    sql_print_error("Character set #%d is not supported for messagefile '%s'",
                    (int)head[30],name);
    goto err1;
  }

  length=uint2korr(head+6); count=uint2korr(head+8);

  if (count < error_messages)
  {
    sql_print_error("\
Error message file '%s' had only %d error messages,\n\
but it should contain at least %d error messages.\n\
Check that the above file is the right version for this program!",
		    name,count,error_messages);
    VOID(my_close(file,MYF(MY_WME)));
    unireg_abort(1);
  }

  x_free((gptr) *point);		/* Free old language */
  if (!(*point= (const char**)
	my_malloc((uint) (length+count*sizeof(char*)),MYF(0))))
  {
    funktpos=2;					/* purecov: inspected */
    goto err;					/* purecov: inspected */
  }
  buff= (char*) (*point + count);

  if (my_read(file,(byte*) buff,(uint) count*2,MYF(MY_NABP))) goto err;
  for (i=0, pos= (uchar*) buff ; i< count ; i++)
  {
    (*point)[i]=buff+uint2korr(pos);
    pos+=2;
  }
  if (my_read(file,(byte*) buff,(uint) length,MYF(MY_NABP))) goto err;

  for (i=1 ; i < textcount ; i++)
  {
    point[i]= *point +uint2korr(head+10+i+i);
  }
  VOID(my_close(file,MYF(0)));
  DBUG_VOID_RETURN;

err:
  switch (funktpos) {
  case 2:
    buff="Not enough memory for messagefile '%s'";
    break;
  case 1:
    buff="Can't read from messagefile '%s'";
    break;
  default:
    buff="Can't find messagefile '%s'";
    break;
  }
  sql_print_error(buff,name);
err1:
  if (file != FERR)
    VOID(my_close(file,MYF(MY_WME)));
  unireg_abort(1);
} /* read_texts */

	/* Initiates error-messages used by my_func-library */

static void init_myfunc_errs()
{
  init_glob_errs();			/* Initiate english errors */
  if (!(specialflag & SPECIAL_ENGLISH))
  {
    globerrs[EE_FILENOTFOUND % ERRMOD]	= ER(ER_FILE_NOT_FOUND);
    globerrs[EE_CANTCREATEFILE % ERRMOD]= ER(ER_CANT_CREATE_FILE);
    globerrs[EE_READ % ERRMOD]		= ER(ER_ERROR_ON_READ);
    globerrs[EE_WRITE % ERRMOD]		= ER(ER_ERROR_ON_WRITE);
    globerrs[EE_BADCLOSE % ERRMOD]	= ER(ER_ERROR_ON_CLOSE);
    globerrs[EE_OUTOFMEMORY % ERRMOD]	= ER(ER_OUTOFMEMORY);
    globerrs[EE_DELETE % ERRMOD]	= ER(ER_CANT_DELETE_FILE);
    globerrs[EE_LINK % ERRMOD]		= ER(ER_ERROR_ON_RENAME);
    globerrs[EE_EOFERR % ERRMOD]	= ER(ER_UNEXPECTED_EOF);
    globerrs[EE_CANTLOCK % ERRMOD]	= ER(ER_CANT_LOCK);
    globerrs[EE_DIR % ERRMOD]		= ER(ER_CANT_READ_DIR);
    globerrs[EE_STAT % ERRMOD]		= ER(ER_CANT_GET_STAT);
    globerrs[EE_GETWD % ERRMOD]		= ER(ER_CANT_GET_WD);
    globerrs[EE_SETWD % ERRMOD]		= ER(ER_CANT_SET_WD);
    globerrs[EE_DISK_FULL % ERRMOD]	= ER(ER_DISK_FULL);
  }
}
<commit_msg>derror.cc:   Better English message<commit_after>/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB

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

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

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */

/* Read language depeneded messagefile */

#include "mysql_priv.h"
#include "mysys_err.h"

static void read_texts(const char *file_name,const char ***point,
		       uint error_messages);
static void init_myfunc_errs(void);

	/* Read messages from errorfile */

void init_errmessage(void)
{
  DBUG_ENTER("init_errmessage");

  read_texts(ERRMSG_FILE,&my_errmsg[ERRMAPP],ER_ERROR_MESSAGES);
  errmesg=my_errmsg[ERRMAPP];		/* Init global variabel */
  init_myfunc_errs();			/* Init myfunc messages */
  DBUG_VOID_RETURN;
}

	/* Read text from packed textfile in language-directory */
	/* If we can't read messagefile then it's panic- we can't continue */

static void read_texts(const char *file_name,const char ***point,
		       uint error_messages)
{
  register uint i;
  uint count,funktpos,length,textcount;
  File file;
  char name[FN_REFLEN];
  const char *buff;
  uchar head[32],*pos;
  CHARSET_INFO *cset;
  DBUG_ENTER("read_texts");

  *point=0;					// If something goes wrong
  LINT_INIT(buff);
  funktpos=0;
  if ((file=my_open(fn_format(name,file_name,language,"",4),
		    O_RDONLY | O_SHARE | O_BINARY,
		    MYF(0))) < 0)
    goto err; /* purecov: inspected */

  funktpos=1;
  if (my_read(file,(byte*) head,32,MYF(MY_NABP))) goto err;
  if (head[0] != (uchar) 254 || head[1] != (uchar) 254 ||
      head[2] != 2 || head[3] != 1)
    goto err; /* purecov: inspected */
  textcount=head[4];

  if (!head[30])
  {
    sql_print_error("Character set information in not found in '%s'. \
Please install the latest version of this file.",name);
    goto err1;
  }

  if (!(cset= get_charset(head[30],MYF(MY_WME))))
  {
    sql_print_error("Character set #%d is not supported for messagefile '%s'",
                    (int)head[30],name);
    goto err1;
  }

  length=uint2korr(head+6); count=uint2korr(head+8);

  if (count < error_messages)
  {
    sql_print_error("\
Error message file '%s' had only %d error messages,\n\
but it should contain at least %d error messages.\n\
Check that the above file is the right version for this program!",
		    name,count,error_messages);
    VOID(my_close(file,MYF(MY_WME)));
    unireg_abort(1);
  }

  x_free((gptr) *point);		/* Free old language */
  if (!(*point= (const char**)
	my_malloc((uint) (length+count*sizeof(char*)),MYF(0))))
  {
    funktpos=2;					/* purecov: inspected */
    goto err;					/* purecov: inspected */
  }
  buff= (char*) (*point + count);

  if (my_read(file,(byte*) buff,(uint) count*2,MYF(MY_NABP))) goto err;
  for (i=0, pos= (uchar*) buff ; i< count ; i++)
  {
    (*point)[i]=buff+uint2korr(pos);
    pos+=2;
  }
  if (my_read(file,(byte*) buff,(uint) length,MYF(MY_NABP))) goto err;

  for (i=1 ; i < textcount ; i++)
  {
    point[i]= *point +uint2korr(head+10+i+i);
  }
  VOID(my_close(file,MYF(0)));
  DBUG_VOID_RETURN;

err:
  switch (funktpos) {
  case 2:
    buff="Not enough memory for messagefile '%s'";
    break;
  case 1:
    buff="Can't read from messagefile '%s'";
    break;
  default:
    buff="Can't find messagefile '%s'";
    break;
  }
  sql_print_error(buff,name);
err1:
  if (file != FERR)
    VOID(my_close(file,MYF(MY_WME)));
  unireg_abort(1);
} /* read_texts */

	/* Initiates error-messages used by my_func-library */

static void init_myfunc_errs()
{
  init_glob_errs();			/* Initiate english errors */
  if (!(specialflag & SPECIAL_ENGLISH))
  {
    globerrs[EE_FILENOTFOUND % ERRMOD]	= ER(ER_FILE_NOT_FOUND);
    globerrs[EE_CANTCREATEFILE % ERRMOD]= ER(ER_CANT_CREATE_FILE);
    globerrs[EE_READ % ERRMOD]		= ER(ER_ERROR_ON_READ);
    globerrs[EE_WRITE % ERRMOD]		= ER(ER_ERROR_ON_WRITE);
    globerrs[EE_BADCLOSE % ERRMOD]	= ER(ER_ERROR_ON_CLOSE);
    globerrs[EE_OUTOFMEMORY % ERRMOD]	= ER(ER_OUTOFMEMORY);
    globerrs[EE_DELETE % ERRMOD]	= ER(ER_CANT_DELETE_FILE);
    globerrs[EE_LINK % ERRMOD]		= ER(ER_ERROR_ON_RENAME);
    globerrs[EE_EOFERR % ERRMOD]	= ER(ER_UNEXPECTED_EOF);
    globerrs[EE_CANTLOCK % ERRMOD]	= ER(ER_CANT_LOCK);
    globerrs[EE_DIR % ERRMOD]		= ER(ER_CANT_READ_DIR);
    globerrs[EE_STAT % ERRMOD]		= ER(ER_CANT_GET_STAT);
    globerrs[EE_GETWD % ERRMOD]		= ER(ER_CANT_GET_WD);
    globerrs[EE_SETWD % ERRMOD]		= ER(ER_CANT_SET_WD);
    globerrs[EE_DISK_FULL % ERRMOD]	= ER(ER_DISK_FULL);
  }
}
<|endoftext|>