Panda3D
dcNumericRange.I
Go to the documentation of this file.
1 /**
2  * PANDA 3D SOFTWARE
3  * Copyright (c) Carnegie Mellon University. All rights reserved.
4  *
5  * All use of this software is subject to the terms of the revised BSD
6  * license. You should have received a copy of this license along
7  * with this source code in a file named "LICENSE."
8  *
9  * @file dcNumericRange.I
10  * @author drose
11  * @date 2004-06-21
12  */
13 
14 /**
15  *
16  */
17 template <class NUM>
20 }
21 
22 /**
23  *
24  */
25 template <class NUM>
27 DCNumericRange(Number min, Number max) {
28  add_range(min, max);
29 }
30 
31 /**
32  *
33  */
34 template <class NUM>
37  _ranges(copy._ranges)
38 {
39 }
40 
41 /**
42  *
43  */
44 template <class NUM>
45 INLINE void DCNumericRange<NUM>::
46 operator = (const DCNumericRange<NUM> &copy) {
47  _ranges = copy._ranges;
48 }
49 
50 /**
51  * Returns true if the indicated number is within the specified range, false
52  * otherwise.
53  */
54 template <class NUM>
55 INLINE bool DCNumericRange<NUM>::
56 is_in_range(Number num) const {
57  if (_ranges.empty()) {
58  return true;
59  }
60 
61  typename Ranges::const_iterator ri;
62  for (ri = _ranges.begin(); ri != _ranges.end(); ++ri) {
63  if (num >= (*ri)._min && num <= (*ri)._max) {
64  return true;
65  }
66  }
67 
68  return false;
69 }
70 
71 /**
72  * Convenience function to validate the indicated number. If the number is
73  * within the specified range, does nothing; otherwise, if it is outside the
74  * range, sets range_error to true.
75  */
76 template <class NUM>
77 INLINE void DCNumericRange<NUM>::
78 validate(Number num, bool &range_error) const {
79  if (!is_in_range(num)) {
80  range_error = true;
81  }
82 }
83 
84 /**
85  * Returns true if the numeric range specifies exactly one legal value, false
86  * if multiple values are legal.
87  */
88 template <class NUM>
89 INLINE bool DCNumericRange<NUM>::
90 has_one_value() const {
91  return _ranges.size() == 1 && _ranges[0]._min == _ranges[0]._max;
92 }
93 
94 /**
95  * If has_one_value() returns true, this returns the one legal value accepted
96  * by the numeric range.
97  */
98 template <class NUM>
99 INLINE typename DCNumericRange<NUM>::Number DCNumericRange<NUM>::
100 get_one_value() const {
101  nassertr(has_one_value(), 0);
102  return _ranges[0]._min;
103 }
104 
105 /**
106  *
107  */
108 template <class NUM>
109 INLINE void DCNumericRange<NUM>::
110 generate_hash(HashGenerator &hashgen) const {
111  if (!_ranges.empty()) {
112  hashgen.add_int(_ranges.size());
113  typename Ranges::const_iterator ri;
114  for (ri = _ranges.begin(); ri != _ranges.end(); ++ri) {
115  // We don't account for the fractional part of floating-point ranges
116  // here. Shouldn't be a real issue.
117  hashgen.add_int((int)(*ri)._min);
118  hashgen.add_int((int)(*ri)._max);
119  }
120  }
121 }
122 
123 /**
124  *
125  */
126 template <class NUM>
127 INLINE void DCNumericRange<NUM>::
128 output(std::ostream &out, Number divisor) const {
129  if (!_ranges.empty()) {
130  typename Ranges::const_iterator ri;
131  ri = _ranges.begin();
132  output_minmax(out, divisor, *ri);
133  ++ri;
134  while (ri != _ranges.end()) {
135  out << ", ";
136  output_minmax(out, divisor, *ri);
137  ++ri;
138  }
139  }
140 }
141 
142 /**
143  * Outputs the range, formatting the numeric values as quoted ASCII
144  * characters.
145  */
146 template <class NUM>
147 INLINE void DCNumericRange<NUM>::
148 output_char(std::ostream &out, Number divisor) const {
149  if (divisor != 1) {
150  output(out, divisor);
151 
152  } else {
153  if (!_ranges.empty()) {
154  typename Ranges::const_iterator ri;
155  ri = _ranges.begin();
156  output_minmax_char(out, *ri);
157  ++ri;
158  while (ri != _ranges.end()) {
159  out << ", ";
160  output_minmax_char(out, *ri);
161  ++ri;
162  }
163  }
164  }
165 }
166 
167 /**
168  *
169  */
170 template <class NUM>
171 INLINE void DCNumericRange<NUM>::
172 clear() {
173  _ranges.clear();
174 }
175 
176 /**
177  * Adds a new minmax to the list of ranges. This is normally called only
178  * during dc file parsing. Returns true if successful, or false if the new
179  * minmax overlaps an existing minmax.
180  */
181 template <class NUM>
182 INLINE bool DCNumericRange<NUM>::
183 add_range(Number min, Number max) {
184  // Check for an overlap. This is probably indicative of a typo and should
185  // be reported.
186  if (max < min) {
187  return false;
188  }
189 
190  typename Ranges::const_iterator ri;
191  for (ri = _ranges.begin(); ri != _ranges.end(); ++ri) {
192  if ((min >= (*ri)._min && min <= (*ri)._max) ||
193  (max >= (*ri)._min && max <= (*ri)._max) ||
194  (min < (*ri)._min && max > (*ri)._max)) {
195  return false;
196  }
197  }
198 
199  MinMax minmax;
200  minmax._min = min;
201  minmax._max = max;
202  _ranges.push_back(minmax);
203 
204  return true;
205 }
206 
207 /**
208  * Returns true if the range contains no elements (and thus allows all
209  * numbers), false if it contains at least one.
210  */
211 template <class NUM>
212 INLINE bool DCNumericRange<NUM>::
213 is_empty() const {
214  return _ranges.empty();
215 }
216 
217 /**
218  * Returns the number of minmax components in the range description.
219  */
220 template <class NUM>
221 INLINE int DCNumericRange<NUM>::
222 get_num_ranges() const {
223  return _ranges.size();
224 }
225 
226 /**
227  * Returns the minimum value defined by the nth component.
228  */
229 template <class NUM>
230 INLINE typename DCNumericRange<NUM>::Number DCNumericRange<NUM>::
231 get_min(int n) const {
232  nassertr(n >= 0 && n < (int)_ranges.size(), 0);
233  return _ranges[n]._min;
234 }
235 
236 /**
237  * Returns the maximum value defined by the nth component.
238  */
239 template <class NUM>
240 INLINE typename DCNumericRange<NUM>::Number DCNumericRange<NUM>::
241 get_max(int n) const {
242  nassertr(n >= 0 && n < (int)_ranges.size(), 0);
243  return _ranges[n]._max;
244 }
245 
246 /**
247  * Outputs a single element of the range description.
248  */
249 template <class NUM>
250 INLINE void DCNumericRange<NUM>::
251 output_minmax(std::ostream &out, Number divisor, const MinMax &range) const {
252  if (divisor == 1) {
253  if (range._min == range._max) {
254  out << range._min;
255  } else {
256  out << range._min << "-" << range._max;
257  }
258  } else {
259  if (range._min == range._max) {
260  out << (double)range._min / (double)divisor;
261  } else {
262  out << (double)range._min / (double)divisor
263  << "-"
264  << (double)range._max / (double)divisor;
265  }
266  }
267 }
268 
269 /**
270  * Outputs a single element of the range description.
271  */
272 template <class NUM>
273 INLINE void DCNumericRange<NUM>::
274 output_minmax_char(std::ostream &out, const MinMax &range) const {
275  if (range._min == range._max) {
276  DCPacker::enquote_string(out, '\'', std::string(1, range._min));
277  } else {
278  DCPacker::enquote_string(out, '\'', std::string(1, range._min));
279  out << "-";
280  DCPacker::enquote_string(out, '\'', std::string(1, range._max));
281  }
282 }
void add_int(int num)
Adds another integer to the hash so far.
void validate(Number num, bool &range_error) const
Convenience function to validate the indicated number.
bool add_range(Number min, Number max)
Adds a new minmax to the list of ranges.
bool has_one_value() const
Returns true if the numeric range specifies exactly one legal value, false if multiple values are leg...
Represents a range of legal integer or floating-point values.
int get_num_ranges() const
Returns the number of minmax components in the range description.
Number get_max(int n) const
Returns the maximum value defined by the nth component.
Number get_one_value() const
If has_one_value() returns true, this returns the one legal value accepted by the numeric range.
Number get_min(int n) const
Returns the minimum value defined by the nth component.
static void enquote_string(std::ostream &out, char quote_mark, const std::string &str)
Outputs the indicated string within quotation marks.
Definition: dcPacker.cxx:1097
This class generates an arbitrary hash number from a sequence of ints.
Definition: hashGenerator.h:24
void output_char(std::ostream &out, Number divisor=1) const
Outputs the range, formatting the numeric values as quoted ASCII characters.
bool is_empty() const
Returns true if the range contains no elements (and thus allows all numbers), false if it contains at...
bool is_in_range(Number num) const
Returns true if the indicated number is within the specified range, false otherwise.