<commit_before>/*

Copyright (c) 2010, Arvid Norberg
All rights reserved.

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

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in
      the documentation and/or other materials provided with the distribution.
    * Neither the name of the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

*/

#include <boost/bind.hpp>
#include <list>
#include "libtorrent/thread.hpp"
#include "test.hpp"

using namespace libtorrent;

void fun(condition_variable* s, libtorrent::mutex* m, int i)
{
	fprintf(stderr, "thread %d waiting\n", i);
	libtorrent::mutex::scoped_lock l(*m);
	s->wait(l);
	fprintf(stderr, "thread %d done\n", i);
}

int test_main()
{
	condition_variable cond;
	libtorrent::mutex m;
	std::list<thread*> threads;
	for (int i = 0; i < 20; ++i)
	{
		threads.push_back(new thread(boost::bind(&fun, &cond, &m, i)));
	}

	// make sure all threads are waiting on the condition_variable
	sleep(10);

	libtorrent::mutex::scoped_lock l(m);
	cond.notify_all();
	l.unlock();

	for (std::list<thread*>::iterator i = threads.begin(); i != threads.end(); ++i)
	{
		(*i)->join();
		delete *i;
	}

	return 0;
}

<commit_msg>fix race condition in test_threads<commit_after>/*

Copyright (c) 2010, Arvid Norberg
All rights reserved.

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

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in
      the documentation and/or other materials provided with the distribution.
    * Neither the name of the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

*/

#include <boost/bind.hpp>
#include <list>
#include "libtorrent/thread.hpp"
#include <boost/smart_ptr/detail/atomic_count.hpp>
#include "test.hpp"

using boost::detail::atomic_count;
using namespace libtorrent;

void fun(condition_variable* s, libtorrent::mutex* m, int* waiting, int i)
{
	fprintf(stderr, "thread %d waiting\n", i);
	libtorrent::mutex::scoped_lock l(*m);
	*waiting += 1;
	s->wait(l);
	fprintf(stderr, "thread %d done\n", i);
}

void increment(condition_variable* s, libtorrent::mutex* m, int* waiting, atomic_count* c)
{
	libtorrent::mutex::scoped_lock l(*m);
	*waiting += 1;
	s->wait(l);
	l.unlock();
	for (int i = 0; i < 1000000; ++i)
		++*c;
}

void decrement(condition_variable* s, libtorrent::mutex* m, int* waiting, atomic_count* c)
{
	libtorrent::mutex::scoped_lock l(*m);
	*waiting += 1;
	s->wait(l);
	l.unlock();
	for (int i = 0; i < 1000000; ++i)
		--*c;
}

int test_main()
{
	condition_variable cond;
	libtorrent::mutex m;
	std::list<thread*> threads;
	int waiting = 0;
	for (int i = 0; i < 20; ++i)
	{
		threads.push_back(new thread(boost::bind(&fun, &cond, &m, &waiting, i)));
	}

	// make sure all threads are waiting on the condition_variable
	libtorrent::mutex::scoped_lock l(m);
	while (waiting < 20)
	{
		l.unlock();
		sleep(10);
		l.lock();
	}

	cond.notify_all();
	l.unlock();

	for (std::list<thread*>::iterator i = threads.begin(); i != threads.end(); ++i)
	{
		(*i)->join();
		delete *i;
	}
	threads.clear();

	waiting = 0;
	atomic_count c(0);
	for (int i = 0; i < 3; ++i)
	{
		threads.push_back(new thread(boost::bind(&increment, &cond, &m, &waiting, &c)));
		threads.push_back(new thread(boost::bind(&decrement, &cond, &m, &waiting, &c)));
	}

	// make sure all threads are waiting on the condition_variable
	l.lock();
	while (waiting < 6)
	{
		l.unlock();
		sleep(10);
		l.lock();
	}

	cond.notify_all();
	l.unlock();

	for (std::list<thread*>::iterator i = threads.begin(); i != threads.end(); ++i)
	{
		(*i)->join();
		delete *i;
	}

	TEST_CHECK(c == 0);

	return 0;
}

<|endoftext|>


<commit_before>#include "test.hpp"
#include "setup_transfer.hpp"
#include "libtorrent/alert.hpp"
#include "libtorrent/session.hpp"
#include "libtorrent/error_code.hpp"

#include <fstream>

using namespace libtorrent;

int test_main()
{
	int http_port = start_web_server();
	int udp_port = start_tracker();

	int prev_udp_announces = g_udp_tracker_requests;
	int prev_http_announces = g_http_tracker_requests;

	int const alert_mask = alert::all_categories
		& ~alert::progress_notification
		& ~alert::stats_notification;

	session* s = new libtorrent::session(fingerprint("LT", 0, 1, 0, 0), std::make_pair(48875, 49800), "0.0.0.0", 0, alert_mask);

	session_settings sett;
	sett.half_open_limit = 1;
	sett.announce_to_all_trackers = true;
	sett.announce_to_all_tiers = true;
	s->set_settings(sett);

	error_code ec;
	create_directory("./tmp1_tracker", ec);
	std::ofstream file("./tmp1_tracker/temporary");
	boost::intrusive_ptr<torrent_info> t = ::create_torrent(&file, 16 * 1024, 13, false);
	file.close();

	char tracker_url[200];
	snprintf(tracker_url, sizeof(tracker_url), "http://127.0.0.1:%d/announce", http_port);
	t->add_tracker(tracker_url);

	snprintf(tracker_url, sizeof(tracker_url), "udp://127.0.0.1:%d/announce", udp_port);
	t->add_tracker(tracker_url);

	add_torrent_params addp;
	addp.paused = false;
	addp.auto_managed = false;
	addp.ti = t;
	addp.save_path = "./tmp1_tracker";
	torrent_handle h = s->add_torrent(addp);

	test_sleep(2000);

	// we should have announced to the tracker by now
	TEST_EQUAL(g_udp_tracker_requests, prev_udp_announces + 1);
	TEST_EQUAL(g_http_tracker_requests, prev_http_announces + 1);

	delete s;

	// we should have announced the stopped event now
	TEST_EQUAL(g_udp_tracker_requests, prev_udp_announces + 2);
	TEST_EQUAL(g_http_tracker_requests, prev_http_announces + 2);

	// ========================================
	// test that we move on to try the next tier if the first one fails
	// ========================================

	s = new libtorrent::session(fingerprint("LT", 0, 1, 0, 0), std::make_pair(39775, 39800), "0.0.0.0", 0, alert_mask);

	sett.half_open_limit = 1;
	sett.announce_to_all_trackers = true;
	sett.announce_to_all_tiers = false;
	sett.tracker_completion_timeout = 2;
	sett.tracker_receive_timeout = 1;
	s->set_settings(sett);

	create_directory("./tmp2_tracker", ec);
	file.open("./tmp2_tracker/temporary");
	t = ::create_torrent(&file, 16 * 1024, 13, false);
	file.close();

	// this should fail
	snprintf(tracker_url, sizeof(tracker_url), "udp://www.google.com:80/announce");
	t->add_tracker(tracker_url, 0);

	// and this should fail
	snprintf(tracker_url, sizeof(tracker_url), "http://127.0.0.2:3/announce");
	t->add_tracker(tracker_url, 1);

	// this should be announced to
	// udp trackers are prioritized if they're on the same host as an http one
	// so this must be before the http one on 127.0.0.1
	snprintf(tracker_url, sizeof(tracker_url), "udp://127.0.0.1:%d/announce", udp_port);
	t->add_tracker(tracker_url, 2);

	// and this should not be announced to (since the one before it succeeded)
	snprintf(tracker_url, sizeof(tracker_url), "http://127.0.0.1:%d/announce", http_port);
	t->add_tracker(tracker_url, 3);

	prev_udp_announces = g_udp_tracker_requests;
	prev_http_announces = g_http_tracker_requests;

	addp.paused = false;
	addp.auto_managed = false;
	addp.ti = t;
	addp.save_path = "./tmp2_tracker";
	h = s->add_torrent(addp);

	for (int i = 0; i < 10; ++i)
	{
		print_alerts(*s, "s");
		test_sleep(1000);
		if (g_udp_tracker_requests == prev_udp_announces + 1) break;
	}

	test_sleep(1000);

	TEST_EQUAL(g_udp_tracker_requests, prev_udp_announces + 1);
	TEST_EQUAL(g_http_tracker_requests, prev_http_announces);

	delete s;

	stop_tracker();
	stop_web_server();

	return 0;
}

<commit_msg>added more diagnostics to test_tracker.cpp<commit_after>#include "test.hpp"
#include "setup_transfer.hpp"
#include "libtorrent/alert.hpp"
#include "libtorrent/session.hpp"
#include "libtorrent/error_code.hpp"

#include <fstream>

using namespace libtorrent;

int test_main()
{
	int http_port = start_web_server();
	int udp_port = start_tracker();

	int prev_udp_announces = g_udp_tracker_requests;
	int prev_http_announces = g_http_tracker_requests;

	int const alert_mask = alert::all_categories
		& ~alert::progress_notification
		& ~alert::stats_notification;

	session* s = new libtorrent::session(fingerprint("LT", 0, 1, 0, 0), std::make_pair(48875, 49800), "0.0.0.0", 0, alert_mask);

	session_settings sett;
	sett.half_open_limit = 1;
	sett.announce_to_all_trackers = true;
	sett.announce_to_all_tiers = true;
	s->set_settings(sett);

	error_code ec;
	create_directory("./tmp1_tracker", ec);
	std::ofstream file("./tmp1_tracker/temporary");
	boost::intrusive_ptr<torrent_info> t = ::create_torrent(&file, 16 * 1024, 13, false);
	file.close();

	char tracker_url[200];
	snprintf(tracker_url, sizeof(tracker_url), "http://127.0.0.1:%d/announce", http_port);
	t->add_tracker(tracker_url, 0);

	snprintf(tracker_url, sizeof(tracker_url), "udp://127.0.0.1:%d/announce", udp_port);
	t->add_tracker(tracker_url, 1);

	add_torrent_params addp;
	addp.paused = false;
	addp.auto_managed = false;
	addp.ti = t;
	addp.save_path = "./tmp1_tracker";
	torrent_handle h = s->add_torrent(addp);

	for (int i = 0; i < 100; ++i)
	{
		print_alerts(*s, "s");
		test_sleep(100);
		if (g_udp_tracker_requests == prev_udp_announces + 1
			&& g_http_tracker_requests == prev_http_announces + 1) break;
	}

	// we should have announced to the tracker by now
	TEST_EQUAL(g_udp_tracker_requests, prev_udp_announces + 1);
	TEST_EQUAL(g_http_tracker_requests, prev_http_announces + 1);

	fprintf(stderr, "destructing session\n");
	delete s;
	fprintf(stderr, "done\n");

	// we should have announced the stopped event now
	TEST_EQUAL(g_udp_tracker_requests, prev_udp_announces + 2);
	TEST_EQUAL(g_http_tracker_requests, prev_http_announces + 2);

	// ========================================
	// test that we move on to try the next tier if the first one fails
	// ========================================

	s = new libtorrent::session(fingerprint("LT", 0, 1, 0, 0), std::make_pair(39775, 39800), "0.0.0.0", 0, alert_mask);

	sett.half_open_limit = 1;
	sett.announce_to_all_trackers = true;
	sett.announce_to_all_tiers = false;
	sett.tracker_completion_timeout = 2;
	sett.tracker_receive_timeout = 1;
	s->set_settings(sett);

	create_directory("./tmp2_tracker", ec);
	file.open("./tmp2_tracker/temporary");
	t = ::create_torrent(&file, 16 * 1024, 13, false);
	file.close();

	// this should fail
	snprintf(tracker_url, sizeof(tracker_url), "udp://www.google.com:80/announce");
	t->add_tracker(tracker_url, 0);

	// and this should fail
	snprintf(tracker_url, sizeof(tracker_url), "http://127.0.0.2:3/announce");
	t->add_tracker(tracker_url, 1);

	// this should be announced to
	// udp trackers are prioritized if they're on the same host as an http one
	// so this must be before the http one on 127.0.0.1
	snprintf(tracker_url, sizeof(tracker_url), "udp://127.0.0.1:%d/announce", udp_port);
	t->add_tracker(tracker_url, 2);

	// and this should not be announced to (since the one before it succeeded)
	snprintf(tracker_url, sizeof(tracker_url), "http://127.0.0.1:%d/announce", http_port);
	t->add_tracker(tracker_url, 3);

	prev_udp_announces = g_udp_tracker_requests;
	prev_http_announces = g_http_tracker_requests;

	addp.paused = false;
	addp.auto_managed = false;
	addp.ti = t;
	addp.save_path = "./tmp2_tracker";
	h = s->add_torrent(addp);

	for (int i = 0; i < 10; ++i)
	{
		print_alerts(*s, "s");
		test_sleep(1000);
		if (g_udp_tracker_requests == prev_udp_announces + 1) break;
	}

	test_sleep(1000);

	TEST_EQUAL(g_udp_tracker_requests, prev_udp_announces + 1);
	TEST_EQUAL(g_http_tracker_requests, prev_http_announces);

	fprintf(stderr, "destructing session\n");
	delete s;
	fprintf(stderr, "done\n");

	stop_tracker();
	stop_web_server();

	return 0;
}

<|endoftext|>


<commit_before>///
/// @file  prime_iterator.cpp
///
/// Copyright (C) 2013 Kim Walisch, <kim.walisch@gmail.com>
///
/// This file is distributed under the BSD License. See the COPYING
/// file in the top level directory.
///

#include <primesieve.h>
#include <primesieve/soe/prime_iterator.h>
#include <primesieve/soe/primesieve_error.h>

#include <algorithm>
#include <cmath>
#include <string>
#include <vector>

using namespace std;

namespace primesieve {

prime_iterator::prime_iterator(uint64_t start)
{
  skip_to(start);
}

void prime_iterator::skip_to(uint64_t start)
{
  i_ = 0;
  count_ = 0;
  start_ = start;
  first_ = true;
  adjust_skip_to_ = false;

  if (start_ > max_stop())
    throw primesieve_error("start must be <= " + max_stop_string());

  if (!primes_.empty() &&
       primes_.front() <= start_ &&
       primes_.back() >= start_)
  {
    adjust_skip_to_ = true;
    i_ = lower_bound(primes_.begin(), primes_.end(), start_) - primes_.begin();
  }
}

/// Calculate an interval size that ensures a good load balance.
/// @param n  Start or stop number.
///
uint64_t prime_iterator::get_interval_size(uint64_t n)
{
  count_++;
  uint64_t kilobyte = 1 << 10;
  uint64_t megabyte = 1 << 20;
  uint64_t primes = (count_ < 10) ? (kilobyte * 32) / sizeof(uint64_t)
      : (megabyte * 4) / sizeof(uint64_t);

  double x = max(static_cast<double>(n), 100.0);
  double sqrtx = sqrt(x);
  uint64_t sqrtx_primes = static_cast<uint64_t>(sqrtx / (log(sqrtx) - 1.0));
  uint64_t max_primes = (megabyte * 512) / sizeof(uint64_t);

  primes = max(primes, sqrtx_primes);
  primes = min(primes, max_primes);
  return static_cast<uint64_t>(primes * log(x));
}

void prime_iterator::generate_primes(uint64_t start, uint64_t stop)
{
  primes_.clear();
  primesieve::generate_primes(start, stop, &primes_);
  if (primes_.empty())
    primes_.push_back(0);
}

void prime_iterator::generate_next_primes()
{
  if (adjust_skip_to_)
  {
    adjust_skip_to_ = false;
    if (i_ > 0 && primes_[i_ - 1] >= start_)
      i_--;
  }
  else
  {
    uint64_t start = (first_) ? start_ : primes_.back() + 1;
    uint64_t interval_size = get_interval_size(start);
    uint64_t stop = (start < max_stop() - interval_size) ? start + interval_size : max_stop();
    generate_primes(start, stop);
    i_ = 0;
  }
  first_ = false;
}

void prime_iterator::generate_previous_primes()
{
  if (adjust_skip_to_)
  {
    adjust_skip_to_ = false;
    if (i_ > 0 && primes_[i_] > start_)
      i_--;
  }
  else
  {
    uint64_t stop = start_;
    if (!first_)
      stop = (primes_.front() > 1) ? primes_.front() - 1 : 0;
    uint64_t interval_size = get_interval_size(stop);
    uint64_t start = (stop > interval_size) ? stop - interval_size : 0;
    generate_primes(start, stop);
    i_ = primes_.size();
  }
  first_ = false;
}

} // end namespace
<commit_msg>Update prime_iterator.cpp<commit_after>///
/// @file  prime_iterator.cpp
///
/// Copyright (C) 2013 Kim Walisch, <kim.walisch@gmail.com>
///
/// This file is distributed under the BSD License. See the COPYING
/// file in the top level directory.
///

#include <primesieve.h>
#include <primesieve/soe/prime_iterator.h>
#include <primesieve/soe/primesieve_error.h>

#include <algorithm>
#include <cmath>
#include <string>
#include <vector>

namespace primesieve {

prime_iterator::prime_iterator(uint64_t start)
{
  skip_to(start);
}

void prime_iterator::skip_to(uint64_t start)
{
  first_ = true;
  adjust_skip_to_ = false;
  i_ = 0;
  count_ = 0;
  start_ = start;

  if (start_ > max_stop())
    throw primesieve_error("start must be <= " + max_stop_string());

  if (!primes_.empty() &&
       primes_.front() <= start_ &&
       primes_.back() >= start_)
  {
    adjust_skip_to_ = true;
    i_ = std::lower_bound(primes_.begin(), primes_.end(), start_) - primes_.begin();
  }
}

/// Calculate an interval size that ensures a good load balance.
/// @param n  Start or stop number.
///
uint64_t prime_iterator::get_interval_size(uint64_t n)
{
  count_++;
  const uint64_t KILOBYTE = 1 << 10;
  const uint64_t MEGABYTE = 1 << 20;

  double x = std::max(static_cast<double>(n), 10.0);
  double sqrtx = std::sqrt(x);
  uint64_t sqrtx_primes = static_cast<uint64_t>(sqrtx / (std::log(sqrtx) - 1));

  uint64_t max_primes = (MEGABYTE * 512) / sizeof(uint64_t);
  uint64_t primes = ((count_ < 10) ? (KILOBYTE * 32) : (MEGABYTE * 4))  / sizeof(uint64_t);
  primes = std::min(std::max(primes, sqrtx_primes), max_primes);

  return static_cast<uint64_t>(primes * std::log(x));
}

void prime_iterator::generate_primes(uint64_t start, uint64_t stop)
{
  primes_.clear();
  primesieve::generate_primes(start, stop, &primes_);
  if (primes_.empty())
    primes_.push_back(0);
}

void prime_iterator::generate_next_primes()
{
  if (adjust_skip_to_)
  {
    adjust_skip_to_ = false;
    if (i_ > 0 && primes_[i_ - 1] >= start_)
      i_--;
  }
  else
  {
    uint64_t start = (first_) ? start_ : primes_.back() + 1;
    uint64_t interval_size = get_interval_size(start);
    uint64_t stop = (start < max_stop() - interval_size) ? start + interval_size : max_stop();
    generate_primes(start, stop);
    i_ = 0;
  }
  first_ = false;
}

void prime_iterator::generate_previous_primes()
{
  if (adjust_skip_to_)
  {
    adjust_skip_to_ = false;
    if (i_ > 0 && primes_[i_] > start_)
      i_--;
  }
  else
  {
    uint64_t stop = start_;
    if (!first_)
      stop = (primes_.front() > 1) ? primes_.front() - 1 : 0;
    uint64_t interval_size = get_interval_size(stop);
    uint64_t start = (stop > interval_size) ? stop - interval_size : 0;
    generate_primes(start, stop);
    i_ = primes_.size();
  }
  first_ = false;
}

} // end namespace
<|endoftext|>


<commit_before>#include <iostream>
#include <fstream>
#include <sstream>
#include <cerrno>
#include "memory.h"
#include "sysbus.h"
#include "utils.h"

Memory::Memory(unsigned int size_kb)
{
  m_memory = new uint8_t[size_kb * 1024];
  m_size_kb = size_kb;
}

uint32_t Memory::read32(uint32_t addr)
{
  uint32_t val;

  val = m_memory[addr];
  val |= m_memory[addr + 1] << 8;
  val |= m_memory[addr + 2] << 16;
  val |= m_memory[addr + 3] << 24;

  return val;
}

void Memory::write32(uint32_t addr, uint32_t data)
{
  m_memory[addr] = data & 0xFF;
  m_memory[addr + 1] = (data >> 8) & 0xFF;
  m_memory[addr + 2] = (data >> 16) & 0xFF;
  m_memory[addr + 3] = (data >> 24) & 0xFF;
}

void Memory::load_bin(char const *filename, uint32_t offset)
{
  std::ifstream infile;
  uint32_t size = m_size_kb * 1024;

  infile.open(filename);

  if (!infile) {
    std::ostringstream message;
    message << "error opening file '" << filename << "': ";
    throw IOError(errno, message.str());
  }

  while (!infile.eof()) {
    uint8_t byte;

    if (offset >= size)
      break;

    infile >> byte;
    m_memory[offset] = byte;
    offset++;
  }
}

uint32_t Memory::get_size()
{
  return m_size_kb * 1024;
}
<commit_msg>Clear memory on power-on.<commit_after>#include <iostream>
#include <fstream>
#include <sstream>
#include <cerrno>
#include <cstring>
#include "memory.h"
#include "sysbus.h"
#include "utils.h"

Memory::Memory(unsigned int size_kb)
{
  m_memory = new uint8_t[size_kb * 1024];
  std::memset(m_memory, 0, size_kb * 1024);
  m_size_kb = size_kb;
}

uint32_t Memory::read32(uint32_t addr)
{
  uint32_t val;

  val = m_memory[addr];
  val |= m_memory[addr + 1] << 8;
  val |= m_memory[addr + 2] << 16;
  val |= m_memory[addr + 3] << 24;

  return val;
}

void Memory::write32(uint32_t addr, uint32_t data)
{
  m_memory[addr] = data & 0xFF;
  m_memory[addr + 1] = (data >> 8) & 0xFF;
  m_memory[addr + 2] = (data >> 16) & 0xFF;
  m_memory[addr + 3] = (data >> 24) & 0xFF;
}

void Memory::load_bin(char const *filename, uint32_t offset)
{
  std::ifstream infile;
  uint32_t size = m_size_kb * 1024;

  infile.open(filename);

  if (!infile) {
    std::ostringstream message;
    message << "error opening file '" << filename << "': ";
    throw IOError(errno, message.str());
  }

  while (!infile.eof()) {
    uint8_t byte;

    if (offset >= size)
      break;

    infile >> byte;
    m_memory[offset] = byte;
    offset++;
  }
}

uint32_t Memory::get_size()
{
  return m_size_kb * 1024;
}
<|endoftext|>


<commit_before>#include "render/init.h"

#include <SDL2/SDL_video.h>
#include "render/gl.h"

#include <iostream>

Init::Init() : ok(true) {
  const int glad_result = gladLoadGLLoader(SDL_GL_GetProcAddress);
  if(!glad_result) {
    std::cerr << "Failed to init glad, error: " << glad_result
              << "\n";
    ok = false;
  }

  std::cout << "Vendor:         " << glGetString(GL_VENDOR) << "\n";
  std::cout << "Renderer:       " << glGetString(GL_RENDERER) << "\n";
  std::cout << "Version OpenGL: " << glGetString(GL_VERSION) << "\n";
  std::cout << "Version GLSL:   " << glGetString(GL_SHADING_LANGUAGE_VERSION) << "\n";

  int attribute_count;
  glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &attribute_count);
  std::cout << "Max shader attribute count: " << attribute_count << "\n";

  // todo: move this to a better place
  glDisable(GL_DEPTH_TEST);
  glDisable(GL_CULL_FACE);
  glEnable(GL_BLEND);
  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}

Init::~Init() {
}

void Init::SetViewport(const Recti &viewport) {
  const vec2i top_left = viewport.TopLeft();
  glViewport(top_left.x, top_left.y, viewport.GetWidth(), viewport.GetHeight());
}

void Init::ClearScreen(const Rgb& color) {
  // 42.0f / 255, 45.0f / 255, 51.0f / 255
  glClearColor(color.GetRed(), color.GetGreen(), color.GetBlue(), 1.0f);
  glClear(GL_COLOR_BUFFER_BIT);
}
<commit_msg>added todo<commit_after>#include "render/init.h"

#include <SDL2/SDL_video.h>
#include "render/gl.h"

#include <iostream>

Init::Init() : ok(true) {
  const int glad_result = gladLoadGLLoader(SDL_GL_GetProcAddress);
  if(!glad_result) {
    std::cerr << "Failed to init glad, error: " << glad_result
              << "\n";
    ok = false;
  }

  // todo: replace cout with log system
  std::cout << "Vendor:         " << glGetString(GL_VENDOR) << "\n";
  std::cout << "Renderer:       " << glGetString(GL_RENDERER) << "\n";
  std::cout << "Version OpenGL: " << glGetString(GL_VERSION) << "\n";
  std::cout << "Version GLSL:   " << glGetString(GL_SHADING_LANGUAGE_VERSION) << "\n";

  int attribute_count;
  glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &attribute_count);
  std::cout << "Max shader attribute count: " << attribute_count << "\n";

  // todo: move this to a better place
  glDisable(GL_DEPTH_TEST);
  glDisable(GL_CULL_FACE);
  glEnable(GL_BLEND);
  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}

Init::~Init() {
}

void Init::SetViewport(const Recti &viewport) {
  const vec2i top_left = viewport.TopLeft();
  glViewport(top_left.x, top_left.y, viewport.GetWidth(), viewport.GetHeight());
}

void Init::ClearScreen(const Rgb& color) {
  // 42.0f / 255, 45.0f / 255, 51.0f / 255
  glClearColor(color.GetRed(), color.GetGreen(), color.GetBlue(), 1.0f);
  glClear(GL_COLOR_BUFFER_BIT);
}
<|endoftext|>


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

#define __STDC_LIMIT_MACROS

// HyperDex
#include "admin/admin.h"
#include "admin/constants.h"
#include "admin/pending_perf_counters.h"

using hyperdex::pending_perf_counters;

static uint64_t
monotonic_time()
{
    timespec ts;

    if (clock_gettime(CLOCK_MONOTONIC, &ts) < 0)
    {
        throw po6::error(errno);
    }

    return ts.tv_sec * 1000000000ULL + ts.tv_nsec;
}

struct pending_perf_counters::perf_counter
{
    perf_counter(uint64_t i, uint64_t t, const std::string& p, uint64_t m)
        : id(i), time(t), property(p), measurement(m) {}
    uint64_t id;
    uint64_t time;
    std::string property;
    uint64_t measurement;
};

pending_perf_counters :: pending_perf_counters(uint64_t id,
                                               hyperdex_admin_returncode* s,
                                               hyperdex_admin_perf_counter* pc)
    : pending(id, s)
    , m_pc(pc)
    , m_next_send(0)
    , m_pcs()
    , m_scratch()
    , m_cutoffs()
{
}

pending_perf_counters :: ~pending_perf_counters() throw ()
{
}

void
pending_perf_counters :: send_perf_reqs(admin* adm,
                                        const configuration* config,
                                        hyperdex_admin_returncode* status)
{
    std::vector<std::pair<server_id, po6::net::location> > addrs;
    config->get_all_addresses(&addrs);
    uint64_t failed = 0;

    for (size_t i = 0; i < addrs.size(); ++i)
    {
        uint64_t nonce = adm->m_next_server_nonce;
        ++adm->m_next_server_nonce;
        uint64_t when = 0;
        std::map<server_id, uint64_t>::iterator it = m_cutoffs.find(addrs[i].first);

        if (it == m_cutoffs.end())
        {
            m_cutoffs[addrs[i].first] = 0;
        }
        else
        {
            when = it->second;
        }

        size_t sz = HYPERDEX_ADMIN_HEADER_SIZE_REQ + sizeof(uint64_t);
        std::auto_ptr<e::buffer> msg(e::buffer::create(sz));
        msg->pack_at(HYPERDEX_ADMIN_HEADER_SIZE_REQ) << when;

        if (!adm->send(PERF_COUNTERS, addrs[i].first, nonce, msg, this, status))
        {
            ++failed;
        }
    }

    std::map<server_id, uint64_t>::iterator it = m_cutoffs.begin();

    while (it != m_cutoffs.end())
    {
        bool found = false;

        for (size_t i = 0; i < addrs.size(); ++i)
        {
            if (it->first == addrs[i].first)
            {
                found = true;
                break;
            }
        }

        if (found)
        {
            ++it;
        }
        else
        {
            m_cutoffs.erase(it);
            it = m_cutoffs.begin();
        }
    }
}

int
pending_perf_counters :: millis_to_next_send()
{
    const uint64_t one_second = 1000ULL * 1000ULL * 1000ULL;
    uint64_t now = monotonic_time();

    if (now >= m_next_send)
    {
        m_next_send = now + one_second;
        return 0;
    }

    return ((m_next_send - now) / one_second) + 1;
}

bool
pending_perf_counters :: can_yield()
{
    return !m_pcs.empty();
}

bool
pending_perf_counters :: yield(hyperdex_admin_returncode* status)
{
    assert(can_yield());
    m_scratch = m_pcs.front().property;
    m_pc->id = m_pcs.front().id;
    m_pc->time = m_pcs.front().time;
    m_pc->property = m_scratch.c_str();
    m_pc->measurement = m_pcs.front().measurement;
    m_pcs.pop_front();
    *status = HYPERDEX_ADMIN_SUCCESS;
    return true;
}

void
pending_perf_counters :: handle_sent_to(const server_id&)
{
}

void
pending_perf_counters :: handle_failure(const server_id&)
{
}

bool
pending_perf_counters :: handle_message(admin*,
                                        const server_id& si,
                                        network_msgtype mt,
                                        std::auto_ptr<e::buffer>,
                                        e::unpacker up,
                                        hyperdex_admin_returncode* status)
{
    *status = HYPERDEX_ADMIN_SUCCESS;
    set_status(HYPERDEX_ADMIN_SUCCESS);

    if (mt != PERF_COUNTERS)
    {
        YIELDING_ERROR(SERVERERROR) << "server " << si.get() << " responded to PERF_COUNTERS with wrong message type";
        return true;
    }

    e::slice rem = up.as_slice();
    char* ptr = const_cast<char*>(reinterpret_cast<const char*>(rem.data()));
    char* end = ptr + rem.size() - 1;
    uint64_t max_time = 0;

    // parse one line at a time
    while (ptr < end)
    {
        char* eol = reinterpret_cast<char*>(memchr(ptr, '\n', end - ptr));
        eol = eol ? eol : end;
        *eol = '\0';
        char* tmp = ptr;

        // parse the time
        tmp = strchr(ptr, ' ');
        tmp = tmp ? tmp : eol;
        *tmp = '\0';
        uint64_t time = strtoull(ptr, NULL, 0);
        max_time = std::max(time, max_time);
        ptr = tmp + 1;

        while (ptr < eol)
        {
            tmp = strchr(ptr, ' ');
            tmp = tmp ? tmp : eol;
            *tmp = '\0';

            char* equals = strchr(ptr, '=');
            equals = equals ? equals: tmp;
            *equals = '\0';
            uint64_t value = 0;

            if (equals < tmp)
            {
                ++equals;
                value = strtoull(equals, NULL, 0);
            }

            m_pcs.push_back(perf_counter(si.get(), time, ptr, value));
            ptr = tmp + 1;
        }

        ptr = eol + 1;
    }

    m_cutoffs[si] = max_time;
    return true;
}
<commit_msg>Switch to mach_absolute_time() under Mac OS X, iOS, and *BSD which don't support clock_gettime().<commit_after>// Copyright (c) 2013, Cornell University
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
//     * Redistributions of source code must retain the above copyright notice,
//       this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above copyright
//       notice, this list of conditions and the following disclaimer in the
//       documentation and/or other materials provided with the distribution.
//     * Neither the name of HyperDex nor the names of its contributors may be
//       used to endorse or promote products derived from this software without
//       specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.

#define __STDC_LIMIT_MACROS

// HyperDex
#include "admin/admin.h"
#include "admin/constants.h"
#include "admin/pending_perf_counters.h"

using hyperdex::pending_perf_counters;

#if defined(__APPLE__)
#include <mach/mach_time.h>
#endif

static uint64_t
monotonic_time()
{
#if defined(__APPLE__)
    static mach_timebase_info_data_t tb = { 0 };
    if ( !tb.denom )
        mach_timebase_info(&tb);

    return mach_absolute_time() * tb.numer / tb.denom;
#else
    timespec ts;

    if (clock_gettime(CLOCK_MONOTONIC, &ts) < 0)
    {
        throw po6::error(errno);
    }

    return ts.tv_sec * 1000000000ULL + ts.tv_nsec;
#endif
}

struct pending_perf_counters::perf_counter
{
    perf_counter(uint64_t i, uint64_t t, const std::string& p, uint64_t m)
        : id(i), time(t), property(p), measurement(m) {}
    uint64_t id;
    uint64_t time;
    std::string property;
    uint64_t measurement;
};

pending_perf_counters :: pending_perf_counters(uint64_t id,
                                               hyperdex_admin_returncode* s,
                                               hyperdex_admin_perf_counter* pc)
    : pending(id, s)
    , m_pc(pc)
    , m_next_send(0)
    , m_pcs()
    , m_scratch()
    , m_cutoffs()
{
}

pending_perf_counters :: ~pending_perf_counters() throw ()
{
}

void
pending_perf_counters :: send_perf_reqs(admin* adm,
                                        const configuration* config,
                                        hyperdex_admin_returncode* status)
{
    std::vector<std::pair<server_id, po6::net::location> > addrs;
    config->get_all_addresses(&addrs);
    uint64_t failed = 0;

    for (size_t i = 0; i < addrs.size(); ++i)
    {
        uint64_t nonce = adm->m_next_server_nonce;
        ++adm->m_next_server_nonce;
        uint64_t when = 0;
        std::map<server_id, uint64_t>::iterator it = m_cutoffs.find(addrs[i].first);

        if (it == m_cutoffs.end())
        {
            m_cutoffs[addrs[i].first] = 0;
        }
        else
        {
            when = it->second;
        }

        size_t sz = HYPERDEX_ADMIN_HEADER_SIZE_REQ + sizeof(uint64_t);
        std::auto_ptr<e::buffer> msg(e::buffer::create(sz));
        msg->pack_at(HYPERDEX_ADMIN_HEADER_SIZE_REQ) << when;

        if (!adm->send(PERF_COUNTERS, addrs[i].first, nonce, msg, this, status))
        {
            ++failed;
        }
    }

    std::map<server_id, uint64_t>::iterator it = m_cutoffs.begin();

    while (it != m_cutoffs.end())
    {
        bool found = false;

        for (size_t i = 0; i < addrs.size(); ++i)
        {
            if (it->first == addrs[i].first)
            {
                found = true;
                break;
            }
        }

        if (found)
        {
            ++it;
        }
        else
        {
            m_cutoffs.erase(it);
            it = m_cutoffs.begin();
        }
    }
}

int
pending_perf_counters :: millis_to_next_send()
{
    const uint64_t one_second = 1000ULL * 1000ULL * 1000ULL;
    uint64_t now = monotonic_time();

    if (now >= m_next_send)
    {
        m_next_send = now + one_second;
        return 0;
    }

    return ((m_next_send - now) / one_second) + 1;
}

bool
pending_perf_counters :: can_yield()
{
    return !m_pcs.empty();
}

bool
pending_perf_counters :: yield(hyperdex_admin_returncode* status)
{
    assert(can_yield());
    m_scratch = m_pcs.front().property;
    m_pc->id = m_pcs.front().id;
    m_pc->time = m_pcs.front().time;
    m_pc->property = m_scratch.c_str();
    m_pc->measurement = m_pcs.front().measurement;
    m_pcs.pop_front();
    *status = HYPERDEX_ADMIN_SUCCESS;
    return true;
}

void
pending_perf_counters :: handle_sent_to(const server_id&)
{
}

void
pending_perf_counters :: handle_failure(const server_id&)
{
}

bool
pending_perf_counters :: handle_message(admin*,
                                        const server_id& si,
                                        network_msgtype mt,
                                        std::auto_ptr<e::buffer>,
                                        e::unpacker up,
                                        hyperdex_admin_returncode* status)
{
    *status = HYPERDEX_ADMIN_SUCCESS;
    set_status(HYPERDEX_ADMIN_SUCCESS);

    if (mt != PERF_COUNTERS)
    {
        YIELDING_ERROR(SERVERERROR) << "server " << si.get() << " responded to PERF_COUNTERS with wrong message type";
        return true;
    }

    e::slice rem = up.as_slice();
    char* ptr = const_cast<char*>(reinterpret_cast<const char*>(rem.data()));
    char* end = ptr + rem.size() - 1;
    uint64_t max_time = 0;

    // parse one line at a time
    while (ptr < end)
    {
        char* eol = reinterpret_cast<char*>(memchr(ptr, '\n', end - ptr));
        eol = eol ? eol : end;
        *eol = '\0';
        char* tmp = ptr;

        // parse the time
        tmp = strchr(ptr, ' ');
        tmp = tmp ? tmp : eol;
        *tmp = '\0';
        uint64_t time = strtoull(ptr, NULL, 0);
        max_time = std::max(time, max_time);
        ptr = tmp + 1;

        while (ptr < eol)
        {
            tmp = strchr(ptr, ' ');
            tmp = tmp ? tmp : eol;
            *tmp = '\0';

            char* equals = strchr(ptr, '=');
            equals = equals ? equals: tmp;
            *equals = '\0';
            uint64_t value = 0;

            if (equals < tmp)
            {
                ++equals;
                value = strtoull(equals, NULL, 0);
            }

            m_pcs.push_back(perf_counter(si.get(), time, ptr, value));
            ptr = tmp + 1;
        }

        ptr = eol + 1;
    }

    m_cutoffs[si] = max_time;
    return true;
}
<|endoftext|>


<commit_before>
/*
 * Copyright 2011 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */
#include "Test.h"
#include "SkPath.h"
#include "SkLineClipper.h"
#include "SkEdgeClipper.h"

#include "SkCanvas.h"
static void test_hairclipping(skiatest::Reporter* reporter) {
    SkBitmap bm;
    bm.setConfig(SkBitmap::kARGB_8888_Config, 4, 4);
    bm.allocPixels();
    bm.eraseColor(SK_ColorWHITE);

    SkPaint paint;
    paint.setAntiAlias(true);

    SkCanvas canvas(bm);
    canvas.clipRect(SkRect::MakeWH(4, 2));
    canvas.drawLine(1.5, 1.5, 3.5, 3.5, paint);

    /**
     *  We had a bug where we misinterpreted the bottom of the clip, and
     *  would draw another pixel (to the right in this case) on the same
     *  last scanline. i.e. we would draw to [2,1], even though this hairline
     *  should just draw to [1,1], [2,2], [3,3] modulo the clip.
     *
     *  The result of this entire draw should be that we only draw to [1,1]
     *
     *  Fixed in rev. 3366
     */
    for (int y = 0; y < 4; ++y) {
        for (int x = 0; x < 4; ++x) {
            bool nonWhite = (1 == y) && (1 == x);
            SkPMColor c = *bm.getAddr32(x, y);
            if (nonWhite) {
                REPORTER_ASSERT(reporter, 0xFFFFFFFF != c);
            } else {
                REPORTER_ASSERT(reporter, 0xFFFFFFFF == c);
            }
        }
    }
}

static void test_edgeclipper(skiatest::Reporter* reporter) {
    SkEdgeClipper clipper;

    const SkPoint pts[] = {
        { SkFloatToScalar(3.0995476e+010),  SkFloatToScalar(42.929779) },
        { SkFloatToScalar(-3.0995163e+010), SkFloatToScalar(51.050385) },
        { SkFloatToScalar(-3.0995157e+010), SkFloatToScalar(51.050392) },
        { SkFloatToScalar(-3.0995134e+010), SkFloatToScalar(51.050400) },
    };

    const SkRect clip = { 0, 0, SkIntToScalar(300), SkIntToScalar(200) };

    // this should not assert, even though our choppers do a poor numerical
    // job when computing their t values.
    // http://code.google.com/p/skia/issues/detail?id=444
    clipper.clipCubic(pts, clip);
}

static void test_intersectline(skiatest::Reporter* reporter) {
    static const SkScalar L = 0;
    static const SkScalar T = 0;
    static const SkScalar R = SkIntToScalar(100);
    static const SkScalar B = SkIntToScalar(100);
    static const SkScalar CX = SkScalarHalf(L + R);
    static const SkScalar CY = SkScalarHalf(T + B);
    static const SkRect gR = { L, T, R, B };

    size_t i;
    SkPoint dst[2];

    static const SkPoint gEmpty[] = {
        // sides
        { L, CY }, { L - 10, CY },
        { R, CY }, { R + 10, CY },
        { CX, T }, { CX, T - 10 },
        { CX, B }, { CX, B + 10 },
        // corners
        { L, T }, { L - 10, T - 10 },
        { L, B }, { L - 10, B + 10 },
        { R, T }, { R + 10, T - 10 },
        { R, B }, { R + 10, B + 10 },
    };
    for (i = 0; i < SK_ARRAY_COUNT(gEmpty); i += 2) {
        bool valid = SkLineClipper::IntersectLine(&gEmpty[i], gR, dst);
        if (valid) {
            SkDebugf("----- [%d] %g %g -> %g %g\n", i/2, dst[0].fX, dst[0].fY, dst[1].fX, dst[1].fY);
        }
        REPORTER_ASSERT(reporter, !valid);
    }

    static const SkPoint gFull[] = {
        // diagonals, chords
        { L, T }, { R, B },
        { L, B }, { R, T },
        { CX, T }, { CX, B },
        { L, CY }, { R, CY },
        { CX, T }, { R, CY },
        { CX, T }, { L, CY },
        { L, CY }, { CX, B },
        { R, CY }, { CX, B },
        // edges
        { L, T }, { L, B },
        { R, T }, { R, B },
        { L, T }, { R, T },
        { L, B }, { R, B },
    };
    for (i = 0; i < SK_ARRAY_COUNT(gFull); i += 2) {
        bool valid = SkLineClipper::IntersectLine(&gFull[i], gR, dst);
        if (!valid || memcmp(&gFull[i], dst, sizeof(dst))) {
            SkDebugf("++++ [%d] %g %g -> %g %g\n", i/2, dst[0].fX, dst[0].fY, dst[1].fX, dst[1].fY);
        }
        REPORTER_ASSERT(reporter, valid && !memcmp(&gFull[i], dst, sizeof(dst)));
    }

    static const SkPoint gPartial[] = {
        { L - 10, CY }, { CX, CY }, { L, CY }, { CX, CY },
        { CX, T - 10 }, { CX, CY }, { CX, T }, { CX, CY },
        { R + 10, CY }, { CX, CY }, { R, CY }, { CX, CY },
        { CX, B + 10 }, { CX, CY }, { CX, B }, { CX, CY },
        // extended edges
        { L, T - 10 }, { L, B + 10 }, { L, T }, { L, B },
        { R, T - 10 }, { R, B + 10 }, { R, T }, { R, B },
        { L - 10, T }, { R + 10, T }, { L, T }, { R, T },
        { L - 10, B }, { R + 10, B }, { L, B }, { R, B },
    };
    for (i = 0; i < SK_ARRAY_COUNT(gPartial); i += 4) {
        bool valid = SkLineClipper::IntersectLine(&gPartial[i], gR, dst);
        if (!valid || memcmp(&gPartial[i+2], dst, sizeof(dst))) {
            SkDebugf("++++ [%d] %g %g -> %g %g\n", i/2, dst[0].fX, dst[0].fY, dst[1].fX, dst[1].fY);
        }
        REPORTER_ASSERT(reporter, valid &&
                                  !memcmp(&gPartial[i+2], dst, sizeof(dst)));
    }

}

void TestClipper(skiatest::Reporter* reporter) {
    test_intersectline(reporter);
    test_edgeclipper(reporter);
    test_hairclipping(reporter);
}

#include "TestClassDef.h"
DEFINE_TESTCLASS("Clipper", TestClipperClass, TestClipper)
<commit_msg>promote floats to scalars for the fixed-point build<commit_after>
/*
 * Copyright 2011 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */
#include "Test.h"
#include "SkPath.h"
#include "SkLineClipper.h"
#include "SkEdgeClipper.h"

#include "SkCanvas.h"
static void test_hairclipping(skiatest::Reporter* reporter) {
    SkBitmap bm;
    bm.setConfig(SkBitmap::kARGB_8888_Config, 4, 4);
    bm.allocPixels();
    bm.eraseColor(SK_ColorWHITE);

    SkPaint paint;
    paint.setAntiAlias(true);

    SkCanvas canvas(bm);
    canvas.clipRect(SkRect::MakeWH(SkIntToScalar(4), SkIntToScalar(2)));
    canvas.drawLine(SkFloatToScalar(1.5), SkFloatToScalar(1.5),
                    SkFloatToScalar(3.5), SkFloatToScalar(3.5), paint);

    /**
     *  We had a bug where we misinterpreted the bottom of the clip, and
     *  would draw another pixel (to the right in this case) on the same
     *  last scanline. i.e. we would draw to [2,1], even though this hairline
     *  should just draw to [1,1], [2,2], [3,3] modulo the clip.
     *
     *  The result of this entire draw should be that we only draw to [1,1]
     *
     *  Fixed in rev. 3366
     */
    for (int y = 0; y < 4; ++y) {
        for (int x = 0; x < 4; ++x) {
            bool nonWhite = (1 == y) && (1 == x);
            SkPMColor c = *bm.getAddr32(x, y);
            if (nonWhite) {
                REPORTER_ASSERT(reporter, 0xFFFFFFFF != c);
            } else {
                REPORTER_ASSERT(reporter, 0xFFFFFFFF == c);
            }
        }
    }
}

static void test_edgeclipper(skiatest::Reporter* reporter) {
    SkEdgeClipper clipper;

    const SkPoint pts[] = {
        { SkFloatToScalar(3.0995476e+010),  SkFloatToScalar(42.929779) },
        { SkFloatToScalar(-3.0995163e+010), SkFloatToScalar(51.050385) },
        { SkFloatToScalar(-3.0995157e+010), SkFloatToScalar(51.050392) },
        { SkFloatToScalar(-3.0995134e+010), SkFloatToScalar(51.050400) },
    };

    const SkRect clip = { 0, 0, SkIntToScalar(300), SkIntToScalar(200) };

    // this should not assert, even though our choppers do a poor numerical
    // job when computing their t values.
    // http://code.google.com/p/skia/issues/detail?id=444
    clipper.clipCubic(pts, clip);
}

static void test_intersectline(skiatest::Reporter* reporter) {
    static const SkScalar L = 0;
    static const SkScalar T = 0;
    static const SkScalar R = SkIntToScalar(100);
    static const SkScalar B = SkIntToScalar(100);
    static const SkScalar CX = SkScalarHalf(L + R);
    static const SkScalar CY = SkScalarHalf(T + B);
    static const SkRect gR = { L, T, R, B };

    size_t i;
    SkPoint dst[2];

    static const SkPoint gEmpty[] = {
        // sides
        { L, CY }, { L - 10, CY },
        { R, CY }, { R + 10, CY },
        { CX, T }, { CX, T - 10 },
        { CX, B }, { CX, B + 10 },
        // corners
        { L, T }, { L - 10, T - 10 },
        { L, B }, { L - 10, B + 10 },
        { R, T }, { R + 10, T - 10 },
        { R, B }, { R + 10, B + 10 },
    };
    for (i = 0; i < SK_ARRAY_COUNT(gEmpty); i += 2) {
        bool valid = SkLineClipper::IntersectLine(&gEmpty[i], gR, dst);
        if (valid) {
            SkDebugf("----- [%d] %g %g -> %g %g\n", i/2, dst[0].fX, dst[0].fY, dst[1].fX, dst[1].fY);
        }
        REPORTER_ASSERT(reporter, !valid);
    }

    static const SkPoint gFull[] = {
        // diagonals, chords
        { L, T }, { R, B },
        { L, B }, { R, T },
        { CX, T }, { CX, B },
        { L, CY }, { R, CY },
        { CX, T }, { R, CY },
        { CX, T }, { L, CY },
        { L, CY }, { CX, B },
        { R, CY }, { CX, B },
        // edges
        { L, T }, { L, B },
        { R, T }, { R, B },
        { L, T }, { R, T },
        { L, B }, { R, B },
    };
    for (i = 0; i < SK_ARRAY_COUNT(gFull); i += 2) {
        bool valid = SkLineClipper::IntersectLine(&gFull[i], gR, dst);
        if (!valid || memcmp(&gFull[i], dst, sizeof(dst))) {
            SkDebugf("++++ [%d] %g %g -> %g %g\n", i/2, dst[0].fX, dst[0].fY, dst[1].fX, dst[1].fY);
        }
        REPORTER_ASSERT(reporter, valid && !memcmp(&gFull[i], dst, sizeof(dst)));
    }

    static const SkPoint gPartial[] = {
        { L - 10, CY }, { CX, CY }, { L, CY }, { CX, CY },
        { CX, T - 10 }, { CX, CY }, { CX, T }, { CX, CY },
        { R + 10, CY }, { CX, CY }, { R, CY }, { CX, CY },
        { CX, B + 10 }, { CX, CY }, { CX, B }, { CX, CY },
        // extended edges
        { L, T - 10 }, { L, B + 10 }, { L, T }, { L, B },
        { R, T - 10 }, { R, B + 10 }, { R, T }, { R, B },
        { L - 10, T }, { R + 10, T }, { L, T }, { R, T },
        { L - 10, B }, { R + 10, B }, { L, B }, { R, B },
    };
    for (i = 0; i < SK_ARRAY_COUNT(gPartial); i += 4) {
        bool valid = SkLineClipper::IntersectLine(&gPartial[i], gR, dst);
        if (!valid || memcmp(&gPartial[i+2], dst, sizeof(dst))) {
            SkDebugf("++++ [%d] %g %g -> %g %g\n", i/2, dst[0].fX, dst[0].fY, dst[1].fX, dst[1].fY);
        }
        REPORTER_ASSERT(reporter, valid &&
                                  !memcmp(&gPartial[i+2], dst, sizeof(dst)));
    }

}

void TestClipper(skiatest::Reporter* reporter) {
    test_intersectline(reporter);
    test_edgeclipper(reporter);
    test_hairclipping(reporter);
}

#include "TestClassDef.h"
DEFINE_TESTCLASS("Clipper", TestClipperClass, TestClipper)
<|endoftext|>


<commit_before>// Copyright (C) 2017 Rob Caelers <rob.caelers@gmail.com>
//
// 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 "os/NetworkErrors.hpp"

namespace
{
  struct NetworkErrCategory : std::error_category
  {
    const char* name() const noexcept override;
    std::string message(int ev) const override;
  };

  const char* NetworkErrCategory::name() const noexcept
  {
    return "network";
  }

  std::string NetworkErrCategory::message(int ev) const
  {
    switch (static_cast<os::NetworkErrc>(ev))
      {
      case os::NetworkErrc::Timeout:
        return "network timeout";
      case os::NetworkErrc::InternalError:
        return "internal error";
      case os::NetworkErrc::NameResolutionFailed:
        return "name resolution failed";
      case os::NetworkErrc::InvalidAddress:
        return "invalid address";
      case os::NetworkErrc::TLSProtocolError:
        return "TLS protocol error";
      case os::NetworkErrc::ConnectionRefused:
        return "connection refused";
      case os::NetworkErrc::ConnectionClosed:
        return "connection closed";
      case os::NetworkErrc::ReadError:
        return "read errors";
      case os::NetworkErrc::WriteError:
        return "write error";
      default:
        return "(unrecognized error)";
      }
  }

  const NetworkErrCategory theNetworkErrCategory {};
}

namespace os
{
  std::error_code make_error_code(NetworkErrc ec)
  {
    return {static_cast<int>(ec), theNetworkErrCategory};
  }
}
<commit_msg>Fix typo<commit_after>// Copyright (C) 2017 Rob Caelers <rob.caelers@gmail.com>
//
// 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 "os/NetworkErrors.hpp"

namespace
{
  struct NetworkErrCategory : std::error_category
  {
    const char* name() const noexcept override;
    std::string message(int ev) const override;
  };

  const char* NetworkErrCategory::name() const noexcept
  {
    return "network";
  }

  std::string NetworkErrCategory::message(int ev) const
  {
    switch (static_cast<os::NetworkErrc>(ev))
      {
      case os::NetworkErrc::Timeout:
        return "network timeout";
      case os::NetworkErrc::InternalError:
        return "internal error";
      case os::NetworkErrc::NameResolutionFailed:
        return "name resolution failed";
      case os::NetworkErrc::InvalidAddress:
        return "invalid address";
      case os::NetworkErrc::TLSProtocolError:
        return "TLS protocol error";
      case os::NetworkErrc::ConnectionRefused:
        return "connection refused";
      case os::NetworkErrc::ConnectionClosed:
        return "connection closed";
      case os::NetworkErrc::ReadError:
        return "read error";
      case os::NetworkErrc::WriteError:
        return "write error";
      default:
        return "(unrecognized error)";
      }
  }

  const NetworkErrCategory theNetworkErrCategory {};
}

namespace os
{
  std::error_code make_error_code(NetworkErrc ec)
  {
    return {static_cast<int>(ec), theNetworkErrCategory};
  }
}
<|endoftext|>


<commit_before>//
// Created by Red Dec on 21.04.15.
//

#include "serial.h"
#include <fcntl.h>

io::Serial::Serial(const std::string &path) {
    descriptor_ = open(path.c_str(), O_RDWR | O_NOCTTY);
    if (descriptor_ < 0) {
        set_error();
        return;
    }
    set_auto_close(true);
    set_attributes();
}

bool io::Serial::set_attributes(Speed speed, Parity parity, Bits bits) {
    if (has_error() || !has_valid_descriptor())return false;
    struct termios tty;
    memset(&tty, 0, sizeof tty);

    /* Error Handling */
    if (tcgetattr(descriptor_, &tty) != 0) {
        set_error();
        return false;
    }
    /* Set Baud Rate */
    cfsetospeed(&tty, static_cast<speed_t>(speed));
    cfsetispeed(&tty, static_cast<speed_t>(speed));

    /* Setting other Port Stuff */
    tty.c_cflag &= ~static_cast<uint32_t>(parity);               // Make 8n1
    tty.c_cflag &= ~CSTOPB;
    tty.c_cflag &= ~CSIZE;
    tty.c_cflag |= static_cast<uint32_t>(bits);

    tty.c_cflag &= ~CRTSCTS;              // no flow control
    tty.c_cc[VMIN] = 0;                   // 1 - nonblock
    tty.c_cc[VTIME] = 1;                  // 1 seconds read timeout
    tty.c_cflag |= CREAD | CLOCAL;        // turn on READ & ignore ctrl lines

    return true;
}<commit_msg>Serial port improvments<commit_after>//
// Created by Red Dec on 21.04.15.
//

#include "serial.h"
#include <fcntl.h>

io::Serial::Serial(const std::string &path) {
    descriptor_ = open(path.c_str(), O_RDWR | O_NOCTTY);
    if (descriptor_ < 0) {
        set_error();
        return;
    }
    set_auto_close(true);
    set_attributes();
}

bool io::Serial::set_attributes(Speed speed, Parity parity, Bits bits) {
    if (has_error() || !has_valid_descriptor())return false;
    struct termios tty;
    memset(&tty, 0, sizeof tty);

    /* Error Handling */
    if (tcgetattr(descriptor_, &tty) != 0) {
        set_error();
        return false;
    }
    /* Set Baud Rate */
    cfsetospeed(&tty, static_cast<speed_t>(speed));
    cfsetispeed(&tty, static_cast<speed_t>(speed));

    /* Setting other Port Stuff */
    tty.c_cflag &= ~static_cast<uint32_t>(parity);               // Make 8n1
    tty.c_cflag &= ~CSTOPB;
    tty.c_cflag &= ~CSIZE;
    tty.c_cflag |= static_cast<uint32_t>(bits);

    tty.c_cflag &= ~CRTSCTS;              // no flow control
    tty.c_cc[VMIN] = 1;                   // 1 - nonblock
    tty.c_cc[VTIME] = 5;                  // 1 seconds read timeout
    tty.c_cflag |= CREAD | CLOCAL;        // turn on READ & ignore ctrl lines
    tcflush(descriptor_, TCIFLUSH);

    if (tcsetattr(descriptor_, TCSANOW, &tty) != 0) {
        set_error();
        return false;
    }
    return true;
}<|endoftext|>


<commit_before>#include "blockindex.h"

#include "bignum.h"
#include "block.h"
#include "boost/shared_ptr.hpp"
#include "util.h"

CBlockIndex::CBlockIndex()
{
    blockHash              = 0;
    hashPrev               = 0;
    hashNext               = 0;
    nHeight                = 0;
    nChainTrust            = 0;
    nFlags                 = 0;
    nStakeModifier         = 0;
    nStakeModifierChecksum = 0;
    hashProof              = 0;
    prevoutStake.SetNull();
    nStakeTime = 0;

    nVersion       = 0;
    hashMerkleRoot = 0;
    nTime          = 0;
    nBits          = 0;
    nNonce         = 0;
}

CBlockIndex::CBlockIndex(uint256 blockHashIn, const CBlock& block)
{
    blockHash              = blockHashIn;
    hashPrev               = 0;
    hashNext               = 0;
    nHeight                = 0;
    nChainTrust            = 0;
    nFlags                 = 0;
    nStakeModifier         = 0;
    nStakeModifierChecksum = 0;
    hashProof              = 0;
    if (block.IsProofOfStake()) {
        SetProofOfStake();
        prevoutStake = block.vtx[1].vin[0].prevout;
        nStakeTime   = block.vtx[1].nTime;
    } else {
        prevoutStake.SetNull();
        nStakeTime = 0;
    }

    nVersion       = block.nVersion;
    hashMerkleRoot = block.hashMerkleRoot;
    nTime          = block.nTime;
    nBits          = block.nBits;
    nNonce         = block.nNonce;
}

CBlock CBlockIndex::GetBlockHeader() const
{
    CBlock block;
    block.nVersion       = nVersion;
    block.hashPrevBlock  = hashPrev;
    block.hashMerkleRoot = hashMerkleRoot;
    block.nTime          = nTime;
    block.nBits          = nBits;
    block.nNonce         = nNonce;
    return block;
}

uint256 CBlockIndex::GetBlockHash() const { return blockHash; }

int64_t CBlockIndex::GetBlockTime() const { return (int64_t)nTime; }

std::string CBlockIndex::ToString() const
{
    return fmt::format("CBlockIndex(hashPrev={}, hashNext={}, nHeight={}, "
                       "nFlags=({})({})({}), nStakeModifier={:x}"
                       ", nStakeModifierChecksum={:x}, hashProof={}, prevoutStake=({}), nStakeTime={} "
                       "merkle={}, hashBlock={})",
                       hashPrev.ToString(), hashNext.ToString(), nHeight,
                       GeneratedStakeModifier() ? "MOD" : "-", GetStakeEntropyBit(),
                       IsProofOfStake() ? "PoS" : "PoW", nStakeModifier, nStakeModifierChecksum,
                       hashProof.ToString(), prevoutStake.ToString(), nStakeTime,
                       hashMerkleRoot.ToString(), GetBlockHash().ToString());
}

void CBlockIndex::print() const { NLog.write(b_sev::info, "{}", ToString()); }

boost::optional<CBlockIndex> CBlockIndex::getPrev(const ITxDB& txdb) const
{
    if (hashPrev != 0) {
        return txdb.ReadBlockIndex(hashPrev);
    } else {
        return boost::none;
    }
}

boost::optional<CBlockIndex> CBlockIndex::getNext(const ITxDB& txdb) const
{
    if (hashNext != 0) {
        return txdb.ReadBlockIndex(hashNext);
    } else {
        return boost::none;
    }
}

uint256 CBlockIndex::GetBlockTrust() const
{
    CBigNum bnTarget;
    bnTarget.SetCompact(nBits);

    if (bnTarget <= 0)
        return 0;

    return ((CBigNum(1) << 256) / (bnTarget + 1)).getuint256();
}

bool CBlockIndex::IsInMainChain(const ITxDB& txdb) const
{
    return (hashNext != 0 || blockHash == txdb.GetBestBlockHash());
}

int64_t CBlockIndex::GetPastTimeLimit(const ITxDB& txdb) const { return GetMedianTimePast(txdb); }

int64_t CBlockIndex::GetMedianTimePast(const ITxDB& txdb) const
{
    int64_t  pmedian[nMedianTimeSpan];
    int64_t* pbegin = &pmedian[nMedianTimeSpan];
    int64_t* pend   = &pmedian[nMedianTimeSpan];

    CBlockIndex index = *this;
    for (int i = 0; i < nMedianTimeSpan; i++) {
        *(--pbegin)                     = index.GetBlockTime();
        boost::optional<CBlockIndex> bi = index.getPrev(txdb);
        if (!bi) {
            break;
        }
        index = std::move(*bi);
    }

    std::sort(pbegin, pend);
    return pbegin[(pend - pbegin) / 2];
}

bool CBlockIndex::IsProofOfWork() const { return !(nFlags & BLOCK_PROOF_OF_STAKE); }

bool CBlockIndex::IsProofOfStake() const { return (nFlags & BLOCK_PROOF_OF_STAKE); }

void CBlockIndex::SetProofOfStake() { nFlags |= BLOCK_PROOF_OF_STAKE; }

unsigned int CBlockIndex::GetStakeEntropyBit() const { return ((nFlags & BLOCK_STAKE_ENTROPY) >> 1); }

bool CBlockIndex::SetStakeEntropyBit(unsigned int nEntropyBit)
{
    if (nEntropyBit > 1)
        return false;
    nFlags |= (nEntropyBit ? BLOCK_STAKE_ENTROPY : 0);
    return true;
}

bool CBlockIndex::GeneratedStakeModifier() const { return (nFlags & BLOCK_STAKE_MODIFIER); }

void CBlockIndex::SetStakeModifier(uint64_t nModifier, bool fGeneratedStakeModifier)
{
    nStakeModifier = nModifier;
    if (fGeneratedStakeModifier)
        nFlags |= BLOCK_STAKE_MODIFIER;
}
<commit_msg>Add caching for calculating median time past in CBlockIndex<commit_after>#include "blockindex.h"

#include "bignum.h"
#include "block.h"
#include "blockindexlrucache.h"
#include "boost/shared_ptr.hpp"
#include "util.h"

CBlockIndex::CBlockIndex()
{
    blockHash              = 0;
    hashPrev               = 0;
    hashNext               = 0;
    nHeight                = 0;
    nChainTrust            = 0;
    nFlags                 = 0;
    nStakeModifier         = 0;
    nStakeModifierChecksum = 0;
    hashProof              = 0;
    prevoutStake.SetNull();
    nStakeTime = 0;

    nVersion       = 0;
    hashMerkleRoot = 0;
    nTime          = 0;
    nBits          = 0;
    nNonce         = 0;
}

CBlockIndex::CBlockIndex(uint256 blockHashIn, const CBlock& block)
{
    blockHash              = blockHashIn;
    hashPrev               = 0;
    hashNext               = 0;
    nHeight                = 0;
    nChainTrust            = 0;
    nFlags                 = 0;
    nStakeModifier         = 0;
    nStakeModifierChecksum = 0;
    hashProof              = 0;
    if (block.IsProofOfStake()) {
        SetProofOfStake();
        prevoutStake = block.vtx[1].vin[0].prevout;
        nStakeTime   = block.vtx[1].nTime;
    } else {
        prevoutStake.SetNull();
        nStakeTime = 0;
    }

    nVersion       = block.nVersion;
    hashMerkleRoot = block.hashMerkleRoot;
    nTime          = block.nTime;
    nBits          = block.nBits;
    nNonce         = block.nNonce;
}

CBlock CBlockIndex::GetBlockHeader() const
{
    CBlock block;
    block.nVersion       = nVersion;
    block.hashPrevBlock  = hashPrev;
    block.hashMerkleRoot = hashMerkleRoot;
    block.nTime          = nTime;
    block.nBits          = nBits;
    block.nNonce         = nNonce;
    return block;
}

uint256 CBlockIndex::GetBlockHash() const { return blockHash; }

int64_t CBlockIndex::GetBlockTime() const { return (int64_t)nTime; }

std::string CBlockIndex::ToString() const
{
    return fmt::format("CBlockIndex(hashPrev={}, hashNext={}, nHeight={}, "
                       "nFlags=({})({})({}), nStakeModifier={:x}"
                       ", nStakeModifierChecksum={:x}, hashProof={}, prevoutStake=({}), nStakeTime={} "
                       "merkle={}, hashBlock={})",
                       hashPrev.ToString(), hashNext.ToString(), nHeight,
                       GeneratedStakeModifier() ? "MOD" : "-", GetStakeEntropyBit(),
                       IsProofOfStake() ? "PoS" : "PoW", nStakeModifier, nStakeModifierChecksum,
                       hashProof.ToString(), prevoutStake.ToString(), nStakeTime,
                       hashMerkleRoot.ToString(), GetBlockHash().ToString());
}

void CBlockIndex::print() const { NLog.write(b_sev::info, "{}", ToString()); }

boost::optional<CBlockIndex> CBlockIndex::getPrev(const ITxDB& txdb) const
{
    if (hashPrev != 0) {
        return txdb.ReadBlockIndex(hashPrev);
    } else {
        return boost::none;
    }
}

boost::optional<CBlockIndex> CBlockIndex::getNext(const ITxDB& txdb) const
{
    if (hashNext != 0) {
        return txdb.ReadBlockIndex(hashNext);
    } else {
        return boost::none;
    }
}

uint256 CBlockIndex::GetBlockTrust() const
{
    CBigNum bnTarget;
    bnTarget.SetCompact(nBits);

    if (bnTarget <= 0)
        return 0;

    return ((CBigNum(1) << 256) / (bnTarget + 1)).getuint256();
}

bool CBlockIndex::IsInMainChain(const ITxDB& txdb) const
{
    return (hashNext != 0 || blockHash == txdb.GetBestBlockHash());
}

int64_t CBlockIndex::GetPastTimeLimit(const ITxDB& txdb) const { return GetMedianTimePast(txdb); }

int64_t CBlockIndex::GetMedianTimePast(const ITxDB& txdb) const
{
    int64_t  pmedian[nMedianTimeSpan];
    int64_t* pbegin = &pmedian[nMedianTimeSpan];
    int64_t* pend   = &pmedian[nMedianTimeSpan];

    using BlockTimeCacheType = BlockIndexLRUCache<int64_t, boost::mutex>;

    static typename BlockTimeCacheType::ExtractorFunc extractorFunc =
        [](const CBlockIndex& bi) -> int64_t { return bi.GetBlockTime(); };

    static BlockTimeCacheType blockTimeCache(500, extractorFunc);

    uint256 currHash = this->GetBlockHash();
    blockTimeCache.manualAdd(*this);
    for (int i = 0; i < nMedianTimeSpan; i++) {
        const boost::optional<BlockTimeCacheType::BICacheEntry> blockTime =
            blockTimeCache.get(txdb, currHash);
        if (!blockTime) {
            NLog.write(b_sev::err, "CRITICAL ERROR: block not found while calculating target");
            break;
        }

        *(--pbegin) = blockTime->value;

        // move to the previous block
        if (blockTime->prevHash != 0) {
            currHash = blockTime->prevHash;
        } else {
            if (currHash != Params().GenesisBlockHash()) {
                NLog.write(b_sev::critical,
                           "CRITICAL ERROR: prev block has zero hash even though it's not genesis. "
                           "THIS SHOULD NEVER HAPPEN. Database corrupt?");
            }
        }
    }

    std::sort(pbegin, pend);
    return pbegin[(pend - pbegin) / 2];
}

bool CBlockIndex::IsProofOfWork() const { return !(nFlags & BLOCK_PROOF_OF_STAKE); }

bool CBlockIndex::IsProofOfStake() const { return (nFlags & BLOCK_PROOF_OF_STAKE); }

void CBlockIndex::SetProofOfStake() { nFlags |= BLOCK_PROOF_OF_STAKE; }

unsigned int CBlockIndex::GetStakeEntropyBit() const { return ((nFlags & BLOCK_STAKE_ENTROPY) >> 1); }

bool CBlockIndex::SetStakeEntropyBit(unsigned int nEntropyBit)
{
    if (nEntropyBit > 1)
        return false;
    nFlags |= (nEntropyBit ? BLOCK_STAKE_ENTROPY : 0);
    return true;
}

bool CBlockIndex::GeneratedStakeModifier() const { return (nFlags & BLOCK_STAKE_MODIFIER); }

void CBlockIndex::SetStakeModifier(uint64_t nModifier, bool fGeneratedStakeModifier)
{
    nStakeModifier = nModifier;
    if (fGeneratedStakeModifier)
        nFlags |= BLOCK_STAKE_MODIFIER;
}
<|endoftext|>


<commit_before>/*  This file is part of the Vc library. {{{
Copyright © 2015 Matthias Kretz <kretz@kde.org>
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in the
      documentation and/or other materials provided with the distribution.
    * Neither the names of contributing organizations nor the
      names of its contributors may be used to endorse or promote products
      derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

}}}*/

#include "unittest.h"

template <std::size_t N> using Int = std::integral_constant<std::size_t, N>;

template <std::size_t A> struct Foo : public Vc::AlignedBase
{
    static constexpr std::size_t alignment() { return A; }
    int x;
};

std::uintptr_t addressOf(void *ptr)
{
    return reinterpret_cast<std::uintptr_t>(ptr);
}

void *blackhole = nullptr;

TEST_TYPES(A, alignedbase,
           (Int<4>, Int<8>, Int<16>, Int<32>, Int<64>, Int<128>, Int<256>))
{
    using T = Foo;
    COMPARE(alignof(T), A::value);
    char padding = 1;
    blackhole = &padding;
    T onStack;
    COMPARE(addressOf(&onStack) & (A::value - 1), 0u);

    std::unique_ptr<T[]> onHeap{new T[3]};
    COMPARE(addressOf(&onHeap[0]) & (A::value - 1), 0u);
    COMPARE(addressOf(&onHeap[1]) & (A::value - 1), 0u);
    COMPARE(addressOf(&onHeap[2]) & (A::value - 1), 0u);
}

template <typename T> struct VectorAligned : public Vc::VectorAlignedBase<T>
{
    int x;
};

TEST_TYPES(N, vectoralignedbase,
           (Int<4>, Int<8>, Int<16>, Int<32>, Int<64>, Int<128>, Int<256>))
{
    using V = Vc::SimdMaskArray<int, N::value>;
    using T = VectorAligned<V>;
    constexpr auto A = alignof(V);
    COMPARE(alignof(T), A);
    char padding = 1;
    blackhole = &padding;
    T onStack;
    COMPARE(addressOf(&onStack) & (A - 1), 0u);

    std::unique_ptr<T[]> onHeap{new T[3]};
    COMPARE(addressOf(&onHeap[0]) & (A - 1), 0u);
    COMPARE(addressOf(&onHeap[1]) & (A - 1), 0u);
    COMPARE(addressOf(&onHeap[2]) & (A - 1), 0u);
}

template <typename T> struct MemoryAligned : public Vc::MemoryAlignedBase<T>
{
    int x;
};

TEST_TYPES(N, memoryalignedbase,
           (Int<4>, Int<8>, Int<16>, Int<32>, Int<64>, Int<128>, Int<256>))
{
    using V = Vc::SimdMaskArray<int, N::value>;
    using T = MemoryAligned<V>;
    constexpr auto A = V::MemoryAlignment;
    COMPARE(alignof(T), A);
    char padding = 1;
    blackhole = &padding;
    T onStack;
    COMPARE(addressOf(&onStack) & (A - 1), 0u);

    std::unique_ptr<T[]> onHeap{new T[3]};
    COMPARE(addressOf(&onHeap[0]) & (A - 1), 0u);
    COMPARE(addressOf(&onHeap[1]) & (A - 1), 0u);
    COMPARE(addressOf(&onHeap[2]) & (A - 1), 0u);
}

// vim: foldmethod=marker
<commit_msg>Drop test for 256-Byte alignment<commit_after>/*  This file is part of the Vc library. {{{
Copyright © 2015 Matthias Kretz <kretz@kde.org>
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in the
      documentation and/or other materials provided with the distribution.
    * Neither the names of contributing organizations nor the
      names of its contributors may be used to endorse or promote products
      derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

}}}*/

#include "unittest.h"

template <std::size_t N> using Int = std::integral_constant<std::size_t, N>;

template <std::size_t A> struct Foo : public Vc::AlignedBase
{
    static constexpr std::size_t alignment() { return A; }
    int x;
};

std::uintptr_t addressOf(void *ptr)
{
    return reinterpret_cast<std::uintptr_t>(ptr);
}

void *blackhole = nullptr;

TEST_TYPES(A, alignedbase, (Int<4>, Int<8>, Int<16>, Int<32>, Int<64>, Int<128>))
{
    using T = Foo;
    COMPARE(alignof(T), A::value);
    char padding = 1;
    blackhole = &padding;
    T onStack;
    COMPARE(addressOf(&onStack) & (A::value - 1), 0u);

    std::unique_ptr<T[]> onHeap{new T[3]};
    COMPARE(addressOf(&onHeap[0]) & (A::value - 1), 0u);
    COMPARE(addressOf(&onHeap[1]) & (A::value - 1), 0u);
    COMPARE(addressOf(&onHeap[2]) & (A::value - 1), 0u);
}

template <typename T> struct VectorAligned : public Vc::VectorAlignedBase<T>
{
    int x;
};

TEST_TYPES(N, vectoralignedbase,
           (Int<4>, Int<8>, Int<16>, Int<32>, Int<64>, Int<128>, Int<256>))
{
    using V = Vc::SimdMaskArray<int, N::value>;
    using T = VectorAligned<V>;
    constexpr auto A = alignof(V);
    COMPARE(alignof(T), A);
    char padding = 1;
    blackhole = &padding;
    T onStack;
    COMPARE(addressOf(&onStack) & (A - 1), 0u);

    std::unique_ptr<T[]> onHeap{new T[3]};
    COMPARE(addressOf(&onHeap[0]) & (A - 1), 0u);
    COMPARE(addressOf(&onHeap[1]) & (A - 1), 0u);
    COMPARE(addressOf(&onHeap[2]) & (A - 1), 0u);
}

template <typename T> struct MemoryAligned : public Vc::MemoryAlignedBase<T>
{
    int x;
};

TEST_TYPES(N, memoryalignedbase,
           (Int<4>, Int<8>, Int<16>, Int<32>, Int<64>, Int<128>, Int<256>))
{
    using V = Vc::SimdMaskArray<int, N::value>;
    using T = MemoryAligned<V>;
    constexpr auto A = V::MemoryAlignment;
    COMPARE(alignof(T), A);
    char padding = 1;
    blackhole = &padding;
    T onStack;
    COMPARE(addressOf(&onStack) & (A - 1), 0u);

    std::unique_ptr<T[]> onHeap{new T[3]};
    COMPARE(addressOf(&onHeap[0]) & (A - 1), 0u);
    COMPARE(addressOf(&onHeap[1]) & (A - 1), 0u);
    COMPARE(addressOf(&onHeap[2]) & (A - 1), 0u);
}

// vim: foldmethod=marker
<|endoftext|>


<commit_before>// Copyright 2015 Toggl Desktop developers.

#include "../src/netconf.h"

#include <string>
#include <sstream>
#include <winhttp.h>

#include "./https_client.h"

#include "Poco/Environment.h"
#include "Poco/Logger.h"
#include "Poco/Net/HTTPCredentials.h"
#include "Poco/Net/HTTPSClientSession.h"
#include "Poco/URI.h"

#ifdef __MACH__
#include <CoreFoundation/CoreFoundation.h>  // NOLINT
#include <CoreServices/CoreServices.h>  // NOLINT
#endif

namespace toggl {

error Netconf::autodetectProxy(
    const std::string &encoded_url,
    std::string *proxy_url) {

    *proxy_url = "";

    // Inspired from Stack Overflow
    // http://stackoverflow.com/questions/202547/how-do-i-find-out-the-browsers-proxy-settings
#ifdef _WIN32
    if (WinHttpGetIEProxyConfigForCurrentUser(&ieProxyConfig)) {
        if (ieProxyConfig.fAutoDetect) {
            fAutoProxy = TRUE;
        }

        if (ieProxyConfig.lpszAutoConfigUrl != NULL) {
            fAutoProxy = TRUE;
            autoProxyOptions.lpszAutoConfigUrl =
                ieProxyConfig.lpszAutoConfigUrl;
        }
    } else {
        // use autoproxy
        fAutoProxy = TRUE;
    }

    if (fAutoProxy) {
        if (autoProxyOptions.lpszAutoConfigUrl != NULL) {
            autoProxyOptions.dwFlags = WINHTTP_AUTOPROXY_CONFIG_URL;
        } else {
            autoProxyOptions.dwFlags = WINHTTP_AUTOPROXY_AUTO_DETECT;
            autoProxyOptions.dwAutoDetectFlags =
                WINHTTP_AUTO_DETECT_TYPE_DHCP | WINHTTP_AUTO_DETECT_TYPE_DNS_A;
        }

        // basic flags you almost always want
        autoProxyOptions.fAutoLogonIfChallenged = TRUE;

        // here we reset fAutoProxy in case an auto-proxy isn't actually
        // configured for this url
        fAutoProxy = WinHttpGetProxyForUrl(
            hiOpen, pwszUrl, &autoProxyOptions, &autoProxyInfo);
    }

    if (fAutoProxy) {
        // set proxy options for libcurl based on autoProxyInfo
    } else {
        if (ieProxyConfig.lpszProxy != NULL) {
            // IE has an explicit proxy. set proxy options for libcurl here
            // based on ieProxyConfig
            //
            // note that sometimes IE gives just a single or double colon
            // for proxy or bypass list, which means "no proxy"
        } else {
            // there is no auto proxy and no manually configured proxy
        }
    }
#endif

    // Inspider by VLC source code
    // https://github.com/videolan/vlc/blob/master/src/darwin/netconf.c
#ifdef __MACH__
    CFDictionaryRef dicRef = CFNetworkCopySystemProxySettings();
    if (NULL != dicRef) {
        const CFStringRef proxyCFstr = (const CFStringRef)CFDictionaryGetValue(
            dicRef, (const void*)kCFNetworkProxiesHTTPProxy);
        const CFNumberRef portCFnum = (const CFNumberRef)CFDictionaryGetValue(
            dicRef, (const void*)kCFNetworkProxiesHTTPPort);
        if (NULL != proxyCFstr && NULL != portCFnum) {
            int port = 0;
            if (!CFNumberGetValue(portCFnum, kCFNumberIntType, &port)) {
                CFRelease(dicRef);
                return noError;
            }

            const std::size_t kBufsize(4096);
            char host_buffer[kBufsize];
            memset(host_buffer, 0, sizeof(host_buffer));
            if (CFStringGetCString(proxyCFstr, host_buffer, sizeof(host_buffer)
                                   - 1, kCFStringEncodingUTF8)) {
                char buffer[kBufsize];
                snprintf(buffer, kBufsize, "%s:%d", host_buffer, port);
                *proxy_url = std::string(buffer);
            }
        }

        CFRelease(dicRef);
    }
#endif

    return noError;
}

void Netconf::ConfigureProxy(
    const std::string encoded_url,
    Poco::Net::HTTPSClientSession *session) {

    Poco::Logger &logger = Poco::Logger::get("ConfigureProxy");

    std::string proxy_url("");
    if (HTTPSClient::Config.AutodetectProxy) {
        if (Poco::Environment::has("HTTP_PROXY")) {
            proxy_url = Poco::Environment::get("HTTP_PROXY");
        }
        if (proxy_url.empty()) {
            error err = autodetectProxy(encoded_url, &proxy_url);
        }
        if (proxy_url.find("://") == std::string::npos) {
            proxy_url = "http://" + proxy_url;
        }
        Poco::URI proxy_uri(proxy_url);

        std::stringstream ss;
        ss << "Proxy detected URI=" + proxy_uri.toString()
           << " host=" << proxy_uri.getHost()
           << " port=" << proxy_uri.getPort();
        logger.debug(ss.str());

        session->setProxy(
            proxy_uri.getHost(),
            proxy_uri.getPort());

        if (!proxy_uri.getUserInfo().empty()) {
            Poco::Net::HTTPCredentials credentials;
            credentials.fromUserInfo(proxy_uri.getUserInfo());
            session->setProxyCredentials(
                credentials.getUsername(),
                credentials.getPassword());

            logger.debug("Proxy credentials detected username="
                         + credentials.getUsername());
        }
    }

    // Try to use user-configured proxy
    if (proxy_url.empty() && HTTPSClient::Config.UseProxy &&
            HTTPSClient::Config.ProxySettings.IsConfigured()) {
        session->setProxy(
            HTTPSClient::Config.ProxySettings.Host(),
            static_cast<Poco::UInt16>(
                HTTPSClient::Config.ProxySettings.Port()));

        std::stringstream ss;
        ss << "Proxy configured "
           << " host=" << HTTPSClient::Config.ProxySettings.Host()
           << " port=" << HTTPSClient::Config.ProxySettings.Port();
        logger.debug(ss.str());

        if (HTTPSClient::Config.ProxySettings.HasCredentials()) {
            session->setProxyCredentials(
                HTTPSClient::Config.ProxySettings.Username(),
                HTTPSClient::Config.ProxySettings.Password());

            logger.debug("Proxy credentials configured username="
                         + HTTPSClient::Config.ProxySettings.Username());
        }
    }
}

}   // namespace toggl
<commit_msg>netconf include winhttp only for windows (win)<commit_after>// Copyright 2015 Toggl Desktop developers.

#include "../src/netconf.h"

#include <string>
#include <sstream>
#ifdef _WIN32
	#include <winhttp.h>
#endif

#include "./https_client.h"

#include "Poco/Environment.h"
#include "Poco/Logger.h"
#include "Poco/Net/HTTPCredentials.h"
#include "Poco/Net/HTTPSClientSession.h"
#include "Poco/URI.h"

#ifdef __MACH__
#include <CoreFoundation/CoreFoundation.h>  // NOLINT
#include <CoreServices/CoreServices.h>  // NOLINT
#endif

namespace toggl {

error Netconf::autodetectProxy(
    const std::string &encoded_url,
    std::string *proxy_url) {

    *proxy_url = "";

    // Inspired from Stack Overflow
    // http://stackoverflow.com/questions/202547/how-do-i-find-out-the-browsers-proxy-settings
#ifdef _WIN32
    if (WinHttpGetIEProxyConfigForCurrentUser(&ieProxyConfig)) {
        if (ieProxyConfig.fAutoDetect) {
            fAutoProxy = TRUE;
        }

        if (ieProxyConfig.lpszAutoConfigUrl != NULL) {
            fAutoProxy = TRUE;
            autoProxyOptions.lpszAutoConfigUrl =
                ieProxyConfig.lpszAutoConfigUrl;
        }
    } else {
        // use autoproxy
        fAutoProxy = TRUE;
    }

    if (fAutoProxy) {
        if (autoProxyOptions.lpszAutoConfigUrl != NULL) {
            autoProxyOptions.dwFlags = WINHTTP_AUTOPROXY_CONFIG_URL;
        } else {
            autoProxyOptions.dwFlags = WINHTTP_AUTOPROXY_AUTO_DETECT;
            autoProxyOptions.dwAutoDetectFlags =
                WINHTTP_AUTO_DETECT_TYPE_DHCP | WINHTTP_AUTO_DETECT_TYPE_DNS_A;
        }

        // basic flags you almost always want
        autoProxyOptions.fAutoLogonIfChallenged = TRUE;

        // here we reset fAutoProxy in case an auto-proxy isn't actually
        // configured for this url
        fAutoProxy = WinHttpGetProxyForUrl(
            hiOpen, pwszUrl, &autoProxyOptions, &autoProxyInfo);
    }

    if (fAutoProxy) {
        // set proxy options for libcurl based on autoProxyInfo
    } else {
        if (ieProxyConfig.lpszProxy != NULL) {
            // IE has an explicit proxy. set proxy options for libcurl here
            // based on ieProxyConfig
            //
            // note that sometimes IE gives just a single or double colon
            // for proxy or bypass list, which means "no proxy"
        } else {
            // there is no auto proxy and no manually configured proxy
        }
    }
#endif

    // Inspider by VLC source code
    // https://github.com/videolan/vlc/blob/master/src/darwin/netconf.c
#ifdef __MACH__
    CFDictionaryRef dicRef = CFNetworkCopySystemProxySettings();
    if (NULL != dicRef) {
        const CFStringRef proxyCFstr = (const CFStringRef)CFDictionaryGetValue(
            dicRef, (const void*)kCFNetworkProxiesHTTPProxy);
        const CFNumberRef portCFnum = (const CFNumberRef)CFDictionaryGetValue(
            dicRef, (const void*)kCFNetworkProxiesHTTPPort);
        if (NULL != proxyCFstr && NULL != portCFnum) {
            int port = 0;
            if (!CFNumberGetValue(portCFnum, kCFNumberIntType, &port)) {
                CFRelease(dicRef);
                return noError;
            }

            const std::size_t kBufsize(4096);
            char host_buffer[kBufsize];
            memset(host_buffer, 0, sizeof(host_buffer));
            if (CFStringGetCString(proxyCFstr, host_buffer, sizeof(host_buffer)
                                   - 1, kCFStringEncodingUTF8)) {
                char buffer[kBufsize];
                snprintf(buffer, kBufsize, "%s:%d", host_buffer, port);
                *proxy_url = std::string(buffer);
            }
        }

        CFRelease(dicRef);
    }
#endif

    return noError;
}

void Netconf::ConfigureProxy(
    const std::string encoded_url,
    Poco::Net::HTTPSClientSession *session) {

    Poco::Logger &logger = Poco::Logger::get("ConfigureProxy");

    std::string proxy_url("");
    if (HTTPSClient::Config.AutodetectProxy) {
        if (Poco::Environment::has("HTTP_PROXY")) {
            proxy_url = Poco::Environment::get("HTTP_PROXY");
        }
        if (proxy_url.empty()) {
            error err = autodetectProxy(encoded_url, &proxy_url);
        }
        if (proxy_url.find("://") == std::string::npos) {
            proxy_url = "http://" + proxy_url;
        }
        Poco::URI proxy_uri(proxy_url);

        std::stringstream ss;
        ss << "Proxy detected URI=" + proxy_uri.toString()
           << " host=" << proxy_uri.getHost()
           << " port=" << proxy_uri.getPort();
        logger.debug(ss.str());

        session->setProxy(
            proxy_uri.getHost(),
            proxy_uri.getPort());

        if (!proxy_uri.getUserInfo().empty()) {
            Poco::Net::HTTPCredentials credentials;
            credentials.fromUserInfo(proxy_uri.getUserInfo());
            session->setProxyCredentials(
                credentials.getUsername(),
                credentials.getPassword());

            logger.debug("Proxy credentials detected username="
                         + credentials.getUsername());
        }
    }

    // Try to use user-configured proxy
    if (proxy_url.empty() && HTTPSClient::Config.UseProxy &&
            HTTPSClient::Config.ProxySettings.IsConfigured()) {
        session->setProxy(
            HTTPSClient::Config.ProxySettings.Host(),
            static_cast<Poco::UInt16>(
                HTTPSClient::Config.ProxySettings.Port()));

        std::stringstream ss;
        ss << "Proxy configured "
           << " host=" << HTTPSClient::Config.ProxySettings.Host()
           << " port=" << HTTPSClient::Config.ProxySettings.Port();
        logger.debug(ss.str());

        if (HTTPSClient::Config.ProxySettings.HasCredentials()) {
            session->setProxyCredentials(
                HTTPSClient::Config.ProxySettings.Username(),
                HTTPSClient::Config.ProxySettings.Password());

            logger.debug("Proxy credentials configured username="
                         + HTTPSClient::Config.ProxySettings.Username());
        }
    }
}

}   // namespace toggl
<|endoftext|>