libUTL++
Integer.h
1 #pragma once
2 
4 
5 #include <libutl/Number.h>
6 
8 
9 UTL_NS_BEGIN;
10 
12 
20 
22 template <class T>
23 class Integer : public Number<T>
24 {
27 
28 public:
33  Integer(T i)
34  : Number<T>(i)
35  {
36  }
37 
38  virtual size_t hash(size_t size) const;
39 
42  mod(const Integer<T>& rhs) const
43  {
44  return Integer<T>(this->_n % rhs._n);
45  }
46 
48  bool
49  isDivisibleBy(T num) const
50  {
51  return utl::isDivisibleBy(this->_n, num);
52  }
53 
58  inline Integer<T>
59  nextMultiple(T target) const
60  {
61  return Integer<T>(utl::nextMultiple(this->_n, target));
62  }
63 
64  void
65  set(T n)
66  {
67  super::set(n);
68  }
69 
71  virtual Number<T>& set(const String& str);
72 
74  Integer<T>& setBinary(const String& str);
75 
77  Integer<T>& setHex(const String& str);
78 
84  String toBinary(uint_t numDigits = 0) const;
85 
91  String toOctal(uint_t numDigits = 0) const;
92 
98  String toDecimal(uint_t numDigits = 0) const;
99 
105  String toHex(uint_t numDigits = 0) const;
106 };
107 
109 
110 template <class T>
111 size_t
112 Integer<T>::hash(size_t size) const
113 {
114  return (size_t)(this->_n % size);
115 }
116 
118 
119 template <class T>
120 Number<T>&
122 {
123  char c = str[0];
124  if (!isdigit(c) && (c != '-') && (c != '+')) goto fail;
125  if (std::is_signed<T>())
126  {
127  this->_n = strtol(str, nullptr, 0);
128  }
129  else
130  {
131  this->_n = strtoul(str, nullptr, 0);
132  }
133  if (errno == EINVAL) goto fail;
134  return self;
135 fail:
136  this->_n = 0;
137  throw IllegalValueEx(str);
138 }
139 
141 
142 template <class T>
143 Integer<T>&
145 {
146  if (!isdigit(str[0])) goto fail;
147  if (std::is_signed<T>())
148  {
149  this->_n = strtol(str, nullptr, 2);
150  }
151  else
152  {
153  this->_n = strtoul(str, nullptr, 2);
154  }
155  if (errno == EINVAL) goto fail;
156  return self;
157 fail:
158  this->_n = 0;
159  throw IllegalValueEx(str);
160  return self;
161 }
162 
164 
165 template <class T>
166 Integer<T>&
168 {
169  if (!isxdigit(str[0])) goto fail;
170  if (std::is_signed<T>())
171  {
172  this->_n = strtol(str, nullptr, 16);
173  }
174  else
175  {
176  this->_n = strtoul(str, nullptr, 16);
177  }
178  if (errno == EINVAL) goto fail;
179  return self;
180 fail:
181  this->_n = 0;
182  throw IllegalValueEx(str);
183  return self;
184 }
185 
187 
188 template <class T>
189 String
190 Integer<T>::toBinary(uint_t numDigits) const
191 {
192  uint64_t n = (this->_n < 0) ? -1 * this->_n : this->_n;
193  if (numDigits == 0)
194  {
195  numDigits = 64;
196  while (((n & (1ULL << (numDigits - 1))) == 0) && (numDigits > 1))
197  {
198  --numDigits;
199  }
200  }
201 
202  char* res = new char[numDigits + 2];
203  char* resChar = res;
204  if (this->_n < 0)
205  {
206  *(resChar++) = '-';
207  }
208  uint64_t mask = ((uint64_t)1 << (numDigits - 1));
209  while (mask != 0)
210  {
211  if ((n & mask) == 0)
212  {
213  *resChar++ = '1';
214  }
215  else
216  {
217  *resChar++ = '0';
218  }
219  mask >>= 1;
220  }
221  *resChar = '\0';
222  ASSERTD((resChar + 1 - res) <= (numDigits + 2));
223  return String(res, true, false);
224 }
225 
227 
228 template <class T>
229 String
231 {
232  if (numDigits == 0) return this->toString();
233  String fmt = "%0*";
234  fmt += Printf<T>::formatType;
235  char buf[64];
236  sprintf(buf, fmt, (int)numDigits, this->_n);
237  return buf;
238 }
239 
241 
242 template <class T>
243 String
244 Integer<T>::toOctal(uint_t numDigits) const
245 {
246  String fmt = "%";
247  if (numDigits == 0)
248  {
250  fmt += 'o';
251  return this->toString(fmt);
252  }
253  fmt += "0*";
255  fmt += 'o';
256  char buf[64];
257  sprintf(buf, fmt, (int)numDigits, this->_n);
258  return buf;
259 }
260 
262 
263 template <class T>
264 String
265 Integer<T>::toHex(uint_t numDigits) const
266 {
267  String fmt = "%";
268  if (numDigits == 0)
269  {
271  fmt += 'x';
272  return this->toString(fmt);
273  }
274  fmt += "0*";
276  fmt += 'x';
277  char buf[64];
278  sprintf(buf, fmt, (int)numDigits, this->_n);
279  return buf;
280 }
281 
283 
284 UTL_NS_END;
285 
287 
#define UTL_CLASS_IMPL_TPL(className, T)
Implementation of standard UTL++ functionality for a template class.
Definition: macros.h:906
#define UTL_CLASS_DEFID
Default init() and deInit() (which are merely place-holders).
Definition: macros.h:532
Integer(T i)
Constructor.
Definition: Integer.h:33
String toString(const FwdIt &begin, const FwdIt &end, const String &sep, bool key=false)
Obtain a string representation of a sequence (via Object::toString()).
Numeric value.
Definition: Number.h:23
Character string.
Definition: String.h:31
Integer value.
Definition: Integer.h:23
bool isDivisibleBy(const T &x, const T &n)
Determine whether x is evenly divisible by n.
Definition: util_inl.h:711
unsigned long uint64_t
Unsigned 64-bit integer.
Definition: types.h:154
bool isDivisibleBy(T num) const
Determine whether self is divisible by the given number.
Definition: Integer.h:49
unsigned int uint_t
Unsigned integer.
Definition: types.h:59
Illegal value exception.
Definition: Exception.h:334
Provide printf formatting strings for common types.
Definition: types.h:435
#define UTL_CLASS_DECL_TPL(DC, T, BC)
Declaration of standard UTL++ functionality for a template class with one parameter.
Definition: macros.h:713
Integer< T > mod(const Integer< T > &rhs) const
Get the result of self modulo rhs.
Definition: Integer.h:42
Integer< T > nextMultiple(T target) const
Determine the smallest number n, s.t.
Definition: Integer.h:59
#define ASSERTD
Do an assertion in DEBUG mode only.
T nextMultiple(const T &x, const T &target)
Return the smallest number n s.t.
Definition: util_inl.h:142