add modulus syntax
This commit is contained in:
parent
8477e70e0e
commit
50974f8189
File diff suppressed because it is too large
Load Diff
|
|
@ -146,6 +146,7 @@ dc_cleanup_parser() {
|
|||
%type <u.field> atomic_field
|
||||
%type <u.field> molecular_field
|
||||
%type <u.subatomic> type_token
|
||||
%type <u.parameter> simple_type_name
|
||||
%type <u.parameter> type_name
|
||||
%type <u.parameter> type_definition
|
||||
%type <u.parameter> named_parameter
|
||||
|
|
@ -591,58 +592,53 @@ parameter_description:
|
|||
}
|
||||
;
|
||||
|
||||
type_name:
|
||||
type_token
|
||||
simple_type_name:
|
||||
type_token
|
||||
{
|
||||
$$ = new DCSimpleParameter($1);
|
||||
}
|
||||
| type_token '(' double_range ')'
|
||||
| simple_type_name '(' double_range ')'
|
||||
{
|
||||
DCSimpleParameter *simple_param = new DCSimpleParameter($1);
|
||||
DCSimpleParameter *simple_param = $1->as_simple_parameter();
|
||||
nassertr(simple_param != (DCSimpleParameter *)NULL, 0);
|
||||
if (!simple_param->set_range(double_range)) {
|
||||
yyerror("Inappropriate range for type");
|
||||
}
|
||||
$$ = simple_param;
|
||||
}
|
||||
| type_token '/' small_unsigned_integer
|
||||
| simple_type_name '/' small_unsigned_integer
|
||||
{
|
||||
DCSimpleParameter *simple_param = new DCSimpleParameter($1);
|
||||
if ($3 == 0) {
|
||||
yyerror("Invalid divisor.");
|
||||
DCSimpleParameter *simple_param = $1->as_simple_parameter();
|
||||
nassertr(simple_param != (DCSimpleParameter *)NULL, 0);
|
||||
if (!simple_param->is_numeric_type()) {
|
||||
yyerror("A divisor is only valid on a numeric type.");
|
||||
|
||||
} else if (!simple_param->set_divisor($3)) {
|
||||
yyerror("A divisor is only valid on a numeric type.");
|
||||
}
|
||||
$$ = simple_param;
|
||||
}
|
||||
| type_token '/' small_unsigned_integer '(' double_range ')'
|
||||
{
|
||||
DCSimpleParameter *simple_param = new DCSimpleParameter($1);
|
||||
if ($3 == 0) {
|
||||
yyerror("Invalid divisor.");
|
||||
|
||||
} else if (!simple_param->set_divisor($3)) {
|
||||
yyerror("A divisor is only valid on a numeric type.");
|
||||
}
|
||||
if (!simple_param->set_range(double_range)) {
|
||||
yyerror("Inappropriate range for type");
|
||||
} else if (simple_param->has_modulus() && !simple_param->set_modulus(simple_param->get_modulus())) {
|
||||
// Changing the divisor may change the valid range for the modulus.
|
||||
yyerror("Invalid modulus.");
|
||||
}
|
||||
$$ = simple_param;
|
||||
}
|
||||
| type_token '(' double_range ')' '/' small_unsigned_integer
|
||||
{
|
||||
DCSimpleParameter *simple_param = new DCSimpleParameter($1);
|
||||
if ($6 == 0) {
|
||||
yyerror("Invalid divisor.");
|
||||
;
|
||||
| simple_type_name '%' number
|
||||
{
|
||||
DCSimpleParameter *simple_param = $1->as_simple_parameter();
|
||||
nassertr(simple_param != (DCSimpleParameter *)NULL, 0);
|
||||
if (!simple_param->is_numeric_type()) {
|
||||
yyerror("A divisor is only valid on a numeric type.");
|
||||
|
||||
} else if (!simple_param->set_divisor($6)) {
|
||||
yyerror("A divisor is only valid on a numeric type.");
|
||||
}
|
||||
if (!simple_param->set_range(double_range)) {
|
||||
yyerror("Inappropriate range for type");
|
||||
} else if (!simple_param->set_modulus($3)) {
|
||||
yyerror("Invalid modulus.");
|
||||
}
|
||||
$$ = simple_param;
|
||||
}
|
||||
;
|
||||
|
||||
type_name:
|
||||
simple_type_name
|
||||
| IDENTIFIER
|
||||
{
|
||||
if (dc_file == (DCFile *)NULL) {
|
||||
|
|
@ -828,15 +824,31 @@ parameter_definition:
|
|||
}
|
||||
| parameter_definition '/' small_unsigned_integer
|
||||
{
|
||||
if ($3 == 0) {
|
||||
yyerror("Invalid divisor.");
|
||||
|
||||
} else if ($1->as_simple_parameter() == NULL || $1->get_typedef() != (DCTypedef *)NULL) {
|
||||
DCSimpleParameter *simple_param = $1->as_simple_parameter();
|
||||
if (simple_param == NULL || simple_param->get_typedef() != (DCTypedef *)NULL) {
|
||||
yyerror("A divisor is only allowed on a primitive type.");
|
||||
|
||||
} else {
|
||||
if (!$1->as_simple_parameter()->set_divisor($3)) {
|
||||
} else if (!simple_param->is_numeric_type()) {
|
||||
yyerror("A divisor is only valid on a numeric type.");
|
||||
|
||||
} else {
|
||||
if (!simple_param->set_divisor($3)) {
|
||||
yyerror("Invalid divisor.");
|
||||
}
|
||||
}
|
||||
}
|
||||
| parameter_definition '%' number
|
||||
{
|
||||
DCSimpleParameter *simple_param = $1->as_simple_parameter();
|
||||
if (simple_param == NULL || simple_param->get_typedef() != (DCTypedef *)NULL) {
|
||||
yyerror("A modulus is only allowed on a primitive type.");
|
||||
|
||||
} else if (!simple_param->is_numeric_type()) {
|
||||
yyerror("A modulus is only valid on a numeric type.");
|
||||
|
||||
} else {
|
||||
if (!simple_param->set_modulus($3)) {
|
||||
yyerror("Invalid modulus.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,7 +36,8 @@ DCClassParameter *DCSimpleParameter::_uint32uint8_type = NULL;
|
|||
DCSimpleParameter::
|
||||
DCSimpleParameter(DCSubatomicType type, unsigned int divisor) :
|
||||
_type(type),
|
||||
_divisor(1)
|
||||
_divisor(1),
|
||||
_has_modulus(false)
|
||||
{
|
||||
_pack_type = PT_invalid;
|
||||
_nested_type = ST_invalid;
|
||||
|
|
@ -210,11 +211,17 @@ DCSimpleParameter(const DCSimpleParameter ©) :
|
|||
_divisor(copy._divisor),
|
||||
_nested_field(copy._nested_field),
|
||||
_bytes_per_element(copy._bytes_per_element),
|
||||
_orig_range(copy._orig_range),
|
||||
_has_modulus(copy._has_modulus),
|
||||
_orig_modulus(copy._orig_modulus),
|
||||
_int_range(copy._int_range),
|
||||
_uint_range(copy._uint_range),
|
||||
_int64_range(copy._int64_range),
|
||||
_uint64_range(copy._uint64_range),
|
||||
_double_range(copy._double_range)
|
||||
_double_range(copy._double_range),
|
||||
_uint_modulus(copy._uint_modulus),
|
||||
_uint64_modulus(copy._uint64_modulus),
|
||||
_double_modulus(copy._double_modulus)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -271,6 +278,33 @@ get_type() const {
|
|||
return _type;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DCSimpleParameter::has_modulus
|
||||
// Access: Published
|
||||
// Description: Returns true if there is a modulus associated, false
|
||||
// otherwise.,
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool DCSimpleParameter::
|
||||
has_modulus() const {
|
||||
return _has_modulus;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DCSimpleParameter::get_modulus
|
||||
// Access: Published
|
||||
// Description: Returns the modulus associated with this type, if
|
||||
// any. It is an error to call this if has_modulus()
|
||||
// returned false.
|
||||
//
|
||||
// If present, this is the modulus that is used to
|
||||
// constrain the numeric value of the field before it is
|
||||
// packed (and range-checked).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
double DCSimpleParameter::
|
||||
get_modulus() const {
|
||||
return _orig_modulus;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DCSimpleParameter::get_divisor
|
||||
// Access: Published
|
||||
|
|
@ -286,12 +320,97 @@ get_divisor() const {
|
|||
return _divisor;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DCSimpleParameter::is_numeric_type
|
||||
// Access: Public
|
||||
// Description: Returns true if the type is a numeric type (and
|
||||
// therefore can accept a divisor and/or a modulus), or
|
||||
// false if it is some string-based type.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool DCSimpleParameter::
|
||||
is_numeric_type() const {
|
||||
return !(_pack_type == PT_string || _pack_type == PT_blob);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DCSimpleParameter::set_modulus
|
||||
// Access: Public
|
||||
// Description: Assigns the indicated modulus to the simple type.
|
||||
// Any packed value will be constrained to be within [0,
|
||||
// modulus).
|
||||
//
|
||||
// Returns true if assigned, false if this type cannot
|
||||
// accept a modulus or if the modulus is invalid.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool DCSimpleParameter::
|
||||
set_modulus(double modulus) {
|
||||
if (_pack_type == PT_string || _pack_type == PT_blob || modulus <= 0.0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
_has_modulus = true;
|
||||
_orig_modulus = modulus;
|
||||
|
||||
bool range_error = false;
|
||||
_double_modulus = modulus * _divisor;
|
||||
_uint64_modulus = (PN_uint64)floor(_double_modulus + 0.5);
|
||||
_uint_modulus = (unsigned int)_uint64_modulus;
|
||||
|
||||
// Check the range. The legitimate range for a modulus value is 1
|
||||
// through (maximum_value + 1).
|
||||
switch (_type) {
|
||||
case ST_int8:
|
||||
case ST_int8array:
|
||||
validate_uint64_limits(_uint64_modulus - 1, 7, range_error);
|
||||
break;
|
||||
|
||||
case ST_int16:
|
||||
case ST_int16array:
|
||||
validate_uint64_limits(_uint64_modulus - 1, 15, range_error);
|
||||
break;
|
||||
|
||||
case ST_int32:
|
||||
case ST_int32array:
|
||||
validate_uint64_limits(_uint64_modulus - 1, 31, range_error);
|
||||
break;
|
||||
|
||||
case ST_int64:
|
||||
validate_uint64_limits(_uint64_modulus - 1, 63, range_error);
|
||||
break;
|
||||
|
||||
case ST_char:
|
||||
case ST_uint8:
|
||||
case ST_uint8array:
|
||||
validate_uint64_limits(_uint64_modulus - 1, 8, range_error);
|
||||
break;
|
||||
|
||||
case ST_uint16:
|
||||
case ST_uint16array:
|
||||
validate_uint64_limits(_uint64_modulus - 1, 16, range_error);
|
||||
break;
|
||||
|
||||
case ST_uint32:
|
||||
case ST_uint32array:
|
||||
validate_uint64_limits(_uint64_modulus - 1, 32, range_error);
|
||||
break;
|
||||
|
||||
case ST_uint64:
|
||||
case ST_float64:
|
||||
break;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
return !range_error;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DCSimpleParameter::set_divisor
|
||||
// Access: Public
|
||||
// Description: Assigns the indicated divisor to the simple type.
|
||||
// Returns true if assigned, false if this type cannot
|
||||
// accept a divisor.
|
||||
// accept a divisor or if the divisor is invalid.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool DCSimpleParameter::
|
||||
set_divisor(unsigned int divisor) {
|
||||
|
|
@ -306,6 +425,13 @@ set_divisor(unsigned int divisor) {
|
|||
_pack_type = PT_double;
|
||||
}
|
||||
|
||||
if (_has_range_limits) {
|
||||
set_range(_orig_range);
|
||||
}
|
||||
if (_has_modulus) {
|
||||
set_modulus(_orig_modulus);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -326,6 +452,7 @@ set_range(const DCDoubleRange &range) {
|
|||
int i;
|
||||
|
||||
_has_range_limits = (num_ranges != 0);
|
||||
_orig_range = range;
|
||||
|
||||
switch (_type) {
|
||||
case ST_int8:
|
||||
|
|
@ -523,6 +650,16 @@ void DCSimpleParameter::
|
|||
pack_double(DCPackData &pack_data, double value,
|
||||
bool &pack_error, bool &range_error) const {
|
||||
double real_value = value * _divisor;
|
||||
if (_has_modulus) {
|
||||
if (real_value < 0.0) {
|
||||
real_value = _double_modulus - fmod(-real_value, _double_modulus);
|
||||
if (real_value == _double_modulus) {
|
||||
real_value = 0.0;
|
||||
}
|
||||
} else {
|
||||
real_value = fmod(real_value, _double_modulus);
|
||||
}
|
||||
}
|
||||
|
||||
switch (_type) {
|
||||
case ST_int8:
|
||||
|
|
@ -614,6 +751,13 @@ void DCSimpleParameter::
|
|||
pack_int(DCPackData &pack_data, int value,
|
||||
bool &pack_error, bool &range_error) const {
|
||||
int int_value = value * _divisor;
|
||||
if (_has_modulus && _uint_modulus != 0) {
|
||||
if (int_value < 0) {
|
||||
int_value = _uint_modulus - 1 - (-int_value - 1) % _uint_modulus;
|
||||
} else {
|
||||
int_value = int_value % _uint_modulus;
|
||||
}
|
||||
}
|
||||
|
||||
switch (_type) {
|
||||
case ST_int8:
|
||||
|
|
@ -693,6 +837,9 @@ void DCSimpleParameter::
|
|||
pack_uint(DCPackData &pack_data, unsigned int value,
|
||||
bool &pack_error, bool &range_error) const {
|
||||
unsigned int int_value = value * _divisor;
|
||||
if (_has_modulus && _uint_modulus != 0) {
|
||||
int_value = int_value % _uint_modulus;
|
||||
}
|
||||
|
||||
switch (_type) {
|
||||
case ST_int8:
|
||||
|
|
@ -772,6 +919,13 @@ void DCSimpleParameter::
|
|||
pack_int64(DCPackData &pack_data, PN_int64 value,
|
||||
bool &pack_error, bool &range_error) const {
|
||||
PN_int64 int_value = value * _divisor;
|
||||
if (_has_modulus && _uint64_modulus != 0) {
|
||||
if (int_value < 0) {
|
||||
int_value = _uint64_modulus - 1 - (-int_value - 1) % _uint64_modulus;
|
||||
} else {
|
||||
int_value = int_value % _uint64_modulus;
|
||||
}
|
||||
}
|
||||
|
||||
switch (_type) {
|
||||
case ST_int8:
|
||||
|
|
@ -853,6 +1007,9 @@ void DCSimpleParameter::
|
|||
pack_uint64(DCPackData &pack_data, PN_uint64 value,
|
||||
bool &pack_error, bool &range_error) const {
|
||||
PN_uint64 int_value = value * _divisor;
|
||||
if (_has_modulus && _uint64_modulus != 0) {
|
||||
int_value = int_value % _uint64_modulus;
|
||||
}
|
||||
|
||||
switch (_type) {
|
||||
case ST_int8:
|
||||
|
|
@ -2113,6 +2270,9 @@ output_instance(ostream &out, bool brief, const string &prename,
|
|||
|
||||
} else {
|
||||
out << _type;
|
||||
if (_has_modulus) {
|
||||
out << "%" << _orig_modulus;
|
||||
}
|
||||
if (_divisor != 1) {
|
||||
out << "/" << _divisor;
|
||||
}
|
||||
|
|
@ -2193,6 +2353,9 @@ generate_hash(HashGenerator &hashgen) const {
|
|||
|
||||
hashgen.add_int(_type);
|
||||
hashgen.add_int(_divisor);
|
||||
if (_has_modulus) {
|
||||
hashgen.add_int((int)_double_modulus);
|
||||
}
|
||||
|
||||
_int_range.generate_hash(hashgen);
|
||||
_int64_range.generate_hash(hashgen);
|
||||
|
|
|
|||
|
|
@ -45,9 +45,13 @@ PUBLISHED:
|
|||
virtual bool is_valid() const;
|
||||
|
||||
DCSubatomicType get_type() const;
|
||||
bool has_modulus() const;
|
||||
double get_modulus() const;
|
||||
int get_divisor() const;
|
||||
|
||||
public:
|
||||
bool is_numeric_type() const;
|
||||
bool set_modulus(double modulus);
|
||||
bool set_divisor(unsigned int divisor);
|
||||
bool set_range(const DCDoubleRange &range);
|
||||
|
||||
|
|
@ -114,12 +118,25 @@ private:
|
|||
typedef pmap<DCSubatomicType, DivisorMap> NestedFieldMap;
|
||||
static NestedFieldMap _nested_field_map;
|
||||
|
||||
// These are the range and modulus values as specified by the user,
|
||||
// unscaled by the divisor.
|
||||
DCDoubleRange _orig_range;
|
||||
bool _has_modulus;
|
||||
double _orig_modulus;
|
||||
|
||||
// Only the range appropriate to this type will be filled in.
|
||||
DCIntRange _int_range;
|
||||
DCUnsignedIntRange _uint_range;
|
||||
DCInt64Range _int64_range;
|
||||
DCUnsignedInt64Range _uint64_range;
|
||||
DCDoubleRange _double_range;
|
||||
|
||||
// All of these modulus values will be filled in, regardless of the
|
||||
// type.
|
||||
unsigned int _uint_modulus;
|
||||
PN_uint64 _uint64_modulus;
|
||||
double _double_modulus;
|
||||
|
||||
static DCClassParameter *_uint32uint8_type;
|
||||
};
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue