Panda3D
 All Classes Functions Variables Enumerations
xFileDataNodeTemplate.cxx
00001 // Filename: xFileDataNodeTemplate.cxx
00002 // Created by:  drose (03Oct04)
00003 //
00004 ////////////////////////////////////////////////////////////////////
00005 //
00006 // PANDA 3D SOFTWARE
00007 // Copyright (c) Carnegie Mellon University.  All rights reserved.
00008 //
00009 // All use of this software is subject to the terms of the revised BSD
00010 // license.  You should have received a copy of this license along
00011 // with this source code in a file named "LICENSE."
00012 //
00013 ////////////////////////////////////////////////////////////////////
00014 
00015 #include "xFileDataNodeTemplate.h"
00016 #include "indent.h"
00017 #include "xFileParseData.h"
00018 #include "xLexerDefs.h"
00019 #include "config_xfile.h"
00020 
00021 TypeHandle XFileDataNodeTemplate::_type_handle;
00022 
00023 ////////////////////////////////////////////////////////////////////
00024 //     Function: XFileDataNodeTemplate::Constructor
00025 //       Access: Public
00026 //  Description:
00027 ////////////////////////////////////////////////////////////////////
00028 XFileDataNodeTemplate::
00029 XFileDataNodeTemplate(XFile *x_file, const string &name,
00030                       XFileTemplate *xtemplate) :
00031   XFileDataNode(x_file, name, xtemplate)
00032 {
00033 }
00034 
00035 ////////////////////////////////////////////////////////////////////
00036 //     Function: XFileDataNodeTemplate::zero_fill
00037 //       Access: Public
00038 //  Description: Fills the data node with zero-valued elements
00039 //               appropriate to the template.
00040 ////////////////////////////////////////////////////////////////////
00041 void XFileDataNodeTemplate::
00042 zero_fill() {
00043   _template->fill_zero_data(this);
00044 }
00045 
00046 ////////////////////////////////////////////////////////////////////
00047 //     Function: XFileDataNodeTemplate::is_complex_object
00048 //       Access: Public, Virtual
00049 //  Description: Returns true if this kind of data object is a complex
00050 //               object that can hold nested data elements, false
00051 //               otherwise.
00052 ////////////////////////////////////////////////////////////////////
00053 bool XFileDataNodeTemplate::
00054 is_complex_object() const {
00055   return true;
00056 }
00057 
00058 ////////////////////////////////////////////////////////////////////
00059 //     Function: XFileDataNodeTemplate::add_parse_double
00060 //       Access: Public
00061 //  Description: Adds the indicated list of doubles as a data element
00062 //               encountered in the parser.  It will later be
00063 //               processed by finalize_parse_data().
00064 ////////////////////////////////////////////////////////////////////
00065 void XFileDataNodeTemplate::
00066 add_parse_double(PTA_double double_list) {
00067   XFileParseData pdata;
00068   pdata._double_list = double_list;
00069   pdata._parse_flags = XFileParseData::PF_double;
00070 
00071   _parse_data_list._list.push_back(pdata);
00072 }
00073 
00074 ////////////////////////////////////////////////////////////////////
00075 //     Function: XFileDataNodeTemplate::add_parse_int
00076 //       Access: Public
00077 //  Description: Adds the indicated list of ints as a data element
00078 //               encountered in the parser.  It will later be
00079 //               processed by finalize_parse_data().
00080 ////////////////////////////////////////////////////////////////////
00081 void XFileDataNodeTemplate::
00082 add_parse_int(PTA_int int_list) {
00083   XFileParseData pdata;
00084   pdata._int_list = int_list;
00085   pdata._parse_flags = XFileParseData::PF_int;
00086 
00087   _parse_data_list._list.push_back(pdata);
00088 }
00089 
00090 ////////////////////////////////////////////////////////////////////
00091 //     Function: XFileDataNodeTemplate::add_parse_string
00092 //       Access: Public
00093 //  Description: Adds the indicated string as a data element
00094 //               encountered in the parser.  It will later be
00095 //               processed by finalize_parse_data().
00096 ////////////////////////////////////////////////////////////////////
00097 void XFileDataNodeTemplate::
00098 add_parse_string(const string &str) {
00099   XFileParseData pdata;
00100   pdata._string = str;
00101   pdata._parse_flags = XFileParseData::PF_string;
00102 
00103   _parse_data_list._list.push_back(pdata);
00104 }
00105 
00106 ////////////////////////////////////////////////////////////////////
00107 //     Function: XFileDataNodeTemplate::finalize_parse_data
00108 //       Access: Public
00109 //  Description: Processes all of the data elements added by
00110 //               add_parse_*(), checks them for syntactic and semantic
00111 //               correctness against the Template definition, and
00112 //               stores the appropriate child data elements.  Returns
00113 //               true on success, false if there is a mismatch.
00114 ////////////////////////////////////////////////////////////////////
00115 bool XFileDataNodeTemplate::
00116 finalize_parse_data() {
00117   // Recursively walk through our template definition, while
00118   // simultaneously walking through the list of parse data elements we
00119   // encountered, and re-pack them as actual nested elements.
00120   PrevData prev_data;
00121   size_t index = 0;
00122   size_t sub_index = 0;
00123 
00124   if (!_template->repack_data(this, _parse_data_list, 
00125                               prev_data, index, sub_index)) {
00126     return false;
00127   }
00128 
00129   if (index != _parse_data_list._list.size()) {
00130     xyywarning("Too many data elements in structure.");
00131   }
00132   
00133   return true;
00134 }
00135 
00136 ////////////////////////////////////////////////////////////////////
00137 //     Function: XFileDataNodeTemplate::add_element
00138 //       Access: Public, Virtual
00139 //  Description: Adds the indicated element as a nested data element,
00140 //               if this data object type supports it.  Returns true
00141 //               if added successfully, false if the data object type
00142 //               does not support nested data elements.
00143 ////////////////////////////////////////////////////////////////////
00144 bool XFileDataNodeTemplate::
00145 add_element(XFileDataObject *element) {
00146   _nested_elements.push_back(element);
00147   return true;
00148 }
00149 
00150 ////////////////////////////////////////////////////////////////////
00151 //     Function: XFileDataNodeTemplate::write_text
00152 //       Access: Public, Virtual
00153 //  Description: Writes a suitable representation of this node to an
00154 //               .x file in text mode.
00155 ////////////////////////////////////////////////////////////////////
00156 void XFileDataNodeTemplate::
00157 write_text(ostream &out, int indent_level) const {
00158   indent(out, indent_level)
00159     << _template->get_name();
00160   if (has_name()) {
00161     out << " " << get_name();
00162   }
00163   out << " {\n";
00164 
00165   NestedElements::const_iterator ni;
00166   for (ni = _nested_elements.begin(); ni != _nested_elements.end(); ++ni) {
00167     (*ni)->write_data(out, indent_level + 2, ";");
00168   }
00169 
00170   XFileNode::write_text(out, indent_level + 2);
00171   indent(out, indent_level)
00172     << "}\n";
00173 }
00174 
00175 ////////////////////////////////////////////////////////////////////
00176 //     Function: XFileDataNodeTemplate::write_data
00177 //       Access: Public, Virtual
00178 //  Description: Writes a suitable representation of this node to an
00179 //               .x file in text mode.
00180 ////////////////////////////////////////////////////////////////////
00181 void XFileDataNodeTemplate::
00182 write_data(ostream &out, int indent_level, const char *separator) const {
00183   if (!_nested_elements.empty()) {
00184     bool indented = false;
00185     for (size_t i = 0; i < _nested_elements.size() - 1; i++) {
00186       XFileDataObject *object = _nested_elements[i];
00187       if (object->is_complex_object()) {
00188         // If we have a "complex" nested object, output it on its own
00189         // line.
00190         if (indented) {
00191           out << "\n";
00192           indented = false;
00193         }
00194         object->write_data(out, indent_level, ";");
00195 
00196       } else {
00197         // Otherwise, output them all on the same line.
00198         if (!indented) {
00199           indent(out, indent_level);
00200           indented = true;
00201         }
00202         out << *object << "; ";
00203       }
00204     }
00205 
00206     // The last object is the set is different, because it gets
00207     // separator appended to it, and it always gets a newline.
00208     XFileDataObject *object = _nested_elements.back();
00209     if (object->is_complex_object()) {
00210       if (indented) {
00211         out << "\n";
00212       }
00213       string combined_separator = string(";") + string(separator);
00214       object->write_data(out, indent_level, combined_separator.c_str());
00215 
00216     } else {
00217       if (!indented) {
00218         indent(out, indent_level);
00219       }
00220       out << *object << ";" << separator << "\n";
00221     }
00222   }
00223 }
00224 
00225 ////////////////////////////////////////////////////////////////////
00226 //     Function: XFileDataNodeTemplate::get_num_elements
00227 //       Access: Protected, Virtual
00228 //  Description: Returns the number of nested data elements within the
00229 //               object.  This may be, e.g. the size of the array, if
00230 //               it is an array.
00231 ////////////////////////////////////////////////////////////////////
00232 int XFileDataNodeTemplate::
00233 get_num_elements() const {
00234   return _nested_elements.size();
00235 }
00236 
00237 ////////////////////////////////////////////////////////////////////
00238 //     Function: XFileDataNodeTemplate::get_element
00239 //       Access: Protected, Virtual
00240 //  Description: Returns the nth nested data element within the
00241 //               object.
00242 ////////////////////////////////////////////////////////////////////
00243 XFileDataObject *XFileDataNodeTemplate::
00244 get_element(int n) {
00245   nassertr(n >= 0 && n < (int)_nested_elements.size(), NULL);
00246   return _nested_elements[n];
00247 }
00248 
00249 ////////////////////////////////////////////////////////////////////
00250 //     Function: XFileDataNodeTemplate::get_element
00251 //       Access: Protected, Virtual
00252 //  Description: Returns the nested data element within the
00253 //               object that has the indicated name.
00254 ////////////////////////////////////////////////////////////////////
00255 XFileDataObject *XFileDataNodeTemplate::
00256 get_element(const string &name) {
00257   int child_index = _template->find_child_index(name);
00258   if (child_index >= 0) {
00259     return get_element(child_index);
00260   }
00261   xfile_cat.warning()
00262     << "\"" << name << "\" not a member of " << _template->get_name()
00263     << "\n";
00264   return NULL;
00265 }
 All Classes Functions Variables Enumerations