<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 <CommandLine.hpp>

void processCommandLineOptions(isa::utils::ArgumentList & argumentList, Options & options, DeviceOptions & deviceOptions, DataOptions & dataOptions, Configurations & configurations, GeneratorOptions & generatorOptions, AstroData::Observation & observation) {
  try {
    options.print = argumentList.getSwitch("-print");
    options.subbandDedispersion = argumentList.getSwitch("-subband_dedispersion");
    options.compactResults = argumentList.getSwitch("-compact_results");
    options.threshold = argumentList.getSwitchArgument<float>("-threshold");
    deviceOptions.platformID = argumentList.getSwitchArgument<unsigned int>("-opencl_platform");
    deviceOptions.deviceID = argumentList.getSwitchArgument<unsigned int>("-opencl_device");
    deviceOptions.deviceName = argumentList.getSwitchArgument<std::string>("-device_name");
    AstroData::readPaddingConf(deviceOptions.padding, argumentList.getSwitchArgument<std::string>("-padding_file"));
    dataOptions.dataLOFAR = argumentList.getSwitch("-lofar");
#ifndef HAVE_HDF5
    if (dataOptions.dataLOFAR) {
      std::cerr << "Not compiled with HDF5 support." << std::endl;
      throw std::exception();
    };
#endif // HAVE_HDF5
    dataOptions.dataPSRDADA = argumentList.getSwitch("-dada");
#ifndef HAVE_PSRDADA
    if (dataOptions.dataPSRDADA) {
      std::cerr << "Not compiled with PSRDADA support." << std::endl;
      throw std::exception();
    };
#endif // HAVE_PSRDADA
    dataOptions.dataSIGPROC = argumentList.getSwitch("-sigproc");
    if ( !((((!(dataOptions.dataLOFAR && dataOptions.dataSIGPROC) && dataOptions.dataPSRDADA) || (!(dataOptions.dataLOFAR && dataOptions.dataPSRDADA) && dataOptions.dataSIGPROC)) || (!(dataOptions.dataSIGPROC && dataOptions.dataPSRDADA) && dataOptions.dataLOFAR)) || ((!dataOptions.dataLOFAR && !dataOptions.dataSIGPROC) && !dataOptions.dataPSRDADA)) ) {
      std::cerr << "-lofar -sigproc and -dada are mutually exclusive." << std::endl;
      throw std::exception();
    }
    dataOptions.channelsFile = argumentList.getSwitchArgument<std::string>("-zapped_channels");
    dataOptions.integrationFile = argumentList.getSwitchArgument<std::string>("-integration_steps");
    if ( !options.subbandDedispersion ) {
      Dedispersion::readTunedDedispersionConf(configurations.dedispersionParameters, argumentList.getSwitchArgument<std::string>("-dedispersion_file"));
    } else {
      Dedispersion::readTunedDedispersionConf(configurations.dedispersionStepOneParameters, argumentList.getSwitchArgument<std::string>("-dedispersion_step_one_file"));
      Dedispersion::readTunedDedispersionConf(configurations.dedispersionStepTwoParameters, argumentList.getSwitchArgument<std::string>("-dedispersion_step_two_file"));
    }
    Integration::readTunedIntegrationConf(configurations.integrationParameters, argumentList.getSwitchArgument<std::string>("-integration_file"));
    SNR::readTunedSNRConf(configurations.snrParameters, argumentList.getSwitchArgument<std::string>("-snr_file"));
    if ( dataOptions.dataLOFAR ) {
      observation.setNrBeams(1);
      observation.setNrSynthesizedBeams(1);
      dataOptions.headerFile = argumentList.getSwitchArgument<std::string>("-header");
      dataOptions.dataFile = argumentList.getSwitchArgument<std::string>("-data");
      dataOptions.limit = argumentList.getSwitch("-limit");
      if ( dataOptions.limit ) {
        observation.setNrBatches(argumentList.getSwitchArgument<unsigned int>("-batches"));
      }
    } else if ( dataOptions.dataSIGPROC ) {
      observation.setNrBeams(1);
      observation.setNrSynthesizedBeams(1);
      dataOptions.headerSizeSIGPROC = argumentList.getSwitchArgument<unsigned int>("-header");
      dataOptions.dataFile = argumentList.getSwitchArgument<std::string>("-data");
      observation.setNrBatches(argumentList.getSwitchArgument<unsigned int>("-batches"));
      if ( options.subbandDedispersion ) {
        observation.setFrequencyRange(argumentList.getSwitchArgument<unsigned int>("-subbands"), argumentList.getSwitchArgument<unsigned int>("-channels"), argumentList.getSwitchArgument<float>("-min_freq"), argumentList.getSwitchArgument<float>("-channel_bandwidth"));
      } else {
        observation.setFrequencyRange(1, argumentList.getSwitchArgument<unsigned int>("-channels"), argumentList.getSwitchArgument<float>("-min_freq"), argumentList.getSwitchArgument<float>("-channel_bandwidth"));
      }
      observation.setNrSamplesPerBatch(argumentList.getSwitchArgument<unsigned int>("-samples"));
      observation.setSamplingTime(argumentList.getSwitchArgument<float>("-sampling_time"));
    } else if ( dataOptions.dataPSRDADA ) {
#ifdef HAVE_PSRDADA
      dataOptions.dadaKey = std::stoi("0x" + argumentList.getSwitchArgument<std::string>("-dada_key"), 0, 16);
      observation.setNrBeams(argumentList.getSwitchArgument<unsigned int>("-beams"));
      observation.setNrSynthesizedBeams(argumentList.getSwitchArgument<unsigned int>("-synthesized_beams"));
      observation.setNrBatches(argumentList.getSwitchArgument<unsigned int>("-batches"));
#endif // HAVE_PSRDADA
    } else {
      observation.setNrBeams(argumentList.getSwitchArgument<unsigned int>("-beams"));
      observation.setNrSynthesizedBeams(argumentList.getSwitchArgument<unsigned int>("-synthesized_beams"));
      observation.setNrBatches(argumentList.getSwitchArgument<unsigned int>("-batches"));
      if ( options.subbandDedispersion ) {
        observation.setFrequencyRange(argumentList.getSwitchArgument<unsigned int>("-subbands"), argumentList.getSwitchArgument<unsigned int>("-channels"), argumentList.getSwitchArgument<float>("-min_freq"), argumentList.getSwitchArgument<float>("-channel_bandwidth"));
      } else {
        observation.setFrequencyRange(1, argumentList.getSwitchArgument<unsigned int>("-channels"), argumentList.getSwitchArgument<float>("-min_freq"), argumentList.getSwitchArgument<float>("-channel_bandwidth"));
      }
      observation.setNrSamplesPerBatch(argumentList.getSwitchArgument<unsigned int>("-samples"));
      observation.setSamplingTime(argumentList.getSwitchArgument<float>("-sampling_time"));
      generatorOptions.random = argumentList.getSwitch("-random");
      generatorOptions.width = argumentList.getSwitchArgument<unsigned int>("-width");
      generatorOptions.DM = argumentList.getSwitchArgument<float>("-dm");
    }
    dataOptions.outputFile = argumentList.getSwitchArgument<std::string>("-output");
    if ( options.subbandDedispersion ) {
      observation.setDMRange(argumentList.getSwitchArgument<unsigned int>("-subbanding_dms"), argumentList.getSwitchArgument<float>("-subbanding_dm_first"), argumentList.getSwitchArgument<float>("-subbanding_dm_step"), true);
    }
    observation.setDMRange(argumentList.getSwitchArgument<unsigned int>("-dms"), argumentList.getSwitchArgument<float>("-dm_first"), argumentList.getSwitchArgument<float>("-dm_step"));
  } catch ( isa::utils::EmptyCommandLine & err ) {
    usage(argumentList.getName());
    throw;
  } catch ( isa::utils::SwitchNotFound & err ) {
    std::cerr << err.what() << std::endl;
    throw;
  } catch ( std::exception & err ) {
    throw;
  }
}

void usage(const std::string & program) {
    std::cerr << program << " -opencl_platform ... -opencl_device ... -device_name ... -padding_file ... -zapped_channels ... -integration_steps ... -integration_file ... -snr_file ... [-subband_dedispersion] [-print] [-compact_results] -output ... -dms ... -dm_first ... -dm_step ... -threshold ... [-sigproc]";
#ifdef HAVE_HDF5
    std::cerr << " [-lofar]";
#endif // HAVE_HDF5
#ifdef HAVE_PSRDADA
    std::cerr << " [-dada]";
#endif // HAVE_PSRDADA
    std::cerr << std::endl;
    std::cerr << "\tDedispersion: -dedispersion_file ..." << std::endl;
    std::cerr << "\tSubband Dedispersion: -subband_dedispersion -dedispersion_step_one_file ... -dedispersion_step_two_file ... -subbands ... -subbanding_dms ... -subbanding_dm_first ... -subbanding_dm_step ..." << std::endl;
#ifdef HAVE_HDF5
    std::cerr << "\tLOFAR: -lofar -header ... -data ... [-limit]" << std::endl;
    std::cerr << "\t\t -limit -batches ..." << std::endl;
#endif // HAVE_HDF5
    std::cerr << "\tSIGPROC: -sigproc -header ... -data ... -batches ... -channels ... -min_freq ... -channel_bandwidth ... -samples ... -sampling_time ..." << std::endl;
#ifdef HAVE_PSRDADA
    std::cerr << "\tPSRDADA: -dada -dada_key ... -beams ... -synthesized_beams ... -batches ..." << std::endl;
#endif // HAVE_PSRDADA
    std::cerr << "\t [-random] -width ... -dm ... -beams ... -synthesized_beams ... -batches ... -channels ... -min_freq ... -channel_bandwidth ... -samples ... -sampling_time ..." << std::endl;
}
<commit_msg>Added an error message for std::exception.<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 <CommandLine.hpp>

void processCommandLineOptions(isa::utils::ArgumentList & argumentList, Options & options, DeviceOptions & deviceOptions, DataOptions & dataOptions, Configurations & configurations, GeneratorOptions & generatorOptions, AstroData::Observation & observation) {
  try {
    options.print = argumentList.getSwitch("-print");
    options.subbandDedispersion = argumentList.getSwitch("-subband_dedispersion");
    options.compactResults = argumentList.getSwitch("-compact_results");
    options.threshold = argumentList.getSwitchArgument<float>("-threshold");
    deviceOptions.platformID = argumentList.getSwitchArgument<unsigned int>("-opencl_platform");
    deviceOptions.deviceID = argumentList.getSwitchArgument<unsigned int>("-opencl_device");
    deviceOptions.deviceName = argumentList.getSwitchArgument<std::string>("-device_name");
    AstroData::readPaddingConf(deviceOptions.padding, argumentList.getSwitchArgument<std::string>("-padding_file"));
    dataOptions.dataLOFAR = argumentList.getSwitch("-lofar");
#ifndef HAVE_HDF5
    if (dataOptions.dataLOFAR) {
      std::cerr << "Not compiled with HDF5 support." << std::endl;
      throw std::exception();
    };
#endif // HAVE_HDF5
    dataOptions.dataPSRDADA = argumentList.getSwitch("-dada");
#ifndef HAVE_PSRDADA
    if (dataOptions.dataPSRDADA) {
      std::cerr << "Not compiled with PSRDADA support." << std::endl;
      throw std::exception();
    };
#endif // HAVE_PSRDADA
    dataOptions.dataSIGPROC = argumentList.getSwitch("-sigproc");
    if ( !((((!(dataOptions.dataLOFAR && dataOptions.dataSIGPROC) && dataOptions.dataPSRDADA) || (!(dataOptions.dataLOFAR && dataOptions.dataPSRDADA) && dataOptions.dataSIGPROC)) || (!(dataOptions.dataSIGPROC && dataOptions.dataPSRDADA) && dataOptions.dataLOFAR)) || ((!dataOptions.dataLOFAR && !dataOptions.dataSIGPROC) && !dataOptions.dataPSRDADA)) ) {
      std::cerr << "-lofar -sigproc and -dada are mutually exclusive." << std::endl;
      throw std::exception();
    }
    dataOptions.channelsFile = argumentList.getSwitchArgument<std::string>("-zapped_channels");
    dataOptions.integrationFile = argumentList.getSwitchArgument<std::string>("-integration_steps");
    if ( !options.subbandDedispersion ) {
      Dedispersion::readTunedDedispersionConf(configurations.dedispersionParameters, argumentList.getSwitchArgument<std::string>("-dedispersion_file"));
    } else {
      Dedispersion::readTunedDedispersionConf(configurations.dedispersionStepOneParameters, argumentList.getSwitchArgument<std::string>("-dedispersion_step_one_file"));
      Dedispersion::readTunedDedispersionConf(configurations.dedispersionStepTwoParameters, argumentList.getSwitchArgument<std::string>("-dedispersion_step_two_file"));
    }
    Integration::readTunedIntegrationConf(configurations.integrationParameters, argumentList.getSwitchArgument<std::string>("-integration_file"));
    SNR::readTunedSNRConf(configurations.snrParameters, argumentList.getSwitchArgument<std::string>("-snr_file"));
    if ( dataOptions.dataLOFAR ) {
      observation.setNrBeams(1);
      observation.setNrSynthesizedBeams(1);
      dataOptions.headerFile = argumentList.getSwitchArgument<std::string>("-header");
      dataOptions.dataFile = argumentList.getSwitchArgument<std::string>("-data");
      dataOptions.limit = argumentList.getSwitch("-limit");
      if ( dataOptions.limit ) {
        observation.setNrBatches(argumentList.getSwitchArgument<unsigned int>("-batches"));
      }
    } else if ( dataOptions.dataSIGPROC ) {
      observation.setNrBeams(1);
      observation.setNrSynthesizedBeams(1);
      dataOptions.headerSizeSIGPROC = argumentList.getSwitchArgument<unsigned int>("-header");
      dataOptions.dataFile = argumentList.getSwitchArgument<std::string>("-data");
      observation.setNrBatches(argumentList.getSwitchArgument<unsigned int>("-batches"));
      if ( options.subbandDedispersion ) {
        observation.setFrequencyRange(argumentList.getSwitchArgument<unsigned int>("-subbands"), argumentList.getSwitchArgument<unsigned int>("-channels"), argumentList.getSwitchArgument<float>("-min_freq"), argumentList.getSwitchArgument<float>("-channel_bandwidth"));
      } else {
        observation.setFrequencyRange(1, argumentList.getSwitchArgument<unsigned int>("-channels"), argumentList.getSwitchArgument<float>("-min_freq"), argumentList.getSwitchArgument<float>("-channel_bandwidth"));
      }
      observation.setNrSamplesPerBatch(argumentList.getSwitchArgument<unsigned int>("-samples"));
      observation.setSamplingTime(argumentList.getSwitchArgument<float>("-sampling_time"));
    } else if ( dataOptions.dataPSRDADA ) {
#ifdef HAVE_PSRDADA
      dataOptions.dadaKey = std::stoi("0x" + argumentList.getSwitchArgument<std::string>("-dada_key"), 0, 16);
      observation.setNrBeams(argumentList.getSwitchArgument<unsigned int>("-beams"));
      observation.setNrSynthesizedBeams(argumentList.getSwitchArgument<unsigned int>("-synthesized_beams"));
      observation.setNrBatches(argumentList.getSwitchArgument<unsigned int>("-batches"));
#endif // HAVE_PSRDADA
    } else {
      observation.setNrBeams(argumentList.getSwitchArgument<unsigned int>("-beams"));
      observation.setNrSynthesizedBeams(argumentList.getSwitchArgument<unsigned int>("-synthesized_beams"));
      observation.setNrBatches(argumentList.getSwitchArgument<unsigned int>("-batches"));
      if ( options.subbandDedispersion ) {
        observation.setFrequencyRange(argumentList.getSwitchArgument<unsigned int>("-subbands"), argumentList.getSwitchArgument<unsigned int>("-channels"), argumentList.getSwitchArgument<float>("-min_freq"), argumentList.getSwitchArgument<float>("-channel_bandwidth"));
      } else {
        observation.setFrequencyRange(1, argumentList.getSwitchArgument<unsigned int>("-channels"), argumentList.getSwitchArgument<float>("-min_freq"), argumentList.getSwitchArgument<float>("-channel_bandwidth"));
      }
      observation.setNrSamplesPerBatch(argumentList.getSwitchArgument<unsigned int>("-samples"));
      observation.setSamplingTime(argumentList.getSwitchArgument<float>("-sampling_time"));
      generatorOptions.random = argumentList.getSwitch("-random");
      generatorOptions.width = argumentList.getSwitchArgument<unsigned int>("-width");
      generatorOptions.DM = argumentList.getSwitchArgument<float>("-dm");
    }
    dataOptions.outputFile = argumentList.getSwitchArgument<std::string>("-output");
    if ( options.subbandDedispersion ) {
      observation.setDMRange(argumentList.getSwitchArgument<unsigned int>("-subbanding_dms"), argumentList.getSwitchArgument<float>("-subbanding_dm_first"), argumentList.getSwitchArgument<float>("-subbanding_dm_step"), true);
    }
    observation.setDMRange(argumentList.getSwitchArgument<unsigned int>("-dms"), argumentList.getSwitchArgument<float>("-dm_first"), argumentList.getSwitchArgument<float>("-dm_step"));
  } catch ( isa::utils::EmptyCommandLine & err ) {
    usage(argumentList.getName());
    throw;
  } catch ( isa::utils::SwitchNotFound & err ) {
    std::cerr << err.what() << std::endl;
    throw;
  } catch ( std::exception & err ) {
    std::cerr << "Unknown error: " << err.what() << std::endl;
    throw;
  }
}

void usage(const std::string & program) {
    std::cerr << program << " -opencl_platform ... -opencl_device ... -device_name ... -padding_file ... -zapped_channels ... -integration_steps ... -integration_file ... -snr_file ... [-subband_dedispersion] [-print] [-compact_results] -output ... -dms ... -dm_first ... -dm_step ... -threshold ... [-sigproc]";
#ifdef HAVE_HDF5
    std::cerr << " [-lofar]";
#endif // HAVE_HDF5
#ifdef HAVE_PSRDADA
    std::cerr << " [-dada]";
#endif // HAVE_PSRDADA
    std::cerr << std::endl;
    std::cerr << "\tDedispersion: -dedispersion_file ..." << std::endl;
    std::cerr << "\tSubband Dedispersion: -subband_dedispersion -dedispersion_step_one_file ... -dedispersion_step_two_file ... -subbands ... -subbanding_dms ... -subbanding_dm_first ... -subbanding_dm_step ..." << std::endl;
#ifdef HAVE_HDF5
    std::cerr << "\tLOFAR: -lofar -header ... -data ... [-limit]" << std::endl;
    std::cerr << "\t\t -limit -batches ..." << std::endl;
#endif // HAVE_HDF5
    std::cerr << "\tSIGPROC: -sigproc -header ... -data ... -batches ... -channels ... -min_freq ... -channel_bandwidth ... -samples ... -sampling_time ..." << std::endl;
#ifdef HAVE_PSRDADA
    std::cerr << "\tPSRDADA: -dada -dada_key ... -beams ... -synthesized_beams ... -batches ..." << std::endl;
#endif // HAVE_PSRDADA
    std::cerr << "\t [-random] -width ... -dm ... -beams ... -synthesized_beams ... -batches ... -channels ... -min_freq ... -channel_bandwidth ... -samples ... -sampling_time ..." << std::endl;
}
<|endoftext|>


<commit_before>
/*
   Copyright 2017 Red-Portal

   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 <vector>
#include <iostream>
#include <functional>
#include <string>
#include <chrono>

#include "../include/QM.hpp"

std::string decoder(int in)
{
    if(in < 0)
    {
	std::string temp(1, static_cast<char>(-in + 64));
	temp.push_back('\'');
	return temp;
    }
    else
	return std::string(1, static_cast<char>(in + 64));
}

int main(int argc, char* argv[])
{
    using namespace std::placeholders;

    std::vector<int> mTerms{4, 8, 10, 11, 12, 15};
    std::vector<int> dTerms{9, 14};

    {
	auto start = std::chrono::high_resolution_clock::now();

	auto reducer = QM::Reducer<uint64_t>(4, mTerms, dTerms);
	auto reduced = reducer.getBooleanFunction();

	auto end = std::chrono::high_resolution_clock::now();
	auto duration = end - start;
	auto time = std::chrono::duration<double, std::micro>(duration);

	std::cout << "duration: " << time.count()
		  << " ns"
		  << std::endl;

	std::cout << "result: ";
	for (auto i = 0u; i < reduced.size(); ++i)
	{
	    for (auto j: reduced[i])
	    {
		std::cout << decoder(j);
	    }

	    if(i < reduced.size() - 1)
		std::cout << " + ";
	}
	std::cout << std::endl;
    }

    {
	std::vector<int> mTerms{0, 1, 4, 8, 9, 10, 11, 20, 22};
	std::vector<int> dTerms{7, 13, 14, 16,};

	auto start = std::chrono::high_resolution_clock::now();

	auto reducer = QM::Reducer<uint64_t>(5, mTerms, dTerms);
	auto reduced = reducer.getBooleanFunction();

	auto end = std::chrono::high_resolution_clock::now();
	auto duration = end - start;

	auto time = std::chrono::duration<double, std::micro>(duration);

	std::cout << "duration: " << time.count()
		  << " ns" << std::endl;

	std::cout << "result: ";
	for (auto i = 0u; i < reduced.size(); ++i)
	{
	    for (auto j: reduced[i])
	    {
		std::cout << decoder(j);
	    }

	    if(i < reduced.size() - 1)
		std::cout << " + ";
	}
	std::cout << std::endl;
    }
    return 0;
}
<commit_msg>fixed redefinition error in example<commit_after>
/*
   Copyright 2017 Red-Portal

   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 <vector>
#include <iostream>
#include <functional>
#include <string>
#include <chrono>

#include "../include/QM.hpp"

std::string decoder(int in)
{
    if(in < 0)
    {
	std::string temp(1, static_cast<char>(-in + 64));
	temp.push_back('\'');
	return temp;
    }
    else
	return std::string(1, static_cast<char>(in + 64));
}

int main(int argc, char* argv[])
{
    using namespace std::placeholders;

	{
		std::vector<int> mTerms{ 4, 8, 10, 11, 12, 15 };
		std::vector<int> dTerms{ 9, 14 };

		auto start = std::chrono::high_resolution_clock::now();

		auto reducer = QM::Reducer<uint64_t>(4, mTerms, dTerms);
		auto reduced = reducer.getBooleanFunction();

		auto end = std::chrono::high_resolution_clock::now();
		auto duration = end - start;
		auto time = std::chrono::duration<double, std::micro>(duration);

		std::cout << "duration: " << time.count()
			<< " ns"
			<< std::endl;

		std::cout << "result: ";
		for (auto i = 0u; i < reduced.size(); ++i)
		{
			for (auto j : reduced[i])
			{
				std::cout << decoder(j);
			}

			if (i < reduced.size() - 1)
				std::cout << " + ";
		}
		std::cout << std::endl;
	}

	{
		std::vector<int> mTerms{ 0, 1, 4, 8, 9, 10, 11, 20, 22 };
		std::vector<int> dTerms{ 7, 13, 14, 16, };

		auto start = std::chrono::high_resolution_clock::now();

		auto reducer = QM::Reducer<uint64_t>(5, mTerms, dTerms);
		auto reduced = reducer.getBooleanFunction();

		auto end = std::chrono::high_resolution_clock::now();
		auto duration = end - start;

		auto time = std::chrono::duration<double, std::micro>(duration);

		std::cout << "duration: " << time.count()
			<< " ns" << std::endl;

		std::cout << "result: ";
		for (auto i = 0u; i < reduced.size(); ++i)
		{
			for (auto j : reduced[i])
			{
				std::cout << decoder(j);
			}

			if (i < reduced.size() - 1)
				std::cout << " + ";
		}
		std::cout << std::endl;
	}
	return 0;
}
<|endoftext|>


<commit_before>#include <iostream>

#include "Utils/utils.h"
#include "numgrind.h"
#include "Solvers/GradientDescentSolver.h"
#include "Solvers/SGDSolver.h"
#include "Solvers/SGDWithMomentumSolver.h"
#include "Solvers/checkgradient.h"
#include "DeepGrind/ActivationFunctions.h"
#include "mnist.h"

void mnistTest01() {
    const std::string fnameMNISTDir = "/home/daiver/coding/data/mnist/";
    const std::string fnameImagesTrain = fnameMNISTDir + "train-images-idx3-ubyte";
    const std::string fnameLabelsTrain = fnameMNISTDir + "train-labels-idx1-ubyte";
    const std::string fnameImagesTest = fnameMNISTDir + "t10k-images-idx3-ubyte";
    const std::string fnameLabelsTest = fnameMNISTDir + "t10k-labels-idx1-ubyte";

    const Eigen::MatrixXf trainData = mnist::readMNISTImages(fnameImagesTrain) / 255.0;
    const Eigen::VectorXi trainLabelsPure = mnist::readMNISTLabels(fnameLabelsTrain);

    const Eigen::MatrixXf testData = mnist::readMNISTImages(fnameImagesTest) / 255.0;
    const Eigen::VectorXi testLabelsPure = mnist::readMNISTLabels(fnameLabelsTest);

    Eigen::MatrixXf trainLabels = NumGrind::Utils::labelsToMatrix(trainLabelsPure, 10);

    std::default_random_engine generator;
    generator.seed(42);

    using namespace NumGrind::SymbolicGraph;
    NumGrind::GraphManager gm;

    auto X = gm.constant(trainData);
    auto y = gm.constant(trainLabels);

    auto W1 = gm.variable(NumGrind::Utils::gaussf(trainData.cols(), 500, 0.0, 0.02, generator));
    auto b1 = gm.variable(NumGrind::Utils::gaussf(1, 500, 0.0, 0.02, generator));
    auto W2 = gm.variable(NumGrind::Utils::gaussf(500, 10, 0.0, 0.01, generator));
    auto b2 = gm.variable(NumGrind::Utils::gaussf(1, 10, 0.0f, 0.01f, generator));
    auto f1 = apply<NumGrind::DeepGrind::relu, NumGrind::DeepGrind::reluDer>(matmult(X, W1) + b1);
    auto f2 = apply<NumGrind::DeepGrind::sigmoid, NumGrind::DeepGrind::sigmoidDer>(matmult(f1, W2) + b2);

    auto output = f2;
    const int batchSize = 50;
    auto err = sumOfSquares(output - y);

    auto vars = gm.initializeVariables();

    NumGrind::Solvers::SolverSettings settings;
    settings.nMaxIterations = 20;
    settings.verbose = false;

    float bestAcc = 0.0;

    X.setValue(trainData.block(0, 0, batchSize, trainData.cols()));
    y.setValue(trainLabels.block(0, 0, batchSize, trainLabels.cols()));
    NumGrind::Solvers::gradientDescent(settings, 0.0003, gm.funcFromNode(&err), gm.gradFromNode(&err), vars);
    settings.nMaxIterations = 1;
//    NumGrind::Solvers::SGDSolver solver(settings, 0.002, vars);
    NumGrind::Solvers::SGDWithMomentumSolver solver(settings, 0.0025, 0.9, vars);

    Eigen::MatrixXf trainDataSamples(trainData.rows(), trainData.cols());
    Eigen::MatrixXf trainLabelsSamples(trainData.rows(), trainLabels.cols());
    std::vector<int> shuffledIndices = NumGrind::Utils::range(0, trainData.rows());

    for (int epochInd = 0; epochInd < 10000; ++epochInd) {
        std::shuffle(shuffledIndices.begin(), shuffledIndices.end(), generator);
        NumGrind::Utils::sampleRowsByIndices(shuffledIndices, trainData, trainDataSamples);
        NumGrind::Utils::sampleRowsByIndices(shuffledIndices, trainLabels, trainLabelsSamples);
//        solver.setStep(0.003/(0.05*epochInd + 1));//step decay
//        solver.setMomentumCoeff(0.9/(0.05*epochInd + 1));
        for (int iterInd = 0; iterInd < trainData.rows() / batchSize + 1; ++iterInd) {

            X.setValue(trainDataSamples.block((iterInd * batchSize) % (trainData.rows() - batchSize), 0, batchSize, trainDataSamples.cols()));
            y.setValue(trainLabelsSamples.block((iterInd * batchSize) % (trainData.rows() - batchSize), 0, batchSize, trainLabelsSamples.cols()));
            solver.makeStep(gm.funcFromNode(&err),
                            gm.gradFromNode(&err));

            if (iterInd % 10 == 0)
                std::cout << "Epoch: " << epochInd << " iter: " << iterInd << " err " << err.node()->value() << std::endl;
            if (iterInd % 100 == 0) {
                X.setValue(testData);
                output.node()->forwardPass(solver.vars());
                auto res = f2.value();
                const auto colwiseMax = NumGrind::Utils::argmaxRowwise(res);
                int nErr = 0;
                for (int j = 0; j < colwiseMax.rows(); ++j) {
                    if (colwiseMax[j] != testLabelsPure[j])
                        nErr += 1;
                }
                const float fErr = (float) nErr / testLabelsPure.rows();
                const float acc = (1.0 - fErr) * 100;
                if (acc > bestAcc)
                    bestAcc = acc;
                std::cout
                        << std::endl
                        << "Test error " << fErr << ", "
                        << "acc " << (1.0 - fErr) * 100 << "%, "
                        << "n errors " << (float) nErr << ", "
                        << "best " << bestAcc << "% "
                        << std::endl << std::endl;
            }
        }
    }
}

int main() {
    mnistTest01();
    return 0;
}

<commit_msg>make validation section smaller<commit_after>#include <iostream>

#include "Utils/utils.h"
#include "numgrind.h"
#include "Solvers/GradientDescentSolver.h"
#include "Solvers/SGDSolver.h"
#include "Solvers/SGDWithMomentumSolver.h"
#include "Solvers/checkgradient.h"
#include "DeepGrind/ActivationFunctions.h"
#include "mnist.h"

void mnistTest01() {
    const std::string fnameMNISTDir = "/home/daiver/coding/data/mnist/";
    const std::string fnameImagesTrain = fnameMNISTDir + "train-images-idx3-ubyte";
    const std::string fnameLabelsTrain = fnameMNISTDir + "train-labels-idx1-ubyte";
    const std::string fnameImagesTest = fnameMNISTDir + "t10k-images-idx3-ubyte";
    const std::string fnameLabelsTest = fnameMNISTDir + "t10k-labels-idx1-ubyte";

    const Eigen::MatrixXf trainData = mnist::readMNISTImages(fnameImagesTrain) / 255.0;
    const Eigen::VectorXi trainLabelsPure = mnist::readMNISTLabels(fnameLabelsTrain);

    const Eigen::MatrixXf testData = mnist::readMNISTImages(fnameImagesTest) / 255.0;
    const Eigen::VectorXi testLabelsPure = mnist::readMNISTLabels(fnameLabelsTest);

    Eigen::MatrixXf trainLabels = NumGrind::Utils::labelsToMatrix(trainLabelsPure, 10);

    std::default_random_engine generator;
    generator.seed(42);

    using namespace NumGrind::SymbolicGraph;
    NumGrind::GraphManager gm;

    auto X = gm.constant(trainData);
    auto y = gm.constant(trainLabels);

    auto W1 = gm.variable(NumGrind::Utils::gaussf(trainData.cols(), 500, 0.0, 0.02, generator));
    auto b1 = gm.variable(NumGrind::Utils::gaussf(1, 500, 0.0, 0.02, generator));
    auto W2 = gm.variable(NumGrind::Utils::gaussf(500, 10, 0.0, 0.01, generator));
    auto b2 = gm.variable(NumGrind::Utils::gaussf(1, 10, 0.0f, 0.01f, generator));
    auto f1 = apply<NumGrind::DeepGrind::relu, NumGrind::DeepGrind::reluDer>(matmult(X, W1) + b1);
    auto f2 = apply<NumGrind::DeepGrind::sigmoid, NumGrind::DeepGrind::sigmoidDer>(matmult(f1, W2) + b2);

    auto output = f2;
    const int batchSize = 50;
    auto err = sumOfSquares(output - y);

    auto vars = gm.initializeVariables();

    NumGrind::Solvers::SolverSettings settings;
    settings.nMaxIterations = 20;
    settings.verbose = false;

    float bestAcc = 0.0;

    X.setValue(trainData.block(0, 0, batchSize, trainData.cols()));
    y.setValue(trainLabels.block(0, 0, batchSize, trainLabels.cols()));
    NumGrind::Solvers::gradientDescent(settings, 0.0003, gm.funcFromNode(&err), gm.gradFromNode(&err), vars);
    settings.nMaxIterations = 1;
//    NumGrind::Solvers::SGDSolver solver(settings, 0.002, vars);
    NumGrind::Solvers::SGDWithMomentumSolver solver(settings, 0.0025, 0.9, vars);

    Eigen::MatrixXf trainDataSamples(trainData.rows(), trainData.cols());
    Eigen::MatrixXf trainLabelsSamples(trainData.rows(), trainLabels.cols());
    std::vector<int> shuffledIndices = NumGrind::Utils::range(0, trainData.rows());

    for (int epochInd = 0; epochInd < 10000; ++epochInd) {
        std::shuffle(shuffledIndices.begin(), shuffledIndices.end(), generator);
        NumGrind::Utils::sampleRowsByIndices(shuffledIndices, trainData, trainDataSamples);
        NumGrind::Utils::sampleRowsByIndices(shuffledIndices, trainLabels, trainLabelsSamples);

        for (int iterInd = 0; iterInd < trainData.rows() / batchSize + 1; ++iterInd) {

            X.setValue(trainDataSamples.block((iterInd * batchSize) % (trainData.rows() - batchSize), 0, batchSize, trainDataSamples.cols()));
            y.setValue(trainLabelsSamples.block((iterInd * batchSize) % (trainData.rows() - batchSize), 0, batchSize, trainLabelsSamples.cols()));
            solver.makeStep(gm.funcFromNode(&err),
                            gm.gradFromNode(&err));

            if (iterInd % 10 == 0)
                std::cout << "Epoch: " << epochInd << " iter: " << iterInd << " err " << err.node()->value() << std::endl;
            if (iterInd % 100 == 0) {
                X.setValue(testData);
                output.node()->forwardPass(solver.vars());
                auto res = f2.value();
                const int nErr = (NumGrind::Utils::argmaxRowwise(res).array() != testLabelsPure.array()).count();

                const float fErr = (float) nErr / testLabelsPure.rows();
                const float acc = (1.0 - fErr) * 100;
                if (acc > bestAcc)
                    bestAcc = acc;
                std::cout
                        << std::endl
                        << "Test error " << fErr << ", "
                        << "acc " << (1.0 - fErr) * 100 << "%, "
                        << "n errors " << (float) nErr << ", "
                        << "best " << bestAcc << "% "
                        << std::endl << std::endl;
            }
        }
    }
}

int main() {
    mnistTest01();
    return 0;
}

<|endoftext|>


<commit_before>#ifndef VFRAME_NO_3D
#include "V3DScene.h"
#include "V3DObject.h"
#include "V3DBatchModelGroup.h"
#include "V3DShader.h"
#include "V3DCamera.h"
#include <cstring>

#pragma comment(lib, "glu32.lib")

V3DScene::V3DScene(float x, float y, unsigned int width, unsigned int height, const sf::ContextSettings& settings, unsigned int maxSize) : VRenderGroup(maxSize), contextSettings(settings)
{
	renderTex.create(width, height, settings);
	Sprite->Position = sf::Vector2f(x, y);
	Sprite->Size = sf::Vector2f(sf::Vector2u(width, height));
}

V3DScene::V3DScene(sf::Vector2f position, sf::Vector2u size, const sf::ContextSettings& settings, unsigned int maxSize) : VRenderGroup(maxSize), contextSettings(settings)
{
	renderTex.create(size.x, size.y, settings);
	Sprite->Position = position;
	Sprite->Size = sf::Vector2f(size);
}

void V3DScene::SetActive(bool value)
{
	renderTex.setActive(value);
}

void V3DScene::PushGLStates()
{
	renderTex.pushGLStates();
}

void V3DScene::PopGLStates()
{
	renderTex.popGLStates();
}

void V3DScene::ResetGLStates()
{
	renderTex.resetGLStates();
}

#include "V3DModel.h"
void V3DScene::Destroy()
{
	VSUPERCLASS::Destroy();

	renderTex.resetGLStates();
	renderTex.setActive(false);

	if (V3DModel::DefaultTexture)
		glDeleteTextures(1, &V3DModel::DefaultTexture);
}

void V3DScene::Resize(int width, int height)
{
	postProcessTex.create(width, height);
	renderTex.create(width, height, contextSettings);
	Sprite->Size = sf::Vector2f(sf::Vector2u(width, height));
}

void V3DScene::Update(float dt)
{
	VSUPERCLASS::Update(dt);
}

void V3DScene::RenderGroup(VGroup* group)
{
	for (int i = 0; i < group->Length(); i++)
	{
		V3DObject* base = dynamic_cast<V3DObject*>(group->GetGroupItem(i));

		if (base != nullptr && base->exists && base->visible)
		{
			if (Camera[CurrentCamera]->BoxInView(base->Position, base->GetMinimum(), base->GetMaximum()))
			{
				base->UpdateShader(Shader.get(), Camera[CurrentCamera].get());
				base->Draw(renderTex); //If Renderable 3D Object
			}
		}
		else
		{
			V3DBatchModelGroup* batchGroup = dynamic_cast<V3DBatchModelGroup*>(group->GetGroupItem(i));

			if (batchGroup != nullptr)
			{
				batchGroup->UpdateShader(Camera[CurrentCamera].get(), Shader.get()); //If RenderBatch Group
				batchGroup->Draw(renderTex);
			}
			else
			{
				VGroup* childGroup = dynamic_cast<VGroup*>(group->GetGroupItem(i));
				if (childGroup != nullptr)
				{
					RenderGroup(childGroup); //If regular group.
				}
				else
				{
					group->GetGroupItem(i)->Draw(renderTex); //If nothing else, just draw it.
				}
			}
		}
	}
}

const sf::Texture& V3DScene::GetTexture()
{
	sf::Texture::getMaximumSize();

	renderTex.setActive(true);
	renderTex.clear(BackgroundTint);

	glCheck(glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT));
	glCheck(glEnable(GL_BLEND));
	glCheck(glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA));
	glCheck(glEnable(GL_DEPTH_TEST));
	glCheck(glEnable(GL_CULL_FACE));
	glCheck(glCullFace(GL_BACK));
	for (CurrentCamera = 0; CurrentCamera < Camera.size(); CurrentCamera++)
	{
		sf::IntRect Viewport(
			(int)(Camera[CurrentCamera]->Viewport.left		* renderTex.getSize().x),
			(int)(Camera[CurrentCamera]->Viewport.top		* renderTex.getSize().y),
			(int)(Camera[CurrentCamera]->Viewport.width		* renderTex.getSize().x),
			(int)(Camera[CurrentCamera]->Viewport.height	* renderTex.getSize().y)
		);

		glCheck(glViewport(Viewport.left, Viewport.top, Viewport.width, Viewport.height));
		Shader->SetCamera(Camera[CurrentCamera].get());
		Shader->Update();
		Shader->Bind();

		RenderGroup(this);
	}

	renderTex.display();
	renderTex.setActive(false);

	return renderTex.getTexture();
}

const sf::Texture V3DScene::GetTexture(V3DShader* shader, V3DCamera* camera)
{
	std::unique_ptr<V3DShader> uShader(shader);
	std::unique_ptr<V3DCamera> uCamera(camera);

	if (Shader.get() != shader)
		Shader.swap(uShader);

	if (Camera[CurrentCamera].get() != camera)
		Camera[CurrentCamera].swap(uCamera);

	GetTexture();

	if (Shader.get() != shader)
		Shader.swap(uShader);

	if (Camera[CurrentCamera].get() != camera)
		Camera[CurrentCamera].swap(uCamera);

	uShader.release();
	uCamera.release();

	return renderTex.getTexture();
}

void V3DScene::Draw(sf::RenderTarget& RenderTarget)
{
	if (!visible)
		return;

	GetTexture();

	RenderTarget.resetGLStates();
	if (PostEffect != nullptr && VPostEffectBase::isSupported())
	{
		if (postProcessTex.getSize().x == 0 || postProcessTex.getSize().y == 0)
		{
			postProcessTex.create(renderTex.getSize().x, renderTex.getSize().y);
		}

		PostEffect->Apply(renderTex.getTexture(), postProcessTex);
		postProcessTex.display();

		updateTexture(postProcessTex.getTexture());
	}
	else
	{
		updateTexture(renderTex.getTexture());
	}

	Sprite->Draw(RenderTarget);
}
#endif<commit_msg>No need for glu32.lib to be linked in the code.<commit_after>#ifndef VFRAME_NO_3D
#include "V3DScene.h"
#include "V3DObject.h"
#include "V3DBatchModelGroup.h"
#include "V3DShader.h"
#include "V3DCamera.h"
#include <cstring>

V3DScene::V3DScene(float x, float y, unsigned int width, unsigned int height, const sf::ContextSettings& settings, unsigned int maxSize) : VRenderGroup(maxSize), contextSettings(settings)
{
	renderTex.create(width, height, settings);
	Sprite->Position = sf::Vector2f(x, y);
	Sprite->Size = sf::Vector2f(sf::Vector2u(width, height));
}

V3DScene::V3DScene(sf::Vector2f position, sf::Vector2u size, const sf::ContextSettings& settings, unsigned int maxSize) : VRenderGroup(maxSize), contextSettings(settings)
{
	renderTex.create(size.x, size.y, settings);
	Sprite->Position = position;
	Sprite->Size = sf::Vector2f(size);
}

void V3DScene::SetActive(bool value)
{
	renderTex.setActive(value);
}

void V3DScene::PushGLStates()
{
	renderTex.pushGLStates();
}

void V3DScene::PopGLStates()
{
	renderTex.popGLStates();
}

void V3DScene::ResetGLStates()
{
	renderTex.resetGLStates();
}

#include "V3DModel.h"
void V3DScene::Destroy()
{
	VSUPERCLASS::Destroy();

	renderTex.resetGLStates();
	renderTex.setActive(false);

	if (V3DModel::DefaultTexture)
		glDeleteTextures(1, &V3DModel::DefaultTexture);
}

void V3DScene::Resize(int width, int height)
{
	postProcessTex.create(width, height);
	renderTex.create(width, height, contextSettings);
	Sprite->Size = sf::Vector2f(sf::Vector2u(width, height));
}

void V3DScene::Update(float dt)
{
	VSUPERCLASS::Update(dt);
}

void V3DScene::RenderGroup(VGroup* group)
{
	for (int i = 0; i < group->Length(); i++)
	{
		V3DObject* base = dynamic_cast<V3DObject*>(group->GetGroupItem(i));

		if (base != nullptr && base->exists && base->visible)
		{
			if (Camera[CurrentCamera]->BoxInView(base->Position, base->GetMinimum(), base->GetMaximum()))
			{
				base->UpdateShader(Shader.get(), Camera[CurrentCamera].get());
				base->Draw(renderTex); //If Renderable 3D Object
			}
		}
		else
		{
			V3DBatchModelGroup* batchGroup = dynamic_cast<V3DBatchModelGroup*>(group->GetGroupItem(i));

			if (batchGroup != nullptr)
			{
				batchGroup->UpdateShader(Camera[CurrentCamera].get(), Shader.get()); //If RenderBatch Group
				batchGroup->Draw(renderTex);
			}
			else
			{
				VGroup* childGroup = dynamic_cast<VGroup*>(group->GetGroupItem(i));
				if (childGroup != nullptr)
				{
					RenderGroup(childGroup); //If regular group.
				}
				else
				{
					group->GetGroupItem(i)->Draw(renderTex); //If nothing else, just draw it.
				}
			}
		}
	}
}

const sf::Texture& V3DScene::GetTexture()
{
	sf::Texture::getMaximumSize();

	renderTex.setActive(true);
	renderTex.clear(BackgroundTint);

	glCheck(glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT));
	glCheck(glEnable(GL_BLEND));
	glCheck(glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA));
	glCheck(glEnable(GL_DEPTH_TEST));
	glCheck(glEnable(GL_CULL_FACE));
	glCheck(glCullFace(GL_BACK));
	for (CurrentCamera = 0; CurrentCamera < Camera.size(); CurrentCamera++)
	{
		sf::IntRect Viewport(
			(int)(Camera[CurrentCamera]->Viewport.left		* renderTex.getSize().x),
			(int)(Camera[CurrentCamera]->Viewport.top		* renderTex.getSize().y),
			(int)(Camera[CurrentCamera]->Viewport.width		* renderTex.getSize().x),
			(int)(Camera[CurrentCamera]->Viewport.height	* renderTex.getSize().y)
		);

		glCheck(glViewport(Viewport.left, Viewport.top, Viewport.width, Viewport.height));
		Shader->SetCamera(Camera[CurrentCamera].get());
		Shader->Update();
		Shader->Bind();

		RenderGroup(this);
	}

	renderTex.display();
	renderTex.setActive(false);

	return renderTex.getTexture();
}

const sf::Texture V3DScene::GetTexture(V3DShader* shader, V3DCamera* camera)
{
	std::unique_ptr<V3DShader> uShader(shader);
	std::unique_ptr<V3DCamera> uCamera(camera);

	if (Shader.get() != shader)
		Shader.swap(uShader);

	if (Camera[CurrentCamera].get() != camera)
		Camera[CurrentCamera].swap(uCamera);

	GetTexture();

	if (Shader.get() != shader)
		Shader.swap(uShader);

	if (Camera[CurrentCamera].get() != camera)
		Camera[CurrentCamera].swap(uCamera);

	uShader.release();
	uCamera.release();

	return renderTex.getTexture();
}

void V3DScene::Draw(sf::RenderTarget& RenderTarget)
{
	if (!visible)
		return;

	GetTexture();

	RenderTarget.resetGLStates();
	if (PostEffect != nullptr && VPostEffectBase::isSupported())
	{
		if (postProcessTex.getSize().x == 0 || postProcessTex.getSize().y == 0)
		{
			postProcessTex.create(renderTex.getSize().x, renderTex.getSize().y);
		}

		PostEffect->Apply(renderTex.getTexture(), postProcessTex);
		postProcessTex.display();

		updateTexture(postProcessTex.getTexture());
	}
	else
	{
		updateTexture(renderTex.getTexture());
	}

	Sprite->Draw(RenderTarget);
}
#endif<|endoftext|>


<commit_before>/*
 * Copyright (c) 2015, 2016, 2017, Intel Corporation
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in
 *       the documentation and/or other materials provided with the
 *       distribution.
 *
 *     * Neither the name of Intel Corporation nor the names of its
 *       contributors may be used to endorse or promote products derived
 *       from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY LOG OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <errno.h>
#include <string>

#include "geopm_env.h"
#include "Exception.hpp"

namespace geopm
{
    /// @brief Environment class encapuslaes all functionality related to
    /// dealing with runtime environment variables.
    class Environment
    {
        public:
            Environment();
            virtual ~Environment();
            const char *report(void) const;
            const char *policy(void) const;
            const char *shmkey(void) const;
            const char *trace(void) const;
            const char *plugin_path(void) const;
            int report_verbosity(void) const;
            int pmpi_ctl(void) const;
            int do_region_barrier(void) const;
            int do_trace(void) const;
            int do_ignore_affinity() const;
            int do_profile() const;
            int profile_timeout(void) const;
            int debug_attach(void) const;
        private:
            bool get_env(const char *name, std::string &env_string) const;
            bool get_env(const char *name, int &value) const;
            std::string m_report_env;
            std::string m_policy_env;
            std::string m_shmkey_env;
            std::string m_trace_env;
            std::string m_plugin_path_env;
            int m_report_verbosity;
            int m_pmpi_ctl;
            bool m_do_region_barrier;
            bool m_do_trace;
            bool m_do_ignore_affinity;
            bool m_do_profile;
            int m_profile_timeout;
            int m_debug_attach;
    };

    static const Environment &environment(void)
    {
        static const Environment instance;
        return instance;
    }

    Environment::Environment()
        : m_report_env("")
        , m_policy_env("")
        , m_shmkey_env("/geopm-shm")
        , m_trace_env("")
        , m_plugin_path_env("")
        , m_report_verbosity(0)
        , m_pmpi_ctl(GEOPM_PMPI_CTL_NONE)
        , m_do_region_barrier(false)
        , m_do_trace(false)
        , m_do_ignore_affinity(false)
        , m_do_profile(false)
        , m_profile_timeout(30)
        , m_debug_attach(-1)
    {
        std::string tmp_str("");

        (void)get_env("GEOPM_REPORT", m_report_env);
        (void)get_env("GEOPM_POLICY", m_policy_env);
        (void)get_env("GEOPM_SHMKEY", m_shmkey_env);
        m_do_trace = get_env("GEOPM_TRACE", m_trace_env);
        (void)get_env("GEOPM_PLUGIN_PATH", m_plugin_path_env);
        if (!get_env("GEOPM_REPORT_VERBOSITY", m_report_verbosity) && m_report_env.size()) {
            m_report_verbosity = 1;
        }
        m_do_region_barrier = get_env("GEOPM_REGION_BARRIER", tmp_str);
        m_do_ignore_affinity = get_env("GEOPM_ERROR_AFFINITY_IGNORE", tmp_str);
        (void)get_env("GEOPM_PROFILE_TIMEOUT", m_profile_timeout);
        if (get_env("GEOPM_PMPI_CTL", tmp_str)) {
            if (tmp_str == "process") {
                m_pmpi_ctl = GEOPM_PMPI_CTL_PROCESS;
            }
            else if (tmp_str == "pthread") {
                m_pmpi_ctl = GEOPM_PMPI_CTL_PTHREAD;
            }
        }
        get_env("GEOPM_DEBUG_ATTACH", m_debug_attach);
        m_do_profile = m_report_env.length() ||
                       m_do_trace ||
                       m_pmpi_ctl != GEOPM_PMPI_CTL_NONE ||
                       get_env("GEOPM_PROFILE", tmp_str);
    }

    Environment::~Environment()
    {

    }

    bool Environment::get_env(const char *name, std::string &env_string) const
    {
        bool result = false;
        char *check_string = getenv(name);
        if (check_string != NULL) {
            if (strlen(check_string) > NAME_MAX) {
                throw Exception("Environment::Environment(): Environment variable too long",
                                GEOPM_ERROR_INVALID, __FILE__, __LINE__);
            }
            env_string = check_string;
            result = true;
        }
        return result;
    }

    bool Environment::get_env(const char *name, int &value) const
    {
        bool result = false;
        std::string tmp_str("");
        char *end_ptr = NULL;

        if (get_env(name, tmp_str)) {
            value = strtol(tmp_str.c_str(), &end_ptr, 10);
            if (tmp_str.c_str() == end_ptr) {
                throw Exception("Environment::Environment(): Value could not be converted to an integer",
                                GEOPM_ERROR_INVALID, __FILE__, __LINE__);
            }
            result = true;
        }
        return result;
    }

    const char *Environment::report(void) const
    {
        return m_report_env.c_str();
    }

    const char *Environment::policy(void) const
    {
        return m_policy_env.c_str();
    }

    const char *Environment::shmkey(void) const
    {
        return m_shmkey_env.c_str();
    }

    const char *Environment::trace(void) const
    {
        return m_trace_env.c_str();
    }

    const char *Environment::plugin_path(void) const
    {
        return m_plugin_path_env.c_str();
    }

    int Environment::report_verbosity(void) const
    {
        return m_report_verbosity;
    }

    int Environment::pmpi_ctl(void) const
    {
        return m_pmpi_ctl;
    }

    int Environment::do_region_barrier(void) const
    {
        return m_do_region_barrier;
    }

    int Environment::do_trace(void) const
    {
        return m_do_trace;
    }

    int Environment::do_ignore_affinity(void) const
    {
        return m_do_ignore_affinity;
    }

    int Environment::do_profile(void) const
    {
        return m_do_profile;
    }

    int Environment::profile_timeout(void) const
    {
        return m_profile_timeout;
    }

    int Environment::debug_attach(void) const
    {
        return m_debug_attach;
    }
}

extern "C"
{
    const char *geopm_env_policy(void)
    {
        return geopm::environment().policy();
    }

    const char *geopm_env_shmkey(void)
    {
        return geopm::environment().shmkey();
    }

    const char *geopm_env_trace(void)
    {
        return geopm::environment().trace();
    }

    const char *geopm_env_plugin_path(void)
    {
        return geopm::environment().plugin_path();
    }

    const char *geopm_env_report(void)
    {
        return geopm::environment().report();
    }

    int geopm_env_report_verbosity(void)
    {
        return geopm::environment().report_verbosity();
    }

    int geopm_env_pmpi_ctl(void)
    {
        return geopm::environment().pmpi_ctl();
    }

    int geopm_env_do_region_barrier(void)
    {
        return geopm::environment().do_region_barrier();
    }

    int geopm_env_do_trace(void)
    {
        return geopm::environment().do_trace();
    }

    int geopm_env_do_ignore_affinity(void)
    {
        return geopm::environment().do_ignore_affinity();
    }

    int geopm_env_do_profile(void)
    {
        return geopm::environment().do_profile();
    }

    int geopm_env_profile_timeout(void)
    {
        return geopm::environment().profile_timeout();
    }

    int geopm_env_debug_attach(void)
    {
        return geopm::environment().debug_attach();
    }
}
<commit_msg>Add user id to shmkey prefix.<commit_after>/*
 * Copyright (c) 2015, 2016, 2017, Intel Corporation
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in
 *       the documentation and/or other materials provided with the
 *       distribution.
 *
 *     * Neither the name of Intel Corporation nor the names of its
 *       contributors may be used to endorse or promote products derived
 *       from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY LOG OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <errno.h>
#include <string>
#include <unistd.h>

#include "geopm_env.h"
#include "Exception.hpp"

namespace geopm
{
    /// @brief Environment class encapuslaes all functionality related to
    /// dealing with runtime environment variables.
    class Environment
    {
        public:
            Environment();
            virtual ~Environment();
            const char *report(void) const;
            const char *policy(void) const;
            const char *shmkey(void) const;
            const char *trace(void) const;
            const char *plugin_path(void) const;
            int report_verbosity(void) const;
            int pmpi_ctl(void) const;
            int do_region_barrier(void) const;
            int do_trace(void) const;
            int do_ignore_affinity() const;
            int do_profile() const;
            int profile_timeout(void) const;
            int debug_attach(void) const;
        private:
            bool get_env(const char *name, std::string &env_string) const;
            bool get_env(const char *name, int &value) const;
            std::string m_report_env;
            std::string m_policy_env;
            std::string m_shmkey_env;
            std::string m_trace_env;
            std::string m_plugin_path_env;
            int m_report_verbosity;
            int m_pmpi_ctl;
            bool m_do_region_barrier;
            bool m_do_trace;
            bool m_do_ignore_affinity;
            bool m_do_profile;
            int m_profile_timeout;
            int m_debug_attach;
    };

    static const Environment &environment(void)
    {
        static const Environment instance;
        return instance;
    }

    Environment::Environment()
        : m_report_env("")
        , m_policy_env("")
        , m_shmkey_env("/geopm-shm")
        , m_trace_env("")
        , m_plugin_path_env("")
        , m_report_verbosity(0)
        , m_pmpi_ctl(GEOPM_PMPI_CTL_NONE)
        , m_do_region_barrier(false)
        , m_do_trace(false)
        , m_do_ignore_affinity(false)
        , m_do_profile(false)
        , m_profile_timeout(30)
        , m_debug_attach(-1)
    {
        std::string tmp_str("");

        (void)get_env("GEOPM_REPORT", m_report_env);
        (void)get_env("GEOPM_POLICY", m_policy_env);
        (void)get_env("GEOPM_SHMKEY", m_shmkey_env);
        m_shmkey_env += "-" + std::to_string(geteuid());
        m_do_trace = get_env("GEOPM_TRACE", m_trace_env);
        (void)get_env("GEOPM_PLUGIN_PATH", m_plugin_path_env);
        if (!get_env("GEOPM_REPORT_VERBOSITY", m_report_verbosity) && m_report_env.size()) {
            m_report_verbosity = 1;
        }
        m_do_region_barrier = get_env("GEOPM_REGION_BARRIER", tmp_str);
        m_do_ignore_affinity = get_env("GEOPM_ERROR_AFFINITY_IGNORE", tmp_str);
        (void)get_env("GEOPM_PROFILE_TIMEOUT", m_profile_timeout);
        if (get_env("GEOPM_PMPI_CTL", tmp_str)) {
            if (tmp_str == "process") {
                m_pmpi_ctl = GEOPM_PMPI_CTL_PROCESS;
            }
            else if (tmp_str == "pthread") {
                m_pmpi_ctl = GEOPM_PMPI_CTL_PTHREAD;
            }
        }
        get_env("GEOPM_DEBUG_ATTACH", m_debug_attach);
        m_do_profile = m_report_env.length() ||
                       m_do_trace ||
                       m_pmpi_ctl != GEOPM_PMPI_CTL_NONE ||
                       get_env("GEOPM_PROFILE", tmp_str);
    }

    Environment::~Environment()
    {

    }

    bool Environment::get_env(const char *name, std::string &env_string) const
    {
        bool result = false;
        char *check_string = getenv(name);
        if (check_string != NULL) {
            if (strlen(check_string) > NAME_MAX) {
                throw Exception("Environment::Environment(): Environment variable too long",
                                GEOPM_ERROR_INVALID, __FILE__, __LINE__);
            }
            env_string = check_string;
            result = true;
        }
        return result;
    }

    bool Environment::get_env(const char *name, int &value) const
    {
        bool result = false;
        std::string tmp_str("");
        char *end_ptr = NULL;

        if (get_env(name, tmp_str)) {
            value = strtol(tmp_str.c_str(), &end_ptr, 10);
            if (tmp_str.c_str() == end_ptr) {
                throw Exception("Environment::Environment(): Value could not be converted to an integer",
                                GEOPM_ERROR_INVALID, __FILE__, __LINE__);
            }
            result = true;
        }
        return result;
    }

    const char *Environment::report(void) const
    {
        return m_report_env.c_str();
    }

    const char *Environment::policy(void) const
    {
        return m_policy_env.c_str();
    }

    const char *Environment::shmkey(void) const
    {
        return m_shmkey_env.c_str();
    }

    const char *Environment::trace(void) const
    {
        return m_trace_env.c_str();
    }

    const char *Environment::plugin_path(void) const
    {
        return m_plugin_path_env.c_str();
    }

    int Environment::report_verbosity(void) const
    {
        return m_report_verbosity;
    }

    int Environment::pmpi_ctl(void) const
    {
        return m_pmpi_ctl;
    }

    int Environment::do_region_barrier(void) const
    {
        return m_do_region_barrier;
    }

    int Environment::do_trace(void) const
    {
        return m_do_trace;
    }

    int Environment::do_ignore_affinity(void) const
    {
        return m_do_ignore_affinity;
    }

    int Environment::do_profile(void) const
    {
        return m_do_profile;
    }

    int Environment::profile_timeout(void) const
    {
        return m_profile_timeout;
    }

    int Environment::debug_attach(void) const
    {
        return m_debug_attach;
    }
}

extern "C"
{
    const char *geopm_env_policy(void)
    {
        return geopm::environment().policy();
    }

    const char *geopm_env_shmkey(void)
    {
        return geopm::environment().shmkey();
    }

    const char *geopm_env_trace(void)
    {
        return geopm::environment().trace();
    }

    const char *geopm_env_plugin_path(void)
    {
        return geopm::environment().plugin_path();
    }

    const char *geopm_env_report(void)
    {
        return geopm::environment().report();
    }

    int geopm_env_report_verbosity(void)
    {
        return geopm::environment().report_verbosity();
    }

    int geopm_env_pmpi_ctl(void)
    {
        return geopm::environment().pmpi_ctl();
    }

    int geopm_env_do_region_barrier(void)
    {
        return geopm::environment().do_region_barrier();
    }

    int geopm_env_do_trace(void)
    {
        return geopm::environment().do_trace();
    }

    int geopm_env_do_ignore_affinity(void)
    {
        return geopm::environment().do_ignore_affinity();
    }

    int geopm_env_do_profile(void)
    {
        return geopm::environment().do_profile();
    }

    int geopm_env_profile_timeout(void)
    {
        return geopm::environment().profile_timeout();
    }

    int geopm_env_debug_attach(void)
    {
        return geopm::environment().debug_attach();
    }
}
<|endoftext|>


<commit_before>#include "File.h"

std::map<__ino_t, File *> File::uk_inode;
std::multimap<fsize_t, File *> File::cx_size;

File::File(const std::string &path, const std::string &filename) {
	name = filename;
	relativepath.append(path) += std::string("/") += filename;
	std::cout << relativepath << std::endl;
	struct stat sb;

	if (stat(relativepath.c_str(), &sb) == -1) {
		perror("stat");
		exit(EXIT_FAILURE);
	}
	inode = sb.st_ino;
	size = sb.st_size;

	auto r = uk_inode.insert(std::pair<__ino_t, File *>(inode, this));
	if (!r.second) { //duplicate inode, must already be a hardlink
		std::cout << filename << " dup" << std::endl;
		hardlink = true;
		r.first->second->hardlink = true;
	}
	cx_size.insert(std::pair<fsize_t, File *>(size, this));
	if (cx_size.count(size) > 1) {
		// calc the md5 for this entrant
		sha = calc_sha();
	}
	if (cx_size.count(size) == 2) {
		// find the other identically sized file and calc it's sha512
		// acording to the spec the first one is garenteed to be first in the container
		std::multimap<fsize_t, File *>::iterator it = cx_size.find(size);
		it->second->calc_sha();
	}
}

bool File::operator==(File &rhs) {
	if (size == rhs.size) {
		if (sha	== NULL)
			calc_sha();
		if (rhs.sha == NULL)
			rhs.calc_sha();
		return sha == rhs.sha;
	}

	return false;
}

unsigned char *File::calc_sha() {
	EVP_MD_CTX *mdctx;
	const EVP_MD *md;
	char *file_buffer;
	unsigned int md_len, i;
	unsigned char *md_value = new unsigned char [EVP_MAX_MD_SIZE+1];

	if (size == 0) //this can happen
		return NULL;

	OpenSSL_add_all_digests();

	md = EVP_get_digestbyname("sha512");

	if(!md) {
		printf("Unknown message digest \n");
		exit(EXIT_FAILURE);
	}

	int file_descript = open(relativepath.c_str(), O_RDONLY);
	if(file_descript < 0) exit(-1);

	file_buffer = (char *)mmap(NULL, size, PROT_READ, MAP_SHARED, file_descript, 0);

	mdctx = EVP_MD_CTX_create();
	EVP_DigestInit_ex(mdctx, md, NULL);
	EVP_DigestUpdate(mdctx, file_buffer, strlen(file_buffer));
	EVP_DigestFinal_ex(mdctx, md_value, &md_len);
	EVP_MD_CTX_destroy(mdctx);

	std::cout << md_len << std::endl;
	printf("Digest is: ");
	for(i = 0; i < md_len; i++)
		printf("%02x", md_value[i]);
	printf("\n");

	/* Call this once before exit. */
	EVP_cleanup();
	return md_value;
};

bool File::isHardlink(File *file) {
	return file->inode == this->inode;
}
<commit_msg>fix a couple aesthetic things<commit_after>#include "File.h"

std::map<__ino_t, File *> File::uk_inode;
std::multimap<fsize_t, File *> File::cx_size;

File::File(const std::string &path, const std::string &filename) {
	name = filename;
	relativepath.append(path) += std::string("/") += filename;
	std::cout << relativepath << std::endl;
	struct stat sb;

	if (stat(relativepath.c_str(), &sb) == -1) {
		perror("stat");
		exit(EXIT_FAILURE);
	}
	inode = sb.st_ino;
	size = sb.st_size;

	auto r = uk_inode.insert(std::pair<__ino_t, File*>(inode, this));
	if (!r.second) { //duplicate inode, must already be a hardlink
		std::cout << filename << " dup" << std::endl;
		hardlink = true;
		r.first->second->hardlink = true;
	}
	cx_size.insert(std::pair<fsize_t, File *>(size, this));
	if (cx_size.count(size) > 1) {
		// calc the md5 for this entrant
		sha = calc_sha();
	}
	if (cx_size.count(size) == 2) {
		std::multimap<fsize_t, File*>::iterator it = cx_size.find(size);
		it->second->calc_sha(); // find the other identically sized file and calc it's sha512
	}
}

bool File::operator==(File &rhs) {
	if (size == rhs.size) {
		if (sha	== NULL)
			calc_sha();
		if (rhs.sha == NULL)
			rhs.calc_sha();
		return sha == rhs.sha;
	}

	return false;
}

unsigned char *File::calc_sha() {
	EVP_MD_CTX *mdctx;
	const EVP_MD *md;
	char *file_buffer;
	unsigned int md_len, i;
	unsigned char *md_value = new unsigned char [EVP_MAX_MD_SIZE+1];

	if (size == 0) //this can happen
		return NULL;

	OpenSSL_add_all_digests();

	md = EVP_get_digestbyname("sha512");

	if(!md) {
		printf("Unknown message digest \n");
		exit(EXIT_FAILURE);
	}

	int file_descript = open(relativepath.c_str(), O_RDONLY);
	if(file_descript < 0) exit(-1);

	file_buffer = (char *)mmap(NULL, size, PROT_READ, MAP_SHARED, file_descript, 0);

	mdctx = EVP_MD_CTX_create();
	EVP_DigestInit_ex(mdctx, md, NULL);
	EVP_DigestUpdate(mdctx, file_buffer, strlen(file_buffer));
	EVP_DigestFinal_ex(mdctx, md_value, &md_len);
	EVP_MD_CTX_destroy(mdctx);

	std::cout << md_len << std::endl;
	printf("Digest is: ");
	for(i = 0; i < md_len; i++)
		printf("%02x", md_value[i]);
	printf("\n");

	/* Call this once before exit. */
	EVP_cleanup();
	return md_value;
};

bool File::isHardlink(File *file) {
	return file->inode == this->inode;
}
<|endoftext|>


<commit_before>/**
 * Copyright 2015 Colin Doig.  Distributed under the MIT license.
 */

#include <curl/curl.h>
#include <sstream>

#include "greentop/DummyRequest.h"
#include "greentop/ExchangeApi.h"
#include "greentop/HttpCookie.h"

namespace greentop {

const std::string ExchangeApi::LOGIN_END_POINT = "https://identitysso.betfair.com/api/login";
const std::string ExchangeApi::HOST_UK = "https://api.betfair.com";
const std::string ExchangeApi::HOST_AUS = "https://api-au.betfair.com";

size_t curlWriteCallback(char* buffer, size_t size, size_t nitems, std::ostream* stream) {

    size_t realwrote = size * nitems;
    stream->write(buffer, static_cast<std::streamsize>(realwrote));
    if (!(*stream)) {
        realwrote = 0;
    }

    return realwrote;
}

ExchangeApi::ExchangeApi(const std::string& applicationKey) {
    curl_global_init(CURL_GLOBAL_ALL);
    ssoid = "";
    this->applicationKey = applicationKey;
}

bool ExchangeApi::login(std::string username, std::string password) {

    bool success = false;

    CURL* curl;
    curl = curl_easy_init();
    if (curl) {
        curl_easy_setopt(curl, CURLOPT_URL, LOGIN_END_POINT.c_str());
        curl_easy_setopt(curl, CURLOPT_USE_SSL, CURLUSESSL_ALL);
        curl_easy_setopt(curl, CURLOPT_COOKIE, "loggedIn=false; expires=Sun, 17-Jan-2038 19:14:07 GMT; path=/; domain=.betfair.com");

        std::string postFields = "username=" + username + "&password=" + password +
            "&login=true&redirectMethod=POST&product=" + applicationKey
            + "&url=https://www.betfair.com/";

        curl_easy_setopt(curl, CURLOPT_POSTFIELDS, postFields.c_str());
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curlWriteCallback);
        std::stringstream result;
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, &result);
        curl_easy_setopt(curl, CURLOPT_COOKIEFILE, "");
        curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
        char errorBuffer[CURL_ERROR_SIZE];
        curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, errorBuffer);
        errorBuffer[0] = 0;
        CURLcode curlResult = curl_easy_perform(curl);

        if (curlResult == CURLE_OK) {

            struct curl_slist* cookies;

            curl_easy_getinfo(curl, CURLINFO_COOKIELIST, &cookies);

            int i = 1;
            while (cookies) {
                HttpCookie cookie(cookies->data);
                cookies = cookies->next;

                if (cookie.name == "ssoid") {
                    ssoid = cookie.value;
                } else if (cookie.name == "loggedIn" && cookie.value == "true") {
                    success = true;
                }

            }
            curl_slist_free_all(cookies);

        } else {
            curl_easy_cleanup(curl);
            throw std::runtime_error(errorBuffer);
        }

        curl_easy_cleanup(curl);
    }

    return success;

}

void ExchangeApi::logout() {
    ssoid = "";
}

void ExchangeApi::setApplicationKey(const std::string& appKey) {
    applicationKey = appKey;
}

ListCompetitionsResponse
ExchangeApi::listCompetitions(const Exchange exchange,
        const ListCompetitionsRequest& listCompetitionsRequest) const {
    ListCompetitionsResponse listCompetitionsResponse;
    performRequest(exchange, Api::BETTING, "listCompetitions", listCompetitionsRequest, listCompetitionsResponse);
    return listCompetitionsResponse;
}

ListCountriesResponse
ExchangeApi::listCountries(const Exchange exchange,
        const ListCountriesRequest& listCountriesRequest) const {
    ListCountriesResponse listCountriesResponse;
    performRequest(exchange, Api::BETTING, "listCountries", listCountriesRequest, listCountriesResponse);
    return listCountriesResponse;
}

CurrentOrderSummaryReport
ExchangeApi::listCurrentOrders(const Exchange exchange,
        const ListCurrentOrdersRequest& listCurrentOrdersRequest) const {
    CurrentOrderSummaryReport currentOrderSummaryReport;
    performRequest(exchange, Api::BETTING, "listCurrentOrders", listCurrentOrdersRequest, currentOrderSummaryReport);
    return currentOrderSummaryReport;
}

ClearedOrderSummaryReport
ExchangeApi::listClearedOrders(const Exchange exchange,
        const ListClearedOrdersRequest& listClearedOrdersRequest) const {
    ClearedOrderSummaryReport clearedOrderSummaryReport;
    performRequest(exchange, Api::BETTING, "listClearedOrders", listClearedOrdersRequest, clearedOrderSummaryReport);
    return clearedOrderSummaryReport;
}

ListEventTypesResponse
ExchangeApi::listEventTypes(const Exchange exchange,
        const ListEventTypesRequest& listEventTypesRequest) const {
    ListEventTypesResponse listEventTypesResponse;
    performRequest(exchange, Api::BETTING, "listEventTypes", listEventTypesRequest, listEventTypesResponse);
    return listEventTypesResponse;
}

ListEventsResponse
ExchangeApi::listEvents(const Exchange exchange,
        const ListEventsRequest& listEventsRequest) const {
    ListEventsResponse listEventsResponse;
    performRequest(exchange, Api::BETTING, "listEvents", listEventsRequest, listEventsResponse);
    return listEventsResponse;
}

ListMarketCatalogueResponse
ExchangeApi::listMarketCatalogue(const Exchange exchange,
        const ListMarketCatalogueRequest& listMarketCatalogueRequest) const {
    ListMarketCatalogueResponse listMarketCatalogueResponse;
    performRequest(exchange, Api::BETTING, "listMarketCatalogue", listMarketCatalogueRequest, listMarketCatalogueResponse);
    return listMarketCatalogueResponse;
}

ListMarketBookResponse
ExchangeApi::listMarketBook(const Exchange exchange,
        const ListMarketBookRequest& listMarketBookRequest) const {
    ListMarketBookResponse listMarketBookResponse;
    performRequest(exchange, Api::BETTING, "listMarketBook", listMarketBookRequest, listMarketBookResponse);
    return listMarketBookResponse;
}

PlaceExecutionReport
ExchangeApi::placeOrders(const Exchange exchange,
        const PlaceOrdersRequest& placeOrdersRequest) const {
    PlaceExecutionReport placeExecutionReport;
    performRequest(exchange, Api::BETTING, "placeOrders", placeOrdersRequest, placeExecutionReport);
    return placeExecutionReport;
}

CancelExecutionReport
ExchangeApi::cancelOrders(const Exchange exchange,
        const CancelOrdersRequest& cancelOrdersRequest) const {
    CancelExecutionReport cancelExecutionReport;
    performRequest(exchange, Api::BETTING, "cancelOrders", cancelOrdersRequest, cancelExecutionReport);
    return cancelExecutionReport;
}

ListMarketProfitAndLossResponse
ExchangeApi::listMarketProfitAndLoss(const Exchange exchange,
        const ListMarketProfitAndLossRequest& listMarketProfitAndLossRequest) const {
    ListMarketProfitAndLossResponse listMarketProfitAndLossResponse;
    performRequest(exchange, Api::BETTING, "listMarketProfitAndLoss", listMarketProfitAndLossRequest, listMarketProfitAndLossResponse);
    return listMarketProfitAndLossResponse;
}

ReplaceExecutionReport
ExchangeApi::replaceOrders(const Exchange exchange,
        const ReplaceOrdersRequest& replaceOrdersRequest) const {
    ReplaceExecutionReport replaceExecutionReport;
    performRequest(exchange, Api::BETTING, "replaceOrders", replaceOrdersRequest, replaceExecutionReport);
    return replaceExecutionReport;
}

AccountFundsResponse
ExchangeApi::getAccountFunds(const Exchange exchange,
        const GetAccountFundsRequest& getAccountFundsRequest) const {
    AccountFundsResponse accountFundsResponse;
    performRequest(exchange, Api::ACCOUNT, "getAccountFunds", getAccountFundsRequest, accountFundsResponse);
    return accountFundsResponse;
}

AccountDetailsResponse
ExchangeApi::getAccountDetails(const Exchange exchange) const {
    DummyRequest dummyRequest;
    AccountDetailsResponse accountDetailsResponse;
    performRequest(exchange, Api::ACCOUNT, "getAccountDetails", dummyRequest, accountDetailsResponse);
    return accountDetailsResponse;
}

TransferResponse
ExchangeApi::transferFunds(const Exchange exchange,
        const TransferFundsRequest& transferFundsRequest) const {
    TransferResponse transferResponse;
    performRequest(exchange, Api::ACCOUNT, "transferFunds", transferFundsRequest, transferResponse);
    return transferResponse;
}

DeveloperApp
ExchangeApi::createDeveloperAppKeys(const Exchange exchange,
        const CreateDeveloperAppKeysRequest& createDeveloperAppKeysRequest) const {
    DeveloperApp developerApp;
    performRequest(exchange, Api::ACCOUNT, "createDeveloperAppKeys", createDeveloperAppKeysRequest, developerApp);
    return developerApp;
}

GetDeveloperAppKeysResponse
ExchangeApi::getDeveloperAppKeys(const Exchange exchange) const {
    DummyRequest dummyRequest;
    GetDeveloperAppKeysResponse getDeveloperAppKeysResponse;
    performRequest(exchange, Api::ACCOUNT, "getDeveloperAppKeys", dummyRequest, getDeveloperAppKeysResponse);
    return getDeveloperAppKeysResponse;
}

AccountStatementReport
ExchangeApi::getAccountStatement(const Exchange exchange,
        const GetAccountStatementRequest& getAccountStatementRequest) const {
    AccountStatementReport accountStatementReport;
    performRequest(exchange, Api::ACCOUNT, "getAccountStatement", getAccountStatementRequest, accountStatementReport);
    return accountStatementReport;
}

ListCurrencyRatesResponse
ExchangeApi::listCurrencyRates(const Exchange exchange,
        const ListCurrencyRatesRequest& listCurrencyRatesRequest) const {
    ListCurrencyRatesResponse listCurrencyRatesResponse;
    performRequest(exchange, Api::ACCOUNT, "listCurrencyRates", listCurrencyRatesRequest, listCurrencyRatesResponse);
    return listCurrencyRatesResponse;
}

HeartbeatReport
ExchangeApi::heartbeat(const Exchange exchange,
        const HeartbeatRequest& heartbeatRequest) const {
    HeartbeatReport heartbeatReport;
    performRequest(exchange, Api::HEARTBEAT, "heartbeat", heartbeatRequest, heartbeatReport);
    return heartbeatReport;
}

ActivateApplicationSubscriptionResponse
ExchangeApi::activateApplicationSubscription(const Exchange exchange,
        const ActivateApplicationSubscriptionRequest& activateApplicationSubscriptionRequest) const {
    ActivateApplicationSubscriptionResponse activateApplicationSubscriptionResponse;
    performRequest(exchange, Api::ACCOUNT, "activateApplicationSubscription", activateApplicationSubscriptionRequest,
        activateApplicationSubscriptionResponse);
    return activateApplicationSubscriptionResponse;
}

bool ExchangeApi::performRequest(const Exchange exchange,
        const Api api,
        const std::string& method,
        const JsonRequest& jsonRequest, JsonResponse& jsonResponse) const {

    CURL* curl;
    curl = curl_easy_init();
    if (curl) {

        initRequest(exchange, api, method, curl);

        std::string request = jsonRequest.toString();

        if (request != "") {
            curl_easy_setopt(curl, CURLOPT_POSTFIELDS, request.c_str());
        }

        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curlWriteCallback);
        std::stringstream result;
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, &result);

        curl_easy_perform(curl);

        curl_easy_cleanup(curl);

        result >> jsonResponse;

        return jsonResponse.isSuccess();

    }

}

bool ExchangeApi::initRequest(const Exchange exchange,
        const Api api,
        const std::string method, CURL* curl) const {

    curl_easy_setopt(curl, CURLOPT_URL, buildUri(exchange, api, method).c_str());
    curl_easy_setopt(curl, CURLOPT_USE_SSL, CURLUSESSL_ALL);
    curl_easy_setopt(curl, CURLOPT_ACCEPT_ENCODING, "gzip");
    curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);

    struct curl_slist* chunk = NULL;

    std::string header = "X-Application: " + applicationKey;
    chunk = curl_slist_append(chunk, header.c_str());
    header = "X-Authentication: " + ssoid;
    chunk = curl_slist_append(chunk, header.c_str());
    chunk = curl_slist_append(chunk, "content-type: application/json");

    curl_easy_setopt(curl, CURLOPT_HTTPHEADER, chunk);

    return true;
}

std::string ExchangeApi::buildUri(const Exchange exchange, const Api api, const std::string method) const {

    std::string apiString;
    switch (api) {
        case Api::ACCOUNT:
            apiString = "account";
            break;
        case Api::BETTING:
            apiString = "betting";
            break;
        case Api::HEARTBEAT:
            apiString = "heartbeat";
            break;
        default:
            throw std::runtime_error("invalid API");
    }

    switch (exchange) {
        case Exchange::UK:
            return HOST_UK + "/exchange/" + apiString + "/rest/v1.0/" + method + "/";
        case Exchange::AUS:
            return HOST_AUS + "/exchange/" + apiString + "/rest/v1.0/" + method + "/";
        default:
            throw std::runtime_error("invalid exchange");
    }

}

ExchangeApi::~ExchangeApi() {
    curl_global_cleanup();
}

}
<commit_msg>throw exception if curl request fails<commit_after>/**
 * Copyright 2015 Colin Doig.  Distributed under the MIT license.
 */

#include <curl/curl.h>
#include <sstream>

#include "greentop/DummyRequest.h"
#include "greentop/ExchangeApi.h"
#include "greentop/HttpCookie.h"

namespace greentop {

const std::string ExchangeApi::LOGIN_END_POINT = "https://identitysso.betfair.com/api/login";
const std::string ExchangeApi::HOST_UK = "https://api.betfair.com";
const std::string ExchangeApi::HOST_AUS = "https://api-au.betfair.com";

size_t curlWriteCallback(char* buffer, size_t size, size_t nitems, std::ostream* stream) {

    size_t realwrote = size * nitems;
    stream->write(buffer, static_cast<std::streamsize>(realwrote));
    if (!(*stream)) {
        realwrote = 0;
    }

    return realwrote;
}

ExchangeApi::ExchangeApi(const std::string& applicationKey) {
    curl_global_init(CURL_GLOBAL_ALL);
    ssoid = "";
    this->applicationKey = applicationKey;
}

bool ExchangeApi::login(std::string username, std::string password) {

    bool success = false;

    CURL* curl;
    curl = curl_easy_init();
    if (curl) {
        curl_easy_setopt(curl, CURLOPT_URL, LOGIN_END_POINT.c_str());
        curl_easy_setopt(curl, CURLOPT_USE_SSL, CURLUSESSL_ALL);
        curl_easy_setopt(curl, CURLOPT_COOKIE, "loggedIn=false; expires=Sun, 17-Jan-2038 19:14:07 GMT; path=/; domain=.betfair.com");

        std::string postFields = "username=" + username + "&password=" + password +
            "&login=true&redirectMethod=POST&product=" + applicationKey
            + "&url=https://www.betfair.com/";

        curl_easy_setopt(curl, CURLOPT_POSTFIELDS, postFields.c_str());
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curlWriteCallback);
        std::stringstream result;
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, &result);
        curl_easy_setopt(curl, CURLOPT_COOKIEFILE, "");
        curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
        char errorBuffer[CURL_ERROR_SIZE];
        curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, errorBuffer);
        errorBuffer[0] = 0;
        CURLcode curlResult = curl_easy_perform(curl);

        if (curlResult == CURLE_OK) {

            struct curl_slist* cookies;

            curl_easy_getinfo(curl, CURLINFO_COOKIELIST, &cookies);

            int i = 1;
            while (cookies) {
                HttpCookie cookie(cookies->data);
                cookies = cookies->next;

                if (cookie.name == "ssoid") {
                    ssoid = cookie.value;
                } else if (cookie.name == "loggedIn" && cookie.value == "true") {
                    success = true;
                }

            }
            curl_slist_free_all(cookies);

        } else {
            curl_easy_cleanup(curl);
            throw std::runtime_error(errorBuffer);
        }

        curl_easy_cleanup(curl);
    }

    return success;

}

void ExchangeApi::logout() {
    ssoid = "";
}

void ExchangeApi::setApplicationKey(const std::string& appKey) {
    applicationKey = appKey;
}

ListCompetitionsResponse
ExchangeApi::listCompetitions(const Exchange exchange,
        const ListCompetitionsRequest& listCompetitionsRequest) const {
    ListCompetitionsResponse listCompetitionsResponse;
    performRequest(exchange, Api::BETTING, "listCompetitions", listCompetitionsRequest, listCompetitionsResponse);
    return listCompetitionsResponse;
}

ListCountriesResponse
ExchangeApi::listCountries(const Exchange exchange,
        const ListCountriesRequest& listCountriesRequest) const {
    ListCountriesResponse listCountriesResponse;
    performRequest(exchange, Api::BETTING, "listCountries", listCountriesRequest, listCountriesResponse);
    return listCountriesResponse;
}

CurrentOrderSummaryReport
ExchangeApi::listCurrentOrders(const Exchange exchange,
        const ListCurrentOrdersRequest& listCurrentOrdersRequest) const {
    CurrentOrderSummaryReport currentOrderSummaryReport;
    performRequest(exchange, Api::BETTING, "listCurrentOrders", listCurrentOrdersRequest, currentOrderSummaryReport);
    return currentOrderSummaryReport;
}

ClearedOrderSummaryReport
ExchangeApi::listClearedOrders(const Exchange exchange,
        const ListClearedOrdersRequest& listClearedOrdersRequest) const {
    ClearedOrderSummaryReport clearedOrderSummaryReport;
    performRequest(exchange, Api::BETTING, "listClearedOrders", listClearedOrdersRequest, clearedOrderSummaryReport);
    return clearedOrderSummaryReport;
}

ListEventTypesResponse
ExchangeApi::listEventTypes(const Exchange exchange,
        const ListEventTypesRequest& listEventTypesRequest) const {
    ListEventTypesResponse listEventTypesResponse;
    performRequest(exchange, Api::BETTING, "listEventTypes", listEventTypesRequest, listEventTypesResponse);
    return listEventTypesResponse;
}

ListEventsResponse
ExchangeApi::listEvents(const Exchange exchange,
        const ListEventsRequest& listEventsRequest) const {
    ListEventsResponse listEventsResponse;
    performRequest(exchange, Api::BETTING, "listEvents", listEventsRequest, listEventsResponse);
    return listEventsResponse;
}

ListMarketCatalogueResponse
ExchangeApi::listMarketCatalogue(const Exchange exchange,
        const ListMarketCatalogueRequest& listMarketCatalogueRequest) const {
    ListMarketCatalogueResponse listMarketCatalogueResponse;
    performRequest(exchange, Api::BETTING, "listMarketCatalogue", listMarketCatalogueRequest, listMarketCatalogueResponse);
    return listMarketCatalogueResponse;
}

ListMarketBookResponse
ExchangeApi::listMarketBook(const Exchange exchange,
        const ListMarketBookRequest& listMarketBookRequest) const {
    ListMarketBookResponse listMarketBookResponse;
    performRequest(exchange, Api::BETTING, "listMarketBook", listMarketBookRequest, listMarketBookResponse);
    return listMarketBookResponse;
}

PlaceExecutionReport
ExchangeApi::placeOrders(const Exchange exchange,
        const PlaceOrdersRequest& placeOrdersRequest) const {
    PlaceExecutionReport placeExecutionReport;
    performRequest(exchange, Api::BETTING, "placeOrders", placeOrdersRequest, placeExecutionReport);
    return placeExecutionReport;
}

CancelExecutionReport
ExchangeApi::cancelOrders(const Exchange exchange,
        const CancelOrdersRequest& cancelOrdersRequest) const {
    CancelExecutionReport cancelExecutionReport;
    performRequest(exchange, Api::BETTING, "cancelOrders", cancelOrdersRequest, cancelExecutionReport);
    return cancelExecutionReport;
}

ListMarketProfitAndLossResponse
ExchangeApi::listMarketProfitAndLoss(const Exchange exchange,
        const ListMarketProfitAndLossRequest& listMarketProfitAndLossRequest) const {
    ListMarketProfitAndLossResponse listMarketProfitAndLossResponse;
    performRequest(exchange, Api::BETTING, "listMarketProfitAndLoss", listMarketProfitAndLossRequest, listMarketProfitAndLossResponse);
    return listMarketProfitAndLossResponse;
}

ReplaceExecutionReport
ExchangeApi::replaceOrders(const Exchange exchange,
        const ReplaceOrdersRequest& replaceOrdersRequest) const {
    ReplaceExecutionReport replaceExecutionReport;
    performRequest(exchange, Api::BETTING, "replaceOrders", replaceOrdersRequest, replaceExecutionReport);
    return replaceExecutionReport;
}

AccountFundsResponse
ExchangeApi::getAccountFunds(const Exchange exchange,
        const GetAccountFundsRequest& getAccountFundsRequest) const {
    AccountFundsResponse accountFundsResponse;
    performRequest(exchange, Api::ACCOUNT, "getAccountFunds", getAccountFundsRequest, accountFundsResponse);
    return accountFundsResponse;
}

AccountDetailsResponse
ExchangeApi::getAccountDetails(const Exchange exchange) const {
    DummyRequest dummyRequest;
    AccountDetailsResponse accountDetailsResponse;
    performRequest(exchange, Api::ACCOUNT, "getAccountDetails", dummyRequest, accountDetailsResponse);
    return accountDetailsResponse;
}

TransferResponse
ExchangeApi::transferFunds(const Exchange exchange,
        const TransferFundsRequest& transferFundsRequest) const {
    TransferResponse transferResponse;
    performRequest(exchange, Api::ACCOUNT, "transferFunds", transferFundsRequest, transferResponse);
    return transferResponse;
}

DeveloperApp
ExchangeApi::createDeveloperAppKeys(const Exchange exchange,
        const CreateDeveloperAppKeysRequest& createDeveloperAppKeysRequest) const {
    DeveloperApp developerApp;
    performRequest(exchange, Api::ACCOUNT, "createDeveloperAppKeys", createDeveloperAppKeysRequest, developerApp);
    return developerApp;
}

GetDeveloperAppKeysResponse
ExchangeApi::getDeveloperAppKeys(const Exchange exchange) const {
    DummyRequest dummyRequest;
    GetDeveloperAppKeysResponse getDeveloperAppKeysResponse;
    performRequest(exchange, Api::ACCOUNT, "getDeveloperAppKeys", dummyRequest, getDeveloperAppKeysResponse);
    return getDeveloperAppKeysResponse;
}

AccountStatementReport
ExchangeApi::getAccountStatement(const Exchange exchange,
        const GetAccountStatementRequest& getAccountStatementRequest) const {
    AccountStatementReport accountStatementReport;
    performRequest(exchange, Api::ACCOUNT, "getAccountStatement", getAccountStatementRequest, accountStatementReport);
    return accountStatementReport;
}

ListCurrencyRatesResponse
ExchangeApi::listCurrencyRates(const Exchange exchange,
        const ListCurrencyRatesRequest& listCurrencyRatesRequest) const {
    ListCurrencyRatesResponse listCurrencyRatesResponse;
    performRequest(exchange, Api::ACCOUNT, "listCurrencyRates", listCurrencyRatesRequest, listCurrencyRatesResponse);
    return listCurrencyRatesResponse;
}

HeartbeatReport
ExchangeApi::heartbeat(const Exchange exchange,
        const HeartbeatRequest& heartbeatRequest) const {
    HeartbeatReport heartbeatReport;
    performRequest(exchange, Api::HEARTBEAT, "heartbeat", heartbeatRequest, heartbeatReport);
    return heartbeatReport;
}

ActivateApplicationSubscriptionResponse
ExchangeApi::activateApplicationSubscription(const Exchange exchange,
        const ActivateApplicationSubscriptionRequest& activateApplicationSubscriptionRequest) const {
    ActivateApplicationSubscriptionResponse activateApplicationSubscriptionResponse;
    performRequest(exchange, Api::ACCOUNT, "activateApplicationSubscription", activateApplicationSubscriptionRequest,
        activateApplicationSubscriptionResponse);
    return activateApplicationSubscriptionResponse;
}

bool ExchangeApi::performRequest(const Exchange exchange,
        const Api api,
        const std::string& method,
        const JsonRequest& jsonRequest, JsonResponse& jsonResponse) const {

    CURL* curl;
    curl = curl_easy_init();
    if (curl) {

        initRequest(exchange, api, method, curl);

        std::string request = jsonRequest.toString();

        if (request != "") {
            curl_easy_setopt(curl, CURLOPT_POSTFIELDS, request.c_str());
        }

        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curlWriteCallback);
        std::stringstream result;
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, &result);

        char errorBuffer[CURL_ERROR_SIZE];
        curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, errorBuffer);
        errorBuffer[0] = 0;

        CURLcode curlResult = curl_easy_perform(curl);
        if (curlResult == CURLE_OK) {
            result >> jsonResponse;
        } else {
            curl_easy_cleanup(curl);
            throw std::runtime_error(errorBuffer);
        }

        curl_easy_cleanup(curl);

        return jsonResponse.isSuccess();
    }

}

bool ExchangeApi::initRequest(const Exchange exchange,
        const Api api,
        const std::string method, CURL* curl) const {

    curl_easy_setopt(curl, CURLOPT_URL, buildUri(exchange, api, method).c_str());
    curl_easy_setopt(curl, CURLOPT_USE_SSL, CURLUSESSL_ALL);
    curl_easy_setopt(curl, CURLOPT_ACCEPT_ENCODING, "gzip");
    curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);

    struct curl_slist* chunk = NULL;

    std::string header = "X-Application: " + applicationKey;
    chunk = curl_slist_append(chunk, header.c_str());
    header = "X-Authentication: " + ssoid;
    chunk = curl_slist_append(chunk, header.c_str());
    chunk = curl_slist_append(chunk, "content-type: application/json");

    curl_easy_setopt(curl, CURLOPT_HTTPHEADER, chunk);

    return true;
}

std::string ExchangeApi::buildUri(const Exchange exchange, const Api api, const std::string method) const {

    std::string apiString;
    switch (api) {
        case Api::ACCOUNT:
            apiString = "account";
            break;
        case Api::BETTING:
            apiString = "betting";
            break;
        case Api::HEARTBEAT:
            apiString = "heartbeat";
            break;
        default:
            throw std::runtime_error("invalid API");
    }

    switch (exchange) {
        case Exchange::UK:
            return HOST_UK + "/exchange/" + apiString + "/rest/v1.0/" + method + "/";
        case Exchange::AUS:
            return HOST_AUS + "/exchange/" + apiString + "/rest/v1.0/" + method + "/";
        default:
            throw std::runtime_error("invalid exchange");
    }

}

ExchangeApi::~ExchangeApi() {
    curl_global_cleanup();
}

}
<|endoftext|>