Panda3D
dcAtomicField.cxx
1 // Filename: dcAtomicField.cxx
2 // Created by: drose (05Oct00)
3 //
4 ////////////////////////////////////////////////////////////////////
5 //
6 // PANDA 3D SOFTWARE
7 // Copyright (c) Carnegie Mellon University. All rights reserved.
8 //
9 // All use of this software is subject to the terms of the revised BSD
10 // license. You should have received a copy of this license along
11 // with this source code in a file named "LICENSE."
12 //
13 ////////////////////////////////////////////////////////////////////
14 
15 #include "dcAtomicField.h"
16 #include "hashGenerator.h"
17 #include "dcindent.h"
18 #include "dcSimpleParameter.h"
19 #include "dcPacker.h"
20 
21 #include <math.h>
22 
23 ////////////////////////////////////////////////////////////////////
24 // Function: DCAtomicField::Constructor
25 // Access: Public
26 // Description:
27 ////////////////////////////////////////////////////////////////////
28 DCAtomicField::
29 DCAtomicField(const string &name, DCClass *dclass,
30  bool bogus_field) :
31  DCField(name, dclass)
32 {
33  _bogus_field = bogus_field;
34 }
35 
36 ////////////////////////////////////////////////////////////////////
37 // Function: DCAtomicField::Destructor
38 // Access: Public, Virtual
39 // Description:
40 ////////////////////////////////////////////////////////////////////
41 DCAtomicField::
42 ~DCAtomicField() {
43  Elements::iterator ei;
44  for (ei = _elements.begin(); ei != _elements.end(); ++ei) {
45  delete (*ei);
46  }
47  _elements.clear();
48 }
49 
50 ////////////////////////////////////////////////////////////////////
51 // Function: DCAtomicField::as_atomic_field
52 // Access: Published, Virtual
53 // Description: Returns the same field pointer converted to an atomic
54 // field pointer, if this is in fact an atomic field;
55 // otherwise, returns NULL.
56 ////////////////////////////////////////////////////////////////////
59  return this;
60 }
61 
62 ////////////////////////////////////////////////////////////////////
63 // Function: DCAtomicField::as_atomic_field
64 // Access: Published, Virtual
65 // Description: Returns the same field pointer converted to an atomic
66 // field pointer, if this is in fact an atomic field;
67 // otherwise, returns NULL.
68 ////////////////////////////////////////////////////////////////////
70 as_atomic_field() const {
71  return this;
72 }
73 
74 ////////////////////////////////////////////////////////////////////
75 // Function: DCAtomicField::get_num_elements
76 // Access: Published
77 // Description: Returns the number of elements (parameters) of the
78 // atomic field.
79 ////////////////////////////////////////////////////////////////////
82  return _elements.size();
83 }
84 
85 ////////////////////////////////////////////////////////////////////
86 // Function: DCAtomicField::get_element
87 // Access: Published
88 // Description: Returns the parameter object describing the
89 // nth element.
90 ////////////////////////////////////////////////////////////////////
92 get_element(int n) const {
93  nassertr(n >= 0 && n < (int)_elements.size(), NULL);
94  return _elements[n];
95 }
96 
97 ////////////////////////////////////////////////////////////////////
98 // Function: DCAtomicField::get_element_default
99 // Access: Published
100 // Description: Returns the pre-formatted default value associated
101 // with the nth element of the field. This is only
102 // valid if has_element_default() returns true, in which
103 // case this string represents the bytes that should be
104 // assigned to the field as a default value.
105 //
106 // If the element is an array-type element, the returned
107 // value will include the two-byte length preceding the
108 // array data.
109 //
110 // This is deprecated; use get_element() instead.
111 ////////////////////////////////////////////////////////////////////
112 string DCAtomicField::
113 get_element_default(int n) const {
114  nassertr(n >= 0 && n < (int)_elements.size(), string());
115  return _elements[n]->get_default_value();
116 }
117 
118 ////////////////////////////////////////////////////////////////////
119 // Function: DCAtomicField::has_element_default
120 // Access: Published
121 // Description: Returns true if the nth element of the field has a
122 // default value specified, false otherwise.
123 //
124 // This is deprecated; use get_element() instead.
125 ////////////////////////////////////////////////////////////////////
126 bool DCAtomicField::
127 has_element_default(int n) const {
128  nassertr(n >= 0 && n < (int)_elements.size(), false);
129  return _elements[n]->has_default_value();
130 }
131 
132 ////////////////////////////////////////////////////////////////////
133 // Function: DCAtomicField::get_element_name
134 // Access: Published
135 // Description: Returns the name of the nth element of the field.
136 // This name is strictly for documentary purposes; it
137 // does not generally affect operation. If a name is
138 // not specified, this will be the empty string.
139 //
140 // This method is deprecated; use
141 // get_element()->get_name() instead.
142 ////////////////////////////////////////////////////////////////////
143 string DCAtomicField::
144 get_element_name(int n) const {
145  nassertr(n >= 0 && n < (int)_elements.size(), string());
146  return _elements[n]->get_name();
147 }
148 
149 ////////////////////////////////////////////////////////////////////
150 // Function: DCAtomicField::get_element_type
151 // Access: Published
152 // Description: Returns the numeric type of the nth element of the
153 // field. This method is deprecated; use
154 // get_element() instead.
155 ////////////////////////////////////////////////////////////////////
156 DCSubatomicType DCAtomicField::
157 get_element_type(int n) const {
158  nassertr(n >= 0 && n < (int)_elements.size(), ST_invalid);
159  DCSimpleParameter *simple_parameter = _elements[n]->as_simple_parameter();
160  nassertr(simple_parameter != (DCSimpleParameter *)NULL, ST_invalid);
161  return simple_parameter->get_type();
162 }
163 
164 ////////////////////////////////////////////////////////////////////
165 // Function: DCAtomicField::get_element_divisor
166 // Access: Published
167 // Description: Returns the divisor associated with the nth element
168 // of the field. This implements an implicit
169 // fixed-point system; floating-point values are to be
170 // multiplied by this value before encoding into a
171 // packet, and divided by this number after decoding.
172 //
173 // This method is deprecated; use
174 // get_element()->get_divisor() instead.
175 ////////////////////////////////////////////////////////////////////
176 int DCAtomicField::
177 get_element_divisor(int n) const {
178  nassertr(n >= 0 && n < (int)_elements.size(), 1);
179  DCSimpleParameter *simple_parameter = _elements[n]->as_simple_parameter();
180  nassertr(simple_parameter != (DCSimpleParameter *)NULL, 1);
181  return simple_parameter->get_divisor();
182 }
183 
184 ////////////////////////////////////////////////////////////////////
185 // Function: DCAtomicField::output
186 // Access: Public, Virtual
187 // Description:
188 ////////////////////////////////////////////////////////////////////
189 void DCAtomicField::
190 output(ostream &out, bool brief) const {
191  out << _name << "(";
192 
193  if (!_elements.empty()) {
194  Elements::const_iterator ei = _elements.begin();
195  output_element(out, brief, *ei);
196  ++ei;
197  while (ei != _elements.end()) {
198  out << ", ";
199  output_element(out, brief, *ei);
200  ++ei;
201  }
202  }
203  out << ")";
204 
205  output_keywords(out);
206 }
207 
208 ////////////////////////////////////////////////////////////////////
209 // Function: DCAtomicField::write
210 // Access: Public, Virtual
211 // Description: Generates a parseable description of the object to
212 // the indicated output stream.
213 ////////////////////////////////////////////////////////////////////
214 void DCAtomicField::
215 write(ostream &out, bool brief, int indent_level) const {
216  indent(out, indent_level);
217  output(out, brief);
218  out << ";";
219  if (!brief && _number >= 0) {
220  out << " // field " << _number;
221  }
222  out << "\n";
223 }
224 
225 ////////////////////////////////////////////////////////////////////
226 // Function: DCAtomicField::generate_hash
227 // Access: Public, Virtual
228 // Description: Accumulates the properties of this field into the
229 // hash.
230 ////////////////////////////////////////////////////////////////////
231 void DCAtomicField::
232 generate_hash(HashGenerator &hashgen) const {
233  DCField::generate_hash(hashgen);
234 
235  hashgen.add_int(_elements.size());
236  Elements::const_iterator ei;
237  for (ei = _elements.begin(); ei != _elements.end(); ++ei) {
238  (*ei)->generate_hash(hashgen);
239  }
240 
242 }
243 
244 ////////////////////////////////////////////////////////////////////
245 // Function: DCAtomicField::get_nested_field
246 // Access: Public, Virtual
247 // Description: Returns the DCPackerInterface object that represents
248 // the nth nested field. This may return NULL if there
249 // is no such field (but it shouldn't do this if n is in
250 // the range 0 <= n < get_num_nested_fields()).
251 ////////////////////////////////////////////////////////////////////
253 get_nested_field(int n) const {
254  nassertr(n >= 0 && n < (int)_elements.size(), NULL);
255  return _elements[n];
256 }
257 
258 ////////////////////////////////////////////////////////////////////
259 // Function: DCAtomicField::add_element
260 // Access: Public
261 // Description: Adds a new element (parameter) to the field.
262 // Normally this is called only during parsing. The
263 // DCAtomicField object becomes the owner of the new
264 // pointer and will delete it upon destruction.
265 ////////////////////////////////////////////////////////////////////
266 void DCAtomicField::
268  _elements.push_back(element);
269  _num_nested_fields = (int)_elements.size();
270 
271  // See if we still have a fixed byte size.
272  if (_has_fixed_byte_size) {
273  _has_fixed_byte_size = element->has_fixed_byte_size();
274  _fixed_byte_size += element->get_fixed_byte_size();
275  }
276  if (_has_fixed_structure) {
277  _has_fixed_structure = element->has_fixed_structure();
278  }
279  if (!_has_range_limits) {
280  _has_range_limits = element->has_range_limits();
281  }
282  if (!_has_default_value) {
283  _has_default_value = element->has_default_value();
284  }
285  _default_value_stale = true;
286 }
287 
288 ////////////////////////////////////////////////////////////////////
289 // Function: DCAtomicField::do_check_match
290 // Access: Protected, Virtual
291 // Description: Returns true if the other interface is bitwise the
292 // same as this one--that is, a uint32 only matches a
293 // uint32, etc. Names of components, and range limits,
294 // are not compared.
295 ////////////////////////////////////////////////////////////////////
296 bool DCAtomicField::
297 do_check_match(const DCPackerInterface *other) const {
298  return other->do_check_match_atomic_field(this);
299 }
300 
301 ////////////////////////////////////////////////////////////////////
302 // Function: DCAtomicField::do_check_match_atomic_field
303 // Access: Protected, Virtual
304 // Description: Returns true if this field matches the indicated
305 // atomic field, false otherwise.
306 ////////////////////////////////////////////////////////////////////
307 bool DCAtomicField::
308 do_check_match_atomic_field(const DCAtomicField *other) const {
309  if (_elements.size() != other->_elements.size()) {
310  return false;
311  }
312  for (size_t i = 0; i < _elements.size(); i++) {
313  if (!_elements[i]->check_match(other->_elements[i])) {
314  return false;
315  }
316  }
317 
318  return true;
319 }
320 
321 ////////////////////////////////////////////////////////////////////
322 // Function: DCAtomicField::output_element
323 // Access: Private
324 // Description:
325 ////////////////////////////////////////////////////////////////////
326 void DCAtomicField::
327 output_element(ostream &out, bool brief, DCParameter *element) const {
328  element->output(out, brief);
329 
330  if (!brief && element->has_default_value()) {
331  out << " = ";
332  DCPacker packer;
333  packer.set_unpack_data(element->get_default_value());
334  packer.begin_unpack(element);
335  packer.unpack_and_format(out, false);
336  packer.end_unpack();
337  }
338 }
virtual void generate_hash(HashGenerator &hashgen) const
Accumulates the properties of this field into the hash.
virtual DCAtomicField * as_atomic_field()
Returns the same field pointer converted to an atomic field pointer, if this is in fact an atomic fie...
const string & get_default_value() const
Returns the default value for this field.
Definition: dcField.I:60
bool has_fixed_structure() const
Returns true if this field type always has the same structure regardless of the data in the stream...
void add_int(int num)
Adds another integer to the hash so far.
A single field of a Distributed Class, either atomic or molecular.
Definition: dcField.h:40
DCParameter * get_element(int n) const
Returns the parameter object describing the nth element.
This is the most fundamental kind of parameter type: a single number or string, one of the DCSubatomi...
bool has_fixed_byte_size() const
Returns true if this field type always packs to the same number of bytes, false if it is variable...
Defines a particular DistributedClass as read from an input .dc file.
Definition: dcClass.h:47
A single atomic field of a Distributed Class, as read from a .dc file.
Definition: dcAtomicField.h:34
virtual void generate_hash(HashGenerator &hashgen) const
Accumulates the properties of this field into the hash.
Definition: dcField.cxx:528
size_t get_fixed_byte_size() const
If has_fixed_byte_size() returns true, this returns the number of bytes this field type will use...
void add_element(DCParameter *element)
Adds a new element (parameter) to the field.
bool has_range_limits() const
Returns true if this field, or any sub-field of this field, has a limit imposed in the DC file on its...
virtual void write(ostream &out, bool brief, int indent_level) const
Generates a parseable description of the object to the indicated output stream.
int get_num_elements() const
Returns the number of elements (parameters) of the atomic field.
Represents the type specification for a single parameter within a field specification.
Definition: dcParameter.h:39
DCSubatomicType get_element_type(int n) const
Returns the numeric type of the nth element of the field.
bool check_match(const DCPackerInterface *other) const
Returns true if the other interface is bitwise the same as this one–that is, a uint32 only matches a...
bool has_default_value() const
Returns true if a default value has been explicitly established for this field, false otherwise...
Definition: dcField.I:46
This class generates an arbitrary hash number from a sequence of ints.
Definition: hashGenerator.h:26
string unpack_and_format(bool show_field_names=true)
Unpacks an object and formats its value into a syntax suitable for parsing in the dc file (e...
Definition: dcPacker.cxx:1056
virtual bool do_check_match_atomic_field(const DCAtomicField *other) const
Returns true if this field matches the indicated atomic field, false otherwise.
void generate_hash(HashGenerator &hashgen) const
Accumulates the properties of these keywords into the hash.
This class can be used for packing a series of numeric and string data into a binary stream...
Definition: dcPacker.h:38
int get_element_divisor(int n) const
Returns the divisor associated with the nth element of the field.
void set_unpack_data(const string &data)
Sets up the unpack_data pointer.
Definition: dcPacker.cxx:125
string get_element_default(int n) const
Returns the pre-formatted default value associated with the nth element of the field.
This defines the internal interface for packing values into a DCField.
bool has_element_default(int n) const
Returns true if the nth element of the field has a default value specified, false otherwise...
string get_element_name(int n) const
Returns the name of the nth element of the field.
void begin_unpack(const DCPackerInterface *root)
Begins an unpacking session.
Definition: dcPacker.cxx:168
bool end_unpack()
Finishes the unpacking session.
Definition: dcPacker.cxx:197
virtual DCPackerInterface * get_nested_field(int n) const
Returns the DCPackerInterface object that represents the nth nested field.