<commit_before>#include "utils.h"
#include "crypto/sha2.h"
#include "flaggedarrayset.h"
#include "relayprocess.h"

#include <stdio.h>
#include <sys/time.h>
#include <algorithm>
#include <random>
#include <string.h>
#include <unistd.h>

void do_nothing(...) {}

#ifdef BENCH
#define PRINT_TIME do_nothing
#else
#define PRINT_TIME printf
#endif

std::linear_congruential_engine<std::uint_fast32_t, 48271, 0, 2147483647> engine(42);

void fill_txv(std::vector<unsigned char>& block, std::vector<std::shared_ptr<std::vector<unsigned char> > >& txVectors, float includeP) {
	std::vector<unsigned char>::const_iterator readit = block.begin();
	move_forward(readit, sizeof(struct bitcoin_msg_header), block.end());
	move_forward(readit, 80, block.end());
	uint32_t txcount = read_varint(readit, block.end());

	std::uniform_real_distribution<double> distribution(0.0, 1.0);

	for (uint32_t i = 0; i < txcount; i++) {
		std::vector<unsigned char>::const_iterator txstart = readit;

		move_forward(readit, 4, block.end());

		uint32_t txins = read_varint(readit, block.end());
		for (uint32_t j = 0; j < txins; j++) {
			move_forward(readit, 36, block.end());
			uint32_t scriptlen = read_varint(readit, block.end());
			move_forward(readit, scriptlen + 4, block.end());
		}

		uint32_t txouts = read_varint(readit, block.end());
		for (uint32_t j = 0; j < txouts; j++) {
			move_forward(readit, 8, block.end());
			uint32_t scriptlen = read_varint(readit, block.end());
			move_forward(readit, scriptlen, block.end());
		}

		move_forward(readit, 4, block.end());

		if (distribution(engine) < includeP)
			txVectors.push_back(std::make_shared<std::vector<unsigned char> >(txstart, readit));
	}

	std::shuffle(txVectors.begin(), txVectors.end(), engine);
}

int pipefd[2];
uint32_t block_tx_count;
std::shared_ptr<std::vector<unsigned char> > decompressed_block;
RelayNodeCompressor receiver;

void recv_block() {
	struct timeval start, decompressed;
	gettimeofday(&start, NULL);
	auto res = receiver.decompress_relay_block(pipefd[0], block_tx_count);
	gettimeofday(&decompressed, NULL);

	if (std::get<2>(res)) {
		printf("ERROR Decompressing block %s\n", std::get<2>(res));
		exit(2);
	} else
		PRINT_TIME("Decompressed block in %lu ms\n", int64_t(decompressed.tv_sec - start.tv_sec)*1000 + (int64_t(decompressed.tv_usec) - start.tv_usec)/1000);
	decompressed_block = std::get<1>(res);
}

void test_compress_block(std::vector<unsigned char>& data, std::vector<std::shared_ptr<std::vector<unsigned char> > > txVectors) {
	std::vector<unsigned char> fullhash(32);
	getblockhash(fullhash, data, sizeof(struct bitcoin_msg_header));

	RelayNodeCompressor sender, tester;
	receiver.reset();

	for (auto& v : txVectors) {
		unsigned int made = sender.get_relay_transaction(v).use_count();
		if (made)
			receiver.recv_tx(v);
		if (made != tester.get_relay_transaction(v).use_count()) {
			printf("get_relay_transaction behavior not consistent???\n");
			exit(5);
		}
	}

	unsigned int i = 0;
	sender.for_each_sent_tx([&](std::shared_ptr<std::vector<unsigned char> > tx) {
		ssize_t index = std::max((ssize_t)0, (ssize_t)txVectors.size() - 1525) + i++;
		if (tx != txVectors[index]) {
			printf("for_each_sent_tx was not in order!\n");
			exit(6);
		}
		if (tester.send_tx_cache.remove(0) != txVectors[index]) {
			printf("for_each_sent_tx output did not match remove(0)\n");
			exit(7);
		}
	});

	struct timeval start, compressed;
	gettimeofday(&start, NULL);
	auto res = sender.maybe_compress_block(fullhash, data, true);
	gettimeofday(&compressed, NULL);
	PRINT_TIME("Compressed from %lu to %lu in %ld ms with %lu txn pre-relayed\n", data.size(), std::get<0>(res)->size(), int64_t(compressed.tv_sec - start.tv_sec)*1000 + (int64_t(compressed.tv_usec) - start.tv_usec)/1000, txVectors.size());

	struct relay_msg_header header;
	memcpy(&header, &(*std::get<0>(res))[0], sizeof(header));
	block_tx_count = ntohl(header.length);

	if (pipe(pipefd)) {
		printf("Failed to create pipe?\n");
		exit(3);
	}

	std::thread recv(recv_block);
	write(pipefd[1], &(*std::get<0>(res))[sizeof(header)], std::get<0>(res)->size() - sizeof(header));
	recv.join();

	if (*decompressed_block != data) {
		printf("Re-constructed block did not match!\n");
		exit(4);
	}

	close(pipefd[0]);
	close(pipefd[1]);
}

void run_test(std::vector<unsigned char>& data) {
	std::vector<std::shared_ptr<std::vector<unsigned char> > > txVectors;
	test_compress_block(data, txVectors);

	fill_txv(data, txVectors, 1.0);
	test_compress_block(data, txVectors);

	txVectors.clear();
	fill_txv(data, txVectors, 0.5);
	test_compress_block(data, txVectors);

	txVectors.clear();
	fill_txv(data, txVectors, 0.9);
	test_compress_block(data, txVectors);
}

int main() {
	std::vector<unsigned char> data(sizeof(struct bitcoin_msg_header));
	std::vector<unsigned char> lastBlock;

	std::vector<std::shared_ptr<std::vector<unsigned char> > > allTxn;

	FILE* f = fopen("block.txt", "r");
	while (true) {
		char hex[2];
		if (fread(hex, 1, 1, f) != 1)
			break;
		else if (hex[0] == '\n') {
			if (data.size()) {
#ifdef BENCH
				for (int i = 0; i < 1000; i++)
#endif
					run_test(data);
				fill_txv(data, allTxn, 0.9);
				lastBlock = data;
			}
			data = std::vector<unsigned char>(sizeof(struct bitcoin_msg_header));
		} else if (fread(hex + 1, 1, 1, f) != 1)
			break;
		else {
			if (hex[0] >= 'a')
				hex[0] -= 'a' - '9' - 1;
			if (hex[1] >= 'a')
				hex[1] -= 'a' - '9' - 1;
			data.push_back((hex[0] - '0') << 4 | (hex[1] - '0'));
		}
	}

#ifdef BENCH
	for (int i = 0; i < 1000; i++)
#endif
		test_compress_block(lastBlock, allTxn);
	return 0;
}
<commit_msg>Run slightly fewer iterations<commit_after>#include "utils.h"
#include "crypto/sha2.h"
#include "flaggedarrayset.h"
#include "relayprocess.h"

#include <stdio.h>
#include <sys/time.h>
#include <algorithm>
#include <random>
#include <string.h>
#include <unistd.h>

void do_nothing(...) {}

#ifdef BENCH
#define PRINT_TIME do_nothing
#else
#define PRINT_TIME printf
#endif

std::linear_congruential_engine<std::uint_fast32_t, 48271, 0, 2147483647> engine(42);

void fill_txv(std::vector<unsigned char>& block, std::vector<std::shared_ptr<std::vector<unsigned char> > >& txVectors, float includeP) {
	std::vector<unsigned char>::const_iterator readit = block.begin();
	move_forward(readit, sizeof(struct bitcoin_msg_header), block.end());
	move_forward(readit, 80, block.end());
	uint32_t txcount = read_varint(readit, block.end());

	std::uniform_real_distribution<double> distribution(0.0, 1.0);

	for (uint32_t i = 0; i < txcount; i++) {
		std::vector<unsigned char>::const_iterator txstart = readit;

		move_forward(readit, 4, block.end());

		uint32_t txins = read_varint(readit, block.end());
		for (uint32_t j = 0; j < txins; j++) {
			move_forward(readit, 36, block.end());
			uint32_t scriptlen = read_varint(readit, block.end());
			move_forward(readit, scriptlen + 4, block.end());
		}

		uint32_t txouts = read_varint(readit, block.end());
		for (uint32_t j = 0; j < txouts; j++) {
			move_forward(readit, 8, block.end());
			uint32_t scriptlen = read_varint(readit, block.end());
			move_forward(readit, scriptlen, block.end());
		}

		move_forward(readit, 4, block.end());

		if (distribution(engine) < includeP)
			txVectors.push_back(std::make_shared<std::vector<unsigned char> >(txstart, readit));
	}

	std::shuffle(txVectors.begin(), txVectors.end(), engine);
}

int pipefd[2];
uint32_t block_tx_count;
std::shared_ptr<std::vector<unsigned char> > decompressed_block;
RelayNodeCompressor receiver;

void recv_block() {
	struct timeval start, decompressed;
	gettimeofday(&start, NULL);
	auto res = receiver.decompress_relay_block(pipefd[0], block_tx_count);
	gettimeofday(&decompressed, NULL);

	if (std::get<2>(res)) {
		printf("ERROR Decompressing block %s\n", std::get<2>(res));
		exit(2);
	} else
		PRINT_TIME("Decompressed block in %lu ms\n", int64_t(decompressed.tv_sec - start.tv_sec)*1000 + (int64_t(decompressed.tv_usec) - start.tv_usec)/1000);
	decompressed_block = std::get<1>(res);
}

void test_compress_block(std::vector<unsigned char>& data, std::vector<std::shared_ptr<std::vector<unsigned char> > > txVectors) {
	std::vector<unsigned char> fullhash(32);
	getblockhash(fullhash, data, sizeof(struct bitcoin_msg_header));

	RelayNodeCompressor sender, tester;
	receiver.reset();

	for (auto& v : txVectors) {
		unsigned int made = sender.get_relay_transaction(v).use_count();
		if (made)
			receiver.recv_tx(v);
		if (made != tester.get_relay_transaction(v).use_count()) {
			printf("get_relay_transaction behavior not consistent???\n");
			exit(5);
		}
	}

	unsigned int i = 0;
	sender.for_each_sent_tx([&](std::shared_ptr<std::vector<unsigned char> > tx) {
		ssize_t index = std::max((ssize_t)0, (ssize_t)txVectors.size() - 1525) + i++;
		if (tx != txVectors[index]) {
			printf("for_each_sent_tx was not in order!\n");
			exit(6);
		}
		if (tester.send_tx_cache.remove(0) != txVectors[index]) {
			printf("for_each_sent_tx output did not match remove(0)\n");
			exit(7);
		}
	});

	struct timeval start, compressed;
	gettimeofday(&start, NULL);
	auto res = sender.maybe_compress_block(fullhash, data, true);
	gettimeofday(&compressed, NULL);
	PRINT_TIME("Compressed from %lu to %lu in %ld ms with %lu txn pre-relayed\n", data.size(), std::get<0>(res)->size(), int64_t(compressed.tv_sec - start.tv_sec)*1000 + (int64_t(compressed.tv_usec) - start.tv_usec)/1000, txVectors.size());

	struct relay_msg_header header;
	memcpy(&header, &(*std::get<0>(res))[0], sizeof(header));
	block_tx_count = ntohl(header.length);

	if (pipe(pipefd)) {
		printf("Failed to create pipe?\n");
		exit(3);
	}

	std::thread recv(recv_block);
	write(pipefd[1], &(*std::get<0>(res))[sizeof(header)], std::get<0>(res)->size() - sizeof(header));
	recv.join();

	if (*decompressed_block != data) {
		printf("Re-constructed block did not match!\n");
		exit(4);
	}

	close(pipefd[0]);
	close(pipefd[1]);
}

void run_test(std::vector<unsigned char>& data) {
	std::vector<std::shared_ptr<std::vector<unsigned char> > > txVectors;
	test_compress_block(data, txVectors);

	fill_txv(data, txVectors, 1.0);
	test_compress_block(data, txVectors);

	txVectors.clear();
	fill_txv(data, txVectors, 0.5);
	test_compress_block(data, txVectors);

	txVectors.clear();
	fill_txv(data, txVectors, 0.9);
	test_compress_block(data, txVectors);
}

int main() {
	std::vector<unsigned char> data(sizeof(struct bitcoin_msg_header));
	std::vector<unsigned char> lastBlock;

	std::vector<std::shared_ptr<std::vector<unsigned char> > > allTxn;

	FILE* f = fopen("block.txt", "r");
	while (true) {
		char hex[2];
		if (fread(hex, 1, 1, f) != 1)
			break;
		else if (hex[0] == '\n') {
			if (data.size()) {
#ifdef BENCH
				for (int i = 0; i < 300; i++)
#endif
					run_test(data);
				fill_txv(data, allTxn, 0.9);
				lastBlock = data;
			}
			data = std::vector<unsigned char>(sizeof(struct bitcoin_msg_header));
		} else if (fread(hex + 1, 1, 1, f) != 1)
			break;
		else {
			if (hex[0] >= 'a')
				hex[0] -= 'a' - '9' - 1;
			if (hex[1] >= 'a')
				hex[1] -= 'a' - '9' - 1;
			data.push_back((hex[0] - '0') << 4 | (hex[1] - '0'));
		}
	}

#ifdef BENCH
	for (int i = 0; i < 300; i++)
#endif
		test_compress_block(lastBlock, allTxn);
	return 0;
}
<|endoftext|>


<commit_before>// Copyright (c) 2010 - 2013 Leap Motion. All rights reserved. Proprietary and confidential.
#include "stdafx.h"
#include "ScopeTest.h"
#include "GlobalCoreContext.h"
#include "Autowired.h"

TEST_F(ScopeTest, VerifyGlobalExists) {
  // Verify that we at least get a global scope
  AutoGlobalContext global;
  EXPECT_TRUE(nullptr != global.get()) << "Failed to autowire the global context";
}
<commit_msg>expanded on scoping test<commit_after>// Copyright (c) 2010 - 2013 Leap Motion. All rights reserved. Proprietary and confidential.
#include "stdafx.h"
#include "ScopeTest.h"
#include "GlobalCoreContext.h"
#include "Autowired.h"

TEST_F(ScopeTest, VerifyGlobalExists) {
  // Verify that we at least get a global scope
  AutoGlobalContext global;
  EXPECT_TRUE(nullptr != global.get()) << "Failed to autowire the global context";
}

class A : public ContextMember {};
class B : public ContextMember {};

TEST_F(ScopeTest, VerifyInherit) {
  AutoCurrentContext ctxt;

  //Add a member to the current context
  ctxt->Add<A>();

  std::shared_ptr<CoreContext> pContext = ctxt->CreateAnonymous();
  //Create and switch to a sub-context
  {
    CurrentContextPusher pusher;
    pContext->SetCurrent();

    EXPECT_TRUE(ctxt.get() != pContext.get()) << "Failed to create a sub-context";

    //try and autowire a member from the parent context
    Autowired<A> autoA;
    EXPECT_FALSE(!autoA.get()) << "Autowired member not wired from parent context";

    //add a member in the subcontext
    pContext->Add<B>();
  }

  Autowired<B> autoB;
  EXPECT_TRUE(!autoB.get()) << "Autowired member wired from sub-context";
}<|endoftext|>


<commit_before>//System includes
#include <fstream>
#include <iostream>
#include <ctime>
#include <string>
#include <cstdlib>
#include <iomanip>

// Point
#include "point.h"

// Ugly fixes
#include <assert.h>

// Kratos Independent
#define KRATOS_INDEPENDENT

#ifndef KRATOS_INDEPENDENT
#define KRATOS_ERROR std::cout

// Kratos includes
#include "spatial_containers/spatial_containers.h"
#endif // KRATOS_INDEPENDENT

#include "points_bins.h"
#include "points_hash.h"

double GetCurrentTime() {
#ifndef _OPENMP
	return std::clock() / static_cast<double>(CLOCKS_PER_SEC);
#else
	return omp_get_wtime();
#endif
}

template< class T, std::size_t dim >
class PointDistance2 {
public:
	double operator()(T const& p1, T const& p2) {
		double dist = 0.0;
		for (std::size_t i = 0; i < dim; i++) {
			double tmp = p1[i] - p2[i];
			dist += tmp*tmp;
		}
		return dist;
	}
};

template<class SearchStructureType, class PointType, class IteratorType, class DistanceIterator>
void RunTestsOldInterface(char const Title[], IteratorType PBegin, IteratorType PEnd, IteratorType results0, DistanceIterator distances0, std::size_t MaxResults, PointType* allPoints, double radius0, std::size_t numsearch, std::size_t bucket_size) {
	double t0, t1;
	std::size_t n;

	std::size_t npoints = PEnd - PBegin;
	std::vector<std::size_t> numresArray(numsearch);
	PointType& point0 = allPoints[0];

	std::size_t numsearch_nearest = 10 * numsearch;

	t0 = GetCurrentTime();
	SearchStructureType nodes_tree(PBegin, PEnd);
	t1 = GetCurrentTime();
	std::cout << Title << "\t" << t1 - t0 << "\t";

	t0 = GetCurrentTime();
  #pragma omp parallel for
	for (std::size_t i = 0; i < numsearch; i++) {
		n = nodes_tree.SearchInRadius(point0, radius0, results0, distances0, MaxResults);
  }
	t1 = GetCurrentTime();
	std::cout << t1 - t0 << "\t";

	t0 = GetCurrentTime();
	for (std::size_t i = 0; i < numsearch; i++) {
		n = nodes_tree.SearchInRadius(point0, radius0, results0, distances0, MaxResults);
  }
	t1 = GetCurrentTime();
	std::cout << t1 - t0 << "\t";

	PointType** PNearestArray = new PointType*[numsearch];
	std::vector<double> distancesArrayNearest(numsearch);
	PointType* PNearest = PNearestArray[0];

	t0 = GetCurrentTime();
	for (std::size_t i = 0; i < 10; i++) {
		nodes_tree.SearchNearestPoint(allPoints, numsearch, PNearestArray, distancesArrayNearest);
  }
	t1 = GetCurrentTime();

	std::cout << t1 - t0 << "\t";
	double distance = 0;

	t0 = GetCurrentTime();
	for (std::size_t i = 0; i < numsearch_nearest; i++) {
		PNearest = nodes_tree.SearchNearestPoint(point0, distance);
  }
	t1 = GetCurrentTime();
	std::cout << t1 - t0 << "\t";

	std::cout << n << "\t" << *PNearestArray[0] << std::endl;
};

template<class BinsType>
void RunTestsNewInterface(char const Title[], std::vector<Point<3>> & points_vector, const Point<3> & search_point, double radius, std::size_t numsearch, std::size_t numsearch_nearest) {
  double t0 = GetCurrentTime();
  BinsType bins(points_vector.begin(), points_vector.end());
  double t1 = GetCurrentTime();
  std::cout << "Points Bin" << "\t" << t1 - t0 << "\t";

  std::vector<PointsBins<Point<3>>::ResultType> results;
  PointsBins<Point<3>>::ResultType nearest_point_result;

  t0 = GetCurrentTime();
  #pragma omp parallel for firstprivate(results)
  for (std::size_t i = 0; i < numsearch; i++) {
    results.clear();
    bins.SearchInRadius(search_point, radius, results);
  }
  t1 = GetCurrentTime();
  std::cout << t1 - t0 << "\t";

  t0 = GetCurrentTime();
  for (std::size_t i = 0; i < numsearch; i++) {
    results.clear();
    bins.SearchInRadius(search_point, radius, results);
  }
  t1 = GetCurrentTime();
  std::cout << t1 - t0 << "\t";

  t0 = GetCurrentTime();

  #pragma omp parallel for firstprivate(nearest_point_result)
  for (std::size_t i = 0; i < numsearch_nearest; i++) {
    nearest_point_result = bins.SearchNearest(search_point);
  }
  t1 = GetCurrentTime();
  std::cout << t1 - t0 << "\t";

  t0 = GetCurrentTime();
  for (std::size_t i = 0; i < numsearch_nearest; i++) {
    nearest_point_result = bins.SearchNearest(search_point);
  }
  t1 = GetCurrentTime();
  std::cout << t1 - t0 << "\t" << results.size() << "\t" << *nearest_point_result.Get();
  std::cout << std::endl;
}

int RunPointSearchComparison(std::string Filename, double Radius) {
	constexpr std::size_t Dim = 3;

	typedef Point<Dim>       PointType;

	typedef PointType *      PtrPointType;
	typedef PtrPointType *   PointVector;
	typedef PtrPointType *   PointIterator;

	typedef double* DistanceVector;
	typedef double* DistanceIterator;

#ifndef KRATOS_INDEPENDENT
	typedef Kratos::Bucket<Dim, PointType, PointVector, PtrPointType, PointIterator, DistanceIterator, PointDistance2<PointType, Dim>>       bucket_type;  //Bucket;
	typedef Kratos::Bins<Dim, PointType, PointVector, PtrPointType, PointIterator, DistanceIterator, PointDistance2<PointType, Dim>>         StaticBinsType;           //StaticBins;
	typedef Kratos::BinsDynamic<Dim, PointType, PointVector, PtrPointType, PointIterator, DistanceIterator, PointDistance2<PointType, Dim>>  DynamicBinsType; //DynamicBins;

	typedef Kratos::Tree< Kratos::KDTreePartition<bucket_type>>                  kdtree_type;                //Kdtree;
	typedef Kratos::Tree< Kratos::KDTreePartitionAverageSplit<bucket_type>>      kdtree_average_split_type;  //Kdtree;
	typedef Kratos::Tree< Kratos::KDTreePartitionMidPointSplit<bucket_type>>     kdtree_midpoint_split_type; //Kdtree;
	typedef Kratos::Tree< Kratos::OCTreePartition<bucket_type>>                  OctreeType;                 //Octree;
	typedef Kratos::Tree< Kratos::KDTreePartitionMidPointSplit<StaticBinsType>>  kdtree_StaticBinsType;      //KdtreeBins;
	typedef Kratos::Tree< Kratos::OCTreePartition<StaticBinsType>>               octree_StaticBinsType;      //OctreeBins;
	typedef Kratos::Tree< Kratos::KDTreePartitionMidPointSplit<DynamicBinsType>> kdtree_DynamicBinsType;     //KdtreeBins;
	typedef Kratos::Tree< Kratos::OCTreePartition<DynamicBinsType>>              octree_bins_type;           //OctreeBins;
#endif // KRATOS_INDEPENDENT

	// Input data
	std::cout << std::setprecision(4) << std::fixed;

	PointVector points;

	std::ifstream input;
	input.open(Filename.c_str());

	if (!input) {
		std::cout << "Cannot open data file" << std::endl;
		return 0;
	}
	std::cout << "Comparison for " << Filename << std::endl;
	PointType   point;
	std::size_t npoints;

	input >> npoints;
	points = new PointType*[npoints];

	std::size_t pid;

	for (std::size_t i = 0; i < npoints; i++) {
		input >> pid;
		input >> point;

		points[i] = new PointType(point);
		points[i]->id = pid;
	}

	PointType min_point(*points[0]);
	PointType max_point(*points[0]);
	PointType mid_point;

	min_point.id = 0;
	max_point.id = 0;
	mid_point.id = 0;

	for (std::size_t i = 0; i < npoints; i++) {
		for (std::size_t j = 0; j < 3; j++) {
			if (min_point[j] > (*points[i])[j]) min_point[j] = (*points[i])[j];
			if (max_point[j] < (*points[i])[j]) max_point[j] = (*points[i])[j];
		}
	}

	for (std::size_t i = 0; i < Dim; i++) {
		mid_point.coord[i] = (max_point[i] + min_point[i]) / 2.00;
	}

	// Output data Info
	PointType & search_point = mid_point;

	std::size_t numsearch = 100000;
	std::size_t numsearch_nearest = numsearch * 10;

	std::cout << " min point : " << min_point << std::endl;
	std::cout << " max point : " << max_point << std::endl;
	std::cout << " search_point : " << search_point << std::endl;
	std::cout << " search radius : " << Radius << std::endl;
	std::cout << std::endl;

	std::cout << " Number of Points : " << npoints << std::endl;
	std::cout << " Number of Repetitions : " << numsearch << std::endl;
	std::cout << std::endl;

	std::cout << "SS\t\tGEN\tSIROMP\tSIRSER\tSNPOMP\tSNPSER\tNOFR\tNP" << std::endl;

	// Data Setup
	PointType * allPoints;
	allPoints = new PointType[numsearch];

	std::size_t max_results = npoints;
	for (std::size_t i = 0; i < 1; i++) {
		allPoints[i] = search_point;
	}

	//Prepare the search point, search radius and resut arrays
	DistanceIterator distances = new double[npoints];
	PointIterator p_results = new PtrPointType[max_results];

	// Point-Based Search Structures
	std::vector<Point<3>> points_vector;
	for (std::size_t i = 0; i < npoints; i++) {
		points_vector.push_back(*(points[i]));
	}

  // New Interface
	RunTestsNewInterface<PointsBins<Point<3>>>("PointBins", points_vector, search_point, Radius, numsearch, numsearch_nearest);

  // Old Interface
#ifndef KRATOS_INDEPENDENT
	RunTestsOldInterface<StaticBinsType>("StaticBins", points, points + npoints, p_results, distances, max_results, allPoints, Radius, numsearch, 1);
	RunTestsOldInterface<DynamicBinsType>("DynamicBins", points, points + npoints, p_results, distances, max_results, allPoints, Radius, numsearch, 1);
  RunTestsOldInterface<OctreeType>("OcTree\t", points, points + npoints, p_results, distances, max_results, allPoints, Radius, numsearch, 10);

  //RunTestsOldInterface<kdtree_type>("KdTree\t", points, points + npoints, p_results, distances, max_results, allPoints, radius, numsearch, 10);
	//RunTestsOldInterface<kdtree_average_split_type>("KdTreeAverage", points, points + npoints, resultsArray, distancesArray, max_results, allPoints, radiusArray, numsearch, 10);
	//RunTestsOldInterface<kdtree_midpoint_split_type>("KdTreeMidpoint", points, points + npoints, resultsArray, distancesArray, max_results, allPoints, radiusArray, numsearch, 10);
#endif // KRATOS_INDEPENDENT

	return 0;
}

int main(int arg, char* argv[]) {
	std::string filename;

	double radius = 0.01;

	if (arg > 1) {
		std::cout << "Argument not founded " << std::endl;
		filename = argv[1];

		if (arg == 3) {
			radius = atof(argv[2]) / 1000000;
		}

		return 0;
	}

	filename = "genericCube100x100x100.5051.pts";
	RunPointSearchComparison(filename, radius);
	filename = "offsetCube79x79x79.1603.pts";
	RunPointSearchComparison(filename, radius);
	filename = "clusterCube6x6x6X4913.490.pts";
	RunPointSearchComparison(filename, radius);
	filename = "line100000.5.pts";
	RunPointSearchComparison(filename, radius);

	return 0;
}
<commit_msg>Adding the omp.h include<commit_after>//System includes
#include <fstream>
#include <iostream>
#include <ctime>
#include <string>
#include <cstdlib>
#include <iomanip>

#ifdef _OPENMP
#include <omp.h>
#endif

// Point
#include "point.h"

// Ugly fixes
#include <assert.h>

// Kratos Independent
#define KRATOS_INDEPENDENT

#ifndef KRATOS_INDEPENDENT
#define KRATOS_ERROR std::cout

// Kratos includes
#include "spatial_containers/spatial_containers.h"
#endif // KRATOS_INDEPENDENT

#include "points_bins.h"
#include "points_hash.h"

double GetCurrentTime() {
#ifndef _OPENMP
	return std::clock() / static_cast<double>(CLOCKS_PER_SEC);
#else
	return omp_get_wtime();
#endif
}

template< class T, std::size_t dim >
class PointDistance2 {
public:
	double operator()(T const& p1, T const& p2) {
		double dist = 0.0;
		for (std::size_t i = 0; i < dim; i++) {
			double tmp = p1[i] - p2[i];
			dist += tmp*tmp;
		}
		return dist;
	}
};

template<class SearchStructureType, class PointType, class IteratorType, class DistanceIterator>
void RunTestsOldInterface(char const Title[], IteratorType PBegin, IteratorType PEnd, IteratorType results0, DistanceIterator distances0, std::size_t MaxResults, PointType* allPoints, double radius0, std::size_t numsearch, std::size_t bucket_size) {
	double t0, t1;
	std::size_t n;

	std::size_t npoints = PEnd - PBegin;
	std::vector<std::size_t> numresArray(numsearch);
	PointType& point0 = allPoints[0];

	std::size_t numsearch_nearest = 10 * numsearch;

	t0 = GetCurrentTime();
	SearchStructureType nodes_tree(PBegin, PEnd);
	t1 = GetCurrentTime();
	std::cout << Title << "\t" << t1 - t0 << "\t";

	t0 = GetCurrentTime();
  #pragma omp parallel for
	for (std::size_t i = 0; i < numsearch; i++) {
		n = nodes_tree.SearchInRadius(point0, radius0, results0, distances0, MaxResults);
  }
	t1 = GetCurrentTime();
	std::cout << t1 - t0 << "\t";

	t0 = GetCurrentTime();
	for (std::size_t i = 0; i < numsearch; i++) {
		n = nodes_tree.SearchInRadius(point0, radius0, results0, distances0, MaxResults);
  }
	t1 = GetCurrentTime();
	std::cout << t1 - t0 << "\t";

	PointType** PNearestArray = new PointType*[numsearch];
	std::vector<double> distancesArrayNearest(numsearch);
	PointType* PNearest = PNearestArray[0];

	t0 = GetCurrentTime();
	for (std::size_t i = 0; i < 10; i++) {
		nodes_tree.SearchNearestPoint(allPoints, numsearch, PNearestArray, distancesArrayNearest);
  }
	t1 = GetCurrentTime();

	std::cout << t1 - t0 << "\t";
	double distance = 0;

	t0 = GetCurrentTime();
	for (std::size_t i = 0; i < numsearch_nearest; i++) {
		PNearest = nodes_tree.SearchNearestPoint(point0, distance);
  }
	t1 = GetCurrentTime();
	std::cout << t1 - t0 << "\t";

	std::cout << n << "\t" << *PNearestArray[0] << std::endl;
};

template<class BinsType>
void RunTestsNewInterface(char const Title[], std::vector<Point<3>> & points_vector, const Point<3> & search_point, double radius, std::size_t numsearch, std::size_t numsearch_nearest) {
  double t0 = GetCurrentTime();
  BinsType bins(points_vector.begin(), points_vector.end());
  double t1 = GetCurrentTime();
  std::cout << "Points Bin" << "\t" << t1 - t0 << "\t";

  std::vector<PointsBins<Point<3>>::ResultType> results;
  PointsBins<Point<3>>::ResultType nearest_point_result;

  t0 = GetCurrentTime();
  #pragma omp parallel for firstprivate(results)
  for (std::size_t i = 0; i < numsearch; i++) {
    results.clear();
    bins.SearchInRadius(search_point, radius, results);
  }
  t1 = GetCurrentTime();
  std::cout << t1 - t0 << "\t";

  t0 = GetCurrentTime();
  for (std::size_t i = 0; i < numsearch; i++) {
    results.clear();
    bins.SearchInRadius(search_point, radius, results);
  }
  t1 = GetCurrentTime();
  std::cout << t1 - t0 << "\t";

  t0 = GetCurrentTime();

  #pragma omp parallel for firstprivate(nearest_point_result)
  for (std::size_t i = 0; i < numsearch_nearest; i++) {
    nearest_point_result = bins.SearchNearest(search_point);
  }
  t1 = GetCurrentTime();
  std::cout << t1 - t0 << "\t";

  t0 = GetCurrentTime();
  for (std::size_t i = 0; i < numsearch_nearest; i++) {
    nearest_point_result = bins.SearchNearest(search_point);
  }
  t1 = GetCurrentTime();
  std::cout << t1 - t0 << "\t" << results.size() << "\t" << *nearest_point_result.Get();
  std::cout << std::endl;
}

int RunPointSearchComparison(std::string Filename, double Radius) {
	constexpr std::size_t Dim = 3;

	typedef Point<Dim>       PointType;

	typedef PointType *      PtrPointType;
	typedef PtrPointType *   PointVector;
	typedef PtrPointType *   PointIterator;

	typedef double* DistanceVector;
	typedef double* DistanceIterator;

#ifndef KRATOS_INDEPENDENT
	typedef Kratos::Bucket<Dim, PointType, PointVector, PtrPointType, PointIterator, DistanceIterator, PointDistance2<PointType, Dim>>       bucket_type;  //Bucket;
	typedef Kratos::Bins<Dim, PointType, PointVector, PtrPointType, PointIterator, DistanceIterator, PointDistance2<PointType, Dim>>         StaticBinsType;           //StaticBins;
	typedef Kratos::BinsDynamic<Dim, PointType, PointVector, PtrPointType, PointIterator, DistanceIterator, PointDistance2<PointType, Dim>>  DynamicBinsType; //DynamicBins;

	typedef Kratos::Tree< Kratos::KDTreePartition<bucket_type>>                  kdtree_type;                //Kdtree;
	typedef Kratos::Tree< Kratos::KDTreePartitionAverageSplit<bucket_type>>      kdtree_average_split_type;  //Kdtree;
	typedef Kratos::Tree< Kratos::KDTreePartitionMidPointSplit<bucket_type>>     kdtree_midpoint_split_type; //Kdtree;
	typedef Kratos::Tree< Kratos::OCTreePartition<bucket_type>>                  OctreeType;                 //Octree;
	typedef Kratos::Tree< Kratos::KDTreePartitionMidPointSplit<StaticBinsType>>  kdtree_StaticBinsType;      //KdtreeBins;
	typedef Kratos::Tree< Kratos::OCTreePartition<StaticBinsType>>               octree_StaticBinsType;      //OctreeBins;
	typedef Kratos::Tree< Kratos::KDTreePartitionMidPointSplit<DynamicBinsType>> kdtree_DynamicBinsType;     //KdtreeBins;
	typedef Kratos::Tree< Kratos::OCTreePartition<DynamicBinsType>>              octree_bins_type;           //OctreeBins;
#endif // KRATOS_INDEPENDENT

	// Input data
	std::cout << std::setprecision(4) << std::fixed;

	PointVector points;

	std::ifstream input;
	input.open(Filename.c_str());

	if (!input) {
		std::cout << "Cannot open data file" << std::endl;
		return 0;
	}
	std::cout << "Comparison for " << Filename << std::endl;
	PointType   point;
	std::size_t npoints;

	input >> npoints;
	points = new PointType*[npoints];

	std::size_t pid;

	for (std::size_t i = 0; i < npoints; i++) {
		input >> pid;
		input >> point;

		points[i] = new PointType(point);
		points[i]->id = pid;
	}

	PointType min_point(*points[0]);
	PointType max_point(*points[0]);
	PointType mid_point;

	min_point.id = 0;
	max_point.id = 0;
	mid_point.id = 0;

	for (std::size_t i = 0; i < npoints; i++) {
		for (std::size_t j = 0; j < 3; j++) {
			if (min_point[j] > (*points[i])[j]) min_point[j] = (*points[i])[j];
			if (max_point[j] < (*points[i])[j]) max_point[j] = (*points[i])[j];
		}
	}

	for (std::size_t i = 0; i < Dim; i++) {
		mid_point.coord[i] = (max_point[i] + min_point[i]) / 2.00;
	}

	// Output data Info
	PointType & search_point = mid_point;

	std::size_t numsearch = 100000;
	std::size_t numsearch_nearest = numsearch * 10;

	std::cout << " min point : " << min_point << std::endl;
	std::cout << " max point : " << max_point << std::endl;
	std::cout << " search_point : " << search_point << std::endl;
	std::cout << " search radius : " << Radius << std::endl;
	std::cout << std::endl;

	std::cout << " Number of Points : " << npoints << std::endl;
	std::cout << " Number of Repetitions : " << numsearch << std::endl;
	std::cout << std::endl;

	std::cout << "SS\t\tGEN\tSIROMP\tSIRSER\tSNPOMP\tSNPSER\tNOFR\tNP" << std::endl;

	// Data Setup
	PointType * allPoints;
	allPoints = new PointType[numsearch];

	std::size_t max_results = npoints;
	for (std::size_t i = 0; i < 1; i++) {
		allPoints[i] = search_point;
	}

	//Prepare the search point, search radius and resut arrays
	DistanceIterator distances = new double[npoints];
	PointIterator p_results = new PtrPointType[max_results];

	// Point-Based Search Structures
	std::vector<Point<3>> points_vector;
	for (std::size_t i = 0; i < npoints; i++) {
		points_vector.push_back(*(points[i]));
	}

  // New Interface
	RunTestsNewInterface<PointsBins<Point<3>>>("PointBins", points_vector, search_point, Radius, numsearch, numsearch_nearest);

  // Old Interface
#ifndef KRATOS_INDEPENDENT
	RunTestsOldInterface<StaticBinsType>("StaticBins", points, points + npoints, p_results, distances, max_results, allPoints, Radius, numsearch, 1);
	RunTestsOldInterface<DynamicBinsType>("DynamicBins", points, points + npoints, p_results, distances, max_results, allPoints, Radius, numsearch, 1);
  RunTestsOldInterface<OctreeType>("OcTree\t", points, points + npoints, p_results, distances, max_results, allPoints, Radius, numsearch, 10);

  //RunTestsOldInterface<kdtree_type>("KdTree\t", points, points + npoints, p_results, distances, max_results, allPoints, radius, numsearch, 10);
	//RunTestsOldInterface<kdtree_average_split_type>("KdTreeAverage", points, points + npoints, resultsArray, distancesArray, max_results, allPoints, radiusArray, numsearch, 10);
	//RunTestsOldInterface<kdtree_midpoint_split_type>("KdTreeMidpoint", points, points + npoints, resultsArray, distancesArray, max_results, allPoints, radiusArray, numsearch, 10);
#endif // KRATOS_INDEPENDENT

	return 0;
}

int main(int arg, char* argv[]) {
	std::string filename;

	double radius = 0.01;

	if (arg > 1) {
		std::cout << "Argument not founded " << std::endl;
		filename = argv[1];

		if (arg == 3) {
			radius = atof(argv[2]) / 1000000;
		}

		return 0;
	}

	filename = "genericCube100x100x100.5051.pts";
	RunPointSearchComparison(filename, radius);
	filename = "offsetCube79x79x79.1603.pts";
	RunPointSearchComparison(filename, radius);
	filename = "clusterCube6x6x6X4913.490.pts";
	RunPointSearchComparison(filename, radius);
	filename = "line100000.5.pts";
	RunPointSearchComparison(filename, radius);

	return 0;
}
<|endoftext|>


<commit_before>/*
 * Polyphase channelizer
 *
 * Copyright (C) 2012-2014 Tom Tsou <tom@tsou.cc>
 * Copyright (C) 2015 Ettus Research LLC
 *
 * SPDX-License-Identifier: AGPL-3.0+
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 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 Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 * See the COPYING file in the main directory for details.
 */

#include <malloc.h>
#include <math.h>
#include <assert.h>
#include <string.h>
#include <cstdio>

#include "Logger.h"
#include "ChannelizerBase.h"

extern "C" {
#include "fft.h"
}

static float sinc(float x)
{
	if (x == 0.0f)
		return 0.999999999999f;

	return sin(M_PI * x) / (M_PI * x);
}

/*
 * There are more efficient reversal algorithms, but we only reverse at
 * initialization so we don't care.
 */
static void reverse(float *buf, size_t len)
{
	float tmp[2 * len];
	memcpy(tmp, buf, 2 * len * sizeof(float));

	for (size_t i = 0; i < len; i++) {
		buf[2 * i + 0] = tmp[2 * (len - 1 - i) + 0];
		buf[2 * i + 1] = tmp[2 * (len - 1 - i) + 1];
	}
}

/*
 * Create polyphase filterbank
 *
 * Implementation based material found in,
 *
 * "harris, fred, Multirate Signal Processing, Upper Saddle River, NJ,
 *     Prentice Hall, 2006."
 */
bool ChannelizerBase::initFilters()
{
	size_t protoLen = m * hLen;
	float *proto;
	float sum = 0.0f, scale = 0.0f;
	float midpt = (float) (protoLen - 1.0) / 2.0;

	/*
	 * Allocate 'M' partition filters and the temporary prototype
	 * filter. Coefficients are real only and must be 16-byte memory
	 * aligned for SSE usage.
	 */
	proto = new float[protoLen];
	if (!proto)
		return false;

	subFilters = (float **) malloc(sizeof(float *) * m);
	if (!subFilters) {
		delete[] proto;
		return false;
	}

	for (size_t i = 0; i < m; i++) {
		subFilters[i] = (float *)
				memalign(16, hLen * 2 * sizeof(float));
	}

	/*
	 * Generate the prototype filter with a Blackman-harris window.
	 * Scale coefficients with DC filter gain set to unity divided
	 * by the number of channels.
	 */
	float a0 = 0.35875;
	float a1 = 0.48829;
	float a2 = 0.14128;
	float a3 = 0.01168;

	for (size_t i = 0; i < protoLen; i++) {
		proto[i] = sinc(((float) i - midpt) / (float) m);
		proto[i] *= a0 -
			    a1 * cos(2 * M_PI * i / (protoLen - 1)) +
			    a2 * cos(4 * M_PI * i / (protoLen - 1)) -
			    a3 * cos(6 * M_PI * i / (protoLen - 1));
		sum += proto[i];
	}
	scale = (float) m / sum;

	/*
	 * Populate partition filters and reverse the coefficients per
	 * convolution requirements.
	 */
	for (size_t i = 0; i < hLen; i++) {
		for (size_t n = 0; n < m; n++) {
			subFilters[n][2 * i + 0] = proto[i * m + n] * scale;
			subFilters[n][2 * i + 1] = 0.0f;
		}
	}

	for (size_t i = 0; i < m; i++)
		reverse(subFilters[i], hLen);

	delete[] proto;

	return true;
}

bool ChannelizerBase::initFFT()
{
	size_t size;

	if (fftInput || fftOutput || fftHandle)
		return false;

	size = blockLen * m * 2 * sizeof(float);
	fftInput = (float *) fft_malloc(size);
	memset(fftInput, 0, size);

	size = (blockLen + hLen) * m * 2 * sizeof(float);
	fftOutput = (float *) fft_malloc(size);
	memset(fftOutput, 0, size);

	if (!fftInput | !fftOutput) {
		LOG(ALERT) << "Memory allocation error";
		return false;
	}

	fftHandle = init_fft(0, m, blockLen, blockLen + hLen,
			     fftInput, fftOutput, hLen);
	return true;
}

bool ChannelizerBase::mapBuffers()
{
	if (!fftHandle) {
		LOG(ALERT) << "FFT buffers not initialized";
		return false;
	}

	hInputs = (float **) malloc(sizeof(float *) * m);
	hOutputs = (float **) malloc(sizeof(float *) * m);
	if (!hInputs | !hOutputs)
		return false;

	for (size_t i = 0; i < m; i++) {
		hInputs[i] = &fftOutput[2 * (i * (blockLen + hLen) + hLen)];
		hOutputs[i] = &fftInput[2 * (i * blockLen)];
	}

	return true;
}

/*
 * Setup filterbank internals
 */
bool ChannelizerBase::init()
{
	/*
	 * Filterbank coefficients, fft plan, history, and output sample
	 * rate conversion blocks
	 */
	if (!initFilters()) {
		LOG(ALERT) << "Failed to initialize channelizing filter";
		return false;
	}

	hist = (float **) malloc(sizeof(float *) * m);
	for (size_t i = 0; i < m; i++) {
		hist[i] = new float[2 * hLen];
		memset(hist[i], 0, 2 * hLen * sizeof(float));
	}

	if (!initFFT()) {
		LOG(ALERT) << "Failed to initialize FFT";
		return false;
	}

	mapBuffers();

	return true;
}

/* Check vector length validity */
bool ChannelizerBase::checkLen(size_t innerLen, size_t outerLen)
{
	if (outerLen != innerLen * m) {
		LOG(ALERT) << "Invalid outer length " << innerLen
			   <<  " is not multiple of " << blockLen;
		return false;
	}

	if (innerLen != blockLen) {
		LOG(ALERT) << "Invalid inner length " << outerLen
			   <<  " does not equal " << blockLen;
		return false;
	}

	return true;
}

/*
 * Setup channelizer parameters
 */
ChannelizerBase::ChannelizerBase(size_t m, size_t blockLen, size_t hLen)
	: subFilters(NULL), hInputs(NULL), hOutputs(NULL), hist(NULL),
	  fftInput(NULL), fftOutput(NULL), fftHandle(NULL)
{
	this->m = m;
	this->hLen = hLen;
	this->blockLen = blockLen;
}

ChannelizerBase::~ChannelizerBase()
{
	free_fft(fftHandle);

	for (size_t i = 0; i < m; i++) {
		free(subFilters[i]);
		delete[] hist[i];
	}

	fft_free(fftInput);
	fft_free(fftOutput);

	free(hInputs);
	free(hOutputs);
	free(hist);
}
<commit_msg>ChannelizerBase: Fix memory leak<commit_after>/*
 * Polyphase channelizer
 *
 * Copyright (C) 2012-2014 Tom Tsou <tom@tsou.cc>
 * Copyright (C) 2015 Ettus Research LLC
 *
 * SPDX-License-Identifier: AGPL-3.0+
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 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 Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 * See the COPYING file in the main directory for details.
 */

#include <malloc.h>
#include <math.h>
#include <assert.h>
#include <string.h>
#include <cstdio>

#include "Logger.h"
#include "ChannelizerBase.h"

extern "C" {
#include "fft.h"
}

static float sinc(float x)
{
	if (x == 0.0f)
		return 0.999999999999f;

	return sin(M_PI * x) / (M_PI * x);
}

/*
 * There are more efficient reversal algorithms, but we only reverse at
 * initialization so we don't care.
 */
static void reverse(float *buf, size_t len)
{
	float tmp[2 * len];
	memcpy(tmp, buf, 2 * len * sizeof(float));

	for (size_t i = 0; i < len; i++) {
		buf[2 * i + 0] = tmp[2 * (len - 1 - i) + 0];
		buf[2 * i + 1] = tmp[2 * (len - 1 - i) + 1];
	}
}

/*
 * Create polyphase filterbank
 *
 * Implementation based material found in,
 *
 * "harris, fred, Multirate Signal Processing, Upper Saddle River, NJ,
 *     Prentice Hall, 2006."
 */
bool ChannelizerBase::initFilters()
{
	size_t protoLen = m * hLen;
	float *proto;
	float sum = 0.0f, scale = 0.0f;
	float midpt = (float) (protoLen - 1.0) / 2.0;

	/*
	 * Allocate 'M' partition filters and the temporary prototype
	 * filter. Coefficients are real only and must be 16-byte memory
	 * aligned for SSE usage.
	 */
	proto = new float[protoLen];
	if (!proto)
		return false;

	subFilters = (float **) malloc(sizeof(float *) * m);
	if (!subFilters) {
		delete[] proto;
		return false;
	}

	for (size_t i = 0; i < m; i++) {
		subFilters[i] = (float *)
				memalign(16, hLen * 2 * sizeof(float));
	}

	/*
	 * Generate the prototype filter with a Blackman-harris window.
	 * Scale coefficients with DC filter gain set to unity divided
	 * by the number of channels.
	 */
	float a0 = 0.35875;
	float a1 = 0.48829;
	float a2 = 0.14128;
	float a3 = 0.01168;

	for (size_t i = 0; i < protoLen; i++) {
		proto[i] = sinc(((float) i - midpt) / (float) m);
		proto[i] *= a0 -
			    a1 * cos(2 * M_PI * i / (protoLen - 1)) +
			    a2 * cos(4 * M_PI * i / (protoLen - 1)) -
			    a3 * cos(6 * M_PI * i / (protoLen - 1));
		sum += proto[i];
	}
	scale = (float) m / sum;

	/*
	 * Populate partition filters and reverse the coefficients per
	 * convolution requirements.
	 */
	for (size_t i = 0; i < hLen; i++) {
		for (size_t n = 0; n < m; n++) {
			subFilters[n][2 * i + 0] = proto[i * m + n] * scale;
			subFilters[n][2 * i + 1] = 0.0f;
		}
	}

	for (size_t i = 0; i < m; i++)
		reverse(subFilters[i], hLen);

	delete[] proto;

	return true;
}

bool ChannelizerBase::initFFT()
{
	size_t size;

	if (fftInput || fftOutput || fftHandle)
		return false;

	size = blockLen * m * 2 * sizeof(float);
	fftInput = (float *) fft_malloc(size);
	memset(fftInput, 0, size);

	size = (blockLen + hLen) * m * 2 * sizeof(float);
	fftOutput = (float *) fft_malloc(size);
	memset(fftOutput, 0, size);

	if (!fftInput | !fftOutput) {
		LOG(ALERT) << "Memory allocation error";
		return false;
	}

	fftHandle = init_fft(0, m, blockLen, blockLen + hLen,
			     fftInput, fftOutput, hLen);
	return true;
}

bool ChannelizerBase::mapBuffers()
{
	if (!fftHandle) {
		LOG(ALERT) << "FFT buffers not initialized";
		return false;
	}

	hInputs = (float **) malloc(sizeof(float *) * m);
	hOutputs = (float **) malloc(sizeof(float *) * m);
	if (!hInputs | !hOutputs)
		return false;

	for (size_t i = 0; i < m; i++) {
		hInputs[i] = &fftOutput[2 * (i * (blockLen + hLen) + hLen)];
		hOutputs[i] = &fftInput[2 * (i * blockLen)];
	}

	return true;
}

/*
 * Setup filterbank internals
 */
bool ChannelizerBase::init()
{
	/*
	 * Filterbank coefficients, fft plan, history, and output sample
	 * rate conversion blocks
	 */
	if (!initFilters()) {
		LOG(ALERT) << "Failed to initialize channelizing filter";
		return false;
	}

	hist = (float **) malloc(sizeof(float *) * m);
	for (size_t i = 0; i < m; i++) {
		hist[i] = new float[2 * hLen];
		memset(hist[i], 0, 2 * hLen * sizeof(float));
	}

	if (!initFFT()) {
		LOG(ALERT) << "Failed to initialize FFT";
		return false;
	}

	mapBuffers();

	return true;
}

/* Check vector length validity */
bool ChannelizerBase::checkLen(size_t innerLen, size_t outerLen)
{
	if (outerLen != innerLen * m) {
		LOG(ALERT) << "Invalid outer length " << innerLen
			   <<  " is not multiple of " << blockLen;
		return false;
	}

	if (innerLen != blockLen) {
		LOG(ALERT) << "Invalid inner length " << outerLen
			   <<  " does not equal " << blockLen;
		return false;
	}

	return true;
}

/*
 * Setup channelizer parameters
 */
ChannelizerBase::ChannelizerBase(size_t m, size_t blockLen, size_t hLen)
	: subFilters(NULL), hInputs(NULL), hOutputs(NULL), hist(NULL),
	  fftInput(NULL), fftOutput(NULL), fftHandle(NULL)
{
	this->m = m;
	this->hLen = hLen;
	this->blockLen = blockLen;
}

ChannelizerBase::~ChannelizerBase()
{
	free_fft(fftHandle);

	for (size_t i = 0; i < m; i++) {
		free(subFilters[i]);
		delete[] hist[i];
	}
	free(subFilters);

	fft_free(fftInput);
	fft_free(fftOutput);

	free(hInputs);
	free(hOutputs);
	free(hist);
}
<|endoftext|>


<commit_before>/**
 * \file scheme.cpp
 * \date 2015
 */

#include <string>
#include <iostream>

#include <uscheme/defs.hpp>

void usage(void)
{
    std::cout <<
    "\n"
    "usage: scheme [-h]\n"
    "\n"
    "Scheme interpreter using libuscheme.\n"
    "\n"
    "libuscheme version: " << uscheme::version() << "\n" <<
    "\n";
}

void usage_and_die(void)
{
    usage();
    exit(1);
}

int main(int argc, const char* argv[])
{
    if (argc != 2) { usage_and_die(); }

    std::string arg1(argv[1]);
    if (arg1 != "-h") {
        usage_and_die();
    } else {
        usage();
    }

    return 0;
}
<commit_msg>Add copyright to scheme.cpp<commit_after>/*
Copyright (c) 2015, Aaditya Kalsi
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice, this
   list of conditions and the following disclaimer.
2. 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.

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 OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

/**
 * \file scheme.cpp
 * \date 2015
 */

#include <string>
#include <iostream>

#include <uscheme/defs.hpp>

void usage(void)
{
    std::cout <<
    "\n"
    "usage: scheme [-h]\n"
    "\n"
    "Scheme interpreter using libuscheme.\n"
    "\n"
    "libuscheme version: " << uscheme::version() << "\n" <<
    "\n";
}

void usage_and_die(void)
{
    usage();
    exit(1);
}

int main(int argc, const char* argv[])
{
    if (argc != 2) { usage_and_die(); }

    std::string arg1(argv[1]);
    if (arg1 != "-h") {
        usage_and_die();
    } else {
        usage();
    }

    return 0;
}
<|endoftext|>


<commit_before>/*
 * Copyright 2006-2008 The FLWOR Foundation.
 *
 * 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 <iostream>
#include <cassert>
#include <zorba/zorba.h>
#include <zorba/debugger_client.h>
#include <zorba/debugger_default_event_handler.h>
#include <simplestore/simplestore.h>
#include <zorbautils/thread.h>
#include <zorbaerrors/errors.h>
#ifdef WIN32
#include <windows.h>
#define sleep(s) Sleep(s*1000)
#endif

using namespace zorba;

class MyDebuggerEventHandler: public DefaultDebuggerEventHandler
{
  public:
    virtual ~MyDebuggerEventHandler(){}

    void started()
    {
      std::cerr << "Query started" << std::endl;
    }

    void idle()
    {
      std::cerr << "Query idle" << std::endl;
    }

    void suspended( QueryLocation &aLocation, SuspendedBy aCause )
    {
      std::cerr << "Suspended at line: " << aLocation.getLineBegin();
    }

    void resumed()
    {
      std::cerr << "Query resumed" << std::endl;
    }

    void terminated()
    {
      std::cerr << "Query terminated" << std::endl;
    }

    void evaluated( String &anExpr, String &aResult, String &aReturnType, String &anError )
    {
      if ( anError == "" )
      {
        std::cerr << anExpr << ": " << aResult << std::endl;
      } else {
        std::cerr << anError << std::endl;
      }
    }
};

ZORBA_THREAD_RETURN runClient( void* )
{
  sleep(3);
  MyDebuggerEventHandler lEventHandler;
  ZorbaDebuggerClient * lClient = ZorbaDebuggerClient::createClient( 8000, 9000 );
  lClient->registerEventHandler( &lEventHandler );
  lClient->run();
  sleep(1);
  lClient->quit();
  delete lClient;
  return 0;
}

bool debugger_example_1(Zorba *aZorba)
{
  XQuery_t lQuery = aZorba->createQuery();
  lQuery->setDebugMode(true);
  lQuery->compile("for $i in ( 1 to 10 ) return $i");
  lQuery->debug();
  lQuery->close();
  return true;
}

bool debugger_example_2(Zorba *aZorba)
{
  XQuery_t lQuery = aZorba->createQuery();
  lQuery->setFileName("foo.xq");
  lQuery->setDebugMode(true);
  assert(lQuery->getDebugMode());
  lQuery->compile("1+2");
  lQuery->debug( 8000, 9000 );
  lQuery->close();
  return true;
}

bool debugger_example_3(Zorba *aZorba)
{
  try
  {
    XQuery_t lQuery = aZorba->createQuery();
    lQuery->compile("1+2");
    lQuery->debug();
    lQuery->close();
  } catch( error::ZorbaError &e ) {
    return true;
  }
  return false;
}

int debugger( int argc, char *argv[] )
{
  simplestore::SimpleStore *lStore = simplestore::SimpleStoreManager::getStore();
  Zorba *lZorba = Zorba::getInstance( lStore );
  bool res = false;
  {
    Thread lThread(runClient, 0);
    std::cout << "executing example 1" << std::endl;
    res = debugger_example_1(lZorba);
    lThread.join();
    if ( !res ) return 1;
    std::cout << std::endl;
  }

  {
    Thread lThread(runClient, 0);
    std::cout << "executing example 2" << std::endl;
    res = debugger_example_2(lZorba);
    lThread.join();
    if ( !res ) return 1;
    std::cout << std::endl;
  }

  {
    std::cout << "executing example 3" << std::endl;
    res = debugger_example_3(lZorba);
    if ( !res ) return 1;
    std::cout << std::endl;
  }

  lZorba->shutdown();
  simplestore::SimpleStoreManager::shutdownStore(lStore);
  return 0;
}

<commit_msg>Remove illegal dependency: zorbautils/thread.h<commit_after>/*
 * Copyright 2006-2008 The FLWOR Foundation.
 *
 * 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 <iostream>
#include <cassert>
#include <zorba/zorba.h>
#include <zorba/debugger_client.h>
#include <zorba/debugger_default_event_handler.h>
#include <simplestore/simplestore.h>
#include <zorbaerrors/errors.h>
#ifdef WIN32
#include <windows.h>
#define sleep(s) Sleep(s*1000)
#endif
#ifdef ZORBA_HAVE_PTHREAD_H
#include <pthread.h>
#define ZORBA_THREAD_RETURN void *
#else
#define ZORBA_THREAD_RETURN DWORD WINAPI
#endif

using namespace zorba;

class MyDebuggerEventHandler: public DefaultDebuggerEventHandler
{
  public:
    virtual ~MyDebuggerEventHandler(){}

    void started()
    {
      std::cerr << "Query started" << std::endl;
    }

    void idle()
    {
      std::cerr << "Query idle" << std::endl;
    }

    void suspended( QueryLocation &aLocation, SuspendedBy aCause )
    {
      std::cerr << "Suspended at line: " << aLocation.getLineBegin();
    }

    void resumed()
    {
      std::cerr << "Query resumed" << std::endl;
    }

    void terminated()
    {
      std::cerr << "Query terminated" << std::endl;
    }

    void evaluated( String &anExpr, String &aResult, String &aReturnType, String &anError )
    {
      if ( anError == "" )
      {
        std::cerr << anExpr << ": " << aResult << std::endl;
      } else {
        std::cerr << anError << std::endl;
      }
    }
};

ZORBA_THREAD_RETURN runClient( void* )
{
  sleep(3);
  MyDebuggerEventHandler lEventHandler;
  ZorbaDebuggerClient * lClient = ZorbaDebuggerClient::createClient( 8000, 9000 );
  lClient->registerEventHandler( &lEventHandler );
  lClient->run();
  sleep(1);
  lClient->quit();
  delete lClient;
  return 0;
}

bool debugger_example_1(Zorba *aZorba)
{
  XQuery_t lQuery = aZorba->createQuery();
  lQuery->setDebugMode(true);
  lQuery->compile("for $i in ( 1 to 10 ) return $i");
  lQuery->debug();
  lQuery->close();
  return true;
}

bool debugger_example_2(Zorba *aZorba)
{
  XQuery_t lQuery = aZorba->createQuery();
  lQuery->setFileName("foo.xq");
  lQuery->setDebugMode(true);
  assert(lQuery->getDebugMode());
  lQuery->compile("1+2");
  lQuery->debug( 8000, 9000 );
  lQuery->close();
  return true;
}

bool debugger_example_3(Zorba *aZorba)
{
  try
  {
    XQuery_t lQuery = aZorba->createQuery();
    lQuery->compile("1+2");
    lQuery->debug();
    lQuery->close();
  } catch( error::ZorbaError &e ) {
    return true;
  }
  return false;
}

int debugger( int argc, char *argv[] )
{
  simplestore::SimpleStore *lStore = simplestore::SimpleStoreManager::getStore();
  Zorba *lZorba = Zorba::getInstance( lStore );
  bool res = false;
  {
#ifdef ZORBA_HAVE_PTHREAD_H
    pthread_t lThread;
    if ( pthread_create( &lThread, 0, runClient, 0 ) != 0 )
#else
    HANDLE lThread;
    if ( ( lThread = CreateThread(0, 0, runClient, 0, 0, 0) ) == 0 )
#endif
    {
      std::cerr << "Couldn't start the thread" << std::endl;
      return 1;
    }
    std::cout << "executing example 1" << std::endl;
    res = debugger_example_1(lZorba);
#ifdef ZORBA_HAVE_PTHREAD_H
    pthread_join( lThread, 0 );
#else
    WaitForSingleObject( lThread, INFINITE );
#endif
    if ( !res ) return 1;
    std::cout << std::endl;
  }

  {
    std::cout << "executing example 2" << std::endl;
#ifdef ZORBA_HAVE_PTHREAD_H
    pthread_t lThread;
    if ( pthread_create( &lThread, 0, runClient, 0 ) != 0 )
#else
    HANDLE lThread;
    if ( ( lThread = CreateThread(0, 0, runClient, 0, 0, 0) ) == 0 )
#endif
    {
      std::cerr << "Couldn't start the thread" << std::endl;
      return 1;
    }
    res = debugger_example_2(lZorba);
#ifdef ZORBA_HAVE_PTHREAD_H
    pthread_join( lThread, 0 );
#else
    WaitForSingleObject( lThread, INFINITE );
#endif
    if ( !res ) return 1;
    std::cout << std::endl;
  }

  {
    std::cout << "executing example 3" << std::endl;
    res = debugger_example_3(lZorba);
    if ( !res ) return 1;
    std::cout << std::endl;
  }

  lZorba->shutdown();
  simplestore::SimpleStoreManager::shutdownStore(lStore);
  return 0;
}

<|endoftext|>


<commit_before>/*
 * Copyright 2006-2008 The FLWOR Foundation.
 *
 * 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 <iostream>
#include <cassert>
#include <zorba/zorba.h>
#include <zorba/debugger_client.h>
#include <zorba/debugger_default_event_handler.h>
#include <simplestore/simplestore.h>
#ifdef WIN32
#include <windows.h>
#define sleep(s) Sleep(s*1000)
#endif
#ifdef ZORBA_HAVE_PTHREAD_H
#include <pthread.h>
#define ZORBA_THREAD_RETURN void *
#else
#define ZORBA_THREAD_RETURN DWORD WINAPI
#endif

using namespace zorba;

class MyDebuggerEventHandler: public DefaultDebuggerEventHandler
{
  public:
    virtual ~MyDebuggerEventHandler(){}

    void started()
    {
      std::cerr << "Query started" << std::endl;
    }

    void idle()
    {
      std::cerr << "Query idle" << std::endl;
    }

    void suspended( QueryLocation &aLocation, SuspendedBy aCause )
    {
      std::cerr << "Suspended at line: " << aLocation.getLineBegin();
    }

    void resumed()
    {
      std::cerr << "Query resumed" << std::endl;
    }

    void terminated()
    {
      std::cerr << "Query terminated" << std::endl;
    }

    void evaluated(String &anExpr, std::list< std::pair<String, String> > &aValuesAndTypes)
    {
      std::list<std::pair<String, String> >::iterator it;
      for(it=aValuesAndTypes.begin(); it!=aValuesAndTypes.end(); ++it)
      {
        std::cerr << it->first << " " << it->second << std::endl;
      }
    }

    void evaluated(String &anExpr, String &anError)
    {
      std::cerr << "An error happened: " << anError << std::endl;
    }
};

ZORBA_THREAD_RETURN runClient( void* )
{
  sleep(1);
  MyDebuggerEventHandler lEventHandler;
  ZorbaDebuggerClient * lClient = ZorbaDebuggerClient::createClient( 8000, 9000 );
  lClient->registerEventHandler( &lEventHandler );
  lClient->run();
  sleep(1);
  lClient->terminate();
  delete lClient;
  return 0;
}

bool debugger_example_1(Zorba *aZorba)
{
  XQuery_t lQuery = aZorba->createQuery();
  lQuery->setDebugMode(true);
  lQuery->compile("for $i in ( 1 to 10 ) return $i");
  lQuery->debug();
  lQuery->close();
  return true;
}

bool debugger_example_3(Zorba *aZorba)
{
  try
  {
    XQuery_t lQuery = aZorba->createQuery();
    lQuery->compile("1+2");
    lQuery->debug();
    lQuery->close();
  } catch( ZorbaException &e ) {
    return true;
  }
  return false;
}

int debugger( int argc, char *argv[] )
{
  simplestore::SimpleStore *lStore = simplestore::SimpleStoreManager::getStore();
  Zorba *lZorba = Zorba::getInstance( lStore );
  bool res = false;
  {
#ifdef ZORBA_HAVE_PTHREAD_H
    pthread_t lThread;
    if ( pthread_create( &lThread, 0, runClient, 0 ) != 0 )
#else
    HANDLE lThread;
    if ( ( lThread = CreateThread(0, 0, runClient, 0, 0, 0) ) == 0 )
#endif
    {
      std::cerr << "Couldn't start the thread" << std::endl;
      return 1;
    }
    std::cout << "executing example 1" << std::endl;
    res = debugger_example_1(lZorba);
#ifdef ZORBA_HAVE_PTHREAD_H
    pthread_cancel( lThread );
#else
    CloseHandle( lThread );;
#endif
    if ( !res ) return 1;
    std::cout << std::endl;
  }

  {
    std::cout << "executing example 3" << std::endl;
    res = debugger_example_3(lZorba);
    if ( !res ) return 1;
    std::cout << std::endl;
  }

  lZorba->shutdown();
  simplestore::SimpleStoreManager::shutdownStore(lStore);
  return 0;
}

<commit_msg>fixed a warning<commit_after>/*
 * Copyright 2006-2008 The FLWOR Foundation.
 *
 * 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 <iostream>
#include <cassert>
#include <zorba/zorba.h>
#include <zorba/debugger_client.h>
#include <zorba/debugger_default_event_handler.h>
#include <simplestore/simplestore.h>
#ifdef WIN32
#include <windows.h>
#define sleep(s) Sleep(s*1000)
#endif
#ifdef ZORBA_HAVE_PTHREAD_H
#include <pthread.h>
#define ZORBA_THREAD_RETURN void *
#else
#define ZORBA_THREAD_RETURN DWORD WINAPI
#endif

using namespace zorba;

class MyDebuggerEventHandler: public DefaultDebuggerEventHandler
{
  public:
    virtual ~MyDebuggerEventHandler(){}

    void started()
    {
      std::cerr << "Query started" << std::endl;
    }

    void idle()
    {
      std::cerr << "Query idle" << std::endl;
    }

    void suspended( QueryLocation &aLocation, SuspendedBy aCause )
    {
      std::cerr << "Suspended at line: " << aLocation.getLineBegin();
    }

    void resumed()
    {
      std::cerr << "Query resumed" << std::endl;
    }

    void terminated()
    {
      std::cerr << "Query terminated" << std::endl;
    }

    void evaluated(String &anExpr, std::list< std::pair<String, String> > &aValuesAndTypes)
    {
      std::list<std::pair<String, String> >::iterator it;
      for(it=aValuesAndTypes.begin(); it!=aValuesAndTypes.end(); ++it)
      {
        std::cerr << it->first << " " << it->second << std::endl;
      }
    }

    void evaluated(String &anExpr, String &anError)
    {
      std::cerr << "An error happened: " << anError << std::endl;
    }
};

ZORBA_THREAD_RETURN runClient( void* )
{
  sleep(1);
  MyDebuggerEventHandler lEventHandler;
  ZorbaDebuggerClient * lClient = ZorbaDebuggerClient::createClient( 8000, 9000 );
  lClient->registerEventHandler( &lEventHandler );
  lClient->run();
  sleep(1);
  lClient->terminate();
  delete lClient;
  return 0;
}

bool debugger_example_1(Zorba *aZorba)
{
  XQuery_t lQuery = aZorba->createQuery();
  lQuery->setDebugMode(true);
  lQuery->compile("for $i in ( 1 to 10 ) return $i");
  lQuery->debug();
  lQuery->close();
  return true;
}

bool debugger_example_3(Zorba *aZorba)
{
  try
  {
    XQuery_t lQuery = aZorba->createQuery();
    lQuery->compile("1+2");
    lQuery->debug();
    lQuery->close();
  } catch( ZorbaException & ) {
    return true;
  }
  return false;
}

int debugger( int argc, char *argv[] )
{
  simplestore::SimpleStore *lStore = simplestore::SimpleStoreManager::getStore();
  Zorba *lZorba = Zorba::getInstance( lStore );
  bool res = false;
  {
#ifdef ZORBA_HAVE_PTHREAD_H
    pthread_t lThread;
    if ( pthread_create( &lThread, 0, runClient, 0 ) != 0 )
#else
    HANDLE lThread;
    if ( ( lThread = CreateThread(0, 0, runClient, 0, 0, 0) ) == 0 )
#endif
    {
      std::cerr << "Couldn't start the thread" << std::endl;
      return 1;
    }
    std::cout << "executing example 1" << std::endl;
    res = debugger_example_1(lZorba);
#ifdef ZORBA_HAVE_PTHREAD_H
    pthread_cancel( lThread );
#else
    CloseHandle( lThread );;
#endif
    if ( !res ) return 1;
    std::cout << std::endl;
  }

  {
    std::cout << "executing example 3" << std::endl;
    res = debugger_example_3(lZorba);
    if ( !res ) return 1;
    std::cout << std::endl;
  }

  lZorba->shutdown();
  simplestore::SimpleStoreManager::shutdownStore(lStore);
  return 0;
}

<|endoftext|>


<commit_before>/** @file
    @brief Implementation

    @date 2014

    @author
    Sensics, Inc.
    <http://sensics.com/osvr>
*/

// Copyright 2014 Sensics, Inc.
//
// 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.

// Internal Includes
#include "DevicesWithParameters.h"
#include "GetSerialPortState.h"
#include <osvr/VRPNServer/VRPNDeviceRegistration.h>
#include <osvr/USBSerial/USBSerial.h>

// Library/third-party includes
#include <json/reader.h>
#include <json/value.h>

#include <vrpn_YEI_3Space.h>

// Standard includes
#include <vector>
#include <memory>
#include <string>
#include <string.h>

namespace {
/// @brief Manage an array of dynamically allocated c-strings, terminated with a
/// null entry.
class CStringArray : boost::noncopyable {
  public:
    typedef std::unique_ptr<char[]> UniqueCharArray;
    void push_back(std::string const &str) {
        // Remove null terminator from array
        if (m_arrayHasNullTerminator()) {
            m_data.pop_back();
        }
        {
            const size_t stringLength = str.size() + 1;
            UniqueCharArray copy(new char[stringLength]);
            memcpy(copy.get(), str.c_str(), stringLength);
            m_dataOwnership.push_back(std::move(copy));
        }
        m_data.push_back(m_dataOwnership.back().get());
    }
    const char **get_array() {
        // Ensure null terminator on array
        if (!m_arrayHasNullTerminator()) {
            m_data.push_back(nullptr);
        }
        return m_data.data();
    }

  private:
    bool m_arrayHasNullTerminator() const {
        return !m_data.empty() && nullptr == m_data.back();
    }
    std::vector<const char *> m_data;
    std::vector<UniqueCharArray> m_dataOwnership;
};
} // namespace

void createYEI(VRPNMultiserverData &data, OSVR_PluginRegContext ctx,
               const char *params) {
    Json::Reader reader;
    Json::Value root;
    if (!reader.parse(params, root)) {
        throw std::runtime_error("Could not parse configuration: " +
                                 reader.getFormattedErrorMessages());
    }

    osvr::usbserial::USBSerialDevice serialDevice(root["vendorID"].asString(),
                                                  root["productID"].asString());

    std::string port = normalizeAndVerifySerialPort(serialDevice.getPort());
    bool calibrate_gyros_on_setup =
        root.get("calibrateGyrosOnSetup", false).asBool();
    bool tare_on_setup = root.get("tareOnSetup", false).asBool();
    double frames_per_second = root.get("framesPerSecond", 250).asFloat();

    Json::Value commands = root.get("resetCommands", Json::arrayValue);
    CStringArray reset_commands;

    for (Json::ArrayIndex i = 0, e = commands.size(); i < e; ++i) {
        reset_commands.push_back(commands[i].asString());
    }

    osvr::vrpnserver::VRPNDeviceRegistration reg(ctx);

    reg.registerDevice(new vrpn_YEI_3Space_Sensor(
        reg.useDecoratedName(data.getName("YEI_3Space_Sensor")).c_str(),
        reg.getVRPNConnection(), port.c_str(), 115200, calibrate_gyros_on_setup,
        tare_on_setup, frames_per_second, 0, 0, 1, 0,
        reset_commands.get_array()));
}
<commit_msg>iterate over connected serial devices(YEI trackers) and register them<commit_after>/** @file
    @brief Implementation

    @date 2014

    @author
    Sensics, Inc.
    <http://sensics.com/osvr>
*/

// Copyright 2014 Sensics, Inc.
//
// 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.

// Internal Includes
#include "DevicesWithParameters.h"
#include "GetSerialPortState.h"
#include <osvr/VRPNServer/VRPNDeviceRegistration.h>
#include <osvr/USBSerial/USBSerialEnum.h>

// Library/third-party includes
#include <json/reader.h>
#include <json/value.h>

#include <vrpn_YEI_3Space.h>

// Standard includes
#include <vector>
#include <memory>
#include <string>
#include <string.h>

namespace {
/// @brief Manage an array of dynamically allocated c-strings, terminated with a
/// null entry.
class CStringArray : boost::noncopyable {
  public:
    typedef std::unique_ptr<char[]> UniqueCharArray;
    void push_back(std::string const &str) {
        // Remove null terminator from array
        if (m_arrayHasNullTerminator()) {
            m_data.pop_back();
        }
        {
            const size_t stringLength = str.size() + 1;
            UniqueCharArray copy(new char[stringLength]);
            memcpy(copy.get(), str.c_str(), stringLength);
            m_dataOwnership.push_back(std::move(copy));
        }
        m_data.push_back(m_dataOwnership.back().get());
    }
    const char **get_array() {
        // Ensure null terminator on array
        if (!m_arrayHasNullTerminator()) {
            m_data.push_back(nullptr);
        }
        return m_data.data();
    }

  private:
    bool m_arrayHasNullTerminator() const {
        return !m_data.empty() && nullptr == m_data.back();
    }
    std::vector<const char *> m_data;
    std::vector<UniqueCharArray> m_dataOwnership;
};
} // namespace

void createYEI(VRPNMultiserverData &data, OSVR_PluginRegContext ctx,
               const char *params) {
    Json::Reader reader;
    Json::Value root;
    if (!reader.parse(params, root)) {
        throw std::runtime_error("Could not parse configuration: " +
                                 reader.getFormattedErrorMessages());
    }
	uint16_t vID = 0x9AC;
	uint16_t pID = 0x3F2;
	for (auto dev : osvr::usbserial::Enumerator(vID, pID)){

		std::string port = normalizeAndVerifySerialPort(dev->getPort());

		bool calibrate_gyros_on_setup =
			root.get("calibrateGyrosOnSetup", false).asBool();
		bool tare_on_setup = root.get("tareOnSetup", false).asBool();
		double frames_per_second = root.get("framesPerSecond", 250).asFloat();

		Json::Value commands = root.get("resetCommands", Json::arrayValue);
		CStringArray reset_commands;

		for (Json::ArrayIndex i = 0, e = commands.size(); i < e; ++i) {
			reset_commands.push_back(commands[i].asString());
		}

		osvr::vrpnserver::VRPNDeviceRegistration reg(ctx);

		reg.registerDevice(new vrpn_YEI_3Space_Sensor(
			reg.useDecoratedName(data.getName("YEI_3Space_Sensor")).c_str(),
			reg.getVRPNConnection(), port.c_str(), 115200, calibrate_gyros_on_setup,
			tare_on_setup, frames_per_second, 0, 0, 1, 0,
			reset_commands.get_array()));
	}

}
<|endoftext|>


<commit_before>/* BEGIN_COMMON_COPYRIGHT_HEADER
 * (c)LGPL2+
 *
 * LXQt - a lightweight, Qt based, desktop toolset
 * https://lxqt.org/
 *
 * Copyright: 2018 LXQt team
 *
 * This program or library is free software; you can redistribute it
 * and/or modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * 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
 * Lesser General Public License for more details.

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

#include "configothertoolkits.h"
#include <QFile>
#include <QTextStream>
#include <QStandardPaths>
#include <QMetaEnum>
#include <QToolBar>
#include <QDir>
#include <QFileInfo>
#include <QFont>
#include <QDateTime>
#include <QMessageBox>

#include <sys/types.h>
#include <signal.h>

static const char *GTK2_CONFIG = R"GTK2_CONFIG(
# Created by lxqt-config-appearance (DO NOT EDIT!)
gtk-theme-name = "%1"
gtk-icon-theme-name = "%2"
gtk-font-name = "%3"
gtk-button-images = %4
gtk-menu-images = %4
gtk-toolbar-style = %5
)GTK2_CONFIG";

static const char *GTK3_CONFIG = R"GTK3_CONFIG(
# Created by lxqt-config-appearance (DO NOT EDIT!)
[Settings]
gtk-theme-name = %1
gtk-icon-theme-name = %2
# GTK3 ignores bold or italic attributes.
gtk-font-name = %3
gtk-menu-images = %4
gtk-button-images = %4
gtk-toolbar-style = %5
)GTK3_CONFIG";

static const char *XSETTINGS_CONFIG = R"XSETTINGS_CONFIG(
# Created by lxqt-config-appearance (DO NOT EDIT!)
Net/IconThemeName "%2"
Net/ThemeName "%1"
Gtk/FontName "%3"
Gtk/MenuImages %4
Gtk/ButtonImages %4
Gtk/ToolbarStyle "%5"
)XSETTINGS_CONFIG";

ConfigOtherToolKits::ConfigOtherToolKits(LXQt::Settings *settings,  LXQt::Settings *configAppearanceSettings, QObject *parent) : QObject(parent)
{
    mSettings = settings;
    mConfigAppearanceSettings = configAppearanceSettings;
    if(tempFile.open()) {
        mXsettingsdProc.setProcessChannelMode(QProcess::ForwardedChannels);
        mXsettingsdProc.start("xsettingsd", QStringList() << "-c" << tempFile.fileName());
        if(!mXsettingsdProc.waitForStarted())
            return;
        tempFile.close();
    }
}

ConfigOtherToolKits::~ConfigOtherToolKits()
{
    mXsettingsdProc.close();
}

static QString get_environment_var(const char *envvar, const char *defaultValue)
{
    QString homeDir = QStandardPaths::writableLocation(QStandardPaths::HomeLocation);
    QString mDirPath = QString::fromLocal8Bit(qgetenv(envvar));
    if(mDirPath.isEmpty())
        mDirPath = homeDir + defaultValue;
    else {
        for(QString path : mDirPath.split(":") ) {
            mDirPath = path;
            break;
        }
    }
    return mDirPath;
}

static QString _get_config_path(QString path)
{
    QString homeDir = QStandardPaths::writableLocation(QStandardPaths::HomeLocation);
    path.replace("$XDG_CONFIG_HOME", get_environment_var("XDG_CONFIG_HOME", "/.config"));
    path.replace("$GTK2_RC_FILES",   get_environment_var("GTK2_RC_FILES", "/.gtkrc-2.0")); // If $GTK2_RC_FILES is undefined, "~/.gtkrc-2.0" will be used.
    path.replace("~", homeDir);
    return path;
}

QString ConfigOtherToolKits::getGTKConfigPath(QString version)
{
    if(version == "2.0")
        return _get_config_path("$GTK2_RC_FILES");
    return _get_config_path(QString("$XDG_CONFIG_HOME/gtk-%1/settings.ini").arg(version));
}

static bool grep(QFile &file, QByteArray text)
{
    if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
        return false;
    while (!file.atEnd()) {
        QByteArray line = file.readLine().trimmed();
        if(line.startsWith(text)) {
            return true;
        }
    }
    file.close();
    return false;
}

bool ConfigOtherToolKits::backupGTKSettings(QString version)
{
        QString gtkrcPath = getGTKConfigPath(version);
        QFile file(gtkrcPath);
        if(file.exists() && !grep(file, "# Created by lxqt-config-appearance (DO NOT EDIT!)")) {
            QString backupPath = gtkrcPath + "-" + QString::number(QDateTime::currentSecsSinceEpoch()) + "~";
            file.copy(backupPath);
            QMessageBox::warning(nullptr, tr("GTK themes"),
                tr("
'%1' has been overwritten.

You can find a copy of your old settings in '%2'
")
                .arg(getGTKConfigPath(version))
                .arg(backupPath)
                , QMessageBox::Ok);
            return true;
        }
        return false;
}

void ConfigOtherToolKits::setConfig()
{
    if(!mConfigAppearanceSettings->contains("ControlGTKThemeEnabled"))
        mConfigAppearanceSettings->setValue("ControlGTKThemeEnabled", false);
    bool controlGTKThemeEnabled = mConfigAppearanceSettings->value("ControlGTKThemeEnabled").toBool();
    if(! controlGTKThemeEnabled)
        return;
    updateConfigFromSettings();
    mConfig.styleTheme = getGTKThemeFromRCFile("3.0");
    setGTKConfig("3.0");
    mConfig.styleTheme = getGTKThemeFromRCFile("2.0");
    setGTKConfig("2.0");
    setXSettingsConfig();
}

void ConfigOtherToolKits::setXSettingsConfig()
{
    // setGTKConfig is called before calling setXSettingsConfig,
    // then updateConfigFromSettings is not required.
    //updateConfigFromSettings();
    //mConfig.styleTheme = getGTKThemeFromRCFile(version);

    // Reload settings. xsettingsd must be installed.
    // xsettingsd settings are written to stdin.
    if(QProcess::Running == mXsettingsdProc.state()) {
        QFile file(tempFile.fileName());
        if(file.open(QIODevice::WriteOnly)) {
            file.write( getConfig(XSETTINGS_CONFIG).toLocal8Bit() );
            file.flush();
            file.close();
        }
        int pid = mXsettingsdProc.processId();
        kill(pid, SIGHUP);
    }
}

void ConfigOtherToolKits::setGTKConfig(QString version, QString theme)
{
    updateConfigFromSettings();
    if(!theme.isEmpty())
        mConfig.styleTheme = theme;
    backupGTKSettings(version);
    QString gtkrcPath = getGTKConfigPath(version);
    if(version == "2.0")
        writeConfig(gtkrcPath, GTK2_CONFIG);
    else
        writeConfig(gtkrcPath, GTK3_CONFIG);
}

QString ConfigOtherToolKits::getConfig(const char *configString)
{
    return QString(configString).arg(mConfig.styleTheme, mConfig.iconTheme,
        mConfig.fontName, mConfig.buttonStyle==0 ? "0":"1",
        mConfig.toolButtonStyle
        );
}

void ConfigOtherToolKits::writeConfig(QString path, const char *configString)
{
    path = _get_config_path(path);

    QFile file(path);
    if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
        return;
    }
    QTextStream out(&file);
    out << getConfig(configString);
    out.flush();
    file.close();
}

QStringList ConfigOtherToolKits::getGTKThemes(QString version)
{
    QStringList themeList;
    QString configFile = version=="2.0" ? "gtk-2.0/gtkrc" : QString("gtk-%1/gtk.css").arg(version);

    QStringList dataPaths = QStandardPaths::standardLocations(QStandardPaths::GenericDataLocation);
    for(QString dataPath : dataPaths) {
        QDir themesPath(dataPath + "/themes");
        QStringList themes = themesPath.entryList(QDir::Dirs);
        for(QString theme : themes) {
            QFileInfo themePath(QString("%1/themes/%2/%3").arg(dataPath, theme, configFile));
            if(themePath.exists())
                themeList.append(theme);
        }
    }
    return themeList;
}

QString ConfigOtherToolKits::getGTKThemeFromRCFile(QString version)
{
    if(version == "2.0") {
        QString gtkrcPath = _get_config_path("$GTK2_RC_FILES");
        QFile file(gtkrcPath);
        if(file.exists()) {
            if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
                return QString();
            while (!file.atEnd()) {
                QByteArray line = file.readLine().trimmed();
                if(line.startsWith("gtk-theme-name")) {
                    QList<QByteArray> parts = line.split('=');
                    if(parts.size()>=2) {
                        file.close();
                        return parts[1].replace('"', "").trimmed();
                    }
                }
            }
            file.close();
        }
    } else {
        QString gtkrcPath = _get_config_path(QString("$XDG_CONFIG_HOME/gtk-%1/settings.ini").arg(version));
        QFile file(gtkrcPath);
        if(file.exists()) {
            if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
                return QString();
            bool settingsFound = false;
            while (!file.atEnd()) {
                QByteArray line = file.readLine().trimmed();
                if(line.startsWith("[Settings]"))
                    settingsFound = true;
                else if(line.startsWith("[") && line.endsWith("]"))
                    settingsFound = false;
                else if(settingsFound && line.startsWith("gtk-theme-name")) {
                    QList<QByteArray> parts = line.split('=');
                    if(parts.size()>=2) {
                        file.close();
                        return parts[1].trimmed();
                    }
                }
            }
            file.close();
        }
    }
    return QString();
}

void ConfigOtherToolKits::updateConfigFromSettings()
{
    mSettings->beginGroup(QLatin1String("Qt"));
    QFont font;
    font.fromString(mSettings->value("font").toString());
    // Font name from: https://developer.gnome.org/pango/stable/pango-Fonts.html#pango-font-description-from-string
    // FAMILY-LIST [SIZE]", where FAMILY-LIST is a comma separated list of families optionally terminated by a comma,
    // STYLE_OPTIONS is a whitespace separated list of words where each word describes one of style, variant, weight, stretch, or gravity, and
    // SIZE is a decimal number (size in points) or optionally followed by the unit modifier "px" for absolute size.
    mConfig.fontName = QString("%1%2%3 %4")
        .arg(font.family())                                 //%1
        .arg(font.style()==QFont::StyleNormal?"":" Italic") //%2
        .arg(font.weight()==QFont::Normal?"":" Bold")       //%3
        .arg(font.pointSize());                             //%4
    mSettings->endGroup();

    mConfig.iconTheme = mSettings->value("icon_theme").toString();
    {
        // Tool button style
        QByteArray tb_style = mSettings->value("tool_button_style").toByteArray();
        // convert toolbar style name to value
        QMetaEnum me = QToolBar::staticMetaObject.property(QToolBar::staticMetaObject.indexOfProperty("toolButtonStyle")).enumerator();
        int val = me.keyToValue(tb_style.constData());
        mConfig.buttonStyle = 1;
        switch(val) {
            case Qt::ToolButtonIconOnly:
                mConfig.toolButtonStyle = "GTK_TOOLBAR_ICONS";
                break;
            case Qt::ToolButtonTextOnly:
                mConfig.toolButtonStyle = "GTK_TOOLBAR_TEXT";
                mConfig.buttonStyle = 0;
                break;
            case Qt::ToolButtonTextUnderIcon:
                mConfig.toolButtonStyle = "GTK_TOOLBAR_BOTH";
                break;
            default:
                mConfig.toolButtonStyle = "GTK_TOOLBAR_BOTH_HORIZ";
        }
    }
}

<commit_msg>lxqt-config-appearance: mkpath if settings of GTK doesn't exists.<commit_after>/* BEGIN_COMMON_COPYRIGHT_HEADER
 * (c)LGPL2+
 *
 * LXQt - a lightweight, Qt based, desktop toolset
 * https://lxqt.org/
 *
 * Copyright: 2018 LXQt team
 *
 * This program or library is free software; you can redistribute it
 * and/or modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * 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
 * Lesser General Public License for more details.

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

#include "configothertoolkits.h"
#include <QFile>
#include <QTextStream>
#include <QStandardPaths>
#include <QMetaEnum>
#include <QToolBar>
#include <QDir>
#include <QFileInfo>
#include <QFont>
#include <QDateTime>
#include <QMessageBox>

#include <sys/types.h>
#include <signal.h>

static const char *GTK2_CONFIG = R"GTK2_CONFIG(
# Created by lxqt-config-appearance (DO NOT EDIT!)
gtk-theme-name = "%1"
gtk-icon-theme-name = "%2"
gtk-font-name = "%3"
gtk-button-images = %4
gtk-menu-images = %4
gtk-toolbar-style = %5
)GTK2_CONFIG";

static const char *GTK3_CONFIG = R"GTK3_CONFIG(
# Created by lxqt-config-appearance (DO NOT EDIT!)
[Settings]
gtk-theme-name = %1
gtk-icon-theme-name = %2
# GTK3 ignores bold or italic attributes.
gtk-font-name = %3
gtk-menu-images = %4
gtk-button-images = %4
gtk-toolbar-style = %5
)GTK3_CONFIG";

static const char *XSETTINGS_CONFIG = R"XSETTINGS_CONFIG(
# Created by lxqt-config-appearance (DO NOT EDIT!)
Net/IconThemeName "%2"
Net/ThemeName "%1"
Gtk/FontName "%3"
Gtk/MenuImages %4
Gtk/ButtonImages %4
Gtk/ToolbarStyle "%5"
)XSETTINGS_CONFIG";

ConfigOtherToolKits::ConfigOtherToolKits(LXQt::Settings *settings,  LXQt::Settings *configAppearanceSettings, QObject *parent) : QObject(parent)
{
    mSettings = settings;
    mConfigAppearanceSettings = configAppearanceSettings;
    if(tempFile.open()) {
        mXsettingsdProc.setProcessChannelMode(QProcess::ForwardedChannels);
        mXsettingsdProc.start("xsettingsd", QStringList() << "-c" << tempFile.fileName());
        if(!mXsettingsdProc.waitForStarted())
            return;
        tempFile.close();
    }
}

ConfigOtherToolKits::~ConfigOtherToolKits()
{
    mXsettingsdProc.close();
}

static QString get_environment_var(const char *envvar, const char *defaultValue)
{
    QString homeDir = QStandardPaths::writableLocation(QStandardPaths::HomeLocation);
    QString mDirPath = QString::fromLocal8Bit(qgetenv(envvar));
    if(mDirPath.isEmpty())
        mDirPath = homeDir + defaultValue;
    else {
        for(QString path : mDirPath.split(":") ) {
            mDirPath = path;
            break;
        }
    }
    return mDirPath;
}

static QString _get_config_path(QString path)
{
    QString homeDir = QStandardPaths::writableLocation(QStandardPaths::HomeLocation);
    path.replace("$XDG_CONFIG_HOME", get_environment_var("XDG_CONFIG_HOME", "/.config"));
    path.replace("$GTK2_RC_FILES",   get_environment_var("GTK2_RC_FILES", "/.gtkrc-2.0")); // If $GTK2_RC_FILES is undefined, "~/.gtkrc-2.0" will be used.
    path.replace("~", homeDir);
    return path;
}

QString ConfigOtherToolKits::getGTKConfigPath(QString version)
{
    if(version == "2.0")
        return _get_config_path("$GTK2_RC_FILES");
    return _get_config_path(QString("$XDG_CONFIG_HOME/gtk-%1/settings.ini").arg(version));
}

static bool grep(QFile &file, QByteArray text)
{
    if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
        return false;
    while (!file.atEnd()) {
        QByteArray line = file.readLine().trimmed();
        if(line.startsWith(text)) {
            return true;
        }
    }
    file.close();
    return false;
}

bool ConfigOtherToolKits::backupGTKSettings(QString version)
{
        QString gtkrcPath = getGTKConfigPath(version);
        QFile file(gtkrcPath);
        if(file.exists() && !grep(file, "# Created by lxqt-config-appearance (DO NOT EDIT!)")) {
            QString backupPath = gtkrcPath + "-" + QString::number(QDateTime::currentSecsSinceEpoch()) + "~";
            file.copy(backupPath);
            QMessageBox::warning(nullptr, tr("GTK themes"),
                tr("
'%1' has been overwritten.

You can find a copy of your old settings in '%2'
")
                .arg(getGTKConfigPath(version))
                .arg(backupPath)
                , QMessageBox::Ok);
            return true;
        }
        return false;
}

void ConfigOtherToolKits::setConfig()
{
    if(!mConfigAppearanceSettings->contains("ControlGTKThemeEnabled"))
        mConfigAppearanceSettings->setValue("ControlGTKThemeEnabled", false);
    bool controlGTKThemeEnabled = mConfigAppearanceSettings->value("ControlGTKThemeEnabled").toBool();
    if(! controlGTKThemeEnabled)
        return;
    updateConfigFromSettings();
    mConfig.styleTheme = getGTKThemeFromRCFile("3.0");
    setGTKConfig("3.0");
    mConfig.styleTheme = getGTKThemeFromRCFile("2.0");
    setGTKConfig("2.0");
    setXSettingsConfig();
}

void ConfigOtherToolKits::setXSettingsConfig()
{
    // setGTKConfig is called before calling setXSettingsConfig,
    // then updateConfigFromSettings is not required.
    //updateConfigFromSettings();
    //mConfig.styleTheme = getGTKThemeFromRCFile(version);

    // Reload settings. xsettingsd must be installed.
    // xsettingsd settings are written to stdin.
    if(QProcess::Running == mXsettingsdProc.state()) {
        QFile file(tempFile.fileName());
        if(file.open(QIODevice::WriteOnly)) {
            file.write( getConfig(XSETTINGS_CONFIG).toLocal8Bit() );
            file.flush();
            file.close();
        }
        int pid = mXsettingsdProc.processId();
        kill(pid, SIGHUP);
    }
}

void ConfigOtherToolKits::setGTKConfig(QString version, QString theme)
{
    updateConfigFromSettings();
    if(!theme.isEmpty())
        mConfig.styleTheme = theme;
    backupGTKSettings(version);
    QString gtkrcPath = getGTKConfigPath(version);
    if(version == "2.0")
        writeConfig(gtkrcPath, GTK2_CONFIG);
    else
        writeConfig(gtkrcPath, GTK3_CONFIG);
}

QString ConfigOtherToolKits::getConfig(const char *configString)
{
    return QString(configString).arg(mConfig.styleTheme, mConfig.iconTheme,
        mConfig.fontName, mConfig.buttonStyle==0 ? "0":"1",
        mConfig.toolButtonStyle
        );
}

void ConfigOtherToolKits::writeConfig(QString path, const char *configString)
{
    path = _get_config_path(path);

    QFile file(path);
    if(! file.exists()) {
        QFileInfo fileInfo(file);
        QDir::home().mkpath(fileInfo.path());
    }
    if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
        return;
    }
    QTextStream out(&file);
    out << getConfig(configString);
    out.flush();
    file.close();
}

QStringList ConfigOtherToolKits::getGTKThemes(QString version)
{
    QStringList themeList;
    QString configFile = version=="2.0" ? "gtk-2.0/gtkrc" : QString("gtk-%1/gtk.css").arg(version);

    QStringList dataPaths = QStandardPaths::standardLocations(QStandardPaths::GenericDataLocation);
    for(QString dataPath : dataPaths) {
        QDir themesPath(dataPath + "/themes");
        QStringList themes = themesPath.entryList(QDir::Dirs);
        for(QString theme : themes) {
            QFileInfo themePath(QString("%1/themes/%2/%3").arg(dataPath, theme, configFile));
            if(themePath.exists())
                themeList.append(theme);
        }
    }
    return themeList;
}

QString ConfigOtherToolKits::getGTKThemeFromRCFile(QString version)
{
    if(version == "2.0") {
        QString gtkrcPath = _get_config_path("$GTK2_RC_FILES");
        QFile file(gtkrcPath);
        if(file.exists()) {
            if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
                return QString();
            while (!file.atEnd()) {
                QByteArray line = file.readLine().trimmed();
                if(line.startsWith("gtk-theme-name")) {
                    QList<QByteArray> parts = line.split('=');
                    if(parts.size()>=2) {
                        file.close();
                        return parts[1].replace('"', "").trimmed();
                    }
                }
            }
            file.close();
        }
    } else {
        QString gtkrcPath = _get_config_path(QString("$XDG_CONFIG_HOME/gtk-%1/settings.ini").arg(version));
        QFile file(gtkrcPath);
        if(file.exists()) {
            if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
                return QString();
            bool settingsFound = false;
            while (!file.atEnd()) {
                QByteArray line = file.readLine().trimmed();
                if(line.startsWith("[Settings]"))
                    settingsFound = true;
                else if(line.startsWith("[") && line.endsWith("]"))
                    settingsFound = false;
                else if(settingsFound && line.startsWith("gtk-theme-name")) {
                    QList<QByteArray> parts = line.split('=');
                    if(parts.size()>=2) {
                        file.close();
                        return parts[1].trimmed();
                    }
                }
            }
            file.close();
        }
    }
    return QString();
}

void ConfigOtherToolKits::updateConfigFromSettings()
{
    mSettings->beginGroup(QLatin1String("Qt"));
    QFont font;
    font.fromString(mSettings->value("font").toString());
    // Font name from: https://developer.gnome.org/pango/stable/pango-Fonts.html#pango-font-description-from-string
    // FAMILY-LIST [SIZE]", where FAMILY-LIST is a comma separated list of families optionally terminated by a comma,
    // STYLE_OPTIONS is a whitespace separated list of words where each word describes one of style, variant, weight, stretch, or gravity, and
    // SIZE is a decimal number (size in points) or optionally followed by the unit modifier "px" for absolute size.
    mConfig.fontName = QString("%1%2%3 %4")
        .arg(font.family())                                 //%1
        .arg(font.style()==QFont::StyleNormal?"":" Italic") //%2
        .arg(font.weight()==QFont::Normal?"":" Bold")       //%3
        .arg(font.pointSize());                             //%4
    mSettings->endGroup();

    mConfig.iconTheme = mSettings->value("icon_theme").toString();
    {
        // Tool button style
        QByteArray tb_style = mSettings->value("tool_button_style").toByteArray();
        // convert toolbar style name to value
        QMetaEnum me = QToolBar::staticMetaObject.property(QToolBar::staticMetaObject.indexOfProperty("toolButtonStyle")).enumerator();
        int val = me.keyToValue(tb_style.constData());
        mConfig.buttonStyle = 1;
        switch(val) {
            case Qt::ToolButtonIconOnly:
                mConfig.toolButtonStyle = "GTK_TOOLBAR_ICONS";
                break;
            case Qt::ToolButtonTextOnly:
                mConfig.toolButtonStyle = "GTK_TOOLBAR_TEXT";
                mConfig.buttonStyle = 0;
                break;
            case Qt::ToolButtonTextUnderIcon:
                mConfig.toolButtonStyle = "GTK_TOOLBAR_BOTH";
                break;
            default:
                mConfig.toolButtonStyle = "GTK_TOOLBAR_BOTH_HORIZ";
        }
    }
}

<|endoftext|>