more parser stuff

This commit is contained in:
David Rose 2004-10-08 00:45:23 +00:00
parent 8ce7d33fd8
commit e4bd5e2c46
31 changed files with 1554 additions and 131 deletions

View File

@ -20,8 +20,12 @@
xFileArrayDef.cxx xFileArrayDef.I xFileArrayDef.h \
xFileDataDef.cxx xFileDataDef.I xFileDataDef.h \
xFileDataObject.cxx xFileDataObject.I xFileDataObject.h \
xFileDataObjectArray.cxx xFileDataObjectArray.I xFileDataObjectArray.h \
xFileDataObjectDouble.cxx xFileDataObjectDouble.I xFileDataObjectDouble.h \
xFileDataObjectInteger.cxx xFileDataObjectInteger.I xFileDataObjectInteger.h \
xFileDataObjectTemplate.cxx xFileDataObjectTemplate.I xFileDataObjectTemplate.h \
xFileNode.cxx xFileNode.I xFileNode.h \
xFileParseData.cxx xFileParseData.I xFileParseData.h \
xFileTemplate.cxx xFileTemplate.I xFileTemplate.h
#end ss_lib_target

View File

@ -20,6 +20,9 @@
#include "xFile.h"
#include "xFileDataDef.h"
#include "xFileDataObject.h"
#include "xFileDataObjectArray.h"
#include "xFileDataObjectDouble.h"
#include "xFileDataObjectInteger.h"
#include "xFileDataObjectTemplate.h"
#include "xFileNode.h"
#include "xFileTemplate.h"
@ -58,6 +61,9 @@ init_libxfile() {
XFile::init_type();
XFileDataDef::init_type();
XFileDataObject::init_type();
XFileDataObjectArray::init_type();
XFileDataObjectDouble::init_type();
XFileDataObjectInteger::init_type();
XFileDataObjectTemplate::init_type();
XFileNode::init_type();
XFileTemplate::init_type();

View File

@ -20,7 +20,7 @@
#include "xParserDefs.h"
#include "xLexerDefs.h"
#include "xFileTemplate.h"
#include "xFileDataObject.h"
#include "xFileDataObjectTemplate.h"
#include "config_xfile.h"
#include "standard_templates.h"
#include "zStream.h"
@ -250,12 +250,12 @@ find_template(const WindowsGuid &guid) const {
// Description: Returns the data object associated with the indicated
// name, if any, or NULL if none.
////////////////////////////////////////////////////////////////////
XFileDataObject *XFile::
XFileDataObjectTemplate *XFile::
find_data_object(const string &name) const {
XFileNode *child = find_descendent(name);
if (child != (XFileNode *)NULL &&
child->is_of_type(XFileDataObject::get_class_type())) {
return DCAST(XFileDataObject, child);
child->is_of_type(XFileDataObjectTemplate::get_class_type())) {
return DCAST(XFileDataObjectTemplate, child);
}
return NULL;
@ -267,13 +267,13 @@ find_data_object(const string &name) const {
// Description: Returns the data object associated with the indicated
// GUID, if any, or NULL if none.
////////////////////////////////////////////////////////////////////
XFileDataObject *XFile::
XFileDataObjectTemplate *XFile::
find_data_object(const WindowsGuid &guid) const {
NodesByGuid::const_iterator gi;
gi = _nodes_by_guid.find(guid);
if (gi != _nodes_by_guid.end() &&
(*gi).second->is_of_type(XFileDataObject::get_class_type())) {
return DCAST(XFileDataObject, (*gi).second);
(*gi).second->is_of_type(XFileDataObjectTemplate::get_class_type())) {
return DCAST(XFileDataObjectTemplate, (*gi).second);
}
return NULL;

View File

@ -27,7 +27,7 @@
#include "pointerTo.h"
class XFileTemplate;
class XFileDataObject;
class XFileDataObjectTemplate;
////////////////////////////////////////////////////////////////////
// Class : XFile
@ -51,8 +51,8 @@ public:
XFileTemplate *find_template(const string &name) const;
XFileTemplate *find_template(const WindowsGuid &guid) const;
XFileDataObject *find_data_object(const string &name) const;
XFileDataObject *find_data_object(const WindowsGuid &guid) const;
XFileDataObjectTemplate *find_data_object(const string &name) const;
XFileDataObjectTemplate *find_data_object(const WindowsGuid &guid) const;
virtual void write_text(ostream &out, int indent_level) const;

View File

@ -18,6 +18,30 @@
#include "xFileArrayDef.h"
#include "xFileDataDef.h"
#include "xFileDataObject.h"
////////////////////////////////////////////////////////////////////
// Function: XFileArrayDef::get_size
// Access: Public
// Description: Returns the size of the array dimension. If this is
// a fixed array, the size is trivial; if it is dynamic,
// the size is determined by looking up the dynamic_size
// element in the prev_data table (which lists all of
// the data values already defined at this scoping
// level).
////////////////////////////////////////////////////////////////////
int XFileArrayDef::
get_size(const XFileNode::PrevData &prev_data) const {
if (is_fixed_size()) {
return _fixed_size;
} else {
XFileNode::PrevData::const_iterator pi;
pi = prev_data.find(_dynamic_size);
nassertr(pi != prev_data.end(), 0);
nassertr((*pi).second != (XFileDataObject *)NULL, 0);
return (*pi).second->i();
}
}
////////////////////////////////////////////////////////////////////
// Function: XFileArrayDef::output

View File

@ -21,6 +21,7 @@
#include "pandatoolbase.h"
#include "notify.h"
#include "xFileNode.h"
class XFileDataDef;
@ -38,6 +39,8 @@ public:
INLINE int get_fixed_size() const;
INLINE XFileDataDef *get_dynamic_size() const;
int get_size(const XFileNode::PrevData &prev_data) const;
void output(ostream &out) const;
private:

View File

@ -18,6 +18,12 @@
#include "xFileDataDef.h"
#include "indent.h"
#include "xLexerDefs.h"
#include "xFileParseData.h"
#include "xFileDataObjectInteger.h"
#include "xFileDataObjectDouble.h"
#include "xFileDataObjectTemplate.h"
#include "xFileDataObjectArray.h"
TypeHandle XFileDataDef::_type_handle;
@ -128,3 +134,291 @@ write_text(ostream &out, int indent_level) const {
out << ";\n";
}
////////////////////////////////////////////////////////////////////
// Function: XFileDataDef::repack_data
// Access: Public, Virtual
// Description: This is called on the template that defines an
// object, once the data for the object has been parsed.
// It is responsible for identifying which component of
// the template owns each data element, and packing the
// data elements appropriately back into the object.
//
// It returns true on success, or false on an error
// (e.g. too many semicolons, not enough data elements,
// mismatched data type).
////////////////////////////////////////////////////////////////////
bool XFileDataDef::
repack_data(XFileDataObject *object,
const XFileParseDataList &parse_data_list,
XFileDataDef::PrevData &prev_data,
size_t &index, size_t &sub_index) const {
if (index >= parse_data_list._list.size()) {
xyyerror("Not enough data elements in structure.");
return false;
}
// We'll fill this in with the data value we pack, if any.
PT(XFileDataObject) data_value;
// What kind of data element are we expecting?
switch (_type) {
case T_word:
case T_dword:
case T_char:
case T_uchar:
case T_sword:
case T_sdword:
// Expected integer data.
data_value = unpack_value(parse_data_list, 0,
prev_data, index, sub_index,
XFileParseData::PF_semicolon,
&XFileDataDef::unpack_integer_value);
break;
case T_float:
case T_double:
data_value = unpack_value(parse_data_list, 0,
prev_data, index, sub_index,
XFileParseData::PF_semicolon,
&XFileDataDef::unpack_double_value);
break;
case T_template:
data_value = unpack_value(parse_data_list, 0,
prev_data, index, sub_index,
XFileParseData::PF_semicolon,
&XFileDataDef::unpack_template_value);
break;
default:
{
const XFileParseData &parse_data = parse_data_list._list[index];
parse_data.yyerror("Unexpected data for " + get_name());
}
return false;
}
if (data_value != (XFileDataObject *)NULL) {
if (!object->add_element(data_value)) {
// This is really an internal error--this shouldn't happen.
const XFileParseData &parse_data = parse_data_list._list[index];
parse_data.yyerror("Data does not accept a nested element.");
}
}
prev_data[this] = data_value;
return XFileNode::repack_data(object, parse_data_list,
prev_data, index, sub_index);
}
////////////////////////////////////////////////////////////////////
// Function: XFileDataDef::unpack_integer_value
// Access: Private
// Description: Unpacks and returns the next sequential integer value
// from the parse_data_list.
////////////////////////////////////////////////////////////////////
PT(XFileDataObject) XFileDataDef::
unpack_integer_value(const XFileParseDataList &parse_data_list,
const XFileDataDef::PrevData &prev_data,
size_t &index, size_t &sub_index,
int separator_mask) const {
const XFileParseData &parse_data = parse_data_list._list[index];
PT(XFileDataObject) data_value;
if ((parse_data._parse_flags & XFileParseData::PF_int) != 0) {
nassertr(sub_index < parse_data._int_list.size(), false);
int value = parse_data._int_list[sub_index];
data_value = new XFileDataObjectInteger(this, value);
sub_index++;
if (sub_index >= parse_data._int_list.size()) {
index++;
sub_index = 0;
}
if (separator_mask != 0) {
// Now consume a separator character. These may be defined
// implicitly on an integer list.
if ((parse_data._parse_flags & separator_mask) == 0) {
// The separator we were looking for wasn't what was being
// used to delimit the list. As a special exception, if we
// just reached the end of the list and the next token is a
// standalone separator that matches what we expect, take that
// one.
if (sub_index == 0 && index < parse_data_list._list.size() &&
parse_data_list._list[index]._parse_flags == separator_mask) {
// Bingo! This is the special case--we incremented past
// the end of the list to a standalone separator.
index++;
} else {
// Some other case; the separator character we were
// expecting isn't to be found.
if ((separator_mask & XFileParseData::PF_semicolon) != 0) {
parse_data.yyerror("Semicolon expected.");
} else {
parse_data.yyerror("Comma expected.");
}
}
}
}
} else {
parse_data.yyerror("Expected integer data for " + get_name());
}
return data_value;
}
////////////////////////////////////////////////////////////////////
// Function: XFileDataDef::unpack_double_value
// Access: Private
// Description: Unpacks and returns the next sequential double value
// from the parse_data_list.
////////////////////////////////////////////////////////////////////
PT(XFileDataObject) XFileDataDef::
unpack_double_value(const XFileParseDataList &parse_data_list,
const XFileDataDef::PrevData &prev_data,
size_t &index, size_t &sub_index,
int separator_mask) const {
const XFileParseData &parse_data = parse_data_list._list[index];
PT(XFileDataObject) data_value;
if ((parse_data._parse_flags & XFileParseData::PF_double) != 0) {
if (separator_mask != 0 &&
(parse_data._parse_flags & separator_mask) == 0) {
if ((separator_mask & XFileParseData::PF_semicolon) != 0) {
parse_data.yyerror("Semicolon expected.");
} else {
parse_data.yyerror("Comma expected.");
}
} else {
nassertr(sub_index < parse_data._double_list.size(), false);
double value = parse_data._double_list[sub_index];
data_value = new XFileDataObjectDouble(this, value);
sub_index++;
if (sub_index >= parse_data._double_list.size()) {
index++;
sub_index = 0;
}
}
} else if ((parse_data._parse_flags & XFileParseData::PF_int) != 0) {
if (separator_mask != 0 &&
(parse_data._parse_flags & separator_mask) == 0) {
if ((separator_mask & XFileParseData::PF_semicolon) != 0) {
parse_data.yyerror("Semicolon expected.");
} else {
parse_data.yyerror("Comma expected.");
}
} else {
nassertr(sub_index < parse_data._int_list.size(), false);
int value = parse_data._int_list[sub_index];
data_value = new XFileDataObjectDouble(this, value);
sub_index++;
if (sub_index >= parse_data._int_list.size()) {
index++;
sub_index = 0;
}
}
} else {
parse_data.yyerror("Expected floating-point data for " + get_name());
}
return data_value;
}
////////////////////////////////////////////////////////////////////
// Function: XFileDataDef::unpack_template_value
// Access: Private
// Description: Unpacks a nested template object's data.
////////////////////////////////////////////////////////////////////
PT(XFileDataObject) XFileDataDef::
unpack_template_value(const XFileParseDataList &parse_data_list,
const XFileDataDef::PrevData &prev_data,
size_t &index, size_t &sub_index,
int separator_mask) const {
PT(XFileDataObjectTemplate) data_value =
new XFileDataObjectTemplate(get_x_file(), get_name(), _template);
PrevData nested_prev_data(prev_data);
if (!_template->repack_data(data_value, parse_data_list,
nested_prev_data, index, sub_index)) {
return NULL;
}
if (separator_mask != 0) {
// Also expect a trailing semicolon or comma.
if (index >= parse_data_list._list.size()) {
if ((separator_mask & XFileParseData::PF_semicolon) != 0) {
xyyerror("Semicolon expected.");
} else {
xyyerror("Comma expected.");
}
return NULL;
}
const XFileParseData &new_parse_data = parse_data_list._list[index];
if ((new_parse_data._parse_flags & XFileParseData::PF_any_data) != 0 ||
(new_parse_data._parse_flags & separator_mask) == 0) {
if ((separator_mask & XFileParseData::PF_semicolon) != 0) {
new_parse_data.yyerror("Semicolon expected.");
} else {
new_parse_data.yyerror("Comma expected.");
}
return false;
}
index++;
}
return data_value.p();
}
////////////////////////////////////////////////////////////////////
// Function: XFileDataDef::unpack_value
// Access: Private
// Description: Unpacks and returns the next sequential value, of the
// type supported by the unpack_method. If the value
// is an array type, unpacks all the elements of the
// array.
////////////////////////////////////////////////////////////////////
PT(XFileDataObject) XFileDataDef::
unpack_value(const XFileParseDataList &parse_data_list, int array_index,
const XFileDataDef::PrevData &prev_data,
size_t &index, size_t &sub_index, int separator_mask,
XFileDataDef::UnpackMethod unpack_method) const {
PT(XFileDataObject) data_value;
if (array_index == (int)_array_def.size()) {
data_value = (this->*unpack_method)(parse_data_list, prev_data,
index, sub_index, separator_mask);
} else {
data_value = new XFileDataObjectArray(this);
int array_size = _array_def[array_index].get_size(prev_data);
for (int i = 0; i < array_size - 1; i++) {
PT(XFileDataObject) array_element =
unpack_value(parse_data_list, array_index + 1,
prev_data, index, sub_index,
XFileParseData::PF_comma, unpack_method);
data_value->add_element(array_element);
}
PT(XFileDataObject) array_element =
unpack_value(parse_data_list, array_index + 1,
prev_data, index, sub_index,
separator_mask, unpack_method);
data_value->add_element(array_element);
}
return data_value;
}

View File

@ -24,6 +24,7 @@
#include "xFileNode.h"
#include "xFileArrayDef.h"
#include "xFileTemplate.h"
#include "xFileDataObject.h"
#include "pvector.h"
#include "pointerTo.h"
@ -67,6 +68,40 @@ public:
virtual void write_text(ostream &out, int indent_level) const;
virtual bool repack_data(XFileDataObject *object,
const XFileParseDataList &parse_data_list,
PrevData &prev_data,
size_t &index, size_t &sub_index) const;
private:
typedef PT(XFileDataObject)
(XFileDataDef::*UnpackMethod)(const XFileParseDataList &parse_data_list,
const PrevData &prev_data,
size_t &index, size_t &sub_index,
int separator_mask) const;
PT(XFileDataObject)
unpack_integer_value(const XFileParseDataList &parse_data_list,
const PrevData &prev_data,
size_t &index, size_t &sub_index,
int separator_mask) const;
PT(XFileDataObject)
unpack_double_value(const XFileParseDataList &parse_data_list,
const PrevData &prev_data,
size_t &index, size_t &sub_index,
int separator_mask) const;
PT(XFileDataObject)
unpack_template_value(const XFileParseDataList &parse_data_list,
const PrevData &prev_data,
size_t &index, size_t &sub_index,
int separator_mask) const;
PT(XFileDataObject)
unpack_value(const XFileParseDataList &parse_data_list, int array_index,
const PrevData &prev_data,
size_t &index, size_t &sub_index, int separator_mask,
UnpackMethod unpack_method) const;
private:
Type _type;
PT(XFileTemplate) _template;

View File

@ -23,8 +23,8 @@
// Description:
////////////////////////////////////////////////////////////////////
INLINE XFileDataObject::
XFileDataObject(XFile *x_file, const string &name) :
XFileNode(x_file, name)
XFileDataObject(const XFileDataDef *data_def) :
_data_def(data_def)
{
}
@ -34,7 +34,7 @@ XFileDataObject(XFile *x_file, const string &name) :
// Description: Returns the data object that this object is
// represented by, if any, or NULL if there is none.
////////////////////////////////////////////////////////////////////
INLINE XFileDataDef *XFileDataObject::
INLINE const XFileDataDef *XFileDataObject::
get_data_def() const {
return _data_def;
}
@ -115,6 +115,17 @@ operator string () const {
return as_string_value();
}
////////////////////////////////////////////////////////////////////
// Function: XFileDataObject::size
// Access: Public
// Description: Returns the number of nested data objects within this
// object.
////////////////////////////////////////////////////////////////////
INLINE int XFileDataObject::
size() const {
return get_num_elements();
}
////////////////////////////////////////////////////////////////////
// Function: XFileDataObject::operator [] (int)
// Access: Public
@ -124,8 +135,9 @@ operator string () const {
////////////////////////////////////////////////////////////////////
INLINE const XFileDataObject &XFileDataObject::
operator [] (int n) const {
nassertr(n >= 0 && n < get_num_children(), *this);
return *DCAST(XFileDataObject, get_child(n));
const XFileDataObject *element = get_element(n);
nassertr(element != (XFileDataObject *)NULL, *this);
return *element;
}
////////////////////////////////////////////////////////////////////
@ -137,7 +149,13 @@ operator [] (int n) const {
////////////////////////////////////////////////////////////////////
INLINE const XFileDataObject &XFileDataObject::
operator [] (const string &name) const {
XFileNode *child = find_child(name);
nassertr(child != (XFileNode *)NULL, *this);
return *DCAST(XFileDataObject, child);
const XFileDataObject *element = get_element(name);
nassertr(element != (XFileDataObject *)NULL, *this);
return *element;
}
INLINE ostream &
operator << (ostream &out, const XFileDataObject &data_object) {
data_object.output_data(out);
return out;
}

View File

@ -17,9 +17,55 @@
////////////////////////////////////////////////////////////////////
#include "xFileDataObject.h"
#include "indent.h"
TypeHandle XFileDataObject::_type_handle;
////////////////////////////////////////////////////////////////////
// Function: XFileDataObject::Destructor
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
XFileDataObject::
~XFileDataObject() {
}
////////////////////////////////////////////////////////////////////
// Function: XFileDataObject::add_element
// Access: Public, Virtual
// Description: Adds the indicated element as a nested data element,
// if this data object type supports it. Returns true
// if added successfully, false if the data object type
// does not support nested data elements.
////////////////////////////////////////////////////////////////////
bool XFileDataObject::
add_element(XFileDataObject *element) {
return false;
}
////////////////////////////////////////////////////////////////////
// Function: XFileDataObject::output_data
// Access: Public, Virtual
// Description: Writes a suitable representation of this node to an
// .x file in text mode.
////////////////////////////////////////////////////////////////////
void XFileDataObject::
output_data(ostream &out) const {
out << "(" << get_type() << "::output_data() not implemented.)";
}
////////////////////////////////////////////////////////////////////
// Function: XFileDataObject::write_data
// Access: Public, Virtual
// Description: Writes a suitable representation of this node to an
// .x file in text mode.
////////////////////////////////////////////////////////////////////
void XFileDataObject::
write_data(ostream &out, int indent_level, const char *) const {
indent(out, indent_level)
<< "(" << get_type() << "::write_data() not implemented.)\n";
}
////////////////////////////////////////////////////////////////////
// Function: XFileDataObject::as_integer_value
// Access: Protected, Virtual
@ -52,3 +98,37 @@ string XFileDataObject::
as_string_value() const {
return string();
}
////////////////////////////////////////////////////////////////////
// Function: XFileDataObject::get_num_elements
// Access: Protected, Virtual
// Description: Returns the number of nested data elements within the
// object. This may be, e.g. the size of the array, if
// it is an array.
////////////////////////////////////////////////////////////////////
int XFileDataObject::
get_num_elements() const {
return 0;
}
////////////////////////////////////////////////////////////////////
// Function: XFileDataObject::get_element
// Access: Protected, Virtual
// Description: Returns the nth nested data element within the
// object.
////////////////////////////////////////////////////////////////////
const XFileDataObject *XFileDataObject::
get_element(int n) const {
return NULL;
}
////////////////////////////////////////////////////////////////////
// Function: XFileDataObject::get_element
// Access: Protected, Virtual
// Description: Returns the nested data element within the
// object that has the indicated name.
////////////////////////////////////////////////////////////////////
const XFileDataObject *XFileDataObject::
get_element(const string &name) const {
return NULL;
}

View File

@ -20,22 +20,24 @@
#define XFILEDATAOBJECT_H
#include "pandatoolbase.h"
#include "xFileNode.h"
#include "xFileDataDef.h"
#include "referenceCount.h"
#include "pointerTo.h"
#include "dcast.h"
class XFileDataDef;
////////////////////////////////////////////////////////////////////
// Class : XFileDataObject
// Description : The abstract base class for a number of different
// types of data elements that may be stored in the X
// file.
////////////////////////////////////////////////////////////////////
class XFileDataObject : public XFileNode {
class XFileDataObject : virtual public ReferenceCount {
public:
INLINE XFileDataObject(XFile *x_file, const string &name);
INLINE XFileDataObject(const XFileDataDef *data_def = NULL);
virtual ~XFileDataObject();
INLINE XFileDataDef *get_data_def() const;
INLINE const XFileDataDef *get_data_def() const;
INLINE int i() const;
INLINE double d() const;
@ -44,24 +46,35 @@ public:
INLINE operator double () const;
INLINE operator string () const;
INLINE int size() const;
INLINE const XFileDataObject &operator [] (int n) const;
INLINE const XFileDataObject &operator [] (const string &name) const;
virtual bool add_element(XFileDataObject *element);
virtual void output_data(ostream &out) const;
virtual void write_data(ostream &out, int indent_level,
const char *separator) const;
protected:
virtual int as_integer_value() const;
virtual double as_double_value() const;
virtual string as_string_value() const;
PT(XFileDataDef) _data_def;
virtual int get_num_elements() const;
virtual const XFileDataObject *get_element(int n) const;
virtual const XFileDataObject *get_element(const string &name) const;
const XFileDataDef *_data_def;
public:
static TypeHandle get_class_type() {
return _type_handle;
}
static void init_type() {
XFileNode::init_type();
ReferenceCount::init_type();
register_type(_type_handle, "XFileDataObject",
XFileNode::get_class_type());
ReferenceCount::get_class_type());
}
virtual TypeHandle get_type() const {
return get_class_type();
@ -72,6 +85,8 @@ private:
static TypeHandle _type_handle;
};
INLINE ostream &operator << (ostream &out, const XFileDataObject &data_object);
#include "xFileDataObject.I"
#endif

View File

@ -0,0 +1,29 @@
// Filename: xFileDataObjectArray.I
// Created by: drose (07Oct04)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
// Function: XFileDataObjectArray::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
XFileDataObjectArray::
XFileDataObjectArray(const XFileDataDef *data_def) :
XFileDataObject(data_def)
{
}

View File

@ -0,0 +1,88 @@
// Filename: xFileDataObjectArray.cxx
// Created by: drose (07Oct04)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
#include "xFileDataObjectArray.h"
#include "string_utils.h"
#include "indent.h"
TypeHandle XFileDataObjectArray::_type_handle;
////////////////////////////////////////////////////////////////////
// Function: XFileDataObjectArray::write_data
// Access: Public, Virtual
// Description: Writes a suitable representation of this node to an
// .x file in text mode.
////////////////////////////////////////////////////////////////////
void XFileDataObjectArray::
write_data(ostream &out, int indent_level, const char *separator) const {
if (!_nested_elements.empty()) {
if (_nested_elements.front()->size() != 0) {
// If we have a complex nested structure, output one per line.
for (size_t i = 0; i < _nested_elements.size() - 1; i++) {
_nested_elements[i]->write_data(out, indent_level, ",");
}
_nested_elements.back()->write_data(out, indent_level, separator);
} else {
// Otherwise, output them all on the same line.
indent(out, indent_level);
for (size_t i = 0; i < _nested_elements.size() - 1; i++) {
out << *_nested_elements[i] << ", ";
}
out << *_nested_elements.back() << separator << "\n";
}
}
}
////////////////////////////////////////////////////////////////////
// Function: XFileDataObjectArray::add_element
// Access: Public, Virtual
// Description: Adds the indicated element as a nested data element,
// if this data object type supports it. Returns true
// if added successfully, false if the data object type
// does not support nested data elements.
////////////////////////////////////////////////////////////////////
bool XFileDataObjectArray::
add_element(XFileDataObject *element) {
_nested_elements.push_back(element);
return true;
}
////////////////////////////////////////////////////////////////////
// Function: XFileDataObjectArray::get_num_elements
// Access: Protected, Virtual
// Description: Returns the number of nested data elements within the
// object. This may be, e.g. the size of the array, if
// it is an array.
////////////////////////////////////////////////////////////////////
int XFileDataObjectArray::
get_num_elements() const {
return _nested_elements.size();
}
////////////////////////////////////////////////////////////////////
// Function: XFileDataObjectArray::get_element
// Access: Protected, Virtual
// Description: Returns the nth nested data element within the
// object.
////////////////////////////////////////////////////////////////////
const XFileDataObject *XFileDataObjectArray::
get_element(int n) const {
nassertr(n >= 0 && n < (int)_nested_elements.size(), NULL);
return _nested_elements[n];
}

View File

@ -0,0 +1,66 @@
// Filename: xFileDataObjectArray.h
// Created by: drose (07Oct04)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
#ifndef XFILEDATAOBJECTARRAY_H
#define XFILEDATAOBJECTARRAY_H
#include "pandatoolbase.h"
#include "xFileDataObject.h"
////////////////////////////////////////////////////////////////////
// Class : XFileDataObjectArray
// Description : An array of nested data elements.
////////////////////////////////////////////////////////////////////
class XFileDataObjectArray : public XFileDataObject {
public:
INLINE XFileDataObjectArray(const XFileDataDef *data_def);
virtual void write_data(ostream &out, int indent_level,
const char *separator) const;
virtual bool add_element(XFileDataObject *element);
protected:
virtual int get_num_elements() const;
virtual const XFileDataObject *get_element(int n) const;
private:
typedef pvector< PT(XFileDataObject) > NestedElements;
NestedElements _nested_elements;
public:
static TypeHandle get_class_type() {
return _type_handle;
}
static void init_type() {
XFileDataObject::init_type();
register_type(_type_handle, "XFileDataObjectArray",
XFileDataObject::get_class_type());
}
virtual TypeHandle get_type() const {
return get_class_type();
}
virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
private:
static TypeHandle _type_handle;
};
#include "xFileDataObjectArray.I"
#endif

View File

@ -0,0 +1,18 @@
// Filename: xFileDataObjectDouble.I
// Created by: drose (07Oct04)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////

View File

@ -0,0 +1,97 @@
// Filename: xFileDataObjectDouble.cxx
// Created by: drose (07Oct04)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
#include "xFileDataObjectDouble.h"
#include "string_utils.h"
#include "indent.h"
TypeHandle XFileDataObjectDouble::_type_handle;
////////////////////////////////////////////////////////////////////
// Function: XFileDataObjectDouble::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
XFileDataObjectDouble::
XFileDataObjectDouble(const XFileDataDef *data_def, double value) :
XFileDataObject(data_def),
_value(value)
{
}
////////////////////////////////////////////////////////////////////
// Function: XFileDataObjectDouble::output_data
// Access: Public, Virtual
// Description: Writes a suitable representation of this node to an
// .x file in text mode.
////////////////////////////////////////////////////////////////////
void XFileDataObjectDouble::
output_data(ostream &out) const {
out << as_string_value();
}
////////////////////////////////////////////////////////////////////
// Function: XFileDataObjectDouble::write_data
// Access: Public, Virtual
// Description: Writes a suitable representation of this node to an
// .x file in text mode.
////////////////////////////////////////////////////////////////////
void XFileDataObjectDouble::
write_data(ostream &out, int indent_level, const char *separator) const {
indent(out, indent_level)
<< as_string_value() << separator << "\n";
}
////////////////////////////////////////////////////////////////////
// Function: XFileDataObjectDouble::as_integer_value
// Access: Protected, Virtual
// Description: Returns the object's representation as an integer, if
// it has one.
////////////////////////////////////////////////////////////////////
int XFileDataObjectDouble::
as_integer_value() const {
return (int)_value;
}
////////////////////////////////////////////////////////////////////
// Function: XFileDataObjectDouble::as_double_value
// Access: Protected, Virtual
// Description: Returns the object's representation as a double, if
// it has one.
////////////////////////////////////////////////////////////////////
double XFileDataObjectDouble::
as_double_value() const {
return _value;
}
////////////////////////////////////////////////////////////////////
// Function: XFileDataObjectDouble::as_string_value
// Access: Protected, Virtual
// Description: Returns the object's representation as a string, if
// it has one.
////////////////////////////////////////////////////////////////////
string XFileDataObjectDouble::
as_string_value() const {
// It's important to format with a decimal point, even if the value
// is integral, since the DirectX .x reader differentiates betweens
// doubles and integers on parsing.
char buffer[128];
sprintf(buffer, "%f", _value);
return buffer;
}

View File

@ -0,0 +1,67 @@
// Filename: xFileDataObjectDouble.h
// Created by: drose (07Oct04)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
#ifndef XFILEDATAOBJECTDOUBLE_H
#define XFILEDATAOBJECTDOUBLE_H
#include "pandatoolbase.h"
#include "xFileDataObject.h"
////////////////////////////////////////////////////////////////////
// Class : XFileDataObjectDouble
// Description : An double-valued data element. This matches one
// double data member of a template, or a single
// element of an double array.
////////////////////////////////////////////////////////////////////
class XFileDataObjectDouble : public XFileDataObject {
public:
XFileDataObjectDouble(const XFileDataDef *data_def, double value);
virtual void output_data(ostream &out) const;
virtual void write_data(ostream &out, int indent_level,
const char *separator) const;
protected:
virtual int as_integer_value() const;
virtual double as_double_value() const;
virtual string as_string_value() const;
private:
double _value;
public:
static TypeHandle get_class_type() {
return _type_handle;
}
static void init_type() {
XFileDataObject::init_type();
register_type(_type_handle, "XFileDataObjectDouble",
XFileDataObject::get_class_type());
}
virtual TypeHandle get_type() const {
return get_class_type();
}
virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
private:
static TypeHandle _type_handle;
};
#include "xFileDataObjectDouble.I"
#endif

View File

@ -0,0 +1,18 @@
// Filename: xFileDataObjectInteger.I
// Created by: drose (07Oct04)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////

View File

@ -0,0 +1,91 @@
// Filename: xFileDataObjectInteger.cxx
// Created by: drose (07Oct04)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
#include "xFileDataObjectInteger.h"
#include "string_utils.h"
#include "indent.h"
TypeHandle XFileDataObjectInteger::_type_handle;
////////////////////////////////////////////////////////////////////
// Function: XFileDataObjectInteger::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
XFileDataObjectInteger::
XFileDataObjectInteger(const XFileDataDef *data_def, int value) :
XFileDataObject(data_def),
_value(value)
{
}
////////////////////////////////////////////////////////////////////
// Function: XFileDataObjectInteger::output_data
// Access: Public, Virtual
// Description: Writes a suitable representation of this node to an
// .x file in text mode.
////////////////////////////////////////////////////////////////////
void XFileDataObjectInteger::
output_data(ostream &out) const {
out << _value;
}
////////////////////////////////////////////////////////////////////
// Function: XFileDataObjectInteger::write_data
// Access: Public, Virtual
// Description: Writes a suitable representation of this node to an
// .x file in text mode.
////////////////////////////////////////////////////////////////////
void XFileDataObjectInteger::
write_data(ostream &out, int indent_level, const char *separator) const {
indent(out, indent_level)
<< _value << separator << "\n";
}
////////////////////////////////////////////////////////////////////
// Function: XFileDataObjectInteger::as_integer_value
// Access: Protected, Virtual
// Description: Returns the object's representation as an integer, if
// it has one.
////////////////////////////////////////////////////////////////////
int XFileDataObjectInteger::
as_integer_value() const {
return _value;
}
////////////////////////////////////////////////////////////////////
// Function: XFileDataObjectInteger::as_double_value
// Access: Protected, Virtual
// Description: Returns the object's representation as a double, if
// it has one.
////////////////////////////////////////////////////////////////////
double XFileDataObjectInteger::
as_double_value() const {
return _value;
}
////////////////////////////////////////////////////////////////////
// Function: XFileDataObjectInteger::as_string_value
// Access: Protected, Virtual
// Description: Returns the object's representation as a string, if
// it has one.
////////////////////////////////////////////////////////////////////
string XFileDataObjectInteger::
as_string_value() const {
return format_string(_value);
}

View File

@ -0,0 +1,67 @@
// Filename: xFileDataObjectInteger.h
// Created by: drose (07Oct04)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
#ifndef XFILEDATAOBJECTINTEGER_H
#define XFILEDATAOBJECTINTEGER_H
#include "pandatoolbase.h"
#include "xFileDataObject.h"
////////////////////////////////////////////////////////////////////
// Class : XFileDataObjectInteger
// Description : An integer-valued data element. This matches one
// integer data member of a template, or a single
// element of an integer array.
////////////////////////////////////////////////////////////////////
class XFileDataObjectInteger : public XFileDataObject {
public:
XFileDataObjectInteger(const XFileDataDef *data_def, int value);
virtual void output_data(ostream &out) const;
virtual void write_data(ostream &out, int indent_level,
const char *separator) const;
protected:
virtual int as_integer_value() const;
virtual double as_double_value() const;
virtual string as_string_value() const;
private:
int _value;
public:
static TypeHandle get_class_type() {
return _type_handle;
}
static void init_type() {
XFileDataObject::init_type();
register_type(_type_handle, "XFileDataObjectInteger",
XFileDataObject::get_class_type());
}
virtual TypeHandle get_type() const {
return get_class_type();
}
virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
private:
static TypeHandle _type_handle;
};
#include "xFileDataObjectInteger.I"
#endif

View File

@ -18,6 +18,8 @@
#include "xFileDataObjectTemplate.h"
#include "indent.h"
#include "xFileParseData.h"
#include "xLexerDefs.h"
TypeHandle XFileDataObjectTemplate::_type_handle;
@ -29,7 +31,7 @@ TypeHandle XFileDataObjectTemplate::_type_handle;
XFileDataObjectTemplate::
XFileDataObjectTemplate(XFile *x_file, const string &name,
XFileTemplate *xtemplate) :
XFileDataObject(x_file, name),
XFileNode(x_file, name),
_template(xtemplate)
{
}
@ -48,11 +50,46 @@ write_text(ostream &out, int indent_level) const {
out << " " << get_name();
}
out << " {\n";
XFileDataObject::write_text(out, indent_level + 2);
int num_elements = get_num_elements();
for (int i = 0; i < num_elements; i++) {
get_element(i)->write_data(out, indent_level + 2, ";");
}
XFileNode::write_text(out, indent_level + 2);
indent(out, indent_level)
<< "}\n";
}
////////////////////////////////////////////////////////////////////
// Function: XFileDataObjectTemplate::write_data
// Access: Public, Virtual
// Description: Writes a suitable representation of this node to an
// .x file in text mode.
////////////////////////////////////////////////////////////////////
void XFileDataObjectTemplate::
write_data(ostream &out, int indent_level, const char *separator) const {
if (!_nested_elements.empty()) {
if (_nested_elements.front()->size() != 0) {
// If we have a complex nested structure, output one per line.
for (size_t i = 0; i < _nested_elements.size() - 1; i++) {
_nested_elements[i]->write_data(out, indent_level, ";");
}
string combined_separator = string(";") + string(separator);
_nested_elements.back()->write_data(out, indent_level,
combined_separator.c_str());
} else {
// Otherwise, output them all on the same line.
indent(out, indent_level);
for (size_t i = 0; i < _nested_elements.size() - 1; i++) {
out << *_nested_elements[i] << "; ";
}
out << *_nested_elements.back() << ";" << separator << "\n";
}
}
}
////////////////////////////////////////////////////////////////////
// Function: XFileDataObjectTemplate::add_parse_object
// Access: Public
@ -62,6 +99,14 @@ write_text(ostream &out, int indent_level) const {
////////////////////////////////////////////////////////////////////
void XFileDataObjectTemplate::
add_parse_object(XFileDataObjectTemplate *object, bool reference) {
XFileParseData pdata;
pdata._object = object;
pdata._parse_flags = XFileParseData::PF_object;
if (reference) {
pdata._parse_flags |= XFileParseData::PF_reference;
}
_parse_data_list._list.push_back(pdata);
}
////////////////////////////////////////////////////////////////////
@ -73,6 +118,20 @@ add_parse_object(XFileDataObjectTemplate *object, bool reference) {
////////////////////////////////////////////////////////////////////
void XFileDataObjectTemplate::
add_parse_double(PTA_double double_list, char separator) {
XFileParseData pdata;
pdata._double_list = double_list;
pdata._parse_flags = XFileParseData::PF_double;
switch (separator) {
case ',':
pdata._parse_flags |= XFileParseData::PF_comma;
break;
case ';':
pdata._parse_flags |= XFileParseData::PF_semicolon;
break;
}
_parse_data_list._list.push_back(pdata);
}
////////////////////////////////////////////////////////////////////
@ -84,6 +143,20 @@ add_parse_double(PTA_double double_list, char separator) {
////////////////////////////////////////////////////////////////////
void XFileDataObjectTemplate::
add_parse_int(PTA_int int_list, char separator) {
XFileParseData pdata;
pdata._int_list = int_list;
pdata._parse_flags = XFileParseData::PF_int;
switch (separator) {
case ',':
pdata._parse_flags |= XFileParseData::PF_comma;
break;
case ';':
pdata._parse_flags |= XFileParseData::PF_semicolon;
break;
}
_parse_data_list._list.push_back(pdata);
}
////////////////////////////////////////////////////////////////////
@ -95,6 +168,20 @@ add_parse_int(PTA_int int_list, char separator) {
////////////////////////////////////////////////////////////////////
void XFileDataObjectTemplate::
add_parse_string(const string &str, char separator) {
XFileParseData pdata;
pdata._string = str;
pdata._parse_flags = XFileParseData::PF_string;
switch (separator) {
case ',':
pdata._parse_flags |= XFileParseData::PF_comma;
break;
case ';':
pdata._parse_flags |= XFileParseData::PF_semicolon;
break;
}
_parse_data_list._list.push_back(pdata);
}
////////////////////////////////////////////////////////////////////
@ -106,6 +193,19 @@ add_parse_string(const string &str, char separator) {
////////////////////////////////////////////////////////////////////
void XFileDataObjectTemplate::
add_parse_separator(char separator) {
XFileParseData pdata;
pdata._parse_flags = 0;
switch (separator) {
case ',':
pdata._parse_flags |= XFileParseData::PF_comma;
break;
case ';':
pdata._parse_flags |= XFileParseData::PF_semicolon;
break;
}
_parse_data_list._list.push_back(pdata);
}
////////////////////////////////////////////////////////////////////
@ -119,5 +219,79 @@ add_parse_separator(char separator) {
////////////////////////////////////////////////////////////////////
bool XFileDataObjectTemplate::
finalize_parse_data() {
// Recursively walk through our template definition, while
// simultaneously walking through the list of parse data elements we
// encountered, and re-pack them as actual nested elements.
PrevData prev_data;
size_t index = 0;
size_t sub_index = 0;
if (!_template->repack_data(this, _parse_data_list,
prev_data, index, sub_index)) {
return false;
}
// Quietly allow an extra semicolon at the end of the structure.
// (Why is this sometimes here?)
if (index < _parse_data_list._list.size() &&
_parse_data_list._list[index]._parse_flags == XFileParseData::PF_semicolon) {
index++;
}
if (index != _parse_data_list._list.size()) {
cerr << "flags = " << hex << _parse_data_list._list[index]._parse_flags << dec << "\n";
xyyerror("Too many data elements in structure.");
return false;
}
return true;
}
////////////////////////////////////////////////////////////////////
// Function: XFileDataObjectTemplate::add_element
// Access: Public, Virtual
// Description: Adds the indicated element as a nested data element,
// if this data object type supports it. Returns true
// if added successfully, false if the data object type
// does not support nested data elements.
////////////////////////////////////////////////////////////////////
bool XFileDataObjectTemplate::
add_element(XFileDataObject *element) {
_nested_elements.push_back(element);
return true;
}
////////////////////////////////////////////////////////////////////
// Function: XFileDataObjectTemplate::get_num_elements
// Access: Protected, Virtual
// Description: Returns the number of nested data elements within the
// object. This may be, e.g. the size of the array, if
// it is an array.
////////////////////////////////////////////////////////////////////
int XFileDataObjectTemplate::
get_num_elements() const {
return _nested_elements.size();
}
////////////////////////////////////////////////////////////////////
// Function: XFileDataObjectTemplate::get_element
// Access: Protected, Virtual
// Description: Returns the nth nested data element within the
// object.
////////////////////////////////////////////////////////////////////
const XFileDataObject *XFileDataObjectTemplate::
get_element(int n) const {
nassertr(n >= 0 && n < (int)_nested_elements.size(), NULL);
return _nested_elements[n];
}
////////////////////////////////////////////////////////////////////
// Function: XFileDataObjectTemplate::get_element
// Access: Protected, Virtual
// Description: Returns the nested data element within the
// object that has the indicated name.
////////////////////////////////////////////////////////////////////
const XFileDataObject *XFileDataObjectTemplate::
get_element(const string &name) const {
return NULL;
}

View File

@ -20,8 +20,10 @@
#define XFILEDATAOBJECTTEMPLATE_H
#include "pandatoolbase.h"
#include "xFileNode.h"
#include "xFileDataObject.h"
#include "xFileTemplate.h"
#include "xFileParseData.h"
#include "pointerTo.h"
#include "pta_int.h"
#include "pta_double.h"
@ -34,7 +36,7 @@
// obtained by walking through the children of this
// object.
////////////////////////////////////////////////////////////////////
class XFileDataObjectTemplate : public XFileDataObject {
class XFileDataObjectTemplate : public XFileNode, public XFileDataObject {
public:
XFileDataObjectTemplate(XFile *x_file, const string &name,
XFileTemplate *xtemplate);
@ -42,6 +44,8 @@ public:
INLINE XFileTemplate *get_template() const;
virtual void write_text(ostream &out, int indent_level) const;
virtual void write_data(ostream &out, int indent_level,
const char *separator) const;
public:
void add_parse_object(XFileDataObjectTemplate *object, bool reference);
@ -51,41 +55,30 @@ public:
void add_parse_separator(char separator);
bool finalize_parse_data();
virtual bool add_element(XFileDataObject *element);
protected:
virtual int get_num_elements() const;
virtual const XFileDataObject *get_element(int n) const;
virtual const XFileDataObject *get_element(const string &name) const;
private:
PT(XFileTemplate) _template;
// This class is used to fill up the data as the values are parsed.
// It only has a temporary lifespan; it will be converted into
// actual data by finalize_parse_data().
enum ParseFlags {
PF_object = 0x001,
PF_reference = 0x002,
PF_double = 0x004,
PF_int = 0x008,
PF_string = 0x010,
PF_comma = 0x020,
PF_semicolon = 0x040,
};
class ParseData {
public:
PT(XFileDataObjectTemplate) _object;
PTA_double _double_list;
PTA_int _int_list;
string _string;
int _parse_flags;
};
typedef pvector<ParseData> ParseDataList;
ParseDataList _parse_data_list;
XFileParseDataList _parse_data_list;
typedef pvector< PT(XFileDataObject) > NestedElements;
NestedElements _nested_elements;
public:
static TypeHandle get_class_type() {
return _type_handle;
}
static void init_type() {
XFileNode::init_type();
XFileDataObject::init_type();
register_type(_type_handle, "XFileDataObjectTemplate",
XFileNode::get_class_type(),
XFileDataObject::get_class_type());
}
virtual TypeHandle get_type() const {

View File

@ -17,6 +17,16 @@
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
// Function: XFileNode::get_num_children
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE XFile *XFileNode::
get_x_file() const {
return _x_file;
}
////////////////////////////////////////////////////////////////////
// Function: XFileNode::get_num_children
// Access: Public

View File

@ -19,6 +19,8 @@
#include "xFileNode.h"
#include "windowsGuid.h"
#include "xFile.h"
#include "xLexerDefs.h"
#include "xFileParseData.h"
TypeHandle XFileNode::_type_handle;
@ -149,3 +151,37 @@ write_text(ostream &out, int indent_level) const {
(*ci)->write_text(out, indent_level);
}
}
////////////////////////////////////////////////////////////////////
// Function: XFileNode::repack_data
// Access: Public, Virtual
// Description: This is called on the template that defines an
// object, once the data for the object has been parsed.
// It is responsible for identifying which component of
// the template owns each data element, and packing the
// data elements appropriately back into the object.
//
// It returns true on success, or false on an error
// (e.g. too many semicolons, not enough data elements,
// mismatched data type).
////////////////////////////////////////////////////////////////////
bool XFileNode::
repack_data(XFileDataObject *object,
const XFileParseDataList &parse_data_list,
XFileNode::PrevData &prev_data,
size_t &index, size_t &sub_index) const {
// This method should be specialized for data types that actually
// consume a data element. Here in the base class, it just walks
// through its children, asking each one to pull off the appropriate
// number of data elements.
Children::const_iterator ci;
for (ci = _children.begin(); ci != _children.end(); ++ci) {
if (!(*ci)->repack_data(object, parse_data_list,
prev_data, index, sub_index)) {
return false;
}
}
return true;
}

View File

@ -20,7 +20,8 @@
#define XFILENODE_H
#include "pandatoolbase.h"
#include "typedReferenceCount.h"
#include "typedObject.h"
#include "referenceCount.h"
#include "pointerTo.h"
#include "namable.h"
#include "notify.h"
@ -29,17 +30,23 @@
class XFile;
class WindowsGuid;
class XFileParseDataList;
class XFileDataDef;
class XFileDataObject;
////////////////////////////////////////////////////////////////////
// Class : XFileNode
// Description : A single node of an X file. This may be either a
// template or a data node.
////////////////////////////////////////////////////////////////////
class XFileNode : public TypedReferenceCount, public Namable {
class XFileNode : public TypedObject, public Namable,
virtual public ReferenceCount {
public:
XFileNode(XFile *x_file, const string &name);
virtual ~XFileNode();
INLINE XFile *get_x_file() const;
INLINE int get_num_children() const;
INLINE XFileNode *get_child(int n) const;
XFileNode *find_child(const string &name) const;
@ -53,6 +60,13 @@ public:
virtual void write_text(ostream &out, int indent_level) const;
typedef pmap<const XFileDataDef *, XFileDataObject *> PrevData;
virtual bool repack_data(XFileDataObject *object,
const XFileParseDataList &parse_data_list,
PrevData &prev_data,
size_t &index, size_t &sub_index) const;
protected:
XFile *_x_file;
@ -67,9 +81,11 @@ public:
return _type_handle;
}
static void init_type() {
TypedReferenceCount::init_type();
TypedObject::init_type();
ReferenceCount::init_type();
register_type(_type_handle, "XFileNode",
TypedReferenceCount::get_class_type());
TypedObject::get_class_type(),
ReferenceCount::get_class_type());
}
virtual TypeHandle get_type() const {
return get_class_type();

View File

@ -0,0 +1,18 @@
// Filename: xFileParseData.I
// Created by: drose (07Oct04)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////

View File

@ -0,0 +1,50 @@
// Filename: xFileParseData.cxx
// Created by: drose (07Oct04)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
#include "xFileParseData.h"
#include "xLexerDefs.h"
////////////////////////////////////////////////////////////////////
// Function: XFileParseData::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
XFileParseData::
XFileParseData() :
_parse_flags(0)
{
// Save the line number, column number, and line text in case we
// detect an error later and want to report a meaningful message to
// the user.
_line_number = x_line_number;
_col_number = x_col_number;
_current_line = x_current_line;
}
////////////////////////////////////////////////////////////////////
// Function: XFileParseData::yyerror
// Access: Public
// Description: Reports a parsing error message to the user, showing
// the line and column from which this object was
// originally parsed.
////////////////////////////////////////////////////////////////////
void XFileParseData::
yyerror(const string &message) const {
xyyerror(message, _line_number, _col_number, _current_line);
}

View File

@ -0,0 +1,82 @@
// Filename: xFileParseData.h
// Created by: drose (07Oct04)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
#ifndef XFILEPARSEDATA_H
#define XFILEPARSEDATA_H
#include "pandatoolbase.h"
#include "xFileDataObject.h"
#include "pointerTo.h"
#include "pta_int.h"
#include "pta_double.h"
#include "pvector.h"
////////////////////////////////////////////////////////////////////
// Class : XFileParseData
// Description : This class is used to fill up the data into an
// XFileDataObjectTemplate object as the data values are
// parsed out of the X file. It only has a temporary
// lifespan; it will be converted into actual data by
// XFileDataObjectTemplate::finalize_parse_data().
////////////////////////////////////////////////////////////////////
class XFileParseData {
public:
XFileParseData();
void yyerror(const string &message) const;
enum ParseFlags {
PF_object = 0x001,
PF_reference = 0x002,
PF_double = 0x004,
PF_int = 0x008,
PF_string = 0x010,
PF_any_data = 0x01f,
PF_comma = 0x020,
PF_semicolon = 0x040,
};
PT(XFileDataObject) _object;
PTA_double _double_list;
PTA_int _int_list;
string _string;
int _parse_flags;
int _line_number;
int _col_number;
string _current_line;
};
////////////////////////////////////////////////////////////////////
// Class : XFileParseDataList
// Description : A container for a pvector of the above objects. We
// need this wrapper class to avoid circular #includes;
// this allows XFileNode to define a forward reference
// to this class (without having to include this file or
// know that it contains a template class).
////////////////////////////////////////////////////////////////////
class XFileParseDataList {
public:
typedef pvector<XFileParseData> List;
List _list;
};
#include "xFileParseData.I"
#endif

View File

@ -11,7 +11,7 @@
#include "xParser.h"
#include "indent.h"
#include "string_utils.h"
#include "notify.h"
#include "config_xfile.h"
static int yyinput(void); // declared by flex.
extern "C" int xyywrap();
@ -22,13 +22,13 @@ extern "C" int xyywrap();
// We'll increment line_number and col_number as we parse the file, so
// that we can report the position of an error.
static int line_number = 0;
static int col_number = 0;
int x_line_number = 0;
int x_col_number = 0;
// current_line holds as much of the current line as will fit. Its
// only purpose is for printing it out to report an error to the user.
static const int max_error_width = 1024;
static char current_line[max_error_width + 1];
char x_current_line[max_error_width + 1];
static int error_count = 0;
static int warning_count = 0;
@ -49,8 +49,8 @@ void
x_init_lexer(istream &in, const string &filename) {
inp = &in;
x_filename = filename;
line_number = 0;
col_number = 0;
x_line_number = 0;
x_col_number = 0;
error_count = 0;
warning_count = 0;
}
@ -77,14 +77,20 @@ xyywrap(void) {
void
xyyerror(const string &msg) {
cerr << "\nError";
xyyerror(msg, x_line_number, x_col_number, x_current_line);
}
void
xyyerror(const string &msg, int line_number, int col_number,
const string &current_line) {
xfile_cat.error(false) << "\nError";
if (!x_filename.empty()) {
cerr << " in " << x_filename;
xfile_cat.error(false) << " in " << x_filename;
}
cerr
xfile_cat.error(false)
<< " at line " << line_number << ", column " << col_number << ":\n"
<< current_line << "\n";
indent(cerr, col_number-1)
indent(xfile_cat.error(false), col_number-1)
<< "^\n" << msg << "\n\n";
error_count++;
@ -92,14 +98,14 @@ xyyerror(const string &msg) {
void
xyywarning(const string &msg) {
cerr << "\nWarning";
xfile_cat.warning(false) << "\nWarning";
if (!x_filename.empty()) {
cerr << " in " << x_filename;
xfile_cat.warning(false) << " in " << x_filename;
}
cerr
<< " at line " << line_number << ", column " << col_number << ":\n"
<< current_line << "\n";
indent(cerr, col_number-1)
xfile_cat.warning(false)
<< " at line " << x_line_number << ", column " << x_col_number << ":\n"
<< x_current_line << "\n";
indent(xfile_cat.warning(false), x_col_number-1)
<< "^\n" << msg << "\n\n";
warning_count++;
@ -118,18 +124,18 @@ input_chars(char *buffer, int &result, int max_size) {
buffer[result] = '\0';
}
if (line_number == 0) {
if (x_line_number == 0) {
// This is a special case. If we are reading the very first bit
// from the stream, copy it into the current_line array. This
// is because the \n.* rule below, which fills current_line
// from the stream, copy it into the x_current_line array. This
// is because the \n.* rule below, which fills x_current_line
// normally, doesn't catch the first line.
strncpy(current_line, xyytext, max_error_width);
current_line[max_error_width] = '\0';
line_number++;
col_number = 0;
strncpy(x_current_line, xyytext, max_error_width);
x_current_line[max_error_width] = '\0';
x_line_number++;
x_col_number = 0;
// Truncate it at the newline.
char *end = strchr(current_line, '\n');
char *end = strchr(x_current_line, '\n');
if (end != NULL) {
*end = '\0';
}
@ -170,11 +176,11 @@ scan_quoted_string(char quote_mark) {
// occurring at the start of the string, not at the end--somewhat
// more convenient for the user.
// Instead of adjusting the global line_number and col_number
// Instead of adjusting the global x_line_number and x_col_number
// variables, we'll operate on our own local variables for the
// interim.
int line = line_number;
int col = col_number;
int line = x_line_number;
int col = x_col_number;
int c;
c = read_char(line, col);
@ -274,8 +280,8 @@ scan_quoted_string(char quote_mark) {
xyyerror("This quotation mark is unterminated.");
}
line_number = line;
col_number = col;
x_line_number = line;
x_col_number = col;
return result;
}
@ -290,11 +296,11 @@ scan_guid_string() {
// occurring at the start of the string, not at the end--somewhat
// more convenient for the user.
// Instead of adjusting the global line_number and col_number
// Instead of adjusting the global x_line_number and x_col_number
// variables, we'll operate on our own local variables for the
// interim.
int line = line_number;
int col = col_number;
int line = x_line_number;
int col = x_col_number;
int num_digits = 0;
int num_hyphens = 0;
@ -311,8 +317,8 @@ scan_guid_string() {
num_hyphens++;
} else {
line_number = line;
col_number = col;
x_line_number = line;
x_col_number = col;
xyyerror("Invalid character in GUID.");
return string();
}
@ -335,19 +341,25 @@ scan_guid_string() {
return string();
}
line_number = line;
col_number = col;
x_line_number = line;
x_col_number = col;
return result;
}
// Parses the text into a list of integers and returns them.
static PTA_int
parse_int_list(const string &text, const string &delimiter) {
parse_int_list(const string &text, char delimiter) {
PTA_int result;
vector_string words;
tokenize(text, words, delimiter);
// The last character of text might be the delimiter.
if (!text.empty() && text[text.size() - 1] == delimiter) {
tokenize(text.substr(0, text.size() - 1), words, string(1, delimiter));
} else {
tokenize(text, words, string(1, delimiter));
}
vector_string::const_iterator wi;
for (wi = words.begin(); wi != words.end(); ++wi) {
@ -361,11 +373,17 @@ parse_int_list(const string &text, const string &delimiter) {
// Parses the text into a list of doubles and returns them.
static PTA_double
parse_double_list(const string &text, const string &delimiter) {
parse_double_list(const string &text, char delimiter) {
PTA_double result;
vector_string words;
tokenize(text, words, delimiter);
// The last character of text might be the delimiter.
if (!text.empty() && text[text.size() - 1] == delimiter) {
tokenize(text.substr(0, text.size() - 1), words, string(1, delimiter));
} else {
tokenize(text, words, string(1, delimiter));
}
vector_string::const_iterator wi;
for (wi = words.begin(); wi != words.end(); ++wi) {
@ -382,7 +400,7 @@ parse_double_list(const string &text, const string &delimiter) {
// accept() is called below as each piece is pulled off and
// accepted by the lexer; it increments the current column number.
inline void accept() {
col_number += yyleng;
x_col_number += yyleng;
}
%}
@ -399,10 +417,10 @@ REALNUM ([+-]?(([0-9]+[.])|([0-9]*[.][0-9]+))([eE][+-]?[0-9]+)?)
// New line. Save a copy of the line so we can print it out for the
// benefit of the user in case we get an error.
strncpy(current_line, xyytext+1, max_error_width);
current_line[max_error_width] = '\0';
line_number++;
col_number=0;
strncpy(x_current_line, xyytext+1, max_error_width);
x_current_line[max_error_width] = '\0';
x_line_number++;
x_col_number=0;
// Return the whole line to the lexer, except the newline character,
// which we eat.
@ -541,7 +559,7 @@ REALNUM ([+-]?(([0-9]+[.])|([0-9]*[.][0-9]+))([eE][+-]?[0-9]+)?)
({INTEGERNUM};)+ {
// An integer as part of a semicolon-delimited list.
accept();
xyylval.int_list = parse_int_list(xyytext, ";");
xyylval.int_list = parse_int_list(xyytext, ';');
xyylval.u.separator = ';';
return TOKEN_INTEGER_LIST;
@ -550,25 +568,43 @@ REALNUM ([+-]?(([0-9]+[.])|([0-9]*[.][0-9]+))([eE][+-]?[0-9]+)?)
({REALNUM};)+ {
// A floating-point number as part of a semicolon-delimited list.
accept();
xyylval.double_list = parse_double_list(xyytext, ";");
xyylval.double_list = parse_double_list(xyytext, ';');
xyylval.u.separator = ';';
return TOKEN_REALNUM_LIST;
}
({INTEGERNUM},)+ {
// An integer as part of a semicolon-delimited list.
// An integer as part of a comma-delimited list.
accept();
xyylval.int_list = parse_int_list(xyytext, ",");
xyylval.int_list = parse_int_list(xyytext, ',');
xyylval.u.separator = ',';
return TOKEN_INTEGER_LIST;
}
({REALNUM},)+ {
// A floating-point number as part of a semicolon-delimited list.
// A floating-point number as part of a comma-delimited list.
accept();
xyylval.double_list = parse_double_list(xyytext, ",");
xyylval.double_list = parse_double_list(xyytext, ',');
xyylval.u.separator = ',';
return TOKEN_REALNUM_LIST;
}
({INTEGERNUM},)+{INTEGERNUM} {
// An integer as part of a comma-delimited list.
accept();
xyylval.int_list = parse_int_list(xyytext, ',');
xyylval.u.separator = ',';
return TOKEN_INTEGER_LIST;
}
({REALNUM},)+{REALNUM} {
// A floating-point number as part of a comma-delimited list.
accept();
xyylval.double_list = parse_double_list(xyytext, ',');
xyylval.u.separator = ',';
return TOKEN_REALNUM_LIST;

View File

@ -26,8 +26,14 @@ int x_error_count();
int x_warning_count();
void xyyerror(const string &msg);
void xyyerror(const string &msg, int line_number, int col_number,
const string &current_line);
void xyywarning(const string &msg);
int xyylex();
extern int x_line_number;
extern int x_col_number;
extern char x_current_line[];
#endif

View File

@ -349,9 +349,7 @@ object:
{
XFileDataObjectTemplate *current_template =
DCAST(XFileDataObjectTemplate, current_node);
if (!current_template->finalize_parse_data()) {
yyerror("Invalid data for object.");
}
current_template->finalize_parse_data();
$$ = current_node;
current_node = $<u.node>4;
@ -366,27 +364,11 @@ data_parts_list:
data_part:
TOKEN_OBRACE data_reference TOKEN_CBRACE
{
if ($2 != (XFileNode *)NULL) {
if (!$2->is_of_type(XFileDataObjectTemplate::get_class_type())) {
// Actually, maybe you can--the docs aren't clear about this.
// But I don't think there's any real reason to.
yyerror("Can't reference primitive data type.");
} else {
XFileDataObjectTemplate *object =
DCAST(XFileDataObjectTemplate, $2);
XFileDataObjectTemplate *current_template =
DCAST(XFileDataObjectTemplate, current_node);
current_template->add_parse_object(object, true);
}
}
// nested references should be added as children too.
}
| object
{
XFileDataObjectTemplate *object =
DCAST(XFileDataObjectTemplate, $1);
XFileDataObjectTemplate *current_template =
DCAST(XFileDataObjectTemplate, current_node);
current_template->add_parse_object(object, false);
// nested objects are just quietly added as children.
}
| integer_list
{
@ -440,7 +422,7 @@ list_separator:
data_reference:
name
{
XFileDataObject *data_object = x_file->find_data_object($1);
XFileDataObjectTemplate *data_object = x_file->find_data_object($1);
if (data_object == (XFileDataObject *)NULL) {
yyerror("Unknown data_object: " + $1);
}
@ -449,7 +431,7 @@ data_reference:
}
| name class_id
{
XFileDataObject *data_object = x_file->find_data_object($2);
XFileDataObjectTemplate *data_object = x_file->find_data_object($2);
if (data_object == (XFileDataObject *)NULL) {
yyerror("Unknown data_object: " + $1);
} else {