Panda3D
xFileDataNodeTemplate.cxx
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 xFileDataNodeTemplate.cxx
10  * @author drose
11  * @date 2004-10-03
12  */
13 
14 #include "xFileDataNodeTemplate.h"
15 #include "indent.h"
16 #include "xFileParseData.h"
17 #include "xLexerDefs.h"
18 #include "config_xfile.h"
19 
20 using std::string;
21 
22 TypeHandle XFileDataNodeTemplate::_type_handle;
23 
24 /**
25  *
26  */
27 XFileDataNodeTemplate::
28 XFileDataNodeTemplate(XFile *x_file, const string &name,
29  XFileTemplate *xtemplate) :
30  XFileDataNode(x_file, name, xtemplate)
31 {
32 }
33 
34 /**
35  * Fills the data node with zero-valued elements appropriate to the template.
36  */
39  _template->fill_zero_data(this);
40 }
41 
42 /**
43  * Returns true if this kind of data object is a complex object that can hold
44  * nested data elements, false otherwise.
45  */
48  return true;
49 }
50 
51 /**
52  * Adds the indicated list of doubles as a data element encountered in the
53  * parser. It will later be processed by finalize_parse_data().
54  */
56 add_parse_double(PTA_double double_list) {
57  XFileParseData pdata;
58  pdata._double_list = double_list;
59  pdata._parse_flags = XFileParseData::PF_double;
60 
61  _parse_data_list._list.push_back(pdata);
62 }
63 
64 /**
65  * Adds the indicated list of ints as a data element encountered in the
66  * parser. It will later be processed by finalize_parse_data().
67  */
69 add_parse_int(PTA_int int_list) {
70  XFileParseData pdata;
71  pdata._int_list = int_list;
72  pdata._parse_flags = XFileParseData::PF_int;
73 
74  _parse_data_list._list.push_back(pdata);
75 }
76 
77 /**
78  * Adds the indicated string as a data element encountered in the parser. It
79  * will later be processed by finalize_parse_data().
80  */
82 add_parse_string(const string &str) {
83  XFileParseData pdata;
84  pdata._string = str;
85  pdata._parse_flags = XFileParseData::PF_string;
86 
87  _parse_data_list._list.push_back(pdata);
88 }
89 
90 /**
91  * Processes all of the data elements added by add_parse_*(), checks them for
92  * syntactic and semantic correctness against the Template definition, and
93  * stores the appropriate child data elements. Returns true on success, false
94  * if there is a mismatch.
95  */
98  // Recursively walk through our template definition, while simultaneously
99  // walking through the list of parse data elements we encountered, and re-
100  // pack them as actual nested elements.
101  PrevData prev_data;
102  size_t index = 0;
103  size_t sub_index = 0;
104 
105  if (!_template->repack_data(this, _parse_data_list,
106  prev_data, index, sub_index)) {
107  return false;
108  }
109 
110  if (index != _parse_data_list._list.size()) {
111  xyywarning("Too many data elements in structure.");
112  }
113 
114  return true;
115 }
116 
117 /**
118  * Adds the indicated element as a nested data element, if this data object
119  * type supports it. Returns true if added successfully, false if the data
120  * object type does not support nested data elements.
121  */
124  _nested_elements.push_back(element);
125  return true;
126 }
127 
128 /**
129  * Writes a suitable representation of this node to an .x file in text mode.
130  */
132 write_text(std::ostream &out, int indent_level) const {
133  indent(out, indent_level)
134  << _template->get_name();
135  if (has_name()) {
136  out << " " << get_name();
137  }
138  out << " {\n";
139 
140  NestedElements::const_iterator ni;
141  for (ni = _nested_elements.begin(); ni != _nested_elements.end(); ++ni) {
142  (*ni)->write_data(out, indent_level + 2, ";");
143  }
144 
145  XFileNode::write_text(out, indent_level + 2);
146  indent(out, indent_level)
147  << "}\n";
148 }
149 
150 /**
151  * Writes a suitable representation of this node to an .x file in text mode.
152  */
154 write_data(std::ostream &out, int indent_level, const char *separator) const {
155  if (!_nested_elements.empty()) {
156  bool indented = false;
157  for (size_t i = 0; i < _nested_elements.size() - 1; i++) {
158  XFileDataObject *object = _nested_elements[i];
159  if (object->is_complex_object()) {
160  // If we have a "complex" nested object, output it on its own line.
161  if (indented) {
162  out << "\n";
163  indented = false;
164  }
165  object->write_data(out, indent_level, ";");
166 
167  } else {
168  // Otherwise, output them all on the same line.
169  if (!indented) {
170  indent(out, indent_level);
171  indented = true;
172  }
173  out << *object << "; ";
174  }
175  }
176 
177  // The last object is the set is different, because it gets separator
178  // appended to it, and it always gets a newline.
179  XFileDataObject *object = _nested_elements.back();
180  if (object->is_complex_object()) {
181  if (indented) {
182  out << "\n";
183  }
184  string combined_separator = string(";") + string(separator);
185  object->write_data(out, indent_level, combined_separator.c_str());
186 
187  } else {
188  if (!indented) {
189  indent(out, indent_level);
190  }
191  out << *object << ";" << separator << "\n";
192  }
193  }
194 }
195 
196 /**
197  * Returns the number of nested data elements within the object. This may be,
198  * e.g. the size of the array, if it is an array.
199  */
200 int XFileDataNodeTemplate::
201 get_num_elements() const {
202  return _nested_elements.size();
203 }
204 
205 /**
206  * Returns the nth nested data element within the object.
207  */
208 XFileDataObject *XFileDataNodeTemplate::
209 get_element(int n) {
210  nassertr(n >= 0 && n < (int)_nested_elements.size(), nullptr);
211  return _nested_elements[n];
212 }
213 
214 /**
215  * Returns the nested data element within the object that has the indicated
216  * name.
217  */
218 XFileDataObject *XFileDataNodeTemplate::
219 get_element(const string &name) {
220  int child_index = _template->find_child_index(name);
221  if (child_index >= 0) {
222  return get_element(child_index);
223  }
224  xfile_cat.warning()
225  << "\"" << name << "\" not a member of " << _template->get_name()
226  << "\n";
227  return nullptr;
228 }
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:49
void add_parse_double(PTA_double double_list)
Adds the indicated list of doubles as a data element encountered in the parser.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
int i() const
Unambiguously returns the object's representation as an integer, or 0 if the object has no integer re...
virtual void write_text(std::ostream &out, int indent_level) const
Writes a suitable representation of this node to an .x file in text mode.
Definition: xFileNode.cxx:219
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(std::ostream &out, int indent_level) const
Writes a suitable representation of this node to an .x file in text mode.
virtual void write_data(std::ostream &out, int indent_level, const char *separator) const
Writes a suitable representation of this node to an .x file in text mode.
std::ostream & indent(std::ostream &out, int indent_level)
A handy function for doing text formatting.
Definition: indent.cxx:20
virtual bool is_complex_object() const
Returns true if this kind of data object is a complex object that can hold nested data elements,...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
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:33
This represents the complete contents of an X file (file.x) in memory.
Definition: xFile.h:32
A template definition in the X file.
Definition: xFileTemplate.h:27
bool has_name() const
Returns true if the Namable has a nonempty name set, false if the name is empty.
Definition: namable.I:44
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:81
void add_parse_string(const std::string &str)
Adds the indicated string as a data element encountered in the parser.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
The abstract base class for a number of different types of data elements that may be stored in the X ...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.