/*
	PIP - Platform Independent Primitives
	Generic containers
	Ivan Pelipenko peri4ko@yandex.ru

	This program 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 3 of the License, or
	(at your option) any later version.

	This program 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 program.  If not, see <http://www.gnu.org/licenses/>.
*/


/** \class PIVector
 * \brief Dynamic array of any type
 * \details This class used to store dynamic array of any
 * type of data. In memory data stored linear. You can insert
 * item in any place of remove some items from any place.
 * For quick add elements this is stream operator <<.

 * \fn PIVector::PIVector();
 * Contructs an empty vector

 * \fn PIVector::PIVector(size_t size, const T & value = T());
 * \brief Contructs vector with size "size" filled elements "value"
 * \details Example: \snippet picontainers.cpp PIVector::PIVector

 * \fn PIVector::PIVector(std::initializer_list list);
 * \brief Contructs vector from C++11 initializer list
 * \details Example: \snippet picontainers.cpp PIVector::PIVector

 * \fn const T & PIVector::at(size_t index) const;
 * \brief Read-only access to element by index "index"
 * \details Example: \snippet picontainers.cpp PIVector::at_c
 * \sa \a operator[]

 * \fn T & PIVector::at(size_t index);
 * \brief Full access to element by index "index"
 * \details Example: \snippet picontainers.cpp PIVector::at
 * \sa \a operator[]

 * \fn const T * PIVector::data(size_t index = 0) const;
 * \brief Read-only pointer to element by index "index"
 * \details Example: \snippet picontainers.cpp PIVector::data_c

 * \fn T * PIVector::data(size_t index = 0);
 * \brief Pointer to element by index "index"
 * \details Example: \snippet picontainers.cpp PIVector::data

 * \fn size_t PIVector::size() const;
 * \brief Elements count

 * \fn ssize_t PIVector::size_s() const;
 * \brief Elements count

 * \fn bool PIVector::isEmpty() const;
 * \brief Return \c "true" if vector is empty, i.e. size = 0

 * \fn bool PIVector::has(const T & t) const;

 * \fn bool PIVector::contains(const T & v) const;
 * \brief Return \c "true" if vector has at least one element equal "t"

 * \fn int PIVector::etries(const T & t) const;
 * \brief Return how many times element "t" appears in vector

 * \fn ssize_t PIVector::indexOf(const T & t) const;
 * \brief Return index of first element equal "t" or -1 if there is no such element

 * \fn ssize_t PIVector::lastIndexOf(const T & t) const;
 * \brief Return index of last element equal "t" or -1 if there is no such element

 * \fn static int PIVector::compare_func(const T * t0, const T * t1);
 * \brief Standard compare function for type "T". Return  0 if t0 = t1,  -1 if t0 < t1  and  1 if t0 > t1.

 * \fn void PIVector::resize(size_t size, const T & new_type = T());
 * \brief Resize vector to size "size"
 * \details Elements removed from end of vector if new size < old size, or added new elements = "new_type" if new size > old size.\n
 * Example: \snippet picontainers.cpp PIVector::resize
 * \sa \a size(), \a clear()

 * \fn PIVector & PIVector::enlarge(size_t size);
 * \brief Increase vector size with "size" elements

 * \fn void PIVector::clear();
 * \brief Clear vector. Equivalent to call <tt>"resize(0)"</tt>

 * \fn PIVector & PIVector::sort(CompareFunc compare = compare_func);
 * \brief Sort vector using quick sort algorithm and standard compare function
 * \details Example: \snippet picontainers.cpp PIVector::sort_0 
 * With custom compare function: \snippet picontainers.cpp PIVector::sort_1

 * \fn PIVector & PIVector::fill(const T & t);
 * \brief Fill vector with elements "t" leave size is unchanged and return reference to vector
 * \details Example: \snippet picontainers.cpp PIVector::fill

 * \fn PIVector & PIVector::assign(const T & t = T());
 * \brief Synonym of \a fill(t)

 * \fn PIVector & PIVector::assign(size_t new_size, const T & t);
 * \brief Resize to "new_size", then fill with "t"

 * \fn T & PIVector::back();
 * \brief Last element of the vector

 * \fn const T & PIVector::back() const;
 * \brief Last element of the vector

 * \fn T & PIVector::front();
 * \brief First element of the vector

 * \fn const T & PIVector::front() const;
 * \brief First element of the vector

 * \fn PIVector & PIVector::push_back(const T & t);
 * \brief Add new element "t" at the end of vector and return reference to vector

 * \fn PIVector & PIVector::push_front(const T & t);
 * \brief Add new element "t" at the beginning of vector and return reference to vector

 * \fn PIVector & PIVector::pop_back();
 * \brief Remove one element from the end of vector and return reference to vector

 * \fn PIVector & PIVector::pop_front();
 * \brief Remove one element from the beginning of vector and return reference to vector

 * \fn T PIVector::take_back();
 * \brief Remove one element from the end of vector and return it

 * \fn T PIVector::take_front();
 * \brief Remove one element from the beginning of vector and return it

 * \fn PIVector & PIVector::remove(size_t index);
 * \brief Remove one element by index "index" and return reference to vector
 * \details Example: \snippet picontainers.cpp PIVector::remove_0
 * \sa \a removeOne(), \a removeAll()

 * \fn PIVector & PIVector::remove(size_t index, size_t count);
 * \brief Remove "count" elements by first index "index" and return reference to vector
 * \details Example: \snippet picontainers.cpp PIVector::remove_1
 * \sa \a removeOne(), \a removeAll()

 * \fn PIVector & PIVector::removeOne(const T & v);
 * \brief Remove no more than one element equal "v" and return reference to vector
 * \details Example: \snippet picontainers.cpp PIVector::removeOne
 * \sa \a remove(), \a removeAll()

 * \fn PIVector & PIVector::removeAll(const T & v);
 * \brief Remove all elements equal "v" and return reference to vector
 * \details Example: \snippet picontainers.cpp PIVector::removeAll
 * \sa \a remove(), \a removeOne()

 * \fn PIVector & PIVector::insert(size_t pos, const T & t);
 * \brief Insert element "t" after index "pos" and return reference to vector
 * \details Example: \snippet picontainers.cpp PIVector::insert_0

 * \fn PIVector & PIVector::insert(size_t pos, const PIVector & t);
 * \brief Insert other vector "t" after index "pos" and return reference to vector
 * \details Example: \snippet picontainers.cpp PIVector::insert_1

 * \fn T & PIVector::operator [](size_t index);
 * \brief Full access to element by index "index"
 * \details Example: \snippet picontainers.cpp PIVector::()
 * \sa \a at()

 * \fn const T & PIVector::operator [](size_t index) const;
 * \brief Read-only access to element by index "index"
 * \details Example: \snippet picontainers.cpp PIVector::()_c
 * \sa \a at()

 * \fn PIVector & PIVector::operator <<(const T & t);
 * \brief Add new element "t" at the end of vector and return reference to vector

 * \fn PIVector & PIVector::operator <<(const PIVector & t);
 * \brief Add vector "t" at the end of vector and return reference to vector

 * \fn bool PIVector::operator ==(const PIVector & t);
 * \brief Compare with vector "t"

 * \fn bool PIVector::operator !=(const PIVector & t);
 * \brief Compare with vector "t"

 * */




/** \class PIMap
 * \brief Associative array
 * \details This class used to store Key = Value array of any
 * type of data. \a value() returns value for key and leave map
 * unchaged in any case. \a operator [] create entry in map if
 * there is no entry for given key. You can retrieve all
 * keys by method \a keys() and all values by methos \a values().
 * To iterate all entries use class PIMapIterator, or methods
 * \a makeIterator() and \a makeReverseIterator().

 * \fn PIMap::PIMap();
 * \brief Contructs an empty map

 * \fn PIMap::PIMap(const PIMap & other);
 * \brief Contructs a copy of "other"

 * \fn PIMap & PIMap::operator =(const PIMap & other);
 * \brief Copy operator

 * \fn PIMap::PIMap(const PIMap & other);
 * \brief Contructs a copy of "other"

* \fn PIMapIterator PIMap::makeIterator() const
* \brief Returns PIMapIterator for this map

* \fn PIMapIterator PIMap::makeReverseIterator() const
* \brief Returns reverse PIMapIterator for this map


* \fn size_t PIMap::size() const
* \brief Returns entries count

* \fn int PIMap::size_s() const
* \brief Returns entries count

* \fn size_t PIMap::length() const
* \brief Returns entries count

* \fn bool PIMap::isEmpty() const
* \brief Returns if map is empty


* \fn T & PIMap::operator [](const Key & key)
* \brief Returns value for key "key". If there is no key in map, create one.

* \fn const T PIMap::operator [](const Key & key) const
* \brief Returns value for key "key". If there is no key in map, returns default T().

* \fn T & PIMap::at(const Key & key)
* \brief Equivalent to operator []

* \fn const T PIMap::at(const Key & key) const
* \brief Equivalent to operator []


* \fn PIMap & PIMap::operator <<(const PIMap & other)
* \brief Insert all etries of "other" to this map. Override existing values.

* \fn bool PIMap::operator ==(const PIMap & t) const
* \brief Compare operator

* \fn bool PIMap::operator !=(const PIMap & t) const
* \brief Compare operator

* \fn bool PIMap::contains(const Key & key) const
* \brief Returns "true" if map contains entry with key "key"


* \fn PIMap & PIMap::reserve(size_t new_size)
* \brief Reserve space for "new_size" entries

* \fn PIMap & PIMap::removeOne(const Key & key)
* \brief Remove entry with key "key"

* \fn PIMap & PIMap::remove(const Key & key)
* \brief Equivalent \a removeOne(key)

* \fn PIMap & PIMap::erase(const Key & key)
* \brief Equivalent \a removeOne(key)

* \fn PIMap & PIMap::clear()
* \brief Clear map


* \fn void PIMap::swap(PIMap & other)
* \brief Swap map with "other"


* \fn PIMap & PIMap::insert(const Key & key, const T & value)
* \brief Insert or rewrite entry with key "key" and value "value"

* \fn const T PIMap::value(const Key & key, const T & default = T())
* \brief Returns value for key "key". If there is no key in map, returns "default".

* \fn PIVector<T> PIMap::values() const
* \brief Returns all values as PIVector

* \fn Key PIMap::key(const T & value, const Key & default = Key()) const
* \brief Returns key for first founded value "value". If there is no such value in map, returns "default".

* \fn PIVector<Key> PIMap::keys() const
* \brief Returns all keys as PIVector

 * */




/** \class PIMapIterator
 * \brief Helper class to iterate over PIMap
 * \details This class used to access keys and values in PIMap.
 * You can use constructor to create iterator, or use \a PIMap::makeIterator()
 * and \a PIMap::makeReverseIterator() methods.
 *
 * First usage variant:
 * \code
 * PIMap<int, PIString> m;
 * m[1] = "one";
 * m[2] = "two";
 * m[4] = "four";
 *
 * auto it = m.makeIterator();
 * while (it.next()) {
 *     piCout << it.key() << it.value();
 * }
 * // 1 one
 * // 2 two
 * // 4 four
 * \endcode
 *
 * Using hasNext():
 * \code
 * while (it.hasNext()) {
 *     it.next();
 * \endcode
 *
 * Using constructor:
 * \code
 * PIMapIterator<int, PIString> it(m);
 * \endcode
 *
 * Write access:
 * \code
 * while (it.next()) {
 *     it.valueRef().append("_!");
 *     piCout << it.key() << it.value();
 * }
 *
 * // 1 one_!
 * // 2 two_!
 * // 4 four_!
 * \endcode
 *
 * Reverse iterator:
 * \code
 * auto it = m.makeReverseIterator();
 * while (it.next()) {
 *     piCout << it.key() << it.value();
 * }
 *
 * // 4 four
 * // 2 two
 * // 1 one
 * \endcode

* \fn PIMapIterator(const PIMap & map, bool reverse = false)
* \brief Contructs iterator for "map". Current position is invalid.

* \fn const Key & PIMapIterator::key() const
* \brief Returns current entry key

* \fn const T & PIMapIterator::value() const
* \brief Returns current entry value

* \fn T & PIMapIterator::valueRef() const
* \brief Returns reference to current entry value

* \fn bool PIMapIterator::hasNext()
* \brief Returns if iterator can jump to next entry

* \fn bool PIMapIterator::next()
* \brief Jump to next entry and return if new position is valid.

* \fn void PIMapIterator::reset()
* \brief Reset iterator to initial position.

 * */
