<commit_before>#include <DpaHandler.h>
#include <iostream>
#include <string.h>
#include <iomanip>
#include <thread>
#include "DpaLibraryDemo.h"
#include "CdcDpaInterface.h"

DpaLibraryDemo* demo_;
CDCImpl* cdc_parser_;

void asyncMsgListener(unsigned char* data, unsigned int length);

void ShowModuleInfo();

int main(void) {
  std::cout << "Start demo\n";

  cdc_parser_ = nullptr;

  try {
	cdc_parser_ = new CDCImpl("/dev/ttyACM0");
	bool test = cdc_parser_->test();

	if (test) {
	  std::cout << "Test OK\n";
	} else {
	  std::cout << "Test FAILED\n";
	  delete cdc_parser_;
	  return 2;
	}
  } catch (CDCImplException& e) {
	std::cout << e.getDescr() << "\n";
	if (cdc_parser_ != NULL) {
	  delete cdc_parser_;
	}
	return 1;
  }

  CdcDpaInterface* communication_interface = new CdcDpaInterface();
  communication_interface->Init(cdc_parser_);
  demo_ = new DpaLibraryDemo(communication_interface);

  ShowModuleInfo();

  cdc_parser_->registerAsyncMsgListener(&asyncMsgListener);

  demo_->Start();

  std::cout << "That's all for today...";

  delete communication_interface;
  delete demo_;
  return 0;
}

void asyncMsgListener(unsigned char* data, unsigned int length) {
  demo_->ListenerWrapper(data, length);
}

void ShowModuleInfo() {
  ModuleInfo* moduleInfo = nullptr;
  moduleInfo = cdc_parser_->getTRModuleInfo();

  std::cout << "Module Info:\n";
  std::cout << "Serial Number: ";
  for (int i = 0; i < ModuleInfo::SN_SIZE; ++i) {
	std::cout << std::hex
		<< std::uppercase
		<< std::setw(2)
		<< std::setfill('0')
		<< (int) moduleInfo->serialNumber[i] << ' ';
  }
  std::cout << '\n';
  std::cout << "OS version: " << std::hex << moduleInfo->osVersion << '\n';

  delete (moduleInfo);
}

DpaLibraryDemo::DpaLibraryDemo(DpaInterface* communication_interface)
	: dpa_handler_(nullptr) {
  dpaInterface_ = communication_interface;
}

DpaLibraryDemo::~DpaLibraryDemo() {
  delete dpa_handler_;
}

void DpaLibraryDemo::Start() {
  try {
	dpa_handler_ = new DpaHandler(dpaInterface_);
	dpa_handler_->RegisterAsyncMessageHandler(std::bind(&DpaLibraryDemo::UnexpectedMessage,
														this,
														std::placeholders::_1));
  }
  catch (std::invalid_argument& ae) {
	std::cout << "There was an error during DPA handler creation.\n";
  }

  dpa_handler_->Timeout(10);    // Default timeout is infinite

  int16_t i = 100;
  //wait for a while, there could be some unread message in CDC
  std::this_thread::sleep_for(std::chrono::seconds(1));

  while (i--) {
	PulseLed(0x00, kLedRed);    // Pulse with red led on coordinator
	PulseLed(0x00, kLedGreen);    // Pulse with green led on coordinator
	PulseLed(0x03, kLedRed);    // Pulse with red led on node with address 3
	PulseLed(0x03, kLedGreen);    // Pulse with green led on node with address 3
	ReadTemperature(0x03);        // Get temperature from node with address 3
  }
}

void DpaLibraryDemo::ListenerWrapper(unsigned char* data, unsigned int length) {
  dpa_handler_->ResponseHandler(data, length);
}

void DpaLibraryDemo::PulseLed(uint16_t address, LedColor color) {
  DpaMessage::DpaPacket_t packet;
  packet.DpaRequestPacket_t.NADR = address;
  if (color == kLedRed)
	packet.DpaRequestPacket_t.PNUM = PNUM_LEDR;
  else
	packet.DpaRequestPacket_t.PNUM = PNUM_LEDG;

  packet.DpaRequestPacket_t.PCMD = CMD_LED_PULSE;
  packet.DpaRequestPacket_t.HWPID = HWPID_DoNotCheck;

  DpaMessage message;
  message.AddDataToBuffer(packet.Buffer, sizeof(TDpaIFaceHeader));

  ExecuteCommand(message);
}

void DpaLibraryDemo::ExecuteCommand(DpaMessage& message) {
  static uint16_t sent_messages = 0;
  static uint16_t timeouts = 0;
  try {
	dpa_handler_->SendDpaMessage(message);
  }
  catch (std::logic_error& le) {
	std::cout << "Send error occured.\n";
	return;
  }

  ++sent_messages;

  while (dpa_handler_->IsDpaMessageInProgress()) {
	std::this_thread::sleep_for(std::chrono::milliseconds(100));
  }

  if (dpa_handler_->Status() == DpaRequest::DpaRequestStatus::kTimeout) {
	++timeouts;
	std::cout << message.NodeAddress()
		<< " - Timeout ..."
		<< sent_messages
		<< ':'
		<< timeouts
		<< '\n';
  }

}
void DpaLibraryDemo::UnexpectedMessage(const DpaMessage& message) {
  std::cout << "Unexpected message received.\n";
}

void DpaLibraryDemo::ReadTemperature(uint16_t address) {
  DpaMessage::DpaPacket_t packet;
  packet.DpaRequestPacket_t.NADR = address;
  packet.DpaRequestPacket_t.PNUM = PNUM_THERMOMETER;

  packet.DpaRequestPacket_t.PCMD = CMD_THERMOMETER_READ;
  packet.DpaRequestPacket_t.HWPID = HWPID_DoNotCheck;

  DpaMessage message;
  message.AddDataToBuffer(packet.Buffer, sizeof(TDpaIFaceHeader));

  ExecuteCommand(message);

  if (dpa_handler_->Status() == DpaRequest::DpaRequestStatus::kProcessed) {
	int16_t temperature =
		dpa_handler_->CurrentRequest().ResponseMessage().DpaPacket().DpaResponsePacket_t.DpaMessage.PerThermometerRead_Response.IntegerValue;
	std::cout << "Temperature: "
		<< std::dec << temperature << " °C\n";
  }
}
<commit_msg>Update of callback function in demo<commit_after>#include <DpaHandler.h>
#include <iostream>
#include <string.h>
#include <iomanip>
#include <thread>
#include "DpaLibraryDemo.h"
#include "CdcDpaInterface.h"

DpaLibraryDemo* demo_;
CDCImpl* cdc_parser_;
CdcDpaInterface* communication_interface_;

void asyncMsgListener(unsigned char* data, unsigned int length);

void ShowModuleInfo();

int main(void) {
  std::cout << "Start demo\n";

  cdc_parser_ = nullptr;

  try {
	cdc_parser_ = new CDCImpl("/dev/ttyACM0");
	bool test = cdc_parser_->test();

	if (test) {
	  std::cout << "Test OK\n";
	} else {
	  std::cout << "Test FAILED\n";
	  delete cdc_parser_;
	  return 2;
	}
  } catch (CDCImplException& e) {
	std::cout << e.getDescr() << "\n";
	if (cdc_parser_ != NULL) {
	  delete cdc_parser_;
	}
	return 1;
  }

  communication_interface_ = new CdcDpaInterface();
  communication_interface_->Init(cdc_parser_);
  demo_ = new DpaLibraryDemo(communication_interface_);

  ShowModuleInfo();

  cdc_parser_->registerAsyncMsgListener(&asyncMsgListener);

  demo_->Start();

  std::cout << "That's all for today...";

  delete communication_interface_;
  delete demo_;
  return 0;
}

void asyncMsgListener(unsigned char* data, unsigned int length) {
  demo_->ListenerWrapper(data, length);
}

void ShowModuleInfo() {
  ModuleInfo* moduleInfo = nullptr;
  moduleInfo = cdc_parser_->getTRModuleInfo();

  std::cout << "Module Info:\n";
  std::cout << "Serial Number: ";
  for (int i = 0; i < ModuleInfo::SN_SIZE; ++i) {
	std::cout << std::hex
		<< std::uppercase
		<< std::setw(2)
		<< std::setfill('0')
		<< (int) moduleInfo->serialNumber[i] << ' ';
  }
  std::cout << '\n';
  std::cout << "OS version: " << std::hex << moduleInfo->osVersion << '\n';

  delete (moduleInfo);
}

DpaLibraryDemo::DpaLibraryDemo(DpaInterface* communication_interface)
	: dpa_handler_(nullptr) {
  dpaInterface_ = communication_interface;
}

DpaLibraryDemo::~DpaLibraryDemo() {
  delete dpa_handler_;
}

void DpaLibraryDemo::Start() {
  try {
	dpa_handler_ = new DpaHandler(dpaInterface_);
	dpa_handler_->RegisterAsyncMessageHandler(std::bind(&DpaLibraryDemo::UnexpectedMessage,
														this,
														std::placeholders::_1));
  }
  catch (std::invalid_argument& ae) {
	std::cout << "There was an error during DPA handler creation.\n";
  }

  dpa_handler_->Timeout(10);    // Default timeout is infinite

  int16_t i = 100;
  //wait for a while, there could be some unread message in CDC
  std::this_thread::sleep_for(std::chrono::seconds(1));

  while (i--) {
	PulseLed(0x00, kLedRed);    // Pulse with red led on coordinator
	PulseLed(0x00, kLedGreen);    // Pulse with green led on coordinator
	PulseLed(0x03, kLedRed);    // Pulse with red led on node with address 3
	PulseLed(0x03, kLedGreen);    // Pulse with green led on node with address 3
	ReadTemperature(0x03);        // Get temperature from node with address 3
  }
}

void DpaLibraryDemo::ListenerWrapper(unsigned char* data, unsigned int length) {
  communication_interface_->ReceiveData(data, length);
}

void DpaLibraryDemo::PulseLed(uint16_t address, LedColor color) {
  DpaMessage::DpaPacket_t packet;
  packet.DpaRequestPacket_t.NADR = address;
  if (color == kLedRed)
	packet.DpaRequestPacket_t.PNUM = PNUM_LEDR;
  else
	packet.DpaRequestPacket_t.PNUM = PNUM_LEDG;

  packet.DpaRequestPacket_t.PCMD = CMD_LED_PULSE;
  packet.DpaRequestPacket_t.HWPID = HWPID_DoNotCheck;

  DpaMessage message;
  message.AddDataToBuffer(packet.Buffer, sizeof(TDpaIFaceHeader));

  ExecuteCommand(message);
}

void DpaLibraryDemo::ExecuteCommand(DpaMessage& message) {
  static uint16_t sent_messages = 0;
  static uint16_t timeouts = 0;
  try {
	dpa_handler_->SendDpaMessage(message);
  }
  catch (std::logic_error& le) {
	std::cout << "Send error occured.\n";
	return;
  }

  ++sent_messages;

  while (dpa_handler_->IsDpaMessageInProgress()) {
	std::this_thread::sleep_for(std::chrono::milliseconds(100));
  }

  if (dpa_handler_->Status() == DpaRequest::DpaRequestStatus::kTimeout) {
	++timeouts;
	std::cout << message.NodeAddress()
		<< " - Timeout ..."
		<< sent_messages
		<< ':'
		<< timeouts
		<< '\n';
  }

}
void DpaLibraryDemo::UnexpectedMessage(const DpaMessage& message) {
  std::cout << "Unexpected message received.\n";
}

void DpaLibraryDemo::ReadTemperature(uint16_t address) {
  DpaMessage::DpaPacket_t packet;
  packet.DpaRequestPacket_t.NADR = address;
  packet.DpaRequestPacket_t.PNUM = PNUM_THERMOMETER;

  packet.DpaRequestPacket_t.PCMD = CMD_THERMOMETER_READ;
  packet.DpaRequestPacket_t.HWPID = HWPID_DoNotCheck;

  DpaMessage message;
  message.AddDataToBuffer(packet.Buffer, sizeof(TDpaIFaceHeader));

  ExecuteCommand(message);

  if (dpa_handler_->Status() == DpaRequest::DpaRequestStatus::kProcessed) {
	int16_t temperature =
		dpa_handler_->CurrentRequest().ResponseMessage().DpaPacket().DpaResponsePacket_t.DpaMessage.PerThermometerRead_Response.IntegerValue;
	std::cout << "Temperature: "
		<< std::dec << temperature << " °C\n";
  }
}
<|endoftext|>


<commit_before>#include <anna/graphics/OpenGlGraphicApi.h>
#include <anna/graphics/Skybox.h>
#include <anna/graphics/CubeMesh.h>
#include <pthread.h>
#include <ctime>
#include <iostream>

using namespace thewizardplusplus::anna::graphics;
using namespace thewizardplusplus::anna::maths;

static const float CAMERA_ROTATION_RADIUS = 5;
static const float CAMERA_ROTATION_SPEED = 2.5;
static const float ANIMATION_SPEED = 25;
static const size_t NUMBER_OF_TREES = 75;

// http://stackoverflow.com/a/20105913/3884331
int Dummy(void) {
	static int level_of_concurrency = pthread_getconcurrency();
	return level_of_concurrency;
}

std::string GetBasePath(const std::string& app_path) {
	std::string base_path;
	size_t separator_index = app_path.rfind('/');
	if (separator_index != std::string::npos) {
		base_path = app_path.substr(0, separator_index + 1);
	}

	return base_path;
}

float GetRandomNumber(float minimum, float maximum) {
	return
		static_cast<float>(std::rand()) / RAND_MAX * (maximum - minimum)
		+ minimum;
}

float GetCurrentTime(void) {
	return static_cast<float>(std::clock()) / CLOCKS_PER_SEC;
}

int main(int number_of_arguments, char* arguments[]) try {
	(void)number_of_arguments;

	World world;
	Camera camera;
	camera.setPosition(0, 0, 2);
	camera.setRotation(15, 0, 0);
	world.setCamera(&camera);

	std::string base_path = GetBasePath(arguments[0]);
	GraphicApi* gapi = GraphicApi::create<OpenGlGraphicApi>();
	Object* skybox = new Skybox(
		gapi->createTexture(
			base_path
			+ "data/textures/skybox_axis_z_positive_direction.bmp"
		),
		gapi->createTexture(
			base_path
			+ "data/textures/skybox_axis_z_negative_direction.bmp"
		),
		gapi->createTexture(
			base_path
			+ "data/textures/skybox_axis_x_positive_direction.bmp"
		),
		gapi->createTexture(
			base_path
			+ "data/textures/skybox_axis_y_positive_direction.bmp"
		),
		gapi->createTexture(
			base_path
			+ "data/textures/skybox_axis_x_negative_direction.bmp"
		),
		gapi->createTexture(
			base_path
			+ "data/textures/skybox_axis_y_negative_direction.bmp"
		)
	);
	skybox->setScale(1000, 1000, 1000);
	world.addObject(skybox);

	AnimateObject* ground = AnimateObject::load(
		base_path
			+ "data/models/ground.ao",
		gapi,
		false
	);
	ground->setScale(10, 10, 10);
	world.addObject(ground);

	AnimateObject* windmill = AnimateObject::load(
		base_path
			+ "data/models/windmill.ao",
		gapi
	);
	windmill->setPosition(0, 0, -0.2);
	windmill->setRotation(0, 0, -120);
	windmill->setScale(0.25, 0.25, 0.25);
	windmill->play(true);
	world.addAnimateObject(windmill);

	for (size_t i = 0; i < NUMBER_OF_TREES; i++) {
		AnimateObject* tree = AnimateObject::load(
			base_path
				+ "data/models/tree.ao",
			gapi,
			false
		);
		tree->setScale(0.1, 0.1, 0.1);
		world.addObject(tree);

		float angle = GetRandomNumber(0, 360);
		float radius = GetRandomNumber(1.25, 7.5);
		float x = radius * std::cos(Maths::toRadians(angle));
		float y = radius * std::sin(Maths::toRadians(angle));
		tree->setPosition(x, y, -0.25);
	}

	Window* window = gapi->getWindow();
	float last_time = GetCurrentTime();
	while (!window->isPressedKey(KeyCode::KEY_ESCAPE)) {
		float current_time = GetCurrentTime();
		float x =
			CAMERA_ROTATION_RADIUS
			* std::cos(CAMERA_ROTATION_SPEED * current_time);
		float y =
			CAMERA_ROTATION_RADIUS
			* std::sin(CAMERA_ROTATION_SPEED * current_time);
		camera.setPosition(x, y, camera.getPosition().z);
		camera.setRotation(
			camera.getRotation().x,
			camera.getRotation().y,
			Maths::toDegrees(std::atan2(y, x)) - 90
		);

		world.update(1000 * ANIMATION_SPEED * (current_time - last_time));
		last_time = current_time;

		gapi->clear();
		gapi->drawWorld(&world);
		window->update();
	}

	delete gapi;
} catch (const std::exception& exception) {
	std::cerr << exception.what() << std::endl;
}
<commit_msg>Correct test: add fog.<commit_after>#include <anna/graphics/OpenGlGraphicApi.h>
#include <anna/graphics/FogParameters.h>
#include <anna/graphics/Skybox.h>
#include <pthread.h>
#include <ctime>
#include <iostream>

using namespace thewizardplusplus::anna::graphics;
using namespace thewizardplusplus::anna::maths;

static const float CAMERA_ROTATION_RADIUS = 5;
static const float CAMERA_ROTATION_SPEED = 1;
static const float ANIMATION_SPEED = 25;
static const size_t NUMBER_OF_TREES = 75;

// http://stackoverflow.com/a/20105913/3884331
int Dummy(void) {
	static int level_of_concurrency = pthread_getconcurrency();
	return level_of_concurrency;
}

std::string GetBasePath(const std::string& app_path) {
	std::string base_path;
	size_t separator_index = app_path.rfind('/');
	if (separator_index != std::string::npos) {
		base_path = app_path.substr(0, separator_index + 1);
	}

	return base_path;
}

float GetRandomNumber(float minimum, float maximum) {
	return
		static_cast<float>(std::rand()) / RAND_MAX * (maximum - minimum)
		+ minimum;
}

float GetCurrentTime(void) {
	return static_cast<float>(std::clock()) / CLOCKS_PER_SEC;
}

int main(int number_of_arguments, char* arguments[]) try {
	(void)number_of_arguments;

	World world;
	Camera camera;
	camera.setPosition(0, 0, 2);
	camera.setRotation(15, 0, 0);
	world.setCamera(&camera);

	GraphicApi* gapi = GraphicApi::create<OpenGlGraphicApi>();
	FogParameters fog_parameters(Vector3D<float>(0, 0, 0), 1, 1, 7.5);
	gapi->setFogParameters(fog_parameters);
	gapi->setFogMode(true);

	std::string base_path = GetBasePath(arguments[0]);
	Object* skybox = new Skybox(
		gapi->createTexture(
			base_path
			+ "data/textures/skybox_axis_z_positive_direction.bmp"
		),
		gapi->createTexture(
			base_path
			+ "data/textures/skybox_axis_z_negative_direction.bmp"
		),
		gapi->createTexture(
			base_path
			+ "data/textures/skybox_axis_x_positive_direction.bmp"
		),
		gapi->createTexture(
			base_path
			+ "data/textures/skybox_axis_y_positive_direction.bmp"
		),
		gapi->createTexture(
			base_path
			+ "data/textures/skybox_axis_x_negative_direction.bmp"
		),
		gapi->createTexture(
			base_path
			+ "data/textures/skybox_axis_y_negative_direction.bmp"
		)
	);
	skybox->setScale(1000, 1000, 1000);
	world.addObject(skybox);

	AnimateObject* ground = AnimateObject::load(
		base_path
			+ "data/models/ground.ao",
		gapi,
		false
	);
	ground->setScale(10, 10, 10);
	world.addObject(ground);

	AnimateObject* windmill = AnimateObject::load(
		base_path
			+ "data/models/windmill.ao",
		gapi
	);
	windmill->setPosition(0, 0, -0.2);
	windmill->setRotation(0, 0, -120);
	windmill->setScale(0.25, 0.25, 0.25);
	windmill->play(true);
	world.addAnimateObject(windmill);

	for (size_t i = 0; i < NUMBER_OF_TREES; i++) {
		AnimateObject* tree = AnimateObject::load(
			base_path
				+ "data/models/tree.ao",
			gapi,
			false
		);
		tree->setScale(0.1, 0.1, 0.1);
		world.addObject(tree);

		float angle = GetRandomNumber(0, 360);
		float radius = GetRandomNumber(1.25, 7.5);
		float x = radius * std::cos(Maths::toRadians(angle));
		float y = radius * std::sin(Maths::toRadians(angle));
		tree->setPosition(x, y, -0.25);
	}

	Window* window = gapi->getWindow();
	float last_time = GetCurrentTime();
	while (!window->isPressedKey(KeyCode::KEY_ESCAPE)) {
		float current_time = GetCurrentTime();
		float x =
			CAMERA_ROTATION_RADIUS
			* std::cos(CAMERA_ROTATION_SPEED * current_time);
		float y =
			CAMERA_ROTATION_RADIUS
			* std::sin(CAMERA_ROTATION_SPEED * current_time);
		camera.setPosition(x, y, camera.getPosition().z);
		camera.setRotation(
			camera.getRotation().x,
			camera.getRotation().y,
			Maths::toDegrees(std::atan2(y, x)) - 90
		);

		world.update(1000 * ANIMATION_SPEED * (current_time - last_time));
		last_time = current_time;

		gapi->clear();
		gapi->drawWorld(&world);
		window->update();
	}

	delete gapi;
} catch (const std::exception& exception) {
	std::cerr << exception.what() << std::endl;
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2017 Manzil Zaheer All rights reserved.
 *
 * 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 <Python.h>
#include "numpy/arrayobject.h"
#include "cover_tree.h"

#include <future>
#include <thread>

#include <iostream>
# include <iomanip>

template<class UnaryFunction>
UnaryFunction parallel_for_each(size_t first, size_t last, UnaryFunction f)
{
    if (first >= last) {
        return f;
    }

  unsigned cores = std::thread::hardware_concurrency();
  //std::cout << "Number of cores: " << cores << std::endl;

  auto task = [&f](size_t start, size_t end)->void{
    for (; start < end; ++start)
      f(start);
  };

  const size_t total_length = last - first;
  const size_t chunk_length = std::max(size_t(total_length / cores), size_t(1));
  size_t chunk_start = first;
  std::vector<std::future<void>>  for_threads;
  for (unsigned i = 0; i < (cores - 1) && i < total_length; ++i)
  {
    const auto chunk_stop = chunk_start + chunk_length;
    for_threads.push_back(std::async(std::launch::async, task, chunk_start, chunk_stop));
    chunk_start = chunk_stop;
  }
  for_threads.push_back(std::async(std::launch::async, task, chunk_start, last));

  for (auto& thread : for_threads)
    thread.get();
  return f;
}

static inline void progressbar(unsigned int x, unsigned int n, unsigned int w = 50){
    if ( (x != n) && (x % (n/10+1) != 0) ) return;

    float ratio =  x/(float)n;
    unsigned c = ratio * w;

    std::cout << std::setw(3) << (int)(ratio*100) << "% [";
    for (unsigned x=0; x<c; x++) std::cout << "=";
    for (unsigned x=c; x<w; x++) std::cout << " ";
    std::cout << "]\r" << std::flush;
}

template<class UnaryFunction>
UnaryFunction parallel_for_progressbar(size_t first, size_t last, UnaryFunction f)
{
    if (first >= last) {
        return f;
    }

    unsigned cores = std::thread::hardware_concurrency();
    const size_t total_length = last - first;
    const size_t chunk_length = std::max(size_t(total_length / cores), size_t(1));

    auto task = [&f,&chunk_length](size_t start, size_t end)->void{
        for (; start < end; ++start){
            progressbar(start%chunk_length, chunk_length);
            f(start);
        }
    };

    size_t chunk_start = first;
    std::vector<std::future<void>>  for_threads;
    for (unsigned i = 0; i < (cores - 1) && i < total_length; ++i)
    {
        const auto chunk_stop = chunk_start + chunk_length;
        for_threads.push_back(std::async(std::launch::async, task, chunk_start, chunk_stop));
        chunk_start = chunk_stop;
    }
    for_threads.push_back(std::async(std::launch::async, task, chunk_start, last));

    for (auto& thread : for_threads)
        thread.get();
    progressbar(chunk_length, chunk_length);
    std::cout << std::endl;
    return f;
}

static PyObject *CovertreecError;

static PyObject *new_covertreec(PyObject *self, PyObject *args)
{
  PyArrayObject *in_array;

  if (!PyArg_ParseTuple(args,"O!:new_covertreec", &PyArray_Type, &in_array))
    return NULL;

  long numPoints = PyArray_DIM(in_array, 0);
  long numDims = PyArray_DIM(in_array, 1);
  //std::cout<<numPoints<<", "<<numDims<<std::endl;
  long idx[2] = {0, 0};
  double * fnp = reinterpret_cast< double * >( PyArray_GetPtr(in_array, idx) );
  Eigen::Map<Eigen::MatrixXd> pointMatrix(fnp, numDims, numPoints);

  CoverTree* cTree = CoverTree::from_matrix(pointMatrix, -1, false);
  size_t int_ptr = reinterpret_cast< size_t >(cTree);

  return Py_BuildValue("k", int_ptr);
}

static PyObject *delete_covertreec(PyObject *self, PyObject *args)
{
  CoverTree *obj;
  size_t int_ptr;

  if (!PyArg_ParseTuple(args,"k:delete_covertreec", &int_ptr))
    return NULL;

  obj = reinterpret_cast< CoverTree * >(int_ptr);
  delete obj;

  return Py_BuildValue("k", int_ptr);
}

static PyObject *covertreec_insert(PyObject *self, PyObject *args) {

  CoverTree *obj;
  size_t int_ptr;
  PyArrayObject *in_array;

  /*  parse the input, from python int to c++ int */
  if (!PyArg_ParseTuple(args, "kO!:covertreec_insert", &int_ptr, &PyArray_Type, &in_array))
    return NULL;

  int d = PyArray_NDIM(in_array);
  long *idx = new long[d];
  for(int i=0; i<d; ++i)
    idx[i] = 0;
  double * fnp = reinterpret_cast< double * >( PyArray_GetPtr(in_array, idx) );
  Eigen::Map<pointType> value(fnp, PyArray_SIZE(in_array));

  obj = reinterpret_cast< CoverTree * >(int_ptr);
  obj->insert(value);

  Py_RETURN_NONE;
}

static PyObject *covertreec_remove(PyObject *self, PyObject *args) {

  CoverTree *obj;
  size_t int_ptr;
  PyArrayObject *in_array;

  /*  parse the input, from python int to c++ int */
  if (!PyArg_ParseTuple(args, "kO!:covertreec_insert", &int_ptr, &PyArray_Type, &in_array))
    return NULL;

  int d = PyArray_NDIM(in_array);
  long *idx = new long[d];
  for(int i=0; i<d; ++i)
    idx[i] = 0;
  double * fnp = reinterpret_cast< double * >( PyArray_GetPtr(in_array, idx) );
  Eigen::Map<pointType> value(fnp, PyArray_SIZE(in_array));

  obj = reinterpret_cast< CoverTree * >(int_ptr);
  bool val = obj->remove(value);

  if (val)
  	Py_RETURN_TRUE;

  Py_RETURN_FALSE;
}

static PyObject *covertreec_nn(PyObject *self, PyObject *args) {

  CoverTree *obj;
  size_t int_ptr;
  PyArrayObject *in_array;

  /*  parse the input, from python int to c++ int */
  if (!PyArg_ParseTuple(args, "kO!:covertreec_nn", &int_ptr, &PyArray_Type, &in_array))
    return NULL;

  long idx[2] = {0,0};
  long numPoints = PyArray_DIM(in_array, 0);
  long numDims = PyArray_DIM(in_array, 1);
  //std::cout<<numPoints<<", "<<numDims<<std::endl;
  double * fnp = reinterpret_cast< double * >( PyArray_GetPtr(in_array, idx) );
  Eigen::Map<Eigen::MatrixXd> queryPts(fnp, numDims, numPoints);

  obj = reinterpret_cast< CoverTree * >(int_ptr);

  //obj->dist_count.clear();

  double *results = new double[numDims*numPoints];
  parallel_for_progressbar(0L, numPoints, [&](long i)->void{
    std::pair<CoverTree::Node*, double> ct_nn = obj->NearestNeighbour(queryPts.col(i));
    double *data = ct_nn.first->_p.data();
    long offset = i*numDims;
    for(long j=0; j<numDims; ++j)
      results[offset++] = data[j];
  });
  //std::pair<CoverTree::Node*, double> cnn = obj->NearestNeighbour(value);

  // unsigned tot_comp = 0;
  // for(auto const& qc : obj->dist_count)
  // {
  //   std::cout << "Average number of distance computations at level: " << qc.first << " = " << 1.0 * (qc.second.load())/numPoints << std::endl;
  //   tot_comp += qc.second.load();
  // }
  // std::cout << "Average number of distance computations: " << 1.0*tot_comp/numPoints << std::endl;
  // std::cout << cnn.first->_p << std::endl;
  //Py_RETURN_NONE;

  long dims[2] = {numPoints, numDims};
  PyObject *out_array = PyArray_SimpleNewFromData(2, dims, PyArray_FLOAT64, results);

  Py_INCREF(out_array);
  return out_array;
}

static PyObject *covertreec_knn(PyObject *self, PyObject *args) {

  CoverTree *obj;
  size_t int_ptr;
  PyArrayObject *in_array;
  long k;

  /*  parse the input, from python int to c++ int */
  if (!PyArg_ParseTuple(args, "kO!l:covertreec_knn", &int_ptr, &PyArray_Type, &in_array, &k))
    return NULL;

  long idx[2] = {0,0};
  long numPoints = PyArray_DIM(in_array, 0);
  long numDims = PyArray_DIM(in_array, 1);
  double * fnp = reinterpret_cast< double * >( PyArray_GetPtr(in_array, idx) );
  Eigen::Map<Eigen::MatrixXd> queryPts(fnp, numDims, numPoints);

  obj = reinterpret_cast< CoverTree * >(int_ptr);

  double *results = new double[k*numDims*numPoints];
  parallel_for_progressbar(0L, numPoints, [&](long i)->void{
    std::vector<std::pair<CoverTree::Node*, double>> ct_nn = obj->kNearestNeighbours(queryPts.col(i), k);
    long offset = k*numDims*i;
    for(long t=0; t<k; ++t)
    {
      double *data = ct_nn[t].first->_p.data();
      for(long j=0; j<numDims; ++j)
        results[offset++] = data[j];
    }
  });
  //std::pair<CoverTree::Node*, double> cnn = obj->NearestNeighbour(value);

  // std::cout << cnn.first->_p << std::endl;
  //Py_RETURN_NONE;

  long dims[3] = {numPoints, k, numDims};
  PyObject *out_array = PyArray_SimpleNewFromData(3, dims, PyArray_FLOAT64, results);

  Py_INCREF(out_array);
  return out_array;
}

static PyObject *covertreec_display(PyObject *self, PyObject *args) {

  CoverTree *obj;
  size_t int_ptr;

  /*  parse the input, from python int to c++ int */
  if (!PyArg_ParseTuple(args, "k:covertreec_display", &int_ptr))
    return NULL;

  obj = reinterpret_cast< CoverTree * >(int_ptr);
  std::cout << *obj;

  Py_RETURN_NONE;
}

static PyObject *covertreec_test_covering(PyObject *self, PyObject *args) {

  CoverTree *obj;
  size_t int_ptr;

  /*  parse the input, from python int to c++ int */
  if (!PyArg_ParseTuple(args, "k:covertreec_test_covering", &int_ptr))
    return NULL;

  obj = reinterpret_cast< CoverTree * >(int_ptr);
  if(obj->check_covering())
    Py_RETURN_TRUE;

  Py_RETURN_FALSE;
}

PyMODINIT_FUNC initcovertreec(void)
{
  PyObject *m;
  static PyMethodDef CovertreecMethods[] = {
    {"new", new_covertreec, METH_VARARGS, "Initialize a new Cover Tree."},
    {"delete", delete_covertreec, METH_VARARGS, "Delete the Cover Tree."},
    {"insert", covertreec_insert, METH_VARARGS, "Insert a point to the Cover Tree."},
    {"remove", covertreec_remove, METH_VARARGS, "Remove a point from the Cover Tree."},
    {"NearestNeighbour", covertreec_nn, METH_VARARGS, "Find the nearest neighbour."},
    {"kNearestNeighbours", covertreec_knn, METH_VARARGS, "Find the k nearest neighbours."},
    {"display", covertreec_display, METH_VARARGS, "Display the Cover Tree."},
    {"test_covering", covertreec_test_covering, METH_VARARGS, "Check if covering property is satisfied."},
    {NULL, NULL, 0, NULL}
  };
  m = Py_InitModule("covertreec", CovertreecMethods);
  if ( m == NULL )
    return;

  /* IMPORTANT: this must be called */
  import_array();

  CovertreecError = PyErr_NewException("covertreec.error", NULL, NULL);
  Py_INCREF(CovertreecError);
  PyModule_AddObject(m, "error", CovertreecError);
}

int main(int argc, char *argv[])
{
  /* Pass argv[0] to the Python interpreter */
  Py_SetProgramName(argv[0]);

  /* Initialize the Python interpreter.  Required. */
  Py_Initialize();

  /* Add a static module */
  initcovertreec();
}

<commit_msg>Switching to Python 3<commit_after>/*
 * Copyright (c) 2017 Manzil Zaheer All rights reserved.
 *
 * 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.
 */

#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION
#define PY_SSIZE_T_CLEAN

#include <Python.h>
#include "numpy/arrayobject.h"
#include "cover_tree.h"

#include <future>
#include <thread>

#include <iostream>
# include <iomanip>

template<class UnaryFunction>
UnaryFunction parallel_for_each(size_t first, size_t last, UnaryFunction f)
{
    if (first >= last) {
        return f;
    }

  unsigned cores = std::thread::hardware_concurrency();
  //std::cout << "Number of cores: " << cores << std::endl;

  auto task = [&f](size_t start, size_t end)->void{
    for (; start < end; ++start)
      f(start);
  };

  const size_t total_length = last - first;
  const size_t chunk_length = std::max(size_t(total_length / cores), size_t(1));
  size_t chunk_start = first;
  std::vector<std::future<void>>  for_threads;
  for (unsigned i = 0; i < (cores - 1) && i < total_length; ++i)
  {
    const auto chunk_stop = chunk_start + chunk_length;
    for_threads.push_back(std::async(std::launch::async, task, chunk_start, chunk_stop));
    chunk_start = chunk_stop;
  }
  for_threads.push_back(std::async(std::launch::async, task, chunk_start, last));

  for (auto& thread : for_threads)
    thread.get();
  return f;
}

static inline void progressbar(unsigned int x, unsigned int n, unsigned int w = 50){
    if ( (x != n) && (x % (n/10+1) != 0) ) return;

    float ratio =  x/(float)n;
    unsigned c = ratio * w;

    std::cout << std::setw(3) << (int)(ratio*100) << "% [";
    for (unsigned x=0; x<c; x++) std::cout << "=";
    for (unsigned x=c; x<w; x++) std::cout << " ";
    std::cout << "]\r" << std::flush;
}

template<class UnaryFunction>
UnaryFunction parallel_for_progressbar(size_t first, size_t last, UnaryFunction f)
{
    if (first >= last) {
        return f;
    }

    unsigned cores = std::thread::hardware_concurrency();
    const size_t total_length = last - first;
    const size_t chunk_length = std::max(size_t(total_length / cores), size_t(1));

    auto task = [&f,&chunk_length](size_t start, size_t end)->void{
        for (; start < end; ++start){
            progressbar(start%chunk_length, chunk_length);
            f(start);
        }
    };

    size_t chunk_start = first;
    std::vector<std::future<void>>  for_threads;
    for (unsigned i = 0; i < (cores - 1) && i < total_length; ++i)
    {
        const auto chunk_stop = chunk_start + chunk_length;
        for_threads.push_back(std::async(std::launch::async, task, chunk_start, chunk_stop));
        chunk_start = chunk_stop;
    }
    for_threads.push_back(std::async(std::launch::async, task, chunk_start, last));

    for (auto& thread : for_threads)
        thread.get();
    progressbar(chunk_length, chunk_length);
    std::cout << std::endl;
    return f;
}

static PyObject *CovertreecError;

static PyObject *new_covertreec(PyObject *self, PyObject *args)
{
  PyArrayObject *in_array;

  if (!PyArg_ParseTuple(args,"O!:new_covertreec", &PyArray_Type, &in_array))
    return NULL;

  long numPoints = PyArray_DIM(in_array, 0);
  long numDims = PyArray_DIM(in_array, 1);
  //std::cout<<numPoints<<", "<<numDims<<std::endl;
  long idx[2] = {0, 0};
  double * fnp = reinterpret_cast< double * >( PyArray_GetPtr(in_array, idx) );
  Eigen::Map<Eigen::MatrixXd> pointMatrix(fnp, numDims, numPoints);

  CoverTree* cTree = CoverTree::from_matrix(pointMatrix, -1, false);
  size_t int_ptr = reinterpret_cast< size_t >(cTree);

  return Py_BuildValue("k", int_ptr);
}

static PyObject *delete_covertreec(PyObject *self, PyObject *args)
{
  CoverTree *obj;
  size_t int_ptr;

  if (!PyArg_ParseTuple(args,"k:delete_covertreec", &int_ptr))
    return NULL;

  obj = reinterpret_cast< CoverTree * >(int_ptr);
  delete obj;

  return Py_BuildValue("k", int_ptr);
}

static PyObject *covertreec_insert(PyObject *self, PyObject *args) {

  CoverTree *obj;
  size_t int_ptr;
  PyArrayObject *in_array;

  /*  parse the input, from python int to c++ int */
  if (!PyArg_ParseTuple(args, "kO!:covertreec_insert", &int_ptr, &PyArray_Type, &in_array))
    return NULL;

  int d = PyArray_NDIM(in_array);
  long *idx = new long[d];
  for(int i=0; i<d; ++i)
    idx[i] = 0;
  double * fnp = reinterpret_cast< double * >( PyArray_GetPtr(in_array, idx) );
  Eigen::Map<pointType> value(fnp, PyArray_SIZE(in_array));

  obj = reinterpret_cast< CoverTree * >(int_ptr);
  obj->insert(value);

  Py_RETURN_NONE;
}

static PyObject *covertreec_remove(PyObject *self, PyObject *args) {

  CoverTree *obj;
  size_t int_ptr;
  PyArrayObject *in_array;

  /*  parse the input, from python int to c++ int */
  if (!PyArg_ParseTuple(args, "kO!:covertreec_insert", &int_ptr, &PyArray_Type, &in_array))
    return NULL;

  int d = PyArray_NDIM(in_array);
  long *idx = new long[d];
  for(int i=0; i<d; ++i)
    idx[i] = 0;
  double * fnp = reinterpret_cast< double * >( PyArray_GetPtr(in_array, idx) );
  Eigen::Map<pointType> value(fnp, PyArray_SIZE(in_array));

  obj = reinterpret_cast< CoverTree * >(int_ptr);
  bool val = obj->remove(value);

  if (val)
  	Py_RETURN_TRUE;

  Py_RETURN_FALSE;
}

static PyObject *covertreec_nn(PyObject *self, PyObject *args) {

  CoverTree *obj;
  size_t int_ptr;
  PyArrayObject *in_array;

  /*  parse the input, from python int to c++ int */
  if (!PyArg_ParseTuple(args, "kO!:covertreec_nn", &int_ptr, &PyArray_Type, &in_array))
    return NULL;

  long idx[2] = {0,0};
  long numPoints = PyArray_DIM(in_array, 0);
  long numDims = PyArray_DIM(in_array, 1);
  //std::cout<<numPoints<<", "<<numDims<<std::endl;
  double * fnp = reinterpret_cast< double * >( PyArray_GetPtr(in_array, idx) );
  Eigen::Map<Eigen::MatrixXd> queryPts(fnp, numDims, numPoints);

  obj = reinterpret_cast< CoverTree * >(int_ptr);

  //obj->dist_count.clear();

  double *results = new double[numDims*numPoints];
  parallel_for_progressbar(0L, numPoints, [&](long i)->void{
    std::pair<CoverTree::Node*, double> ct_nn = obj->NearestNeighbour(queryPts.col(i));
    double *data = ct_nn.first->_p.data();
    long offset = i*numDims;
    for(long j=0; j<numDims; ++j)
      results[offset++] = data[j];
  });
  //std::pair<CoverTree::Node*, double> cnn = obj->NearestNeighbour(value);

  // unsigned tot_comp = 0;
  // for(auto const& qc : obj->dist_count)
  // {
  //   std::cout << "Average number of distance computations at level: " << qc.first << " = " << 1.0 * (qc.second.load())/numPoints << std::endl;
  //   tot_comp += qc.second.load();
  // }
  // std::cout << "Average number of distance computations: " << 1.0*tot_comp/numPoints << std::endl;
  // std::cout << cnn.first->_p << std::endl;
  //Py_RETURN_NONE;

  long dims[2] = {numPoints, numDims};
  PyObject *out_array = PyArray_SimpleNewFromData(2, dims, PyArray_FLOAT64, results);

  Py_INCREF(out_array);
  return out_array;
}

static PyObject *covertreec_knn(PyObject *self, PyObject *args) {

  CoverTree *obj;
  size_t int_ptr;
  PyArrayObject *in_array;
  long k;

  /*  parse the input, from python int to c++ int */
  if (!PyArg_ParseTuple(args, "kO!l:covertreec_knn", &int_ptr, &PyArray_Type, &in_array, &k))
    return NULL;

  long idx[2] = {0,0};
  long numPoints = PyArray_DIM(in_array, 0);
  long numDims = PyArray_DIM(in_array, 1);
  double * fnp = reinterpret_cast< double * >( PyArray_GetPtr(in_array, idx) );
  Eigen::Map<Eigen::MatrixXd> queryPts(fnp, numDims, numPoints);

  obj = reinterpret_cast< CoverTree * >(int_ptr);

  double *results = new double[k*numDims*numPoints];
  parallel_for_progressbar(0L, numPoints, [&](long i)->void{
    std::vector<std::pair<CoverTree::Node*, double>> ct_nn = obj->kNearestNeighbours(queryPts.col(i), k);
    long offset = k*numDims*i;
    for(long t=0; t<k; ++t)
    {
      double *data = ct_nn[t].first->_p.data();
      for(long j=0; j<numDims; ++j)
        results[offset++] = data[j];
    }
  });
  //std::pair<CoverTree::Node*, double> cnn = obj->NearestNeighbour(value);

  // std::cout << cnn.first->_p << std::endl;
  //Py_RETURN_NONE;

  long dims[3] = {numPoints, k, numDims};
  PyObject *out_array = PyArray_SimpleNewFromData(3, dims, PyArray_FLOAT64, results);

  Py_INCREF(out_array);
  return out_array;
}

static PyObject *covertreec_display(PyObject *self, PyObject *args) {

  CoverTree *obj;
  size_t int_ptr;

  /*  parse the input, from python int to c++ int */
  if (!PyArg_ParseTuple(args, "k:covertreec_display", &int_ptr))
    return NULL;

  obj = reinterpret_cast< CoverTree * >(int_ptr);
  std::cout << *obj;

  Py_RETURN_NONE;
}

static PyObject *covertreec_test_covering(PyObject *self, PyObject *args) {

  CoverTree *obj;
  size_t int_ptr;

  /*  parse the input, from python int to c++ int */
  if (!PyArg_ParseTuple(args, "k:covertreec_test_covering", &int_ptr))
    return NULL;

  obj = reinterpret_cast< CoverTree * >(int_ptr);
  if(obj->check_covering())
    Py_RETURN_TRUE;

  Py_RETURN_FALSE;
}

PyMODINIT_FUNC PyInit_covertreec(void)
{
  PyObject *m;
  static PyMethodDef CovertreecMethods[] = {
    {"new", new_covertreec, METH_VARARGS, "Initialize a new Cover Tree."},
    {"delete", delete_covertreec, METH_VARARGS, "Delete the Cover Tree."},
    {"insert", covertreec_insert, METH_VARARGS, "Insert a point to the Cover Tree."},
    {"remove", covertreec_remove, METH_VARARGS, "Remove a point from the Cover Tree."},
    {"NearestNeighbour", covertreec_nn, METH_VARARGS, "Find the nearest neighbour."},
    {"kNearestNeighbours", covertreec_knn, METH_VARARGS, "Find the k nearest neighbours."},
    {"display", covertreec_display, METH_VARARGS, "Display the Cover Tree."},
    {"test_covering", covertreec_test_covering, METH_VARARGS, "Check if covering property is satisfied."},
    {NULL, NULL, 0, NULL}
  };
  static struct PyModuleDef mdef = {PyModuleDef_HEAD_INIT,
                                 "covertreec",
                                 "Example module that creates an extension type.",
                                 -1,
                                 CovertreecMethods};
  m = PyModule_Create(&mdef);
  if ( m == NULL )
    return;

  /* IMPORTANT: this must be called */
  import_array();

  CovertreecError = PyErr_NewException("covertreec.error", NULL, NULL);
  Py_INCREF(CovertreecError);
  PyModule_AddObject(m, "error", CovertreecError);

  return m;
}

int main(int argc, char *argv[])
{
  /* Convert to wchar */
  wchar_t *program = Py_DecodeLocale(argv[0], NULL);
  if (program == NULL) {
     std::cerr << "Fatal error: cannot decode argv[0]" << std::endl;
     return 1;
  }

  /* Add a built-in module, before Py_Initialize */
  //PyImport_AppendInittab("covertreec", PyInit_covertreec);

  /* Pass argv[0] to the Python interpreter */
  Py_SetProgramName(program);

  /* Initialize the Python interpreter.  Required. */
  Py_Initialize();

  /* Add a static module */
  //PyInit_covertreec();
}

<|endoftext|>


<commit_before>#ifndef NEK_TYPE_TRAITS_TEST_STATIC_ASSERT_HPP
#define NEK_TYPE_TRAITS_TEST_STATIC_ASSERT_HPP

// this macro is in order to use static assert more easier.
#define STATIC_ASSERT(expression)\
  static_assert(expression, #expression)

#endif<commit_msg>update static_assert.hpp<commit_after>#ifndef NEK_TYPE_TRAITS_TEST_STATIC_ASSERT_HPP
#define NEK_TYPE_TRAITS_TEST_STATIC_ASSERT_HPP

#include <type_traits>

// these macros are in order to use static assert more easier.
#define STATIC_ASSERT_TRUE(pred)\
  static_assert(pred::value, #pred "::value == true")

#define STATIC_ASSERT_FALSE(pred)\
  static_assert(!pred::value, #pred "::value == true")

#define STATIC_ASSERT_EQ(actual_type, expect_type)\
  static_assert(std::is_same<actual_type, expect_type>::value, "std::is_same<" #actual_type ", " #expect_type ">::value")

#define STATIC_ASSERT_NE(actual_type, expect_type)\
  static_assert(!std::is_same<actual_type, expect_type>::value, "std::is_same<" #actual_type ", " #expect_type ">::value")

#endif<|endoftext|>


<commit_before><commit_msg>Iterative modexp<commit_after><|endoftext|>


<commit_before>#define BUILDING_NODE_EXTENSION

#include "EmiSockDelegate.h"

#include "EmiNodeUtil.h"
#include "EmiSocket.h"
#include "EmiConnection.h"
#include "slab_allocator.h"

#include <stdexcept>
#include <node.h>

#define SLAB_SIZE (1024 * 1024)

using namespace v8;

static node::SlabAllocator slab_allocator(SLAB_SIZE);

static Handle<String> errStr(uv_err_t err) {
    HandleScope scope;

    Local<String> errStr;

    if (err.code == UV_UNKNOWN) {
        char errno_buf[100];
        snprintf(errno_buf, 100, "Unknown system errno %d", err.sys_errno_);
        errStr = String::New(errno_buf);
    } else {
        errStr = String::NewSymbol(uv_err_name(err));
    }

    return scope.Close(errStr);
}

inline static uint16_t sockaddrPort(const struct sockaddr_storage& addr) {
    if (AF_INET6 == addr.ss_family) {
        struct sockaddr_in6& addr6(*((struct sockaddr_in6 *)&addr));
        return addr6.sin6_port;
    }
    else if (AF_INET == addr.ss_family) {
        struct sockaddr_in& addr(*((struct sockaddr_in *)&addr));
        return addr.sin_port;
    }
    else {
        ASSERT(0 && "unexpected address family");
        abort();
    }
}

static void send_cb(uv_udp_send_t* req, int status) {
    free(req);
}

static uv_buf_t alloc_cb(uv_handle_t* handle, size_t suggested_size) {
    char *buf = slab_allocator.Allocate(Context::GetCurrent()->Global(), suggested_size);
    return uv_buf_init(buf, suggested_size);
}

static void recv_cb(uv_udp_t *handle,
                    ssize_t nread,
                    uv_buf_t buf,
                    struct sockaddr *addr,
                    unsigned flags) {
    HandleScope scope;

    EmiSocket *wrap = reinterpret_cast<EmiSocket *>(handle->data);

    Local<Object> slab = slab_allocator.Shrink(Context::GetCurrent()->Global(),
                                               buf.base,
                                               nread < 0 ? 0 : nread);
    if (nread == 0) return;

    if (nread < 0) {
        const unsigned argc = 2;
        Handle<Value> argv[argc] = {
            wrap->handle_,
            errStr(uv_last_error(uv_default_loop()))
        };
        EmiSocket::connectionError->Call(Context::GetCurrent()->Global(), argc, argv);
        return;
    }

    if (flags & UV_UDP_PARTIAL) {
        // Discard the packet
        return;
    }

    wrap->getSock().onMessage(EmiConnection::Now(),
                              handle,
                              *((struct sockaddr_storage *)addr),
                              slab,
                              buf.base - node::Buffer::Data(slab),
                              nread);
}

static void close_cb(uv_handle_t* handle) {
    free(handle);
}

EmiSockDelegate::EmiSockDelegate(EmiSocket& es) : _es(es) {}

void EmiSockDelegate::closeSocket(EmiSockDelegate::ES& sock, uv_udp_t *socket) {
    // This allows V8's GC to reclaim the EmiSocket when no UDP sockets are open
    //
    // TODO Perhaps I should do this on the next uv tick, since this might dealloc
    // the whole socket, which will probably not end up well.
    //
    // TODO What happens when this method is actually called from _es's destructor?
    sock.getDelegate()._es.Unref();

    uv_close((uv_handle_t *)socket, close_cb);
}

uv_udp_t *EmiSockDelegate::openSocket(EmiSockDelegate::ES& sock, uint16_t port, Error& error) {
    int err;
    uv_udp_t *socket = (uv_udp_t *)malloc(sizeof(uv_udp_t));

    err = uv_udp_init(uv_default_loop(), socket);
    if (0 != err) {
        goto error;
    }

    if (AF_INET == sock.config.address.ss_family) {
        struct sockaddr_in& addr(*((struct sockaddr_in *)&sock.config.address));

        char buf[100];
        uv_ip4_name(&addr, buf, sizeof(buf));

        err = uv_udp_bind(socket, addr, /*flags:*/0);
        if (0 != err) {
            goto error;
        }
    }
    else if (AF_INET6 == sock.config.address.ss_family) {
        struct sockaddr_in6& addr6(*((struct sockaddr_in6 *)&sock.config.address));
        err = uv_udp_bind6(socket, addr6, /*flags:*/0);
        if (0 != err) {
            goto error;
        }
    }
    else {
        ASSERT(0 && "unexpected address family");
        abort();
    }

    err = uv_udp_recv_start(socket, alloc_cb, recv_cb);
    if (0 != err) {
        goto error;
    }

    socket->data = &sock.getDelegate()._es;

    // This prevents V8's GC to reclaim the EmiSocket while UDP sockets are open
    sock.getDelegate()._es.Ref();

    return socket;

error:
    free(socket);
    return NULL;
}

uint16_t EmiSockDelegate::extractLocalPort(uv_udp_t *socket) {
    struct sockaddr_storage address;
    int len(sizeof(address));

    uv_udp_getsockname(socket, (struct sockaddr *)&address, &len);

    if (AF_INET == address.ss_family) {
        sockaddr_in *addr = (sockaddr_in *)&address;
        return addr->sin_port;
    }
    else if (AF_INET6 == address.ss_family) {
        sockaddr_in6 *addr = (sockaddr_in6 *)&address;
        return addr->sin6_port;
    }
    else {
        ASSERT(0 && "unexpected address family");
        abort();
    }
}

EmiSockDelegate::EC *EmiSockDelegate::makeConnection(const Address& address,
                                                     uint16_t inboundPort,
                                                     bool initiator) {
    HandleScope scope;

    // TODO I think the HandleScope will dispose of EmiConnection after
    // this function, which is not what we want... Exactly what will
    // happen?

    Handle<Object> obj(EmiConnection::NewInstance(_es,
                                                  address,
                                                  inboundPort,
                                                  initiator));
    EmiConnection *ec = node::ObjectWrap::Unwrap<EmiConnection>(obj);
    return &ec->getConn();
}

void EmiSockDelegate::sendData(uv_udp_t *socket,
                               const Address& address,
                               const uint8_t *data,
                               size_t size) {
    uv_udp_send_t *req = (uv_udp_send_t *)malloc(sizeof(uv_udp_send_t)+
                                                 sizeof(uv_buf_t));
    uv_buf_t      *buf = (uv_buf_t *)&req[1];

    *buf = uv_buf_init((char *)data, size);

    if (AF_INET == address.ss_family) {
        if (0 != uv_udp_send(req,
                             socket,
                             buf,
                             /*bufcnt:*/1,
                             *((struct sockaddr_in *)&address),
                             send_cb)) {
            free(req);
        }
    }
    else if (AF_INET6 == address.ss_family) {
        if (0 != uv_udp_send6(req,
                              socket,
                              buf,
                              /*bufcnt:*/1,
                              *((struct sockaddr_in6 *)&address),
                              send_cb)) {
            free(req);
        }
    }
    else {
        ASSERT(0 && "unexpected address family");
    }
}

void EmiSockDelegate::gotConnection(EC& conn) {
    HandleScope scope;

    Handle<Value> jsHandle(conn.getEmiSock().getDelegate()._es._jsHandle);

    const unsigned argc = 3;
    Handle<Value> argv[argc] = {
        jsHandle.IsEmpty() ? Handle<Value>(Undefined()) : jsHandle,
        conn.getEmiSock().getDelegate()._es.handle_,
        conn.getDelegate().getConnection().handle_
    };
    Local<Value> ret = EmiSocket::gotConnection->Call(Context::GetCurrent()->Global(), argc, argv);

    if (!ret.IsEmpty() && ret->IsObject()) {
        conn.getDelegate().getConnection().setJsHandle(ret->ToObject());
    }
}

void EmiSockDelegate::connectionOpened(ConnectionOpenedCallbackCookie& cookie,
                                       bool error,
                                       EmiDisconnectReason reason,
                                       EC& conn) {
    HandleScope scope;

    const unsigned argc = 2;
    Handle<Value> argv[argc];

    // TODO Give the error as something better than just the error code
    argv[0] = error ? Number::New(reason) : Null();

    if (error) {
        argv[1] = Null();
    }
    else {
        argv[1] = conn.getDelegate().getConnection().handle_;
    }

    Local<Value> ret = cookie->CallAsFunction(Context::GetCurrent()->Global(), argc, argv);

    if (!ret.IsEmpty() && ret->IsObject()) {
        conn.getDelegate().getConnection().setJsHandle(ret->ToObject());
    }

    cookie.Dispose();
}

void EmiSockDelegate::panic() {
    throw std::runtime_error("EmiNet internal error");
}

Persistent<Object> EmiSockDelegate::makePersistentData(const Local<Object>& data,
                                                       size_t offset,
                                                       size_t length) {
    HandleScope scope;

    // Copy the buffer
    node::Buffer *buf(node::Buffer::New(node::Buffer::Data(data)+offset,
                                        length));

    // Make a new persistent handle (do not just reuse the persistent buf->handle_ handle)
    return Persistent<Object>::New(buf->handle_);
}<commit_msg>It is now possible to open more than one connection to a single server with the node.js EmiNet bindings<commit_after>#define BUILDING_NODE_EXTENSION

#include "EmiSockDelegate.h"

#include "EmiNodeUtil.h"
#include "EmiSocket.h"
#include "EmiConnection.h"
#include "slab_allocator.h"

#include <stdexcept>
#include <node.h>

#define SLAB_SIZE (1024 * 1024)

using namespace v8;

static node::SlabAllocator slab_allocator(SLAB_SIZE);

static Handle<String> errStr(uv_err_t err) {
    HandleScope scope;

    Local<String> errStr;

    if (err.code == UV_UNKNOWN) {
        char errno_buf[100];
        snprintf(errno_buf, 100, "Unknown system errno %d", err.sys_errno_);
        errStr = String::New(errno_buf);
    } else {
        errStr = String::NewSymbol(uv_err_name(err));
    }

    return scope.Close(errStr);
}

inline static uint16_t sockaddrPort(const struct sockaddr_storage& addr) {
    if (AF_INET6 == addr.ss_family) {
        struct sockaddr_in6& addr6(*((struct sockaddr_in6 *)&addr));
        return addr6.sin6_port;
    }
    else if (AF_INET == addr.ss_family) {
        struct sockaddr_in& addr(*((struct sockaddr_in *)&addr));
        return addr.sin_port;
    }
    else {
        ASSERT(0 && "unexpected address family");
        abort();
    }
}

static void send_cb(uv_udp_send_t* req, int status) {
    free(req);
}

static uv_buf_t alloc_cb(uv_handle_t* handle, size_t suggested_size) {
    char *buf = slab_allocator.Allocate(Context::GetCurrent()->Global(), suggested_size);
    return uv_buf_init(buf, suggested_size);
}

static void recv_cb(uv_udp_t *handle,
                    ssize_t nread,
                    uv_buf_t buf,
                    struct sockaddr *addr,
                    unsigned flags) {
    HandleScope scope;

    EmiSocket *wrap = reinterpret_cast<EmiSocket *>(handle->data);

    Local<Object> slab = slab_allocator.Shrink(Context::GetCurrent()->Global(),
                                               buf.base,
                                               nread < 0 ? 0 : nread);
    if (nread == 0) return;

    if (nread < 0) {
        const unsigned argc = 2;
        Handle<Value> argv[argc] = {
            wrap->handle_,
            errStr(uv_last_error(uv_default_loop()))
        };
        EmiSocket::connectionError->Call(Context::GetCurrent()->Global(), argc, argv);
        return;
    }

    if (flags & UV_UDP_PARTIAL) {
        // Discard the packet
        return;
    }

    wrap->getSock().onMessage(EmiConnection::Now(),
                              handle,
                              *((struct sockaddr_storage *)addr),
                              slab,
                              buf.base - node::Buffer::Data(slab),
                              nread);
}

static void close_cb(uv_handle_t* handle) {
    free(handle);
}

EmiSockDelegate::EmiSockDelegate(EmiSocket& es) : _es(es) {}

void EmiSockDelegate::closeSocket(EmiSockDelegate::ES& sock, uv_udp_t *socket) {
    // This allows V8's GC to reclaim the EmiSocket when no UDP sockets are open
    //
    // TODO Perhaps I should do this on the next uv tick, since this might dealloc
    // the whole socket, which will probably not end up well.
    //
    // TODO What happens when this method is actually called from _es's destructor?
    sock.getDelegate()._es.Unref();

    uv_close((uv_handle_t *)socket, close_cb);
}

uv_udp_t *EmiSockDelegate::openSocket(EmiSockDelegate::ES& sock, uint16_t port, Error& error) {
    int err;
    uv_udp_t *socket = (uv_udp_t *)malloc(sizeof(uv_udp_t));

    err = uv_udp_init(uv_default_loop(), socket);
    if (0 != err) {
        goto error;
    }

    if (AF_INET == sock.config.address.ss_family) {
        struct sockaddr_in addr(*((struct sockaddr_in *)&sock.config.address));
        addr.sin_port = htons(port);

        char buf[100];
        uv_ip4_name(&addr, buf, sizeof(buf));

        err = uv_udp_bind(socket, addr, /*flags:*/0);
        if (0 != err) {
            goto error;
        }
    }
    else if (AF_INET6 == sock.config.address.ss_family) {
        struct sockaddr_in6 addr6(*((struct sockaddr_in6 *)&sock.config.address));
        addr6.sin6_port = htons(port);

        err = uv_udp_bind6(socket, addr6, /*flags:*/0);
        if (0 != err) {
            goto error;
        }
    }
    else {
        ASSERT(0 && "unexpected address family");
        abort();
    }

    err = uv_udp_recv_start(socket, alloc_cb, recv_cb);
    if (0 != err) {
        goto error;
    }

    socket->data = &sock.getDelegate()._es;

    // This prevents V8's GC to reclaim the EmiSocket while UDP sockets are open
    sock.getDelegate()._es.Ref();

    return socket;

error:
    free(socket);
    return NULL;
}

uint16_t EmiSockDelegate::extractLocalPort(uv_udp_t *socket) {
    struct sockaddr_storage address;
    int len(sizeof(address));

    uv_udp_getsockname(socket, (struct sockaddr *)&address, &len);

    if (AF_INET == address.ss_family) {
        sockaddr_in *addr = (sockaddr_in *)&address;
        return addr->sin_port;
    }
    else if (AF_INET6 == address.ss_family) {
        sockaddr_in6 *addr = (sockaddr_in6 *)&address;
        return addr->sin6_port;
    }
    else {
        ASSERT(0 && "unexpected address family");
        abort();
    }
}

EmiSockDelegate::EC *EmiSockDelegate::makeConnection(const Address& address,
                                                     uint16_t inboundPort,
                                                     bool initiator) {
    HandleScope scope;

    // TODO I think the HandleScope will dispose of EmiConnection after
    // this function, which is not what we want... Exactly what will
    // happen?

    Handle<Object> obj(EmiConnection::NewInstance(_es,
                                                  address,
                                                  inboundPort,
                                                  initiator));
    EmiConnection *ec = node::ObjectWrap::Unwrap<EmiConnection>(obj);
    return &ec->getConn();
}

void EmiSockDelegate::sendData(uv_udp_t *socket,
                               const Address& address,
                               const uint8_t *data,
                               size_t size) {
    uv_udp_send_t *req = (uv_udp_send_t *)malloc(sizeof(uv_udp_send_t)+
                                                 sizeof(uv_buf_t));
    uv_buf_t      *buf = (uv_buf_t *)&req[1];

    *buf = uv_buf_init((char *)data, size);

    if (AF_INET == address.ss_family) {
        if (0 != uv_udp_send(req,
                             socket,
                             buf,
                             /*bufcnt:*/1,
                             *((struct sockaddr_in *)&address),
                             send_cb)) {
            free(req);
        }
    }
    else if (AF_INET6 == address.ss_family) {
        if (0 != uv_udp_send6(req,
                              socket,
                              buf,
                              /*bufcnt:*/1,
                              *((struct sockaddr_in6 *)&address),
                              send_cb)) {
            free(req);
        }
    }
    else {
        ASSERT(0 && "unexpected address family");
    }
}

void EmiSockDelegate::gotConnection(EC& conn) {
    HandleScope scope;

    Handle<Value> jsHandle(conn.getEmiSock().getDelegate()._es._jsHandle);

    const unsigned argc = 3;
    Handle<Value> argv[argc] = {
        jsHandle.IsEmpty() ? Handle<Value>(Undefined()) : jsHandle,
        conn.getEmiSock().getDelegate()._es.handle_,
        conn.getDelegate().getConnection().handle_
    };
    Local<Value> ret = EmiSocket::gotConnection->Call(Context::GetCurrent()->Global(), argc, argv);

    if (!ret.IsEmpty() && ret->IsObject()) {
        conn.getDelegate().getConnection().setJsHandle(ret->ToObject());
    }
}

void EmiSockDelegate::connectionOpened(ConnectionOpenedCallbackCookie& cookie,
                                       bool error,
                                       EmiDisconnectReason reason,
                                       EC& conn) {
    HandleScope scope;

    const unsigned argc = 2;
    Handle<Value> argv[argc];

    // TODO Give the error as something better than just the error code
    argv[0] = error ? Number::New(reason) : Null();

    if (error) {
        argv[1] = Null();
    }
    else {
        argv[1] = conn.getDelegate().getConnection().handle_;
    }

    Local<Value> ret = cookie->CallAsFunction(Context::GetCurrent()->Global(), argc, argv);

    if (!ret.IsEmpty() && ret->IsObject()) {
        conn.getDelegate().getConnection().setJsHandle(ret->ToObject());
    }

    cookie.Dispose();
}

void EmiSockDelegate::panic() {
    throw std::runtime_error("EmiNet internal error");
}

Persistent<Object> EmiSockDelegate::makePersistentData(const Local<Object>& data,
                                                       size_t offset,
                                                       size_t length) {
    HandleScope scope;

    // Copy the buffer
    node::Buffer *buf(node::Buffer::New(node::Buffer::Data(data)+offset,
                                        length));

    // Make a new persistent handle (do not just reuse the persistent buf->handle_ handle)
    return Persistent<Object>::New(buf->handle_);
}<|endoftext|>


<commit_before>/*
Copyright (c) 2013 Daniele Bartolini, Michele Rossi
Copyright (c) 2012 Daniele Bartolini, Simone Boscaratto

Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:

The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
*/

#include "Filesystem.h"
#include "Log.h"
#include "OS.h"
#include "DiskFile.h"
#include "Memory.h"
#include "Hash.h"
#include "DiskMountPoint.h"

namespace crown
{

//-----------------------------------------------------------------------------
Filesystem::Filesystem() :
	m_mount_point_head(NULL)
{

}

//-----------------------------------------------------------------------------
Filesystem::~Filesystem()
{
}

//-----------------------------------------------------------------------------
void Filesystem::mount(MountPoint& mp)
{
	if (m_mount_point_head != NULL)
	{
		mp.m_next = m_mount_point_head;
	}

	m_mount_point_head = ∓
}

//-----------------------------------------------------------------------------
void Filesystem::umount(MountPoint& mp)
{
	MountPoint* current = m_mount_point_head;
	MountPoint* previous;
	MountPoint* tmp;
	(void)tmp;

	if (&mp == current)
	{
		tmp = current;

		current = current->m_next;

		tmp = NULL;

		return;
	}
	else
	{
		previous = current;
		current = current->m_next;

		while (current != NULL && &mp != current)
		{
			previous = current;

			current = current->m_next;
		}

		if (current != NULL)
		{
			tmp = current;

			previous->m_next = current->m_next;

			tmp = NULL;

			return;
		}
	}
}

//-----------------------------------------------------------------------------
File* Filesystem::open(const char* mount_point, const char* relative_path, FileOpenMode mode)
{
	MountPoint* mp = find_mount_point(mount_point);

	if (mp)
	{
		return mp->open(relative_path, mode);
	}

	return NULL;
}

//-----------------------------------------------------------------------------
void Filesystem::close(File* file)
{
	CE_DELETE(m_allocator, file);
}

//-----------------------------------------------------------------------------
bool Filesystem::exists(const char* mount_point, const char* relative_path)
{
	MountPoint* mp = find_mount_point(mount_point);

	if (mp)
	{
		return mp->exists(relative_path);
	}

	return false;
}

//-----------------------------------------------------------------------------
const char* Filesystem::os_path(const char* mount_point, const char* relative_path)
{
	MountPoint* mp = find_mount_point(mount_point);

	if (mp)
	{
		return ((DiskMountPoint*)mp)->os_path(relative_path);
	}

	return NULL;
}

//-----------------------------------------------------------------------------
MountPoint*	Filesystem::find_mount_point(const char* mount_point)
{
	MountPoint* curr = m_mount_point_head;

	uint32_t type_hash = hash::murmur2_32(mount_point, string::strlen(mount_point), 0);

	while(curr != NULL)
	{
		if (curr->type() == type_hash)
		{
			Log::d("Android mount point found!");
			return curr;
		}

		curr = curr->m_next;
	}

	return NULL;
}

} // namespace crown

<commit_msg>minor fix to Filesystem<commit_after>/*
Copyright (c) 2013 Daniele Bartolini, Michele Rossi
Copyright (c) 2012 Daniele Bartolini, Simone Boscaratto

Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:

The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
*/

#include "Filesystem.h"
#include "Log.h"
#include "OS.h"
#include "DiskFile.h"
#include "Memory.h"
#include "Hash.h"
#include "DiskMountPoint.h"

namespace crown
{

//-----------------------------------------------------------------------------
Filesystem::Filesystem() :
	m_mount_point_head(NULL)
{

}

//-----------------------------------------------------------------------------
Filesystem::~Filesystem()
{
}

//-----------------------------------------------------------------------------
void Filesystem::mount(MountPoint& mp)
{
	if (m_mount_point_head != NULL)
	{
		mp.m_next = m_mount_point_head;
	}

	m_mount_point_head = ∓
}

//-----------------------------------------------------------------------------
void Filesystem::umount(MountPoint& mp)
{
	MountPoint* current = m_mount_point_head;
	MountPoint* previous;
	MountPoint* tmp;
	(void)tmp;

	if (&mp == current)
	{
		tmp = current;

		current = current->m_next;

		tmp = NULL;

		return;
	}
	else
	{
		previous = current;
		current = current->m_next;

		while (current != NULL && &mp != current)
		{
			previous = current;

			current = current->m_next;
		}

		if (current != NULL)
		{
			tmp = current;

			previous->m_next = current->m_next;

			tmp = NULL;

			return;
		}
	}
}

//-----------------------------------------------------------------------------
File* Filesystem::open(const char* mount_point, const char* relative_path, FileOpenMode mode)
{
	MountPoint* mp = find_mount_point(mount_point);

	if (mp)
	{
		return mp->open(relative_path, mode);
	}

	return NULL;
}

//-----------------------------------------------------------------------------
void Filesystem::close(File* file)
{
	CE_DELETE(m_allocator, file);
}

//-----------------------------------------------------------------------------
bool Filesystem::exists(const char* mount_point, const char* relative_path)
{
	MountPoint* mp = find_mount_point(mount_point);

	if (mp)
	{
		return mp->exists(relative_path);
	}

	return false;
}

//-----------------------------------------------------------------------------
const char* Filesystem::os_path(const char* mount_point, const char* relative_path)
{
	MountPoint* mp = find_mount_point(mount_point);

	if (mp)
	{
		return mp->os_path(relative_path);
	}

	return NULL;
}

//-----------------------------------------------------------------------------
MountPoint*	Filesystem::find_mount_point(const char* mount_point)
{
	MountPoint* curr = m_mount_point_head;

	uint32_t type_hash = hash::murmur2_32(mount_point, string::strlen(mount_point), 0);

	while(curr != NULL)
	{
		if (curr->type() == type_hash)
		{
			return curr;
		}

		curr = curr->m_next;
	}

	return NULL;
}

} // namespace crown

<|endoftext|>


<commit_before>/*!
 * @file FgController.cpp
 *
 * @brief Controller
 *
 * @author Andrey Shelest
 * @author Oleksii Aliakin (alex@nls.la)
 * @date Created Feb 08, 2015
 * @date Modified Jun 30, 2015
 */

#include "FgController.h"
#include "FgTransport.h"

#include <QFile>
#include <QJsonArray>
#include <QJsonDocument>

FgController::FgController(QObject *parent) :
    QObject(parent)
{

}

FgController::~FgController()
{
//    saveConfig("./config/fgapConfig.json");
}

bool FgController::init()
{
    QFile configFile("./config/fgapConfig.json");
    if (!configFile.open(QIODevice::ReadOnly))
    {
        qWarning("Couldn't open config file.");
        return false;
    }
    QJsonDocument configData(QJsonDocument::fromJson(configFile.readAll()));
    QJsonObject configObj = configData.object();
    QJsonArray aircrafts = configObj["aircrafts"].toArray();

    for (auto parameter : aircrafts)
    {
        auto aircraft = std::make_shared<FgControlledAircraft>(parameter.toObject());
        m_OurAircrafts.insert(aircraft->callsign(), aircraft);
        connect(this, &FgController::fdmDataChanged, aircraft.get(), &FgControlledAircraft::onFdmDataChanged);
        emit ourAircraftConnected(aircraft.get());
    }

    m_Transport = (*m_OurAircrafts.begin())->transport();
    connect(m_Transport.get(), &FgTransport::fgDataReceived, this, &FgController::onDataReceived);

    return true;
}

void FgController::updateAircraft(const QString & /* aircraftId */)
{
}

void FgController::onDataReceived()
{
    updateOtherAircraftsCount();

    emit fdmDataChanged(m_Transport);

    //eleron
    //elevator

    if (m_OurAircrafts.isEmpty())
    {
        qDebug() << "Our aircraft is empty!";
        return;
    }

    auto aircraft = *m_OurAircrafts.begin();
    QString data = QString::number(aircraft->ailerons()) + '\t' + QString::number(aircraft->elevator()) + "\n";
    m_Transport->writeData(data);
}

void FgController::updateOtherAircraftsCount()
{
    qint32 count = m_Transport->getInt("/ai/models/num-players");

    if (m_AircraftsCount == count)
    {
        // assume that aircrafts remain the same
        return;
    }

    m_AircraftsCount = count;

    // get all aircrafts and add new ones to the list
    QList<QString> callsigns;
    for (int i = 0; i < count; ++i)
    {
        QString callsign = m_Transport->getString("/ai/models/multiplayer[" + QString::number(i) + "]/callsign");
        qDebug() << "callsign = " << callsign;
        callsigns.push_back(callsign);
        if (m_OtherAircrafts.contains(callsigns.back()))
        {
            continue;
        }

        auto aircraft = std::make_shared<FgAircraft>(callsign);
        aircraft->setConnected(true);
        //! @todo  aircraft->setIndex();
        m_OtherAircrafts[callsign] = aircraft;
        emit aircraftConnected(aircraft.get());
        qDebug() << "otherAircraftConnected";
    }

    // remove disconnected aircrafts from the list
    auto it = m_OtherAircrafts.begin();
    while (it != m_OtherAircrafts.end())
    {
        if (!callsigns.contains((*it)->callsign()))
        {
            emit aircraftDisconnected((*it).get());
            qDebug() << "aircraftDisconnected";

            it = m_OtherAircrafts.erase(it);
        }
        else
        {
            ++it;
        }
    }
}
<commit_msg>Fixed settings file name.<commit_after>/*!
 * @file FgController.cpp
 *
 * @brief Controller
 *
 * @author Andrey Shelest
 * @author Oleksii Aliakin (alex@nls.la)
 * @date Created Feb 08, 2015
 * @date Modified Jun 30, 2015
 */

#include "FgController.h"
#include "FgTransport.h"

#include <QFile>
#include <QJsonArray>
#include <QJsonDocument>
#include <QCoreApplication>

FgController::FgController(QObject *parent) :
    QObject(parent)
{

}

FgController::~FgController()
{
//    saveConfig("./config/fgapConfig.json");
}

bool FgController::init()
{
    // FIX: filename determining
    QString configFileName = QCoreApplication::applicationDirPath() + "/config/fgapConfig.json";
    QFile configFile(configFileName);
    if (!configFile.open(QIODevice::ReadOnly))
    {
        qWarning("Couldn't open config file: %s",  configFileName.toStdString().c_str());
        return false;
    }
    QJsonDocument configData(QJsonDocument::fromJson(configFile.readAll()));
    QJsonObject configObj = configData.object();
    QJsonArray aircrafts = configObj["aircrafts"].toArray();

    for (auto parameter : aircrafts)
    {
        auto aircraft = std::make_shared<FgControlledAircraft>(parameter.toObject());
        m_OurAircrafts.insert(aircraft->callsign(), aircraft);
        connect(this, &FgController::fdmDataChanged, aircraft.get(), &FgControlledAircraft::onFdmDataChanged);
        emit ourAircraftConnected(aircraft.get());
    }

    m_Transport = (*m_OurAircrafts.begin())->transport();
    connect(m_Transport.get(), &FgTransport::fgDataReceived, this, &FgController::onDataReceived);

    return true;
}

void FgController::updateAircraft(const QString & /* aircraftId */)
{
}

void FgController::onDataReceived()
{
    updateOtherAircraftsCount();

    emit fdmDataChanged(m_Transport);

    //eleron
    //elevator

    if (m_OurAircrafts.isEmpty())
    {
        qDebug() << "Our aircraft is empty!";
        return;
    }

    auto aircraft = *m_OurAircrafts.begin();
    QString data = QString::number(aircraft->ailerons()) + '\t' + QString::number(aircraft->elevator()) + "\n";
    m_Transport->writeData(data);
}

void FgController::updateOtherAircraftsCount()
{
    qint32 count = m_Transport->getInt("/ai/models/num-players");

    if (m_AircraftsCount == count)
    {
        // assume that aircrafts remain the same
        return;
    }

    m_AircraftsCount = count;

    // get all aircrafts and add new ones to the list
    QList<QString> callsigns;
    for (int i = 0; i < count; ++i)
    {
        QString callsign = m_Transport->getString("/ai/models/multiplayer[" + QString::number(i) + "]/callsign");
        qDebug() << "callsign = " << callsign;
        callsigns.push_back(callsign);
        if (m_OtherAircrafts.contains(callsigns.back()))
        {
            continue;
        }

        auto aircraft = std::make_shared<FgAircraft>(callsign);
        aircraft->setConnected(true);
        //! @todo  aircraft->setIndex();
        m_OtherAircrafts[callsign] = aircraft;
        emit aircraftConnected(aircraft.get());
        qDebug() << "otherAircraftConnected";
    }

    // remove disconnected aircrafts from the list
    auto it = m_OtherAircrafts.begin();
    while (it != m_OtherAircrafts.end())
    {
        if (!callsigns.contains((*it)->callsign()))
        {
            emit aircraftDisconnected((*it).get());
            qDebug() << "aircraftDisconnected";

            it = m_OtherAircrafts.erase(it);
        }
        else
        {
            ++it;
        }
    }
}
<|endoftext|>


<commit_before>// Copyright 2012-2013 Samplecount S.L.
//
// 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.

#ifndef METHCLA_AUDIO_RESOURCE_HPP_INCLUDED
#define METHCLA_AUDIO_RESOURCE_HPP_INCLUDED

#include <boost/intrusive_ptr.hpp>
#include <boost/utility.hpp>
#include <stdexcept>
#include <vector>

namespace Methcla { namespace Audio
{
    class Environment;

    template<typename T>
    inline void intrusive_ptr_add_ref(T* expr)
    {
        expr->retain();
    }

    template<typename T>
    inline void intrusive_ptr_release(T* expr)
    {
        expr->release();
    }

    //* Reference counted base class
    class Reference : public boost::noncopyable
    {
    public:
        Reference()
            : m_refs(0)
        { }

        inline void retain()
        {
            m_refs++;
        }

        inline void release()
        {
            m_refs--;
            BOOST_ASSERT_MSG( m_refs >= 0 , "release() called once too many" );
            if (m_refs == 0)
                this->free();
        }

    protected:
        virtual ~Reference()
        { }

        virtual void free()
        {
            delete this;
        }

    private:
        int m_refs;
    };

    /// Resource base class.
    //
    // A resource has a reference to its environment and a unique id.
    template <typename Id> class Resource : public Reference
    {
    public:
        Resource(Environment& env, Id id)
            : m_env(env)
            , m_id(id)
        { }

        /// Access environment.
        const Environment& env() const { return m_env; }
        Environment& env() { return m_env; }

        /// Return unique id.
        Id id() const { return m_id; }

    private:
        Environment&    m_env;
        Id              m_id;
    };

    /// Simple map for holding pointers to resources.
    //
    // Also provides unique id allocation facility.
    template <typename Id, class T> class ResourceMap : boost::noncopyable
    {
    public:
        typedef boost::intrusive_ptr<T> Pointer;

        ResourceMap(size_t size)
            : m_elems(size, nullptr)
        { }

        size_t size() const
        {
            return m_elems.size();
        }

        bool contains(Id id) const
        {
            return m_elems[id] != nullptr;
        }

        Id nextId()
        {
            for (size_t i=0; i < m_elems.size(); i++) {
                if (m_elems[i] == nullptr) {
                    return static_cast<Id>(i);
                }
            }
            throw std::runtime_error("No free ids");
        }

        void insert(Id id, Pointer a)
        {
            if ((id >= Id(0)) && (id < Id(m_elems.size()))) {
                m_elems[id] = a;
            } else {
                throw std::out_of_range("Invalid resource id");
            }
        }

        void insert(Id id, T* a)
        {
            insert(id, Pointer(a));
        }

        void remove(Id id)
        {
            m_elems[id] = nullptr;
        }

        Pointer lookup(Id id) noexcept
        {
            if ((id >= Id(0)) && (id < Id(m_elems.size())))
                return m_elems[id];
            return nullptr;
        }

    private:
        std::vector<Pointer> m_elems;
    };
} }

#endif // METHCLA_AUDIO_RESOURCE_HPP_INCLUDED
<commit_msg>Declare Reference::retain/release noexcept and delete copy constructor<commit_after>// Copyright 2012-2013 Samplecount S.L.
//
// 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.

#ifndef METHCLA_AUDIO_RESOURCE_HPP_INCLUDED
#define METHCLA_AUDIO_RESOURCE_HPP_INCLUDED

#include <boost/intrusive_ptr.hpp>
#include <cassert>
#include <stdexcept>
#include <vector>

namespace Methcla { namespace Audio
{
    class Environment;

    template<typename T>
    inline void intrusive_ptr_add_ref(T* expr)
    {
        expr->retain();
    }

    template<typename T>
    inline void intrusive_ptr_release(T* expr)
    {
        expr->release();
    }

    //* Reference counted base class
    class Reference
    {
    public:
        Reference()
            : m_refs(0)
        { }
        Reference(const Reference&) = delete;

        inline void retain() noexcept
        {
            m_refs++;
        }

        inline void release() noexcept
        {
            m_refs--;
            assert(m_refs >= 0);
            if (m_refs == 0)
                this->free();
        }

    protected:
        virtual ~Reference()
        { }

        virtual void free()
        {
            delete this;
        }

    private:
        int m_refs;
    };

    /// Resource base class.
    //
    // A resource has a reference to its environment and a unique id.
    template <typename Id> class Resource : public Reference
    {
    public:
        Resource(Environment& env, Id id)
            : m_env(env)
            , m_id(id)
        { }

        /// Access environment.
        const Environment& env() const { return m_env; }
        Environment& env() { return m_env; }

        /// Return unique id.
        Id id() const { return m_id; }

    private:
        Environment&    m_env;
        Id              m_id;
    };

    /// Simple map for holding pointers to resources.
    //
    // Also provides unique id allocation facility.
    template <typename Id, class T> class ResourceMap
    {
    public:
        typedef boost::intrusive_ptr<T> Pointer;

        ResourceMap(size_t size)
            : m_elems(size, nullptr)
        { }
        ResourceMap(const ResourceMap&) = delete;

        size_t size() const
        {
            return m_elems.size();
        }

        bool contains(Id id) const
        {
            return m_elems[id] != nullptr;
        }

        Id nextId()
        {
            for (size_t i=0; i < m_elems.size(); i++) {
                if (m_elems[i] == nullptr) {
                    return static_cast<Id>(i);
                }
            }
            throw std::runtime_error("No free ids");
        }

        void insert(Id id, Pointer a)
        {
            if ((id >= Id(0)) && (id < Id(m_elems.size()))) {
                m_elems[id] = a;
            } else {
                throw std::out_of_range("Invalid resource id");
            }
        }

        void insert(Id id, T* a)
        {
            insert(id, Pointer(a));
        }

        void remove(Id id)
        {
            m_elems[id] = nullptr;
        }

        Pointer lookup(Id id) noexcept
        {
            if ((id >= Id(0)) && (id < Id(m_elems.size())))
                return m_elems[id];
            return nullptr;
        }

    private:
        std::vector<Pointer> m_elems;
    };
} }

#endif // METHCLA_AUDIO_RESOURCE_HPP_INCLUDED
<|endoftext|>


<commit_before>#include <wx/wx.h>
#include <wx/stc/stc.h>

class MyApp: public wxApp
{
public:
virtual bool OnInit();
};

enum
{
  MARGIN_LINE_NUMBERS,
  MARGIN_FOLD
};

class MyFrame: public wxFrame
{
public:
	MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size);

private:
	void OnHello(wxCommandEvent& event);
	void OnExit(wxCommandEvent& event);
	void OnAbout(wxCommandEvent& event);

  void OnMarginClick(wxStyledTextEvent& event);
	wxDECLARE_EVENT_TABLE();

private:
  void setupEdit();
  wxStyledTextCtrl* text;
};

enum
{
	ID_Hello = 1
};

//{ wx widget macros
wxBEGIN_EVENT_TABLE(MyFrame, wxFrame)
	EVT_MENU(ID_Hello, MyFrame::OnHello)
	EVT_MENU(wxID_EXIT, MyFrame::OnExit)
	EVT_MENU(wxID_ABOUT, MyFrame::OnAbout)
wxEND_EVENT_TABLE()

wxIMPLEMENT_APP(MyApp);
//}

bool MyApp::OnInit()
{
	MyFrame *frame = new MyFrame("Pegasus - Rust IDE", wxPoint(50, 50), wxSize(450, 340) );
	frame->Show( true );
	return true;
}

MyFrame::MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size)
	: wxFrame(NULL, wxID_ANY, title, pos, size)
{
	wxMenu *menuFile = new wxMenu;
	menuFile->Append(ID_Hello, "&Hello...\tCtrl-H", "Help string shown in status bar for this menu item");
	menuFile->AppendSeparator();
	menuFile->Append(wxID_EXIT);
	wxMenu *menuHelp = new wxMenu;
	menuHelp->Append(wxID_ABOUT);
	wxMenuBar *menuBar = new wxMenuBar;
	menuBar->Append( menuFile, "&File" );
	menuBar->Append( menuHelp, "&Help" );
	SetMenuBar( menuBar );
	CreateStatusBar();
	SetStatusText("");

  setupEdit();
}

void MyFrame::setupEdit() {
  text = new wxStyledTextCtrl(this, wxID_ANY);

  text->StyleClearAll();
  text->SetLexer(wxSTC_LEX_CPP);

  text->SetMarginWidth(MARGIN_LINE_NUMBERS, 50);
  text->StyleSetForeground(wxSTC_STYLE_LINENUMBER, wxColour(75, 75, 75));
  text->StyleSetBackground(wxSTC_STYLE_LINENUMBER, wxColour(220, 220, 220));
  text->SetMarginType(MARGIN_LINE_NUMBERS, wxSTC_MARGIN_NUMBER);

  // ---- Enable code folding
  text->SetMarginType(MARGIN_FOLD, wxSTC_MARGIN_SYMBOL);
  text->SetMarginWidth(MARGIN_FOLD, 15);
  text->SetMarginMask(MARGIN_FOLD, wxSTC_MASK_FOLDERS);
  text->StyleSetBackground(MARGIN_FOLD, wxColor(200, 200, 200));
  text->SetMarginSensitive(MARGIN_FOLD, true);

  // Properties found from http://www.scintilla.org/SciTEDoc.html
  text->SetProperty(wxT("fold"), wxT("1"));
  text->SetProperty(wxT("fold.comment"), wxT("1"));
  text->SetProperty(wxT("fold.compact"), wxT("1"));

  wxColor grey(100, 100, 100);
  text->MarkerDefine(wxSTC_MARKNUM_FOLDER, wxSTC_MARK_ARROW);
  text->MarkerSetForeground(wxSTC_MARKNUM_FOLDER, grey);
  text->MarkerSetBackground(wxSTC_MARKNUM_FOLDER, grey);

  text->MarkerDefine(wxSTC_MARKNUM_FOLDEROPEN, wxSTC_MARK_ARROWDOWN);
  text->MarkerSetForeground(wxSTC_MARKNUM_FOLDEROPEN, grey);
  text->MarkerSetBackground(wxSTC_MARKNUM_FOLDEROPEN, grey);

  text->MarkerDefine(wxSTC_MARKNUM_FOLDERSUB, wxSTC_MARK_EMPTY);
  text->MarkerSetForeground(wxSTC_MARKNUM_FOLDERSUB, grey);
  text->MarkerSetBackground(wxSTC_MARKNUM_FOLDERSUB, grey);

  text->MarkerDefine(wxSTC_MARKNUM_FOLDEREND, wxSTC_MARK_ARROW);
  text->MarkerSetForeground(wxSTC_MARKNUM_FOLDEREND, grey);
  text->MarkerSetBackground(wxSTC_MARKNUM_FOLDEREND, _T("WHITE"));

  text->MarkerDefine(wxSTC_MARKNUM_FOLDEROPENMID, wxSTC_MARK_ARROWDOWN);
  text->MarkerSetForeground(wxSTC_MARKNUM_FOLDEROPENMID, grey);
  text->MarkerSetBackground(wxSTC_MARKNUM_FOLDEROPENMID, _T("WHITE"));

  text->MarkerDefine(wxSTC_MARKNUM_FOLDERMIDTAIL, wxSTC_MARK_EMPTY);
  text->MarkerSetForeground(wxSTC_MARKNUM_FOLDERMIDTAIL, grey);
  text->MarkerSetBackground(wxSTC_MARKNUM_FOLDERMIDTAIL, grey);

  text->MarkerDefine(wxSTC_MARKNUM_FOLDERTAIL, wxSTC_MARK_EMPTY);
  text->MarkerSetForeground(wxSTC_MARKNUM_FOLDERTAIL, grey);
  text->MarkerSetBackground(wxSTC_MARKNUM_FOLDERTAIL, grey);
  // ---- End of code folding part

  text->SetWrapMode(wxSTC_WRAP_WORD); // other choice is wxSCI_WRAP_NONE

  // text->SetText(source);

  /*
  text->StyleSetForeground(wxSTC_C_STRING, wxColour(150, 0, 0));
  text->StyleSetForeground(wxSTC_C_PREPROCESSOR, wxColour(165, 105, 0));
  text->StyleSetForeground(wxSTC_C_IDENTIFIER, wxColour(40, 0, 60));
  text->StyleSetForeground(wxSTC_C_NUMBER, wxColour(0, 150, 0));
  text->StyleSetForeground(wxSTC_C_CHARACTER, wxColour(150, 0, 0));
  text->StyleSetForeground(wxSTC_C_WORD, wxColour(0, 0, 150));
  text->StyleSetForeground(wxSTC_C_WORD2, wxColour(0, 150, 0));
  text->StyleSetForeground(wxSTC_C_COMMENT, wxColour(150, 150, 150));
  text->StyleSetForeground(wxSTC_C_COMMENTLINE, wxColour(150, 150, 150));
  text->StyleSetForeground(wxSTC_C_COMMENTDOC, wxColour(150, 150, 150));
  text->StyleSetForeground(wxSTC_C_COMMENTDOCKEYWORD, wxColour(0, 0, 200));
  text->StyleSetForeground(wxSTC_C_COMMENTDOCKEYWORDERROR, wxColour(0, 0, 200));
  text->StyleSetBold(wxSTC_C_WORD, true);
  text->StyleSetBold(wxSTC_C_WORD2, true);
  text->StyleSetBold(wxSTC_C_COMMENTDOCKEYWORD, true);
  */

  // a sample list of keywords, I haven't included them all to keep it short...
  text->SetKeyWords(0, wxT("return for while break continue"));
  text->SetKeyWords(1, wxT("const int float void char double"));

  wxBoxSizer* sizer = new wxBoxSizer(wxVERTICAL);
  sizer->Add(text, 1, wxEXPAND);
  SetSizer(sizer);

  text->Connect(wxEVT_STC_MARGINCLICK, wxStyledTextEventHandler(MyFrame::OnMarginClick), NULL, this);
}

/** Event callback when a margin is clicked, used here for code folding */
void MyFrame::OnMarginClick(wxStyledTextEvent& event)
{
  if (event.GetMargin() == MARGIN_FOLD)
  {
    int lineClick = text->LineFromPosition(event.GetPosition());
    int levelClick = text->GetFoldLevel(lineClick);

    if ((levelClick & wxSTC_FOLDLEVELHEADERFLAG) > 0)
    {
      text->ToggleFold(lineClick);
    }
  }
}

void MyFrame::OnExit(wxCommandEvent& event)
{
	Close( true );
}

void MyFrame::OnAbout(wxCommandEvent& event)
{
	wxMessageBox( "This is a wxWidgets' Hello world sample", "About Hello World", wxOK | wxICON_INFORMATION );
}

void MyFrame::OnHello(wxCommandEvent& event)
{
	wxLogMessage("Hello world from wxWidgets!");
}
<commit_msg>updated sample<commit_after>#include <wx/wx.h>
#include <wx/stc/stc.h>

class MyApp: public wxApp
{
public:
  virtual bool OnInit();
};

enum
{
  MARGIN_LINE_NUMBERS,
  MARGIN_FOLD
};

class MyFrame: public wxFrame
{
public:
	MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size);

private:
	void OnHello(wxCommandEvent& event);
	void OnExit(wxCommandEvent& event);
	void OnAbout(wxCommandEvent& event);

  void OnMarginClick(wxStyledTextEvent& event);
	wxDECLARE_EVENT_TABLE();

private:
  void setupEdit();
  wxStyledTextCtrl* text;
};

enum
{
	ID_Hello = 1
};

//{ wx widget macros
wxBEGIN_EVENT_TABLE(MyFrame, wxFrame)
	EVT_MENU(ID_Hello, MyFrame::OnHello)
	EVT_MENU(wxID_EXIT, MyFrame::OnExit)
	EVT_MENU(wxID_ABOUT, MyFrame::OnAbout)
wxEND_EVENT_TABLE()

wxIMPLEMENT_APP(MyApp);
//}

bool MyApp::OnInit()
{
	MyFrame *frame = new MyFrame("Pegasus - Rust IDE", wxPoint(50, 50), wxSize(450, 340) );
	frame->Show( true );
	return true;
}

MyFrame::MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size)
	: wxFrame(NULL, wxID_ANY, title, pos, size)
{
	wxMenu *menuFile = new wxMenu;
	menuFile->Append(ID_Hello, "&Hello...\tCtrl-H", "Help string shown in status bar for this menu item");
	menuFile->AppendSeparator();
	menuFile->Append(wxID_EXIT);
	wxMenu *menuHelp = new wxMenu;
	menuHelp->Append(wxID_ABOUT);
	wxMenuBar *menuBar = new wxMenuBar;
	menuBar->Append( menuFile, "&File" );
	menuBar->Append( menuHelp, "&Help" );
	SetMenuBar( menuBar );
	CreateStatusBar();
	SetStatusText("");

  setupEdit();
}

void MyFrame::setupEdit() {
  text = new wxStyledTextCtrl(this, wxID_ANY);

  text->StyleClearAll();
  text->SetLexer(wxSTC_LEX_CPP);

  text->SetMarginWidth(MARGIN_LINE_NUMBERS, 50);
  text->StyleSetForeground(wxSTC_STYLE_LINENUMBER, wxColour(75, 75, 75));
  text->StyleSetBackground(wxSTC_STYLE_LINENUMBER, wxColour(220, 220, 220));
  text->SetMarginType(MARGIN_LINE_NUMBERS, wxSTC_MARGIN_NUMBER);

  // ---- Enable code folding
  text->SetMarginType(MARGIN_FOLD, wxSTC_MARGIN_SYMBOL);
  text->SetMarginWidth(MARGIN_FOLD, 15);
  text->SetMarginMask(MARGIN_FOLD, wxSTC_MASK_FOLDERS);
  text->StyleSetBackground(MARGIN_FOLD, wxColor(200, 200, 200));
  text->SetMarginSensitive(MARGIN_FOLD, true);

  // Properties found from http://www.scintilla.org/SciTEDoc.html
  text->SetProperty(wxT("fold"), wxT("1"));
  text->SetProperty(wxT("fold.comment"), wxT("1"));
  text->SetProperty(wxT("fold.compact"), wxT("1"));

  wxColor grey(100, 100, 100);
  text->MarkerDefine(wxSTC_MARKNUM_FOLDER, wxSTC_MARK_ARROW);
  text->MarkerSetForeground(wxSTC_MARKNUM_FOLDER, grey);
  text->MarkerSetBackground(wxSTC_MARKNUM_FOLDER, grey);

  text->MarkerDefine(wxSTC_MARKNUM_FOLDEROPEN, wxSTC_MARK_ARROWDOWN);
  text->MarkerSetForeground(wxSTC_MARKNUM_FOLDEROPEN, grey);
  text->MarkerSetBackground(wxSTC_MARKNUM_FOLDEROPEN, grey);

  text->MarkerDefine(wxSTC_MARKNUM_FOLDERSUB, wxSTC_MARK_EMPTY);
  text->MarkerSetForeground(wxSTC_MARKNUM_FOLDERSUB, grey);
  text->MarkerSetBackground(wxSTC_MARKNUM_FOLDERSUB, grey);

  text->MarkerDefine(wxSTC_MARKNUM_FOLDEREND, wxSTC_MARK_ARROW);
  text->MarkerSetForeground(wxSTC_MARKNUM_FOLDEREND, grey);
  text->MarkerSetBackground(wxSTC_MARKNUM_FOLDEREND, _T("WHITE"));

  text->MarkerDefine(wxSTC_MARKNUM_FOLDEROPENMID, wxSTC_MARK_ARROWDOWN);
  text->MarkerSetForeground(wxSTC_MARKNUM_FOLDEROPENMID, grey);
  text->MarkerSetBackground(wxSTC_MARKNUM_FOLDEROPENMID, _T("WHITE"));

  text->MarkerDefine(wxSTC_MARKNUM_FOLDERMIDTAIL, wxSTC_MARK_EMPTY);
  text->MarkerSetForeground(wxSTC_MARKNUM_FOLDERMIDTAIL, grey);
  text->MarkerSetBackground(wxSTC_MARKNUM_FOLDERMIDTAIL, grey);

  text->MarkerDefine(wxSTC_MARKNUM_FOLDERTAIL, wxSTC_MARK_EMPTY);
  text->MarkerSetForeground(wxSTC_MARKNUM_FOLDERTAIL, grey);
  text->MarkerSetBackground(wxSTC_MARKNUM_FOLDERTAIL, grey);
  // ---- End of code folding part

  text->SetWrapMode(wxSTC_WRAP_WORD); // other choice is wxSCI_WRAP_NONE

  // text->SetText(source);

  /*
  text->StyleSetForeground(wxSTC_C_STRING, wxColour(150, 0, 0));
  text->StyleSetForeground(wxSTC_C_PREPROCESSOR, wxColour(165, 105, 0));
  text->StyleSetForeground(wxSTC_C_IDENTIFIER, wxColour(40, 0, 60));
  text->StyleSetForeground(wxSTC_C_NUMBER, wxColour(0, 150, 0));
  text->StyleSetForeground(wxSTC_C_CHARACTER, wxColour(150, 0, 0));
  text->StyleSetForeground(wxSTC_C_WORD, wxColour(0, 0, 150));
  text->StyleSetForeground(wxSTC_C_WORD2, wxColour(0, 150, 0));
  text->StyleSetForeground(wxSTC_C_COMMENT, wxColour(150, 150, 150));
  text->StyleSetForeground(wxSTC_C_COMMENTLINE, wxColour(150, 150, 150));
  text->StyleSetForeground(wxSTC_C_COMMENTDOC, wxColour(150, 150, 150));
  text->StyleSetForeground(wxSTC_C_COMMENTDOCKEYWORD, wxColour(0, 0, 200));
  text->StyleSetForeground(wxSTC_C_COMMENTDOCKEYWORDERROR, wxColour(0, 0, 200));
  text->StyleSetBold(wxSTC_C_WORD, true);
  text->StyleSetBold(wxSTC_C_WORD2, true);
  text->StyleSetBold(wxSTC_C_COMMENTDOCKEYWORD, true);
  */

  // a sample list of keywords, I haven't included them all to keep it short...
  text->SetKeyWords(0, wxT("return for while break continue"));
  text->SetKeyWords(1, wxT("const int float void char double"));

  wxBoxSizer* sizer = new wxBoxSizer(wxVERTICAL);
  sizer->Add(text, 1, wxEXPAND);
  SetSizer(sizer);

  text->Connect(wxEVT_STC_MARGINCLICK, wxStyledTextEventHandler(MyFrame::OnMarginClick), NULL, this);
}

/** Event callback when a margin is clicked, used here for code folding */
void MyFrame::OnMarginClick(wxStyledTextEvent& event)
{
  if (event.GetMargin() == MARGIN_FOLD)
  {
    int lineClick = text->LineFromPosition(event.GetPosition());
    int levelClick = text->GetFoldLevel(lineClick);

    if ((levelClick & wxSTC_FOLDLEVELHEADERFLAG) > 0)
    {
      text->ToggleFold(lineClick);
    }
  }
}

void MyFrame::OnExit(wxCommandEvent& event)
{
	Close( true );
}

void MyFrame::OnAbout(wxCommandEvent& event)
{
	wxMessageBox( "This is a wxWidgets' Hello world sample", "About Hello World", wxOK | wxICON_INFORMATION );
}

void MyFrame::OnHello(wxCommandEvent& event)
{
	wxLogMessage("Hello world from wxWidgets!");
}
<|endoftext|>