blob: 2401d4fb0bac85b4d50bf4fb55179efe3895ee82 [file] [log] [blame]
/**************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*************************************************************/
#ifndef CSV_RANGE_HXX
#define CSV_RANGE_HXX
#include <cstring> // for std::size_t
namespace csv
{
/** Represents a range of integer or iterator values.
@tpl T
Has to be assignable, add- and subtractable. That is:
either it is
- an integral type
- or a random access iterator.
*/
template <class T>
class range
{
public:
typedef T element_type; /// Provided for generic programming.
typedef range<T> self;
// LIFECYCLE
range(
T i_inclusiveLowerBorder,
T i_exclusiveUpperBorder );
~range();
// INQUIRY
T begin() const;
T end() const;
std::size_t size() const;
bool contains(
T i_value ) const;
bool contains(
const self & i_other ) const;
bool overlaps(
const self & i_other ) const;
/// @return i_other.begin() - this->end()
long distance_to(
const self & i_other ) const;
private:
// DATA
T nBegin;
T nEnd;
};
template <class T>
inline range<T>
make_range(T i1, T i2)
{
return range<T>(i1, i2);
}
template <class T>
inline range<typename T::const_iterator>
range_of(const T & i_container)
{
return make_range( i_container.begin(),
i_container.end()
);
}
template <class T>
inline range<typename T::iterator>
range_of(T & io_container)
{
return make_range( io_container.begin(),
io_container.end()
);
}
// IMPLEMENTATION
template <class T>
range<T>::range( T i_inclusiveLowerBorder,
T i_exclusiveUpperBorder )
: nBegin(i_inclusiveLowerBorder),
nEnd(i_exclusiveUpperBorder)
{
csv_assert( nBegin <= nEnd
&& "Invalid parameters for range<> constructor.");
}
template <class T>
range<T>::~range()
{
}
template <class T>
inline T
range<T>::begin() const
{
return nBegin;
}
template <class T>
inline T
range<T>::end() const
{
return nEnd;
}
template <class T>
inline std::size_t
range<T>::size() const
{
csv_assert( nBegin <= nEnd
&& "Invalid range limits in range<>::size().");
return static_cast<std::size_t>( end() - begin() );
}
template <class T>
bool
range<T>::contains(T i_value ) const
{
return begin() <= i_value
&& i_value < end();
}
template <class T>
bool
range<T>::contains(const self & i_other) const
{
// This is subtle, because this would be wrong:
// begin() <= i_other.begin()
// && i_other.end() <= end();
// An empty range that begins and starts at my end()
// must not be contained.
return contains(i_other.begin())
&& i_other.end() <= end();
}
template <class T>
bool
range<T>::overlaps(const self & i_other) const
{
return contains(i_other.begin())
|| i_other.contains(begin());
}
template <class T>
long
range<T>::distance_to(const self & i_other) const
{
return i_other.begin() - end();
}
} // namespace csv
#endif