<commit_before>/// @file
/// @author uentity
/// @date 03.04.2017
/// @brief any_array is an array of values of arbitrary type, based on boost::any
/// @copyright
/// This Source Code Form is subject to the terms of the Mozilla Public License,
/// v. 2.0. If a copy of the MPL was not distributed with this file,
/// You can obtain one at https://mozilla.org/MPL/2.0/

#pragma once

#include "common.h"
#include <boost/any.hpp>
#include <map>

NAMESPACE_BEGIN(blue_sky)

template< template< class > class cont_traits >
class any_array : public cont_traits< boost::any > {
public:
	using container_t = cont_traits< boost::any >;

private:
	// SFINAE check if container T has mapped_type defined
	// i.e. is a map-like
	template< typename T >
	struct void_ { using type = void; };

	template< typename T, typename = void >
	struct has_mapped_t : std::false_type {};

	template< typename T >
	struct has_mapped_t< T, typename void_< typename T::mapped_type >::type > : std::true_type {};

public:
	// trait for vector-like containers
	template< typename Cont = container_t, typename = void >
	struct trait_impl {
		using key_type = std::size_t;

		template< typename Iterator >
		static auto& iter2val(const Iterator& i) {
			return *i;
		}

		template< class Iterator >
		static key_type iter2key(const Cont& C, const Iterator& i) {
			return std::distance(C.begin(), i);
		}

		// use bound-checking to simulate map behaviour and make comparison of returned iterator
		// with C.end() valid
		template< typename Container >
		static auto find(Container& C, const key_type& k) {
			auto res = C.begin();
			std::advance(res, std::min(k, C.size()));
			return res;
		}

		static bool has_key(const Cont& C, const key_type& k) {
			return k < C.size();
		}

		static bool insert(Cont& C, const key_type& k, boost::any value) {
			if(k <= C.size()) {
				C.insert(std::next(C.begin(), k), std::move(value));
				return true;
			}
			return false;
		}
	};

	// trait for map-like containers
	template< typename Cont >
	struct trait_impl< Cont, typename std::enable_if_t< has_mapped_t< Cont >::value > > {
		using key_type = typename Cont::key_type;
		using value_type = typename Cont::value_type;

		template< typename Iterator >
		static auto& iter2val(const Iterator& i) {
			return i->second;
		}

		template< class Iterator >
		static const key_type& iter2key(const Cont& C, const Iterator& i) {
			return i->first;
		}

		template< typename Container >
		static auto find(Container& C, const key_type& k) {
			return C.find(k);
		}

		static bool has_key(const Cont& C, const key_type& k) {
			return C.find(k) != C.end();
		}

		static bool insert(Cont& C, const key_type& k, boost::any value) {
			return C.insert(value_type(k, std::move(value))).second;
		}
	};

	using trait = trait_impl< container_t >;

	// helper class to auto-convert return type to destination const reference type
	struct value_cast {
		explicit value_cast(const boost::any& val) : val_(val) {}

		// only move semantics allowed
		value_cast(const value_cast&) = delete;
		value_cast& operator=(const value_cast&) = delete;
		value_cast(value_cast&&) = default;

		// allow only implicit conversions to const reference
		template< typename T >
		operator T() const && {
			return boost::any_cast< const T& >(val_);
		}

	private:
		const boost::any& val_;
	};

	using key_type = typename trait::key_type;

	// import base class constructors
	using container_t::container_t;
	// import commonly used functions
	using container_t::begin;
	using container_t::end;
	using container_t::size;

	// count number of elements of givent type
	template< typename T >
	std::size_t size() const {
		std::size_t res = 0;
		for(auto pv = begin(); pv != end(); ++pv) {
			if(trait::iter2val(pv).type() == typeid(T))
				++res;
		}
		return res;
	}

	// test if array contain specified key
	bool has_key(const key_type& k) const {
		return trait::has_key(*this, k);
	}

	// return reference to value at specified index
	// value type is specified explicitly
	template< typename value_type >
	value_type& ss(const key_type& key) {
		return boost::any_cast< value_type& >(
			trait::iter2val(trait::find(*this, key))
		);
	}
	template< typename value_type >
	const value_type& ss(const key_type& key) const {
		return boost::any_cast< const value_type& >(
			trait::iter2val(trait::find(*this, key))
		);
	}

	// value type is omitted - do lazy cast
	// can only appear on right side of expression
	value_cast ss(const key_type& key) const {
		return value_cast(
			trait::iter2val(trait::find(*this, key))
		);
	}

	// tries to find value by given key
	// if value isn't found, target value is not modified
	// does not throw
	template< typename value_type >
	bool extract(const key_type& key, value_type& target) const {
		auto pval = trait::find(*this, key);
		if(pval == end()) return false;
		try {
			// copy value from source to target
			target = boost::any_cast< const value_type& >(trait::iter2val(pval));
			return true;
		}
		catch(boost::bad_any_cast) {
			return false;
		}
	}

	// Safely extract and return COPY of some value by given key. If no such value found,
	// default value is returned.
	template< typename value_type >
	value_type at(const key_type& key, const value_type def_val = value_type()) const {
		value_type res;
		if(!extract(key, res))
			res = def_val;
		return res;
	}

	// extract all keys
	std::vector< key_type > keys() const {<commit_msg>any_array: catch polymorphic exception by reference<commit_after>/// @file
/// @author uentity
/// @date 03.04.2017
/// @brief any_array is an array of values of arbitrary type, based on boost::any
/// @copyright
/// This Source Code Form is subject to the terms of the Mozilla Public License,
/// v. 2.0. If a copy of the MPL was not distributed with this file,
/// You can obtain one at https://mozilla.org/MPL/2.0/

#pragma once

#include "common.h"
#include <boost/any.hpp>
#include <map>

NAMESPACE_BEGIN(blue_sky)

template< template< class > class cont_traits >
class any_array : public cont_traits< boost::any > {
public:
	using container_t = cont_traits< boost::any >;

private:
	// SFINAE check if container T has mapped_type defined
	// i.e. is a map-like
	template< typename T >
	struct void_ { using type = void; };

	template< typename T, typename = void >
	struct has_mapped_t : std::false_type {};

	template< typename T >
	struct has_mapped_t< T, typename void_< typename T::mapped_type >::type > : std::true_type {};

public:
	// trait for vector-like containers
	template< typename Cont = container_t, typename = void >
	struct trait_impl {
		using key_type = std::size_t;

		template< typename Iterator >
		static auto& iter2val(const Iterator& i) {
			return *i;
		}

		template< class Iterator >
		static key_type iter2key(const Cont& C, const Iterator& i) {
			return std::distance(C.begin(), i);
		}

		// use bound-checking to simulate map behaviour and make comparison of returned iterator
		// with C.end() valid
		template< typename Container >
		static auto find(Container& C, const key_type& k) {
			auto res = C.begin();
			std::advance(res, std::min(k, C.size()));
			return res;
		}

		static bool has_key(const Cont& C, const key_type& k) {
			return k < C.size();
		}

		static bool insert(Cont& C, const key_type& k, boost::any value) {
			if(k <= C.size()) {
				C.insert(std::next(C.begin(), k), std::move(value));
				return true;
			}
			return false;
		}
	};

	// trait for map-like containers
	template< typename Cont >
	struct trait_impl< Cont, typename std::enable_if_t< has_mapped_t< Cont >::value > > {
		using key_type = typename Cont::key_type;
		using value_type = typename Cont::value_type;

		template< typename Iterator >
		static auto& iter2val(const Iterator& i) {
			return i->second;
		}

		template< class Iterator >
		static const key_type& iter2key(const Cont& C, const Iterator& i) {
			return i->first;
		}

		template< typename Container >
		static auto find(Container& C, const key_type& k) {
			return C.find(k);
		}

		static bool has_key(const Cont& C, const key_type& k) {
			return C.find(k) != C.end();
		}

		static bool insert(Cont& C, const key_type& k, boost::any value) {
			return C.insert(value_type(k, std::move(value))).second;
		}
	};

	using trait = trait_impl< container_t >;

	// helper class to auto-convert return type to destination const reference type
	struct value_cast {
		explicit value_cast(const boost::any& val) : val_(val) {}

		// only move semantics allowed
		value_cast(const value_cast&) = delete;
		value_cast& operator=(const value_cast&) = delete;
		value_cast(value_cast&&) = default;

		// allow only implicit conversions to const reference
		template< typename T >
		operator T() const && {
			return boost::any_cast< const T& >(val_);
		}

	private:
		const boost::any& val_;
	};

	using key_type = typename trait::key_type;

	// import base class constructors
	using container_t::container_t;
	// import commonly used functions
	using container_t::begin;
	using container_t::end;
	using container_t::size;

	// count number of elements of givent type
	template< typename T >
	std::size_t size() const {
		std::size_t res = 0;
		for(auto pv = begin(); pv != end(); ++pv) {
			if(trait::iter2val(pv).type() == typeid(T))
				++res;
		}
		return res;
	}

	// test if array contain specified key
	bool has_key(const key_type& k) const {
		return trait::has_key(*this, k);
	}

	// return reference to value at specified index
	// value type is specified explicitly
	template< typename value_type >
	value_type& ss(const key_type& key) {
		return boost::any_cast< value_type& >(
			trait::iter2val(trait::find(*this, key))
		);
	}
	template< typename value_type >
	const value_type& ss(const key_type& key) const {
		return boost::any_cast< const value_type& >(
			trait::iter2val(trait::find(*this, key))
		);
	}

	// value type is omitted - do lazy cast
	// can only appear on right side of expression
	value_cast ss(const key_type& key) const {
		return value_cast(
			trait::iter2val(trait::find(*this, key))
		);
	}

	// tries to find value by given key
	// if value isn't found, target value is not modified
	// does not throw
	template< typename value_type >
	bool extract(const key_type& key, value_type& target) const {
		auto pval = trait::find(*this, key);
		if(pval == end()) return false;
		try {
			// copy value from source to target
			target = boost::any_cast< const value_type& >(trait::iter2val(pval));
			return true;
		}
		catch(const boost::bad_any_cast&) {
			return false;
		}
	}

	// Safely extract and return COPY of some value by given key. If no such value found,
	// default value is returned.
	template< typename value_type >
	value_type at(const key_type& key, const value_type def_val = value_type()) const {
		value_type res;
		if(!extract(key, res))
			res = def_val;
		return res;
	}

	// extract all keys
	std::vector< key_type > keys() const {
{'fraction_non_alphanumeric': 0.12349977095739807, 'fraction_numerical': 0.004031149793861658, 'mean_word_length': 3.739904472427269, 'pattern_counts': {'":': 0, '<': 75, '<?xml version=': 0, '>': 75, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4486119', 'n_tokens_mistral': 3950, 'n_tokens_neox': 3580, 'n_words': 1176}