<commit_before>/*******************************
Copyright (c) 2016-2017 Grégoire Angerand

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 "YaveApp.h"

#include <yave/image/ImageData.h>
#include <yave/buffer/TypedBuffer.h>

#include <y/io/File.h>

#include <iostream>

void wat(int) {}

namespace yave {

YaveApp::YaveApp(DebugParams params) : instance(params), device(instance), command_pool(&device), mesh_pool(&device) {
	log_msg("sizeof(StaticMesh) = "_s + sizeof(StaticMesh));
	log_msg("sizeof(Matrix4) = "_s + sizeof(math::Matrix4<>));
}

YaveApp::~YaveApp() {
	delete pipeline;

	delete scene_view;
	delete scene;

	material = nullptr;
	mesh_texture = Texture();

	delete swapchain;
}

vk::Extent2D extent(const math::Vec2ui& v) {
	return vk::Extent2D{v.x(), v.y()};
}

void YaveApp::create_command_buffers() {
	/*for(const auto& img : swapchain->images()) {
		CmdBufferRecorder<CmdBufferUsage::Normal> recorder(command_pool.create_buffer());

		renderer->draw(recorder, img);

		command_buffers << recorder.end();
	}*/
}

core::Duration YaveApp::draw() {
	core::Chrono ch;

	auto vk_swap = swapchain->vk_swapchain();
	auto image_acquired_semaphore = device.vk_device().createSemaphore(vk::SemaphoreCreateInfo());
	auto render_finished_semaphore = device.vk_device().createSemaphore(vk::SemaphoreCreateInfo());
	vk::PipelineStageFlags pipe_stage_flags = vk::PipelineStageFlagBits::eBottomOfPipe;
	auto graphic_queue = device.vk_queue(QueueFamily::Graphics);

	FrameToken frame = std::move(swapchain->next_frame(image_acquired_semaphore));

	//renderer->update();
	auto cmd_buffer =  CmdBufferRecorder<>(command_pool.create_buffer());
	pipeline->process(frame, cmd_buffer);
	{

		auto buffer = cmd_buffer.end().vk_cmd_buffer();
		auto submit_info = vk::SubmitInfo()
				.setWaitSemaphoreCount(0)
				.setPWaitDstStageMask(&pipe_stage_flags)
				.setCommandBufferCount(1)
				.setPCommandBuffers(&buffer)
				.setSignalSemaphoreCount(1)
				.setPSignalSemaphores(&render_finished_semaphore);

		graphic_queue.submit(1, &submit_info, VK_NULL_HANDLE);

		graphic_queue.presentKHR(vk::PresentInfoKHR()
				.setSwapchainCount(1)
				.setPSwapchains(&vk_swap)
				.setPImageIndices(&frame.image_index)
				.setWaitSemaphoreCount(1)
				.setPWaitSemaphores(&render_finished_semaphore)
			);

	}
	graphic_queue.waitIdle();

	device.vk_device().destroySemaphore(image_acquired_semaphore);
	device.vk_device().destroySemaphore(render_finished_semaphore);

	if(command_pool.active_buffers() > 1) {
		fatal("Unable to collect command buffers.");
	}

	return ch.elapsed();
}

void YaveApp::update(math::Vec2 angles) {
	auto cam_pos =
			(math::rotation(angles.x(), math::Vec3(0, 0, -1)) *
			math::rotation(angles.y(), math::Vec3(0, 1, 0))) * math::Vec4(2.2, 0, 0, 1);

	camera.set_view(math::look_at(cam_pos.sub(3) / cam_pos.w(), math::Vec3()));
}

void YaveApp::create_assets() {
	{
		{
			auto file = std::move(io::File::open("../tools/image_to_yt/chalet.jpg.yt").expected("Unable to load texture file."));
			auto image = ImageData::from_file(file);
			log_msg(core::String() + (image.size().x() * image.size().y()) + " pixels loaded");
			mesh_texture = Texture(&device, image);
		}
		material = asset_ptr(Material(&device, MaterialData()
				.set_frag_data(SpirVData::from_file(io::File::open("basic.frag.spv").expected("Unable to load spirv file")))
				.set_vert_data(SpirVData::from_file(io::File::open("basic.vert.spv").expected("Unable to load spirv file")))
				.set_bindings({Binding(TextureView(mesh_texture))})
			));
	}

	core::Vector<const char*> meshes = {"../tools/obj_to_ym/chalet.obj.ym"};
	core::Vector<StaticMesh> objects;
	for(auto name : meshes) {
		auto m_data = MeshData::from_file(io::File::open(name).expected("Unable to load mesh file"));
		log_msg(core::str() + m_data.triangles.size() + " triangles loaded");
		auto mesh = AssetPtr<StaticMeshInstance>(mesh_pool.create_static_mesh(/*new StaticMeshInstance(&device,*/ m_data));
		for(usize i = 0; i != 30; i++) {
			auto m = StaticMesh(mesh, material);
			m.set_position(math::Vec3(objects.size() * (objects.size() % 2 ? -4.0f : 4.0f), 0, 0));

			objects << std::move(m);
		}
	}
	scene = new Scene(std::move(objects));
	scene_view = new SceneView(*scene, camera);

	update();

	{
		auto culling = core::Rc<CullingNode>(new CullingNode(*scene_view));
		auto gbuffer = core::Rc<GBufferRenderer>(new GBufferRenderer(&device, swapchain->size(), culling));
		auto deferred = core::Rc<DeferredRenderer>(new DeferredRenderer(gbuffer));

		pipeline = new Pipeline(deferred);
	}

	//renderer = new DeferredRenderer(*scene_view, swapchain->size());

}

}

<commit_msg>Fixed Rc construction.<commit_after>/*******************************
Copyright (c) 2016-2017 Grégoire Angerand

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 "YaveApp.h"

#include <yave/image/ImageData.h>
#include <yave/buffer/TypedBuffer.h>

#include <y/io/File.h>

#include <iostream>

void wat(int) {}

namespace yave {

YaveApp::YaveApp(DebugParams params) : instance(params), device(instance), command_pool(&device), mesh_pool(&device) {
	log_msg("sizeof(StaticMesh) = "_s + sizeof(StaticMesh));
	log_msg("sizeof(Matrix4) = "_s + sizeof(math::Matrix4<>));
}

YaveApp::~YaveApp() {
	delete pipeline;

	delete scene_view;
	delete scene;

	material = nullptr;
	mesh_texture = Texture();

	delete swapchain;
}

vk::Extent2D extent(const math::Vec2ui& v) {
	return vk::Extent2D{v.x(), v.y()};
}

void YaveApp::create_command_buffers() {
	/*for(const auto& img : swapchain->images()) {
		CmdBufferRecorder<CmdBufferUsage::Normal> recorder(command_pool.create_buffer());

		renderer->draw(recorder, img);

		command_buffers << recorder.end();
	}*/
}

core::Duration YaveApp::draw() {
	core::Chrono ch;

	auto vk_swap = swapchain->vk_swapchain();
	auto image_acquired_semaphore = device.vk_device().createSemaphore(vk::SemaphoreCreateInfo());
	auto render_finished_semaphore = device.vk_device().createSemaphore(vk::SemaphoreCreateInfo());
	vk::PipelineStageFlags pipe_stage_flags = vk::PipelineStageFlagBits::eBottomOfPipe;
	auto graphic_queue = device.vk_queue(QueueFamily::Graphics);

	FrameToken frame = std::move(swapchain->next_frame(image_acquired_semaphore));

	//renderer->update();
	auto cmd_buffer =  CmdBufferRecorder<>(command_pool.create_buffer());
	pipeline->process(frame, cmd_buffer);
	{

		auto buffer = cmd_buffer.end().vk_cmd_buffer();
		auto submit_info = vk::SubmitInfo()
				.setWaitSemaphoreCount(0)
				.setPWaitDstStageMask(&pipe_stage_flags)
				.setCommandBufferCount(1)
				.setPCommandBuffers(&buffer)
				.setSignalSemaphoreCount(1)
				.setPSignalSemaphores(&render_finished_semaphore);

		graphic_queue.submit(1, &submit_info, VK_NULL_HANDLE);

		graphic_queue.presentKHR(vk::PresentInfoKHR()
				.setSwapchainCount(1)
				.setPSwapchains(&vk_swap)
				.setPImageIndices(&frame.image_index)
				.setWaitSemaphoreCount(1)
				.setPWaitSemaphores(&render_finished_semaphore)
			);

	}
	graphic_queue.waitIdle();

	device.vk_device().destroySemaphore(image_acquired_semaphore);
	device.vk_device().destroySemaphore(render_finished_semaphore);

	if(command_pool.active_buffers() > 1) {
		fatal("Unable to collect command buffers.");
	}

	return ch.elapsed();
}

void YaveApp::update(math::Vec2 angles) {
	auto cam_pos =
			(math::rotation(angles.x(), math::Vec3(0, 0, -1)) *
			math::rotation(angles.y(), math::Vec3(0, 1, 0))) * math::Vec4(2.2, 0, 0, 1);

	camera.set_view(math::look_at(cam_pos.sub(3) / cam_pos.w(), math::Vec3()));
}

void YaveApp::create_assets() {
	{
		{
			auto file = std::move(io::File::open("../tools/image_to_yt/chalet.jpg.yt").expected("Unable to load texture file."));
			auto image = ImageData::from_file(file);
			log_msg(core::String() + (image.size().x() * image.size().y()) + " pixels loaded");
			mesh_texture = Texture(&device, image);
		}
		material = asset_ptr(Material(&device, MaterialData()
				.set_frag_data(SpirVData::from_file(io::File::open("basic.frag.spv").expected("Unable to load spirv file")))
				.set_vert_data(SpirVData::from_file(io::File::open("basic.vert.spv").expected("Unable to load spirv file")))
				.set_bindings({Binding(TextureView(mesh_texture))})
			));
	}

	core::Vector<const char*> meshes = {"../tools/obj_to_ym/chalet.obj.ym"};
	core::Vector<StaticMesh> objects;
	for(auto name : meshes) {
		auto m_data = MeshData::from_file(io::File::open(name).expected("Unable to load mesh file"));
		log_msg(core::str() + m_data.triangles.size() + " triangles loaded");
		auto mesh = AssetPtr<StaticMeshInstance>(mesh_pool.create_static_mesh(/*new StaticMeshInstance(&device,*/ m_data));
		for(usize i = 0; i != 30; i++) {
			auto m = StaticMesh(mesh, material);
			m.set_position(math::Vec3(objects.size() * (objects.size() % 2 ? -4.0f : 4.0f), 0, 0));

			objects << std::move(m);
		}
	}
	scene = new Scene(std::move(objects));
	scene_view = new SceneView(*scene, camera);

	update();

	{
		auto culling = core::Rc<CullingNode>(new CullingNode(*scene_view));
		auto gbuffer = core::Rc<GBufferRenderer>(new GBufferRenderer(&device, swapchain->size(), culling));
		auto deferred = core::Rc<Node>(new DeferredRenderer(gbuffer));

		pipeline = new Pipeline(deferred);
	}

	//renderer = new DeferredRenderer(*scene_view, swapchain->size());

}

}

<|endoftext|>


<commit_before>// Copyright (c) 2013 Intel Corporation. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "xwalk/application/browser/application_system.h"

#include <string>
#include "base/command_line.h"
#include "base/file_util.h"
#include "net/base/net_util.h"
#include "xwalk/application/browser/application_process_manager.h"
#include "xwalk/application/browser/application_service.h"
#include "xwalk/runtime/browser/runtime_context.h"
#include "xwalk/runtime/common/xwalk_switches.h"

using xwalk::RuntimeContext;

namespace xwalk {
namespace application {

ApplicationSystem::ApplicationSystem(RuntimeContext* runtime_context) {
  runtime_context_ = runtime_context;
  process_manager_.reset(new ApplicationProcessManager(runtime_context));
  application_service_.reset(new ApplicationService(runtime_context));
}

ApplicationSystem::~ApplicationSystem() {
}

bool ApplicationSystem::HandleApplicationManagementCommands(
    const CommandLine& cmd_line, const GURL& url) {
  if (cmd_line.HasSwitch(switches::kListApplications)) {
    ApplicationStore::ApplicationMap* apps =
        application_service_->GetInstalledApplications();
    LOG(INFO) << "Application ID                       Application Name";
    LOG(INFO) << "-----------------------------------------------------";
    ApplicationStore::ApplicationMapIterator it;
    for (it = apps->begin(); it != apps->end(); ++it)
      LOG(INFO) << it->first << "     " << it->second->Name();
    LOG(INFO) << "-----------------------------------------------------";
    return true;
  }

  if (cmd_line.HasSwitch(switches::kUninstall)) {
    const CommandLine::StringVector& args = cmd_line.GetArgs();
    if (args.empty())
      return false;

    std::string app_id = std::string(args[0].begin(), args[0].end());
    if (!Application::IsIDValid(app_id))
      return false;

    if (application_service_->Uninstall(app_id)) {
      LOG(INFO) << "[OK] Application uninstalled successfully: " << app_id;
    } else {
      LOG(ERROR) << "[ERR] An error occurred when uninstalling application "
                 << app_id;
    }
    return true;
  }

  if (cmd_line.HasSwitch(switches::kInstall)) {
    base::FilePath path;
    if (!net::FileURLToFilePath(url, &path))
      return false;

    if (!base::PathExists(path))
      return false;

    std::string app_id;
    if (application_service_->Install(path, &app_id))
      LOG(INFO) << "[OK] Application installed: " << app_id;
    else
      LOG(ERROR) << "[ERR] Application install failure: " << path.value();
    return true;
  }

  return false;
}

bool ApplicationSystem::LaunchFromCommandLine(
    const CommandLine& cmd_line, const GURL& url,
    bool* run_default_message_loop) {
  // On Tizen, applications are launched by a symbolic link named like the
  // application ID.
  // FIXME(cmarcelo): Remove when we move to a separate launcher on Tizen.
#if defined(OS_TIZEN_MOBILE)
  std::string command_name = cmd_line.GetProgram().BaseName().MaybeAsASCII();
  if (Application::IsIDValid(command_name)) {
    *run_default_message_loop = application_service_->Launch(command_name);
    return true;
  }
#endif

  if (!url.SchemeIsFile())
    return false;

  // Handles raw app_id passed as first non-switch argument.
  const CommandLine::StringVector& args = cmd_line.GetArgs();
  if (!args.empty()) {
    std::string app_id = std::string(args[0].begin(), args[0].end());
    *run_default_message_loop = application_service_->Launch(app_id);
    return true;
  }

  // Handles local directory.
  base::FilePath path;
  if (net::FileURLToFilePath(url, &path) && base::DirectoryExists(path)) {
    *run_default_message_loop = application_service_->Launch(path);
    return true;
  }

  return false;
}

}  // namespace application
}  // namespace xwalk
<commit_msg>[Application] Fix loading local files<commit_after>// Copyright (c) 2013 Intel Corporation. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "xwalk/application/browser/application_system.h"

#include <string>
#include "base/command_line.h"
#include "base/file_util.h"
#include "net/base/net_util.h"
#include "xwalk/application/browser/application_process_manager.h"
#include "xwalk/application/browser/application_service.h"
#include "xwalk/runtime/browser/runtime_context.h"
#include "xwalk/runtime/common/xwalk_switches.h"

using xwalk::RuntimeContext;

namespace xwalk {
namespace application {

ApplicationSystem::ApplicationSystem(RuntimeContext* runtime_context) {
  runtime_context_ = runtime_context;
  process_manager_.reset(new ApplicationProcessManager(runtime_context));
  application_service_.reset(new ApplicationService(runtime_context));
}

ApplicationSystem::~ApplicationSystem() {
}

bool ApplicationSystem::HandleApplicationManagementCommands(
    const CommandLine& cmd_line, const GURL& url) {
  if (cmd_line.HasSwitch(switches::kListApplications)) {
    ApplicationStore::ApplicationMap* apps =
        application_service_->GetInstalledApplications();
    LOG(INFO) << "Application ID                       Application Name";
    LOG(INFO) << "-----------------------------------------------------";
    ApplicationStore::ApplicationMapIterator it;
    for (it = apps->begin(); it != apps->end(); ++it)
      LOG(INFO) << it->first << "     " << it->second->Name();
    LOG(INFO) << "-----------------------------------------------------";
    return true;
  }

  if (cmd_line.HasSwitch(switches::kUninstall)) {
    const CommandLine::StringVector& args = cmd_line.GetArgs();
    if (args.empty())
      return false;

    std::string app_id = std::string(args[0].begin(), args[0].end());
    if (!Application::IsIDValid(app_id))
      return false;

    if (application_service_->Uninstall(app_id)) {
      LOG(INFO) << "[OK] Application uninstalled successfully: " << app_id;
    } else {
      LOG(ERROR) << "[ERR] An error occurred when uninstalling application "
                 << app_id;
    }
    return true;
  }

  if (cmd_line.HasSwitch(switches::kInstall)) {
    base::FilePath path;
    if (!net::FileURLToFilePath(url, &path))
      return false;

    if (!base::PathExists(path))
      return false;

    std::string app_id;
    if (application_service_->Install(path, &app_id))
      LOG(INFO) << "[OK] Application installed: " << app_id;
    else
      LOG(ERROR) << "[ERR] Application install failure: " << path.value();
    return true;
  }

  return false;
}

bool ApplicationSystem::LaunchFromCommandLine(
    const CommandLine& cmd_line, const GURL& url,
    bool* run_default_message_loop) {
  // On Tizen, applications are launched by a symbolic link named like the
  // application ID.
  // FIXME(cmarcelo): Remove when we move to a separate launcher on Tizen.
#if defined(OS_TIZEN_MOBILE)
  std::string command_name = cmd_line.GetProgram().BaseName().MaybeAsASCII();
  if (Application::IsIDValid(command_name)) {
    *run_default_message_loop = application_service_->Launch(command_name);
    return true;
  }
#endif

  if (!url.SchemeIsFile())
    return false;

  // Handles raw app_id passed as first non-switch argument.
  const CommandLine::StringVector& args = cmd_line.GetArgs();
  if (!args.empty()) {
    std::string app_id = std::string(args[0].begin(), args[0].end());
    if (Application::IsIDValid(app_id)) {
        *run_default_message_loop = application_service_->Launch(app_id);
        return true;
    }
  }

  // Handles local directory.
  base::FilePath path;
  if (net::FileURLToFilePath(url, &path) && base::DirectoryExists(path)) {
    *run_default_message_loop = application_service_->Launch(path);
    return true;
  }

  return false;
}

}  // namespace application
}  // namespace xwalk
<|endoftext|>


<commit_before>#include <string.h>
#include <stdio.h>
#include <utility>

struct BigInteger
{
	BigInteger():
		neg_(false),
		size_(0),
		num_(nullptr)
	{}
	BigInteger(const char *input)
	{
		neg_ = input[0] == '-' ? true : false;
		int input_size = static_cast<int>(strlen(input));
		size_ = neg_ ? input_size - 1 : input_size;
		num_ = new int[size_];
		for(int index = 0; index < size_; ++index)
		{
			num_[index] = input[input_size - 1 - index] - '0';
		}
	}
	BigInteger(bool neg, int size):
		neg_(neg),
		size_(size),
		num_(new int[size_])
	{
		memset(num_, 0, size_ * sizeof(int));
	}
	BigInteger(const BigInteger &rhs):
		neg_(rhs.neg_),
		size_(rhs.size_),
		num_(new int[size_])
	{
		memmove(num_, rhs.num_, size_ * sizeof(int));
	}
	BigInteger(BigInteger &&rhs):
		neg_(rhs.neg_),
		size_(rhs.size_),
		num_(rhs.num_)
	{
		rhs.neg_ = false;
		rhs.size_ = 0;
		rhs.num_ = nullptr;
	}
	BigInteger &operator=(BigInteger rhs)
	{
		Swap(rhs);
		return *this;
	}
	void Swap(BigInteger &rhs)
	{
		std::swap(neg_, rhs.neg_);
		std::swap(size_, rhs.size_);
		std::swap(num_, rhs.num_);
	}
	~BigInteger()
	{
		delete [] num_;
		num_ = nullptr;
	}
	void set_neg(bool neg)
	{
		neg_ = neg;
	}
	void set_size(int new_size)
	{
		size_ = new_size;
		delete [] num_;
		num_ = new int[size_];
		memset(num_, 0, size_ * sizeof(int));
	}
	void ShowContent()
	{
		if(neg_ == true)
		{
			printf("-");
		}
		for(int index = size_ - 1; index >= 0; --index)
		{
			printf("%d", num_[index]);
		}
		printf("\n");
	}

	BigInteger Add(BigInteger &rhs)
	{
		BigInteger result;
		if((neg_ == true && rhs.neg_ == true) ||
		        (neg_ == false && rhs.neg_ == false))
		{
			int max_size = size_ > rhs.size_ ? size_ : rhs.size_;
			result.set_neg(neg_);
			result.set_size(max_size + 1);
			int min_size = size_ < rhs.size_ ? size_ : rhs.size_;
			for(int index = 0; index < min_size; ++index)
			{
				result.num_[index] = num_[index] + rhs.num_[index];
			}
			int *more_num = size_ > rhs.size_ ? num_ : rhs.num_;
			for(int index = min_size; index < max_size; ++index)
			{
				result.num_[index] = more_num[index];
			}
			for(int index = 0; index < max_size; ++index)
			{
				result.num_[index + 1] += result.num_[index] / 10;
				result.num_[index] %= 10;
			}
			if(result.num_[max_size] == 0)
			{
				--result.size_;
			}
		}
		else if(neg_ == false && rhs.neg_ == true)
		{
			rhs.neg_ = false;
			result = Subtract(rhs);
			rhs.neg_ = true;
		}
		else
		{
			neg_ = false;
			result = rhs.Subtract(*this);
			neg_ = true;
		}
		return result;
	}
	BigInteger Subtract(BigInteger &rhs)
	{
		BigInteger result;
		if(neg_ == false && rhs.neg_ == false)
		{
			int comp = CompareAbs(rhs);
			if(comp == 0)
			{
				result.set_size(1);
			}
			else
			{
				result.neg_ = comp > 0 ? false : true;
				int max_size = size_ > rhs.size_ ? size_ : rhs.size_;
				result.set_size(max_size);
				int min_size = size_ < rhs.size_ ? size_ : rhs.size_;
				for(int index = 0; index < min_size; ++index)
				{
					result.num_[index] = comp * (num_[index] - rhs.num_[index]);
				}
				int *more_num = size_ > rhs.size_ ? num_ : rhs.num_;
				for(int index = min_size; index < max_size; ++index)
				{
					result.num_[index] = more_num[index];
				}
				for(int low = 0; low < max_size; ++low)
				{
					if(result.num_[low] < 0)
					{
						int high = low;
						while(result.num_[++high] <= 0);
						--result.num_[high];
						while(--high != low)
						{
							result.num_[high] += 9;
						}
						result.num_[low] += 10;
					}
				}
				for(; result.num_[result.size_ - 1] == 0; --result.size_);
			}
		}
		else if(neg_ == true && rhs.neg_ == true)
		{
			neg_ = rhs.neg_ = false;
			result = rhs.Subtract(*this);
			neg_ = rhs.neg_ = true;
		}
		else if(neg_ == false && rhs.neg_ == true)
		{
			rhs.neg_ = false;
			result = Add(rhs);
			rhs.neg_ = true;
		}
		else
		{
			rhs.neg_ = true;
			result = Add(rhs);
			rhs.neg_ = false;
		}
		return result;
	}
	int CompareAbs(const BigInteger &rhs)
	{
		if(size_ > rhs.size_)
		{
			return 1;
		}
		else if(size_ < rhs.size_)
		{
			return -1;
		}
		for(int index = size_ - 1; index >= 0; --index)
		{
			if(num_[index] > rhs.num_[index])
			{
				return 1;
			}
			else if(num_[index] < rhs.num_[index])
			{
				return -1;
			}
		}
		return 0;
	}
	BigInteger Multiple(const BigInteger &rhs)
	{
		BigInteger result;
		if((neg_ == true && rhs.neg_ == false) || (neg_ == false && rhs.neg_ == true))
		{
			result.set_neg(true);
		}
		result.set_size(size_ > rhs.size_ ? size_ * 2 + 1 : rhs.size_ * 2 + 1);
		for(int index1 = 0; index1 < size_; ++index1)
		{
			for(int index2 = 0; index2 < rhs.size_; ++index2)
			{
				result.num_[index1 + index2] += num_[index1] * rhs.num_[index2];
			}
		}
		for(int index = 0; index < result.size_; ++index)
		{
			result.num_[index + 1] += result.num_[index] / 10;
			result.num_[index] %= 10;
		}
		for(; result.num_[result.size_ - 1] == 0; --result.size_);
		return result;
	}
	std::pair<BigInteger, BigInteger> DivideAndMod(const BigInteger &rhs)
	{
		BigInteger division, mod;
		if((neg_ == true && rhs.neg_ == false) || (neg_ == false && rhs.neg_ == true))
		{
			division.set_neg(true);
		}
		int comp = CompareAbs(rhs);
		if(comp <= 0)
		{
			division.set_size(1);
			if(comp == -1)
			{
				division.set_neg(false); // -0 -> 0
				mod = *this;
			}
			else
			{
				division.num_[0] = 1;
				mod.set_size(1);
			}
		}
		else
		{
			int size_diff = size_ - rhs.size_;
			division.set_size(size_diff + 1); // At most x-y+1 digits.
			BigInteger temp_lhs(*this);
			temp_lhs.set_neg(false);
			for(int offset = size_diff; offset >= 0; --offset)
			{
				BigInteger temp_rhs(false, rhs.size_ + offset);
				memmove(temp_rhs.num_ + offset, rhs.num_, rhs.size_ * sizeof(int));
				for(;;)
				{
					BigInteger sub_result = temp_lhs.Subtract(temp_rhs);
					if(sub_result.neg_ == false)
					{
						++division.num_[offset];
						temp_lhs = sub_result;
					}
					else
					{
						break;
					}
				}
			}
			mod = temp_lhs;
			mod.set_neg(neg_);
			if(division.num_[division.size_ - 1] == 0)
			{
				--division.size_;
			}
		}
		return std::pair<BigInteger, BigInteger>(division, mod);
	}

	bool neg_;
	int size_;
	int *num_;
};

int main()
{
	const int kBufferSize = 64 * 1024; // 64kB
	char buffer[kBufferSize];
	while(scanf("%s", buffer) == 1)
	{
		BigInteger bi1(buffer);
		scanf("%s", buffer);
		BigInteger bi2(buffer);
		(bi1.Add(bi2)).ShowContent();
		(bi1.Subtract(bi2)).ShowContent();
		(bi1.Multiple(bi2)).ShowContent();
		std::pair<BigInteger, BigInteger> bi_pair = bi1.DivideAndMod(bi2);
		bi_pair.first.ShowContent();
		bi_pair.second.ShowContent();
		printf("\n");
	}
}
/*
512 512
-512 -512
512 408
408 512
992 38
38 992
908 38
38 908
-38 -992
************************
1024 0 262144 1 0
-1024 0 262144 1 0
920 104 208896 1 104
920 -104 208896 0 408
1030 954 37696 26 4
1030 -954 37696 0 38
946 870 34504 23 34
946 -870 34504 0 38
-1030 954 37696 0 -38
*/
<commit_msg>feat: impl BigInteger::DivideAndMod<commit_after>#include <string.h>
#include <stdio.h>
#include <utility>

struct BigInteger
{
	BigInteger():
		neg_(false),
		size_(0),
		num_(nullptr)
	{}
	BigInteger(const char *input)
	{
		neg_ = input[0] == '-' ? true : false;
		int input_size = static_cast<int>(strlen(input));
		size_ = neg_ ? input_size - 1 : input_size;
		num_ = new int[size_];
		for(int index = 0; index < size_; ++index)
		{
			num_[index] = input[input_size - 1 - index] - '0';
		}
		for(; size_ != 1 && num_[size_ - 1] == 0; --size_);
	}
	BigInteger(bool neg, int size):
		neg_(neg),
		size_(size),
		num_(new int[size_])
	{
		memset(num_, 0, size_ * sizeof(int));
	}
	BigInteger(const BigInteger &rhs):
		neg_(rhs.neg_),
		size_(rhs.size_),
		num_(new int[size_])
	{
		memmove(num_, rhs.num_, size_ * sizeof(int));
	}
	BigInteger(BigInteger &&rhs):
		neg_(rhs.neg_),
		size_(rhs.size_),
		num_(rhs.num_)
	{
		rhs.neg_ = false;
		rhs.size_ = 0;
		rhs.num_ = nullptr;
	}
	BigInteger &operator=(BigInteger rhs)
	{
		Swap(rhs);
		return *this;
	}
	void Swap(BigInteger &rhs)
	{
		std::swap(neg_, rhs.neg_);
		std::swap(size_, rhs.size_);
		std::swap(num_, rhs.num_);
	}
	~BigInteger()
	{
		delete [] num_;
		num_ = nullptr;
	}

	void set_size(int new_size)
	{
		size_ = new_size;
		delete [] num_;
		num_ = new int[size_];
		memset(num_, 0, size_ * sizeof(int));
	}
	void ShowContent() const
	{
		if(size_ == 0)
		{
			printf("INF\n");
			return;
		}
		if(neg_ == true && (num_[0] != 0 || size_ > 1))
		{
			printf("-");
		}
		for(int index = size_ - 1; index >= 0; --index)
		{
			printf("%d", num_[index]);
		}
		printf("\n");
	}
	int CompareAbs(const BigInteger &rhs) const
	{
		if(size_ > rhs.size_)
		{
			return 1;
		}
		else if(size_ < rhs.size_)
		{
			return -1;
		}
		for(int index = size_ - 1; index >= 0; --index)
		{
			if(num_[index] > rhs.num_[index])
			{
				return 1;
			}
			else if(num_[index] < rhs.num_[index])
			{
				return -1;
			}
		}
		return 0;
	}

	BigInteger Add(BigInteger &rhs)
	{
		BigInteger result;
		if((neg_ == false && rhs.neg_ == false) || (neg_ == true && rhs.neg_ == true))
		{
			result.neg_ = neg_;
			int max_size = size_ > rhs.size_ ? size_ : rhs.size_;
			result.set_size(max_size + 1);
			int min_size = size_ < rhs.size_ ? size_ : rhs.size_;
			for(int index = 0; index < min_size; ++index)
			{
				result.num_[index] = num_[index] + rhs.num_[index];
			}
			int *more_num = size_ > rhs.size_ ? num_ : rhs.num_;
			for(int index = min_size; index < max_size; ++index)
			{
				result.num_[index] = more_num[index];
			}
			for(int index = 0; index < max_size; ++index)
			{
				result.num_[index + 1] += result.num_[index] / 10;
				result.num_[index] %= 10;
			}
			for(; result.size_ != 1 && result.num_[result.size_ - 1] == 0; --result.size_);
		}
		else if(neg_ == false && rhs.neg_ == true)
		{
			rhs.neg_ = false;
			result = Subtract(rhs);
			rhs.neg_ = true;
		}
		else
		{
			neg_ = false;
			result = rhs.Subtract(*this);
			neg_ = true;
		}
		return result;
	}
	BigInteger Subtract(BigInteger &rhs)
	{
		BigInteger result;
		if(neg_ == false && rhs.neg_ == false)
		{
			int comp = CompareAbs(rhs);
			if(comp == 0)
			{
				result.set_size(1);
			}
			else
			{
				result.neg_ = comp > 0 ? false : true;
				int max_size = size_ > rhs.size_ ? size_ : rhs.size_;
				result.set_size(max_size);
				int min_size = size_ < rhs.size_ ? size_ : rhs.size_;
				for(int index = 0; index < min_size; ++index)
				{
					result.num_[index] = comp * (num_[index] - rhs.num_[index]);
				}
				int *more_num = size_ > rhs.size_ ? num_ : rhs.num_;
				for(int index = min_size; index < max_size; ++index)
				{
					result.num_[index] = more_num[index];
				}
				for(int low = 0; low < max_size; ++low)
				{
					if(result.num_[low] < 0)
					{
						int high = low;
						while(result.num_[++high] <= 0);
						--result.num_[high];
						while(--high != low)
						{
							result.num_[high] += 9;
						}
						result.num_[low] += 10;
					}
				}
				for(; result.size_ != 1 && result.num_[result.size_ - 1] == 0; --result.size_);
			}
		}
		else if(neg_ == false && rhs.neg_ == true)
		{
			rhs.neg_ = false;
			result = Add(rhs);
			rhs.neg_ = true;
		}
		else if(neg_ == true && rhs.neg_ == false)
		{
			rhs.neg_ = true;
			result = Add(rhs);
			rhs.neg_ = false;
		}
		else
		{
			neg_ = rhs.neg_ = false;
			result = rhs.Subtract(*this);
			neg_ = rhs.neg_ = true;
		}
		return result;
	}
	BigInteger Multiple(const BigInteger &rhs) const
	{
		BigInteger result;
		if((neg_ == true && rhs.neg_ == false) || (neg_ == false && rhs.neg_ == true))
		{
			result.neg_ = true;
		}
		result.set_size(size_ > rhs.size_ ? size_ * 2: rhs.size_ * 2);
		for(int index1 = 0; index1 < size_; ++index1)
		{
			for(int index2 = 0; index2 < rhs.size_; ++index2)
			{
				result.num_[index1 + index2] += num_[index1] * rhs.num_[index2];
			}
		}
		for(int index = 0; index < result.size_; ++index)
		{
			result.num_[index + 1] += result.num_[index] / 10;
			result.num_[index] %= 10;
		}
		for(; result.size_ != 1 && result.num_[result.size_ - 1] == 0; --result.size_);
		return result;
	}
	std::pair<BigInteger, BigInteger> DivideAndMod(const BigInteger &rhs) const
	{
		BigInteger division, mod;
		if(rhs.size_ > 1 || rhs.num_[0] > 0)
		{
			int comp = CompareAbs(rhs);
			if(comp == -1)
			{
				division.set_size(1);
				mod = *this;
			}
			else if(comp == 0)
			{
				division.set_size(1);
				division.num_[0] = 1;
				mod.set_size(1);
			}
			else
			{
				int size_diff = size_ - rhs.size_;
				division.set_size(size_diff + 1);
				BigInteger temp_lhs(*this);
				temp_lhs.neg_ = false;
				for(int offset = size_diff; offset >= 0; --offset)
				{
					BigInteger temp_rhs(false, rhs.size_ + offset);
					memmove(temp_rhs.num_ + offset, rhs.num_, rhs.size_ * sizeof(int));
					for(;;)
					{
						BigInteger sub_result = temp_lhs.Subtract(temp_rhs);
						if(sub_result.neg_ == false)
						{
							++division.num_[offset];
							temp_lhs = sub_result;
							continue;
						}
						break;
					}
				}
				mod = temp_lhs;
				for(; division.size_ != 1 && division.num_[division.size_ - 1] == 0; --division.size_);
			}
		}
		if((neg_ == true && rhs.neg_ == false) || (neg_ == false && rhs.neg_ == true))
		{
			division.neg_ = true;
		}
		mod.neg_ = neg_;
		return std::pair<BigInteger, BigInteger>(division, mod);
	}

	bool neg_;
	int size_;
	int *num_;
};

int main()
{
	const int kBufferSize = 64 * 1024; // 64kB
	char buffer[kBufferSize];
	while(scanf("%s", buffer) == 1)
	{
		BigInteger bi1(buffer);
		scanf("%s", buffer);
		BigInteger bi2(buffer);
		(bi1.Add(bi2)).ShowContent();
		(bi1.Subtract(bi2)).ShowContent();
		(bi1.Multiple(bi2)).ShowContent();
		std::pair<BigInteger, BigInteger> bi_pair = bi1.DivideAndMod(bi2);
		bi_pair.first.ShowContent();
		bi_pair.second.ShowContent();
		printf("\n");
	}
}
/*
512 512
-512 -512
512 408
408 512
992 38
38 992
908 38
38 908
-38 -992
************************
1024
0
262144
1
0

-1024
0
262144
1
0

920
104
208896
1
104

920
-104
208896
0
408

1030
954
37696
26
4

1030
-954
37696
0
38

946
870
34504
23
34

946
-870
34504
0
38

-1030
954
37696
0
-38
*/
unsigned next_seed = 1;
unsigned rand()
{
	next_seed = next_seed * 1103515245 + 12543;
	return (next_seed >> 16) % 32768;
}
void srand(unsigned new_seed)
{
	next_seed = new_seed;
}
<|endoftext|>


<commit_before>/*
 * ngtcp2
 *
 * Copyright (c) 2020 ngtcp2 contributors
 *
 * 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 "util.h"

#include <cassert>
#include <iostream>
#include <fstream>
#include <array>

#include <ngtcp2/ngtcp2_crypto.h>

#include <gnutls/crypto.h>

#include "template.h"

// Based on https://github.com/ueno/ngtcp2-gnutls-examples

namespace ngtcp2 {

namespace util {

int generate_secure_random(uint8_t *data, size_t datalen) {
  if (gnutls_rnd(GNUTLS_RND_RANDOM, data, datalen) != 0) {
    return -1;
  }

  return 0;
}

int generate_secret(uint8_t *secret, size_t secretlen) {
  std::array<uint8_t, 16> rand;
  std::array<uint8_t, 32> md;

  assert(md.size() == secretlen);

  if (generate_secure_random(rand.data(), rand.size()) != 0) {
    return -1;
  }

  if (gnutls_hash_fast(GNUTLS_DIG_SHA256, rand.data(), rand.size(),
                       md.data()) != 0) {
    return -1;
  }

  std::copy_n(std::begin(md), secretlen, secret);
  return 0;
}

std::optional<std::string> read_token(const std::string_view &filename) {
  auto f = std::ifstream(filename.data());
  if (!f) {
    std::cerr << "Could not read token file " << filename << std::endl;
    return {};
  }

  auto pos = f.tellg();
  std::vector<char> content(pos);
  f.seekg(0, std::ios::beg);
  f.read(content.data(), pos);

  gnutls_datum_t s;
  s.data = reinterpret_cast<unsigned char *>(content.data());
  s.size = content.size();

  gnutls_datum_t d;
  if (auto rv = gnutls_pem_base64_decode2("QUIC TOKEN", &s, &d); rv < 0) {
    std::cerr << "Could not read token in " << filename << std::endl;
    return {};
  }

  auto res = std::string{d.data, d.data + d.size};

  gnutls_free(d.data);

  return res;
}

int write_token(const std::string_view &filename, const uint8_t *token,
                size_t tokenlen) {
  auto f = std::ofstream(filename.data());
  if (!f) {
    std::cerr << "Could not write token in " << filename << std::endl;
    return -1;
  }

  gnutls_datum_t s;
  s.data = const_cast<uint8_t *>(token);
  s.size = tokenlen;

  gnutls_datum_t d;
  if (auto rv = gnutls_pem_base64_encode2("QUIC TOKEN", &s, &d); rv < 0) {
    std::cerr << "Could not encode token in " << filename << std::endl;
    return -1;
  }

  f.write(reinterpret_cast<const char *>(d.data), d.size);
  gnutls_free(d.data);

  return 0;
}

const char *crypto_default_ciphers() {
  return "NORMAL:-VERS-ALL:+VERS-TLS1.3:-CIPHER-ALL:+AES-128-GCM:+AES-256-GCM:"
         "+CHACHA20-POLY1305:+AES-128-CCM";
}

const char *crypto_default_groups() {
  return "-GROUP-ALL:+GROUP-SECP256R1:+GROUP-X25519:+GROUP-SECP384R1:"
         "+GROUP-SECP521R1";
}

} // namespace util

} // namespace ngtcp2
<commit_msg>gtlsclient, gtlsserver: Prioritize X25519 over other groups<commit_after>/*
 * ngtcp2
 *
 * Copyright (c) 2020 ngtcp2 contributors
 *
 * 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 "util.h"

#include <cassert>
#include <iostream>
#include <fstream>
#include <array>

#include <ngtcp2/ngtcp2_crypto.h>

#include <gnutls/crypto.h>

#include "template.h"

// Based on https://github.com/ueno/ngtcp2-gnutls-examples

namespace ngtcp2 {

namespace util {

int generate_secure_random(uint8_t *data, size_t datalen) {
  if (gnutls_rnd(GNUTLS_RND_RANDOM, data, datalen) != 0) {
    return -1;
  }

  return 0;
}

int generate_secret(uint8_t *secret, size_t secretlen) {
  std::array<uint8_t, 16> rand;
  std::array<uint8_t, 32> md;

  assert(md.size() == secretlen);

  if (generate_secure_random(rand.data(), rand.size()) != 0) {
    return -1;
  }

  if (gnutls_hash_fast(GNUTLS_DIG_SHA256, rand.data(), rand.size(),
                       md.data()) != 0) {
    return -1;
  }

  std::copy_n(std::begin(md), secretlen, secret);
  return 0;
}

std::optional<std::string> read_token(const std::string_view &filename) {
  auto f = std::ifstream(filename.data());
  if (!f) {
    std::cerr << "Could not read token file " << filename << std::endl;
    return {};
  }

  auto pos = f.tellg();
  std::vector<char> content(pos);
  f.seekg(0, std::ios::beg);
  f.read(content.data(), pos);

  gnutls_datum_t s;
  s.data = reinterpret_cast<unsigned char *>(content.data());
  s.size = content.size();

  gnutls_datum_t d;
  if (auto rv = gnutls_pem_base64_decode2("QUIC TOKEN", &s, &d); rv < 0) {
    std::cerr << "Could not read token in " << filename << std::endl;
    return {};
  }

  auto res = std::string{d.data, d.data + d.size};

  gnutls_free(d.data);

  return res;
}

int write_token(const std::string_view &filename, const uint8_t *token,
                size_t tokenlen) {
  auto f = std::ofstream(filename.data());
  if (!f) {
    std::cerr << "Could not write token in " << filename << std::endl;
    return -1;
  }

  gnutls_datum_t s;
  s.data = const_cast<uint8_t *>(token);
  s.size = tokenlen;

  gnutls_datum_t d;
  if (auto rv = gnutls_pem_base64_encode2("QUIC TOKEN", &s, &d); rv < 0) {
    std::cerr << "Could not encode token in " << filename << std::endl;
    return -1;
  }

  f.write(reinterpret_cast<const char *>(d.data), d.size);
  gnutls_free(d.data);

  return 0;
}

const char *crypto_default_ciphers() {
  return "NORMAL:-VERS-ALL:+VERS-TLS1.3:-CIPHER-ALL:+AES-128-GCM:+AES-256-GCM:"
         "+CHACHA20-POLY1305:+AES-128-CCM";
}

const char *crypto_default_groups() {
  return "-GROUP-ALL:+GROUP-X25519:+GROUP-SECP256R1:+GROUP-SECP384R1:"
         "+GROUP-SECP521R1";
}

} // namespace util

} // namespace ngtcp2
<|endoftext|>


<commit_before>#ifndef MIMOSA_REF_COUNTED_PTR_HH
# define MIMOSA_REF_COUNTED_PTR_HH

namespace mimosa
{
  template <typename T>
  class RefCountedPtr
  {
  public:
    inline RefCountedPtr()
      : ptr_(0)
    {
    }

    inline RefCountedPtr(T * ptr)
      : ptr_(ptr)
    {
      if (ptr)
        addRef(ptr);
    }

    template <typename U>
    inline RefCountedPtr(const RefCountedPtr<U> & ptr)
    {
      assign(ptr.get());
    }

    inline ~RefCountedPtr()
    {
      assign(0);
    }

    inline RefCountedPtr<T> & operator=(T * ptr)
    {
      assign(ptr);
      return *this;
    }

    inline RefCountedPtr<T> & operator=(const RefCountedPtr<T> & ptr)
    {
      assign(ptr.get());
      return *this;
    }

    inline T & operator*() const { return *ptr_; }
    inline T * operator->() const { return ptr_; }
    inline T * get() const { return ptr_; }
    inline void assign(T * ptr)
    {
      if (ptr)
        addRef(ptr);
      if (ptr_)
        releaseRef(ptr_);
      ptr_ = ptr;
    }

  private:
    T * ptr_;
  };
}

#endif /* !MIMOSA_REF_COUNTED_PTR_HH */
<commit_msg>Added operator (bool), ! and ->* to RefCountedPtr<commit_after>#ifndef MIMOSA_REF_COUNTED_PTR_HH
# define MIMOSA_REF_COUNTED_PTR_HH

namespace mimosa
{
  template <typename T>
  class RefCountedPtr
  {
  public:
    inline RefCountedPtr()
      : ptr_(0)
    {
    }

    inline RefCountedPtr(T * ptr)
      : ptr_(ptr)
    {
      if (ptr)
        addRef(ptr);
    }

    template <typename U>
    inline RefCountedPtr(const RefCountedPtr<U> & ptr)
    {
      assign(ptr.get());
    }

    inline ~RefCountedPtr()
    {
      assign(0);
    }

    inline RefCountedPtr<T> & operator=(T * ptr)
    {
      assign(ptr);
      return *this;
    }

    inline RefCountedPtr<T> & operator=(const RefCountedPtr<T> & ptr)
    {
      assign(ptr.get());
      return *this;
    }

    inline bool operator!() const
    {
      return !ptr_;
    }

    inline operator bool () const
    {
      return ptr_;
    }

    inline T & operator*() const { return *ptr_; }
    inline T * operator->() const { return ptr_; }
    template <typename Member>
    inline auto operator->*(Member member) const -> decltype(((T*)nullptr)->*member) { return ptr_->*member; }
    inline T * get() const { return ptr_; }
    inline void assign(T * ptr)
    {
      if (ptr)
        addRef(ptr);
      if (ptr_)
        releaseRef(ptr_);
      ptr_ = ptr;
    }

  private:
    T * ptr_;
  };
}

#endif /* !MIMOSA_REF_COUNTED_PTR_HH */
<|endoftext|>


<commit_before>#include "ZSpider.hpp"
#include "ClientNode.hpp"
#include "Parser.hpp"
#include "zlog.hpp"

ZLOG_INIT(spider.log);
ZSpider::ZSpider()
{
    m_status = false;
    std::string url = "http://www.the9.com/";
    //std::string url = "http://www.sina.com.cn/";
    m_todolist.push_back(url);
}

void ZSpider::Run()
{
    m_status = true;

    char buf[128];
    int n=1;
    ClientNode client;
    Parser parser;
    while(m_status)	{
        if(m_todolist.empty()) {
            break;
        }

        std::string url = m_todolist.front();
        //if this page need to be fetched

        CPage page(url);
        client.Fetch(page);

        sprintf(buf, "%d", n++);
        std::string filename(buf);
        page.ProcessResponse();
        page.Output(filename);
        parser.Parse(page, m_todolist, m_visitedlist);

        m_visitedlist.push_back(url);
        m_todolist.pop_front();
        sleep(1);
        //break;
    }
}
<commit_msg>miss ZSpider.cpp<commit_after>#include "ZSpider.hpp"
#include "ClientNode.hpp"
#include "Parser.hpp"
#include "zlog.hpp"

ZLOG_INIT(spider.log);
ZSpider::ZSpider()
{
    m_status = false;
    //std::string url = "http://www.the9.com/";
    std::string url = "http://www.srzc.com/";
    //std::string url = "http://www.sina.com.cn/";
    m_todolist.push_back(url);
}

void ZSpider::Run()
{
    m_status = true;

    char buf[128];
    int n=1;
    ClientNode client;
    Parser parser;
    while(m_status)	{
        ZDEBUG_LOG("todolist size:%d", m_todolist.size());
        if(m_todolist.empty()) {
            break;
        }

        std::string url = m_todolist.front();
        //if this page need to be fetched
        CPage page(url);
        client.Fetch(page);

        sprintf(buf, "%d", n++);
        std::string filename(buf);
        page.ProcessResponse();
        page.Output(filename);
        parser.Parse(page, m_todolist, m_visitedlist);

        m_visitedlist.push_back(url);
        m_todolist.pop_front();
        sleep(1);
        //break;
    }
}
<|endoftext|>


<commit_before>/*
 * This file is a part of Xpiks - cross platform application for
 * keywording and uploading images for microstocks
 * Copyright (C) 2014-2017 Taras Kushnir <kushnirTV@gmail.com>
 *
 * Xpiks is distributed under the GNU Lesser General Public License, version 3.0
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "switcherconfig.h"
#include "../Helpers/asynccoordinator.h"
#include "apimanager.h"

namespace Conectivity {
#ifdef QT_DEBUG
    #define LOCAL_SWITCHER_CONFIG "debug_switcher.json"
#else
    #define LOCAL_SWITCHER_CONFIG "switcher.json"
#endif

#define OVERWRITE_KEY QLatin1String("overwrite")
#define DONATE_CAMPAIGN_1_KEY QLatin1String("donateCampaign1")
#define OVERWRITE_SWITCHER_CONFIG true

    SwitcherConfig::SwitcherConfig(QObject *parent):
        Models::AbstractConfigUpdaterModel(OVERWRITE_SWITCHER_CONFIG, parent)
    {
    }

    void SwitcherConfig::initializeConfigs(Helpers::AsyncCoordinator *initCoordinator) {
        Helpers::AsyncCoordinatorLocker locker(initCoordinator);
        Helpers::AsyncCoordinatorUnlocker unlocker(initCoordinator);
        Q_UNUSED(locker); Q_UNUSED(unlocker);

        QString localConfigPath;

        QString appDataPath = XPIKS_USERDATA_PATH;
        if (!appDataPath.isEmpty()) {
            QDir appDataDir(appDataPath);
            localConfigPath = appDataDir.filePath(LOCAL_SWITCHER_CONFIG);
        } else {
            localConfigPath = LOCAL_SWITCHER_CONFIG;
        }

        auto &apiManager = Conectivity::ApiManager::getInstance();
        QString remoteAddress = apiManager.getSwitcherAddr();
        AbstractConfigUpdaterModel::initializeConfigs(remoteAddress, localConfigPath);
    }

    bool SwitcherConfig::isSwitchOn(int switchKey) {
        QReadLocker locker(&m_RwLock);
        Q_UNUSED(locker);
        bool result = m_SwitchesHash.value(switchKey, false);
        return result;
    }

    bool SwitcherConfig::processLocalConfig(const QJsonDocument &document) {
        LOG_INTEGR_TESTS_OR_DEBUG << document;
        bool anyError = false;

        do {
            if (!document.isObject()) {
                LOG_WARNING << "Json document is not an object";
                anyError = true;
                break;
            }

            QJsonObject rootObject = document.object();
            parseSwitches(rootObject);
        } while (false);

        return anyError;
    }

    void SwitcherConfig::processRemoteConfig(const QJsonDocument &remoteDocument, bool overwriteLocal) {
        bool overwrite = false;

        if (!overwriteLocal && remoteDocument.isObject()) {
            QJsonObject rootObject = remoteDocument.object();
            if (rootObject.contains(OVERWRITE_KEY)) {
                QJsonValue overwriteValue = rootObject[OVERWRITE_KEY];
                if (overwriteValue.isBool()) {
                    overwrite = overwriteValue.toBool();
                    LOG_DEBUG << "Overwrite flag present in the config:" << overwrite;
                } else {
                    LOG_WARNING << "Overwrite flag is not boolean";
                }
            }
        } else {
            overwrite = overwriteLocal;
        }

        Models::AbstractConfigUpdaterModel::processRemoteConfig(remoteDocument, overwrite);

        if (remoteDocument.isObject()) {
            parseSwitches(remoteDocument.object());
        } else {
            LOG_WARNING << "Remote document is not an object";
        }
    }

    int SwitcherConfig::operator ()(const QJsonObject &val1, const QJsonObject &val2) {
        // values are always considered equal. This may lead to loss of local changes.
        Q_UNUSED(val1);
        Q_UNUSED(val2);
        return 0;
    }

    void SwitcherConfig::parseSwitches(const QJsonObject &object) {
        LOG_DEBUG << "#";
        bool donateCampaign1Active = false;

        QJsonValue isOnValue = object[DONATE_CAMPAIGN_1_KEY];
        if (isOnValue.isBool()) {
            donateCampaign1Active = isOnValue.toBool();
        }

        // overwrite these values
        {
            QWriteLocker locker(&m_RwLock);
            m_SwitchesHash.clear();
            m_SwitchesHash[DonateCampaign1] = donateCampaign1Active;
        }

        emit switchesUpdated();
    }
}
<commit_msg>Build fixes<commit_after>/*
 * This file is a part of Xpiks - cross platform application for
 * keywording and uploading images for microstocks
 * Copyright (C) 2014-2017 Taras Kushnir <kushnirTV@gmail.com>
 *
 * Xpiks is distributed under the GNU Lesser General Public License, version 3.0
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "switcherconfig.h"
#include <QDir>
#include <QJsonValue>
#include "../Helpers/asynccoordinator.h"
#include "apimanager.h"

namespace Conectivity {
#ifdef QT_DEBUG
    #define LOCAL_SWITCHER_CONFIG "debug_switcher.json"
#else
    #define LOCAL_SWITCHER_CONFIG "switcher.json"
#endif

#define OVERWRITE_KEY QLatin1String("overwrite")
#define DONATE_CAMPAIGN_1_KEY QLatin1String("donateCampaign1")
#define OVERWRITE_SWITCHER_CONFIG true

    SwitcherConfig::SwitcherConfig(QObject *parent):
        Models::AbstractConfigUpdaterModel(OVERWRITE_SWITCHER_CONFIG, parent)
    {
    }

    void SwitcherConfig::initializeConfigs(Helpers::AsyncCoordinator *initCoordinator) {
        Helpers::AsyncCoordinatorLocker locker(initCoordinator);
        Helpers::AsyncCoordinatorUnlocker unlocker(initCoordinator);
        Q_UNUSED(locker); Q_UNUSED(unlocker);

        QString localConfigPath;

        QString appDataPath = XPIKS_USERDATA_PATH;
        if (!appDataPath.isEmpty()) {
            QDir appDataDir(appDataPath);
            localConfigPath = appDataDir.filePath(LOCAL_SWITCHER_CONFIG);
        } else {
            localConfigPath = LOCAL_SWITCHER_CONFIG;
        }

        auto &apiManager = Conectivity::ApiManager::getInstance();
        QString remoteAddress = apiManager.getSwitcherAddr();
        AbstractConfigUpdaterModel::initializeConfigs(remoteAddress, localConfigPath);
    }

    bool SwitcherConfig::isSwitchOn(int switchKey) {
        QReadLocker locker(&m_RwLock);
        Q_UNUSED(locker);
        bool result = m_SwitchesHash.value(switchKey, false);
        return result;
    }

    bool SwitcherConfig::processLocalConfig(const QJsonDocument &document) {
        LOG_INTEGR_TESTS_OR_DEBUG << document;
        bool anyError = false;

        do {
            if (!document.isObject()) {
                LOG_WARNING << "Json document is not an object";
                anyError = true;
                break;
            }

            QJsonObject rootObject = document.object();
            parseSwitches(rootObject);
        } while (false);

        return anyError;
    }

    void SwitcherConfig::processRemoteConfig(const QJsonDocument &remoteDocument, bool overwriteLocal) {
        bool overwrite = false;

        if (!overwriteLocal && remoteDocument.isObject()) {
            QJsonObject rootObject = remoteDocument.object();
            if (rootObject.contains(OVERWRITE_KEY)) {
                QJsonValue overwriteValue = rootObject[OVERWRITE_KEY];
                if (overwriteValue.isBool()) {
                    overwrite = overwriteValue.toBool();
                    LOG_DEBUG << "Overwrite flag present in the config:" << overwrite;
                } else {
                    LOG_WARNING << "Overwrite flag is not boolean";
                }
            }
        } else {
            overwrite = overwriteLocal;
        }

        Models::AbstractConfigUpdaterModel::processRemoteConfig(remoteDocument, overwrite);

        if (remoteDocument.isObject()) {
            parseSwitches(remoteDocument.object());
        } else {
            LOG_WARNING << "Remote document is not an object";
        }
    }

    int SwitcherConfig::operator ()(const QJsonObject &val1, const QJsonObject &val2) {
        // values are always considered equal. This may lead to loss of local changes.
        Q_UNUSED(val1);
        Q_UNUSED(val2);
        return 0;
    }

    void SwitcherConfig::parseSwitches(const QJsonObject &object) {
        LOG_DEBUG << "#";
        bool donateCampaign1Active = false;

        QJsonValue isOnValue = object[DONATE_CAMPAIGN_1_KEY];
        if (isOnValue.isBool()) {
            donateCampaign1Active = isOnValue.toBool();
        }

        // overwrite these values
        {
            QWriteLocker locker(&m_RwLock);
            m_SwitchesHash.clear();
            m_SwitchesHash[DonateCampaign1] = donateCampaign1Active;
        }

        emit switchesUpdated();
    }
}
<|endoftext|>


<commit_before>#include "estimator/dcm_attitude_estimator.hpp"
#include "util/time.hpp"

#include "ch.hpp"
#include "protocol/messages.hpp"

#include "unit_config.hpp"

#include <chprintf.h>

DCMAttitudeEstimator::DCMAttitudeEstimator(Communicator& communicator, Logger& logger)
  : dcm(Eigen::Matrix3f::Identity()),
    attitudeMessageStream(communicator, 10),
    logger(logger) {
}

AttitudeEstimate DCMAttitudeEstimator::update(const SensorMeasurements& meas) {
  Eigen::Vector3f corr = Eigen::Vector3f::Zero();

  // Assume zero weights until we have verified the presence of these sensors.
  float accelWeight = 0.0f;
  float magWeight = 0.0f;

  // If an accelerometer is available, use the provided gravity vector to
  // correct for drift in the DCM.
  if(meas.accel) {
    Eigen::Vector3f accel((*meas.accel).axes.data());

    // Calculate accelerometer weight before normalization
    accelWeight = getAccelWeight(accel);

    accel.normalize();
    corr += dcm.col(2).cross(-accel) * accelWeight;
  }

  // If a magnetometer is available, use the provided north vector to correct
  // the yaw.
  if(meas.mag) {
    Eigen::Vector3f mag((*meas.mag).axes.data());

    // TODO: Calculate mag weight?
    magWeight = 0.001f;

    // "Project" the magnetometer into the global xy plane.
    Eigen::Vector3f magGlobal = dcm.transpose() * mag;
    magGlobal(2) = 0.0f;

    // Convert back to body coordinates.
    Eigen::Vector3f magBody = dcm * magGlobal;

    // Normalize because we only care about the prevailing direction.
    magBody.normalize();

    corr += dcm.col(0).cross(magBody - dcm.col(0)) * magWeight;
  }

  // If a gyroscope is available, integrate the provided rotational velocity and
  // add it to the correction vector.
  if(meas.gyro) {
    Eigen::Vector3f gyro((*meas.gyro).axes.data());
    corr += gyro * unit_config::DT * (1.0f - accelWeight - magWeight);
  }

  // Use small angle approximations to build a rotation matrix modelling the
  // attitude change over the time step.
  Eigen::Matrix3f dcmStep;
  dcmStep <<      1.0f,  corr.z(), -corr.y(),
             -corr.z(),      1.0f,  corr.x(),
              corr.y(), -corr.x(),      1.0f;

  // Rotate the DCM.
  dcm = dcmStep * dcm;

  orthonormalize();

  updateStream();

  return makeEstimate(meas);
}

void DCMAttitudeEstimator::orthonormalize() {
  // Orthogonalize i and j vectors
  //
  // We assume small angles. We calculate the magnitude of error as the
  // projection of i on j and generate correction vectors i' and j' with
  // magnitude error/2 and direction opposite j and i, respectively. Then we
  // update i and j:
  //
  //   i = i + i'
  //   j = j + j'
  //
  float error = dcm.row(0).dot(dcm.row(1));   // Magnitude of error
  Eigen::Matrix3f corr = Eigen::Matrix3f::Zero();   // Generate correction vectors
  corr.row(0) = (-error / 2) * dcm.row(1);   // i'
  corr.row(1) = (-error / 2) * dcm.row(0);   // j'

  dcm.row(0) += corr.row(0);   // i = i + i'
  dcm.row(1) += corr.row(1);   // j = j + j'

  // Regenerate k from the corrected i and j and normalize the DCM.
  dcm.row(2) = dcm.row(0).cross(dcm.row(1));   // k = i x j
  dcm.rowwise().normalize();
}

float DCMAttitudeEstimator::getAccelWeight(Eigen::Vector3f accel) const {
  // TODO(kyle): Pull these out as parameters
  float maxAccelWeight = 0.005f; // Accelerometer weight at exactly 1g
  float validAccelRange = 0.2f; // Maximum additional acceleration until accelWeight goes to 0

  // Deweight accelerometer as a linear function of the reading's difference
  // from 1g.
  float accelOffset = std::abs(1.0f - accel.norm());
  float accelWeight = -maxAccelWeight / validAccelRange * accelOffset + maxAccelWeight;

  // Zero weight if correction would be too large. Specifically want to avoid
  // rockets flipping on deceleration.
  if (dcm.col(2).dot(accel) < 0) {
    accelWeight = 0;
  }

  // Limit weight to a minimum of 0
  accelWeight = std::max(0.0f, accelWeight);

  return accelWeight;
}

AttitudeEstimate DCMAttitudeEstimator::makeEstimate(const SensorMeasurements& meas) {
  AttitudeEstimate estimate = {
    .time = ST2MS(chibios_rt::System::getTime()),
    .dcm = {
      dcm(0, 0), dcm(0, 1), dcm(0, 2),
      dcm(1, 0), dcm(1, 1), dcm(1, 2),
      dcm(2, 0), dcm(2, 1), dcm(2, 2)
    },

    // Euler angles (yaw-pitch-roll)
    // TODO(yoos): Due to singularities, this is really only safe for
    // visualization. We can use this for position control but should not
    // deviate more than perhaps 30 degrees away from horizontal.
    .roll = atan2(dcm(1,2), dcm(2,2)),
    .pitch = asin(-dcm(0,2)),
    .yaw = atan2(dcm(0,1), dcm(0,0)),

    // Velocities are set later if a gyro is available.
    .rollVel = 0.0f,
    .pitchVel = 0.0f,
    .yawVel = 0.0f,

    // TODO: Calculate accelerations.
    .rollAcc = 0.0f,
    .pitchAcc = 0.0f,
    .yawAcc = 0.0f
  };

  // If a gyro is available then use the direct measurements for velocity
  // calculation.
  if(meas.gyro) {
    estimate.rollVel = (*meas.gyro).axes[0];
    estimate.pitchVel = (*meas.gyro).axes[1];
    estimate.yawVel = (*meas.gyro).axes[2];
  } else {
    // TODO: Differentiate estimates or just ignore?
  }

  return estimate;
}

void DCMAttitudeEstimator::updateStream() {
  protocol::message::attitude_message_t m {
    .time = ST2MS(chibios_rt::System::getTime()),
    .dcm = {
      dcm(0, 0), dcm(0, 1), dcm(0, 2),
      dcm(1, 0), dcm(1, 1), dcm(1, 2),
      dcm(2, 0), dcm(2, 1), dcm(2, 2)
    }
  };

  if(attitudeMessageStream.ready()) {
    attitudeMessageStream.publish(m);
  }

  // Full-resolution attitude log by itself accounts for nearly half of all
  // logging. Downsample to 100 Hz so the filesystem has an easier time keeping
  // up.
  static int i=0;
  if (i % 10 == 0) {
    logger.write(m);
  }
  i = (i+1) % 1000;
}
<commit_msg>Tweak accel correction angle limit to 120 deg.<commit_after>#include "estimator/dcm_attitude_estimator.hpp"
#include "util/time.hpp"

#include "ch.hpp"
#include "protocol/messages.hpp"

#include "unit_config.hpp"

#include <chprintf.h>

DCMAttitudeEstimator::DCMAttitudeEstimator(Communicator& communicator, Logger& logger)
  : dcm(Eigen::Matrix3f::Identity()),
    attitudeMessageStream(communicator, 10),
    logger(logger) {
}

AttitudeEstimate DCMAttitudeEstimator::update(const SensorMeasurements& meas) {
  Eigen::Vector3f corr = Eigen::Vector3f::Zero();

  // Assume zero weights until we have verified the presence of these sensors.
  float accelWeight = 0.0f;
  float magWeight = 0.0f;

  // If an accelerometer is available, use the provided gravity vector to
  // correct for drift in the DCM.
  if(meas.accel) {
    Eigen::Vector3f accel((*meas.accel).axes.data());

    // Calculate accelerometer weight before normalization
    accelWeight = getAccelWeight(accel);

    accel.normalize();
    corr += dcm.col(2).cross(-accel) * accelWeight;
  }

  // If a magnetometer is available, use the provided north vector to correct
  // the yaw.
  if(meas.mag) {
    Eigen::Vector3f mag((*meas.mag).axes.data());

    // TODO: Calculate mag weight?
    magWeight = 0.001f;

    // "Project" the magnetometer into the global xy plane.
    Eigen::Vector3f magGlobal = dcm.transpose() * mag;
    magGlobal(2) = 0.0f;

    // Convert back to body coordinates.
    Eigen::Vector3f magBody = dcm * magGlobal;

    // Normalize because we only care about the prevailing direction.
    magBody.normalize();

    corr += dcm.col(0).cross(magBody - dcm.col(0)) * magWeight;
  }

  // If a gyroscope is available, integrate the provided rotational velocity and
  // add it to the correction vector.
  if(meas.gyro) {
    Eigen::Vector3f gyro((*meas.gyro).axes.data());
    corr += gyro * unit_config::DT * (1.0f - accelWeight - magWeight);
  }

  // Use small angle approximations to build a rotation matrix modelling the
  // attitude change over the time step.
  Eigen::Matrix3f dcmStep;
  dcmStep <<      1.0f,  corr.z(), -corr.y(),
             -corr.z(),      1.0f,  corr.x(),
              corr.y(), -corr.x(),      1.0f;

  // Rotate the DCM.
  dcm = dcmStep * dcm;

  orthonormalize();

  updateStream();

  return makeEstimate(meas);
}

void DCMAttitudeEstimator::orthonormalize() {
  // Orthogonalize i and j vectors
  //
  // We assume small angles. We calculate the magnitude of error as the
  // projection of i on j and generate correction vectors i' and j' with
  // magnitude error/2 and direction opposite j and i, respectively. Then we
  // update i and j:
  //
  //   i = i + i'
  //   j = j + j'
  //
  float error = dcm.row(0).dot(dcm.row(1));   // Magnitude of error
  Eigen::Matrix3f corr = Eigen::Matrix3f::Zero();   // Generate correction vectors
  corr.row(0) = (-error / 2) * dcm.row(1);   // i'
  corr.row(1) = (-error / 2) * dcm.row(0);   // j'

  dcm.row(0) += corr.row(0);   // i = i + i'
  dcm.row(1) += corr.row(1);   // j = j + j'

  // Regenerate k from the corrected i and j and normalize the DCM.
  dcm.row(2) = dcm.row(0).cross(dcm.row(1));   // k = i x j
  dcm.rowwise().normalize();
}

float DCMAttitudeEstimator::getAccelWeight(Eigen::Vector3f accel) const {
  // TODO(kyle): Pull these out as parameters
  float maxAccelWeight = 0.005f; // Accelerometer weight at exactly 1g
  float validAccelRange = 0.2f; // Maximum additional acceleration until accelWeight goes to 0

  // Deweight accelerometer as a linear function of the reading's difference
  // from 1g.
  float accelOffset = std::abs(1.0f - accel.norm());
  float accelWeight = -maxAccelWeight / validAccelRange * accelOffset + maxAccelWeight;

  // Zero weight if correction would be too large. Specifically want to avoid
  // rockets flipping on deceleration.
  if (dcm.col(2).dot(accel) < -0.5) {
    accelWeight = 0;
  }

  // Limit weight to a minimum of 0
  accelWeight = std::max(0.0f, accelWeight);

  return accelWeight;
}

AttitudeEstimate DCMAttitudeEstimator::makeEstimate(const SensorMeasurements& meas) {
  AttitudeEstimate estimate = {
    .time = ST2MS(chibios_rt::System::getTime()),
    .dcm = {
      dcm(0, 0), dcm(0, 1), dcm(0, 2),
      dcm(1, 0), dcm(1, 1), dcm(1, 2),
      dcm(2, 0), dcm(2, 1), dcm(2, 2)
    },

    // Euler angles (yaw-pitch-roll)
    // TODO(yoos): Due to singularities, this is really only safe for
    // visualization. We can use this for position control but should not
    // deviate more than perhaps 30 degrees away from horizontal.
    .roll = atan2(dcm(1,2), dcm(2,2)),
    .pitch = asin(-dcm(0,2)),
    .yaw = atan2(dcm(0,1), dcm(0,0)),

    // Velocities are set later if a gyro is available.
    .rollVel = 0.0f,
    .pitchVel = 0.0f,
    .yawVel = 0.0f,

    // TODO: Calculate accelerations.
    .rollAcc = 0.0f,
    .pitchAcc = 0.0f,
    .yawAcc = 0.0f
  };

  // If a gyro is available then use the direct measurements for velocity
  // calculation.
  if(meas.gyro) {
    estimate.rollVel = (*meas.gyro).axes[0];
    estimate.pitchVel = (*meas.gyro).axes[1];
    estimate.yawVel = (*meas.gyro).axes[2];
  } else {
    // TODO: Differentiate estimates or just ignore?
  }

  return estimate;
}

void DCMAttitudeEstimator::updateStream() {
  protocol::message::attitude_message_t m {
    .time = ST2MS(chibios_rt::System::getTime()),
    .dcm = {
      dcm(0, 0), dcm(0, 1), dcm(0, 2),
      dcm(1, 0), dcm(1, 1), dcm(1, 2),
      dcm(2, 0), dcm(2, 1), dcm(2, 2)
    }
  };

  if(attitudeMessageStream.ready()) {
    attitudeMessageStream.publish(m);
  }

  // Full-resolution attitude log by itself accounts for nearly half of all
  // logging. Downsample to 100 Hz so the filesystem has an easier time keeping
  // up.
  static int i=0;
  if (i % 10 == 0) {
    logger.write(m);
  }
  i = (i+1) % 1000;
}
<|endoftext|>


<commit_before>#include "davmeta.hpp"
#include <memory>
#include <ostream>
#include <sstream>
#include <string>
#include <cstring>
#include <cstdlib>
#include <deque>
#include <xml/davpropxmlparser.hpp>
#include <logger/davix_logger_internal.h>
#include <request/httprequest.hpp>
#include <fileops/fileutils.hpp>
#include <fileops/davops.hpp>
#include <utils/davix_utils_internal.hpp>

namespace Davix{

namespace Meta{

static const std::string propfind_request_replicas("<D:propfind xmlns:D=\"DAV:\" xmlns:L=\"LCGDM:\">"
                                                   "<D:prop><L:replicas/></D:prop>"
                                                   "</D:propfind>");

// get all reps from webdav queries
dav_ssize_t getAllReplicas(Context & c, const Uri & uri,
                              const RequestParams & params, ReplicaVec & vec, DavixError** err){
    dav_ssize_t ret =-1;
    DavixError* tmp_err=NULL;
    PropfindRequest req(c, uri, &tmp_err);
    if(tmp_err == NULL){
        req.setParameters(params);
        req.setRequestBody(propfind_request_replicas);
        if( req.executeRequest(&tmp_err) == 0){

        }
    }

    if(tmp_err)
        DavixError::propagateError(err, tmp_err);
    return ret;
}

/**
  execute a propfind/stat request on a given HTTP request handle
  return a vector with the content of the request if success
*/
const char* req_webdav_propfind(HttpRequest* req, DavixError** err){
    DavixError* tmp_err=NULL;
    int ret =-1;

    req->addHeaderField("Depth","0");
    req->setRequestMethod("PROPFIND");
    if( (ret = req->executeRequest(&tmp_err)) ==0){
        ret = davixRequestToFileStatus(req, davix_scope_stat_str(), &tmp_err);
    }

    if(ret != 0)
        DavixError::propagateError(err, tmp_err);

    return req->getAnswerContent();
}

int dav_stat_mapper_webdav(Context &context, const RequestParams* params, const Uri & url, struct stat* st, HttpCacheToken** token_ptr,
                           DavixError** err){
    int ret =-1;

    DavPropXMLParser parser;
    DavixError * tmp_err=NULL;
    HttpRequest req(context, url, &tmp_err);
    if( tmp_err == NULL){
        req.setParameters(params);

        const char * res = req_webdav_propfind(&req, &tmp_err);
        if(!tmp_err){
            if( (ret = parser.parseChuck((const char*) res, strlen(res)) ) < 0){
                DavixError::propagateError(err, parser.getLastErr());
                return -1;
            }

            std::deque<FileProperties> & props = parser.getProperties();
            if( props.size() < 1){
                DavixError::setupError(&tmp_err, davix_scope_stat_str(), Davix::StatusCode::WebDavPropertiesParsingError, "Parsing Error : properties number < 1");
                ret =-1;
            }else{
                fill_stat_from_fileproperties(st, props.front());
                ret =0;
                if(token_ptr)
                    *token_ptr = req.extractCacheToken();
        }
        }
    }
    if(tmp_err)
        DavixError::propagateError(err, tmp_err);
    return ret;
}

int dav_stat_mapper_http(Context& context, const RequestParams* params, const Uri & uri, struct stat* st, HttpCacheToken** token_ptr,
                         DavixError** err){
    int ret = -1;
    DavixError * tmp_err=NULL;
    HeadRequest req(context, uri, &tmp_err);

    if( tmp_err == NULL){
        req.setParameters(params);
        req.executeRequest(&tmp_err);

        if(!tmp_err){
            if(httpcodeIsValid(req.getRequestCode()) ){
                memset(st, 0, sizeof(struct stat));
                const dav_ssize_t s = req.getAnswerSize();
                st->st_size = (size_t) (s <0)?0:s;
                st->st_mode = 0755;
                ret = 0;
                if(token_ptr)
                    *token_ptr = req.extractCacheToken();
            }else{
                httpcodeToDavixCode(req.getRequestCode(), davix_scope_http_request(), uri.getString() , &tmp_err);
                ret = -1;
            }
        }
    }
    if(tmp_err)
        DavixError::propagateError(err, tmp_err);
    return ret;
}

dav_ssize_t posixStat(Context & c, const Uri & url, const RequestParams * params,
                      struct stat* st, HttpCacheToken** token_ptr,
                      DavixError** err){
    RequestParams _params(params);
    DavixError* tmp_err=NULL;
    int ret =-1;
    configureRequestParamsProto(url, _params);

    switch(_params.getProtocol()){
         case RequestProtocol::Webdav:
            ret = dav_stat_mapper_webdav(c, &_params, url, st, token_ptr, &tmp_err);
            break;
        default:
            ret = dav_stat_mapper_http(c, &_params, url, st, token_ptr, &tmp_err);
            break;

    }
    DAVIX_DEBUG(" davix_stat <-");
    if(tmp_err)
        DavixError::propagatePrefixedError(err, tmp_err, "stat ops : ");
    return ret;
}

int deleteResource(Context & c, const Uri & url, const RequestParams & params, DavixError** err){
    DavixError* tmp_err=NULL;
    int ret=-1;
    RequestParams _params(params);
    configureRequestParamsProto(url, _params);

    DeleteRequest req(c,url, err);
    req.setParameters(_params);
    if(!tmp_err){
        ret=req.executeRequest(&tmp_err);
        if(!tmp_err && httpcodeIsValid(req.getRequestCode()) == false){
                httpcodeToDavixCode(req.getRequestCode(), davix_scope_stat_str(), url.getString() , &tmp_err);
                ret = -1;
         }
    }

    if(tmp_err)
        DavixError::propagateError(err, tmp_err);
    return ret;
}

int makeCollection(Context & c, const Uri & url, const RequestParams & params, DavixError** err){
    DAVIX_DEBUG(" -> makeCollection");
    int ret=-1;
    DavixError* tmp_err=NULL;
    RequestParams _params(params);
    configureRequestParamsProto(url, _params);

    HttpRequest req(c, url, &tmp_err);

    if(tmp_err == NULL){
        req.setParameters(params);
        req.setRequestMethod("MKCOL");
        if( (ret = req.executeRequest(&tmp_err)) == 0){
            ret = davixRequestToFileStatus(&req, davix_scope_mkdir_str(), &tmp_err);
        }

        DAVIX_DEBUG(" makeCollection <-");
    }
    if(tmp_err)
        DavixError::propagateError(err, tmp_err);
    return ret;
}

} // Meta

} // Davix
<commit_msg>-mark pure http resource as regular file in stat()<commit_after>#include "davmeta.hpp"
#include <memory>
#include <ostream>
#include <sstream>
#include <string>
#include <cstring>
#include <cstdlib>
#include <deque>
#include <xml/davpropxmlparser.hpp>
#include <logger/davix_logger_internal.h>
#include <request/httprequest.hpp>
#include <fileops/fileutils.hpp>
#include <fileops/davops.hpp>
#include <utils/davix_utils_internal.hpp>

namespace Davix{

namespace Meta{

static const std::string propfind_request_replicas("<D:propfind xmlns:D=\"DAV:\" xmlns:L=\"LCGDM:\">"
                                                   "<D:prop><L:replicas/></D:prop>"
                                                   "</D:propfind>");

// get all reps from webdav queries
dav_ssize_t getAllReplicas(Context & c, const Uri & uri,
                              const RequestParams & params, ReplicaVec & vec, DavixError** err){
    dav_ssize_t ret =-1;
    DavixError* tmp_err=NULL;
    PropfindRequest req(c, uri, &tmp_err);
    if(tmp_err == NULL){
        req.setParameters(params);
        req.setRequestBody(propfind_request_replicas);
        if( req.executeRequest(&tmp_err) == 0){

        }
    }

    if(tmp_err)
        DavixError::propagateError(err, tmp_err);
    return ret;
}

/**
  execute a propfind/stat request on a given HTTP request handle
  return a vector with the content of the request if success
*/
const char* req_webdav_propfind(HttpRequest* req, DavixError** err){
    DavixError* tmp_err=NULL;
    int ret =-1;

    req->addHeaderField("Depth","0");
    req->setRequestMethod("PROPFIND");
    if( (ret = req->executeRequest(&tmp_err)) ==0){
        ret = davixRequestToFileStatus(req, davix_scope_stat_str(), &tmp_err);
    }

    if(ret != 0)
        DavixError::propagateError(err, tmp_err);

    return req->getAnswerContent();
}

int dav_stat_mapper_webdav(Context &context, const RequestParams* params, const Uri & url, struct stat* st, HttpCacheToken** token_ptr,
                           DavixError** err){
    int ret =-1;

    DavPropXMLParser parser;
    DavixError * tmp_err=NULL;
    HttpRequest req(context, url, &tmp_err);
    if( tmp_err == NULL){
        req.setParameters(params);

        const char * res = req_webdav_propfind(&req, &tmp_err);
        if(!tmp_err){
            if( (ret = parser.parseChuck((const char*) res, strlen(res)) ) < 0){
                DavixError::propagateError(err, parser.getLastErr());
                return -1;
            }

            std::deque<FileProperties> & props = parser.getProperties();
            if( props.size() < 1){
                DavixError::setupError(&tmp_err, davix_scope_stat_str(), Davix::StatusCode::WebDavPropertiesParsingError, "Parsing Error : properties number < 1");
                ret =-1;
            }else{
                fill_stat_from_fileproperties(st, props.front());
                ret =0;
                if(token_ptr)
                    *token_ptr = req.extractCacheToken();
        }
        }
    }
    if(tmp_err)
        DavixError::propagateError(err, tmp_err);
    return ret;
}

int dav_stat_mapper_http(Context& context, const RequestParams* params, const Uri & uri, struct stat* st, HttpCacheToken** token_ptr,
                         DavixError** err){
    int ret = -1;
    DavixError * tmp_err=NULL;
    HeadRequest req(context, uri, &tmp_err);

    if( tmp_err == NULL){
        req.setParameters(params);
        req.executeRequest(&tmp_err);

        if(!tmp_err){
            if(httpcodeIsValid(req.getRequestCode()) ){
                memset(st, 0, sizeof(struct stat));
                const dav_ssize_t s = req.getAnswerSize();
                st->st_size = (size_t) (s <0)?0:s;
                st->st_mode = 0755 | S_IFREG;
                ret = 0;
                if(token_ptr)
                    *token_ptr = req.extractCacheToken();
            }else{
                httpcodeToDavixCode(req.getRequestCode(), davix_scope_http_request(), uri.getString() , &tmp_err);
                ret = -1;
            }
        }
    }
    if(tmp_err)
        DavixError::propagateError(err, tmp_err);
    return ret;
}

dav_ssize_t posixStat(Context & c, const Uri & url, const RequestParams * params,
                      struct stat* st, HttpCacheToken** token_ptr,
                      DavixError** err){
    RequestParams _params(params);
    DavixError* tmp_err=NULL;
    int ret =-1;
    configureRequestParamsProto(url, _params);

    switch(_params.getProtocol()){
         case RequestProtocol::Webdav:
            ret = dav_stat_mapper_webdav(c, &_params, url, st, token_ptr, &tmp_err);
            break;
        default:
            ret = dav_stat_mapper_http(c, &_params, url, st, token_ptr, &tmp_err);
            break;

    }
    DAVIX_DEBUG(" davix_stat <-");
    if(tmp_err)
        DavixError::propagatePrefixedError(err, tmp_err, "stat ops : ");
    return ret;
}

int deleteResource(Context & c, const Uri & url, const RequestParams & params, DavixError** err){
    DavixError* tmp_err=NULL;
    int ret=-1;
    RequestParams _params(params);
    configureRequestParamsProto(url, _params);

    DeleteRequest req(c,url, err);
    req.setParameters(_params);
    if(!tmp_err){
        ret=req.executeRequest(&tmp_err);
        if(!tmp_err && httpcodeIsValid(req.getRequestCode()) == false){
                httpcodeToDavixCode(req.getRequestCode(), davix_scope_stat_str(), url.getString() , &tmp_err);
                ret = -1;
         }
    }

    if(tmp_err)
        DavixError::propagateError(err, tmp_err);
    return ret;
}

int makeCollection(Context & c, const Uri & url, const RequestParams & params, DavixError** err){
    DAVIX_DEBUG(" -> makeCollection");
    int ret=-1;
    DavixError* tmp_err=NULL;
    RequestParams _params(params);
    configureRequestParamsProto(url, _params);

    HttpRequest req(c, url, &tmp_err);

    if(tmp_err == NULL){
        req.setParameters(params);
        req.setRequestMethod("MKCOL");
        if( (ret = req.executeRequest(&tmp_err)) == 0){
            ret = davixRequestToFileStatus(&req, davix_scope_mkdir_str(), &tmp_err);
        }

        DAVIX_DEBUG(" makeCollection <-");
    }
    if(tmp_err)
        DavixError::propagateError(err, tmp_err);
    return ret;
}

} // Meta

} // Davix
<|endoftext|>


<commit_before>#include "estimator/dcm_attitude_estimator.hpp"

#include "hal.h"
#include "protocol/messages.hpp"

#include "unit_config.hpp"

DCMAttitudeEstimator::DCMAttitudeEstimator(Communicator& communicator)
  : dcm(Eigen::Matrix3f::Identity()),
    attitudeMessageStream(communicator, 20) {
}

attitude_estimate_t DCMAttitudeEstimator::update(gyroscope_reading_t& gyroReading, accelerometer_reading_t& accelReading) {
  Eigen::Vector3f gyro(gyroReading.axes.data());
  Eigen::Vector3f accel(accelReading.axes.data());

  // Calculate accelerometer weight before normalization
  float accelWeight = getAccelWeight(accel);

  accel.normalize();

  // Complementary filter
  Eigen::Vector3f corr = Eigen::Vector3f::Zero();
  corr += gyro * unit_config::DT * (1.0f - accelWeight);
  corr -= dcm.col(2).cross(-accel) * accelWeight;

  Eigen::Matrix3f dcmStep;
  dcmStep <<      1.0f,  corr.z(), -corr.y(),
             -corr.z(),      1.0f,  corr.x(),
              corr.y(), -corr.x(),      1.0f;

  dcm = dcmStep * dcm;

  orthonormalize();

  attitude_estimate_t estimate {
    // TODO: Are these trig functions safe at extreme angles?
    .roll = -atan2f(dcm(2, 1), dcm(2, 2)) * dcm(0, 0) + atan2f(dcm(2, 0), dcm(2, 2)) * dcm(0, 1),
    .pitch = atan2f(dcm(2, 0), dcm(2, 2)) * dcm(1, 1) - atan2f(dcm(2, 1), dcm(2, 2)) * dcm(1, 0),
    .yaw = 0.0f, // atan2f(dcm(1, 1), dcm(0, 1)),
    .roll_vel = gyro.x(),
    .pitch_vel = gyro.y(),
    .yaw_vel = gyro.z()
  };

  if(attitudeMessageStream.ready()) {
    protocol::message::attitude_message_t m {
      .dcm = {
        // estimate.roll, estimate.pitch, estimate.yaw,
        // accel(0), accel(1), accel(2), // NOTE: normalized
        // gyro(0), gyro(1), gyro(2),
        dcm(0, 0), dcm(0, 1), dcm(0, 2),
        dcm(1, 0), dcm(1, 1), dcm(1, 2),
        dcm(2, 0), dcm(2, 1), dcm(2, 2)
      }
    };

    attitudeMessageStream.publish(m);
  }

  return estimate;
}

void DCMAttitudeEstimator::orthonormalize() {
  // Make the i and j vectors orthogonal
  float error = dcm.row(0).dot(dcm.row(1));

  Eigen::Matrix3f corr = Eigen::Matrix3f::Zero();
  corr.row(0) = dcm.row(1) * (-error) / 2;
  corr.row(1) = dcm.row(0) * (-error) / 2;

  dcm.row(0) += corr.row(0);
  dcm.row(1) += corr.row(1);

  // Estimate k vector from corrected i and j vectors
  dcm.row(2) = dcm.row(0).cross(dcm.row(1));

  // Normalize all vectors
  dcm.rowwise().normalize();
}

float DCMAttitudeEstimator::getAccelWeight(Eigen::Vector3f accel) {
  // TODO(kyle): Pull these out as parameters
  float maxAccelWeight = 0.002f; // Accelerometer weight at exactly 1g
  float validAccelRange = 0.5f; // Maximum additional acceleration until accelWeight goes to 0

  // Deweight accelerometer as a linear function of the reading's difference
  // from 1g.
  float accelOffset = std::abs(1.0f - accel.norm());
  float accelWeight = -maxAccelWeight / validAccelRange * accelOffset + maxAccelWeight;

  // Limit weight to a minimum of 0
  accelWeight = std::max(0.0f, accelWeight);

  return accelWeight;
}
<commit_msg>Increase accelerometer weighting.<commit_after>#include "estimator/dcm_attitude_estimator.hpp"

#include "hal.h"
#include "protocol/messages.hpp"

#include "unit_config.hpp"

DCMAttitudeEstimator::DCMAttitudeEstimator(Communicator& communicator)
  : dcm(Eigen::Matrix3f::Identity()),
    attitudeMessageStream(communicator, 20) {
}

attitude_estimate_t DCMAttitudeEstimator::update(gyroscope_reading_t& gyroReading, accelerometer_reading_t& accelReading) {
  Eigen::Vector3f gyro(gyroReading.axes.data());
  Eigen::Vector3f accel(accelReading.axes.data());

  // Calculate accelerometer weight before normalization
  float accelWeight = getAccelWeight(accel);

  accel.normalize();

  // Complementary filter
  Eigen::Vector3f corr = Eigen::Vector3f::Zero();
  corr += gyro * unit_config::DT * (1.0f - accelWeight);
  corr -= dcm.col(2).cross(-accel) * accelWeight;

  Eigen::Matrix3f dcmStep;
  dcmStep <<      1.0f,  corr.z(), -corr.y(),
             -corr.z(),      1.0f,  corr.x(),
              corr.y(), -corr.x(),      1.0f;

  dcm = dcmStep * dcm;

  orthonormalize();

  attitude_estimate_t estimate {
    // TODO: Are these trig functions safe at extreme angles?
    .roll = -atan2f(dcm(2, 1), dcm(2, 2)) * dcm(0, 0) + atan2f(dcm(2, 0), dcm(2, 2)) * dcm(0, 1),
    .pitch = atan2f(dcm(2, 0), dcm(2, 2)) * dcm(1, 1) - atan2f(dcm(2, 1), dcm(2, 2)) * dcm(1, 0),
    .yaw = 0.0f, // atan2f(dcm(1, 1), dcm(0, 1)),
    .roll_vel = gyro.x(),
    .pitch_vel = gyro.y(),
    .yaw_vel = gyro.z()
  };

  if(attitudeMessageStream.ready()) {
    protocol::message::attitude_message_t m {
      .dcm = {
        // estimate.roll, estimate.pitch, estimate.yaw,
        // accel(0), accel(1), accel(2), // NOTE: normalized
        // gyro(0), gyro(1), gyro(2),
        dcm(0, 0), dcm(0, 1), dcm(0, 2),
        dcm(1, 0), dcm(1, 1), dcm(1, 2),
        dcm(2, 0), dcm(2, 1), dcm(2, 2)
      }
    };

    attitudeMessageStream.publish(m);
  }

  return estimate;
}

void DCMAttitudeEstimator::orthonormalize() {
  // Make the i and j vectors orthogonal
  float error = dcm.row(0).dot(dcm.row(1));

  Eigen::Matrix3f corr = Eigen::Matrix3f::Zero();
  corr.row(0) = dcm.row(1) * (-error) / 2;
  corr.row(1) = dcm.row(0) * (-error) / 2;

  dcm.row(0) += corr.row(0);
  dcm.row(1) += corr.row(1);

  // Estimate k vector from corrected i and j vectors
  dcm.row(2) = dcm.row(0).cross(dcm.row(1));

  // Normalize all vectors
  dcm.rowwise().normalize();
}

float DCMAttitudeEstimator::getAccelWeight(Eigen::Vector3f accel) {
  // TODO(kyle): Pull these out as parameters
  float maxAccelWeight = 0.005f; // Accelerometer weight at exactly 1g
  float validAccelRange = 0.5f; // Maximum additional acceleration until accelWeight goes to 0

  // Deweight accelerometer as a linear function of the reading's difference
  // from 1g.
  float accelOffset = std::abs(1.0f - accel.norm());
  float accelWeight = -maxAccelWeight / validAccelRange * accelOffset + maxAccelWeight;

  // Limit weight to a minimum of 0
  accelWeight = std::max(0.0f, accelWeight);

  return accelWeight;
}
<|endoftext|>