<commit_before>#ifndef UTIL_CONT_MAP_H__
#define UTIL_CONT_MAP_H__

#include <vector>
#include <map>

namespace util {

/**
 * Default converter that does nothing.
 */
template <typename T>
struct identity {

	typedef T TargetType;

	const TargetType& operator()(const T& t) { return t; }
};

/**
 * Implements a std::map interface for keys that have a numerical interpretation
 * and are expected to be continuous.
 *
 * Key-value pairs are internally stored as std::pair elements of a std::vector,
 * such that the index i in the vector is the same as the numerical
 * interpretation of the key (pair.first). Empty elements are represented by
 * keys that are not the same as the index, but point to the next valid element
 * for fast forward iteration. Consequently, backward iteration is slower than
 * forward iteration.
 */
template <
		typename Key,
		typename T,
		typename NumConverter = identity<Key>,
		typename Alloc = std::allocator<std::pair<const typename NumConverter::TargetType, T> > >
class cont_map {

public:

	// forward declaration
	template <typename Direction>
	class cont_map_iterator_base;
	class forward_direction;
	class backward_direction;

	typedef cont_map_iterator_base<forward_direction>  cont_map_iterator;
	typedef cont_map_iterator_base<backward_direction> cont_map_reverse_iterator;

	typedef cont_map<Key, T, NumConverter, Alloc> map_type;
	typedef typename NumConverter::TargetType num_key_type;

	// map interface
	typedef Key                                       key_type;
	typedef T                                         mapped_type;
	typedef std::pair<Key, T>                         value_type;
	typedef Alloc                                     allocator_type;
	typedef typename allocator_type::reference        reference;
	typedef typename allocator_type::const_reference  const_reference;
	typedef typename allocator_type::pointer          pointer;
	typedef typename allocator_type::const_pointer    const_pointer;
	typedef cont_map_iterator                         iterator;
	typedef const cont_map_iterator                   const_iterator;
	typedef cont_map_reverse_iterator                 reverse_iterator;
	typedef const cont_map_reverse_iterator           const_reverse_iterator;
	typedef std::vector<value_type, Alloc>            list_type;
	typedef typename list_type::difference_type       difference_type;
	typedef typename list_type::size_type             size_type;

	////////////////////////////////////////////////////////////////////////////////
	// iterator
	////////////////////////////////////////////////////////////////////////////////

	template <typename Direction>
	class cont_map_iterator_base : public Direction {

	public:

		typedef cont_map_iterator_base<Direction> iterator_type;

		cont_map_iterator_base(list_type& list, num_key_type i, NumConverter& converter) :
			Direction(list, i, converter),
			_list(list),
			_i(i),
			_converter(converter) {

			if (_i < 0)            _i = 0;
			if (_i > _list.size()) _i = _list.size();

			Direction::skip_invalids(_i);
		}

		value_type&       operator*()       { return _list[_i]; }
		const value_type& operator*() const { return _list[_i]; }

		      value_type* operator->()       { return &_list[_i]; }
		const value_type* operator->() const { return &_list[_i]; }

		iterator_type        operator++(int)       {       iterator_type p = *this; Direction::inc(_i); return p; }
		const iterator_type  operator++(int) const { const iterator_type p = *this; Direction::inc(_i); return p; }
		iterator_type&       operator++()          { Direction::inc(_i); return *this; }
		const iterator_type& operator++()    const { Direction::inc(_i); return *this; }

		bool operator==(const iterator_type& other) const { return _i == other._i; }
		bool operator!=(const iterator_type& other) const { return _i != other._i; }

		inline num_key_type index() { return _i; }

	private:

		list_type&            _list;
		mutable num_key_type  _i;
		NumConverter&         _converter;
	};

	class forward_direction {

	public:

		forward_direction(list_type& list, num_key_type&, NumConverter& converter) :
			_list(list),
			_converter(converter) {}

		void inc(num_key_type& i) { i++; skip_invalids(i); }

	protected:

		num_key_type end() { return _list.size(); }

		void skip_invalids(num_key_type& i) {

			if (i == end())
				return;

			// keys of invalid elements point to the next valid one, keys of
			// valid elements point to themselves
			i = _converter(_list[i].first);
		}

	private:

		list_type&            _list;
		NumConverter&         _converter;
	};

	class backward_direction {

	public:

		backward_direction(list_type& list, num_key_type& i, NumConverter& converter) :
			_list(list),
			_converter(converter) {

			// we represent element i by keeping an index to i+1 (this way we
			// can have 0 as end)
			i++;
		}

		void inc(num_key_type& i) { i--; skip_invalids(i); }

	protected:

		num_key_type end() { return 0; }

		void skip_invalids(num_key_type& i) {

			// traverse the list until we find a valid element
			while (i != end() && i-1 != _converter(_list[i-1].first))
				i--;
		}

	private:

		list_type&            _list;
		NumConverter&         _converter;
	};

	////////////////////////////////////////////////////////////////////////////////
	// member functions
	////////////////////////////////////////////////////////////////////////////////

	cont_map(const NumConverter& converter = NumConverter()) :
		_size(0),
		_converter(converter) {}

	// iterators
	iterator begin() { return iterator(_list, 0, _converter); }
	iterator end() { return iterator(_list, _list.size(), _converter); }
	const_iterator begin() const { return iterator(_list, 0, _converter); }
	const_iterator end() const { return iterator(_list, _list.size(), _converter); }
	reverse_iterator rbegin() { return reverse_iterator(_list, _list.size() - 1, _converter); }
	reverse_iterator rend() { return ++reverse_iterator(_list, 0, _converter); }
	const_reverse_iterator rbegin() const { return reverse_iterator(_list, _list.size() - 1, _converter); }
	const_reverse_iterator rend() const { return ++reverse_iterator(_list, 0, _converter); }

	// capacity
	bool empty() { return _size == 0; }
	size_type size() { return _size; }
	size_type max_size() { return _list.max_size(); }

	// element access
	mapped_type& operator[](const key_type& key) {

		num_key_type k = _converter(key);

		accomodate(k);

		// make valid
		if (!is_valid(k)) {
			reverse_iterator prev_valid(_list, k, _converter);
			for (num_key_type i = prev_valid.index(); i <= k; i++)
				_list[i].first = key;
			_size++;
		}

		return _list[k].second;
	}

	const mapped_type& at(const key_type& key) const {

		num_key_type k = _converter(key);

		if (k >= _list.size() || k != _converter(_list[k].first))
			throw std::out_of_range("cont_map::at");

		return _list[k].second;
	}

	// modifiers
	std::pair<iterator, bool> insert(const value_type& value) {

		num_key_type k = _converter(value.first);

		accomodate(k);
		bool contained = is_valid(k);

		_list[k] = value;
		if (!contained)
			_size++;

		return std::make_pair(iterator(_list, k, _converter), contained);
	}

	iterator insert(iterator position, const value_type& value) {
		return insert(value).first;
	}
	template <class InputIterator>
	void insert(InputIterator first, InputIterator last) {
		while (first != last) {
			insert(*first);
			first++;
		}
	}

	void erase(iterator position) {

		if (position == end())
			return;

		if (!is_valid(position.index()))
			return;

		// find previous and next valid element or end
		iterator         next_valid = position;
		reverse_iterator prev_valid(_list, position.index(), _converter);
		next_valid++;
		prev_valid++;

		// update pointers to next valid
		for (num_key_type i = prev_valid.index(); i <= position.index(); i++)
			_list[i].first = _converter(next_valid.index());

		_size--;
	}

	size_type erase(const key_type& key) {

		iterator position(_list, _converter(key), _converter);
		if (position == end())
			return 0;

		erase(position);
		return 1;
	}

	void erase(iterator first, iterator last) {
		while (first != last) {
			erase(first);
			++first;
		}
	}

	void swap(map_type& other) {
		_list.swap(other._list);
		std::swap(_size, other._size);
		std::swap(_converter, other._converter);
	}

	void clear() {
		_list.clear();
		_size = 0;
	}

	// observers
	std::less<num_key_type> key_comp() { return std::less<num_key_type>(); }
	typename std::map<Key, T, Alloc>::value_compare value_comp() { return std::map<Key, T, Alloc>::value_comp(); }

	// operations
	iterator find(const key_type& key) {
		return __find<iterator>(key);
	}
	const_iterator find(const key_type& key) const {
		return __find<const_iterator>(key);
	}

	size_type count(const key_type& key) {
		return _converter(key) < _list.size() && is_valid(_converter(key));
	}

	iterator lower_bound(const key_type& key) {
		return iterator(_list, _converter(key), _converter);
	}
	const_iterator lower_bound(const key_type& key) const {
		return const_iterator(_list, _converter(key), _converter);
	}

	iterator upper_bound(const key_type& key) {
		iterator i(_list, _converter(key), _converter);
		if (i.index() == _converter(key))
			i++;
		return i;
	}
	const_iterator upper_bound(const key_type& key) const {
		const_iterator i(_list, _converter(key), _converter);
		if (i.index() == _converter(key))
			i++;
		return i;
	}

	std::pair<iterator,iterator> equal_range(const key_type& key) {
		return std::make_pair(lower_bound(), upper_bound());
	}
	std::pair<const_iterator,const_iterator> equal_range(const key_type& key) const {
		return std::make_pair(lower_bound(), upper_bound());
	}

	// allocator
	allocator_type get_allocator() const { return _list.get_allocator(); }

private:

	inline bool is_valid(num_key_type k) { return _converter(_list[k].first) == k; }

	// grow the list to accomodate keys with numerical value k
	inline void accomodate(num_key_type k) {

		// key is beyond current list size
		if (k >= _list.size()) {

			// create new fields at the end, with keys that point to the
			// one-past last element (which is k+1)
			_list.resize(k+1, std::make_pair(_converter(k+1), T()));
		}
	}

	template <typename Iterator>
	inline Iterator __find(const key_type& key) {
		if (count(key))
			return Iterator(_converter(key));
		return end();
	}

	list_type    _list;
	size_type    _size;
	NumConverter _converter;
};

} // namespace util

#endif // UTIL_CONT_MAP_H__

<commit_msg>fought a bit in the constness djungle of cont_map<commit_after>#ifndef UTIL_CONT_MAP_H__
#define UTIL_CONT_MAP_H__

#include <vector>
#include <map>

namespace util {

/**
 * Default converter that does nothing.
 */
template <typename T>
struct identity {

	typedef T TargetType;

	const TargetType& operator()(const T& t) { return t; }
};

/**
 * Implements a std::map interface for keys that have a numerical interpretation
 * and are expected to be continuous.
 *
 * Key-value pairs are internally stored as std::pair elements of a std::vector,
 * such that the index i in the vector is the same as the numerical
 * interpretation of the key (pair.first). Empty elements are represented by
 * keys that are not the same as the index, but point to the next valid element
 * for fast forward iteration. Consequently, backward iteration is slower than
 * forward iteration.
 */
template <
		typename Key,
		typename T,
		typename NumConverter = identity<Key>,
		typename Alloc = std::allocator<std::pair<const typename NumConverter::TargetType, T> > >
class cont_map {

public:

	// forward declaration
	template <typename Direction>
	class cont_map_iterator_base;
	class forward_direction;
	class backward_direction;

	typedef cont_map_iterator_base<forward_direction>  cont_map_iterator;
	typedef cont_map_iterator_base<backward_direction> cont_map_reverse_iterator;

	typedef cont_map<Key, T, NumConverter, Alloc> map_type;
	typedef typename NumConverter::TargetType num_key_type;

	// map interface
	typedef Key                                       key_type;
	typedef T                                         mapped_type;
	typedef std::pair<Key, T>                         value_type;
	typedef Alloc                                     allocator_type;
	typedef typename allocator_type::reference        reference;
	typedef typename allocator_type::const_reference  const_reference;
	typedef typename allocator_type::pointer          pointer;
	typedef typename allocator_type::const_pointer    const_pointer;
	typedef cont_map_iterator                         iterator;
	typedef const cont_map_iterator                   const_iterator;
	typedef cont_map_reverse_iterator                 reverse_iterator;
	typedef const cont_map_reverse_iterator           const_reverse_iterator;
	typedef std::vector<value_type, Alloc>            list_type;
	typedef typename list_type::difference_type       difference_type;
	typedef typename list_type::size_type             size_type;

	////////////////////////////////////////////////////////////////////////////////
	// iterator
	////////////////////////////////////////////////////////////////////////////////

	template <typename Direction>
	class cont_map_iterator_base : public Direction {

	public:

		typedef cont_map_iterator_base<Direction> iterator_type;

		cont_map_iterator_base(list_type& list, num_key_type i, NumConverter& converter) :
			Direction(list, i, converter),
			_list(list),
			_i(i),
			_converter(converter) {

			if (_i < 0)            _i = 0;
			if (_i > _list.size()) _i = _list.size();

			Direction::skip_invalids(_i);
		}

		value_type&       operator*()       { return _list[_i]; }
		const value_type& operator*() const { return _list[_i]; }

		      value_type* operator->()       { return &_list[_i]; }
		const value_type* operator->() const { return &_list[_i]; }

		iterator_type        operator++(int)       {       iterator_type p = *this; Direction::inc(_i); return p; }
		const iterator_type  operator++(int) const { const iterator_type p = *this; Direction::inc(_i); return p; }
		iterator_type&       operator++()          { Direction::inc(_i); return *this; }
		const iterator_type& operator++()    const { Direction::inc(_i); return *this; }

		bool operator==(const iterator_type& other) const { return _i == other._i; }
		bool operator!=(const iterator_type& other) const { return _i != other._i; }

		inline num_key_type index() { return _i; }

	private:

		list_type&            _list;
		mutable num_key_type  _i;
		NumConverter&         _converter;
	};

	class forward_direction {

	public:

		forward_direction(list_type& list, num_key_type&, NumConverter& converter) :
			_list(list),
			_converter(converter) {}

		void inc(num_key_type& i) const { i++; skip_invalids(i); }

	protected:

		num_key_type end() const { return _list.size(); }

		void skip_invalids(num_key_type& i) const {

			if (i == end())
				return;

			// keys of invalid elements point to the next valid one, keys of
			// valid elements point to themselves
			i = _converter(_list[i].first);
		}

	private:

		list_type&            _list;
		NumConverter&         _converter;
	};

	class backward_direction {

	public:

		backward_direction(list_type& list, num_key_type& i, NumConverter& converter) :
			_list(list),
			_converter(converter) {

			// we represent element i by keeping an index to i+1 (this way we
			// can have 0 as end)
			i++;
		}

		void inc(num_key_type& i) const { i--; skip_invalids(i); }

	protected:

		num_key_type end() const { return 0; }

		void skip_invalids(num_key_type& i) const {

			// traverse the list until we find a valid element
			while (i != end() && i-1 != _converter(_list[i-1].first))
				i--;
		}

	private:

		list_type&            _list;
		NumConverter&         _converter;
	};

	////////////////////////////////////////////////////////////////////////////////
	// member functions
	////////////////////////////////////////////////////////////////////////////////

	cont_map(const NumConverter& converter = NumConverter()) :
		_size(0),
		_converter(converter) {}

	// iterators
	iterator begin() { return iterator(_list, 0, _converter); }
	iterator end() { return iterator(_list, _list.size(), _converter); }
	const_iterator begin() const { return iterator(_list, 0, _converter); }
	const_iterator end() const { return iterator(_list, _list.size(), _converter); }
	reverse_iterator rbegin() { return reverse_iterator(_list, _list.size() - 1, _converter); }
	reverse_iterator rend() { return ++reverse_iterator(_list, 0, _converter); }
	const_reverse_iterator rbegin() const { return reverse_iterator(_list, _list.size() - 1, _converter); }
	const_reverse_iterator rend() const { return ++reverse_iterator(_list, 0, _converter); }

	// capacity
	bool empty() { return _size == 0; }
	size_type size() { return _size; }
	size_type max_size() { return _list.max_size(); }

	// element access
	mapped_type& operator[](const key_type& key) {

		num_key_type k = _converter(key);

		accomodate(k);

		// make valid
		if (!is_valid(k)) {
			reverse_iterator prev_valid(_list, k, _converter);
			for (num_key_type i = prev_valid.index(); i <= k; i++)
				_list[i].first = key;
			_size++;
		}

		return _list[k].second;
	}

	const mapped_type& at(const key_type& key) const {

		num_key_type k = _converter(key);

		if (k >= _list.size() || k != _converter(_list[k].first))
			throw std::out_of_range("cont_map::at");

		return _list[k].second;
	}

	// modifiers
	std::pair<iterator, bool> insert(const value_type& value) {

		num_key_type k = _converter(value.first);

		accomodate(k);
		bool contained = is_valid(k);

		_list[k] = value;
		if (!contained)
			_size++;

		return std::make_pair(iterator(_list, k, _converter), contained);
	}

	iterator insert(iterator position, const value_type& value) {
		return insert(value).first;
	}
	template <class InputIterator>
	void insert(InputIterator first, InputIterator last) {
		while (first != last) {
			insert(*first);
			first++;
		}
	}

	void erase(iterator position) {

		if (position == end())
			return;

		if (!is_valid(position.index()))
			return;

		// find previous and next valid element or end
		iterator         next_valid = position;
		reverse_iterator prev_valid(_list, position.index(), _converter);
		next_valid++;
		prev_valid++;

		// update pointers to next valid
		for (num_key_type i = prev_valid.index(); i <= position.index(); i++)
			_list[i].first = _converter(next_valid.index());

		_size--;
	}

	size_type erase(const key_type& key) {

		iterator position(_list, _converter(key), _converter);
		if (position == end())
			return 0;

		erase(position);
		return 1;
	}

	void erase(iterator first, iterator last) {
		while (first != last) {
			erase(first);
			++first;
		}
	}

	void swap(map_type& other) {
		_list.swap(other._list);
		std::swap(_size, other._size);
		std::swap(_converter, other._converter);
	}

	void clear() {
		_list.clear();
		_size = 0;
	}

	// observers
	std::less<num_key_type> key_comp() { return std::less<num_key_type>(); }
	typename std::map<Key, T, Alloc>::value_compare value_comp() { return std::map<Key, T, Alloc>::value_comp(); }

	// operations
	iterator find(const key_type& key) {
		return __find<iterator>(key);
	}
	const_iterator find(const key_type& key) const {
		return __find<const_iterator>(key);
	}

	size_type count(const key_type& key) {
		return _converter(key) < _list.size() && is_valid(_converter(key));
	}

	iterator lower_bound(const key_type& key) {
		return iterator(_list, _converter(key), _converter);
	}
	const_iterator lower_bound(const key_type& key) const {
		return const_iterator(_list, _converter(key), _converter);
	}

	iterator upper_bound(const key_type& key) {
		iterator i(_list, _converter(key), _converter);
		if (i.index() == _converter(key))
			i++;
		return i;
	}
	const_iterator upper_bound(const key_type& key) const {
		const_iterator i(_list, _converter(key), _converter);
		if (i.index() == _converter(key))
			i++;
		return i;
	}

	std::pair<iterator,iterator> equal_range(const key_type& key) {
		return std::make_pair(lower_bound(), upper_bound());
	}
	std::pair<const_iterator,const_iterator> equal_range(const key_type& key) const {
		return std::make_pair(lower_bound(), upper_bound());
	}

	// allocator
	allocator_type get_allocator() const { return _list.get_allocator(); }

private:

	inline bool is_valid(num_key_type k) { return _converter(_list[k].first) == k; }

	// grow the list to accomodate keys with numerical value k
	inline void accomodate(num_key_type k) {

		// key is beyond current list size
		if (k >= _list.size()) {

			// create new fields at the end, with keys that point to the
			// one-past last element (which is k+1)
			_list.resize(k+1, std::make_pair(_converter(k+1), T()));
		}
	}

	template <typename Iterator>
	inline Iterator __find(const key_type& key) {
		if (count(key))
			return Iterator(_converter(key));
		return end();
	}

	list_type    _list;
	size_type    _size;
	NumConverter _converter;
};

} // namespace util

#endif // UTIL_CONT_MAP_H__

<|endoftext|>


<commit_before>
// Required headers
#include <iostream>
#include <sstream>
#include <cstring>
#include <string>
#include <ctime>

// CPP Unit - Single source file C++ Unit testing framework (github.com/cppunit/cppunit)
class Cppunit { public:
    #define CHECK(a,b)  check<long long>(a, b, #a, #b, __FILE__, __LINE__, __FUNCTION__);
    #define CHECKT(a)   check<bool>(a, true, #a, "true", __FILE__, __LINE__, __FUNCTION__);
    #define CHECKS(a,b) check<cs>(a, b, #a, #b, __FILE__, __LINE__, __FUNCTION__);
    typedef const std::string& cs;
    int checks, fails; std::ostringstream serr; std::istringstream *in;
    Cppunit() { checks = fails = 0;}
    void test_cin(cs s){ in = new std::istringstream(s); std::cin.rdbuf(in->rdbuf()); }
    void fail_hdr(cs stra, cs strb, cs file, int line, cs func) {
        serr << "==================================================" << std::endl;
        serr << "FAIL: " << func << std::endl;
        serr << "--------------------------------------------------" << std::endl;
        serr << "File \"" << file << "\", line " << line << " in " << func << std::endl;
        serr << "  Checking " << stra << " == " << strb << std::endl;
    }
    template <typename T> void check(T a, T b, cs stra, cs strb, cs file, int line, cs func) {
        checks++; if (a == b) { std::cout << "."; return; }
        fails++; std::cout << "F"; fail_hdr(stra, strb, file, line, func);
        serr << "  Error: \"" << a << "\" ! = \"" << b << "\"" << std::endl << std::endl;
    }
    virtual void single_test() {}
    virtual void test_list() { single_test(); }
    double dclock() { return double(clock()) / CLOCKS_PER_SEC; }
    status() {
        std::cout << std::endl; if (fails) std::cout << serr.str();
        std::cout << "--------------------------------------------------" << std::endl;
        std::cout << "Ran " << checks << " checks in " << dclock() << "s" << std::endl << std::endl;
        if (fails) std::cout << "FAILED (failures=" << fails << ")"; else std::cout << "OK" << std::endl;
        return fails > 0;
    }
    run() { std::streambuf* ocin = std::cin.rdbuf(); test_list(); std::cin.rdbuf(ocin); return status(); }
};

// Test example
class Localcppunit: public Cppunit {

    void single_test() {

        // Integral type match
        CHECK(2 + 2, 4);

        // Boolean type
        CHECKT(2 + 2 == 4);

        // String type match
        CHECKS("a" "b", "ab");
    }
};

// Invocation example
int main(int argc, char *argv[]) {

    // Run unit tests only if -ut switch is used
    if (argc > 1 && !strcmp(argv[1], "-ut")) {
        Localcppunit lut;
        return lut.run();
    }

    std::cout << "NOTE: Use -ut switch to run cppunit tests";
    return 0;
}

<commit_msg>Update cppunit.cc<commit_after>
// Required headers
#include <iostream>
#include <sstream>
#include <cstring>
#include <string>
#include <ctime>

// Cppunit - C++ Unit testing TDD framework (github.com/cppunit/cppunit)
class Cppunit { public:
    #define CHECK(a,b)  check<long long>(a, b, #a, #b, __FILE__, __LINE__, __FUNCTION__);
    #define CHECKT(a)   check<bool>(a, true, #a, "true", __FILE__, __LINE__, __FUNCTION__);
    #define CHECKS(a,b) check<cs>(a, b, #a, #b, __FILE__, __LINE__, __FUNCTION__);
    typedef const std::string& cs;
    int checks, fails; std::ostringstream serr; std::istringstream *in;
    Cppunit() { checks = fails = 0;}
    void test_cin(cs s){ in = new std::istringstream(s); std::cin.rdbuf(in->rdbuf()); }
    void fail_hdr(cs stra, cs strb, cs file, int line, cs func) {
        serr << "==================================================" << std::endl;
        serr << "FAIL: " << func << std::endl;
        serr << "--------------------------------------------------" << std::endl;
        serr << "File \"" << file << "\", line " << line << " in " << func << std::endl;
        serr << "  Checking " << stra << " == " << strb << std::endl;
    }
    template <typename T> void check(T a, T b, cs stra, cs strb, cs file, int line, cs func) {
        checks++; if (a == b) { std::cout << "."; return; }
        fails++; std::cout << "F"; fail_hdr(stra, strb, file, line, func);
        serr << "  Error: \"" << a << "\" ! = \"" << b << "\"" << std::endl << std::endl;
    }
    virtual void single_test() {}
    virtual void test_list() { single_test(); }
    double dclock() { return double(clock()) / CLOCKS_PER_SEC; }
    status() {
        std::cout << std::endl; if (fails) std::cout << serr.str();
        std::cout << "--------------------------------------------------" << std::endl;
        std::cout << "Ran " << checks << " checks in " << dclock() << "s" << std::endl << std::endl;
        if (fails) std::cout << "FAILED (failures=" << fails << ")"; else std::cout << "OK" << std::endl;
        return fails > 0;
    }
    run() { std::streambuf* ocin = std::cin.rdbuf(); test_list(); std::cin.rdbuf(ocin); return status(); }
};

// Class under test example
class test_class {

    public: int calculate(){
        int n, m;
        std::cin >> n >> m;
        return n + m;
    }
};

// Test example
class MyCppunit: public Cppunit {

    void single_test() {

        // Integral type match check
        CHECK(2 + 2, 4);

        // Boolean type check
        CHECKT(2 + 2 == 4);

        // String match check
        CHECKS("a" "b", "ab");

        // Stdin override example
        test_cin("2\n2");
        CHECK((new test_class)->calculate(), 4);

    }
};

// Invocation example
int main(int argc, char *argv[]) {

    // Run unit tests only if -ut switch is used
    if (argc > 1 && !strcmp(argv[1], "-ut")) {
        MyCppunit ut;
        return ut.run();
    }

    std::cout << "NOTE: Use -ut switch to run cppunit tests";
    return 0;
}

<|endoftext|>


<commit_before>/////////////////////////////////////////////////////////////////////////
// $Id$
/////////////////////////////////////////////////////////////////////////
//
//  Copyright (C) 2002  MandrakeSoft S.A.
//
//    MandrakeSoft S.A.
//    43, rue d'Aboukir
//    75002 Paris - France
//    http://www.linux-mandrake.com/
//    http://www.mandrakesoft.com/
//
//  This library is free software; you can redistribute it and/or
//  modify it under the terms of the GNU Lesser General Public
//  License as published by the Free Software Foundation; either
//  version 2 of the License, or (at your option) any later version.
//
//  This library is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
//  Lesser General Public License for more details.
//
//  You should have received a copy of the GNU Lesser General Public
//  License along with this library; if not, write to the Free Software
//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA

#define NEED_CPU_REG_SHORTCUTS 1
#include "bochs.h"
#define LOG_THIS BX_CPU_THIS_PTR

  void
BX_CPU_C::DAS(bxInstruction_c *)
{
  Bit8u tmpCF, tmpAL;

  /* ??? */
  /* the algorithm for DAS is fashioned after the pseudo code in the
   * Pentium Processor Family Developer's Manual, volume 3.  It seems
   * to have changed from earlier processor's manuals.  I'm not sure
   * if this is a correction in the algorithm printed, or Intel has
   * changed the handling of instruction.  It might not even be
   * correct yet...
   */

  tmpCF = 0;
  tmpAL = AL;

  /* DAS effect the following flags: A,C,S,Z,P */

  if (((tmpAL & 0x0F) > 0x09) || get_AF()) {
    set_AF(1);
    tmpCF = (AL < 0x06) || get_CF();
    AL = AL - 0x06;
    /*tmpCF = (AL < 0) || CF;*/
    }
  if ( (tmpAL > 0x99) || get_CF() ) {
    AL = AL - 0x60;
    tmpCF = 1;
    }

  set_CF(tmpCF);
  set_SF(AL >> 7);
  set_ZF(AL==0);
  set_PF_base(AL);
}

  void
BX_CPU_C::AAA(bxInstruction_c *)
{
  Bit8u ALcarry;

  ALcarry = AL > 0xf9;

  /* AAA effects the following flags: A,C */
  if ( ((AL & 0x0f) > 9) || get_AF() ) {
    AL = (AL + 6) & 0x0f;
    AH = AH + 1 + ALcarry;
    set_AF(1);
    set_CF(1);
    }
  else {
    set_AF(0);
    set_CF(0);
    AL = AL & 0x0f;
    }
}

  void
BX_CPU_C::AAS(bxInstruction_c *)
{
  Bit8u ALborrow;

  /* AAS affects the following flags: A,C */

  ALborrow = AL < 6;

  if ( ((AL & 0x0F) > 0x09) || get_AF() ) {
    AL = (AL - 6) & 0x0f;
    AH = AH - 1 - ALborrow;
    set_AF(1);
    set_CF(1);
    }
  else {
    set_CF(0);
    set_AF(0);
    AL = AL & 0x0f;
    }
}

  void
BX_CPU_C::AAM(bxInstruction_c *i)
{
  Bit8u al, imm8;

  imm8 = i->Ib();

  if (imm8 == 0) {
    exception(BX_DE_EXCEPTION, 0, 0);
    }

  al = AL;
  AH = al / imm8;
  AL = al % imm8;

  /* AAM always clears the flags A and C */
  set_AF(0);
  set_CF(0);
  /* AAM affects the following flags: S,Z,P */
  set_SF((AL & 0x80) > 0);
  set_ZF(AL == 0);
  set_PF_base(AL);
}

  void
BX_CPU_C::AAD(bxInstruction_c *i)
{
  Bit8u al, imm8;
  Bit16u ax1, ax2;

  imm8 = i->Ib();

  ax1 = AH * imm8;
  ax2 = ax1 + AL;
  al = AL;
  AL = (Bit8u)ax2;
  AH = 0;

  /* AAD effects the following flags: A,C,O,S,Z,P */
  /* modification of flags A,C,O is undocumented */
  set_AF((ax1 & 0x08) != (ax2 & 0x08));
  set_CF(ax2 > 0xff);
  set_OF((AL & 0x80) != (al & 0x80));
  set_SF(AL >= 0x80);
  set_ZF(AL == 0);
  set_PF_base(AL);
}

  void
BX_CPU_C::DAA(bxInstruction_c *)
{
  Bit8u al;

  al = AL;

  // DAA affects the following flags: S,Z,A,P,C
  // ???

  if (((al & 0x0F) > 0x09) || get_AF()) {
    al = al + 0x06;
    set_AF(1);
    }
  else
    set_AF(0);

  if ((al > 0x9F) || get_CF()) {
    al = al + 0x60;
    set_CF(1);
    }
  else
    set_CF(0);

  AL = al;

  set_SF(al >> 7);
  set_ZF(al==0);
  set_PF_base(al);
}
<commit_msg>Fixed BCD instructions to be suitable with Intel docs<commit_after>/////////////////////////////////////////////////////////////////////////
// $Id$
/////////////////////////////////////////////////////////////////////////
//
//  Copyright (C) 2002  MandrakeSoft S.A.
//
//    MandrakeSoft S.A.
//    43, rue d'Aboukir
//    75002 Paris - France
//    http://www.linux-mandrake.com/
//    http://www.mandrakesoft.com/
//
//  This library is free software; you can redistribute it and/or
//  modify it under the terms of the GNU Lesser General Public
//  License as published by the Free Software Foundation; either
//  version 2 of the License, or (at your option) any later version.
//
//  This library is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
//  Lesser General Public License for more details.
//
//  You should have received a copy of the GNU Lesser General Public
//  License along with this library; if not, write to the Free Software
//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA

#define NEED_CPU_REG_SHORTCUTS 1
#include "bochs.h"
#define LOG_THIS BX_CPU_THIS_PTR

  void
BX_CPU_C::DAS(bxInstruction_c *)
{
  /* the algorithm for DAS is fashioned after the pseudo code in the
   * Pentium Processor Family Developer's Manual, volume 3.  It seems
   * to have changed from earlier processor's manuals.  I'm not sure
   * if this is a correction in the algorithm printed, or Intel has
   * changed the handling of instruction.  It might not even be
   * correct yet...
   */

  Bit8u tmpAL = AL;
  int tmpCF = 0;

  /* DAS effect the following flags: A,C,S,Z,P */

  if (((AL & 0x0F) > 0x09) || get_AF())
  {
    tmpAL = AL - 0x06;
    if ((AL < 0x06) || get_CF()) tmpCF = 1;
    set_AF(1);
  }
  else
    set_AF(0);

  if ((AL > 0x99) || get_CF())
  {
    AL = AL - 0x60;
    tmpCF = 1;
  }
  else
    tmpCF = 0;

  AL = tmpAL;

  set_CF(tmpCF);
  set_SF(tmpAL >> 7);
  set_ZF(tmpAL==0);
  set_PF_base(tmpAL);
}

  void
BX_CPU_C::AAA(bxInstruction_c *)
{
  /* AAA affects the following flags: A,C */

  if ( ((AL & 0x0f) > 9) || get_AF() )
  {
    AL = AL + 6;
    AH = AH + 1;
    set_AF(1);
    set_CF(1);
  }
  else {
    set_AF(0);
    set_CF(0);
  }

  AL = AL & 0x0f;
}

  void
BX_CPU_C::AAS(bxInstruction_c *)
{
  /* AAS affects the following flags: A,C */

  if ( ((AL & 0x0F) > 0x09) || get_AF() )
  {
    AL = AL - 6;
    AH = AH - 1;
    set_AF(1);
    set_CF(1);
  }
  else {
    set_CF(0);
    set_AF(0);
  }

  AL = AL & 0x0f;
}

  void
BX_CPU_C::AAM(bxInstruction_c *i)
{
  Bit8u al, imm8;

  imm8 = i->Ib();

  if (imm8 == 0)
    exception(BX_DE_EXCEPTION, 0, 0);

  al = AL;
  AH = al / imm8;
  AL = al % imm8;

  /* AAM always clears the flags A and C */
  set_AF(0);
  set_CF(0);

  /* AAM affects the following flags: S,Z,P */
  set_SF((AL & 0x80) > 0);
  set_ZF(AL == 0);
  set_PF_base(AL);
}

  void
BX_CPU_C::AAD(bxInstruction_c *i)
{
  Bit8u al, imm8;
  Bit16u ax1, ax2;

  imm8 = i->Ib();

  ax1 = AH * imm8;
  ax2 = ax1 + AL;
  al = AL;
  AL = (Bit8u)(ax2 & 0xFF);
  AH = 0;

  /* AAD effects the following flags: A,C,O,S,Z,P */
  /* modification of flags A,C,O is undocumented */
  set_AF((ax1 & 0x08) != (ax2 & 0x08));
  set_CF(ax2 > 0xff);
  set_OF((AL & 0x80) != (al & 0x80));
  set_SF(AL >= 0x80);
  set_ZF(AL == 0);
  set_PF_base(AL);
}

  void
BX_CPU_C::DAA(bxInstruction_c *)
{
  Bit8u tmpAL = AL;
  int tmpCF = 0;

  // DAA affects the following flags: S,Z,A,P,C

  if (((AL & 0x0F) > 0x09) || get_AF())
  {
    tmpAL = AL + 0x06;
    if (get_CF() || (tmpAL < AL)) tmpCF = 1;
    set_AF(1);
  }
  else
    set_AF(0);

  if ((AL > 0x99) || get_CF())
  {
    tmpAL = AL + 0x60;
    tmpCF = 1;
  }
  else
    tmpCF = 0;

  AL = tmpAL;

  set_CF(tmpCF);
  set_SF(tmpAL >> 7);
  set_ZF(tmpAL==0);
  set_PF_base(tmpAL);
}
<|endoftext|>


<commit_before>#include "nextpassesview.h"
#include <QPainter>
#include <QDebug>

NextPassesView::NextPassesView(QWidget *parent)
    : QWidget(parent)
    , trackers(nullptr)
{
    setMinimumHeight(1);
}

void NextPassesView::setTrackers(QList<Tracker>* trackers) {
    this->trackers = trackers;
}

// https://stackoverflow.com/questions/24831484/how-to-align-qpainter-drawtext-around-a-point-not-a-rectangle
void drawText(QPainter & painter, qreal x, qreal y, Qt::Alignment flags,
              const QString & text, QRectF * boundingRect = 0) {
   const qreal size = 32767.0;
   QPointF corner(x, y - size);
   if (flags & Qt::AlignHCenter) corner.rx() -= size/2.0;
   else if (flags & Qt::AlignRight) corner.rx() -= size;
   if (flags & Qt::AlignVCenter) corner.ry() += size/2.0;
   else if (flags & Qt::AlignTop) corner.ry() += size;
   else flags |= Qt::AlignBottom;
   QRectF rect{corner.x(), corner.y(), size, size};
   painter.drawText(rect, flags, text, boundingRect);
}

void drawText(QPainter & painter, const QPointF & point, Qt::Alignment flags,
              const QString & text, QRectF * boundingRect = {}) {
   drawText(painter, point.x(), point.y(), flags, text, boundingRect);
}

void NextPassesView::paintEvent(QPaintEvent *) {
    if(trackers != nullptr) {
        QPainter painter;
        int totalHeight = 0;
        const int margins = 10;
        const int trackerHeight = 16;

        painter.begin(this);
        painter.setRenderHint(QPainter::Antialiasing);
        int textMaxWidth = 0;
        for(QList<Tracker>::iterator it = trackers->begin(); it != trackers->end(); ++it) {
            Tracker t = *it;
            if(textMaxWidth < painter.fontMetrics().width(t.getTitle())) {
                textMaxWidth = painter.fontMetrics().width(t.getTitle());
            }
        }

        const int hours = 12;
        auto now = DateTime::Now(false);
        auto later = DateTime::Now(false).AddHours(hours);
        auto totalTicks = (later - now).Ticks();

        QRectF xAxisRect(QPointF(margins + textMaxWidth + margins, totalHeight),
                         QPointF(width() - 1 - margins, totalHeight + trackerHeight * trackers->length()));
        auto dateIt = now.AddMinutes(60 - now.Minute());

        painter.setPen(Qt::gray);
        painter.drawLine(QPointF(xAxisRect.left(), xAxisRect.top()),
                         QPointF(xAxisRect.left(), xAxisRect.bottom()));
        drawText(painter,
                 QPointF(xAxisRect.left(), xAxisRect.bottom() + margins),
                 Qt::AlignVCenter | Qt::AlignHCenter,
                 QString::number(now.Hour()) + ":" + QString::number(now.Minute()) + ":" + QString::number(now.Second()));

        while(dateIt < later) {
            auto linePercentage = (float) (dateIt - now).Ticks() / totalTicks;
            float lineX = xAxisRect.left() + (xAxisRect.width() * linePercentage);
            painter.drawLine(QPointF(lineX, xAxisRect.top()),
                             QPointF(lineX, xAxisRect.bottom()));

            drawText(painter,
                     QPointF(lineX, xAxisRect.bottom() + margins),
                     Qt::AlignVCenter | Qt::AlignHCenter,
                     QString::number(dateIt.Hour()) + ":" + QString::number(dateIt.Minute()));
            dateIt = dateIt.AddHours(1);
        }

        bool alternate = 0;

        for(QList<Tracker>::iterator it = trackers->begin(); it != trackers->end(); ++it) {
            QRectF itemRect(0, totalHeight, width(), trackerHeight);

            /*
            if(alternate) {
                painter.setPen(Qt::NoPen);
                painter.setBrush(QColor(250, 250, 250));
                painter.drawRect(itemRect);
                painter.setBrush(Qt::NoBrush);
            }
            */

            alternate = !alternate;

            auto tracker = *it;
            painter.setPen(Qt::black);
            drawText(painter,
                     QPointF(margins, itemRect.center().y()),
                     Qt::AlignVCenter,
                     tracker.getTitle());

            auto passes = tracker.GeneratePassListQt(now, later);
            for(QList<PassDetails>::iterator it2 = passes.begin(); it2 != passes.end(); ++it2) {
                auto pass = *it2;
                auto leftPercentage = (float) (pass.aos - now).Ticks() / totalTicks;
                auto rightPercentage = (float) (pass.los - now).Ticks() / totalTicks;
                QRectF barRect(itemRect);
                barRect.setTop(itemRect.top() + 5);
                barRect.setBottom(itemRect.bottom() - 5);
                barRect.setLeft(xAxisRect.left() + xAxisRect.width() * leftPercentage);
                barRect.setRight(xAxisRect.left() + xAxisRect.width() * rightPercentage);
                painter.setPen(Qt::NoPen);
                painter.setBrush(Qt::black);
                painter.drawRect(barRect);
                painter.setBrush(Qt::NoBrush);
            }

            totalHeight += trackerHeight;
        }

        totalHeight += margins * 2;

        /*
        QRectF fullRect(QPointF(1, 1),
                        QPointF(width() - 1, totalHeight - 1));
        painter.setPen(Qt::red);
        painter.drawRect(fullRect);
        */
        painter.end();

        setMinimumHeight(totalHeight);
    }
}

/*
void NextPassesView::paintEvent(QPaintEvent *) {
    const int rectHeight = 10;
    const int padding = 5;
    const int trackerMargin = 15;
    const int xAxisStart = 50;
    QPainter painter;
    QStringList trackerStrings;
    trackerStrings << "SCD1" << "SCD2" << "CBERS-4" << "FELSAT";
    painter.begin(this);
    //painter.setRenderHint(QPainter::Antialiasing);
    painter.setPen(Qt::black);
    painter.drawRect(0, 0, width() - 1, height() - 1);
    painter.setPen(Qt::red);
    painter.drawRect(padding, padding, width() - padding * 2, height() - padding * 2);
    painter.setPen(Qt::black);

    int currentMargin = 10;
    for(QStringList::iterator it = trackerStrings.begin(); it != trackerStrings.end(); ++it) {
        QString current = *it;
        painter.drawText(padding, padding + currentMargin, current);
        painter.drawRect(padding + xAxisStart, padding + currentMargin - 8, 300, rectHeight);
        currentMargin += trackerMargin;
    }

    const int axisSpacing = (width() - (padding + xAxisStart)) / 9;
    int i;
    for(i = 0; i < 10; ++i) {
        QPoint tickPoint(padding + xAxisStart + axisSpacing * i,
                         currentMargin + 10);
        painter.setPen(Qt::gray);
        painter.drawLine(tickPoint + QPoint(0, -currentMargin),
                         tickPoint + QPoint(0, -5));
        painter.setPen(Qt::black);
        drawText(painter,
                 tickPoint,
                 Qt::AlignVCenter | Qt::AlignHCenter,
                 QString::number(i) + "0:00");
    }

    setMinimumHeight(currentMargin + 20);
    painter.end();
}
*/
<commit_msg>Estética<commit_after>#include "nextpassesview.h"
#include <QPainter>
#include <QDebug>

NextPassesView::NextPassesView(QWidget *parent)
    : QWidget(parent)
    , trackers(nullptr)
{
    setMinimumHeight(1);
}

void NextPassesView::setTrackers(QList<Tracker>* trackers) {
    this->trackers = trackers;
}

// https://stackoverflow.com/questions/24831484/how-to-align-qpainter-drawtext-around-a-point-not-a-rectangle
void drawText(QPainter & painter, qreal x, qreal y, Qt::Alignment flags,
              const QString & text, QRectF * boundingRect = 0) {
   const qreal size = 32767.0;
   QPointF corner(x, y - size);
   if (flags & Qt::AlignHCenter) corner.rx() -= size/2.0;
   else if (flags & Qt::AlignRight) corner.rx() -= size;
   if (flags & Qt::AlignVCenter) corner.ry() += size/2.0;
   else if (flags & Qt::AlignTop) corner.ry() += size;
   else flags |= Qt::AlignBottom;
   QRectF rect{corner.x(), corner.y(), size, size};
   painter.drawText(rect, flags, text, boundingRect);
}

void drawText(QPainter & painter, const QPointF & point, Qt::Alignment flags,
              const QString & text, QRectF * boundingRect = {}) {
   drawText(painter, point.x(), point.y(), flags, text, boundingRect);
}
// ------------------

void NextPassesView::paintEvent(QPaintEvent *) {
    if(trackers != nullptr) {
        QPainter painter;
        int totalHeight = 0;
        const int margins = 10;
        const int trackerHeight = 16;

        painter.begin(this);
        painter.setRenderHint(QPainter::Antialiasing);
        int textMaxWidth = 0;
        for(QList<Tracker>::iterator it = trackers->begin(); it != trackers->end(); ++it) {
            Tracker t = *it;
            if(textMaxWidth < painter.fontMetrics().width(t.getTitle())) {
                textMaxWidth = painter.fontMetrics().width(t.getTitle());
            }
        }

        const int hours = 12;
        auto now = DateTime::Now(false);
        auto later = DateTime::Now(false).AddHours(hours);
        auto totalTicks = (later - now).Ticks();

        QRectF xAxisRect(QPointF(margins + textMaxWidth + margins, totalHeight),
                         QPointF(width() - 1 - margins, totalHeight + trackerHeight * trackers->length()));
        auto dateIt = now.AddMinutes(60 - now.Minute());

        // draws reference lines
        painter.setPen(Qt::gray);
        while(dateIt < later) {
            auto linePercentage = (float) (dateIt - now).Ticks() / totalTicks;
            float lineX = xAxisRect.left() + (xAxisRect.width() * linePercentage);
            painter.drawLine(QPointF(lineX, xAxisRect.top()),
                             QPointF(lineX, xAxisRect.bottom()));

            drawText(painter,
                     QPointF(lineX, xAxisRect.bottom() + margins),
                     Qt::AlignVCenter | Qt::AlignHCenter,
                     QString::number(dateIt.Hour()) + ":" + QString::number(dateIt.Minute()));
            dateIt = dateIt.AddHours(1);
        }

        // draws reference line for current time
        QString nowStr(QString::number(now.Hour()) + ":" + QString::number(now.Minute()));
        QRectF boundingRect = painter.fontMetrics().boundingRect(nowStr);
        boundingRect.setWidth(boundingRect.width() + 10);
        boundingRect.moveCenter(QPointF(xAxisRect.left(), xAxisRect.bottom() + margins + 1));
        painter.drawLine(QPointF(xAxisRect.left(), xAxisRect.top()),
                         QPointF(xAxisRect.left(), xAxisRect.bottom()));
        painter.setPen(Qt::NoPen);
        QColor transpBgColor = palette().color(QPalette::Window);
        transpBgColor.setAlphaF(0.7);
        painter.setBrush(transpBgColor);
        QRectF textBgRect(boundingRect);
        painter.drawRect(textBgRect);
        painter.setPen(Qt::gray);
        drawText(painter,
                 QPointF(xAxisRect.left(), xAxisRect.bottom() + margins),
                 Qt::AlignVCenter | Qt::AlignHCenter,
                 nowStr);

        // draws items
        for(QList<Tracker>::iterator it = trackers->begin(); it != trackers->end(); ++it) {
            QRectF itemRect(0, totalHeight, width(), trackerHeight);

            auto tracker = *it;
            painter.setPen(Qt::black);
            drawText(painter,
                     QPointF(margins, itemRect.center().y()),
                     Qt::AlignVCenter,
                     tracker.getTitle());

            auto passes = tracker.GeneratePassListQt(now, later);
            for(QList<PassDetails>::iterator it2 = passes.begin(); it2 != passes.end(); ++it2) {
                auto pass = *it2;
                auto leftPercentage = (float) (pass.aos - now).Ticks() / totalTicks;
                auto rightPercentage = (float) (pass.los - now).Ticks() / totalTicks;
                QRectF barRect(itemRect);
                barRect.setTop(itemRect.top() + 5);
                barRect.setBottom(itemRect.bottom() - 5);
                barRect.setLeft(xAxisRect.left() + xAxisRect.width() * leftPercentage);
                barRect.setRight(xAxisRect.left() + xAxisRect.width() * rightPercentage);
                painter.setPen(Qt::NoPen);
                painter.setBrush(Qt::black);
                painter.drawRect(barRect);
                painter.setBrush(Qt::NoBrush);
            }

            totalHeight += trackerHeight;
        }

        totalHeight += margins * 2;

        /*
        QRectF fullRect(QPointF(1, 1),
                        QPointF(width() - 1, totalHeight - 1));
        painter.setPen(Qt::red);
        painter.drawRect(fullRect);
        */
        painter.end();

        setMinimumHeight(totalHeight);
    }
}
<|endoftext|>


<commit_before>enum AlgoType {kKT, kANTIKT};
enum JetType  {kFULLJETS, kCHARGEDJETS, kNEUTRALJETS};

AliAnalysisTaskEmcalJetTagger* AddTaskEmcalJetTagger(const char * njetsBase,
						     const char * njetsTag,
						     const Double_t R,
						     const char * nrhoBase,
						     const char * nrhoTag,
						     const char * ntracks,
						     const char * nclusters,
						     const char *type,
						     const char *CentEst,
						     Int_t       pSel,
						     TString     trigClass      = "",
						     TString     kEmcalTriggers = "");

AliAnalysisTaskEmcalJetTagger* AddTaskEmcalJetTagger(TString     kTracksName         = "PicoTracks",
						     TString     kClusName           = "caloClustersCorr",
						     Double_t    R                   = 0.4,
						     Double_t    ptminTrack          = 0.15,
						     Double_t    etminClus           = 0.3,
						     Double_t    ptminTag            = 4.,
						     Int_t       rhoType             = 1,
						     const char *type                = "EMCAL",
						     const char *CentEst             = "V0M",
						     Int_t       pSel                = AliVEvent::kCentral | AliVEvent::kSemiCentral | AliVEvent::kMB,
						     TString     trigClass           = "",
						     TString     kEmcalTriggers      = "",
						     TString     kPeriod             = "LHC11h",
						     Int_t       recombScheme        = 0,
						     TString     tag                 = "Jet"
						     ) {

  AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
  if (!mgr)
    {
      Error("AddTaskEmcalJetTagger","No analysis manager found.");
      return 0;
    }

  // Check the analysis type using the event handlers connected to the analysis manager.
  //==============================================================================
  if (!mgr->GetInputEventHandler())
    {
      ::Error("AddTaskEmcalJetTagger", "This task requires an input event handler");
      return NULL;
    }

  // #### Add necessary jet finder tasks
  gROOT->LoadMacro("$ALICE_ROOT/PWGJE/EMCALJetTasks/macros/AddTaskEmcalJet.C");

  AliEmcalJetTask* jetFinderTaskBase = 0x0;
  if (strcmp(type,"TPC")==0)
    jetFinderTaskBase = AddTaskEmcalJet(kTracksName, "", kANTIKT, R, kCHARGEDJETS, ptminTrack, etminClus,0.005,recombScheme,tag.Data());
  else if (strcmp(type,"EMCAL")==0)
    jetFinderTaskBase = AddTaskEmcalJet(kTracksName, kClusName, kANTIKT, R, kFULLJETS, ptminTrack, etminClus,0.005,recombScheme,tag.Data());
  jetFinderTaskBase->SelectCollisionCandidates(AliVEvent::kAny);

  AliEmcalJetTask* jetFinderTaskTag  = AddTaskEmcalJet(kTracksName, "", kANTIKT, R, kCHARGEDJETS, ptminTag, etminClus,0.005,recombScheme,tag.Data());
  jetFinderTaskTag->SelectCollisionCandidates(AliVEvent::kAny);

  if(tag.EqualTo("JetPythia")) {
    jetFinderTaskBase->SelectConstituents(TObject::kBitMask, 0);
    jetFinderTaskTag->SelectConstituents(TObject::kBitMask, 0);
  }

  TString strJetsBase = jetFinderTaskBase->GetName();
  TString strJetsTag  = jetFinderTaskTag->GetName();

  AliAnalysisTaskRhoBase *rhoTaskBase;
  AliAnalysisTaskRhoBase *rhoTaskTag;
  TString rhoNameBase = "";
  TString rhoNameTag  = "";
  if(rhoType==1) {
    rhoTaskBase = AttachRhoTaskTagger(kPeriod,kTracksName,kClusName,R,ptminTrack,etminClus,recombScheme,tag);
    if(rhoTaskBase) {
      rhoTaskBase->SetCentralityEstimator(CentEst);
      rhoTaskBase->SelectCollisionCandidates(AliVEvent::kAny);
      if (strcmp(type,"TPC")==0)
	rhoNameBase = rhoTaskBase->GetOutRhoName();
      if (strcmp(type,"EMCAL")==0)
	rhoNameBase = rhoTaskBase->GetOutRhoScaledName();
    }
    if(rhoTaskTag) {
      rhoTaskTag = AttachRhoTaskTagger(kPeriod,kTracksName,kClusName,R,ptminTag,0.,recombScheme,tag);
      rhoTaskTag->SetCentralityEstimator(CentEst);
      rhoTaskTag->SelectCollisionCandidates(AliVEvent::kAny);
      rhoNameTag  = rhoTaskTag->GetOutRhoName();
    }
  }

  //Configure jet tagger task
  AliAnalysisTaskEmcalJetTagger *task = AddTaskEmcalJetTagger(jetFinderTaskBase->GetName(),
							      jetFinderTaskTag->GetName(),
							      R,
							      rhoNameBase,
							      rhoNameTag,
							      kTracksName.Data(),
							      kClusName.Data(),
							      type,
							      CentEst,
							      pSel,
							      trigClass,
							      kEmcalTriggers
							      );

  return task;

}

AliAnalysisTaskEmcalJetTagger* AddTaskEmcalJetTagger(const char * njetsBase,
						     const char * njetsTag,
						     const Double_t R,
						     const char * nrhoBase,
						     const char * nrhoTag,
						     const char * ntracks,
						     const char * nclusters,
						     const char * type,
						     const char * CentEst,
						     Int_t        pSel,
						     TString      trigClass,
						     TString      kEmcalTriggers
						     ) {

  AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
  if (!mgr)
    {
      Error("AddTaskEmcalJetTagger","No analysis manager found.");
      return 0;
    }

  // Check the analysis type using the event handlers connected to the analysis manager.
  //==============================================================================
  if (!mgr->GetInputEventHandler())
    {
      ::Error("AddTaskEmcalJetTagger", "This task requires an input event handler");
      return NULL;
    }

  TString wagonName = Form("JetTagger_%s_%s_TC%s",njetsBase,njetsTag,trigClass.Data());

  //Configure jet tagger task
  AliAnalysisTaskEmcalJetTagger *task = new AliAnalysisTaskEmcalJetTagger(wagonName.Data());

  task->SetNCentBins(4);
  //task->SetVzRange(-10.,10.);

  AliParticleContainer *trackCont  = task->AddParticleContainer(ntracks);
  AliClusterContainer *clusterCont = task->AddClusterContainer(nclusters);

  task->SetJetContainerBase(0);
  task->SetJetContainerTag(1);

  TString strType(type);
  AliJetContainer *jetContBase = task->AddJetContainer(njetsBase,strType,R);
  if(jetContBase) {
    jetContBase->SetRhoName(nrhoBase);
    jetContBase->ConnectParticleContainer(trackCont);
    jetContBase->ConnectClusterContainer(clusterCont);
    jetContBase->SetZLeadingCut(0.98,0.98);
  }

  AliJetContainer *jetContTag = task->AddJetContainer(njetsTag,"TPC",R);
  if(jetContTag) {
    jetContTag->SetRhoName(nrhoTag);
    jetContTag->ConnectParticleContainer(trackCont);
    jetContTag->ConnectClusterContainer(clusterCont);
  }
  for(Int_t i=0; i<2; i++) {
    task->SetPercAreaCut(0.6, i);
  }
  task->SetCaloTriggerPatchInfoName(kEmcalTriggers.Data());
  task->SetCentralityEstimator(CentEst);
  task->SelectCollisionCandidates(pSel);
  task->SetUseAliAnaUtils(kFALSE);

  mgr->AddTask(task);

  //Connnect input
  mgr->ConnectInput (task, 0, mgr->GetCommonInputContainer() );

  //Connect output
  TString contName(wagonName);
  TString outputfile = Form("%s",AliAnalysisManager::GetCommonFileName());
  AliAnalysisDataContainer *coutput1 = mgr->CreateContainer(contName.Data(), TList::Class(),AliAnalysisManager::kOutputContainer,outputfile);
  mgr->ConnectOutput(task,1,coutput1);

  return task;
}

AliAnalysisTaskRhoBase *AttachRhoTaskTagger(TString     kPeriod             = "LHC13b",
					    TString     kTracksName         = "PicoTracks",
					    TString     kClusName           = "caloClustersCorr",
					    Double_t    R                   = 0.4,
					    Double_t    ptminTrack          = 0.15,
					    Double_t    etminClus           = 0.3,
					    Int_t       recombScheme        = 0,
					    TString     tag                 = "Jet"
					    ) {

  AliAnalysisTaskRhoBase *rhoTaskBase;

  kPeriod.ToLower();

  // Add kt jet finder and rho task in case we want background subtraction
  AliEmcalJetTask *jetFinderKt;
  AliEmcalJetTask *jetFinderAKt;
  jetFinderKt   = AddTaskEmcalJet(kTracksName, "", kKT, R, kCHARGEDJETS, ptminTrack, etminClus,0.005,recombScheme,tag.Data());
  jetFinderAKt  = AddTaskEmcalJet(kTracksName, "", kANTIKT, R, kCHARGEDJETS, ptminTrack, etminClus,0.005,recombScheme,tag.Data());
  jetFinderKt->SelectCollisionCandidates(AliVEvent::kAny);
  jetFinderAKt->SelectCollisionCandidates(AliVEvent::kAny);
  if(tag.EqualTo("JetPythia")) {
    jetFinderKt->SelectConstituents(TObject::kBitMask, 0);
    jetFinderAKt->SelectConstituents(TObject::kBitMask, 0);
  }

  if(kPeriod.EqualTo("lhc13b") || kPeriod.EqualTo("lhc13c") || kPeriod.EqualTo("lhc13d") || kPeriod.EqualTo("lhc13e") || kPeriod.EqualTo("lhc13f")) {

    jetFinderKt->SetMinJetPt(0.);

    gROOT->LoadMacro("$ALICE_ROOT/PWGJE/EMCALJetTasks/macros/AddTaskRhoSparse.C");
    TF1 *fScale = new TF1("fScale","1.42",0.,100.); //scale factor for pPb
    AliAnalysisTaskRhoSparse *rhoTaskSparse = AddTaskRhoSparse(
			       jetFinderKt->GetName(),
			       jetFinderAKt->GetName(),
			       kTracksName,
			       kClusName,
			       Form("RhoSparseR%03d",(int)(100*R)),
			       R,
			       "TPC",
			       0.01,
			       0.15,
			       0,
			       fScale,
			       0,
			       kTRUE,
			       Form("RhoSparseR%03d",(int)(100*R)),
			       kTRUE
			       );
    rhoTaskSparse->SetUseAliAnaUtils(kTRUE);
    rhoTaskBase = dynamic_cast<AliAnalysisTaskRhoBase*>rhoTaskSparse;
  }
  else if(kPeriod.EqualTo("lhc10h") || kPeriod.EqualTo("lhc11h") ) {

    gROOT->LoadMacro("$ALICE_ROOT/PWGJE/EMCALJetTasks/macros/AddTaskRho.C");

    TF1* sfunc = new TF1("sfunc","[0]*x*x+[1]*x+[2]",-1,100);
    sfunc->SetParameter(2,1.76458);
    sfunc->SetParameter(1,-0.0111656);
    sfunc->SetParameter(0,0.000107296);
    TString rhoname = Form("%sRhoR%03dptmin%3.0f%s",tag.Data(),(int)(100*R),ptminTrack*1000.0,kTracksName.Data());
    Printf("rhoname: %s",rhoname.Data());
    AliAnalysisTaskRho *rhoTask = AddTaskRho(
					     jetFinderKt->GetName(),
					     kTracksName,
					     kClusName,
					     rhoname,
					     R,
					     "TPC",
					     0.01,
					     0,
					     sfunc,
					     2,
					     kTRUE);
    rhoTask->SetHistoBins(100,0,250);

    rhoTaskBase = dynamic_cast<AliAnalysisTaskRhoBase*>rhoTask;
  }

  return rhoTaskBase;
}
<commit_msg>keep all jets<commit_after>enum AlgoType {kKT, kANTIKT};
enum JetType  {kFULLJETS, kCHARGEDJETS, kNEUTRALJETS};

AliAnalysisTaskEmcalJetTagger* AddTaskEmcalJetTagger(const char * njetsBase,
						     const char * njetsTag,
						     const Double_t R,
						     const char * nrhoBase,
						     const char * nrhoTag,
						     const char * ntracks,
						     const char * nclusters,
						     const char *type,
						     const char *CentEst,
						     Int_t       pSel,
						     TString     trigClass      = "",
						     TString     kEmcalTriggers = "");

AliAnalysisTaskEmcalJetTagger* AddTaskEmcalJetTagger(TString     kTracksName         = "PicoTracks",
						     TString     kClusName           = "caloClustersCorr",
						     Double_t    R                   = 0.4,
						     Double_t    ptminTrack          = 0.15,
						     Double_t    etminClus           = 0.3,
						     Double_t    ptminTag            = 4.,
						     Int_t       rhoType             = 1,
						     const char *type                = "EMCAL",
						     const char *CentEst             = "V0M",
						     Int_t       pSel                = AliVEvent::kCentral | AliVEvent::kSemiCentral | AliVEvent::kMB,
						     TString     trigClass           = "",
						     TString     kEmcalTriggers      = "",
						     TString     kPeriod             = "LHC11h",
						     Int_t       recombScheme        = 0,
						     TString     tag                 = "Jet"
						     ) {

  AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
  if (!mgr)
    {
      Error("AddTaskEmcalJetTagger","No analysis manager found.");
      return 0;
    }

  // Check the analysis type using the event handlers connected to the analysis manager.
  //==============================================================================
  if (!mgr->GetInputEventHandler())
    {
      ::Error("AddTaskEmcalJetTagger", "This task requires an input event handler");
      return NULL;
    }

  // #### Add necessary jet finder tasks
  gROOT->LoadMacro("$ALICE_ROOT/PWGJE/EMCALJetTasks/macros/AddTaskEmcalJet.C");

  AliEmcalJetTask* jetFinderTaskBase = 0x0;
  if (strcmp(type,"TPC")==0)
    jetFinderTaskBase = AddTaskEmcalJet(kTracksName, "", kANTIKT, R, kCHARGEDJETS, ptminTrack, etminClus,0.005,recombScheme,tag.Data());
  else if (strcmp(type,"EMCAL")==0)
    jetFinderTaskBase = AddTaskEmcalJet(kTracksName, kClusName, kANTIKT, R, kFULLJETS, ptminTrack, etminClus,0.005,recombScheme,tag.Data());
  jetFinderTaskBase->SelectCollisionCandidates(AliVEvent::kAny);
  jetFinderTaskBase->SetMinJetPt(0.);

  AliEmcalJetTask* jetFinderTaskTag  = AddTaskEmcalJet(kTracksName, "", kANTIKT, R, kCHARGEDJETS, ptminTag, etminClus,0.005,recombScheme,tag.Data());
  jetFinderTaskTag->SelectCollisionCandidates(AliVEvent::kAny);
  jetFinderTaskTag->SetMinJetPt(0.);

  if(tag.EqualTo("JetPythia")) {
    jetFinderTaskBase->SelectConstituents(TObject::kBitMask, 0);
    jetFinderTaskTag->SelectConstituents(TObject::kBitMask, 0);
  }

  TString strJetsBase = jetFinderTaskBase->GetName();
  TString strJetsTag  = jetFinderTaskTag->GetName();

  AliAnalysisTaskRhoBase *rhoTaskBase;
  AliAnalysisTaskRhoBase *rhoTaskTag;
  TString rhoNameBase = "";
  TString rhoNameTag  = "";
  if(rhoType==1) {
    rhoTaskBase = AttachRhoTaskTagger(kPeriod,kTracksName,kClusName,R,ptminTrack,etminClus,recombScheme,tag);
    if(rhoTaskBase) {
      rhoTaskBase->SetCentralityEstimator(CentEst);
      rhoTaskBase->SelectCollisionCandidates(AliVEvent::kAny);
      if (strcmp(type,"TPC")==0)
	rhoNameBase = rhoTaskBase->GetOutRhoName();
      if (strcmp(type,"EMCAL")==0)
	rhoNameBase = rhoTaskBase->GetOutRhoScaledName();
    }
    if(rhoTaskTag) {
      rhoTaskTag = AttachRhoTaskTagger(kPeriod,kTracksName,kClusName,R,ptminTag,0.,recombScheme,tag);
      rhoTaskTag->SetCentralityEstimator(CentEst);
      rhoTaskTag->SelectCollisionCandidates(AliVEvent::kAny);
      rhoNameTag  = rhoTaskTag->GetOutRhoName();
    }
  }

  //Configure jet tagger task
  AliAnalysisTaskEmcalJetTagger *task = AddTaskEmcalJetTagger(jetFinderTaskBase->GetName(),
							      jetFinderTaskTag->GetName(),
							      R,
							      rhoNameBase,
							      rhoNameTag,
							      kTracksName.Data(),
							      kClusName.Data(),
							      type,
							      CentEst,
							      pSel,
							      trigClass,
							      kEmcalTriggers
							      );

  return task;

}

AliAnalysisTaskEmcalJetTagger* AddTaskEmcalJetTagger(const char * njetsBase,
						     const char * njetsTag,
						     const Double_t R,
						     const char * nrhoBase,
						     const char * nrhoTag,
						     const char * ntracks,
						     const char * nclusters,
						     const char * type,
						     const char * CentEst,
						     Int_t        pSel,
						     TString      trigClass,
						     TString      kEmcalTriggers
						     ) {

  AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
  if (!mgr)
    {
      Error("AddTaskEmcalJetTagger","No analysis manager found.");
      return 0;
    }

  // Check the analysis type using the event handlers connected to the analysis manager.
  //==============================================================================
  if (!mgr->GetInputEventHandler())
    {
      ::Error("AddTaskEmcalJetTagger", "This task requires an input event handler");
      return NULL;
    }

  TString wagonName = Form("JetTagger_%s_%s_TC%s",njetsBase,njetsTag,trigClass.Data());

  //Configure jet tagger task
  AliAnalysisTaskEmcalJetTagger *task = new AliAnalysisTaskEmcalJetTagger(wagonName.Data());

  task->SetNCentBins(4);
  //task->SetVzRange(-10.,10.);

  AliParticleContainer *trackCont  = task->AddParticleContainer(ntracks);
  AliClusterContainer *clusterCont = task->AddClusterContainer(nclusters);

  task->SetJetContainerBase(0);
  task->SetJetContainerTag(1);

  TString strType(type);
  AliJetContainer *jetContBase = task->AddJetContainer(njetsBase,strType,R);
  if(jetContBase) {
    jetContBase->SetRhoName(nrhoBase);
    jetContBase->ConnectParticleContainer(trackCont);
    jetContBase->ConnectClusterContainer(clusterCont);
    jetContBase->SetZLeadingCut(0.98,0.98);
  }

  AliJetContainer *jetContTag = task->AddJetContainer(njetsTag,"TPC",R);
  if(jetContTag) {
    jetContTag->SetRhoName(nrhoTag);
    jetContTag->ConnectParticleContainer(trackCont);
    jetContTag->ConnectClusterContainer(clusterCont);
  }
  for(Int_t i=0; i<2; i++) {
    task->SetPercAreaCut(0.6, i);
  }
  task->SetCaloTriggerPatchInfoName(kEmcalTriggers.Data());
  task->SetCentralityEstimator(CentEst);
  task->SelectCollisionCandidates(pSel);
  task->SetUseAliAnaUtils(kFALSE);

  mgr->AddTask(task);

  //Connnect input
  mgr->ConnectInput (task, 0, mgr->GetCommonInputContainer() );

  //Connect output
  TString contName(wagonName);
  TString outputfile = Form("%s",AliAnalysisManager::GetCommonFileName());
  AliAnalysisDataContainer *coutput1 = mgr->CreateContainer(contName.Data(), TList::Class(),AliAnalysisManager::kOutputContainer,outputfile);
  mgr->ConnectOutput(task,1,coutput1);

  return task;
}

AliAnalysisTaskRhoBase *AttachRhoTaskTagger(TString     kPeriod             = "LHC13b",
					    TString     kTracksName         = "PicoTracks",
					    TString     kClusName           = "caloClustersCorr",
					    Double_t    R                   = 0.4,
					    Double_t    ptminTrack          = 0.15,
					    Double_t    etminClus           = 0.3,
					    Int_t       recombScheme        = 0,
					    TString     tag                 = "Jet"
					    ) {

  AliAnalysisTaskRhoBase *rhoTaskBase;

  kPeriod.ToLower();

  // Add kt jet finder and rho task in case we want background subtraction
  AliEmcalJetTask *jetFinderKt;
  AliEmcalJetTask *jetFinderAKt;
  jetFinderKt   = AddTaskEmcalJet(kTracksName, "", kKT, R, kCHARGEDJETS, ptminTrack, etminClus,0.005,recombScheme,tag.Data());
  jetFinderAKt  = AddTaskEmcalJet(kTracksName, "", kANTIKT, R, kCHARGEDJETS, ptminTrack, etminClus,0.005,recombScheme,tag.Data());
  jetFinderKt->SelectCollisionCandidates(AliVEvent::kAny);
  jetFinderAKt->SelectCollisionCandidates(AliVEvent::kAny);
  jetFinderKt->SetMinJetPt(0.);
  jetFinderAKt->SetMinJetPt(0.);

  if(tag.EqualTo("JetPythia")) {
    jetFinderKt->SelectConstituents(TObject::kBitMask, 0);
    jetFinderAKt->SelectConstituents(TObject::kBitMask, 0);
  }

  if(kPeriod.EqualTo("lhc13b") || kPeriod.EqualTo("lhc13c") || kPeriod.EqualTo("lhc13d") || kPeriod.EqualTo("lhc13e") || kPeriod.EqualTo("lhc13f")) {

    jetFinderKt->SetMinJetPt(0.);

    gROOT->LoadMacro("$ALICE_ROOT/PWGJE/EMCALJetTasks/macros/AddTaskRhoSparse.C");
    TF1 *fScale = new TF1("fScale","1.42",0.,100.); //scale factor for pPb
    AliAnalysisTaskRhoSparse *rhoTaskSparse = AddTaskRhoSparse(
			       jetFinderKt->GetName(),
			       jetFinderAKt->GetName(),
			       kTracksName,
			       kClusName,
			       Form("RhoSparseR%03d",(int)(100*R)),
			       R,
			       "TPC",
			       0.01,
			       0.15,
			       0,
			       fScale,
			       0,
			       kTRUE,
			       Form("RhoSparseR%03d",(int)(100*R)),
			       kTRUE
			       );
    rhoTaskSparse->SetUseAliAnaUtils(kTRUE);
    rhoTaskBase = dynamic_cast<AliAnalysisTaskRhoBase*>rhoTaskSparse;
  }
  else if(kPeriod.EqualTo("lhc10h") || kPeriod.EqualTo("lhc11h") ) {

    gROOT->LoadMacro("$ALICE_ROOT/PWGJE/EMCALJetTasks/macros/AddTaskRho.C");

    TF1* sfunc = new TF1("sfunc","[0]*x*x+[1]*x+[2]",-1,100);
    sfunc->SetParameter(2,1.76458);
    sfunc->SetParameter(1,-0.0111656);
    sfunc->SetParameter(0,0.000107296);
    TString rhoname = Form("%sRhoR%03dptmin%3.0f%s",tag.Data(),(int)(100*R),ptminTrack*1000.0,kTracksName.Data());
    Printf("rhoname: %s",rhoname.Data());
    AliAnalysisTaskRho *rhoTask = AddTaskRho(
					     jetFinderKt->GetName(),
					     kTracksName,
					     kClusName,
					     rhoname,
					     R,
					     "TPC",
					     0.01,
					     0,
					     sfunc,
					     2,
					     kTRUE);
    rhoTask->SetHistoBins(100,0,250);

    rhoTaskBase = dynamic_cast<AliAnalysisTaskRhoBase*>rhoTask;
  }

  return rhoTaskBase;
}
<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights.  These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include <QtCore/qmetaobject.h>

#include <qmediaobject_p.h>

#include <qmediaservice.h>
#include <qmetadatacontrol.h>

QT_BEGIN_NAMESPACE

void QMediaObjectPrivate::_q_notify()
{
    Q_Q(QMediaObject);

    const QMetaObject* m = q->metaObject();

    foreach (int pi, notifyProperties) {
        QMetaProperty p = m->property(pi);
        p.notifySignal().invoke(
            q, QGenericArgument(QMetaType::typeName(p.userType()), p.read(q).data()));
    }
}

/*!
    \class QMediaObject
    \preliminary
    \brief The QMediaObject class provides a common base for multimedia objects.

    \ingroup multimedia

    QMediaObject derived classes provide access to the functionality of a
    QMediaService.  Each media object hosts a QMediaService and uses the
    QMediaControl interfaces implemented by the service to implement its
    API.  Most media objects when constructed will request a new
    QMediaService instance from a QMediaServiceProvider, but some like
    QMediaRecorder will share a service with another object.

    QMediaObject itself provides an API for accessing a media service's \l {metaData()}{meta-data} and a means of connecting other media objects,
    and peripheral classes like QVideoWidget and QMediaPlaylist.

    \sa QMediaService, QMediaControl
*/

/*!
    Destroys a media object.
*/

QMediaObject::~QMediaObject()
{
    delete d_ptr;
}

/*!
    Returns the service availability error state.
*/

QtMediaServices::AvailabilityError QMediaObject::availabilityError() const
{
    return QtMediaServices::ServiceMissingError;
}

/*!
    Returns true if the service is available for use.
*/

bool QMediaObject::isAvailable() const
{
    return false;
}

/*!
    Returns the media service that provides the functionality of a multimedia object.
*/

QMediaService* QMediaObject::service() const
{
    return d_func()->service;
}

int QMediaObject::notifyInterval() const
{
    return d_func()->notifyTimer->interval();
}

void QMediaObject::setNotifyInterval(int milliSeconds)
{
    Q_D(QMediaObject);

    if (d->notifyTimer->interval() != milliSeconds) {
        d->notifyTimer->setInterval(milliSeconds);

        emit notifyIntervalChanged(milliSeconds);
    }
}

/*!
  \internal
*/
void QMediaObject::bind(QObject*)
{
}

/*!
  \internal
*/
void QMediaObject::unbind(QObject*)
{
}

/*!
    Constructs a media object which uses the functionality provided by a media \a service.

    The \a parent is passed to QObject.

    This class is meant as a base class for Multimedia objects so this
    constructor is protected.
*/

QMediaObject::QMediaObject(QObject *parent, QMediaService *service):
    QObject(parent),
    d_ptr(new QMediaObjectPrivate)

{
    Q_D(QMediaObject);

    d->q_ptr = this;

    d->notifyTimer = new QTimer(this);
    d->notifyTimer->setInterval(1000);
    connect(d->notifyTimer, SIGNAL(timeout()), SLOT(_q_notify()));

    d->service = service;

    setupMetaData();
}

/*!
    \internal
*/

QMediaObject::QMediaObject(QMediaObjectPrivate &dd, QObject *parent,
                                            QMediaService *service):
    QObject(parent),
    d_ptr(&dd)
{
    Q_D(QMediaObject);
    d->q_ptr = this;

    d->notifyTimer = new QTimer(this);
    d->notifyTimer->setInterval(1000);
    connect(d->notifyTimer, SIGNAL(timeout()), SLOT(_q_notify()));

    d->service = service;

    setupMetaData();
}

/*!
    Watch the property \a name. The property's notify signal will be emitted
    once every notifyInterval milliseconds.

    \sa notifyInterval
*/

void QMediaObject::addPropertyWatch(QByteArray const &name)
{
    Q_D(QMediaObject);

    const QMetaObject* m = metaObject();

    int index = m->indexOfProperty(name.constData());

    if (index != -1 && m->property(index).hasNotifySignal()) {
        d->notifyProperties.insert(index);

        if (!d->notifyTimer->isActive())
            d->notifyTimer->start();
    }
}

/*!
    Remove property \a name from the list of properties whose changes are
    regularly signaled.

    \sa notifyInterval
*/

void QMediaObject::removePropertyWatch(QByteArray const &name)
{
    Q_D(QMediaObject);

    int index = metaObject()->indexOfProperty(name.constData());

    if (index != -1) {
        d->notifyProperties.remove(index);

        if (d->notifyProperties.isEmpty())
            d->notifyTimer->stop();
    }
}

/*!
    \property QMediaObject::notifyInterval

    The interval at which notifiable properties will update.

    The interval is expressed in milliseconds, the default value is 1000.

    \sa addPropertyWatch(), removePropertyWatch()
*/

/*!
    \fn void QMediaObject::notifyIntervalChanged(int milliseconds)

    Signal a change in the notify interval period to \a milliseconds.
*/

/*!
    \property QMediaObject::metaDataAvailable
    \brief whether access to a media object's meta-data is available.

    If this is true there is meta-data available, otherwise there is no meta-data available.
*/

bool QMediaObject::isMetaDataAvailable() const
{
    Q_D(const QMediaObject);

    return d->metaDataControl
            ? d->metaDataControl->isMetaDataAvailable()
            : false;
}

/*!
    \fn QMediaObject::metaDataAvailableChanged(bool available)

    Signals that the \a available state of a media object's meta-data has changed.
*/

/*!
    \property QMediaObject::metaDataWritable
    \brief whether a media object's meta-data is writable.

    If this is true the meta-data is writable, otherwise the meta-data is read-only.
*/

bool QMediaObject::isMetaDataWritable() const
{
    Q_D(const QMediaObject);

    return d->metaDataControl
            ? d->metaDataControl->isWritable()
            : false;
}

/*!
    \fn QMediaObject::metaDataWritableChanged(bool writable)

    Signals that the \a writable state of a media object's meta-data has changed.
*/

/*!
    Returns the value associated with a meta-data \a key.
*/
QVariant QMediaObject::metaData(QtMediaServices::MetaData key) const
{
    Q_D(const QMediaObject);

    return d->metaDataControl
            ? d->metaDataControl->metaData(key)
            : QVariant();
}

/*!
    Sets a \a value for a meta-data \a key.
*/
void QMediaObject::setMetaData(QtMediaServices::MetaData key, const QVariant &value)
{
    Q_D(QMediaObject);

    if (d->metaDataControl)
        d->metaDataControl->setMetaData(key, value);
}

/*!
    Returns a list of keys there is meta-data available for.
*/
QList<QtMediaServices::MetaData> QMediaObject::availableMetaData() const
{
    Q_D(const QMediaObject);

    return d->metaDataControl
            ? d->metaDataControl->availableMetaData()
            : QList<QtMediaServices::MetaData>();
}

/*!
    \fn QMediaObject::metaDataChanged()

    Signals that a media object's meta-data has changed.
*/

/*!
    Returns the value associated with a meta-data \a key.

    The naming and type of extended meta-data is not standardized, so the values and meaning
    of keys may vary between backends.
*/
QVariant QMediaObject::extendedMetaData(const QString &key) const
{
    Q_D(const QMediaObject);

    return d->metaDataControl
            ? d->metaDataControl->extendedMetaData(key)
            : QVariant();
}

/*!
    Sets a \a value for a meta-data \a key.

    The naming and type of extended meta-data is not standardized, so the values and meaning
    of keys may vary between backends.
*/
void QMediaObject::setExtendedMetaData(const QString &key, const QVariant &value)
{
    Q_D(QMediaObject);

    if (d->metaDataControl)
        d->metaDataControl->setExtendedMetaData(key, value);
}

/*!
    Returns a list of keys there is extended meta-data available for.
*/
QStringList QMediaObject::availableExtendedMetaData() const
{
    Q_D(const QMediaObject);

    return d->metaDataControl
            ? d->metaDataControl->availableExtendedMetaData()
            : QStringList();
}

void QMediaObject::setupMetaData()
{
    Q_D(QMediaObject);

    if (d->service != 0) {
        d->metaDataControl =
            qobject_cast<QMetaDataControl*>(d->service->control(QMetaDataControl_iid));

        if (d->metaDataControl) {
            connect(d->metaDataControl, SIGNAL(metaDataChanged()), SIGNAL(metaDataChanged()));
            connect(d->metaDataControl,
                    SIGNAL(metaDataAvailableChanged(bool)),
                    SIGNAL(metaDataAvailableChanged(bool)));
            connect(d->metaDataControl,
                    SIGNAL(writableChanged(bool)),
                    SIGNAL(metaDataWritableChanged(bool)));
        }
    }
}

/*!
    \fn QMediaObject::availabilityChanged(bool available)

    Signal emitted when the availability state has changed to \a available
*/

#include "moc_qmediaobject.cpp"
QT_END_NAMESPACE

<commit_msg>Update QMediaObject with request/releaseControl changes.<commit_after>/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights.  These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include <QtCore/qmetaobject.h>

#include <qmediaobject_p.h>

#include <qmediaservice.h>
#include <qmetadatacontrol.h>

QT_BEGIN_NAMESPACE

void QMediaObjectPrivate::_q_notify()
{
    Q_Q(QMediaObject);

    const QMetaObject* m = q->metaObject();

    foreach (int pi, notifyProperties) {
        QMetaProperty p = m->property(pi);
        p.notifySignal().invoke(
            q, QGenericArgument(QMetaType::typeName(p.userType()), p.read(q).data()));
    }
}

/*!
    \class QMediaObject
    \preliminary
    \brief The QMediaObject class provides a common base for multimedia objects.

    \ingroup multimedia

    QMediaObject derived classes provide access to the functionality of a
    QMediaService.  Each media object hosts a QMediaService and uses the
    QMediaControl interfaces implemented by the service to implement its
    API.  Most media objects when constructed will request a new
    QMediaService instance from a QMediaServiceProvider, but some like
    QMediaRecorder will share a service with another object.

    QMediaObject itself provides an API for accessing a media service's \l {metaData()}{meta-data} and a means of connecting other media objects,
    and peripheral classes like QVideoWidget and QMediaPlaylist.

    \sa QMediaService, QMediaControl
*/

/*!
    Destroys a media object.
*/

QMediaObject::~QMediaObject()
{
    delete d_ptr;
}

/*!
    Returns the service availability error state.
*/

QtMediaServices::AvailabilityError QMediaObject::availabilityError() const
{
    return QtMediaServices::ServiceMissingError;
}

/*!
    Returns true if the service is available for use.
*/

bool QMediaObject::isAvailable() const
{
    return false;
}

/*!
    Returns the media service that provides the functionality of a multimedia object.
*/

QMediaService* QMediaObject::service() const
{
    return d_func()->service;
}

int QMediaObject::notifyInterval() const
{
    return d_func()->notifyTimer->interval();
}

void QMediaObject::setNotifyInterval(int milliSeconds)
{
    Q_D(QMediaObject);

    if (d->notifyTimer->interval() != milliSeconds) {
        d->notifyTimer->setInterval(milliSeconds);

        emit notifyIntervalChanged(milliSeconds);
    }
}

/*!
  \internal
*/
void QMediaObject::bind(QObject*)
{
}

/*!
  \internal
*/
void QMediaObject::unbind(QObject*)
{
}

/*!
    Constructs a media object which uses the functionality provided by a media \a service.

    The \a parent is passed to QObject.

    This class is meant as a base class for Multimedia objects so this
    constructor is protected.
*/

QMediaObject::QMediaObject(QObject *parent, QMediaService *service):
    QObject(parent),
    d_ptr(new QMediaObjectPrivate)

{
    Q_D(QMediaObject);

    d->q_ptr = this;

    d->notifyTimer = new QTimer(this);
    d->notifyTimer->setInterval(1000);
    connect(d->notifyTimer, SIGNAL(timeout()), SLOT(_q_notify()));

    d->service = service;

    setupMetaData();
}

/*!
    \internal
*/

QMediaObject::QMediaObject(QMediaObjectPrivate &dd, QObject *parent,
                                            QMediaService *service):
    QObject(parent),
    d_ptr(&dd)
{
    Q_D(QMediaObject);
    d->q_ptr = this;

    d->notifyTimer = new QTimer(this);
    d->notifyTimer->setInterval(1000);
    connect(d->notifyTimer, SIGNAL(timeout()), SLOT(_q_notify()));

    d->service = service;

    setupMetaData();
}

/*!
    Watch the property \a name. The property's notify signal will be emitted
    once every notifyInterval milliseconds.

    \sa notifyInterval
*/

void QMediaObject::addPropertyWatch(QByteArray const &name)
{
    Q_D(QMediaObject);

    const QMetaObject* m = metaObject();

    int index = m->indexOfProperty(name.constData());

    if (index != -1 && m->property(index).hasNotifySignal()) {
        d->notifyProperties.insert(index);

        if (!d->notifyTimer->isActive())
            d->notifyTimer->start();
    }
}

/*!
    Remove property \a name from the list of properties whose changes are
    regularly signaled.

    \sa notifyInterval
*/

void QMediaObject::removePropertyWatch(QByteArray const &name)
{
    Q_D(QMediaObject);

    int index = metaObject()->indexOfProperty(name.constData());

    if (index != -1) {
        d->notifyProperties.remove(index);

        if (d->notifyProperties.isEmpty())
            d->notifyTimer->stop();
    }
}

/*!
    \property QMediaObject::notifyInterval

    The interval at which notifiable properties will update.

    The interval is expressed in milliseconds, the default value is 1000.

    \sa addPropertyWatch(), removePropertyWatch()
*/

/*!
    \fn void QMediaObject::notifyIntervalChanged(int milliseconds)

    Signal a change in the notify interval period to \a milliseconds.
*/

/*!
    \property QMediaObject::metaDataAvailable
    \brief whether access to a media object's meta-data is available.

    If this is true there is meta-data available, otherwise there is no meta-data available.
*/

bool QMediaObject::isMetaDataAvailable() const
{
    Q_D(const QMediaObject);

    return d->metaDataControl
            ? d->metaDataControl->isMetaDataAvailable()
            : false;
}

/*!
    \fn QMediaObject::metaDataAvailableChanged(bool available)

    Signals that the \a available state of a media object's meta-data has changed.
*/

/*!
    \property QMediaObject::metaDataWritable
    \brief whether a media object's meta-data is writable.

    If this is true the meta-data is writable, otherwise the meta-data is read-only.
*/

bool QMediaObject::isMetaDataWritable() const
{
    Q_D(const QMediaObject);

    return d->metaDataControl
            ? d->metaDataControl->isWritable()
            : false;
}

/*!
    \fn QMediaObject::metaDataWritableChanged(bool writable)

    Signals that the \a writable state of a media object's meta-data has changed.
*/

/*!
    Returns the value associated with a meta-data \a key.
*/
QVariant QMediaObject::metaData(QtMediaServices::MetaData key) const
{
    Q_D(const QMediaObject);

    return d->metaDataControl
            ? d->metaDataControl->metaData(key)
            : QVariant();
}

/*!
    Sets a \a value for a meta-data \a key.
*/
void QMediaObject::setMetaData(QtMediaServices::MetaData key, const QVariant &value)
{
    Q_D(QMediaObject);

    if (d->metaDataControl)
        d->metaDataControl->setMetaData(key, value);
}

/*!
    Returns a list of keys there is meta-data available for.
*/
QList<QtMediaServices::MetaData> QMediaObject::availableMetaData() const
{
    Q_D(const QMediaObject);

    return d->metaDataControl
            ? d->metaDataControl->availableMetaData()
            : QList<QtMediaServices::MetaData>();
}

/*!
    \fn QMediaObject::metaDataChanged()

    Signals that a media object's meta-data has changed.
*/

/*!
    Returns the value associated with a meta-data \a key.

    The naming and type of extended meta-data is not standardized, so the values and meaning
    of keys may vary between backends.
*/
QVariant QMediaObject::extendedMetaData(const QString &key) const
{
    Q_D(const QMediaObject);

    return d->metaDataControl
            ? d->metaDataControl->extendedMetaData(key)
            : QVariant();
}

/*!
    Sets a \a value for a meta-data \a key.

    The naming and type of extended meta-data is not standardized, so the values and meaning
    of keys may vary between backends.
*/
void QMediaObject::setExtendedMetaData(const QString &key, const QVariant &value)
{
    Q_D(QMediaObject);

    if (d->metaDataControl)
        d->metaDataControl->setExtendedMetaData(key, value);
}

/*!
    Returns a list of keys there is extended meta-data available for.
*/
QStringList QMediaObject::availableExtendedMetaData() const
{
    Q_D(const QMediaObject);

    return d->metaDataControl
            ? d->metaDataControl->availableExtendedMetaData()
            : QStringList();
}

void QMediaObject::setupMetaData()
{
    Q_D(QMediaObject);

    if (d->service != 0) {
        d->metaDataControl =
            qobject_cast<QMetaDataControl*>(d->service->requestControl(QMetaDataControl_iid));

        if (d->metaDataControl) {
            connect(d->metaDataControl, SIGNAL(metaDataChanged()), SIGNAL(metaDataChanged()));
            connect(d->metaDataControl,
                    SIGNAL(metaDataAvailableChanged(bool)),
                    SIGNAL(metaDataAvailableChanged(bool)));
            connect(d->metaDataControl,
                    SIGNAL(writableChanged(bool)),
                    SIGNAL(metaDataWritableChanged(bool)));
        }
    }
}

/*!
    \fn QMediaObject::availabilityChanged(bool available)

    Signal emitted when the availability state has changed to \a available
*/

#include "moc_qmediaobject.cpp"
QT_END_NAMESPACE

<|endoftext|>