Panda3D
xFileDataNodeTemplate.cxx
1 // Filename: xFileDataNodeTemplate.cxx
2 // Created by: drose (03Oct04)
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 "xFileDataNodeTemplate.h"
16 #include "indent.h"
17 #include "xFileParseData.h"
18 #include "xLexerDefs.h"
19 #include "config_xfile.h"
20 
21 TypeHandle XFileDataNodeTemplate::_type_handle;
22 
23 ////////////////////////////////////////////////////////////////////
24 // Function: XFileDataNodeTemplate::Constructor
25 // Access: Public
26 // Description:
27 ////////////////////////////////////////////////////////////////////
28 XFileDataNodeTemplate::
29 XFileDataNodeTemplate(XFile *x_file, const string &name,
30  XFileTemplate *xtemplate) :
31  XFileDataNode(x_file, name, xtemplate)
32 {
33 }
34 
35 ////////////////////////////////////////////////////////////////////
36 // Function: XFileDataNodeTemplate::zero_fill
37 // Access: Public
38 // Description: Fills the data node with zero-valued elements
39 // appropriate to the template.
40 ////////////////////////////////////////////////////////////////////
43  _template->fill_zero_data(this);
44 }
45 
46 ////////////////////////////////////////////////////////////////////
47 // Function: XFileDataNodeTemplate::is_complex_object
48 // Access: Public, Virtual
49 // Description: Returns true if this kind of data object is a complex
50 // object that can hold nested data elements, false
51 // otherwise.
52 ////////////////////////////////////////////////////////////////////
55  return true;
56 }
57 
58 ////////////////////////////////////////////////////////////////////
59 // Function: XFileDataNodeTemplate::add_parse_double
60 // Access: Public
61 // Description: Adds the indicated list of doubles as a data element
62 // encountered in the parser. It will later be
63 // processed by finalize_parse_data().
64 ////////////////////////////////////////////////////////////////////
66 add_parse_double(PTA_double double_list) {
67  XFileParseData pdata;
68  pdata._double_list = double_list;
69  pdata._parse_flags = XFileParseData::PF_double;
70 
71  _parse_data_list._list.push_back(pdata);
72 }
73 
74 ////////////////////////////////////////////////////////////////////
75 // Function: XFileDataNodeTemplate::add_parse_int
76 // Access: Public
77 // Description: Adds the indicated list of ints as a data element
78 // encountered in the parser. It will later be
79 // processed by finalize_parse_data().
80 ////////////////////////////////////////////////////////////////////
82 add_parse_int(PTA_int int_list) {
83  XFileParseData pdata;
84  pdata._int_list = int_list;
85  pdata._parse_flags = XFileParseData::PF_int;
86 
87  _parse_data_list._list.push_back(pdata);
88 }
89 
90 ////////////////////////////////////////////////////////////////////
91 // Function: XFileDataNodeTemplate::add_parse_string
92 // Access: Public
93 // Description: Adds the indicated string as a data element
94 // encountered in the parser. It will later be
95 // processed by finalize_parse_data().
96 ////////////////////////////////////////////////////////////////////
98 add_parse_string(const string &str) {
99  XFileParseData pdata;
100  pdata._string = str;
101  pdata._parse_flags = XFileParseData::PF_string;
102 
103  _parse_data_list._list.push_back(pdata);
104 }
105 
106 ////////////////////////////////////////////////////////////////////
107 // Function: XFileDataNodeTemplate::finalize_parse_data
108 // Access: Public
109 // Description: Processes all of the data elements added by
110 // add_parse_*(), checks them for syntactic and semantic
111 // correctness against the Template definition, and
112 // stores the appropriate child data elements. Returns
113 // true on success, false if there is a mismatch.
114 ////////////////////////////////////////////////////////////////////
117  // Recursively walk through our template definition, while
118  // simultaneously walking through the list of parse data elements we
119  // encountered, and re-pack them as actual nested elements.
120  PrevData prev_data;
121  size_t index = 0;
122  size_t sub_index = 0;
123 
124  if (!_template->repack_data(this, _parse_data_list,
125  prev_data, index, sub_index)) {
126  return false;
127  }
128 
129  if (index != _parse_data_list._list.size()) {
130  xyywarning("Too many data elements in structure.");
131  }
132 
133  return true;
134 }
135 
136 ////////////////////////////////////////////////////////////////////
137 // Function: XFileDataNodeTemplate::add_element
138 // Access: Public, Virtual
139 // Description: Adds the indicated element as a nested data element,
140 // if this data object type supports it. Returns true
141 // if added successfully, false if the data object type
142 // does not support nested data elements.
143 ////////////////////////////////////////////////////////////////////
146  _nested_elements.push_back(element);
147  return true;
148 }
149 
150 ////////////////////////////////////////////////////////////////////
151 // Function: XFileDataNodeTemplate::write_text
152 // Access: Public, Virtual
153 // Description: Writes a suitable representation of this node to an
154 // .x file in text mode.
155 ////////////////////////////////////////////////////////////////////
157 write_text(ostream &out, int indent_level) const {
158  indent(out, indent_level)
159  << _template->get_name();
160  if (has_name()) {
161  out << " " << get_name();
162  }
163  out << " {\n";
164 
165  NestedElements::const_iterator ni;
166  for (ni = _nested_elements.begin(); ni != _nested_elements.end(); ++ni) {
167  (*ni)->write_data(out, indent_level + 2, ";");
168  }
169 
170  XFileNode::write_text(out, indent_level + 2);
171  indent(out, indent_level)
172  << "}\n";
173 }
174 
175 ////////////////////////////////////////////////////////////////////
176 // Function: XFileDataNodeTemplate::write_data
177 // Access: Public, Virtual
178 // Description: Writes a suitable representation of this node to an
179 // .x file in text mode.
180 ////////////////////////////////////////////////////////////////////
182 write_data(ostream &out, int indent_level, const char *separator) const {
183  if (!_nested_elements.empty()) {
184  bool indented = false;
185  for (size_t i = 0; i < _nested_elements.size() - 1; i++) {
186  XFileDataObject *object = _nested_elements[i];
187  if (object->is_complex_object()) {
188  // If we have a "complex" nested object, output it on its own
189  // line.
190  if (indented) {
191  out << "\n";
192  indented = false;
193  }
194  object->write_data(out, indent_level, ";");
195 
196  } else {
197  // Otherwise, output them all on the same line.
198  if (!indented) {
199  indent(out, indent_level);
200  indented = true;
201  }
202  out << *object << "; ";
203  }
204  }
205 
206  // The last object is the set is different, because it gets
207  // separator appended to it, and it always gets a newline.
208  XFileDataObject *object = _nested_elements.back();
209  if (object->is_complex_object()) {
210  if (indented) {
211  out << "\n";
212  }
213  string combined_separator = string(";") + string(separator);
214  object->write_data(out, indent_level, combined_separator.c_str());
215 
216  } else {
217  if (!indented) {
218  indent(out, indent_level);
219  }
220  out << *object << ";" << separator << "\n";
221  }
222  }
223 }
224 
225 ////////////////////////////////////////////////////////////////////
226 // Function: XFileDataNodeTemplate::get_num_elements
227 // Access: Protected, Virtual
228 // Description: Returns the number of nested data elements within the
229 // object. This may be, e.g. the size of the array, if
230 // it is an array.
231 ////////////////////////////////////////////////////////////////////
232 int XFileDataNodeTemplate::
233 get_num_elements() const {
234  return _nested_elements.size();
235 }
236 
237 ////////////////////////////////////////////////////////////////////
238 // Function: XFileDataNodeTemplate::get_element
239 // Access: Protected, Virtual
240 // Description: Returns the nth nested data element within the
241 // object.
242 ////////////////////////////////////////////////////////////////////
243 XFileDataObject *XFileDataNodeTemplate::
244 get_element(int n) {
245  nassertr(n >= 0 && n < (int)_nested_elements.size(), NULL);
246  return _nested_elements[n];
247 }
248 
249 ////////////////////////////////////////////////////////////////////
250 // Function: XFileDataNodeTemplate::get_element
251 // Access: Protected, Virtual
252 // Description: Returns the nested data element within the
253 // object that has the indicated name.
254 ////////////////////////////////////////////////////////////////////
255 XFileDataObject *XFileDataNodeTemplate::
256 get_element(const string &name) {
257  int child_index = _template->find_child_index(name);
258  if (child_index >= 0) {
259  return get_element(child_index);
260  }
261  xfile_cat.warning()
262  << "\"" << name << "\" not a member of " << _template->get_name()
263  << "\n";
264  return NULL;
265 }
virtual bool add_element(XFileDataObject *element)
Adds the indicated element as a nested data element, if this data object type supports it...
This is our own Panda specialization on the default STL map.
Definition: pmap.h:52
virtual void write_text(ostream &out, int indent_level) const
Writes a suitable representation of this node to an .x file in text mode.
void add_parse_double(PTA_double double_list)
Adds the indicated list of doubles as a data element encountered in the parser.
int i() const
Unambiguously returns the object&#39;s representation as an integer, or 0 if the object has no integer re...
This class is used to fill up the data into an XFileDataNodeTemplate object as the data values are pa...
void zero_fill()
Fills the data node with zero-valued elements appropriate to the template.
void add_parse_int(PTA_int int_list)
Adds the indicated list of ints as a data element encountered in the parser.
virtual void write_text(ostream &out, int indent_level) const
Writes a suitable representation of this node to an .x file in text mode.
Definition: xFileNode.cxx:263
virtual void write_data(ostream &out, int indent_level, const char *separator) const
Writes a suitable representation of this node to an .x file in text mode.
void add_parse_string(const string &str)
Adds the indicated string as a data element encountered in the parser.
virtual bool is_complex_object() const
Returns true if this kind of data object is a complex object that can hold nested data elements...
bool finalize_parse_data()
Processes all of the data elements added by add_parse_*(), checks them for syntactic and semantic cor...
This is an abstract base class for an XFileNode which is also an XFileDataObject. ...
Definition: xFileDataNode.h:36
This represents the complete contents of an X file (file.x) in memory.
Definition: xFile.h:35
A template definition in the X file.
Definition: xFileTemplate.h:29
bool has_name() const
Returns true if the Namable has a nonempty name set, false if the name is empty.
Definition: namable.I:75
virtual bool is_complex_object() const
Returns true if this kind of data object is a complex object that can hold nested data elements...
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:85
The abstract base class for a number of different types of data elements that may be stored in the X ...