<commit_before>/*
* Runtime CPU detection
* (C) 2009-2010 Jack Lloyd
*
* Distributed under the terms of the Botan license
*/

#include <botan/cpuid.h>
#include <botan/types.h>
#include <botan/get_byte.h>
#include <botan/mem_ops.h>

#if defined(BOTAN_TARGET_OS_IS_DARWIN)
  #include <sys/sysctl.h>
#endif

#if defined(BOTAN_TARGET_CPU_IS_X86_FAMILY)

#if defined(BOTAN_BUILD_COMPILER_IS_MSVC)

  #include <intrin.h>
  #define CALL_CPUID(type, out) do { __cpuid((int*)out, type); } while(0)

#elif defined(BOTAN_BUILD_COMPILER_IS_INTEL)

  #include <ia32intrin.h>
  #define CALL_CPUID(type, out) do { __cpuid(out, type); } while(0);

#elif (BOTAN_GCC_VERSION >= 430)

  // Only available starting in GCC 4.3
  #include <cpuid.h>

namespace {

  /*
  * Prevent inlining to work around GCC bug 44174
  */
  void __attribute__((__noinline__)) call_gcc_cpuid(Botan::u32bit type,
                                                    Botan::u32bit out[4])
     {
     __get_cpuid(type, out, out+1, out+2, out+3);
     }

  #define CALL_CPUID call_gcc_cpuid

}

#else
  #warning "No method of calling CPUID for this compiler"
#endif

#endif

#ifndef CALL_CPUID
  // In all other cases, just zeroize the supposed cpuid output
  #define CALL_CPUID(type, out) \
    do { out[0] = out[1] = out[2] = out[3] = 0; } while(0);
#endif

namespace Botan {

u64bit CPUID::x86_processor_flags = 0;
size_t CPUID::cache_line = 32;
bool CPUID::altivec_capable = false;

namespace {

u32bit get_x86_cache_line_size()
   {
   const u32bit INTEL_CPUID[3] = { 0x756E6547, 0x6C65746E, 0x49656E69 };
   const u32bit AMD_CPUID[3] = { 0x68747541, 0x444D4163, 0x69746E65 };

   u32bit cpuid[4] = { 0 };
   CALL_CPUID(0, cpuid);

   if(same_mem(cpuid + 1, INTEL_CPUID, 3))
      {
      CALL_CPUID(1, cpuid);
      return 8 * get_byte(2, cpuid[1]);
      }
   else if(same_mem(cpuid + 1, AMD_CPUID, 3))
      {
      CALL_CPUID(0x80000005, cpuid);
      return get_byte(3, cpuid[2]);
      }
   else
      return 32; // default cache line guess
   }

#if defined(BOTAN_TARGET_CPU_IS_PPC_FAMILY)

bool altivec_check_sysctl()
   {
#if defined(BOTAN_TARGET_OS_IS_DARWIN)

   // From Apple's docs
   int sels[2] = { CTL_HW, HW_VECTORUNIT };
   int vector_type = 0;
   size_t length = sizeof(vector_type);
   int error = sysctl(sels, 2, &vector_type, &length, NULL, 0);

   if(error == 0 && vector_type > 0)
      return true;
#endif

   return false;
   }

bool altivec_check_pvr_emul()
   {
   bool altivec_capable = false;

#if defined(BOTAN_TARGET_OS_IS_LINUX) || defined(BOTAN_TARGET_OS_IS_NETBSD)

   /*
   On PowerPC, MSR 287 is PVR, the Processor Version Number
   Normally it is only accessible to ring 0, but Linux and NetBSD
   (others, too, maybe?) will trap and emulate it for us.

   PVR identifiers for various AltiVec enabled CPUs. Taken from
   PearPC and Linux sources, mostly.
   */

   const u16bit PVR_G4_7400  = 0x000C;
   const u16bit PVR_G5_970   = 0x0039;
   const u16bit PVR_G5_970FX = 0x003C;
   const u16bit PVR_G5_970MP = 0x0044;
   const u16bit PVR_G5_970GX = 0x0045;
   const u16bit PVR_POWER6   = 0x003E;
   const u16bit PVR_POWER7   = 0x003F;
   const u16bit PVR_CELL_PPU = 0x0070;

   // Motorola produced G4s with PVR 0x800[0123C] (at least)
   const u16bit PVR_G4_74xx_24  = 0x800;

   u32bit pvr = 0;

   asm volatile("mfspr %0, 287" : "=r" (pvr));

   // Top 16 bit suffice to identify model
   pvr >>= 16;

   altivec_capable |= (pvr == PVR_G4_7400);
   altivec_capable |= ((pvr >> 4) == PVR_G4_74xx_24);
   altivec_capable |= (pvr == PVR_G5_970);
   altivec_capable |= (pvr == PVR_G5_970FX);
   altivec_capable |= (pvr == PVR_G5_970MP);
   altivec_capable |= (pvr == PVR_G5_970GX);
   altivec_capable |= (pvr == PVR_POWER6);
   altivec_capable |= (pvr == PVR_POWER7);
   altivec_capable |= (pvr == PVR_CELL_PPU);
#endif

   return altivec_capable;
   }

#endif

}

void CPUID::initialize()
   {
   u32bit cpuid[4] = { 0 };
   CALL_CPUID(1, cpuid);

   x86_processor_flags = (static_cast<u64bit>(cpuid[2]) << 32) | cpuid[3];

#if defined(BOTAN_TARGET_ARCH_IS_X86_64)
   /*
   * If we don't have access to CPUID, we can still safely assume that
   * any x86-64 processor has SSE2.
   */
   if(x86_processor_flags == 0)
     x86_processor_flags |= (1 << CPUID_SSE2_BIT);
#endif

   cache_line = get_x86_cache_line_size();

   altivec_capable = false;

#if defined(BOTAN_TARGET_CPU_IS_PPC_FAMILY)
      if(altivec_check_sysctl() || altivec_check_pvr_emul())
         altivec_capable = true;
#endif
   }

}
<commit_msg>Call cpuid via inline asm on x86-64, so we can use it with Clang (no cpuid intrinsic) and older GCC (no cpuid.h before 4.3)<commit_after>/*
* Runtime CPU detection
* (C) 2009-2010 Jack Lloyd
*
* Distributed under the terms of the Botan license
*/

#include <botan/cpuid.h>
#include <botan/types.h>
#include <botan/get_byte.h>
#include <botan/mem_ops.h>

#if defined(BOTAN_TARGET_OS_IS_DARWIN)
  #include <sys/sysctl.h>
#endif

#if defined(BOTAN_TARGET_CPU_IS_X86_FAMILY)

#if defined(BOTAN_BUILD_COMPILER_IS_MSVC)

  #include <intrin.h>
  #define CALL_CPUID(type, out) do { __cpuid((int*)out, type); } while(0)

#elif defined(BOTAN_BUILD_COMPILER_IS_INTEL)

  #include <ia32intrin.h>
  #define CALL_CPUID(type, out) do { __cpuid(out, type); } while(0)

#elif defined(BOTAN_BUILD_COMPILER_IS_GCC) && (BOTAN_GCC_VERSION >= 430)

  // Only available starting in GCC 4.3
  #include <cpuid.h>

namespace {

  /*
  * Prevent inlining to work around GCC bug 44174
  */
  void __attribute__((__noinline__)) call_gcc_cpuid(Botan::u32bit type,
                                                    Botan::u32bit out[4])
     {
     __get_cpuid(type, out, out+1, out+2, out+3);
     }

  #define CALL_CPUID call_gcc_cpuid

}

#elif defined(BOTAN_TARGET_ARCH_IS_X86_64) && \
   (defined(BOTAN_BUILD_COMPILER_IS_CLANG) || defined(BOTAN_BUILD_COMPILER_IS_GCC))

  /*
  * We can't safely use this on x86-32 as some 32-bit ABIs use ebx as
  * a PIC register, and in theory there are some x86-32s still out
  * there that don't support cpuid at all; it requires strange
  * contortions to detect them.
  */

  #define CALL_CPUID(type, out) \
    asm("cpuid\n\t" : "=a" (out[0]), "=b" (out[1]), "=c" (out[2]), "=d" (out[3]) \
        : "0" (type))

#else
  #warning "No method of calling CPUID for this compiler"
#endif

#endif

#ifndef CALL_CPUID
  // In all other cases, just zeroize the supposed cpuid output
  #define CALL_CPUID(type, out) \
    do { out[0] = out[1] = out[2] = out[3] = 0; } while(0);
#endif

namespace Botan {

u64bit CPUID::x86_processor_flags = 0;
size_t CPUID::cache_line = 32;
bool CPUID::altivec_capable = false;

namespace {

u32bit get_x86_cache_line_size()
   {
   const u32bit INTEL_CPUID[3] = { 0x756E6547, 0x6C65746E, 0x49656E69 };
   const u32bit AMD_CPUID[3] = { 0x68747541, 0x444D4163, 0x69746E65 };

   u32bit cpuid[4] = { 0 };
   CALL_CPUID(0, cpuid);

   if(same_mem(cpuid + 1, INTEL_CPUID, 3))
      {
      CALL_CPUID(1, cpuid);
      return 8 * get_byte(2, cpuid[1]);
      }
   else if(same_mem(cpuid + 1, AMD_CPUID, 3))
      {
      CALL_CPUID(0x80000005, cpuid);
      return get_byte(3, cpuid[2]);
      }
   else
      return 32; // default cache line guess
   }

#if defined(BOTAN_TARGET_CPU_IS_PPC_FAMILY)

bool altivec_check_sysctl()
   {
#if defined(BOTAN_TARGET_OS_IS_DARWIN)

   // From Apple's docs
   int sels[2] = { CTL_HW, HW_VECTORUNIT };
   int vector_type = 0;
   size_t length = sizeof(vector_type);
   int error = sysctl(sels, 2, &vector_type, &length, NULL, 0);

   if(error == 0 && vector_type > 0)
      return true;
#endif

   return false;
   }

bool altivec_check_pvr_emul()
   {
   bool altivec_capable = false;

#if defined(BOTAN_TARGET_OS_IS_LINUX) || defined(BOTAN_TARGET_OS_IS_NETBSD)

   /*
   On PowerPC, MSR 287 is PVR, the Processor Version Number
   Normally it is only accessible to ring 0, but Linux and NetBSD
   (others, too, maybe?) will trap and emulate it for us.

   PVR identifiers for various AltiVec enabled CPUs. Taken from
   PearPC and Linux sources, mostly.
   */

   const u16bit PVR_G4_7400  = 0x000C;
   const u16bit PVR_G5_970   = 0x0039;
   const u16bit PVR_G5_970FX = 0x003C;
   const u16bit PVR_G5_970MP = 0x0044;
   const u16bit PVR_G5_970GX = 0x0045;
   const u16bit PVR_POWER6   = 0x003E;
   const u16bit PVR_POWER7   = 0x003F;
   const u16bit PVR_CELL_PPU = 0x0070;

   // Motorola produced G4s with PVR 0x800[0123C] (at least)
   const u16bit PVR_G4_74xx_24  = 0x800;

   u32bit pvr = 0;

   asm volatile("mfspr %0, 287" : "=r" (pvr));

   // Top 16 bit suffice to identify model
   pvr >>= 16;

   altivec_capable |= (pvr == PVR_G4_7400);
   altivec_capable |= ((pvr >> 4) == PVR_G4_74xx_24);
   altivec_capable |= (pvr == PVR_G5_970);
   altivec_capable |= (pvr == PVR_G5_970FX);
   altivec_capable |= (pvr == PVR_G5_970MP);
   altivec_capable |= (pvr == PVR_G5_970GX);
   altivec_capable |= (pvr == PVR_POWER6);
   altivec_capable |= (pvr == PVR_POWER7);
   altivec_capable |= (pvr == PVR_CELL_PPU);
#endif

   return altivec_capable;
   }

#endif

}

void CPUID::initialize()
   {
   u32bit cpuid[4] = { 0 };
   CALL_CPUID(1, cpuid);

   x86_processor_flags = (static_cast<u64bit>(cpuid[2]) << 32) | cpuid[3];

#if defined(BOTAN_TARGET_ARCH_IS_X86_64)
   /*
   * If we don't have access to CPUID, we can still safely assume that
   * any x86-64 processor has SSE2.
   */
   if(x86_processor_flags == 0)
     x86_processor_flags |= (1 << CPUID_SSE2_BIT);
#endif

   cache_line = get_x86_cache_line_size();

   altivec_capable = false;

#if defined(BOTAN_TARGET_CPU_IS_PPC_FAMILY)
      if(altivec_check_sysctl() || altivec_check_pvr_emul())
         altivec_capable = true;
#endif
   }

}
<|endoftext|>


<commit_before>

#include "../src/clientconsole.h"
#include "../../include/catch.hpp"
#include <QFile>

/*
template<class R, class... Args >
class funcRef<R(Args...)> {

};
*/

template <class C>
class RefData {
	bool topLevel;
	C * data;
public:
	RefData() : data(new C), topLevel(true) {};
	RefData(const C & d) : data(new C(d)) {};
	RefData(const RefData & o) : data(o.data), topLevel(false) {};
	~RefData() {
		if (topLevel) delete data;
	};

	RefData & operator= (const RefData &) = delete;
	RefData & operator= (const C & d) {
		*data = d;
		return *this;
	};

	C & getData() { return *data; };
	const C & getData() const { return *data; };

	operator C &() { return *data; };
	operator const C &() const { return *data; };
};

class TestParseIntercept {
	bool checkType;
	Messages::MsgType type;

	RefData<Messages::ReceivedMessage> data;
public:
	TestParseIntercept() : checkType(false) {};
	TestParseIntercept(Messages::MsgType t) : type(t), checkType(true){ };
	TestParseIntercept(const TestParseIntercept & o) : checkType(o.checkType), type(o.type), data(o.data) {};
	~TestParseIntercept() {};

	void operator()(Session & session, Messages::MsgType t, const Messages::ReceivedMessage & payload) {
		if (checkType && type != t) throw MessageException("Wrong type returned!");
		data = payload;
	};

	operator Messages::ReceivedMessage &() {
		return data;
	};

	Messages::ReceivedMessage & getData() {
		return data;
	};
};

class TestSession {
	Session *s1;
	Session *s2;
public:

	TestSession() {
		mbedtls_entropy_context mtls_entropy;
		mbedtls_entropy_init(&mtls_entropy);
		mbedtls_entropy_gather(&mtls_entropy);

		s1 = new Session("ke@##$VFSDBket", "druhykeket#@1431", &mtls_entropy);
		s2 = new Session("druhykeket#@1431", "ke@##$VFSDBket", &mtls_entropy);

		exchangeDH();
	};

	void exchangeDH() {
		//get each other's Diffie Hellman
		s1->getKey().setDH(s2->getKey().getDH());
		s2->getKey().setDH(s1->getKey().getDH());

		//generate private key
		s1->getKey().generateKey();
		s2->getKey().generateKey();
	};

	~TestSession() {
		delete s1;
		delete s2;
	};

	Session & getS1() { return *s1; };
	Session & getS2() { return *s2; };
};

class TestSessionHandler {
	Session & s;
public:
	TestSessionHandler(Session & s) : s(s) {};
	Session & operator()(const QString & name) {
		if (name.compare(s.getPartnerName())) throw MessageException("Unknown sender!");
		return s;
	};
};

class TestDataSender {

public:
	TestDataSender() {};
	void operator()(const QByteArray & data) {
		qDebug() << data.length();
	};
};

class TestDataSender2 {
	std::function<Session &(const QString &)> sessionHandler;
	std::function<void(Session &, Messages::MsgType, const Messages::ReceivedMessage &)> callback;
public:
	TestDataSender2(std::function<void(Session &, Messages::MsgType, const Messages::ReceivedMessage &)> cb, std::function<Session &(const QString &)> s) : callback(cb), sessionHandler(s) {};
	TestDataSender2(const TestDataSender2 & o) : callback(o.callback), sessionHandler(o.sessionHandler) {};

	void operator()(const QByteArray & data) {
		Messages::parseMessage(sessionHandler, data, callback);
	};
};

class TestDataSender3 {
	std::function<void(qint64, qint64, const QByteArray &)> callback;
public:
	TestDataSender3(std::function<void(qint64, qint64, const QByteArray &)> cb) : callback(cb) {};
	TestDataSender3(const TestDataSender3 & o) : callback(o.callback) {};

	void operator()(Session & s, Messages::MsgType t, const Messages::ReceivedMessage & data) {
		QList<QByteArray> list = data.messageText.split(Messages::armaSeparator);

		qint64 id = list[0].toLongLong();
		qint64 start = list[1].toLongLong();
		qint64 len = list[2].toLongLong();

		callback(start, len, data.messageText.right(data.messageText.length() - (list[0].length() + list[1].length() + list[2].length() + 3)));
	};
};

TEST_CASE("Key exchange", "[Krypto]") {
	mbedtls_entropy_context mtls_entropy;
	mbedtls_entropy_init(&mtls_entropy);
	mbedtls_entropy_gather(&mtls_entropy);

	//Create "virtual" sessions for both clients
	Session s("ke@##$VFSDBket", "druhykeket#@1431", &mtls_entropy);
	Session s2("druhykeket#@1431", "ke@##$VFSDBket", &mtls_entropy);

	QSet<QString> usedKeys;

	for (int i = 0; i < 20; ++i) {
		//get each other's Diffie Hellman
		s.getKey().setDH(s2.getKey().getDH());
		s2.getKey().setDH(s.getKey().conditionalGetDH());

		//generate private key
		s.getKey().generateKey();
		s2.getKey().generateKey();

		//the key must be the same
		REQUIRE_FALSE(usedKeys.contains(s.getKey().getSharedKey()));
		usedKeys.insert(s.getKey().getSharedKey());
		REQUIRE(usedKeys.contains(s.getKey().getSharedKey()));
		bool same = s.getKey().getSharedKey() == s2.getKey().getSharedKey();
		REQUIRE(same);
		REQUIRE(s.getKey().getSharedKey().length() == 256);
	}

	REQUIRE(usedKeys.size() == 20);
}

TEST_CASE("Sending simple message", "[message]") {
	TestSession s;

	// Send simple message
	Messages m(nullptr, 0);
	QString sprava("TESTOVACIA SPRAVA # wlivywouihfwicdcoywgv aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaas");
	QByteArray encrypted = m.createRegularMessage(s.getS1(), sprava);

	// Recieve simple message
	TestParseIntercept received;
	bool valid = m.parseMessage(TestSessionHandler(s.getS2()), encrypted, received);
	REQUIRE(valid);

	QString receivedString = QString::fromUtf8(received.getData().messageText);
	REQUIRE(receivedString == sprava);
}

TEST_CASE("Sending complex messages", "[message]") {
	TestSession s;

	Messages m(nullptr, 0);
	QString sprava("TESTOVACIA SPRAVA");
	QByteArray encrypted = m.createRegularMessage(s.getS1(), sprava);
	//	qDebug() << "PROTECTED:   " << encrypted;
	TestParseIntercept received;
	bool valid = m.parseMessage(TestSessionHandler(s.getS2()), encrypted, received);
	REQUIRE(valid);
	//	qDebug() << "Raw unprotected = " << received.messageText;
	QString receivedString = QString::fromUtf8(received.getData().messageText);

	REQUIRE(receivedString == sprava);

	sprava = "In sprva s diakritikou. # a pecilnym znakom ooooha";
	encrypted = m.createRegularMessage(s.getS2(), sprava);
	valid = m.parseMessage(TestSessionHandler(s.getS1()), encrypted, received);
	receivedString = QString::fromUtf8(received.getData().messageText);
	REQUIRE(receivedString == sprava);

	//without key change:

	sprava = "Tto sprva sa pouije niekokokrt z jednej session";
	for (int i = 0; i<10; ++i) {
		encrypted = m.createRegularMessage(s.getS1(), sprava);
		valid = m.parseMessage(TestSessionHandler(s.getS2()), encrypted, received);
		receivedString = QString::fromUtf8(received.getData().messageText);
		REQUIRE(receivedString == sprava);
	}
	REQUIRE_THROWS_AS(encrypted = m.createRegularMessage(s.getS1(), sprava), KryptoOveruseException);
	REQUIRE_THROWS_AS(encrypted = m.createRegularMessage(s.getS1(), sprava), KryptoOveruseException);

	REQUIRE_FALSE(m.parseMessage(TestSessionHandler(s.getS2()), encrypted, received));
	REQUIRE_FALSE(m.parseMessage(TestSessionHandler(s.getS2()), encrypted, received));
}

TEST_CASE("Sending out of order message", "[message]") {
	TestSession s;

	// Send simple message
	Messages m(nullptr, 0);
	QString sprava("TESTOVACIA SPRAVA # wlivywouihfwicdcoywgv aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaas");
	QByteArray encrypted = m.createRegularMessage(s.getS1(), sprava);

	s.exchangeDH();

	TestParseIntercept received;
	bool valid;
	for (int i = 0; i < 10; ++i) {
		// Recieve simple message
		REQUIRE_NOTHROW(valid = m.parseMessage(TestSessionHandler(s.getS2()), encrypted, received));
		REQUIRE(valid);

		QString receivedString = QString::fromUtf8(received.getData().messageText);
		REQUIRE(receivedString == sprava);
	}
	REQUIRE_FALSE(m.parseMessage(TestSessionHandler(s.getS2()), encrypted, received));
}

TEST_CASE("Performance tests", "[message]") {
	TestSession s;
	Messages m(nullptr, 0);

	QString originalMessage("ORIGINAL MESSAGE WITH SIZE = 32B");
	QString sprava;
	QByteArray encrypted;
	bool valid;
	TestParseIntercept received;
	QString receivedString;

	clock_t encryptStart, encryptEnd, decryptStart, decryptEnd;
	double timeSpentEncrypt, timeSpentDecrypt;

	for (int i = 1; i <= 0; ++i) {
		sprava = originalMessage.repeated(2);
		encryptStart = clock();
		encrypted = m.createRegularMessage(s.getS1(), sprava);
		encryptEnd = clock();
		decryptStart = clock();
		valid = m.parseMessage(TestSessionHandler(s.getS2()), encrypted, received);
		decryptEnd = clock();
		receivedString = QString::fromUtf8(received.getData().messageText);

		timeSpentEncrypt = (encryptEnd - encryptStart) / ((double)CLOCKS_PER_SEC / 1000);
		timeSpentDecrypt = (decryptEnd - decryptStart) / ((double)CLOCKS_PER_SEC / 1000);

		qDebug() << "Message Size: " << sprava.size() << "B, encrypt time: " << qSetRealNumberPrecision(10) << timeSpentEncrypt
			<< "ms, decrypt time: " << timeSpentDecrypt << "ms";

		REQUIRE(receivedString == sprava);

		originalMessage = sprava;

		s.exchangeDH();
	}
}

TEST_CASE("Sending file", "[File transfer]") {
	static const char * path = "test.t";
	QFile file(path);
	file.open(QIODevice::WriteOnly);

	QString testData = "ORIGINAL MESSAGE WITH SIZE = 32B\nORIGINAL MESSAGE WITH SIZE = 32B";
	file.write(testData.toUtf8());
	file.close();

	TestSession s;

	Messages::FileSendingContext test(s.getS1(), path, TestDataSender());
	REQUIRE_NOTHROW(test.startSending());

	QThread::sleep(3);
	file.remove();
}

TEST_CASE("Sending long files", "[File transfer]") {
	static const char * path = "test.t";
	QFile file(path);

	TestSession s;

	QString testData = "My little test\nTesting\n";
	for (int i = 1; i < 32; i *= 2) {
		file.open(QIODevice::WriteOnly);
		do {
			testData += testData;
		} while (testData.length() <= i * Messages::maxChunkSize);
		file.write(testData.toUtf8());
		file.close();

		s.exchangeDH();

		Messages::FileSendingContext test(s.getS1(), path, TestDataSender());
		REQUIRE_NOTHROW(test.startSending());
	}
	QThread::sleep(5);
	file.remove();
}

void helperFunction(Messages::MsgType t, const Messages::ReceivedMessage & data) {
	qDebug() << "Message(" << t << "): " << data.messageText;
}

TEST_CASE("Receiving file", "[File transfer]") {
	static const char * path = "test.t";
	static const char * path2 = "test_r.t";

	QFile file(path);
	file.open(QIODevice::WriteOnly);

	const QString testData = "ORIGINAL MESSAGE WITH SIZE = 32B\nORIGINAL MESSAGE WITH SIZE = 32B";
	file.write(testData.toUtf8());
	file.close();

	TestSession s;
	QByteArray msg;

	Messages::FileReceivingContext testr(s.getS2(), path2);
	Messages::FileSendingContext test(s.getS1(), path, TestDataSender2(TestDataSender3(testr), TestSessionHandler(s.getS2())));
	REQUIRE_NOTHROW(test.startSending());

	QThread::sleep(3);
	file.remove();

	QFile file2(path2);
	file2.open(QIODevice::ReadOnly);
	QString t_data = QString::fromUtf8(file2.readAll());

	REQUIRE(t_data == testData);
	file2.close();
	file2.remove();
}

<commit_msg>Improved unit tests<commit_after>

#include <stdexcept>
#include "../src/clientconsole.h"
#include "../../include/catch.hpp"
#include <QFile>

/*
template<class R, class... Args >
class funcRef<R(Args...)> {

};
*/

template <class C>
class RefData {
	bool topLevel;
	C * data;
public:
	RefData() : data(new C), topLevel(true) {};
	RefData(const C & d) : data(new C(d)) {};
	RefData(const RefData & o) : data(o.data), topLevel(false) {};
	~RefData() {
		if (topLevel) delete data;
	};

	RefData & operator= (const RefData &) = delete;
	RefData & operator= (const C & d) {
		*data = d;
		return *this;
	};

	C & getData() { return *data; };
	const C & getData() const { return *data; };

	operator C &() { return *data; };
	operator const C &() const { return *data; };
};

class TestParseIntercept {
	bool checkType;
	Messages::MsgType type;

	RefData<Messages::ReceivedMessage> data;
public:
	TestParseIntercept() : checkType(false) {};
	TestParseIntercept(Messages::MsgType t) : type(t), checkType(true){ };
	TestParseIntercept(const TestParseIntercept & o) : checkType(o.checkType), type(o.type), data(o.data) {};
	~TestParseIntercept() {};

	void operator()(Session & session, Messages::MsgType t, const Messages::ReceivedMessage & payload) {
		if (checkType && type != t) throw MessageException("Wrong type returned!");
		data = payload;
	};

	operator Messages::ReceivedMessage &() {
		return data;
	};

	Messages::ReceivedMessage & getData() {
		return data;
	};
};

class TestSession {
	Session *s1;
	Session *s2;
public:

	TestSession() {
		mbedtls_entropy_context mtls_entropy;
		mbedtls_entropy_init(&mtls_entropy);
		mbedtls_entropy_gather(&mtls_entropy);

		s1 = new Session("ke@##$VFSDBket", "druhykeket#@1431", &mtls_entropy);
		s2 = new Session("druhykeket#@1431", "ke@##$VFSDBket", &mtls_entropy);

		exchangeDH();
	};

	void exchangeDH() {
		//get each other's Diffie Hellman
		s1->getKey().setDH(s2->getKey().getDH());
		s2->getKey().setDH(s1->getKey().getDH());

		//generate private key
		s1->getKey().generateKey();
		s2->getKey().generateKey();
	};

	~TestSession() {
		delete s1;
		delete s2;
	};

	Session & getS1() { return *s1; };
	Session & getS2() { return *s2; };
};

class TestSessionHandler {
	Session & s;
public:
	TestSessionHandler(Session & s) : s(s) {};
	Session & operator()(const QString & name) {
		if (name.compare(s.getPartnerName())) throw MessageException("Unknown sender!");
		return s;
	};
};

class TestDataSender {

public:
	TestDataSender() {};
	void operator()(const QByteArray & data) {
		qDebug() << data.length();
	};
};

class TestDataSender2 {
	std::function<Session &(const QString &)> sessionHandler;
	std::function<void(Session &, Messages::MsgType, const Messages::ReceivedMessage &)> callback;
public:
	TestDataSender2(std::function<void(Session &, Messages::MsgType, const Messages::ReceivedMessage &)> cb, std::function<Session &(const QString &)> s) : callback(cb), sessionHandler(s) {};
	TestDataSender2(const TestDataSender2 & o) : callback(o.callback), sessionHandler(o.sessionHandler) {};

	void operator()(const QByteArray & data) {
		Messages::parseMessage(sessionHandler, data, callback);
	};
};

class TestDataSender3 {
	Messages::MsgType expectedType;
	std::function<void(qint64, qint64, const QByteArray &)> callback;
public:
	TestDataSender3(std::function<void(qint64, qint64, const QByteArray &)> cb, Messages::MsgType expectedType = Messages::MsgType::None) : callback(cb), expectedType(expectedType) {};
	TestDataSender3(const TestDataSender3 & o) : callback(o.callback), expectedType(o.expectedType) {};

	void operator()(Session & s, Messages::MsgType t, const Messages::ReceivedMessage & data) {
		if (expectedType != Messages::MsgType::None && expectedType != t) throw std::runtime_error("Test: Invalid message type!");
		QList<QByteArray> list = data.messageText.split(Messages::armaSeparator);

		qint64 id = list[0].toLongLong();
		qint64 start = list[1].toLongLong();
		qint64 len = list[2].toLongLong();

		callback(start, len, data.messageText.right(data.messageText.length() - (list[0].length() + list[1].length() + list[2].length() + 3)));
	};
};

TEST_CASE("Key exchange", "[Krypto]") {
	mbedtls_entropy_context mtls_entropy;
	mbedtls_entropy_init(&mtls_entropy);
	mbedtls_entropy_gather(&mtls_entropy);

	//Create "virtual" sessions for both clients
	Session s("ke@##$VFSDBket", "druhykeket#@1431", &mtls_entropy);
	Session s2("druhykeket#@1431", "ke@##$VFSDBket", &mtls_entropy);

	QSet<QString> usedKeys;

	for (int i = 0; i < 20; ++i) {
		//get each other's Diffie Hellman
		s.getKey().setDH(s2.getKey().getDH());
		s2.getKey().setDH(s.getKey().conditionalGetDH());

		//generate private key
		s.getKey().generateKey();
		s2.getKey().generateKey();

		//the key must be the same
		REQUIRE_FALSE(usedKeys.contains(s.getKey().getSharedKey()));
		usedKeys.insert(s.getKey().getSharedKey());
		REQUIRE(usedKeys.contains(s.getKey().getSharedKey()));
		bool same = s.getKey().getSharedKey() == s2.getKey().getSharedKey();
		REQUIRE(same);
		REQUIRE(s.getKey().getSharedKey().length() == 256);
	}

	REQUIRE(usedKeys.size() == 20);
}

TEST_CASE("Sending simple message", "[message]") {
	TestSession s;

	// Send simple message
	Messages m(nullptr, 0);
	QString sprava("TESTOVACIA SPRAVA # wlivywouihfwicdcoywgv aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaas");
	QByteArray encrypted = m.createRegularMessage(s.getS1(), sprava);

	// Recieve simple message
	TestParseIntercept received;
	bool valid = m.parseMessage(TestSessionHandler(s.getS2()), encrypted, received);
	REQUIRE(valid);

	QString receivedString = QString::fromUtf8(received.getData().messageText);
	REQUIRE(receivedString == sprava);
}

TEST_CASE("Sending complex messages", "[message]") {
	TestSession s;

	Messages m(nullptr, 0);
	QString sprava("TESTOVACIA SPRAVA");
	QByteArray encrypted = m.createRegularMessage(s.getS1(), sprava);
	//	qDebug() << "PROTECTED:   " << encrypted;
	TestParseIntercept received;
	bool valid = m.parseMessage(TestSessionHandler(s.getS2()), encrypted, received);
	REQUIRE(valid);
	//	qDebug() << "Raw unprotected = " << received.messageText;
	QString receivedString = QString::fromUtf8(received.getData().messageText);

	REQUIRE(receivedString == sprava);

	sprava = "In sprva s diakritikou. # a pecilnym znakom ooooha";
	encrypted = m.createRegularMessage(s.getS2(), sprava);
	valid = m.parseMessage(TestSessionHandler(s.getS1()), encrypted, received);
	receivedString = QString::fromUtf8(received.getData().messageText);
	REQUIRE(receivedString == sprava);

	//without key change:

	sprava = "Tto sprva sa pouije niekokokrt z jednej session";
	for (int i = 0; i<10; ++i) {
		encrypted = m.createRegularMessage(s.getS1(), sprava);
		valid = m.parseMessage(TestSessionHandler(s.getS2()), encrypted, received);
		receivedString = QString::fromUtf8(received.getData().messageText);
		REQUIRE(receivedString == sprava);
	}
	REQUIRE_THROWS_AS(encrypted = m.createRegularMessage(s.getS1(), sprava), KryptoOveruseException);
	REQUIRE_THROWS_AS(encrypted = m.createRegularMessage(s.getS1(), sprava), KryptoOveruseException);

	REQUIRE_FALSE(m.parseMessage(TestSessionHandler(s.getS2()), encrypted, received));
	REQUIRE_FALSE(m.parseMessage(TestSessionHandler(s.getS2()), encrypted, received));
}

TEST_CASE("Sending out of order message", "[message]") {
	TestSession s;

	// Send simple message
	Messages m(nullptr, 0);
	QString sprava("TESTOVACIA SPRAVA # wlivywouihfwicdcoywgv aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaas");
	QByteArray encrypted = m.createRegularMessage(s.getS1(), sprava);

	s.exchangeDH();

	TestParseIntercept received;
	bool valid;
	for (int i = 0; i < 10; ++i) {
		// Recieve simple message
		REQUIRE_NOTHROW(valid = m.parseMessage(TestSessionHandler(s.getS2()), encrypted, received));
		REQUIRE(valid);

		QString receivedString = QString::fromUtf8(received.getData().messageText);
		REQUIRE(receivedString == sprava);
	}
	REQUIRE_FALSE(m.parseMessage(TestSessionHandler(s.getS2()), encrypted, received));
}

TEST_CASE("Performance tests", "[message]") {
	TestSession s;
	Messages m(nullptr, 0);

	QString originalMessage("ORIGINAL MESSAGE WITH SIZE = 32B");
	QString sprava;
	QByteArray encrypted;
	bool valid;
	TestParseIntercept received;
	QString receivedString;

	clock_t encryptStart, encryptEnd, decryptStart, decryptEnd;
	double timeSpentEncrypt, timeSpentDecrypt;

	for (int i = 1; i <= 0; ++i) {
		sprava = originalMessage.repeated(2);
		encryptStart = clock();
		encrypted = m.createRegularMessage(s.getS1(), sprava);
		encryptEnd = clock();
		decryptStart = clock();
		valid = m.parseMessage(TestSessionHandler(s.getS2()), encrypted, received);
		decryptEnd = clock();
		receivedString = QString::fromUtf8(received.getData().messageText);

		timeSpentEncrypt = (encryptEnd - encryptStart) / ((double)CLOCKS_PER_SEC / 1000);
		timeSpentDecrypt = (decryptEnd - decryptStart) / ((double)CLOCKS_PER_SEC / 1000);

		qDebug() << "Message Size: " << sprava.size() << "B, encrypt time: " << qSetRealNumberPrecision(10) << timeSpentEncrypt
			<< "ms, decrypt time: " << timeSpentDecrypt << "ms";

		REQUIRE(receivedString == sprava);

		originalMessage = sprava;

		s.exchangeDH();
	}
}

TEST_CASE("Sending file", "[File transfer]") {
	static const char * path = "test.t";
	QFile file(path);
	file.open(QIODevice::WriteOnly);

	QString testData = "ORIGINAL MESSAGE WITH SIZE = 32B\nORIGINAL MESSAGE WITH SIZE = 32B";
	file.write(testData.toUtf8());
	file.close();

	TestSession s;

	Messages::FileSendingContext test(s.getS1(), path, TestDataSender());
	REQUIRE_NOTHROW(test.startSending());

	QThread::sleep(3);
	file.remove();
}

TEST_CASE("Sending long files", "[File transfer]") {
	static const char * path = "test.t";
	QFile file(path);

	TestSession s;

	QString testData = "My little test\nTesting\n";
	for (int i = 1; i < 32; i *= 2) {
		file.open(QIODevice::WriteOnly);
		do {
			testData += testData;
		} while (testData.length() <= i * Messages::maxChunkSize);
		file.write(testData.toUtf8());
		file.close();

		s.exchangeDH();

		Messages::FileSendingContext test(s.getS1(), path, TestDataSender());
		REQUIRE_NOTHROW(test.startSending());
	}
	QThread::sleep(5);
	file.remove();
}

void helperFunction(Messages::MsgType t, const Messages::ReceivedMessage & data) {
	qDebug() << "Message(" << t << "): " << data.messageText;
}

TEST_CASE("Receiving file", "[File transfer]") {
	static const char * path = "test.t";
	static const char * path2 = "test_r.t";

	QFile file(path);
	file.open(QIODevice::WriteOnly);

	const QString testData = "ORIGINAL MESSAGE WITH SIZE = 32B\nORIGINAL MESSAGE WITH SIZE = 32B";
	file.write(testData.toUtf8());
	file.close();

	TestSession s;
	QByteArray msg;

	Messages::FileReceivingContext testr(s.getS2(), path2);
	Messages::FileSendingContext test(s.getS1(), path, TestDataSender2(TestDataSender3(testr), TestSessionHandler(s.getS2())));
	REQUIRE_NOTHROW(test.startSending());

	QThread::sleep(3);
	file.remove();

	QFile file2(path2);
	file2.open(QIODevice::ReadOnly);
	QString t_data = QString::fromUtf8(file2.readAll());

	REQUIRE(t_data == testData);
	file2.close();
	file2.remove();
}

<|endoftext|>


<commit_before>#include <cstdio>
#include <cstdlib>
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <stdint.h>
#include <math.h>

#undef DEBUG_PRINT

// For lightweight communication with the FPGA:
#define FPGA_MANAGER_BASE 0xFF706000
#define FPGA_GPO_OFFSET 0x10
#define FPGA_GPI_OFFSET 0x14

// HPS-to-FPGA:
#define H2F_DATA_READY (1 << 0)

// FPGA-to-HPS:
#define F2H_BUSY (1 << 0)

// Shared memory addresses:
#define BASE 0x38000000
#define RAM_SIZE 0x40000000
#define COLOR_BUFFER_1_OFFSET 0
#define BUFFER_SIZE (800*480*4)
#define COLOR_BUFFER_2_OFFSET (COLOR_BUFFER_1_OFFSET + BUFFER_SIZE)
#define Z_BUFFER_OFFSET (COLOR_BUFFER_2_OFFSET + BUFFER_SIZE)
#define PROTOCOL_BUFFER_OFFSET (Z_BUFFER_OFFSET + BUFFER_SIZE)

// Protocol command number:
#define CMD_CLEAR 1
#define CMD_ZCLEAR 2
#define CMD_PATTERN 3
#define CMD_DRAW 4
#define CMD_BITMAP 5
#define CMD_SWAP 6
#define CMD_END 7

// Draw type:
#define DRAW_TRIANGLES 0
#define DRAW_LINES 1
#define DRAW_POINTS 2
#define DRAW_LINE_STRIP 3
#define DRAW_TRIANGLE_STRIP 5
#define DRAW_TRIANGLE_FAN 6

void cmd_clear(volatile uint64_t **p, uint8_t red, uint8_t green, uint8_t blue)
{
    *(*p)++ = CMD_CLEAR
	| ((uint64_t) red << 56)
	| ((uint64_t) green << 48)
	| ((uint64_t) blue << 40);
}

void cmd_pattern(volatile uint64_t **p,
	uint64_t pattern0,
	uint64_t pattern1,
	uint64_t pattern2,
	uint64_t pattern3)
{
    *(*p)++ = CMD_PATTERN;
    *(*p)++ = pattern0;
    *(*p)++ = pattern1;
    *(*p)++ = pattern2;
    *(*p)++ = pattern3;
}

void cmd_draw(volatile uint64_t **p, int type, int count, int pattern_enable)
{
    *(*p)++ = CMD_DRAW
    	| ((uint64_t) type << 8)
	| ((uint64_t) count << 16)
	| ((uint64_t) pattern_enable << 33);
}

void vertex(volatile uint64_t **p, int x, int y, int z,
    uint8_t red, uint8_t green, uint8_t blue)
{
    *(*p)++ =
    	  ((uint64_t) x << 2)
	| ((uint64_t) y << 15)
	| ((uint64_t) red << 56)
	| ((uint64_t) green << 48)
	| ((uint64_t) blue << 40);
}

void cmd_swap(volatile uint64_t **p)
{
    *(*p)++ = CMD_SWAP;
}

void cmd_end(volatile uint64_t **p)
{
    *(*p)++ = CMD_END;
}

int main()
{
    float speed = 0.001;

    int dev_mem = open("/dev/mem", O_RDWR);
    if(dev_mem == -1) {
        perror("open");
        exit(EXIT_FAILURE);
    }

    // Get access to lightweight FPGA communication.
    uint8_t *fpga_manager_base = (uint8_t *) mmap(0, 64,
	PROT_READ | PROT_WRITE, MAP_SHARED, dev_mem, FPGA_MANAGER_BASE);
    if(fpga_manager_base == MAP_FAILED) {
        perror("mmap for fpga manager base");
        exit(EXIT_FAILURE);
    }
    volatile uint32_t *gpo = (uint32_t*)(fpga_manager_base + FPGA_GPO_OFFSET);
    volatile uint32_t *gpi = (uint32_t*)(fpga_manager_base + FPGA_GPI_OFFSET);

    // Get access to the various RAM buffers.
    uint8_t *buffers_base = (uint8_t *) mmap(0, RAM_SIZE - BASE,
	PROT_READ | PROT_WRITE, MAP_SHARED, dev_mem, BASE);
    if(buffers_base == MAP_FAILED) {
        perror("mmap for buffers");
        exit(EXIT_FAILURE);
    }
    volatile uint64_t *protocol_buffer =
	(uint64_t *) (buffers_base + PROTOCOL_BUFFER_OFFSET);

    *gpo = 0;
    int counter = 0;
    while (1) {
	// Start of frame.
	if ((*gpi & F2H_BUSY) != 0) {
	    printf("Warning: FPGA is busy at top of loop.\n");
	}

	// Write protocol buffer.
#ifdef DEBUG_PRINT
	printf("Writing protocol buffer.\n");
#endif
	volatile uint64_t *p = protocol_buffer;
	if (0) {
	    cmd_clear(&p,
		(counter & 0x04) ? 255 : 0,
		(counter & 0x02) ? 255 : 0,
		(counter & 0x01) ? 255 : 0);
	} else {
	    cmd_clear(&p, 0, 0, 0);
	}
	cmd_pattern(&p,
		0x5555aaaa5555aaaaLL,
		0x5555aaaa5555aaaaLL,
		0x5555aaaa5555aaaaLL,
		0x5555aaaa5555aaaaLL);
	int pattern_enable = (counter & 0x40) != 0;
	cmd_draw(&p, DRAW_TRIANGLES, 1, pattern_enable);
	vertex(&p,
	    800/2 + (int) (200*sin(counter*speed)),
	    450/2 + (int) (200*cos(counter*speed)),
	    0, 50, 100, 150);
	vertex(&p,
	    800/2 + (int) (200*sin(counter*speed + M_PI*2/3)),
	    450/2 + (int) (200*cos(counter*speed + M_PI*2/3)),
	    0, 50, 100, 150);
	vertex(&p,
	    800/2 + (int) (200*sin(counter*speed + M_PI*4/3)),
	    450/2 + (int) (200*cos(counter*speed + M_PI*4/3)),
	    0, 50, 100, 150);
	cmd_swap(&p);
	cmd_end(&p);
#ifdef DEBUG_PRINT
	printf("    Wrote %d words:\n", p - protocol_buffer);
	for (volatile uint64_t *t = protocol_buffer; t < p; t++) {
	    printf("        0x%016llX\n", *t);
	}
#endif

	// Tell FPGA that our data is ready.
#ifdef DEBUG_PRINT
	printf("Telling FPGA that the data is ready.\n");
#endif
	*gpo |= H2F_DATA_READY;

	// Wait until we find out that it has heard us.
#ifdef DEBUG_PRINT
	printf("Waiting for FPGA to get busy.\n");
#endif
	while ((*gpi & F2H_BUSY) == 0) {
	    // Busy loop.
	}

	// Let FPGA know that we know that it's busy.
#ifdef DEBUG_PRINT
	printf("Telling FPGA that we know it's busy.\n");
#endif
	*gpo &= ~H2F_DATA_READY;

	// Wait until it's done rasterizing.
#ifdef DEBUG_PRINT
	printf("Waiting for FPGA to finish rasterizing.\n");
#endif
	while ((*gpi & F2H_BUSY) != 0) {
	    // Busy loop.
	}

	// usleep(1000*100);
	counter++;
    }

    exit(EXIT_SUCCESS);
}

<commit_msg>Protocol test that spins red triangle.<commit_after>#include <cstdio>
#include <cstdlib>
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <stdint.h>
#include <math.h>

#undef DEBUG_PRINT

// For lightweight communication with the FPGA:
#define FPGA_MANAGER_BASE 0xFF706000
#define FPGA_GPO_OFFSET 0x10
#define FPGA_GPI_OFFSET 0x14

// HPS-to-FPGA:
#define H2F_DATA_READY (1 << 0)

// FPGA-to-HPS:
#define F2H_BUSY (1 << 0)

// Shared memory addresses:
#define BASE 0x38000000
#define RAM_SIZE 0x40000000
#define COLOR_BUFFER_1_OFFSET 0
#define BUFFER_SIZE (800*480*4)
#define COLOR_BUFFER_2_OFFSET (COLOR_BUFFER_1_OFFSET + BUFFER_SIZE)
#define Z_BUFFER_OFFSET (COLOR_BUFFER_2_OFFSET + BUFFER_SIZE)
#define PROTOCOL_BUFFER_OFFSET (Z_BUFFER_OFFSET + BUFFER_SIZE)

// Protocol command number:
#define CMD_CLEAR 1
#define CMD_ZCLEAR 2
#define CMD_PATTERN 3
#define CMD_DRAW 4
#define CMD_BITMAP 5
#define CMD_SWAP 6
#define CMD_END 7

// Draw type:
#define DRAW_TRIANGLES 0
#define DRAW_LINES 1
#define DRAW_POINTS 2
#define DRAW_LINE_STRIP 3
#define DRAW_TRIANGLE_STRIP 5
#define DRAW_TRIANGLE_FAN 6

#define TEST_PATTERN 0
#define TEST_SPINNING_TRIANGLE 1
#define TEST_TWO_TRIANGLES 0

void cmd_clear(volatile uint64_t **p, uint8_t red, uint8_t green, uint8_t blue)
{
    *(*p)++ = CMD_CLEAR
	| ((uint64_t) red << 56)
	| ((uint64_t) green << 48)
	| ((uint64_t) blue << 40);
}

void cmd_pattern(volatile uint64_t **p,
	uint64_t pattern0,
	uint64_t pattern1,
	uint64_t pattern2,
	uint64_t pattern3)
{
    *(*p)++ = CMD_PATTERN;
    *(*p)++ = pattern0;
    *(*p)++ = pattern1;
    *(*p)++ = pattern2;
    *(*p)++ = pattern3;
}

void cmd_draw(volatile uint64_t **p, int type, int count, int pattern_enable)
{
    *(*p)++ = CMD_DRAW
    	| ((uint64_t) type << 8)
	| ((uint64_t) count << 16)
	| ((uint64_t) pattern_enable << 33);
}

void vertex(volatile uint64_t **p, int x, int y, int z,
    uint8_t red, uint8_t green, uint8_t blue)
{
    *(*p)++ =
    	  ((uint64_t) x << 2)
	| ((uint64_t) y << 15)
	| ((uint64_t) red << 56)
	| ((uint64_t) green << 48)
	| ((uint64_t) blue << 40);
}

void cmd_swap(volatile uint64_t **p)
{
    *(*p)++ = CMD_SWAP;
}

void cmd_end(volatile uint64_t **p)
{
    *(*p)++ = CMD_END;
}

int main()
{
    float speed = 0.01;

    int dev_mem = open("/dev/mem", O_RDWR);
    if(dev_mem == -1) {
        perror("open");
        exit(EXIT_FAILURE);
    }

    // Get access to lightweight FPGA communication.
    uint8_t *fpga_manager_base = (uint8_t *) mmap(0, 64,
	PROT_READ | PROT_WRITE, MAP_SHARED, dev_mem, FPGA_MANAGER_BASE);
    if(fpga_manager_base == MAP_FAILED) {
        perror("mmap for fpga manager base");
        exit(EXIT_FAILURE);
    }
    volatile uint32_t *gpo = (uint32_t*)(fpga_manager_base + FPGA_GPO_OFFSET);
    volatile uint32_t *gpi = (uint32_t*)(fpga_manager_base + FPGA_GPI_OFFSET);

    // Get access to the various RAM buffers.
    uint8_t *buffers_base = (uint8_t *) mmap(0, RAM_SIZE - BASE,
	PROT_READ | PROT_WRITE, MAP_SHARED, dev_mem, BASE);
    if(buffers_base == MAP_FAILED) {
        perror("mmap for buffers");
        exit(EXIT_FAILURE);
    }
    volatile uint64_t *protocol_buffer =
	(uint64_t *) (buffers_base + PROTOCOL_BUFFER_OFFSET);

    int brightness = 1000;
    *gpo = (brightness << 2) | (1 << 1);
    int counter = 0;
    while (1) {
	// Start of frame.
	if ((*gpi & F2H_BUSY) != 0) {
	    printf("Warning: FPGA is busy at top of loop.\n");
	}

	// Write protocol buffer.
#ifdef DEBUG_PRINT
	printf("Writing protocol buffer.\n");
#endif
	volatile uint64_t *p = protocol_buffer;
	if (0) {
	    cmd_clear(&p,
		(counter & 0x04) ? 255 : 0,
		(counter & 0x02) ? 255 : 0,
		(counter & 0x01) ? 255 : 0);
	} else {
	    cmd_clear(&p, 0, 0, 0);
	}
#if TEST_PATTERN
	cmd_pattern(&p,
		0x5555aaaa5555aaaaLL,
		0x5555aaaa5555aaaaLL,
		0x5555aaaa5555aaaaLL,
		0x5555aaaa5555aaaaLL);
#endif
	int pattern_enable = (counter & 0x40) != 0 && TEST_PATTERN;
#if TEST_SPINNING_TRIANGLE
	cmd_draw(&p, DRAW_TRIANGLES, 1, pattern_enable);
	vertex(&p,
	    800/2 + (int) (200*sin(counter*speed + M_PI*2/3)),
	    450/2 + (int) (200*cos(counter*speed + M_PI*2/3)),
	    0, 255, 0, 0);
	vertex(&p,
	    800/2 + (int) (200*sin(counter*speed)),
	    450/2 + (int) (200*cos(counter*speed)),
	    0, 0, 0, 0);
	vertex(&p,
	    800/2 + (int) (200*sin(counter*speed + M_PI*4/3)),
	    450/2 + (int) (200*cos(counter*speed + M_PI*4/3)),
	    0, 0, 0, 0);
#endif
#if TEST_TWO_TRIANGLES
	cmd_draw(&p, DRAW_TRIANGLES, 2, pattern_enable);

	// vertex(&p, 416, 346, 0, 255, 255, 255);
	// vertex(&p, 392, 346, 0, 255, 255, 255);
	// vertex(&p, 416, 321, 0, 255, 255, 255);

	int dy = ((counter / 50) % 20) - 10;

	// Bottom triangle.
	vertex(&p, 392, 346 + dy, 0, 255, 200, 255);
	vertex(&p, 416, 321 + dy, 0, 255, 200, 255);
	vertex(&p, 392, 321 + dy, 0, 255, 200, 255);

	// Top triangle.
	vertex(&p, 416, 321 + dy, 0, 255, 255, 200);
	vertex(&p, 392, 321 + dy, 0, 255, 255, 200);
	vertex(&p, 416, 296 + dy, 0, 255, 255, 200);

	// vertex(&p, 392, 321, 0, 200, 255, 255);
	// vertex(&p, 416, 296, 0, 200, 255, 255);
	// vertex(&p, 392, 297, 0, 200, 255, 255);
#endif
	cmd_swap(&p);
	cmd_end(&p);
#ifdef DEBUG_PRINT
	printf("    Wrote %d words:\n", p - protocol_buffer);
	for (volatile uint64_t *t = protocol_buffer; t < p; t++) {
	    printf("        0x%016llX\n", *t);
	}
#endif

	// Tell FPGA that our data is ready.
#ifdef DEBUG_PRINT
	printf("Telling FPGA that the data is ready.\n");
#endif
	*gpo |= H2F_DATA_READY;

	// Wait until we find out that it has heard us.
#ifdef DEBUG_PRINT
	printf("Waiting for FPGA to get busy.\n");
#endif
	while ((*gpi & F2H_BUSY) == 0) {
	    // Busy loop.
	}

	// Let FPGA know that we know that it's busy.
#ifdef DEBUG_PRINT
	printf("Telling FPGA that we know it's busy.\n");
#endif
	*gpo &= ~H2F_DATA_READY;

	// Wait until it's done rasterizing.
#ifdef DEBUG_PRINT
	printf("Waiting for FPGA to finish rasterizing.\n");
#endif
	while ((*gpi & F2H_BUSY) != 0) {
	    // Busy loop.
	}

	// usleep(1000*100);
	counter++;
    }

    exit(EXIT_SUCCESS);
}

<|endoftext|>


<commit_before>/**
 Copyright 2015 Joachim Wolff
 Master Thesis
 Tutors: Milad Miladi, Fabrizio Costa
 Winter semester 2015/2016

 Chair of Bioinformatics
 Department of Computer Science
 Faculty of Engineering
 Albert-Ludwig-University Freiburg im Breisgau
**/

#include <iostream>

#include "minHashBase.h"
#include "sparseMatrix.h"

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

MinHashBase::MinHashBase(size_t pNumberOfHashFunctions, size_t pBlockSize,
                    size_t pNumberOfCores, size_t pChunkSize,
                    size_t pMaxBinSize,
                    size_t pSizeOfNeighborhood, size_t pMinimalBlocksInCommon,
                    size_t pExcessFactor, size_t pMaximalNumberOfHashCollisions,
                    int pFast) {

        mInverseIndex = new InverseIndex(pNumberOfHashFunctions, pBlockSize,
                                        pNumberOfCores, pChunkSize,
                                        pMaxBinSize, pMinimalBlocksInCommon,
                                        pExcessFactor, pMaximalNumberOfHashCollisions);
        mNneighbors = pSizeOfNeighborhood;
        mFast = pFast;
        mNumberOfCores = pNumberOfCores;
        mChunkSize = pChunkSize;

}

MinHashBase::~MinHashBase(){
    delete mInverseIndex;
    delete mOriginalData;
}

void MinHashBase::fit(const SparseMatrixFloat* pRawData) {
    mInverseIndex->fit(pRawData);
    return;
}

void MinHashBase::partialFit() {

}
neighborhood* MinHashBase::kneighbors(const SparseMatrixFloat* pRawData, size_t pNneighbors, int pFast, size_t pSimilarity) {
    // std::cout << "53M" << std::endl;
    if (pFast == -1) {
        pFast = mFast;
    }
    if (pNneighbors == 0) {
        pNneighbors = mNneighbors;
    }
    // std::cout << "61M" << std::endl;

    umap_uniqueElement* X;
    bool doubleElementsStorageCount = false;
    if (pRawData->size() == 0) {
        // no query data given, use stored signatures
        X = mInverseIndex->getSignatureStorage();
        doubleElementsStorageCount = true;
    } else {
        X = mInverseIndex->computeSignatureMap(pRawData);
    }
    neighborhood* neighborhood_ = mInverseIndex->kneighbors(X, pNneighbors, doubleElementsStorageCount);

    if (pFast) {
        return neighborhood_;
    }
    // std::cout << "77M" << std::endl;

    neighborhood* neighborhoodExact = new neighborhood();
    neighborhoodExact->neighbors = new vvint(neighborhood_->neighbors->size());
    neighborhoodExact->distances = new vvfloat(neighborhood_->neighbors->size());

if (mChunkSize <= 0) {
        mChunkSize = ceil(neighborhood_->neighbors->size() / static_cast<float>(mNumberOfCores));
    }
#ifdef OPENMP
    omp_set_dynamic(0);
#endif
    // std::cout << "89M" << std::endl;

#pragma omp parallel for schedule(static, mChunkSize) num_threads(mNumberOfCores)
    for (size_t i = 0; i < neighborhood_->neighbors->size(); ++i) {
    // std::cout << "93M" << std::endl;

        if (neighborhood_->neighbors->operator[](i).size() != 1) {
    // std::cout << "96M" << std::endl;
    // std::cout << "i: " << i << std::endl;
    // std::cout << "size: " << neighborhood_->neighbors->size() << std::endl;
    // std::cout << "start foo: " << neighborhood_->neighbors->operator[](i).size() << std::endl ;
    // std::cout << "again foo: "<< neighborhood_->neighbors->operator[](i)[0] << std::endl;
            std::vector<sortMapFloat>* exactNeighbors;
            if (pSimilarity) {
                exactNeighbors =
                    mOriginalData->cosineSimilarity(neighborhood_->neighbors->operator[](i), neighborhood_->neighbors->operator[](i)[0], pNneighbors);
            } else {
                exactNeighbors =
                    mOriginalData->euclidianDistance(neighborhood_->neighbors->operator[](i), neighborhood_->neighbors->operator[](i)[0], pNneighbors);
            }

    // std::cout << "101M" << std::endl;
            std::vector<int> neighborsVector(exactNeighbors->size());
            std::vector<float> distancesVector(exactNeighbors->size());
    // std::cout << "104M" << std::endl;

            for (size_t j = 0; j < exactNeighbors->size(); ++j) {
                neighborsVector[j] = (*exactNeighbors)[j].key;
                distancesVector[j] = (*exactNeighbors)[j].val;
            }
    // std::cout << "105M" << std::endl;

#pragma omp critical
            {
    // std::cout << "109M" << std::endl;

                neighborhoodExact->neighbors->operator[](i) = neighborsVector;
                neighborhoodExact->distances->operator[](i) = distancesVector;
            }
        } else {
#pragma omp critical
            {
    // std::cout << "117M" << std::endl;

                neighborhoodExact->neighbors->operator[](i) = neighborhood_->neighbors->operator[](i);
                neighborhoodExact->distances->operator[](i) = neighborhood_->distances->operator[](i);
            }
        }
    }
    // std::cout << "124M" << std::endl;

    delete neighborhood_->neighbors;
    delete neighborhood_->distances;
    delete neighborhood_;
    // std::cout << "129M" << std::endl;

    return neighborhoodExact;
}
<commit_msg>Added support for query defined sparse matricies<commit_after>/**
 Copyright 2015 Joachim Wolff
 Master Thesis
 Tutors: Milad Miladi, Fabrizio Costa
 Winter semester 2015/2016

 Chair of Bioinformatics
 Department of Computer Science
 Faculty of Engineering
 Albert-Ludwig-University Freiburg im Breisgau
**/

#include <iostream>

#include "minHashBase.h"
#include "sparseMatrix.h"

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

MinHashBase::MinHashBase(size_t pNumberOfHashFunctions, size_t pBlockSize,
                    size_t pNumberOfCores, size_t pChunkSize,
                    size_t pMaxBinSize,
                    size_t pSizeOfNeighborhood, size_t pMinimalBlocksInCommon,
                    size_t pExcessFactor, size_t pMaximalNumberOfHashCollisions,
                    int pFast) {

        mInverseIndex = new InverseIndex(pNumberOfHashFunctions, pBlockSize,
                                        pNumberOfCores, pChunkSize,
                                        pMaxBinSize, pMinimalBlocksInCommon,
                                        pExcessFactor, pMaximalNumberOfHashCollisions);
        mNneighbors = pSizeOfNeighborhood;
        mFast = pFast;
        mNumberOfCores = pNumberOfCores;
        mChunkSize = pChunkSize;
}

MinHashBase::~MinHashBase(){
    delete mInverseIndex;
    delete mOriginalData;
}

void MinHashBase::fit(const SparseMatrixFloat* pRawData) {
    mInverseIndex->fit(pRawData);
    return;
}

void MinHashBase::partialFit() {

}
neighborhood* MinHashBase::kneighbors(const SparseMatrixFloat* pRawData, size_t pNneighbors, int pFast, size_t pSimilarity) {
    // std::cout << "53M" << std::endl;
    if (pFast == -1) {
        pFast = mFast;
    }
    if (pNneighbors == 0) {
        pNneighbors = mNneighbors;
    }
    // std::cout << "61M" << std::endl;

    umap_uniqueElement* X;
    bool doubleElementsStorageCount = false;
    if (pRawData == NULL) {
        // no query data given, use stored signatures
        X = mInverseIndex->getSignatureStorage();
        doubleElementsStorageCount = true;
    } else {
        X = mInverseIndex->computeSignatureMap(pRawData);
    }
    neighborhood* neighborhood_ = mInverseIndex->kneighbors(X, pNneighbors, doubleElementsStorageCount);

    if (pFast) {
        return neighborhood_;
    }
    // std::cout << "77M" << std::endl;

    neighborhood* neighborhoodExact = new neighborhood();
    neighborhoodExact->neighbors = new vvint(neighborhood_->neighbors->size());
    neighborhoodExact->distances = new vvfloat(neighborhood_->neighbors->size());

if (mChunkSize <= 0) {
        mChunkSize = ceil(neighborhood_->neighbors->size() / static_cast<float>(mNumberOfCores));
    }
#ifdef OPENMP
    omp_set_dynamic(0);
#endif
    // std::cout << "89M" << std::endl;

#pragma omp parallel for schedule(static, mChunkSize) num_threads(mNumberOfCores)
    for (size_t i = 0; i < neighborhood_->neighbors->size(); ++i) {
    // std::cout << "93M" << std::endl;

        if (neighborhood_->neighbors->operator[](i).size() != 1) {
    // std::cout << "96M" << std::endl;
    // std::cout << "i: " << i << std::endl;
    // std::cout << "size: " << neighborhood_->neighbors->size() << std::endl;
    // std::cout << "start foo: " << neighborhood_->neighbors->operator[](i).size() << std::endl ;
    // std::cout << "again foo: "<< neighborhood_->neighbors->operator[](i)[0] << std::endl;
            std::vector<sortMapFloat>* exactNeighbors;
            if (pSimilarity) {
                exactNeighbors =
                    mOriginalData->cosineSimilarity(neighborhood_->neighbors->operator[](i), neighborhood_->neighbors->operator[](i)[0], pNneighbors, pRawData);
            } else {
                exactNeighbors =
                    mOriginalData->euclidianDistance(neighborhood_->neighbors->operator[](i), neighborhood_->neighbors->operator[](i)[0], pNneighbors, pRawData);
            }

    // std::cout << "101M" << std::endl;
            std::vector<int> neighborsVector(exactNeighbors->size());
            std::vector<float> distancesVector(exactNeighbors->size());
    // std::cout << "104M" << std::endl;

            for (size_t j = 0; j < exactNeighbors->size(); ++j) {
                neighborsVector[j] = (*exactNeighbors)[j].key;
                distancesVector[j] = (*exactNeighbors)[j].val;
            }
    // std::cout << "105M" << std::endl;

#pragma omp critical
            {
    // std::cout << "109M" << std::endl;

                neighborhoodExact->neighbors->operator[](i) = neighborsVector;
                neighborhoodExact->distances->operator[](i) = distancesVector;
            }
        } else {
#pragma omp critical
            {
    // std::cout << "117M" << std::endl;

                neighborhoodExact->neighbors->operator[](i) = neighborhood_->neighbors->operator[](i);
                neighborhoodExact->distances->operator[](i) = neighborhood_->distances->operator[](i);
            }
        }
    }
    // std::cout << "124M" << std::endl;

    delete neighborhood_->neighbors;
    delete neighborhood_->distances;
    delete neighborhood_;
    // std::cout << "129M" << std::endl;

    return neighborhoodExact;
}
<|endoftext|>


<commit_before>// This is a personal academic project. Dear PVS-Studio, please check it.
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
/**
 * A mesh component that specifies that the entity can be rendered.
 * It contains a DrawObject instance from the renderer.
 *
 * License: Mozilla Public License Version 2.0 (https://www.mozilla.org/en-US/MPL/2.0/ OR See accompanying file LICENSE)
 * Authors:
 *  - Dan Printzell
 */
#include <hydra/component/meshcomponent.hpp>

#include <imgui/imgui.h>
#include <hydra/renderer/glrenderer.hpp>

#include <hydra/engine.hpp>

using namespace Hydra::World;
using namespace Hydra::Component;

MeshComponent::~MeshComponent() {}

void MeshComponent::loadMesh(const std::string meshFile) {
	this->meshFile = meshFile;
	if (!Hydra::IEngine::getInstance()->getState()->getMeshLoader())
		return;
	drawObject = Hydra::World::World::getEntity(entityID)->addComponent<DrawObjectComponent>();
	mesh = Hydra::IEngine::getInstance()->getState()->getMeshLoader()->getMesh(meshFile);
	auto newMesh = drawObject->drawObject->mesh = mesh.get();

	if (meshFile == "PARTICLEQUAD" || meshFile == "TEXTQUAD" || meshFile == "QUAD")
		drawObject->drawObject->disable = true;

	if (meshFile.find("Wall") != std::string::npos || meshFile.find("Tunnel") != std::string::npos
		 || meshFile.find("Roof") != std::string::npos || meshFile.find("Floor_v") != std::string::npos
		|| meshFile.find("HangingCable") != std::string::npos || meshFile.find("Monitor") != std::string::npos
		|| meshFile.find("BookShelf") != std::string::npos || meshFile.find("Pillar") != std::string::npos || meshFile.find("Locker") != std::string::npos
		|| meshFile.find("WaterContainer") != std::string::npos || meshFile.find("EnglishWordForHyllla") != std::string::npos
		|| meshFile.find("Fridge") != std::string::npos){
		drawObject->drawObject->hasShadow = false;
	}
}

void MeshComponent::serialize(nlohmann::json& json) const {
	json["meshFile"] = meshFile;
	json["currentFrame"] = currentFrame;
	json["animationIndex"] = animationIndex;
	json["animationCounter"] = animationCounter;
}

void MeshComponent::deserialize(nlohmann::json& json) {
	loadMesh(json["meshFile"].get<std::string>());
	currentFrame = json.value<int>("currentFrame", 1);
	animationIndex = json.value<int>("animationIndex", 0);
	animationCounter = json.value<float>("animationCounter", 0);
}

void MeshComponent::registerUI() {
	ImGui::InputText("Mesh file", (char*)meshFile.c_str(), meshFile.length(), ImGuiInputTextFlags_ReadOnly);
	ImGui::DragInt("CurrentFrame", &currentFrame);
	ImGui::DragInt("AnimationIndex", &animationIndex);
	ImGui::DragFloat("AnimationCounter", &animationCounter);
}
<commit_msg>Blacklisted Door for shadows.<commit_after>// This is a personal academic project. Dear PVS-Studio, please check it.
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
/**
 * A mesh component that specifies that the entity can be rendered.
 * It contains a DrawObject instance from the renderer.
 *
 * License: Mozilla Public License Version 2.0 (https://www.mozilla.org/en-US/MPL/2.0/ OR See accompanying file LICENSE)
 * Authors:
 *  - Dan Printzell
 */
#include <hydra/component/meshcomponent.hpp>

#include <imgui/imgui.h>
#include <hydra/renderer/glrenderer.hpp>

#include <hydra/engine.hpp>

using namespace Hydra::World;
using namespace Hydra::Component;

MeshComponent::~MeshComponent() {}

void MeshComponent::loadMesh(const std::string meshFile) {
	this->meshFile = meshFile;
	if (!Hydra::IEngine::getInstance()->getState()->getMeshLoader())
		return;
	drawObject = Hydra::World::World::getEntity(entityID)->addComponent<DrawObjectComponent>();
	mesh = Hydra::IEngine::getInstance()->getState()->getMeshLoader()->getMesh(meshFile);
	auto newMesh = drawObject->drawObject->mesh = mesh.get();

	if (meshFile == "PARTICLEQUAD" || meshFile == "TEXTQUAD" || meshFile == "QUAD")
		drawObject->drawObject->disable = true;

	if (meshFile.find("Wall") != std::string::npos || meshFile.find("Tunnel") != std::string::npos
		 || meshFile.find("Roof") != std::string::npos || meshFile.find("Floor_v") != std::string::npos
		|| meshFile.find("HangingCable") != std::string::npos || meshFile.find("Monitor") != std::string::npos
		|| meshFile.find("BookShelf") != std::string::npos || meshFile.find("Pillar") != std::string::npos || meshFile.find("Locker") != std::string::npos
		|| meshFile.find("WaterContainer") != std::string::npos || meshFile.find("EnglishWordForHyllla") != std::string::npos
		|| meshFile.find("Fridge") != std::string::npos || meshFile.find("Door") != std::string::npos){
		drawObject->drawObject->hasShadow = false;
	}
}

void MeshComponent::serialize(nlohmann::json& json) const {
	json["meshFile"] = meshFile;
	json["currentFrame"] = currentFrame;
	json["animationIndex"] = animationIndex;
	json["animationCounter"] = animationCounter;
}

void MeshComponent::deserialize(nlohmann::json& json) {
	loadMesh(json["meshFile"].get<std::string>());
	currentFrame = json.value<int>("currentFrame", 1);
	animationIndex = json.value<int>("animationIndex", 0);
	animationCounter = json.value<float>("animationCounter", 0);
}

void MeshComponent::registerUI() {
	ImGui::InputText("Mesh file", (char*)meshFile.c_str(), meshFile.length(), ImGuiInputTextFlags_ReadOnly);
	ImGui::DragInt("CurrentFrame", &currentFrame);
	ImGui::DragInt("AnimationIndex", &animationIndex);
	ImGui::DragFloat("AnimationCounter", &animationCounter);
}
<|endoftext|>


<commit_before>#include <iostream>
using namespace std;

class DepositoSimulacion{

private:
    double capital;
    int interes;

public:
    //Constructos
    DepositoSimulacion(double dinero, int inte){
        while(dinero < 0){
            cout<<"Capital incorrecto,vuelva a introducir el capital: ";
            cin>>dinero;
        }
        while(inte < 0 || inte > 100){
            cout<<"El interes tiene que estar entre un 0% y un 100%, introduzcalo de nuevo: ";
            cin>>inte;
        }
        capital = dinero;
        interes = inte;
    }

    //Calculamos el capital que tendremos en un numero de años dados sabiento el interes
    double calcularCapital(int anios){
        double total=capital;
        for(int i=1; i <= anios; i++){
            total = total + ((capital*interes)/100.0);
            cout <<"El capital en el año "<< i << " es de: "<<total<<endl;
        }
        return total;
    }

    //Calculamos los años que transcurriran hasta lograr el doble del capital
    int calcularAnios(double capital){

    }
};

int main(){

    int opcion=0,
        interes,
        anios;

    double capital,
            totalCapital;

    while(opcion != -1){
        cout<<"-----------------------------------------------------------"<<endl<<
            "1. Calcular nuevo capital dado un CAPITAL, NUMERO DE AÑOS y %"<<endl<<
            "2. Calcular numero de años para obtener el doble de un CAPITAL dado con un %"<<endl<<
            "-1. Salir"<<endl<<
            "-------------------------------------------------------------"<<endl;
            cin>>opcion;

            if(opcion == 1){
                cout<<"Introduce el capital inicial: ";
                cin>>capital;

                cout<<"Introduce el interes: ";
                cin>>interes;

                cout<<"Introduce el numero de años: ";
                cin>>anios;

                DepositoSimulacion deposito (capital,interes);

                totalCapital = deposito.calcularCapital(anios);

                cout<<"El total de capital en "<< anios << " años es de: "<< totalCapital << endl;

            }

    }

}
<commit_msg>Terminado ejercicio 3.19<commit_after>#include <iostream>
using namespace std;

class DepositoSimulacion{

private:
    double capital;
    int interes;

public:
    //Constructos
    DepositoSimulacion(double dinero, int inte){
        while(dinero < 0){
            cout<<"Capital incorrecto,vuelva a introducir el capital: ";
            cin>>dinero;
        }
        while(inte < 0 || inte > 100){
            cout<<"El interes tiene que estar entre un 0% y un 100%, introduzcalo de nuevo: ";
            cin>>inte;
        }
        capital = dinero;
        interes = inte;
    }

    //Calculamos el capital que tendremos en un numero de años dados sabiento el interes
    double calcularCapital(int anios){
        double total=capital;
        for(int i=1; i <= anios; i++){
            total = total + ((capital*interes)/100.0);
            cout <<"El capital en el año "<< i << " es de: "<<total<<endl;
        }
        return total;
    }

    //Calculamos los años que transcurriran hasta lograr el doble del capital
    int calcularAnios(){
        double dobleCapital = capital * 2;
        double copia = capital;
        int anios=0;

        while(copia < dobleCapital){
            copia = copia + ((capital*interes)/100.0);
            anios++;
        }
        return anios;
    }
};

int main(){

    int opcion=0,
        interes,
        anios;

    double capital,
            totalCapital;

    while(opcion != -1){
        cout<<"-----------------------------------------------------------"<<endl<<
            "1. Calcular nuevo capital dado un CAPITAL, NUMERO DE AÑOS y %"<<endl<<
            "2. Calcular numero de años para obtener el doble de un CAPITAL dado con un %"<<endl<<
            "-1. Salir"<<endl<<
            "-------------------------------------------------------------"<<endl;
            cin>>opcion;

            if(opcion == 1){
                cout<<"Introduce el capital inicial: ";
                cin>>capital;

                cout<<"Introduce el interes: ";
                cin>>interes;

                cout<<"Introduce el numero de años: ";
                cin>>anios;

                DepositoSimulacion deposito (capital,interes);

                totalCapital = deposito.calcularCapital(anios);

                cout<<"El total de capital en "<< anios << " años es de: "<< totalCapital << endl;

            }
            if(opcion == 2){
                cout<<"Introduce el capital inicial: ";
                cin>>capital;

                cout<<"Introduce el interes: ";
                cin>>interes;

                DepositoSimulacion deposito (capital, interes);

                anios = deposito.calcularAnios();

                cout<<"Tienen que transcurrir "<< anios << " años para tener el doble de tu capital"<<endl;
            }

    }

}
<|endoftext|>


<commit_before>#pragma once

#include <agency/detail/config.hpp>
#include <agency/detail/tuple.hpp>
#include <agency/detail/arithmetic_tuple_facade.hpp>
#include <agency/detail/type_traits.hpp>
#include <agency/detail/make_tuple_if_not_nested.hpp>

namespace agency
{
namespace detail
{

// index_tuple can't just be an alias for a particular kind of tuple
// because it also requires arithmetic operators
template<class... Indices>
class index_tuple :
  public agency::detail::tuple<Indices...>,
  public arithmetic_tuple_facade<index_tuple<Indices...>>
{
  public:
    using agency::detail::tuple<Indices...>::tuple;
};

template<class... Indices>
__AGENCY_ANNOTATION
index_tuple<Indices...> make_index_tuple(const std::tuple<Indices...>& indices)
{
  return index_tuple<Indices...>(indices);
}

template<class... Args>
__AGENCY_ANNOTATION
index_tuple<decay_t<Args>...> make_index_tuple(Args&&... args)
{
  return index_tuple<decay_t<Args>...>(std::forward<Args>(args)...);
}

struct index_tuple_maker
{
  template<class... Args>
  __AGENCY_ANNOTATION
  auto operator()(Args&&... args) const
    -> decltype(
         make_index_tuple(std::forward<Args>(args)...)
       )
  {
    return make_index_tuple(std::forward<Args>(args)...);
  }
};

template<class ExecutionCategory1,
         class ExecutionCategory2,
         class Index1,
         class Index2>
struct nested_index
{
  using type = decltype(
    __tu::tuple_cat_apply(
      detail::index_tuple_maker{},
      detail::make_tuple_if_not_nested<ExecutionCategory1>(std::declval<Index1>()),
      detail::make_tuple_if_not_nested<ExecutionCategory2>(std::declval<Index2>())
    )
  );
};

template<class ExecutionCategory1,
         class ExecutionCategory2,
         class Index1,
         class Index2>
using nested_index_t = typename nested_index<
  ExecutionCategory1,
  ExecutionCategory2,
  Index1,
  Index2
>::type;

template<class ExecutionCategory1,
         class ExecutionCategory2,
         class Index1,
         class Index2>
__AGENCY_ANNOTATION
nested_index_t<ExecutionCategory1,ExecutionCategory2,Index1,Index2> make_nested_index(const Index1& outer_idx, const Index2& inner_idx)
{
  return __tu::tuple_cat_apply(
    detail::index_tuple_maker{},
    detail::make_tuple_if_not_nested<ExecutionCategory1>(outer_idx),
    detail::make_tuple_if_not_nested<ExecutionCategory2>(inner_idx)
  );
}

} // end detail
} // end agency

namespace __tu
{

// tuple_traits specializations

template<class... Indices>
struct tuple_traits<agency::detail::index_tuple<Indices...>>
  : __tu::tuple_traits<agency::detail::tuple<Indices...>>
{
  using tuple_type = agency::detail::tuple<Indices...>;
}; // end tuple_traits

} // end __tu

namespace std
{

template<class... Indices>
struct tuple_size<agency::detail::index_tuple<Indices...>> : std::tuple_size<agency::detail::tuple<Indices...>> {};

template<size_t i, class... Indices>
struct tuple_element<i,agency::detail::index_tuple<Indices...>> : std::tuple_element<i,agency::detail::tuple<Indices...>> {};

} // end namespace std

<commit_msg>Add agency::detail::is_bounded_by()<commit_after>#pragma once

#include <agency/detail/config.hpp>
#include <agency/detail/tuple.hpp>
#include <agency/detail/arithmetic_tuple_facade.hpp>
#include <agency/detail/type_traits.hpp>
#include <agency/detail/make_tuple_if_not_nested.hpp>

namespace agency
{
namespace detail
{

// index_tuple can't just be an alias for a particular kind of tuple
// because it also requires arithmetic operators
template<class... Indices>
class index_tuple :
  public agency::detail::tuple<Indices...>,
  public arithmetic_tuple_facade<index_tuple<Indices...>>
{
  public:
    using agency::detail::tuple<Indices...>::tuple;
};

template<class... Indices>
__AGENCY_ANNOTATION
index_tuple<Indices...> make_index_tuple(const std::tuple<Indices...>& indices)
{
  return index_tuple<Indices...>(indices);
}

template<class... Args>
__AGENCY_ANNOTATION
index_tuple<decay_t<Args>...> make_index_tuple(Args&&... args)
{
  return index_tuple<decay_t<Args>...>(std::forward<Args>(args)...);
}

struct index_tuple_maker
{
  template<class... Args>
  __AGENCY_ANNOTATION
  auto operator()(Args&&... args) const
    -> decltype(
         make_index_tuple(std::forward<Args>(args)...)
       )
  {
    return make_index_tuple(std::forward<Args>(args)...);
  }
};

template<class ExecutionCategory1,
         class ExecutionCategory2,
         class Index1,
         class Index2>
struct nested_index
{
  using type = decltype(
    __tu::tuple_cat_apply(
      detail::index_tuple_maker{},
      detail::make_tuple_if_not_nested<ExecutionCategory1>(std::declval<Index1>()),
      detail::make_tuple_if_not_nested<ExecutionCategory2>(std::declval<Index2>())
    )
  );
};

template<class ExecutionCategory1,
         class ExecutionCategory2,
         class Index1,
         class Index2>
using nested_index_t = typename nested_index<
  ExecutionCategory1,
  ExecutionCategory2,
  Index1,
  Index2
>::type;

template<class ExecutionCategory1,
         class ExecutionCategory2,
         class Index1,
         class Index2>
__AGENCY_ANNOTATION
nested_index_t<ExecutionCategory1,ExecutionCategory2,Index1,Index2> make_nested_index(const Index1& outer_idx, const Index2& inner_idx)
{
  return __tu::tuple_cat_apply(
    detail::index_tuple_maker{},
    detail::make_tuple_if_not_nested<ExecutionCategory1>(outer_idx),
    detail::make_tuple_if_not_nested<ExecutionCategory2>(inner_idx)
  );
}

// a point on the number line is bounded by another if it is strictly less than the other
template<class Integral1, class Integral2,
         class = typename std::enable_if<
           std::is_integral<Integral1>::value && std::is_integral<Integral2>::value
         >::type>
__AGENCY_ANNOTATION
bool is_bounded_by(const Integral1& x, const Integral2& bound)
{
  return x < bound;
}

// a multidimensional index is bounded by another if all of its elements are
// bounded by the corresponding element of the other
// essentially we test whether x is contained within (not lying on)
// the axis-aligned bounding box from the origin to the bound
template<class IndexTuple1, class IndexTuple2,
         class = typename std::enable_if<
           is_tuple<IndexTuple1>::value && is_tuple<IndexTuple2>::value
         >::type,
         class = typename std::enable_if<
           std::tuple_size<IndexTuple1>::value == std::tuple_size<IndexTuple2>::value
         >::type>
__AGENCY_ANNOTATION
bool is_bounded_by(const IndexTuple1& x, const IndexTuple2& bound);

// terminal case: x is bounded by bound
template<size_t i, class IndexTuple1, class IndexTuple2>
__AGENCY_ANNOTATION
typename std::enable_if<
  std::tuple_size<IndexTuple1>::value <= i,
  bool
>::type
  is_bounded_by_impl(const IndexTuple1& x, const IndexTuple2& bound)
{
  return true;
}

// recursive case: early out if x[i] is not bounded by bound[i]
template<size_t i, class IndexTuple1, class IndexTuple2>
__AGENCY_ANNOTATION
typename std::enable_if<
  i < std::tuple_size<IndexTuple1>::value,
  bool
>::type
  is_bounded_by_impl(const IndexTuple1& x, const IndexTuple2& bound)
{
  return detail::is_bounded_by(detail::get<i>(x), detail::get<i>(bound)) && detail::is_bounded_by_impl<i+1>(x,bound);
}

template<class IndexTuple1, class IndexTuple2,
         class EnableIf1, class EnableIf2>
__AGENCY_ANNOTATION
bool is_bounded_by(const IndexTuple1& x, const IndexTuple2& bound)
{
  return detail::is_bounded_by_impl<0>(x,bound);
}

} // end detail
} // end agency

namespace __tu
{

// tuple_traits specializations

template<class... Indices>
struct tuple_traits<agency::detail::index_tuple<Indices...>>
  : __tu::tuple_traits<agency::detail::tuple<Indices...>>
{
  using tuple_type = agency::detail::tuple<Indices...>;
}; // end tuple_traits

} // end __tu

namespace std
{

template<class... Indices>
struct tuple_size<agency::detail::index_tuple<Indices...>> : std::tuple_size<agency::detail::tuple<Indices...>> {};

template<size_t i, class... Indices>
struct tuple_element<i,agency::detail::index_tuple<Indices...>> : std::tuple_element<i,agency::detail::tuple<Indices...>> {};

} // end namespace std

<|endoftext|>


<commit_before>#include "logging.hpp"

#include <android/log.h>
#include <cassert>

#include "../../../../../base/assert.hpp"
#include "../../../../../base/logging.hpp"
#include "../../../../../base/exception.hpp"

namespace jni
{

using namespace my;

void AndroidLogMessage(LogLevel l, SrcPoint const & src, string const & s)
{
  android_LogPriority pr = ANDROID_LOG_SILENT;

  switch (l)
  {
  case LINFO: pr = ANDROID_LOG_INFO; break;
  case LDEBUG: pr = ANDROID_LOG_DEBUG; break;
  case LWARNING: pr = ANDROID_LOG_WARN; break;
  case LERROR: pr = ANDROID_LOG_ERROR; break;
  case LCRITICAL: pr = ANDROID_LOG_FATAL; break;
  }

  string const out = DebugPrint(src) + " " + s;
  __android_log_write(pr, "MapsWithMe_JNI", out.c_str());
}

void AndroidAssertMessage(SrcPoint const & src, string const & s)
{
  AndroidLogMessage(LERROR, src, s);

#ifdef DEBUG
    assert(false);
#else
    MYTHROW(RootException, (s));
#endif
}

void InitSystemLog()
{
  SetLogMessageFn(&AndroidLogMessage);
}

void InitAssertLog()
{
  SetAssertFunction(&AndroidAssertMessage);
}

}
<commit_msg>compile time switcher to write log into file<commit_after>#include "logging.hpp"

#include <android/log.h>
#include <cassert>

#include "../../../../../base/assert.hpp"
#include "../../../../../base/logging.hpp"
#include "../../../../../base/exception.hpp"
#include "../../../../../coding/file_writer.hpp"
#include "../../../../../platform/platform.hpp"

#include "../../../../../std/scoped_ptr.hpp"

//#define MWM_LOG_TO_FILE

namespace jni
{

using namespace my;

void AndroidLogMessage(LogLevel l, SrcPoint const & src, string const & s)
{
  android_LogPriority pr = ANDROID_LOG_SILENT;

  switch (l)
  {
  case LINFO: pr = ANDROID_LOG_INFO; break;
  case LDEBUG: pr = ANDROID_LOG_DEBUG; break;
  case LWARNING: pr = ANDROID_LOG_WARN; break;
  case LERROR: pr = ANDROID_LOG_ERROR; break;
  case LCRITICAL: pr = ANDROID_LOG_FATAL; break;
  }

  string const out = DebugPrint(src) + " " + s;
  __android_log_write(pr, "MapsWithMe_JNI", out.c_str());
}

void AndroidLogToFile(LogLevel l, SrcPoint const & src, string const & s)
{
  static scoped_ptr<FileWriter> file;

  if (file == NULL)
  {
    if (GetPlatform().WritableDir().empty())
      return;

    file.reset(new FileWriter(GetPlatform().WritablePathForFile("logging.txt")));
  }

  string srcString = DebugPrint(src) + " " + s + "\n";

  file->Write(srcString.c_str(), srcString.size());
  file->Flush();
}

void AndroidAssertMessage(SrcPoint const & src, string const & s)
{
#if defined(MWM_LOG_TO_FILE)
  AndroidLogToFile(LERROR, src, s);
#else
  AndroidLogMessage(LERROR, src, s);
#endif

#ifdef DEBUG
    assert(false);
#else
    MYTHROW(RootException, (s));
#endif
}

void InitSystemLog()
{
#if defined(MWM_LOG_TO_FILE)
  SetLogMessageFn(&AndroidLogToFile);
#else
  SetLogMessageFn(&AndroidLogMessage);
#endif
}

void InitAssertLog()
{
  SetAssertFunction(&AndroidAssertMessage);
}

}
<|endoftext|>


<commit_before>#include "MPEditor.h"

MPEditor::MPEditor(const BMessage &msg, const BMessenger &msgr, BString windowTitle, int ideaID)
	:	BWindow(BRect(100, 100, 900, 700), windowTitle, B_TITLED_WINDOW, B_ASYNCHRONOUS_CONTROLS | B_AUTO_UPDATE_SIZE_LIMITS, B_CURRENT_WORKSPACE), launcherMessage(msg), launcherMessenger(msgr)
{
	// initialize controls
	BRect r = Bounds();
	r.bottom = r.bottom - 50;
	editorTextView = new BTextView(r, NULL, r, B_FOLLOW_ALL, B_WILL_DRAW);
	backView = new BView(Bounds(), "backview", B_FOLLOW_ALL, B_WILL_DRAW);
	backView->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
	AddChild(backView);
	// gui layout builder
	backView->SetLayout(new BGroupLayout(B_HORIZONTAL, 0.0));
	backView->AddChild(BGridLayoutBuilder()
		.Add(new EditorMenu(), 0, 0)
		.Add(new BScrollView("scroll_editor", editorTextView, B_FOLLOW_ALL_SIDES, 0, false, true, B_FANCY_BORDER), 0, 1)
		.SetInsets(0, 0, 0, 0)
	);

	currentideaID = ideaID; // pass current idea id selected to editor window for use
	if(currentideaID != -1) // if id has a real value
	{
		sqlObject = new SqlObject(ideaStatement, "7");
		sqlObject->PrepareSql("select ideatext from ideatable where ideaid = ?");
		sqlObject->BindValue(1, currentideaID);
		sqlObject->StepSql();
		editorTextView->SetText(sqlObject->ReturnText(0));
		sqlObject->FinalizeSql();
		sqlObject->CloseSql();
	}
}
void MPEditor::MessageReceived(BMessage* msg)
{
	BRect r(Bounds());
	switch(msg->what)
	{
		case MENU_NEW_THT: // open another untitled editor window
			tmpEditor = new MPEditor(BMessage(SHOW_LAUNCHER), BMessenger(this), "MasterPiece Editor - untitled", -1);
			tmpEditor->Show();
			break;
		case MENU_EDT_THT: // edit current idea name for editing
			xPos = (r.right - r.left) / 2; // find xpos for window
			yPos = (r.bottom - r.top) / 2; // find ypos for window
			editIdeaName = new EditIdeaName(BMessage(UPDATE_TITLE), BMessenger(this), xPos, yPos, currentideaID);
			editIdeaName->Show(); // show edit idea name window
			break;
		case MENU_SAV_THT: // save current idea progress
			if(currentideaID == -1) // if its untitled insert new thought, then show saveidea to apply a name...
			{
				sqlObject = new SqlObject(ideaStatement, "8");
				sqlObject->PrepareSql("insert into ideatable (ideaname, ideatext, ismp) values('untitled', ?, 0)");
				sqlObject->BindValue(1, editorTextView->Text());
				sqlObject->StepSql();
				xPos = (r.right - r.left) / 2; // find xpos for window
				yPos = (r.bottom - r.top) / 2; // find ypos for window
				saveIdea = new SaveIdea(BMessage(UPDATE_TITLE), BMessenger(this), xPos, yPos, sqlObject->ReturnLastInsertRowID());
				currentideaID = sqlObject->ReturnLastInsertRowID();
				sqlObject->FinalizeSql();
				sqlObject->CloseSql();
				saveIdea->Show(); // show save window to name the untitled thought
			}
			else // already exists, just update ideatext and save new information
			{
				sqlObject = new SqlObject(ideaStatement, "9");
				sqlObject->PrepareSql("update ideatable set ideatext = ? where ideaid = ?");
				sqlObject->BindValue(1, editorTextView->Text());
				sqlObject->BindValue(2, currentideaID);
				sqlObject->StepSql();
				sqlObject->FinalizeSql();
				sqlObject->CloseSql();
			}
			break;
		case MENU_PRV_THT: // preview thought in html in webpositive
			printf("save data to tmp file, export to python html one and open data in preview window or webpositive\n\n");
			// AM NO LONGER WRITING A FULL BLOWN PARSER AND DISPLAYER IN A TEXTVIEW.  IF I DO THAT, I HAVE WRITTEN A FULL BLOWN WORD PROCESSOR.
			// WILL SIMPLY USE THE PREVIEWER TO PREVIEW IN HTML WITH WEBPOSITIVE.

			// FORK/EXEC IN POSIX LINUX WILL RUN AN APP FROM C++.  HAVE TO RESEARCH THIS.
			//mpPreview = new MPPreview(currentideaID);
			//mpPreview->Show();
			system("/boot/apps/WebPositive/WebPositive file:///boot/home/Projects/masterpiece/test.html &");
			Py_Initialize();
			PyRun_SimpleString("from time import time,ctime\n"
								"print 'Today is', ctime(time())\n");
			Py_Finalize();

			break;
		case MENU_PUB_THT: // publish thought by opening publish window
			printf("save data, open publish to window, export to python and save as name in publish window");
			break;
		case MENU_HLP_THT: // open help topic window
			printf("open help topic window");
			break;
		case MENU_KEY_THT: // open keyboard reference window
			printf("open keyboard reference window");
			break;
		case MENU_MRK_THT: // open markup reference window
			printf("open markup reference window");
			break;
		case MENU_ABT_THT: // open about window
			printf("open about window");
			break;
		case UPDATE_TITLE: // update title with the name from the saveidea window
			if(msg->FindString("updatetitle", &updateTitle) == B_OK) // updated title exists in variable
			{
				tmpString = "Masterpiece Editor - ";
				tmpString += updateTitle;
				this->SetTitle(tmpString);
			}
			else //
			{
				eAlert = new ErrorAlert("3.1 Editor Error: Message not found."); // message variable not found
			}
			break;
		default:
		{
			BWindow::MessageReceived(msg);
			break;
		}
	}
}
bool MPEditor::QuitRequested(void)
{
	// on quit, show launcher by sending message
	launcherMessage.MakeEmpty();
	launcherMessage.AddInt64("showLauncher", 1);
	launcherMessenger.SendMessage(&launcherMessage);
	return true;
}
<commit_msg>got initial window shortcut working.  will need to map out all functions  and their respective shortcuts.<commit_after>#include "MPEditor.h"

MPEditor::MPEditor(const BMessage &msg, const BMessenger &msgr, BString windowTitle, int ideaID)
	:	BWindow(BRect(100, 100, 900, 700), windowTitle, B_TITLED_WINDOW, B_ASYNCHRONOUS_CONTROLS | B_AUTO_UPDATE_SIZE_LIMITS, B_CURRENT_WORKSPACE), launcherMessage(msg), launcherMessenger(msgr)
{
	AddShortcut('q', B_COMMAND_KEY, new BMessage(B_QUIT_REQUESTED)); // sample window shortcut without keydown method
	// initialize controls
	BRect r = Bounds();
	r.bottom = r.bottom - 50;
	editorTextView = new BTextView(r, NULL, r, B_FOLLOW_ALL, B_WILL_DRAW);
	backView = new BView(Bounds(), "backview", B_FOLLOW_ALL, B_WILL_DRAW);
	backView->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
	AddChild(backView);
	// gui layout builder
	backView->SetLayout(new BGroupLayout(B_HORIZONTAL, 0.0));
	backView->AddChild(BGridLayoutBuilder()
		.Add(new EditorMenu(), 0, 0)
		.Add(new BScrollView("scroll_editor", editorTextView, B_FOLLOW_ALL_SIDES, 0, false, true, B_FANCY_BORDER), 0, 1)
		.SetInsets(0, 0, 0, 0)
	);

	currentideaID = ideaID; // pass current idea id selected to editor window for use
	if(currentideaID != -1) // if id has a real value
	{
		sqlObject = new SqlObject(ideaStatement, "7");
		sqlObject->PrepareSql("select ideatext from ideatable where ideaid = ?");
		sqlObject->BindValue(1, currentideaID);
		sqlObject->StepSql();
		editorTextView->SetText(sqlObject->ReturnText(0));
		sqlObject->FinalizeSql();
		sqlObject->CloseSql();
	}
}
void MPEditor::MessageReceived(BMessage* msg)
{
	BRect r(Bounds());
	switch(msg->what)
	{
		case MENU_NEW_THT: // open another untitled editor window
			tmpEditor = new MPEditor(BMessage(SHOW_LAUNCHER), BMessenger(this), "MasterPiece Editor - untitled", -1);
			tmpEditor->Show();
			break;
		case MENU_EDT_THT: // edit current idea name for editing
			xPos = (r.right - r.left) / 2; // find xpos for window
			yPos = (r.bottom - r.top) / 2; // find ypos for window
			editIdeaName = new EditIdeaName(BMessage(UPDATE_TITLE), BMessenger(this), xPos, yPos, currentideaID);
			editIdeaName->Show(); // show edit idea name window
			break;
		case MENU_SAV_THT: // save current idea progress
			if(currentideaID == -1) // if its untitled insert new thought, then show saveidea to apply a name...
			{
				sqlObject = new SqlObject(ideaStatement, "8");
				sqlObject->PrepareSql("insert into ideatable (ideaname, ideatext, ismp) values('untitled', ?, 0)");
				sqlObject->BindValue(1, editorTextView->Text());
				sqlObject->StepSql();
				xPos = (r.right - r.left) / 2; // find xpos for window
				yPos = (r.bottom - r.top) / 2; // find ypos for window
				saveIdea = new SaveIdea(BMessage(UPDATE_TITLE), BMessenger(this), xPos, yPos, sqlObject->ReturnLastInsertRowID());
				currentideaID = sqlObject->ReturnLastInsertRowID();
				sqlObject->FinalizeSql();
				sqlObject->CloseSql();
				saveIdea->Show(); // show save window to name the untitled thought
			}
			else // already exists, just update ideatext and save new information
			{
				sqlObject = new SqlObject(ideaStatement, "9");
				sqlObject->PrepareSql("update ideatable set ideatext = ? where ideaid = ?");
				sqlObject->BindValue(1, editorTextView->Text());
				sqlObject->BindValue(2, currentideaID);
				sqlObject->StepSql();
				sqlObject->FinalizeSql();
				sqlObject->CloseSql();
			}
			break;
		case MENU_PRV_THT: // preview thought in html in webpositive
			printf("save data to tmp file, export to python html one and open data in preview window or webpositive\n\n");
			// AM NO LONGER WRITING A FULL BLOWN PARSER AND DISPLAYER IN A TEXTVIEW.  IF I DO THAT, I HAVE WRITTEN A FULL BLOWN WORD PROCESSOR.
			// WILL SIMPLY USE THE PREVIEWER TO PREVIEW IN HTML WITH WEBPOSITIVE.

			// FORK/EXEC IN POSIX LINUX WILL RUN AN APP FROM C++.  HAVE TO RESEARCH THIS.
			//mpPreview = new MPPreview(currentideaID);
			//mpPreview->Show();
			system("/boot/apps/WebPositive/WebPositive file:///boot/home/Projects/masterpiece/test.html &");
			Py_Initialize();
			PyRun_SimpleString("from time import time,ctime\n"
								"print 'Today is', ctime(time())\n");
			Py_Finalize();

			break;
		case MENU_PUB_THT: // publish thought by opening publish window
			printf("save data, open publish to window, export to python and save as name in publish window");
			break;
		case MENU_HLP_THT: // open help topic window
			printf("open help topic window");
			break;
		case MENU_KEY_THT: // open keyboard reference window
			printf("open keyboard reference window");
			break;
		case MENU_MRK_THT: // open markup reference window
			printf("open markup reference window");
			break;
		case MENU_ABT_THT: // open about window
			printf("open about window");
			break;
		case UPDATE_TITLE: // update title with the name from the saveidea window
			if(msg->FindString("updatetitle", &updateTitle) == B_OK) // updated title exists in variable
			{
				tmpString = "Masterpiece Editor - ";
				tmpString += updateTitle;
				this->SetTitle(tmpString);
			}
			else //
			{
				eAlert = new ErrorAlert("3.1 Editor Error: Message not found."); // message variable not found
			}
			break;
		default:
		{
			BWindow::MessageReceived(msg);
			break;
		}
	}
}
bool MPEditor::QuitRequested(void)
{
	// on quit, show launcher by sending message
	launcherMessage.MakeEmpty();
	launcherMessage.AddInt64("showLauncher", 1);
	launcherMessenger.SendMessage(&launcherMessage);
	return true;
}
<|endoftext|>