libutil++  1.9.3
 All Classes Functions Variables
Interval.cpp
1 /*
2 ** libutil++
3 ** $Id: Interval.cpp 1911 2017-09-02 17:37:35Z sella $
4 ** Copyright (c) 2011-2016 Digital Genesis, LLC. All Rights Reserved.
5 ** Released under the LGPL Version 2.1 License.
6 ** http://www.digitalgenesis.com
7 */
8 
9 static const char rcsid[] __attribute__((used)) = "$Id: Interval.cpp 1911 2017-09-02 17:37:35Z sella $";
10 
11 #include "Interval.h"
12 #include "../util/CommonMacro.h"
13 
14 using namespace sella::variant;
15 
16 Interval::Interval() throw () : Nullable(std::make_shared<uint64_t>(0)) { }
17 
18 Interval::Interval(const std::string &value) throw (TypeCastException) : Nullable() {
19  boost::smatch matcher;
20 
21  if (boost::regex_match(value, matcher, Interval::Pattern())) {
22  int64_t usec;
23 
24  try {
25  usec = std::stoll(matcher[1].str().c_str());
26  } catch (std::invalid_argument &e) {
27  THROW(TypeCastException, "unable to cast '%s' to an interval value (invalid string)", value.c_str());
28  } catch (std::out_of_range &e) {
29  THROW(TypeCastException, "unable to cast '%s' to an interval value (overflow/underflow)", value.c_str());
30  }
31 
32  switch (matcher[2].str().c_str()[0]) {
33  case 'd':
34  usec *= 86400000000LL;
35  break;
36 
37  case 'h':
38  usec *= 3600000000LL;
39  break;
40 
41  case 'm':
42  usec *= 60000000LL;
43  break;
44 
45  case 's':
46  usec *= 1000000LL;
47  break;
48 
49  case 'u':
50  break;
51 
52  default:
53  THROW(TypeCastException, "unable to cast '%s' to an interval value", value.c_str());
54  }
55 
56  this->value = std::make_shared<uint64_t>(usec);
57  } else {
58  THROW(TypeCastException, "unable to cast '%s' to an interval value", value.c_str());
59  }
60 }
61 
62 Interval::Interval(int64_t value) throw () : Nullable(std::make_shared<int64_t>(value)) { }
63 
64 Interval::Interval(const Interval &other) throw () : Nullable() {
65  if (this != &other) {
66  if (!other.isNull()) {
67  if (isNull()) {
68  this->value = std::make_shared<int64_t>(other.getUsec());
69  } else {
70  *std::static_pointer_cast<int64_t>(this->value) = *std::static_pointer_cast<int64_t>(other.value);
71  }
72  } else {
73  this->value.reset();
74  }
75  }
76 }
77 
78 Interval::~Interval() throw () { }
79 
80 bool Interval::operator==(const Interval &other) const throw () {
81  return (*std::static_pointer_cast<int64_t>(this->value) == *std::static_pointer_cast<int64_t>(other.value));
82 }
83 
84 bool Interval::operator!=(const Interval &other) const throw () {
85  return !(*this == other);
86 }
87 
88 bool Interval::operator>(const Interval &other) const throw () {
89  return (*std::static_pointer_cast<int64_t>(this->value) > *std::static_pointer_cast<int64_t>(other.value));
90 }
91 
92 bool Interval::operator<(const Interval &other) const throw () {
93  return (*std::static_pointer_cast<int64_t>(this->value) < *std::static_pointer_cast<int64_t>(other.value));
94 }
95 
96 Interval& Interval::operator=(const Interval &other) throw () {
97  if (this != &other) {
98  if (!other.isNull()) {
99  if (isNull()) {
100  this->value = std::make_shared<int64_t>(other.getUsec());
101  } else {
102  *std::static_pointer_cast<int64_t>(this->value) = *std::static_pointer_cast<int64_t>(other.value);
103  }
104  } else {
105  this->value.reset();
106  }
107  }
108 
109  return *this;
110 }
111 
112 Interval& Interval::operator+=(int64_t value) throw () {
113  (*std::static_pointer_cast<int64_t>(this->value)) += value;
114 
115  return *this;
116 }
117 
118 Interval& Interval::operator-=(int64_t value) throw () {
119  (*std::static_pointer_cast<int64_t>(this->value)) -= value;
120 
121  return *this;
122 }
123 
124 Interval& Interval::operator*=(int64_t value) throw () {
125  (*std::static_pointer_cast<int64_t>(this->value)) *= value;
126 
127  return *this;
128 }
129 
130 Interval& Interval::operator/=(int64_t value) throw () {
131  (*std::static_pointer_cast<int64_t>(this->value)) /= value;
132 
133  return *this;
134 }
135 
136 Interval& Interval::operator^=(int64_t value) throw () {
137  (*std::static_pointer_cast<int64_t>(this->value)) = pow((*std::static_pointer_cast<int64_t>(this->value)), value);
138 
139  return *this;
140 }
141 
142 Interval& Interval::operator%=(int64_t value) throw () {
143  (*std::static_pointer_cast<int64_t>(this->value)) %= value;
144 
145  return *this;
146 }
147 
148 Interval& Interval::operator&=(int64_t value) throw () {
149  (*std::static_pointer_cast<int64_t>(this->value)) &= value;
150 
151  return *this;
152 }
153 
154 Interval& Interval::operator|=(int64_t value) throw () {
155  (*std::static_pointer_cast<int64_t>(this->value)) |= value;
156 
157  return *this;
158 }
159 
160 int64_t Interval::getUsec() const throw (UnsupportedOperatorException) {
161  if (isNull()) {
162  THROW(UnsupportedOperatorException, "unable to take reference of null value");
163  }
164 
165  return *std::static_pointer_cast<int64_t>(this->value);
166 }
167 
168 void Interval::msgpack(sella::util::MessagePack &mpack, uint32_t &offset) const throw (TypeCastException) {
169  uint32_t c;
170 
171  if (UNLIKELY(this->isNull())) {
172  c = mpack.append(offset);
173  } else {
174  c = mpack.append(offset, this->str(JSON));
175  }
176 
177  offset += c;
178 
179  if (UNLIKELY(c == 0)) {
180  THROW(TypeCastException, "Failed to append '%s' at offset %d (buffer length: %d)", str(JSON).c_str(), offset, mpack.length());
181  }
182 }
183 
184 void Interval::msgpackBufferSize(size_t &size) const throw () {
185  if (UNLIKELY(isNull())) {
186  size += 1;
187 
188  return;
189  }
190 
191  size += 9;
192 }
193 
194 std::string Interval::str(int type) const throw () {
195  if (UNLIKELY(this->isNull())) {
196  return "null";
197  }
198 
199  char buffer[4096];
200  int64_t usec = this->getUsec();
201 
202  if ((usec % 3600000000LL) == 0) {
203  snprintf(buffer, sizeof(buffer), "%lldh", usec % 3600000000LL);
204  } else if ((usec % 60000000LL) == 0) {
205  snprintf(buffer, sizeof(buffer), "%lldm", usec % 60000000LL);
206  } else if ((usec % 1000000LL) == 0) {
207  snprintf(buffer, sizeof(buffer), "%llds", usec % 1000000LL);
208  } else {
209  snprintf(buffer, sizeof(buffer), "%" PRId64 "u", usec);
210  }
211 
212  return buffer;
213 }
214 
215 bool Interval::isType(const char *value, size_t size) throw () {
216  return (size > 1 && (value[size - 1] == 'd' || value[size - 1] == 'h' || value[size - 1] == 'm' || value[size - 1] == 's' || value[size - 1] == 'u') && boost::regex_match(std::string(value, size), Pattern()));
217 }
218 
219 /*
220 ** vim: noet ts=3 sw=3
221 */