00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00043 #ifndef RANGELIB_INCL_RANGELIB_HPP_INTEGRAL_RANGE
00044 #define RANGELIB_INCL_RANGELIB_HPP_INTEGRAL_RANGE
00045
00046 #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
00047 # define RANGELIB_VER_RANGELIB_HPP_INTEGRAL_RANGE_MAJOR 2
00048 # define RANGELIB_VER_RANGELIB_HPP_INTEGRAL_RANGE_MINOR 6
00049 # define RANGELIB_VER_RANGELIB_HPP_INTEGRAL_RANGE_REVISION 4
00050 # define RANGELIB_VER_RANGELIB_HPP_INTEGRAL_RANGE_EDIT 55
00051 #endif
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068 #ifndef RANGELIB_INCL_RANGELIB_HPP_RANGELIB
00069 # include <rangelib/rangelib.hpp>
00070 #endif
00071 #ifndef RANGELIB_INCL_RANGELIB_HPP_RANGE_CATEGORIES
00072 # include <rangelib/range_categories.hpp>
00073 #endif
00074 #ifndef STLSOFT_INCL_STLSOFT_UTIL_HPP_OPERATOR_BOOL
00075 # include <stlsoft/util/operator_bool.hpp>
00076 #endif
00077 #ifndef STLSOFT_INCL_STLSOFT_ERROR_HPP_EXCEPTIONS
00078 # include <stlsoft/error/exceptions.hpp>
00079 #endif
00080 #ifndef STLSOFT_INCL_STLSOFT_UTIL_HPP_CONSTRAINTS
00081 # include <stlsoft/util/constraints.hpp>
00082 #endif
00083 #ifndef STLSOFT_INCL_STLSOFT_META_HPP_IS_CHARACTER_TYPE
00084 # include <stlsoft/meta/is_character_type.hpp>
00085 #endif
00086 #ifndef STLSOFT_INCL_STLSOFT_META_HPP_IS_INTEGRAL_TYPE
00087 # include <stlsoft/meta/is_integral_type.hpp>
00088 #endif
00089 #ifndef STLSOFT_INCL_STLSOFT_META_HPP_IS_NUMERIC_TYPE
00090 # include <stlsoft/meta/is_numeric_type.hpp>
00091 #endif
00092 #ifndef STLSOFT_INCL_STLSOFT_UTIL_HPP_PRINTF_TRAITS
00093 # include <stlsoft/util/printf_traits.hpp>
00094 #endif
00095 #ifndef STLSOFT_INCL_STLSOFT_UTIL_HPP_STD_SWAP
00096 # include <stlsoft/util/std_swap.hpp>
00097 #endif
00098
00099 #ifndef STLSOFT_INCL_STDEXCEPT
00100 # define STLSOFT_INCL_STDEXCEPT
00101 # include <stdexcept>
00102 #endif
00103
00104 #ifndef STLSOFT_INCL_H_STDIO
00105 # define STLSOFT_INCL_H_STDIO
00106 # include <stdio.h>
00107 #endif
00108
00109
00110
00111
00112
00113 #ifndef RANGELIB_NO_NAMESPACE
00114 # if defined(_STLSOFT_NO_NAMESPACE) || \
00115 defined(STLSOFT_DOCUMENTATION_SKIP_SECTION)
00116
00117 namespace rangelib
00118 {
00119 # else
00120
00121
00122 namespace stlsoft
00123 {
00124
00125 namespace rangelib_project
00126 {
00127
00128 # endif
00129 #endif
00130
00131
00132
00133
00134
00139 struct invalid_integral_range_policy
00140 {
00141 public:
00143 typedef std::out_of_range thrown_type;
00144
00145 public:
00147 void operator ()(ss_sint32_t first, ss_sint32_t last, ss_sint32_t increment) const
00148 {
00149 static const char s_format[] = "Invalid integral range [%ld, %ld), %ld";
00150 char message[3 * 21 + STLSOFT_NUM_ELEMENTS(s_format)];
00151 const ss_size_t cch = static_cast<ss_size_t>(::sprintf(message, s_format, long(first), long(last), long(increment)));
00152
00153 STLSOFT_ASSERT(cch < STLSOFT_NUM_ELEMENTS(message));
00154 STLSOFT_SUPPRESS_UNUSED(cch);
00155
00156 throw thrown_type(message);
00157 }
00159 void operator ()(ss_uint32_t first, ss_uint32_t last, ss_uint32_t increment) const
00160 {
00161 static const char s_format[] = "Invalid integral range [%lu, %lu), %lu";
00162 char message[3 * 21 + STLSOFT_NUM_ELEMENTS(s_format)];
00163 const ss_size_t cch = static_cast<ss_size_t>(::sprintf(message, "Invalid integral range [%lu, %lu), %lu", ss_ulong_t(first), ss_ulong_t(last), ss_ulong_t(increment)));
00164
00165 STLSOFT_ASSERT(cch < STLSOFT_NUM_ELEMENTS(message));
00166 STLSOFT_SUPPRESS_UNUSED(cch);
00167 #if defined(STLSOFT_COMPILER_IS_COMO)
00168 STLSOFT_SUPPRESS_UNUSED(s_format);
00169 #endif
00170
00171 throw thrown_type(message);
00172 }
00173 #ifdef STLSOFT_CF_INT_DISTINCT_INT_TYPE
00175 void operator ()(int first, int last, int increment) const
00176 {
00177 operator ()(ss_sint32_t(first), ss_sint32_t(last), ss_sint32_t(increment));
00178 }
00180 void operator ()(unsigned int first, unsigned int last, unsigned int increment) const
00181 {
00182 operator ()(ss_uint32_t(first), ss_uint32_t(last), ss_uint32_t(increment));
00183 }
00184 #endif
00185
00186 #ifdef STLSOFT_CF_64BIT_INT_SUPPORT
00187 private:
00188 static char const* format_sint64()
00189 {
00190 return printf_traits<ss_sint64_t>::format_a();
00191 }
00192 static char const* format_uint64()
00193 {
00194 return printf_traits<ss_uint64_t>::format_a();
00195 }
00196
00197 public:
00199 void operator ()(ss_sint64_t first, ss_sint64_t last, ss_sint64_t increment) const
00200 {
00201 static const char s_fmtfmt[] = "Invalid integral range [%s, %s), %s";
00202 char format[3 * 4 + STLSOFT_NUM_ELEMENTS(s_fmtfmt)];
00203 char message[3 * 21 + STLSOFT_NUM_ELEMENTS(s_fmtfmt)];
00204 const ss_size_t cch1 = static_cast<ss_size_t>(::sprintf(format, s_fmtfmt, format_sint64(), format_sint64(), format_sint64()));
00205 const ss_size_t cch2 = static_cast<ss_size_t>(::sprintf(message, format, first, last, increment));
00206
00207 STLSOFT_ASSERT(cch1 < STLSOFT_NUM_ELEMENTS(format));
00208 STLSOFT_SUPPRESS_UNUSED(cch1);
00209 STLSOFT_ASSERT(cch2 < STLSOFT_NUM_ELEMENTS(message));
00210 STLSOFT_SUPPRESS_UNUSED(cch2);
00211
00212 throw thrown_type(message);
00213 }
00215 void operator ()(ss_uint64_t first, ss_uint64_t last, ss_uint64_t increment) const
00216 {
00217 static const char s_fmtfmt[] = "Invalid integral range [%s, %s), %s";
00218 char format[3 * 4 + STLSOFT_NUM_ELEMENTS(s_fmtfmt)];
00219 char message[3 * 21 + STLSOFT_NUM_ELEMENTS(s_fmtfmt)];
00220 const ss_size_t cch1 = static_cast<ss_size_t>(::sprintf(format, s_fmtfmt, format_uint64(), format_uint64(), format_uint64()));
00221 const ss_size_t cch2 = static_cast<ss_size_t>(::sprintf(message, format, first, last, increment));
00222
00223 STLSOFT_ASSERT(cch1 < STLSOFT_NUM_ELEMENTS(format));
00224 STLSOFT_SUPPRESS_UNUSED(cch1);
00225 STLSOFT_ASSERT(cch2 < STLSOFT_NUM_ELEMENTS(message));
00226 STLSOFT_SUPPRESS_UNUSED(cch2);
00227
00228 throw thrown_type(message);
00229 }
00230 #endif
00231 };
00232
00248 template< ss_typename_param_k T
00249 #ifdef STLSOFT_CF_EXCEPTION_SUPPORT
00250 , ss_typename_param_k XP = invalid_integral_range_policy
00251 #else
00252 , ss_typename_param_k XP = null_exception_policy
00253 #endif
00254 >
00255 class integral_range
00256 : public notional_range_tag
00257 {
00260 public:
00261 typedef T value_type;
00262 typedef T const& const_reference;
00263 typedef XP exception_policy_type;
00264 typedef notional_range_tag range_tag_type;
00265 typedef integral_range<T, XP> class_type;
00267
00270 public:
00272 integral_range(value_type first, value_type last, value_type increment = +1)
00273 : m_position(first)
00274 , m_last(last)
00275 , m_increment(increment)
00276 {
00277 if(m_last < m_position)
00278 {
00279
00280
00281 if(m_increment > 0)
00282 {
00283 m_increment = -m_increment;
00284 }
00285 }
00286
00287 validate_range(m_position, m_last, m_increment);
00288 }
00290 ~integral_range() stlsoft_throw_0()
00291 {
00292
00293
00294 STLSOFT_STATIC_ASSERT(0 != is_integral_type<value_type>::value);
00295 STLSOFT_STATIC_ASSERT(0 != is_numeric_type<value_type>::value || 0 != is_character_type<value_type>::value);
00296 }
00298
00301 private:
00302 STLSOFT_DEFINE_OPERATOR_BOOL_TYPES_T(class_type, operator_bool_generator_type, operator_bool_type);
00303 public:
00305 ss_bool_t is_open() const
00306 {
00307 return m_position != m_last;
00308 }
00310 const_reference current() const
00311 {
00312 STLSOFT_MESSAGE_ASSERT("Attempting to access the value of a closed range", is_open());
00313
00314 return m_position;
00315 }
00317 class_type& advance()
00318 {
00319 STLSOFT_MESSAGE_ASSERT("Attempting to advance a closed range", is_open());
00320 STLSOFT_MESSAGE_ASSERT("Attempting to increment the range past its end point", ((m_increment > 0 && m_position < m_last) || (m_increment < 0 && m_position > m_last)));
00321
00322 m_position += m_increment;
00323
00324 return *this;
00325 }
00326
00328 operator operator_bool_type() const
00329 {
00330 return operator_bool_generator_type::translate(is_open());
00331 }
00333 const_reference operator *() const
00334 {
00335 return current();
00336 }
00338 class_type& operator ++()
00339 {
00340 return advance();
00341 }
00344 class_type operator ++(int)
00345 {
00346 class_type ret(*this);
00347
00348 operator ++();
00349
00350 return ret;
00351 }
00353
00356 public:
00358 bool operator ==(class_type const& rhs) const
00359 {
00360 STLSOFT_MESSAGE_ASSERT("Comparing unrelated ranges!", m_last == rhs.m_last);
00361
00362 return m_position == rhs.m_position;
00363 }
00365 bool operator !=(class_type const& rhs) const
00366 {
00367 return ! operator ==(rhs);
00368 }
00370
00371
00372 private:
00373 static void validate_range(value_type first, value_type last, value_type increment)
00374 {
00375 ss_bool_t bValid = true;
00376
00377
00378 if(bValid)
00379 {
00380 if( first != last &&
00381 0 != increment)
00382 {
00383 bValid = (0 == ((last - first) % increment));
00384 }
00385 }
00386
00387
00388 if(bValid)
00389 {
00390 if( ( last < first &&
00391 increment > 0) ||
00392 ( first < last &&
00393 increment < 0))
00394 {
00395 bValid = false;
00396 }
00397 }
00398
00399
00400
00401
00402 if(!bValid)
00403 {
00404 exception_policy_type()(first, last, increment);
00405 }
00406
00407
00408 STLSOFT_MESSAGE_ASSERT("invalid integral range", bValid);
00409 }
00410
00411
00412 private:
00413 value_type m_position;
00414 value_type m_last;
00415 value_type m_increment;
00416 };
00417
00418
00419
00420
00421
00422 template <ss_typename_param_k T>
00423 inline integral_range<T> make_integral_range(T first, T last)
00424 {
00425 return integral_range<T>(first, last);
00426 }
00427
00428 template <ss_typename_param_k T>
00429 inline integral_range<T> make_integral_range(T first, T last, T increment)
00430 {
00431 return integral_range<T>(first, last, increment);
00432 }
00433
00435
00436
00437 #ifdef STLSOFT_UNITTEST
00438 # include "./unittest/integral_range_unittest_.h"
00439 #endif
00440
00441
00442
00443 #ifndef RANGELIB_NO_NAMESPACE
00444 # if defined(_STLSOFT_NO_NAMESPACE) || \
00445 defined(STLSOFT_DOCUMENTATION_SKIP_SECTION)
00446 }
00447 # else
00448 }
00449 }
00450 # endif
00451 #endif
00452
00453
00454
00455 #endif
00456
00457