Apply patch for [CVE-2012-2677][boost] ordered_malloc() overflow
[external/boost.git] / boost / gil / utilities.hpp
1 /*
2     Copyright 2005-2007 Adobe Systems Incorporated
3    
4     Use, modification and distribution are subject to the Boost Software License,
5     Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
6     http://www.boost.org/LICENSE_1_0.txt).
7
8     See http://opensource.adobe.com/gil for most recent version including documentation.
9 */
10
11 /*************************************************************************************************/
12
13 #ifndef GIL_UTILITIES_H
14 #define GIL_UTILITIES_H
15
16 #include "gil_config.hpp"
17 #include <functional>
18 #include <boost/config/no_tr1/cmath.hpp>
19 #include <cstddef>
20 #include <algorithm>
21 #include <utility>
22 #include <iterator>
23 #include <boost/static_assert.hpp>
24 #include <boost/type_traits.hpp>
25 #include <boost/mpl/size.hpp>
26 #include <boost/mpl/distance.hpp>
27 #include <boost/mpl/begin.hpp>
28 #include <boost/mpl/find.hpp>
29 #include <boost/mpl/range_c.hpp>
30 #include <boost/iterator/iterator_adaptor.hpp>
31 #include <boost/iterator/iterator_facade.hpp>
32
33 ////////////////////////////////////////////////////////////////////////////////////////
34 /// \file               
35 /// \brief  Various utilities not specific to the image library. Some are non-standard STL extensions or generic iterator adaptors
36 /// \author Lubomir Bourdev and Hailin Jin \n
37 ///         Adobe Systems Incorporated
38 /// \date   2005-2007 \n Last updated on September 18, 2007
39 ///
40 ///
41 ////////////////////////////////////////////////////////////////////////////////////////
42
43 namespace boost { namespace gil {
44
45 /**
46 \addtogroup PointModel
47
48 Example:
49 \code
50 point2<std::ptrdiff_t> p(3,2);
51 assert((p[0] == p.x) && (p[1] == p.y));
52 assert(axis_value<0>(p) == 3);
53 assert(axis_value<1>(p) == 2);
54 \endcode
55 */
56
57 ////////////////////////////////////////////////////////////////////////////////////////
58 //                           CLASS point2
59 ///
60 /// \brief 2D point both axes of which have the same dimension type
61 /// \ingroup PointModel
62 /// Models: Point2DConcept
63 ///
64 ////////////////////////////////////////////////////////////////////////////////////////
65
66 template <typename T>
67 class point2 {
68 public:
69     typedef T value_type;
70     template <std::size_t D> struct axis { typedef value_type coord_t; };
71     static const std::size_t num_dimensions=2;
72
73     point2()                : x(0),     y(0)    {}
74     point2(T newX, T newY)  : x(newX),  y(newY) {}
75     point2(const point2& p) : x(p.x), y(p.y) {}
76     ~point2() {}
77
78     point2& operator=(const point2& p)            { x=p.x; y=p.y; return *this; }
79
80     point2        operator<<(std::ptrdiff_t shift)         const   { return point2(x<<shift,y<<shift); }
81     point2        operator>>(std::ptrdiff_t shift)         const   { return point2(x>>shift,y>>shift); }
82     point2& operator+=(const point2& p)           { x+=p.x; y+=p.y; return *this; }
83     point2& operator-=(const point2& p)           { x-=p.x; y-=p.y; return *this; }
84     point2& operator/=(double t)                  { x/=t; y/=t; return *this; }
85
86     const T& operator[](std::size_t i)          const   { return this->*mem_array[i]; }
87           T& operator[](std::size_t i)                  { return this->*mem_array[i]; }
88
89     T x,y;
90 private:
91     // this static array of pointers to member variables makes operator[] safe and doesn't seem to exhibit any performance penalty
92     static T point2<T>::* const mem_array[num_dimensions];
93 };
94
95 template <typename T>
96 T point2<T>::* const point2<T>::mem_array[point2<T>::num_dimensions] = { &point2<T>::x, &point2<T>::y };
97
98 /// \ingroup PointModel
99 template <typename T> GIL_FORCEINLINE
100 bool operator==(const point2<T>& p1, const point2<T>& p2) { return (p1.x==p2.x && p1.y==p2.y); }
101 /// \ingroup PointModel
102 template <typename T> GIL_FORCEINLINE
103 bool operator!=(const point2<T>& p1, const point2<T>& p2) { return  p1.x!=p2.x || p1.y!=p2.y; }
104 /// \ingroup PointModel
105 template <typename T> GIL_FORCEINLINE
106 point2<T> operator+(const point2<T>& p1, const point2<T>& p2) { return point2<T>(p1.x+p2.x,p1.y+p2.y); }
107 /// \ingroup PointModel
108 template <typename T> GIL_FORCEINLINE
109 point2<T> operator-(const point2<T>& p) { return point2<T>(-p.x,-p.y); }
110 /// \ingroup PointModel
111 template <typename T> GIL_FORCEINLINE
112 point2<T> operator-(const point2<T>& p1, const point2<T>& p2) { return point2<T>(p1.x-p2.x,p1.y-p2.y); }
113 /// \ingroup PointModel
114 template <typename T> GIL_FORCEINLINE
115 point2<double> operator/(const point2<T>& p, double t)      { return t==0 ? point2<double>(0,0):point2<double>(p.x/t,p.y/t); }
116 /// \ingroup PointModel
117 template <typename T> GIL_FORCEINLINE
118 point2<T> operator*(const point2<T>& p, std::ptrdiff_t t)      { return point2<T>(p.x*t,p.y*t); }
119 /// \ingroup PointModel
120 template <typename T> GIL_FORCEINLINE
121 point2<T> operator*(std::ptrdiff_t t, const point2<T>& p)      { return point2<T>(p.x*t,p.y*t); }
122
123 /// \ingroup PointModel
124 template <std::size_t K, typename T> GIL_FORCEINLINE
125 const T& axis_value(const point2<T>& p) { return p[K]; }
126
127 /// \ingroup PointModel
128 template <std::size_t K, typename T> GIL_FORCEINLINE
129       T& axis_value(      point2<T>& p) { return p[K]; }
130
131 ////////////////////////////////////////////////////////////////////////////////////////
132 ///
133 ///  Rounding of real numbers / points to integers / integer points
134 ///
135 ////////////////////////////////////////////////////////////////////////////////////////
136
137 inline std::ptrdiff_t iround(float x ) { return static_cast<std::ptrdiff_t>(x + (x < 0.0f ? -0.5f : 0.5f)); }
138 inline std::ptrdiff_t iround(double x) { return static_cast<std::ptrdiff_t>(x + (x < 0.0 ? -0.5 : 0.5)); }
139 inline std::ptrdiff_t ifloor(float x ) { return static_cast<std::ptrdiff_t>(std::floor(x)); }
140 inline std::ptrdiff_t ifloor(double x) { return static_cast<std::ptrdiff_t>(std::floor(x)); }
141 inline std::ptrdiff_t iceil(float x )  { return static_cast<std::ptrdiff_t>(std::ceil(x)); }
142 inline std::ptrdiff_t iceil(double x)  { return static_cast<std::ptrdiff_t>(std::ceil(x)); }
143
144 /**
145 \addtogroup PointAlgorithm
146
147 Example:
148 \code
149 assert(iround(point2<double>(3.1, 3.9)) == point2<std::ptrdiff_t>(3,4));
150 \endcode
151 */
152
153 /// \ingroup PointAlgorithm
154 inline point2<std::ptrdiff_t> iround(const point2<float >& p)  { return point2<std::ptrdiff_t>(iround(p.x),iround(p.y)); }
155 /// \ingroup PointAlgorithm
156 inline point2<std::ptrdiff_t> iround(const point2<double>& p)  { return point2<std::ptrdiff_t>(iround(p.x),iround(p.y)); }
157 /// \ingroup PointAlgorithm
158 inline point2<std::ptrdiff_t> ifloor(const point2<float >& p)  { return point2<std::ptrdiff_t>(ifloor(p.x),ifloor(p.y)); }
159 /// \ingroup PointAlgorithm
160 inline point2<std::ptrdiff_t> ifloor(const point2<double>& p)  { return point2<std::ptrdiff_t>(ifloor(p.x),ifloor(p.y)); }
161 /// \ingroup PointAlgorithm
162 inline point2<std::ptrdiff_t> iceil (const point2<float >& p)  { return point2<std::ptrdiff_t>(iceil(p.x), iceil(p.y)); }
163 /// \ingroup PointAlgorithm
164 inline point2<std::ptrdiff_t> iceil (const point2<double>& p)  { return point2<std::ptrdiff_t>(iceil(p.x), iceil(p.y)); }
165
166 ////////////////////////////////////////////////////////////////////////////////////////
167 ///
168 ///  computing size with alignment
169 ///
170 ////////////////////////////////////////////////////////////////////////////////////////
171
172 template <typename T> 
173 inline T align(T val, std::size_t alignment) { 
174     return val+(alignment - val%alignment)%alignment; 
175 }
176
177 /// \brief Helper base class for pixel dereference adaptors. 
178 /// \ingroup PixelDereferenceAdaptorModel
179 ///
180 template <typename ConstT, typename Value, typename Reference, typename ConstReference,
181           typename ArgType, typename ResultType, bool IsMutable>
182 struct deref_base : public std::unary_function<ArgType, ResultType> {
183     typedef ConstT         const_t;
184     typedef Value          value_type;
185     typedef Reference      reference;
186     typedef ConstReference const_reference;
187     BOOST_STATIC_CONSTANT(bool, is_mutable = IsMutable);
188 };
189
190 /// \brief Composes two dereference function objects. Similar to std::unary_compose but needs to pull some typedefs from the component types.  Models: PixelDereferenceAdaptorConcept
191 /// \ingroup PixelDereferenceAdaptorModel
192 ///
193 template <typename D1, typename D2>
194 class deref_compose : public deref_base<
195       deref_compose<typename D1::const_t, typename D2::const_t>,
196       typename D1::value_type, typename D1::reference, typename D1::const_reference, 
197       typename D2::argument_type, typename D1::result_type, D1::is_mutable && D2::is_mutable>
198 {
199 public:
200     D1 _fn1;
201     D2 _fn2;
202
203     typedef typename D2::argument_type   argument_type;
204     typedef typename D1::result_type     result_type;
205
206     deref_compose() {}
207     deref_compose(const D1& x, const D2& y) : _fn1(x), _fn2(y) {}
208     deref_compose(const deref_compose& dc)  : _fn1(dc._fn1), _fn2(dc._fn2) {}
209     template <typename _D1, typename _D2> deref_compose(const deref_compose<_D1,_D2>& dc) : _fn1(dc._fn1), _fn2(dc._fn2) {}
210
211     result_type operator()(argument_type x) const { return _fn1(_fn2(x)); }
212     result_type operator()(argument_type x)       { return _fn1(_fn2(x)); }
213 };
214
215 // reinterpret_cast is implementation-defined. Static cast is not.
216 template <typename OutPtr, typename In> GIL_FORCEINLINE
217       OutPtr gil_reinterpret_cast(      In* p) { return static_cast<OutPtr>(static_cast<void*>(p)); }
218
219 template <typename OutPtr, typename In> GIL_FORCEINLINE
220 const OutPtr gil_reinterpret_cast_c(const In* p) { return static_cast<const OutPtr>(static_cast<const void*>(p)); }
221
222 namespace detail {
223
224 ////////////////////////////////////////////////////////////////////////////////////////
225 ///
226 ///  \brief copy_n taken from SGI STL.
227 ///
228 ////////////////////////////////////////////////////////////////////////////////////////
229
230 template <class InputIter, class Size, class OutputIter>
231 std::pair<InputIter, OutputIter> _copy_n(InputIter first, Size count,
232                                          OutputIter result,
233                                          std::input_iterator_tag) {
234    for ( ; count > 0; --count) {
235       *result = *first;
236       ++first;
237       ++result;
238    }
239    return std::pair<InputIter, OutputIter>(first, result);
240 }
241
242 template <class RAIter, class Size, class OutputIter>
243 inline std::pair<RAIter, OutputIter>
244 _copy_n(RAIter first, Size count, OutputIter result, std::random_access_iterator_tag) {
245    RAIter last = first + count;
246    return std::pair<RAIter, OutputIter>(last, std::copy(first, last, result));
247 }
248
249 template <class InputIter, class Size, class OutputIter>
250 inline std::pair<InputIter, OutputIter>
251 _copy_n(InputIter first, Size count, OutputIter result) {
252    return _copy_n(first, count, result, typename std::iterator_traits<InputIter>::iterator_category());
253 }
254
255 template <class InputIter, class Size, class OutputIter>
256 inline std::pair<InputIter, OutputIter>
257 copy_n(InputIter first, Size count, OutputIter result) {
258     return detail::_copy_n(first, count, result);
259 }
260
261 /// \brief identity taken from SGI STL.
262 template <typename T> 
263 struct identity : public std::unary_function<T,T> {
264     const T& operator()(const T& val) const { return val; }
265 };
266
267 /*************************************************************************************************/
268
269 /// \brief plus function object whose arguments may be of different type.
270 template <typename T1, typename T2>
271 struct plus_asymmetric : public std::binary_function<T1,T2,T1> {
272     T1 operator()(T1 f1, T2 f2) const {
273         return f1+f2;
274     }
275 };
276
277 /*************************************************************************************************/
278
279 /// \brief operator++ wrapped in a function object
280 template <typename T>
281 struct inc : public std::unary_function<T,T> {
282     T operator()(T x) const { return ++x; }
283 };
284
285 /*************************************************************************************************/
286
287 /// \brief operator-- wrapped in a function object
288 template <typename T>
289 struct dec : public std::unary_function<T,T> {
290     T operator()(T x) const { return --x; }
291 };
292
293 /// \brief Returns the index corresponding to the first occurrance of a given given type in 
294 //         a given MPL RandomAccessSequence (or size if the type is not present)
295 template <typename Types, typename T>
296 struct type_to_index 
297     : public mpl::distance<typename mpl::begin<Types>::type, 
298                                   typename mpl::find<Types,T>::type>::type {};
299 } // namespace detail
300
301
302
303 /// \ingroup ColorSpaceAndLayoutModel
304 /// \brief Represents a color space and ordering of channels in memory
305 template <typename ColorSpace, typename ChannelMapping = mpl::range_c<int,0,mpl::size<ColorSpace>::value> >
306 struct layout {
307     typedef ColorSpace      color_space_t;
308     typedef ChannelMapping  channel_mapping_t;
309 };
310
311 /// \brief A version of swap that also works with reference proxy objects
312 template <typename Value, typename T1, typename T2> // where value_type<T1>  == value_type<T2> == Value
313 void swap_proxy(T1& left, T2& right) {
314     Value tmp = left;
315     left = right;
316     right = tmp;
317 }
318
319 /// \brief Run-time detection of whether the underlying architecture is little endian
320 inline bool little_endian() {
321     short tester = 0x0001;
322     return  *(char*)&tester!=0;
323 }
324 /// \brief Run-time detection of whether the underlying architecture is big endian
325 inline bool big_endian() {
326     return !little_endian();
327 }
328
329 } }  // namespace boost::gil
330
331 #endif