ome-xml  5.2.0
ConstrainedNumeric.h
1 /*
2  * #%L
3  * OME-XML C++ library for working with OME-XML metadata structures.
4  * %%
5  * Copyright © 2006 - 2016 Open Microscopy Environment:
6  * - Massachusetts Institute of Technology
7  * - National Institutes of Health
8  * - University of Dundee
9  * - Board of Regents of the University of Wisconsin-Madison
10  * - Glencoe Software, Inc.
11  * %%
12  * Redistribution and use in source and binary forms, with or without
13  * modification, are permitted provided that the following conditions are met:
14  *
15  * 1. Redistributions of source code must retain the above copyright notice,
16  * this list of conditions and the following disclaimer.
17  * 2. Redistributions in binary form must reproduce the above copyright notice,
18  * this list of conditions and the following disclaimer in the documentation
19  * and/or other materials provided with the distribution.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
25  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31  * POSSIBILITY OF SUCH DAMAGE.
32  *
33  * The views and conclusions contained in the software and documentation are
34  * those of the authors and should not be interpreted as representing official
35  * policies, either expressed or implied, of any organization.
36  * #L%
37  */
38 
39 #ifndef OME_XML_MODEL_PRIMITIVES_CONSTRAINEDNUMERIC_H
40 #define OME_XML_MODEL_PRIMITIVES_CONSTRAINEDNUMERIC_H
41 
42 #include <limits>
43 #include <string>
44 #include <sstream>
45 
46 #include <boost/format.hpp>
47 #include <boost/operators.hpp>
48 
49 #include <ome/compat/cstdint.h>
50 
51 namespace ome
52 {
53  namespace xml
54  {
55  namespace model
56  {
60  namespace primitives
61  {
62 
68  {
76  template<typename T>
77  inline void
78  operator() (const T& value,
79  const std::string& typestr)
80  {
81  boost::format fmt("‘%1%’ not a supported value of %2%");
82  fmt % value % typestr;
83  throw std::invalid_argument(fmt.str());
84  }
85  };
86 
116  template<typename N,
117  typename C,
118  typename E = ConstrainedNumericError>
119  class ConstrainedNumeric : private boost::partially_ordered<ConstrainedNumeric<N, C, E>, N,
120  boost::partially_ordered<ConstrainedNumeric<N, C, E>,
121  boost::equality_comparable2<ConstrainedNumeric<N, C, E>, N,
122  boost::equality_comparable<ConstrainedNumeric<N, C, E>,
123  boost::addable2<ConstrainedNumeric<N, C, E>, N,
124  boost::addable<ConstrainedNumeric<N, C, E>,
125  boost::subtractable2<ConstrainedNumeric<N, C, E>, N,
126  boost::subtractable<ConstrainedNumeric<N, C, E>,
127  boost::dividable2<ConstrainedNumeric<N, C, E>, N,
128  boost::dividable<ConstrainedNumeric<N, C, E>,
129  boost::multipliable2<ConstrainedNumeric<N, C, E>, N,
130  boost::multipliable<ConstrainedNumeric<N, C, E>,
131  boost::incrementable<ConstrainedNumeric<N, C, E>,
132  boost::decrementable<ConstrainedNumeric<N, C, E> > > > > > > > > > > > > > >
133  {
134  public:
136  typedef N value_type;
138  typedef C constraint_type;
140  typedef E error_policy_type;
141 
143  static const value_type default_value;
144 
155  value(default_value)
156  {
157  check();
158  }
159 
167  ConstrainedNumeric(value_type value):
168  value(value)
169  {
170  check();
171  }
172 
180  ConstrainedNumeric(const std::string& value)
181  {
182  std::istringstream is(value);
183  is.imbue(std::locale::classic());
184  value_type nval;
185  is >> nval;
186  if (!is)
187  {
188  error_policy_type error;
189  error(value, this->typestr);
190  }
191  this->value = nval;
192  check();
193  }
194 
201  value(value)
202  {
203  check();
204  }
205 
211  inline
212  operator value_type () const
213  {
214  return this->value;
215  }
216 
226  inline ConstrainedNumeric&
227  operator= (const ConstrainedNumeric& value)
228  {
229  this->value = value.value;
230  check();
231  return *this;
232  }
233 
242  inline ConstrainedNumeric&
243  operator= (const value_type& value)
244  {
245  this->value = value;
246  check();
247  return *this;
248  }
249 
258  inline ConstrainedNumeric&
259  operator+= (const ConstrainedNumeric& value)
260  {
261  this->value += value.value;
262  check();
263  return *this;
264  }
265 
274  inline ConstrainedNumeric&
275  operator-= (const ConstrainedNumeric& value)
276  {
277  this->value -= value.value;
278  check();
279  return *this;
280  }
281 
290  inline ConstrainedNumeric&
291  operator*= (const ConstrainedNumeric& value)
292  {
293  this->value *= value.value;
294  check();
295  return *this;
296  }
297 
306  inline ConstrainedNumeric&
307  operator/= (const ConstrainedNumeric& value)
308  {
309  this->value /= value.value;
310  check();
311  return *this;
312  }
313 
322  inline ConstrainedNumeric&
323  operator%= (const ConstrainedNumeric& value)
324  {
325  this->value %= value.value;
326  check();
327  return *this;
328  }
329 
338  inline ConstrainedNumeric&
339  operator+= (const value_type& value)
340  {
341  this->value += value;
342  check();
343  return *this;
344  }
345 
354  inline ConstrainedNumeric&
355  operator-= (const value_type& value)
356  {
357  this->value -= value;
358  check();
359  return *this;
360  }
361 
370  inline ConstrainedNumeric&
371  operator*= (const value_type& value)
372  {
373  this->value *= value;
374  check();
375  return *this;
376  }
377 
386  inline ConstrainedNumeric&
387  operator/= (const value_type& value)
388  {
389  this->value /= value;
390  check();
391  return *this;
392  }
393 
402  inline ConstrainedNumeric&
403  operator%= (const value_type& value)
404  {
405  this->value %= value;
406  check();
407  return *this;
408  }
409 
416  inline ConstrainedNumeric&
417  operator++ ()
418  {
419  ++this->value;
420  check();
421  return *this;
422  }
423 
430  inline ConstrainedNumeric&
431  operator-- ()
432  {
433  --this->value;
434  check();
435  return *this;
436  }
437 
445  inline bool
446  operator< (const ConstrainedNumeric& value) const
447  {
448  return this->value < value.value;
449  }
450 
458  inline bool
459  operator< (const value_type& value) const
460  {
461  return this->value < value;
462  }
463 
464  // Note operator> (const ConstrainedNumeric& value) const is
465  // provided by Boost.Operators.
466 
474  inline bool
475  operator> (const value_type& value) const
476  {
477  return this->value > value;
478  }
479 
487  inline bool
488  operator== (const ConstrainedNumeric& value) const
489  {
490  return this->value == value.value;
491  }
492 
500  inline bool
501  operator== (const value_type& value) const
502  {
503  return this->value == value;
504  }
505 
506  private:
513  inline void
514  check ()
515  {
516  constraint_type constraint;
517  if (!constraint(this->value))
518  {
519  error_policy_type error;
520  error(this->value, this->typestr);
521  }
522  }
523 
525  value_type value;
527  static const std::string typestr;
528 
536  template<class _charT,
537  class _traits,
538  typename _N,
539  typename _C,
540  typename _E>
541  friend
542  std::basic_istream<_charT,_traits>&
543  operator>> (std::basic_istream<_charT,_traits>& is,
545  };
546 
554  template<class charT,
555  class traits,
556  typename N,
557  typename C,
558  typename E>
559  inline std::basic_istream<charT,traits>&
560  operator>> (std::basic_istream<charT,traits>& is,
562  {
564  is >> nval;
565  if (!is)
566  {
567  boost::format fmt("Failed to parse invalid input for %1%");
569  throw std::invalid_argument(fmt.str());
570  }
571 
572  value = nval;
573 
574  return is;
575  }
576 
584  template<class charT,
585  class traits,
586  typename N,
587  typename C,
588  typename E>
589  inline std::basic_ostream<charT,traits>&
590  operator<< (std::basic_ostream<charT,traits>& os,
591  const ConstrainedNumeric<N, C, E>& value)
592  {
593  return os << static_cast<typename ConstrainedNumeric<N, C, E>::value_type>(value);
594  }
595 
596  }
597  }
598  }
599 }
600 
601 #endif // OME_XML_MODEL_PRIMITIVES_CONSTRAINEDNUMERIC_H
602 
603 /*
604  * Local Variables:
605  * mode:C++
606  * End:
607  */
C constraint_type
The constraint to impose.
Definition: ConstrainedNumeric.h:138
value_type value
The value being constrained.
Definition: ConstrainedNumeric.h:525
ConstrainedNumeric(const ConstrainedNumeric &value)
Copy constructor.
Definition: ConstrainedNumeric.h:200
static const value_type default_value
Default value for default construction.
Definition: ConstrainedNumeric.h:143
Open Microscopy Environment C++ implementation.
E error_policy_type
The error policy to apply on constraint violation.
Definition: ConstrainedNumeric.h:140
bool operator==(const Color &lhs, const Color &rhs)
Compare two Color objects for equality.
Definition: Color.h:316
ConstrainedNumeric(value_type value)
Construct a ConstrainedNumeric from an unconstrained value.
Definition: ConstrainedNumeric.h:167
void check()
Check that the set value meets the required constraints, and if it does not, handle this according to...
Definition: ConstrainedNumeric.h:514
static const std::string typestr
The name of the type. Used for diagnostics only.
Definition: ConstrainedNumeric.h:527
Default error handler for ConstrainedNumeric.
Definition: ConstrainedNumeric.h:67
void operator()(const T &value, const std::string &typestr)
Throw an exception.
Definition: ConstrainedNumeric.h:78
std::basic_istream< charT, traits > & operator>>(std::basic_istream< charT, traits > &is, Color &color)
Set Color from input stream.
Definition: Color.h:472
N value_type
The type to constrain.
Definition: ConstrainedNumeric.h:136
ConstrainedNumeric()
Construct a ConstrainedNumeric.
Definition: ConstrainedNumeric.h:154
ConstrainedNumeric(const std::string &value)
Construct a ConstrainedNumeric a string value.
Definition: ConstrainedNumeric.h:180
A numeric type constrained to a subrange (or subranges) of its range limits.
Definition: ConstrainedNumeric.h:119