331 lines
11 KiB
Plaintext
331 lines
11 KiB
Plaintext
// Filename: dcNumericRange.I
|
|
// Created by: drose (21Jun04)
|
|
//
|
|
////////////////////////////////////////////////////////////////////
|
|
//
|
|
// PANDA 3D SOFTWARE
|
|
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
|
|
//
|
|
// All use of this software is subject to the terms of the Panda 3d
|
|
// Software license. You should have received a copy of this license
|
|
// along with this source code; you will also find a current copy of
|
|
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
|
|
//
|
|
// To contact the maintainers of this program write to
|
|
// panda3d-general@lists.sourceforge.net .
|
|
//
|
|
////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: DCNumericRange::Constructor
|
|
// Access: Public
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
template <class NUM>
|
|
INLINE DCNumericRange<NUM>::
|
|
DCNumericRange() {
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: DCNumericRange::Constructor
|
|
// Access: Public
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
template <class NUM>
|
|
INLINE DCNumericRange<NUM>::
|
|
DCNumericRange(Number min, Number max) {
|
|
add_range(min, max);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: DCNumericRange::Copy Constructor
|
|
// Access: Public
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
template <class NUM>
|
|
INLINE DCNumericRange<NUM>::
|
|
DCNumericRange(const DCNumericRange<NUM> ©) :
|
|
_ranges(copy._ranges)
|
|
{
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: DCNumericRange::Copy Assignment Operator
|
|
// Access: Public
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
template <class NUM>
|
|
INLINE void DCNumericRange<NUM>::
|
|
operator = (const DCNumericRange<NUM> ©) {
|
|
_ranges = copy._ranges;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: DCNumericRange::is_in_range
|
|
// Access: Public
|
|
// Description: Returns true if the indicated number is within the
|
|
// specified range, false otherwise.
|
|
////////////////////////////////////////////////////////////////////
|
|
template <class NUM>
|
|
bool DCNumericRange<NUM>::
|
|
is_in_range(Number num) const {
|
|
if (_ranges.empty()) {
|
|
return true;
|
|
}
|
|
|
|
TYPENAME Ranges::const_iterator ri;
|
|
for (ri = _ranges.begin(); ri != _ranges.end(); ++ri) {
|
|
if (num >= (*ri)._min && num <= (*ri)._max) {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: DCNumericRange::validate
|
|
// Access: Public
|
|
// Description: Convenience function to validate the indicated
|
|
// number. If the number is within the specified range,
|
|
// does nothing; otherwise, if it is outside the range,
|
|
// sets range_error to true.
|
|
////////////////////////////////////////////////////////////////////
|
|
template <class NUM>
|
|
INLINE void DCNumericRange<NUM>::
|
|
validate(Number num, bool &range_error) const {
|
|
if (!is_in_range(num)) {
|
|
range_error = true;
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: DCNumericRange::has_one_value
|
|
// Access: Public
|
|
// Description: Returns true if the numeric range specifies exactly
|
|
// one legal value, false if multiple values are legal.
|
|
////////////////////////////////////////////////////////////////////
|
|
template <class NUM>
|
|
INLINE bool DCNumericRange<NUM>::
|
|
has_one_value() const {
|
|
return _ranges.size() == 1 && _ranges[0]._min == _ranges[0]._max;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: DCNumericRange::get_one_value
|
|
// Access: Public
|
|
// Description: If has_one_value() returns true, this returns the one
|
|
// legal value accepted by the numeric range.
|
|
////////////////////////////////////////////////////////////////////
|
|
template <class NUM>
|
|
INLINE TYPENAME DCNumericRange<NUM>::Number DCNumericRange<NUM>::
|
|
get_one_value() const {
|
|
nassertr(has_one_value(), 0);
|
|
return _ranges[0]._min;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: DCNumericRange::generate_hash
|
|
// Access: Public
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
template <class NUM>
|
|
void DCNumericRange<NUM>::
|
|
generate_hash(HashGenerator &hashgen) const {
|
|
if (!_ranges.empty()) {
|
|
hashgen.add_int(_ranges.size());
|
|
TYPENAME Ranges::const_iterator ri;
|
|
for (ri = _ranges.begin(); ri != _ranges.end(); ++ri) {
|
|
// We don't account for the fractional part of floating-point
|
|
// ranges here. Shouldn't be a real issue.
|
|
hashgen.add_int((int)(*ri)._min);
|
|
hashgen.add_int((int)(*ri)._max);
|
|
}
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: DCNumericRange::output
|
|
// Access: Public
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
template <class NUM>
|
|
void DCNumericRange<NUM>::
|
|
output(ostream &out, Number divisor) const {
|
|
if (!_ranges.empty()) {
|
|
TYPENAME Ranges::const_iterator ri;
|
|
ri = _ranges.begin();
|
|
output_minmax(out, divisor, *ri);
|
|
++ri;
|
|
while (ri != _ranges.end()) {
|
|
out << ", ";
|
|
output_minmax(out, divisor, *ri);
|
|
++ri;
|
|
}
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: DCNumericRange::output_char
|
|
// Access: Public
|
|
// Description: Outputs the range, formatting the numeric values as
|
|
// quoted ASCII characters.
|
|
////////////////////////////////////////////////////////////////////
|
|
template <class NUM>
|
|
void DCNumericRange<NUM>::
|
|
output_char(ostream &out, Number divisor) const {
|
|
if (divisor != 1) {
|
|
output(out, divisor);
|
|
|
|
} else {
|
|
if (!_ranges.empty()) {
|
|
TYPENAME Ranges::const_iterator ri;
|
|
ri = _ranges.begin();
|
|
output_minmax_char(out, *ri);
|
|
++ri;
|
|
while (ri != _ranges.end()) {
|
|
out << ", ";
|
|
output_minmax_char(out, *ri);
|
|
++ri;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: DCNumericRange::clear
|
|
// Access: Public
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
template <class NUM>
|
|
INLINE void DCNumericRange<NUM>::
|
|
clear() {
|
|
_ranges.clear();
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: DCNumericRange::add_range
|
|
// Access: Public
|
|
// Description: Adds a new minmax to the list of ranges. This is
|
|
// normally called only during dc file parsing. Returns
|
|
// true if successful, or false if the new minmax
|
|
// overlaps an existing minmax.
|
|
////////////////////////////////////////////////////////////////////
|
|
template <class NUM>
|
|
bool DCNumericRange<NUM>::
|
|
add_range(Number min, Number max) {
|
|
// Check for an overlap. This is probably indicative of a typo and
|
|
// should be reported.
|
|
if (max < min) {
|
|
return false;
|
|
}
|
|
|
|
TYPENAME Ranges::const_iterator ri;
|
|
for (ri = _ranges.begin(); ri != _ranges.end(); ++ri) {
|
|
if ((min >= (*ri)._min && min <= (*ri)._max) ||
|
|
(max >= (*ri)._min && max <= (*ri)._max) ||
|
|
(min < (*ri)._min && max > (*ri)._max)) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
MinMax minmax;
|
|
minmax._min = min;
|
|
minmax._max = max;
|
|
_ranges.push_back(minmax);
|
|
|
|
return true;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: DCNumericRange::is_empty
|
|
// Access: Private
|
|
// Description: Returns true if the range contains no elements (and
|
|
// thus allows all numbers), false if it contains at
|
|
// least one.
|
|
////////////////////////////////////////////////////////////////////
|
|
template <class NUM>
|
|
INLINE bool DCNumericRange<NUM>::
|
|
is_empty() const {
|
|
return _ranges.empty();
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: DCNumericRange::get_num_ranges
|
|
// Access: Private
|
|
// Description: Returns the number of minmax components in the range
|
|
// description.
|
|
////////////////////////////////////////////////////////////////////
|
|
template <class NUM>
|
|
INLINE int DCNumericRange<NUM>::
|
|
get_num_ranges() const {
|
|
return _ranges.size();
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: DCNumericRange::get_min
|
|
// Access: Private
|
|
// Description: Returns the minimum value defined by the nth component.
|
|
////////////////////////////////////////////////////////////////////
|
|
template <class NUM>
|
|
INLINE TYPENAME DCNumericRange<NUM>::Number DCNumericRange<NUM>::
|
|
get_min(int n) const {
|
|
nassertr(n >= 0 && n < (int)_ranges.size(), 0);
|
|
return _ranges[n]._min;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: DCNumericRange::get_max
|
|
// Access: Private
|
|
// Description: Returns the maximum value defined by the nth component.
|
|
////////////////////////////////////////////////////////////////////
|
|
template <class NUM>
|
|
INLINE TYPENAME DCNumericRange<NUM>::Number DCNumericRange<NUM>::
|
|
get_max(int n) const {
|
|
nassertr(n >= 0 && n < (int)_ranges.size(), 0);
|
|
return _ranges[n]._max;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: DCNumericRange::output_minmax
|
|
// Access: Private
|
|
// Description: Outputs a single element of the range description.
|
|
////////////////////////////////////////////////////////////////////
|
|
template <class NUM>
|
|
INLINE void DCNumericRange<NUM>::
|
|
output_minmax(ostream &out, Number divisor, const MinMax &range) const {
|
|
if (divisor == 1) {
|
|
if (range._min == range._max) {
|
|
out << range._min;
|
|
} else {
|
|
out << range._min << "-" << range._max;
|
|
}
|
|
} else {
|
|
if (range._min == range._max) {
|
|
out << (double)range._min / (double)divisor;
|
|
} else {
|
|
out << (double)range._min / (double)divisor
|
|
<< "-"
|
|
<< (double)range._max / (double)divisor;
|
|
}
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: DCNumericRange::output_minmax_char
|
|
// Access: Private
|
|
// Description: Outputs a single element of the range description.
|
|
////////////////////////////////////////////////////////////////////
|
|
template <class NUM>
|
|
INLINE void DCNumericRange<NUM>::
|
|
output_minmax_char(ostream &out, const MinMax &range) const {
|
|
if (range._min == range._max) {
|
|
DCPacker::enquote_string(out, '\'', string(1, range._min));
|
|
} else {
|
|
DCPacker::enquote_string(out, '\'', string(1, range._min));
|
|
out << "-";
|
|
DCPacker::enquote_string(out, '\'', string(1, range._max));
|
|
}
|
|
}
|