/** @file overflow.h
 *
 *	Interface of simple overflowen statistics tracker.
 *
 *	(C) Ceslav Przywara 2008, MFF UK Prague
 *
 */

#ifndef _OVERFLOW_H
#define	_OVERFLOW_H

#include <limits>
#include <map>

namespace ace {

/** Class serves as mapping between objects of given type
 *	and (some) statistics, which shall be stored in _ValueType.
 *	Although design of this class is quite general, within program
 *	it's used just to hold overflowen statistics, so the class name
 *	is kept related.
 */
template<class _KeyType, class _ValueType>
class Overflow {
	/** Mapping is performed by simple map.
	 */
	typedef typename std::map<_KeyType, _ValueType> _overflows_map_t;
	/** Maximum allowed value for given type (may be safely static).
	 */
	static const _ValueType _max_value;
	/** Mapping container.
	 */
	_overflows_map_t _overflows_map;
public:
	/** Add new "key, value" pair.
	 *	@param key Key to be added.
	 *	@param value Value to be added.
	 */
	void add(_KeyType key, _ValueType value) {
		typename _overflows_map_t::iterator iter = _overflows_map.lower_bound(key);
		if ( iter->first == key ) {
			iter->second = add_to_maximum(iter->second, value);
		} else {
			_overflows_map.insert(iter, typename _overflows_map_t::value_type(key, value));
		}
	}
	/** @param a First value to add.
	 *  @param b Second value to add.
	 *	@return Sum of a and b or maximum value storable in _ValueType,
	 *		if a + b would overflow.
	 */
	static _ValueType add_to_maximum(_ValueType a, _ValueType b) {
		return ((_max_value - a) < b ) ? _max_value : a + b;
	}
	/** @param key Key (must be already in, no checks are performed).
	 *	@return Value assigned to given key.
	 */
	inline _ValueType get(_KeyType key) { return _overflows_map[key]; }
};

template<class _KeyType, class _ValueType>
const _ValueType Overflow<_KeyType, _ValueType>::_max_value = std::numeric_limits<_ValueType>::max();

} // namespace ace

#endif
