<commit_before>/*

Copyright (c) 2006, 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.

*/

#ifndef TORRENT_SESSION_HPP_INCLUDED
#define TORRENT_SESSION_HPP_INCLUDED

#include <ctime>
#include <algorithm>
#include <vector>
#include <set>
#include <list>
#include <deque>

#ifdef _MSC_VER
#pragma warning(push, 1)
#endif

#include <boost/limits.hpp>
#include <boost/tuple/tuple.hpp>
#include <boost/filesystem/path.hpp>
#include <boost/thread.hpp>

#ifdef _MSC_VER
#pragma warning(pop)
#endif

#include "libtorrent/config.hpp"
#include "libtorrent/torrent_handle.hpp"
#include "libtorrent/entry.hpp"
#include "libtorrent/alert.hpp"
#include "libtorrent/session_status.hpp"
#include "libtorrent/version.hpp"
#include "libtorrent/fingerprint.hpp"

#include "libtorrent/storage.hpp"

#ifdef _MSC_VER
#	include <eh.h>
#endif

namespace libtorrent
{
	struct torrent_plugin;
	class torrent;
	class ip_filter;
	class port_filter;
	class connection_queue;

	namespace fs = boost::filesystem;

	namespace aux
	{
		// workaround for microsofts
		// hardware exceptions that makes
		// it hard to debug stuff
#ifdef _MSC_VER
		struct eh_initializer
		{
			eh_initializer()
			{
				::_set_se_translator(straight_to_debugger);
			}

			static void straight_to_debugger(unsigned int, _EXCEPTION_POINTERS*)
			{ throw; }
		};
#else
		struct eh_initializer {};
#endif
		struct session_impl;

		struct filesystem_init
		{
			filesystem_init();
		};

	}

	class TORRENT_EXPORT session_proxy
	{
		friend class session;
	public:
		session_proxy() {}
	private:
		session_proxy(boost::shared_ptr<aux::session_impl> impl)
			: m_impl(impl) {}
		boost::shared_ptr<aux::session_impl> m_impl;
	};

	class TORRENT_EXPORT session: public boost::noncopyable, aux::eh_initializer
	{
	public:

		session(fingerprint const& print = fingerprint("LT"
			, LIBTORRENT_VERSION_MAJOR, LIBTORRENT_VERSION_MINOR, 0, 0));
		session(
			fingerprint const& print
			, std::pair<int, int> listen_port_range
			, char const* listen_interface = "0.0.0.0");

		~session();

		// returns a list of all torrents in this session
		std::vector<torrent_handle> get_torrents() const;

		// returns an invalid handle in case the torrent doesn't exist
		torrent_handle find_torrent(sha1_hash const& info_hash) const;

		// all torrent_handles must be destructed before the session is destructed!
		torrent_handle add_torrent(
			torrent_info const& ti
			, fs::path const& save_path
			, entry const& resume_data = entry()
			, bool compact_mode = true
			, bool paused = false
			, storage_constructor_type sc = default_storage_constructor);

		torrent_handle add_torrent(
			char const* tracker_url
			, sha1_hash const& info_hash
			, char const* name
			, fs::path const& save_path
			, entry const& resume_data = entry()
			, bool compact_mode = true
			, bool paused = true
			, storage_constructor_type sc = default_storage_constructor);

		session_proxy abort() { return session_proxy(m_impl); }

		session_status status() const;

#ifndef TORRENT_DISABLE_DHT
		void start_dht(entry const& startup_state = entry());
		void stop_dht();
		void set_dht_settings(dht_settings const& settings);
		entry dht_state() const;
		void add_dht_node(std::pair<std::string, int> const& node);
		void add_dht_router(std::pair<std::string, int> const& node);
#endif

#ifndef TORRENT_DISABLE_ENCRYPTION
		void set_pe_settings(pe_settings const& settings);
		pe_settings const& get_pe_settings() const;
#endif

#ifndef TORRENT_DISABLE_EXTENSIONS
		void add_extension(boost::function<boost::shared_ptr<torrent_plugin>(torrent*)> ext);
#endif

		void set_ip_filter(ip_filter const& f);
		void set_port_filter(port_filter const& f);
		void set_peer_id(peer_id const& pid);
		void set_key(int key);
		peer_id id() const;

		bool is_listening() const;

		// if the listen port failed in some way
		// you can retry to listen on another port-
		// range with this function. If the listener
		// succeeded and is currently listening,
		// a call to this function will shut down the
		// listen port and reopen it using these new
		// properties (the given interface and port range).
		// As usual, if the interface is left as 0
		// this function will return false on failure.
		// If it fails, it will also generate alerts describing
		// the error. It will return true on success.
		bool listen_on(
			std::pair<int, int> const& port_range
			, const char* net_interface = 0);

		// returns the port we ended up listening on
		unsigned short listen_port() const;

		// Get the number of uploads.
		int num_uploads() const;

		// Get the number of connections. This number also contains the
		// number of half open connections.
		int num_connections() const;

		void remove_torrent(const torrent_handle& h);

		void set_settings(session_settings const& s);
		session_settings const& settings();

		void set_peer_proxy(proxy_settings const& s);
		void set_web_seed_proxy(proxy_settings const& s);
		void set_tracker_proxy(proxy_settings const& s);

		proxy_settings const& peer_proxy() const;
		proxy_settings const& web_seed_proxy() const;
		proxy_settings const& tracker_proxy() const;

#ifndef TORRENT_DISABLE_DHT
		void set_dht_proxy(proxy_settings const& s);
		proxy_settings const& dht_proxy() const;
#endif

		int upload_rate_limit() const;
		int download_rate_limit() const;

		void set_upload_rate_limit(int bytes_per_second);
		void set_download_rate_limit(int bytes_per_second);
		void set_max_uploads(int limit);
		void set_max_connections(int limit);
		void set_max_half_open_connections(int limit);

		std::auto_ptr<alert> pop_alert();
		void set_severity_level(alert::severity_t s);

		connection_queue& get_connection_queue();

		// starts/stops UPnP, NATPMP or LSD port mappers
		// they are stopped by default
		void start_lsd();
		void start_natpmp();
		void start_upnp();

		void stop_lsd();
		void stop_natpmp();
		void stop_upnp();

	private:

		// just a way to initialize boost.filesystem
		// before the session_impl is created
		aux::filesystem_init m_dummy;

		// data shared between the main thread
		// and the working thread
		boost::shared_ptr<aux::session_impl> m_impl;
	};

}

#endif // TORRENT_SESSION_HPP_INCLUDED

<commit_msg>fixed default value for paused<commit_after>/*

Copyright (c) 2006, 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.

*/

#ifndef TORRENT_SESSION_HPP_INCLUDED
#define TORRENT_SESSION_HPP_INCLUDED

#include <ctime>
#include <algorithm>
#include <vector>
#include <set>
#include <list>
#include <deque>

#ifdef _MSC_VER
#pragma warning(push, 1)
#endif

#include <boost/limits.hpp>
#include <boost/tuple/tuple.hpp>
#include <boost/filesystem/path.hpp>
#include <boost/thread.hpp>

#ifdef _MSC_VER
#pragma warning(pop)
#endif

#include "libtorrent/config.hpp"
#include "libtorrent/torrent_handle.hpp"
#include "libtorrent/entry.hpp"
#include "libtorrent/alert.hpp"
#include "libtorrent/session_status.hpp"
#include "libtorrent/version.hpp"
#include "libtorrent/fingerprint.hpp"

#include "libtorrent/storage.hpp"

#ifdef _MSC_VER
#	include <eh.h>
#endif

namespace libtorrent
{
	struct torrent_plugin;
	class torrent;
	class ip_filter;
	class port_filter;
	class connection_queue;

	namespace fs = boost::filesystem;

	namespace aux
	{
		// workaround for microsofts
		// hardware exceptions that makes
		// it hard to debug stuff
#ifdef _MSC_VER
		struct eh_initializer
		{
			eh_initializer()
			{
				::_set_se_translator(straight_to_debugger);
			}

			static void straight_to_debugger(unsigned int, _EXCEPTION_POINTERS*)
			{ throw; }
		};
#else
		struct eh_initializer {};
#endif
		struct session_impl;

		struct filesystem_init
		{
			filesystem_init();
		};

	}

	class TORRENT_EXPORT session_proxy
	{
		friend class session;
	public:
		session_proxy() {}
	private:
		session_proxy(boost::shared_ptr<aux::session_impl> impl)
			: m_impl(impl) {}
		boost::shared_ptr<aux::session_impl> m_impl;
	};

	class TORRENT_EXPORT session: public boost::noncopyable, aux::eh_initializer
	{
	public:

		session(fingerprint const& print = fingerprint("LT"
			, LIBTORRENT_VERSION_MAJOR, LIBTORRENT_VERSION_MINOR, 0, 0));
		session(
			fingerprint const& print
			, std::pair<int, int> listen_port_range
			, char const* listen_interface = "0.0.0.0");

		~session();

		// returns a list of all torrents in this session
		std::vector<torrent_handle> get_torrents() const;

		// returns an invalid handle in case the torrent doesn't exist
		torrent_handle find_torrent(sha1_hash const& info_hash) const;

		// all torrent_handles must be destructed before the session is destructed!
		torrent_handle add_torrent(
			torrent_info const& ti
			, fs::path const& save_path
			, entry const& resume_data = entry()
			, bool compact_mode = true
			, bool paused = false
			, storage_constructor_type sc = default_storage_constructor);

		torrent_handle add_torrent(
			char const* tracker_url
			, sha1_hash const& info_hash
			, char const* name
			, fs::path const& save_path
			, entry const& resume_data = entry()
			, bool compact_mode = true
			, bool paused = false
			, storage_constructor_type sc = default_storage_constructor);

		session_proxy abort() { return session_proxy(m_impl); }

		session_status status() const;

#ifndef TORRENT_DISABLE_DHT
		void start_dht(entry const& startup_state = entry());
		void stop_dht();
		void set_dht_settings(dht_settings const& settings);
		entry dht_state() const;
		void add_dht_node(std::pair<std::string, int> const& node);
		void add_dht_router(std::pair<std::string, int> const& node);
#endif

#ifndef TORRENT_DISABLE_ENCRYPTION
		void set_pe_settings(pe_settings const& settings);
		pe_settings const& get_pe_settings() const;
#endif

#ifndef TORRENT_DISABLE_EXTENSIONS
		void add_extension(boost::function<boost::shared_ptr<torrent_plugin>(torrent*)> ext);
#endif

		void set_ip_filter(ip_filter const& f);
		void set_port_filter(port_filter const& f);
		void set_peer_id(peer_id const& pid);
		void set_key(int key);
		peer_id id() const;

		bool is_listening() const;

		// if the listen port failed in some way
		// you can retry to listen on another port-
		// range with this function. If the listener
		// succeeded and is currently listening,
		// a call to this function will shut down the
		// listen port and reopen it using these new
		// properties (the given interface and port range).
		// As usual, if the interface is left as 0
		// this function will return false on failure.
		// If it fails, it will also generate alerts describing
		// the error. It will return true on success.
		bool listen_on(
			std::pair<int, int> const& port_range
			, const char* net_interface = 0);

		// returns the port we ended up listening on
		unsigned short listen_port() const;

		// Get the number of uploads.
		int num_uploads() const;

		// Get the number of connections. This number also contains the
		// number of half open connections.
		int num_connections() const;

		void remove_torrent(const torrent_handle& h);

		void set_settings(session_settings const& s);
		session_settings const& settings();

		void set_peer_proxy(proxy_settings const& s);
		void set_web_seed_proxy(proxy_settings const& s);
		void set_tracker_proxy(proxy_settings const& s);

		proxy_settings const& peer_proxy() const;
		proxy_settings const& web_seed_proxy() const;
		proxy_settings const& tracker_proxy() const;

#ifndef TORRENT_DISABLE_DHT
		void set_dht_proxy(proxy_settings const& s);
		proxy_settings const& dht_proxy() const;
#endif

		int upload_rate_limit() const;
		int download_rate_limit() const;

		void set_upload_rate_limit(int bytes_per_second);
		void set_download_rate_limit(int bytes_per_second);
		void set_max_uploads(int limit);
		void set_max_connections(int limit);
		void set_max_half_open_connections(int limit);

		std::auto_ptr<alert> pop_alert();
		void set_severity_level(alert::severity_t s);

		connection_queue& get_connection_queue();

		// starts/stops UPnP, NATPMP or LSD port mappers
		// they are stopped by default
		void start_lsd();
		void start_natpmp();
		void start_upnp();

		void stop_lsd();
		void stop_natpmp();
		void stop_upnp();

	private:

		// just a way to initialize boost.filesystem
		// before the session_impl is created
		aux::filesystem_init m_dummy;

		// data shared between the main thread
		// and the working thread
		boost::shared_ptr<aux::session_impl> m_impl;
	};

}

#endif // TORRENT_SESSION_HPP_INCLUDED

<|endoftext|>


<commit_before><?hh
abstract class BaseStore {
  protected $class;
  protected $db;

  protected static $instance;

  public function __construct(string $collection = null, string $class = null) {
    if (defined('static::COLLECTION') && defined('static::MODEL')) {
      $collection = static::COLLECTION;
      $class = static::MODEL;
    }

    invariant($collection && $class, 'Collection or class not provided');

    $this->collection = $collection;
    $this->class = $class;
    $this->db = MongoInstance::get($collection);
    static::$instance = $this;
  }

  protected static function i() {
    if (!static::$instance) {
      static::$instance = new static();
    }

    return static::$instance;
  }

  public function db() {
    return static::i()->db;
  }

  public function find(
    array $query = [],
    ?int $skip = 0,
    ?int $limit = 0): BaseModel {
    $docs = static::i()->db->find($query);
    $class = static::i()->class;

    if ($skip !== null) {
      $docs = $docs->skip($skip);
    }

    if ($limit !== null) {
      $limit = $docs->limit($limit);
    }

    foreach ($docs as $doc) {
      yield new $class($doc);
    }
  }

  public function distinct(string $key, array $query = []) {
    $docs = static::i()->db->distinct($key, $query);
    return !is_array($docs) ? [] : $docs;
  }

  public function findOne(array $query): ?BaseModel {
    $doc = static::i()->db->findOne($query);
    $class = static::i()->class;
    return $doc ? new $class($doc) : null;
  }

  public function findById(MongoId $id): ?BaseModel {
    return static::i()->findOne(['_id' => $id]);
  }

  public function count(array $query): int {
    return static::i()->db->count($query);
  }

  protected function ensureType(BaseModel $item): bool {
    return class_exists(static::i()->class) && is_a($item, $this->class);
  }

  public function remove(BaseModel $item) {
    if (!static::i()->ensureType($item)) {
      throw new Exception(
        'Invalid object provided, expected ' . static::i()->class);
      return false;
    }

    if ($item == null) {
      return false;
    }

    try {
      if ($item->getID()) {
        static::i()->db->remove($item->document());
        return true;
      } else {
        return false;
      }
    } catch (MongoException $e) {
      l('MongoException:', $e->getMessage());
      return false;
    }
  }

  public function removeWhere($query = []) {
    try {
      static::i()->db->remove($query);
      return true;
    } catch (MongoException $e) {
      l('MongoException:', $e->getMessage());
      return false;
    }
  }

  public function removeById($id) {
    return static::i()->removeWhere(['_id' => mid($id)]);
  }

  public function aggregate(BaseAggregation $aggregation) {
    return call_user_func_array(
      [static::i()->db, 'aggregate'],
      $aggregation->getPipeline());
  }

  public function mapReduce(
    MongoCode $map,
    MongoCode $reduce,
    array $query = null,
    array $config = null) {

    $options = [
      'mapreduce' => static::i()->collection,
      'map' => $map,
      'reduce' => $reduce,
      'out' => ['inline' => true]];

    if ($query) {
      $options['query'] = $query;
    }

    if ($config) {
      unset($options['mapreduce']);
      unset($options['map']);
      unset($options['reduce']);
      unset($options['query']);
      $options = array_merge($options, $config);
    }

    $res = MongoInstance::get()->command($options);

    if (idx($res, 'ok')) {
      return $res;
    } else {
      l('MapReduce error:', $res);
      return null;
    }
  }

  public function save(BaseModel &$item) {
    if (!static::i()->ensureType($item)) {
      throw new Exception(
        'Invalid object provided, expected ' . static::i()->class);
      return false;
    }

    if ($item == null) {
      return false;
    }

    try {
      if (!$item->getID()) {
        $id = new MongoId();
        $item->setID($id);
        $document = $item->document();
        static::i()->db->insert($document);
      } else {
        $document = $item->document();
        static::i()->db->save($document);
      }
      return true;
    } catch (MongoException $e) {
      l('MongoException:', $e->getMessage());
      return false;
    }
    return true;
  }
}

class BaseStoreCursor {
  protected
    $class,
    $count,
    $cursor,
    $next;

  public function __construct($class, $count, $cursor, $skip, $limit) {
    $this->class = $class;
    $this->count = $count;
    $this->cursor = $cursor;
    $this->next = $count > $limit ? $skip + 1 : null;
  }

  public function count() {
    return $this->count;
  }

  public function nextPage() {
    return $this->next;
  }

  public function docs() {
    $class = $this->class;
    foreach ($this->cursor as $entry) {
      yield new $class($entry);
    }
  }
}

class BaseAggregation {
  protected $pipeline;
  public function __construct() {
    $this->pipeline = [];
  }

  public function getPipeline() {
    return $this->pipeline;
  }

  public function project(array $spec) {
    if (!empty($spec)) {
      $this->pipeline[] = ['$project' => $spec];
    }
    return $this;
  }

  public function match(array $spec) {
    if (!empty($spec)) {
      $this->pipeline[] = ['$match' => $spec];
    }
    return $this;
  }

  public function limit($limit) {
    $this->pipeline[] = ['$limit' => $limit];
    return $this;
  }

  public function skip($skip) {
    $this->pipeline[] = ['$skip' => $skip];
    return $this;
  }

  public function unwind($field) {
    $this->pipeline[] = ['$unwind' => '$' . $field];
    return $this;
  }

  public function group(array $spec) {
    if (!empty($spec)) {
      $this->pipeline[] = ['$group' => $spec];
    }
    return $this;
  }

  public function sort(array $spec) {
    if (!empty($spec)) {
      $this->pipeline[] = ['$sort' => $spec];
    }
    return $this;
  }

  public static function addToSet(string $field): array {
    return ['$addToSet' => '$' . $field];
  }

  public static function sum($value = 1): array {
    if (!is_numeric($value)) {
      $value = '$' . $value;
    }
    return ['$sum' => $value];
  }

  public function __call($name, $args) {
    $field = array_pop($args);
    switch ($name) {
      case 'addToSet':
      case 'first':
      case 'last':
      case 'max':
      case 'min':
      case 'avg':
        return ['$' . $name => '$' . $field];
    }

    throw new RuntimeException('Method not found: ' . $name);
  }

  public function push($field) {
    if (is_array($field)) {
      foreach ($field as &$f) {
        $f = '$' . $f;
      }
    } else {
      $field = '$' . $field;
    }

    return ['$push' => $field];
  }
}

abstract class BaseModel {
  public ?MongoId $_id;
  public function __construct(array<string, mixed> $document = []) {

    foreach ($document as $key => $value) {
      if (property_exists($this, $key)) {
        $this->$key = $key == '_id' ? mid($value) : $value;
      }
    }
  }

  public function document(): array<string, mixed> {
    return get_object_vars($this);
  }

  final public function getID(): ?MongoId {
    return $this->_id;
  }

  final public function setID(MongoId $_id): void {
    $this->_id = $_id;
  }

  public function __call($method, $args) {
    if (strpos($method, 'get') === 0) {
      $op = 'get';
    } elseif (strpos($method, 'set') === 0) {
      $op = 'set';
    } elseif (strpos($method, 'remove') === 0) {
      $op = 'remove';
    } elseif (strpos($method, 'has') === 0) {
      $op = 'has';
    } else {
      $e = sprintf('Method "%s" not found in %s', $method, get_called_class());
      throw new RuntimeException($e);
      return null;
    }

    // $method = preg_replace('/^(get|set|remove|has)/i', '', $method);
    $method = preg_replace('/^(get|set)/i', '', $method);

    preg_match_all(
      '!([A-Z][A-Z0-9]*(?=$|[A-Z][a-z0-9])|[A-Za-z][a-z0-9]+)!',
      $method,
      $matches);

    $ret = $matches[0];
    foreach ($ret as &$match) {
      $match = $match == strtoupper($match) ?
        strtolower($match) :
        lcfirst($match);
    }

    $field = implode('_', $ret);

    $arg = array_pop($args);

    switch ($op) {
      case 'set':
        $this->$field = $arg;
        return;

      case 'get':
        invariant(
          property_exists($this, $field),
          '%s is not a valid field for %s',
          $field,
          get_called_class());
        return $this->$field;
    }
  }
}
<commit_msg>removed caching of static instances in BaseStore<commit_after><?hh
abstract class BaseStore {
  protected $class;
  protected $db;

  protected static $instance;

  public function __construct(string $collection = null, string $class = null) {
    if (defined('static::COLLECTION') && defined('static::MODEL')) {
      $collection = static::COLLECTION;
      $class = static::MODEL;
    }

    invariant($collection && $class, 'Collection or class not provided');

    $this->collection = $collection;
    $this->class = $class;
    $this->db = MongoInstance::get($collection);
    static::$instance = $this;
  }

  protected static function i() {
    return new static();
  }

  public function db() {
    return static::i()->db;
  }

  public function find(
    array $query = [],
    ?int $skip = 0,
    ?int $limit = 0): BaseModel {
    $docs = static::i()->db->find($query);
    $class = static::i()->class;

    if ($skip !== null) {
      $docs = $docs->skip($skip);
    }

    if ($limit !== null) {
      $limit = $docs->limit($limit);
    }

    foreach ($docs as $doc) {
      yield new $class($doc);
    }
  }

  public function distinct(string $key, array $query = []) {
    $docs = static::i()->db->distinct($key, $query);
    return !is_array($docs) ? [] : $docs;
  }

  public function findOne(array $query): ?BaseModel {
    $doc = static::i()->db->findOne($query);
    $class = static::i()->class;
    return $doc ? new $class($doc) : null;
  }

  public function findById(MongoId $id): ?BaseModel {
    return static::i()->findOne(['_id' => $id]);
  }

  public function count(array $query): int {
    return static::i()->db->count($query);
  }

  protected function ensureType(BaseModel $item): bool {
    return class_exists(static::i()->class) && is_a($item, $this->class);
  }

  public function remove(BaseModel $item) {
    if (!static::i()->ensureType($item)) {
      throw new Exception(
        'Invalid object provided, expected ' . static::i()->class);
      return false;
    }

    if ($item == null) {
      return false;
    }

    try {
      if ($item->getID()) {
        static::i()->db->remove($item->document());
        return true;
      } else {
        return false;
      }
    } catch (MongoException $e) {
      l('MongoException:', $e->getMessage());
      return false;
    }
  }

  public function removeWhere($query = []) {
    try {
      static::i()->db->remove($query);
      return true;
    } catch (MongoException $e) {
      l('MongoException:', $e->getMessage());
      return false;
    }
  }

  public function removeById($id) {
    return static::i()->removeWhere(['_id' => mid($id)]);
  }

  public function aggregate(BaseAggregation $aggregation) {
    return call_user_func_array(
      [static::i()->db, 'aggregate'],
      $aggregation->getPipeline());
  }

  public function mapReduce(
    MongoCode $map,
    MongoCode $reduce,
    array $query = null,
    array $config = null) {

    $options = [
      'mapreduce' => static::i()->collection,
      'map' => $map,
      'reduce' => $reduce,
      'out' => ['inline' => true]];

    if ($query) {
      $options['query'] = $query;
    }

    if ($config) {
      unset($options['mapreduce']);
      unset($options['map']);
      unset($options['reduce']);
      unset($options['query']);
      $options = array_merge($options, $config);
    }

    $res = MongoInstance::get()->command($options);

    if (idx($res, 'ok')) {
      return $res;
    } else {
      l('MapReduce error:', $res);
      return null;
    }
  }

  public function save(BaseModel &$item) {
    if (!static::i()->ensureType($item)) {
      throw new Exception(
        'Invalid object provided, expected ' . static::i()->class);
      return false;
    }

    if ($item == null) {
      return false;
    }

    try {
      if (!$item->getID()) {
        $id = new MongoId();
        $item->setID($id);
        $document = $item->document();
        static::i()->db->insert($document);
      } else {
        $document = $item->document();
        static::i()->db->save($document);
      }
      return true;
    } catch (MongoException $e) {
      l('MongoException:', $e->getMessage());
      return false;
    }
    return true;
  }
}

class BaseStoreCursor {
  protected
    $class,
    $count,
    $cursor,
    $next;

  public function __construct($class, $count, $cursor, $skip, $limit) {
    $this->class = $class;
    $this->count = $count;
    $this->cursor = $cursor;
    $this->next = $count > $limit ? $skip + 1 : null;
  }

  public function count() {
    return $this->count;
  }

  public function nextPage() {
    return $this->next;
  }

  public function docs() {
    $class = $this->class;
    foreach ($this->cursor as $entry) {
      yield new $class($entry);
    }
  }
}

class BaseAggregation {
  protected $pipeline;
  public function __construct() {
    $this->pipeline = [];
  }

  public function getPipeline() {
    return $this->pipeline;
  }

  public function project(array $spec) {
    if (!empty($spec)) {
      $this->pipeline[] = ['$project' => $spec];
    }
    return $this;
  }

  public function match(array $spec) {
    if (!empty($spec)) {
      $this->pipeline[] = ['$match' => $spec];
    }
    return $this;
  }

  public function limit($limit) {
    $this->pipeline[] = ['$limit' => $limit];
    return $this;
  }

  public function skip($skip) {
    $this->pipeline[] = ['$skip' => $skip];
    return $this;
  }

  public function unwind($field) {
    $this->pipeline[] = ['$unwind' => '$' . $field];
    return $this;
  }

  public function group(array $spec) {
    if (!empty($spec)) {
      $this->pipeline[] = ['$group' => $spec];
    }
    return $this;
  }

  public function sort(array $spec) {
    if (!empty($spec)) {
      $this->pipeline[] = ['$sort' => $spec];
    }
    return $this;
  }

  public static function addToSet(string $field): array {
    return ['$addToSet' => '$' . $field];
  }

  public static function sum($value = 1): array {
    if (!is_numeric($value)) {
      $value = '$' . $value;
    }
    return ['$sum' => $value];
  }

  public function __call($name, $args) {
    $field = array_pop($args);
    switch ($name) {
      case 'addToSet':
      case 'first':
      case 'last':
      case 'max':
      case 'min':
      case 'avg':
        return ['$' . $name => '$' . $field];
    }

    throw new RuntimeException('Method not found: ' . $name);
  }

  public function push($field) {
    if (is_array($field)) {
      foreach ($field as &$f) {
        $f = '$' . $f;
      }
    } else {
      $field = '$' . $field;
    }

    return ['$push' => $field];
  }
}

abstract class BaseModel {
  public ?MongoId $_id;
  public function __construct(array<string, mixed> $document = []) {

    foreach ($document as $key => $value) {
      if (property_exists($this, $key)) {
        $this->$key = $key == '_id' ? mid($value) : $value;
      }
    }
  }

  public function document(): array<string, mixed> {
    return get_object_vars($this);
  }

  final public function getID(): ?MongoId {
    return $this->_id;
  }

  final public function setID(MongoId $_id): void {
    $this->_id = $_id;
  }

  public function __call($method, $args) {
    if (strpos($method, 'get') === 0) {
      $op = 'get';
    } elseif (strpos($method, 'set') === 0) {
      $op = 'set';
    } elseif (strpos($method, 'remove') === 0) {
      $op = 'remove';
    } elseif (strpos($method, 'has') === 0) {
      $op = 'has';
    } else {
      $e = sprintf('Method "%s" not found in %s', $method, get_called_class());
      throw new RuntimeException($e);
      return null;
    }

    // $method = preg_replace('/^(get|set|remove|has)/i', '', $method);
    $method = preg_replace('/^(get|set)/i', '', $method);

    preg_match_all(
      '!([A-Z][A-Z0-9]*(?=$|[A-Z][a-z0-9])|[A-Za-z][a-z0-9]+)!',
      $method,
      $matches);

    $ret = $matches[0];
    foreach ($ret as &$match) {
      $match = $match == strtoupper($match) ?
        strtolower($match) :
        lcfirst($match);
    }

    $field = implode('_', $ret);

    $arg = array_pop($args);

    switch ($op) {
      case 'set':
        $this->$field = $arg;
        return;

      case 'get':
        invariant(
          property_exists($this, $field),
          '%s is not a valid field for %s',
          $field,
          get_called_class());
        return $this->$field;
    }
  }
}
<|endoftext|>


<commit_before>#include "../include/BlueFile.h"

//Prpare pour la lecture
BlueFile::BlueFile(string nom_fichier) : nom_fichier(nom_fichier)
{
	bits.reserve(BLOCK_SIZE);

	determineTaille();

	fichier_lecture = NULL;
	fichier_ecriture = NULL;

	cout << "__________/_\\__________" << endl;
	cout << "CRYPTAGE/DECRYPTAGE DE " << nom_fichier << endl;
	cout << "TAILLE: " << taille << endl << endl;
}

//Dtruit les donnes
BlueFile::~BlueFile()
{
	fichier_lecture->close();
	fichier_ecriture->close();
	delete fichier_lecture;
	delete fichier_ecriture;
}

//Dtermine la taille du fichier
void BlueFile::determineTaille()
{
	ifstream in("" DOSSIER_EFFECTIF "/" + nom_fichier, ifstream::ate | ifstream::binary);
	taille = in.tellg();
}

//Lecture en binaire d'un fichier
void BlueFile::lireBinaire()
{
	if(fichier_lecture == NULL)
		fichier_lecture = new ifstream("" DOSSIER_EFFECTIF "/" + nom_fichier, ios::binary);

	//lecture caractre par caractre
	char c = '_';
	while(bits.size() < BLOCK_SIZE && (int)fichier_lecture->tellg() != taille)
	{
		*fichier_lecture >> noskipws >> c;
		//lecture bit par bit
		for(int i = 7; i >= 0; i--)
			bits.push_back(((c >> i) & 1));

	}

}

//Dtecte si le fichier a fini d'tre crypt
int BlueFile::procedureFinie()
{
	int position = (int)fichier_lecture->tellg();
	bool end = position == taille;

	//message de fin / progression
	if(end)
		cout << "CRYPTAGE/DECRYPTAGE FINI" << endl << "__________\\_/__________" << endl << endl;
	else
		cout << "Progression : " << (float)fichier_lecture->tellg() / (float) taille << "%" << endl;

	if(end)
		return 1;
	else if(position == -1)
		return -1;
	else return 0;
}

//Crypte l'ensemble des bits courants
void BlueFile::crypter()
{
	//cryptage basique: inverser les bits deux  deux
	for(size_t i = 0; i < bits.size() -1; i+=2)
	{
		char c1 = bits[i];
		bits[i] = bits[i + 1];
		bits[i + 1] = c1;
	}
}

//Dcrypte l'ensemble des bits courants
void BlueFile::decrypter()
{
	//dcryptage basique: inverser les bits deux  deux
	for(size_t i = 0; i < bits.size() - 1; i+=2)
	{
		char c1 = bits[i];
		bits[i] = bits[i + 1];
		bits[i + 1] = c1;
	}
}

//Rcris l'ensemble des bits courants dans le fichier en binaire
void BlueFile::ecrireBinaire()
{
	if(!fichier_ecriture)
		fichier_ecriture = new ofstream("" DOSSIER_EFFECTIF "/" + nom_fichier,   ios::binary);

	//lecture des bits
	for(size_t i = 0; i < bits.size(); i+=8)
	{
		//regroupement en caractre
		char c = 0;
		for(int j = 0; j < 8; j++)
			c ^= (-(int)bits[i + j] ^ c) & (1 << (7 - j));

		//si non saut de ligne spcial
		*fichier_ecriture << c;
	}
	bits.clear();
}

//Affiche les bits
void BlueFile::afficherBits()
{
	cout << endl << "AFFICHAGE BITS:" << endl;
	for(size_t i = 0; i < bits.size(); i++)
	{
		if(i % 8 == 0)
			cout << endl;
		char bit = (bits[i] ? '1' : '0');
		cout << bit;
	}
	cout << endl << "______" << endl << endl;

}

//Whiax<commit_msg>correction mineure<commit_after>#include "../include/BlueFile.h"

//Prpare pour la lecture
BlueFile::BlueFile(string nom_fichier) : nom_fichier(nom_fichier)
{
	bits.reserve(BLOCK_SIZE);

	determineTaille();

	fichier_lecture = NULL;
	fichier_ecriture = NULL;

	cout << "__________/_\\__________" << endl;
	cout << "CRYPTAGE/DECRYPTAGE DE " << nom_fichier << endl;
	cout << "TAILLE: " << taille << endl << endl;
}

//Dtruit les donnes
BlueFile::~BlueFile()
{
	fichier_lecture->close();
	fichier_ecriture->close();
	delete fichier_lecture;
	delete fichier_ecriture;
}

//Dtermine la taille du fichier
void BlueFile::determineTaille()
{
	ifstream in("" DOSSIER_EFFECTIF "/" + nom_fichier, ifstream::ate | ifstream::binary);
	taille = in.tellg();
}

//Lecture en binaire d'un fichier
void BlueFile::lireBinaire()
{
	if(fichier_lecture == NULL)
		fichier_lecture = new ifstream("" DOSSIER_EFFECTIF "/" + nom_fichier, ios::binary);

	//lecture caractre par caractre
	char c = '_';
	while(bits.size() < BLOCK_SIZE && (int)fichier_lecture->tellg() != taille)
	{
		*fichier_lecture >> noskipws >> c;
		//lecture bit par bit
		for(int i = 7; i >= 0; i--)
			bits.push_back(((c >> i) & 1));

	}

}

//Dtecte si le fichier a fini d'tre crypt
int BlueFile::procedureFinie()
{
	int position = (int)fichier_lecture->tellg();
	bool end = position == taille;

	//message de fin / progression
	if(end)
		cout << "CRYPTAGE/DECRYPTAGE FINI" << endl << "__________\\_/__________" << endl << endl;
	else
		cout << "Progression : " << (float)position / (float) taille << "%" << endl;

	if(end)
		return 1;
	else if(position == -1)
		return -1;
	else return 0;
}

//Crypte l'ensemble des bits courants
void BlueFile::crypter()
{
	//cryptage basique: inverser les bits deux  deux
	for(size_t i = 0; i < bits.size() -1; i+=2)
	{
		char c1 = bits[i];
		bits[i] = bits[i + 1];
		bits[i + 1] = c1;
	}
}

//Dcrypte l'ensemble des bits courants
void BlueFile::decrypter()
{
	//dcryptage basique: inverser les bits deux  deux
	for(size_t i = 0; i < bits.size() - 1; i+=2)
	{
		char c1 = bits[i];
		bits[i] = bits[i + 1];
		bits[i + 1] = c1;
	}
}

//Rcris l'ensemble des bits courants dans le fichier en binaire
void BlueFile::ecrireBinaire()
{
	if(!fichier_ecriture)
		fichier_ecriture = new ofstream("" DOSSIER_EFFECTIF "/" + nom_fichier,   ios::binary);

	//lecture des bits
	for(size_t i = 0; i < bits.size(); i+=8)
	{
		//regroupement en caractre
		char c = 0;
		for(int j = 0; j < 8; j++)
			c ^= (-(int)bits[i + j] ^ c) & (1 << (7 - j));

		//si non saut de ligne spcial
		*fichier_ecriture << c;
	}
	bits.clear();
}

//Affiche les bits
void BlueFile::afficherBits()
{
	cout << endl << "AFFICHAGE BITS:" << endl;
	for(size_t i = 0; i < bits.size(); i++)
	{
		if(i % 8 == 0)
			cout << endl;
		char bit = (bits[i] ? '1' : '0');
		cout << bit;
	}
	cout << endl << "______" << endl << endl;

}

//Whiax<|endoftext|>


<commit_before>#ifndef NN_CONTAINER_HPP
#define NN_CONTAINER_HPP

#include "module.hpp"

namespace nnlib
{

/// The abtract base class for neural network modules that are made up of sub-modules.
template <typename T = double>
class Container : public Module<T>
{
public:
	template <typename ... Ms>
	Container(Ms... components) :
		m_components({ static_cast<Module<T> *>(components)... })
	{}

	Container(const Container &module) :
		m_components(module.m_components)
	{
		for(Module<T> *&m : m_components)
		{
			/// \note intentionally not releasing; module still owns the original
			m = m->copy();
		}
	}

	Container(const Serialized &node) :
		m_components(node.get<Storage<Module<T> *>>("components"))
	{}

	Container &operator=(const Container &module)
	{
		Storage<Module<T> *> components = module.m_components;
		for(Module<T> *&m : components)
		{
			/// \note intentionally not releasing; module still owns the original
			m = m->copy();
		}

		for(Module<T> *m : m_components)
			delete m;

		m_components = components;

		return *this;
	}

	virtual ~Container()
	{
		for(Module<T> *comp : m_components)
			delete comp;
	}

	virtual void training(bool training = true) override
	{
		for(Module<T> *comp : m_components)
			comp->training(training);
	}

	virtual void forget() override
	{
		Module<T>::forget();
		for(Module<T> *comp : m_components)
			comp->forget();
	}

	virtual void save(Serialized &node) const override
	{
		node.set("components", m_components);
	}

	/// Get a specific component from this container.
	Module<T> *component(size_t index)
	{
		return m_components[index];
	}

	/// Get the number of components in this container.
	size_t components() const
	{
		return m_components.size();
	}

	/// Add multiple components to this container.
	template <typename ... Ms>
	Container &add(Module<T> *component, Ms *...more)
	{
		add(component);
		add(more...);
		return *this;
	}

	/// Add a component to this container.
	virtual Container &add(Module<T> *component)
	{
		m_components.push_back(component);
		return *this;
	}

	/// Remove and return a specific component from this container. Caller is responsible for deleting this module.
	virtual Module<T> *remove(size_t index)
	{
		Module<T> *comp = m_components[index];
		m_components.erase(index);
		return comp;
	}

	/// Remove all components from this container and delete them.
	virtual Container &clear()
	{
		for(Module<T> *comp : m_components)
			delete comp;
		m_components.clear();
		return *this;
	}

	/// A vector of tensors filled with (views of) each sub-module's parameters.
	virtual Storage<Tensor<T> *> paramsList() override
	{
		Storage<Tensor<T> *> params;
		for(Module<T> *comp : m_components)
			params.append(comp->paramsList());
		return params;
	}

	/// A vector of tensors filled with (views of) each sub-module's parameters' gradient.
	virtual Storage<Tensor<T> *> gradList() override
	{
		Storage<Tensor<T> *> blams;
		for(Module<T> *comp : m_components)
			blams.append(comp->gradList());
		return blams;
	}

	/// A vector of tensors filled with (views of) each sub-module's internal state.
	virtual Storage<Tensor<T> *> stateList() override
	{
		Storage<Tensor<T> *> states = Module<T>::stateList();
		for(Module<T> *comp : m_components)
			states.append(comp->stateList());
		return states;
	}

protected:
	Storage<Module<T> *> m_components;
};

}

NNRegisterType(Container, Module);

#endif
<commit_msg>Reverted last change.<commit_after>#ifndef NN_CONTAINER_HPP
#define NN_CONTAINER_HPP

#include "module.hpp"

namespace nnlib
{

/// The abtract base class for neural network modules that are made up of sub-modules.
template <typename T = double>
class Container : public Module<T>
{
public:
	template <typename ... Ms>
	Container(Ms... components) :
		m_components({ static_cast<Module<T> *>(components)... })
	{}

	Container(const Container &module) :
		m_components(module.m_components)
	{
		for(Module<T> *&m : m_components)
		{
			/// \note intentionally not releasing; module still owns the original
			m = m->copy();
		}
	}

	Container(const Serialized &node) :
		m_components(node.get<Storage<Module<T> *>>("components"))
	{}

	Container &operator=(const Container &module)
	{
		Storage<Module<T> *> components = module.m_components;
		for(Module<T> *&m : components)
		{
			/// \note intentionally not releasing; module still owns the original
			m = m->copy();
		}

		for(Module<T> *m : m_components)
			delete m;

		m_components = components;

		return *this;
	}

	virtual ~Container()
	{
		for(Module<T> *comp : m_components)
			delete comp;
	}

	virtual void training(bool training = true) override
	{
		for(Module<T> *comp : m_components)
			comp->training(training);
	}

	virtual void forget() override
	{
		Module<T>::forget();
		for(Module<T> *comp : m_components)
			comp->forget();
	}

	virtual void save(Serialized &node) const override
	{
		node.set("components", m_components);
	}

	/// Get a specific component from this container.
	Module<T> *component(size_t index)
	{
		return m_components[index];
	}

	/// Get the number of components in this container.
	size_t components() const
	{
		return m_components.size();
	}

	/// Add multiple components to this container.
	template <typename ... Ms>
	Container &add(Module<T> *component, Ms *...more)
	{
		add(component);
		add(more...);
		return *this;
	}

	/// Add a component to this container.
	virtual Container &add(Module<T> *component)
	{
		m_components.push_back(component);
		return *this;
	}

	/// Remove and return a specific component from this container. Caller is responsible for deleting this module.
	virtual Module<T> *remove(size_t index)
	{
		Module<T> *comp = m_components[index];
		m_components.erase(index);
		return comp;
	}

	/// Remove all components from this container and delete them.
	virtual Container &clear()
	{
		for(Module<T> *comp : m_components)
			delete comp;
		m_components.clear();
		return *this;
	}

	/// A vector of tensors filled with (views of) each sub-module's parameters.
	virtual Storage<Tensor<T> *> paramsList() override
	{
		Storage<Tensor<T> *> params;
		for(Module<T> *comp : m_components)
			params.append(comp->paramsList());
		return params;
	}

	/// A vector of tensors filled with (views of) each sub-module's parameters' gradient.
	virtual Storage<Tensor<T> *> gradList() override
	{
		Storage<Tensor<T> *> blams;
		for(Module<T> *comp : m_components)
			blams.append(comp->gradList());
		return blams;
	}

	/// A vector of tensors filled with (views of) each sub-module's internal state.
	virtual Storage<Tensor<T> *> stateList() override
	{
		Storage<Tensor<T> *> states;
		for(Module<T> *comp : m_components)
			states.append(comp->stateList());
		return states;
	}

protected:
	Storage<Module<T> *> m_components;
};

}

NNRegisterType(Container, Module);

#endif
<|endoftext|>


<commit_before>#pragma once

#include <utility>
#include <type_traits>
#include <string>

#include "any.hpp"
#include <type_list.hpp>
#include <function_deduction.hpp>
#include <member_variable_deduction.hpp>
#include <void_t.hpp>

namespace shadow
{
// free function signature
typedef any (*free_function_binding_signature)(any*);
// member function signature
typedef any (*member_function_binding_signature)(any&, any*);
// member variable getter
typedef any (*member_variable_get_binding_signature)(const any&);
// member variable setter
typedef void (*member_variable_set_binding_signature)(any&, const any&);
// constructor signature
typedef any (*constructor_binding_signature)(any*);
// conversion signature
typedef any (*conversion_binding_signature)(const any&);
// string serialize signature
typedef std::string (*string_serialization_signature)(const any&);
// string deserialization signature
typedef any (*string_deserialization_signature)(const std::string&);

////////////////////////////////////////////////////////////////////////////////
// generic bind point for free functions
// has the same signature as function pointer free_function_binding_signature
// which can be stored in the free_function_info struct

namespace free_function_detail
{
// necessary to handle void as return type differently when calling underlying
// free function
template <class ReturnType>
struct return_type_specializer
{
    // dispatch: unpacks argument type list and sequence to correctly index into
    // argument array and call get with the right types to retrieve raw values
    // from the anys
    template <class FunctionPointerType,
              FunctionPointerType FunctionPointerValue,
              class... ArgTypes,
              std::size_t... ArgSeq>
    static any
    dispatch(any* argument_array,
             metamusil::t_list::type_list<ArgTypes...>,
             std::index_sequence<ArgSeq...>)
    {
        // necessary to remove reference from types as any only stores
        // unqualified types, ie values only
        return FunctionPointerValue(
            argument_array[ArgSeq]
                .get<typename std::remove_reference_t<ArgTypes>>()...);
    }
};

template <>
struct return_type_specializer<void>
{
    // dispatch: unpacks argument type list and sequence to correctly index into
    // argument array and call get with the right types to retrieve raw values
    // from the anys
    template <class FunctionPointerType,
              FunctionPointerType FunctionPointerValue,
              class... ArgTypes,
              std::size_t... ArgSeq>
    static any
    dispatch(any* argument_array,
             metamusil::t_list::type_list<ArgTypes...>,
             std::index_sequence<ArgSeq...>)
    {
        // necessary to remove reference from types as any only stores
        // unqualified types, ie values only
        FunctionPointerValue(
            argument_array[ArgSeq]
                .get<typename std::remove_reference_t<ArgTypes>>()...);

        // return empty any, ie 'void'
        return any();
    }
};

// the value of the function pointer is stored at runtime in the template
// overload set
// this enables any function to be wrapped into uniform function signature that
// can be stored homogenously at runtime
template <class FunctionPointerType, FunctionPointerType FunctionPointerValue>
any
generic_free_function_bind_point(any* argument_array)
{
    typedef metamusil::deduce_return_type_t<FunctionPointerType> return_type;
    typedef metamusil::deduce_parameter_types_t<FunctionPointerType>
        parameter_types;
    // make integer sequence from type list
    typedef metamusil::t_list::index_sequence_for_t<parameter_types>
        parameter_sequence;

    return return_type_specializer<return_type>::
        template dispatch<FunctionPointerType, FunctionPointerValue>(
            argument_array, parameter_types(), parameter_sequence());
}
} // namespace free_function_detail

namespace member_function_detail
{

template <class ReturnType>
struct return_type_specializer
{
    template <class MemFunPointerType,
              MemFunPointerType MemFunPointerValue,
              class ObjectType,
              class... ParamTypes,
              std::size_t... ParamSequence>
    static any
    dispatch(any& object,
             any* argument_array,
             metamusil::t_list::type_list<ParamTypes...>,
             std::index_sequence<ParamSequence...>)
    {
        return (object.get<ObjectType>().*MemFunPointerValue)(
            argument_array[ParamSequence]
                .get<std::remove_reference_t<ParamTypes>>()...);
    }
};

template <>
struct return_type_specializer<void>
{
    template <class MemFunPointerType,
              MemFunPointerType MemFunPointerValue,
              class ObjectType,
              class... ParamTypes,
              std::size_t... ParamSequence>
    static any
    dispatch(any& object,
             any* argument_array,
             metamusil::t_list::type_list<ParamTypes...>,
             std::index_sequence<ParamSequence...>)
    {
        (object.get<ObjectType>().*MemFunPointerValue)(
            argument_array[ParamSequence]
                .get<std::remove_reference_t<ParamTypes>>()...);

        return any();
    }
};

template <class MemFunPointerType, MemFunPointerType MemFunPointerValue>
any
generic_member_function_bind_point(any& object, any* argument_array)
{
    // deduce return type
    typedef metamusil::deduce_return_type_t<MemFunPointerType> return_type;

    // deduce parameter types
    typedef metamusil::deduce_parameter_types_t<MemFunPointerType>
        parameter_types;

    // make integer sequence from parameter type list
    typedef metamusil::t_list::index_sequence_for_t<parameter_types>
        parameter_sequence;

    // deduce object type
    typedef metamusil::deduce_object_type_t<MemFunPointerType> object_type;

    return return_type_specializer<return_type>::
        template dispatch<MemFunPointerType, MemFunPointerValue, object_type>(
            object, argument_array, parameter_types(), parameter_sequence());
}
} // namespace member_function_detail

namespace member_variable_detail
{

template <class MemVarPointerType,
          MemVarPointerType MemVarPointerValue,
          class ObjectType,
          class MemVarType>
any
get_dispatch(const any& object)
{
    return (object.get<ObjectType>().*MemVarPointerValue);
}

template <class MemVarPointerType,
          MemVarPointerType MemVarPointerValue,
          class ObjectType,
          class MemVarType>
void
set_dispatch(any& object, const any& value)
{
    (object.get<ObjectType>().*MemVarPointerValue) = value.get<MemVarType>();
}

template <class MemVarPointerType, MemVarPointerType MemVarPointerValue>
any
generic_member_variable_get_bind_point(const any& object)
{
    typedef metamusil::deduce_member_variable_object_type_t<MemVarPointerType>
        object_type;
    typedef metamusil::deduce_member_variable_type_t<MemVarPointerType>
        member_variable_type;

    return get_dispatch<MemVarPointerType,
                        MemVarPointerValue,
                        object_type,
                        member_variable_type>(object);
}

template <class MemVarPointerType, MemVarPointerType MemVarPointerValue>
void
generic_member_variable_set_bind_point(any& object, const any& value)
{
    typedef metamusil::deduce_member_variable_object_type_t<MemVarPointerType>
        object_type;
    typedef metamusil::deduce_member_variable_type_t<MemVarPointerType>
        member_variable_type;

    return set_dispatch<MemVarPointerType,
                        MemVarPointerValue,
                        object_type,
                        member_variable_type>(object, value);
}
} // namespace member_variable_detail

namespace constructor_detail
{

// purpose of braced_init_selector is to attempt to use constructor T(...) if
// available, otherwise fall back to braced init list initialization
template <class, class T, class... ParamTypes>
struct braced_init_selector_impl
{
    template <std::size_t... Seq>
    static any
    constructor_dispatch(any* argument_array, std::index_sequence<Seq...>)
    {
        any out = T{argument_array[Seq].get<ParamTypes>()...};
        return out;
    }
};

template <class T, class... ParamTypes>
struct braced_init_selector_impl<
    metamusil::void_t<decltype(T(std::declval<ParamTypes>()...))>,
    T,
    ParamTypes...>
{
    template <std::size_t... Seq>
    static any
    constructor_dispatch(any* argument_array, std::index_sequence<Seq...>)
    {
        any out = T(argument_array[Seq].get<ParamTypes>()...);
        return out;
    }
};

template <class T, class... ParamTypes>
using braced_init_selector = braced_init_selector_impl<void, T, ParamTypes...>;

template <class T, class... ParamTypes>
any
generic_constructor_bind_point(any* argument_array)
{
    typedef std::index_sequence_for<ParamTypes...> param_sequence;

    return braced_init_selector<T, ParamTypes...>::constructor_dispatch(
        argument_array, param_sequence());
}
} // namespace constructor_detail

namespace conversion_detail
{
template <class TargetType, class SourceType, class = void>
struct conversion_specializer;

template <>
struct conversion_specializer<void, void>;

template <class TargetType, class SourceType>
struct conversion_specializer<
    TargetType,
    SourceType,
    std::enable_if_t<std::is_convertible<SourceType, TargetType>::value>>
{
    static any
    dispatch(const any& src)
    {
        TargetType temp = (TargetType)src.get<SourceType>();
        return temp;
    }
};

template <class TargetType, class SourceType>
any
generic_conversion_bind_point(const any& src)
{
    return conversion_specializer<TargetType, SourceType>::dispatch(src);
}
} // namespace conversion_detail

namespace string_serialization_detail
{

template <class T, class = void>
struct string_serialize_type_selector;

template <class T>
struct string_serialize_type_selector<
    T,
    std::enable_if_t<std::is_arithmetic<T>::value>>
{
    static std::string
    dispatch(const any& value)
    {
        return std::to_string(value.get<T>());
    }
};

template <>
struct string_serialize_type_selector<std::string>
{
    static std::string
    dispatch(const any& value)
    {
        return value.get<std::string>();
    }
};

template <>
struct string_serialize_type_selector<char>
{
    static std::string
    dispatch(const any& value)
    {
        std::string out;
        out.push_back(value.get<char>());
        return out;
    }
};

template <>
struct string_serialize_type_selector<void>
{
    static std::string
    dispatch(const any& value)
    {
        return "empty";
    }
};

template <class T>
std::string
generic_string_serialization_bind_point(const any& value)
{
    return string_serialize_type_selector<T>::dispatch(value);
}

template <class T, class = void>
struct string_deserialize_type_selector;

template <class T>
struct string_deserialize_type_selector<
    T,
    std::enable_if_t<std::is_arithmetic<T>::value>>
{
    static any
    dispatch(const std::string& str_value)
    {
        T out = std::stold(str_value);
        return out;
    }
};

template <>
struct string_deserialize_type_selector<char>
{
    static any
    dispatch(const std::string& str_value)
    {
        return str_value[0];
    }
};

template <>
struct string_deserialize_type_selector<std::string>
{
    static any
    dispatch(const std::string& str_value)
    {
        return str_value;
    }
};

template <>
struct string_deserialize_type_selector<int>
{
    static any
    dispatch(const std::string& str_value)
    {
        return std::stoi(str_value);
    }
};

template <>
struct string_deserialize_type_selector<long>
{
    static any
    dispatch(const std::string& str_value)
    {
        return std::stol(str_value);
    }
};

template <>
struct string_deserialize_type_selector<long long>
{
    static any
    dispatch(const std::string& str_value)
    {
        return std::stoll(str_value);
    }
};

template <>
struct string_deserialize_type_selector<unsigned long>
{
    static any
    dispatch(const std::string& str_value)
    {
        return std::stoul(str_value);
    }
};

template <>
struct string_deserialize_type_selector<unsigned long long>
{
    static any
    dispatch(const std::string& str_value)
    {
        return std::stoull(str_value);
    }
};

template <>
struct string_deserialize_type_selector<float>
{
    static any
    dispatch(const std::string& str_value)
    {
        return std::stof(str_value);
    }
};

template <>
struct string_deserialize_type_selector<double>
{
    static any
    dispatch(const std::string& str_value)
    {
        return std::stod(str_value);
    }
};

template <>
struct string_deserialize_type_selector<long double>
{
    static any
    dispatch(const std::string& str_value)
    {
        return std::stold(str_value);
    }
};

template <>
struct string_deserialize_type_selector<void>
{
    static any
    dispatch(const std::string& str_value)
    {
        return shadow::any();
    }
};

template <class T>
any
generic_string_deserialization_bind_point(const std::string& str_value)
{
    return string_deserialize_type_selector<T>::dispatch(str_value);
}
} // namespace string_serialization_detail

namespace address_of_detail
{
template <class T>
any
generic_address_of_bind_point(any& value)
{
    return any(&(value.get<T>()));
}
} // namespace address_of_detail

} // namespace shadow
<commit_msg>Add pointer to function signature for address bind points. 	modified:   include/reflection_binding.hpp<commit_after>#pragma once

#include <utility>
#include <type_traits>
#include <string>

#include "any.hpp"
#include <type_list.hpp>
#include <function_deduction.hpp>
#include <member_variable_deduction.hpp>
#include <void_t.hpp>

namespace shadow
{
// free function signature
typedef any (*free_function_binding_signature)(any*);
// member function signature
typedef any (*member_function_binding_signature)(any&, any*);
// member variable getter
typedef any (*member_variable_get_binding_signature)(const any&);
// member variable setter
typedef void (*member_variable_set_binding_signature)(any&, const any&);
// constructor signature
typedef any (*constructor_binding_signature)(any*);
// conversion signature
typedef any (*conversion_binding_signature)(const any&);
// string serialize signature
typedef std::string (*string_serialization_signature)(const any&);
// string deserialization signature
typedef any (*string_deserialization_signature)(const std::string&);
// address of signature
typedef any (*address_of_signature)(any&);

////////////////////////////////////////////////////////////////////////////////
// generic bind point for free functions
// has the same signature as function pointer free_function_binding_signature
// which can be stored in the free_function_info struct

namespace free_function_detail
{
// necessary to handle void as return type differently when calling underlying
// free function
template <class ReturnType>
struct return_type_specializer
{
    // dispatch: unpacks argument type list and sequence to correctly index into
    // argument array and call get with the right types to retrieve raw values
    // from the anys
    template <class FunctionPointerType,
              FunctionPointerType FunctionPointerValue,
              class... ArgTypes,
              std::size_t... ArgSeq>
    static any
    dispatch(any* argument_array,
             metamusil::t_list::type_list<ArgTypes...>,
             std::index_sequence<ArgSeq...>)
    {
        // necessary to remove reference from types as any only stores
        // unqualified types, ie values only
        return FunctionPointerValue(
            argument_array[ArgSeq]
                .get<typename std::remove_reference_t<ArgTypes>>()...);
    }
};

template <>
struct return_type_specializer<void>
{
    // dispatch: unpacks argument type list and sequence to correctly index into
    // argument array and call get with the right types to retrieve raw values
    // from the anys
    template <class FunctionPointerType,
              FunctionPointerType FunctionPointerValue,
              class... ArgTypes,
              std::size_t... ArgSeq>
    static any
    dispatch(any* argument_array,
             metamusil::t_list::type_list<ArgTypes...>,
             std::index_sequence<ArgSeq...>)
    {
        // necessary to remove reference from types as any only stores
        // unqualified types, ie values only
        FunctionPointerValue(
            argument_array[ArgSeq]
                .get<typename std::remove_reference_t<ArgTypes>>()...);

        // return empty any, ie 'void'
        return any();
    }
};

// the value of the function pointer is stored at runtime in the template
// overload set
// this enables any function to be wrapped into uniform function signature that
// can be stored homogenously at runtime
template <class FunctionPointerType, FunctionPointerType FunctionPointerValue>
any
generic_free_function_bind_point(any* argument_array)
{
    typedef metamusil::deduce_return_type_t<FunctionPointerType> return_type;
    typedef metamusil::deduce_parameter_types_t<FunctionPointerType>
        parameter_types;
    // make integer sequence from type list
    typedef metamusil::t_list::index_sequence_for_t<parameter_types>
        parameter_sequence;

    return return_type_specializer<return_type>::
        template dispatch<FunctionPointerType, FunctionPointerValue>(
            argument_array, parameter_types(), parameter_sequence());
}
} // namespace free_function_detail

namespace member_function_detail
{

template <class ReturnType>
struct return_type_specializer
{
    template <class MemFunPointerType,
              MemFunPointerType MemFunPointerValue,
              class ObjectType,
              class... ParamTypes,
              std::size_t... ParamSequence>
    static any
    dispatch(any& object,
             any* argument_array,
             metamusil::t_list::type_list<ParamTypes...>,
             std::index_sequence<ParamSequence...>)
    {
        return (object.get<ObjectType>().*MemFunPointerValue)(
            argument_array[ParamSequence]
                .get<std::remove_reference_t<ParamTypes>>()...);
    }
};

template <>
struct return_type_specializer<void>
{
    template <class MemFunPointerType,
              MemFunPointerType MemFunPointerValue,
              class ObjectType,
              class... ParamTypes,
              std::size_t... ParamSequence>
    static any
    dispatch(any& object,
             any* argument_array,
             metamusil::t_list::type_list<ParamTypes...>,
             std::index_sequence<ParamSequence...>)
    {
        (object.get<ObjectType>().*MemFunPointerValue)(
            argument_array[ParamSequence]
                .get<std::remove_reference_t<ParamTypes>>()...);

        return any();
    }
};

template <class MemFunPointerType, MemFunPointerType MemFunPointerValue>
any
generic_member_function_bind_point(any& object, any* argument_array)
{
    // deduce return type
    typedef metamusil::deduce_return_type_t<MemFunPointerType> return_type;

    // deduce parameter types
    typedef metamusil::deduce_parameter_types_t<MemFunPointerType>
        parameter_types;

    // make integer sequence from parameter type list
    typedef metamusil::t_list::index_sequence_for_t<parameter_types>
        parameter_sequence;

    // deduce object type
    typedef metamusil::deduce_object_type_t<MemFunPointerType> object_type;

    return return_type_specializer<return_type>::
        template dispatch<MemFunPointerType, MemFunPointerValue, object_type>(
            object, argument_array, parameter_types(), parameter_sequence());
}
} // namespace member_function_detail

namespace member_variable_detail
{

template <class MemVarPointerType,
          MemVarPointerType MemVarPointerValue,
          class ObjectType,
          class MemVarType>
any
get_dispatch(const any& object)
{
    return (object.get<ObjectType>().*MemVarPointerValue);
}

template <class MemVarPointerType,
          MemVarPointerType MemVarPointerValue,
          class ObjectType,
          class MemVarType>
void
set_dispatch(any& object, const any& value)
{
    (object.get<ObjectType>().*MemVarPointerValue) = value.get<MemVarType>();
}

template <class MemVarPointerType, MemVarPointerType MemVarPointerValue>
any
generic_member_variable_get_bind_point(const any& object)
{
    typedef metamusil::deduce_member_variable_object_type_t<MemVarPointerType>
        object_type;
    typedef metamusil::deduce_member_variable_type_t<MemVarPointerType>
        member_variable_type;

    return get_dispatch<MemVarPointerType,
                        MemVarPointerValue,
                        object_type,
                        member_variable_type>(object);
}

template <class MemVarPointerType, MemVarPointerType MemVarPointerValue>
void
generic_member_variable_set_bind_point(any& object, const any& value)
{
    typedef metamusil::deduce_member_variable_object_type_t<MemVarPointerType>
        object_type;
    typedef metamusil::deduce_member_variable_type_t<MemVarPointerType>
        member_variable_type;

    return set_dispatch<MemVarPointerType,
                        MemVarPointerValue,
                        object_type,
                        member_variable_type>(object, value);
}
} // namespace member_variable_detail

namespace constructor_detail
{

// purpose of braced_init_selector is to attempt to use constructor T(...) if
// available, otherwise fall back to braced init list initialization
template <class, class T, class... ParamTypes>
struct braced_init_selector_impl
{
    template <std::size_t... Seq>
    static any
    constructor_dispatch(any* argument_array, std::index_sequence<Seq...>)
    {
        any out = T{argument_array[Seq].get<ParamTypes>()...};
        return out;
    }
};

template <class T, class... ParamTypes>
struct braced_init_selector_impl<
    metamusil::void_t<decltype(T(std::declval<ParamTypes>()...))>,
    T,
    ParamTypes...>
{
    template <std::size_t... Seq>
    static any
    constructor_dispatch(any* argument_array, std::index_sequence<Seq...>)
    {
        any out = T(argument_array[Seq].get<ParamTypes>()...);
        return out;
    }
};

template <class T, class... ParamTypes>
using braced_init_selector = braced_init_selector_impl<void, T, ParamTypes...>;

template <class T, class... ParamTypes>
any
generic_constructor_bind_point(any* argument_array)
{
    typedef std::index_sequence_for<ParamTypes...> param_sequence;

    return braced_init_selector<T, ParamTypes...>::constructor_dispatch(
        argument_array, param_sequence());
}
} // namespace constructor_detail

namespace conversion_detail
{
template <class TargetType, class SourceType, class = void>
struct conversion_specializer;

template <>
struct conversion_specializer<void, void>;

template <class TargetType, class SourceType>
struct conversion_specializer<
    TargetType,
    SourceType,
    std::enable_if_t<std::is_convertible<SourceType, TargetType>::value>>
{
    static any
    dispatch(const any& src)
    {
        TargetType temp = (TargetType)src.get<SourceType>();
        return temp;
    }
};

template <class TargetType, class SourceType>
any
generic_conversion_bind_point(const any& src)
{
    return conversion_specializer<TargetType, SourceType>::dispatch(src);
}
} // namespace conversion_detail

namespace string_serialization_detail
{

template <class T, class = void>
struct string_serialize_type_selector;

template <class T>
struct string_serialize_type_selector<
    T,
    std::enable_if_t<std::is_arithmetic<T>::value>>
{
    static std::string
    dispatch(const any& value)
    {
        return std::to_string(value.get<T>());
    }
};

template <>
struct string_serialize_type_selector<std::string>
{
    static std::string
    dispatch(const any& value)
    {
        return value.get<std::string>();
    }
};

template <>
struct string_serialize_type_selector<char>
{
    static std::string
    dispatch(const any& value)
    {
        std::string out;
        out.push_back(value.get<char>());
        return out;
    }
};

template <>
struct string_serialize_type_selector<void>
{
    static std::string
    dispatch(const any& value)
    {
        return "empty";
    }
};

template <class T>
std::string
generic_string_serialization_bind_point(const any& value)
{
    return string_serialize_type_selector<T>::dispatch(value);
}

template <class T, class = void>
struct string_deserialize_type_selector;

template <class T>
struct string_deserialize_type_selector<
    T,
    std::enable_if_t<std::is_arithmetic<T>::value>>
{
    static any
    dispatch(const std::string& str_value)
    {
        T out = std::stold(str_value);
        return out;
    }
};

template <>
struct string_deserialize_type_selector<char>
{
    static any
    dispatch(const std::string& str_value)
    {
        return str_value[0];
    }
};

template <>
struct string_deserialize_type_selector<std::string>
{
    static any
    dispatch(const std::string& str_value)
    {
        return str_value;
    }
};

template <>
struct string_deserialize_type_selector<int>
{
    static any
    dispatch(const std::string& str_value)
    {
        return std::stoi(str_value);
    }
};

template <>
struct string_deserialize_type_selector<long>
{
    static any
    dispatch(const std::string& str_value)
    {
        return std::stol(str_value);
    }
};

template <>
struct string_deserialize_type_selector<long long>
{
    static any
    dispatch(const std::string& str_value)
    {
        return std::stoll(str_value);
    }
};

template <>
struct string_deserialize_type_selector<unsigned long>
{
    static any
    dispatch(const std::string& str_value)
    {
        return std::stoul(str_value);
    }
};

template <>
struct string_deserialize_type_selector<unsigned long long>
{
    static any
    dispatch(const std::string& str_value)
    {
        return std::stoull(str_value);
    }
};

template <>
struct string_deserialize_type_selector<float>
{
    static any
    dispatch(const std::string& str_value)
    {
        return std::stof(str_value);
    }
};

template <>
struct string_deserialize_type_selector<double>
{
    static any
    dispatch(const std::string& str_value)
    {
        return std::stod(str_value);
    }
};

template <>
struct string_deserialize_type_selector<long double>
{
    static any
    dispatch(const std::string& str_value)
    {
        return std::stold(str_value);
    }
};

template <>
struct string_deserialize_type_selector<void>
{
    static any
    dispatch(const std::string& str_value)
    {
        return shadow::any();
    }
};

template <class T>
any
generic_string_deserialization_bind_point(const std::string& str_value)
{
    return string_deserialize_type_selector<T>::dispatch(str_value);
}
} // namespace string_serialization_detail

namespace address_of_detail
{
template <class T>
any
generic_address_of_bind_point(any& value)
{
    return any(&(value.get<T>()));
}
} // namespace address_of_detail

} // namespace shadow
<|endoftext|>


<commit_before>#ifndef TUDOCOMP_VIEW_H
#define TUDOCOMP_VIEW_H

#include <algorithm>
#include <cmath>
#include <cstddef>
#include <fstream>
#include <iostream>
#include <memory>
#include <sstream>
#include <string>
#include <type_traits>
#include <utility>
#include <iomanip>

namespace tudocomp {

/// A view into a slice of memory.
template<class T>
class View {
    T*     m_data;
    size_t m_size;

    void bound_check(size_t pos) {
        if (pos >= m_size) {
            std::stringstream ss;
            ss << "indexed view of size ";
            ss << m_size;
            ss << " with out-of-bounds value ";
            ss << pos;
            throw std::out_of_range(ss.str());
        }
    }

public:
    // Type members

    using value_type             = T;
    using size_type              = std::size_t;
    using difference_type        = std::ptrdiff_t;
    using reference              = value_type&;
    using const_reference        = const value_type&;
    using pointer                = value_type*;
    using const_pointer          = const value_type*;
    using iterator               = pointer;
    using const_iterator         = const_pointer;
    using reverse_iterator       = std::reverse_iterator<iterator>;
    using const_reverse_iterator = std::reverse_iterator<const_iterator>;

    // static value members

    static const size_type npos = -1;

    // Constructors

    View(T* data, size_t len): m_data(data), m_size(len) {}

    View(const View<T>& other):   View(other.m_data, other.m_size) {}
    View(View<T>&& other):        View(other.m_data, other.m_size) {}

    View(std::vector<T>& other): View(other.data(), other.size()) {}

    // Element access

    reference       at(size_type pos) {
        bound_check(pos);
        return m_data[pos];
    }
    const_reference at(size_type pos) const {
        bound_check(pos);
        return m_data[pos];
    }

    reference       operator[](size_type pos) {
#ifdef DEBUG
        bound_check(pos);
#endif
        return m_data[pos];
    }
    const_reference operator[](size_type pos) const {
#ifdef DEBUG
        bound_check(pos);
#endif
        return m_data[pos];
    }

    reference front() {
        return (*this)[0];
    }
    const_reference front() const {
        return (*this)[0];
    }

    reference back() {
        return (*this)[m_size - 1];
    }
    const_reference back() const {
        return (*this)[m_size - 1];
    }

    T* data() {
        return front();
    }
    const T* data() const {
        return front();
    }

    // Iterators

    iterator begin() {
        return (*this)[0];
    }
    const_iterator begin() const {
        return (*this)[0];
    }
    const_iterator cbegin() const {
        return begin();
    }

    iterator end() {
        return (*this)[m_size];
    }
    const_iterator end() const {
        return (*this)[m_size];
    }
    const_iterator cend() const {
        return end();
    }

    reverse_iterator rbegin() {
        return std::reverse_iterator<iterator>(end());
    }
    const_reverse_iterator rbegin() const {
        return std::reverse_iterator<const_reverse_iterator>(end());
    }
    const_reverse_iterator crbegin() const {
        return rbegin();
    }

    reverse_iterator rend() {
        return std::reverse_iterator<iterator>(begin());
    }
    const_reverse_iterator rend() const {
        return std::reverse_iterator<const_reverse_iterator>(begin());
    }
    const_reverse_iterator crend() const {
        return rend();
    }

    // Capacity

    bool empty() const {
        return m_size == 0;
    }

    size_type size() const {
        return m_size;
    }

    // Modifiers

    void swap(View<T>& other) {
        using std::swap;

        swap(m_data, other.m_data);
        swap(m_size, other.m_size);
    }

    friend void swap(View<T>& a, View<T>& b) {
        a.swap(b);
    }

    // Slicing

    View slice(size_type from, size_type to = npos) {
        // TODO
        // DCHECK(from <= to);

        if (to == npos) {
            to = m_size;
        }
        return View(&(*this)[from], to - from);
    }

    View substr(size_type from, size_type to = npos) {
        return slice(from, to);
    }
};

template<class T>
bool operator==(const View<T>& lhs, const View<T>& rhs) {
    return (lhs.size() == rhs.size())
        && std::equal(lhs.cbegin(), lhs.cend(), rhs.cbegin());
}
template<class T>
bool operator!=(const View<T>& lhs, const View<T>& rhs) {
    return !(lhs == rhs);
}
template<class T>
bool operator<(const View<T>& lhs, const View<T>& rhs) {
    return std::lexicographical_compare(lhs.cbegin(), lhs.cend(),
                                        rhs.cbegin(), rhs.cend());
}
template<class T>
bool operator>(const View<T>& lhs, const View<T>& rhs) {
    struct greater {
        inline bool cmp(const T& l, const T& r) {
            return l > r;
        }
    };

    return std::lexicographical_compare(lhs.cbegin(), lhs.cend(),
                                        rhs.cbegin(), rhs.cend(),
                                        greater());
}
template<class T>
bool operator<=(const View<T>& lhs, const View<T>& rhs) {
    return !(lhs > rhs);
}
template<class T>
bool operator>=(const View<T>& lhs, const View<T>& rhs) {
    return !(lhs < rhs);
}

}

#endif
<commit_msg>Turned View into a const View<commit_after>#ifndef TUDOCOMP_VIEW_H
#define TUDOCOMP_VIEW_H

#include <algorithm>
#include <cmath>
#include <cstddef>
#include <fstream>
#include <iostream>
#include <memory>
#include <sstream>
#include <string>
#include <type_traits>
#include <utility>
#include <iomanip>

namespace tudocomp {

/// A view into a slice of memory.
template<class T>
class View {
    const T* m_data;
    size_t   m_size;

    void bound_check(size_t pos) {
        if (pos >= m_size) {
            std::stringstream ss;
            ss << "indexed view of size ";
            ss << m_size;
            ss << " with out-of-bounds value ";
            ss << pos;
            throw std::out_of_range(ss.str());
        }
    }

public:
    // Type members

    using value_type             = T;
    using size_type              = std::size_t;
    using difference_type        = std::ptrdiff_t;
    using const_reference        = const value_type&;
    using const_pointer          = const value_type*;
    using const_iterator         = const_pointer;
    using const_reverse_iterator = std::reverse_iterator<const_iterator>;

    // static value members

    static const size_type npos = -1;

    // Constructors

    View(const T* data, size_t len): m_data(data), m_size(len) {}

    View(const View<T>& other):   View(other.m_data, other.m_size) {}
    View(View<T>&& other):        View(other.m_data, other.m_size) {}

    View(const std::vector<T>& other): View(other.data(), other.size()) {}

    // Element access

    const_reference at(size_type pos) const {
        bound_check(pos);
        return m_data[pos];
    }

    const_reference operator[](size_type pos) const {
#ifdef DEBUG
        bound_check(pos);
#endif
        return m_data[pos];
    }

    const_reference front() const {
        return (*this)[0];
    }

    const_reference back() const {
        return (*this)[m_size - 1];
    }

    const T* data() const {
        return front();
    }

    // Iterators

    const_iterator begin() const {
        return (*this)[0];
    }
    const_iterator cbegin() const {
        return begin();
    }

    const_iterator end() const {
        return (*this)[m_size];
    }
    const_iterator cend() const {
        return end();
    }

    const_reverse_iterator rbegin() const {
        return std::reverse_iterator<const_reverse_iterator>(end());
    }
    const_reverse_iterator crbegin() const {
        return rbegin();
    }

    const_reverse_iterator rend() const {
        return std::reverse_iterator<const_reverse_iterator>(begin());
    }
    const_reverse_iterator crend() const {
        return rend();
    }

    // Capacity

    bool empty() const {
        return m_size == 0;
    }

    size_type size() const {
        return m_size;
    }

    // Modifiers

    void swap(View<T>& other) {
        using std::swap;

        swap(m_data, other.m_data);
        swap(m_size, other.m_size);
    }

    friend void swap(View<T>& a, View<T>& b) {
        a.swap(b);
    }

    // Slicing

    View slice(size_type from, size_type to = npos) const {
        // TODO
        // DCHECK(from <= to);

        if (to == npos) {
            to = m_size;
        }
        return View(&(*this)[from], to - from);
    }

    View substr(size_type from, size_type to = npos) const {
        return slice(from, to);
    }
};

template<class T>
bool operator==(const View<T>& lhs, const View<T>& rhs) {
    return (lhs.size() == rhs.size())
        && std::equal(lhs.cbegin(), lhs.cend(), rhs.cbegin());
}
template<class T>
bool operator!=(const View<T>& lhs, const View<T>& rhs) {
    return !(lhs == rhs);
}
template<class T>
bool operator<(const View<T>& lhs, const View<T>& rhs) {
    return std::lexicographical_compare(lhs.cbegin(), lhs.cend(),
                                        rhs.cbegin(), rhs.cend());
}
template<class T>
bool operator>(const View<T>& lhs, const View<T>& rhs) {
    struct greater {
        inline bool cmp(const T& l, const T& r) {
            return l > r;
        }
    };

    return std::lexicographical_compare(lhs.cbegin(), lhs.cend(),
                                        rhs.cbegin(), rhs.cend(),
                                        greater());
}
template<class T>
bool operator<=(const View<T>& lhs, const View<T>& rhs) {
    return !(lhs > rhs);
}
template<class T>
bool operator>=(const View<T>& lhs, const View<T>& rhs) {
    return !(lhs < rhs);
}

}

#endif
<|endoftext|>


<commit_before>#ifndef INTEGER_RANGE_HPP
#define INTEGER_RANGE_HPP

#include <boost/assert.hpp>

#include <type_traits>

#include <cstdint>

namespace osrm
{
namespace util
{

// Warning: do not try to replace this with Boost's irange, as it is broken on Boost 1.55:
//     auto r = boost::irange<unsigned int>(0, 15);
//     std::cout << r.size() << std::endl;
// results in -4294967281. Latest Boost versions fix this, but we still support older ones.

template <typename Integer> class range
{
  private:
    const Integer last;
    Integer iter;

  public:
    range(Integer start, Integer end) noexcept : last(end), iter(start)
    {
        BOOST_ASSERT_MSG(start <= end, "backwards counting ranges not suppoted");
        static_assert(std::is_integral<Integer>::value, "range type must be integral");
    }

    // Iterable functions
    const range &begin() const noexcept { return *this; }
    const range &end() const noexcept { return *this; }
    Integer front() const noexcept { return iter; }
    Integer back() const noexcept { return last - 1; }
    std::size_t size() const noexcept { return static_cast<std::size_t>(last - iter); }

    // Iterator functions
    bool operator!=(const range &) const noexcept { return iter < last; }
    void operator++() noexcept { ++iter; }
    Integer operator*() const noexcept { return iter; }
};

// convenience function to construct an integer range with type deduction
template <typename Integer>
range<Integer>
irange(const Integer first,
       const Integer last,
       typename std::enable_if<std::is_integral<Integer>::value>::type * = 0) noexcept
{
    return range<Integer>(first, last);
}
}
}

#endif // INTEGER_RANGE_HPP
<commit_msg>Make osrm::util::range a model of SinglePassRangeConcept<commit_after>#ifndef INTEGER_RANGE_HPP
#define INTEGER_RANGE_HPP

#include <boost/assert.hpp>
#include <boost/iterator/iterator_facade.hpp>

#include <type_traits>

#include <cstdint>

namespace osrm
{
namespace util
{

// Ported from Boost.Range 1.56 due to required fix
// https://github.com/boostorg/range/commit/9e6bdc13ba94af4e150afae547557a2fbbfe3bf0
// Can be removed after dropping support of Boost < 1.56
template <typename Integer>
class integer_iterator : public boost::iterator_facade<integer_iterator<Integer>,
                                                       Integer,
                                                       boost::random_access_traversal_tag,
                                                       Integer>
{
    typedef boost::iterator_facade<integer_iterator<Integer>,
                                   Integer,
                                   boost::random_access_traversal_tag,
                                   Integer>
        base_t;

  public:
    typedef typename base_t::value_type value_type;
    typedef typename base_t::difference_type difference_type;
    typedef typename base_t::reference reference;
    typedef std::random_access_iterator_tag iterator_category;

    integer_iterator() : m_value() {}
    explicit integer_iterator(value_type x) : m_value(x) {}

  private:
    void increment() { ++m_value; }
    void decrement() { --m_value; }
    void advance(difference_type offset) { m_value += offset; }
    bool equal(const integer_iterator &other) const { return m_value == other.m_value; }
    reference dereference() const { return m_value; }

    difference_type distance_to(const integer_iterator &other) const
    {
        return std::is_signed<value_type>::value
                   ? (other.m_value - m_value)
                   : (other.m_value >= m_value)
                         ? static_cast<difference_type>(other.m_value - m_value)
                         : -static_cast<difference_type>(m_value - other.m_value);
    }

    friend class ::boost::iterator_core_access;
    value_type m_value;
};

// Warning: do not try to replace this with Boost's irange, as it is broken on Boost 1.55:
//     auto r = boost::irange<unsigned int>(0, 15);
//     std::cout << r.size() << std::endl;
// results in -4294967281. Latest Boost versions fix this, but we still support older ones.

template <typename Integer> class range
{
  public:
    typedef integer_iterator<Integer> const_iterator;
    typedef integer_iterator<Integer> iterator;

    range(Integer begin, Integer end) : iter(begin), last(end) {}

    iterator begin() const noexcept { return iter; }
    iterator end() const noexcept { return last; }
    Integer front() const noexcept { return *iter; }
    Integer back() const noexcept { return *last - 1; }
    std::size_t size() const noexcept { return static_cast<std::size_t>(last - iter); }

  private:
    iterator iter;
    iterator last;
};

// convenience function to construct an integer range with type deduction
template <typename Integer>
range<Integer>
irange(const Integer first,
       const Integer last,
       typename std::enable_if<std::is_integral<Integer>::value>::type * = 0) noexcept
{
    return range<Integer>(first, last);
}
}
}

#endif // INTEGER_RANGE_HPP
<|endoftext|>


<commit_before>/***************************************************************************
* Copyright (c) 2016, Johan Mabille and Sylvain Corlay                     *
*                                                                          *
* Distributed under the terms of the BSD 3-Clause License.                 *
*                                                                          *
* The full license is in the file LICENSE, distributed with this software. *
****************************************************************************/

#ifndef XVECTORIZE_HPP
#define XVECTORIZE_HPP

#include <type_traits>
#include <utility>

#include "xutils.hpp"

namespace xt
{

    /***************
     * xvectorizer *
     ***************/

    template <class F, class R>
    class xvectorizer
    {

    public:

        template <class... E>
        using xfunction_type = xfunction<F, R, xclosure_t<E>...>;

        template <class Func>
        explicit xvectorizer(Func&& f);

        template <class... E>
        xfunction_type<E...> operator()(E&&... e) const;

    private:

        typename std::remove_reference<F>::type m_f;
    };

    namespace detail
    {
        template <class F>
        using get_function_type = remove_class_t<decltype(&std::remove_reference_t<F>::operator())>;
    }

    template <class R, class... Args>
    xvectorizer<R (*)(Args...), R> vectorize(R (*f)(Args...));

    template <class F, class R, class... Args>
    xvectorizer<F, R> vectorize(F&& f, R (*)(Args...));

    template <class F>
    auto vectorize(F&& f) -> decltype(vectorize(std::forward<F>(f), (detail::get_function_type<F>*)nullptr));

    /******************************
     * xvectorizer implementation *
     ******************************/

    template <class F, class R>
    template <class Func>
    inline xvectorizer<F, R>::xvectorizer(Func&& f)
        : m_f(std::forward<Func>(f))
    {
    }

    template <class F, class R>
    template <class... E>
    inline auto xvectorizer<F, R>::operator()(E&&... e) const -> xfunction_type<E...>
    {
        return xfunction_type<E...>(m_f, std::forward<E>(e)...);
    }

    template <class R, class... Args>
    inline xvectorizer<R (*)(Args...), R> vectorize(R (*f)(Args...))
    {
        return xvectorizer<R (*)(Args...), R>(f);
    }

    template <class F, class R, class... Args>
    inline xvectorizer<F, R> vectorize(F&& f, R (*)(Args...))
    {
        return xvectorizer<F, R>(std::forward<F>(f));
    }

    template <class F>
    inline auto vectorize(F&& f) -> decltype(vectorize(std::forward<F>(f), (detail::get_function_type<F>*)nullptr))
    {
        return vectorize(std::forward<F>(f), (detail::get_function_type<F>*)nullptr);
    }
}

#endif
<commit_msg>Disable catch-all constructor<commit_after>/***************************************************************************
* Copyright (c) 2016, Johan Mabille and Sylvain Corlay                     *
*                                                                          *
* Distributed under the terms of the BSD 3-Clause License.                 *
*                                                                          *
* The full license is in the file LICENSE, distributed with this software. *
****************************************************************************/

#ifndef XVECTORIZE_HPP
#define XVECTORIZE_HPP

#include <type_traits>
#include <utility>

#include "xutils.hpp"

namespace xt
{

    /***************
     * xvectorizer *
     ***************/

    template <class F, class R>
    class xvectorizer
    {

    public:

        template <class... E>
        using xfunction_type = xfunction<F, R, xclosure_t<E>...>;

        template <class Func, class = std::enable_if_t<!std::is_same<std::decay_t<Func>, xvectorizer>::value>>
        xvectorizer(Func&& f);

        template <class... E>
        xfunction_type<E...> operator()(E&&... e) const;

    private:

        typename std::remove_reference<F>::type m_f;
    };

    namespace detail
    {
        template <class F>
        using get_function_type = remove_class_t<decltype(&std::remove_reference_t<F>::operator())>;
    }

    template <class R, class... Args>
    xvectorizer<R (*)(Args...), R> vectorize(R (*f)(Args...));

    template <class F, class R, class... Args>
    xvectorizer<F, R> vectorize(F&& f, R (*)(Args...));

    template <class F>
    auto vectorize(F&& f) -> decltype(vectorize(std::forward<F>(f), (detail::get_function_type<F>*)nullptr));

    /******************************
     * xvectorizer implementation *
     ******************************/

    template <class F, class R>
    template <class Func, class>
    inline xvectorizer<F, R>::xvectorizer(Func&& f)
        : m_f(std::forward<Func>(f))
    {
    }

    template <class F, class R>
    template <class... E>
    inline auto xvectorizer<F, R>::operator()(E&&... e) const -> xfunction_type<E...>
    {
        return xfunction_type<E...>(m_f, std::forward<E>(e)...);
    }

    template <class R, class... Args>
    inline xvectorizer<R (*)(Args...), R> vectorize(R (*f)(Args...))
    {
        return xvectorizer<R (*)(Args...), R>(f);
    }

    template <class F, class R, class... Args>
    inline xvectorizer<F, R> vectorize(F&& f, R (*)(Args...))
    {
        return xvectorizer<F, R>(std::forward<F>(f));
    }

    template <class F>
    inline auto vectorize(F&& f) -> decltype(vectorize(std::forward<F>(f), (detail::get_function_type<F>*)nullptr))
    {
        return vectorize(std::forward<F>(f), (detail::get_function_type<F>*)nullptr);
    }
}

#endif
<|endoftext|>